summaryrefslogtreecommitdiff
path: root/gs/base/gdevdrop.c
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2011-11-14 12:19:32 +0000
committerRobin Watts <robin.watts@artifex.com>2011-11-14 18:12:20 +0000
commit96ab69c8bcc1bcf3e366b494ed099dc5b46009fe (patch)
tree4aa5b3a2f2655f896c7a3aefd1272fc6f5ae7d77 /gs/base/gdevdrop.c
parent940b007282d74686a20aa5cf434d20353680344c (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.
Diffstat (limited to 'gs/base/gdevdrop.c')
-rw-r--r--gs/base/gdevdrop.c110
1 files changed, 94 insertions, 16 deletions
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);