Coverage Report

Created: 2025-11-16 07:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/base/gdevmpla.c
Line
Count
Source
1
/* Copyright (C) 2001-2025 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,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
/* Any-depth planar "memory" (stored bitmap) device */
17
#include "memory_.h"
18
#include "gx.h"
19
#include "gserrors.h"
20
#include "gsbitops.h"
21
#include "gxdevice.h"
22
#include "gxdcolor.h"   /* for gx_fill_rectangle_device_rop */
23
#include "gxpcolor.h"           /* for gx_dc_devn_masked */
24
#include "gxdevmem.h"           /* semi-public definitions */
25
#include "gxgetbit.h"
26
#include "gdevmem.h"            /* private definitions */
27
#include "gdevmpla.h"           /* interface */
28
#include "gxdevsop.h"
29
30
/* procedures */
31
static dev_proc_open_device(mem_planar_open);
32
static dev_proc_open_device(mem_planar_open_interleaved);
33
declare_mem_procs(mem_planar_copy_mono, mem_planar_copy_color, mem_planar_fill_rectangle);
34
static dev_proc_copy_color(mem_planar_copy_color_24to8);
35
static dev_proc_copy_color(mem_planar_copy_color_4to1);
36
static dev_proc_copy_planes(mem_planar_copy_planes);
37
/* Not static due to an optimized case in tile_clip_fill_rectangle_hl_color*/
38
static dev_proc_strip_tile_rectangle(mem_planar_strip_tile_rectangle);
39
static dev_proc_strip_tile_rect_devn(mem_planar_strip_tile_rect_devn);
40
static dev_proc_strip_copy_rop2(mem_planar_strip_copy_rop2);
41
static dev_proc_get_bits_rectangle(mem_planar_get_bits_rectangle);
42
static dev_proc_fill_rectangle_hl_color(mem_planar_fill_rectangle_hl_color);
43
static dev_proc_put_image(mem_planar_put_image);
44
45
int
46
mem_spec_op(gx_device *pdev, int dev_spec_op,
47
            void *data, int size)
48
1.17G
{
49
1.17G
    cmm_dev_profile_t *dev_profile;
50
1.17G
    gx_device_memory *mdev = (gx_device_memory *)pdev;
51
52
1.17G
    if (pdev->num_planar_planes &&
53
90.9M
        (dev_spec_op == gxdso_supports_devn ||
54
89.5M
         dev_spec_op == gxdso_skip_icc_component_validation)) {
55
1.43M
        dev_proc(pdev, get_profile)(pdev, &dev_profile);
56
1.43M
        if (dev_profile != NULL && dev_profile->supports_devn &&
57
1.43M
            dev_proc(pdev, fill_rectangle_hl_color) == mem_planar_fill_rectangle_hl_color)
58
1.43M
            return 1;
59
1.43M
    }
60
1.17G
    if (dev_spec_op == gxdso_is_std_cmyk_1bit)
61
486M
         return dev_proc(pdev, copy_color) == mem_planar_copy_color_4to1;
62
684M
    if (dev_spec_op == gxdso_is_pdf14_device || dev_spec_op == gxdso_pattern_handles_clip_path)
63
5.59k
         return 0;
64
684M
    if (mdev->owner)
65
684M
        return dev_proc(mdev->owner, dev_spec_op)(mdev->owner, dev_spec_op, data, size);
66
41.1k
    return gx_default_dev_spec_op(pdev, dev_spec_op, data, size);
67
684M
}
68
69
/*
70
 * Set up a planar memory device, after calling gs_make_mem_device but
71
 * before opening the device.  The pre-existing device provides the color
72
 * mapping procedures, but not the drawing procedures.  Requires: num_planes
73
 * > 0, plane_depths[0 ..  num_planes - 1] > 0, sum of plane depths =
74
 * mdev->color_info.depth.
75
 *
76
 * Note that this is the only public procedure in this file, and the only
77
 * sanctioned way to set up a planar memory device.
78
 */
79
int
80
gdev_mem_set_planar(gx_device_memory * mdev, int num_planes,
81
                    const gx_render_plane_t *planes /*[num_planes]*/)
82
11.0M
{
83
11.0M
    return gdev_mem_set_planar_interleaved(mdev, num_planes, planes, 0);
84
11.0M
}
85
86
int
87
gdev_mem_set_planar_interleaved(gx_device_memory * mdev, int num_planes,
88
                                const gx_render_plane_t *planes /*[num_planes]*/,
89
                                int interleaved)
90
11.0M
{
91
11.0M
    int total_depth;
92
11.0M
    int same_depth = planes[0].depth;
93
11.0M
    gx_color_index covered = 0;
94
11.0M
    int pi;
95
11.0M
    const gdev_mem_functions *fns =
96
11.0M
                    gdev_mem_functions_for_bits(mdev->color_info.depth);
97
98
11.0M
    if (num_planes < 1 || num_planes > GX_DEVICE_COLOR_MAX_COMPONENTS || num_planes < mdev->color_info.num_components)
99
0
        return_error(gs_error_rangecheck);
100
67.1M
    for (pi = 0, total_depth = 0; pi < num_planes; ++pi) {
101
56.1M
        int shift = planes[pi].shift;
102
56.1M
        int plane_depth = planes[pi].depth;
103
56.1M
        gx_color_index mask;
104
105
56.1M
        if (shift < 0 || plane_depth > 16 ||
106
56.1M
            !gdev_mem_device_for_bits(plane_depth))
107
0
            return_error(gs_error_rangecheck);
108
        /* Don't test overlap if shift is too large to fit in the variable */
109
56.1M
        if (shift < 8*sizeof(gx_color_index))
110
55.2M
        {
111
55.2M
            mask = (((gx_color_index)1 << plane_depth) - 1) << shift;
112
55.2M
            if (covered & mask)
113
0
                return_error(gs_error_rangecheck);
114
55.2M
            covered |= mask;
115
55.2M
        }
116
56.1M
        if (plane_depth != same_depth)
117
0
            same_depth = 0;
118
56.1M
        total_depth += plane_depth;
119
56.1M
    }
120
11.0M
    if (total_depth > mdev->color_info.depth)
121
0
        return_error(gs_error_rangecheck);
122
11.0M
    mdev->num_planar_planes = num_planes;
123
11.0M
    memcpy(mdev->planes, planes, num_planes * sizeof(planes[0]));
124
11.0M
    mdev->plane_depth = same_depth;
125
    /* Change the drawing procedures. */
126
11.0M
    if (interleaved)
127
0
        set_dev_proc(mdev, open_device, mem_planar_open_interleaved);
128
11.0M
    else
129
11.0M
        set_dev_proc(mdev, open_device, mem_planar_open);
130
    /* Regardless of how many planes we are using, always let the
131
     * device know how to handle hl_color. Even if we spot that we
132
     * can get away with a normal device, our callers may want to
133
     * feed us single component devn data. */
134
11.0M
    set_dev_proc(mdev, fill_rectangle_hl_color,
135
11.0M
                 mem_planar_fill_rectangle_hl_color);
136
11.0M
    if (num_planes == 1) {
137
        /* For 1 plane, just use a normal device */
138
0
        set_dev_proc(mdev, fill_rectangle, fns->fill_rectangle);
139
0
        set_dev_proc(mdev, copy_mono,  fns->copy_mono);
140
0
        set_dev_proc(mdev, copy_color, fns->copy_color);
141
0
        set_dev_proc(mdev, copy_alpha, fns->copy_alpha);
142
0
        set_dev_proc(mdev, strip_tile_rectangle, fns->strip_tile_rectangle);
143
0
        set_dev_proc(mdev, strip_copy_rop2, fns->strip_copy_rop2);
144
0
        set_dev_proc(mdev, get_bits_rectangle, fns->get_bits_rectangle);
145
11.0M
    } else {
146
        /* If we are going out to a separation device or one that has more than
147
           four planes then use the high level color filling procedure.  Also
148
           make use of the put_image operation to go from the pdf14 device
149
           directly to the planar buffer. */
150
11.0M
        if (num_planes >= 4) {
151
            /* put_image always gives us our data in bytes (or 16bits) per
152
             * component. When we have a suitably deep device we can assume
153
             * that this will match our own representation, and use a fast
154
             * copy_planes based implementation. If not, we have to use the
155
             * default's copy-via-image implementation. */
156
11.0M
            if (mdev->color_info.depth / num_planes >= 8)
157
230k
               set_dev_proc(mdev, put_image, mem_planar_put_image);
158
11.0M
        }
159
11.0M
        set_dev_proc(mdev, fill_rectangle, mem_planar_fill_rectangle);
160
11.0M
        set_dev_proc(mdev, copy_alpha_hl_color, gx_default_copy_alpha_hl_color);
161
11.0M
        set_dev_proc(mdev, copy_mono, mem_planar_copy_mono);
162
11.0M
        if ((mdev->color_info.depth == 24) &&
163
244
            (num_planes == 3) &&
164
244
            (mdev->planes[0].depth == 8) && (mdev->planes[0].shift == 16) &&
165
244
            (mdev->planes[1].depth == 8) && (mdev->planes[1].shift == 8) &&
166
244
            (mdev->planes[2].depth == 8) && (mdev->planes[2].shift == 0))
167
244
            set_dev_proc(mdev, copy_color, mem_planar_copy_color_24to8);
168
11.0M
        else if ((mdev->color_info.depth == 4) &&
169
9.56M
                 (num_planes == 4) &&
170
9.56M
                 (mdev->planes[0].depth == 1) && (mdev->planes[0].shift == 3) &&
171
9.56M
                 (mdev->planes[1].depth == 1) && (mdev->planes[1].shift == 2) &&
172
9.56M
                 (mdev->planes[2].depth == 1) && (mdev->planes[2].shift == 1) &&
173
9.56M
                 (mdev->planes[3].depth == 1) && (mdev->planes[3].shift == 0)) {
174
9.56M
            set_dev_proc(mdev, copy_color, mem_planar_copy_color_4to1);
175
9.56M
        } else
176
1.46M
            set_dev_proc(mdev, copy_color, mem_planar_copy_color);
177
11.0M
        set_dev_proc(mdev, copy_alpha, gx_default_copy_alpha);
178
11.0M
        set_dev_proc(mdev, strip_tile_rectangle, mem_planar_strip_tile_rectangle);
179
11.0M
        set_dev_proc(mdev, strip_tile_rect_devn, mem_planar_strip_tile_rect_devn);
180
11.0M
        set_dev_proc(mdev, strip_copy_rop2, mem_planar_strip_copy_rop2);
181
11.0M
        set_dev_proc(mdev, get_bits_rectangle, mem_planar_get_bits_rectangle);
182
11.0M
    }
183
11.0M
    fill_dev_proc(mdev, dev_spec_op, mem_spec_op);
184
11.0M
    set_dev_proc(mdev, copy_planes, mem_planar_copy_planes);
185
11.0M
    return 0;
186
11.0M
}
187
188
/* Open a planar memory device. */
189
static int
190
mem_planar_open(gx_device * dev)
191
981
{
192
981
    gx_device_memory *const mdev = (gx_device_memory *)dev;
193
194
    /* Check that we aren't trying to open a chunky device as planar. */
195
981
    if (!dev->num_planar_planes)
196
0
        return_error(gs_error_rangecheck);
197
981
    return gdev_mem_open_scan_lines(mdev, dev->height);
198
981
}
199
200
static int
201
mem_planar_open_interleaved(gx_device * dev)
202
0
{
203
0
    gx_device_memory *const mdev = (gx_device_memory *)dev;
204
205
    /* Check that we aren't trying to open a chunky device as planar. */
206
0
    if (!dev->num_planar_planes)
207
0
        return_error(gs_error_rangecheck);
208
0
    return gdev_mem_open_scan_lines_interleaved(mdev, dev->height, 1);
209
0
}
210
211
/*
212
 * We execute drawing operations by patching a few parameters in the
213
 * device structure and then calling the procedure appropriate to the
214
 * plane depth.
215
 */
216
typedef struct mem_save_params_s {
217
    int depth;                  /* color_info.depth */
218
    byte *base;
219
    byte **line_ptrs;
220
} mem_save_params_t;
221
#define MEM_SAVE_PARAMS(mdev, msp)\
222
95.3M
  (msp.depth = mdev->color_info.depth,\
223
95.3M
   msp.base = mdev->base,\
224
95.3M
   msp.line_ptrs = mdev->line_ptrs)
225
/* Previous versions of MEM_SET_PARAMS calculated raster as
226
 * bitmap_raster(mdev->width * plane_depth), but this restricts us to
227
 * non interleaved frame buffers. Now we calculate it from the difference
228
 * between the first 2 line pointers; this clearly only works if there are
229
 * at least 2 line pointers to use. Otherwise, we fall back to the old
230
 * method.
231
 */
232
/* FIXME: Find a nicer way of calculating raster. This is only required if
233
 * we allow the plane_depth to vary per plane, and the rest of the code
234
 * assumes that it never does. This can probably be simplified now. */
235
#define MEM_SET_PARAMS(mdev, plane_depth)\
236
275M
  (mdev->color_info.depth = plane_depth, /* maybe not needed */\
237
275M
   mdev->base = mdev->line_ptrs[0],\
238
275M
   mdev->raster = (mdev->height > 1 ? mdev->line_ptrs[1]-mdev->line_ptrs[0] : bitmap_raster(mdev->width * plane_depth)))
239
#define MEM_RESTORE_PARAMS(mdev, msp)\
240
95.3M
  (mdev->color_info.depth = msp.depth,\
241
95.3M
   mdev->base = msp.base,\
242
95.3M
   mdev->line_ptrs = msp.line_ptrs)
243
244
/* Note tag_offset == 0 if there is no tag plane. Tags always follow the
245
   color data, but not neccessarily right after. */
246
static int
247
put_image_copy_planes(gx_device * dev, const byte **base_ptr, int sourcex,
248
                      int sraster, gx_bitmap_id id,
249
                      int x, int y, int w, int h, int tag_offset)
250
252
{
251
252
    gx_device_memory * const mdev = (gx_device_memory *)dev;
252
252
    int plane_depth;
253
252
    mem_save_params_t save;
254
252
    const gdev_mem_functions *fns;
255
252
    int code = 0;
256
252
    int plane;
257
252
    const byte *base;
258
252
    int last_plane = mdev->num_planar_planes - 1;
259
260
252
    MEM_SAVE_PARAMS(mdev, save);
261
1.27k
    for (plane = 0; plane < mdev->num_planar_planes; plane++)
262
1.02k
    {
263
1.02k
        if (tag_offset && plane == last_plane)
264
0
            base = base_ptr[tag_offset];
265
1.02k
        else
266
1.02k
            base = base_ptr[plane];
267
1.02k
        plane_depth = mdev->planes[plane].depth;
268
1.02k
        fns = gdev_mem_functions_for_bits(plane_depth);
269
1.02k
        if (base == NULL) {
270
            /* Blank the plane */
271
0
            code = fns->fill_rectangle(dev, x, y, w, h,
272
0
                (gx_color_index)(dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE ? 0 : -1));
273
1.02k
        } else if (plane_depth == 1)
274
0
            code = fns->copy_mono(dev, base, sourcex, sraster, id,
275
0
                                  x, y, w, h,
276
0
                                  (gx_color_index)0, (gx_color_index)1);
277
1.02k
        else
278
1.02k
            fns->copy_color(dev, base, sourcex, sraster, id, x, y, w, h);
279
1.02k
        mdev->line_ptrs += mdev->height;
280
1.02k
    }
281
252
    MEM_RESTORE_PARAMS(mdev, save);
282
252
    return code;
283
252
}
284
285
/* Put image command for copying the planar image buffers with or without
286
   alpha directly to the device buffer */
287
static int
288
mem_planar_put_image(gx_device *pdev, gx_device *pmdev, const byte **buffers, int num_chan, int xstart,
289
              int ystart, int width, int height, int row_stride,
290
              int alpha_plane_index, int tag_plane_index)
291
252
{
292
    /* We don't want alpha, return 0 to ask for the pdf14 device to do the
293
       alpha composition. We also do not want chunky data coming in */
294
252
    if (alpha_plane_index != 0)
295
0
        return 0;
296
297
252
    put_image_copy_planes(pdev, buffers, 0, row_stride,
298
252
                          gx_no_bitmap_id, xstart, ystart,
299
252
                          width, height, tag_plane_index);
300
301
    /* we used all of the data */
302
252
    return height;
303
252
}
304
305
/* Fill a rectangle with a high level color.  This is used for separation
306
   devices. (e.g. tiffsep, psdcmyk) */
307
static int
308
mem_planar_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect,
309
    const gs_gstate *pgs, const gx_drawing_color *pdcolor,
310
    const gx_clip_path *pcpath)
311
3.20M
{
312
3.20M
    gx_device_memory * const mdev = (gx_device_memory *)dev;
313
3.20M
    mem_save_params_t save;
314
3.20M
    int pi;
315
3.20M
    int x = fixed2int(rect->p.x);
316
3.20M
    int y = fixed2int(rect->p.y);
317
3.20M
    int w = fixed2int(rect->q.x) - x;
318
3.20M
    int h = fixed2int(rect->q.y) - y;
319
3.20M
    int has_tags = device_encodes_tags(dev);
320
3.20M
    int npp = mdev->num_planar_planes - has_tags;
321
322
    /* We can only handle devn cases, so use the default if not */
323
    /* We can get called here from gx_dc_devn_masked_fill_rectangle */
324
3.20M
    if (pdcolor->type != gx_dc_type_devn && pdcolor->type != &gx_dc_devn_masked) {
325
0
        return gx_fill_rectangle_device_rop( x, y, w, h, pdcolor, dev, lop_default);
326
0
    }
327
3.20M
    MEM_SAVE_PARAMS(mdev, save);
328
19.2M
    for (pi = 0; pi < npp; ++pi) {
329
16.0M
        int plane_depth = mdev->planes[pi].depth;
330
16.0M
        gx_color_index mask = ((gx_color_index)1 << plane_depth) - 1;
331
16.0M
        int shift = 16 - plane_depth;
332
16.0M
        const gdev_mem_functions *fns =
333
16.0M
                               gdev_mem_functions_for_bits(plane_depth);
334
335
16.0M
        MEM_SET_PARAMS(mdev, plane_depth);
336
16.0M
        fns->fill_rectangle(dev, x, y, w, h,
337
16.0M
                            (pdcolor->colors.devn.values[pi]) >> shift & mask);
338
16.0M
        mdev->line_ptrs += mdev->height;
339
16.0M
    }
340
3.20M
    if (has_tags) {
341
0
        int plane_depth = mdev->planes[pi].depth;
342
0
        gx_color_index mask = ((gx_color_index)1 << plane_depth) - 1;
343
0
        const gdev_mem_functions *fns =
344
0
                    gdev_mem_functions_for_bits(plane_depth);
345
346
0
        MEM_SET_PARAMS(mdev, plane_depth);
347
0
        fns->fill_rectangle(dev, x, y, w, h,
348
0
                    (pdcolor->colors.devn.values[pi]) & mask);
349
0
        mdev->line_ptrs += mdev->height;
350
0
    }
351
3.20M
    MEM_RESTORE_PARAMS(mdev, save);
352
3.20M
    return 0;
353
3.20M
}
354
355
/* Fill a rectangle with a color. */
356
static int
357
mem_planar_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
358
                          gx_color_index color)
359
31.1M
{
360
31.1M
    gx_device_memory * const mdev = (gx_device_memory *)dev;
361
31.1M
    mem_save_params_t save;
362
31.1M
    int pi;
363
364
31.1M
    MEM_SAVE_PARAMS(mdev, save);
365
166M
    for (pi = 0; pi < mdev->num_planar_planes; ++pi) {
366
135M
        int plane_depth = mdev->planes[pi].depth;
367
135M
        gx_color_index mask = ((gx_color_index)1 << plane_depth) - 1;
368
135M
        const gdev_mem_functions *fns =
369
135M
                               gdev_mem_functions_for_bits(plane_depth);
370
371
135M
        MEM_SET_PARAMS(mdev, plane_depth);
372
135M
        fns->fill_rectangle(dev, x, y, w, h,
373
135M
                            (color >> mdev->planes[pi].shift) & mask);
374
135M
        mdev->line_ptrs += mdev->height;
375
135M
    }
376
31.1M
    MEM_RESTORE_PARAMS(mdev, save);
377
31.1M
    return 0;
378
31.1M
}
379
380
/* Copy a bitmap. */
381
static int
382
mem_planar_copy_mono(gx_device * dev, const byte * base, int sourcex,
383
                     int sraster, gx_bitmap_id id, int x, int y, int w, int h,
384
                     gx_color_index color0, gx_color_index color1)
385
813k
{
386
813k
    gx_device_memory * const mdev = (gx_device_memory *)dev;
387
813k
    mem_save_params_t save;
388
813k
    int pi;
389
390
813k
    MEM_SAVE_PARAMS(mdev, save);
391
4.18M
    for (pi = 0; pi < mdev->num_planar_planes; ++pi) {
392
3.37M
        int plane_depth = mdev->planes[pi].depth;
393
3.37M
        int shift = mdev->planes[pi].shift;
394
3.37M
        gx_color_index mask = ((gx_color_index)1 << plane_depth) - 1;
395
3.37M
        const gdev_mem_functions *fns =
396
3.37M
                               gdev_mem_functions_for_bits(plane_depth);
397
3.37M
        gx_color_index c0 =
398
3.37M
            (color0 == gx_no_color_index ? gx_no_color_index :
399
3.37M
             (color0 >> shift) & mask);
400
3.37M
        gx_color_index c1 =
401
3.37M
            (color1 == gx_no_color_index ? gx_no_color_index :
402
3.37M
             (color1 >> shift) & mask);
403
404
3.37M
        MEM_SET_PARAMS(mdev, plane_depth);
405
3.37M
        if (c0 == c1)
406
87.0k
            fns->fill_rectangle(dev, x, y, w, h, c0);
407
3.28M
        else
408
3.28M
            fns->copy_mono(dev, base, sourcex, sraster, id,
409
3.28M
                           x, y, w, h, c0, c1);
410
3.37M
        mdev->line_ptrs += mdev->height;
411
3.37M
    }
412
813k
    MEM_RESTORE_PARAMS(mdev, save);
413
813k
    return 0;
414
813k
}
415
416
/* Copy color: Special case the 24 -> 8+8+8 case. */
417
static int
418
mem_planar_copy_color_24to8(gx_device * dev, const byte * base, int sourcex,
419
                            int sraster, gx_bitmap_id id,
420
                            int x, int y, int w, int h)
421
0
{
422
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
423
0
#define BUF_LONGS 100   /* arbitrary, >= 1 */
424
0
#define BUF_BYTES (BUF_LONGS * ARCH_SIZEOF_LONG)
425
0
    union b_ {
426
0
        ulong l[BUF_LONGS];
427
0
        byte b[BUF_BYTES];
428
0
    } buf, buf1, buf2;
429
0
    mem_save_params_t save;
430
0
    dev_proc_copy_color((*copy_color)) =
431
0
                             gdev_mem_functions_for_bits(8)->copy_color;
432
0
    uint plane_raster = bitmap_raster(w<<3);
433
0
    int br, bw, bh, cx, cy, cw, ch, ix, iy;
434
435
0
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
436
0
    MEM_SAVE_PARAMS(mdev, save);
437
0
    MEM_SET_PARAMS(mdev, 8);
438
0
    if (plane_raster > BUF_BYTES) {
439
0
        br = BUF_BYTES;
440
0
        bw = BUF_BYTES;
441
0
        bh = 1;
442
0
    } else {
443
0
        br = plane_raster;
444
0
        bw = w;
445
0
        bh = BUF_BYTES / plane_raster;
446
0
    }
447
0
    for (cy = y; cy < y + h; cy += ch) {
448
0
        ch = min(bh, y + h - cy);
449
0
        for (cx = x; cx < x + w; cx += cw) {
450
0
            int sx = sourcex + cx - x;
451
0
            const byte *source_base = base + sraster * (cy - y);
452
453
0
            cw = min(bw, x + w - cx);
454
0
            source_base += sx * 3;
455
0
            for (iy = 0; iy < ch; ++iy) {
456
0
                const byte *sptr = source_base;
457
0
                byte *dptr0 = buf.b  + br * iy;
458
0
                byte *dptr1 = buf1.b + br * iy;
459
0
                byte *dptr2 = buf2.b + br * iy;
460
0
                ix = cw;
461
0
                do {
462
                    /* Use the temporary variables below to free the C compiler
463
                     * to interleave load/stores for latencies sake despite the
464
                     * pointer aliasing rules. */
465
0
                    byte r = *sptr++;
466
0
                    byte g = *sptr++;
467
0
                    byte b = *sptr++;
468
0
                    *dptr0++ = r;
469
0
                    *dptr1++ = g;
470
0
                    *dptr2++ = b;
471
0
                } while (--ix);
472
0
                source_base += sraster;
473
0
            }
474
0
            copy_color(dev, buf.b, 0, br, gx_no_bitmap_id, cx, cy, cw, ch);
475
0
            mdev->line_ptrs += mdev->height;
476
0
            copy_color(dev, buf1.b, 0, br, gx_no_bitmap_id, cx, cy, cw, ch);
477
0
            mdev->line_ptrs += mdev->height;
478
0
            copy_color(dev, buf2.b, 0, br, gx_no_bitmap_id, cx, cy, cw, ch);
479
0
            mdev->line_ptrs -= 2*mdev->height;
480
0
        }
481
0
    }
482
0
    MEM_RESTORE_PARAMS(mdev, save);
483
0
    return 0;
484
0
}
485
486
/* Copy color: Special case the 4 -> 1+1+1+1 case. */
487
/* Two versions of this routine; the first does bit comparisons. This should
488
 * work well on architectures with small cache and conditional execution
489
 * (such as ARM). Hurts on x86 due to the ifs in the loop all causing small
490
 * skips ahead that defeat the branch predictor.
491
 * Second version uses a table lookup; 1K of table is nothing on x86, and
492
 * so this runs much faster. */
493
#ifdef PREFER_ALTERNATIION_TO_TABLES
494
static int
495
mem_planar_copy_color_4to1(gx_device * dev, const byte * base, int sourcex,
496
                            int sraster, gx_bitmap_id id,
497
                            int x, int y, int w, int h)
498
{
499
    gx_device_memory * const mdev = (gx_device_memory *)dev;
500
#define BUF_LONGS 100   /* arbitrary, >= 1 */
501
#define BUF_BYTES (BUF_LONGS * ARCH_SIZEOF_LONG)
502
    union b_ {
503
        ulong l[BUF_LONGS];
504
        byte b[BUF_BYTES];
505
    } buf0, buf1, buf2, buf3;
506
    mem_save_params_t save;
507
    dev_proc_copy_mono((*copy_mono)) =
508
                        gdev_mem_fill_functions_for_bits(1)->copy_mono;
509
    uint plane_raster = bitmap_raster(w);
510
    int br, bw, bh, cx, cy, cw, ch, ix, iy;
511
512
#ifdef MEMENTO
513
    /* Pacify valgrind */
514
    memset(buf0.l, 0, sizeof(ulong) * BUF_LONGS);
515
    memset(buf1.l, 0, sizeof(ulong) * BUF_LONGS);
516
    memset(buf2.l, 0, sizeof(ulong) * BUF_LONGS);
517
    memset(buf3.l, 0, sizeof(ulong) * BUF_LONGS);
518
#endif
519
520
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
521
    MEM_SAVE_PARAMS(mdev, save);
522
    MEM_SET_PARAMS(mdev, 1);
523
    if (plane_raster > BUF_BYTES) {
524
        br = BUF_BYTES;
525
        bw = BUF_BYTES<<3;
526
        bh = 1;
527
    } else {
528
        br = plane_raster;
529
        bw = w;
530
        bh = BUF_BYTES / plane_raster;
531
    }
532
    for (cy = y; cy < y + h; cy += ch) {
533
        ch = min(bh, y + h - cy);
534
        for (cx = x; cx < x + w; cx += cw) {
535
            int sx = sourcex + cx - x;
536
            const byte *source_base = base + sraster * (cy - y) + (sx>>1);
537
538
            cw = min(bw, x + w - cx);
539
            if ((sx & 1) == 0) {
540
                for (iy = 0; iy < ch; ++iy) {
541
                    const byte *sptr = source_base;
542
                    byte *dptr0 = buf0.b + br * iy;
543
                    byte *dptr1 = buf1.b + br * iy;
544
                    byte *dptr2 = buf2.b + br * iy;
545
                    byte *dptr3 = buf3.b + br * iy;
546
                    byte roll = 0x80;
547
                    byte bc = 0;
548
                    byte bm = 0;
549
                    byte by = 0;
550
                    byte bk = 0;
551
                    ix = cw;
552
                    do {
553
                        byte b = *sptr++;
554
                        if (b & 0x80)
555
                            bc |= roll;
556
                        if (b & 0x40)
557
                            bm |= roll;
558
                        if (b & 0x20)
559
                            by |= roll;
560
                        if (b & 0x10)
561
                            bk |= roll;
562
                        roll >>= 1;
563
                        if (b & 0x08)
564
                            bc |= roll;
565
                        if (b & 0x04)
566
                            bm |= roll;
567
                        if (b & 0x02)
568
                            by |= roll;
569
                        if (b & 0x01)
570
                            bk |= roll;
571
                        roll >>= 1;
572
                        if (roll == 0) {
573
                            *dptr0++ = bc;
574
                            *dptr1++ = bm;
575
                            *dptr2++ = by;
576
                            *dptr3++ = bk;
577
                            bc = 0;
578
                            bm = 0;
579
                            by = 0;
580
                            bk = 0;
581
                            roll = 0x80;
582
                        }
583
                        ix -= 2;
584
                    } while (ix > 0);
585
                    if (roll != 0x80) {
586
                        *dptr0++ = bc;
587
                        *dptr1++ = bm;
588
                        *dptr2++ = by;
589
                        *dptr3++ = bk;
590
                    }
591
                    source_base += sraster;
592
                }
593
            } else {
594
                for (iy = 0; iy < ch; ++iy) {
595
                    const byte *sptr = source_base;
596
                    byte *dptr0 = buf0.b + br * iy;
597
                    byte *dptr1 = buf1.b + br * iy;
598
                    byte *dptr2 = buf2.b + br * iy;
599
                    byte *dptr3 = buf3.b + br * iy;
600
                    byte roll = 0x80;
601
                    byte bc = 0;
602
                    byte bm = 0;
603
                    byte by = 0;
604
                    byte bk = 0;
605
                    byte b = *sptr++;
606
                    ix = cw;
607
                    goto loop_entry;
608
                    do {
609
                        b = *sptr++;
610
                        if (b & 0x80)
611
                            bc |= roll;
612
                        if (b & 0x40)
613
                            bm |= roll;
614
                        if (b & 0x20)
615
                            by |= roll;
616
                        if (b & 0x10)
617
                            bk |= roll;
618
                        roll >>= 1;
619
                        if (roll == 0) {
620
                            *dptr0++ = bc;
621
                            *dptr1++ = bm;
622
                            *dptr2++ = by;
623
                            *dptr3++ = bk;
624
                            bc = 0;
625
                            bm = 0;
626
                            by = 0;
627
                            bk = 0;
628
                            roll = 0x80;
629
                        }
630
loop_entry:
631
                        if (b & 0x08)
632
                            bc |= roll;
633
                        if (b & 0x04)
634
                            bm |= roll;
635
                        if (b & 0x02)
636
                            by |= roll;
637
                        if (b & 0x01)
638
                            bk |= roll;
639
                        roll >>= 1;
640
                        ix -= 2;
641
                    } while (ix >= 0); /* ix == -2 means 1 extra done */
642
                    if ((ix == -2) && (roll == 0x40)) {
643
                        /* We did an extra one, and it was the last thing
644
                         * we did. Nothing to store. */
645
                    } else {
646
                        /* Flush the stored bytes */
647
                        *dptr0++ = bc;
648
                        *dptr1++ = bm;
649
                        *dptr2++ = by;
650
                        *dptr3++ = bk;
651
                    }
652
                    source_base += sraster;
653
                }
654
            }
655
            copy_mono(dev, buf0.b, 0, br, gx_no_bitmap_id, cx, cy, cw, ch,
656
                      (gx_color_index)0, (gx_color_index)1);
657
            mdev->line_ptrs += mdev->height;
658
            copy_mono(dev, buf1.b, 0, br, gx_no_bitmap_id, cx, cy, cw, ch,
659
                      (gx_color_index)0, (gx_color_index)1);
660
            mdev->line_ptrs += mdev->height;
661
            copy_mono(dev, buf2.b, 0, br, gx_no_bitmap_id, cx, cy, cw, ch,
662
                      (gx_color_index)0, (gx_color_index)1);
663
            mdev->line_ptrs += mdev->height;
664
            copy_mono(dev, buf3.b, 0, br, gx_no_bitmap_id, cx, cy, cw, ch,
665
                      (gx_color_index)0, (gx_color_index)1);
666
            mdev->line_ptrs -= 3*mdev->height;
667
        }
668
    }
669
    MEM_RESTORE_PARAMS(mdev, save);
670
    return 0;
671
}
672
#else
673
674
static bits32 expand_4to1[256] =
675
{
676
0x00000000,0x00000001,0x00000100,0x00000101,
677
0x00010000,0x00010001,0x00010100,0x00010101,
678
0x01000000,0x01000001,0x01000100,0x01000101,
679
0x01010000,0x01010001,0x01010100,0x01010101,
680
0x00000002,0x00000003,0x00000102,0x00000103,
681
0x00010002,0x00010003,0x00010102,0x00010103,
682
0x01000002,0x01000003,0x01000102,0x01000103,
683
0x01010002,0x01010003,0x01010102,0x01010103,
684
0x00000200,0x00000201,0x00000300,0x00000301,
685
0x00010200,0x00010201,0x00010300,0x00010301,
686
0x01000200,0x01000201,0x01000300,0x01000301,
687
0x01010200,0x01010201,0x01010300,0x01010301,
688
0x00000202,0x00000203,0x00000302,0x00000303,
689
0x00010202,0x00010203,0x00010302,0x00010303,
690
0x01000202,0x01000203,0x01000302,0x01000303,
691
0x01010202,0x01010203,0x01010302,0x01010303,
692
0x00020000,0x00020001,0x00020100,0x00020101,
693
0x00030000,0x00030001,0x00030100,0x00030101,
694
0x01020000,0x01020001,0x01020100,0x01020101,
695
0x01030000,0x01030001,0x01030100,0x01030101,
696
0x00020002,0x00020003,0x00020102,0x00020103,
697
0x00030002,0x00030003,0x00030102,0x00030103,
698
0x01020002,0x01020003,0x01020102,0x01020103,
699
0x01030002,0x01030003,0x01030102,0x01030103,
700
0x00020200,0x00020201,0x00020300,0x00020301,
701
0x00030200,0x00030201,0x00030300,0x00030301,
702
0x01020200,0x01020201,0x01020300,0x01020301,
703
0x01030200,0x01030201,0x01030300,0x01030301,
704
0x00020202,0x00020203,0x00020302,0x00020303,
705
0x00030202,0x00030203,0x00030302,0x00030303,
706
0x01020202,0x01020203,0x01020302,0x01020303,
707
0x01030202,0x01030203,0x01030302,0x01030303,
708
0x02000000,0x02000001,0x02000100,0x02000101,
709
0x02010000,0x02010001,0x02010100,0x02010101,
710
0x03000000,0x03000001,0x03000100,0x03000101,
711
0x03010000,0x03010001,0x03010100,0x03010101,
712
0x02000002,0x02000003,0x02000102,0x02000103,
713
0x02010002,0x02010003,0x02010102,0x02010103,
714
0x03000002,0x03000003,0x03000102,0x03000103,
715
0x03010002,0x03010003,0x03010102,0x03010103,
716
0x02000200,0x02000201,0x02000300,0x02000301,
717
0x02010200,0x02010201,0x02010300,0x02010301,
718
0x03000200,0x03000201,0x03000300,0x03000301,
719
0x03010200,0x03010201,0x03010300,0x03010301,
720
0x02000202,0x02000203,0x02000302,0x02000303,
721
0x02010202,0x02010203,0x02010302,0x02010303,
722
0x03000202,0x03000203,0x03000302,0x03000303,
723
0x03010202,0x03010203,0x03010302,0x03010303,
724
0x02020000,0x02020001,0x02020100,0x02020101,
725
0x02030000,0x02030001,0x02030100,0x02030101,
726
0x03020000,0x03020001,0x03020100,0x03020101,
727
0x03030000,0x03030001,0x03030100,0x03030101,
728
0x02020002,0x02020003,0x02020102,0x02020103,
729
0x02030002,0x02030003,0x02030102,0x02030103,
730
0x03020002,0x03020003,0x03020102,0x03020103,
731
0x03030002,0x03030003,0x03030102,0x03030103,
732
0x02020200,0x02020201,0x02020300,0x02020301,
733
0x02030200,0x02030201,0x02030300,0x02030301,
734
0x03020200,0x03020201,0x03020300,0x03020301,
735
0x03030200,0x03030201,0x03030300,0x03030301,
736
0x02020202,0x02020203,0x02020302,0x02020303,
737
0x02030202,0x02030203,0x02030302,0x02030303,
738
0x03020202,0x03020203,0x03020302,0x03020303,
739
0x03030202,0x03030203,0x03030302,0x03030303
740
};
741
742
static int
743
mem_planar_copy_color_4to1(gx_device * dev, const byte * base, int sourcex,
744
                            int sraster, gx_bitmap_id id,
745
                            int x, int y, int w, int h)
746
42.3M
{
747
42.3M
    gx_device_memory * const mdev = (gx_device_memory *)dev;
748
84.1M
#define BUF_LONGS 100   /* arbitrary, >= 1 */
749
84.1M
#define BUF_BYTES (BUF_LONGS * ARCH_SIZEOF_LONG)
750
42.3M
    union b_ {
751
42.3M
        ulong l[BUF_LONGS];
752
42.3M
        byte b[BUF_BYTES];
753
42.3M
    } buf0, buf1, buf2, buf3;
754
42.3M
    mem_save_params_t save;
755
42.3M
    dev_proc_copy_mono((*copy_mono)) =
756
42.3M
                         gdev_mem_functions_for_bits(1)->copy_mono;
757
42.3M
    uint plane_raster = bitmap_raster(w);
758
42.3M
    int br, bw, bh, cx, cy, cw, ch, ix, iy;
759
760
42.3M
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
761
42.0M
    MEM_SAVE_PARAMS(mdev, save);
762
42.0M
    MEM_SET_PARAMS(mdev, 1);
763
42.0M
    if (plane_raster > BUF_BYTES) {
764
0
        br = BUF_BYTES;
765
0
        bw = BUF_BYTES<<3;
766
0
        bh = 1;
767
42.0M
    } else {
768
42.0M
        br = plane_raster;
769
42.0M
        bw = w;
770
42.0M
        bh = BUF_BYTES / plane_raster;
771
42.0M
    }
772
84.1M
    for (cy = y; cy < y + h; cy += ch) {
773
42.0M
        ch = min(bh, y + h - cy);
774
84.1M
        for (cx = x; cx < x + w; cx += cw) {
775
42.0M
            int sx = sourcex + cx - x;
776
42.0M
            const byte *source_base = base + sraster * (cy - y) + (sx>>1);
777
778
42.0M
            cw = min(bw, x + w - cx);
779
42.0M
            if ((sx & 1) == 0) {
780
90.2M
                for (iy = 0; iy < ch; ++iy) {
781
48.6M
                    const byte *sptr = source_base;
782
48.6M
                    byte *dptr0 = buf0.b + br * iy;
783
48.6M
                    byte *dptr1 = buf1.b + br * iy;
784
48.6M
                    byte *dptr2 = buf2.b + br * iy;
785
48.6M
                    byte *dptr3 = buf3.b + br * iy;
786
48.6M
                    int roll = 6;
787
48.6M
                    int cmyk = 0;
788
48.6M
                    ix = cw;
789
509M
                    do {
790
509M
                        cmyk |= expand_4to1[*sptr++]<<roll;
791
509M
                        roll -= 2;
792
509M
                        if (roll < 0) {
793
110M
                            *dptr0++ = cmyk>>24;
794
110M
                            *dptr1++ = cmyk>>16;
795
110M
                            *dptr2++ = cmyk>>8;
796
110M
                            *dptr3++ = cmyk;
797
110M
                            cmyk = 0;
798
110M
                            roll = 6;
799
110M
                        }
800
509M
                        ix -= 2;
801
509M
                    } while (ix > 0);
802
48.6M
                    if (roll != 6) {
803
45.0M
                        *dptr0++ = cmyk>>24;
804
45.0M
                        *dptr1++ = cmyk>>16;
805
45.0M
                        *dptr2++ = cmyk>>8;
806
45.0M
                        *dptr3++ = cmyk;
807
45.0M
                    }
808
48.6M
                    source_base += sraster;
809
48.6M
                }
810
41.5M
            } else {
811
1.19M
                for (iy = 0; iy < ch; ++iy) {
812
702k
                    const byte *sptr = source_base;
813
702k
                    byte *dptr0 = buf0.b + br * iy;
814
702k
                    byte *dptr1 = buf1.b + br * iy;
815
702k
                    byte *dptr2 = buf2.b + br * iy;
816
702k
                    byte *dptr3 = buf3.b + br * iy;
817
702k
                    int roll = 7;
818
702k
                    int cmyk = 0;
819
702k
                    byte b = *sptr++ & 0x0f;
820
702k
                    ix = cw;
821
702k
                    goto loop_entry;
822
11.3M
                    do {
823
11.3M
                        b = *sptr++;
824
11.3M
                        roll -= 2;
825
11.3M
                        if (roll < 0)
826
2.64M
                        {
827
2.64M
                            cmyk |= expand_4to1[b & 0xf0]>>1;
828
2.64M
                            *dptr0++ = cmyk>>24;
829
2.64M
                            *dptr1++ = cmyk>>16;
830
2.64M
                            *dptr2++ = cmyk>>8;
831
2.64M
                            *dptr3++ = cmyk;
832
2.64M
                            cmyk = 0;
833
2.64M
                            roll = 7;
834
2.64M
                            b &= 0x0f;
835
2.64M
                        }
836
12.0M
loop_entry:
837
12.0M
                        cmyk |= expand_4to1[b]<<roll;
838
12.0M
                        ix -= 2;
839
12.0M
                    } while (ix >= 0); /* ix == -2 means 1 extra done */
840
702k
                    if ((ix == -2) && (roll == 7)) {
841
                        /* We did an extra one, and it was the last thing
842
                         * we did. Nothing to store. */
843
677k
                    } else {
844
                        /* Flush the stored bytes */
845
677k
                        *dptr0++ = cmyk>>24;
846
677k
                        *dptr1++ = cmyk>>16;
847
677k
                        *dptr2++ = cmyk>>8;
848
677k
                        *dptr3++ = cmyk;
849
677k
                    }
850
702k
                    source_base += sraster;
851
702k
                }
852
492k
            }
853
42.0M
            copy_mono(dev, buf0.b, 0, br, gx_no_bitmap_id, cx, cy, cw, ch,
854
42.0M
                      (gx_color_index)0, (gx_color_index)1);
855
42.0M
            mdev->line_ptrs += mdev->height;
856
42.0M
            copy_mono(dev, buf1.b, 0, br, gx_no_bitmap_id, cx, cy, cw, ch,
857
42.0M
                      (gx_color_index)0, (gx_color_index)1);
858
42.0M
            mdev->line_ptrs += mdev->height;
859
42.0M
            copy_mono(dev, buf2.b, 0, br, gx_no_bitmap_id, cx, cy, cw, ch,
860
42.0M
                      (gx_color_index)0, (gx_color_index)1);
861
42.0M
            mdev->line_ptrs += mdev->height;
862
42.0M
            copy_mono(dev, buf3.b, 0, br, gx_no_bitmap_id, cx, cy, cw, ch,
863
42.0M
                      (gx_color_index)0, (gx_color_index)1);
864
42.0M
            mdev->line_ptrs -= 3*mdev->height;
865
42.0M
        }
866
42.0M
    }
867
42.0M
    MEM_RESTORE_PARAMS(mdev, save);
868
42.0M
    return 0;
869
42.0M
}
870
#endif
871
872
/* Copy a color bitmap. */
873
/* This is slow and messy. */
874
static int
875
mem_planar_copy_color(gx_device * dev, const byte * base, int sourcex,
876
                      int sraster, gx_bitmap_id id,
877
                      int x, int y, int w, int h)
878
987k
{
879
987k
    gx_device_memory * const mdev = (gx_device_memory *)dev;
880
15.2M
#define BUF_LONGS 100   /* arbitrary, >= 1 */
881
15.2M
#define BUF_BYTES (BUF_LONGS * ARCH_SIZEOF_LONG)
882
987k
    union b_ {
883
987k
        ulong l[BUF_LONGS];
884
987k
        byte b[BUF_BYTES];
885
987k
    } buf;
886
987k
    int source_depth = dev->color_info.depth;
887
987k
    mem_save_params_t save;
888
987k
    int pi;
889
890
    /* This routine cannot copy from 3bit chunky data, as 3 bit
891
     * things don't pack nicely into bytes or words. Accordingly
892
     * treat 3 bit things as 4 bit things. This is appropriate as
893
     * 3 bit data will generally have been passed to us as 4bit
894
     * data - such as halftones. */
895
987k
    if (source_depth == 3)
896
0
        source_depth = 4;
897
898
987k
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
899
982k
    MEM_SAVE_PARAMS(mdev, save);
900
8.60M
    for (pi = 0; pi < mdev->num_planar_planes; ++pi) {
901
7.62M
        int plane_depth = mdev->planes[pi].depth;
902
7.62M
        int shift = mdev->planes[pi].shift;
903
7.62M
        gx_color_index mask = ((gx_color_index)1 << plane_depth) - 1;
904
7.62M
        const gdev_mem_functions *fns =
905
7.62M
                               gdev_mem_functions_for_bits(plane_depth);
906
        /*
907
         * Divide up the transfer into chunks that can be assembled
908
         * within the fixed-size buffer.  This code can be simplified
909
         * a lot if all planes have the same depth, by simply using
910
         * copy_color to transfer one column at a time, but it might
911
         * be very inefficient.
912
         */
913
7.62M
        uint plane_raster = bitmap_raster(plane_depth * w);
914
7.62M
        int br, bw, bh, cx, cy, cw, ch, ix, iy;
915
916
7.62M
        MEM_SET_PARAMS(mdev, plane_depth);
917
7.62M
        if (plane_raster > BUF_BYTES) {
918
0
            br = BUF_BYTES;
919
0
            bw = BUF_BYTES * 8 / plane_depth;
920
0
            bh = 1;
921
7.62M
        } else {
922
7.62M
            br = plane_raster;
923
7.62M
            bw = w;
924
7.62M
            bh = BUF_BYTES / plane_raster;
925
7.62M
        }
926
        /*
927
         * We could do the extraction with get_bits_rectangle
928
         * selecting a single plane, but this is critical enough
929
         * code that we more or less replicate it here.
930
         */
931
15.2M
        for (cy = y; cy < y + h; cy += ch) {
932
7.62M
            ch = min(bh, y + h - cy);
933
15.2M
            for (cx = x; cx < x + w; cx += cw) {
934
7.62M
                int sx = sourcex + cx - x;
935
7.62M
                const byte *source_base = base + sraster * (cy - y);
936
7.62M
                int source_bit = 0;
937
938
7.62M
                cw = min(bw, x + w - cx);
939
7.62M
                if (sx) {
940
3.43M
                    int xbit = sx * source_depth;
941
942
3.43M
                    source_base += xbit >> 3;
943
3.43M
                    source_bit = xbit & 7;
944
3.43M
                }
945
18.0M
                for (iy = 0; iy < ch; ++iy) {
946
10.3M
                    const byte *sptr =source_base;
947
10.3M
                    int sbit = source_bit;
948
10.3M
                    byte *dptr = buf.b + br * iy;
949
10.3M
                    int dbit = 0;
950
10.3M
                    byte dbbyte = (dbit ? (byte)(*dptr & (0xff00 >> dbit)) : 0);
951
952
457M
                    for (ix = 0; ix < cw; ++ix) {
953
447M
                        gx_color_index value;
954
955
447M
                        if (sizeof(value) > 4){
956
447M
                            if (sample_load_next64((uint64_t *)&value, &sptr, &sbit, source_depth) < 0)
957
0
                                return_error(gs_error_rangecheck);
958
447M
                        }
959
0
                        else {
960
0
                            if (sample_load_next32((uint32_t *)&value, &sptr, &sbit, source_depth) < 0)
961
0
                                return_error(gs_error_rangecheck);
962
0
                        }
963
447M
                        value = (value >> shift) & mask;
964
447M
                        if (sample_store_next16(value, &dptr, &dbit, plane_depth,
965
447M
                                            &dbbyte) < 0)
966
0
                            return_error(gs_error_rangecheck);
967
447M
                    }
968
10.3M
                    sample_store_flush(dptr, dbit, dbbyte);
969
10.3M
                    source_base += sraster;
970
10.3M
                }
971
                /*
972
                 * Detect and bypass the possibility that copy_color is
973
                 * defined in terms of copy_mono.
974
                 */
975
7.62M
                if (plane_depth == 1)
976
7.62M
                    fns->copy_mono
977
7.62M
                        (dev, buf.b, 0, br, gx_no_bitmap_id, cx, cy, cw, ch,
978
7.62M
                         (gx_color_index)0, (gx_color_index)1);
979
0
                else
980
0
                    fns->copy_color
981
0
                        (dev, buf.b, 0, br, gx_no_bitmap_id, cx, cy, cw, ch);
982
7.62M
            }
983
7.62M
        }
984
7.62M
        mdev->line_ptrs += mdev->height;
985
7.62M
    }
986
982k
    MEM_RESTORE_PARAMS(mdev, save);
987
982k
    return 0;
988
982k
#undef BUF_BYTES
989
982k
#undef BUF_LONGS
990
982k
}
991
992
/* Copy a given bitmap into a bitmap. */
993
static int
994
mem_planar_copy_planes(gx_device * dev, const byte * base, int sourcex,
995
                       int sraster, gx_bitmap_id id,
996
                       int x, int y, int w, int h, int plane_height)
997
563k
{
998
563k
    gx_device_memory * const mdev = (gx_device_memory *)dev;
999
563k
    mem_save_params_t save;
1000
563k
    int code = 0;
1001
563k
    int plane;
1002
1003
563k
    MEM_SAVE_PARAMS(mdev, save);
1004
2.81M
    for (plane = 0; plane < mdev->num_planar_planes; plane++)
1005
2.25M
    {
1006
2.25M
        int plane_depth = mdev->planes[plane].depth;
1007
2.25M
        const gdev_mem_functions *fns =
1008
2.25M
                               gdev_mem_functions_for_bits(plane_depth);
1009
2.25M
        if (plane_depth == 1)
1010
2.24M
            code = fns->copy_mono(dev, base, sourcex, sraster, id,
1011
2.24M
                                  x, y, w, h,
1012
2.24M
                                  (gx_color_index)0, (gx_color_index)1);
1013
6.97k
        else
1014
6.97k
            code = fns->copy_color(dev, base, sourcex, sraster,
1015
6.97k
                                   id, x, y, w, h);
1016
2.25M
        base += sraster * (size_t)plane_height;
1017
2.25M
        mdev->line_ptrs += mdev->height;
1018
2.25M
    }
1019
563k
    MEM_RESTORE_PARAMS(mdev, save);
1020
563k
    return code;
1021
563k
}
1022
1023
int
1024
mem_planar_strip_tile_rect_devn(gx_device * dev, const gx_strip_bitmap * tiles,
1025
                                int x, int y, int w, int h,
1026
                                const gx_drawing_color *pdcolor0,
1027
                                const gx_drawing_color *pdcolor1, int px, int py)
1028
31
{
1029
31
    gx_device_memory * const mdev = (gx_device_memory *)dev;
1030
31
    mem_save_params_t save;
1031
31
    int pi;
1032
1033
31
    MEM_SAVE_PARAMS(mdev, save);
1034
155
    for (pi = 0; pi < mdev->num_planar_planes; ++pi) {
1035
124
        int plane_depth = mdev->planes[pi].depth;
1036
124
        gx_color_index mask = ((gx_color_index)1 << plane_depth) - 1;
1037
124
        int shift = 16 - plane_depth;
1038
124
        const gdev_mem_functions *fns =
1039
124
                               gdev_mem_functions_for_bits(plane_depth);
1040
124
        gx_color_index c1, c0;
1041
1042
124
        if (pdcolor0->type == gx_dc_type_devn) {
1043
0
            c0 = (pdcolor0->colors.devn.values[pi]) >> shift & mask;
1044
124
        } else {
1045
124
            c0 = gx_no_color_index;
1046
124
        }
1047
124
        if (pdcolor1->type == gx_dc_type_devn) {
1048
124
            c1 = (pdcolor1->colors.devn.values[pi]) >> shift & mask;
1049
124
        } else {
1050
0
            c1 = gx_no_color_index;
1051
0
        }
1052
#ifdef DEBUG
1053
        if (c0 == gx_no_color_index && c1 == gx_no_color_index) {
1054
            dprintf("mem_planar_strip_tile_rect_dev called with two non-devn colors\n");
1055
        }
1056
#endif
1057
124
        MEM_SET_PARAMS(mdev, plane_depth);
1058
124
        if (c0 == c1)
1059
0
            fns->fill_rectangle(dev, x, y, w, h, c0);
1060
124
        else {
1061
            /*
1062
             * Temporarily replace copy_mono in case strip_tile_rectangle is
1063
             * defined in terms of it.
1064
             */
1065
124
            set_dev_proc(dev, copy_mono, fns->copy_mono);
1066
124
            fns->strip_tile_rectangle(dev, tiles, x, y, w, h, c0, c1, px, py);
1067
124
        }
1068
124
        mdev->line_ptrs += mdev->height;
1069
124
    }
1070
31
    MEM_RESTORE_PARAMS(mdev, save);
1071
31
    set_dev_proc(dev, copy_mono, mem_planar_copy_mono);
1072
31
    return 0;
1073
31
}
1074
1075
int
1076
mem_planar_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tiles,
1077
                                int x, int y, int w, int h,
1078
                                gx_color_index color0, gx_color_index color1,
1079
                                int px, int py)
1080
16.5M
{
1081
16.5M
    gx_device_memory * const mdev = (gx_device_memory *)dev;
1082
16.5M
    mem_save_params_t save;
1083
16.5M
    int pi;
1084
1085
    /* We can't split up the transfer if the tile is colored. */
1086
16.5M
    if (color0 == gx_no_color_index && color1 == gx_no_color_index)
1087
22.9k
        return gx_default_strip_tile_rectangle
1088
22.9k
            (dev, tiles, x, y, w, h, color0, color1, px, py);
1089
16.5M
    MEM_SAVE_PARAMS(mdev, save);
1090
88.0M
    for (pi = 0; pi < mdev->num_planar_planes; ++pi) {
1091
71.4M
        int plane_depth = mdev->planes[pi].depth;
1092
71.4M
        int shift = mdev->planes[pi].shift;
1093
71.4M
        gx_color_index mask = ((gx_color_index)1 << plane_depth) - 1;
1094
71.4M
        const gdev_mem_functions *fns =
1095
71.4M
                               gdev_mem_functions_for_bits(plane_depth);
1096
71.4M
        gx_color_index c0 =
1097
71.4M
            (color0 == gx_no_color_index ? gx_no_color_index :
1098
71.4M
             (color0 >> shift) & mask);
1099
71.4M
        gx_color_index c1 =
1100
71.4M
            (color1 == gx_no_color_index ? gx_no_color_index :
1101
71.4M
             (color1 >> shift) & mask);
1102
1103
71.4M
        MEM_SET_PARAMS(mdev, plane_depth);
1104
71.4M
        if (c0 == c1)
1105
54.8M
            fns->fill_rectangle(dev, x, y, w, h, c0);
1106
16.5M
        else {
1107
            /*
1108
             * Temporarily replace copy_mono in case strip_tile_rectangle is
1109
             * defined in terms of it.
1110
             */
1111
16.5M
            set_dev_proc(dev, copy_mono, fns->copy_mono);
1112
16.5M
            fns->strip_tile_rectangle(dev, tiles, x, y, w, h, c0, c1, px, py);
1113
16.5M
        }
1114
71.4M
        mdev->line_ptrs += mdev->height;
1115
71.4M
    }
1116
16.5M
    MEM_RESTORE_PARAMS(mdev, save);
1117
16.5M
    set_dev_proc(dev, copy_mono, mem_planar_copy_mono);
1118
16.5M
    return 0;
1119
16.5M
}
1120
1121
static int
1122
planar_cmyk4bit_strip_copy_rop2(gx_device_memory * mdev,
1123
                                const byte * srow, int sourcex, uint sraster,
1124
                                gx_bitmap_id id, const gx_color_index * scolors,
1125
                                const gx_strip_bitmap * textures,
1126
                                const gx_color_index * tcolors,
1127
                                int x, int y, int width, int height,
1128
                                int phase_x, int phase_y,
1129
                                gs_logical_operation_t lop,
1130
                                uint planar_height)
1131
0
{
1132
0
    gs_rop3_t rop = (gs_rop3_t)lop;
1133
0
    intptr_t draster = mdev->raster;
1134
0
    int line_count;
1135
0
    byte *cdrow, *mdrow, *ydrow, *kdrow;
1136
0
    byte lmask, rmask;
1137
0
    rop_proc cproc = NULL, mproc = NULL, yproc = NULL;
1138
0
    int dbit;
1139
0
    int cscolor = 0, mscolor = 0, yscolor = 0, kscolor = 0;
1140
0
    int ctcolor = 0, mtcolor = 0, ytcolor = 0, ktcolor = 0;
1141
0
    int constant_s = 0;
1142
1143
    /* assert(planar_height == 0) */
1144
1145
    /* Modify the raster operation according to the source palette. */
1146
0
    fit_copy(mdev, srow, sourcex, sraster, id, x, y, width, height);
1147
1148
    /* This function assumes constant (or unused) scolors and tcolors */
1149
0
    if (scolors)
1150
0
    {
1151
0
        if (scolors[0] == scolors[1]) {
1152
0
            kscolor = ((scolors[0] & 1) ? -1 : 0);
1153
0
            cscolor = ((scolors[0] & 8) ? -1 : 0) | kscolor;
1154
0
            mscolor = ((scolors[0] & 4) ? -1 : 0) | kscolor;
1155
0
            yscolor = ((scolors[0] & 2) ? -1 : 0) | kscolor;
1156
0
            constant_s = 1;
1157
0
        } else {
1158
0
            kscolor =  (scolors[0] & 1)     | ((scolors[1] & 1)<<1);
1159
0
            cscolor = ((scolors[0] & 8)>>3) | ((scolors[1] & 8)>>2) | kscolor;
1160
0
            mscolor = ((scolors[0] & 4)>>2) | ((scolors[1] & 4)>>1) | kscolor;
1161
0
            yscolor = ((scolors[0] & 2)>>1) |  (scolors[1] & 2)     | kscolor;
1162
0
            switch (cscolor) {
1163
0
                case 0:
1164
0
                    cproc = rop_proc_table[rop3_know_S_0(rop)];
1165
0
                    break;
1166
0
                case 1:
1167
0
                    cproc = rop_proc_table[rop3_invert_S(rop)];
1168
0
                    break;
1169
0
                case 2:
1170
0
                    cproc = rop_proc_table[rop];
1171
0
                    break;
1172
0
                default: /* 3 */
1173
0
                    cproc = rop_proc_table[rop3_know_S_1(rop)];
1174
0
                    break;
1175
0
            }
1176
0
            switch (mscolor) {
1177
0
                case 0:
1178
0
                    mproc = rop_proc_table[rop3_know_S_0(rop)];
1179
0
                    break;
1180
0
                case 1:
1181
0
                    mproc = rop_proc_table[rop3_invert_S(rop)];
1182
0
                    break;
1183
0
                case 2:
1184
0
                    mproc = rop_proc_table[rop];
1185
0
                    break;
1186
0
                default: /* 3 */
1187
0
                    mproc = rop_proc_table[rop3_know_S_1(rop)];
1188
0
                    break;
1189
0
            }
1190
0
            switch (yscolor) {
1191
0
                case 0:
1192
0
                    yproc = rop_proc_table[rop3_know_S_0(rop)];
1193
0
                    break;
1194
0
                case 1:
1195
0
                    yproc = rop_proc_table[rop3_invert_S(rop)];
1196
0
                    break;
1197
0
                case 2:
1198
0
                    yproc = rop_proc_table[rop];
1199
0
                    break;
1200
0
                default: /* 3 */
1201
0
                    yproc = rop_proc_table[rop3_know_S_1(rop)];
1202
0
                    break;
1203
0
            }
1204
0
        }
1205
0
    }
1206
0
    if (tcolors)
1207
0
    {
1208
0
        ktcolor = ((tcolors[0] & 1) ? -1 : 0);
1209
0
        ctcolor = ((tcolors[0] & 8) ? -1 : 0) | ktcolor;
1210
0
        mtcolor = ((tcolors[0] & 4) ? -1 : 0) | ktcolor;
1211
0
        ytcolor = ((tcolors[0] & 2) ? -1 : 0) | ktcolor;
1212
0
    }
1213
1214
    /* Set up transfer parameters. */
1215
0
    line_count = height;
1216
0
    if (lop_uses_T(lop) && (tcolors == NULL)) { /* && (textures != NULL) */
1217
        /* Pixmap textures. For now we'll only get into this routine if
1218
         * textures is a pixmap (or constant, in which case we'll do it
1219
         * below). */
1220
0
        int ty;
1221
0
        intptr_t traster;
1222
1223
/* Calculate the X offset for a given Y value, */
1224
/* taking shift into account if necessary. */
1225
0
#define x_offset(px, ty, textures)\
1226
0
  ((textures)->shift == 0 ? (px) :\
1227
0
   (px) + (ty) / (textures)->rep_height * (textures)->rep_shift)
1228
1229
0
        cdrow = scan_line_base(mdev, y);
1230
0
        mdrow = cdrow + mdev->height * draster;
1231
0
        ydrow = mdrow + mdev->height * draster;
1232
0
        kdrow = ydrow + mdev->height * draster;
1233
0
        if (!textures)
1234
0
            return 0;
1235
0
        traster = textures->raster;
1236
0
        ty = y + phase_y;
1237
0
        for (; line_count-- > 0; cdrow += draster, mdrow += draster, ydrow += draster, kdrow += draster, srow += sraster, ++ty) {
1238
0
            int sx = sourcex;
1239
0
            int dx = x;
1240
0
            int w = width;
1241
0
            const byte *trow = textures->data + (ty % textures->rep_height) * traster;
1242
0
            int xoff = x_offset(phase_x, ty, textures);
1243
0
            int nw;
1244
0
            int tx = (dx + xoff) % textures->rep_width;
1245
1246
            /* Loop over (horizontal) copies of the tile. */
1247
0
            for (; w > 0; sx += nw, dx += nw, w -= nw, tx = 0) {
1248
                /* sptr and tptr point to bytes of cmykcmyk. Need to convert
1249
                 * these to planar format. */
1250
0
                int dbit = dx & 7;
1251
0
                int tbit = tx & 1;
1252
0
                int tskew = tbit - dbit; /* -7 >= tskew >= 1 */
1253
0
                int left = (nw = min(w, textures->size.x - tx))-8+dbit;
1254
0
                int sbit = sx & 1;
1255
0
                int sskew = sbit - dbit; /* -7 >= sskew >= 1 */
1256
0
                byte lmask = 0xff >> dbit;
1257
0
                byte rmask = 0xff << (~(dbit + nw - 1) & 7);
1258
0
                byte *cdptr = cdrow + (dx>>3);
1259
0
                byte *mdptr = mdrow + (dx>>3);
1260
0
                byte *ydptr = ydrow + (dx>>3);
1261
0
                byte *kdptr = kdrow + (dx>>3);
1262
0
                const byte *tptr = trow;
1263
0
                const rop_proc proc = rop_proc_table[rop];
1264
0
                const byte *sptr = srow;
1265
0
                sptr += (sskew>>1); /* Backtrack sptr if required. */
1266
0
                sptr += (sx>>1);
1267
0
                tptr += (tskew>>1); /* Backtrack tptr if required. */
1268
0
                tptr += (tx>>1);
1269
0
                if (left < 0)
1270
0
                    lmask &= rmask;
1271
0
                {
1272
                    /* Left hand bytes */
1273
0
                    byte kdbyte = *kdptr;
1274
0
                    byte cdbyte = *cdptr;
1275
0
                    byte mdbyte = *mdptr;
1276
0
                    byte ydbyte = *ydptr;
1277
0
                    byte cresult, mresult, yresult, kresult;
1278
0
                    bits32 scol = 0, tcol = 0;
1279
0
                    if ((sskew & 1) == 0) {
1280
0
                        if (sskew >= 0)
1281
0
                            scol = expand_4to1[sptr[0]]<<6;
1282
0
                        if ((sskew >= -2) && (left > -6))
1283
0
                            scol |= expand_4to1[sptr[1]]<<4;
1284
0
                        if ((sskew >= -4) && (left > -4))
1285
0
                            scol |= expand_4to1[sptr[2]]<<2;
1286
0
                        if (left > -2)
1287
0
                            scol |= expand_4to1[sptr[3]];
1288
0
                    } else {
1289
0
                        if (sskew >= 0)
1290
0
                            scol = expand_4to1[sptr[0] & 0x0f]<<7;
1291
0
                        if ((sskew >= -2) && (left > -7))
1292
0
                            scol |= expand_4to1[sptr[1]]<<5;
1293
0
                        if ((sskew >= -4) && (left > -5))
1294
0
                            scol |= expand_4to1[sptr[2]]<<3;
1295
0
                        if ((sskew >= -6) && (left > -3))
1296
0
                            scol |= expand_4to1[sptr[3]]<<1;
1297
0
                        if (left > -1)
1298
0
                            scol |= expand_4to1[sptr[4] & 0xf0]>>1;
1299
0
                    }
1300
0
                    if ((tskew & 1) == 0) {
1301
0
                        if (tskew >= 0)
1302
0
                            tcol = expand_4to1[tptr[0]]<<6;
1303
0
                        if ((tskew >= -2) && (left > -6))
1304
0
                            tcol |= expand_4to1[tptr[1]]<<4;
1305
0
                        if ((tskew >= -4) && (left > -4))
1306
0
                            tcol |= expand_4to1[tptr[2]]<<2;
1307
0
                        if (left > -2)
1308
0
                            tcol |= expand_4to1[tptr[3]];
1309
0
                    } else {
1310
0
                        if (tskew >= 0)
1311
0
                            tcol = expand_4to1[tptr[0] & 0x0f]<<7;
1312
0
                        if ((tskew >= -2) && (left > -7))
1313
0
                            tcol |= expand_4to1[tptr[1]]<<5;
1314
0
                        if ((tskew >= -4) && (left > -5))
1315
0
                            tcol |= expand_4to1[tptr[2]]<<3;
1316
0
                        if ((tskew >= -6) && (left > -3))
1317
0
                            tcol |= expand_4to1[tptr[3]]<<1;
1318
0
                        if (left > -1)
1319
0
                            tcol |= expand_4to1[tptr[4] & 0xf0]>>1;
1320
0
                    }
1321
0
                    cresult = (*proc)(cdbyte | kdbyte,scol|(scol>>24),tcol|(tcol>>24));
1322
0
                    mresult = (*proc)(mdbyte | kdbyte,scol|(scol>>16),tcol|(tcol>>16));
1323
0
                    yresult = (*proc)(ydbyte | kdbyte,scol|(scol>> 8),tcol|(tcol>> 8));
1324
0
                    kresult = cresult & mresult & yresult;
1325
0
                    cresult &= ~kresult;
1326
0
                    mresult &= ~kresult;
1327
0
                    yresult &= ~kresult;
1328
0
                    *cdptr++ = (cresult & lmask) | (cdbyte & ~lmask);
1329
0
                    *mdptr++ = (mresult & lmask) | (mdbyte & ~lmask);
1330
0
                    *ydptr++ = (yresult & lmask) | (ydbyte & ~lmask);
1331
0
                    *kdptr++ = (kresult & lmask) | (kdbyte & ~lmask);
1332
0
                }
1333
0
                if (left <= 0) /* if (width <= 8) we're done */
1334
0
                    continue;
1335
0
                sptr += 4;
1336
0
                tptr += 4;
1337
0
                left -= 8; /* left = bits to go - 8 */
1338
0
                while (left > 0)
1339
0
                {
1340
0
                    byte kdbyte = *kdptr;
1341
0
                    byte cdbyte = *cdptr | kdbyte;
1342
0
                    byte mdbyte = *mdptr | kdbyte;
1343
0
                    byte ydbyte = *ydptr | kdbyte;
1344
0
                    byte cresult, mresult, yresult, kresult;
1345
0
                    bits32 scol, tcol;
1346
0
                    if ((sskew & 1) == 0) {
1347
0
                        scol  = expand_4to1[sptr[0]]<<6;
1348
0
                        scol |= expand_4to1[sptr[1]]<<4;
1349
0
                        scol |= expand_4to1[sptr[2]]<<2;
1350
0
                        scol |= expand_4to1[sptr[3]];
1351
0
                    } else {
1352
0
                        scol  = expand_4to1[sptr[0] & 0x0f]<<7;
1353
0
                        scol |= expand_4to1[sptr[1]]<<5;
1354
0
                        scol |= expand_4to1[sptr[2]]<<3;
1355
0
                        scol |= expand_4to1[sptr[3]]<<1;
1356
0
                        scol |= expand_4to1[sptr[4] & 0xf0]>>1;
1357
0
                    }
1358
0
                    if ((tskew & 1) == 0) {
1359
0
                        tcol  = expand_4to1[tptr[0]]<<6;
1360
0
                        tcol |= expand_4to1[tptr[1]]<<4;
1361
0
                        tcol |= expand_4to1[tptr[2]]<<2;
1362
0
                        tcol |= expand_4to1[tptr[3]];
1363
0
                    } else {
1364
0
                        tcol  = expand_4to1[tptr[0] & 0x0f]<<7;
1365
0
                        tcol |= expand_4to1[tptr[1]]<<5;
1366
0
                        tcol |= expand_4to1[tptr[2]]<<3;
1367
0
                        tcol |= expand_4to1[tptr[3]]<<1;
1368
0
                        tcol |= expand_4to1[tptr[4] & 0xf0]>>1;
1369
0
                    }
1370
0
                    cresult = (*proc)(cdbyte | kdbyte,scol|(scol>>24),tcol|(tcol>>24));
1371
0
                    mresult = (*proc)(mdbyte | kdbyte,scol|(scol>>16),tcol|(tcol>>16));
1372
0
                    yresult = (*proc)(ydbyte | kdbyte,scol|(scol>> 8),tcol|(tcol>> 8));
1373
0
                    kresult = cresult & mresult & yresult;
1374
0
                    cresult &= ~kresult;
1375
0
                    mresult &= ~kresult;
1376
0
                    yresult &= ~kresult;
1377
0
                    *cdptr++ = cresult & ~kresult;
1378
0
                    *mdptr++ = mresult & ~kresult;
1379
0
                    *ydptr++ = yresult & ~kresult;
1380
0
                    *kdptr++ = kresult;
1381
0
                    sptr += 4;
1382
0
                    tptr += 4;
1383
0
                    left -= 8;
1384
0
                }
1385
0
                {
1386
0
                    byte kdbyte = *kdptr;
1387
0
                    byte cdbyte = *cdptr;
1388
0
                    byte mdbyte = *mdptr;
1389
0
                    byte ydbyte = *ydptr;
1390
0
                    byte cresult, mresult, yresult, kresult;
1391
0
                    bits32 scol, tcol;
1392
0
                    if ((sskew & 1) == 0) {
1393
0
                        scol = expand_4to1[sptr[0]]<<6;
1394
0
                        if (left > -6)
1395
0
                            scol |= expand_4to1[sptr[1]]<<4;
1396
0
                        if (left > -4)
1397
0
                            scol |= expand_4to1[sptr[2]]<<2;
1398
0
                        if (left > -2)
1399
0
                            scol |= expand_4to1[sptr[3]];
1400
0
                    } else {
1401
0
                        scol = expand_4to1[sptr[0] & 0x0f]<<7;
1402
0
                        if (left > -7)
1403
0
                            scol |= expand_4to1[sptr[1]]<<5;
1404
0
                        if (left > -5)
1405
0
                            scol |= expand_4to1[sptr[2]]<<3;
1406
0
                        if (left > -3)
1407
0
                            scol |= expand_4to1[sptr[3]]<<1;
1408
0
                        if (left > -1)
1409
0
                            scol |= expand_4to1[sptr[4] & 0xf0]>>1;
1410
0
                    }
1411
0
                    if ((tskew & 1) == 0) {
1412
0
                        tcol = expand_4to1[tptr[0]]<<6;
1413
0
                        if (left > -6)
1414
0
                            tcol |= expand_4to1[tptr[1]]<<4;
1415
0
                        if (left > -4)
1416
0
                            tcol |= expand_4to1[tptr[2]]<<2;
1417
0
                        if (left > -2)
1418
0
                            tcol |= expand_4to1[tptr[3]];
1419
0
                    } else {
1420
0
                        tcol = expand_4to1[tptr[0] & 0x0f]<<7;
1421
0
                        if (left > -7)
1422
0
                            tcol |= expand_4to1[tptr[1]]<<5;
1423
0
                        if (left > -5)
1424
0
                            tcol |= expand_4to1[tptr[2]]<<3;
1425
0
                        if (left > -3)
1426
0
                            tcol |= expand_4to1[tptr[3]]<<1;
1427
0
                        if (left > -1)
1428
0
                            tcol |= expand_4to1[tptr[4] & 0xf0]>>1;
1429
0
                    }
1430
0
                    cresult = (*proc)(cdbyte | kdbyte,scol|(scol>>24),tcol|(tcol>>24));
1431
0
                    mresult = (*proc)(mdbyte | kdbyte,scol|(scol>>16),tcol|(tcol>>16));
1432
0
                    yresult = (*proc)(ydbyte | kdbyte,scol|(scol>> 8),tcol|(tcol>> 8));
1433
0
                    kresult = cresult & mresult & yresult;
1434
0
                    cresult &= ~kresult;
1435
0
                    mresult &= ~kresult;
1436
0
                    yresult &= ~kresult;
1437
0
                    *cdptr++ = (cresult & rmask) | (cdbyte & ~rmask);
1438
0
                    *mdptr++ = (mresult & rmask) | (mdbyte & ~rmask);
1439
0
                    *ydptr++ = (yresult & rmask) | (ydbyte & ~rmask);
1440
0
                    *kdptr++ = (kresult & rmask) | (kdbyte & ~rmask);
1441
0
                }
1442
0
            }
1443
0
        }
1444
0
        return 0;
1445
0
    }
1446
    /* Texture constant (or unimportant) cases */
1447
0
    dbit = x & 7;
1448
0
    cdrow = scan_line_base(mdev, y) + (x>>3);
1449
0
    mdrow = cdrow + mdev->height * draster;
1450
0
    ydrow = mdrow + mdev->height * draster;
1451
0
    kdrow = ydrow + mdev->height * draster;
1452
0
    lmask = 0xff >> dbit;
1453
0
    width += dbit;
1454
0
    rmask = 0xff << (~(width - 1) & 7);
1455
0
    if (width < 8)
1456
0
        lmask &= rmask;
1457
0
    if (scolors == NULL) {
1458
        /* sptr points to bytes of cmykcmyk. Need to convert these to
1459
         * planar format. */
1460
0
        const rop_proc proc = rop_proc_table[rop];
1461
0
        int sbit = sourcex & 1;
1462
0
        int sskew = sbit - dbit; /* -7 >= sskew >= 1 */
1463
0
        srow += (sskew>>1); /* Backtrack srow if required. */
1464
0
        srow += (sourcex>>1);
1465
0
        for (; line_count-- > 0; cdrow += draster, mdrow += draster, ydrow += draster, kdrow += draster, srow += sraster) {
1466
0
            byte *cdptr = cdrow;
1467
0
            byte *mdptr = mdrow;
1468
0
            byte *ydptr = ydrow;
1469
0
            byte *kdptr = kdrow;
1470
0
            const byte *sptr = srow;
1471
0
            int left = width-8;
1472
0
            {
1473
                /* Left hand bytes */
1474
0
                byte kdbyte = *kdptr;
1475
0
                byte cdbyte = *cdptr;
1476
0
                byte mdbyte = *mdptr;
1477
0
                byte ydbyte = *ydptr;
1478
0
                byte cresult, mresult, yresult, kresult;
1479
0
                bits32 scol = 0;
1480
0
                if ((sskew & 1) == 0) {
1481
0
                    if (sskew >= 0)
1482
0
                        scol = expand_4to1[sptr[0]]<<6;
1483
0
                    if ((sskew >= -2) && (left > -6))
1484
0
                        scol |= expand_4to1[sptr[1]]<<4;
1485
0
                    if ((sskew >= -4) && (left > -4))
1486
0
                        scol |= expand_4to1[sptr[2]]<<2;
1487
0
                    if (left > -2)
1488
0
                        scol |= expand_4to1[sptr[3]];
1489
0
                } else {
1490
0
                    if (sskew >= 0)
1491
0
                        scol = expand_4to1[sptr[0] & 0x0f]<<7;
1492
0
                    if ((sskew >= -2) && (left > -7))
1493
0
                        scol |= expand_4to1[sptr[1]]<<5;
1494
0
                    if ((sskew >= -4) && (left > -5))
1495
0
                        scol |= expand_4to1[sptr[2]]<<3;
1496
0
                    if ((sskew >= -6) && (left > -3))
1497
0
                        scol |= expand_4to1[sptr[3]]<<1;
1498
0
                    if (left > -1)
1499
0
                        scol |= expand_4to1[sptr[4] & 0xf0]>>1;
1500
0
                }
1501
0
                cresult = (*proc)(cdbyte | kdbyte,scol|(scol>>24),ctcolor);
1502
0
                mresult = (*proc)(mdbyte | kdbyte,scol|(scol>>16),mtcolor);
1503
0
                yresult = (*proc)(ydbyte | kdbyte,scol|(scol>> 8),ytcolor);
1504
0
                kresult = cresult & mresult & yresult;
1505
0
                cresult &= ~kresult;
1506
0
                mresult &= ~kresult;
1507
0
                yresult &= ~kresult;
1508
0
                *cdptr++ = (cresult & lmask) | (cdbyte & ~lmask);
1509
0
                *mdptr++ = (mresult & lmask) | (mdbyte & ~lmask);
1510
0
                *ydptr++ = (yresult & lmask) | (ydbyte & ~lmask);
1511
0
                *kdptr++ = (kresult & lmask) | (kdbyte & ~lmask);
1512
0
            }
1513
0
            if (left <= 0) /* if (width <= 8) we're done */
1514
0
                continue;
1515
0
            sptr += 4;
1516
0
            left -= 8; /* left = bits to go - 8 */
1517
0
            while (left > 0)
1518
0
            {
1519
0
                byte kdbyte = *kdptr;
1520
0
                byte cdbyte = *cdptr | kdbyte;
1521
0
                byte mdbyte = *mdptr | kdbyte;
1522
0
                byte ydbyte = *ydptr | kdbyte;
1523
0
                byte cresult, mresult, yresult, kresult;
1524
0
                bits32 scol;
1525
0
                if ((sskew & 1) == 0) {
1526
0
                    scol  = expand_4to1[sptr[0]]<<6;
1527
0
                    scol |= expand_4to1[sptr[1]]<<4;
1528
0
                    scol |= expand_4to1[sptr[2]]<<2;
1529
0
                    scol |= expand_4to1[sptr[3]];
1530
0
                } else {
1531
0
                    scol  = expand_4to1[sptr[0] & 0x0f]<<7;
1532
0
                    scol |= expand_4to1[sptr[1]]<<5;
1533
0
                    scol |= expand_4to1[sptr[2]]<<3;
1534
0
                    scol |= expand_4to1[sptr[3]]<<1;
1535
0
                    scol |= expand_4to1[sptr[4] & 0xf0]>>1;
1536
0
                }
1537
0
                cresult = (*proc)(cdbyte | kdbyte,scol|(scol>>24),ctcolor);
1538
0
                mresult = (*proc)(mdbyte | kdbyte,scol|(scol>>16),mtcolor);
1539
0
                yresult = (*proc)(ydbyte | kdbyte,scol|(scol>> 8),ytcolor);
1540
0
                kresult = cresult & mresult & yresult;
1541
0
                cresult &= ~kresult;
1542
0
                mresult &= ~kresult;
1543
0
                yresult &= ~kresult;
1544
0
                *cdptr++ = cresult & ~kresult;
1545
0
                *mdptr++ = mresult & ~kresult;
1546
0
                *ydptr++ = yresult & ~kresult;
1547
0
                *kdptr++ = kresult;
1548
0
                sptr += 4;
1549
0
                left -= 8;
1550
0
            }
1551
0
            {
1552
0
                byte kdbyte = *kdptr;
1553
0
                byte cdbyte = *cdptr;
1554
0
                byte mdbyte = *mdptr;
1555
0
                byte ydbyte = *ydptr;
1556
0
                byte cresult, mresult, yresult, kresult;
1557
0
                bits32 scol;
1558
0
                if ((sskew & 1) == 0) {
1559
0
                    scol = expand_4to1[sptr[0]]<<6;
1560
0
                    if (left > -6)
1561
0
                        scol |= expand_4to1[sptr[1]]<<4;
1562
0
                    if (left > -4)
1563
0
                        scol |= expand_4to1[sptr[2]]<<2;
1564
0
                    if (left > -2)
1565
0
                        scol |= expand_4to1[sptr[3]];
1566
0
                } else {
1567
0
                    scol = expand_4to1[sptr[0] & 0x0f]<<7;
1568
0
                    if (left > -7)
1569
0
                        scol |= expand_4to1[sptr[1]]<<5;
1570
0
                    if (left > -5)
1571
0
                        scol |= expand_4to1[sptr[2]]<<3;
1572
0
                    if (left > -3)
1573
0
                        scol |= expand_4to1[sptr[3]]<<1;
1574
0
                    if (left > -1)
1575
0
                        scol |= expand_4to1[sptr[4] & 0xf0]>>1;
1576
0
                }
1577
0
                cresult = (*proc)(cdbyte | kdbyte,scol|(scol>>24),ctcolor);
1578
0
                mresult = (*proc)(mdbyte | kdbyte,scol|(scol>>16),mtcolor);
1579
0
                yresult = (*proc)(ydbyte | kdbyte,scol|(scol>> 8),ytcolor);
1580
0
                kresult = cresult & mresult & yresult;
1581
0
                cresult &= ~kresult;
1582
0
                mresult &= ~kresult;
1583
0
                yresult &= ~kresult;
1584
0
                *cdptr++ = (cresult & rmask) | (cdbyte & ~rmask);
1585
0
                *mdptr++ = (mresult & rmask) | (mdbyte & ~rmask);
1586
0
                *ydptr++ = (yresult & rmask) | (ydbyte & ~rmask);
1587
0
                *kdptr++ = (kresult & rmask) | (kdbyte & ~rmask);
1588
0
            }
1589
0
        }
1590
0
    } else if (constant_s) {
1591
0
        const rop_proc proc = rop_proc_table[rop];
1592
0
        for (; line_count-- > 0; cdrow += draster, mdrow += draster, ydrow += draster, kdrow += draster) {
1593
0
            byte *cdptr = cdrow;
1594
0
            byte *mdptr = mdrow;
1595
0
            byte *ydptr = ydrow;
1596
0
            byte *kdptr = kdrow;
1597
0
            int left = width-8;
1598
0
            {
1599
                /* Left hand bytes */
1600
0
                byte kdbyte = *kdptr;
1601
0
                byte cdbyte = *cdptr;
1602
0
                byte mdbyte = *mdptr;
1603
0
                byte ydbyte = *ydptr;
1604
0
                byte cresult = (*proc)(cdbyte | kdbyte,cscolor,ctcolor);
1605
0
                byte mresult = (*proc)(mdbyte | kdbyte,mscolor,mtcolor);
1606
0
                byte yresult = (*proc)(ydbyte | kdbyte,yscolor,ytcolor);
1607
0
                byte kresult = cresult & mresult & yresult;
1608
0
                cresult &= ~kresult;
1609
0
                mresult &= ~kresult;
1610
0
                yresult &= ~kresult;
1611
0
                *cdptr++ = (cresult & lmask) | (cdbyte & ~lmask);
1612
0
                *mdptr++ = (mresult & lmask) | (mdbyte & ~lmask);
1613
0
                *ydptr++ = (yresult & lmask) | (ydbyte & ~lmask);
1614
0
                *kdptr++ = (kresult & lmask) | (kdbyte & ~lmask);
1615
0
            }
1616
0
            if (left <= 0) /* if (width <= 8) we're done */
1617
0
                continue;
1618
0
            left -= 8; /* left = bits to go - 8 */
1619
0
            while (left > 0)
1620
0
            {
1621
0
                byte kdbyte = *kdptr;
1622
0
                byte cdbyte = *cdptr | kdbyte;
1623
0
                byte mdbyte = *mdptr | kdbyte;
1624
0
                byte ydbyte = *ydptr | kdbyte;
1625
0
                byte cresult = (*proc)(cdbyte,cscolor,ctcolor);
1626
0
                byte mresult = (*proc)(mdbyte,mscolor,mtcolor);
1627
0
                byte yresult = (*proc)(ydbyte,yscolor,ytcolor);
1628
0
                byte kresult = cresult & mresult & yresult;
1629
0
                cresult &= ~kresult;
1630
0
                mresult &= ~kresult;
1631
0
                yresult &= ~kresult;
1632
0
                *cdptr++ = cresult & ~kresult;
1633
0
                *mdptr++ = mresult & ~kresult;
1634
0
                *ydptr++ = yresult & ~kresult;
1635
0
                *kdptr++ = kresult;
1636
0
                left -= 8;
1637
0
            }
1638
0
            {
1639
0
                byte kdbyte = *kdptr;
1640
0
                byte cdbyte = *cdptr;
1641
0
                byte mdbyte = *mdptr;
1642
0
                byte ydbyte = *ydptr;
1643
0
                byte cresult = (*proc)(cdbyte | kdbyte,cscolor,ctcolor);
1644
0
                byte mresult = (*proc)(mdbyte | kdbyte,mscolor,mtcolor);
1645
0
                byte yresult = (*proc)(ydbyte | kdbyte,yscolor,ytcolor);
1646
0
                byte kresult = cresult & mresult & yresult;
1647
0
                cresult &= ~kresult;
1648
0
                mresult &= ~kresult;
1649
0
                yresult &= ~kresult;
1650
0
                *cdptr++ = (cresult & rmask) | (cdbyte & ~rmask);
1651
0
                *mdptr++ = (mresult & rmask) | (mdbyte & ~rmask);
1652
0
                *ydptr++ = (yresult & rmask) | (ydbyte & ~rmask);
1653
0
                *kdptr++ = (kresult & rmask) | (kdbyte & ~rmask);
1654
0
            }
1655
0
        }
1656
0
    } else {
1657
        /* Constant T, bitmap S */
1658
0
        int sbit = sourcex & 7;
1659
0
        int sskew = sbit - dbit;
1660
0
        if (sskew < 0)
1661
0
            --srow, sskew += 8;
1662
0
        srow += (sourcex>>3);
1663
0
        for (; line_count-- > 0; cdrow += draster, mdrow += draster, ydrow += draster, kdrow += draster, srow += sraster) {
1664
0
            const byte *sptr = srow;
1665
0
            byte *cdptr = cdrow;
1666
0
            byte *mdptr = mdrow;
1667
0
            byte *ydptr = ydrow;
1668
0
            byte *kdptr = kdrow;
1669
0
            int left = width-8;
1670
0
            {
1671
                /* Left hand byte (maybe the only one) */
1672
0
                byte kdbyte = *kdptr;
1673
0
                byte cdbyte = *cdptr;
1674
0
                byte mdbyte = *mdptr;
1675
0
                byte ydbyte = *ydptr;
1676
0
#define fetch1(ptr, skew)\
1677
0
  (skew ? (ptr[0] << skew) + (ptr[1] >> (8 - skew)) : *ptr)
1678
0
                byte sbyte = fetch1(sptr, sskew);
1679
0
                byte cresult = (*cproc)(cdbyte|kdbyte,sbyte,ctcolor);
1680
0
                byte mresult = (*mproc)(mdbyte|kdbyte,sbyte,mtcolor);
1681
0
                byte yresult = (*yproc)(ydbyte|kdbyte,sbyte,ytcolor);
1682
0
                byte kresult = cresult & mresult & yresult;
1683
0
                cresult &= ~kresult;
1684
0
                mresult &= ~kresult;
1685
0
                yresult &= ~kresult;
1686
0
                *cdptr++ = (cresult & lmask) | (cdbyte & ~lmask);
1687
0
                *mdptr++ = (mresult & lmask) | (mdbyte & ~lmask);
1688
0
                *ydptr++ = (yresult & lmask) | (ydbyte & ~lmask);
1689
0
                *kdptr++ = (kresult & lmask) | (kdbyte & ~lmask);
1690
0
                sptr++;
1691
0
                left -= 8;
1692
0
            }
1693
0
            while (left > 0) {
1694
                /* Bytes where all 8 bits of S are needed */
1695
0
                byte kdbyte = *kdptr;
1696
0
                byte cdbyte = *cdptr | kdbyte;
1697
0
                byte mdbyte = *mdptr | kdbyte;
1698
0
                byte ydbyte = *ydptr | kdbyte;
1699
0
                byte sbyte = fetch1(sptr, sskew);
1700
0
                byte cresult = (*cproc)(cdbyte,sbyte,ctcolor);
1701
0
                byte mresult = (*mproc)(mdbyte,sbyte,mtcolor);
1702
0
                byte yresult = (*yproc)(ydbyte,sbyte,ytcolor);
1703
0
                byte kresult = cresult & mresult & yresult;
1704
0
                *cdptr++ = cresult & ~kresult;
1705
0
                *mdptr++ = mresult & ~kresult;
1706
0
                *ydptr++ = yresult & ~kresult;
1707
0
                *kdptr++ = kresult;
1708
0
                sptr++;
1709
0
                left -= 8;
1710
0
            }
1711
            /* Final byte */
1712
0
            if (left > -8) {
1713
0
                byte kdbyte = *kdptr;
1714
0
                byte cdbyte = *cdptr;
1715
0
                byte mdbyte = *mdptr;
1716
0
                byte ydbyte = *ydptr;
1717
0
                byte sbyte = fetch1(sptr, sskew);
1718
0
#undef fetch1
1719
0
                byte cresult = (*cproc)(cdbyte | kdbyte,sbyte,ctcolor);
1720
0
                byte mresult = (*mproc)(mdbyte | kdbyte,sbyte,mtcolor);
1721
0
                byte yresult = (*yproc)(ydbyte | kdbyte,sbyte,ytcolor);
1722
0
                byte kresult = cresult & mresult & yresult;
1723
0
                cresult &= ~kresult;
1724
0
                mresult &= ~kresult;
1725
0
                yresult &= ~kresult;
1726
0
                *cdptr++ = (cresult & rmask) | (cdbyte & ~rmask);
1727
0
                *mdptr++ = (mresult & rmask) | (mdbyte & ~rmask);
1728
0
                *ydptr++ = (yresult & rmask) | (ydbyte & ~rmask);
1729
0
                *kdptr++ = (kresult & rmask) | (kdbyte & ~rmask);
1730
0
            }
1731
0
        }
1732
0
    }
1733
0
    return 0;
1734
0
}
1735
1736
static int
1737
plane_strip_copy_rop2(gx_device_memory * mdev,
1738
                      const byte * sdata, int sourcex, uint sraster,
1739
                      gx_bitmap_id id, const gx_color_index * scolors,
1740
                      const gx_strip_bitmap * textures,
1741
                      const gx_color_index * tcolors,
1742
                      int x, int y, int width, int height,
1743
                      int phase_x, int phase_y,
1744
                      gs_logical_operation_t lop, int plane,
1745
                      uint planar_height)
1746
0
{
1747
0
    mem_save_params_t save;
1748
0
    int code;
1749
0
    const gdev_mem_functions *fns;
1750
0
    int n, m;
1751
0
    dev_proc_encode_color(*save_encode);
1752
0
    dev_proc_get_color_mapping_procs(*save_gcmp);
1753
0
    gx_color_index save_black, save_white;
1754
1755
    /* assert(planar_height == 0); */
1756
1757
0
    MEM_SAVE_PARAMS(mdev, save);
1758
0
    mdev->line_ptrs += mdev->height * (intptr_t)plane;
1759
0
    fns = gdev_mem_functions_for_bits(mdev->planes[plane].depth);
1760
    /* strip_copy_rop2 might end up calling get_bits_rectangle or fill_rectangle,
1761
     * so ensure we have the right ones in there. */
1762
0
    set_dev_proc(mdev, get_bits_rectangle, fns->get_bits_rectangle);
1763
0
    set_dev_proc(mdev, fill_rectangle, fns->fill_rectangle);
1764
    /* We are about to change the number of components, so the cached black
1765
     * and white values are no longer correct. */
1766
0
    save_black = mdev->cached_colors.black;
1767
0
    save_white = mdev->cached_colors.white;
1768
0
    mdev->cached_colors.black = gx_no_color_index;
1769
0
    mdev->cached_colors.white = gx_no_color_index;
1770
    /* The strip_copy_rop2 routine can end up trying to calculate black
1771
     * and white values. For this it will call 'get_color_mapping_procs'
1772
     * and encode_color. We can't have it calling the devices own ones
1773
     * because they assume multiple planes, not just one. Store the
1774
     * originals, and swap them out for sane ones. It's possible that
1775
     * for some crazy devices, these choices might not be perfect,
1776
     * but it's hard to see what we could do better, so those devices
1777
     * might need to implement their own strip_copy_rop2. */
1778
0
    save_encode = dev_proc(mdev, encode_color);
1779
0
    save_gcmp = dev_proc(mdev, get_color_mapping_procs);
1780
0
    set_dev_proc(mdev, get_color_mapping_procs, gx_default_DevGray_get_color_mapping_procs);
1781
0
    set_dev_proc(mdev, encode_color, gx_default_gray_encode_color);
1782
    /* mdev->color_info.depth is restored by MEM_RESTORE_PARAMS below. */
1783
0
    mdev->color_info.depth = mdev->planes[plane].depth;
1784
0
    n = mdev->color_info.num_components;
1785
0
    mdev->color_info.num_components = 1;
1786
0
    m = mdev->num_planar_planes;
1787
0
    mdev->num_planar_planes = 1;
1788
0
    code = fns->strip_copy_rop2((gx_device *)mdev, sdata, sourcex, sraster,
1789
0
                                id, scolors, textures, tcolors,
1790
0
                                x, y, width, height,
1791
0
                                phase_x, phase_y, lop, planar_height);
1792
    /* Restore color details. */
1793
0
    mdev->color_info.num_components = n;
1794
0
    mdev->num_planar_planes = m;
1795
0
    set_dev_proc(mdev, get_bits_rectangle, mem_planar_get_bits_rectangle);
1796
0
    set_dev_proc(mdev, fill_rectangle, mem_planar_fill_rectangle);
1797
0
    set_dev_proc(mdev, encode_color, save_encode);
1798
0
    set_dev_proc(mdev, get_color_mapping_procs, save_gcmp);
1799
0
    mdev->cached_colors.black = save_black;
1800
0
    mdev->cached_colors.white = save_white;
1801
    /* The following effectively does: mdev->line_ptrs -= mdev->height * plane; */
1802
0
    MEM_RESTORE_PARAMS(mdev, save);
1803
0
    return code;
1804
0
}
1805
1806
/*
1807
 * Repack planar into chunky format.  This is an internal procedure that
1808
 * implements the straightforward chunky case of get_bits_rectangle, and
1809
 * is also used for the general cases.
1810
 */
1811
static int
1812
planar_to_chunky(gx_device_memory *mdev, int x, int y, int w, int h,
1813
                 int offset, intptr_t draster, byte *dest, byte **line_ptrs,
1814
                 int plane_height)
1815
819k
{
1816
819k
    int num_planes = mdev->num_planar_planes;
1817
819k
    const byte *sptr[GX_DEVICE_COLOR_MAX_COMPONENTS];
1818
819k
    int sbit[GX_DEVICE_COLOR_MAX_COMPONENTS];
1819
819k
    byte *dptr;
1820
819k
    int dbit;
1821
819k
    byte dbbyte;
1822
819k
    int ddepth = mdev->color_info.depth;
1823
819k
    int direct =
1824
819k
        (mdev->color_info.depth != num_planes * mdev->plane_depth ? 0 :
1825
819k
         mdev->planes[0].shift == 0 ? -mdev->plane_depth : mdev->plane_depth);
1826
819k
    int pi, ix, iy;
1827
1828
    /* Check whether the planes are of equal size and sequential. */
1829
    /* If direct != 0, we already know they exactly fill the depth. */
1830
819k
    if (direct < 0) {
1831
0
        for (pi = 0; pi < num_planes; ++pi)
1832
0
            if (mdev->planes[pi].shift != pi * -direct) {
1833
0
                direct = 0; break;
1834
0
            }
1835
819k
    } else if (direct > 0) {
1836
3.28M
        for (pi = 0; pi < num_planes; ++pi)
1837
2.62M
            if (mdev->planes[num_planes - 1 - pi].shift != pi * direct) {
1838
0
                direct = 0; break;
1839
0
            }
1840
656k
    }
1841
1.63M
    for (iy = y; iy < y + h; ++iy) {
1842
819k
        byte **line_ptr = line_ptrs + iy;
1843
1844
4.25M
        for (pi = 0; pi < num_planes; ++pi, line_ptr += plane_height) {
1845
3.43M
            int plane_depth = mdev->planes[pi].depth;
1846
3.43M
            int xbit = x * plane_depth;
1847
1848
3.43M
            sptr[pi] = *line_ptr + (xbit >> 3);
1849
3.43M
            sbit[pi] = xbit & 7;
1850
3.43M
        }
1851
819k
        {
1852
819k
            int xbit = offset * ddepth;
1853
1854
819k
            dptr = dest + (iy - y) * draster + (xbit >> 3);
1855
819k
            dbit = xbit & 7;
1856
819k
        }
1857
819k
        if (direct == -8) {
1858
            /* 1 byte per component, lsb first. */
1859
0
            switch (num_planes) {
1860
0
            case 3: {
1861
0
                const byte *p0 = sptr[2];
1862
0
                const byte *p1 = sptr[1];
1863
0
                const byte *p2 = sptr[0];
1864
1865
0
                for (ix = w; ix > 0; --ix, dptr += 3) {
1866
0
                    dptr[0] = *p0++;
1867
0
                    dptr[1] = *p1++;
1868
0
                    dptr[2] = *p2++;
1869
0
                }
1870
0
            }
1871
0
            continue;
1872
0
            case 4:
1873
0
                for (ix = w; ix > 0; --ix, dptr += 4) {
1874
0
                    dptr[0] = *sptr[3]++;
1875
0
                    dptr[1] = *sptr[2]++;
1876
0
                    dptr[2] = *sptr[1]++;
1877
0
                    dptr[3] = *sptr[0]++;
1878
0
                }
1879
0
                continue;
1880
0
            default:
1881
0
                break;
1882
0
            }
1883
0
        }
1884
819k
        dbbyte = (dbit ? (byte)(*dptr & (0xff00 >> dbit)) : 0);
1885
/*        sample_store_preload(dbbyte, dptr, dbit, ddepth);*/
1886
22.6M
        for (ix = w; ix > 0; --ix) {
1887
21.8M
            gx_color_index color = 0;
1888
1889
109M
            for (pi = 0; pi < num_planes; ++pi) {
1890
87.4M
                int plane_depth = mdev->planes[pi].depth;
1891
87.4M
                ushort value;
1892
1893
87.4M
                if (sample_load_next16(&value, &sptr[pi], &sbit[pi], plane_depth) < 0)
1894
0
                    return_error(gs_error_rangecheck);
1895
87.4M
                color |= (gx_color_index)value << mdev->planes[pi].shift;
1896
87.4M
            }
1897
21.8M
            if (sizeof(color) > 4) {
1898
21.8M
                if (sample_store_next64(color, &dptr, &dbit, ddepth, &dbbyte) < 0)
1899
0
                    return_error(gs_error_rangecheck);
1900
21.8M
            }
1901
0
            else {
1902
0
                if (sample_store_next32(color, &dptr, &dbit, ddepth, &dbbyte) < 0)
1903
0
                    return_error(gs_error_rangecheck);
1904
0
            }
1905
21.8M
        }
1906
819k
        sample_store_flush(dptr, dbit, dbbyte);
1907
819k
    }
1908
819k
    return 0;
1909
819k
}
1910
1911
static byte cmykrop[256] =
1912
{
1913
    255,127,191,63,223,95,159,31,239,111,175,47,207,79,143,15,
1914
    247,119,183,55,215,87,151,23,231,103,167,39,199,71,135,7,
1915
    251,123,187,59,219,91,155,27,235,107,171,43,203,75,139,11,
1916
    243,115,179,51,211,83,147,19,227,99,163,35,195,67,131,3,
1917
    253,125,189,61,221,93,157,29,237,109,173,45,205,77,141,13,
1918
    245,117,181,53,213,85,149,21,229,101,165,37,197,69,133,5,
1919
    249,121,185,57,217,89,153,25,233,105,169,41,201,73,137,9,
1920
    241,113,177,49,209,81,145,17,225,97,161,33,193,65,129,1,
1921
    254,126,190,62,222,94,158,30,238,110,174,46,206,78,142,14,
1922
    246,118,182,54,214,86,150,22,230,102,166,38,198,70,134,6,
1923
    250,122,186,58,218,90,154,26,234,106,170,42,202,74,138,10,
1924
    242,114,178,50,210,82,146,18,226,98,162,34,194,66,130,2,
1925
    252,124,188,60,220,92,156,28,236,108,172,44,204,76,140,12,
1926
    244,116,180,52,212,84,148,20,228,100,164,36,196,68,132,4,
1927
    248,120,184,56,216,88,152,24,232,104,168,40,200,72,136,8,
1928
    240,112,176,48,208,80,144,16,224,96,160,32,192,64,128,0
1929
};
1930
1931
static int
1932
mem_planar_strip_copy_rop2(gx_device * dev,
1933
                           const byte * sdata, int sourcex, uint sraster,
1934
                           gx_bitmap_id id, const gx_color_index * scolors,
1935
                           const gx_strip_bitmap * textures,
1936
                           const gx_color_index * tcolors,
1937
                           int x, int y, int width, int height,
1938
                           int phase_x, int phase_y,
1939
                           gs_logical_operation_t lop,
1940
                           uint planar_height)
1941
0
{
1942
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
1943
0
    int code;
1944
1945
0
    lop = lop_sanitize(lop);
1946
0
    if (planar_height != 0) {
1947
        /* S is in planar format; expand it to a temporary buffer, then
1948
         * call ourselves back with a modified rop to use it, then free
1949
         * the temporary buffer, and return. */
1950
        /* Make a temporary buffer that contains both the raster and the line
1951
         * pointers for the buffer. For now, for the sake of sanity, we
1952
         * convert whole lines of s, but only as many lines as we have to. */
1953
        /* We assume that scolors == NULL here */
1954
0
        int i;
1955
0
        int j;
1956
0
        intptr_t chunky_sraster;
1957
0
        int64_t nbytes;
1958
0
        byte **line_ptrs;
1959
0
        byte *sbuf, *buf;
1960
1961
0
        chunky_sraster = sraster * (intptr_t)mdev->num_planar_planes;
1962
0
        if (check_64bit_multiply(height, chunky_sraster, &nbytes) != 0)
1963
0
            return gs_note_error(gs_error_undefinedresult);
1964
0
        buf = gs_alloc_bytes(mdev->memory, nbytes, "mem_planar_strip_copy_rop(buf)");
1965
0
        if (buf == NULL) {
1966
0
            return gs_note_error(gs_error_VMerror);
1967
0
        }
1968
0
        nbytes = sizeof(byte *) * (intptr_t)mdev->num_planar_planes * height;
1969
0
        line_ptrs = (byte **)gs_alloc_bytes(mdev->memory, nbytes, "mem_planar_strip_copy_rop(line_ptrs)");
1970
0
        if (line_ptrs == NULL) {
1971
0
            gs_free_object(mdev->memory, buf, "mem_planar_strip_copy_rop(buf)");
1972
0
            return gs_note_error(gs_error_VMerror);
1973
0
        }
1974
0
        for (j = 0; j < mdev->color_info.num_components; j++) {
1975
0
            sbuf = (byte *)sdata + j * (intptr_t)sraster * planar_height;
1976
0
            for (i = height; i > 0; i--) {
1977
0
                *line_ptrs++ = sbuf;
1978
0
                sbuf += sraster;
1979
0
            }
1980
0
        }
1981
0
        line_ptrs -= height * (intptr_t)mdev->num_planar_planes;
1982
0
        planar_to_chunky(mdev, sourcex, 0, width, height,
1983
0
                         0, chunky_sraster, buf, line_ptrs, height);
1984
0
        gs_free_object(mdev->memory, line_ptrs, "mem_planar_strip_copy_rop(line_ptrs)");
1985
0
        code = mem_planar_strip_copy_rop2(dev, buf, 0, chunky_sraster,
1986
0
                                          id, scolors, textures, tcolors,
1987
0
                                          x, y, width, height, phase_x, phase_y,
1988
0
                                          lop, 0);
1989
0
        gs_free_object(mdev->memory, buf, "mem_planar_strip_copy_rop(buf)");
1990
0
        return code;
1991
0
    }
1992
1993
0
    if (textures && textures->num_planes > 1) {
1994
        /* T is in planar format; expand it to a temporary buffer, then
1995
         * call ourselves back with a modified rop to use it, then free
1996
         * the temporary buffer, and return. */
1997
        /* Make a temporary buffer that contains both the raster and the line
1998
         * pointers for the buffer. For now, for the sake of sanity, we
1999
         * convert whole lines of t, but only as many lines as we have to
2000
         * (unless it loops). */
2001
        /* We assume that tcolors == NULL here */
2002
0
        int ty;
2003
0
        intptr_t i;
2004
0
        intptr_t chunky_t_raster;
2005
0
        int chunky_t_height;
2006
0
        int64_t nbytes;
2007
0
        byte **line_ptrs;
2008
0
        byte *tbuf, *buf;
2009
0
        gx_strip_bitmap newtex;
2010
2011
0
        ty = (y + phase_y) % textures->rep_height;
2012
0
        if (ty < 0)
2013
0
            ty += textures->rep_height;
2014
0
        chunky_t_raster = bitmap_raster(textures->rep_width * (intptr_t)mdev->color_info.depth);
2015
0
        if (ty + height <= textures->rep_height) {
2016
0
            chunky_t_height = height;
2017
0
            phase_y = -y;
2018
0
        } else {
2019
0
            ty = 0;
2020
0
            chunky_t_height = textures->rep_height;
2021
0
        }
2022
0
        if (check_64bit_multiply(chunky_t_height, chunky_t_raster, &nbytes) != 0)
2023
0
            return gs_note_error(gs_error_undefinedresult);
2024
0
        buf = gs_alloc_bytes(mdev->memory, nbytes, "mem_planar_strip_copy_rop(buf)");
2025
0
        if (buf == NULL) {
2026
0
            return gs_note_error(gs_error_VMerror);
2027
0
        }
2028
0
        nbytes = sizeof(byte *) * (intptr_t)mdev->num_planar_planes * textures->rep_height;
2029
0
        line_ptrs = (byte **)gs_alloc_bytes(mdev->memory, nbytes, "mem_planar_strip_copy_rop(line_ptrs)");
2030
0
        if (line_ptrs == NULL) {
2031
0
            gs_free_object(mdev->memory, buf, "mem_planar_strip_copy_rop(buf)");
2032
0
            return gs_note_error(gs_error_VMerror);
2033
0
        }
2034
0
        tbuf = textures->data;
2035
0
        for (i = textures->rep_height * (intptr_t)mdev->num_planar_planes; i > 0; i--) {
2036
0
            *line_ptrs++ = tbuf;
2037
0
            tbuf += textures->raster;
2038
0
        }
2039
0
        line_ptrs -= textures->rep_height * (intptr_t)mdev->num_planar_planes;
2040
0
        planar_to_chunky(mdev, 0, ty, textures->rep_width, chunky_t_height,
2041
0
                         0, chunky_t_raster, buf, line_ptrs, textures->rep_height);
2042
0
        gs_free_object(mdev->memory, line_ptrs, "mem_planar_strip_copy_rop(line_ptrs)");
2043
0
        newtex = *textures;
2044
0
        newtex.data = buf;
2045
0
        newtex.raster = chunky_t_raster;
2046
0
        newtex.num_planes = 1;
2047
0
        newtex.size.x = textures->rep_width;
2048
0
        newtex.size.y = textures->rep_height;
2049
0
        code = mem_planar_strip_copy_rop2(dev, sdata, sourcex, sraster,
2050
0
                                          id, scolors, &newtex, tcolors,
2051
0
                                          x, y, width, height, phase_x, phase_y,
2052
0
                                          lop, planar_height);
2053
0
        gs_free_object(mdev->memory, buf, "mem_planar_strip_copy_rop(buf)");
2054
0
        return code;
2055
0
    }
2056
2057
    /* Not doing a planar lop. If we carry on down the default path here,
2058
     * we'll end up doing a planar_to_chunky; we may be able to sidestep
2059
     * that by spotting cases where we can operate directly. */
2060
0
    if ((!lop_uses_T(lop) || (tcolors && (tcolors[0] == tcolors[1]))) &&
2061
0
        (mdev->color_info.num_components == mdev->num_planar_planes)) {
2062
        /* No T in use, or constant T. */
2063
0
        if ((!lop_uses_S(lop) || (scolors && (scolors[0] == scolors[1]))) &&
2064
0
            ((mdev->color_info.num_components == 1) || (mdev->color_info.num_components == 3))) {
2065
0
            int plane;
2066
            /* No S in use, or constant S. And either greyscale or rgb,
2067
             * so we can just do the rop on each plane in turn. */
2068
0
            for (plane=0; plane < mdev->color_info.num_components; plane++)
2069
0
            {
2070
0
                gx_color_index tcolors2[2], scolors2[2];
2071
0
                int shift = mdev->planes[plane].shift;
2072
0
                int mask = (1<<mdev->planes[plane].depth)-1;
2073
2074
0
                if (tcolors) {
2075
0
                    tcolors2[0] = (tcolors[0] >> shift) & mask;
2076
0
                    tcolors2[1] = (tcolors[1] >> shift) & mask;
2077
0
                }
2078
0
                if (scolors) {
2079
0
                    scolors2[0] = (scolors[0] >> shift) & mask;
2080
0
                    scolors2[1] = (scolors[1] >> shift) & mask;
2081
0
                }
2082
0
                code = plane_strip_copy_rop2(mdev, sdata, sourcex, sraster,
2083
0
                                             id, (scolors ? scolors2 : NULL),
2084
0
                                             textures, (tcolors ? tcolors2 : NULL),
2085
0
                                             x, y, width, height,
2086
0
                                             phase_x, phase_y, lop, plane, 0);
2087
0
                if (code < 0)
2088
0
                    return code;
2089
0
            }
2090
0
            return 0;
2091
0
        }
2092
0
        if ((mdev->color_info.num_components == 4) && (mdev->plane_depth == 1))
2093
0
        {
2094
0
            lop = cmykrop[lop & 0xff] | (lop & ~0xff);
2095
0
            return planar_cmyk4bit_strip_copy_rop2(mdev, sdata, sourcex,
2096
0
                                                   sraster, id, scolors,
2097
0
                                                   textures, tcolors,
2098
0
                                                   x, y, width, height,
2099
0
                                                   phase_x, phase_y,
2100
0
                                                   lop, 0);
2101
0
        }
2102
0
    }
2103
0
    if (!tcolors && !scolors &&
2104
0
        (mdev->color_info.num_components == 4) && (mdev->plane_depth == 1)) {
2105
0
        lop = cmykrop[lop & 0xff] | (lop & ~0xff);
2106
0
        return planar_cmyk4bit_strip_copy_rop2(mdev, sdata, sourcex,
2107
0
                                               sraster, id, scolors,
2108
0
                                               textures, tcolors,
2109
0
                                               x, y, width, height,
2110
0
                                               phase_x, phase_y,
2111
0
                                               lop, 0);
2112
0
    }
2113
    /* Fall back to the default implementation (the only one that
2114
     * guarantees to properly cope with D being planar). */
2115
0
    return mem_default_strip_copy_rop2(dev, sdata, sourcex, sraster,
2116
0
                                       id, scolors, textures, tcolors,
2117
0
                                       x, y, width, height,
2118
0
                                       phase_x, phase_y, lop, 0);
2119
0
}
2120
2121
/* Copy bits back from a planar memory device. */
2122
static int
2123
mem_planar_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect,
2124
                              gs_get_bits_params_t * params)
2125
11.4M
{
2126
    /* This duplicates most of mem_get_bits_rectangle.  Tant pgs. */
2127
11.4M
    gx_device_memory * const mdev = (gx_device_memory *)dev;
2128
11.4M
    gs_get_bits_options_t options = params->options;
2129
11.4M
    int x = prect->p.x, w = prect->q.x - x, y = prect->p.y, h = prect->q.y - y;
2130
11.4M
    int num_planes = mdev->num_planar_planes;
2131
11.4M
    gs_get_bits_params_t copy_params;
2132
11.4M
    int code;
2133
2134
11.4M
    if (options == 0) {
2135
        /*
2136
         * Unfortunately, as things stand, we have to support
2137
         * GB_PACKING_CHUNKY.  In fact, we can't even claim to support
2138
         * GB_PACKING_PLANAR, because there is currently no way to
2139
         * describe the particular planar packing format that the device
2140
         * actually stores.
2141
         */
2142
0
        params->options =
2143
0
            (GB_ALIGN_STANDARD | GB_ALIGN_ANY) |
2144
0
            (GB_RETURN_COPY | GB_RETURN_POINTER) |
2145
0
            (GB_OFFSET_0 | GB_OFFSET_SPECIFIED | GB_OFFSET_ANY) |
2146
0
            (GB_RASTER_STANDARD | GB_RASTER_SPECIFIED | GB_RASTER_ANY) |
2147
            /*
2148
            (mdev->num_planes == mdev->color_info.depth ?
2149
             GB_PACKING_CHUNKY | GB_PACKING_PLANAR | GB_PACKING_BIT_PLANAR :
2150
             GB_PACKING_CHUNKY | GB_PACKING_PLANAR)
2151
            */
2152
0
            GB_PACKING_CHUNKY |
2153
0
            GB_COLORS_NATIVE | GB_ALPHA_NONE;
2154
0
        return_error(gs_error_rangecheck);
2155
0
    }
2156
2157
11.4M
    if (mdev->line_ptrs == 0x00)
2158
0
        return_error(gs_error_rangecheck);
2159
2160
11.4M
    if ((w <= 0) | (h <= 0)) {
2161
0
        if ((w | h) < 0)
2162
0
            return_error(gs_error_rangecheck);
2163
0
        return 0;
2164
0
    }
2165
11.4M
    if (x < 0 || w > dev->width - x ||
2166
11.4M
        y < 0 || h > dev->height - y
2167
11.4M
        )
2168
0
        return_error(gs_error_rangecheck);
2169
2170
    /* First off, see if we can satisfy get_bits_rectangle with just returning
2171
     * pointers to the existing data. */
2172
11.4M
    if (params->options & GB_RETURN_POINTER)
2173
10.6M
    {
2174
10.6M
        gs_get_bits_params_t copy_params;
2175
10.6M
        byte **base = &scan_line_base(mdev, y);
2176
10.6M
        int code;
2177
2178
10.6M
        copy_params.options =
2179
10.6M
            GB_COLORS_NATIVE | GB_PACKING_PLANAR | GB_ALPHA_NONE |
2180
10.6M
            (mdev->raster ==
2181
10.6M
             bitmap_raster(mdev->width * mdev->color_info.depth) ?
2182
10.6M
             GB_RASTER_STANDARD : GB_RASTER_SPECIFIED);
2183
10.6M
        copy_params.raster = mdev->raster;
2184
10.6M
        code = gx_get_bits_return_pointer(dev, x, h, params,
2185
10.6M
                                          &copy_params, base);
2186
10.6M
        if (code >= 0)
2187
10.6M
            return code;
2188
10.6M
    }
2189
2190
    /*
2191
     * If the request is for exactly one plane, hand it off to a device
2192
     * temporarily tweaked to return just that plane.
2193
     */
2194
822k
    if (!(~options & (GB_PACKING_PLANAR | GB_SELECT_PLANES))) {
2195
        /* Check that only a single plane is being requested. */
2196
3.34k
        int pi;
2197
2198
8.40k
        for (pi = 0; pi < num_planes; ++pi)
2199
8.40k
            if (params->data[pi] != 0)
2200
3.34k
                break;
2201
3.34k
        if (pi < num_planes) {
2202
3.34k
            int plane = pi++;
2203
2204
8.40k
            for (; pi < num_planes; ++pi)
2205
5.05k
                if (params->data[pi] != 0)
2206
0
                    break;
2207
3.34k
            if (pi == num_planes) {
2208
3.34k
                mem_save_params_t save;
2209
2210
3.34k
                copy_params = *params;
2211
3.34k
                copy_params.options =
2212
3.34k
                    (options & ~(GB_PACKING_ALL | GB_SELECT_PLANES)) |
2213
3.34k
                    GB_PACKING_CHUNKY;
2214
3.34k
                copy_params.data[0] = copy_params.data[plane];
2215
3.34k
                MEM_SAVE_PARAMS(mdev, save);
2216
3.34k
                mdev->line_ptrs += mdev->height * plane;
2217
3.34k
                MEM_SET_PARAMS(mdev, mdev->planes[plane].depth);
2218
3.34k
                code = mem_get_bits_rectangle(dev, prect, &copy_params);
2219
3.34k
                MEM_RESTORE_PARAMS(mdev, save);
2220
3.34k
                if (code >= 0) {
2221
3.34k
                    params->data[plane] = copy_params.data[0];
2222
3.34k
                    return code;
2223
3.34k
                }
2224
3.34k
            }
2225
3.34k
        }
2226
3.34k
    }
2227
2228
819k
    if ((params->options & GB_RETURN_POINTER) == 0) {
2229
        /* Can we do the fetch using a faked GB_RETURN_POINTER request
2230
         * and then copy the data? */
2231
819k
        gs_get_bits_params_t params2 = *params;
2232
819k
        gs_get_bits_params_t copy_params;
2233
819k
        byte **base = &scan_line_base(mdev, y);
2234
819k
        int code;
2235
2236
819k
        params2.options &= ~GB_RETURN_COPY;
2237
819k
        params2.options |= GB_RETURN_POINTER;
2238
2239
819k
        copy_params.options =
2240
819k
            GB_COLORS_NATIVE | GB_PACKING_PLANAR | GB_ALPHA_NONE |
2241
819k
            (mdev->raster ==
2242
819k
             bitmap_raster(mdev->width * mdev->color_info.depth) ?
2243
819k
             GB_RASTER_STANDARD : GB_RASTER_SPECIFIED);
2244
819k
        params2.raster = mdev->raster;
2245
819k
        copy_params.raster = mdev->raster;
2246
819k
        code = gx_get_bits_return_pointer(dev, x, h, &params2,
2247
819k
                                          &copy_params, base);
2248
819k
        if (code >= 0) {
2249
            /* get_bits worked. Let's copy the data out. */
2250
0
            int bpc = mdev->color_info.depth / mdev->num_planar_planes;
2251
0
            int left = x;
2252
0
            int right = x+w;
2253
0
            int i, j;
2254
0
            switch (bpc) {
2255
0
                case  1: left >>= 3; right = (right+7)>>3; break;
2256
0
                case  2: left >>= 2; right = (right+3)>>2; break;
2257
0
                case  4: left >>= 1; right = (right+1)>>1; break;
2258
0
                case  8: break;
2259
0
                case 12: left = (left&~1); left += left>>1;
2260
0
                         right = right+(right>>1)+(right&1); break;
2261
0
                case 16: left *= 2; right *= 2; break;
2262
0
                default: return_error(gs_error_rangecheck);
2263
0
            }
2264
0
            right -= left;
2265
0
            for (i = 0; i < mdev->num_planar_planes; i++) {
2266
0
                byte *d = params->data[i];
2267
0
                const byte *s = params2.data[i];
2268
0
                for (j = 0; j < h; j++) {
2269
0
                    memcpy(d, s, right);
2270
0
                    d += params->raster;
2271
0
                    s += params2.raster;
2272
0
                }
2273
0
            }
2274
0
            return code;
2275
0
        }
2276
819k
    }
2277
2278
    /*
2279
     * We can't return the requested plane by itself.  Fall back to
2280
     * chunky format.  This is somewhat painful.
2281
     *
2282
     * The code here knows how to produce just one chunky format:
2283
     * GB_COLORS_NATIVE, GB_ALPHA_NONE, GB_RETURN_COPY.
2284
     * For any other format, we generate this one in a buffer and
2285
     * hand it off to gx_get_bits_copy.  This is *really* painful.
2286
     */
2287
819k
    if (!(~options & (GB_COLORS_NATIVE | GB_ALPHA_NONE |
2288
819k
                      GB_PACKING_CHUNKY | GB_RETURN_COPY))) {
2289
819k
        int offset = (options & GB_OFFSET_SPECIFIED ? params->x_offset : 0);
2290
819k
        intptr_t draster =
2291
819k
            (options & GB_RASTER_SPECIFIED ? params->raster :
2292
819k
             bitmap_raster((offset + w) * (intptr_t)mdev->color_info.depth));
2293
2294
819k
        planar_to_chunky(mdev, x, y, w, h, offset, draster, params->data[0],
2295
819k
                         mdev->line_ptrs, mdev->height);
2296
819k
    } else {
2297
        /*
2298
         * Do the transfer through an intermediate buffer.
2299
         * The buffer must be large enough to hold at least one pixel,
2300
         * i.e., GX_DEVICE_COLOR_MAX_COMPONENTS 16-bit values.
2301
         * The algorithms are very similar to those in copy_color.
2302
         */
2303
0
#define BUF_LONGS\
2304
0
  max(100, (GX_DEVICE_COLOR_MAX_COMPONENTS * 2 + sizeof(long) - 1) /\
2305
0
      sizeof(long))
2306
0
#define BUF_BYTES (BUF_LONGS * ARCH_SIZEOF_LONG)
2307
0
        union b_ {
2308
0
            ulong l[BUF_LONGS];
2309
0
            byte b[BUF_BYTES];
2310
0
        } buf;
2311
0
        intptr_t br;
2312
0
        int bw, bh, cx, cy, cw, ch;
2313
0
        int ddepth = mdev->color_info.depth;
2314
0
        uint raster = bitmap_raster(ddepth * mdev->width);
2315
0
        gs_get_bits_params_t dest_params;
2316
0
        int dest_bytes;
2317
2318
0
        if (raster > BUF_BYTES) {
2319
0
            br = BUF_BYTES;
2320
0
            bw = BUF_BYTES * 8 / ddepth;
2321
0
            bh = 1;
2322
0
        } else {
2323
0
            br = raster;
2324
0
            bw = w;
2325
0
            bh = BUF_BYTES / raster;
2326
0
        }
2327
0
        copy_params.options =
2328
0
            GB_COLORS_NATIVE | GB_PACKING_CHUNKY | GB_ALPHA_NONE |
2329
0
            GB_RASTER_STANDARD;
2330
0
        copy_params.raster = raster;
2331
        /* The options passed in from above may have GB_OFFSET_0, and what's
2332
         * more, the code below may insist on GB_OFFSET_0 being set. Hence we
2333
         * can't rely on x_offset to allow for the block size we are using.
2334
         * We'll have to adjust the pointer by steam. */
2335
0
        dest_params = *params;
2336
0
        dest_params.x_offset = params->x_offset;
2337
0
        if (options & GB_COLORS_RGB)
2338
0
            dest_bytes = 3;
2339
0
        else if (options & GB_COLORS_CMYK)
2340
0
            dest_bytes = 4;
2341
0
        else if (options & GB_COLORS_GRAY)
2342
0
            dest_bytes = 1;
2343
0
        else
2344
0
            dest_bytes = mdev->color_info.depth / mdev->plane_depth;
2345
        /* We assume options & GB_DEPTH_8 */
2346
0
        for (cy = y; cy < y + h; cy += ch) {
2347
0
            ch = min(bh, y + h - cy);
2348
0
            for (cx = x; cx < x + w; cx += cw) {
2349
0
                cw = min(bw, x + w - cx);
2350
0
                planar_to_chunky(mdev, cx, cy, cw, ch, 0, br, buf.b,
2351
0
                                 mdev->line_ptrs, mdev->height);
2352
0
                code = gx_get_bits_copy(dev, 0, cw, ch, &dest_params,
2353
0
                                        &copy_params, buf.b, br);
2354
0
                if (code < 0)
2355
0
                    return code;
2356
0
                dest_params.data[0] += cw * dest_bytes;
2357
0
            }
2358
0
            dest_params.data[0] += ch * dest_params.raster - (w*dest_bytes);
2359
0
        }
2360
0
#undef BUF_BYTES
2361
0
#undef BUF_LONGS
2362
0
    }
2363
819k
    return 0;
2364
819k
}