Coverage Report

Created: 2022-10-31 07:00

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