diff options
author | Robin Watts <robin.watts@artifex.com> | 2011-11-14 12:19:32 +0000 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2011-11-14 18:12:20 +0000 |
commit | 96ab69c8bcc1bcf3e366b494ed099dc5b46009fe (patch) | |
tree | 4aa5b3a2f2655f896c7a3aefd1272fc6f5ae7d77 | |
parent | 940b007282d74686a20aa5cf434d20353680344c (diff) |
Planar rop fixes; extensive changes throughout code.
The changes here are largely forced upon us by the rop source device,
the internal mechanism used within the gs lib to cope with performing
rop operations with drawing operations. The rop source device is
created and is given a 'source'. Any operations then done to that device
are then passed on to its target device rewritten into a form that will
cause the output to be ropped with the source.
This causes problems when the source is in planar format (such as when
the source is a pattern tile intended for use on a planar device). There
is no way to call strip_copy_rop with planar data currently, neither
can it easily be shoehorned through. We therefore add a new
'strip_copy_rop2' entrypoint that takes an additional 'planar_height'
parameter that gives the number of lines of data before the next
planes data starts.
We add implementations of this call throughout the code; some are
very simple (bbox, null, trace, clip, clip2, clip2, tile_clip etc).
Others 'common up' with the strip_copy_rop (gx_default,
mem_planar).
The underlying memory devices should never be called with strip_copy_rop2
as the planar data will always be rewritten to chunky format before
this happens. We are free to change this approach later if we want.
The gx_rop_source_t structure used by the rop source device is extended
to have a new planar_height field, and the rop source device itself
extended to pass this on. Various places that create this structure now
initialise that correctly.
The clist reader/writer is updated to send the extra planar_height
field through and call strip_cop_rop or strip_copy_rop2 as appropriate.
In a similar vein, we are forced to change the copy_plane entry point
to be copy_planes (as it is impossible (or very hard at least) for the
rop source device to implement copy_plane).
This incorporates changes from Michael to the new "fast threshold" image
halftoning code to make it use the new copy_planes operation.
-rw-r--r-- | gs/base/gdevbbox.c | 33 | ||||
-rw-r--r-- | gs/base/gdevdflt.c | 3 | ||||
-rw-r--r-- | gs/base/gdevdrop.c | 110 | ||||
-rw-r--r-- | gs/base/gdevmem.h | 3 | ||||
-rw-r--r-- | gs/base/gdevmpla.c | 227 | ||||
-rw-r--r-- | gs/base/gdevnfwd.c | 52 | ||||
-rw-r--r-- | gs/base/gdevrops.c | 18 | ||||
-rw-r--r-- | gs/base/gdevtrac.c | 42 | ||||
-rw-r--r-- | gs/base/gxacpath.c | 2 | ||||
-rw-r--r-- | gs/base/gxcht.c | 26 | ||||
-rw-r--r-- | gs/base/gxcldev.h | 7 | ||||
-rw-r--r-- | gs/base/gxclimag.c | 6 | ||||
-rw-r--r-- | gs/base/gxclip.c | 59 | ||||
-rw-r--r-- | gs/base/gxclip.h | 10 | ||||
-rw-r--r-- | gs/base/gxclip2.c | 45 | ||||
-rw-r--r-- | gs/base/gxclipm.c | 26 | ||||
-rw-r--r-- | gs/base/gxclist.c | 5 | ||||
-rw-r--r-- | gs/base/gxclrast.c | 212 | ||||
-rw-r--r-- | gs/base/gxclrect.c | 91 | ||||
-rw-r--r-- | gs/base/gxdcolor.c | 14 | ||||
-rw-r--r-- | gs/base/gxdcolor.h | 3 | ||||
-rw-r--r-- | gs/base/gxdevcli.h | 22 | ||||
-rw-r--r-- | gs/base/gxdevice.h | 2 | ||||
-rw-r--r-- | gs/base/gxht.c | 25 | ||||
-rw-r--r-- | gs/base/gxht_thresh.c | 353 | ||||
-rw-r--r-- | gs/base/gxht_thresh.h | 7 | ||||
-rw-r--r-- | gs/base/gxicolor.c | 27 | ||||
-rw-r--r-- | gs/base/gximage.h | 3 | ||||
-rw-r--r-- | gs/base/gximono.c | 28 | ||||
-rw-r--r-- | gs/base/gxp1fill.c | 107 | ||||
-rw-r--r-- | gs/base/gxpcmap.c | 18 |
31 files changed, 1054 insertions, 532 deletions
diff --git a/gs/base/gdevbbox.c b/gs/base/gdevbbox.c index bc061c8fb..b608fca95 100644 --- a/gs/base/gdevbbox.c +++ b/gs/base/gdevbbox.c @@ -49,6 +49,7 @@ static dev_proc_fill_triangle(bbox_fill_triangle); 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_begin_typed_image(bbox_begin_typed_image); static dev_proc_create_compositor(bbox_create_compositor); static dev_proc_text_begin(bbox_text_begin); @@ -147,7 +148,12 @@ gx_device_bbox gs_bbox_device = bbox_fillpage, /* fillpage */ NULL, /* push_transparency_state */ NULL, /* pop_transparency_state */ - NULL /* put_image */ + NULL, /* put_image */ + NULL, /* dev_spec_op */ + NULL, /* copy_planes */ + NULL, /* get_profile */ + NULL, /* set_graphics_type_tag */ + bbox_strip_copy_rop2 }, 0, /* target */ 1, /*true *//* free_standing */ @@ -494,6 +500,31 @@ bbox_strip_copy_rop(gx_device * dev, return code; } +static int +bbox_strip_copy_rop2(gx_device * dev, + const byte * sdata, int sourcex, uint sraster, + gx_bitmap_id id, + const gx_color_index * scolors, + const gx_strip_bitmap * textures, + const gx_color_index * tcolors, + int x, int y, int w, int h, + int phase_x, int phase_y, gs_logical_operation_t lop, + uint planar_height) +{ + gx_device_bbox *const bdev = (gx_device_bbox *) dev; + /* gx_forward_strip_copy_rop doesn't exist */ + gx_device *tdev = bdev->target; + int code = + (tdev == 0 ? 0 : + dev_proc(tdev, strip_copy_rop2) + (tdev, sdata, sourcex, sraster, id, scolors, + textures, tcolors, x, y, w, h, phase_x, phase_y, lop, + planar_height)); + + BBOX_ADD_INT_RECT(bdev, x, y, x + w, y + h); + return code; +} + /* ---------------- Parameters ---------------- */ /* We implement get_params to provide a way to read out the bounding box. */ diff --git a/gs/base/gdevdflt.c b/gs/base/gdevdflt.c index 98dfb9ec0..805b09b24 100644 --- a/gs/base/gdevdflt.c +++ b/gs/base/gdevdflt.c @@ -559,6 +559,7 @@ gx_device_fill_in_procs(register gx_device * dev) #undef CHECK_NON_DEFAULT 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, 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); @@ -669,7 +670,7 @@ gx_device_fill_in_procs(register gx_device * dev) /* NOT pop_transparency_state */ /* NOT put_image */ fill_dev_proc(dev, dev_spec_op, gx_default_dev_spec_op); - /* NOT copy_plane */ + /* NOT copy_planes */ } int diff --git a/gs/base/gdevdrop.c b/gs/base/gdevdrop.c index ce782759c..05ff0d43f 100644 --- a/gs/base/gdevdrop.c +++ b/gs/base/gdevdrop.c @@ -24,6 +24,7 @@ #include "gxdevrop.h" #include "gxgetbit.h" #include "gdevmem.h" /* for mem_default_strip_copy_rop prototype */ +#include "gdevmpla.h" #include "gdevmrop.h" #include "gxdevsop.h" @@ -98,6 +99,24 @@ gx_default_strip_copy_rop(gx_device * dev, int phase_x, int phase_y, gs_logical_operation_t lop) { + return gx_default_strip_copy_rop2(dev, sdata, sourcex, sraster, id, + scolors, textures, tcolors, + x, y, width, height, + phase_x, phase_y, lop, 0); +} + +int +gx_default_strip_copy_rop2(gx_device * dev, + const byte * sdata, int sourcex, + uint sraster, gx_bitmap_id id, + const gx_color_index * scolors, + const gx_strip_bitmap * textures, + const gx_color_index * tcolors, + int x, int y, int width, int height, + int phase_x, int phase_y, + gs_logical_operation_t lop, + uint planar_height) +{ int depth = dev->color_info.depth; gs_memory_t *mem = dev->memory; const gx_device_memory *mdproto = gdev_mem_device_for_bits(depth); @@ -109,6 +128,7 @@ gx_default_strip_copy_rop(gx_device * dev, int block_height; int code; int py; + int is_planar = 0; #ifdef DEBUG if (gs_debug_c('b')) @@ -129,11 +149,33 @@ gx_default_strip_copy_rop(gx_device * dev, if (max_height == 0) max_height = 1; block_height = min(height, max_height); + if (planar_height > 0) + block_height = planar_height; gs_make_mem_device_with_copydevice(&pmdev, mdproto, mem, -1, dev); pmdev->width = width; pmdev->height = block_height; pmdev->bitmap_memory = mem; pmdev->color_info = dev->color_info; + if (dev_proc(dev, dev_spec_op)(dev, gxdso_is_native_planar, NULL, 0)) + { + gx_render_plane_t planes[GX_DEVICE_COLOR_MAX_COMPONENTS]; + int num_comp = dev->color_info.num_components; + int depth = dev->color_info.depth/num_comp; + int i; + for (i = 0; i < num_comp; i++) + { + planes[i].shift = depth * (num_comp - 1 - i); + planes[i].depth = depth; + planes[i].index = i; + } + /* RJW: This code, like most of ghostscripts planar support, + * will only work if every plane has the same depth. */ + draster = bitmap_raster(width * planes[0].depth); + code = gdev_mem_set_planar(pmdev, num_comp, planes); + if (code < 0) + return code; + is_planar = 1; + } code = (*dev_proc(pmdev, open_device))((gx_device *)pmdev); pmdev->is_open = true; /* not sure why we need this, but we do. */ if (code < 0) @@ -172,16 +214,36 @@ gx_default_strip_copy_rop(gx_device * dev, if (code < 0) return code; } - code = (*dev_proc(pmdev, strip_copy_rop)) - ((gx_device *)pmdev, - sdata + (py - y) * sraster, sourcex, sraster, - gx_no_bitmap_id, scolors, textures, tcolors, - 0, 0, width, block_height, phase_x + x, phase_y + py, lop); + if (planar_height == 0) { + code = (*dev_proc(pmdev, strip_copy_rop)) + ((gx_device *)pmdev, + sdata + (py - y) * sraster, sourcex, sraster, + gx_no_bitmap_id, scolors, textures, tcolors, + 0, 0, width, block_height, + phase_x + x, phase_y + py, + lop); + } else { + code = (*dev_proc(pmdev, strip_copy_rop2)) + ((gx_device *)pmdev, + sdata + (py - y) * sraster, sourcex, sraster, + gx_no_bitmap_id, scolors, textures, tcolors, + 0, 0, width, block_height, + phase_x + x, phase_y + py, + lop, planar_height); + } if (code < 0) break; - code = (*dev_proc(dev, copy_color)) - (dev, scan_line_base(pmdev, 0), 0, draster, gx_no_bitmap_id, - x, py, width, block_height); + if (is_planar) { + code = (*dev_proc(dev, copy_planes)) + (dev, scan_line_base(pmdev, 0), 0, + draster, gx_no_bitmap_id, + x, py, width, block_height, block_height); + } else { + code = (*dev_proc(dev, copy_color)) + (dev, scan_line_base(pmdev, 0), 0, + draster, gx_no_bitmap_id, + x, py, width, block_height); + } if (code < 0) break; } @@ -527,15 +589,31 @@ pack_planar_from_standard(gx_device_memory * dev, int y, int destx, * representation, and copy_color to write the pixels back. */ int +mem_default_strip_copy_rop2(gx_device * dev, + const byte * sdata, int sourcex, + uint sraster, gx_bitmap_id id, + const gx_color_index * scolors, + const gx_strip_bitmap * textures, + const gx_color_index * tcolors, + int x, int y, int width, int height, + int phase_x, int phase_y, + gs_logical_operation_t lop, + uint planar_height) +{ + dlprintf("mem_default_strip_copy_rop2 should never be called!\n"); + return gs_error_Fatal; +} + +int mem_default_strip_copy_rop(gx_device * dev, - const byte * sdata, int sourcex, - uint sraster, gx_bitmap_id id, - const gx_color_index * scolors, - const gx_strip_bitmap * textures, - const gx_color_index * tcolors, - int x, int y, int width, int height, - int phase_x, int phase_y, - gs_logical_operation_t lop) + const byte * sdata, int sourcex, + uint sraster, gx_bitmap_id id, + const gx_color_index * scolors, + const gx_strip_bitmap * textures, + const gx_color_index * tcolors, + int x, int y, int width, int height, + int phase_x, int phase_y, + gs_logical_operation_t lop) { int depth = dev->color_info.depth; int rop_depth = (gx_device_has_color(dev) ? 24 : 8); diff --git a/gs/base/gdevmem.h b/gs/base/gdevmem.h index 39686cbac..559e603ff 100644 --- a/gs/base/gdevmem.h +++ b/gs/base/gdevmem.h @@ -97,8 +97,9 @@ dev_proc_get_bits_rectangle(mem_word_get_bits_rectangle); /* The following are used for the non-true-color devices. */ dev_proc_map_rgb_color(mem_mapped_map_rgb_color); dev_proc_map_color_rgb(mem_mapped_map_color_rgb); -/* Default implementation */ +/* Default implementations */ dev_proc_strip_copy_rop(mem_default_strip_copy_rop); +dev_proc_strip_copy_rop2(mem_default_strip_copy_rop2); /* * Macro for generating the device descriptor. diff --git a/gs/base/gdevmpla.c b/gs/base/gdevmpla.c index a9efd7566..8c6bf2892 100644 --- a/gs/base/gdevmpla.c +++ b/gs/base/gdevmpla.c @@ -28,9 +28,10 @@ static dev_proc_open_device(mem_planar_open); declare_mem_procs(mem_planar_copy_mono, mem_planar_copy_color, mem_planar_fill_rectangle); static dev_proc_copy_color(mem_planar_copy_color_24to8); static dev_proc_copy_color(mem_planar_copy_color_4to1); -static dev_proc_copy_plane(mem_planar_copy_plane); +static dev_proc_copy_planes(mem_planar_copy_planes); static dev_proc_strip_tile_rectangle(mem_planar_strip_tile_rectangle); 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); /* It's a bit nasty to have to fork the planar dev_spec_op like this, but @@ -110,6 +111,7 @@ gdev_mem_set_planar(gx_device_memory * mdev, int num_planes, set_dev_proc(mdev, copy_alpha, dev_proc(mdproto, copy_alpha)); set_dev_proc(mdev, strip_tile_rectangle, dev_proc(mdproto, strip_tile_rectangle)); set_dev_proc(mdev, strip_copy_rop, dev_proc(mdproto, strip_copy_rop)); + 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 { set_dev_proc(mdev, fill_rectangle, mem_planar_fill_rectangle); @@ -132,9 +134,10 @@ gdev_mem_set_planar(gx_device_memory * mdev, int num_planes, } else set_dev_proc(mdev, copy_color, mem_planar_copy_color); set_dev_proc(mdev, copy_alpha, gx_default_copy_alpha); - set_dev_proc(mdev, copy_plane, mem_planar_copy_plane); + 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_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); } return 0; @@ -815,30 +818,33 @@ mem_planar_copy_color(gx_device * dev, const byte * base, int sourcex, /* Copy a given bitmap into a bitmap. */ static int -mem_planar_copy_plane(gx_device * dev, const byte * base, int sourcex, - int sraster, gx_bitmap_id id, - int x, int y, int w, int h, int plane) +mem_planar_copy_planes(gx_device * dev, const byte * base, int sourcex, + int sraster, gx_bitmap_id id, + int x, int y, int w, int h, int plane_height) { gx_device_memory * const mdev = (gx_device_memory *)dev; int plane_depth; mem_save_params_t save; const gx_device_memory *mdproto; - int code; + int code = 0; + int plane; - if ((plane < 0) || (plane >= mdev->num_planes)) - return gs_error_rangecheck; MEM_SAVE_PARAMS(mdev, save); - mdev->line_ptrs += mdev->height * plane; - plane_depth = mdev->planes[plane].depth; - mdproto = gdev_mem_device_for_bits(plane_depth); - if (plane_depth == 1) - code = dev_proc(mdproto, copy_mono)(dev, base, sourcex, sraster, id, - x, y, w, h, - (gx_color_index)0, - (gx_color_index)1); - else - code = dev_proc(mdproto, copy_color)(dev, base, sourcex, sraster, - id, x, y, w, h); + for (plane = 0; plane < mdev->num_planes; plane++) + { + plane_depth = mdev->planes[plane].depth; + mdproto = gdev_mem_device_for_bits(plane_depth); + if (plane_depth == 1) + code = dev_proc(mdproto, copy_mono)(dev, base, sourcex, sraster, id, + x, y, w, h, + (gx_color_index)0, + (gx_color_index)1); + else + code = dev_proc(mdproto, copy_color)(dev, base, sourcex, sraster, + id, x, y, w, h); + base += sraster * plane_height; + mdev->line_ptrs += mdev->height; + } MEM_RESTORE_PARAMS(mdev, save); return code; } @@ -1656,8 +1662,70 @@ mem_planar_strip_copy_rop(gx_device * dev, int phase_x, int phase_y, gs_logical_operation_t lop) { + return mem_planar_strip_copy_rop2(dev, sdata, sourcex, sraster, + id, scolors, textures, tcolors, + x, y, width, height, + phase_x, phase_y, lop, 0); +} + +static int +mem_planar_strip_copy_rop2(gx_device * dev, + const byte * sdata, int sourcex, uint sraster, + gx_bitmap_id id, const gx_color_index * scolors, + const gx_strip_bitmap * textures, + const gx_color_index * tcolors, + int x, int y, int width, int height, + int phase_x, int phase_y, + gs_logical_operation_t lop, + uint planar_height) +{ gx_device_memory * const mdev = (gx_device_memory *)dev; - int plane, code; + int code; + + if (planar_height != 0) { + /* S is in planar format; expand it to a temporary buffer, then + * call ourselves back with a modified rop to use it, then free + * the temporary buffer, and return. */ + /* Make a temporary buffer that contains both the raster and the line + * pointers for the buffer. For now, for the sake of sanity, we + * convert whole lines of s, but only as many lines as we have to. */ + /* We assume that scolors == NULL here */ + int i, j; + uint chunky_sraster; + uint nbytes; + byte **line_ptrs; + byte *sbuf, *buf; + + chunky_sraster = sraster * mdev->num_planes; + nbytes = height * chunky_sraster; + buf = gs_alloc_bytes(mdev->memory, nbytes, "mem_planar_strip_copy_rop(buf)"); + if (buf == NULL) { + return gs_note_error(gs_error_VMerror); + } + nbytes = sizeof(byte *) * mdev->num_planes * height; + line_ptrs = (byte **)gs_alloc_bytes(mdev->memory, nbytes, "mem_planar_strip_copy_rop(line_ptrs)"); + if (line_ptrs == NULL) { + gs_free_object(mdev->memory, buf, "mem_planar_strip_copy_rop(buf)"); + return gs_note_error(gs_error_VMerror); + } + for (j = 0; j < mdev->num_planes; j++) { + sbuf = sdata + j * sraster; + for (i = height; i > 0; i--) { + *line_ptrs++ = sbuf; + sbuf += sraster; + } + } + line_ptrs -= height * mdev->num_planes; + planar_to_chunky(mdev, sourcex, 0, width, height, + 0, chunky_sraster, buf, line_ptrs, planar_height); + gs_free_object(mdev->memory, line_ptrs, "mem_planar_strip_copy_rop(line_ptrs)"); + code = mem_planar_strip_copy_rop2(dev, buf, 0, chunky_sraster, + id, scolors, textures, tcolors, + x, y, width, height, phase_x, phase_y, + lop, 0); + gs_free_object(mdev->memory, buf, "mem_planar_strip_copy_rop(buf)"); + return code; + } if (textures && textures->num_planes > 1) { /* T is in planar format; expand it to a temporary buffer, then @@ -1713,84 +1781,77 @@ mem_planar_strip_copy_rop(gx_device * dev, newtex.num_planes = 1; newtex.size.x = textures->rep_width; newtex.size.y = textures->rep_height; - code = mem_planar_strip_copy_rop(dev, sdata, sourcex, sraster, - id, scolors, &newtex, tcolors, - x, y, width, height, phase_x, phase_y, - lop); + code = mem_planar_strip_copy_rop2(dev, sdata, sourcex, sraster, + id, scolors, &newtex, tcolors, + x, y, width, height, phase_x, phase_y, + lop, planar_height); gs_free_object(mdev->memory, buf, "mem_planar_strip_copy_rop(buf)"); return code; } - if ((lop & lop_planar) == 0) { - /* Not doing a planar lop. If we carry on down the default path here, - * we'll end up doing a planar_to_chunky; we may be able to sidestep - * that by spotting cases where we can operate directly. */ - if (!lop_uses_T(lop) || (tcolors && (tcolors[0] == tcolors[1]))) { - /* No T in use, or constant T. */ - if ((!lop_uses_S(lop) || (scolors && (scolors[0] == scolors[1]))) && - ((mdev->num_planes == 1) || (mdev->num_planes == 3))) { - /* No S in use, or constant S. And either greyscale or rgb, - * so we can just do the rop on each plane in turn. */ - for (plane=0; plane < mdev->num_planes; plane++) - { - gx_color_index tcolors2[2], scolors2[2]; - int shift = mdev->planes[plane].shift; - int mask = (1<<mdev->planes[plane].depth)-1; + /* Not doing a planar lop. If we carry on down the default path here, + * we'll end up doing a planar_to_chunky; we may be able to sidestep + * that by spotting cases where we can operate directly. */ + if (!lop_uses_T(lop) || (tcolors && (tcolors[0] == tcolors[1]))) { + /* No T in use, or constant T. */ + if ((!lop_uses_S(lop) || (scolors && (scolors[0] == scolors[1]))) && + ((mdev->num_planes == 1) || (mdev->num_planes == 3))) { + int plane; + /* No S in use, or constant S. And either greyscale or rgb, + * so we can just do the rop on each plane in turn. */ + for (plane=0; plane < mdev->num_planes; plane++) + { + gx_color_index tcolors2[2], scolors2[2]; + int shift = mdev->planes[plane].shift; + int mask = (1<<mdev->planes[plane].depth)-1; - if (tcolors) { - tcolors2[0] = (tcolors[0] >> shift) & mask; - tcolors2[1] = (tcolors[1] >> shift) & mask; - } - if (scolors) { - scolors2[0] = (scolors[0] >> shift) & mask; - scolors2[1] = (scolors[1] >> shift) & mask; - } - code = plane_strip_copy_rop(mdev, sdata, sourcex, sraster, - id, (scolors ? scolors2 : NULL), - textures, (tcolors ? tcolors2 : NULL), - x, y, width, height, - phase_x, phase_y, lop, plane); - if (code < 0) - return code; + if (tcolors) { + tcolors2[0] = (tcolors[0] >> shift) & mask; + tcolors2[1] = (tcolors[1] >> shift) & mask; } - return 0; - } - if ((mdev->num_planes == 4) && (mdev->plane_depth == 1) && - ((lop & (lop_S_transparent | lop_T_transparent)) == 0)) - { - lop = cmykrop[lop & 0xff] | (lop & ~0xff); - return planar_cmyk4bit_strip_copy_rop(mdev, sdata, sourcex, - sraster, id, scolors, - textures, tcolors, - x, y, width, height, - phase_x, phase_y, lop); + if (scolors) { + scolors2[0] = (scolors[0] >> shift) & mask; + scolors2[1] = (scolors[1] >> shift) & mask; + } + code = plane_strip_copy_rop(mdev, sdata, sourcex, sraster, + id, (scolors ? scolors2 : NULL), + textures, (tcolors ? tcolors2 : NULL), + x, y, width, height, + phase_x, phase_y, lop, plane); + if (code < 0) + return code; } + return 0; } - if (!tcolors && !scolors && - (mdev->num_planes == 4) && (mdev->plane_depth == 1) && - ((lop & (lop_S_transparent | lop_T_transparent)) == 0)) { + if ((mdev->num_planes == 4) && (mdev->plane_depth == 1) && + ((lop & (lop_S_transparent | lop_T_transparent)) == 0)) + { lop = cmykrop[lop & 0xff] | (lop & ~0xff); return planar_cmyk4bit_strip_copy_rop(mdev, sdata, sourcex, sraster, id, scolors, textures, tcolors, x, y, width, height, - phase_x, phase_y, lop); + phase_x, phase_y, + lop); } - /* Fall back to the default implementation (the only one that - * guarantees to properly cope with planar data). */ - return mem_default_strip_copy_rop(dev, sdata, sourcex, sraster, - id, scolors, textures, tcolors, - x, y, width, height, - phase_x, phase_y, lop); } - /* Extract the plane, and sanitise the lop */ - plane = lop>>lop_planar_shift; - lop &= ~((plane<<lop_planar_shift) | lop_planar); - if ((plane < 0) || (plane >= mdev->num_planes)) - return gs_error_rangecheck; - return plane_strip_copy_rop(mdev, sdata, sourcex, sraster, id, scolors, - textures, tcolors, x, y, width, height, - phase_x, phase_y, lop, plane); + if (!tcolors && !scolors && + (mdev->num_planes == 4) && (mdev->plane_depth == 1) && + ((lop & (lop_S_transparent | lop_T_transparent)) == 0)) { + lop = cmykrop[lop & 0xff] | (lop & ~0xff); + return planar_cmyk4bit_strip_copy_rop(mdev, sdata, sourcex, + sraster, id, scolors, + textures, tcolors, + x, y, width, height, + phase_x, phase_y, + lop); + } + /* Fall back to the default implementation (the only one that + * guarantees to properly cope with D being planar). */ + return mem_default_strip_copy_rop(dev, sdata, sourcex, sraster, + id, scolors, textures, tcolors, + x, y, width, height, + phase_x, phase_y, lop); } /* Copy bits back from a planar memory device. */ diff --git a/gs/base/gdevnfwd.c b/gs/base/gdevnfwd.c index 806a7bc03..34d8f74a8 100644 --- a/gs/base/gdevnfwd.c +++ b/gs/base/gdevnfwd.c @@ -110,6 +110,7 @@ gx_device_forward_fill_in_procs(register gx_device_forward * dev) fill_dev_proc(dev, fillpage, gx_forward_fillpage); 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); gx_device_fill_in_procs((gx_device *) dev); } @@ -556,6 +557,38 @@ gx_forward_strip_copy_rop(gx_device * dev, const byte * sdata, int sourcex, phase_x, phase_y, lop); } +int +gx_forward_strip_copy_rop2(gx_device * dev, const byte * sdata, int sourcex, + uint sraster, gx_bitmap_id id, + const gx_color_index * scolors, + const gx_strip_bitmap * textures, + const gx_color_index * tcolors, + int x, int y, int width, int height, + int phase_x, int phase_y, gs_logical_operation_t lop, + uint planar_height) +{ + gx_device_forward * const fdev = (gx_device_forward *)dev; + gx_device *tdev = fdev->target; + + if (planar_height != 0) { + dev_proc_strip_copy_rop2((*proc2)) = + (tdev == 0 ? (tdev = dev, gx_default_strip_copy_rop2) : + dev_proc(tdev, strip_copy_rop2)); + + return proc2(tdev, sdata, sourcex, sraster, id, scolors, + textures, tcolors, x, y, width, height, + phase_x, phase_y, lop, planar_height); + } else { + dev_proc_strip_copy_rop((*proc)) = + (tdev == 0 ? (tdev = dev, gx_default_strip_copy_rop) : + dev_proc(tdev, strip_copy_rop)); + + return proc(tdev, sdata, sourcex, sraster, id, scolors, + textures, tcolors, x, y, width, height, + phase_x, phase_y, lop); + } +} + void gx_forward_get_clipping_box(gx_device * dev, gs_fixed_rect * pbox) { @@ -956,6 +989,7 @@ static dev_proc_decode_color(null_decode_color); /* but we can't do this, because image_data must keep track of the */ /* 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); #define null_procs(get_initial_matrix, get_page_device) {\ gx_default_open_device,\ @@ -1023,7 +1057,11 @@ static dev_proc_strip_copy_rop(null_strip_copy_rop); NULL, /* push_transparency_state */\ NULL, /* pop_transparency_state */\ NULL, /* put_image */\ - gx_default_dev_spec_op /* dev_spec_op */\ + gx_default_dev_spec_op, /* dev_spec_op */\ + NULL, /* copy_planes */\ + NULL, /* get_profile */\ + NULL, /* set_graphics_type_tag */\ + null_strip_copy_rop2\ } #define NULLD_X_RES 72 @@ -1176,6 +1214,18 @@ null_strip_copy_rop(gx_device * dev, const byte * sdata, int sourcex, { return 0; } +static int +null_strip_copy_rop2(gx_device * dev, const byte * sdata, int sourcex, + uint sraster, gx_bitmap_id id, + const gx_color_index * scolors, + const gx_strip_bitmap * textures, + const gx_color_index * tcolors, + int x, int y, int width, int height, + int phase_x, int phase_y, gs_logical_operation_t lop, + uint plane_height) +{ + return 0; +} bool fwd_uses_fwd_cmap_procs(gx_device * dev) diff --git a/gs/base/gdevrops.c b/gs/base/gdevrops.c index 79372a826..8b32472a3 100644 --- a/gs/base/gdevrops.c +++ b/gs/base/gdevrops.c @@ -41,7 +41,7 @@ static RELOC_PTRS_BEGIN(device_rop_texture_reloc_ptrs) { static dev_proc_fill_rectangle(rop_texture_fill_rectangle); static dev_proc_copy_mono(rop_texture_copy_mono); static dev_proc_copy_color(rop_texture_copy_color); -static dev_proc_copy_plane(rop_texture_copy_plane); +static dev_proc_copy_planes(rop_texture_copy_planes); /* The device descriptor. */ static const gx_device_rop_texture gs_rop_texture_device = { @@ -113,7 +113,7 @@ static const gx_device_rop_texture gs_rop_texture_device = { NULL, /* pop_transparency_state */ NULL, /* put_image */ gx_forward_dev_spec_op, - rop_texture_copy_plane, /* copy plane */ + rop_texture_copy_planes, /* copy planes */ gx_forward_get_profile, gx_forward_set_graphics_type_tag }, @@ -163,6 +163,7 @@ rop_texture_fill_rectangle(gx_device * dev, int x, int y, int w, int h, source.sraster = 0; source.id = gx_no_bitmap_id; source.scolors[0] = source.scolors[1] = color; + source.planar_height = 0; source.use_scolors = true; return gx_device_color_fill_rectangle(&rtdev->texture, x, y, w, h, rtdev->target, @@ -186,6 +187,7 @@ rop_texture_copy_mono(gx_device * dev, source.id = id; source.scolors[0] = color0; source.scolors[1] = color1; + source.planar_height = 0; source.use_scolors = true; /* Adjust the logical operation per transparent colors. */ if (color0 == gx_no_color_index) @@ -211,6 +213,7 @@ rop_texture_copy_color(gx_device * dev, source.sraster = raster; source.id = id; source.scolors[0] = source.scolors[1] = gx_no_color_index; + source.planar_height = 0; source.use_scolors = false; return gx_device_color_fill_rectangle(&rtdev->texture, x, y, w, h, rtdev->target, @@ -219,9 +222,10 @@ rop_texture_copy_color(gx_device * dev, /* Copy a color rectangle */ static int -rop_texture_copy_plane(gx_device * dev, - const byte * data, int sourcex, int raster, gx_bitmap_id id, - int x, int y, int w, int h, int plane) +rop_texture_copy_planes(gx_device * dev, + const byte * data, int sourcex, int raster, + gx_bitmap_id id, int x, int y, int w, int h, + int plane_height) { gx_device_rop_texture *const rtdev = (gx_device_rop_texture *)dev; gx_rop_source_t source; @@ -231,10 +235,10 @@ rop_texture_copy_plane(gx_device * dev, source.sraster = raster; source.id = id; source.scolors[0] = source.scolors[1] = gx_no_color_index; + source.planar_height = plane_height; source.use_scolors = false; return gx_device_color_fill_rectangle(&rtdev->texture, x, y, w, h, rtdev->target, - (rtdev->log_op | lop_planar | - (plane<<lop_planar_shift)), + rtdev->log_op, &source); } diff --git a/gs/base/gdevtrac.c b/gs/base/gdevtrac.c index 826f0f02f..535cebc01 100644 --- a/gs/base/gdevtrac.c +++ b/gs/base/gdevtrac.c @@ -280,6 +280,20 @@ trace_strip_copy_rop(gx_device * dev, const byte * sdata, int sourcex, return 0; } +static int +trace_strip_copy_rop2(gx_device * dev, const byte * sdata, int sourcex, + uint sraster, gx_bitmap_id id, + const gx_color_index * scolors, + const gx_strip_bitmap * textures, + const gx_color_index * tcolors, + int x, int y, int width, int height, + int phase_x, int phase_y, gs_logical_operation_t lop, + uint plane_height) +{ + dputs("**strip_copy_rop2**\n"); + return 0; +} + /* ---------------- High-level driver procedures ---------------- */ static int @@ -635,7 +649,33 @@ trace_text_begin(gx_device * dev, gs_imager_state * pis, NULL, /* create_compositor */\ NULL, /* get_hardware_params */\ trace_text_begin,\ - NULL /* finish_copydevice */\ + NULL, /* finish_copydevice */\ + NULL, /* begin_transparency_group */\ + NULL, /* end_transparency_group */\ + NULL, /* begin_transparency_mask */\ + NULL, /* end_transparency_mask */\ + NULL, /* discard_transparency_layer */\ + NULL, /* get_color_mapping_procs */\ + NULL, /* get_color_comp_index */\ + NULL, /* encode_color */\ + NULL, /* decode_color */\ + NULL, /* pattern_manage */\ + NULL, /* fill_rectangle_hl_color */\ + NULL, /* include_color_space */\ + NULL, /* fill_linear_color_scanline */\ + NULL, /* fill_linear_color_trapezoid */\ + NULL, /* fill_linear_color_triangle */\ + NULL, /* update_spot_equivalent_colors */\ + NULL, /* ret_devn_params */\ + NULL, /* fillpage */\ + NULL, /* push_transparency_state */\ + NULL, /* pop_transparency_state */\ + NULL, /* put_image */\ + NULL, /* dev_spec_op */\ + NULL, /* copy_planes */\ + NULL, /* get_profile */\ + NULL, /* set_graphics_type_tag */\ + trace_strip_copy_rop2\ } const gx_device gs_tr_mono_device = { diff --git a/gs/base/gxacpath.c b/gs/base/gxacpath.c index e1e53a373..6414f24ef 100644 --- a/gs/base/gxacpath.c +++ b/gs/base/gxacpath.c @@ -122,7 +122,7 @@ static const gx_device_cpath_accum gs_cpath_accum_device = NULL, /* pop_transparency_state */ NULL, /* put_image */ accum_dev_spec_op, - NULL, /* copy_plane */ + NULL, /* copy_planes */ NULL, /* get_profile */ gx_default_set_graphics_type_tag } diff --git a/gs/base/gxcht.c b/gs/base/gxcht.c index 92f061e45..8db39add4 100644 --- a/gs/base/gxcht.c +++ b/gs/base/gxcht.c @@ -695,7 +695,8 @@ gx_dc_ht_colored_fill_rectangle(const gx_device_color * pdevc, gx_no_color_index, pdevc->phase.x, pdevc->phase.y); - return (*dev_proc(dev, strip_copy_rop)) + if (source->planar_height == 0) + return (*dev_proc(dev, strip_copy_rop)) (dev, source->sdata + (y - origy) * source->sraster, source->sourcex + (x - origx), @@ -704,6 +705,17 @@ gx_dc_ht_colored_fill_rectangle(const gx_device_color * pdevc, &tiles, NULL, x, y, w, h, pdevc->phase.x, pdevc->phase.y, lop); + else + return (*dev_proc(dev, strip_copy_rop2)) + (dev, + source->sdata + (y - origy) * source->sraster, + source->sourcex + (x - origx), + source->sraster, source->id, + (source->use_scolors ? source->scolors : NULL), + &tiles, NULL, + x, y, w, h, + pdevc->phase.x, pdevc->phase.y, lop, + source->planar_height); } } size_x = w * depth; @@ -759,13 +771,23 @@ fit: /* Now the tile will definitely fit. */ x, cy, dw, ch); } else { tiles.rep_height = tiles.size.y = ch; - code = (*dev_proc(dev, strip_copy_rop)) + if (source->planar_height == 0) + code = (*dev_proc(dev, strip_copy_rop)) (dev, source->sdata + source->sraster * (cy-origy), source->sourcex + (x - origx), source->sraster, source->id, (source->use_scolors ? source->scolors : NULL), &tiles, NULL, x, cy, dw, ch, 0, 0, lop); + else + code = (*dev_proc(dev, strip_copy_rop2)) + (dev, source->sdata + source->sraster * (cy-origy), + source->sourcex + (x - origx), + source->sraster, + source->id, + (source->use_scolors ? source->scolors : NULL), + &tiles, NULL, x, cy, dw, ch, 0, 0, lop, + source->planar_height); } if (code < 0) return code; diff --git a/gs/base/gxcldev.h b/gs/base/gxcldev.h index 16b1c739e..f48cb3eb6 100644 --- a/gs/base/gxcldev.h +++ b/gs/base/gxcldev.h @@ -92,7 +92,7 @@ typedef enum { cmd_op_tile_rect = 0x60, /* +dy2dh2, x#, w# | +0, rect# */ cmd_op_tile_rect_short = 0x70, /* +dh, dx, dw | +0, rect_short */ cmd_op_tile_rect_tiny = 0x80, /* +dw+0, rect_tiny | +dw+8 */ - cmd_op_copy_mono_plane = 0x90, /* +compress, plane, x#, y#, (w+data_x)#, */ + cmd_op_copy_mono_planes = 0x90, /* +compress, plane_height, x#, y#, (w+data_x)#, */ /* h#, <bits> | */ #define cmd_copy_ht_color 4 /* +4+compress, x#, y#, (w+data_x)#, */ @@ -111,7 +111,7 @@ typedef enum { #define cmd_op_name_strings\ "(misc)", "set_color[0]", "set_color[1]", "fill_rect",\ "fill_rect_short", "fill_rect_tiny", "tile_rect", "tile_rect_short",\ - "tile_rect_tiny", "copy_mono_plane", "copy_color_alpha", "delta_tile_index",\ + "tile_rect_tiny", "copy_mono_planes", "copy_color_alpha", "delta_tile_index",\ "set_tile_index", "(misc2)", "(segment)", "(path)" #define cmd_misc_op_name_strings\ @@ -294,11 +294,12 @@ 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_copy_rop(clist_strip_copy_rop); +dev_proc_strip_copy_rop2(clist_strip_copy_rop2); dev_proc_fill_trapezoid(clist_fill_trapezoid); 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_plane(clist_copy_plane); +dev_proc_copy_planes(clist_copy_planes); /* In gxclimag.c */ dev_proc_fill_mask(clist_fill_mask); diff --git a/gs/base/gxclimag.c b/gs/base/gxclimag.c index 2e1aba58f..0064b8212 100644 --- a/gs/base/gxclimag.c +++ b/gs/base/gxclimag.c @@ -72,7 +72,7 @@ clist_fill_mask(gx_device * dev, int data_x_bit; byte copy_op = (depth > 1 ? cmd_op_copy_color_alpha : - cmd_op_copy_mono_plane + cmd_copy_ht_color); /* Plane not needed here */ + cmd_op_copy_mono_planes + cmd_copy_ht_color); /* Plane not needed here */ bool slow_rop = cmd_slow_rop(dev, lop_know_S_0(lop), pdcolor) || cmd_slow_rop(dev, lop_know_S_1(lop), pdcolor); @@ -181,7 +181,7 @@ clist_fill_mask(gx_device * dev, rect.x = orig_x, rect.y = y0; rect.width = orig_width, rect.height = re.yend - y0; rsize = 1 + cmd_sizexy(rect); - if (depth == 1) rsize = rsize + cmd_sizew(255); /* need planar 255 setting */ + if (depth == 1) rsize = rsize + cmd_sizew(0); /* need planar_height 0 setting */ do { code = (orig_data_x ? cmd_put_set_data_x(cdev, re.pcls, orig_data_x) : 0); @@ -200,7 +200,7 @@ clist_fill_mask(gx_device * dev, if (code >= 0) { dp++; if (depth == 1) { - cmd_putw(255, dp); + cmd_putw(0, dp); } cmd_putxy(rect, dp); } diff --git a/gs/base/gxclip.c b/gs/base/gxclip.c index 7984e5659..0350d1eb8 100644 --- a/gs/base/gxclip.c +++ b/gs/base/gxclip.c @@ -31,12 +31,13 @@ static dev_proc_open_device(clip_open); static dev_proc_fill_rectangle(clip_fill_rectangle); static dev_proc_copy_mono(clip_copy_mono); -static dev_proc_copy_plane(clip_copy_plane); +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_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); static dev_proc_get_bits_rectangle(clip_get_bits_rectangle); static dev_proc_fill_path(clip_fill_path); @@ -111,9 +112,10 @@ static const gx_device_clip gs_clip_device = NULL, /* pop_transparency_state */ NULL, /* put_image */ gx_forward_dev_spec_op, - clip_copy_plane, /* copy plane */ + clip_copy_planes, /* copy planes */ gx_forward_get_profile, - gx_forward_set_graphics_type_tag + gx_forward_set_graphics_type_tag, + clip_strip_copy_rop2 } }; @@ -421,17 +423,17 @@ clip_copy_mono(gx_device * dev, /* Copy a plane */ int -clip_call_copy_plane(clip_callback_data_t * pccd, int xc, int yc, int xec, int yec) +clip_call_copy_planes(clip_callback_data_t * pccd, int xc, int yc, int xec, int yec) { - return (*dev_proc(pccd->tdev, copy_plane)) + return (*dev_proc(pccd->tdev, copy_planes)) (pccd->tdev, pccd->data + (yc - pccd->y) * pccd->raster, pccd->sourcex + xc - pccd->x, pccd->raster, gx_no_bitmap_id, - xc, yc, xec - xc, yec - yc, pccd->plane); + xc, yc, xec - xc, yec - yc, pccd->plane_height); } static int -clip_copy_plane(gx_device * dev, - const byte * data, int sourcex, int raster, gx_bitmap_id id, - int x, int y, int w, int h, int plane) +clip_copy_planes(gx_device * dev, + const byte * data, int sourcex, int raster, gx_bitmap_id id, + int x, int y, int w, int h, int plane_height) { gx_device_clip *rdev = (gx_device_clip *) dev; clip_callback_data_t ccdata; @@ -450,15 +452,15 @@ clip_copy_plane(gx_device * dev, INCR(in_y); if (x >= rptr->xmin && xe <= rptr->xmax) { INCR(in); - return dev_proc(tdev, copy_plane) - (tdev, data, sourcex, raster, id, x, y, w, h, plane); + return dev_proc(tdev, copy_planes) + (tdev, data, sourcex, raster, id, x, y, w, h, plane_height); } } ccdata.tdev = tdev; ccdata.data = data, ccdata.sourcex = sourcex, ccdata.raster = raster; - ccdata.plane = plane; + ccdata.plane_height = plane_height; return clip_enumerate_rest(rdev, x, y, xe, ye, - clip_call_copy_plane, &ccdata); + clip_call_copy_planes, &ccdata); } /* Copy a color rectangle */ @@ -585,6 +587,37 @@ clip_strip_copy_rop(gx_device * dev, return clip_enumerate(rdev, x, y, w, h, clip_call_strip_copy_rop, &ccdata); } +/* Copy a rectangle with RasterOp and strip texture. */ +int +clip_call_strip_copy_rop2(clip_callback_data_t * pccd, int xc, int yc, int xec, int yec) +{ + return (*dev_proc(pccd->tdev, strip_copy_rop2)) + (pccd->tdev, pccd->data + (yc - pccd->y) * pccd->raster, + pccd->sourcex + xc - pccd->x, pccd->raster, gx_no_bitmap_id, + pccd->scolors, pccd->textures, pccd->tcolors, + xc, yc, xec - xc, yec - yc, pccd->phase.x, pccd->phase.y, + pccd->lop, pccd->plane_height); +} +static int +clip_strip_copy_rop2(gx_device * dev, + const byte * sdata, int sourcex, uint raster, gx_bitmap_id id, + const gx_color_index * scolors, + const gx_strip_bitmap * textures, const gx_color_index * tcolors, + int x, int y, int w, int h, + int phase_x, int phase_y, gs_logical_operation_t lop, + uint planar_height) +{ + gx_device_clip *rdev = (gx_device_clip *) dev; + clip_callback_data_t ccdata; + + ccdata.data = sdata, ccdata.sourcex = sourcex, ccdata.raster = raster; + ccdata.scolors = scolors, ccdata.textures = textures, + ccdata.tcolors = tcolors; + ccdata.phase.x = phase_x, ccdata.phase.y = phase_y, ccdata.lop = lop; + ccdata.plane_height = planar_height; + return clip_enumerate(rdev, x, y, w, h, clip_call_strip_copy_rop2, &ccdata); +} + /* Get the (outer) clipping box, in client coordinates. */ static void clip_get_clipping_box(gx_device * dev, gs_fixed_rect * pbox) diff --git a/gs/base/gxclip.h b/gs/base/gxclip.h index 5712471a9..7ad8a3391 100644 --- a/gs/base/gxclip.h +++ b/gs/base/gxclip.h @@ -45,7 +45,7 @@ typedef struct clip_callback_data_s { const gx_color_index *scolors; /* strip_copy_rop */ const gx_strip_bitmap *textures; /* ibid. */ const gx_color_index *tcolors; /* ibid. */ - int plane; /* copy_plane */ + int plane_height; /* copy_planes, strip_copy_rop2 */ const gs_imager_state * pis; /* fill_path */ gx_path * ppath; /* fill_path */ const gx_fill_params * params; /* fill_path */ @@ -57,8 +57,8 @@ int int xc, int yc, int xec, int yec), clip_call_copy_mono(clip_callback_data_t * pccd, int xc, int yc, int xec, int yec), - clip_call_copy_plane(clip_callback_data_t * pccd, - int xc, int yc, int xec, int yec), + clip_call_copy_planes(clip_callback_data_t * pccd, + int xc, int yc, int xec, int yec), clip_call_copy_color(clip_callback_data_t * pccd, int xc, int yc, int xec, int yec), clip_call_copy_alpha(clip_callback_data_t * pccd, @@ -68,6 +68,8 @@ int clip_call_strip_tile_rectangle(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); + 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); #endif /* gxclip_INCLUDED */ diff --git a/gs/base/gxclip2.c b/gs/base/gxclip2.c index 838a665c0..0b356b498 100644 --- a/gs/base/gxclip2.c +++ b/gs/base/gxclip2.c @@ -27,9 +27,10 @@ private_st_device_tile_clip(); static dev_proc_fill_rectangle(tile_clip_fill_rectangle); static dev_proc_copy_mono(tile_clip_copy_mono); static dev_proc_copy_color(tile_clip_copy_color); -static dev_proc_copy_plane(tile_clip_copy_plane); +static dev_proc_copy_planes(tile_clip_copy_planes); static dev_proc_copy_alpha(tile_clip_copy_alpha); static dev_proc_strip_copy_rop(tile_clip_strip_copy_rop); +static dev_proc_strip_copy_rop2(tile_clip_strip_copy_rop2); /* The device descriptor. */ static const gx_device_tile_clip gs_tile_clip_device = @@ -101,7 +102,10 @@ static const gx_device_tile_clip gs_tile_clip_device = NULL, /* pop_transparency_state */ NULL, /* put_image */ gx_forward_dev_spec_op, - tile_clip_copy_plane + tile_clip_copy_planes, + NULL, /* get_profile */ + NULL, /* set_graphics_type_tag */ + tile_clip_strip_copy_rop2 } }; @@ -278,9 +282,9 @@ tile_clip_copy_color(gx_device * dev, /* Copy a color rectangle. */ static int -tile_clip_copy_plane(gx_device * dev, +tile_clip_copy_planes(gx_device * dev, const byte * data, int sourcex, int raster, gx_bitmap_id id, - int x, int y, int w, int h, int plane) + int x, int y, int w, int h, int plane_height) { gx_device_tile_clip *cdev = (gx_device_tile_clip *) dev; @@ -288,9 +292,9 @@ tile_clip_copy_plane(gx_device * dev, { FOR_RUNS(data_row, txrun, tx, ty) { /* Copy the run. */ - int code = (*dev_proc(cdev->target, copy_plane)) + int code = (*dev_proc(cdev->target, copy_planes)) (cdev->target, data_row, sourcex + txrun - x, raster, - gx_no_bitmap_id, txrun, ty, tx - txrun, 1, plane); + gx_no_bitmap_id, txrun, ty, tx - txrun, 1, plane_height); if (code < 0) return code; @@ -352,3 +356,32 @@ tile_clip_strip_copy_rop(gx_device * dev, } return 0; } + +static int +tile_clip_strip_copy_rop2(gx_device * dev, + const byte * data, int sourcex, uint raster, gx_bitmap_id id, + const gx_color_index * scolors, + const gx_strip_bitmap * textures, const gx_color_index * tcolors, + int x, int y, int w, int h, + int phase_x, int phase_y, gs_logical_operation_t lop, + uint planar_height) +{ + gx_device_tile_clip *cdev = (gx_device_tile_clip *) dev; + + fit_copy(dev, data, sourcex, raster, id, x, y, w, h); + { + FOR_RUNS(data_row, txrun, tx, ty) { + /* Copy the run. */ + int code = (*dev_proc(cdev->target, strip_copy_rop2)) + (cdev->target, data_row, sourcex + txrun - x, raster, + gx_no_bitmap_id, scolors, textures, tcolors, + txrun, ty, tx - txrun, 1, phase_x, phase_y, lop, + planar_height); + + if (code < 0) + return code; + } + END_FOR_RUNS(); + } + return 0; +} diff --git a/gs/base/gxclipm.c b/gs/base/gxclipm.c index 2b574fc4b..18abea537 100644 --- a/gs/base/gxclipm.c +++ b/gs/base/gxclipm.c @@ -27,6 +27,7 @@ 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_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); /* The device descriptor. */ @@ -101,7 +102,8 @@ const gx_device_mask_clip gs_mask_clip_device = gx_forward_dev_spec_op, NULL, gx_forward_get_profile, - gx_forward_set_graphics_type_tag + gx_forward_set_graphics_type_tag, + mask_clip_strip_copy_rop2 } }; @@ -373,6 +375,28 @@ mask_clip_strip_copy_rop(gx_device * dev, return clip_runs_enumerate(cdev, clip_call_strip_copy_rop, &ccdata); } +static int +mask_clip_strip_copy_rop2(gx_device * dev, + const byte * data, int sourcex, uint raster, gx_bitmap_id id, + const gx_color_index * scolors, + const gx_strip_bitmap * textures, const gx_color_index * tcolors, + int x, int y, int w, int h, + int phase_x, int phase_y, gs_logical_operation_t lop, + uint planar_height) +{ + 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.data = data, ccdata.sourcex = sourcex, ccdata.raster = raster; + ccdata.scolors = scolors, ccdata.textures = textures, + ccdata.tcolors = tcolors; + ccdata.phase.x = phase_x, ccdata.phase.y = phase_y, ccdata.lop = lop; + ccdata.plane_height = planar_height; + return clip_runs_enumerate(cdev, clip_call_strip_copy_rop2, &ccdata); +} + static void mask_clip_get_clipping_box(gx_device * dev, gs_fixed_rect * pbox) { diff --git a/gs/base/gxclist.c b/gs/base/gxclist.c index c83114f9b..c53c26805 100644 --- a/gs/base/gxclist.c +++ b/gs/base/gxclist.c @@ -193,9 +193,10 @@ const gx_device_procs gs_clist_device_procs = { NULL, /* pop_transparency_state */ NULL, /* put_image */ clist_dev_spec_op, - clist_copy_plane, /* copy plane */ + clist_copy_planes, /* copy planes */ gx_default_get_profile, - gx_default_set_graphics_type_tag + gx_default_set_graphics_type_tag, + clist_strip_copy_rop2 }; /*------------------- Choose the implementation ----------------------- diff --git a/gs/base/gxclrast.c b/gs/base/gxclrast.c index 467fa09b5..059517ffd 100644 --- a/gs/base/gxclrast.c +++ b/gs/base/gxclrast.c @@ -533,7 +533,7 @@ clist_playback_band(clist_playback_action playback_action, bool clipper_dev_open; patch_fill_state_t pfs; int op = 0; - short plane = 0; + int plane_height = 0; #ifdef DEBUG stream_state *st = s->state; /* Save because s_close resets s->state. */ @@ -925,9 +925,15 @@ in: /* Initialize for a new page. */ } state.rect.width += (op & 7) + cmd_min_dw_tiny; break; - case cmd_op_copy_mono_plane >> 4: - cmd_getw(plane, cbp); - depth = 1; + case cmd_op_copy_mono_planes >> 4: + cmd_getw(plane_height, cbp); + if (plane_height == 0) { + /* We are doing a copy mono */ + depth = 1; + } else { + depth = tdev->color_info.depth; + } + if_debug1('L', " plane_height=0x%x", plane_height); goto copy; case cmd_op_copy_color_alpha >> 4: if (state.color_is_alpha) { @@ -935,6 +941,7 @@ in: /* Initialize for a new page. */ depth = *cbp++; } else depth = tdev->color_info.depth; + plane_height = 0; copy:cmd_getw(state.rect.x, cbp); cmd_getw(state.rect.y, cbp); if (op & 8) { /* Use the current "tile". */ @@ -956,20 +963,27 @@ in: /* Initialize for a new page. */ /* depth was set already. */ uint width_bits, width_bytes; uint bytes; + uint planes = 1; + uint plane_depth = depth; + uint pln; + byte compression = op & 3; cmd_getw(state.rect.width, cbp); cmd_getw(state.rect.height, cbp); - width_bits = state.rect.width * depth; - bytes = - clist_bitmap_bytes(width_bits, - state.rect.height, - op & 3, &width_bytes, - (uint *)&raster); + if (plane_height != 0) { + planes = tdev->color_info.num_components; + plane_depth /= planes; + } + width_bits = state.rect.width * plane_depth; + bytes = clist_bitmap_bytes(width_bits, + state.rect.height, + op & 3, &width_bytes, + (uint *)&raster); /* copy_mono and copy_color/alpha */ /* ensure that the bits will fit in a single buffer, */ /* even after decompression if compressed. */ #ifdef DEBUG - if (bytes > cbuf_size) { + if (planes * 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, @@ -979,72 +993,80 @@ in: /* Initialize for a new page. */ goto out; } #endif - if (op & 3) { /* Decompress the image data. */ - stream_cursor_read r; - stream_cursor_write w; - - /* We don't know the data length a priori, */ - /* so to be conservative, we read */ - /* the uncompressed size. */ - uint cleft = cbuf.end - cbp; - - if (cleft < bytes && !cbuf.end_status) { - uint nread = cbuf_size - cleft; + for (pln = 0; pln < planes; pln++) + { + byte *plane_bits = data_bits + plane_height * raster; + if (pln) + compression = *cbp++; + if (compression) { /* Decompress the image data. */ + stream_cursor_read r; + stream_cursor_write w; + + /* We don't know the data length a priori, */ + /* so to be conservative, we read */ + /* the uncompressed size. */ + uint cleft = cbuf.end - cbp; -# ifdef DEBUG - code = top_up_offset_map(st, cbuf.data, cbp, cbuf.end); - if (code < 0) - return code; -# endif - memmove(cbuf.data, cbp, cleft); - cbuf.end_status = sgets(s, cbuf.data + cleft, nread, &nread); - set_cb_end(&cbuf, cbuf.data + cleft + nread); - cbp = cbuf.data; - } - r.ptr = cbp - 1; - r.limit = cbuf.end - 1; - w.ptr = data_bits - 1; - w.limit = w.ptr + data_bits_size; - switch (op & 3) { - case cmd_compress_rle: - { - stream_RLD_state sstate; + if (cleft < bytes && !cbuf.end_status) { + uint nread = cbuf_size - cleft; - clist_rld_init(&sstate); - /* The process procedure can't fail. */ - (*s_RLD_template.process) - ((stream_state *)&sstate, &r, &w, true); - } - break; - case cmd_compress_cfe: - { - stream_CFD_state sstate; - - clist_cfd_init(&sstate, - width_bytes << 3 /*state.rect.width */ , - state.rect.height, mem); - /* The process procedure can't fail. */ - (*s_CFD_template.process) - ((stream_state *)&sstate, &r, &w, true); - (*s_CFD_template.release) - ((stream_state *)&sstate); - } - break; - default: - goto bad_op; +# ifdef DEBUG + code = top_up_offset_map(st, cbuf.data, cbp, cbuf.end); + if (code < 0) + return code; +# endif + memmove(cbuf.data, cbp, cleft); + cbuf.end_status = sgets(s, cbuf.data + cleft, nread, &nread); + set_cb_end(&cbuf, cbuf.data + cleft + nread); + cbp = cbuf.data; + } + r.ptr = cbp - 1; + r.limit = cbuf.end - 1; + w.ptr = plane_bits - 1; + w.limit = w.ptr + data_bits_size; + switch (compression) { + case cmd_compress_rle: + { + stream_RLD_state sstate; + + clist_rld_init(&sstate); + /* The process procedure can't fail. */ + (*s_RLD_template.process) + ((stream_state *)&sstate, &r, &w, true); + } + break; + case cmd_compress_cfe: + { + stream_CFD_state sstate; + + clist_cfd_init(&sstate, + width_bytes << 3 /*state.rect.width */ , + state.rect.height, mem); + /* The process procedure can't fail. */ + (*s_CFD_template.process) + ((stream_state *)&sstate, &r, &w, true); + (*s_CFD_template.release) + ((stream_state *)&sstate); + } + break; + default: + goto bad_op; + } + cbp = r.ptr + 1; + if (pln == 0) + source = data_bits; + } else if ((state.rect.height > 1 && width_bytes != raster) || + (plane_height != 0)) { + if (pln == 0) + source = data_bits; + cbp = cmd_read_short_bits(&cbuf, plane_bits, width_bytes, + state.rect.height, + raster, cbp); + } else { + /* Never used for planar data */ + cmd_read(cbuf.data, bytes, cbp); + source = cbuf.data; } - cbp = r.ptr + 1; - source = data_bits; - } else if (state.rect.height > 1 && - width_bytes != raster - ) { - source = data_bits; - cbp = cmd_read_short_bits(&cbuf, source, width_bytes, - state.rect.height, - raster, cbp); - } else { - cmd_read(cbuf.data, bytes, cbp); - source = cbuf.data; } #ifdef DEBUG if (gs_debug_c('L')) { @@ -2015,15 +2037,29 @@ idata: data_size = 0; colors[0] = colors[1] = state.colors[1]; log_op = state.lop; pcolor = colors; - do_rop:code = (*dev_proc(tdev, strip_copy_rop)) - (tdev, source, data_x, raster, gx_no_bitmap_id, - pcolor, &state_tile, - (state.tile_colors[0] == gx_no_color_index && - state.tile_colors[1] == gx_no_color_index ? - NULL : state.tile_colors), - state.rect.x - x0, state.rect.y - y0, - state.rect.width - data_x, state.rect.height, - tile_phase.x, tile_phase.y, log_op); + do_rop:if (plane_height == 0) { + code = (*dev_proc(tdev, strip_copy_rop)) + (tdev, source, data_x, raster, gx_no_bitmap_id, + pcolor, &state_tile, + (state.tile_colors[0] == gx_no_color_index && + state.tile_colors[1] == gx_no_color_index ? + NULL : state.tile_colors), + state.rect.x - x0, state.rect.y - y0, + state.rect.width - data_x, state.rect.height, + tile_phase.x, tile_phase.y, log_op); + } else { + code = (*dev_proc(tdev, strip_copy_rop2)) + (tdev, source, data_x, raster, gx_no_bitmap_id, + pcolor, &state_tile, + (state.tile_colors[0] == gx_no_color_index && + state.tile_colors[1] == gx_no_color_index ? + NULL : state.tile_colors), + state.rect.x - x0, state.rect.y - y0, + state.rect.width - data_x, state.rect.height, + tile_phase.x, tile_phase.y, log_op, + plane_height); + plane_height = 0; + } data_x = 0; break; case cmd_op_tile_rect >> 4: @@ -2042,7 +2078,7 @@ idata: data_size = 0; state.tile_colors[0], state.tile_colors[1], tile_phase.x, tile_phase.y); break; - case cmd_op_copy_mono_plane >> 4: + case cmd_op_copy_mono_planes >> 4: if (state.lop_enabled) { pcolor = state.colors; log_op = state.lop; @@ -2058,21 +2094,21 @@ idata: data_size = 0; state.rect.width - data_x, state.rect.height, &dev_color, 1, imager_state.log_op, pcpath); } else { - if (plane == 255) { + if (plane_height == 0) { code = (*dev_proc(tdev, copy_mono)) (tdev, source, data_x, raster, gx_no_bitmap_id, state.rect.x - x0, state.rect.y - y0, state.rect.width - data_x, state.rect.height, state.colors[0], state.colors[1]); } else { - code = (*dev_proc(tdev, copy_plane)) + code = (*dev_proc(tdev, copy_planes)) (tdev, source, data_x, raster, gx_no_bitmap_id, state.rect.x - x0, state.rect.y - y0, state.rect.width - data_x, state.rect.height, - plane); + plane_height); } } - plane = -1; + plane_height = 0; data_x = 0; break; case cmd_op_copy_color_alpha >> 4: diff --git a/gs/base/gxclrect.c b/gs/base/gxclrect.c index c134d651b..6a2803f08 100644 --- a/gs/base/gxclrect.c +++ b/gs/base/gxclrect.c @@ -621,7 +621,7 @@ clist_copy_mono(gx_device * dev, copy:{ gx_cmd_rect rect; int rsize; - byte op = (byte) cmd_op_copy_mono_plane; + byte op = (byte) cmd_op_copy_mono_planes; byte *dp; uint csize; uint compress; @@ -629,7 +629,7 @@ copy:{ rect.x = rx, rect.y = re.y; rect.width = w1, rect.height = re.height; - rsize = (dx ? 3 : 1) + cmd_size_rect(&rect) + cmd_sizew(255); + rsize = (dx ? 3 : 1) + cmd_size_rect(&rect) + cmd_sizew(0); /* planar_height 0 */ do { code = cmd_put_bits(cdev, re.pcls, row, w1, re.height, raster, rsize, (orig_id == gx_no_bitmap_id ? @@ -676,8 +676,8 @@ copy:{ *dp++ = cmd_set_misc_data_x + dx; } *dp++ = cmd_count_op(op, csize); - /* Store the plane count */ - cmd_putw(255, dp); + /* Store the plane_height */ + cmd_putw(0, dp); cmd_put2w(rx, re.y, dp); cmd_put2w(w1, re.height, dp); re.pcls->rect = rect; @@ -694,9 +694,9 @@ error_in_rect: /* The code duplication between this and clist_copy_mono needs to be removed */ int -clist_copy_plane(gx_device * dev, - const byte * data, int data_x, int raster, gx_bitmap_id id, - int rx, int ry, int rwidth, int rheight, int plane) +clist_copy_planes(gx_device * dev, + const byte * data, int data_x, int raster, gx_bitmap_id id, + int rx, int ry, int rwidth, int rheight, int plane_height) { gx_device_clist_writer * const cdev = &((gx_device_clist *)dev)->writer; @@ -704,8 +704,6 @@ clist_copy_plane(gx_device * dev, gx_bitmap_id orig_id = id; cmd_rects_enum_t re; - if (plane < 0) - return gs_error_rangecheck; if (rwidth <= 0 || rheight <= 0) return 0; @@ -734,7 +732,7 @@ clist_copy_plane(gx_device * dev, copy:{ gx_cmd_rect rect; int rsize; - byte op = (byte) cmd_op_copy_mono_plane; + byte op = (byte) cmd_op_copy_mono_planes; byte *dp; uint csize; uint compress; @@ -742,13 +740,33 @@ copy:{ rect.x = rx, rect.y = re.y; rect.width = w1, rect.height = re.height; - rsize = (dx ? 3 : 1) + cmd_size_rect(&rect) + cmd_sizew(plane); + rsize = (dx ? 3 : 1) + cmd_size_rect(&rect) + cmd_sizew(plane_height); 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), &dp, &csize); + if (plane_height > 0) { + for (plane = 1; plane < cdev->color_info.num_components && (code >= 0); plane++) + { + byte *dummy_dp; + 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), + &dummy_dp, &csize2); + if (code >= 0) + *dummy_dp = code; + + csize += csize2; + } + } } while (RECT_RECOVER(code)); if (code < 0 && !(code == gs_error_limitcheck) && SET_BAND_CODE(code)) goto error_in_rect; @@ -768,14 +786,14 @@ copy:{ ++cdev->driver_call_nesting; { - code = clist_copy_plane(dev, row, dx, raster, - gx_no_bitmap_id, rx, re.y, - w2, 1, plane); + 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_plane(dev, row, dx + w2, - raster, gx_no_bitmap_id, - rx + w2, re.y, - w1 - w2, 1, plane); + 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)) @@ -789,8 +807,7 @@ copy:{ *dp++ = cmd_set_misc_data_x + dx; } *dp++ = cmd_count_op(op, csize); - /* Store the plane count */ - cmd_putw(plane, dp); + cmd_putw(plane_height, dp); cmd_put2w(rx, re.y, dp); cmd_put2w(w1, re.height, dp); re.pcls->rect = rect; @@ -1057,6 +1074,21 @@ clist_strip_copy_rop(gx_device * dev, int rx, int ry, int rwidth, int rheight, int phase_x, int phase_y, gs_logical_operation_t lop) { + return clist_strip_copy_rop2(dev, sdata, sourcex, sraster, id, + scolors, textures, tcolors, + rx, ry, rwidth, rheight, phase_x, phase_y, + lop, 0); +} + +int +clist_strip_copy_rop2(gx_device * dev, + const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id, + const gx_color_index * scolors, + const gx_strip_bitmap * textures, const gx_color_index * tcolors, + int rx, int ry, int rwidth, int rheight, + int phase_x, int phase_y, gs_logical_operation_t lop, + uint planar_height) +{ gx_device_clist_writer * const cdev = &((gx_device_clist *)dev)->writer; gs_rop3_t rop = lop_rop(lop); @@ -1170,6 +1202,8 @@ clist_strip_copy_rop(gx_device * dev, line_tile.size.y = 1; line_tile.rep_height = 1; raster = line_tile.raster; + if (line_tile.num_planes > 0) + line_tile.raster *= tiles->size.y; /* The rasterizer assumes tile phase relatively to the rectangle origin, (see x_offset in gdevmr8n.c), so compute "the tile phase in the tile space" with same expression : */ @@ -1182,6 +1216,8 @@ clist_strip_copy_rop(gx_device * dev, */ int depth = cdev->clist_color_info.depth; + if (line_tile.num_planes > 0) + depth /= line_tile.num_planes; # if 0 /* Align bitmap data : */ data_shift = ((tile_space_phase * depth) >> (log2_align_bitmap_mod + 3)) << log2_align_bitmap_mod; @@ -1197,7 +1233,8 @@ clist_strip_copy_rop(gx_device * dev, and because the bitmap height is 1. The clist reader must provide the trailing bytes if the rasterizer needs them. */ - line_tile.raster = (line_tile.rep_width * depth + 7) / 8; + if (line_tile.num_planes <= 1) + line_tile.raster = (line_tile.rep_width * depth + 7) / 8; line_tile.size.x = line_tile.rep_width; line_tile.shift = 0; new_phase = (tile_space_phase - phase_shift - rx % line_tile.rep_width); @@ -1210,13 +1247,13 @@ clist_strip_copy_rop(gx_device * dev, line_tile.id = ids + (iy % rep_height); ++cdev->driver_call_nesting; { - code = clist_strip_copy_rop(dev, + code = clist_strip_copy_rop2(dev, (sdata == 0 ? 0 : row + iy * sraster), sourcex, sraster, gx_no_bitmap_id, scolors, &line_tile, tcolors, rx, re.y + iy, rwidth, 1, - new_phase, 0, lop); + new_phase, 0, lop, planar_height); } --cdev->driver_call_nesting; if (code < 0 && SET_BAND_CODE(code)) @@ -1268,10 +1305,10 @@ clist_strip_copy_rop(gx_device * dev, code = clist_copy_mono(dev, row, sourcex, sraster, id, rx, re.y, rwidth, re.height, scolors[0], scolors[1]); - } else if (lop & lop_planar) { - code = clist_copy_plane(dev, row, sourcex, sraster, id, - rx, re.y, rwidth, re.height, - (lop >> lop_planar_shift)); + } else if (planar_height) { + code = clist_copy_planes(dev, row, sourcex, sraster, id, + rx, re.y, rwidth, re.height, + planar_height); } else { code = clist_copy_color(dev, row, sourcex, sraster, id, rx, re.y, rwidth, re.height); diff --git a/gs/base/gxdcolor.c b/gs/base/gxdcolor.c index 1d9addb01..df25b1b4c 100644 --- a/gs/base/gxdcolor.c +++ b/gs/base/gxdcolor.c @@ -420,10 +420,16 @@ gx_dc_pure_fill_rectangle(const gx_device_color * pdevc, int x, int y, colors[0] = colors[1] = pdevc->colors.pure; if (source == NULL) set_rop_no_source(source, no_source, dev); - return (*dev_proc(dev, strip_copy_rop)) - (dev, source->sdata, source->sourcex, source->sraster, - source->id, (source->use_scolors ? source->scolors : NULL), - NULL /*arbitrary */ , colors, x, y, w, h, 0, 0, lop); + if (source->planar_height == 0) + return (*dev_proc(dev, strip_copy_rop)) + (dev, source->sdata, source->sourcex, source->sraster, + source->id, (source->use_scolors ? source->scolors : NULL), + NULL /*arbitrary */ , colors, x, y, w, h, 0, 0, lop); + else + return (*dev_proc(dev, strip_copy_rop2)) + (dev, source->sdata, source->sourcex, source->sraster, + source->id, (source->use_scolors ? source->scolors : NULL), + NULL /*arbitrary */ , colors, x, y, w, h, 0, 0, lop, source->planar_height); } } diff --git a/gs/base/gxdcolor.h b/gs/base/gxdcolor.h index f85a4962b..94617acdc 100644 --- a/gs/base/gxdcolor.h +++ b/gs/base/gxdcolor.h @@ -44,6 +44,7 @@ typedef struct gx_rop_source_s { uint sraster; gx_bitmap_id id; gx_color_index scolors[2]; + uint planar_height; bool use_scolors; } gx_rop_source_t; @@ -53,7 +54,7 @@ typedef struct gx_rop_source_s { * a different null source if necessary. */ #define gx_rop_no_source_body(black_pixel)\ - NULL, 0, 0, gx_no_bitmap_id, {black_pixel, black_pixel}, true + NULL, 0, 0, gx_no_bitmap_id, {black_pixel, black_pixel}, 0, true #define gx_rop_source_set_color(prs, pixel)\ ((prs)->scolors[0] = (prs)->scolors[1] = (pixel)) void gx_set_rop_no_source(const gx_rop_source_t **psource, diff --git a/gs/base/gxdevcli.h b/gs/base/gxdevcli.h index 83ee08225..4b3ff3107 100644 --- a/gs/base/gxdevcli.h +++ b/gs/base/gxdevcli.h @@ -1421,12 +1421,12 @@ typedef struct gs_devn_params_s gs_devn_params; #define dev_proc_dev_spec_op(proc)\ dev_t_proc_dev_spec_op(proc, gx_device) -#define dev_t_proc_copy_plane(proc, dev_t)\ +#define dev_t_proc_copy_planes(proc, dev_t)\ int proc(dev_t *dev,\ const byte *data, int data_x, int raster, gx_bitmap_id id,\ - int x, int y, int width, int height, int plane) -#define dev_proc_copy_plane(proc)\ - dev_t_proc_copy_plane(proc, gx_device) + int x, int y, int width, int height, int plane_height) +#define dev_proc_copy_planes(proc)\ + dev_t_proc_copy_planes(proc, gx_device) #define dev_t_proc_get_profile(proc, dev_t)\ int proc(dev_t *dev, cmm_dev_profile_t **dev_profile) @@ -1438,6 +1438,17 @@ typedef struct gs_devn_params_s gs_devn_params; #define dev_proc_set_graphics_type_tag(proc)\ dev_t_proc_set_graphics_type_tag(proc, gx_device) +#define dev_t_proc_strip_copy_rop2(proc, dev_t)\ + int proc(dev_t *dev,\ + const byte *sdata, int sourcex, uint sraster, gx_bitmap_id id,\ + const gx_color_index *scolors,\ + const gx_strip_bitmap *textures, const gx_color_index *tcolors,\ + int x, int y, int width, int height,\ + int phase_x, int phase_y, gs_logical_operation_t lop,\ + uint planar_height) +#define dev_proc_strip_copy_rop2(proc)\ + dev_t_proc_strip_copy_rop2(proc, gx_device) + /* Define the device procedure vector template proper. */ #define gx_device_proc_struct(dev_t)\ @@ -1507,9 +1518,10 @@ typedef struct gs_devn_params_s gs_devn_params; dev_t_proc_pop_transparency_state((*pop_transparency_state), dev_t); \ dev_t_proc_put_image((*put_image), dev_t); \ dev_t_proc_dev_spec_op((*dev_spec_op), dev_t); \ - dev_t_proc_copy_plane((*copy_plane), dev_t); \ + dev_t_proc_copy_planes((*copy_planes), dev_t); \ 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);\ } /* diff --git a/gs/base/gxdevice.h b/gs/base/gxdevice.h index 6a7a4fa91..8106f25bc 100644 --- a/gs/base/gxdevice.h +++ b/gs/base/gxdevice.h @@ -280,6 +280,7 @@ dev_proc_ret_devn_params(gx_default_ret_devn_params); 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); /* BACKWARD COMPATIBILITY */ #define gx_non_imaging_create_compositor gx_null_create_compositor @@ -366,6 +367,7 @@ dev_proc_fillpage(gx_forward_fillpage); 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); /* ---------------- Implementation utilities ---------------- */ diff --git a/gs/base/gxht.c b/gs/base/gxht.c index 2d07b3e8e..72d3f1524 100644 --- a/gs/base/gxht.c +++ b/gs/base/gxht.c @@ -331,13 +331,24 @@ gx_dc_ht_binary_fill_rectangle(const gx_device_color * pdevc, int x, int y, lop = rop3_use_D_when_T_1(lop); if (source == NULL) set_rop_no_source(source, no_source, dev); - return (*dev_proc(dev, strip_copy_rop)) (dev, source->sdata, - source->sourcex, source->sraster, source->id, - (source->use_scolors ? source->scolors : NULL), - &pdevc->colors.binary.b_tile->tiles, - pdevc->colors.binary.color, - x, y, w, h, pdevc->phase.x, pdevc->phase.y, - lop); + if (source->planar_height == 0) + return (*dev_proc(dev, strip_copy_rop)) + (dev, source->sdata, + source->sourcex, source->sraster, source->id, + (source->use_scolors ? source->scolors : NULL), + &pdevc->colors.binary.b_tile->tiles, + pdevc->colors.binary.color, + x, y, w, h, pdevc->phase.x, pdevc->phase.y, + lop); + else + return (*dev_proc(dev, strip_copy_rop2)) + (dev, source->sdata, + source->sourcex, source->sraster, source->id, + (source->use_scolors ? source->scolors : NULL), + &pdevc->colors.binary.b_tile->tiles, + pdevc->colors.binary.color, + x, y, w, h, pdevc->phase.x, pdevc->phase.y, + lop, source->planar_height); } static int diff --git a/gs/base/gxht_thresh.c b/gs/base/gxht_thresh.c index d5b6f648d..2f975b478 100644 --- a/gs/base/gxht_thresh.c +++ b/gs/base/gxht_thresh.c @@ -431,9 +431,11 @@ gxht_thresh_image_init(gx_image_enum *penum) penum->line_size * LAND_BITS + 16, "gxht_thresh"); /* That maps into (LAND_BITS/8) bytes of Halftone data */ - penum->ht_buffer = gs_alloc_bytes(penum->memory, - penum->line_size * (LAND_BITS>>3), - "gxht_thresh"); + penum->ht_buffer = + gs_alloc_bytes(penum->memory, + penum->line_size * (LAND_BITS>>3) * spp_out, + "gxht_thresh"); + penum->ht_plane_height = penum->line_size; penum->ht_stride = penum->line_size; if (penum->line == NULL || penum->thresh_buffer == NULL || penum->ht_buffer == NULL) @@ -464,7 +466,7 @@ gxht_thresh_image_init(gx_image_enum *penum) if (code >= 0) { #if defined(DEBUG) || defined(PACIFY_VALGRIND) memset(penum->line, 0, LAND_BITS * penum->line_size * spp_out + 16); - memset(penum->ht_buffer, 0, penum->line_size * (LAND_BITS>>3)); + memset(penum->ht_buffer, 0, penum->line_size * (LAND_BITS>>3) * spp_out); memset(penum->thresh_buffer, 0, LAND_BITS * penum->line_size + 16); #endif } @@ -500,9 +502,11 @@ gxht_thresh_image_init(gx_image_enum *penum) space */ max_height = (int) ceil(fixed2float(any_abs(penum->dst_height)) / (float) penum->Height); - penum->ht_buffer = gs_alloc_bytes(penum->memory, - penum->ht_stride * max_height, - "gxht_thresh"); + penum->ht_buffer = + gs_alloc_bytes(penum->memory, + penum->ht_stride * max_height * spp_out, + "gxht_thresh"); + penum->ht_plane_height = penum->ht_stride * max_height; /* We want to have 128 bit alignement for our contone and threshold strips so that we can use SSE operations in the threshold operation. Add in a minor buffer and offset @@ -529,7 +533,7 @@ gxht_thresh_image_init(gx_image_enum *penum) } else { #if defined(DEBUG) || defined(PACIFY_VALGRIND) memset(penum->line, 0, penum->line_size * spp_out); - memset(penum->ht_buffer, 0, penum->ht_stride * max_height); + memset(penum->ht_buffer, 0, penum->ht_stride * max_height * spp_out); memset(penum->thresh_buffer, 0, penum->line_size * max_height); #endif } @@ -628,96 +632,100 @@ reset_landscape_buffer(ht_landscape_info_t *ht_landscape, byte *contone_align, } } -/* This performs a thresholding operation on a single plane of data and - performs a copy mono operation to the device */ +/* This performs a thresholding operation on multiple planes of data and + stores the bits into a planar buffer which can then be used for + copy_planes */ int -gxht_thresh_plane(gx_image_enum *penum, gx_ht_order *d_order, - fixed xrun, int dest_width, int dest_height, - byte *thresh_align, byte *contone_align, int contone_stride, - gx_device * dev, int plane_number, bool allow_reset) +gxht_thresh_planes(gx_image_enum *penum, fixed xrun, + int dest_width, int dest_height, + byte *thresh_align, gx_device * dev, int offset_contone[], + int contone_stride) { int thresh_width, thresh_height, dx; int left_rem_end, left_width, vdi; int num_full_tiles, right_tile_width; - int k, jj, dy; + int k, jj, dy, j; byte *thresh_tile; int position; bool replicate_tile; image_posture posture = penum->posture; const int y_pos = penum->yci; - int width; + int width = 0; /* Init to silence compiler warnings */ byte *ptr_out, *row_ptr, *ptr_out_temp; - byte *threshold = d_order->threshold; + byte *threshold; int init_tile, in_row_offset, ii, num_tiles, tile_remainder; int offset_bits = penum->ht_offset_bits; - byte *halftone = penum->ht_buffer; + byte *halftone; int dithered_stride = penum->ht_stride; bool is_planar_dev = dev_proc(dev, dev_spec_op)(dev, gxdso_is_native_planar, NULL, 0); gx_color_index dev_white = gx_device_white(dev); gx_color_index dev_black = gx_device_black(dev); bool done = false; + bool allow_reset = false; /* Init to silence compiler warnings */ + int spp_out = dev->color_info.num_components; + byte *contone_align = NULL; /* Init to silence compiler warnings */ /* Go ahead and fill the threshold line buffer with tiled threshold values. First just grab the row or column that we are going to tile with and then do memcpy into the buffer */ - thresh_width = d_order->width; - thresh_height = d_order->full_height; /* Figure out the tile steps. Left offset, Number of tiles, Right offset. */ switch (posture) { case image_portrait: + allow_reset = true; vdi = penum->hci; - /* Compute the tiling positions with dest_width */ - dx = fixed2int_var(xrun) % thresh_width; - /* Left remainder part */ - left_rem_end = min(dx + dest_width, thresh_width); - left_width = left_rem_end - dx; /* The left width of our tile part */ - /* Now the middle part */ - num_full_tiles = - (int)fastfloor((dest_width - left_width)/ (float) thresh_width); - /* Now the right part */ - right_tile_width = dest_width - num_full_tiles * thresh_width - - left_width; - /* Those dimensions stay the same across the set of lines that - we fill in our buffer. Iterate over the vdi and fill up our - threshold buffer */ - for (k = 0; k < vdi; k++) { - /* Get a pointer to our tile row */ - dy = (penum->yci + k + penum->dev->band_offset_y) % thresh_height; - if (dy < 0) - dy += thresh_height; - thresh_tile = threshold + d_order->width * dy; - /* Fill the buffer, can be multiple rows. Make sure - to update with stride */ - position = contone_stride * k; - /* Tile into the 128 bit aligned threshold strip */ - fill_threshhold_buffer(&(thresh_align[position]), - thresh_tile, thresh_width, dx, left_width, - num_full_tiles, right_tile_width); - } - /* Apply the threshold operation */ -#if RAW_HT_DUMP - gx_ht_threshold_row_byte(contone_align, thresh_align, contone_stride, - halftone, dithered_stride, dest_width, vdi); - sprintf(file_name,"HT_Portrait_%d_%dx%dx%d.raw", penum->id, dest_width, - dest_height, spp_out); - fid = fopen(file_name,"a+b"); - fwrite(halftone,1,dest_width * vdi,fid); - fclose(fid); -#else - if (offset_bits > dest_width) - offset_bits = dest_width; - - if (dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE - && is_planar_dev) { - gx_ht_threshold_row_bit(thresh_align, contone_align, contone_stride, - halftone, dithered_stride, dest_width, vdi, - offset_bits); - } else { - gx_ht_threshold_row_bit(contone_align, thresh_align, contone_stride, - halftone, dithered_stride, dest_width, vdi, - offset_bits); + /* Iterate over the vdi and fill up our threshold buffer. We + also need to loop across the planes of data */ + for (j = 0; j < spp_out; j++) { + thresh_width = penum->pis->dev_ht->components[j].corder.width; + thresh_height = penum->pis->dev_ht->components[j].corder.full_height; + halftone = penum->ht_buffer + j * penum->ht_plane_height; + /* Compute the tiling positions with dest_width */ + dx = fixed2int_var(xrun) % thresh_width; + /* Left remainder part */ + left_rem_end = min(dx + dest_width, thresh_width); + /* The left width of our tile part */ + left_width = left_rem_end - dx; + /* Now the middle part */ + num_full_tiles = + (int)fastfloor((dest_width - left_width)/ (float) thresh_width); + /* Now the right part */ + right_tile_width = dest_width - num_full_tiles * thresh_width - + left_width; + /* Get the proper threshold for the colorant count */ + threshold = penum->pis->dev_ht->components[j].corder.threshold; + /* Point to the proper contone data */ + contone_align = penum->line + contone_stride * j + + offset_contone[j]; + for (k = 0; k < vdi; k++) { + /* Get a pointer to our tile row */ + dy = (penum->yci + k + penum->dev->band_offset_y) % thresh_height; + if (dy < 0) + dy += thresh_height; + thresh_tile = threshold + thresh_width * dy; + /* Fill the buffer, can be multiple rows. Make sure + to update with stride */ + position = contone_stride * k; + /* Tile into the 128 bit aligned threshold strip */ + fill_threshhold_buffer(&(thresh_align[position]), + thresh_tile, thresh_width, dx, left_width, + num_full_tiles, right_tile_width); + } + /* Apply the threshold operation */ + if (offset_bits > dest_width) + offset_bits = dest_width; + + if (dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE + && is_planar_dev) { + gx_ht_threshold_row_bit(thresh_align, contone_align, contone_stride, + halftone, dithered_stride, dest_width, vdi, + offset_bits); + } else { + gx_ht_threshold_row_bit(contone_align, thresh_align, contone_stride, + halftone, dithered_stride, dest_width, vdi, + offset_bits); + } } /* FIXME: An improvement here would be to generate the initial * offset_bits at the correct offset within the byte so that they @@ -733,19 +741,19 @@ gxht_thresh_plane(gx_image_enum *penum, gx_ht_order *d_order, if (offset_bits > 0) { int x_pos = fixed2int_var(xrun); if (!is_planar_dev) { - (*dev_proc(dev, copy_mono)) (dev, halftone, 0, dithered_stride, + (*dev_proc(dev, copy_mono)) (dev, penum->ht_buffer, 0, dithered_stride, gx_no_bitmap_id, x_pos, y_pos, offset_bits, vdi, dev_white, dev_black); } else { - (*dev_proc(dev, copy_plane)) (dev, halftone, 0, dithered_stride, + (*dev_proc(dev, copy_planes)) (dev, penum->ht_buffer, 0, dithered_stride, gx_no_bitmap_id, x_pos, y_pos, - offset_bits, vdi, plane_number); + offset_bits, vdi, vdi); } } if ((dest_width - offset_bits) > 0 ) { /* Now the primary aligned bytes */ - byte *curr_ptr = halftone; + byte *curr_ptr = penum->ht_buffer; int curr_width = dest_width - offset_bits; int x_pos = fixed2int_var(xrun) + offset_bits; if (offset_bits > 0) { @@ -757,127 +765,150 @@ gxht_thresh_plane(gx_image_enum *penum, gx_ht_order *d_order, curr_width, vdi, dev_white, dev_black); } else { - (*dev_proc(dev, copy_plane)) (dev, curr_ptr, 0, dithered_stride, + (*dev_proc(dev, copy_planes)) (dev, curr_ptr, 0, dithered_stride, gx_no_bitmap_id, x_pos, y_pos, - curr_width, vdi, plane_number); + curr_width, vdi, vdi); } } -#endif + break; case image_landscape: /* Go ahead and paint the chunk if we have LAND_BITS values or a * partial to get us in sync with the 1 bit devices 16 bit * positions. */ vdi = penum->wci; + /* Now do the haftoning into our buffer. We basically check + first if we have enough data or are all done */ while ( (penum->ht_landscape.count >= LAND_BITS || ((penum->ht_landscape.count >= offset_bits) && penum->ht_landscape.offset_set)) && !done ) { /* Go ahead and 2D tile in the threshold buffer at this time */ /* Always work the tiling from the upper left corner of our LAND_BITS columns */ - if (penum->ht_landscape.offset_set) { - width = offset_bits; - } else { - width = LAND_BITS; - } - if (penum->y_extent.x < 0) { - dx = (penum->ht_landscape.xstart - width + 1) % thresh_width; - } else { - dx = penum->ht_landscape.xstart % thresh_width; - } - dy = (penum->dev->band_offset_y + penum->ht_landscape.y_pos) % thresh_height; - if (dy < 0) - dy += thresh_height; - /* Left remainder part */ - left_rem_end = min(dx + LAND_BITS, thresh_width); - left_width = left_rem_end - dx; - /* Now the middle part */ - num_full_tiles = (LAND_BITS - left_width) / thresh_width; - /* Now the right part */ - right_tile_width = - LAND_BITS - num_full_tiles * thresh_width - left_width; - /* Now loop over the y stuff */ - ptr_out = thresh_align; - /* Do this in three parts. We do a top part, followed by - larger mem copies followed by a bottom partial. After - a slower initial fill we are able to do larger faster - expansions */ - if (dest_height <= 2 * thresh_height) { - init_tile = dest_height; - replicate_tile = false; - } else { - init_tile = thresh_height; - replicate_tile = true; - } - for (jj = 0; jj < init_tile; jj++) { - in_row_offset = (jj + dy) % thresh_height; - row_ptr = threshold + in_row_offset * thresh_width; - ptr_out_temp = ptr_out; - /* Left part */ - memcpy(ptr_out_temp, row_ptr + dx, left_width); - ptr_out_temp += left_width; - /* Now the full tiles */ - for (ii = 0; ii < num_full_tiles; ii++) { - memcpy(ptr_out_temp, row_ptr, thresh_width); - ptr_out_temp += thresh_width; + for (j = 0; j < spp_out; j++) { + halftone = penum->ht_buffer + + j * penum->ht_plane_height * (LAND_BITS>>3); + thresh_width = penum->pis->dev_ht->components[j].corder.width; + thresh_height = + penum->pis->dev_ht->components[j].corder.full_height; + /* Get the proper threshold for the colorant count */ + threshold = penum->pis->dev_ht->components[j].corder.threshold; + /* Point to the proper contone data */ + contone_align = penum->line + offset_contone[j] + + LAND_BITS * j * contone_stride; + if (j == spp_out - 1) { + allow_reset = true; + } else { + allow_reset = false; } - /* Now the remainder */ - memcpy(ptr_out_temp, row_ptr, right_tile_width); - ptr_out += LAND_BITS; - } - if (replicate_tile) { - /* Find out how many we need to copy */ - num_tiles = - (int)fastfloor((float) (dest_height - thresh_height)/ (float) thresh_height); - tile_remainder = dest_height - (num_tiles + 1) * thresh_height; - for (jj = 0; jj < num_tiles; jj ++) { - memcpy(ptr_out, thresh_align, LAND_BITS * thresh_height); - ptr_out += LAND_BITS * thresh_height; + if (penum->ht_landscape.offset_set) { + width = offset_bits; + } else { + width = LAND_BITS; + } + if (penum->y_extent.x < 0) { + dx = (penum->ht_landscape.xstart - width + 1) % + thresh_width; + } else { + dx = penum->ht_landscape.xstart % thresh_width; + } + dy = (penum->dev->band_offset_y + + penum->ht_landscape.y_pos) % thresh_height; + if (dy < 0) + dy += thresh_height; + /* Left remainder part */ + left_rem_end = min(dx + LAND_BITS, thresh_width); + left_width = left_rem_end - dx; + /* Now the middle part */ + num_full_tiles = (LAND_BITS - left_width) / thresh_width; + /* Now the right part */ + right_tile_width = + LAND_BITS - num_full_tiles * thresh_width - left_width; + /* Now loop over the y stuff */ + ptr_out = thresh_align; + /* Do this in three parts. We do a top part, followed by + larger mem copies followed by a bottom partial. After + a slower initial fill we are able to do larger faster + expansions */ + if (dest_height <= 2 * thresh_height) { + init_tile = dest_height; + replicate_tile = false; + } else { + init_tile = thresh_height; + replicate_tile = true; + } + for (jj = 0; jj < init_tile; jj++) { + in_row_offset = (jj + dy) % thresh_height; + row_ptr = threshold + in_row_offset * thresh_width; + ptr_out_temp = ptr_out; + /* Left part */ + memcpy(ptr_out_temp, row_ptr + dx, left_width); + ptr_out_temp += left_width; + /* Now the full tiles */ + for (ii = 0; ii < num_full_tiles; ii++) { + memcpy(ptr_out_temp, row_ptr, thresh_width); + ptr_out_temp += thresh_width; + } + /* Now the remainder */ + memcpy(ptr_out_temp, row_ptr, right_tile_width); + ptr_out += LAND_BITS; + } + if (replicate_tile) { + /* Find out how many we need to copy */ + num_tiles = + (int)fastfloor((float) (dest_height - thresh_height)/ (float) thresh_height); + tile_remainder = dest_height - (num_tiles + 1) * thresh_height; + for (jj = 0; jj < num_tiles; jj ++) { + memcpy(ptr_out, thresh_align, LAND_BITS * thresh_height); + ptr_out += LAND_BITS * thresh_height; + } + /* Now fill in the remainder */ + memcpy(ptr_out, thresh_align, LAND_BITS * tile_remainder); + } + /* Apply the threshold operation */ + if (dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE + && is_planar_dev) { + gx_ht_threshold_landscape(thresh_align, contone_align, + penum->ht_landscape, halftone, dest_height); + } else { + gx_ht_threshold_landscape(contone_align, thresh_align, + penum->ht_landscape, halftone, dest_height); } - /* Now fill in the remainder */ - memcpy(ptr_out, thresh_align, LAND_BITS * tile_remainder); - } - /* Apply the threshold operation */ - if (dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE - && is_planar_dev) { - gx_ht_threshold_landscape(thresh_align, contone_align, - penum->ht_landscape, halftone, dest_height); - } else { - gx_ht_threshold_landscape(contone_align, thresh_align, - penum->ht_landscape, halftone, dest_height); } /* Perform the copy mono */ if (penum->ht_landscape.index < 0) { if (!is_planar_dev) { - (*dev_proc(dev, copy_mono)) (dev, halftone, 0, LAND_BITS>>3, - gx_no_bitmap_id, - penum->ht_landscape.xstart - width + 1, - penum->ht_landscape.y_pos, - width, dest_height, - dev_white, dev_black); + (*dev_proc(dev, copy_mono)) + (dev, penum->ht_buffer, 0, LAND_BITS>>3, + gx_no_bitmap_id, + penum->ht_landscape.xstart - width + 1, + penum->ht_landscape.y_pos, + width, dest_height, + dev_white, dev_black); } else { - (*dev_proc(dev, copy_plane)) (dev, halftone, 0, LAND_BITS>>3, - gx_no_bitmap_id, - penum->ht_landscape.xstart - width + 1, - penum->ht_landscape.y_pos, - width, dest_height, - plane_number); + (*dev_proc(dev, copy_planes)) + (dev, penum->ht_buffer, 0, LAND_BITS>>3, + gx_no_bitmap_id, + penum->ht_landscape.xstart - width + 1, + penum->ht_landscape.y_pos, + width, dest_height, + penum->ht_plane_height); } } else { if (!is_planar_dev) { - (*dev_proc(dev, copy_mono)) (dev, halftone, 0, LAND_BITS>>3, + (*dev_proc(dev, copy_mono)) (dev, penum->ht_buffer, 0, LAND_BITS>>3, gx_no_bitmap_id, penum->ht_landscape.xstart, penum->ht_landscape.y_pos, width, dest_height, dev_white, dev_black); } else { - (*dev_proc(dev, copy_plane)) (dev, halftone, 0, LAND_BITS>>3, + (*dev_proc(dev, copy_planes)) (dev, penum->ht_buffer, 0, LAND_BITS>>3, gx_no_bitmap_id, penum->ht_landscape.xstart, penum->ht_landscape.y_pos, - width, dest_height, - plane_number); + width, dest_height, + penum->ht_plane_height); } } /* Clean up and reset our buffer. We may have a line left diff --git a/gs/base/gxht_thresh.h b/gs/base/gxht_thresh.h index 7f0f63153..ef4a8ecc9 100644 --- a/gs/base/gxht_thresh.h +++ b/gs/base/gxht_thresh.h @@ -33,8 +33,7 @@ void gx_ht_threshold_landscape(byte *contone_align, byte *thresh_align, ht_landscape_info_t ht_landscape, byte *halftone, int data_length); int gxht_thresh_image_init(gx_image_enum *penum); -int gxht_thresh_plane(gx_image_enum *penum, gx_ht_order *d_order, - fixed xrun, int dest_width, int dest_height, - byte *thresh_align, byte *contone_align, int contone_stride, - gx_device * dev, int plane_number, bool allow_reset); +int gxht_thresh_planes(gx_image_enum *penum, fixed xrun, int dest_width, + int dest_height, byte *thresh_align, gx_device * dev, + int offset_contone[], int contone_stride); #endif /* gshtx_INCLUDED */ diff --git a/gs/base/gxicolor.c b/gs/base/gxicolor.c index 2213c9963..5483c12a9 100644 --- a/gs/base/gxicolor.c +++ b/gs/base/gxicolor.c @@ -391,12 +391,10 @@ image_render_color_thresh(gx_image_enum *penum_orig, const byte *buffer, int dat byte *thresh_align; byte *devc_contone[GX_DEVICE_COLOR_MAX_COMPONENTS]; byte *psrc_plane[GX_DEVICE_COLOR_MAX_COMPONENTS]; - byte *contone_align; byte *devc_contone_gray; const byte *psrc = buffer + data_x; int dest_width, dest_height, data_length; int spp_out = dev->color_info.num_components; - gx_ht_order *d_order; int position, k, j; int offset_bits = penum->ht_offset_bits; int contone_stride = 0; /* Not used in landscape case */ @@ -414,7 +412,6 @@ image_render_color_thresh(gx_image_enum *penum_orig, const byte *buffer, int dat int psrc_planestride = w/penum->spp; gx_color_value conc; int num_des_comp = penum->dev->color_info.num_components; - bool allow_reset; if (h != 0) { /* Get the buffer into the device color space */ @@ -473,7 +470,7 @@ image_render_color_thresh(gx_image_enum *penum_orig, const byte *buffer, int dat scale_factor = float2fixed_rounded((float) src_size / (float) (dest_width - 1)); #ifdef DEBUG /* Help in spotting problems */ - memset(penum->ht_buffer, 0x00, penum->ht_stride * vdi); + memset(penum->ht_buffer, 0x00, penum->ht_stride * vdi * spp_out); #endif break; case image_landscape: @@ -760,25 +757,9 @@ image_render_color_thresh(gx_image_enum *penum_orig, const byte *buffer, int dat depnding upon the polarity of the device */ flush: thresh_align = penum->thresh_buffer + offset_threshold; - for (k = 0; k < spp_out; k++) { - d_order = &(penum->pis->dev_ht->components[k].corder); - if (posture == image_portrait) { - contone_align = penum->line + contone_stride * k + - offset_contone[k]; - allow_reset = true; - } else { - contone_align = penum->line + offset_contone[k] + - LAND_BITS * k * contone_stride; - if (k == spp_out - 1) { - allow_reset = true; - } else { - allow_reset = false; - } - } - code = gxht_thresh_plane(penum, d_order, xrun, dest_width, dest_height, - thresh_align, contone_align, - contone_stride, dev, k, allow_reset); - } + code = gxht_thresh_planes(penum, xrun, dest_width, dest_height, + thresh_align, dev, offset_contone, + contone_stride); /* Free cm buffer, if it was used */ if (psrc_cm_start != NULL) { gs_free_object(penum->pis->memory, (byte *)psrc_cm_start, diff --git a/gs/base/gximage.h b/gs/base/gximage.h index 748a40523..645d7d3d5 100644 --- a/gs/base/gximage.h +++ b/gs/base/gximage.h @@ -290,7 +290,8 @@ struct gx_image_enum_s { gx_image_color_cache_t *color_cache; /* A cache that is con-tone values */ byte *ht_buffer; /* A buffer to contain halftoned data */ int ht_stride; - int ht_offset_bits; /* An offset adjustement to allow aligned copies */ + int ht_offset_bits; /* An offset adjustement to allow aligned copies */ + int ht_plane_height; /* Needed during the copy_planes operation */ byte *thresh_buffer; /* A buffer to hold threshold values for HT */ int thresh_stride; gs_image_parent_t image_parent_type; /* Need to avoid threshold of type3 images */ diff --git a/gs/base/gximono.c b/gs/base/gximono.c index 2edb970cc..a052df901 100644 --- a/gs/base/gximono.c +++ b/gs/base/gximono.c @@ -789,14 +789,13 @@ image_render_mono_ht(gx_image_enum * penum_orig, const byte * buffer, int data_x image_posture posture = penum->posture; int vdi; /* amounts to replicate */ fixed xrun; - byte *contone_align, *thresh_align; + byte *thresh_align; int spp_out = penum->dev->color_info.num_components; byte *devc_contone[GX_DEVICE_COLOR_MAX_COMPONENTS]; byte *devc_contone_gray; const byte *psrc = buffer + data_x; int dest_width, dest_height, data_length; byte *color_cache; - gx_ht_order *d_order = &(penum->pis->dev_ht->components[0].corder); int position, k, j; int offset_bits = penum->ht_offset_bits; int contone_stride = 0; /* Not used in landscape case */ @@ -807,7 +806,6 @@ image_render_mono_ht(gx_image_enum * penum_orig, const byte * buffer, int data_x int offset_threshold; /* to ensure 128 bit boundary */ gx_dda_int_t dda_ht; int code = 0; - bool allow_reset; byte *dev_value; if (h == 0) { @@ -848,7 +846,7 @@ image_render_mono_ht(gx_image_enum * penum_orig, const byte * buffer, int data_x scale_factor = float2fixed_rounded((float) src_size / (float) (dest_width - 1)); #ifdef DEBUG /* Help in spotting problems */ - memset(penum->ht_buffer,0x00, penum->ht_stride * vdi); + memset(penum->ht_buffer,0x00, penum->ht_stride * vdi * spp_out); #endif break; case image_landscape: @@ -1105,24 +1103,8 @@ image_render_mono_ht(gx_image_enum * penum_orig, const byte * buffer, int data_x /* Apply threshold array to image data */ flush: thresh_align = penum->thresh_buffer + offset_threshold; - for (k = 0; k < spp_out; k++) { - d_order = &(penum->pis->dev_ht->components[k].corder); - if (posture == image_portrait) { - contone_align = penum->line + contone_stride * k + - offset_contone[k]; - allow_reset = true; - } else { - contone_align = penum->line + offset_contone[k] + - LAND_BITS * k * contone_stride; - if (k == spp_out - 1) { - allow_reset = true; - } else { - allow_reset = false; - } - } - code = gxht_thresh_plane(penum, d_order, xrun, dest_width, dest_height, - thresh_align, contone_align, contone_stride, - dev, k, allow_reset); - } + code = gxht_thresh_planes(penum, xrun, dest_width, dest_height, + thresh_align, dev, offset_contone, + contone_stride); return code; } diff --git a/gs/base/gxp1fill.c b/gs/base/gxp1fill.c index 43186fd53..3d87c56da 100644 --- a/gs/base/gxp1fill.c +++ b/gs/base/gxp1fill.c @@ -234,29 +234,39 @@ tile_colored_fill(const tile_fill_state_t * ptfs, gx_device *dev = ptfs->orig_dev; int xoff = ptfs->xoff, yoff = ptfs->yoff; gx_strip_bitmap *bits = &ptile->tbits; - int plane_step = ptile->tbits.raster * ptile->tbits.rep_height; const byte *data = bits->data; bool full_transfer = (w == ptfs->w0 && h == ptfs->h0); int code = 0; - int k; - byte *data_plane; - if (source == NULL && lop_no_S_is_T(lop)) { - if (ptfs->num_planes < 0) { - code = (*dev_proc(ptfs->pcdev, copy_color)) + 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. + */ + { + 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 { - for (k = 0; k < ptfs->num_planes; k++) { - /* Get the proper pointer to the data plane */ - 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 { gx_strip_bitmap data_tile; @@ -273,17 +283,32 @@ tile_colored_fill(const tile_fill_state_t * ptfs, data_tile.id = bits->id; data_tile.shift = data_tile.rep_shift = 0; data_tile.num_planes = (ptfs->num_planes > 1 ? ptfs->num_planes : 1); - code = (*dev_proc(dev, strip_copy_rop)) - (dev, - source->sdata + (y - ptfs->y0) * source->sraster, - source->sourcex + (x - ptfs->x0), - source->sraster, source_id, - (source->use_scolors ? source->scolors : NULL), - &data_tile, NULL, - x, y, w, h, - imod(xoff - x, data_tile.rep_width), - imod(yoff - y, data_tile.rep_height), - lop); + if (source->planar_height == 0) { + code = (*dev_proc(ptfs->pcdev, strip_copy_rop)) + (ptfs->pcdev, + source->sdata + (y - ptfs->y0) * source->sraster, + source->sourcex + (x - ptfs->x0), + source->sraster, source_id, + (source->use_scolors ? source->scolors : NULL), + &data_tile, NULL, + x, y, w, h, + imod(xoff - x, data_tile.rep_width), + imod(yoff - y, data_tile.rep_height), + lop); + } else { + code = (*dev_proc(ptfs->pcdev, strip_copy_rop2)) + (ptfs->pcdev, + source->sdata + (y - ptfs->y0) * source->sraster, + source->sourcex + (x - ptfs->x0), + source->sraster, source_id, + (source->use_scolors ? source->scolors : NULL), + &data_tile, NULL, + x, y, w, h, + imod(xoff - x, data_tile.rep_width), + imod(yoff - y, data_tile.rep_height), + lop, + source->planar_height); + } } return code; } @@ -340,7 +365,7 @@ gx_dc_pattern_fill_rectangle(const gx_device_color * pdevc, int x, int y, code = tile_fill_init(&state, pdevc, dev, false); if (code < 0) return code; - if (ptile->is_simple && ptile->cdev == NULL && state.num_planes == -1) { + if (ptile->is_simple && ptile->cdev == NULL) { int px = imod(-(int)fastfloor(ptile->step_matrix.tx - state.phase.x + 0.5), bits->rep_width); @@ -350,17 +375,30 @@ gx_dc_pattern_fill_rectangle(const gx_device_color * pdevc, int x, int y, if (state.pcdev != dev) tile_clip_set_phase(&state.cdev, px, py); - if (source == NULL && lop_no_S_is_T(lop)) + /* 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) 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); - else + else if (rop_source->planar_height == 0) code = (*dev_proc(state.pcdev, strip_copy_rop)) - (state.pcdev, - rop_source->sdata, rop_source->sourcex, - rop_source->sraster, rop_source->id, - (rop_source->use_scolors ? rop_source->scolors : NULL), - bits, NULL, x, y, w, h, px, py, lop); + (state.pcdev, + rop_source->sdata, rop_source->sourcex, + rop_source->sraster, rop_source->id, + (rop_source->use_scolors ? rop_source->scolors : NULL), + bits, NULL, x, y, w, h, px, py, lop); + else + code = (*dev_proc(state.pcdev, strip_copy_rop2)) + (state.pcdev, + rop_source->sdata, rop_source->sourcex, + rop_source->sraster, rop_source->id, + (rop_source->use_scolors ? rop_source->scolors : NULL), + bits, NULL, x, y, w, h, px, py, lop, + rop_source->planar_height); } else { state.lop = lop; state.source = source; @@ -411,6 +449,7 @@ tile_masked_fill(const tile_fill_state_t * ptfs, source->id : gx_no_bitmap_id); step_source.scolors[0] = source->scolors[0]; step_source.scolors[1] = source->scolors[1]; + step_source.planar_height = source->planar_height; step_source.use_scolors = source->use_scolors; return (*ptfs->fill_rectangle) (ptfs->pdevc, x, y, w, h, ptfs->pcdev, ptfs->lop, &step_source); diff --git a/gs/base/gxpcmap.c b/gs/base/gxpcmap.c index 5b73096cb..6d6208fca 100644 --- a/gs/base/gxpcmap.c +++ b/gs/base/gxpcmap.c @@ -89,7 +89,7 @@ static dev_proc_close_device(pattern_accum_close); static dev_proc_fill_rectangle(pattern_accum_fill_rectangle); static dev_proc_copy_mono(pattern_accum_copy_mono); static dev_proc_copy_color(pattern_accum_copy_color); -static dev_proc_copy_plane(pattern_accum_copy_plane); +static dev_proc_copy_planes(pattern_accum_copy_planes); static dev_proc_get_bits_rectangle(pattern_accum_get_bits_rectangle); /* The device descriptor */ @@ -165,8 +165,10 @@ static const gx_device_pattern_accum gs_pattern_accum_device = NULL, /* pop_transparency_state */ NULL, /* put_image */ NULL, /* dev_spec_op */ - pattern_accum_copy_plane, /* copy_plane */ - NULL /* get_profile */ + pattern_accum_copy_planes, /* copy_planes */ + NULL, /* get_profile */ + NULL, /* set_graphics_type_tag */ + gx_default_strip_copy_rop2 }, 0, /* target */ 0, 0, 0, 0 /* bitmap_memory, bits, mask, instance */ @@ -649,15 +651,15 @@ pattern_accum_copy_color(gx_device * dev, const byte * data, int data_x, /* Copy a color plane. */ static int -pattern_accum_copy_plane(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) +pattern_accum_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) { gx_device_pattern_accum *const padev = (gx_device_pattern_accum *) dev; if (padev->bits) - (*dev_proc(padev->target, copy_plane)) - (padev->target, data, data_x, raster, id, x, y, w, h, plane); + (*dev_proc(padev->target, copy_planes)) + (padev->target, data, data_x, raster, id, x, y, w, h, plane_height); if (padev->mask) return (*dev_proc(padev->mask, fill_rectangle)) ((gx_device *) padev->mask, x, y, w, h, (gx_color_index) 1); |