17dd7cddfSDavid du Colombier /* Copyright (C) 1998, 1999 Aladdin Enterprises. All rights reserved.
27dd7cddfSDavid du Colombier
3*593dc095SDavid du Colombier This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier implied.
57dd7cddfSDavid du Colombier
6*593dc095SDavid du Colombier This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier of the license contained in the file LICENSE in this distribution.
97dd7cddfSDavid du Colombier
10*593dc095SDavid du Colombier For more information about licensing, please refer to
11*593dc095SDavid du Colombier http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier San Rafael, CA 94903, U.S.A., +1(415)492-9861.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier
17*593dc095SDavid du Colombier /* $Id: gdevplnx.c,v 1.10 2004/08/04 19:36:12 stefan Exp $*/
187dd7cddfSDavid du Colombier /* Plane extraction device */
197dd7cddfSDavid du Colombier #include "gx.h"
207dd7cddfSDavid du Colombier #include "gserrors.h"
217dd7cddfSDavid du Colombier #include "gsbitops.h"
227dd7cddfSDavid du Colombier #include "gsrop.h" /* for logical op access */
237dd7cddfSDavid du Colombier #include "gsstruct.h"
247dd7cddfSDavid du Colombier #include "gsutil.h"
257dd7cddfSDavid du Colombier #include "gxdcolor.h"
267dd7cddfSDavid du Colombier #include "gxcmap.h" /* requires gxdcolor.h */
277dd7cddfSDavid du Colombier #include "gxdevice.h"
287dd7cddfSDavid du Colombier #include "gxdevmem.h"
297dd7cddfSDavid du Colombier #include "gxdither.h"
307dd7cddfSDavid du Colombier #include "gxgetbit.h"
317dd7cddfSDavid du Colombier #include "gxiparam.h"
327dd7cddfSDavid du Colombier #include "gxistate.h"
337dd7cddfSDavid du Colombier #include "gdevplnx.h"
347dd7cddfSDavid du Colombier
357dd7cddfSDavid du Colombier /* Define the size of the locally allocated bitmap buffers. */
367dd7cddfSDavid du Colombier #define COPY_COLOR_BUF_SIZE 100
377dd7cddfSDavid du Colombier #define TILE_RECTANGLE_BUF_SIZE 100
387dd7cddfSDavid du Colombier #define COPY_ROP_SOURCE_BUF_SIZE 100
397dd7cddfSDavid du Colombier #define COPY_ROP_TEXTURE_BUF_SIZE 100
407dd7cddfSDavid du Colombier
417dd7cddfSDavid du Colombier /* GC procedures */
427dd7cddfSDavid du Colombier private
437dd7cddfSDavid du Colombier ENUM_PTRS_WITH(device_plane_extract_enum_ptrs, gx_device_plane_extract *edev)
447dd7cddfSDavid du Colombier ENUM_PREFIX(st_device_forward, 1);
457dd7cddfSDavid du Colombier case 0: ENUM_RETURN(gx_device_enum_ptr(edev->target));
467dd7cddfSDavid du Colombier ENUM_PTRS_END
RELOC_PTRS_WITH(device_plane_extract_reloc_ptrs,gx_device_plane_extract * edev)477dd7cddfSDavid du Colombier private RELOC_PTRS_WITH(device_plane_extract_reloc_ptrs, gx_device_plane_extract *edev)
487dd7cddfSDavid du Colombier {
497dd7cddfSDavid du Colombier RELOC_PREFIX(st_device_forward);
507dd7cddfSDavid du Colombier edev->plane_dev = gx_device_reloc_ptr(edev->plane_dev, gcst);
517dd7cddfSDavid du Colombier }
527dd7cddfSDavid du Colombier RELOC_PTRS_END
537dd7cddfSDavid du Colombier public_st_device_plane_extract();
547dd7cddfSDavid du Colombier
557dd7cddfSDavid du Colombier /* Driver procedures */
567dd7cddfSDavid du Colombier private dev_proc_open_device(plane_open_device);
577dd7cddfSDavid du Colombier private dev_proc_fill_rectangle(plane_fill_rectangle);
587dd7cddfSDavid du Colombier private dev_proc_copy_mono(plane_copy_mono);
597dd7cddfSDavid du Colombier private dev_proc_copy_color(plane_copy_color);
607dd7cddfSDavid du Colombier private dev_proc_copy_alpha(plane_copy_alpha);
617dd7cddfSDavid du Colombier private dev_proc_fill_path(plane_fill_path);
627dd7cddfSDavid du Colombier private dev_proc_stroke_path(plane_stroke_path);
637dd7cddfSDavid du Colombier private dev_proc_fill_mask(plane_fill_mask);
647dd7cddfSDavid du Colombier private dev_proc_fill_parallelogram(plane_fill_parallelogram);
657dd7cddfSDavid du Colombier private dev_proc_fill_triangle(plane_fill_triangle);
667dd7cddfSDavid du Colombier private dev_proc_strip_tile_rectangle(plane_strip_tile_rectangle);
677dd7cddfSDavid du Colombier private dev_proc_strip_copy_rop(plane_strip_copy_rop);
687dd7cddfSDavid du Colombier private dev_proc_begin_typed_image(plane_begin_typed_image);
697dd7cddfSDavid du Colombier private dev_proc_get_bits_rectangle(plane_get_bits_rectangle);
707dd7cddfSDavid du Colombier
717dd7cddfSDavid du Colombier /* Device prototype */
727dd7cddfSDavid du Colombier private const gx_device_plane_extract gs_plane_extract_device = {
737dd7cddfSDavid du Colombier std_device_std_body(gx_device_plane_extract, 0, "plane_extract",
747dd7cddfSDavid du Colombier 0, 0, 72, 72),
757dd7cddfSDavid du Colombier {
767dd7cddfSDavid du Colombier plane_open_device,
777dd7cddfSDavid du Colombier NULL,
787dd7cddfSDavid du Colombier NULL,
797dd7cddfSDavid du Colombier NULL,
807dd7cddfSDavid du Colombier gx_default_close_device,
817dd7cddfSDavid du Colombier NULL,
827dd7cddfSDavid du Colombier NULL,
837dd7cddfSDavid du Colombier plane_fill_rectangle,
847dd7cddfSDavid du Colombier gx_default_tile_rectangle,
857dd7cddfSDavid du Colombier plane_copy_mono,
867dd7cddfSDavid du Colombier plane_copy_color,
877dd7cddfSDavid du Colombier gx_default_draw_line,
887dd7cddfSDavid du Colombier gx_default_get_bits,
897dd7cddfSDavid du Colombier NULL,
907dd7cddfSDavid du Colombier NULL,
917dd7cddfSDavid du Colombier NULL,
927dd7cddfSDavid du Colombier NULL,
937dd7cddfSDavid du Colombier NULL,
947dd7cddfSDavid du Colombier NULL,
957dd7cddfSDavid du Colombier NULL,
967dd7cddfSDavid du Colombier NULL,
977dd7cddfSDavid du Colombier plane_copy_alpha,
987dd7cddfSDavid du Colombier NULL,
997dd7cddfSDavid du Colombier gx_default_copy_rop,
1007dd7cddfSDavid du Colombier plane_fill_path,
1017dd7cddfSDavid du Colombier plane_stroke_path,
1027dd7cddfSDavid du Colombier plane_fill_mask,
1037dd7cddfSDavid du Colombier gx_default_fill_trapezoid,
1047dd7cddfSDavid du Colombier plane_fill_parallelogram,
1057dd7cddfSDavid du Colombier plane_fill_triangle,
1067dd7cddfSDavid du Colombier gx_default_draw_thin_line,
1077dd7cddfSDavid du Colombier gx_default_begin_image,
1087dd7cddfSDavid du Colombier gx_default_image_data,
1097dd7cddfSDavid du Colombier gx_default_end_image,
1107dd7cddfSDavid du Colombier plane_strip_tile_rectangle,
1117dd7cddfSDavid du Colombier plane_strip_copy_rop,
1127dd7cddfSDavid du Colombier NULL,
1137dd7cddfSDavid du Colombier plane_begin_typed_image,
1147dd7cddfSDavid du Colombier plane_get_bits_rectangle,
1157dd7cddfSDavid du Colombier NULL,
1167dd7cddfSDavid du Colombier gx_no_create_compositor, /* WRONG */
1177dd7cddfSDavid du Colombier NULL,
1187dd7cddfSDavid du Colombier gx_default_text_begin
1197dd7cddfSDavid du Colombier },
1207dd7cddfSDavid du Colombier /* device-specific members */
1217dd7cddfSDavid du Colombier NULL, /* target */
1227dd7cddfSDavid du Colombier NULL, /* plane_dev */
1237dd7cddfSDavid du Colombier { 0 }, /* plane */
1247dd7cddfSDavid du Colombier 0, /* plane_white */
1257dd7cddfSDavid du Colombier 0, /* plane_mask */
1267dd7cddfSDavid du Colombier 0, /* plane_dev_is_memory */
1277dd7cddfSDavid du Colombier 1 /*true*/ /* any_marks */
1287dd7cddfSDavid du Colombier };
1297dd7cddfSDavid du Colombier
1307dd7cddfSDavid du Colombier /* ---------------- Utilities ---------------- */
1317dd7cddfSDavid du Colombier
1327dd7cddfSDavid du Colombier /* Extract the selected plane from a color (gx_color_index). */
1337dd7cddfSDavid du Colombier #define COLOR_PIXEL(edev, color)\
1347dd7cddfSDavid du Colombier ( ((color) >> (edev)->plane.shift) & (edev)->plane_mask )
1357dd7cddfSDavid du Colombier /* Do the same if the color might be transparent. */
1367dd7cddfSDavid du Colombier #define TRANS_COLOR_PIXEL(edev, color)\
1377dd7cddfSDavid du Colombier ((color) == gx_no_color_index ? gx_no_color_index : COLOR_PIXEL(edev, color))
1387dd7cddfSDavid du Colombier
1397dd7cddfSDavid du Colombier /*
1407dd7cddfSDavid du Colombier * Reduce the drawing color to one for the selected plane.
1417dd7cddfSDavid du Colombier * All we care about is whether the drawing operation should be skipped.
1427dd7cddfSDavid du Colombier */
1437dd7cddfSDavid du Colombier typedef enum {
1447dd7cddfSDavid du Colombier REDUCE_SKIP,
1457dd7cddfSDavid du Colombier REDUCE_DRAW,
1467dd7cddfSDavid du Colombier REDUCE_FAILED /* couldn't reduce */
1477dd7cddfSDavid du Colombier } reduced_color_t;
1487dd7cddfSDavid du Colombier #define REDUCE_PURE(edev, pixel)\
1497dd7cddfSDavid du Colombier ((pixel) == (edev)->plane_white && !(edev)->any_marks ? REDUCE_SKIP :\
1507dd7cddfSDavid du Colombier ((edev)->any_marks = true, REDUCE_DRAW))
1517dd7cddfSDavid du Colombier private reduced_color_t
reduce_drawing_color(gx_device_color * ppdc,gx_device_plane_extract * edev,const gx_drawing_color * pdevc,gs_logical_operation_t * plop)1527dd7cddfSDavid du Colombier reduce_drawing_color(gx_device_color *ppdc, gx_device_plane_extract *edev,
1537dd7cddfSDavid du Colombier const gx_drawing_color *pdevc,
1547dd7cddfSDavid du Colombier gs_logical_operation_t *plop)
1557dd7cddfSDavid du Colombier {
1567dd7cddfSDavid du Colombier reduced_color_t reduced;
1577dd7cddfSDavid du Colombier
1587dd7cddfSDavid du Colombier if (gx_dc_is_pure(pdevc)) {
1597dd7cddfSDavid du Colombier gx_color_index pixel = COLOR_PIXEL(edev, gx_dc_pure_color(pdevc));
1607dd7cddfSDavid du Colombier
161*593dc095SDavid du Colombier set_nonclient_dev_color(ppdc, pixel);
1627dd7cddfSDavid du Colombier reduced = REDUCE_PURE(edev, pixel);
1637dd7cddfSDavid du Colombier } else if (gx_dc_is_binary_halftone(pdevc)) {
1647dd7cddfSDavid du Colombier gx_color_index pixel0 =
1657dd7cddfSDavid du Colombier TRANS_COLOR_PIXEL(edev, gx_dc_binary_color0(pdevc));
1667dd7cddfSDavid du Colombier gx_color_index pixel1 =
1677dd7cddfSDavid du Colombier TRANS_COLOR_PIXEL(edev, gx_dc_binary_color1(pdevc));
1687dd7cddfSDavid du Colombier
1697dd7cddfSDavid du Colombier if (pixel0 == pixel1) {
170*593dc095SDavid du Colombier set_nonclient_dev_color(ppdc, pixel0);
1717dd7cddfSDavid du Colombier reduced = REDUCE_PURE(edev, pixel0);
1727dd7cddfSDavid du Colombier } else {
1737dd7cddfSDavid du Colombier *ppdc = *pdevc;
1747dd7cddfSDavid du Colombier ppdc->colors.binary.color[0] = pixel0;
1757dd7cddfSDavid du Colombier ppdc->colors.binary.color[1] = pixel1;
1767dd7cddfSDavid du Colombier edev->any_marks = true;
1777dd7cddfSDavid du Colombier reduced = REDUCE_DRAW;
1787dd7cddfSDavid du Colombier }
1797dd7cddfSDavid du Colombier } else if (color_is_colored_halftone(pdevc)) {
1807dd7cddfSDavid du Colombier int plane = edev->plane.index;
1817dd7cddfSDavid du Colombier int i;
1827dd7cddfSDavid du Colombier
1837dd7cddfSDavid du Colombier *ppdc = *pdevc;
1847dd7cddfSDavid du Colombier for (i = 0; i < countof(ppdc->colors.colored.c_base); ++i)
1857dd7cddfSDavid du Colombier if (i != edev->plane.index) {
1867dd7cddfSDavid du Colombier ppdc->colors.colored.c_base[i] = 0;
1877dd7cddfSDavid du Colombier ppdc->colors.colored.c_level[i] = 0;
1887dd7cddfSDavid du Colombier }
1897dd7cddfSDavid du Colombier ppdc->colors.colored.plane_mask &= 1 << plane;
1907dd7cddfSDavid du Colombier if (ppdc->colors.colored.c_level[plane] == 0) {
191*593dc095SDavid du Colombier gx_devn_reduce_colored_halftone(ppdc, (gx_device *)edev);
1927dd7cddfSDavid du Colombier ppdc->colors.pure = COLOR_PIXEL(edev, ppdc->colors.pure);
1937dd7cddfSDavid du Colombier reduced = REDUCE_PURE(edev, gx_dc_pure_color(ppdc));
1947dd7cddfSDavid du Colombier } else if (ppdc->colors.colored.alpha != gx_max_color_value)
1957dd7cddfSDavid du Colombier return REDUCE_FAILED; /* can't reduce */
1967dd7cddfSDavid du Colombier else {
197*593dc095SDavid du Colombier gx_devn_reduce_colored_halftone(ppdc, (gx_device *)edev);
1987dd7cddfSDavid du Colombier ppdc->colors.binary.color[0] =
1997dd7cddfSDavid du Colombier COLOR_PIXEL(edev, ppdc->colors.binary.color[0]);
2007dd7cddfSDavid du Colombier ppdc->colors.binary.color[1] =
2017dd7cddfSDavid du Colombier COLOR_PIXEL(edev, ppdc->colors.binary.color[1]);
2027dd7cddfSDavid du Colombier gx_color_load(ppdc, NULL, (gx_device *)edev);
2037dd7cddfSDavid du Colombier edev->any_marks = true;
2047dd7cddfSDavid du Colombier reduced = REDUCE_DRAW;
2057dd7cddfSDavid du Colombier }
2067dd7cddfSDavid du Colombier } else
2077dd7cddfSDavid du Colombier return REDUCE_FAILED; /* can't handle it */
2087dd7cddfSDavid du Colombier if (*plop & lop_T_transparent) {
2097dd7cddfSDavid du Colombier /*
2107dd7cddfSDavid du Colombier * If the logical operation invokes transparency for the texture, we
2117dd7cddfSDavid du Colombier * must do some extra work, since a color that was originally opaque
2127dd7cddfSDavid du Colombier * may become transparent (white) if reduced to a single plane. If
2137dd7cddfSDavid du Colombier * RasterOp transparency were calculated before halftoning, life
2147dd7cddfSDavid du Colombier * would be easy: we would simply turn off texture transparency in
2157dd7cddfSDavid du Colombier * the logical operation iff the original (not reduced) color was
2167dd7cddfSDavid du Colombier * not white. Unfortunately, RasterOp transparency is calculated
2177dd7cddfSDavid du Colombier * after halftoning. (This is arguably wrong, but it's how we've
2187dd7cddfSDavid du Colombier * defined it.) Therefore, if transparency is involved with a
2197dd7cddfSDavid du Colombier * white color or a halftone that can include white, we must keep
2207dd7cddfSDavid du Colombier * the entire pixel together for the RasterOp.
2217dd7cddfSDavid du Colombier */
2227dd7cddfSDavid du Colombier gx_color_index white = gx_device_white((gx_device *)edev);
2237dd7cddfSDavid du Colombier
2247dd7cddfSDavid du Colombier /*
2257dd7cddfSDavid du Colombier * Given that we haven't failed, the only possible colors at this
2267dd7cddfSDavid du Colombier * point are pure or binary halftone.
2277dd7cddfSDavid du Colombier */
2287dd7cddfSDavid du Colombier if (gx_dc_is_pure(ppdc)) {
2297dd7cddfSDavid du Colombier if (gx_dc_pure_color(pdevc) != white)
2307dd7cddfSDavid du Colombier *plop &= ~lop_T_transparent;
2317dd7cddfSDavid du Colombier else if (!gx_dc_is_pure(pdevc))
2327dd7cddfSDavid du Colombier return REDUCE_FAILED;
2337dd7cddfSDavid du Colombier } else {
2347dd7cddfSDavid du Colombier if (gx_dc_binary_color0(pdevc) != white &&
2357dd7cddfSDavid du Colombier gx_dc_binary_color1(pdevc) != white) {
2367dd7cddfSDavid du Colombier *plop &= ~lop_T_transparent;
2377dd7cddfSDavid du Colombier } else
2387dd7cddfSDavid du Colombier return REDUCE_FAILED;
2397dd7cddfSDavid du Colombier }
2407dd7cddfSDavid du Colombier }
2417dd7cddfSDavid du Colombier return reduced;
2427dd7cddfSDavid du Colombier }
2437dd7cddfSDavid du Colombier
2447dd7cddfSDavid du Colombier /*
2457dd7cddfSDavid du Colombier * Set up to create the plane-extracted bitmap corresponding to a
2467dd7cddfSDavid du Colombier * source or halftone pixmap. If the bitmap doesn't fit in the locally
2477dd7cddfSDavid du Colombier * allocated buffer, we may either do the operation in pieces, or allocate
2487dd7cddfSDavid du Colombier * a buffer on the heap. The control structure is:
2497dd7cddfSDavid du Colombier * begin_tiling(&state, ...);
2507dd7cddfSDavid du Colombier * do {
2517dd7cddfSDavid du Colombier * extract_partial_tile(&state);
2527dd7cddfSDavid du Colombier * ... process tile in buffer ...
2537dd7cddfSDavid du Colombier * } while (next_tile(&state));
2547dd7cddfSDavid du Colombier * end_tiling(&state);
2557dd7cddfSDavid du Colombier * If partial_ok is false, there is only a single tile, so the do ... while
2567dd7cddfSDavid du Colombier * is not used.
2577dd7cddfSDavid du Colombier */
2587dd7cddfSDavid du Colombier typedef struct tiling_state_s {
2597dd7cddfSDavid du Colombier /* Save the original operands. */
2607dd7cddfSDavid du Colombier const gx_device_plane_extract *edev;
2617dd7cddfSDavid du Colombier const byte *data;
2627dd7cddfSDavid du Colombier int data_x;
2637dd7cddfSDavid du Colombier uint raster;
2647dd7cddfSDavid du Colombier int width, height;
2657dd7cddfSDavid du Colombier int dest_x; /* only for copy_color, defaults to 0 */
2667dd7cddfSDavid du Colombier /* Define the (aligned) buffer for doing the operation. */
2677dd7cddfSDavid du Colombier struct tsb_ {
2687dd7cddfSDavid du Colombier byte *data;
2697dd7cddfSDavid du Colombier uint size;
2707dd7cddfSDavid du Colombier uint raster;
2717dd7cddfSDavid du Colombier bool on_heap;
2727dd7cddfSDavid du Colombier } buffer;
2737dd7cddfSDavid du Colombier /* Record the current tile available for processing. */
2747dd7cddfSDavid du Colombier /* The client may read these out. */
2757dd7cddfSDavid du Colombier gs_int_point offset;
2767dd7cddfSDavid du Colombier gs_int_point size;
2777dd7cddfSDavid du Colombier /* Record private tiling parameters. */
2787dd7cddfSDavid du Colombier int per_tile_width;
2797dd7cddfSDavid du Colombier } tiling_state_t;
2807dd7cddfSDavid du Colombier
2817dd7cddfSDavid du Colombier /*
2827dd7cddfSDavid du Colombier * Extract the plane's data from one subrectangle of a source tile.
2837dd7cddfSDavid du Colombier */
2847dd7cddfSDavid du Colombier inline private int /* ignore the return value */
extract_partial_tile(const tiling_state_t * pts)2857dd7cddfSDavid du Colombier extract_partial_tile(const tiling_state_t *pts)
2867dd7cddfSDavid du Colombier {
2877dd7cddfSDavid du Colombier const gx_device_plane_extract * const edev = pts->edev;
2887dd7cddfSDavid du Colombier bits_plane_t dest, source;
2897dd7cddfSDavid du Colombier
2907dd7cddfSDavid du Colombier dest.data.write = pts->buffer.data + pts->offset.y * pts->buffer.raster;
2917dd7cddfSDavid du Colombier dest.raster = pts->buffer.raster;
2927dd7cddfSDavid du Colombier dest.depth = edev->plane.depth;
2937dd7cddfSDavid du Colombier dest.x = pts->dest_x;
2947dd7cddfSDavid du Colombier
2957dd7cddfSDavid du Colombier source.data.read = pts->data + pts->offset.y * pts->raster;
2967dd7cddfSDavid du Colombier source.raster = pts->raster;
2977dd7cddfSDavid du Colombier source.depth = edev->color_info.depth;
2987dd7cddfSDavid du Colombier source.x = pts->data_x + pts->offset.x;
2997dd7cddfSDavid du Colombier
3007dd7cddfSDavid du Colombier bits_extract_plane(&dest, &source, edev->plane.shift,
3017dd7cddfSDavid du Colombier pts->size.x, pts->size.y);
3027dd7cddfSDavid du Colombier return 0;
3037dd7cddfSDavid du Colombier }
3047dd7cddfSDavid du Colombier
3057dd7cddfSDavid du Colombier /*
3067dd7cddfSDavid du Colombier * Set up to start (possibly) tiling. Return 0 if the entire tile fit,
3077dd7cddfSDavid du Colombier * 1 if a partial tile fit, or a negative error code.
3087dd7cddfSDavid du Colombier */
3097dd7cddfSDavid du Colombier private int
begin_tiling(tiling_state_t * pts,gx_device_plane_extract * edev,const byte * data,int data_x,uint raster,int width,int height,byte * local_buffer,uint buffer_size,bool partial_ok)3107dd7cddfSDavid du Colombier begin_tiling(tiling_state_t *pts, gx_device_plane_extract *edev,
3117dd7cddfSDavid du Colombier const byte *data, int data_x, uint raster, int width, int height,
3127dd7cddfSDavid du Colombier byte *local_buffer, uint buffer_size, bool partial_ok)
3137dd7cddfSDavid du Colombier {
3147dd7cddfSDavid du Colombier uint width_raster =
3157dd7cddfSDavid du Colombier bitmap_raster(width * edev->plane_dev->color_info.depth);
3167dd7cddfSDavid du Colombier uint full_size = width_raster * height;
3177dd7cddfSDavid du Colombier
3187dd7cddfSDavid du Colombier pts->edev = edev;
3197dd7cddfSDavid du Colombier pts->data = data, pts->data_x = data_x, pts->raster = raster;
3207dd7cddfSDavid du Colombier pts->width = width, pts->height = height;
3217dd7cddfSDavid du Colombier pts->dest_x = 0;
3227dd7cddfSDavid du Colombier if (full_size <= buffer_size) {
3237dd7cddfSDavid du Colombier pts->buffer.data = local_buffer;
3247dd7cddfSDavid du Colombier pts->buffer.size = buffer_size;
3257dd7cddfSDavid du Colombier pts->buffer.raster = width_raster;
3267dd7cddfSDavid du Colombier pts->buffer.on_heap = false;
3277dd7cddfSDavid du Colombier pts->size.x = width, pts->size.y = height;
3287dd7cddfSDavid du Colombier } else if (partial_ok) {
3297dd7cddfSDavid du Colombier pts->buffer.data = local_buffer;
3307dd7cddfSDavid du Colombier pts->buffer.size = buffer_size;
3317dd7cddfSDavid du Colombier pts->buffer.on_heap = false;
3327dd7cddfSDavid du Colombier if (buffer_size >= width_raster) {
3337dd7cddfSDavid du Colombier pts->buffer.raster = width_raster;
3347dd7cddfSDavid du Colombier pts->size.x = width;
3357dd7cddfSDavid du Colombier pts->size.y = buffer_size / width_raster;
3367dd7cddfSDavid du Colombier } else {
3377dd7cddfSDavid du Colombier pts->buffer.raster = buffer_size & -align_bitmap_mod;
3387dd7cddfSDavid du Colombier pts->size.x =
3397dd7cddfSDavid du Colombier pts->buffer.raster * (8 / edev->plane_dev->color_info.depth);
3407dd7cddfSDavid du Colombier pts->size.y = 1;
3417dd7cddfSDavid du Colombier }
3427dd7cddfSDavid du Colombier } else {
3437dd7cddfSDavid du Colombier pts->buffer.data =
3447dd7cddfSDavid du Colombier gs_alloc_bytes(edev->memory, full_size, "begin_tiling");
3457dd7cddfSDavid du Colombier if (!pts->buffer.data)
3467dd7cddfSDavid du Colombier return_error(gs_error_VMerror);
3477dd7cddfSDavid du Colombier pts->buffer.size = full_size;
3487dd7cddfSDavid du Colombier pts->buffer.raster = width_raster;
3497dd7cddfSDavid du Colombier pts->buffer.on_heap = true;
3507dd7cddfSDavid du Colombier pts->size.x = width, pts->size.y = height;
3517dd7cddfSDavid du Colombier }
3527dd7cddfSDavid du Colombier pts->buffer.raster = width_raster;
3537dd7cddfSDavid du Colombier pts->offset.x = pts->offset.y = 0;
3547dd7cddfSDavid du Colombier pts->per_tile_width = pts->size.x;
3557dd7cddfSDavid du Colombier return pts->buffer.size < full_size;
3567dd7cddfSDavid du Colombier }
3577dd7cddfSDavid du Colombier
3587dd7cddfSDavid du Colombier /*
3597dd7cddfSDavid du Colombier * Advance to the next tile. Return true if there are more tiles to do.
3607dd7cddfSDavid du Colombier */
3617dd7cddfSDavid du Colombier private bool
next_tile(tiling_state_t * pts)3627dd7cddfSDavid du Colombier next_tile(tiling_state_t *pts)
3637dd7cddfSDavid du Colombier {
3647dd7cddfSDavid du Colombier if ((pts->offset.x += pts->size.x) >= pts->width) {
3657dd7cddfSDavid du Colombier if ((pts->offset.y += pts->size.y) >= pts->height)
3667dd7cddfSDavid du Colombier return false;
3677dd7cddfSDavid du Colombier pts->offset.x = 0;
3687dd7cddfSDavid du Colombier pts->size.x = pts->per_tile_width;
3697dd7cddfSDavid du Colombier if (pts->offset.y + pts->size.y >= pts->height)
3707dd7cddfSDavid du Colombier pts->size.y = pts->height - pts->offset.y;
3717dd7cddfSDavid du Colombier } else if (pts->offset.x + pts->size.x >= pts->width)
3727dd7cddfSDavid du Colombier pts->size.x = pts->width - pts->offset.x;
3737dd7cddfSDavid du Colombier return true;
3747dd7cddfSDavid du Colombier }
3757dd7cddfSDavid du Colombier
3767dd7cddfSDavid du Colombier /*
3777dd7cddfSDavid du Colombier * Finish tiling by freeing the buffer if necessary.
3787dd7cddfSDavid du Colombier */
3797dd7cddfSDavid du Colombier private void
end_tiling(tiling_state_t * pts)3807dd7cddfSDavid du Colombier end_tiling(tiling_state_t *pts)
3817dd7cddfSDavid du Colombier {
3827dd7cddfSDavid du Colombier if (pts->buffer.on_heap)
3837dd7cddfSDavid du Colombier gs_free_object(pts->edev->memory, pts->buffer.data, "end_tiling");
3847dd7cddfSDavid du Colombier }
3857dd7cddfSDavid du Colombier
3867dd7cddfSDavid du Colombier /* ---------------- Initialization ---------------- */
3877dd7cddfSDavid du Colombier
3887dd7cddfSDavid du Colombier int
plane_device_init(gx_device_plane_extract * edev,gx_device * target,gx_device * plane_dev,const gx_render_plane_t * render_plane,bool clear)3897dd7cddfSDavid du Colombier plane_device_init(gx_device_plane_extract *edev, gx_device *target,
3907dd7cddfSDavid du Colombier gx_device *plane_dev, const gx_render_plane_t *render_plane, bool clear)
3917dd7cddfSDavid du Colombier {
3927dd7cddfSDavid du Colombier /* Check for compatibility of the plane specification. */
3937dd7cddfSDavid du Colombier if (render_plane->depth > plane_dev->color_info.depth)
3947dd7cddfSDavid du Colombier return_error(gs_error_rangecheck);
3957dd7cddfSDavid du Colombier gx_device_init((gx_device *)edev,
3967dd7cddfSDavid du Colombier (const gx_device *)&gs_plane_extract_device,
3977dd7cddfSDavid du Colombier edev->memory, true);
398*593dc095SDavid du Colombier check_device_separable((gx_device *)edev);
3997dd7cddfSDavid du Colombier gx_device_forward_fill_in_procs((gx_device_forward *)edev);
4007dd7cddfSDavid du Colombier gx_device_set_target((gx_device_forward *)edev, target);
4017dd7cddfSDavid du Colombier gx_device_copy_params((gx_device *)edev, target);
4027dd7cddfSDavid du Colombier edev->plane_dev = plane_dev;
4037dd7cddfSDavid du Colombier edev->plane = *render_plane;
4047dd7cddfSDavid du Colombier plane_open_device((gx_device *)edev);
4057dd7cddfSDavid du Colombier if (clear) {
4067dd7cddfSDavid du Colombier dev_proc(plane_dev, fill_rectangle)
4077dd7cddfSDavid du Colombier (plane_dev, 0, 0, plane_dev->width, plane_dev->height,
4087dd7cddfSDavid du Colombier edev->plane_white);
4097dd7cddfSDavid du Colombier edev->any_marks = false;
4107dd7cddfSDavid du Colombier }
4117dd7cddfSDavid du Colombier return 0;
4127dd7cddfSDavid du Colombier }
4137dd7cddfSDavid du Colombier
4147dd7cddfSDavid du Colombier /* ---------------- Driver procedures ---------------- */
4157dd7cddfSDavid du Colombier
4167dd7cddfSDavid du Colombier private int
plane_open_device(gx_device * dev)4177dd7cddfSDavid du Colombier plane_open_device(gx_device *dev)
4187dd7cddfSDavid du Colombier {
4197dd7cddfSDavid du Colombier gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
4207dd7cddfSDavid du Colombier gx_device * const plane_dev = edev->plane_dev;
4217dd7cddfSDavid du Colombier int plane_depth = plane_dev->color_info.depth;
4227dd7cddfSDavid du Colombier const gx_device_memory * const mdproto =
4237dd7cddfSDavid du Colombier gdev_mem_device_for_bits(plane_depth);
4247dd7cddfSDavid du Colombier
4257dd7cddfSDavid du Colombier edev->plane_white = gx_device_white(plane_dev);
4267dd7cddfSDavid du Colombier edev->plane_mask = (1 << plane_depth) - 1;
4277dd7cddfSDavid du Colombier edev->plane_dev_is_memory = mdproto != 0 &&
4287dd7cddfSDavid du Colombier dev_proc(plane_dev, copy_color) == dev_proc(mdproto, copy_color);
4297dd7cddfSDavid du Colombier /* We don't set or clear any_marks here: see ...init above. */
4307dd7cddfSDavid du Colombier return 0;
4317dd7cddfSDavid du Colombier }
4327dd7cddfSDavid du Colombier
4337dd7cddfSDavid du Colombier private int
plane_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)4347dd7cddfSDavid du Colombier plane_fill_rectangle(gx_device *dev,
4357dd7cddfSDavid du Colombier int x, int y, int w, int h, gx_color_index color)
4367dd7cddfSDavid du Colombier {
4377dd7cddfSDavid du Colombier gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
4387dd7cddfSDavid du Colombier gx_device * const plane_dev = edev->plane_dev;
4397dd7cddfSDavid du Colombier gx_color_index pixel = COLOR_PIXEL(edev, color);
4407dd7cddfSDavid du Colombier
4417dd7cddfSDavid du Colombier if (pixel != edev->plane_white)
4427dd7cddfSDavid du Colombier edev->any_marks = true;
4437dd7cddfSDavid du Colombier else if (!edev->any_marks)
4447dd7cddfSDavid du Colombier return 0;
4457dd7cddfSDavid du Colombier return dev_proc(plane_dev, fill_rectangle)
4467dd7cddfSDavid du Colombier (plane_dev, x, y, w, h, pixel);
4477dd7cddfSDavid du Colombier }
4487dd7cddfSDavid du Colombier
4497dd7cddfSDavid du Colombier private int
plane_copy_mono(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index color0,gx_color_index color1)4507dd7cddfSDavid du Colombier plane_copy_mono(gx_device *dev,
4517dd7cddfSDavid du Colombier const byte *data, int data_x, int raster, gx_bitmap_id id,
4527dd7cddfSDavid du Colombier int x, int y, int w, int h,
4537dd7cddfSDavid du Colombier gx_color_index color0, gx_color_index color1)
4547dd7cddfSDavid du Colombier {
4557dd7cddfSDavid du Colombier gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
4567dd7cddfSDavid du Colombier gx_device * const plane_dev = edev->plane_dev;
4577dd7cddfSDavid du Colombier gx_color_index pixel0 = TRANS_COLOR_PIXEL(edev, color0);
4587dd7cddfSDavid du Colombier gx_color_index pixel1 = TRANS_COLOR_PIXEL(edev, color1);
4597dd7cddfSDavid du Colombier
4607dd7cddfSDavid du Colombier if (pixel0 == pixel1)
4617dd7cddfSDavid du Colombier return plane_fill_rectangle(dev, x, y, w, h, color0);
4627dd7cddfSDavid du Colombier if ((pixel0 == edev->plane_white || pixel0 == gx_no_color_index) &&
4637dd7cddfSDavid du Colombier (pixel1 == edev->plane_white || pixel1 == gx_no_color_index)) {
4647dd7cddfSDavid du Colombier /* This operation will only write white. */
4657dd7cddfSDavid du Colombier if (!edev->any_marks)
4667dd7cddfSDavid du Colombier return 0;
4677dd7cddfSDavid du Colombier } else
4687dd7cddfSDavid du Colombier edev->any_marks = true;
4697dd7cddfSDavid du Colombier return dev_proc(plane_dev, copy_mono)
4707dd7cddfSDavid du Colombier (plane_dev, data, data_x, raster, id, x, y, w, h, pixel0, pixel1);
4717dd7cddfSDavid du Colombier }
4727dd7cddfSDavid du Colombier
4737dd7cddfSDavid du Colombier private int
plane_copy_color(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int w,int h)4747dd7cddfSDavid du Colombier plane_copy_color(gx_device *dev,
4757dd7cddfSDavid du Colombier const byte *data, int data_x, int raster, gx_bitmap_id id,
4767dd7cddfSDavid du Colombier int x, int y, int w, int h)
4777dd7cddfSDavid du Colombier {
4787dd7cddfSDavid du Colombier gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
4797dd7cddfSDavid du Colombier gx_device * const plane_dev = edev->plane_dev;
4807dd7cddfSDavid du Colombier tiling_state_t state;
4817dd7cddfSDavid du Colombier long buf[COPY_COLOR_BUF_SIZE / sizeof(long)];
4827dd7cddfSDavid du Colombier int code;
4837dd7cddfSDavid du Colombier
4847dd7cddfSDavid du Colombier if (edev->plane_dev_is_memory) {
4857dd7cddfSDavid du Colombier /* Reduce the source directly into the plane device. */
4867dd7cddfSDavid du Colombier gx_device_memory * const mdev = (gx_device_memory *)plane_dev;
4877dd7cddfSDavid du Colombier
4887dd7cddfSDavid du Colombier fit_copy(edev, data, data_x, raster, id, x, y, w, h);
4897dd7cddfSDavid du Colombier code = begin_tiling(&state, edev, data, data_x, raster, w, h,
4907dd7cddfSDavid du Colombier scan_line_base(mdev, y), max_uint, false);
4917dd7cddfSDavid du Colombier if (code < 0)
4927dd7cddfSDavid du Colombier return code;
4937dd7cddfSDavid du Colombier state.dest_x = x;
4947dd7cddfSDavid du Colombier state.buffer.raster = mdev->raster;
4957dd7cddfSDavid du Colombier extract_partial_tile(&state);
4967dd7cddfSDavid du Colombier end_tiling(&state);
4977dd7cddfSDavid du Colombier edev->any_marks = true;
4987dd7cddfSDavid du Colombier return 0;
4997dd7cddfSDavid du Colombier }
5007dd7cddfSDavid du Colombier code = begin_tiling(&state, edev, data, data_x, raster,
5017dd7cddfSDavid du Colombier w, h, (byte *)buf, sizeof(buf), true);
5027dd7cddfSDavid du Colombier if (code < 0)
5037dd7cddfSDavid du Colombier return code;
5047dd7cddfSDavid du Colombier do {
5057dd7cddfSDavid du Colombier extract_partial_tile(&state);
5067dd7cddfSDavid du Colombier code = dev_proc(plane_dev, copy_color)
5077dd7cddfSDavid du Colombier (plane_dev, state.buffer.data, 0, state.buffer.raster,
5087dd7cddfSDavid du Colombier gx_no_bitmap_id, x + state.offset.x, y + state.offset.y,
5097dd7cddfSDavid du Colombier state.size.x, state.size.y);
5107dd7cddfSDavid du Colombier } while (code >= 0 && next_tile(&state));
5117dd7cddfSDavid du Colombier end_tiling(&state);
5127dd7cddfSDavid du Colombier edev->any_marks = true;
5137dd7cddfSDavid du Colombier return code;
5147dd7cddfSDavid du Colombier }
5157dd7cddfSDavid du Colombier
5167dd7cddfSDavid du Colombier private int
plane_copy_alpha(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index color,int depth)5177dd7cddfSDavid du Colombier plane_copy_alpha(gx_device *dev, const byte *data, int data_x,
5187dd7cddfSDavid du Colombier int raster, gx_bitmap_id id, int x, int y, int w, int h,
5197dd7cddfSDavid du Colombier gx_color_index color, int depth)
5207dd7cddfSDavid du Colombier {
5217dd7cddfSDavid du Colombier gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
5227dd7cddfSDavid du Colombier gx_device * const plane_dev = edev->plane_dev;
5237dd7cddfSDavid du Colombier gx_color_index pixel = COLOR_PIXEL(edev, color);
5247dd7cddfSDavid du Colombier
5257dd7cddfSDavid du Colombier if (pixel != edev->plane_white)
5267dd7cddfSDavid du Colombier edev->any_marks = true;
5277dd7cddfSDavid du Colombier else if (!edev->any_marks)
5287dd7cddfSDavid du Colombier return 0;
5297dd7cddfSDavid du Colombier return dev_proc(plane_dev, copy_alpha)
5307dd7cddfSDavid du Colombier (plane_dev, data, data_x, raster, id, x, y, w, h, pixel, depth);
5317dd7cddfSDavid du Colombier }
5327dd7cddfSDavid du Colombier
5337dd7cddfSDavid du Colombier private int
plane_fill_path(gx_device * dev,const gs_imager_state * pis,gx_path * ppath,const gx_fill_params * params,const gx_drawing_color * pdevc,const gx_clip_path * pcpath)5347dd7cddfSDavid du Colombier plane_fill_path(gx_device *dev,
5357dd7cddfSDavid du Colombier const gs_imager_state *pis, gx_path *ppath,
5367dd7cddfSDavid du Colombier const gx_fill_params *params,
5377dd7cddfSDavid du Colombier const gx_drawing_color *pdevc, const gx_clip_path *pcpath)
5387dd7cddfSDavid du Colombier {
5397dd7cddfSDavid du Colombier gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
5407dd7cddfSDavid du Colombier gx_device * const plane_dev = edev->plane_dev;
5417dd7cddfSDavid du Colombier gs_logical_operation_t lop_orig =
5427dd7cddfSDavid du Colombier gs_current_logical_op((const gs_state *)pis);
5437dd7cddfSDavid du Colombier gs_logical_operation_t lop = lop_orig;
5447dd7cddfSDavid du Colombier gx_device_color dcolor;
5457dd7cddfSDavid du Colombier
5467dd7cddfSDavid du Colombier switch (reduce_drawing_color(&dcolor, edev, pdevc, &lop)) {
5477dd7cddfSDavid du Colombier case REDUCE_SKIP:
5487dd7cddfSDavid du Colombier return 0;
5497dd7cddfSDavid du Colombier case REDUCE_DRAW: {
5507dd7cddfSDavid du Colombier gs_imager_state lopis;
5517dd7cddfSDavid du Colombier const gs_imager_state *pis_draw = pis;
5527dd7cddfSDavid du Colombier
5537dd7cddfSDavid du Colombier if (lop != lop_orig) {
5547dd7cddfSDavid du Colombier lopis = *pis;
5557dd7cddfSDavid du Colombier gs_set_logical_op((gs_state *)&lopis, lop);
5567dd7cddfSDavid du Colombier pis_draw = &lopis;
5577dd7cddfSDavid du Colombier }
5587dd7cddfSDavid du Colombier return dev_proc(plane_dev, fill_path)
5597dd7cddfSDavid du Colombier (plane_dev, pis_draw, ppath, params, &dcolor, pcpath);
5607dd7cddfSDavid du Colombier }
5617dd7cddfSDavid du Colombier default /*REDUCE_FAILED*/:
5627dd7cddfSDavid du Colombier return gx_default_fill_path(dev, pis, ppath, params, pdevc, pcpath);
5637dd7cddfSDavid du Colombier }
5647dd7cddfSDavid du Colombier }
5657dd7cddfSDavid du Colombier
5667dd7cddfSDavid du Colombier private int
plane_stroke_path(gx_device * dev,const gs_imager_state * pis,gx_path * ppath,const gx_stroke_params * params,const gx_drawing_color * pdevc,const gx_clip_path * pcpath)5677dd7cddfSDavid du Colombier plane_stroke_path(gx_device *dev,
5687dd7cddfSDavid du Colombier const gs_imager_state *pis, gx_path *ppath,
5697dd7cddfSDavid du Colombier const gx_stroke_params *params,
5707dd7cddfSDavid du Colombier const gx_drawing_color *pdevc, const gx_clip_path *pcpath)
5717dd7cddfSDavid du Colombier {
5727dd7cddfSDavid du Colombier gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
5737dd7cddfSDavid du Colombier gx_device * const plane_dev = edev->plane_dev;
5747dd7cddfSDavid du Colombier gs_logical_operation_t lop_orig =
5757dd7cddfSDavid du Colombier gs_current_logical_op((const gs_state *)pis);
5767dd7cddfSDavid du Colombier gs_logical_operation_t lop = lop_orig;
5777dd7cddfSDavid du Colombier gx_device_color dcolor;
5787dd7cddfSDavid du Colombier
5797dd7cddfSDavid du Colombier switch (reduce_drawing_color(&dcolor, edev, pdevc, &lop)) {
5807dd7cddfSDavid du Colombier case REDUCE_SKIP:
5817dd7cddfSDavid du Colombier return 0;
5827dd7cddfSDavid du Colombier case REDUCE_DRAW: {
5837dd7cddfSDavid du Colombier gs_imager_state lopis;
5847dd7cddfSDavid du Colombier const gs_imager_state *pis_draw = pis;
5857dd7cddfSDavid du Colombier
5867dd7cddfSDavid du Colombier if (lop != lop_orig) {
5877dd7cddfSDavid du Colombier lopis = *pis;
5887dd7cddfSDavid du Colombier gs_set_logical_op((gs_state *)&lopis, lop);
5897dd7cddfSDavid du Colombier pis_draw = &lopis;
5907dd7cddfSDavid du Colombier }
5917dd7cddfSDavid du Colombier return dev_proc(plane_dev, stroke_path)
5927dd7cddfSDavid du Colombier (plane_dev, pis_draw, ppath, params, &dcolor, pcpath);
5937dd7cddfSDavid du Colombier }
5947dd7cddfSDavid du Colombier default /*REDUCE_FAILED*/:
5957dd7cddfSDavid du Colombier return gx_default_stroke_path(dev, pis, ppath, params, pdevc, pcpath);
5967dd7cddfSDavid du Colombier }
5977dd7cddfSDavid du Colombier }
5987dd7cddfSDavid du Colombier
5997dd7cddfSDavid du Colombier private int
plane_fill_mask(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int w,int h,const gx_drawing_color * pdcolor,int depth,gs_logical_operation_t lop,const gx_clip_path * pcpath)6007dd7cddfSDavid du Colombier plane_fill_mask(gx_device *dev,
6017dd7cddfSDavid du Colombier const byte *data, int data_x, int raster, gx_bitmap_id id,
6027dd7cddfSDavid du Colombier int x, int y, int w, int h,
6037dd7cddfSDavid du Colombier const gx_drawing_color *pdcolor, int depth,
6047dd7cddfSDavid du Colombier gs_logical_operation_t lop, const gx_clip_path *pcpath)
6057dd7cddfSDavid du Colombier {
6067dd7cddfSDavid du Colombier gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
6077dd7cddfSDavid du Colombier gx_device * const plane_dev = edev->plane_dev;
6087dd7cddfSDavid du Colombier gx_device_color dcolor;
6097dd7cddfSDavid du Colombier
6107dd7cddfSDavid du Colombier switch (reduce_drawing_color(&dcolor, edev, pdcolor, &lop)) {
6117dd7cddfSDavid du Colombier case REDUCE_SKIP:
6127dd7cddfSDavid du Colombier return 0;
6137dd7cddfSDavid du Colombier case REDUCE_DRAW:
6147dd7cddfSDavid du Colombier return dev_proc(plane_dev, fill_mask)
6157dd7cddfSDavid du Colombier (plane_dev, data, data_x, raster, gx_no_bitmap_id, x, y, w, h,
6167dd7cddfSDavid du Colombier &dcolor, depth, lop, pcpath);
6177dd7cddfSDavid du Colombier default /*REDUCE_FAILED*/:
6187dd7cddfSDavid du Colombier return gx_default_fill_mask(dev, data, data_x, raster, gx_no_bitmap_id,
6197dd7cddfSDavid du Colombier x, y, w, h, &dcolor, depth, lop, pcpath);
6207dd7cddfSDavid du Colombier }
6217dd7cddfSDavid du Colombier }
6227dd7cddfSDavid du Colombier
6237dd7cddfSDavid du Colombier private int
plane_fill_parallelogram(gx_device * dev,fixed px,fixed py,fixed ax,fixed ay,fixed bx,fixed by,const gx_drawing_color * pdcolor,gs_logical_operation_t lop)6247dd7cddfSDavid du Colombier plane_fill_parallelogram(gx_device * dev,
6257dd7cddfSDavid du Colombier fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
6267dd7cddfSDavid du Colombier const gx_drawing_color * pdcolor, gs_logical_operation_t lop)
6277dd7cddfSDavid du Colombier {
6287dd7cddfSDavid du Colombier gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
6297dd7cddfSDavid du Colombier gx_device * const plane_dev = edev->plane_dev;
6307dd7cddfSDavid du Colombier gx_device_color dcolor;
6317dd7cddfSDavid du Colombier
6327dd7cddfSDavid du Colombier switch (reduce_drawing_color(&dcolor, edev, pdcolor, &lop)) {
6337dd7cddfSDavid du Colombier case REDUCE_SKIP:
6347dd7cddfSDavid du Colombier return 0;
6357dd7cddfSDavid du Colombier case REDUCE_DRAW:
6367dd7cddfSDavid du Colombier return dev_proc(plane_dev, fill_parallelogram)
6377dd7cddfSDavid du Colombier (plane_dev, px, py, ax, ay, bx, by, &dcolor, lop);
6387dd7cddfSDavid du Colombier default /*REDUCE_FAILED*/:
6397dd7cddfSDavid du Colombier return gx_default_fill_parallelogram(dev, px, py, ax, ay, bx, by,
6407dd7cddfSDavid du Colombier pdcolor, lop);
6417dd7cddfSDavid du Colombier }
6427dd7cddfSDavid du Colombier }
6437dd7cddfSDavid du Colombier
6447dd7cddfSDavid du Colombier private int
plane_fill_triangle(gx_device * dev,fixed px,fixed py,fixed ax,fixed ay,fixed bx,fixed by,const gx_drawing_color * pdcolor,gs_logical_operation_t lop)6457dd7cddfSDavid du Colombier plane_fill_triangle(gx_device * dev,
6467dd7cddfSDavid du Colombier fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
6477dd7cddfSDavid du Colombier const gx_drawing_color * pdcolor, gs_logical_operation_t lop)
6487dd7cddfSDavid du Colombier {
6497dd7cddfSDavid du Colombier gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
6507dd7cddfSDavid du Colombier gx_device * const plane_dev = edev->plane_dev;
6517dd7cddfSDavid du Colombier gx_device_color dcolor;
6527dd7cddfSDavid du Colombier
6537dd7cddfSDavid du Colombier switch (reduce_drawing_color(&dcolor, edev, pdcolor, &lop)) {
6547dd7cddfSDavid du Colombier case REDUCE_SKIP:
6557dd7cddfSDavid du Colombier return 0;
6567dd7cddfSDavid du Colombier case REDUCE_DRAW:
6577dd7cddfSDavid du Colombier return dev_proc(plane_dev, fill_triangle)
6587dd7cddfSDavid du Colombier (plane_dev, px, py, ax, ay, bx, by, &dcolor, lop);
6597dd7cddfSDavid du Colombier default /*REDUCE_FAILED*/:
6607dd7cddfSDavid du Colombier return gx_default_fill_triangle(dev, px, py, ax, ay, bx, by,
6617dd7cddfSDavid du Colombier pdcolor, lop);
6627dd7cddfSDavid du Colombier }
6637dd7cddfSDavid du Colombier }
6647dd7cddfSDavid du Colombier
6657dd7cddfSDavid du Colombier private int
plane_strip_tile_rectangle(gx_device * dev,const gx_strip_bitmap * tiles,int x,int y,int w,int h,gx_color_index color0,gx_color_index color1,int phase_x,int phase_y)6667dd7cddfSDavid du Colombier plane_strip_tile_rectangle(gx_device *dev,
6677dd7cddfSDavid du Colombier const gx_strip_bitmap *tiles, int x, int y, int w, int h,
6687dd7cddfSDavid du Colombier gx_color_index color0, gx_color_index color1,
6697dd7cddfSDavid du Colombier int phase_x, int phase_y)
6707dd7cddfSDavid du Colombier {
6717dd7cddfSDavid du Colombier gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
6727dd7cddfSDavid du Colombier gx_device * const plane_dev = edev->plane_dev;
6737dd7cddfSDavid du Colombier gx_color_index pixel0 = TRANS_COLOR_PIXEL(edev, color0);
6747dd7cddfSDavid du Colombier gx_color_index pixel1 = TRANS_COLOR_PIXEL(edev, color1);
6757dd7cddfSDavid du Colombier
6767dd7cddfSDavid du Colombier if (pixel0 == pixel1) {
6777dd7cddfSDavid du Colombier if (pixel0 != gx_no_color_index)
6787dd7cddfSDavid du Colombier return plane_fill_rectangle(dev, x, y, w, h, color0);
6797dd7cddfSDavid du Colombier /* The tile is a pixmap rather than a bitmap. */
6807dd7cddfSDavid du Colombier /* We should use the default implementation if it is small.... */
6817dd7cddfSDavid du Colombier {
6827dd7cddfSDavid du Colombier gx_strip_bitmap plane_tile;
6837dd7cddfSDavid du Colombier tiling_state_t state;
6847dd7cddfSDavid du Colombier long buf[TILE_RECTANGLE_BUF_SIZE / sizeof(long)];
6857dd7cddfSDavid du Colombier int code = begin_tiling(&state, edev, tiles->data, 0, tiles->raster,
6867dd7cddfSDavid du Colombier tiles->size.x, tiles->size.y,
6877dd7cddfSDavid du Colombier (byte *)buf, sizeof(buf), false);
6887dd7cddfSDavid du Colombier
6897dd7cddfSDavid du Colombier if (code < 0)
6907dd7cddfSDavid du Colombier return gx_default_strip_tile_rectangle(dev, tiles, x, y, w, h,
6917dd7cddfSDavid du Colombier color0, color1, phase_x, phase_y);
6927dd7cddfSDavid du Colombier extract_partial_tile(&state);
6937dd7cddfSDavid du Colombier plane_tile = *tiles;
6947dd7cddfSDavid du Colombier plane_tile.data = state.buffer.data;
6957dd7cddfSDavid du Colombier plane_tile.raster = state.buffer.raster;
6967dd7cddfSDavid du Colombier plane_tile.id = gx_no_bitmap_id;
6977dd7cddfSDavid du Colombier code = dev_proc(plane_dev, strip_tile_rectangle)
6987dd7cddfSDavid du Colombier (plane_dev, &plane_tile, x, y, w, h, pixel0, pixel1,
6997dd7cddfSDavid du Colombier phase_x, phase_y);
7007dd7cddfSDavid du Colombier end_tiling(&state);
7017dd7cddfSDavid du Colombier edev->any_marks = true;
7027dd7cddfSDavid du Colombier return code;
7037dd7cddfSDavid du Colombier }
7047dd7cddfSDavid du Colombier }
7057dd7cddfSDavid du Colombier if ((pixel0 == edev->plane_white || pixel0 == gx_no_color_index) &&
7067dd7cddfSDavid du Colombier (pixel1 == edev->plane_white || pixel1 == gx_no_color_index)) {
7077dd7cddfSDavid du Colombier /* This operation will only write white. */
7087dd7cddfSDavid du Colombier if (!edev->any_marks)
7097dd7cddfSDavid du Colombier return 0;
7107dd7cddfSDavid du Colombier } else
7117dd7cddfSDavid du Colombier edev->any_marks = true;
7127dd7cddfSDavid du Colombier return dev_proc(plane_dev, strip_tile_rectangle)
7137dd7cddfSDavid du Colombier (plane_dev, tiles, x, y, w, h, pixel0, pixel1, phase_x, phase_y);
7147dd7cddfSDavid du Colombier }
7157dd7cddfSDavid du Colombier
7167dd7cddfSDavid du Colombier private int
plane_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 w,int h,int phase_x,int phase_y,gs_logical_operation_t lop)7177dd7cddfSDavid du Colombier plane_strip_copy_rop(gx_device *dev,
7187dd7cddfSDavid du Colombier const byte *sdata, int sourcex, uint sraster, gx_bitmap_id id,
7197dd7cddfSDavid du Colombier const gx_color_index *scolors,
7207dd7cddfSDavid du Colombier const gx_strip_bitmap *textures, const gx_color_index *tcolors,
7217dd7cddfSDavid du Colombier int x, int y, int w, int h,
7227dd7cddfSDavid du Colombier int phase_x, int phase_y, gs_logical_operation_t lop)
7237dd7cddfSDavid du Colombier {
7247dd7cddfSDavid du Colombier gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
7257dd7cddfSDavid du Colombier gx_device * const plane_dev = edev->plane_dev;
7267dd7cddfSDavid du Colombier gs_rop3_t rop = lop_rop(lop);
7277dd7cddfSDavid du Colombier struct crp_ {
7287dd7cddfSDavid du Colombier gx_color_index pixels[2];
7297dd7cddfSDavid du Colombier gx_color_index *colors;
7307dd7cddfSDavid du Colombier tiling_state_t state;
7317dd7cddfSDavid du Colombier } source, texture;
7327dd7cddfSDavid du Colombier long sbuf[COPY_ROP_SOURCE_BUF_SIZE / sizeof(long)];
7337dd7cddfSDavid du Colombier long tbuf[COPY_ROP_TEXTURE_BUF_SIZE / sizeof(long)];
7347dd7cddfSDavid du Colombier const byte *plane_source;
735*593dc095SDavid du Colombier uint plane_raster = 0xbaadf00d; /* Initialize against indeterminizm. */
7367dd7cddfSDavid du Colombier gx_strip_bitmap plane_texture;
737*593dc095SDavid du Colombier const gx_strip_bitmap *plane_textures = NULL;
7387dd7cddfSDavid du Colombier int code;
7397dd7cddfSDavid du Colombier
7407dd7cddfSDavid du Colombier /* We should do better than this on transparency.... */
7417dd7cddfSDavid du Colombier if (lop & (lop_S_transparent | lop_T_transparent))
7427dd7cddfSDavid du Colombier return gx_default_strip_copy_rop(dev, sdata, sourcex, sraster, id,
7437dd7cddfSDavid du Colombier scolors, textures, tcolors,
7447dd7cddfSDavid du Colombier x, y, w, h, phase_x, phase_y, lop);
7457dd7cddfSDavid du Colombier if (!rop3_uses_S(rop)) {
7467dd7cddfSDavid du Colombier sdata = 0;
7477dd7cddfSDavid du Colombier source.colors = 0;
7487dd7cddfSDavid du Colombier } else if (scolors) {
7497dd7cddfSDavid du Colombier source.pixels[0] = COLOR_PIXEL(edev, scolors[0]);
7507dd7cddfSDavid du Colombier source.pixels[1] = COLOR_PIXEL(edev, scolors[1]);
7517dd7cddfSDavid du Colombier if (source.pixels[0] == source.pixels[1])
7527dd7cddfSDavid du Colombier sdata = 0;
7537dd7cddfSDavid du Colombier source.colors = source.pixels;
7547dd7cddfSDavid du Colombier }
7557dd7cddfSDavid du Colombier else
7567dd7cddfSDavid du Colombier source.colors = 0;
7577dd7cddfSDavid du Colombier if (!rop3_uses_T(rop)) {
7587dd7cddfSDavid du Colombier textures = 0;
7597dd7cddfSDavid du Colombier texture.colors = 0;
7607dd7cddfSDavid du Colombier } else if (tcolors) {
7617dd7cddfSDavid du Colombier texture.pixels[0] = COLOR_PIXEL(edev, tcolors[0]);
7627dd7cddfSDavid du Colombier texture.pixels[1] = COLOR_PIXEL(edev, tcolors[1]);
7637dd7cddfSDavid du Colombier if (texture.pixels[0] == texture.pixels[1])
7647dd7cddfSDavid du Colombier textures = 0;
7657dd7cddfSDavid du Colombier texture.colors = texture.pixels;
7667dd7cddfSDavid du Colombier }
7677dd7cddfSDavid du Colombier else
7687dd7cddfSDavid du Colombier texture.colors = 0;
7697dd7cddfSDavid du Colombier if (sdata) {
7707dd7cddfSDavid du Colombier code = begin_tiling(&source.state, edev, sdata, sourcex, sraster, w, y,
7717dd7cddfSDavid du Colombier (byte *)sbuf, sizeof(sbuf), true);
7727dd7cddfSDavid du Colombier if (code < 0)
7737dd7cddfSDavid du Colombier return gx_default_strip_copy_rop(dev, sdata, sourcex, sraster, id,
7747dd7cddfSDavid du Colombier scolors, textures, tcolors,
7757dd7cddfSDavid du Colombier x, y, w, h, phase_x, phase_y, lop);
7767dd7cddfSDavid du Colombier plane_source = source.state.buffer.data;
7777dd7cddfSDavid du Colombier plane_raster = source.state.buffer.raster;
7787dd7cddfSDavid du Colombier } else
7797dd7cddfSDavid du Colombier plane_source = 0;
7807dd7cddfSDavid du Colombier if (textures) {
7817dd7cddfSDavid du Colombier code = begin_tiling(&texture.state, edev, textures->data, 0,
7827dd7cddfSDavid du Colombier textures->raster, textures->size.x,
7837dd7cddfSDavid du Colombier textures->size.y, (byte *)tbuf, sizeof(tbuf),
7847dd7cddfSDavid du Colombier false);
7857dd7cddfSDavid du Colombier if (code < 0) {
7867dd7cddfSDavid du Colombier if (plane_source)
7877dd7cddfSDavid du Colombier end_tiling(&source.state);
7887dd7cddfSDavid du Colombier return code;
7897dd7cddfSDavid du Colombier }
7907dd7cddfSDavid du Colombier plane_texture = *textures;
7917dd7cddfSDavid du Colombier plane_texture.data = texture.state.buffer.data;
7927dd7cddfSDavid du Colombier plane_texture.raster = texture.state.buffer.raster;
7937dd7cddfSDavid du Colombier plane_textures = &plane_texture;
7947dd7cddfSDavid du Colombier }
7957dd7cddfSDavid du Colombier if (textures)
7967dd7cddfSDavid du Colombier extract_partial_tile(&texture.state);
7977dd7cddfSDavid du Colombier do {
7987dd7cddfSDavid du Colombier if (sdata)
7997dd7cddfSDavid du Colombier extract_partial_tile(&source.state);
8007dd7cddfSDavid du Colombier code = dev_proc(plane_dev, strip_copy_rop)
8017dd7cddfSDavid du Colombier (plane_dev, plane_source, sourcex, plane_raster, gx_no_bitmap_id,
8027dd7cddfSDavid du Colombier source.colors, plane_textures, texture.colors,
8037dd7cddfSDavid du Colombier x, y, w, h, phase_x, phase_y, lop);
8047dd7cddfSDavid du Colombier } while (code >= 0 && sdata && next_tile(&source.state));
8057dd7cddfSDavid du Colombier if (textures)
8067dd7cddfSDavid du Colombier end_tiling(&texture.state);
8077dd7cddfSDavid du Colombier if (sdata)
8087dd7cddfSDavid du Colombier end_tiling(&source.state);
8097dd7cddfSDavid du Colombier return code;
8107dd7cddfSDavid du Colombier }
8117dd7cddfSDavid du Colombier
8127dd7cddfSDavid du Colombier /* ---------------- Images ---------------- */
8137dd7cddfSDavid du Colombier
8147dd7cddfSDavid du Colombier /* Define the state for image rendering. */
8157dd7cddfSDavid du Colombier typedef struct plane_image_enum_s {
8167dd7cddfSDavid du Colombier gx_image_enum_common;
8177dd7cddfSDavid du Colombier gs_memory_t *memory;
8187dd7cddfSDavid du Colombier gx_image_enum_common_t *info; /* plane device enumerator */
8197dd7cddfSDavid du Colombier const gs_imager_state *pis; /* original imager state */
8207dd7cddfSDavid du Colombier gs_imager_state *pis_image; /* modified imager state */
8217dd7cddfSDavid du Colombier } plane_image_enum_t;
8227dd7cddfSDavid du Colombier gs_private_st_suffix_add3(st_plane_image_enum, plane_image_enum_t,
8237dd7cddfSDavid du Colombier "plane_image_enum_t", plane_image_enum_enum_ptrs,
8247dd7cddfSDavid du Colombier plane_image_enum_reloc_ptrs, st_gx_image_enum_common, info, pis, pis_image);
8257dd7cddfSDavid du Colombier
8267dd7cddfSDavid du Colombier /*
8277dd7cddfSDavid du Colombier * Reduce drawing colors returned by color mapping. Note that these
8287dd7cddfSDavid du Colombier * assume that the call of reduce_drawing_color will not fail:
8297dd7cddfSDavid du Colombier * plane_begin_typed_image must ensure this.
8307dd7cddfSDavid du Colombier *
8317dd7cddfSDavid du Colombier * In the imager state passed to these procedures, the client data is
8327dd7cddfSDavid du Colombier * the plane_image_enum_t.
8337dd7cddfSDavid du Colombier */
8347dd7cddfSDavid du Colombier
8357dd7cddfSDavid du Colombier private void
plane_cmap_gray(frac gray,gx_device_color * pdc,const gs_imager_state * pis_image,gx_device * dev,gs_color_select_t select)8367dd7cddfSDavid du Colombier plane_cmap_gray(frac gray, gx_device_color * pdc,
8377dd7cddfSDavid du Colombier const gs_imager_state *pis_image, gx_device *dev, gs_color_select_t select)
8387dd7cddfSDavid du Colombier {
8397dd7cddfSDavid du Colombier const plane_image_enum_t *ppie =
8407dd7cddfSDavid du Colombier (const plane_image_enum_t *)pis_image->client_data;
8417dd7cddfSDavid du Colombier gx_device_plane_extract * const edev =
8427dd7cddfSDavid du Colombier (gx_device_plane_extract *)ppie->dev;
8437dd7cddfSDavid du Colombier gs_logical_operation_t lop = gs_current_logical_op_inline(pis_image);
8447dd7cddfSDavid du Colombier gx_device_color dcolor;
8457dd7cddfSDavid du Colombier
8467dd7cddfSDavid du Colombier gx_remap_concrete_gray(gray, &dcolor, ppie->pis,
8477dd7cddfSDavid du Colombier (gx_device *)edev, select);
8487dd7cddfSDavid du Colombier reduce_drawing_color(pdc, edev, &dcolor, &lop);
8497dd7cddfSDavid du Colombier }
8507dd7cddfSDavid du Colombier private void
plane_cmap_rgb(frac r,frac g,frac b,gx_device_color * pdc,const gs_imager_state * pis_image,gx_device * dev,gs_color_select_t select)8517dd7cddfSDavid du Colombier plane_cmap_rgb(frac r, frac g, frac b, gx_device_color * pdc,
8527dd7cddfSDavid du Colombier const gs_imager_state *pis_image, gx_device *dev, gs_color_select_t select)
8537dd7cddfSDavid du Colombier {
8547dd7cddfSDavid du Colombier const plane_image_enum_t *ppie =
8557dd7cddfSDavid du Colombier (const plane_image_enum_t *)pis_image->client_data;
8567dd7cddfSDavid du Colombier gx_device_plane_extract * const edev =
8577dd7cddfSDavid du Colombier (gx_device_plane_extract *)ppie->dev;
8587dd7cddfSDavid du Colombier gs_logical_operation_t lop = gs_current_logical_op_inline(pis_image);
8597dd7cddfSDavid du Colombier gx_device_color dcolor;
8607dd7cddfSDavid du Colombier
8617dd7cddfSDavid du Colombier gx_remap_concrete_rgb(r, g, b, &dcolor, ppie->pis,
8627dd7cddfSDavid du Colombier (gx_device *)edev, select);
8637dd7cddfSDavid du Colombier reduce_drawing_color(pdc, edev, &dcolor, &lop);
8647dd7cddfSDavid du Colombier }
8657dd7cddfSDavid du Colombier private void
plane_cmap_cmyk(frac c,frac m,frac y,frac k,gx_device_color * pdc,const gs_imager_state * pis_image,gx_device * dev,gs_color_select_t select)8667dd7cddfSDavid du Colombier plane_cmap_cmyk(frac c, frac m, frac y, frac k, gx_device_color * pdc,
8677dd7cddfSDavid du Colombier const gs_imager_state *pis_image, gx_device *dev, gs_color_select_t select)
8687dd7cddfSDavid du Colombier {
8697dd7cddfSDavid du Colombier const plane_image_enum_t *ppie =
8707dd7cddfSDavid du Colombier (const plane_image_enum_t *)pis_image->client_data;
8717dd7cddfSDavid du Colombier gx_device_plane_extract * const edev =
8727dd7cddfSDavid du Colombier (gx_device_plane_extract *)ppie->dev;
8737dd7cddfSDavid du Colombier gs_logical_operation_t lop = gs_current_logical_op_inline(pis_image);
8747dd7cddfSDavid du Colombier gx_device_color dcolor;
8757dd7cddfSDavid du Colombier
8767dd7cddfSDavid du Colombier gx_remap_concrete_cmyk(c, m, y, k, &dcolor, ppie->pis,
8777dd7cddfSDavid du Colombier (gx_device *)edev, select);
8787dd7cddfSDavid du Colombier reduce_drawing_color(pdc, edev, &dcolor, &lop);
8797dd7cddfSDavid du Colombier }
8807dd7cddfSDavid du Colombier private void
plane_cmap_rgb_alpha(frac r,frac g,frac b,frac alpha,gx_device_color * pdc,const gs_imager_state * pis_image,gx_device * dev,gs_color_select_t select)8817dd7cddfSDavid du Colombier plane_cmap_rgb_alpha(frac r, frac g, frac b, frac alpha, gx_device_color * pdc,
8827dd7cddfSDavid du Colombier const gs_imager_state *pis_image, gx_device *dev, gs_color_select_t select)
8837dd7cddfSDavid du Colombier {
8847dd7cddfSDavid du Colombier const plane_image_enum_t *ppie =
8857dd7cddfSDavid du Colombier (const plane_image_enum_t *)pis_image->client_data;
8867dd7cddfSDavid du Colombier gx_device_plane_extract * const edev =
8877dd7cddfSDavid du Colombier (gx_device_plane_extract *)ppie->dev;
8887dd7cddfSDavid du Colombier gs_logical_operation_t lop = gs_current_logical_op_inline(pis_image);
8897dd7cddfSDavid du Colombier gx_device_color dcolor;
8907dd7cddfSDavid du Colombier
8917dd7cddfSDavid du Colombier gx_remap_concrete_rgb_alpha(r, g, b, alpha, &dcolor, ppie->pis,
8927dd7cddfSDavid du Colombier (gx_device *)edev, select);
8937dd7cddfSDavid du Colombier reduce_drawing_color(pdc, edev, &dcolor, &lop);
8947dd7cddfSDavid du Colombier }
895*593dc095SDavid du Colombier private bool
plane_cmap_is_halftoned(const gs_imager_state * pis_image,gx_device * dev)896*593dc095SDavid du Colombier plane_cmap_is_halftoned(const gs_imager_state *pis_image, gx_device *dev)
897*593dc095SDavid du Colombier {
898*593dc095SDavid du Colombier return false;
899*593dc095SDavid du Colombier }
900*593dc095SDavid du Colombier
9017dd7cddfSDavid du Colombier private const gx_color_map_procs plane_color_map_procs = {
902*593dc095SDavid du Colombier plane_cmap_gray, plane_cmap_rgb, plane_cmap_cmyk, plane_cmap_rgb_alpha,
903*593dc095SDavid du Colombier NULL, NULL, plane_cmap_is_halftoned
9047dd7cddfSDavid du Colombier };
9057dd7cddfSDavid du Colombier private const gx_color_map_procs *
plane_get_cmap_procs(const gs_imager_state * pis,const gx_device * dev)9067dd7cddfSDavid du Colombier plane_get_cmap_procs(const gs_imager_state *pis, const gx_device *dev)
9077dd7cddfSDavid du Colombier {
9087dd7cddfSDavid du Colombier return &plane_color_map_procs;
9097dd7cddfSDavid du Colombier }
9107dd7cddfSDavid du Colombier
9117dd7cddfSDavid du Colombier /* Define the image processing procedures. */
9127dd7cddfSDavid du Colombier private image_enum_proc_plane_data(plane_image_plane_data);
9137dd7cddfSDavid du Colombier private image_enum_proc_end_image(plane_image_end_image);
9147dd7cddfSDavid du Colombier private const gx_image_enum_procs_t plane_image_enum_procs = {
9157dd7cddfSDavid du Colombier plane_image_plane_data, plane_image_end_image
9167dd7cddfSDavid du Colombier };
9177dd7cddfSDavid du Colombier
9187dd7cddfSDavid du Colombier private int
plane_begin_typed_image(gx_device * dev,const gs_imager_state * pis,const gs_matrix * pmat,const gs_image_common_t * pic,const gs_int_rect * prect,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath,gs_memory_t * memory,gx_image_enum_common_t ** pinfo)9197dd7cddfSDavid du Colombier plane_begin_typed_image(gx_device * dev,
9207dd7cddfSDavid du Colombier const gs_imager_state * pis, const gs_matrix * pmat,
9217dd7cddfSDavid du Colombier const gs_image_common_t * pic, const gs_int_rect * prect,
9227dd7cddfSDavid du Colombier const gx_drawing_color * pdcolor, const gx_clip_path * pcpath,
9237dd7cddfSDavid du Colombier gs_memory_t * memory, gx_image_enum_common_t ** pinfo)
9247dd7cddfSDavid du Colombier {
9257dd7cddfSDavid du Colombier /*
9267dd7cddfSDavid du Colombier * For images, we intercept the imager state's cmap_procs and apply
9277dd7cddfSDavid du Colombier * reduce_drawing_color to the colors as they are returned to the image
9287dd7cddfSDavid du Colombier * processing code. For reasons explained above, we can't do this in
9297dd7cddfSDavid du Colombier * some cases of RasterOp that include transparency.
9307dd7cddfSDavid du Colombier */
9317dd7cddfSDavid du Colombier gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
9327dd7cddfSDavid du Colombier gs_logical_operation_t lop = gs_current_logical_op((const gs_state *)pis);
9337dd7cddfSDavid du Colombier const gs_pixel_image_t *pim;
9347dd7cddfSDavid du Colombier plane_image_enum_t *info = 0;
9357dd7cddfSDavid du Colombier gs_imager_state *pis_image = 0;
9367dd7cddfSDavid du Colombier gx_device_color dcolor;
9377dd7cddfSDavid du Colombier bool uses_color = false;
9387dd7cddfSDavid du Colombier int code;
9397dd7cddfSDavid du Colombier
9407dd7cddfSDavid du Colombier /* We can only handle a limited set of image types. */
9417dd7cddfSDavid du Colombier switch (pic->type->index) {
9427dd7cddfSDavid du Colombier case 1: {
9437dd7cddfSDavid du Colombier const gs_image1_t * const pim1 = (const gs_image1_t *)pic;
9447dd7cddfSDavid du Colombier
9457dd7cddfSDavid du Colombier if (pim1->Alpha != gs_image_alpha_none)
9467dd7cddfSDavid du Colombier goto fail;
9477dd7cddfSDavid du Colombier uses_color = pim1->ImageMask;
9487dd7cddfSDavid du Colombier break;
9497dd7cddfSDavid du Colombier }
9507dd7cddfSDavid du Colombier case 3:
9517dd7cddfSDavid du Colombier case 4:
9527dd7cddfSDavid du Colombier break;
9537dd7cddfSDavid du Colombier default:
9547dd7cddfSDavid du Colombier goto fail;
9557dd7cddfSDavid du Colombier }
9567dd7cddfSDavid du Colombier pim = (const gs_pixel_image_t *)pic;
9577dd7cddfSDavid du Colombier if ((lop & lop_S_transparent) ||
9587dd7cddfSDavid du Colombier ((uses_color || pim->CombineWithColor) && (lop & lop_T_transparent))
9597dd7cddfSDavid du Colombier )
9607dd7cddfSDavid du Colombier goto fail;
9617dd7cddfSDavid du Colombier if (uses_color || (pim->CombineWithColor && lop_uses_T(lop))) {
9627dd7cddfSDavid du Colombier if (reduce_drawing_color(&dcolor, edev, pdcolor, &lop) ==
9637dd7cddfSDavid du Colombier REDUCE_FAILED)
9647dd7cddfSDavid du Colombier goto fail;
9657dd7cddfSDavid du Colombier } else {
9667dd7cddfSDavid du Colombier /*
9677dd7cddfSDavid du Colombier * The drawing color won't be used, but if RasterOp is involved,
9687dd7cddfSDavid du Colombier * it may still be accessed in some anomalous cases.
9697dd7cddfSDavid du Colombier */
970*593dc095SDavid du Colombier set_nonclient_dev_color(&dcolor, (gx_color_index)0);
9717dd7cddfSDavid du Colombier }
9727dd7cddfSDavid du Colombier info = gs_alloc_struct(memory, plane_image_enum_t, &st_plane_image_enum,
9737dd7cddfSDavid du Colombier "plane_image_begin_typed(info)");
9747dd7cddfSDavid du Colombier pis_image = gs_imager_state_copy(pis, memory);
9757dd7cddfSDavid du Colombier if (pis_image == 0 || info == 0)
9767dd7cddfSDavid du Colombier goto fail;
9777dd7cddfSDavid du Colombier *pis_image = *pis;
9787dd7cddfSDavid du Colombier pis_image->client_data = info;
9797dd7cddfSDavid du Colombier pis_image->get_cmap_procs = plane_get_cmap_procs;
9807dd7cddfSDavid du Colombier code = dev_proc(edev->plane_dev, begin_typed_image)
9817dd7cddfSDavid du Colombier (edev->plane_dev, pis_image, pmat, pic, prect,
9827dd7cddfSDavid du Colombier &dcolor, pcpath, memory, &info->info);
9837dd7cddfSDavid du Colombier if (code < 0)
9847dd7cddfSDavid du Colombier goto fail;
9857dd7cddfSDavid du Colombier *((gx_image_enum_common_t *)info) = *info->info;
9867dd7cddfSDavid du Colombier info->procs = &plane_image_enum_procs;
9877dd7cddfSDavid du Colombier info->dev = (gx_device *)edev;
988*593dc095SDavid du Colombier info->id = gs_next_ids(memory, 1);
9897dd7cddfSDavid du Colombier info->memory = memory;
9907dd7cddfSDavid du Colombier info->pis = pis;
9917dd7cddfSDavid du Colombier info->pis_image = pis_image;
9927dd7cddfSDavid du Colombier *pinfo = (gx_image_enum_common_t *)info;
9937dd7cddfSDavid du Colombier return code;
9947dd7cddfSDavid du Colombier fail:
9957dd7cddfSDavid du Colombier gs_free_object(memory, pis_image, "plane_image_begin_typed(pis_image)");
9967dd7cddfSDavid du Colombier gs_free_object(memory, info, "plane_image_begin_typed(info)");
9977dd7cddfSDavid du Colombier return gx_default_begin_typed_image(dev, pis, pmat, pic, prect,
9987dd7cddfSDavid du Colombier pdcolor, pcpath, memory, pinfo);
9997dd7cddfSDavid du Colombier }
10007dd7cddfSDavid du Colombier
10017dd7cddfSDavid du Colombier private int
plane_image_plane_data(gx_image_enum_common_t * info,const gx_image_plane_t * planes,int height,int * rows_used)10027dd7cddfSDavid du Colombier plane_image_plane_data(gx_image_enum_common_t * info,
10037dd7cddfSDavid du Colombier const gx_image_plane_t * planes, int height,
10047dd7cddfSDavid du Colombier int *rows_used)
10057dd7cddfSDavid du Colombier {
10067dd7cddfSDavid du Colombier plane_image_enum_t * const ppie = (plane_image_enum_t *)info;
10077dd7cddfSDavid du Colombier
10087dd7cddfSDavid du Colombier return gx_image_plane_data_rows(ppie->info, planes, height, rows_used);
10097dd7cddfSDavid du Colombier }
10107dd7cddfSDavid du Colombier
10117dd7cddfSDavid du Colombier private int
plane_image_end_image(gx_image_enum_common_t * info,bool draw_last)10127dd7cddfSDavid du Colombier plane_image_end_image(gx_image_enum_common_t * info, bool draw_last)
10137dd7cddfSDavid du Colombier {
10147dd7cddfSDavid du Colombier plane_image_enum_t * const ppie = (plane_image_enum_t *)info;
10157dd7cddfSDavid du Colombier int code = gx_image_end(ppie->info, draw_last);
10167dd7cddfSDavid du Colombier
10177dd7cddfSDavid du Colombier gs_free_object(ppie->memory, ppie->pis_image,
10187dd7cddfSDavid du Colombier "plane_image_end_image(pis_image)");
10197dd7cddfSDavid du Colombier gs_free_object(ppie->memory, info, "plane_image_end_image(info)");
10207dd7cddfSDavid du Colombier return code;
10217dd7cddfSDavid du Colombier }
10227dd7cddfSDavid du Colombier
10237dd7cddfSDavid du Colombier /* ---------------- Reading back bits ---------------- */
10247dd7cddfSDavid du Colombier
10257dd7cddfSDavid du Colombier private int
plane_get_bits_rectangle(gx_device * dev,const gs_int_rect * prect,gs_get_bits_params_t * params,gs_int_rect ** unread)10267dd7cddfSDavid du Colombier plane_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect,
10277dd7cddfSDavid du Colombier gs_get_bits_params_t * params, gs_int_rect ** unread)
10287dd7cddfSDavid du Colombier {
10297dd7cddfSDavid du Colombier gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
10307dd7cddfSDavid du Colombier gx_device * const plane_dev = edev->plane_dev;
10317dd7cddfSDavid du Colombier int plane_index = edev->plane.index;
10327dd7cddfSDavid du Colombier gs_get_bits_options_t options = params->options;
10337dd7cddfSDavid du Colombier gs_get_bits_params_t plane_params;
10347dd7cddfSDavid du Colombier int plane;
10357dd7cddfSDavid du Colombier int code;
10367dd7cddfSDavid du Colombier
10377dd7cddfSDavid du Colombier /*
10387dd7cddfSDavid du Colombier * The only real option that this device supports is single-plane
10397dd7cddfSDavid du Colombier * retrieval. However, for the default case of RasterOp, it must be
10407dd7cddfSDavid du Colombier * able to return chunky pixels in which the other components are
10417dd7cddfSDavid du Colombier * arbitrary (but might as well be zero).
10427dd7cddfSDavid du Colombier */
10437dd7cddfSDavid du Colombier if ((options & GB_PACKING_PLANAR) && (options & GB_SELECT_PLANES)) {
10447dd7cddfSDavid du Colombier if (params->data[plane_index] == 0)
10457dd7cddfSDavid du Colombier return gx_default_get_bits_rectangle(dev, prect, params, unread);
10467dd7cddfSDavid du Colombier /* If the caller wants any other plane(s), punt. */
10477dd7cddfSDavid du Colombier for (plane = 0; plane < dev->color_info.num_components; ++plane)
10487dd7cddfSDavid du Colombier if (plane != plane_index && params->data[plane] != 0)
10497dd7cddfSDavid du Colombier return gx_default_get_bits_rectangle(dev, prect, params, unread);
10507dd7cddfSDavid du Colombier /* Pass the request on to the plane device. */
10517dd7cddfSDavid du Colombier plane_params = *params;
10527dd7cddfSDavid du Colombier plane_params.options =
10537dd7cddfSDavid du Colombier (options & ~(GB_PACKING_ALL | GB_SELECT_PLANES)) |
10547dd7cddfSDavid du Colombier GB_PACKING_CHUNKY;
10557dd7cddfSDavid du Colombier plane_params.data[0] = params->data[plane_index];
10567dd7cddfSDavid du Colombier code = dev_proc(plane_dev, get_bits_rectangle)
10577dd7cddfSDavid du Colombier (plane_dev, prect, &plane_params, unread);
10587dd7cddfSDavid du Colombier if (code >= 0) {
10597dd7cddfSDavid du Colombier *params = plane_params;
10607dd7cddfSDavid du Colombier params->options = (params->options & ~GB_PACKING_ALL) |
10617dd7cddfSDavid du Colombier (GB_PACKING_PLANAR | GB_SELECT_PLANES);
10627dd7cddfSDavid du Colombier params->data[plane_index] = params->data[0];
10637dd7cddfSDavid du Colombier for (plane = 0; plane < dev->color_info.num_components; ++plane)
10647dd7cddfSDavid du Colombier if (plane != plane_index)
10657dd7cddfSDavid du Colombier params->data[plane] = 0;
10667dd7cddfSDavid du Colombier }
10677dd7cddfSDavid du Colombier } else if (!(~options & (GB_COLORS_NATIVE | GB_ALPHA_NONE |
10687dd7cddfSDavid du Colombier GB_PACKING_CHUNKY | GB_RETURN_COPY |
10697dd7cddfSDavid du Colombier GB_ALIGN_STANDARD | GB_OFFSET_0 |
10707dd7cddfSDavid du Colombier GB_RASTER_STANDARD))) {
10717dd7cddfSDavid du Colombier /* Expand the plane into chunky pixels. */
10727dd7cddfSDavid du Colombier bits_plane_t dest, source;
10737dd7cddfSDavid du Colombier
10747dd7cddfSDavid du Colombier dest.data.write = params->data[0];
10757dd7cddfSDavid du Colombier dest.raster =
10767dd7cddfSDavid du Colombier bitmap_raster((prect->q.x - prect->p.x) * dev->color_info.depth);
10777dd7cddfSDavid du Colombier dest.depth = edev->color_info.depth;
10787dd7cddfSDavid du Colombier dest.x = 0;
10797dd7cddfSDavid du Colombier
10807dd7cddfSDavid du Colombier /* not source.data, source.raster, source.x */
10817dd7cddfSDavid du Colombier source.depth = plane_dev->color_info.depth;
10827dd7cddfSDavid du Colombier
10837dd7cddfSDavid du Colombier plane_params = *params;
10847dd7cddfSDavid du Colombier plane_params.options = options &=
10857dd7cddfSDavid du Colombier (~(GB_COLORS_ALL | GB_ALPHA_ALL | GB_PACKING_ALL |
10867dd7cddfSDavid du Colombier GB_RETURN_ALL | GB_ALIGN_ALL | GB_OFFSET_ALL | GB_RASTER_ALL) |
10877dd7cddfSDavid du Colombier GB_COLORS_NATIVE | GB_ALPHA_NONE | GB_PACKING_CHUNKY |
10887dd7cddfSDavid du Colombier /* Try for a pointer return the first time. */
10897dd7cddfSDavid du Colombier GB_RETURN_POINTER |
10907dd7cddfSDavid du Colombier GB_ALIGN_STANDARD |
10917dd7cddfSDavid du Colombier (GB_OFFSET_0 | GB_OFFSET_ANY) |
10927dd7cddfSDavid du Colombier (GB_RASTER_STANDARD | GB_RASTER_ANY));
10937dd7cddfSDavid du Colombier plane_params.raster = gx_device_raster(plane_dev, true);
10947dd7cddfSDavid du Colombier code = dev_proc(plane_dev, get_bits_rectangle)
10957dd7cddfSDavid du Colombier (plane_dev, prect, &plane_params, unread);
10967dd7cddfSDavid du Colombier if (code >= 0) {
10977dd7cddfSDavid du Colombier /* Success, expand the plane into pixels. */
10987dd7cddfSDavid du Colombier source.data.read = plane_params.data[0];
10997dd7cddfSDavid du Colombier source.raster = plane_params.raster;
11007dd7cddfSDavid du Colombier source.x = params->x_offset;
11017dd7cddfSDavid du Colombier code = bits_expand_plane(&dest, &source, edev->plane.shift,
11027dd7cddfSDavid du Colombier prect->q.x - prect->p.x,
11037dd7cddfSDavid du Colombier prect->q.y - prect->p.y);
11047dd7cddfSDavid du Colombier }
11057dd7cddfSDavid du Colombier params->options = (options & ~GB_RETURN_POINTER) | GB_RETURN_COPY;
11067dd7cddfSDavid du Colombier } else
11077dd7cddfSDavid du Colombier return gx_default_get_bits_rectangle(dev, prect, params, unread);
11087dd7cddfSDavid du Colombier return code;
11097dd7cddfSDavid du Colombier }
1110