diff options
author | Robin Watts <robin.watts@artifex.com> | 2012-04-27 18:46:27 +0100 |
---|---|---|
committer | Michael Vrhel <michael.vrhel@artifex.com> | 2012-04-29 08:49:49 -0700 |
commit | 60640aeb33b18f9a9fcd76fc6f1083d7c7635f24 (patch) | |
tree | 33a57c250203465c9e754ef9ddba901cac045030 | |
parent | dd09a0706ab09a54f5fbb05c63420c86375b45bf (diff) |
* Change of the tiffsep and psdcmyk device to planar devices.
This change in these devices was made to remove the 64 bit limitation of
our existing color encoding which limits us to 8 colorants without
compressed color encoding. The motivation for this work is that even
with compressed color encoding we were starting
to encounter files with transparency in particular that exceeded the
capabilities of encoding, leading to dropped colors. With this fix, we
encode through the clist the DeviceN color values. The buffers for the
devices are maintained as planar buffers and fills occur with the high level
device colors.
Support was added to handle the devn color type through the shading code. The old
code would have supported only 8 colorants in a shading.
Support was also added to the transparency code to enable the use of the put_image
procedure which for the planar device saves quite a bit of time since we can do the
copy_planes proc directly from the pdf14 planar buffer to the planar memory device buffer.
The pdf14 device also had to support fill_rectangle_hl_color.
Changes were also made to the pattern tiling code so that we avoid any planar to chunky and
back to planar conversions. These were being done to handle ROPs. Even when there were
not any ROPs to perform we were going through strip_tile_rop operations since the
gx_default_strip_tile_rectangle did not support planar to planar. That support is added
with this commit.
Support had to be added to the overprint compositor to support the new color type with
fill_rectangle_hl_color.
Support had to be added to the clist for fill_rectangle_hl_color. This required changes
on both the writing and reading side. It is possible that the amount of data written
for these commands could be reduced and that is commented in the code.
Support also had to be added to the clip device and the mask_clip device as well
for uncolored patterns. Also the tile clip device required support and the transparency device
required support for copy_planes. This last function needs to be optimized.
Both of the separation devices (tiffsep and psdcmyk) that we currently have are updated to
support this method. There is an #if option in each device file to return the
code back to the old chunky format.
A new device procedure for handling strip tiling of masks with devn colors had
to be added. Functionality was only required for the mem planar and clist devices.
Also, it was found that the tiffsep and psdcmyk devices were maintaining separations
(spot colors) across pages. That is if page 1 had a spot color, subsequent pages
created a separation for that spot
even if those pages did not contain it. This was fixed so that separations for a page
are only created for the spots that occur on that page.
A fix was also made to ensure that we had proper handling for the None colorants when
they are part of the DeviceN color space.
56 files changed, 2443 insertions, 287 deletions
diff --git a/gs/base/devs.mak b/gs/base/devs.mak index aa64fdf39..82b82aa74 100644 --- a/gs/base/devs.mak +++ b/gs/base/devs.mak @@ -1290,7 +1290,8 @@ $(DD)psdcmyk.dev : $(DEVS_MAK) $(psd_) $(GLD)page.dev $(GDEV) $(GLOBJ)gdevpsd.$(OBJ) : $(GLSRC)gdevpsd.c $(PDEVH) $(math__h)\ $(gdevdcrd_h) $(gscrd_h) $(gscrdp_h) $(gsparam_h) $(gxlum_h)\ $(gstypes_h) $(gxdcconv_h) $(gdevdevn_h) $(gsequivc_h)\ - $(gscms_h) $(gsicc_cache_h) $(gsicc_manage_h) + $(gscms_h) $(gsicc_cache_h) $(gsicc_manage_h) $(gxgetbit_h)\ + $(gdevppla_h) $(GLCC) $(GLO_)gdevpsd.$(OBJ) $(C_) $(GLSRC)gdevpsd.c $(GLOBJ)gsequivc.$(OBJ) : $(GLSRC)gsequivc.c $(math__h)\ @@ -1694,7 +1695,8 @@ $(DD)tiffgray.dev : $(DEVS_MAK) $(libtiff_dev) $(tiffgray_) $(DD)tiffs.dev\ $(ADDMOD) $(DD)tiffgray -include $(DD)tiffs $(tiff_i_) $(GLOBJ)gdevtsep.$(OBJ) : $(GLSRC)gdevtsep.c $(PDEVH) $(stdint__h)\ - $(gdevtifs_h) $(gdevdevn_h) $(gsequivc_h) $(stdio__h) $(ctype__h) $(GDEV) + $(gdevtifs_h) $(gdevdevn_h) $(gsequivc_h) $(stdio__h) $(ctype__h)\ + $(gxgetbit_h) $(gdevppla_h) $(GDEV) $(GLCC) $(I_)$(TI_)$(_I) $(GLO_)gdevtsep.$(OBJ) $(C_) $(GLSRC)gdevtsep.c # TIFF Scaled (downscaled gray -> mono), configurable compression diff --git a/gs/base/gdevbbox.c b/gs/base/gdevbbox.c index b608fca95..597ea2701 100644 --- a/gs/base/gdevbbox.c +++ b/gs/base/gdevbbox.c @@ -50,6 +50,7 @@ static dev_proc_draw_thin_line(bbox_draw_thin_line); static dev_proc_strip_tile_rectangle(bbox_strip_tile_rectangle); static dev_proc_strip_copy_rop(bbox_strip_copy_rop); static dev_proc_strip_copy_rop2(bbox_strip_copy_rop2); +static dev_proc_strip_tile_rect_devn(bbox_strip_tile_rect_devn); static dev_proc_begin_typed_image(bbox_begin_typed_image); static dev_proc_create_compositor(bbox_create_compositor); static dev_proc_text_begin(bbox_text_begin); @@ -153,7 +154,8 @@ gx_device_bbox gs_bbox_device = NULL, /* copy_planes */ NULL, /* get_profile */ NULL, /* set_graphics_type_tag */ - bbox_strip_copy_rop2 + bbox_strip_copy_rop2, + bbox_strip_tile_rect_devn }, 0, /* target */ 1, /*true *//* free_standing */ @@ -478,6 +480,22 @@ bbox_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tiles, } static int +bbox_strip_tile_rect_devn(gx_device * dev, const gx_strip_bitmap * tiles, + int x, int y, int w, int h, const gx_drawing_color *pdcolor0, + const gx_drawing_color *pdcolor1, int px, int py) +{ + gx_device_bbox *const bdev = (gx_device_bbox *) dev; + /* Skip the call if there is no target. */ + gx_device *tdev = bdev->target; + int code = + (tdev == 0 ? 0 : + dev_proc(tdev, strip_tile_rect_devn) + (tdev, tiles, x, y, w, h, pdcolor0, pdcolor1, px, py)); + BBOX_ADD_INT_RECT(bdev, x, y, x + w, y + h); + return code; +} + +static int bbox_strip_copy_rop(gx_device * dev, const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id, diff --git a/gs/base/gdevdbit.c b/gs/base/gdevdbit.c index 9631517a1..cd56347ac 100644 --- a/gs/base/gdevdbit.c +++ b/gs/base/gdevdbit.c @@ -374,6 +374,18 @@ gx_default_fill_mask(gx_device * orig_dev, x, y, w, h, dev, lop, false); } +/* Default implementation of strip_tile_rect_devn. With the current design + only devices that support devn color will be making use of this + procedure and those are planar devices. So we have an implemenation + for planar devices and not a default implemenetation at this time. */ +int +gx_default_strip_tile_rect_devn(gx_device * dev, const gx_strip_bitmap * tiles, + int x, int y, int w, int h, const gx_drawing_color * pdcolor0, + const gx_drawing_color * pdcolor1, int px, int py) +{ + return_error(gs_error_unregistered); +} + /* Default implementation of strip_tile_rectangle */ int gx_default_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tiles, @@ -450,18 +462,32 @@ gx_default_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tiles, dev_proc_copy_mono((*proc_mono)); dev_proc_copy_color((*proc_color)); + dev_proc_copy_planes((*proc_planes)); int code; - if (color0 == gx_no_color_index && color1 == gx_no_color_index) - proc_color = dev_proc(dev, copy_color), proc_mono = 0; - else - proc_color = 0, proc_mono = dev_proc(dev, copy_mono); + if (color0 == gx_no_color_index && color1 == gx_no_color_index) { + if (tiles->num_planes > 1) { + proc_mono = 0; + proc_color = 0; + proc_planes = dev_proc(dev, copy_planes); + } else { + proc_planes = 0; + proc_color = dev_proc(dev, copy_color); + proc_mono = 0; + } + } else { + proc_planes = 0; + proc_color = 0; + proc_mono = dev_proc(dev, copy_mono); + } #define real_copy_tile(srcx, tx, ty, tw, th, id)\ code =\ + (tiles->num_planes > 1 ?\ + (*proc_planes)(dev, row, srcx, raster, id, tx, ty, tw, th, height) :\ (proc_color != 0 ?\ (*proc_color)(dev, row, srcx, raster, id, tx, ty, tw, th) :\ - (*proc_mono)(dev, row, srcx, raster, id, tx, ty, tw, th, color0, color1));\ + (*proc_mono)(dev, row, srcx, raster, id, tx, ty, tw, th, color0, color1)));\ if (code < 0) return_error(code);\ return_if_interrupt(dev->memory) #ifdef DEBUG diff --git a/gs/base/gdevdevn.c b/gs/base/gdevdevn.c index 4b6a38e67..fd30bbaea 100644 --- a/gs/base/gdevdevn.c +++ b/gs/base/gdevdevn.c @@ -239,7 +239,7 @@ devn_get_color_comp_index(gx_device * dev, gs_devn_params * pdevn_params, * Note: Most device do not allow more spot colors than we can * image. (See the options for auto_spot_color in gdevdevn.h.) */ - if (color_component_number >= dev->color_info.num_components) + if (color_component_number >= dev->color_info.max_components) color_component_number = GX_DEVICE_COLOR_MAX_COMPONENTS; return color_component_number; @@ -254,17 +254,24 @@ devn_get_color_comp_index(gx_device * dev, gs_devn_params * pdevn_params, auto_spot_colors == NO_AUTO_SPOT_COLORS || pdevn_params->num_separation_order_names != 0) return -1; /* Do not add --> indicate colorant unknown. */ + + /* Make sure the name is not "None" this is sometimes + within a DeviceN list and should not be added as one of the + separations. */ + if (strncmp(pname, "None", name_size) == 0) { + return -1; + } + /* * Check if we have room for another spot colorant. */ if (auto_spot_colors == ENABLE_AUTO_SPOT_COLORS) - max_spot_colors = dev->color_info.num_components - + max_spot_colors = dev->color_info.max_components - pdevn_params->num_std_colorant_names; if (pdevn_params->separations.num_separations < max_spot_colors) { byte * sep_name; gs_separations * separations = &pdevn_params->separations; int sep_num = separations->num_separations++; - /* We have a new spot colorant - put in stable memory to avoid "restore" */ sep_name = gs_alloc_bytes(dev->memory->stable_memory, name_size, "devn_get_color_comp_index"); @@ -272,7 +279,7 @@ devn_get_color_comp_index(gx_device * dev, gs_devn_params * pdevn_params, separations->names[sep_num].size = name_size; separations->names[sep_num].data = sep_name; color_component_number = sep_num + pdevn_params->num_std_colorant_names; - if (color_component_number >= dev->color_info.num_components) + if (color_component_number >= dev->color_info.max_components) color_component_number = GX_DEVICE_COLOR_MAX_COMPONENTS; else pdevn_params->separation_order_map[color_component_number] = @@ -384,8 +391,9 @@ devn_put_params(gx_device * pdev, gs_param_list * plist, int num_names = scna.size; fixed_colorant_names_list pcomp_names = pdevn_params->std_colorant_names; - - for (i = num_spot = 0; i < num_names; i++) { + /* Start the num_spot count after the std. colorants */ + num_spot = pdevn_params->num_std_colorant_names; + for (i = 0; i < num_names; i++) { /* Verify that the name is not one of our process colorants */ if (!check_process_color_names(pcomp_names, &scna.data[i])) { byte * sep_name; @@ -405,9 +413,9 @@ devn_put_params(gx_device * pdev, gs_param_list * plist, num_spot++; } } - pdevn_params->separations.num_separations = num_spot; + pdevn_params->separations.num_separations = num_spot - npcmcolors; num_spot_changed = true; - for (i = 0; i < num_spot + npcmcolors; i++) + for (i = npcmcolors; i < num_spot; i++) pdevn_params->separation_order_map[i] = i; } /* @@ -417,9 +425,6 @@ devn_put_params(gx_device * pdev, gs_param_list * plist, int i, comp_num; num_order = sona.size; - for (i = 0; i < num_spot + npcmcolors; i++) - pdevn_params->separation_order_map[i] = - GX_DEVICE_COLOR_MAX_COMPONENTS; for (i = 0; i < num_order; i++) { /* * Check if names match either the process color model or @@ -429,7 +434,7 @@ devn_put_params(gx_device * pdev, gs_param_list * plist, (const char *)sona.data[i].data, sona.data[i].size, 0)) < 0) { return_error(gs_error_rangecheck); } - pdevn_params->separation_order_map[comp_num] = i; + pdevn_params->separation_order_map[comp_num] = comp_num; } } /* @@ -881,9 +886,12 @@ free_separation_names(gs_memory_t * mem, int i; /* Discard the sub levels. */ - for (i = 0; i < pseparation->num_separations; i++) + for (i = 0; i < pseparation->num_separations; i++) { gs_free_object(mem->stable_memory, pseparation->names[i].data, "free_separation_names"); + pseparation->names[i].data = NULL; + pseparation->names[i].size = 0; + } pseparation->num_separations = 0; return; } diff --git a/gs/base/gdevdevn.h b/gs/base/gdevdevn.h index 1b590780d..d9b1d124a 100644 --- a/gs/base/gdevdevn.h +++ b/gs/base/gdevdevn.h @@ -45,7 +45,8 @@ * * To disable compression of encoded colorant values, change this definition. */ -#define USE_COMPRESSED_ENCODING (ARCH_SIZEOF_GX_COLOR_INDEX >= 8) +#define USE_COMPRESSED_ENCODING 0 +/* #define USE_COMPRESSED_ENCODING (ARCH_SIZEOF_GX_COLOR_INDEX >= 8) */ /* * Type definitions associated with the fixed color model names. diff --git a/gs/base/gdevdflt.c b/gs/base/gdevdflt.c index feae1824f..06ba6019e 100644 --- a/gs/base/gdevdflt.c +++ b/gs/base/gdevdflt.c @@ -560,6 +560,7 @@ gx_device_fill_in_procs(register gx_device * dev) fill_dev_proc(dev, strip_tile_rectangle, gx_default_strip_tile_rectangle); fill_dev_proc(dev, strip_copy_rop, gx_default_strip_copy_rop); fill_dev_proc(dev, strip_copy_rop2, gx_default_strip_copy_rop2); + fill_dev_proc(dev, strip_tile_rect_devn, gx_default_strip_tile_rect_devn); fill_dev_proc(dev, get_clipping_box, gx_default_get_clipping_box); fill_dev_proc(dev, begin_typed_image, gx_default_begin_typed_image); fill_dev_proc(dev, get_bits_rectangle, gx_default_get_bits_rectangle); @@ -922,6 +923,8 @@ gx_default_dev_spec_op(gx_device *pdev, int dev_spec_op, void *data, int size) case gxdso_pattern_handles_clip_path: case gxdso_is_pdf14_device: case gxdso_is_native_planar: + case gxdso_supports_devn: + case gxdso_supports_hlcolor: return 0; case gxdso_pattern_shfill_doesnt_need_path: return (pdev->procs.fill_path == gx_default_fill_path); diff --git a/gs/base/gdevdsha.c b/gs/base/gdevdsha.c index a72cff418..fda77b09f 100644 --- a/gs/base/gdevdsha.c +++ b/gs/base/gdevdsha.c @@ -18,6 +18,165 @@ #include "gxdevice.h" #include "gxcindex.h" #include "vdtrace.h" +#include "gxdevsop.h" + +static bool +gx_devn_diff(frac31 devn1[], frac31 devn2[], int num) +{ + int k; + + for (k = 0; k < num; k++) { + if (devn1[k] != devn2[k]) { + return true; + } + } + return false; +} + +int +gx_hl_fill_linear_color_scanline(gx_device *dev, const gs_fill_attributes *fa, + int i0, int j, int w, const frac31 *c0, const int32_t *c0f, + const int32_t *cg_num, int32_t cg_den) +{ + frac31 c[GX_DEVICE_COLOR_MAX_COMPONENTS]; + frac31 curr[GX_DEVICE_COLOR_MAX_COMPONENTS]; + ulong f[GX_DEVICE_COLOR_MAX_COMPONENTS]; + int i, i1 = i0 + w, bi = i0, k; + const gx_device_color_info *cinfo = &dev->color_info; + int n = cinfo->num_components; + int si, ei, di, code; + gs_fixed_rect rect; + gx_device_color devc; + + /* Note: All the stepping math is done with frac color values */ + + devc.type = gx_dc_type_devn; + + if (j < fixed2int(fa->clip->p.y) || + j > fixed2int_ceiling(fa->clip->q.y)) /* Must be compatible to the clipping logic. */ + return 0; + for (k = 0; k < n; k++) { + curr[k] = c[k] = c0[k]; + f[k] = c0f[k]; + } + for (i = i0 + 1, di = 1; i < i1; i += di) { + if (di == 1) { + /* Advance colors by 1 pixel. */ + for (k = 0; k < n; k++) { + if (cg_num[k]) { + int32_t m = f[k] + cg_num[k]; + + c[k] += m / cg_den; + m -= m / cg_den * cg_den; + if (m < 0) { + c[k]--; + m += cg_den; + } + f[k] = m; + } + } + } else { + /* Advance colors by di pixels. */ + for (k = 0; k < n; k++) { + if (cg_num[k]) { + int64_t M = f[k] + (int64_t)cg_num[k] * di; + int32_t m; + + c[k] += (frac31)(M / cg_den); + m = (int32_t)(M - M / cg_den * cg_den); + if (m < 0) { + c[k]--; + m += cg_den; + } + f[k] = m; + } + } + } + if (gx_devn_diff(c, curr, n)) { + si = max(bi, fixed2int(fa->clip->p.x)); /* Must be compatible to the clipping logic. */ + ei = min(i, fixed2int_ceiling(fa->clip->q.x)); /* Must be compatible to the clipping logic. */ + if (si < ei) { + if (fa->swap_axes) { + rect.p.x = j; + rect.p.y = si; + rect.q.x = j + 1; + rect.q.y = ei; + } else { + rect.p.x = si; + rect.p.y = j; + rect.q.x = ei; + rect.q.y = j + 1; + } + for (k = 0; k < n; k++) { + devc.colors.devn.values[k] = frac2cv(curr[k]); + } + code = dev_proc(dev, fill_rectangle_hl_color) (dev, &rect, NULL, &devc, NULL); + if (code < 0) + return code; + } + bi = i; + for (k = 0; k < n; k++) { + curr[k] = c[k]; + } + di = 1; + } else if (i == i1) { + i++; + break; + } else { + /* Compute a color change pixel analitically. */ + di = i1 - i; + for (k = 0; k < n; k++) { + int32_t a; + int64_t x; + frac31 v = 1 << (31 - cinfo->comp_bits[k]); /* Color index precision in frac31. */ + frac31 u = c[k] & (v - 1); + + if (cg_num[k] == 0) { + /* No change. */ + continue; + } if (cg_num[k] > 0) { + /* Solve[(f[k] + cg_num[k]*x)/cg_den == v - u, x] */ + a = v - u; + } else { + /* Solve[(f[k] + cg_num[k]*x)/cg_den == - u - 1, x] */ + a = -u - 1; + } + x = ((int64_t)a * cg_den - f[k]) / cg_num[k]; + if (i + x >= i1) + continue; + else if (x < 0) + return_error(gs_error_unregistered); /* Must not happen. */ + else if (di > (int)x) { + di = (int)x; + if (di <= 1) { + di = 1; + break; + } + } + } + } + } + si = max(bi, fixed2int(fa->clip->p.x)); /* Must be compatible to the clipping logic. */ + ei = min(i, fixed2int_ceiling(fa->clip->q.x)); /* Must be compatible to the clipping logic. */ + if (si < ei) { + if (fa->swap_axes) { + rect.p.x = j; + rect.p.y = si; + rect.q.x = j + 1; + rect.q.y = ei; + } else { + rect.p.x = si; + rect.p.y = j; + rect.q.x = ei; + rect.q.y = j + 1; + } + for (k = 0; k < n; k++) { + devc.colors.devn.values[k] = frac2cv(curr[k]); + } + return dev_proc(dev, fill_rectangle_hl_color) (dev, &rect, NULL, &devc, NULL); + } + return 0; +} int gx_default_fill_linear_color_scanline(gx_device *dev, const gs_fill_attributes *fa, @@ -30,6 +189,8 @@ gx_default_fill_linear_color_scanline(gx_device *dev, const gs_fill_attributes * i.e. with enumerating planes first, with a direct writing to the raster, and with a fixed bits per component. */ + /* First determine if we are doing high level style colors or pure colors */ + bool devn = dev_proc(dev, dev_spec_op)(dev, gxdso_supports_devn, NULL, 0); frac31 c[GX_DEVICE_COLOR_MAX_COMPONENTS]; ulong f[GX_DEVICE_COLOR_MAX_COMPONENTS]; int i, i1 = i0 + w, bi = i0, k; @@ -38,6 +199,10 @@ gx_default_fill_linear_color_scanline(gx_device *dev, const gs_fill_attributes * int n = cinfo->num_components; int si, ei, di, code; + /* Todo: set this up to vector earlier */ + if (devn && cinfo->polarity == GX_CINFO_POLARITY_SUBTRACTIVE) + return gx_hl_fill_linear_color_scanline(dev, fa, i0, j, w, c0, c0f, + cg_num, cg_den); if (j < fixed2int(fa->clip->p.y) || j > fixed2int_ceiling(fa->clip->q.y)) /* Must be compatible to the clipping logic. */ return 0; diff --git a/gs/base/gdevmem.c b/gs/base/gdevmem.c index 7b1e17b8f..f4c2901e5 100644 --- a/gs/base/gdevmem.c +++ b/gs/base/gdevmem.c @@ -81,7 +81,9 @@ const gs_const_string mem_mono_w_b_palette = { /* ------ Generic code ------ */ /* Return the appropriate memory device for a given */ -/* number of bits per pixel (0 if none suitable). */ +/* number of bits per pixel (0 if none suitable). + Greater than 64 occurs for the planar case + which we will then return a mem_x_device */ static const gx_device_memory *const mem_devices[65] = { 0, &mem_mono_device, &mem_mapped2_device, 0, &mem_mapped4_device, 0, 0, 0, &mem_mapped8_device, @@ -96,7 +98,7 @@ static const gx_device_memory *const mem_devices[65] = { const gx_device_memory * gdev_mem_device_for_bits(int bits_per_pixel) { - return ((uint)bits_per_pixel > 64 ? (const gx_device_memory *)0 : + return ((uint)bits_per_pixel > 64 ? &mem_x_device : mem_devices[bits_per_pixel]); } /* Do the same for a word-oriented device. */ @@ -129,12 +131,10 @@ gs_device_is_memory(const gx_device * dev) int bits_per_pixel = dev->color_info.depth; const gx_device_memory *mdproto; - if ((uint)bits_per_pixel > 64) - return false; - mdproto = mem_devices[bits_per_pixel]; + mdproto = gdev_mem_device_for_bits(bits_per_pixel); if (mdproto != 0 && dev_proc(dev, draw_thin_line) == dev_proc(mdproto, draw_thin_line)) return true; - mdproto = mem_word_devices[bits_per_pixel]; + mdproto = gdev_mem_word_device_for_bits(bits_per_pixel); return (mdproto != 0 && dev_proc(dev, draw_thin_line) == dev_proc(mdproto, draw_thin_line)); } diff --git a/gs/base/gdevmem.h b/gs/base/gdevmem.h index 559e603ff..e64e7666c 100644 --- a/gs/base/gdevmem.h +++ b/gs/base/gdevmem.h @@ -210,6 +210,7 @@ extern const gx_device_memory mem_true40_device; extern const gx_device_memory mem_true48_device; extern const gx_device_memory mem_true56_device; extern const gx_device_memory mem_true64_device; +extern const gx_device_memory mem_x_device; extern const gx_device_memory mem_planar_device; /* * We declare the RasterOp implementation procedures here because they are diff --git a/gs/base/gdevmpla.c b/gs/base/gdevmpla.c index 5459d5126..306c3c06d 100644 --- a/gs/base/gdevmpla.c +++ b/gs/base/gdevmpla.c @@ -29,10 +29,14 @@ declare_mem_procs(mem_planar_copy_mono, mem_planar_copy_color, mem_planar_fill_r static dev_proc_copy_color(mem_planar_copy_color_24to8); static dev_proc_copy_color(mem_planar_copy_color_4to1); static dev_proc_copy_planes(mem_planar_copy_planes); +/* Not static due to an optimized case in tile_clip_fill_rectangle_hl_color*/ static dev_proc_strip_tile_rectangle(mem_planar_strip_tile_rectangle); +static dev_proc_strip_tile_rect_devn(mem_planar_strip_tile_rect_devn); static dev_proc_strip_copy_rop(mem_planar_strip_copy_rop); static dev_proc_strip_copy_rop2(mem_planar_strip_copy_rop2); static dev_proc_get_bits_rectangle(mem_planar_get_bits_rectangle); +static dev_proc_fill_rectangle_hl_color(mem_planar_fill_rectangle_hl_color); +static dev_proc_put_image(mem_planar_put_image); /* It's a bit nasty to have to fork the planar dev_spec_op like this, but * the forwarding nature of the device means that the function pointer test @@ -42,8 +46,16 @@ static int mem_planar_dev_spec_op(gx_device *pdev, int dev_spec_op, void *data, int size) { + cmm_dev_profile_t *dev_profile; + if (dev_spec_op == gxdso_is_native_planar) return 1; + if (dev_spec_op == gxdso_supports_devn) { + dev_proc(pdev, get_profile)(pdev, &dev_profile); + if (dev_profile != NULL && dev_profile->supports_devn && + pdev->procs.fill_rectangle_hl_color == mem_planar_fill_rectangle_hl_color) + return 1; + } return gx_default_dev_spec_op(pdev, dev_spec_op, data, size); } @@ -118,6 +130,15 @@ gdev_mem_set_planar(gx_device_memory * mdev, int num_planes, set_dev_proc(mdev, strip_copy_rop2, dev_proc(mdproto, strip_copy_rop2)); set_dev_proc(mdev, get_bits_rectangle, dev_proc(mdproto, get_bits_rectangle)); } else { + /* If we are going out to a separation device or one that has more than + four planes then use the high level color filling procedure. Also + make use of the put_image operation to go from the pdf14 device + directly to the planar buffer. */ + if (mdev->num_planes >= 4) { + set_dev_proc(mdev, fill_rectangle_hl_color, + mem_planar_fill_rectangle_hl_color); + set_dev_proc(mdev, put_image, mem_planar_put_image); + } set_dev_proc(mdev, fill_rectangle, mem_planar_fill_rectangle); set_dev_proc(mdev, copy_mono, mem_planar_copy_mono); set_dev_proc(mdev, dev_spec_op, mem_planar_dev_spec_op); @@ -140,6 +161,7 @@ gdev_mem_set_planar(gx_device_memory * mdev, int num_planes, set_dev_proc(mdev, copy_alpha, gx_default_copy_alpha); set_dev_proc(mdev, copy_planes, mem_planar_copy_planes); set_dev_proc(mdev, strip_tile_rectangle, mem_planar_strip_tile_rectangle); + set_dev_proc(mdev, strip_tile_rect_devn, mem_planar_strip_tile_rect_devn); set_dev_proc(mdev, strip_copy_rop, mem_planar_strip_copy_rop); set_dev_proc(mdev, strip_copy_rop2, mem_planar_strip_copy_rop2); set_dev_proc(mdev, get_bits_rectangle, mem_planar_get_bits_rectangle); @@ -190,6 +212,59 @@ typedef struct mem_save_params_s { mdev->base = msp.base,\ mdev->line_ptrs = msp.line_ptrs) +/* Put image command for copying the planar image buffers with or without + alpha directly to the device buffer */ +static int +mem_planar_put_image(gx_device *pdev, const byte *buffer, int num_chan, int xstart, + int ystart, int width, int height, int row_stride, + int plane_stride, int alpha_plane_index, int tag_plane_index) +{ + gx_device_memory * const mdev = (gx_device_memory *)pdev; + + /* We don't want alpha, return 0 to ask for the pdf14 device to do the + alpha composition. We also do not want chunky data coming in or to deal + with planar devices that are not 8 bit per colorant */ + if (alpha_plane_index != 0 || plane_stride == 0 || + mdev->planes[0].depth != 8) + return 0; + + (*dev_proc(pdev, copy_planes)) (pdev, buffer, 0, row_stride, + gx_no_bitmap_id, xstart, ystart, + width, height, plane_stride/row_stride); + /* we used all of the data */ + return height; +} + +/* Fill a rectangle with a high level color. This is used for separation + devices. (e.g. tiffsep, psdcmyk) */ +static int +mem_planar_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect, + const gs_imager_state *pis, const gx_drawing_color *pdcolor, + const gx_clip_path *pcpath) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + mem_save_params_t save; + int pi; + + MEM_SAVE_PARAMS(mdev, save); + for (pi = 0; pi < mdev->num_planes; ++pi) { + int plane_depth = mdev->planes[pi].depth; + gx_color_index mask = ((gx_color_index)1 << plane_depth) - 1; + int shift = 16 - plane_depth; + const gx_device_memory *mdproto = gdev_mem_device_for_bits(plane_depth); + + MEM_SET_PARAMS(mdev, plane_depth); + dev_proc(mdproto, fill_rectangle)(dev, rect->p.x, rect->p.y, + rect->q.x - rect->p.x, + rect->q.y - rect->p.y, + (pdcolor->colors.devn.values[pi]) >> + shift & mask); + mdev->line_ptrs += mdev->height; + } + MEM_RESTORE_PARAMS(mdev, save); + return 0; +} + /* Fill a rectangle with a color. */ static int mem_planar_fill_rectangle(gx_device * dev, int x, int y, int w, int h, @@ -853,7 +928,55 @@ mem_planar_copy_planes(gx_device * dev, const byte * base, int sourcex, return code; } -static int +int +mem_planar_strip_tile_rect_devn(gx_device * dev, const gx_strip_bitmap * tiles, + int x, int y, int w, int h, + const gx_drawing_color *pdcolor0, + const gx_drawing_color *pdcolor1, int px, int py) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + mem_save_params_t save; + int pi; + + MEM_SAVE_PARAMS(mdev, save); + for (pi = 0; pi < mdev->num_planes; ++pi) { + int plane_depth = mdev->planes[pi].depth; + gx_color_index mask = ((gx_color_index)1 << plane_depth) - 1; + int shift = 16 - plane_depth; + const gx_device_memory *mdproto = + gdev_mem_device_for_bits(plane_depth); + gx_color_index c1, c0; + + if (pdcolor0->type == gx_dc_type_pure) { + c0 = gx_no_color_index; + } else { + c0 = (pdcolor0->colors.devn.values[pi]) >> shift & mask; + } + if (pdcolor1->type == gx_dc_type_pure) { + c1 = gx_no_color_index; + } else { + c1 = (pdcolor1->colors.devn.values[pi]) >> shift & mask; + } + MEM_SET_PARAMS(mdev, plane_depth); + if (c0 == c1) + dev_proc(mdproto, fill_rectangle)(dev, x, y, w, h, c0); + else { + /* + * Temporarily replace copy_mono in case strip_tile_rectangle is + * defined in terms of it. + */ + set_dev_proc(dev, copy_mono, dev_proc(mdproto, copy_mono)); + dev_proc(mdproto, strip_tile_rectangle) + (dev, tiles, x, y, w, h, c0, c1, px, py); + } + mdev->line_ptrs += mdev->height; + } + MEM_RESTORE_PARAMS(mdev, save); + set_dev_proc(dev, copy_mono, mem_planar_copy_mono); + return 0; +} + +int mem_planar_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tiles, int x, int y, int w, int h, gx_color_index color0, gx_color_index color1, diff --git a/gs/base/gdevmx.c b/gs/base/gdevmx.c new file mode 100644 index 000000000..57263abb5 --- /dev/null +++ b/gs/base/gdevmx.c @@ -0,0 +1,26 @@ +/* Copyright (C) 2001-2006 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or + implied. + + This software is distributed under license and may not be copied, modified + or distributed except as expressly authorized under the terms of that + license. Refer to licensing information at http://www.artifex.com/ + or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, + San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. +*/ +/* $Id$ */ +/* x-bit-per-pixel "memory" (stored bitmap) device. */ +/* This is used as a prototype for a memory device for the planar device + to make use of in creating its structure for bit depths greater than + 64. Note that the 256 is a place holder. */ +#include "memory_.h" +#include "gx.h" +#include "gxdevice.h" +#include "gxdevmem.h" /* semi-public definitions */ +#include "gdevmem.h" /* private definitions */ + +/* The device descriptor. */ +const gx_device_memory mem_x_device = + mem_device("imagex", 256, 0, NULL, NULL, NULL, NULL, NULL, NULL); diff --git a/gs/base/gdevnfwd.c b/gs/base/gdevnfwd.c index 571e54aa8..ef65431ff 100644 --- a/gs/base/gdevnfwd.c +++ b/gs/base/gdevnfwd.c @@ -111,6 +111,7 @@ gx_device_forward_fill_in_procs(register gx_device_forward * dev) fill_dev_proc(dev, get_profile, gx_forward_get_profile); fill_dev_proc(dev, set_graphics_type_tag, gx_forward_set_graphics_type_tag); fill_dev_proc(dev, strip_copy_rop2, gx_forward_strip_copy_rop2); + fill_dev_proc(dev, strip_tile_rect_devn, gx_forward_strip_tile_rect_devn); gx_device_fill_in_procs((gx_device *) dev); } @@ -603,6 +604,22 @@ gx_forward_strip_copy_rop2(gx_device * dev, const byte * sdata, int sourcex, } } +int +gx_forward_strip_tile_rect_devn(gx_device * dev, const gx_strip_bitmap * tiles, + int x, int y, int w, int h, const gx_drawing_color * pdcolor0, + const gx_drawing_color * pdcolor1, int px, int py) +{ + gx_device_forward * const fdev = (gx_device_forward *)dev; + gx_device *tdev = fdev->target; + + if (tdev == 0) + return gx_default_strip_tile_rect_devn(dev, tiles, x, y, w, h, pdcolor0, + pdcolor1, px, py); + else + return dev_proc(tdev, strip_tile_rect_devn)(dev, tiles, x, y, w, h, + pdcolor0, pdcolor1, px, py); +} + void gx_forward_get_clipping_box(gx_device * dev, gs_fixed_rect * pbox) { @@ -1004,6 +1021,7 @@ static dev_proc_decode_color(null_decode_color); /* Y position so it can return 1 when done. */ static dev_proc_strip_copy_rop(null_strip_copy_rop); static dev_proc_strip_copy_rop2(null_strip_copy_rop2); +static dev_proc_strip_tile_rect_devn(null_strip_tile_rect_devn); #define null_procs(get_initial_matrix, get_page_device) {\ gx_default_open_device,\ @@ -1075,7 +1093,8 @@ static dev_proc_strip_copy_rop2(null_strip_copy_rop2); NULL, /* copy_planes */\ NULL, /* get_profile */\ NULL, /* set_graphics_type_tag */\ - null_strip_copy_rop2\ + null_strip_copy_rop2,\ + null_strip_tile_rect_devn\ } #define NULLD_X_RES 72 @@ -1241,6 +1260,14 @@ null_strip_copy_rop2(gx_device * dev, const byte * sdata, int sourcex, return 0; } +static int +null_strip_tile_rect_devn(gx_device * dev, const gx_strip_bitmap * tiles, + int x, int y, int w, int h, const gx_drawing_color * pdcolor0, + const gx_drawing_color * pdcolor1, int px, int py) +{ + return 0; +} + bool fwd_uses_fwd_cmap_procs(gx_device * dev) { diff --git a/gs/base/gdevp14.c b/gs/base/gdevp14.c index bb82d33b2..2e653ceea 100644 --- a/gs/base/gdevp14.c +++ b/gs/base/gdevp14.c @@ -80,6 +80,13 @@ static int pdf14_clist_update_params(pdf14_clist_device * pdev, const gs_imager_state * pis, bool crop_blend_params, gs_pdf14trans_params_t *group_params); +static int pdf14_mark_fill_rectangle(gx_device * dev, int x, int y, int w, int h, + gx_color_index color, const gx_device_color *pdc, + bool devn); +static int pdf14_mark_fill_rectangle_ko_simple(gx_device * dev, int x, int y, + int w, int h, gx_color_index color, + const gx_device_color *pdc, + bool devn); /* Functions for dealing with soft mask color */ static int pdf14_decrement_smask_color(gs_imager_state * pis, gx_device * dev); @@ -156,8 +163,7 @@ dev_proc_encode_color(pdf14_compressed_encode_color); dev_proc_decode_color(pdf14_decode_color); dev_proc_decode_color(pdf14_compressed_decode_color); static dev_proc_fill_rectangle(pdf14_fill_rectangle); -static dev_proc_fill_rectangle(pdf14_mark_fill_rectangle); -static dev_proc_fill_rectangle(pdf14_mark_fill_rectangle_ko_simple); +static dev_proc_fill_rectangle_hl_color(pdf14_fill_rectangle_hl_color); static dev_proc_fill_path(pdf14_fill_path); static dev_proc_copy_mono(pdf14_copy_mono); static dev_proc_fill_mask(pdf14_fill_mask); @@ -176,6 +182,7 @@ static dev_proc_push_transparency_state(pdf14_push_transparency_state); static dev_proc_pop_transparency_state(pdf14_pop_transparency_state); static dev_proc_ret_devn_params(pdf14_ret_devn_params); static dev_proc_copy_alpha(pdf14_copy_alpha); +static dev_proc_copy_planes(pdf14_copy_planes); static const gx_color_map_procs * pdf14_get_cmap_procs(const gs_imager_state *, const gx_device *); @@ -243,7 +250,7 @@ static const gx_color_map_procs * encode_color, /* encode_color */\ decode_color, /* decode_color */\ NULL, /* pattern_manage */\ - NULL, /* fill_rectangle_hl_color */\ + pdf14_fill_rectangle_hl_color, /* fill_rectangle_hl_color */\ NULL, /* include_color_space */\ NULL, /* fill_linear_color_scanline */\ NULL, /* fill_linear_color_trapezoid */\ @@ -254,7 +261,8 @@ static const gx_color_map_procs * pdf14_push_transparency_state, /* push_transparency_state */\ pdf14_pop_transparency_state, /* pop_transparency_state */\ NULL, /* put_image */\ - pdf14_dev_spec_op /* dev_spec_op */\ + pdf14_dev_spec_op, /* dev_spec_op */\ + pdf14_copy_planes /* copy_planes */\ } static const gx_device_procs pdf14_Gray_procs = @@ -1695,7 +1703,8 @@ pdf14_cmykspot_put_image(gx_device * dev, gs_imager_state * pis, gx_device * tar clist_band_count++; #endif return gx_put_blended_image_cmykspot(target, buf_ptr, planestride, rowstride, - rect.p.x, rect.p.y, width, height, num_comp, bg, pseparations); + rect.p.x, rect.p.y, width, height, num_comp, bg, + buf->has_tags, rect, pseparations); } /** @@ -1799,6 +1808,7 @@ gs_pdf14_device_copy_params(gx_device *dev, const gx_device *target) &(profile_targ)); profile_dev14->device_profile[0] = profile_targ->device_profile[0]; dev->icc_struct->devicegraytok = profile_targ->devicegraytok; + dev->icc_struct->supports_devn = profile_targ->supports_devn; gx_monitor_enter(profile_dev14->device_profile[0]->lock); rc_increment(profile_dev14->device_profile[0]); gx_monitor_leave(profile_dev14->device_profile[0]->lock); @@ -2692,6 +2702,7 @@ pdf14_forward_device_procs(gx_device * dev) */ set_dev_proc(dev, close_device, gx_forward_close_device); set_dev_proc(dev, fill_rectangle, gx_forward_fill_rectangle); + set_dev_proc(dev, fill_rectangle_hl_color, gx_forward_fill_rectangle_hl_color); set_dev_proc(dev, tile_rectangle, gx_forward_tile_rectangle); set_dev_proc(dev, copy_mono, gx_forward_copy_mono); set_dev_proc(dev, copy_color, gx_forward_copy_color); @@ -2844,9 +2855,11 @@ get_pdf14_device_proto(gx_device * dev, pdf14_device ** pdevproto, ptempdevproto->devn_params.num_std_colorant_names + pdf14pct->params.num_spot_colors; if (ptempdevproto->color_info.num_components > - ptempdevproto->color_info.max_components) + GS_CLIENT_COLOR_MAX_COMPONENTS) ptempdevproto->color_info.num_components = - ptempdevproto->color_info.max_components; + GS_CLIENT_COLOR_MAX_COMPONENTS; + ptempdevproto->color_info.depth = + ptempdevproto->color_info.num_components * 8; *pdevproto = ptempdevproto; } break; @@ -3160,6 +3173,77 @@ pdf14_copy_mono(gx_device * dev, return 0; } +/* Used in a few odd cases where the target device is planar and we have + a planar tile (pattern) and we are copying it into place here */ + +static int +pdf14_copy_planes(gx_device * dev, const byte * data, int data_x, int raster, + gx_bitmap_id id, int x, int y, int w, int h, int plane_height) +{ + pdf14_device *pdev = (pdf14_device *)dev; +#if RAW_DUMP + pdf14_ctx *ctx = pdev->ctx; +#endif + pdf14_buf *buf = pdev->ctx->stack; + int num_planes = dev->color_info.num_components; + byte *dptr = data + data_x; + int yinc, xinc, pi; + gx_drawing_color dcolor; + int code = 0; + + fit_fill_xywh(dev, x, y, w, h); + if (w <= 0 || h <= 0) + return 0; + + dcolor.type = gx_dc_type_devn; + /* Because of the complexity of the blending and my desire to finish + this planar sep device work, I am going to make this a series of + rect fills. ToDo: optimize this for more efficient planar operation. + It would be interesting to use the put_image procedure. */ + for (yinc = 0; yinc < h; yinc++) { + for (xinc = 0; xinc < w; xinc++) { + for (pi = 0; pi < num_planes; pi++) { + dcolor.colors.devn.values[pi] = + *(dptr + plane_height * raster * pi) << 8; + } + if (buf->knockout) + code = + pdf14_mark_fill_rectangle_ko_simple(dev, x + xinc, + y + yinc, 1, 1, 0, + &dcolor, true); + else + code = + pdf14_mark_fill_rectangle(dev, x + xinc, y + yinc, 1, 1, 0, + &dcolor, true); + dptr++; + } + dptr = data + raster * yinc + data_x; + } + return code; +} + +static int +pdf14_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect, + const gs_imager_state *pis, const gx_drawing_color *pdcolor, + const gx_clip_path *pcpath) +{ + pdf14_device *pdev = (pdf14_device *)dev; + pdf14_buf *buf = pdev->ctx->stack; + int x = rect->p.x; + int y = rect->p.y; + int w = rect->q.x - x; + int h = rect->q.y -y; + + fit_fill_xywh(dev, x, y, w, h); + if (w <= 0 || h <= 0) + return 0; + if (buf->knockout) + return pdf14_mark_fill_rectangle_ko_simple(dev, x, y, w, h, 0, pdcolor, + true); + else + return pdf14_mark_fill_rectangle(dev, x, y, w, h, 0, pdcolor, true); +} + static int pdf14_fill_rectangle(gx_device * dev, int x, int y, int w, int h, gx_color_index color) @@ -3171,9 +3255,10 @@ pdf14_fill_rectangle(gx_device * dev, if (w <= 0 || h <= 0) return 0; if (buf->knockout) - return pdf14_mark_fill_rectangle_ko_simple(dev, x, y, w, h, color); + return pdf14_mark_fill_rectangle_ko_simple(dev, x, y, w, h, color, NULL, + false); else - return pdf14_mark_fill_rectangle(dev, x, y, w, h, color); + return pdf14_mark_fill_rectangle(dev, x, y, w, h, color, NULL, false); } static int @@ -4065,8 +4150,9 @@ pdf14_end_transparency_mask(gx_device *dev, gs_imager_state *pis, } static int -pdf14_mark_fill_rectangle(gx_device * dev, - int x, int y, int w, int h, gx_color_index color) +pdf14_mark_fill_rectangle(gx_device * dev, int x, int y, int w, int h, + gx_color_index color, const gx_device_color *pdc, + bool devn) { pdf14_device *pdev = (pdf14_device *)dev; pdf14_buf *buf = pdev->ctx->stack; @@ -4078,7 +4164,7 @@ pdf14_mark_fill_rectangle(gx_device * dev, bool additive = pdev->ctx->additive; int rowstride = buf->rowstride; int planestride = buf->planestride; - gs_graphics_type_tag_t curr_tag; + gs_graphics_type_tag_t curr_tag = GS_UNKNOWN_TAG; /* Quite compiler */ bool has_alpha_g = buf->has_alpha_g; bool has_shape = buf->has_shape; bool has_tags = buf->has_tags; @@ -4092,6 +4178,9 @@ pdf14_mark_fill_rectangle(gx_device * dev, gx_color_index comps; byte shape = 0; /* Quiet compiler. */ byte src_alpha; + gx_color_index mask = ((gx_color_index)1 << 8) - 1; + int shift = 8; + if (buf->data == NULL) return 0; @@ -4113,7 +4202,18 @@ pdf14_mark_fill_rectangle(gx_device * dev, if (has_tags) { curr_tag = (color >> (num_comp*8)) & 0xff; } - pdev->pdf14_procs->unpack_color(num_comp, color, pdev, src); + if (devn) { + if (additive) { + for (j = 0; j < num_comp; j++) { + src[j] = ((pdc->colors.devn.values[j]) >> shift & mask); + } + } else { + for (j = 0; j < num_comp; j++) { + src[j] = 255 - ((pdc->colors.devn.values[j]) >> shift & mask); + } + } + } else + pdev->pdf14_procs->unpack_color(num_comp, color, pdev, src); src_alpha = src[num_comp] = (byte)floor (255 * pdev->alpha + 0.5); if (has_shape) shape = (byte)floor (255 * pdev->shape + 0.5); @@ -4205,8 +4305,9 @@ pdf14_mark_fill_rectangle(gx_device * dev, } static int -pdf14_mark_fill_rectangle_ko_simple(gx_device * dev, - int x, int y, int w, int h, gx_color_index color) +pdf14_mark_fill_rectangle_ko_simple(gx_device * dev, int x, int y, int w, int h, + gx_color_index color, + const gx_device_color *pdc, bool devn) { pdf14_device *pdev = (pdf14_device *)dev; pdf14_buf *buf = pdev->ctx->stack; @@ -4226,6 +4327,8 @@ pdf14_mark_fill_rectangle_ko_simple(gx_device * dev, bool has_tags = buf->has_tags; bool additive = pdev->ctx->additive; gs_graphics_type_tag_t curr_tag = dev->graphics_type_tag & ~GS_DEVICE_ENCODES_TAGS; + gx_color_index mask = ((gx_color_index)1 << 8) - 1; + int shift = 8; if (buf->data == NULL) return 0; @@ -4246,7 +4349,18 @@ pdf14_mark_fill_rectangle_ko_simple(gx_device * dev, if (has_tags) { curr_tag = (color >> (num_comp*8)) & 0xff; } - pdev->pdf14_procs->unpack_color(num_comp, color, pdev, src); + if (devn) { + if (additive) { + for (j = 0; j < num_comp; j++) { + src[j] = ((pdc->colors.devn.values[j]) >> shift & mask); + } + } else { + for (j = 0; j < num_comp; j++) { + src[j] = 255 - ((pdc->colors.devn.values[j]) >> shift & mask); + } + } + } else + pdev->pdf14_procs->unpack_color(num_comp, color, pdev, src); src[num_comp] = (byte)floor (255 * pdev->alpha + 0.5); /* Fit the mark into the bounds of the buffer */ if (x < buf->rect.p.x) { @@ -4442,9 +4556,19 @@ pdf14_cmap_cmyk_direct(frac c, frac m, frac y, frac k, gx_device_color * pdc, dev_proc(trans_device, get_color_mapping_procs)(trans_device)->map_cmyk(trans_device, c, m, y, k, cm_comps); for (i = 0; i < ncomps; i++) cv[i] = frac2cv(cm_comps[i]); - color = dev_proc(trans_device, encode_color)(trans_device, cv); - if (color != gx_no_color_index) - color_set_pure(pdc, color); + /* if output device supports devn, we need to make sure we send it the + proper color type */ + if (dev_proc(trans_device, dev_spec_op)(trans_device, gxdso_supports_devn, NULL, 0)) { + for (i = 0; i < ncomps; i++) + pdc->colors.devn.values[i] = cv[i]; + pdc->type = gx_dc_type_devn; + } else { + /* encode as a color index */ + color = dev_proc(trans_device, encode_color)(trans_device, cv); + /* check if the encoding was successful; we presume failure is rare */ + if (color != gx_no_color_index) + color_set_pure(pdc, color); + } } /* color mapping for when we have an smask or a isolated transparency group with @@ -4667,11 +4791,20 @@ pdf14_cmap_separation_direct(frac all, gx_device_color * pdc, const gs_imager_st for (i = 0; i < ncomps; i++) cv[i] = frac2cv(frac_1 - gx_map_color_frac(pis, (frac)(frac_1 - cm_comps[i]), effective_transfer[i])); - /* encode as a color index */ - color = dev_proc(dev, encode_color)(dev, cv); - /* check if the encoding was successful; we presume failure is rare */ - if (color != gx_no_color_index) - color_set_pure(pdc, color); + + /* if output device supports devn, we need to make sure we send it the + proper color type */ + if (dev_proc(dev, dev_spec_op)(dev, gxdso_supports_devn, NULL, 0)) { + for (i = 0; i < ncomps; i++) + pdc->colors.devn.values[i] = cv[i]; + pdc->type = gx_dc_type_devn; + } else { + /* encode as a color index */ + color = dev_proc(dev, encode_color)(dev, cv); + /* check if the encoding was successful; we presume failure is rare */ + if (color != gx_no_color_index) + color_set_pure(pdc, color); + } } static void @@ -4707,11 +4840,19 @@ pdf14_cmap_devicen_direct(const frac * pcc, for (i = 0; i < ncomps; i++) cv[i] = frac2cv(frac_1 - gx_map_color_frac(pis, (frac)(frac_1 - cm_comps[i]), effective_transfer[i])); + /* if output device supports devn, we need to make sure we send it the + proper color type */ + if (dev_proc(trans_device, dev_spec_op)(trans_device, gxdso_supports_devn, NULL, 0)) { + for (i = 0; i < ncomps; i++) + pdc->colors.devn.values[i] = cv[i]; + pdc->type = gx_dc_type_devn; + } else { /* encode as a color index */ - color = dev_proc(trans_device, encode_color)(trans_device, cv); - /* check if the encoding was successful; we presume failure is rare */ - if (color != gx_no_color_index) - color_set_pure(pdc, color); + color = dev_proc(trans_device, encode_color)(trans_device, cv); + /* check if the encoding was successful; we presume failure is rare */ + if (color != gx_no_color_index) + color_set_pure(pdc, color); + } } static bool @@ -4750,6 +4891,27 @@ pdf14_dev_spec_op(gx_device *pdev, int dev_spec_op, return 1; } } + if (dev_spec_op == gxdso_is_native_planar) { + /* Only return true here if the target is planar. While the pdf14 + device is planar, the underlying buffers for the target + device is what is being asked about */ + gx_device_forward * fdev = (gx_device_forward *)pdev; + gx_device * target = fdev->target; + if (target != NULL) { + return dev_proc(target, dev_spec_op)(target, gxdso_is_native_planar, + NULL, 0); + } else return 0; + } + if (dev_spec_op == gxdso_supports_devn) { + cmm_dev_profile_t *dev_profile; + int code; + code = dev_proc(pdev, get_profile)((gx_device*) pdev, &dev_profile); + if (code == 0) { + return dev_profile->supports_devn; + } else { + return 0; + } + } return gx_default_dev_spec_op(pdev, dev_spec_op, data, size); } @@ -5597,7 +5759,7 @@ send_pdf14trans(gs_imager_state * pis, gx_device * dev, encode_color, /* encode_color */\ decode_color, /* decode_color */\ NULL, /* pattern_manage */\ - NULL, /* fill_rectangle_hl_color */\ + gx_forward_fill_rectangle_hl_color, /* fill_rectangle_hl_color */\ NULL, /* include_color_space */\ NULL, /* fill_linear_color_scanline */\ NULL, /* fill_linear_color_trapezoid */\ @@ -5788,6 +5950,8 @@ get_pdf14_clist_device_proto(gx_device * dev, pdf14_clist_device ** pdevproto, ptempdevproto->color_info.max_components) ptempdevproto->color_info.num_components = ptempdevproto->color_info.max_components; + ptempdevproto->color_info.depth = + ptempdevproto->color_info.num_components * 8; } *pdevproto = ptempdevproto; break; @@ -5866,6 +6030,13 @@ pdf14_create_clist_device(gs_memory_t *mem, gs_imager_state * pis, pdev->my_decode_color = pdev->procs.decode_color; pdev->my_get_color_mapping_procs = pdev->procs.get_color_mapping_procs; pdev->my_get_color_comp_index = pdev->procs.get_color_comp_index; + /* The number of color planes should not exceed that of the target */ + if (pdev->color_info.num_components > target->color_info.num_components) + pdev->color_info.num_components = target->color_info.num_components; + if (pdev->color_info.max_components > target->color_info.max_components) + pdev->color_info.max_components = target->color_info.max_components; + pdev->color_info.separable_and_linear = + target->color_info.separable_and_linear; *ppdev = (gx_device *) pdev; return code; } @@ -7522,4 +7693,4 @@ pdf14_debug_mask_stack_state(pdf14_ctx *ctx) } #endif -#endif +#endif
\ No newline at end of file diff --git a/gs/base/gdevpdfi.c b/gs/base/gdevpdfi.c index 85d043475..4b84ea4a6 100644 --- a/gs/base/gdevpdfi.c +++ b/gs/base/gdevpdfi.c @@ -1504,6 +1504,12 @@ gdev_pdf_dev_spec_op(gx_device *pdev1, int dev_spec_op, void *data, int size) In this case pdfwrite converts the object into rectangles, and the clipping device has to be set up. */ return 0; + case gxdso_supports_hlcolor: + /* This is used due to some aliasing between the rect_hl color + filling used by pdfwrite vs. that used by the planar device + which is actually a devn vs. the pattern type for pdfwrite. + We use this to distingush between the two */ + return 1; } return gx_default_dev_spec_op(pdev1, dev_spec_op, data, size); } diff --git a/gs/base/gdevppla.c b/gs/base/gdevppla.c index 7d835a616..5efcbd028 100644 --- a/gs/base/gdevppla.c +++ b/gs/base/gdevppla.c @@ -84,21 +84,23 @@ static int gdev_prn_set_planar(gx_device_memory *mdev, const gx_device *tdev) { int num_comp = tdev->color_info.num_components; - gx_render_plane_t planes[4]; + gx_render_plane_t planes[GX_DEVICE_COLOR_MAX_COMPONENTS]; int depth = tdev->color_info.depth / num_comp; + int k; - if (num_comp < 1 || num_comp > 4) + if (num_comp < 1 || num_comp > GX_DEVICE_COLOR_MAX_COMPONENTS) return_error(gs_error_rangecheck); /* Round up the depth per plane to a power of 2. */ while (depth & (depth - 1)) --depth, depth = (depth | (depth >> 1)) + 1; - planes[3].depth = planes[2].depth = planes[1].depth = planes[0].depth = - depth; + /* We want the most significant plane to come out first. */ - planes[0].shift = depth * (num_comp - 1); - planes[1].shift = planes[0].shift - depth; - planes[2].shift = planes[1].shift - depth; - planes[3].shift = 0; + planes[num_comp-1].shift = 0; + planes[num_comp-1].depth = depth; + for (k = (num_comp - 2); k >= 0; k--) { + planes[k].depth = depth; + planes[k].shift = planes[k + 1].shift + depth; + } return gdev_mem_set_planar(mdev, num_comp, planes); } diff --git a/gs/base/gdevprn.c b/gs/base/gdevprn.c index 486cb7695..877ac4342 100644 --- a/gs/base/gdevprn.c +++ b/gs/base/gdevprn.c @@ -418,7 +418,8 @@ gdev_prn_allocate(gx_device *pdev, gdev_prn_space_params *new_space_params, COPY_PROC(decode_color); COPY_PROC(update_spot_equivalent_colors); COPY_PROC(ret_devn_params); - COPY_PROC(put_image); + /* This can be set from the memory device (planar) or target */ + fill_dev_proc(ppdev, put_image, ppdev->orig_procs.put_image); #undef COPY_PROC /* If using a command list, already opened the device. */ if (is_command_list) diff --git a/gs/base/gdevpsd.c b/gs/base/gdevpsd.c index ffa945745..226f291fd 100644 --- a/gs/base/gdevpsd.c +++ b/gs/base/gdevpsd.c @@ -28,6 +28,10 @@ #include "gscms.h" #include "gsicc_cache.h" #include "gsicc_manage.h" +#include "gxgetbit.h" +#include "gdevppla.h" + +#define PSD_PLANAR 1 #ifndef cmm_gcmmhlink_DEFINED #define cmm_gcmmhlink_DEFINED @@ -64,10 +68,13 @@ static dev_proc_map_color_rgb(psd_map_color_rgb); static dev_proc_get_color_mapping_procs(get_psdrgb_color_mapping_procs); static dev_proc_get_color_mapping_procs(get_psd_color_mapping_procs); static dev_proc_get_color_comp_index(psd_get_color_comp_index); +#if PSD_PLANAR static dev_proc_encode_color(psd_encode_color); static dev_proc_decode_color(psd_decode_color); +#else static dev_proc_encode_color(psd_encode_compressed_color); static dev_proc_decode_color(psd_decode_compressed_color); +#endif static dev_proc_update_spot_equivalent_colors(psd_update_spot_equivalent_colors); static dev_proc_ret_devn_params(psd_ret_devn_params); @@ -115,6 +122,8 @@ typedef struct psd_device_s { cmm_profile_t *output_profile; gcmmhlink_t output_icc_link; + bool warning_given; /* Used to notify the user that max colorants reached */ + } psd_device; /* GC procedures */ @@ -341,7 +350,43 @@ const psd_device gs_psdcmyk_device = int psd_prn_open(gx_device * pdev) { +#if PSD_PLANAR + psd_device *pdev_psd = (psd_device *) pdev; + int code; + + pdev_psd->warning_given = false; + /* With planar the depth can be more than 64. Update the color + info to reflect the proper depth and number of planes. Also note + that the number of spot colors can change from page to page. + Update things so that we only output separations for the + inks on that page. */ + if (pdev_psd->devn_params.page_spot_colors >= 0) { + pdev->color_info.num_components = + (pdev_psd->devn_params.page_spot_colors + + pdev_psd->devn_params.num_std_colorant_names); + if (pdev->color_info.num_components > pdev->color_info.max_components) + pdev->color_info.num_components = pdev->color_info.max_components; + } else { + /* We do not know how many spots may occur on the page. + For this reason we go ahead and allocate the maximum that we + have available. Note, lack of knowledge only occurs in the case + of PS files. With PDF we know a priori the number of spot + colorants. */ + pdev->color_info.num_components = GS_CLIENT_COLOR_MAX_COMPONENTS; + pdev->color_info.max_components = GS_CLIENT_COLOR_MAX_COMPONENTS; + } + pdev->color_info.depth = pdev->color_info.num_components * + pdev_psd->devn_params.bitspercomponent; + pdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN; + pdev->icc_struct->supports_devn = true; + code = gdev_prn_open_planar(pdev, true); + return code; +#else int code = gdev_prn_open(pdev); + psd_device *pdev_psd = (psd_device *) pdev; + + pdev_psd->warning_given = false; +#endif #if !USE_COMPRESSED_ENCODING /* @@ -566,6 +611,7 @@ get_psd_color_mapping_procs(const gx_device * dev) return NULL; } +#if PSD_PLANAR /* * Encode a list of colorant values into a gx_color_index_value. */ @@ -605,7 +651,7 @@ psd_decode_color(gx_device * dev, gx_color_index color, gx_color_value * out) } return 0; } - +#else /* * Encode a list of colorant values into a gx_color_index_value. * With 64 bit gx_color_index values, we compress the colorant values. This @@ -628,7 +674,7 @@ psd_decode_compressed_color(gx_device * dev, gx_color_index color, gx_color_valu return devn_decode_compressed_color(dev, color, out, &(((psd_device *)dev)->devn_params)); } - +#endif /* * Convert a gx_color_index to RGB. */ @@ -925,10 +971,25 @@ static int psd_get_color_comp_index(gx_device * dev, const char * pname, int name_size, int component_type) { - return devn_get_color_comp_index(dev, + int index; + psd_device *pdev = (psd_device *)dev; + + if (strncmp(pname, "None", name_size) == 0) return -1; + index = devn_get_color_comp_index(dev, &(((psd_device *)dev)->devn_params), &(((psd_device *)dev)->equiv_cmyk_colors), pname, name_size, component_type, ENABLE_AUTO_SPOT_COLORS); + /* This is a one shot deal. That is it will simply post a notice once that + some colorants will be converted due to a limit being reached. It will + not list names of colorants since then I would need to keep track of + which ones I have already mentioned */ + if (index < 0 && component_type == SEPARATION_NAME && + pdev->warning_given == false) { + dlprintf("**** Max spot colorants reached.\n"); + dlprintf("**** Some colorants will be converted to equivalent CMYK values.\n"); + pdev->warning_given = true; + } + return index; } /* ------ Private definitions ------ */ @@ -1200,6 +1261,94 @@ psd_prn_close(gx_device *dev) * data, we will write out any separation data which is specified in the * SeparationOrder data. */ + +#if PSD_PLANAR +static int +psd_write_image_data(psd_write_ctx *xc, gx_device_printer *pdev) +{ + int raster_plane = bitmap_raster(pdev->width * 8); + byte *planes[GS_CLIENT_COLOR_MAX_COMPONENTS]; + int code = 0; + int i, j; + byte *sep_line; + int base_bytes_pp = xc->base_bytes_pp; + int chan_idx; +/* psd_device *xdev = (psd_device *)pdev; + gcmmhlink_t link = xdev->output_icc_link; */ + byte * unpacked; + int num_comp = xc->num_channels; + gs_int_rect rect; + gs_get_bits_params_t params; + + rect.q.x = pdev->width; + rect.p.x = 0; + /* Return planar data */ + params.options = (GB_RETURN_POINTER | GB_RETURN_COPY | + GB_ALIGN_STANDARD | GB_OFFSET_0 | GB_RASTER_STANDARD | + GB_PACKING_PLANAR | GB_COLORS_NATIVE | GB_ALPHA_NONE); + params.x_offset = 0; + params.raster = bitmap_raster(pdev->width * pdev->color_info.depth); + psd_write_16(xc, 0); /* Compression */ + + sep_line = gs_alloc_bytes(pdev->memory, xc->width, "psd_write_sep_line"); + + for (chan_idx = 0; chan_idx < num_comp; chan_idx++) { + planes[chan_idx] = gs_alloc_bytes(pdev->memory, raster_plane, + "psd_write_sep_line"); + params.data[chan_idx] = planes[chan_idx]; + if (params.data[chan_idx] == NULL) + return_error(gs_error_VMerror); + } + + if (sep_line == NULL) + return_error(gs_error_VMerror); + + /* Print the output planes */ + for (chan_idx = 0; chan_idx < num_comp; chan_idx++) { + int data_pos = xc->chnl_to_position[chan_idx]; + if (data_pos >= 0) { + for (j = 0; j < xc->height; ++j) { + rect.p.y = j; + rect.q.y = j + 1; + code = dev_proc(pdev, get_bits_rectangle) + ((gx_device *) pdev, &rect, ¶ms, NULL); + + unpacked = params.data[data_pos]; + /* To do, get ICC stuff in place for planar device */ + // if (link == NULL) { + if (base_bytes_pp == 3) { + /* RGB */ + memcpy(unpacked, sep_line, xc->width); + } else { + for (i = 0; i < xc->width; ++i) { + /* CMYK + spots*/ + sep_line[i] = 255 - unpacked[i]; + } + } + /* } else { + psd_calib_row((gx_device*) xdev, xc, &sep_line, unpacked, data_pos, + link, xdev->output_profile->num_comps, + xdev->output_profile->num_comps_out); + } */ + psd_write(xc, sep_line, xc->width); + } + } else { + if (chan_idx < NUM_CMYK_COMPONENTS) { + /* Write empty process color in the area */ + memset(sep_line,255,xc->width); + psd_write(xc, sep_line, xc->width); + } + } + } + + gs_free_object(pdev->memory, sep_line, "psd_write_sep_line"); + for (chan_idx = 0; chan_idx < num_comp; chan_idx++) { + gs_free_object(pdev->memory, planes[chan_idx], + "psd_write_image_data"); + } + return code; +} +#else static int psd_write_image_data(psd_write_ctx *xc, gx_device_printer *pdev) { @@ -1262,22 +1411,25 @@ psd_write_image_data(psd_write_ctx *xc, gx_device_printer *pdev) } } } - gs_free_object(pdev->memory, sep_line, "psd_write_sep_line"); gs_free_object(pdev->memory, line, "psd_write_image_data"); return code; } +#endif static int psd_print_page(gx_device_printer *pdev, FILE *file) { psd_write_ctx xc; + psd_device *psd_dev = (psd_device *)pdev; xc.f = file; - psd_setup(&xc, (psd_device *)pdev); - psd_write_header(&xc, (psd_device *)pdev); + psd_setup(&xc, psd_dev); + psd_write_header(&xc, psd_dev); psd_write_image_data(&xc, pdev); - + /* Free up the list of spot names as they were only relevent to that page */ + free_separation_names(pdev->memory, &(psd_dev->devn_params.separations)); + psd_dev->devn_params.num_separation_order_names = 0; return 0; -} +}
\ No newline at end of file diff --git a/gs/base/gdevtsep.c b/gs/base/gdevtsep.c index e413d992d..15e276a22 100644 --- a/gs/base/gdevtsep.c +++ b/gs/base/gdevtsep.c @@ -34,6 +34,10 @@ #include "gxiodev.h" #include "stdio_.h" #include "ctype_.h" +#include "gxgetbit.h" +#include "gdevppla.h" + +#define TIFFSEP_PLANAR 1 /* * Some of the code in this module is based upon the gdevtfnx.c module. @@ -421,6 +425,7 @@ static dev_proc_fill_path(sep1_fill_path); typedef struct tiffsep_device_s { tiffsep_devices_common; TIFF *tiff_comp; /* tiff file for comp file */ + bool warning_given; } tiffsep_device; /* threshold array structure */ @@ -1038,15 +1043,23 @@ tiffsep_get_color_comp_index(gx_device * dev, const char * pname, int name_size, int component_type) { tiffsep_device * pdev = (tiffsep_device *) dev; + int index; - /* - * We allow more spot colors than we can image. This allows the user - * to obtain separations for more than our max of 8 by doing multiple - * passes. - */ - return devn_get_color_comp_index(dev, + if (strncmp(pname, "None", name_size) == 0) return -1; + index = devn_get_color_comp_index(dev, &(pdev->devn_params), &(pdev->equiv_cmyk_colors), - pname, name_size, component_type, ALLOW_EXTRA_SPOT_COLORS); + pname, name_size, component_type, ENABLE_AUTO_SPOT_COLORS); + /* This is a one shot deal. That is it will simply post a notice once that + some colorants will be converted due to a limit being reached. It will + not list names of colorants since then I would need to keep track of + which ones I have already mentioned */ + if (index < 0 && component_type == SEPARATION_NAME && + pdev->warning_given == false) { + dlprintf("**** Max spot colorants reached.\n"); + dlprintf("**** Some colorants will be converted to equivalent CMYK values.\n"); + pdev->warning_given = true; + } + return index; } /* @@ -1220,11 +1233,50 @@ build_comp_to_sep_map(tiffsep_device * pdev, short * map_comp_to_sep) } } -/* Open the tiffsep device */ +/* Open the tiffsep device. This will now be using planar buffers so that + we are not limited to 64 bit chunky */ int tiffsep_prn_open(gx_device * pdev) { + +#if TIFFSEP_PLANAR + gx_device_printer * const ppdev = (gx_device_printer *)pdev; + tiffsep_device *pdev_sep = (tiffsep_device *) pdev; + int code; + + /* With planar the depth can be more than 64. Update the color + info to reflect the proper depth and number of planes */ + + pdev_sep->warning_given = false; + if (pdev_sep->devn_params.page_spot_colors >= 0) { + pdev->color_info.num_components = + (pdev_sep->devn_params.page_spot_colors + + pdev_sep->devn_params.num_std_colorant_names); + if (pdev->color_info.num_components > pdev->color_info.max_components) + pdev->color_info.num_components = pdev->color_info.max_components; + } else { + /* We do not know how many spots may occur on the page. + For this reason we go ahead and allocate the maximum that we + have available. Note, lack of knowledge only occurs in the case + of PS files. With PDF we know a priori the number of spot + colorants. */ + pdev->color_info.num_components = GS_CLIENT_COLOR_MAX_COMPONENTS; + pdev->color_info.max_components = GS_CLIENT_COLOR_MAX_COMPONENTS; + } + pdev->color_info.depth = pdev->color_info.num_components * + pdev_sep->devn_params.bitspercomponent; + pdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN; + code = gdev_prn_open_planar(pdev, true); + ppdev->file = NULL; + if (ppdev->OpenOutputFile) + code = gdev_prn_open_printer_seekable(pdev, 1, true); + pdev->icc_struct->supports_devn = true; + return code; +#else int code = tiff_open(pdev); + tiffsep_device *pdev_sep = (tiffsep_device *) pdev; + pdev_sep->warning_given = false; +#endif #if !USE_COMPRESSED_ENCODING /* @@ -1342,6 +1394,53 @@ build_cmyk_map(tiffsep_device * pdev, int num_comp, } } +#if TIFFSEP_PLANAR +/* + * Build a CMYK equivalent to a raster line from planar buffer + */ +static void +build_cmyk_raster_line_fromplanar(gs_get_bits_params_t params, byte * dest, int width, + int num_comp, cmyk_composite_map * cmyk_map) +{ + int pixel, comp_num; + uint temp, cyan, magenta, yellow, black; + cmyk_composite_map * cmyk_map_entry; + + for (pixel = 0; pixel < width; pixel++) { + cmyk_map_entry = cmyk_map; + temp = *(params.data[0] + pixel); + cyan = cmyk_map_entry->c * temp; + magenta = cmyk_map_entry->m * temp; + yellow = cmyk_map_entry->y * temp; + black = cmyk_map_entry->k * temp; + cmyk_map_entry++; + for (comp_num = 1; comp_num < num_comp; comp_num++) { + temp = *(params.data[comp_num] + pixel); + cyan += cmyk_map_entry->c * temp; + magenta += cmyk_map_entry->m * temp; + yellow += cmyk_map_entry->y * temp; + black += cmyk_map_entry->k * temp; + cmyk_map_entry++; + } + cyan /= frac_1; + magenta /= frac_1; + yellow /= frac_1; + black /= frac_1; + if (cyan > MAX_COLOR_VALUE) + cyan = MAX_COLOR_VALUE; + if (magenta > MAX_COLOR_VALUE) + magenta = MAX_COLOR_VALUE; + if (yellow > MAX_COLOR_VALUE) + yellow = MAX_COLOR_VALUE; + if (black > MAX_COLOR_VALUE) + black = MAX_COLOR_VALUE; + *dest++ = cyan; + *dest++ = magenta; + *dest++ = yellow; + *dest++ = black; + } +} +#else /* * Build a CMYK equivalent to a raster line. */ @@ -1387,6 +1486,7 @@ build_cmyk_raster_line(byte * src, byte * dest, int width, *dest++ = black; } } +#endif static int sep1_ht_order_to_thresholds(gx_device *pdev, const gs_imager_state *pis) @@ -1657,6 +1757,68 @@ tiffsep_print_page(gx_device_printer * pdev, FILE * file) build_cmyk_map(tfdev, num_comp, map_comp_to_sep, cmyk_map); +#if TIFFSEP_PLANAR + { + int raster_plane = bitmap_raster(pdev->width * 8); + byte *planes[GS_CLIENT_COLOR_MAX_COMPONENTS]; + int width = tfdev->width; + int cmyk_raster = width * NUM_CMYK_COMPONENTS; + int pixel, y; + byte * sep_line; + + sep_line = + gs_alloc_bytes(pdev->memory, cmyk_raster, "tiffsep_print_page"); + + for (comp_num = 0; comp_num < num_comp; comp_num++ ) + TIFFCheckpointDirectory(tfdev->tiff[comp_num]); + TIFFCheckpointDirectory(tfdev->tiff_comp); + + /* Write the page data. */ + { + gs_int_rect rect; + gs_get_bits_params_t params; + + rect.q.x = pdev->width; + rect.p.x = 0; + /* Return planar data */ + params.options = (GB_RETURN_POINTER | GB_RETURN_COPY | + GB_ALIGN_STANDARD | GB_OFFSET_0 | GB_RASTER_STANDARD | + GB_PACKING_PLANAR | GB_COLORS_NATIVE | GB_ALPHA_NONE); + params.x_offset = 0; + params.raster = bitmap_raster(pdev->width * pdev->color_info.depth); + for (comp_num = 0; comp_num < num_comp; comp_num++) { + planes[comp_num] = gs_alloc_bytes(pdev->memory, raster_plane, + "tiffsep_print_page"); + params.data[comp_num] = planes[comp_num]; + if (params.data[comp_num] == NULL) + return_error(gs_error_VMerror); + } + for (y = 0; y < pdev->height; ++y) { + rect.p.y = y; + rect.q.y = y + 1; + code = dev_proc(pdev, get_bits_rectangle) + ((gx_device *) pdev, &rect, ¶ms, NULL); + /* Write separation data (tiffgray format) */ + for (comp_num = 0; comp_num < num_comp; comp_num++ ) { + byte * src = params.data[comp_num]; + byte * dest = sep_line; + + for (pixel = 0; pixel < width; pixel++, dest++, src++) + *dest = MAX_COLOR_VALUE - *src; /* Gray is additive */ + TIFFWriteScanline(tfdev->tiff[comp_num], (tdata_t)sep_line, y, 0); + } + /* Write CMYK equivalent data (tiff32nc format) */ + build_cmyk_raster_line_fromplanar(params, sep_line, + width, num_comp, cmyk_map); + TIFFWriteScanline(tfdev->tiff_comp, (tdata_t)sep_line, y, 0); + } + gs_free_object(pdev->memory, sep_line, "tiffsep_print_page"); + for (comp_num = 0; comp_num < num_comp; comp_num++) { + gs_free_object(pdev->memory, planes[comp_num], + "tiffsep_print_page"); + } + } +#else { int raster = gdev_prn_raster(pdev); int width = tfdev->width; @@ -1664,7 +1826,7 @@ tiffsep_print_page(gx_device_printer * pdev, FILE * file) int pixel, y; byte * line = gs_alloc_bytes(pdev->memory, raster, "tiffsep_print_page"); byte * unpacked = gs_alloc_bytes(pdev->memory, width * num_comp, - "tiffsep_print_page"); + "tiffsep_print_page"); byte * sep_line; byte * row; @@ -1680,7 +1842,6 @@ tiffsep_print_page(gx_device_printer * pdev, FILE * file) for (comp_num = 0; comp_num < num_comp; comp_num++ ) TIFFCheckpointDirectory(tfdev->tiff[comp_num]); TIFFCheckpointDirectory(tfdev->tiff_comp); - /* Write the page data. */ for (y = 0; y < pdev->height; ++y) { code = gdev_prn_get_bits(pdev, y, line, &row); @@ -1703,12 +1864,12 @@ tiffsep_print_page(gx_device_printer * pdev, FILE * file) width, num_comp, cmyk_map); TIFFWriteScanline(tfdev->tiff_comp, (tdata_t)sep_line, y, 0); } + gs_free_object(pdev->memory, line, "tiffsep_print_page"); + gs_free_object(pdev->memory, sep_line, "tiffsep_print_page"); +#endif for (comp_num = 0; comp_num < num_comp; comp_num++ ) TIFFWriteDirectory(tfdev->tiff[comp_num]); TIFFWriteDirectory(tfdev->tiff_comp); - - gs_free_object(pdev->memory, line, "tiffsep_print_page"); - gs_free_object(pdev->memory, sep_line, "tiffsep_print_page"); } #if defined(DEBUG) && 0 @@ -1723,7 +1884,10 @@ tiffsep_print_page(gx_device_printer * pdev, FILE * file) dlprintf1("WARNING: Non encodable pixels = %d\n", non_encodable_count); return_error(gs_error_rangecheck); } - + /* After page is printed free up the separation list since we may have + different spots on the next page */ + free_separation_names(tfdev->memory, &(tfdev->devn_params.separations)); + tfdev->devn_params.num_separation_order_names = 0; return code; } diff --git a/gs/base/gscdevn.c b/gs/base/gscdevn.c index 69a5ee1db..0d01108b1 100644 --- a/gs/base/gscdevn.c +++ b/gs/base/gscdevn.c @@ -535,9 +535,20 @@ check_DeviceN_component_names(const gs_color_space * pcs, gs_state * pgs) pcolor_component_map->color_map[i] = (colorant_number == GX_DEVICE_COLOR_MAX_COMPONENTS) ? -1 : colorant_number; + } else { + if (strncmp((char *) pname, "None", name_size) != 0) { + non_match = true; + } else { + /* Device N includes one or more None Entries. We can't reduce + the number of components in the list count, since the None Name(s) + are present in the list and GCd and we may need the None + entries in the alternate tint trasform calcuation. + So we will detect the presence of them by setting + pcolor_component_map->color_map[i] = -1 and watching + for this case later during the remap operation. */ + pcolor_component_map->color_map[i] = -1; + } } - else - non_match = true; } pcolor_component_map->use_alt_cspace = non_match; return 0; diff --git a/gs/base/gscicach.c b/gs/base/gscicach.c index b0bd536e1..6012ef0fd 100644 --- a/gs/base/gscicach.c +++ b/gs/base/gscicach.c @@ -27,7 +27,11 @@ typedef struct gs_color_index_cache_elem_s gs_color_index_cache_elem_t; struct gs_color_index_cache_elem_s { - gx_color_index cindex; + union _color { + gx_color_index cindex; + ushort devn[GS_CLIENT_COLOR_MAX_COMPONENTS]; + } color; + gx_device_color_type color_type; uint chain; uint prev, next; /* NULL for unused. */ uint touch_prev, touch_next; @@ -183,7 +187,8 @@ include_into_touch_list(gs_color_index_cache_t *self, uint i) } static int -get_color_index_cache_elem(gs_color_index_cache_t *self, const float *paint_values, uint *pi) +get_color_index_cache_elem(gs_color_index_cache_t *self, + const float *paint_values, uint *pi) { int client_num_components = self->client_num_components; uint c = hash_paint_values(self, paint_values); @@ -192,7 +197,8 @@ get_color_index_cache_elem(gs_color_index_cache_t *self, const float *paint_valu if (i != MYNULL) { uint tries = 16; /* Arbitrary. */ - if (!memcmp(paint_values, self->paint_values + i * client_num_components, sizeof(*paint_values) * client_num_components)) { + if (!memcmp(paint_values, self->paint_values + i * client_num_components, + sizeof(*paint_values) * client_num_components)) { if (self->recent_touch != i) { exclude_from_touch_list(self, i); include_into_touch_list(self, i); @@ -201,7 +207,8 @@ get_color_index_cache_elem(gs_color_index_cache_t *self, const float *paint_valu return 1; } for (j = self->buf[i].next; tries -- && j != i; j = self->buf[j].next) { - if (!memcmp(paint_values, self->paint_values + j * client_num_components, sizeof(*paint_values) * client_num_components)) { + if (!memcmp(paint_values, self->paint_values + j * client_num_components, + sizeof(*paint_values) * client_num_components)) { exclude_from_chain(self, j); include_into_chain(self, j, c); if (self->recent_touch != j) { @@ -232,36 +239,60 @@ get_color_index_cache_elem(gs_color_index_cache_t *self, const float *paint_valu static inline void compute_frac_values(gs_color_index_cache_t *self, uint i) { - gx_color_index c = self->buf[i].cindex; + const gx_device_color_info *cinfo = &self->trans_dev->color_info; int device_num_components = self->device_num_components; int j; + gx_color_index c; - for (j = 0; j < device_num_components; j++) { - int shift = cinfo->comp_shift[j]; - int bits = cinfo->comp_bits[j]; - - self->frac_values[i * device_num_components + j] = ((c >> shift) & ((1 << bits) - 1)) << (sizeof(frac31) * 8 - 1 - bits); + if (self->buf[i].color_type == &gx_dc_type_data_pure) { + c = self->buf[i].color.cindex; + for (j = 0; j < device_num_components; j++) { + int shift = cinfo->comp_shift[j]; + int bits = cinfo->comp_bits[j]; + self->frac_values[i * device_num_components + j] = + ((c >> shift) & ((1 << bits) - 1)) << + (sizeof(frac31) * 8 - 1 - bits); + } + self->buf[i].frac_values_done = true; + } else { + /* Must be devn */ + for (j = 0; j < device_num_components; j++) { + self->frac_values[i * device_num_components + j] = + cv2frac(self->buf[i].color.devn[j]); + } + self->buf[i].frac_values_done = true; } - self->buf[i].frac_values_done = true; } int -gs_cached_color_index(gs_color_index_cache_t *self, const float *paint_values, gx_device_color *pdevc, frac31 *frac_values) +gs_cached_color_index(gs_color_index_cache_t *self, const float *paint_values, + gx_device_color *pdevc, frac31 *frac_values) { /* Must return 2 if the color is not pure. See patch_color_to_device_color. */ const gs_color_space *pcs = self->direct_space; int client_num_components = self->client_num_components; int device_num_components = self->device_num_components; - uint i; + uint i, j; int code; if (get_color_index_cache_elem(self, paint_values, &i)) { if (pdevc != NULL) { - pdevc->colors.pure = self->buf[i].cindex; - pdevc->type = &gx_dc_type_data_pure; - memcpy(pdevc->ccolor.paint.values, paint_values, sizeof(*paint_values) * client_num_components); + if (self->buf[i].color_type == &gx_dc_type_data_pure) { + pdevc->colors.pure = self->buf[i].color.cindex; + pdevc->type = &gx_dc_type_data_pure; + memcpy(pdevc->ccolor.paint.values, paint_values, + sizeof(*paint_values) * client_num_components); + } else { + /* devn case */ + for (j = 0; j < device_num_components; j++) { + pdevc->colors.devn.values[j] = self->buf[i].color.devn[j]; + } + pdevc->type = &gx_dc_type_data_devn; + memcpy(pdevc->ccolor.paint.values, paint_values, + sizeof(*paint_values) * client_num_components); + } pdevc->ccolor_valid = true; } if (frac_values != NULL && !self->buf[i].frac_values_done) @@ -272,22 +303,31 @@ gs_cached_color_index(gs_color_index_cache_t *self, const float *paint_values, g if (pdevc == NULL) pdevc = &devc_local; - memcpy(self->paint_values + i * client_num_components, paint_values, sizeof(*paint_values) * client_num_components); - memcpy(fcc.paint.values, paint_values, sizeof(*paint_values) * client_num_components); - code = pcs->type->remap_color(&fcc, pcs, pdevc, self->pis, self->trans_dev, - gs_color_select_texture); + memcpy(self->paint_values + i * client_num_components, paint_values, + sizeof(*paint_values) * client_num_components); + memcpy(fcc.paint.values, paint_values, + sizeof(*paint_values) * client_num_components); + code = pcs->type->remap_color(&fcc, pcs, pdevc, self->pis, + self->trans_dev, gs_color_select_texture); if (code < 0) return code; - if (pdevc->type != &gx_dc_type_data_pure) + if (pdevc->type == &gx_dc_type_data_pure) { + self->buf[i].color.cindex = pdevc->colors.pure; + } else if (pdevc->type == &gx_dc_type_data_devn) { + for (j = 0; j < device_num_components; j++) { + self->buf[i].color.devn[j] = pdevc->colors.devn.values[j]; + } + } else { return 2; - self->buf[i].cindex = pdevc->colors.pure; - + } + self->buf[i].color_type = pdevc->type; if (frac_values != NULL) compute_frac_values(self, i); else self->buf[i].frac_values_done = false; } if (frac_values != NULL) - memcpy(frac_values, self->frac_values + i * device_num_components, sizeof(*frac_values) * device_num_components); + memcpy(frac_values, self->frac_values + i * device_num_components, + sizeof(*frac_values) * device_num_components); return 0; } diff --git a/gs/base/gscms.h b/gs/base/gscms.h index bad3ae685..c4ed7eb5e 100644 --- a/gs/base/gscms.h +++ b/gs/base/gscms.h @@ -161,6 +161,7 @@ typedef struct cmm_dev_profile_s { gsicc_rendering_intents_t intent[NUM_DEVICE_PROFILES]; bool devicegraytok; /* Used for forcing gray to pure black */ bool usefastcolor; /* Used when we want to use no cm */ + bool supports_devn; /* If the target handles devn colors */ gs_memory_t *memory; rc_header rc; } cmm_dev_profile_t; diff --git a/gs/base/gscsepr.c b/gs/base/gscsepr.c index f377b225a..021109758 100644 --- a/gs/base/gscsepr.c +++ b/gs/base/gscsepr.c @@ -449,7 +449,7 @@ check_Separation_component_name(const gs_color_space * pcs, gs_state * pgs) */ colorant_number = (*dev_proc(dev, get_color_comp_index)) (dev, (const char *)pname, name_size, SEPARATION_NAME); - if (colorant_number >= 0) { /* If valid colorant name */ + if (colorant_number >= 0 && colorant_number < dev->color_info.max_components) { /* If valid colorant name */ pcolor_component_map->color_map[0] = (colorant_number == GX_DEVICE_COLOR_MAX_COMPONENTS) ? -1 : colorant_number; diff --git a/gs/base/gsdcolor.h b/gs/base/gsdcolor.h index 031851fd3..ac56d2d76 100644 --- a/gs/base/gsdcolor.h +++ b/gs/base/gsdcolor.h @@ -292,6 +292,9 @@ struct gx_device_color_s { struct _pat { gx_color_tile *p_tile; } /*(colored) */ pattern; + struct _devn { + ushort values[GS_CLIENT_COLOR_MAX_COMPONENTS]; + } devn; } colors; gs_int_point phase; /* @@ -376,6 +379,9 @@ struct gx_device_color_saved_s { uint c_level[GX_DEVICE_COLOR_MAX_COMPONENTS]; ushort alpha; } colored; + struct _svdevn { + ushort values[GX_DEVICE_COLOR_MAX_COMPONENTS]; + } devn; struct _pattern { gs_id id; gs_int_point phase; @@ -406,6 +412,9 @@ extern const gx_device_color_type_t *const gx_dc_type_null; /* gxdcolor.c */ #ifndef gx_dc_type_pure extern const gx_device_color_type_t *const gx_dc_type_pure; /* gxdcolor.c */ #endif +#ifndef gx_dc_type_devn +extern const gx_device_color_type_t *const gx_dc_type_devn; /* gxdcolor.c */ +#endif /* * We don't declare gx_dc_pattern here, so as not to create * a spurious external reference in Level 1 systems. diff --git a/gs/base/gsdps1.c b/gs/base/gsdps1.c index 21a8fd426..c7717a2a8 100644 --- a/gs/base/gsdps1.c +++ b/gs/base/gsdps1.c @@ -29,6 +29,7 @@ #include "gzcpath.h" #include "gzstate.h" #include "gsutil.h" +#include "gxdevsop.h" /* * Define how much rounding slop setbbox should leave, @@ -192,10 +193,9 @@ gs_rectfill(gs_state * pgs, const gs_rect * pr, uint count) gx_device_color *pdc = gs_currentdevicecolor_inline(pgs); const gs_imager_state *pis = (const gs_imager_state *)pgs; bool hl_color_available = gx_hld_is_hl_color_available(pis, pdc); - gs_fixed_rect empty = {{0, 0}, {0, 0}}; bool hl_color = (hl_color_available && - dev_proc(pdev, fill_rectangle_hl_color)(pdev, - &empty, pis, pdc, NULL) == 0); + dev_proc(pdev, dev_spec_op)(pdev, gxdso_supports_hlcolor, + NULL, 0)); bool center_of_pixel = (pgs->fill_adjust.x == 0 && pgs->fill_adjust.y == 0); /* Processing a fill object operation */ diff --git a/gs/base/gsequivc.c b/gs/base/gsequivc.c index 1aad32c1e..a19e0a38f 100644 --- a/gs/base/gsequivc.c +++ b/gs/base/gsequivc.c @@ -400,6 +400,7 @@ capture_spot_equivalent_cmyk_colors(gx_device * pdev, const gs_state * pgs, temp_device.memory = pgs->memory; temp_profile.usefastcolor = false; /* This avoids a few headaches */ + temp_profile.supports_devn = false; temp_profile.device_profile[0] = curr_output_profile; temp_profile.device_profile[1] = NULL; temp_profile.device_profile[2] = NULL; diff --git a/gs/base/gsicc_manage.c b/gs/base/gsicc_manage.c index a3201ab4c..48e1f8bd6 100644 --- a/gs/base/gsicc_manage.c +++ b/gs/base/gsicc_manage.c @@ -1005,6 +1005,7 @@ gsicc_new_device_profile_array(gs_memory_t *memory) result->oi_profile = NULL; result->devicegraytok = true; /* Default is to map gray to pure K */ result->usefastcolor = false; /* Default is to not use fast color */ + result->supports_devn = false; rc_init_free(result, memory->non_gc_memory, 1, rc_free_profile_array); return(result); } diff --git a/gs/base/gsovrc.c b/gs/base/gsovrc.c index 9580970e2..ae1e20ac3 100644 --- a/gs/base/gsovrc.c +++ b/gs/base/gsovrc.c @@ -291,7 +291,8 @@ typedef struct overprint_device_s { /* * The set of components to be drawn. This field is used only if the - * target color space is not separable and linear. + * target color space is not separable and linear. It is also used + * for the devn color values since we may need more than 8 components */ gx_color_index drawn_comps; @@ -317,6 +318,7 @@ typedef struct overprint_device_s { */ gx_color_index retain_mask; + /* We hold 3 sets of device procedures here. These are initialised from * the equivalently named globals when the device is created, but are * then used from here as we fiddle with them. This ensures that the @@ -453,6 +455,8 @@ static const gx_device_procs no_overprint_procs = { */ static dev_proc_fill_rectangle(overprint_generic_fill_rectangle); static dev_proc_fill_rectangle(overprint_sep_fill_rectangle); +static dev_proc_fill_rectangle_hl_color(overprint_fill_rectangle_hl_color); + /* other low-level overprint_sep_* rendering methods prototypes go here */ static const gx_device_procs generic_overprint_procs = { @@ -510,7 +514,7 @@ static const gx_device_procs generic_overprint_procs = { 0, /* encode_color */ 0, /* decode_color */ 0, /* pattern_manage */ - 0, /* fill_rectangle_hl_color */ + overprint_fill_rectangle_hl_color, /* fill_rectangle_hl_color */ 0, /* include_color_space */ 0, /* fill_linear_color_scanline */ 0, /* fill_linear_color_trapezoid */ @@ -576,11 +580,11 @@ static const gx_device_procs sep_overprint_procs = { 0, /* end_transparency_mask */ 0, /* discard_transparency_layer */ 0, /* get_color_mapping_procs */ - overprint_get_color_comp_index, /* get_color_comp_index */ + overprint_get_color_comp_index, /* get_color_comp_index */ 0, /* encode_color */ 0, /* decode_color */ 0, /* pattern_manage */ - 0, /* fill_rectangle_hl_color */ + overprint_fill_rectangle_hl_color, /* fill_rectangle_hl_color */ 0, /* include_color_space */ 0, /* fill_linear_color_scanline */ 0, /* fill_linear_color_trapezoid */ @@ -926,6 +930,102 @@ overprint_generic_fill_rectangle( dev->memory ); } +/* Currently we really should only be here if the target device is planar + AND it supports devn colors AND is 8 bit. */ +static int +overprint_fill_rectangle_hl_color(gx_device *dev, + const gs_fixed_rect *rect, const gs_imager_state *pis, + const gx_drawing_color *pdcolor, const gx_clip_path *pcpath) +{ + overprint_device_t * opdev = (overprint_device_t *)dev; + gx_device * tdev = opdev->target; + byte * gb_buff = 0; + gs_get_bits_params_t gb_params; + gs_int_rect gb_rect; + int code = 0, raster; + int byte_depth; + int depth, num_comps; + int x,y,w,h,k,j; + gs_memory_t * mem = dev->memory; + gx_color_index comps = opdev->drawn_comps; + gx_color_index mask; + int shift; + + if (tdev == 0) + return 0; + + depth = tdev->color_info.depth; + num_comps = tdev->color_info.num_components; + + x = rect->p.x; + y = rect->p.y; + w = rect->q.x - x; + h = rect->q.y - y; + + fit_fill(tdev, x, y, w, h); + byte_depth = depth / num_comps; + mask = ((gx_color_index)1 << byte_depth) - 1; + shift = 16 - byte_depth; + + /* allocate a buffer for the returned data */ + raster = bitmap_raster(w * byte_depth); + gb_buff = gs_alloc_bytes(mem, raster * num_comps , "overprint_fill_rectangle_hl_color"); + if (gb_buff == 0) + return gs_note_error(gs_error_VMerror); + + /* Initialize the get_bits parameters. Here we just get a plane at a time. */ + gb_params.options = GB_COLORS_NATIVE + | GB_ALPHA_NONE + | GB_DEPTH_ALL + | GB_PACKING_PLANAR + | GB_RETURN_COPY + | GB_ALIGN_STANDARD + | GB_OFFSET_0 + | GB_RASTER_STANDARD + | GB_SELECT_PLANES; + + gb_params.x_offset = 0; /* for consistency */ + gb_params.raster = raster; + gb_rect.p.x = x; + gb_rect.q.x = x + w; + + /* step through the height */ + while (h-- > 0 && code >= 0) { + comps = opdev->drawn_comps; + gb_rect.p.y = y++; + gb_rect.q.y = y; + /* And now through each plane */ + for (k = 0; k < tdev->color_info.num_components; k++) { + /* First set the params to zero for all planes except the one we want */ + for (j = 0; j < tdev->color_info.num_components; j++) + gb_params.data[j] = 0; + gb_params.data[k] = gb_buff + k * raster; + code = dev_proc(tdev, get_bits_rectangle) (tdev, &gb_rect, + &gb_params, 0); + if (code < 0) { + gs_free_object(mem, gb_buff, + "overprint_fill_rectangle_hl_color" ); + return code; + } + /* Skip the plane if this component is not to be drawn. We have + to do a get bits for each plane due to the fact that we have + to do a copy_planes at the end. If we had a copy_plane + operation we would just get the ones need and set those. */ + if ((comps & 0x01) == 1) { + /* Not sure if a loop or a memset is better here */ + memset(gb_params.data[k], + ((pdcolor->colors.devn.values[k]) >> shift & mask), w); + } + comps >>= 1; + } + code = dev_proc(tdev, copy_planes)(tdev, gb_buff, 0, raster, + gs_no_bitmap_id, x, y - 1, w, 1, 1); + } + gs_free_object(mem, gb_buff, + "overprint_fill_rectangle_hl_color" ); + return code; +} + static int overprint_sep_fill_rectangle( gx_device * dev, @@ -1079,4 +1179,4 @@ c_overprint_create_default_compositor( /* set up the overprint parameters */ return update_overprint_params( opdev, ¶ms); -} +}
\ No newline at end of file diff --git a/gs/base/gsptype1.c b/gs/base/gsptype1.c index 1249a1084..87f29f7b3 100644 --- a/gs/base/gsptype1.c +++ b/gs/base/gsptype1.c @@ -999,6 +999,8 @@ static dev_color_proc_load(gx_dc_pattern_load); /*dev_color_proc_fill_rectangle(gx_dc_pattern_fill_rectangle); *//*gxp1fill.h */ static dev_color_proc_equal(gx_dc_pattern_equal); static dev_color_proc_load(gx_dc_pure_masked_load); +static dev_color_proc_load(gx_dc_devn_masked_load); +static dev_color_proc_equal(gx_dc_devn_masked_equal); static dev_color_proc_get_dev_halftone(gx_dc_pure_masked_get_dev_halftone); /*dev_color_proc_fill_rectangle(gx_dc_pure_masked_fill_rect); *//*gxp1fill.h */ @@ -1076,6 +1078,19 @@ const gx_device_color_type_t gx_dc_colored_masked = { gx_dc_ht_colored_get_nonzero_comps }; +gs_private_st_composite_only(st_dc_devn_masked, gx_device_color, + "dc_devn_masked", + dc_masked_enum_ptrs, dc_masked_reloc_ptrs); +const gx_device_color_type_t gx_dc_devn_masked = { + &st_dc_devn_masked, + gx_dc_pattern_save_dc, gx_dc_pure_masked_get_dev_halftone, + gx_dc_no_get_phase, + gx_dc_devn_masked_load, gx_dc_devn_masked_fill_rect, + gx_dc_devn_fill_masked, gx_dc_devn_masked_equal, + gx_dc_cannot_write, gx_dc_cannot_read, + gx_dc_devn_get_nonzero_comps +}; + #undef gx_dc_type_pattern const gx_device_color_type_t *const gx_dc_type_pattern = &gx_dc_pattern; #define gx_dc_type_pattern (&gx_dc_pattern) @@ -1230,6 +1245,16 @@ gx_dc_pure_masked_load(gx_device_color * pdevc, const gs_imager_state * pis, FINISH_PATTERN_LOAD } static int +gx_dc_devn_masked_load(gx_device_color * pdevc, const gs_imager_state * pis, + gx_device * dev, gs_color_select_t select) +{ + int code = (*gx_dc_type_data_devn.load) (pdevc, pis, dev, select); + + if (code < 0) + return code; + FINISH_PATTERN_LOAD +} +static int gx_dc_binary_masked_load(gx_device_color * pdevc, const gs_imager_state * pis, gx_device * dev, gs_color_select_t select) { @@ -1332,6 +1357,13 @@ gx_dc_pattern_get_nonzero_comps( } static bool +gx_dc_devn_masked_equal(const gx_device_color * pdevc1, + const gx_device_color * pdevc2) +{ + return (*gx_dc_type_devn->equal) (pdevc1, pdevc2) && + pdevc1->mask.id == pdevc2->mask.id; +} +static bool gx_dc_pure_masked_equal(const gx_device_color * pdevc1, const gx_device_color * pdevc2) { diff --git a/gs/base/gxblend.h b/gs/base/gxblend.h index 96a7c7d4c..04e46a403 100644 --- a/gs/base/gxblend.h +++ b/gs/base/gxblend.h @@ -409,7 +409,7 @@ void gx_blend_image_buffer(byte *buf_ptr, int width, int height, int gx_put_blended_image_cmykspot(gx_device *target, byte *buf_ptr, int planestride, int rowstride, int x0, int y0, int width, int height, int num_comp, byte bg, - gs_separations *pseparations); + bool has_tags, gs_int_rect rect, gs_separations *pseparations); int gx_put_blended_image_custom(gx_device *target, byte *buf_ptr, int planestride, int rowstride, int x0, int y0, int width, int height, int num_comp, byte bg); diff --git a/gs/base/gxblend1.c b/gs/base/gxblend1.c index 9d092c1e9..857a2f27a 100644 --- a/gs/base/gxblend1.c +++ b/gs/base/gxblend1.c @@ -758,7 +758,7 @@ int gx_put_blended_image_cmykspot(gx_device *target, byte *buf_ptr, int planestride, int rowstride, int x0, int y0, int width, int height, int num_comp, byte bg, - gs_separations * pseparations) + bool has_tags, gs_int_rect rect, gs_separations * pseparations) { int code = 0; int x, y, tmp, comp_num, output_comp_num; @@ -771,6 +771,8 @@ gx_put_blended_image_cmykspot(gx_device *target, byte *buf_ptr, int num_known_comp = 0; int output_num_comp = target->color_info.num_components; int num_sep = pseparations->num_separations++; + bool data_blended = false; + int num_rows_left; /* * The process color model for the PDF 1.4 compositor device is CMYK plus @@ -803,6 +805,58 @@ gx_put_blended_image_cmykspot(gx_device *target, byte *buf_ptr, input_map[num_known_comp++] = comp_num + 4; } } + /* See if the target device has a put_image command. If + yes then see if it can handle the image data directly. */ + if (target->procs.put_image != NULL) { + /* See if the target device can handle the data in its current + form with the alpha component */ + int alpha_offset = num_comp; + int tag_offset = has_tags ? num_comp+1 : 0; + code = dev_proc(target, put_image) (target, buf_ptr, num_comp, + rect.p.x, rect.p.y, width, height, + rowstride, planestride, + num_comp,tag_offset); + if (code == 0) { + /* Device could not handle the alpha data. Go ahead and + preblend now. Note that if we do this, and we end up in the + default below, we only need to repack in chunky not blend */ +#if RAW_DUMP + /* Dump before and after the blend to make sure we are doing that ok */ + dump_raw_buffer(height, width, num_comp+1, planestride, rowstride, + "pre_final_blend",buf_ptr); + global_index++; +#endif + gx_blend_image_buffer(buf_ptr, width, height, rowstride, + planestride, num_comp, bg); +#if RAW_DUMP + /* Dump before and after the blend to make sure we are doing that ok */ + dump_raw_buffer(height, width, num_comp, planestride, rowstride, + "post_final_blend",buf_ptr); + global_index++; + /* clist_band_count++; */ +#endif + data_blended = true; + /* Try again now */ + alpha_offset = 0; + code = dev_proc(target, put_image) (target, buf_ptr, num_comp, + rect.p.x, rect.p.y, width, height, + rowstride, planestride, + alpha_offset, tag_offset); + } + if (code > 0) { + /* We processed some or all of the rows. Continue until we are done */ + num_rows_left = height - code; + while (num_rows_left > 0) { + code = dev_proc(target, put_image) (target, buf_ptr, num_comp, + rect.p.x, rect.p.y+code, width, + num_rows_left, rowstride, + planestride, + alpha_offset, tag_offset); + num_rows_left = num_rows_left - code; + } + return 0; + } + } /* Clear all output colorants first */ for (comp_num = 0; comp_num < output_num_comp; comp_num++) diff --git a/gs/base/gxcldev.h b/gs/base/gxcldev.h index f48cb3eb6..9bcb02d52 100644 --- a/gs/base/gxcldev.h +++ b/gs/base/gxcldev.h @@ -248,6 +248,7 @@ struct gx_clist_state_s { gs_id pattern_id; /* the last stored pattern id. */ gs_int_point tile_phase; /* most recent tile phase */ gx_color_index tile_colors[2]; /* most recent tile colors */ + gx_device_color tile_color_devn[2]; /* devn tile colors */ gx_cmd_rect rect; /* most recent rectangle */ gs_logical_operation_t lop; /* most recent logical op */ short lop_enabled; /* 0 = don't use lop, 1 = use lop, */ @@ -276,6 +277,7 @@ struct gx_clist_state_s { { gx_dc_type_none },\ 0, gx_no_bitmap_id, gs_no_id,\ { 0, 0 }, { gx_no_color_index, gx_no_color_index },\ + { {NULL}, {NULL} },\ { 0, 0, 0, 0 }, lop_default, 0, 0, 0, initial_known,\ { 0, 0 }, { 0, 0 }, { 0, 0 } @@ -293,6 +295,7 @@ dev_proc_copy_mono(clist_copy_mono); dev_proc_copy_color(clist_copy_color); dev_proc_copy_alpha(clist_copy_alpha); dev_proc_strip_tile_rectangle(clist_strip_tile_rectangle); +dev_proc_strip_tile_rect_devn(clist_strip_tile_rect_devn); dev_proc_strip_copy_rop(clist_strip_copy_rop); dev_proc_strip_copy_rop2(clist_strip_copy_rop2); dev_proc_fill_trapezoid(clist_fill_trapezoid); @@ -300,6 +303,7 @@ dev_proc_fill_linear_color_trapezoid(clist_fill_linear_color_trapezoid); dev_proc_fill_linear_color_triangle(clist_fill_linear_color_triangle); dev_proc_dev_spec_op(clist_dev_spec_op); dev_proc_copy_planes(clist_copy_planes); +dev_proc_fill_rectangle_hl_color(clist_fill_rectangle_hl_color); /* In gxclimag.c */ dev_proc_fill_mask(clist_fill_mask); @@ -473,10 +477,13 @@ typedef struct { byte set_op; byte delta_op; bool tile_color; + bool devn; } clist_select_color_t; + extern const clist_select_color_t clist_select_color0, clist_select_color1, clist_select_tile_color0, - clist_select_tile_color1; + clist_select_tile_color1, clist_select_devn_color0, + clist_select_devn_color1; /* See comments in gxclutil.c */ int cmd_put_color(gx_device_clist_writer * cldev, gx_clist_state * pcls, @@ -636,7 +643,10 @@ const byte *cmd_read_matrix(gs_matrix * pmat, const byte * cbp); /* Put out a fill or tile rectangle command. */ int cmd_write_rect_cmd(gx_device_clist_writer * cldev, gx_clist_state * pcls, int op, int x, int y, int width, int height); - +/* Put out a fill with a devn color */ +int cmd_write_rect_hl_cmd(gx_device_clist_writer * cldev, + gx_clist_state * pcls, int op, int x, int y, + int width, int height, bool extended_command); /* Put out a fill or tile rectangle command for fillpage. */ int cmd_write_page_rect_cmd(gx_device_clist_writer * cldev, int op); @@ -777,4 +787,4 @@ typedef enum { SAMEAS_PUSHCROP_BUTNOPUSH } cl_crop_action; -#endif /* gxcldev_INCLUDED */ +#endif /* gxcldev_INCLUDED */
\ No newline at end of file diff --git a/gs/base/gxclimag.c b/gs/base/gxclimag.c index 0064b8212..9d307ca42 100644 --- a/gs/base/gxclimag.c +++ b/gs/base/gxclimag.c @@ -139,7 +139,8 @@ clist_fill_mask(gx_device * dev, if (code < 0 && SET_BAND_CODE(code)) goto error_in_rect; do { - code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re); + code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re, + devn_not_tile); if (code == gs_error_unregistered) return code; if (depth > 1 && code >= 0) @@ -826,7 +827,8 @@ clist_image_plane_data(gx_image_enum_common_t * info, goto error_in_rect; if (pie->uses_color) { do { - code = cmd_put_drawing_color(cdev, re.pcls, &pie->dcolor, &re); + code = cmd_put_drawing_color(cdev, re.pcls, &pie->dcolor, + &re, devn_not_tile); } while (RECT_RECOVER(code)); if (code < 0 && SET_BAND_CODE(code)) goto error_in_rect; diff --git a/gs/base/gxclip.c b/gs/base/gxclip.c index 38365011f..924cbfe04 100644 --- a/gs/base/gxclip.c +++ b/gs/base/gxclip.c @@ -30,12 +30,14 @@ /* all drawing operations. */ static dev_proc_open_device(clip_open); static dev_proc_fill_rectangle(clip_fill_rectangle); +static dev_proc_fill_rectangle_hl_color(clip_fill_rectangle_hl_color); static dev_proc_copy_mono(clip_copy_mono); static dev_proc_copy_planes(clip_copy_planes); static dev_proc_copy_color(clip_copy_color); static dev_proc_copy_alpha(clip_copy_alpha); static dev_proc_fill_mask(clip_fill_mask); static dev_proc_strip_tile_rectangle(clip_strip_tile_rectangle); +static dev_proc_strip_tile_rect_devn(clip_strip_tile_rect_devn); static dev_proc_strip_copy_rop(clip_strip_copy_rop); static dev_proc_strip_copy_rop2(clip_strip_copy_rop2); static dev_proc_get_clipping_box(clip_get_clipping_box); @@ -100,7 +102,7 @@ static const gx_device_clip gs_clip_device = gx_forward_encode_color, gx_forward_decode_color, NULL, - gx_forward_fill_rectangle_hl_color, + clip_fill_rectangle_hl_color, gx_forward_include_color_space, gx_default_fill_linear_color_scanline, gx_default_fill_linear_color_trapezoid, @@ -115,7 +117,8 @@ static const gx_device_clip gs_clip_device = clip_copy_planes, /* copy planes */ gx_forward_get_profile, gx_forward_set_graphics_type_tag, - clip_strip_copy_rop2 + clip_strip_copy_rop2, + clip_strip_tile_rect_devn } }; @@ -416,6 +419,88 @@ clip_fill_rectangle(gx_device * dev, int x, int y, int w, int h, clip_call_fill_rectangle, &ccdata); } +int +clip_call_fill_rectangle_hl_color(clip_callback_data_t * pccd, int xc, int yc, + int xec, int yec) +{ + gs_fixed_rect rect; + + rect.p.x = xc; + rect.p.y = yc; + rect.q.x = xec; + rect.q.y = yec; + return (*dev_proc(pccd->tdev, fill_rectangle_hl_color)) + (pccd->tdev, &rect, pccd->pis, pccd->pdcolor, pccd->pcpath); +} + +static int +clip_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect, + const gs_imager_state *pis, const gx_drawing_color *pdcolor, + const gx_clip_path *pcpath) +{ + gx_device_clip *rdev = (gx_device_clip *) dev; + clip_callback_data_t ccdata; + gx_device *tdev = rdev->target; + gx_clip_rect *rptr = rdev->current; + int xe, ye; + int w, h, x, y; + gs_fixed_rect newrect; + + x = rect->p.x; + y = rect->p.y; + w = rect->q.x - rect->p.x; + h = rect->q.y - rect->p.y; + + if (w <= 0 || h <= 0) + return 0; + x += rdev->translation.x; + xe = x + w; + y += rdev->translation.y; + ye = y + h; + /* We open-code the most common cases here. */ + if ((y >= rptr->ymin && ye <= rptr->ymax) || + ((rptr = rptr->next) != 0 && + y >= rptr->ymin && ye <= rptr->ymax) + ) { + rdev->current = rptr; /* may be redundant, but awkward to avoid */ + INCR(in_y); + if (x >= rptr->xmin && xe <= rptr->xmax) { + INCR(in); + newrect.p.x = x; + newrect.p.y = y; + newrect.q.x = x + w; + newrect.q.y = y + h; + return dev_proc(tdev, fill_rectangle_hl_color)(tdev, &newrect, pis, + pdcolor, pcpath); + } + else if ((rptr->prev == 0 || rptr->prev->ymax != rptr->ymax) && + (rptr->next == 0 || rptr->next->ymax != rptr->ymax) + ) { + INCR(in1); + if (x < rptr->xmin) + x = rptr->xmin; + if (xe > rptr->xmax) + xe = rptr->xmax; + if (x >= xe) + return 0; + else { + newrect.p.x = x; + newrect.p.y = y; + newrect.q.x = xe; + newrect.q.y = y + h; + return dev_proc(tdev, fill_rectangle_hl_color)(tdev, &newrect, pis, + pdcolor, pcpath); + } + } + } + ccdata.tdev = tdev; + ccdata.pdcolor = pdcolor; + ccdata.pis = pis; + ccdata.pcpath = pcpath; + return clip_enumerate_rest(rdev, x, y, xe, ye, + clip_call_fill_rectangle_hl_color, &ccdata); +} + /* Copy a monochrome rectangle */ int clip_call_copy_mono(clip_callback_data_t * pccd, int xc, int yc, int xec, int yec) @@ -574,6 +659,31 @@ clip_fill_mask(gx_device * dev, return clip_enumerate(rdev, x, y, w, h, clip_call_fill_mask, &ccdata); } +/* Strip-tile a rectangle with devn colors. */ +int +clip_call_strip_tile_rect_devn(clip_callback_data_t * pccd, int xc, int yc, int xec, int yec) +{ + return (*dev_proc(pccd->tdev, strip_tile_rect_devn)) + (pccd->tdev, pccd->tiles, xc, yc, xec - xc, yec - yc, + pccd->pdc[0], pccd->pdc[1], pccd->phase.x, pccd->phase.y); +} +static int +clip_strip_tile_rect_devn(gx_device * dev, const gx_strip_bitmap * tiles, + int x, int y, int w, int h, + const gx_drawing_color *pdcolor0, + const gx_drawing_color *pdcolor1, int phase_x, + int phase_y) +{ + gx_device_clip *rdev = (gx_device_clip *) dev; + clip_callback_data_t ccdata; + + ccdata.tiles = tiles; + ccdata.pdc[0] = pdcolor0; + ccdata.pdc[1] = pdcolor1; + ccdata.phase.x = phase_x, ccdata.phase.y = phase_y; + return clip_enumerate(rdev, x, y, w, h, clip_call_strip_tile_rect_devn, &ccdata); +} + /* Strip-tile a rectangle. */ int clip_call_strip_tile_rectangle(clip_callback_data_t * pccd, int xc, int yc, int xec, int yec) @@ -791,4 +901,4 @@ clip_fill_path(gx_device * dev, const gs_imager_state * pis, fixed2int(box.q.x - box.p.x), fixed2int(box.q.y - box.p.y), clip_call_fill_path, &ccdata); -} +}
\ No newline at end of file diff --git a/gs/base/gxclip.h b/gs/base/gxclip.h index 7ad8a3391..a529e3880 100644 --- a/gs/base/gxclip.h +++ b/gs/base/gxclip.h @@ -34,19 +34,20 @@ typedef struct clip_callback_data_s { int x, y, w, h; /* (always set) */ gx_color_index color[2]; /* (all but copy_color) */ const byte *data; /* copy_*, fill_mask */ + const gx_drawing_color *(pdc)[2]; /* strip_tile_rect_devn */ int sourcex; /* ibid. */ uint raster; /* ibid. */ int depth; /* copy_alpha, fill_mask */ - const gx_drawing_color *pdcolor; /* fill_mask */ + const gx_drawing_color *pdcolor; /* fill_mask, fill_rectangle_hl_color */ gs_logical_operation_t lop; /* fill_mask, strip_copy_rop */ - const gx_clip_path *pcpath; /* fill_mask */ + const gx_clip_path *pcpath; /* fill_mask, fill_rectangle_hl_color*/ const gx_strip_bitmap *tiles; /* strip_tile_rectangle */ gs_int_point phase; /* strip_* */ const gx_color_index *scolors; /* strip_copy_rop */ const gx_strip_bitmap *textures; /* ibid. */ const gx_color_index *tcolors; /* ibid. */ int plane_height; /* copy_planes, strip_copy_rop2 */ - const gs_imager_state * pis; /* fill_path */ + const gs_imager_state * pis; /* fill_path, fill_rectangle_hl_color */ gx_path * ppath; /* fill_path */ const gx_fill_params * params; /* fill_path */ } clip_callback_data_t; @@ -67,9 +68,13 @@ int int xc, int yc, int xec, int yec), clip_call_strip_tile_rectangle(clip_callback_data_t * pccd, int xc, int yc, int xec, int yec), + clip_call_strip_tile_rect_devn(clip_callback_data_t * pccd, + int xc, int yc, int xec, int yec), clip_call_strip_copy_rop(clip_callback_data_t * pccd, int xc, int yc, int xec, int yec), clip_call_strip_copy_rop2(clip_callback_data_t * pccd, - int xc, int yc, int xec, int yec); + int xc, int yc, int xec, int yec), + clip_call_fill_rectangle_hl_color(clip_callback_data_t * pccd, + int xc, int yc, int xec, int yec); #endif /* gxclip_INCLUDED */ diff --git a/gs/base/gxclip2.c b/gs/base/gxclip2.c index 71ee2092b..bfbdc2b13 100644 --- a/gs/base/gxclip2.c +++ b/gs/base/gxclip2.c @@ -15,16 +15,20 @@ /* Mask clipping for patterns */ #include "memory_.h" #include "gx.h" +#include "gpcheck.h" #include "gserrors.h" #include "gsstruct.h" #include "gxdevice.h" #include "gxdevmem.h" #include "gxclip2.h" +#include "gxdcolor.h" +#include "gdevmpla.h" private_st_device_tile_clip(); /* Device procedures */ static dev_proc_fill_rectangle(tile_clip_fill_rectangle); +static dev_proc_fill_rectangle_hl_color(tile_clip_fill_rectangle_hl_color); static dev_proc_copy_mono(tile_clip_copy_mono); static dev_proc_copy_color(tile_clip_copy_color); static dev_proc_copy_planes(tile_clip_copy_planes); @@ -90,7 +94,7 @@ static const gx_device_tile_clip gs_tile_clip_device = gx_forward_encode_color, gx_forward_decode_color, NULL, /* pattern_manage */ - gx_forward_fill_rectangle_hl_color, + tile_clip_fill_rectangle_hl_color, gx_forward_include_color_space, gx_forward_fill_linear_color_scanline, gx_forward_fill_linear_color_trapezoid, @@ -105,7 +109,8 @@ static const gx_device_tile_clip gs_tile_clip_device = tile_clip_copy_planes, NULL, /* get_profile */ NULL, /* set_graphics_type_tag */ - tile_clip_strip_copy_rop2 + tile_clip_strip_copy_rop2, + gx_default_strip_tile_rect_devn } }; @@ -141,6 +146,35 @@ tile_clip_set_phase(gx_device_tile_clip * cdev, int px, int py) cdev->phase.y = py; } +/* Fill a rectangle with high level devn color by tiling with the mask. */ +static int +tile_clip_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect, + const gs_imager_state *pis, const gx_drawing_color *pdcolor, + const gx_clip_path *pcpath) +{ + gx_device_tile_clip *cdev = (gx_device_tile_clip *) dev; + gx_device *tdev = cdev->target; + int x, y, w, h; + gx_device_color dcolor0, dcolor1; + int k; + + /* Have to pack the no color index into the pure device type */ + dcolor0.type = gx_dc_type_pure; + dcolor0.colors.pure = gx_no_color_index; + /* Have to set the dcolor1 to a none mask type */ + dcolor1.type = gx_dc_type_devn; + for (k = 0; k < GS_CLIENT_COLOR_MAX_COMPONENTS; k++) { + dcolor1.colors.devn.values[k] = pdcolor->colors.devn.values[k]; + } + x = rect->p.x; + y = rect->p.y; + w = rect->q.x - x; + h = rect->q.y - y; + return (*dev_proc(tdev, strip_tile_rect_devn))(tdev, &cdev->tiles, + x, y, w, h, &dcolor0, &dcolor1, + cdev->phase.x, cdev->phase.y); +} + /* Fill a rectangle by tiling with the mask. */ static int tile_clip_fill_rectangle(gx_device * dev, int x, int y, int w, int h, diff --git a/gs/base/gxclipm.c b/gs/base/gxclipm.c index 18abea537..ea1ee87ea 100644 --- a/gs/base/gxclipm.c +++ b/gs/base/gxclipm.c @@ -19,13 +19,16 @@ #include "gxdevice.h" #include "gxdevmem.h" #include "gxclipm.h" +#include "gxdcolor.h" /* Device procedures */ static dev_proc_fill_rectangle(mask_clip_fill_rectangle); +static dev_proc_fill_rectangle_hl_color(mask_clip_fill_rectangle_hl_color); static dev_proc_copy_mono(mask_clip_copy_mono); static dev_proc_copy_color(mask_clip_copy_color); static dev_proc_copy_alpha(mask_clip_copy_alpha); static dev_proc_strip_tile_rectangle(mask_clip_strip_tile_rectangle); +static dev_proc_strip_tile_rect_devn(mask_clip_strip_tile_rect_devn); static dev_proc_strip_copy_rop(mask_clip_strip_copy_rop); static dev_proc_strip_copy_rop2(mask_clip_strip_copy_rop2); static dev_proc_get_clipping_box(mask_clip_get_clipping_box); @@ -88,7 +91,7 @@ const gx_device_mask_clip gs_mask_clip_device = gx_forward_encode_color, gx_forward_decode_color, NULL, /* pattern_manage */ - gx_forward_fill_rectangle_hl_color, + mask_clip_fill_rectangle_hl_color, gx_forward_include_color_space, gx_forward_fill_linear_color_scanline, gx_forward_fill_linear_color_trapezoid, @@ -103,10 +106,51 @@ const gx_device_mask_clip gs_mask_clip_device = NULL, gx_forward_get_profile, gx_forward_set_graphics_type_tag, - mask_clip_strip_copy_rop2 + mask_clip_strip_copy_rop2, + mask_clip_strip_tile_rect_devn } }; +/* Fill a rectangle with a hl color, painting through the mask */ +static int +mask_clip_fill_rectangle_hl_color(gx_device *dev, + const gs_fixed_rect *rect, + const gs_imager_state *pis, const gx_drawing_color *pdcolor, + const gx_clip_path *pcpath) +{ + gx_device_mask_clip *cdev = (gx_device_mask_clip *) dev; + gx_device *tdev = cdev->target; + int x, y, w, h; + int mx0, mx1, my0, my1; + + x = rect->p.x; + y = rect->p.y; + w = rect->q.x - x; + h = rect->q.y - y; + + /* Clip the rectangle to the region covered by the mask. */ + mx0 = x + cdev->phase.x; + my0 = y + cdev->phase.y; + mx1 = mx0 + w; + my1 = my0 + h; + + if (mx0 < 0) + mx0 = 0; + if (my0 < 0) + my0 = 0; + if (mx1 > cdev->tiles.size.x) + mx1 = cdev->tiles.size.x; + if (my1 > cdev->tiles.size.y) + my1 = cdev->tiles.size.y; + /* It would be nice to have a higher level way to do this operation + like a copy_mono_hl_color */ + return (pdcolor->type->fill_masked) + (pdcolor, cdev->tiles.data + my0 * cdev->tiles.raster, mx0, + cdev->tiles.raster, cdev->tiles.id, mx0 - cdev->phase.x, + my0 - cdev->phase.y, mx1 - mx0, my1 - my0, + tdev, lop_default, false); +} + /* Fill a rectangle by painting through the mask. */ static int mask_clip_fill_rectangle(gx_device * dev, int x, int y, int w, int h, @@ -356,6 +400,24 @@ mask_clip_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tiles, } static int +mask_clip_strip_tile_rect_devn(gx_device * dev, const gx_strip_bitmap * tiles, + int x, int y, int w, int h, + const gx_drawing_color *pdcolor0, + const gx_drawing_color *pdcolor1, + int phase_x, int phase_y) +{ + gx_device_mask_clip *cdev = (gx_device_mask_clip *) dev; + clip_callback_data_t ccdata; + + ccdata.tdev = cdev->target; + ccdata.x = x, ccdata.y = y, ccdata.w = w, ccdata.h = h; + ccdata.tiles = tiles; + ccdata.pdc[0] = pdcolor0, ccdata.pdc[1] = pdcolor1; + ccdata.phase.x = phase_x, ccdata.phase.y = phase_y; + return clip_runs_enumerate(cdev, clip_call_strip_tile_rect_devn, &ccdata); +} + +static int mask_clip_strip_copy_rop(gx_device * dev, const byte * data, int sourcex, uint raster, gx_bitmap_id id, const gx_color_index * scolors, diff --git a/gs/base/gxclist.c b/gs/base/gxclist.c index f034cd541..aefa21b05 100644 --- a/gs/base/gxclist.c +++ b/gs/base/gxclist.c @@ -181,7 +181,7 @@ const gx_device_procs gs_clist_device_procs = { gx_forward_encode_color, gx_forward_decode_color, NULL, /* pattern_manage */ - gx_default_fill_rectangle_hl_color, + clist_fill_rectangle_hl_color, gx_default_include_color_space, gx_default_fill_linear_color_scanline, clist_fill_linear_color_trapezoid, @@ -196,7 +196,8 @@ const gx_device_procs gs_clist_device_procs = { clist_copy_planes, /* copy planes */ gx_default_get_profile, gx_default_set_graphics_type_tag, - clist_strip_copy_rop2 + clist_strip_copy_rop2, + clist_strip_tile_rect_devn }; /*------------------- Choose the implementation ----------------------- diff --git a/gs/base/gxclpath.c b/gs/base/gxclpath.c index 84e96f76a..2985e5fa3 100644 --- a/gs/base/gxclpath.c +++ b/gs/base/gxclpath.c @@ -100,7 +100,8 @@ cmd_slow_rop(gx_device *dev, gs_logical_operation_t lop, /* If the pattern color is big, it can write to "all" bands. */ int cmd_put_drawing_color(gx_device_clist_writer * cldev, gx_clist_state * pcls, - const gx_drawing_color * pdcolor, cmd_rects_enum_t *pre) + const gx_drawing_color * pdcolor, cmd_rects_enum_t *pre, + dc_devn_cl_type devn_type) { const gx_device_halftone * pdht = pdcolor->type->get_dev_halftone(pdcolor); int code, di; @@ -131,6 +132,7 @@ cmd_put_drawing_color(gx_device_clist_writer * cldev, gx_clist_state * pcls, * * The complete cmd_opv_ext_put_drawing_color consists of: * comand code (2 bytes) + * tile index value or non tile color (1) * device color type index (1) * length of serialized device color (enc_u_sizew(dc_size)) * the serialized device color itself (dc_size) @@ -144,7 +146,7 @@ cmd_put_drawing_color(gx_device_clist_writer * cldev, gx_clist_state * pcls, &dc_size ); /* if the returned value is > 0, no change in the color is necessary */ - if (code > 0) + if (code > 0 && devn_type == devn_not_tile) return 0; else if (code < 0 && code != gs_error_rangecheck) return code; @@ -206,7 +208,19 @@ cmd_put_drawing_color(gx_device_clist_writer * cldev, gx_clist_state * pcls, if (code < 0) return code; dp0 = dp; - dp[1] = cmd_opv_ext_put_drawing_color; + switch (devn_type) { + case devn_not_tile: + dp[1] = cmd_opv_ext_put_drawing_color; + break; + case devn_tile0: + dp[1] = cmd_opv_ext_put_tile_devn_color0; + break; + case devn_tile1: + dp[1] = cmd_opv_ext_put_tile_devn_color1; + break; + default: + dp[1] = cmd_opv_ext_put_drawing_color; + } dp += 2; *dp++ = di | (offset > 0 ? 0x80 : 0); if (offset > 0) @@ -772,7 +786,8 @@ clist_fill_path(gx_device * dev, const gs_imager_state * pis, gx_path * ppath, (code = cmd_update_lop(cdev, re.pcls, lop)) < 0 ) return code; - code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re); + code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re, + devn_not_tile); if (code == gs_error_unregistered) return code; if (code < 0) { @@ -915,7 +930,7 @@ clist_stroke_path(gx_device * dev, const gs_imager_state * pis, gx_path * ppath, (code = cmd_update_lop(cdev, re.pcls, lop)) < 0 ) return code; - code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re); + code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re, devn_not_tile); if (code == gs_error_unregistered) return code; if (code < 0) { @@ -996,7 +1011,7 @@ clist_put_polyfill(gx_device *dev, fixed px, fixed py, do { RECT_STEP_INIT(re); if ((code = cmd_update_lop(cdev, re.pcls, lop)) < 0 || - (code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re)) < 0) + (code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re, devn_not_tile)) < 0) goto out; re.pcls->colors_used.slow_rop |= slow_rop; code = cmd_put_path(cdev, re.pcls, &path, diff --git a/gs/base/gxclpath.h b/gs/base/gxclpath.h index 170eeaf54..65c8e8fcb 100644 --- a/gs/base/gxclpath.h +++ b/gs/base/gxclpath.h @@ -60,15 +60,7 @@ typedef enum { /* cmd_opv_set_color = 0xd0, */ /* Used if base values do not fit into 1 bit */ /* #flags,#base[0],...#base[num_comp-1] if flags */ /* colored halftone with base colors a,b,c,d */ - /* obsolete */ - /* cmd_opv_set_color_short = 0xd1, */ /* Used if base values fit into 1 bit */ - /* If num_comp <= 4 then use: */ - /* pqrsabcd, where a = base[0] */ - /* b = base[1], c= base[2], d = base[3] */ - /* p = level[0], q = level[1] */ - /* r = level[2], s = level[3] */ - /* If num_comp > 4 then use: */ - /* #flags, #bases */ + cmd_op_fill_rect_hl = 0xd1, /* rect fill with devn color */ cmd_opv_set_fill_adjust = 0xd2, /* adjust_x/y(fixed) */ cmd_opv_set_ctm = 0xd3, /* [per sput/sget_matrix] */ cmd_opv_set_color_space = 0xd4, /* base(4)Indexed?(2)0(2) */ @@ -135,7 +127,6 @@ typedef enum { cmd_op_path = 0xf0, /* (see below) */ cmd_opv_fill = 0xf0, cmd_opv_rgapto = 0xf1, /* dx%, dy% */ /* was cmd_opv_htfill */ - /* cmd_opv_colorfill = 0xf2, */ /* obsolete */ cmd_opv_eofill = 0xf3, /* cmd_opv_hteofill = 0xf4, */ /* obsolete */ /* cmd_opv_coloreofill = 0xf5, */ /* obsolete */ @@ -148,6 +139,13 @@ typedef enum { cmd_opv_fill_trapezoid = 0xfc } gx_cmd_xop; +/* This is usd for cmd_opv_ext_put_drawing_color so that we know if it + is assocated with a tile or not */ +typedef enum { + devn_not_tile = 0x00, + devn_tile0 = 0x01, + devn_tile1 = 0x02 +} dc_devn_cl_type; /* * Further extended command set. This code always occupies a byte, which * is the second byte of a command whose first byte is cmd_opv_extend. @@ -161,14 +159,17 @@ typedef enum { * halftone segment data */ cmd_opv_ext_put_drawing_color = 0x04, /* length, color type id, * serialized color */ - cmd_opv_ext_put_icc_profile = 0x05 /* ICC profile */ + cmd_opv_ext_tile_rect_hl = 0x05, /* Uses devn colors in tiling fill */ + cmd_opv_ext_put_tile_devn_color0 = 0x6, /* Devn color0 for tile filling */ + cmd_opv_ext_put_tile_devn_color1 = 0x7 /* Devn color1 for tile filling */ } gx_cmd_ext_op; #define cmd_segment_op_num_operands_values\ 2, 2, 1, 1, 4, 6, 6, 6, 4, 4, 4, 4, 2, 2, 0, 0 #define cmd_misc2_op_name_strings\ - "cmd_opv_set_color", "set_color_short", "set_fill_adjust", "set_ctm",\ + "cmd_opv_set_color", "fill_hl_color", \ + "set_fill_adjust", "set_ctm",\ "set_color_space", "set_misc2", "set_dash", "enable_clip",\ "disable_clip", "begin_clip", "end_clip", "begin_image_rect",\ "begin_image", "image_data", "image_plane_data", "put_params" @@ -240,7 +241,7 @@ bool cmd_slow_rop(gx_device *dev, gs_logical_operation_t lop, int cmd_put_drawing_color(gx_device_clist_writer * cldev, gx_clist_state * pcls, const gx_drawing_color * pdcolor, - cmd_rects_enum_t *pre); + cmd_rects_enum_t *pre, dc_devn_cl_type devn_type); /* Clear (a) specific 'known' flag(s) for all bands. */ /* We must do this whenever the value of a 'known' parameter changes. */ diff --git a/gs/base/gxclrast.c b/gs/base/gxclrast.c index c68a1bcad..073de5321 100644 --- a/gs/base/gxclrast.c +++ b/gs/base/gxclrast.c @@ -487,6 +487,7 @@ clist_playback_band(clist_playback_action playback_action, gx_device *tdev; gx_clist_state state; gx_color_index *set_colors; + gx_device_color *set_dev_colors; tile_slot *state_slot; gx_strip_bitmap state_tile; /* parameters for reading tiles */ tile_slot tile_bits; /* parameters of current tile */ @@ -561,6 +562,7 @@ clist_playback_band(clist_playback_action playback_action, in: /* Initialize for a new page. */ tdev = target; set_colors = state.colors; + set_dev_colors = state.tile_color_devn; use_clip = false; pcpath = NULL; clipper_dev_open = false; @@ -632,6 +634,7 @@ in: /* Initialize for a new page. */ byte *source = NULL; /* Initialize against indeterminizm. */ gx_color_index colors[2]; gx_color_index *pcolor; + gx_device_color *pdcolor; gs_logical_operation_t log_op; /* Make sure the buffer contains a full command. */ @@ -967,6 +970,7 @@ in: /* Initialize for a new page. */ uint plane_depth = depth; uint pln; byte compression = op & 3; + uint out_bytes; cmd_getw(state.rect.width, cbp); cmd_getw(state.rect.height, cbp); @@ -979,11 +983,18 @@ in: /* Initialize for a new page. */ state.rect.height, op & 3, &width_bytes, (uint *)&raster); + if (planes > 1) + { + out_bytes = raster * state.rect.height; + plane_height = state.rect.height; + } else { + out_bytes = bytes; + } /* copy_mono and copy_color/alpha */ /* ensure that the bits will fit in a single buffer, */ /* even after decompression if compressed. */ #ifdef DEBUG - if (planes * bytes > cbuf_size) { + if (planes * out_bytes > cbuf_size) { lprintf6("bitmap size exceeds buffer! width=%d raster=%d height=%d\n file pos %ld buf pos %d/%d\n", state.rect.width, raster, state.rect.height, @@ -995,9 +1006,17 @@ in: /* Initialize for a new page. */ #endif for (pln = 0; pln < planes; pln++) { - byte *plane_bits = data_bits + plane_height * raster; + byte *plane_bits = data_bits + pln * plane_height * raster; if (pln) + { + if (cbp >= cbuf.warn_limit) + { + code = top_up_cbuf(&cbuf, &cbp); + if (code < 0) + return code; + } compression = *cbp++; + } if (compression) { /* Decompress the image data. */ stream_cursor_read r; stream_cursor_write w; @@ -1280,6 +1299,28 @@ set_phase: /* goto out; } break; + case cmd_op_fill_rect_hl: + { + gs_fixed_rect rect_hl; + + cbp = cmd_read_rect(op & 0xf0, &state.rect, cbp); + if (dev_color.type != gx_dc_type_devn) { + if_debug0('L', "hl rect fill without devn color\n"); + code = gs_note_error(gs_error_typecheck); + goto out; + } + if_debug4('L', " x=%d y=%d w=%d h=%d\n", + state.rect.x, state.rect.y, + state.rect.width,state.rect.height); + rect_hl.p.x = state.rect.x - x0; + rect_hl.p.y = state.rect.y - y0; + rect_hl.q.x = state.rect.width + rect_hl.p.x; + rect_hl.q.y = state.rect.height + rect_hl.p.y; + code = dev_proc(tdev, fill_rectangle_hl_color) (tdev, + &rect_hl, NULL, + &dev_color, NULL); + } + continue; case cmd_opv_begin_image_rect: cbuf.ptr = cbp; code = read_begin_image(&cbuf, &image.c, pcs); @@ -1663,15 +1704,37 @@ idata: data_size = 0; if (code < 0) goto out; break; + case cmd_opv_ext_tile_rect_hl: + /* Strip tile with devn colors */ + cbp = cmd_read_rect(op & 0xf0, &state.rect, cbp); + if_debug4('L', " x=%d y=%d w=%d h=%d\n", + state.rect.x, state.rect.y, + state.rect.width,state.rect.height); + code = (*dev_proc(tdev, strip_tile_rect_devn)) + (tdev, &state_tile, + state.rect.x - x0, state.rect.y - y0, + state.rect.width, state.rect.height, + &(state.tile_color_devn[0]), + &(state.tile_color_devn[1]), + tile_phase.x, tile_phase.y); + break; + case cmd_opv_ext_put_tile_devn_color0: + pdcolor = &set_dev_colors[0]; + goto load_dcolor; + case cmd_opv_ext_put_tile_devn_color1: + pdcolor = &set_dev_colors[1]; + goto load_dcolor; case cmd_opv_ext_put_drawing_color: - { + pdcolor = &dev_color; + load_dcolor:{ uint color_size; int left, offset, l; const gx_device_color_type_t * pdct; byte type_and_flag = *cbp++; byte is_continuation = type_and_flag & 0x80; - pdct = gx_get_dc_type_from_index(type_and_flag & 0x7F); + if_debug0('L', " cmd_opv_ext_put_drawing_color\n"); + pdct = gx_get_dc_type_from_index(type_and_flag & 0x7F); if (pdct == 0) { code = gs_note_error(gs_error_rangecheck); goto out; @@ -1684,9 +1747,9 @@ idata: data_size = 0; if (!left) { /* We still need to call pdct->read because it may change dev_color.type - see gx_dc_null_read.*/ - code = pdct->read(&dev_color, &imager_state, - &dev_color, tdev, offset, cbp, - 0, mem); + code = pdct->read(pdcolor, &imager_state, + pdcolor, tdev, offset, + cbp, 0, mem); if (code < 0) goto out; } @@ -1697,9 +1760,9 @@ idata: data_size = 0; return code; } l = min(left, cbuf.end - cbp); - code = pdct->read(&dev_color, &imager_state, - &dev_color, tdev, offset, cbp, - l, mem); + code = pdct->read(pdcolor, &imager_state, + pdcolor, tdev, offset, + cbp, l, mem); if (code < 0) goto out; l = code; @@ -1707,8 +1770,8 @@ idata: data_size = 0; offset += l; left -= l; } - code = gx_color_load(&dev_color, - &imager_state, tdev); + code = gx_color_load(pdcolor, &imager_state, + tdev); if (code < 0) goto out; } diff --git a/gs/base/gxclrect.c b/gs/base/gxclrect.c index 6a2803f08..06928969d 100644 --- a/gs/base/gxclrect.c +++ b/gs/base/gxclrect.c @@ -47,6 +47,34 @@ cmd_put_rect(register const gx_cmd_rect * prect, register byte * dp) } int +cmd_write_rect_hl_cmd(gx_device_clist_writer * cldev, gx_clist_state * pcls, + int op, int x, int y, int width, int height, + bool extended_command) +{ + byte *dp; + int code; + int rcsize; + + cmd_set_rect(pcls->rect); + if (extended_command) { + rcsize = 2 + cmd_size_rect(&pcls->rect); + code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_extend, rcsize); + dp[1] = op; + dp += 2; + } else { + rcsize = 1 + cmd_size_rect(&pcls->rect); + code = set_cmd_put_op(dp, cldev, pcls, op, rcsize); + dp += 1; + } + if (code < 0) + return code; + if_debug5('L', "rect hl r%d:%d,%d,%d,%d\n", + rcsize - 1, pcls->rect.x, pcls->rect.y, pcls->rect.width, pcls->rect.height); + cmd_put_rect(&pcls->rect, dp); + return 0; +} + +int cmd_write_rect_cmd(gx_device_clist_writer * cldev, gx_clist_state * pcls, int op, int x, int y, int width, int height) { @@ -276,7 +304,7 @@ clist_fillpage(gx_device * dev, gs_imager_state *pis, gx_drawing_color *pdcolor) int code; do { - code = cmd_put_drawing_color(cdev, pcls, pdcolor, NULL); + code = cmd_put_drawing_color(cdev, pcls, pdcolor, NULL, devn_not_tile); if (code >= 0) code = cmd_write_page_rect_cmd(cdev, cmd_op_fill_rect); } while (RECT_RECOVER(code)); @@ -325,6 +353,54 @@ error_in_rect: return 0; } +/* This is used in fills from devn color types */ +int +clist_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect, + const gs_imager_state *pis, const gx_drawing_color *pdcolor, + const gx_clip_path *pcpath) +{ + gx_device_clist_writer * const cdev = + &((gx_device_clist *)dev)->writer; + int code; + int rx, ry, rwidth, rheight; + cmd_rects_enum_t re; + + rx = rect->p.x; + ry = rect->p.y; + rwidth = rect->q.x - rx; + rheight = rect->q.y - ry; + + crop_fill(cdev, rx, ry, rwidth, rheight); + if (rwidth <= 0 || rheight <= 0) + return 0; + if (cdev->permanent_error < 0) + return (cdev->permanent_error); + RECT_ENUM_INIT(re, ry, rheight); + do { + RECT_STEP_INIT(re); + re.pcls->colors_used.or = 0xffffffff; + re.pcls->band_complexity.uses_color = true; + do { + code = cmd_disable_lop(cdev, re.pcls); + code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re, + devn_not_tile); + if (code >= 0) { + code = cmd_write_rect_hl_cmd(cdev, re.pcls, cmd_op_fill_rect_hl, + rx, re.y, rwidth, re.height, false); + } + } while (RECT_RECOVER(code)); + if (code < 0 && SET_BAND_CODE(code)) + goto error_in_rect; + re.y += re.height; + continue; +error_in_rect: + if (!(cdev->error_is_retryable && cdev->driver_call_nesting == 0 && + SET_BAND_CODE(clist_VMerror_recover_flush(cdev, re.band_code)) >= 0)) + return re.band_code; + } while (re.y < re.yend); + return 0; +} + static inline int clist_write_fill_trapezoid(gx_device * dev, const gs_fixed_edge *left, const gs_fixed_edge *right, @@ -372,7 +448,8 @@ clist_write_fill_trapezoid(gx_device * dev, RECT_STEP_INIT(re); do { if (pdcolor != NULL) { - code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re); + code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re, + devn_not_tile); if (code == gs_error_unregistered) return code; if (code < 0) { @@ -482,12 +559,97 @@ clist_dev_spec_op(gx_device *pdev, int dev_spec_op, void *data, int size) return 1; if (dev_spec_op == gxdso_is_native_planar) return cdev->is_planar; + if (dev_spec_op == gxdso_supports_devn) { + cmm_dev_profile_t *dev_profile; + int code; + code = dev_proc(cdev, get_profile)((gx_device*) cdev, &dev_profile); + if (code == 0) { + return dev_profile->supports_devn; + } else { + return 0; + } + } return gx_default_dev_spec_op(pdev, dev_spec_op, pinst, id); } #define dev_proc_pattern_manage(proc)\ dev_t_proc_pattern_manage(proc, gx_device) +/* Based heavily off of clist_strip_tile_rectangle */ +int +clist_strip_tile_rect_devn(gx_device * dev, const gx_strip_bitmap * tile, + int rx, int ry, int rwidth, int rheight, + const gx_drawing_color *pdcolor0, + const gx_drawing_color *pdcolor1, int px, int py) +{ + gx_device_clist_writer * const cdev = + &((gx_device_clist *)dev)->writer; + int depth = 1; + int code; + cmd_rects_enum_t re; + + crop_fill(cdev, rx, ry, rwidth, rheight); + if (rwidth <= 0 || rheight <= 0) + return 0; + if (cdev->permanent_error < 0) + return (cdev->permanent_error); + RECT_ENUM_INIT(re, ry, rheight); + do { + ulong offset_temp; + + RECT_STEP_INIT(re); + re.pcls->colors_used.or = 0xffffffff; + re.pcls->band_complexity.uses_color = true; + do { + code = cmd_disable_lop(cdev, re.pcls); + } while (RECT_RECOVER(code)); + if (code < 0 && SET_BAND_CODE(code)) + goto error_in_rect; + /* Change the tile if needed */ + if (!cls_has_tile_id(cdev, re.pcls, tile->id, offset_temp)) { + if (tile->id != gx_no_bitmap_id) { + do { + code = clist_change_tile(cdev, re.pcls, tile, depth); + } while (RECT_RECOVER(code)); + if (code < 0 && !(code != gs_error_VMerror || !cdev->error_is_retryable) && SET_BAND_CODE(code)) + goto error_in_rect; + } else + code = -1; + if (code < 0) { + return_error(gs_error_unregistered); + } + } + do { + code = 0; + /* Write out the devn colors */ + code = cmd_put_drawing_color(cdev, re.pcls, pdcolor0, &re, + devn_tile0); + code = cmd_put_drawing_color(cdev, re.pcls, pdcolor1, &re, + devn_tile1); + /* Set the tile phase */ + if (px != re.pcls->tile_phase.x || py != re.pcls->tile_phase.y) { + if (code >= 0) + code = cmd_set_tile_phase(cdev, re.pcls, px, py); + } + /* Write out the actually command to fill with the devn colors */ + if (code >= 0) { + code = cmd_write_rect_hl_cmd(cdev, re.pcls, + cmd_opv_ext_tile_rect_hl, rx, re.y, + rwidth, re.height, true); + } + } while (RECT_RECOVER(code)); + if (code < 0 && SET_BAND_CODE(code)) + goto error_in_rect; + re.y += re.height; + continue; +error_in_rect: + if (!(cdev->error_is_retryable && cdev->driver_call_nesting == 0 && + SET_BAND_CODE(clist_VMerror_recover_flush(cdev, re.band_code)) >= 0)) + return re.band_code; + } while (re.y < re.yend); + return 0; +} + int clist_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tile, int rx, int ry, int rwidth, int rheight, @@ -703,6 +865,7 @@ clist_copy_planes(gx_device * dev, int y0; gx_bitmap_id orig_id = id; cmd_rects_enum_t re; + int bpc = dev->color_info.depth / dev->color_info.num_components; if (rwidth <= 0 || rheight <= 0) return 0; @@ -714,11 +877,12 @@ clist_copy_planes(gx_device * dev, return (cdev->permanent_error); RECT_ENUM_INIT(re, ry, rheight); do { - int dx = data_x & 7; + int dx = data_x % (8/bpc); int w1 = dx + rwidth; - const byte *row = data + (re.y - y0) * raster + (data_x >> 3); + const byte *row = data + (re.y - y0) * raster + (data_x / (8/bpc)); int code; + RECT_STEP_INIT(re); do { code = cmd_disable_lop(cdev, re.pcls); @@ -729,7 +893,38 @@ clist_copy_planes(gx_device * dev, goto error_in_rect; /* Don't bother to check for a possible cache hit: */ /* tile_rectangle and fill_mask handle those cases. */ -copy:{ +copy: + /* We require that in the copy_planes case all the planes fit into + * a single cbuf. */ + if (plane_height > 0) { + int bytes_row = ((w1*bpc+7)/8 + 7) & ~7; + int maxheight = (cbuf_size - 0x100) / bytes_row / cdev->color_info.num_components; + if (re.height > maxheight) + re.height = maxheight; + if (re.height == 0) + { + /* Split a single (very long) row. */ + int w2 = w1 >> 1; + + re.height = 1; + ++cdev->driver_call_nesting; + { + code = clist_copy_planes(dev, row, dx, raster, + gx_no_bitmap_id, rx, re.y, + w2, 1, plane_height); + if (code >= 0) + code = clist_copy_planes(dev, row, dx + w2, + raster, gx_no_bitmap_id, + rx + w2, re.y, + w1 - w2, 1, plane_height); + } + --cdev->driver_call_nesting; + if (code < 0 && SET_BAND_CODE(code)) + goto error_in_rect; + continue; + } + } + { gx_cmd_rect rect; int rsize; byte op = (byte) cmd_op_copy_mono_planes; @@ -744,11 +939,12 @@ copy:{ do { int plane; /* Copy the 0th plane - this is the one the op goes in. */ - code = cmd_put_bits(cdev, re.pcls, row, w1, re.height, raster, - rsize, (orig_id == gx_no_bitmap_id ? - 1 << cmd_compress_rle : - cmd_mask_compress_any), + code = cmd_put_bits(cdev, re.pcls, row, w1*bpc, re.height, raster, + rsize, (bpc == 1 ? (orig_id == gx_no_bitmap_id ? + 1 << cmd_compress_rle : + cmd_mask_compress_any) : 0), &dp, &csize); + compress = (uint)code; if (plane_height > 0) { for (plane = 1; plane < cdev->color_info.num_components && (code >= 0); plane++) { @@ -756,10 +952,13 @@ copy:{ uint csize2; /* Copy subsequent planes - 1 byte header used to send the * compression type. */ - code = cmd_put_bits(cdev, re.pcls, row, w1, re.height, raster, - 1, (orig_id == gx_no_bitmap_id ? - 1 << cmd_compress_rle : - cmd_mask_compress_any), + code = cmd_put_bits(cdev, re.pcls, + row + plane_height * raster, + w1*bpc, re.height, raster, 1, + (bpc == 1 ? + (orig_id == gx_no_bitmap_id ? + 1 << cmd_compress_rle : + cmd_mask_compress_any) : 0), &dummy_dp, &csize2); if (code >= 0) *dummy_dp = code; @@ -770,7 +969,6 @@ copy:{ } while (RECT_RECOVER(code)); if (code < 0 && !(code == gs_error_limitcheck) && SET_BAND_CODE(code)) goto error_in_rect; - compress = (uint)code; if (code < 0) { /* The bitmap was too large; split up the transfer. */ if (re.height > 1) { @@ -810,6 +1008,7 @@ copy:{ cmd_putw(plane_height, dp); cmd_put2w(rx, re.y, dp); cmd_put2w(w1, re.height, dp); + re.pcls->rect = rect; } continue; diff --git a/gs/base/gxcmap.c b/gs/base/gxcmap.c index 2dea60b68..b32c5c874 100644 --- a/gs/base/gxcmap.c +++ b/gs/base/gxcmap.c @@ -33,6 +33,7 @@ #include "gsicc_cache.h" #include "gscms.h" #include "gsicc.h" +#include "gxdevsop.h" /* Structure descriptor */ public_st_device_color(); @@ -975,19 +976,27 @@ cmap_cmyk_direct(frac c, frac m, frac y, frac k, gx_device_color * pdc, gx_color_load_select(pdc, pis, dev, select); return; } - - for (i = 0; i < ncomps; i++) - cv[i] = frac2cv(cm_comps[i]); - - color = dev_proc(dev, encode_color)(dev, cv); - if (color != gx_no_color_index) - color_set_pure(pdc, color); - else { - if (gx_render_device_DeviceN(cm_comps, pdc, dev, - pis->dev_ht, &pis->screen_phase[select]) == 1) - gx_color_load_select(pdc, pis, dev, select); - return; + /* if output device supports devn, we need to make sure we send it the + proper color type */ + /* if output device supports devn, we need to make sure we send it the + proper color type */ + if (dev_proc(dev, dev_spec_op)(dev, gxdso_supports_devn, NULL, 0)) { + for (i = 0; i < ncomps; i++) + pdc->colors.devn.values[i] = frac2cv(cm_comps[i]); + pdc->type = gx_dc_type_devn; + } else { + for (i = 0; i < ncomps; i++) + cv[i] = frac2cv(cm_comps[i]); + color = dev_proc(dev, encode_color)(dev, cv); + if (color != gx_no_color_index) + color_set_pure(pdc, color); + else { + if (gx_render_device_DeviceN(cm_comps, pdc, dev, + pis->dev_ht, &pis->screen_phase[select]) == 1) + gx_color_load_select(pdc, pis, dev, select); + } } + return; } static void @@ -1242,14 +1251,23 @@ cmap_separation_direct(frac all, gx_device_color * pdc, const gs_imager_state * cv[i] = psrc_cm[i]; } } - /* encode as a color index */ - color = dev_proc(dev, encode_color)(dev, cv); + /* if output device supports devn, we need to make sure we send it the + proper color type */ + if (dev_proc(dev, dev_spec_op)(dev, gxdso_supports_devn, NULL, 0)) { + for (i = 0; i < ncomps; i++) + pdc->colors.devn.values[i] = cv[i]; + pdc->type = gx_dc_type_devn; + } else { + /* encode as a color index */ + color = dev_proc(dev, encode_color)(dev, cv); - /* check if the encoding was successful; we presume failure is rare */ - if (color != gx_no_color_index) - color_set_pure(pdc, color); - else - cmap_separation_halftoned(all, pdc, pis, dev, select); + /* check if the encoding was successful; we presume failure is rare */ + if (color != gx_no_color_index) + color_set_pure(pdc, color); + else + cmap_separation_halftoned(all, pdc, pis, dev, select); + } + return; } /* Routines for handling CM of CMYK components of a DeviceN color space */ @@ -1410,22 +1428,35 @@ cmap_devicen_direct(const frac * pcc, in PDF and PS data. */ code = devicen_icc_cmyk(cm_comps, pis, dev); } - /* apply the transfer function(s); convert to color values */ - if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) - for (i = 0; i < ncomps; i++) - cv[i] = frac2cv(gx_map_color_frac(pis, - cm_comps[i], effective_transfer[i])); - else - for (i = 0; i < ncomps; i++) - cv[i] = frac2cv(frac_1 - gx_map_color_frac(pis, - (frac)(frac_1 - cm_comps[i]), effective_transfer[i])); - /* encode as a color index */ - color = dev_proc(dev, encode_color)(dev, cv); - /* check if the encoding was successful; we presume failure is rare */ - if (color != gx_no_color_index) - color_set_pure(pdc, color); - else - cmap_devicen_halftoned(pcc, pdc, pis, dev, select); + /* apply the transfer function(s); convert to color values. + assign directly if output device supports devn */ + if (dev_proc(dev, dev_spec_op)(dev, gxdso_supports_devn, NULL, 0)) { + if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) + for (i = 0; i < ncomps; i++) + pdc->colors.devn.values[i] = frac2cv(gx_map_color_frac(pis, + cm_comps[i], effective_transfer[i])); + else + for (i = 0; i < ncomps; i++) + pdc->colors.devn.values[i] = frac2cv(frac_1 - gx_map_color_frac(pis, + (frac)(frac_1 - cm_comps[i]), effective_transfer[i])); + pdc->type = gx_dc_type_devn; + } else { + if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) + for (i = 0; i < ncomps; i++) + cv[i] = frac2cv(gx_map_color_frac(pis, + cm_comps[i], effective_transfer[i])); + else + for (i = 0; i < ncomps; i++) + cv[i] = frac2cv(frac_1 - gx_map_color_frac(pis, + (frac)(frac_1 - cm_comps[i]), effective_transfer[i])); + /* encode as a color index */ + color = dev_proc(dev, encode_color)(dev, cv); + /* check if the encoding was successful; we presume failure is rare */ + if (color != gx_no_color_index) + color_set_pure(pdc, color); + else + cmap_devicen_halftoned(pcc, pdc, pis, dev, select); + } } /* ------ Halftoning check ----- */ diff --git a/gs/base/gxdcolor.c b/gs/base/gxdcolor.c index 45e8b397d..9d64b41e9 100644 --- a/gs/base/gxdcolor.c +++ b/gs/base/gxdcolor.c @@ -78,6 +78,25 @@ const gx_device_color_type_t gx_dc_type_data_pure = { const gx_device_color_type_t *const gx_dc_type_pure = &gx_dc_type_data_pure; #define gx_dc_type_pure (&gx_dc_type_data_pure) +/* This devn color type is used for handling the separation devices. + It essentially holds devicen and/or separation color values. */ +static dev_color_proc_save_dc(gx_dc_devn_save_dc); +static dev_color_proc_load(gx_dc_devn_load); +static dev_color_proc_fill_rectangle(gx_dc_devn_fill_rectangle); +static dev_color_proc_equal(gx_dc_devn_equal); +static dev_color_proc_write(gx_dc_devn_write); +static dev_color_proc_read(gx_dc_devn_read); +const gx_device_color_type_t gx_dc_type_data_devn = { + &st_bytes, + gx_dc_devn_save_dc, gx_dc_no_get_dev_halftone, gx_dc_no_get_phase, + gx_dc_devn_load, gx_dc_devn_fill_rectangle, gx_dc_devn_fill_masked, + gx_dc_devn_equal, gx_dc_devn_write, gx_dc_devn_read, + gx_dc_devn_get_nonzero_comps +}; +#undef gx_dc_type_devn +const gx_device_color_type_t *const gx_dc_type_devn = &gx_dc_type_data_devn; +#define gx_dc_type_devn (&gx_dc_type_data_devn) + /* * Get the black and white pixel values of a device. */ @@ -182,6 +201,7 @@ static const gx_device_color_type_t * dc_color_type_table[] = { gx_dc_type_pattern, /* patterns */ gx_dc_type_ht_binary, /* binary halftone device colors */ gx_dc_type_ht_colored, /* general halftone device colors */ + gx_dc_type_devn /* DeviceN color for planar sep devices */ }; int @@ -386,6 +406,367 @@ gx_dc_null_read( return 0; } + +/* ------ DeviceN high level colors for sep devices ------ */ + +static void +gx_dc_devn_save_dc(const gx_device_color * pdevc, gx_device_color_saved * psdc) +{ + psdc->type = pdevc->type; + memcpy(&(psdc->colors.devn.values[0]), &(pdevc->colors.devn.values[0]), + GX_DEVICE_COLOR_MAX_COMPONENTS*sizeof(ushort)); +} + +static int +gx_dc_devn_load(gx_device_color * pdevc, const gs_imager_state * ignore_pis, + gx_device * ignore_dev, gs_color_select_t ignore_select) +{ + return 0; +} + +/* Fill a rectangle with a devicen color. */ +static int +gx_dc_devn_fill_rectangle(const gx_device_color * pdevc, int x, int y, + int w, int h, gx_device * dev, + gs_logical_operation_t lop, + const gx_rop_source_t * source) +{ + gs_fixed_rect rect; + + rect.p.x = x; + rect.p.y = y; + rect.q.x = w + x; + rect.q.y = h + y; + return (*dev_proc(dev, fill_rectangle_hl_color)) (dev, &rect, NULL, pdevc, NULL); +} + +/* Fill a mask with a DeviceN color. */ +/* Note that there is no source in this case: the mask is the source. + I would like to add a device proc that was fill_masked_hl for + handling this instead of breaking this down to hl rect fills */ +int +gx_dc_devn_fill_masked(const gx_device_color * pdevc, const byte * data, + int data_x, int raster, gx_bitmap_id id, int x, int y, int w, int h, + gx_device * dev, gs_logical_operation_t lop, bool invert) +{ + int lbit = data_x & 7; + const byte *row = data + (data_x >> 3); + uint one = (invert ? 0 : 0xff); + uint zero = one ^ 0xff; + int iy; + gs_fixed_rect rect; + + for (iy = 0; iy < h; ++iy, row += raster) { + const byte *p = row; + int bit = lbit; + int left = w; + int l0; + + while (left) { + int run, code; + + /* Skip a run of zeros. */ + run = byte_bit_run_length[bit][*p ^ one]; + if (run) { + if (run < 8) { + if (run >= left) + break; /* end of row while skipping */ + bit += run, left -= run; + } else if ((run -= 8) >= left) + break; /* end of row while skipping */ + else { + left -= run; + ++p; + while (left > 8 && *p == zero) + left -= 8, ++p; + run = byte_bit_run_length_0[*p ^ one]; + if (run >= left) /* run < 8 unless very last byte */ + break; /* end of row while skipping */ + else + bit = run & 7, left -= run; + } + } + l0 = left; + /* Scan a run of ones, and then paint it. */ + run = byte_bit_run_length[bit][*p ^ zero]; + if (run < 8) { + if (run >= left) + left = 0; + else + bit += run, left -= run; + } else if ((run -= 8) >= left) + left = 0; + else { + left -= run; + ++p; + while (left > 8 && *p == one) + left -= 8, ++p; + run = byte_bit_run_length_0[*p ^ zero]; + if (run >= left) /* run < 8 unless very last byte */ + left = 0; + else + bit = run & 7, left -= run; + } + rect.p.x = x + w - l0; + rect.p.y = y + iy; + rect.q.x = x + w - left; + rect.q.y = y + iy + 1; + code = (*dev_proc(dev, fill_rectangle_hl_color)) + (dev, &rect, NULL, pdevc, NULL); + if (code < 0) + return code; + } + } + return 0; +} + +static bool +gx_dc_devn_equal(const gx_device_color * pdevc1, const gx_device_color * pdevc2) +{ + int k; + + if (pdevc1->type == gx_dc_type_devn && pdevc2->type == gx_dc_type_devn) { + for (k = 0; k < GX_DEVICE_COLOR_MAX_COMPONENTS; k++) { + if (pdevc1->colors.devn.values[k] != pdevc2->colors.devn.values[k]) { + return false; + } + } + return true; + } else { + return false; + } +} + +/* + * Utility to write a devn color into the clist. We should only be here + * if the device can handle these colors (e.g. a separation device like + * tiffsep). TODO: Reduce the size of this by removing leading zeros in + * the mask. + * + */ +static int +gx_devn_write_color( + const gx_device_color *pdevc, + const gx_device * dev, + byte * pdata, + uint * psize ) +{ + int num_bytes1, num_bytes_temp, num_bytes; + gx_color_index mask, mask_temp; + int count; + int i, ncomps = dev->color_info.num_components; + + /* Figure out the size needed. First find the number of non zero values */ + count = gx_dc_devn_get_nonzero_comps(pdevc, dev, &mask); + num_bytes1 = sizeof(gx_color_index); + num_bytes = num_bytes1 + count * 2 + 1; + num_bytes_temp = num_bytes1; + + /* check for adequate space */ + if (*psize < num_bytes) { + *psize = num_bytes; + return_error(gs_error_rangecheck); + } + *psize = num_bytes; + /* write out the mask */ + mask_temp = mask; + while (--num_bytes1 >= 0) { + pdata[num_bytes1] = mask_temp & 0xff; + mask_temp >>= 8; + } + /* Now the data */ + for (i = 0; i < ncomps; i++) { + if (mask & 1) { + pdata[num_bytes_temp] = pdevc->colors.devn.values[i] & 0xff; + num_bytes_temp++; + pdata[num_bytes_temp] = (pdevc->colors.devn.values[i] >> 8) & 0xff; + num_bytes_temp++; + } + mask >>= 1; + } + return 0; +} + +/* + * Serialize a DeviceN color. + * + * Operands: + * + * pdevc pointer to device color to be serialized + * + * psdc pointer ot saved version of last serialized color (for + * this band); this is ignored + * + * dev pointer to the current device, used to retrieve process + * color model information + * + * pdata pointer to buffer in which to write the data + * + * psize pointer to a location that, on entry, contains the size of + * the buffer pointed to by pdata; on return, the size of + * the data required or actually used will be written here. + * + * Returns: + * + * 1, with *psize set to 0, if *pdevc and *psdc represent the same color + * + * 0, with *psize set to the amount of data written, if everything OK + * + * gs_error_rangecheck, with *psize set to the size of buffer required, + * if *psize was not large enough + * + * < 0, != gs_error_rangecheck, in the event of some other error; in this + * case *psize is not changed. + */ +int +gx_dc_devn_write( + const gx_device_color * pdevc, + const gx_device_color_saved * psdc, /* ignored */ + const gx_device * dev, + int64_t offset, /* ignored */ + byte * pdata, + uint * psize ) +{ + int k; + + if (psdc != 0 && psdc->type == pdevc->type) { + for (k = 0; k < GX_DEVICE_COLOR_MAX_COMPONENTS; k++) { + if (pdevc->colors.devn.values[k] != psdc->colors.devn.values[k]) { + return gx_devn_write_color(pdevc, dev, pdata, psize);; + } + } + *psize = 0; + return 1; + } + return gx_devn_write_color(pdevc, dev, pdata, psize); +} + +/* + * Utility to reconstruct deviceN color from its serial representation. + * + * Operands: + * + * pcolor pointer to the location in which to write the + * reconstucted color + * + * dev pointer to the current device, used to retrieve process + * color model information + * + * pdata pointer to the buffer to be read + * + * size size of the buffer to be read; this is expected to be + * large enough for the full color + * + * Returns: # of bytes read, or < 0 in the event of an error + */ + +static int +gx_devn_read_color( + ushort values[], + const gx_device * dev, + const byte * pdata, + int size ) +{ + gx_color_index mask = 0; + int i; + int ncomps = dev->color_info.num_components; + int pos; + int num_bytes; + + /* check that enough data has been provided */ + if (size < 1) + return_error(gs_error_rangecheck); + + /* First get the mask. */ + for (i = 0; i < sizeof(gx_color_index); i++) + mask = (mask << 8) | pdata[i]; + pos = i; + num_bytes = i; + /* Now the data */ + for (i = 0; i < ncomps; i++) { + if (mask & 1) { + values[i] = pdata[pos]; + pos++; + values[i] += (pdata[pos]<<8); + pos++; + num_bytes += 2; + } else { + values[i] = 0; + } + mask >>= 1; + } + return num_bytes+1; +} + +/* + * Reconstruct a deviceN device color from its serial representation. + * + * Operands: + * + * pdevc pointer to the location in which to write the + * reconstructed device color + * + * pis pointer to the current imager state (ignored here) + * + * prior_devc pointer to the current device color (this is provided + * separately because the device color is not part of the + * imager state; it is ignored here) + * + * dev pointer to the current device, used to retrieve process + * color model information + * + * pdata pointer to the buffer to be read + * + * size size of the buffer to be read; this should be large + * enough to hold the entire color description + * + * mem pointer to the memory to be used for allocations + * (ignored here) + * + * Returns: + * + * # of bytes read if everthing OK, < 0 in the event of an error + */ +static int +gx_dc_devn_read( + gx_device_color * pdevc, + const gs_imager_state * pis, /* ignored */ + const gx_device_color * prior_devc, /* ignored */ + const gx_device * dev, + int64_t offset, /* ignored */ + const byte * pdata, + uint size, + gs_memory_t * mem ) /* ignored */ +{ + pdevc->type = gx_dc_type_devn; + return gx_devn_read_color(&(pdevc->colors.devn.values[0]), dev, pdata, size); +} + +/* Remember these are 16 bit values. Also here we return the number of + nonzero entries so we can figure out the size for the clist more + easily. Hopefully that does not cause any confusion in overprint + situations where is where this operation is also used. */ +int +gx_dc_devn_get_nonzero_comps( + const gx_device_color * pdevc, + const gx_device * dev, + gx_color_index * pcomp_bits ) +{ + int i, ncomps = dev->color_info.num_components; + gx_color_index mask = 0x1, comp_bits = 0; + int count = 0; + + for (i = 0; i < ncomps; i++, mask <<= 1) { + if (pdevc->colors.devn.values[i] != 0) { + comp_bits |= mask; + count++; + } + } + *pcomp_bits = comp_bits; + + return count; +} + /* ------ Pure color ------ */ static void diff --git a/gs/base/gxdcolor.h b/gs/base/gxdcolor.h index 564fa26db..01e2f0bc1 100644 --- a/gs/base/gxdcolor.h +++ b/gs/base/gxdcolor.h @@ -253,6 +253,7 @@ struct gx_device_color_type_s { /* Define the default implementation of fill_masked. */ dev_color_proc_fill_masked(gx_dc_default_fill_masked); +dev_color_proc_fill_masked(gx_dc_devn_fill_masked); extern dev_color_proc_write(gx_dc_cannot_write); extern dev_color_proc_read(gx_dc_cannot_read); @@ -274,9 +275,12 @@ extern const gx_device_color_type_t #define gx_dc_type_ht_binary (&gx_dc_type_data_ht_binary) gx_dc_type_data_ht_binary, /* gxht.c */ #define gx_dc_type_ht_colored (&gx_dc_type_data_ht_colored) - gx_dc_type_data_ht_colored; /* gxcht.c */ + gx_dc_type_data_ht_colored, /* gxcht.c */ +#define gx_dc_type_devn (&gx_dc_type_data_devn) + gx_dc_type_data_devn; /* gxdcolor.c */ /* the following are exported for the benefit of gsptype1.c */ +extern dev_color_proc_get_nonzero_comps(gx_dc_devn_get_nonzero_comps); extern dev_color_proc_get_nonzero_comps(gx_dc_pure_get_nonzero_comps); extern dev_color_proc_get_nonzero_comps(gx_dc_ht_binary_get_nonzero_comps); extern dev_color_proc_get_nonzero_comps(gx_dc_ht_colored_get_nonzero_comps); diff --git a/gs/base/gxdevcli.h b/gs/base/gxdevcli.h index 2ad3b0b82..75264ab2f 100644 --- a/gs/base/gxdevcli.h +++ b/gs/base/gxdevcli.h @@ -323,8 +323,10 @@ typedef struct gx_device_color_info_s { /* * The number of bits of gx_color_index actually used. * This must be <= arch_sizeof_color_index, which is usually 64. + * Note that we now have planar devices which can support much more. + * Changing this to a ushort to reflect this. */ - byte depth; + ushort depth; /* * Index of the gray color component, if any. The max_gray and @@ -1275,8 +1277,10 @@ typedef enum { the high level color. The device should skip such rectangles returning a proper code. - Currently this function is used with gs_rectfill and gs_fillpage only. - In future it should be called while decomposing other objects. + Currently this function is used with gs_rectfill and gs_fillpage. It is + also used for the handling of the devn color type for supporting + large number of spot colorants to planar separation devices. + */ #define dev_t_proc_fill_rectangle_hl_color(proc, dev_t)\ @@ -1449,6 +1453,14 @@ typedef struct gs_devn_params_s gs_devn_params; #define dev_proc_strip_copy_rop2(proc)\ dev_t_proc_strip_copy_rop2(proc, gx_device) +#define dev_t_proc_strip_tile_rect_devn(proc, dev_t)\ + int proc(dev_t *dev,\ + const gx_strip_bitmap *tiles, int x, int y, int width, int height,\ + const gx_drawing_color *pdcolor0, const gx_drawing_color *pdcolor1,\ + int phase_x, int phase_y) +#define dev_proc_strip_tile_rect_devn(proc)\ + dev_t_proc_strip_tile_rect_devn(proc, gx_device) + /* Define the device procedure vector template proper. */ #define gx_device_proc_struct(dev_t)\ @@ -1522,6 +1534,7 @@ typedef struct gs_devn_params_s gs_devn_params; dev_t_proc_get_profile((*get_profile), dev_t); \ dev_t_proc_set_graphics_type_tag((*set_graphics_type_tag), dev_t); \ dev_t_proc_strip_copy_rop2((*strip_copy_rop2), dev_t);\ + dev_t_proc_strip_tile_rect_devn((*strip_tile_rect_devn), dev_t);\ } /* diff --git a/gs/base/gxdevice.h b/gs/base/gxdevice.h index 70bcb02da..f1c2e4720 100644 --- a/gs/base/gxdevice.h +++ b/gs/base/gxdevice.h @@ -273,6 +273,7 @@ dev_proc_dev_spec_op(gx_default_dev_spec_op); dev_proc_fill_rectangle_hl_color(gx_default_fill_rectangle_hl_color); dev_proc_include_color_space(gx_default_include_color_space); dev_proc_fill_linear_color_scanline(gx_default_fill_linear_color_scanline); +dev_proc_fill_linear_color_scanline(gx_hl_fill_linear_color_scanline); dev_proc_fill_linear_color_trapezoid(gx_default_fill_linear_color_trapezoid); dev_proc_fill_linear_color_triangle(gx_default_fill_linear_color_triangle); dev_proc_update_spot_equivalent_colors(gx_default_update_spot_equivalent_colors); @@ -281,6 +282,7 @@ dev_proc_fillpage(gx_default_fillpage); dev_proc_get_profile(gx_default_get_profile); dev_proc_set_graphics_type_tag(gx_default_set_graphics_type_tag); dev_proc_strip_copy_rop2(gx_default_strip_copy_rop2); +dev_proc_strip_tile_rect_devn(gx_default_strip_tile_rect_devn); /* BACKWARD COMPATIBILITY */ #define gx_non_imaging_create_compositor gx_null_create_compositor @@ -369,6 +371,7 @@ dev_proc_create_compositor(gx_forward_create_compositor); dev_proc_get_profile(gx_forward_get_profile); dev_proc_set_graphics_type_tag(gx_forward_set_graphics_type_tag); dev_proc_strip_copy_rop2(gx_forward_strip_copy_rop2); +dev_proc_strip_tile_rect_devn(gx_forward_strip_tile_rect_devn); /* ---------------- Implementation utilities ---------------- */ diff --git a/gs/base/gxdevsop.h b/gs/base/gxdevsop.h index 27433613d..d20d5709a 100644 --- a/gs/base/gxdevsop.h +++ b/gs/base/gxdevsop.h @@ -227,7 +227,16 @@ enum { * Or return 0 if none do. */ gxdso_device_child, - + /* gxdso_supports_devn: + * data = NULL + * size = 0 + * Returns 1 if the device supports devicen colors. example tiffsep. + */ + gxdso_supports_devn, + /* gxdso_supports_hlcolor: + * for devices that can handle pattern and other high level structures + directly. */ + gxdso_supports_hlcolor, /* Add new gxdso_ keys above this. */ gxdso_pattern__LAST }; diff --git a/gs/base/gxgetbit.h b/gs/base/gxgetbit.h index 41b2a841d..d2b3b5fa2 100644 --- a/gs/base/gxgetbit.h +++ b/gs/base/gxgetbit.h @@ -41,7 +41,7 @@ typedef gx_bitmap_format_t gs_get_bits_options_t; */ struct gs_get_bits_params_s { gs_get_bits_options_t options; - byte *data[32]; + byte *data[GS_CLIENT_COLOR_MAX_COMPONENTS]; int x_offset; /* in returned data */ int original_y; uint raster; diff --git a/gs/base/gxht.c b/gs/base/gxht.c index b970a50b5..96b00aa57 100644 --- a/gs/base/gxht.c +++ b/gs/base/gxht.c @@ -728,6 +728,7 @@ gx_ht_init_cache(const gs_memory_t *mem, gx_ht_cache * pcache, const gx_ht_order bt->tiles.rep_width = width; bt->tiles.rep_height = height; bt->tiles.shift = bt->tiles.rep_shift = shift; + bt->tiles.num_planes = 1; } pcache->render_ht = gx_render_ht_default; } diff --git a/gs/base/gxicolor.c b/gs/base/gxicolor.c index 5205bc96e..358a6dd8f 100644 --- a/gs/base/gxicolor.c +++ b/gs/base/gxicolor.c @@ -1012,7 +1012,7 @@ image_render_color_DeviceN(gx_image_enum *penum_orig, const byte *buffer, int da color_samples next; /* next sample value */ const byte *bufend = psrc + w; int code = 0, mcode = 0; - int i; + int i; bits32 mask = penum->mask_color.mask; bits32 test = penum->mask_color.test; @@ -1020,6 +1020,13 @@ image_render_color_DeviceN(gx_image_enum *penum_orig, const byte *buffer, int da return 0; pdevc = &devc1; pdevc_next = &devc2; + /* In case these are devn colors */ + if (dev_proc(dev, dev_spec_op)(dev, gxdso_supports_devn, NULL, 0)) { + for (i = 0; i < GS_CLIENT_COLOR_MAX_COMPONENTS; i++) { + pdevc->colors.devn.values[i] = 0; + pdevc_next->colors.devn.values[i] = 0; + } + } /* These used to be set by init clues */ pdevc->type = gx_dc_type_none; pdevc_next->type = gx_dc_type_none; diff --git a/gs/base/gxp1fill.c b/gs/base/gxp1fill.c index 31a014f62..0022f5f47 100644 --- a/gs/base/gxp1fill.c +++ b/gs/base/gxp1fill.c @@ -243,36 +243,19 @@ tile_colored_fill(const tile_fill_state_t * ptfs, bool full_transfer = (w == ptfs->w0 && h == ptfs->h0); int code = 0; - if (source == NULL && lop_no_S_is_T(lop) && ptfs->num_planes < 0) { - /* RJW: Ideally, we'd like to remove the 'ptfs->num_planes < 0' test - * above, and then do: - * - * if (ptfs->num_planes >= 0) { - * int plane_step = ptile->tbits.raster * ptile->tbits.rep_height; - * int k; - * for (k = 0; k < ptfs->num_planes; k++) { - * byte *data_plane = (byte*) (data + plane_step * k); - * (*dev_proc(ptfs->pcdev, copy_plane)) - * (ptfs->pcdev, - * data_plane + bits->raster * yoff, - * xoff, bits->raster, - * gx_no_bitmap_id, x, y, - * w, h, k); - * } - * } else - * - * Unfortunately, this can cause the rop source device to be called - * with copy_plane. This is currently broken (and I fear cannot ever - * be done properly). We therefore drop back to the strip_copy_rop - * case below. - */ - { + if (source == NULL && lop_no_S_is_T(lop) && dev->procs.copy_planes != NULL && + ptfs->num_planes > 0) { + code = (*dev_proc(ptfs->pcdev, copy_planes)) + (ptfs->pcdev, data + bits->raster * yoff, xoff, + bits->raster, + (full_transfer ? bits->id : gx_no_bitmap_id), + x, y, w, h, ptile->tbits.rep_height); + } else if (source == NULL && lop_no_S_is_T(lop)) { code = (*dev_proc(ptfs->pcdev, copy_color)) (ptfs->pcdev, data + bits->raster * yoff, xoff, bits->raster, (full_transfer ? bits->id : gx_no_bitmap_id), x, y, w, h); - } } else { gx_strip_bitmap data_tile; gx_bitmap_id source_id; @@ -380,12 +363,7 @@ gx_dc_pattern_fill_rectangle(const gx_device_color * pdevc, int x, int y, if (CLIPDEV_INSTALLED) tile_clip_set_phase(&state.cdev, px, py); - /* RJW: Can we get away with calling the simpler version? Not - * if we are working in planar mode because the default - * strip_tile_rectangle doesn't understand bits being in planar - * mode at the moment. - */ - if (source == NULL && lop_no_S_is_T(lop) && state.num_planes == -1) + if (source == NULL && lop_no_S_is_T(lop)) code = (*dev_proc(state.pcdev, strip_tile_rectangle)) (state.pcdev, bits, x, y, w, h, gx_no_color_index, gx_no_color_index, px, py); @@ -495,6 +473,35 @@ gx_dc_pure_masked_fill_rect(const gx_device_color * pdevc, } int +gx_dc_devn_masked_fill_rect(const gx_device_color * pdevc, + int x, int y, int w, int h, gx_device * dev, + gs_logical_operation_t lop, + const gx_rop_source_t * source) +{ + gx_color_tile *ptile = pdevc->mask.m_tile; + tile_fill_state_t state; + int code; + + /* + * This routine should never be called if there is no masking, + * but we leave the checks below just in case. + */ + code = tile_fill_init(&state, pdevc, dev, true); + if (code < 0) + return code; + if (state.pcdev == dev || ptile->is_simple) + return (*gx_dc_type_data_devn.fill_rectangle) + (pdevc, x, y, w, h, state.pcdev, lop, source); + else { + state.lop = lop; + state.source = source; + state.fill_rectangle = gx_dc_type_data_devn.fill_rectangle; + return tile_by_steps(&state, x, y, w, h, ptile, &ptile->tmask, + tile_masked_fill); + } +} + +int gx_dc_binary_masked_fill_rect(const gx_device_color * pdevc, int x, int y, int w, int h, gx_device * dev, gs_logical_operation_t lop, @@ -995,4 +1002,4 @@ gx_trans_pattern_fill_rect(int xmin, int ymin, int xmax, int ymax, } } return(code); -} +}
\ No newline at end of file diff --git a/gs/base/gxp1impl.h b/gs/base/gxp1impl.h index bc016ff59..eb1280417 100644 --- a/gs/base/gxp1impl.h +++ b/gs/base/gxp1impl.h @@ -25,6 +25,7 @@ */ dev_color_proc_fill_rectangle(gx_dc_pattern_fill_rectangle); dev_color_proc_fill_rectangle(gx_dc_pure_masked_fill_rect); +dev_color_proc_fill_rectangle(gx_dc_devn_masked_fill_rect); dev_color_proc_fill_rectangle(gx_dc_binary_masked_fill_rect); dev_color_proc_fill_rectangle(gx_dc_colored_masked_fill_rect); dev_color_proc_fill_rectangle(gx_dc_pat_trans_fill_rectangle); diff --git a/gs/base/gxpcmap.c b/gs/base/gxpcmap.c index 6f255434b..893574355 100644 --- a/gs/base/gxpcmap.c +++ b/gs/base/gxpcmap.c @@ -91,6 +91,7 @@ static dev_proc_copy_mono(pattern_accum_copy_mono); static dev_proc_copy_color(pattern_accum_copy_color); static dev_proc_copy_planes(pattern_accum_copy_planes); static dev_proc_get_bits_rectangle(pattern_accum_get_bits_rectangle); +static dev_proc_fill_rectangle_hl_color(pattern_accum_fill_rectangle_hl_color); /* The device descriptor */ static const gx_device_pattern_accum gs_pattern_accum_device = @@ -153,7 +154,7 @@ static const gx_device_pattern_accum gs_pattern_accum_device = NULL, /* encode_color */ NULL, /* decode_color */ NULL, /* pattern_manage */ - NULL, /* fill_rectangle_hl_color */ + pattern_accum_fill_rectangle_hl_color, /* fill_rectangle_hl_color */ NULL, /* include_color_space */ NULL, /* fill_linear_color_scanline */ NULL, /* fill_linear_color_trapezoid */ @@ -168,7 +169,8 @@ static const gx_device_pattern_accum gs_pattern_accum_device = pattern_accum_copy_planes, /* copy_planes */ NULL, /* get_profile */ NULL, /* set_graphics_type_tag */ - gx_default_strip_copy_rop2 + gx_default_strip_copy_rop2, + gx_default_strip_tile_rect_devn }, 0, /* target */ 0, 0, 0, 0 /* bitmap_memory, bits, mask, instance */ @@ -336,6 +338,7 @@ gx_pattern_accum_alloc(gs_memory_t * mem, gs_memory_t * storage_memory, cwdev->width = pinst->size.x; cwdev->height = pinst->size.y; cwdev->LeadingEdge = tdev->LeadingEdge; + cwdev->is_planar = pinst->is_planar; /* Fields left zeroed : float MediaSize[2]; float ImagingBBox[4]; @@ -584,6 +587,33 @@ pattern_accum_close(gx_device * dev) return 0; } +/* _hl_color */ +static int +pattern_accum_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect, + const gs_imager_state *pis, + const gx_drawing_color *pdcolor, + const gx_clip_path *pcpath) +{ + gx_device_pattern_accum *const padev = (gx_device_pattern_accum *) dev; + + if (padev->bits) + (*dev_proc(padev->target, fill_rectangle_hl_color)) + (padev->target, rect, pis, pdcolor, pcpath); + if (padev->mask) { + int x, y, w, h; + + x = rect->p.x; + y = rect->p.y; + w = rect->q.x - x; + h = rect->q.y - y; + + return (*dev_proc(padev->mask, fill_rectangle)) + ((gx_device *) padev->mask, x, y, w, h, (gx_color_index) 1); + } + else + return 0; +} + /* Fill a rectangle */ static int pattern_accum_fill_rectangle(gx_device * dev, int x, int y, int w, int h, @@ -1119,7 +1149,7 @@ dump_raw_pattern(int height, int width, int n_chan, int depth, width,height,max_bands); } fid = fopen(full_file_name,"wb"); - if (depth == 8 * n_chan) { + if (depth >= 8) { /* Contone data. */ if (is_planar) { for (m = 0; m < max_bands; m++) { @@ -1424,6 +1454,8 @@ gs_pattern1_remap_color(const gs_client_color * pc, const gs_color_space * pcs, pdc->type = &gx_dc_binary_masked; else if (pdc->type == gx_dc_type_ht_colored) pdc->type = &gx_dc_colored_masked; + else if (pdc->type == gx_dc_type_devn) + pdc->type = &gx_dc_devn_masked; else return_error(gs_error_unregistered); } else diff --git a/gs/base/gxpcolor.h b/gs/base/gxpcolor.h index 34ce7a08a..8b28f8fdc 100644 --- a/gs/base/gxpcolor.h +++ b/gs/base/gxpcolor.h @@ -128,8 +128,8 @@ extern const gs_color_space_type gs_color_space_type_Pattern; * device color type. */ extern const gx_device_color_type_t - gx_dc_pattern, - gx_dc_pure_masked, gx_dc_binary_masked, gx_dc_colored_masked; + gx_dc_pattern, gx_dc_pure_masked, gx_dc_binary_masked, + gx_dc_colored_masked, gx_dc_devn_masked; #ifndef gx_dc_type_pattern #define gx_dc_type_pattern (&gx_dc_pattern) diff --git a/gs/base/gxshade6.c b/gs/base/gxshade6.c index c3aa2727a..f08fa8127 100644 --- a/gs/base/gxshade6.c +++ b/gs/base/gxshade6.c @@ -1333,7 +1333,7 @@ gx_shade_trapezoid(patch_fill_state_t *pfs, const gs_fixed_point q[4], } static inline void -dc2fc(const patch_fill_state_t *pfs, gx_color_index c, +dc2fc(const patch_fill_state_t *pfs, gx_device_color *pdevc, frac31 fc[GX_DEVICE_COLOR_MAX_COMPONENTS]) { int j; @@ -1343,24 +1343,37 @@ dc2fc(const patch_fill_state_t *pfs, gx_color_index c, the device from which we want to get the color information from for this */ - for (j = 0; j < cinfo->num_components; j++) { - int shift = cinfo->comp_shift[j]; - int bits = cinfo->comp_bits[j]; + if (pdevc->type == &gx_dc_type_data_pure) { + for (j = 0; j < cinfo->num_components; j++) { + int shift = cinfo->comp_shift[j]; + int bits = cinfo->comp_bits[j]; - fc[j] = ((c >> shift) & ((1 << bits) - 1)) << (sizeof(frac31) * 8 - 1 - bits); + fc[j] = ((pdevc->colors.pure >> shift) & ((1 << bits) - 1)) << + (sizeof(frac31) * 8 - 1 - bits); + } + } else { + for (j = 0; j < cinfo->num_components; j++) { + fc[j] = cv2frac(pdevc->colors.devn.values[j]); + } } } #define DEBUG_COLOR_INDEX_CACHE 0 static inline int -patch_color_to_device_color_inline(const patch_fill_state_t *pfs, const patch_color_t *c, gx_device_color *pdevc, frac31 *frac_values) +patch_color_to_device_color_inline(const patch_fill_state_t *pfs, + const patch_color_t *c, gx_device_color *pdevc, + frac31 *frac_values) { /* Must return 2 if the color is not pure. See try_device_linear_color. */ int code; gx_device_color devc; + gx_device *dev = pfs->dev; + + if (pfs->trans_device != NULL) + dev = pfs->trans_device; if (DEBUG_COLOR_INDEX_CACHE && pdevc == NULL) pdevc = &devc; @@ -1387,9 +1400,10 @@ patch_color_to_device_color_inline(const patch_fill_state_t *pfs, const patch_co if (code < 0) return code; if (frac_values != NULL) { - dc2fc(pfs, pdevc->colors.pure, frac_values); - if (pdevc->type != &gx_dc_type_data_pure) + if (!(pdevc->type == &gx_dc_type_data_devn || + pdevc->type == &gx_dc_type_data_pure)) return 2; + dc2fc(pfs, pdevc, frac_values); } # if DEBUG_COLOR_INDEX_CACHE if (cindex != pdevc->colors.pure) @@ -2146,7 +2160,8 @@ try_device_linear_color(patch_fill_state_t *pfs, bool wedge, code = patch_color_to_device_color_inline(pfs, p0->c, &dc[0], fc[0]); if (code != 0) return code; - if (dc[0].type != &gx_dc_type_data_pure) + if (!(dc[0].type == &gx_dc_type_data_pure || + dc[0].type == &gx_dc_type_data_devn)) return 2; if (!wedge) { code = patch_color_to_device_color_inline(pfs, p1->c, &dc[1], fc[1]); diff --git a/gs/base/lib.mak b/gs/base/lib.mak index 98c3e3f6b..b9df6e8eb 100644 --- a/gs/base/lib.mak +++ b/gs/base/lib.mak @@ -668,7 +668,7 @@ $(GLOBJ)gxcmap.$(OBJ) : $(GLSRC)gxcmap.c $(AK) $(gx_h) $(gserrors_h)\ $(gxdcconv_h) $(gxdevice_h) $(gxcmap_h) $(gxlum_h)\ $(gzstate_h) $(gxdither_h) $(gxcdevn_h) $(string__h)\ $(gsicc_manage_h) $(gdevdevn_h) $(gsicc_cache_h)\ - $(gscms_h) $(gsicc_h) $(MAKEDIRS) + $(gscms_h) $(gsicc_h) $(gxdevsop_h) $(MAKEDIRS) $(GLCC) $(GLO_)gxcmap.$(OBJ) $(C_) $(GLSRC)gxcmap.c $(GLOBJ)gxcpath.$(OBJ) : $(GLSRC)gxcpath.c $(AK) $(gx_h) $(gserrors_h)\ @@ -1089,6 +1089,10 @@ $(GLOBJ)gdevm64.$(OBJ) : $(GLSRC)gdevm64.c $(AK) $(gx_h) $(memory__h)\ $(gxdevice_h) $(gxdevmem_h) $(gdevmem_h) $(MAKEDIRS) $(GLCC) $(GLO_)gdevm64.$(OBJ) $(C_) $(GLSRC)gdevm64.c +$(GLOBJ)gdevmx.$(OBJ) : $(GLSRC)gdevmx.c $(AK) $(gx_h) $(memory__h)\ + $(gxdevice_h) $(gxdevmem_h) $(gdevmem_h) $(MAKEDIRS) + $(GLCC) $(GLO_)gdevmx.$(OBJ) $(C_) $(GLSRC)gdevmx.c + $(GLOBJ)gdevmpla.$(OBJ) : $(GLSRC)gdevmpla.c $(AK) $(gx_h)\ $(gserrors_h) $(memory__h) $(gsbitops_h)\ $(gxdevice_h) $(gxdevmem_h) $(gxgetbit_h) $(gdevmem_h) $(gdevmpla_h)\ @@ -1180,7 +1184,8 @@ $(GLOBJ)gdevddrw.$(OBJ) : $(GLSRC)gdevddrw.c $(AK) $(gx_h)\ $(GLCC) $(GLO_)gdevddrw.$(OBJ) $(C_) $(GLSRC)gdevddrw.c $(GLOBJ)gdevdsha.$(OBJ) : $(GLSRC)gdevdsha.c $(AK) $(gx_h)\ - $(gserrors_h) $(gxdevice_h) $(gxcindex_h) $(vdtrace_h) $(MAKEDIRS) + $(gserrors_h) $(gxdevice_h) $(gxcindex_h) $(vdtrace_h)\ + $(gxdevsop_h) $(MAKEDIRS) $(GLCC) $(GLO_)gdevdsha.$(OBJ) $(C_) $(GLSRC)gdevdsha.c $(GLOBJ)gdevdflt.$(OBJ) : $(GLSRC)gdevdflt.c $(AK) $(gx_h)\ @@ -1248,7 +1253,7 @@ LIB1d=$(GLOBJ)gdevabuf.$(OBJ) $(GLOBJ)gdevdbit.$(OBJ) $(GLOBJ)gdevddrw.$(OBJ) $( LIB2d=$(GLOBJ)gdevdgbr.$(OBJ) $(GLOBJ)gdevnfwd.$(OBJ) $(GLOBJ)gdevmem.$(OBJ) $(GLOBJ)gdevplnx.$(OBJ) LIB3d=$(GLOBJ)gdevm1.$(OBJ) $(GLOBJ)gdevm2.$(OBJ) $(GLOBJ)gdevm4.$(OBJ) $(GLOBJ)gdevm8.$(OBJ) LIB4d=$(GLOBJ)gdevm16.$(OBJ) $(GLOBJ)gdevm24.$(OBJ) $(GLOBJ)gdevm32.$(OBJ) $(GLOBJ)gdevmpla.$(OBJ) -LIB5d=$(GLOBJ)gdevm40.$(OBJ) $(GLOBJ)gdevm48.$(OBJ) $(GLOBJ)gdevm56.$(OBJ) $(GLOBJ)gdevm64.$(OBJ) +LIB5d=$(GLOBJ)gdevm40.$(OBJ) $(GLOBJ)gdevm48.$(OBJ) $(GLOBJ)gdevm56.$(OBJ) $(GLOBJ)gdevm64.$(OBJ) $(GLOBJ)gdevmx.$(OBJ) LIB6d=$(GLOBJ)gdevdsha.$(OBJ) LIBs=$(LIB0s) $(LIB1s) $(LIB2s) $(LIB3s) $(LIB4s) $(LIB5s) $(LIB6s) $(LIB7s)\ $(LIB8s) $(LIB9s) $(LIB10s) $(LIB11s) $(LIB12s) $(LIB13s) @@ -1860,7 +1865,7 @@ gsiparm4_h=$(GLSRC)gsiparm4.h $(gsiparam_h) gximage3_h=$(GLSRC)gximage3.h $(gsiparm3_h) $(gxiparam_h) $(GLOBJ)gxclipm.$(OBJ) : $(GLSRC)gxclipm.c $(AK) $(gx_h) $(memory__h)\ - $(gsbittab_h) $(gxclipm_h) $(gxdevice_h) $(gxdevmem_h) $(MAKEDIRS) + $(gsbittab_h) $(gxclipm_h) $(gxdevice_h) $(gxdevmem_h) $(gxdcolor_h) $(MAKEDIRS) $(GLCC) $(GLO_)gxclipm.$(OBJ) $(C_) $(GLSRC)gxclipm.c $(GLOBJ)gximage3.$(OBJ) : $(GLSRC)gximage3.c $(AK) $(gx_h)\ @@ -2353,9 +2358,9 @@ $(GLOBJ)gsptype1.$(OBJ) : $(GLSRC)gsptype1.c $(AK)\ $(gsimage_h) $(gsiparm4_h) $(gsovrc_h) $(MAKEDIRS) $(GLCC) $(GLO_)gsptype1.$(OBJ) $(C_) $(GLSRC)gsptype1.c -$(GLOBJ)gxclip2.$(OBJ) : $(GLSRC)gxclip2.c $(AK) $(gx_h) $(gserrors_h)\ - $(memory__h) $(gsstruct_h) $(gxclip2_h) $(gxdevice_h) $(gxdevmem_h)\ - $(MAKEDIRS) +$(GLOBJ)gxclip2.$(OBJ) : $(GLSRC)gxclip2.c $(AK) $(gx_h) $(gpcheck_h)\ + $(gserrors_h) $(memory__h) $(gsstruct_h) $(gxclip2_h) $(gxdevice_h) $(gxdevmem_h)\ + $(gxdcolor_h) $(gdevmpla_h) $(MAKEDIRS) $(GLCC) $(GLO_)gxclip2.$(OBJ) $(C_) $(GLSRC)gxclip2.c $(GLOBJ)gxp1fill.$(OBJ) : $(GLSRC)gxp1fill.c $(AK) $(gx_h)\ @@ -2597,7 +2602,7 @@ $(GLD)dps2lib.dev : $(LIB_MAK) $(ECHOGS_XE) $(dps2lib_) $(GLOBJ)gsdps1.$(OBJ) : $(GLSRC)gsdps1.c $(AK) $(gx_h) $(gserrors_h)\ $(gsmatrix_h) $(gscoord_h) $(gspaint_h) $(gxdevice_h) $(gsutil_h)\ $(math__h) $(gxfixed_h) $(gspath_h) $(gspath2_h) $(gxhldevc_h)\ - $(gzpath_h) $(gzcpath_h) $(gzstate_h) $(gxmatrix_h) $(MAKEDIRS) + $(gzpath_h) $(gzcpath_h) $(gzstate_h) $(gxmatrix_h) $(gxdevsop_h) $(MAKEDIRS) $(GLCC) $(GLO_)gsdps1.$(OBJ) $(C_) $(GLSRC)gsdps1.c # ---------------- Functions ---------------- # |