~ubuntu-branches/ubuntu/jaunty/ghostscript/jaunty-updates

« back to all changes in this revision

Viewing changes to base/gdevplnx.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2009-01-20 16:40:45 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090120164045-lnfhi0n30o5lwhwa
Tags: 8.64.dfsg.1~svn9377-0ubuntu1
* New upstream release (SVN rev 9377)
   o Fixes many bugs concerning PDF rendering, to make the PDF printing
     workflow correctly working.
   o Fixes long-standing bugs in many drivers, like input paper tray and
     duplex options not working for the built-in PCL 4, 5, 5c, 5e, and
     6/XL drivers, PDF input not working for bjc600, bjc800, and cups
     output devices, several options not working and uninitialized
     memory with cups output device.
   o Merged nearly all patches of the Ubuntu and Debian packages upstream.
   o Fixes LP: #317810, LP: #314439, LP: #314018.
* debian/patches/03_libpaper_support.dpatch,
  debian/patches/11_gs-cjk_font_glyph_handling_fix.dpatch,
  debian/patches/12_gs-cjk_vertical_writing_metrics_fix.dpatch,
  debian/patches/13_gs-cjk_cjkps_examples.dpatch,
  debian/patches/20_bbox_segv_fix.dpatch,
  debian/patches/21_brother_7x0_gdi_fix.dpatch,
  debian/patches/22_epsn_margin_workaround.dpatch,
  debian/patches/24_gs_man_fix.dpatch,
  debian/patches/25_toolbin_insecure_tmp_usage_fix.dpatch,
  debian/patches/26_assorted_script_fixes.dpatch,
  debian/patches/29_gs_css_fix.dpatch,
  debian/patches/30_ps2pdf_man_improvement.dpatch,
  debian/patches/31_fix-gc-sigbus.dpatch,
  debian/patches/34_ftbfs-on-hurd-fix.dpatch,
  debian/patches/35_disable_libcairo.dpatch,
  debian/patches/38_pxl-duplex.dpatch,
  debian/patches/39_pxl-resolution.dpatch,
  debian/patches/42_gs-init-ps-delaybind-fix.dpatch,
  debian/patches/45_bjc600-bjc800-pdf-input.dpatch,
  debian/patches/48_cups-output-device-pdf-duplex-uninitialized-memory-fix.dpatch,
  debian/patches/50_lips4-floating-point-exception.dpatch,
  debian/patches/52_cups-device-logging.dpatch,
  debian/patches/55_pcl-input-slot-fix.dpatch,
  debian/patches/57_pxl-input-slot-fix.dpatch,
  debian/patches/60_pxl-cups-driver-pdf.dpatch,
  debian/patches/62_onebitcmyk-pdf.dpatch,
  debian/patches/65_too-big-temp-files-1.dpatch,
  debian/patches/67_too-big-temp-files-2.dpatch,
  debian/patches/70_take-into-account-data-in-stream-buffer-before-refill.dpatch:
  Removed, applied upstream.
* debian/patches/01_docdir_fix_for_debian.dpatch,
  debian/patches/02_gs_man_fix_debian.dpatch,
  debian/patches/01_docdir-fix-for-debian.dpatch,
  debian/patches/02_docdir-fix-for-debian.dpatch: Renamed patches to
  make merging with Debian easier.
* debian/patches/32_improve-handling-of-media-size-changes-from-gv.dpatch, 
  debian/patches/33_bad-params-to-xinitimage-on-large-bitmaps.dpatch:
  regenerated for new source directory structure.
* debian/rules: Corrected paths to remove cidfmap (it is in Resource/Init/
  in GS 8.64) and to install headers (source paths are psi/ and base/ now).
* debian/rules: Remove all fontmaps, as DeFoMa replaces them.
* debian/local/pdftoraster/pdftoraster.c,
  debian/local/pdftoraster/pdftoraster.convs, debian/rules: Removed
  added pdftoraster filter and use the one which comes with Ghostscript.
* debian/ghostscript.links: s/8.63/8.64/

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
 
2
   All Rights Reserved.
 
3
  
 
4
   This software is provided AS-IS with no warranty, either express or
 
5
   implied.
 
6
 
 
7
   This software is distributed under license and may not be copied, modified
 
8
   or distributed except as expressly authorized under the terms of that
 
9
   license.  Refer to licensing information at http://www.artifex.com/
 
10
   or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
 
11
   San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
 
12
*/
 
13
 
 
14
/* $Id: gdevplnx.c 8803 2008-06-24 14:16:29Z leonardo $*/
 
15
/* Plane extraction device */
 
16
#include "gx.h"
 
17
#include "gserrors.h"
 
18
#include "gsbitops.h"
 
19
#include "gsrop.h"              /* for logical op access */
 
20
#include "gsstruct.h"
 
21
#include "gsutil.h"
 
22
#include "gxdcolor.h"
 
23
#include "gxcmap.h"             /* requires gxdcolor.h */
 
24
#include "gxdevice.h"
 
25
#include "gxdevmem.h"
 
26
#include "gxdither.h"
 
27
#include "gxgetbit.h"
 
28
#include "gxiparam.h"
 
29
#include "gxistate.h"
 
30
#include "gdevplnx.h"
 
31
 
 
32
/* Define the size of the locally allocated bitmap buffers. */
 
33
#define COPY_COLOR_BUF_SIZE 100
 
34
#define TILE_RECTANGLE_BUF_SIZE 100
 
35
#define COPY_ROP_SOURCE_BUF_SIZE 100
 
36
#define COPY_ROP_TEXTURE_BUF_SIZE 100
 
37
 
 
38
/* GC procedures */
 
39
static 
 
40
ENUM_PTRS_WITH(device_plane_extract_enum_ptrs, gx_device_plane_extract *edev)
 
41
    ENUM_PREFIX(st_device_forward, 1);
 
42
case 0: ENUM_RETURN(gx_device_enum_ptr(edev->target));
 
43
ENUM_PTRS_END
 
44
static RELOC_PTRS_WITH(device_plane_extract_reloc_ptrs, gx_device_plane_extract *edev)
 
45
{
 
46
    RELOC_PREFIX(st_device_forward);
 
47
    edev->plane_dev = gx_device_reloc_ptr(edev->plane_dev, gcst);
 
48
}
 
49
RELOC_PTRS_END
 
50
public_st_device_plane_extract();
 
51
 
 
52
/* Driver procedures */
 
53
static dev_proc_open_device(plane_open_device);
 
54
static dev_proc_fill_rectangle(plane_fill_rectangle);
 
55
static dev_proc_copy_mono(plane_copy_mono);
 
56
static dev_proc_copy_color(plane_copy_color);
 
57
static dev_proc_copy_alpha(plane_copy_alpha);
 
58
static dev_proc_fill_path(plane_fill_path);
 
59
static dev_proc_stroke_path(plane_stroke_path);
 
60
static dev_proc_fill_mask(plane_fill_mask);
 
61
static dev_proc_fill_parallelogram(plane_fill_parallelogram);
 
62
static dev_proc_fill_triangle(plane_fill_triangle);
 
63
static dev_proc_strip_tile_rectangle(plane_strip_tile_rectangle);
 
64
static dev_proc_strip_copy_rop(plane_strip_copy_rop);
 
65
static dev_proc_begin_typed_image(plane_begin_typed_image);
 
66
static dev_proc_get_bits_rectangle(plane_get_bits_rectangle);
 
67
 
 
68
/* Device prototype */
 
69
static const gx_device_plane_extract gs_plane_extract_device = {
 
70
    std_device_std_body(gx_device_plane_extract, 0, "plane_extract",
 
71
                        0, 0, 72, 72),
 
72
    {
 
73
        plane_open_device,
 
74
        NULL,
 
75
        NULL,
 
76
        NULL,
 
77
        gx_default_close_device,
 
78
        NULL,
 
79
        NULL,
 
80
        plane_fill_rectangle,
 
81
        gx_default_tile_rectangle,
 
82
        plane_copy_mono,
 
83
        plane_copy_color,
 
84
        gx_default_draw_line,
 
85
        gx_default_get_bits,
 
86
        NULL,
 
87
        NULL,
 
88
        NULL,
 
89
        NULL,
 
90
        NULL,
 
91
        NULL,
 
92
        NULL,
 
93
        NULL,
 
94
        plane_copy_alpha,
 
95
        NULL,
 
96
        gx_default_copy_rop,
 
97
        plane_fill_path,
 
98
        plane_stroke_path,
 
99
        plane_fill_mask,
 
100
        gx_default_fill_trapezoid,
 
101
        plane_fill_parallelogram,
 
102
        plane_fill_triangle,
 
103
        gx_default_draw_thin_line,
 
104
        gx_default_begin_image,
 
105
        gx_default_image_data,
 
106
        gx_default_end_image,
 
107
        plane_strip_tile_rectangle,
 
108
        plane_strip_copy_rop,
 
109
        NULL,
 
110
        plane_begin_typed_image,
 
111
        plane_get_bits_rectangle,
 
112
        NULL,
 
113
        gx_no_create_compositor, /* WRONG */
 
114
        NULL,
 
115
        gx_default_text_begin
 
116
    },
 
117
    /* device-specific members */
 
118
    NULL,                               /* target */
 
119
    NULL,                               /* plane_dev */
 
120
    { 0 },                              /* plane */
 
121
    0,                                  /* plane_white */
 
122
    0,                                  /* plane_mask */
 
123
    0,                                  /* plane_dev_is_memory */
 
124
    1 /*true*/                          /* any_marks */
 
125
};
 
126
 
 
127
/* ---------------- Utilities ---------------- */
 
128
 
 
129
/* Extract the selected plane from a color (gx_color_index). */
 
130
#define COLOR_PIXEL(edev, color)\
 
131
  ( ((color) >> (edev)->plane.shift) & (edev)->plane_mask )
 
132
/* Do the same if the color might be transparent. */
 
133
#define TRANS_COLOR_PIXEL(edev, color)\
 
134
 ((color) == gx_no_color_index ? gx_no_color_index : COLOR_PIXEL(edev, color))
 
135
 
 
136
/*
 
137
 * Reduce the drawing color to one for the selected plane.
 
138
 * All we care about is whether the drawing operation should be skipped.
 
139
 */
 
140
typedef enum {
 
141
    REDUCE_SKIP,
 
142
    REDUCE_DRAW,
 
143
    REDUCE_FAILED                       /* couldn't reduce */
 
144
} reduced_color_t;
 
145
#define REDUCE_PURE(edev, pixel)\
 
146
  ((pixel) == (edev)->plane_white && !(edev)->any_marks ?  REDUCE_SKIP :\
 
147
   ((edev)->any_marks = true, REDUCE_DRAW))
 
148
static reduced_color_t
 
149
reduce_drawing_color(gx_device_color *ppdc, gx_device_plane_extract *edev,
 
150
                     const gx_drawing_color *pdevc,
 
151
                     gs_logical_operation_t *plop)
 
152
{
 
153
    reduced_color_t reduced;
 
154
 
 
155
    if (gx_dc_is_pure(pdevc)) {
 
156
        gx_color_index pixel = COLOR_PIXEL(edev, gx_dc_pure_color(pdevc));
 
157
 
 
158
        set_nonclient_dev_color(ppdc, pixel);
 
159
        reduced = REDUCE_PURE(edev, pixel);
 
160
    } else if (gx_dc_is_binary_halftone(pdevc)) {
 
161
        gx_color_index pixel0 =
 
162
            TRANS_COLOR_PIXEL(edev, gx_dc_binary_color0(pdevc));
 
163
        gx_color_index pixel1 =
 
164
            TRANS_COLOR_PIXEL(edev, gx_dc_binary_color1(pdevc));
 
165
 
 
166
        if (pixel0 == pixel1) {
 
167
            set_nonclient_dev_color(ppdc, pixel0);
 
168
            reduced = REDUCE_PURE(edev, pixel0);
 
169
        } else {
 
170
            *ppdc = *pdevc;
 
171
            ppdc->colors.binary.color[0] = pixel0;
 
172
            ppdc->colors.binary.color[1] = pixel1;
 
173
            edev->any_marks = true;
 
174
            reduced = REDUCE_DRAW;
 
175
        }
 
176
    } else if (color_is_colored_halftone(pdevc)) {
 
177
        int plane = edev->plane.index;
 
178
        int i;
 
179
 
 
180
        *ppdc = *pdevc;
 
181
        for (i = 0; i < countof(ppdc->colors.colored.c_base); ++i)
 
182
            if (i != edev->plane.index) {
 
183
                ppdc->colors.colored.c_base[i] = 0;
 
184
                ppdc->colors.colored.c_level[i] = 0;
 
185
            }
 
186
        ppdc->colors.colored.plane_mask &= 1 << plane;
 
187
        if (ppdc->colors.colored.c_level[plane] == 0) {
 
188
            gx_devn_reduce_colored_halftone(ppdc, (gx_device *)edev);
 
189
            ppdc->colors.pure = COLOR_PIXEL(edev, ppdc->colors.pure);
 
190
            reduced = REDUCE_PURE(edev, gx_dc_pure_color(ppdc));
 
191
        } else if (ppdc->colors.colored.alpha != gx_max_color_value)
 
192
            return REDUCE_FAILED; /* can't reduce */
 
193
        else {
 
194
            gx_devn_reduce_colored_halftone(ppdc, (gx_device *)edev);
 
195
            ppdc->colors.binary.color[0] =
 
196
                COLOR_PIXEL(edev, ppdc->colors.binary.color[0]);
 
197
            ppdc->colors.binary.color[1] =
 
198
                COLOR_PIXEL(edev, ppdc->colors.binary.color[1]);
 
199
            gx_color_load(ppdc, NULL, (gx_device *)edev);
 
200
            edev->any_marks = true;
 
201
            reduced = REDUCE_DRAW;
 
202
        }
 
203
    } else
 
204
        return REDUCE_FAILED;           /* can't handle it */
 
205
    if (*plop & lop_T_transparent) {
 
206
        /*
 
207
         * If the logical operation invokes transparency for the texture, we
 
208
         * must do some extra work, since a color that was originally opaque
 
209
         * may become transparent (white) if reduced to a single plane.  If
 
210
         * RasterOp transparency were calculated before halftoning, life
 
211
         * would be easy: we would simply turn off texture transparency in
 
212
         * the logical operation iff the original (not reduced) color was
 
213
         * not white.  Unfortunately, RasterOp transparency is calculated
 
214
         * after halftoning.  (This is arguably wrong, but it's how we've
 
215
         * defined it.)  Therefore, if transparency is involved with a
 
216
         * white color or a halftone that can include white, we must keep
 
217
         * the entire pixel together for the RasterOp.
 
218
         */
 
219
        gx_color_index white = gx_device_white((gx_device *)edev);
 
220
 
 
221
        /*
 
222
         * Given that we haven't failed, the only possible colors at this
 
223
         * point are pure or binary halftone.
 
224
         */
 
225
        if (gx_dc_is_pure(ppdc)) {
 
226
            if (gx_dc_pure_color(pdevc) != white)
 
227
                *plop &= ~lop_T_transparent;
 
228
            else if (!gx_dc_is_pure(pdevc))
 
229
                return REDUCE_FAILED;
 
230
        } else {
 
231
            if (gx_dc_binary_color0(pdevc) != white &&
 
232
                gx_dc_binary_color1(pdevc) != white) {
 
233
                *plop &= ~lop_T_transparent;
 
234
            } else
 
235
                return REDUCE_FAILED;
 
236
        }
 
237
    }
 
238
    return reduced;
 
239
}
 
240
 
 
241
/*
 
242
 * Set up to create the plane-extracted bitmap corresponding to a
 
243
 * source or halftone pixmap.  If the bitmap doesn't fit in the locally
 
244
 * allocated buffer, we may either do the operation in pieces, or allocate
 
245
 * a buffer on the heap.  The control structure is:
 
246
 *      begin_tiling(&state, ...);
 
247
 *      do {
 
248
 *          extract_partial_tile(&state);
 
249
 *          ... process tile in buffer ...
 
250
 *      } while (next_tile(&state));
 
251
 *      end_tiling(&state);
 
252
 * If partial_ok is false, there is only a single tile, so the do ... while
 
253
 * is not used.
 
254
 */
 
255
typedef struct tiling_state_s {
 
256
        /* Save the original operands. */
 
257
    const gx_device_plane_extract *edev;
 
258
    const byte *data;
 
259
    int data_x;
 
260
    uint raster;
 
261
    int width, height;
 
262
    int dest_x;                 /* only for copy_color, defaults to 0 */
 
263
        /* Define the (aligned) buffer for doing the operation. */
 
264
    struct tsb_ {
 
265
        byte *data;
 
266
        uint size;
 
267
        uint raster;
 
268
        bool on_heap;
 
269
    } buffer;
 
270
        /* Record the current tile available for processing. */
 
271
        /* The client may read these out. */
 
272
    gs_int_point offset;
 
273
    gs_int_point size;
 
274
        /* Record private tiling parameters. */
 
275
    int per_tile_width;
 
276
} tiling_state_t;
 
277
 
 
278
/*
 
279
 * Extract the plane's data from one subrectangle of a source tile.
 
280
 */
 
281
static inline int /* ignore the return value */
 
282
extract_partial_tile(const tiling_state_t *pts)
 
283
{
 
284
    const gx_device_plane_extract * const edev = pts->edev;
 
285
    bits_plane_t dest, source;
 
286
 
 
287
    dest.data.write = pts->buffer.data + pts->offset.y * pts->buffer.raster;
 
288
    dest.raster = pts->buffer.raster;
 
289
    dest.depth = edev->plane.depth;
 
290
    dest.x = pts->dest_x;
 
291
 
 
292
    source.data.read = pts->data + pts->offset.y * pts->raster;
 
293
    source.raster = pts->raster;
 
294
    source.depth = edev->color_info.depth;
 
295
    source.x = pts->data_x + pts->offset.x;
 
296
 
 
297
    bits_extract_plane(&dest, &source, edev->plane.shift,
 
298
                       pts->size.x, pts->size.y);
 
299
    return 0;
 
300
}
 
301
 
 
302
/*
 
303
 * Set up to start (possibly) tiling.  Return 0 if the entire tile fit,
 
304
 * 1 if a partial tile fit, or a negative error code.
 
305
 */
 
306
static int
 
307
begin_tiling(tiling_state_t *pts, gx_device_plane_extract *edev,
 
308
    const byte *data, int data_x, uint raster, int width, int height,
 
309
    byte *local_buffer, uint buffer_size, bool partial_ok)
 
310
{
 
311
    uint width_raster =
 
312
        bitmap_raster(width * edev->plane_dev->color_info.depth);
 
313
    uint full_size = width_raster * height;
 
314
 
 
315
    pts->edev = edev;
 
316
    pts->data = data, pts->data_x = data_x, pts->raster = raster;
 
317
    pts->width = width, pts->height = height;
 
318
    pts->dest_x = 0;
 
319
    if (full_size <= buffer_size) {
 
320
        pts->buffer.data = local_buffer;
 
321
        pts->buffer.size = buffer_size;
 
322
        pts->buffer.raster = width_raster;
 
323
        pts->buffer.on_heap = false;
 
324
        pts->size.x = width, pts->size.y = height;
 
325
    } else if (partial_ok) {
 
326
        pts->buffer.data = local_buffer;
 
327
        pts->buffer.size = buffer_size;
 
328
        pts->buffer.on_heap = false;
 
329
        if (buffer_size >= width_raster) {
 
330
            pts->buffer.raster = width_raster;
 
331
            pts->size.x = width;
 
332
            pts->size.y = buffer_size / width_raster;
 
333
        } else {
 
334
            pts->buffer.raster = buffer_size & -align_bitmap_mod;
 
335
            pts->size.x =
 
336
                pts->buffer.raster * (8 / edev->plane_dev->color_info.depth);
 
337
            pts->size.y = 1;
 
338
        }
 
339
    } else {
 
340
        pts->buffer.data =
 
341
            gs_alloc_bytes(edev->memory, full_size, "begin_tiling");
 
342
        if (!pts->buffer.data)
 
343
            return_error(gs_error_VMerror);
 
344
        pts->buffer.size = full_size;
 
345
        pts->buffer.raster = width_raster;
 
346
        pts->buffer.on_heap = true;
 
347
        pts->size.x = width, pts->size.y = height;
 
348
    }
 
349
    pts->buffer.raster = width_raster;
 
350
    pts->offset.x = pts->offset.y = 0;
 
351
    pts->per_tile_width = pts->size.x;
 
352
    return pts->buffer.size < full_size;
 
353
}
 
354
 
 
355
/*
 
356
 * Advance to the next tile.  Return true if there are more tiles to do.
 
357
 */
 
358
static bool
 
359
next_tile(tiling_state_t *pts)
 
360
{
 
361
    if ((pts->offset.x += pts->size.x) >= pts->width) {
 
362
        if ((pts->offset.y += pts->size.y) >= pts->height)
 
363
            return false;
 
364
        pts->offset.x = 0;
 
365
        pts->size.x = pts->per_tile_width;
 
366
        if (pts->offset.y + pts->size.y >= pts->height)
 
367
            pts->size.y = pts->height - pts->offset.y;
 
368
    } else if (pts->offset.x + pts->size.x >= pts->width)
 
369
        pts->size.x = pts->width - pts->offset.x;
 
370
    return true;
 
371
}
 
372
 
 
373
/*
 
374
 * Finish tiling by freeing the buffer if necessary.
 
375
 */
 
376
static void
 
377
end_tiling(tiling_state_t *pts)
 
378
{
 
379
    if (pts->buffer.on_heap)
 
380
        gs_free_object(pts->edev->memory, pts->buffer.data, "end_tiling");
 
381
}
 
382
 
 
383
/* ---------------- Initialization ---------------- */
 
384
 
 
385
int
 
386
plane_device_init(gx_device_plane_extract *edev, gx_device *target,
 
387
    gx_device *plane_dev, const gx_render_plane_t *render_plane, bool clear)
 
388
{
 
389
    /* Check for compatibility of the plane specification. */
 
390
    if (render_plane->depth > plane_dev->color_info.depth)
 
391
        return_error(gs_error_rangecheck);
 
392
    gx_device_init((gx_device *)edev,
 
393
                   (const gx_device *)&gs_plane_extract_device,
 
394
                   edev->memory, true);
 
395
    check_device_separable((gx_device *)edev);
 
396
    gx_device_forward_fill_in_procs((gx_device_forward *)edev);
 
397
    gx_device_set_target((gx_device_forward *)edev, target);
 
398
    gx_device_copy_params((gx_device *)edev, target);
 
399
    edev->plane_dev = plane_dev;
 
400
    edev->plane = *render_plane;
 
401
    plane_open_device((gx_device *)edev);
 
402
    if (clear) {
 
403
        dev_proc(plane_dev, fill_rectangle)
 
404
            (plane_dev, 0, 0, plane_dev->width, plane_dev->height,
 
405
             edev->plane_white);
 
406
        edev->any_marks = false;
 
407
    }
 
408
    return 0;
 
409
}
 
410
 
 
411
/* ---------------- Driver procedures ---------------- */
 
412
 
 
413
static int
 
414
plane_open_device(gx_device *dev)
 
415
{
 
416
    gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
 
417
    gx_device * const plane_dev = edev->plane_dev;
 
418
    int plane_depth = plane_dev->color_info.depth;
 
419
    const gx_device_memory * const mdproto =
 
420
        gdev_mem_device_for_bits(plane_depth);
 
421
 
 
422
    edev->plane_white = gx_device_white(plane_dev);
 
423
    edev->plane_mask = (1 << plane_depth) - 1;
 
424
    edev->plane_dev_is_memory = mdproto != 0 &&
 
425
        dev_proc(plane_dev, copy_color) == dev_proc(mdproto, copy_color);
 
426
    /* We don't set or clear any_marks here: see ...init above. */
 
427
    return 0;
 
428
}
 
429
 
 
430
static int
 
431
plane_fill_rectangle(gx_device *dev,
 
432
    int x, int y, int w, int h, gx_color_index color)
 
433
{
 
434
    gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
 
435
    gx_device * const plane_dev = edev->plane_dev;
 
436
    gx_color_index pixel = COLOR_PIXEL(edev, color);
 
437
 
 
438
    if (pixel != edev->plane_white)
 
439
        edev->any_marks = true;
 
440
    else if (!edev->any_marks)
 
441
        return 0;
 
442
    return dev_proc(plane_dev, fill_rectangle)
 
443
        (plane_dev, x, y, w, h, pixel);
 
444
}
 
445
 
 
446
static int
 
447
plane_copy_mono(gx_device *dev,
 
448
    const byte *data, int data_x, int raster, gx_bitmap_id id,
 
449
    int x, int y, int w, int h,
 
450
    gx_color_index color0, gx_color_index color1)
 
451
{
 
452
    gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
 
453
    gx_device * const plane_dev = edev->plane_dev;
 
454
    gx_color_index pixel0 = TRANS_COLOR_PIXEL(edev, color0);
 
455
    gx_color_index pixel1 = TRANS_COLOR_PIXEL(edev, color1);
 
456
 
 
457
    if (pixel0 == pixel1)
 
458
        return plane_fill_rectangle(dev, x, y, w, h, color0);
 
459
    if ((pixel0 == edev->plane_white || pixel0 == gx_no_color_index) &&
 
460
        (pixel1 == edev->plane_white || pixel1 == gx_no_color_index)) {
 
461
        /* This operation will only write white. */
 
462
        if (!edev->any_marks)
 
463
            return 0;
 
464
    } else
 
465
        edev->any_marks = true;
 
466
    return dev_proc(plane_dev, copy_mono)
 
467
        (plane_dev, data, data_x, raster, id, x, y, w, h, pixel0, pixel1);
 
468
}
 
469
 
 
470
static int
 
471
plane_copy_color(gx_device *dev,
 
472
    const byte *data, int data_x, int raster, gx_bitmap_id id,
 
473
    int x, int y, int w, int h)
 
474
{
 
475
    gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
 
476
    gx_device * const plane_dev = edev->plane_dev;
 
477
    tiling_state_t state;
 
478
    long buf[COPY_COLOR_BUF_SIZE / sizeof(long)];
 
479
    int code;
 
480
 
 
481
    if (edev->plane_dev_is_memory) {
 
482
        /* Reduce the source directly into the plane device. */
 
483
        gx_device_memory * const mdev = (gx_device_memory *)plane_dev;
 
484
 
 
485
        fit_copy(edev, data, data_x, raster, id, x, y, w, h);
 
486
        code = begin_tiling(&state, edev, data, data_x, raster, w, h,
 
487
                            scan_line_base(mdev, y), max_uint, false);
 
488
        if (code < 0)
 
489
            return code;
 
490
        state.dest_x = x;
 
491
        state.buffer.raster = mdev->raster;
 
492
        extract_partial_tile(&state);
 
493
        end_tiling(&state);
 
494
        edev->any_marks = true;
 
495
        return 0;
 
496
    }
 
497
    code = begin_tiling(&state, edev, data, data_x, raster,
 
498
                        w, h, (byte *)buf, sizeof(buf), true);
 
499
    if (code < 0)
 
500
        return code;
 
501
    do {
 
502
        extract_partial_tile(&state);
 
503
        code = dev_proc(plane_dev, copy_color)
 
504
            (plane_dev, state.buffer.data, 0, state.buffer.raster,
 
505
             gx_no_bitmap_id, x + state.offset.x, y + state.offset.y,
 
506
             state.size.x, state.size.y);
 
507
    } while (code >= 0 && next_tile(&state));
 
508
    end_tiling(&state);
 
509
    edev->any_marks = true;
 
510
    return code;
 
511
}
 
512
 
 
513
static int
 
514
plane_copy_alpha(gx_device *dev, const byte *data, int data_x,
 
515
    int raster, gx_bitmap_id id, int x, int y, int w, int h,
 
516
    gx_color_index color, int depth)
 
517
{
 
518
    gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
 
519
    gx_device * const plane_dev = edev->plane_dev;
 
520
    gx_color_index pixel = COLOR_PIXEL(edev, color);
 
521
 
 
522
    if (pixel != edev->plane_white)
 
523
        edev->any_marks = true;
 
524
    else if (!edev->any_marks)
 
525
        return 0;
 
526
    return dev_proc(plane_dev, copy_alpha)
 
527
        (plane_dev, data, data_x, raster, id, x, y, w, h, pixel, depth);
 
528
}
 
529
 
 
530
static int
 
531
plane_fill_path(gx_device *dev,
 
532
    const gs_imager_state *pis, gx_path *ppath,
 
533
    const gx_fill_params *params,
 
534
    const gx_drawing_color *pdevc, const gx_clip_path *pcpath)
 
535
{
 
536
    gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
 
537
    gx_device * const plane_dev = edev->plane_dev;
 
538
    gs_logical_operation_t lop_orig =
 
539
        gs_current_logical_op((const gs_state *)pis);
 
540
    gs_logical_operation_t lop = lop_orig;
 
541
    gx_device_color dcolor;
 
542
 
 
543
    switch (reduce_drawing_color(&dcolor, edev, pdevc, &lop)) {
 
544
    case REDUCE_SKIP:
 
545
        return 0;
 
546
    case REDUCE_DRAW: {
 
547
        gs_imager_state lopis;
 
548
        const gs_imager_state *pis_draw = pis;
 
549
 
 
550
        if (lop != lop_orig) {
 
551
            lopis = *pis;
 
552
            gs_set_logical_op((gs_state *)&lopis, lop);
 
553
            pis_draw = &lopis;
 
554
        }
 
555
        return dev_proc(plane_dev, fill_path)
 
556
            (plane_dev, pis_draw, ppath, params, &dcolor, pcpath);
 
557
    }
 
558
    default /*REDUCE_FAILED*/:
 
559
        return gx_default_fill_path(dev, pis, ppath, params, pdevc, pcpath);
 
560
    }
 
561
}
 
562
 
 
563
static int
 
564
plane_stroke_path(gx_device *dev,
 
565
    const gs_imager_state *pis, gx_path *ppath,
 
566
    const gx_stroke_params *params,
 
567
    const gx_drawing_color *pdevc, const gx_clip_path *pcpath)
 
568
{
 
569
    gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
 
570
    gx_device * const plane_dev = edev->plane_dev;
 
571
    gs_logical_operation_t lop_orig =
 
572
        gs_current_logical_op((const gs_state *)pis);
 
573
    gs_logical_operation_t lop = lop_orig;
 
574
    gx_device_color dcolor;
 
575
 
 
576
    switch (reduce_drawing_color(&dcolor, edev, pdevc, &lop)) {
 
577
    case REDUCE_SKIP:
 
578
        return 0;
 
579
    case REDUCE_DRAW: {
 
580
        gs_imager_state lopis;
 
581
        const gs_imager_state *pis_draw = pis;
 
582
 
 
583
        if (lop != lop_orig) {
 
584
            lopis = *pis;
 
585
            gs_set_logical_op((gs_state *)&lopis, lop);
 
586
            pis_draw = &lopis;
 
587
        }
 
588
        return dev_proc(plane_dev, stroke_path)
 
589
            (plane_dev, pis_draw, ppath, params, &dcolor, pcpath);
 
590
    }
 
591
    default /*REDUCE_FAILED*/:
 
592
        return gx_default_stroke_path(dev, pis, ppath, params, pdevc, pcpath);
 
593
    }
 
594
}
 
595
 
 
596
static int
 
597
plane_fill_mask(gx_device *dev,
 
598
    const byte *data, int data_x, int raster, gx_bitmap_id id,
 
599
    int x, int y, int w, int h,
 
600
    const gx_drawing_color *pdcolor, int depth,
 
601
    gs_logical_operation_t lop, const gx_clip_path *pcpath)
 
602
{
 
603
    gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
 
604
    gx_device * const plane_dev = edev->plane_dev;
 
605
    gx_device_color dcolor;
 
606
 
 
607
    switch (reduce_drawing_color(&dcolor, edev, pdcolor, &lop)) {
 
608
    case REDUCE_SKIP:
 
609
        return 0;
 
610
    case REDUCE_DRAW:
 
611
        return dev_proc(plane_dev, fill_mask)
 
612
            (plane_dev, data, data_x, raster, gx_no_bitmap_id, x, y, w, h,
 
613
             &dcolor, depth, lop, pcpath);
 
614
    default /*REDUCE_FAILED*/:
 
615
        return gx_default_fill_mask(dev, data, data_x, raster, gx_no_bitmap_id,
 
616
                                    x, y, w, h, &dcolor, depth, lop, pcpath);
 
617
    }
 
618
}
 
619
 
 
620
static int
 
621
plane_fill_parallelogram(gx_device * dev,
 
622
    fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
 
623
    const gx_drawing_color * pdcolor, gs_logical_operation_t lop)
 
624
{
 
625
    gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
 
626
    gx_device * const plane_dev = edev->plane_dev;
 
627
    gx_device_color dcolor;
 
628
 
 
629
    switch (reduce_drawing_color(&dcolor, edev, pdcolor, &lop)) {
 
630
    case REDUCE_SKIP:
 
631
        return 0;
 
632
    case REDUCE_DRAW:
 
633
        return dev_proc(plane_dev, fill_parallelogram)
 
634
            (plane_dev, px, py, ax, ay, bx, by, &dcolor, lop);
 
635
    default /*REDUCE_FAILED*/:
 
636
        return gx_default_fill_parallelogram(dev, px, py, ax, ay, bx, by,
 
637
                                             pdcolor, lop);
 
638
    }
 
639
}
 
640
 
 
641
static int
 
642
plane_fill_triangle(gx_device * dev,
 
643
    fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
 
644
    const gx_drawing_color * pdcolor, gs_logical_operation_t lop)
 
645
{
 
646
    gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
 
647
    gx_device * const plane_dev = edev->plane_dev;
 
648
    gx_device_color dcolor;
 
649
 
 
650
    switch (reduce_drawing_color(&dcolor, edev, pdcolor, &lop)) {
 
651
    case REDUCE_SKIP:
 
652
        return 0;
 
653
    case REDUCE_DRAW:
 
654
        return dev_proc(plane_dev, fill_triangle)
 
655
            (plane_dev, px, py, ax, ay, bx, by, &dcolor, lop);
 
656
    default /*REDUCE_FAILED*/:
 
657
        return gx_default_fill_triangle(dev, px, py, ax, ay, bx, by,
 
658
                                        pdcolor, lop);
 
659
    }
 
660
}
 
661
 
 
662
static int
 
663
plane_strip_tile_rectangle(gx_device *dev,
 
664
    const gx_strip_bitmap *tiles, int x, int y, int w, int h,
 
665
    gx_color_index color0, gx_color_index color1,
 
666
    int phase_x, int phase_y)
 
667
{
 
668
    gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
 
669
    gx_device * const plane_dev = edev->plane_dev;
 
670
    gx_color_index pixel0 = TRANS_COLOR_PIXEL(edev, color0);
 
671
    gx_color_index pixel1 = TRANS_COLOR_PIXEL(edev, color1);
 
672
 
 
673
    if (pixel0 == pixel1) {
 
674
        if (pixel0 != gx_no_color_index)
 
675
            return plane_fill_rectangle(dev, x, y, w, h, color0);
 
676
        /* The tile is a pixmap rather than a bitmap. */
 
677
        /* We should use the default implementation if it is small.... */
 
678
        {
 
679
            gx_strip_bitmap plane_tile;
 
680
            tiling_state_t state;
 
681
            long buf[TILE_RECTANGLE_BUF_SIZE / sizeof(long)];
 
682
            int code = begin_tiling(&state, edev, tiles->data, 0, tiles->raster,
 
683
                        tiles->size.x, tiles->size.y,
 
684
                                (byte *)buf, sizeof(buf), false);
 
685
 
 
686
            if (code < 0)
 
687
                return gx_default_strip_tile_rectangle(dev, tiles, x, y, w, h,
 
688
                                        color0, color1, phase_x, phase_y);
 
689
            extract_partial_tile(&state);
 
690
            plane_tile = *tiles;
 
691
            plane_tile.data = state.buffer.data;
 
692
            plane_tile.raster = state.buffer.raster;
 
693
            plane_tile.id = gx_no_bitmap_id;
 
694
            code = dev_proc(plane_dev, strip_tile_rectangle)
 
695
                (plane_dev, &plane_tile, x, y, w, h, pixel0, pixel1,
 
696
                 phase_x, phase_y);
 
697
            end_tiling(&state);
 
698
            edev->any_marks = true;
 
699
            return code;
 
700
        }
 
701
    }
 
702
    if ((pixel0 == edev->plane_white || pixel0 == gx_no_color_index) &&
 
703
        (pixel1 == edev->plane_white || pixel1 == gx_no_color_index)) {
 
704
        /* This operation will only write white. */
 
705
        if (!edev->any_marks)
 
706
            return 0;
 
707
    } else
 
708
        edev->any_marks = true;
 
709
    return dev_proc(plane_dev, strip_tile_rectangle)
 
710
        (plane_dev, tiles, x, y, w, h, pixel0, pixel1, phase_x, phase_y);
 
711
}
 
712
 
 
713
static int
 
714
plane_strip_copy_rop(gx_device *dev,
 
715
    const byte *sdata, int sourcex, uint sraster, gx_bitmap_id id,
 
716
    const gx_color_index *scolors,
 
717
    const gx_strip_bitmap *textures, const gx_color_index *tcolors,
 
718
    int x, int y, int w, int h,
 
719
    int phase_x, int phase_y, gs_logical_operation_t lop)
 
720
{
 
721
    gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
 
722
    gx_device * const plane_dev = edev->plane_dev;
 
723
    gs_rop3_t rop = lop_rop(lop);
 
724
    struct crp_ {
 
725
        gx_color_index pixels[2];
 
726
        gx_color_index *colors;
 
727
        tiling_state_t state;
 
728
    } source, texture;
 
729
    long sbuf[COPY_ROP_SOURCE_BUF_SIZE / sizeof(long)];
 
730
    long tbuf[COPY_ROP_TEXTURE_BUF_SIZE / sizeof(long)];
 
731
    const byte *plane_source;
 
732
    uint plane_raster = 0xbaadf00d; /* Initialize against indeterminizm. */
 
733
    gx_strip_bitmap plane_texture;
 
734
    const gx_strip_bitmap *plane_textures = NULL;
 
735
    int code;
 
736
 
 
737
    /* We should do better than this on transparency.... */
 
738
    if (lop & (lop_S_transparent | lop_T_transparent))
 
739
        return gx_default_strip_copy_rop(dev, sdata, sourcex, sraster, id,
 
740
                                         scolors, textures, tcolors,
 
741
                                         x, y, w, h, phase_x, phase_y, lop);
 
742
    if (!rop3_uses_S(rop)) {
 
743
        sdata = 0;
 
744
        source.colors = 0;
 
745
    } else if (scolors) {
 
746
        source.pixels[0] = COLOR_PIXEL(edev, scolors[0]);
 
747
        source.pixels[1] = COLOR_PIXEL(edev, scolors[1]);
 
748
        if (source.pixels[0] == source.pixels[1])
 
749
            sdata = 0;
 
750
        source.colors = source.pixels;
 
751
    }
 
752
    else
 
753
        source.colors = 0;
 
754
    if (!rop3_uses_T(rop)) {
 
755
        textures = 0;
 
756
        texture.colors = 0;
 
757
    } else if (tcolors) {
 
758
        texture.pixels[0] = COLOR_PIXEL(edev, tcolors[0]);
 
759
        texture.pixels[1] = COLOR_PIXEL(edev, tcolors[1]);
 
760
        if (texture.pixels[0] == texture.pixels[1])
 
761
            textures = 0;
 
762
        texture.colors = texture.pixels;
 
763
    }
 
764
    else
 
765
        texture.colors = 0;
 
766
    if (sdata) {
 
767
        code = begin_tiling(&source.state, edev, sdata, sourcex, sraster, w, y,
 
768
                            (byte *)sbuf, sizeof(sbuf), true);
 
769
        if (code < 0)
 
770
            return gx_default_strip_copy_rop(dev, sdata, sourcex, sraster, id,
 
771
                                             scolors, textures, tcolors,
 
772
                                             x, y, w, h, phase_x, phase_y, lop);
 
773
        plane_source = source.state.buffer.data;
 
774
        plane_raster = source.state.buffer.raster;
 
775
    } else
 
776
        plane_source = 0;
 
777
    if (textures) {
 
778
        code = begin_tiling(&texture.state, edev, textures->data, 0,
 
779
                            textures->raster, textures->size.x,
 
780
                            textures->size.y, (byte *)tbuf, sizeof(tbuf),
 
781
                            false);
 
782
        if (code < 0) {
 
783
            if (plane_source)
 
784
                end_tiling(&source.state);
 
785
            return code;
 
786
        }
 
787
        plane_texture = *textures;
 
788
        plane_texture.data = texture.state.buffer.data;
 
789
        plane_texture.raster = texture.state.buffer.raster;
 
790
        plane_textures = &plane_texture;
 
791
    }
 
792
    if (textures)
 
793
        extract_partial_tile(&texture.state);
 
794
    do {
 
795
        if (sdata)
 
796
            extract_partial_tile(&source.state);
 
797
        code = dev_proc(plane_dev, strip_copy_rop)
 
798
            (plane_dev, plane_source, sourcex, plane_raster, gx_no_bitmap_id,
 
799
             source.colors, plane_textures, texture.colors,
 
800
             x, y, w, h, phase_x, phase_y, lop);
 
801
    } while (code >= 0 && sdata && next_tile(&source.state));
 
802
    if (textures)
 
803
        end_tiling(&texture.state);
 
804
    if (sdata)
 
805
        end_tiling(&source.state);
 
806
    return code;
 
807
}
 
808
 
 
809
/* ---------------- Images ---------------- */
 
810
 
 
811
/* Define the state for image rendering. */
 
812
typedef struct plane_image_enum_s {
 
813
    gx_image_enum_common;
 
814
    gx_image_enum_common_t *info; /* plane device enumerator */
 
815
    const gs_imager_state *pis; /* original imager state */
 
816
    gs_imager_state *pis_image; /* modified imager state */
 
817
} plane_image_enum_t;
 
818
gs_private_st_suffix_add3(st_plane_image_enum, plane_image_enum_t,
 
819
  "plane_image_enum_t", plane_image_enum_enum_ptrs,
 
820
  plane_image_enum_reloc_ptrs, st_gx_image_enum_common, info, pis, pis_image);
 
821
 
 
822
/*
 
823
 * Reduce drawing colors returned by color mapping.  Note that these
 
824
 * assume that the call of reduce_drawing_color will not fail:
 
825
 * plane_begin_typed_image must ensure this.
 
826
 *
 
827
 * In the imager state passed to these procedures, the client data is
 
828
 * the plane_image_enum_t.
 
829
 */
 
830
 
 
831
static void
 
832
plane_cmap_gray(frac gray, gx_device_color * pdc,
 
833
    const gs_imager_state *pis_image, gx_device *dev, gs_color_select_t select)
 
834
{
 
835
    const plane_image_enum_t *ppie =
 
836
        (const plane_image_enum_t *)pis_image->client_data;
 
837
    gx_device_plane_extract * const edev =
 
838
        (gx_device_plane_extract *)ppie->dev;
 
839
    gs_logical_operation_t lop = gs_current_logical_op_inline(pis_image);
 
840
    gx_device_color dcolor;
 
841
 
 
842
    gx_remap_concrete_gray(gray, &dcolor, ppie->pis,
 
843
                           (gx_device *)edev, select);
 
844
    reduce_drawing_color(pdc, edev, &dcolor, &lop);
 
845
}
 
846
static void
 
847
plane_cmap_rgb(frac r, frac g, frac b, gx_device_color * pdc,
 
848
    const gs_imager_state *pis_image, gx_device *dev, gs_color_select_t select)
 
849
{
 
850
    const plane_image_enum_t *ppie =
 
851
        (const plane_image_enum_t *)pis_image->client_data;
 
852
    gx_device_plane_extract * const edev =
 
853
        (gx_device_plane_extract *)ppie->dev;
 
854
    gs_logical_operation_t lop = gs_current_logical_op_inline(pis_image);
 
855
    gx_device_color dcolor;
 
856
 
 
857
    gx_remap_concrete_rgb(r, g, b, &dcolor, ppie->pis,
 
858
                          (gx_device *)edev, select);
 
859
    reduce_drawing_color(pdc, edev, &dcolor, &lop);
 
860
}
 
861
static void
 
862
plane_cmap_cmyk(frac c, frac m, frac y, frac k, gx_device_color * pdc,
 
863
    const gs_imager_state *pis_image, gx_device *dev, gs_color_select_t select)
 
864
{
 
865
    const plane_image_enum_t *ppie =
 
866
        (const plane_image_enum_t *)pis_image->client_data;
 
867
    gx_device_plane_extract * const edev =
 
868
        (gx_device_plane_extract *)ppie->dev;
 
869
    gs_logical_operation_t lop = gs_current_logical_op_inline(pis_image);
 
870
    gx_device_color dcolor;
 
871
 
 
872
    gx_remap_concrete_cmyk(c, m, y, k, &dcolor, ppie->pis,
 
873
                           (gx_device *)edev, select);
 
874
    reduce_drawing_color(pdc, edev, &dcolor, &lop);
 
875
}
 
876
static void
 
877
plane_cmap_rgb_alpha(frac r, frac g, frac b, frac alpha, gx_device_color * pdc,
 
878
    const gs_imager_state *pis_image, gx_device *dev, gs_color_select_t select)
 
879
{
 
880
    const plane_image_enum_t *ppie =
 
881
        (const plane_image_enum_t *)pis_image->client_data;
 
882
    gx_device_plane_extract * const edev =
 
883
        (gx_device_plane_extract *)ppie->dev;
 
884
    gs_logical_operation_t lop = gs_current_logical_op_inline(pis_image);
 
885
    gx_device_color dcolor;
 
886
 
 
887
    gx_remap_concrete_rgb_alpha(r, g, b, alpha, &dcolor, ppie->pis,
 
888
                                (gx_device *)edev, select);
 
889
    reduce_drawing_color(pdc, edev, &dcolor, &lop);
 
890
}
 
891
static bool
 
892
plane_cmap_is_halftoned(const gs_imager_state *pis_image, gx_device *dev)
 
893
{
 
894
    return false;
 
895
}
 
896
 
 
897
static const gx_color_map_procs plane_color_map_procs = {
 
898
    plane_cmap_gray, plane_cmap_rgb, plane_cmap_cmyk, plane_cmap_rgb_alpha,
 
899
    NULL, NULL, plane_cmap_is_halftoned
 
900
};
 
901
static const gx_color_map_procs *
 
902
plane_get_cmap_procs(const gs_imager_state *pis, const gx_device *dev)
 
903
{
 
904
    return &plane_color_map_procs;
 
905
}
 
906
 
 
907
/* Define the image processing procedures. */
 
908
static image_enum_proc_plane_data(plane_image_plane_data);
 
909
static image_enum_proc_end_image(plane_image_end_image);
 
910
static const gx_image_enum_procs_t plane_image_enum_procs = {
 
911
    plane_image_plane_data, plane_image_end_image
 
912
};
 
913
 
 
914
static int
 
915
plane_begin_typed_image(gx_device * dev,
 
916
                        const gs_imager_state * pis, const gs_matrix * pmat,
 
917
                   const gs_image_common_t * pic, const gs_int_rect * prect,
 
918
              const gx_drawing_color * pdcolor, const gx_clip_path * pcpath,
 
919
                      gs_memory_t * memory, gx_image_enum_common_t ** pinfo)
 
920
{
 
921
    /*
 
922
     * For images, we intercept the imager state's cmap_procs and apply
 
923
     * reduce_drawing_color to the colors as they are returned to the image
 
924
     * processing code.  For reasons explained above, we can't do this in
 
925
     * some cases of RasterOp that include transparency.
 
926
     */
 
927
    gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
 
928
    gs_logical_operation_t lop = gs_current_logical_op((const gs_state *)pis);
 
929
    const gs_pixel_image_t *pim;
 
930
    plane_image_enum_t *info = 0;
 
931
    gs_imager_state *pis_image = 0;
 
932
    gx_device_color dcolor;
 
933
    bool uses_color = false;
 
934
    int code;
 
935
 
 
936
    /* We can only handle a limited set of image types. */
 
937
    switch (pic->type->index) {
 
938
    case 1: {
 
939
        const gs_image1_t * const pim1 = (const gs_image1_t *)pic;
 
940
 
 
941
        if (pim1->Alpha != gs_image_alpha_none)
 
942
            goto fail;
 
943
        uses_color = pim1->ImageMask;
 
944
        break;
 
945
        }
 
946
    case 3:
 
947
    case 4:
 
948
        break;
 
949
    default:
 
950
        goto fail;
 
951
    }
 
952
    pim = (const gs_pixel_image_t *)pic;
 
953
    if ((lop & lop_S_transparent) ||
 
954
        ((uses_color || pim->CombineWithColor) && (lop & lop_T_transparent))
 
955
        )
 
956
        goto fail;
 
957
    if (uses_color || (pim->CombineWithColor && lop_uses_T(lop))) {
 
958
        if (reduce_drawing_color(&dcolor, edev, pdcolor, &lop) ==
 
959
            REDUCE_FAILED)
 
960
            goto fail;
 
961
    } else {
 
962
        /*
 
963
         * The drawing color won't be used, but if RasterOp is involved,
 
964
         * it may still be accessed in some anomalous cases.
 
965
         */
 
966
        set_nonclient_dev_color(&dcolor, (gx_color_index)0);
 
967
    }
 
968
    info = gs_alloc_struct(memory, plane_image_enum_t, &st_plane_image_enum,
 
969
                           "plane_image_begin_typed(info)");
 
970
    pis_image = gs_imager_state_copy(pis, memory);
 
971
    if (pis_image == 0 || info == 0)
 
972
        goto fail;
 
973
    *pis_image = *pis;
 
974
    pis_image->client_data = info;
 
975
    pis_image->get_cmap_procs = plane_get_cmap_procs;
 
976
    code = dev_proc(edev->plane_dev, begin_typed_image)
 
977
        (edev->plane_dev, pis_image, pmat, pic, prect,
 
978
         &dcolor, pcpath, memory, &info->info);
 
979
    if (code < 0)
 
980
        goto fail;
 
981
    *((gx_image_enum_common_t *)info) = *info->info;
 
982
    info->procs = &plane_image_enum_procs;
 
983
    info->dev = (gx_device *)edev;
 
984
    info->id = gs_next_ids(memory, 1);
 
985
    info->memory = memory;
 
986
    info->pis = pis;
 
987
    info->pis_image = pis_image;
 
988
    *pinfo = (gx_image_enum_common_t *)info;
 
989
    return code;
 
990
fail:
 
991
    gs_free_object(memory, pis_image, "plane_image_begin_typed(pis_image)");
 
992
    gs_free_object(memory, info, "plane_image_begin_typed(info)");
 
993
    return gx_default_begin_typed_image(dev, pis, pmat, pic, prect,
 
994
                                        pdcolor, pcpath, memory, pinfo);
 
995
}
 
996
 
 
997
static int
 
998
plane_image_plane_data(gx_image_enum_common_t * info,
 
999
                       const gx_image_plane_t * planes, int height,
 
1000
                       int *rows_used)
 
1001
{
 
1002
    plane_image_enum_t * const ppie = (plane_image_enum_t *)info;
 
1003
 
 
1004
    return gx_image_plane_data_rows(ppie->info, planes, height, rows_used);
 
1005
}
 
1006
 
 
1007
static int
 
1008
plane_image_end_image(gx_image_enum_common_t * info, bool draw_last)
 
1009
{
 
1010
    plane_image_enum_t * const ppie = (plane_image_enum_t *)info;
 
1011
    int code = gx_image_end(ppie->info, draw_last);
 
1012
 
 
1013
    gs_free_object(ppie->memory, ppie->pis_image,
 
1014
                   "plane_image_end_image(pis_image)");
 
1015
    gx_image_free_enum(&info);
 
1016
    return code;
 
1017
}
 
1018
 
 
1019
/* ---------------- Reading back bits ---------------- */
 
1020
 
 
1021
static int
 
1022
plane_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect,
 
1023
                         gs_get_bits_params_t * params, gs_int_rect ** unread)
 
1024
{
 
1025
    gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
 
1026
    gx_device * const plane_dev = edev->plane_dev;
 
1027
    int plane_index = edev->plane.index;
 
1028
    gs_get_bits_options_t options = params->options;
 
1029
    gs_get_bits_params_t plane_params;
 
1030
    int plane;
 
1031
    int code;
 
1032
 
 
1033
    /*
 
1034
     * The only real option that this device supports is single-plane
 
1035
     * retrieval.  However, for the default case of RasterOp, it must be
 
1036
     * able to return chunky pixels in which the other components are
 
1037
     * arbitrary (but might as well be zero).
 
1038
     */
 
1039
    if ((options & GB_PACKING_PLANAR) && (options & GB_SELECT_PLANES)) {
 
1040
        if (params->data[plane_index] == 0)
 
1041
            return gx_default_get_bits_rectangle(dev, prect, params, unread);
 
1042
        /* If the caller wants any other plane(s), punt. */
 
1043
        for (plane = 0; plane < dev->color_info.num_components; ++plane)
 
1044
            if (plane != plane_index && params->data[plane] != 0)
 
1045
                return gx_default_get_bits_rectangle(dev, prect, params, unread);
 
1046
        /* Pass the request on to the plane device. */
 
1047
        plane_params = *params;
 
1048
        plane_params.options =
 
1049
            (options & ~(GB_PACKING_ALL | GB_SELECT_PLANES)) |
 
1050
            GB_PACKING_CHUNKY;
 
1051
        plane_params.data[0] = params->data[plane_index];
 
1052
        code = dev_proc(plane_dev, get_bits_rectangle)
 
1053
            (plane_dev, prect, &plane_params, unread);
 
1054
        if (code >= 0) {
 
1055
            *params = plane_params;
 
1056
            params->options = (params->options & ~GB_PACKING_ALL) |
 
1057
                (GB_PACKING_PLANAR | GB_SELECT_PLANES);
 
1058
            params->data[plane_index] = params->data[0];
 
1059
            for (plane = 0; plane < dev->color_info.num_components; ++plane)
 
1060
                if (plane != plane_index)
 
1061
                    params->data[plane] = 0;
 
1062
        }
 
1063
    } else if (!(~options & (GB_COLORS_NATIVE | GB_ALPHA_NONE |
 
1064
                             GB_PACKING_CHUNKY | GB_RETURN_COPY |
 
1065
                             GB_ALIGN_STANDARD | GB_OFFSET_0 |
 
1066
                             GB_RASTER_STANDARD))) {
 
1067
        /* Expand the plane into chunky pixels. */
 
1068
        bits_plane_t dest, source;
 
1069
 
 
1070
        dest.data.write = params->data[0];
 
1071
        dest.raster =
 
1072
            bitmap_raster((prect->q.x - prect->p.x) * dev->color_info.depth);
 
1073
        dest.depth = edev->color_info.depth;
 
1074
        dest.x = 0;
 
1075
 
 
1076
        /* not source.data, source.raster, source.x */
 
1077
        source.depth = plane_dev->color_info.depth;
 
1078
 
 
1079
        plane_params = *params;
 
1080
        plane_params.options = options &=
 
1081
            (~(GB_COLORS_ALL | GB_ALPHA_ALL | GB_PACKING_ALL |
 
1082
               GB_RETURN_ALL | GB_ALIGN_ALL | GB_OFFSET_ALL | GB_RASTER_ALL) |
 
1083
             GB_COLORS_NATIVE | GB_ALPHA_NONE | GB_PACKING_CHUNKY |
 
1084
             /* Try for a pointer return the first time. */
 
1085
             GB_RETURN_POINTER |
 
1086
             GB_ALIGN_STANDARD |
 
1087
             (GB_OFFSET_0 | GB_OFFSET_ANY) |
 
1088
             (GB_RASTER_STANDARD | GB_RASTER_ANY));
 
1089
        plane_params.raster = gx_device_raster(plane_dev, true);
 
1090
        code = dev_proc(plane_dev, get_bits_rectangle)
 
1091
            (plane_dev, prect, &plane_params, unread);
 
1092
        if (code >= 0) {
 
1093
            /* Success, expand the plane into pixels. */
 
1094
            source.data.read = plane_params.data[0];
 
1095
            source.raster = plane_params.raster;
 
1096
            source.x = params->x_offset;
 
1097
            code = bits_expand_plane(&dest, &source, edev->plane.shift,
 
1098
                                     prect->q.x - prect->p.x,
 
1099
                                     prect->q.y - prect->p.y);
 
1100
        }
 
1101
        params->options = (options & ~GB_RETURN_POINTER) | GB_RETURN_COPY;
 
1102
    } else
 
1103
        return gx_default_get_bits_rectangle(dev, prect, params, unread);
 
1104
    return code;
 
1105
}