Coverage Report

Created: 2022-04-16 11:23

/src/ghostpdl/base/gdevdrop.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2021 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
/* Default and device-independent RasterOp algorithms */
17
#include "memory_.h"
18
#include "gx.h"
19
#include "gsbittab.h"
20
#include "gserrors.h"
21
#include "gsropt.h"
22
#include "gxcindex.h"
23
#include "gxdcolor.h"
24
#include "gxdevice.h"
25
#include "gxdevmem.h"
26
#include "gxgetbit.h"
27
#include "gdevmem.h"            /* for mem_default_strip_copy_rop prototype */
28
#include "gdevmpla.h"
29
#include "gdevmrop.h"
30
#include "gxdevsop.h"
31
#include "stdint_.h"
32
#ifdef WITH_CAL
33
#include "cal.h"
34
#endif
35
36
/*
37
 * Define the maximum amount of space we are willing to allocate for a
38
 * multiple-row RasterOp buffer.  (We are always willing to allocate
39
 * one row, no matter how wide.)
40
 */
41
static const uint max_rop_bitmap = 1000;
42
43
/* ---------------- Debugging aids ---------------- */
44
45
#ifdef DEBUG
46
47
void
48
trace_copy_rop(const char *cname, gx_device * dev,
49
               const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id,
50
               const gx_color_index * scolors,
51
               const gx_strip_bitmap * textures,
52
               const gx_color_index * tcolors,
53
               int x, int y, int width, int height,
54
               int phase_x, int phase_y, gs_logical_operation_t lop)
55
{
56
    dmlprintf4(dev->memory, "%s: dev="PRI_INTPTR"(%s) depth=%d\n",
57
               cname, (intptr_t)dev, dev->dname, dev->color_info.depth);
58
    dmlprintf4(dev->memory, "  source data="PRI_INTPTR" x=%d raster=%u id=%lu colors=",
59
               (intptr_t)sdata, sourcex, sraster, (ulong) id);
60
    if (scolors)
61
        dmprintf2(dev->memory, "(%"PRIx64",%"PRIx64");\n", (uint64_t)scolors[0], (uint64_t)scolors[1]);
62
    else
63
        dmputs(dev->memory, "none;\n");
64
    if (textures)
65
        dmlprintf8(dev->memory, "  textures="PRI_INTPTR" size=%dx%d(%dx%d) raster=%u shift=%d(%d)",
66
                  (intptr_t)textures, textures->size.x, textures->size.y,
67
                  textures->rep_width, textures->rep_height,
68
                  textures->raster, textures->shift, textures->rep_shift);
69
    else
70
        dmlputs(dev->memory, "  textures=none");
71
    if (tcolors)
72
        dmprintf2(dev->memory, " colors=(%"PRIx64",%"PRIx64")\n", (uint64_t)tcolors[0], (uint64_t)tcolors[1]);
73
    else
74
        dmputs(dev->memory, " colors=none\n");
75
    dmlprintf7(dev->memory, "  rect=(%d,%d),(%d,%d) phase=(%d,%d) op=0x%x\n",
76
              x, y, x + width, y + height, phase_x, phase_y,
77
              (uint) lop);
78
    if (gs_debug_c('B')) {
79
        if (sdata)
80
            debug_dump_bitmap(dev->memory, sdata, sraster, height, "source bits");
81
        if (textures && textures->data)
82
            debug_dump_bitmap(dev->memory, textures->data, textures->raster,
83
                              textures->size.y, "textures bits");
84
    }
85
}
86
87
#endif
88
89
/* ---------------- Default copy_rop implementations ---------------- */
90
91
int
92
gx_default_strip_copy_rop2(gx_device * dev,
93
                           const byte * sdata, int sourcex,
94
                           uint sraster, gx_bitmap_id id,
95
                           const gx_color_index * scolors,
96
                           const gx_strip_bitmap * textures,
97
                           const gx_color_index * tcolors,
98
                           int x, int y, int width, int height,
99
                           int phase_x, int phase_y,
100
                           gs_logical_operation_t lop,
101
                           uint planar_height)
102
0
{
103
0
    int depth = dev->color_info.depth;
104
0
    gs_memory_t *mem = dev->memory;
105
0
    const gx_device_memory *mdproto = gdev_mem_device_for_bits(depth);
106
0
    gx_device_memory *pmdev;
107
0
    uint draster;
108
0
    byte *row = 0;
109
0
    gs_int_rect rect;
110
0
    int max_height;
111
0
    int block_height;
112
0
    int code;
113
0
    int py;
114
0
    int is_planar = 0;
115
0
    int plane_depth;
116
117
#ifdef DEBUG
118
    if (gs_debug_c('b'))
119
        trace_copy_rop("gx_default_strip_copy_rop2",
120
                       dev, sdata, sourcex, sraster,
121
                       id, scolors, textures, tcolors,
122
                       x, y, width, height, phase_x, phase_y, lop);
123
#endif
124
0
    if (mdproto == 0)
125
0
        return_error(gs_error_rangecheck);
126
0
    if (sdata == 0) {
127
0
        fit_fill(dev, x, y, width, height);
128
0
    } else {
129
0
        fit_copy(dev, sdata, sourcex, sraster, id, x, y, width, height);
130
0
    }
131
0
    draster = bitmap_raster(width * depth);
132
0
    max_height = max_rop_bitmap / draster;
133
0
    if (max_height == 0)
134
0
        max_height = 1;
135
0
    block_height = min(height, max_height);
136
0
    if (planar_height > 0)
137
0
        block_height = planar_height;
138
0
    gs_make_mem_device_with_copydevice(&pmdev, mdproto, mem, -1, dev);
139
0
    pmdev->width = width;
140
0
    pmdev->height = block_height;
141
0
    pmdev->bitmap_memory = mem;
142
0
    pmdev->color_info = dev->color_info;
143
0
    if (dev->is_planar)
144
0
    {
145
0
        gx_render_plane_t planes[GX_DEVICE_COLOR_MAX_COMPONENTS];
146
0
        uchar num_comp = dev->color_info.num_components;
147
0
        uchar i;
148
0
        plane_depth = dev->color_info.depth / num_comp;
149
0
        for (i = 0; i < num_comp; i++)
150
0
        {
151
0
            planes[i].shift = plane_depth * (num_comp - 1 - i);
152
0
            planes[i].depth = plane_depth;
153
0
            planes[i].index = i;
154
0
        }
155
        /* RJW: This code, like most of ghostscripts planar support,
156
         * will only work if every plane has the same depth. */
157
0
        draster = bitmap_raster(width * planes[0].depth);
158
0
        code = gdev_mem_set_planar(pmdev, num_comp, planes);
159
0
        if (code < 0)
160
0
            return code;
161
0
        is_planar = 1;
162
0
    }
163
0
    code = (*dev_proc(pmdev, open_device))((gx_device *)pmdev);
164
0
    pmdev->is_open = true; /* not sure why we need this, but we do. */
165
0
    if (code < 0)
166
0
        return code;
167
0
    lop = lop_sanitize(lop);
168
0
    if (rop3_uses_D(lop)) {
169
0
        row = gs_alloc_bytes(mem, (size_t)draster * block_height, "copy_rop row");
170
0
        if (row == 0) {
171
0
            code = gs_note_error(gs_error_VMerror);
172
0
            goto out;
173
0
        }
174
0
    }
175
0
    rect.p.x = x;
176
0
    rect.q.x = x + width;
177
0
    for (py = y; py < y + height; py += block_height) {
178
0
        if (block_height > y + height - py)
179
0
            block_height = y + height - py;
180
0
        rect.p.y = py;
181
0
        rect.q.y = py + block_height;
182
0
        if (row /*uses_d*/) {
183
0
            gs_get_bits_params_t bit_params;
184
185
0
            bit_params.options =
186
0
                GB_COLORS_NATIVE | GB_ALPHA_NONE | GB_DEPTH_ALL |
187
0
                GB_PACKING_CHUNKY | GB_RETURN_ALL | GB_ALIGN_STANDARD |
188
0
                GB_OFFSET_0 | GB_OFFSET_ANY | GB_RASTER_STANDARD;
189
0
            bit_params.data[0] = row;
190
0
            bit_params.x_offset = 0;
191
0
            code = (*dev_proc(dev, get_bits_rectangle))
192
0
                (dev, &rect, &bit_params);
193
0
            if (code < 0)
194
0
                break;
195
0
            code = (*dev_proc(pmdev, copy_color))
196
0
                ((gx_device *)pmdev, bit_params.data[0], bit_params.x_offset,
197
0
                 draster, gx_no_bitmap_id, 0, 0, width,
198
0
                 block_height);
199
0
            if (code < 0)
200
0
                return code;
201
0
        }
202
0
        code = (*dev_proc(pmdev, strip_copy_rop2))
203
0
                        ((gx_device *)pmdev,
204
0
                         sdata + (py - y) * sraster, sourcex, sraster,
205
0
                         gx_no_bitmap_id, scolors, textures, tcolors,
206
0
                         0, 0, width, block_height,
207
0
                         phase_x + x, phase_y + py,
208
0
                         lop, planar_height);
209
0
        if (code < 0)
210
0
            break;
211
0
        if (is_planar) {
212
0
            code = (*dev_proc(dev, copy_planes))
213
0
                            (dev, scan_line_base(pmdev, 0), 0,
214
0
                             draster, gx_no_bitmap_id,
215
0
                             x, py, width, block_height, block_height);
216
0
        } else {
217
0
            code = (*dev_proc(dev, copy_color))
218
0
                            (dev, scan_line_base(pmdev, 0), 0,
219
0
                             draster, gx_no_bitmap_id,
220
0
                             x, py, width, block_height);
221
0
        }
222
0
        if (code < 0)
223
0
            break;
224
0
    }
225
0
out:
226
0
    gs_free_object(mem, row, "copy_rop row");
227
0
    gx_device_retain((gx_device *)pmdev, false);
228
0
    return code;
229
0
}
230
231
/* ---------------- Default memory device copy_rop ---------------- */
232
233
/* Convert color constants to standard RGB representation. */
234
static void
235
unpack_colors_to_standard(gx_device * dev, gx_color_index real_colors[2],
236
                          const gx_color_index * colors, int depth)
237
0
{
238
0
    int i;
239
240
0
    for (i = 0; i < 2; ++i) {
241
0
        gx_color_value rgb[3];
242
0
        gx_color_index pixel;
243
244
0
        (*dev_proc(dev, map_color_rgb)) (dev, colors[i], rgb);
245
0
        pixel = gx_color_value_to_byte(rgb[0]);
246
0
        if (depth > 8) {
247
0
            pixel = (pixel << 16) +
248
0
                (gx_color_value_to_byte(rgb[1]) << 8) +
249
0
                gx_color_value_to_byte(rgb[2]);
250
0
        }
251
0
        real_colors[i] = pixel;
252
0
    }
253
0
}
254
255
/*
256
 * Convert RGB to the device's native format.  We special-case this for
257
 * 1-bit CMYK devices.
258
 */
259
static void
260
pack_cmyk_1bit_from_standard(gx_device_memory * dev, int y, int destx,
261
                             const byte * src, int width, int depth,
262
                             int src_depth)
263
0
{
264
    /*
265
     * This routine is only called if dev_proc(dev, map_cmyk_color) ==
266
     * cmyk_1bit_map_cmyk_color (implying depth == 4) and src_depth == 24.
267
     */
268
0
    byte *dest = scan_line_base(dev, y);
269
0
    int bit_x = destx * 4;
270
0
    byte *dp = dest + (bit_x >> 3);
271
0
    bool hi = (bit_x & 4) != 0;  /* true if last nibble filled was hi */
272
0
    byte buf = (hi ? *dp & 0xf0 : 0);
273
0
    const byte *sp = src;
274
0
    int x;
275
276
0
    for (x = width; --x >= 0; sp += 3) {
277
0
        byte r = sp[0], g = sp[1], b = sp[2];
278
0
        byte pixel =
279
0
            (r | g | b ?
280
0
             (((r >> 4) & 8) | ((g >> 5) & 4) | ((b >> 6) & 2)) ^ 0xe : 1);
281
282
0
        if ((hi = !hi))
283
0
            buf = pixel << 4;
284
0
        else
285
0
            *dp++ = buf | pixel;
286
0
    }
287
0
    if (hi && width > 0)
288
0
        *dp = buf | (*dp & 0xf);
289
290
0
}
291
292
static void
293
pack_planar_cmyk_1bit_from_standard(gx_device_memory * dev, int y, int destx,
294
                                    const byte * src, int width, int depth,
295
                                    int src_depth)
296
0
{
297
    /*
298
     * This routine is only called if dev_proc(dev, map_cmyk_color) ==
299
     * cmyk_1bit_map_cmyk_color (implying depth == 4) and src_depth == 24.
300
     */
301
0
    byte *dp[GX_DEVICE_COLOR_MAX_COMPONENTS];
302
0
    int shift = destx & 7;
303
0
    byte buf[GX_DEVICE_COLOR_MAX_COMPONENTS];
304
0
    const byte *sp = src;
305
0
    int x, plane;
306
307
0
    for (plane = 0; plane < 4; plane++) {
308
0
        byte *dest = scan_line_base(dev, y + plane * dev->height);
309
0
        dp[plane] = dest + (destx >> 3);
310
0
        buf[plane] = (shift == 0 ? 0 : *dp[plane] & (0xff00 >> shift));
311
0
    }
312
313
0
    shift = (0x80>>shift);
314
0
    for (x = width; --x >= 0;) {
315
0
        byte vr, vg, vb;
316
317
0
        vr = *sp++;
318
0
        vg = *sp++;
319
0
        vb = *sp++;
320
0
        if ((vr | vg | vb) == 0)
321
0
            buf[3] += shift;
322
0
        else {
323
0
            if ((vr & 0x80) == 0)
324
0
                buf[0] += shift;
325
0
            if ((vg & 0x80) == 0)
326
0
                buf[1] += shift;
327
0
            if ((vb & 0x80) == 0)
328
0
                buf[2] += shift;
329
0
        }
330
0
        shift >>= 1;
331
0
        if (shift == 0) {
332
0
            *dp[0]++ = buf[0]; buf[0] = 0;
333
0
            *dp[1]++ = buf[1]; buf[1] = 0;
334
0
            *dp[2]++ = buf[2]; buf[2] = 0;
335
0
            *dp[3]++ = buf[3]; buf[3] = 0;
336
0
            shift = 0x80;
337
0
        }
338
0
    }
339
0
    if (shift != 0x80) {
340
0
        shift += shift-1;
341
0
        *dp[0] = (*dp[0] & shift) + buf[0];
342
0
        *dp[1] = (*dp[1] & shift) + buf[1];
343
0
        *dp[2] = (*dp[2] & shift) + buf[2];
344
0
        *dp[3] = (*dp[3] & shift) + buf[3];
345
0
    }
346
0
}
347
348
static gx_color_index
349
map_rgb_to_color_via_cmyk(gx_device * dev, const gx_color_value rgbcv[])
350
0
{
351
0
    gx_color_value cmykcv[4];
352
353
0
    cmykcv[0] = gx_max_color_value - rgbcv[0];
354
0
    cmykcv[1] = gx_max_color_value - rgbcv[1];
355
0
    cmykcv[2] = gx_max_color_value - rgbcv[2];
356
0
    cmykcv[3] = (cmykcv[0] < cmykcv[1] ? min(cmykcv[0], cmykcv[2]) : min(cmykcv[1], cmykcv[2]));
357
358
0
    cmykcv[0] -= cmykcv[3];
359
0
    cmykcv[1] -= cmykcv[3];
360
0
    cmykcv[2] -= cmykcv[3];
361
362
0
    return (*dev_proc(dev, map_cmyk_color)) (dev, cmykcv);
363
0
}
364
static void
365
pack_from_standard(gx_device_memory * dev, int y, int destx, const byte * src,
366
                   int width, int depth, int src_depth)
367
0
{
368
0
    byte *dest = scan_line_base(dev, y);
369
0
    dev_proc_map_rgb_color((*map)) =
370
0
        (dev->color_info.num_components == 4 ?
371
0
         map_rgb_to_color_via_cmyk : dev_proc(dev, map_rgb_color));
372
0
    int bit_x = destx * depth;
373
0
    byte *dp = dest + (bit_x >> 3);
374
    /* RJW: I'm suspicious of this; see how shift = bit_x & 7 in the planar
375
     * 1bit version above? Has anything ever used the <8 bit code here? */
376
0
    int shift = (~bit_x & 7) + 1;
377
0
    byte buf = (shift == 8 ? 0 : *dp & (0xff00 >> shift));
378
0
    const byte *sp = src;
379
0
    int x;
380
381
0
    for (x = width; --x >= 0;) {
382
0
        byte vr, vg, vb;
383
0
        gx_color_index pixel;
384
0
        byte chop = 0x1;
385
386
0
        vr = *sp++;
387
0
        if (src_depth > 8) {
388
0
            vg = *sp++;
389
0
            vb = *sp++;
390
0
        } else
391
0
            vb = vg = vr;
392
        /*
393
         * We have to map back to some pixel value, even if the color
394
         * isn't accurate.
395
         */
396
0
        for (;;) {
397
0
            gx_color_value cv[3];
398
0
            cv[0] = gx_color_value_from_byte(vr);
399
0
            cv[1] = gx_color_value_from_byte(vg);
400
0
            cv[2] = gx_color_value_from_byte(vb);
401
0
            pixel = (*map) ((gx_device *)dev, cv);
402
0
            if (pixel != gx_no_color_index)
403
0
                break;
404
            /* Reduce the color accuracy and try again. */
405
0
            vr = (vr >= 0x80 ? vr | chop : vr & ~chop);
406
0
            vg = (vg >= 0x80 ? vg | chop : vg & ~chop);
407
0
            vb = (vb >= 0x80 ? vb | chop : vb & ~chop);
408
0
            chop <<= 1;
409
0
        }
410
0
        if ((shift -= depth) >= 0)
411
0
            buf += (byte)(pixel << shift);
412
0
        else {
413
0
            switch (depth) {
414
0
            default:            /* 1, 2, 4, 8 */
415
0
                *dp++ = buf;
416
0
                shift += 8;
417
0
                buf = (byte)(pixel << shift);
418
0
                break;
419
0
            case 32:
420
0
                *dp++ = (byte)(pixel >> 24);
421
0
                *dp++ = (byte)(pixel >> 16);
422
                /* fall through */
423
0
            case 16:
424
0
                *dp++ = (byte)(pixel >> 8);
425
0
                *dp++ = (byte)pixel;
426
0
                shift = 0;
427
0
            }
428
0
        }
429
0
    }
430
0
    if (width > 0 && depth <= 8)
431
0
        *dp = (shift == 0 ? buf : buf + (*dp & ((1 << shift) - 1)));
432
0
}
433
434
static void
435
pack_planar_from_standard(gx_device_memory * dev, int y, int destx,
436
                          const byte * src, int width, int depth, int src_depth)
437
0
{
438
    /* This code assumes that all planar planes have the same depth */
439
0
    dev_proc_map_rgb_color((*map)) =
440
0
        (dev->color_info.num_components == 4 ?
441
0
         map_rgb_to_color_via_cmyk : dev_proc(dev, map_rgb_color));
442
0
    int pdepth = dev->plane_depth;
443
0
    int bit_x = destx * pdepth;
444
0
    byte *dp[GX_DEVICE_COLOR_MAX_COMPONENTS];
445
0
    int shift = (~bit_x & 7) + 1;
446
0
    byte buf[GX_DEVICE_COLOR_MAX_COMPONENTS];
447
0
    const byte *sp = src;
448
0
    int x;
449
0
    uchar plane;
450
451
0
    if (pdepth == 1 && dev->color_info.num_components == 4) {
452
0
        pack_planar_cmyk_1bit_from_standard(dev, y, destx, src, width,
453
0
                                            depth, src_depth);
454
0
        return;
455
0
    }
456
457
0
    for (plane = 0; plane < dev->color_info.num_components; plane++) {
458
0
        byte *dest = scan_line_base(dev, y + plane * dev->height);
459
0
        dp[plane] = dest + (bit_x >> 3);
460
0
        buf[plane] = (shift == 8 ? 0 : *dp[plane] & (0xff00 >> shift));
461
0
    }
462
463
0
    for (x = width; --x >= 0;) {
464
0
        byte vr, vg, vb;
465
0
        gx_color_index pixel;
466
0
        byte chop = 0x1;
467
468
0
        vr = *sp++;
469
0
        if (src_depth > 8) {
470
0
            vg = *sp++;
471
0
            vb = *sp++;
472
0
        } else
473
0
            vb = vg = vr;
474
        /*
475
         * We have to map back to some pixel value, even if the color
476
         * isn't accurate.
477
         */
478
0
        for (;;) {
479
0
            gx_color_value cv[3];
480
0
            cv[0] = gx_color_value_from_byte(vr);
481
0
            cv[1] = gx_color_value_from_byte(vg);
482
0
            cv[2] = gx_color_value_from_byte(vb);
483
0
            pixel = (*map) ((gx_device *)dev, cv);
484
0
            if (pixel != gx_no_color_index)
485
0
                break;
486
            /* Reduce the color accuracy and try again. */
487
0
            vr = (vr >= 0x80 ? vr | chop : vr & ~chop);
488
0
            vg = (vg >= 0x80 ? vg | chop : vg & ~chop);
489
0
            vb = (vb >= 0x80 ? vb | chop : vb & ~chop);
490
0
            chop <<= 1;
491
0
        }
492
0
        switch (depth) {
493
0
            case 32:
494
0
                *dp[0]++ = (byte)(pixel >> 24);
495
0
                *dp[1]++ = (byte)(pixel >> 16);
496
0
                *dp[2]++ = (byte)(pixel >> 8);
497
0
                *dp[3]++ = (byte)pixel;
498
0
                shift = 0;
499
0
                break;
500
0
            case 24:
501
0
                *dp[0]++ = (byte)(pixel >> 16);
502
0
                *dp[1]++ = (byte)(pixel >> 8);
503
0
                *dp[2]++ = (byte)pixel;
504
0
                shift = 0;
505
0
                break;
506
0
            case 16:
507
0
                *dp[0]++ = (byte)(pixel >> 8);
508
0
                *dp[1]++ = (byte)pixel;
509
0
                shift = 0;
510
0
                break;
511
0
            default:            /* 1, 2, 4, 8 */
512
0
            {
513
0
                int pmask = (1<<pdepth)-1;
514
515
#ifdef ORIGINAL_CODE_KEPT_FOR_REFERENCE
516
                /* Original code, kept for reference. I believe this copies
517
                 * bits in the wrong order (i.e. the 0th component comes from
518
                 * the lowest bits in pixel, rather than the highest), and
519
                 * gets them from the wrong place (8 bits apart rather than
520
                 * pdepth), but as I have no examples that actually tickle
521
                 * this code, currently, I don't want to throw it away. */
522
                int pshift = 8-pdepth;
523
#else
524
                /* We have pdepth*num_planes bits in 'pixel'. We need to copy
525
                 * them (topmost bits first) into the buffer, packing them at
526
                 * shift position. */
527
0
                int pshift = pdepth*(dev->color_info.num_components-1);
528
0
#endif
529
                /* Can we fit another pdepth bits into our buffer? */
530
0
                shift -= pdepth;
531
0
                if (shift < 0) {
532
                    /* No, so flush the buffer to the planes. */
533
0
                    for (plane = 0; plane < dev->color_info.num_components; plane++)
534
0
                        *dp[plane]++ = buf[plane];
535
0
                    shift += 8;
536
0
                }
537
                /* Copy the next pdepth bits into each planes buffer */
538
#ifdef ORIGINAL_CODE_KEPT_FOR_REFERENCE
539
                for (plane = 0; plane < dev->color_info.num_components; pshift+=8,plane++)
540
                    buf[plane] += (byte)(((pixel>>pshift) & pmask)<<shift);
541
#else
542
0
                for (plane = 0; plane < dev->color_info.num_components; pshift-=pdepth,plane++)
543
0
                    buf[plane] += (byte)(((pixel>>pshift) & pmask)<<shift);
544
0
#endif
545
0
                break;
546
0
            }
547
0
        }
548
0
    }
549
0
    if (width > 0 && depth <= 8) {
550
0
        if (shift == 0)
551
0
            for (plane = 0; plane < dev->color_info.num_components; plane++)
552
0
                *dp[plane] = buf[plane];
553
0
        else {
554
0
            int mask = (1<<shift)-1;
555
0
            for (plane = 0; plane < dev->color_info.num_components; plane++)
556
0
                *dp[plane] = (*dp[plane] & mask) + buf[plane];
557
0
        }
558
0
    }
559
0
}
560
561
/*
562
 * The default implementation for memory devices uses get_bits_rectangle to
563
 * read out the pixels and convert them to standard (8-bit gray or 24-bit
564
 * RGB) representation, the standard memory device implementation to do the
565
 * operation, pack_from_standard to convert them back to the device
566
 * representation, and copy_color to write the pixels back.
567
 */
568
static int
569
do_strip_copy_rop(gx_device * dev,
570
                           const byte * sdata, int sourcex,
571
                           uint sraster, gx_bitmap_id id,
572
                           const gx_color_index * scolors,
573
                           const gx_strip_bitmap * textures,
574
                           const gx_color_index * tcolors,
575
                           int x, int y, int width, int height,
576
                           int phase_x, int phase_y,
577
                           gs_logical_operation_t olop)
578
0
{
579
0
    int depth = dev->color_info.depth;
580
0
    int rop_depth = (gx_device_has_color(dev) ? 24 : 8);
581
0
    void (*pack)(gx_device_memory *, int, int, const byte *, int, int, int);
582
0
    const gx_bitmap_format_t no_expand_options =
583
0
        GB_COLORS_NATIVE | GB_ALPHA_NONE | GB_DEPTH_ALL |
584
0
        GB_PACKING_CHUNKY | GB_RETURN_ALL | GB_ALIGN_STANDARD |
585
0
        GB_OFFSET_0 | GB_OFFSET_ANY | GB_RASTER_STANDARD;
586
0
    const gx_bitmap_format_t no_expand_t_options =
587
0
        GB_COLORS_NATIVE | GB_ALPHA_NONE | GB_DEPTH_ALL |
588
0
        GB_RETURN_ALL | GB_ALIGN_STANDARD |
589
0
        GB_OFFSET_0 | GB_OFFSET_ANY | GB_RASTER_STANDARD |
590
0
        ((textures && textures->num_planes > 1) ? GB_PACKING_PLANAR : GB_PACKING_CHUNKY);
591
0
    const gx_bitmap_format_t expand_options =
592
0
        (rop_depth > 8 ? GB_COLORS_RGB : GB_COLORS_GRAY) |
593
0
        GB_ALPHA_NONE | GB_DEPTH_8 |
594
0
        GB_PACKING_CHUNKY | GB_RETURN_COPY | GB_ALIGN_STANDARD |
595
0
        GB_OFFSET_0 | GB_RASTER_STANDARD;
596
0
    gs_memory_t *mem = dev->memory;
597
0
    const gx_device_memory *mdproto = gdev_mem_device_for_bits(rop_depth);
598
0
    gx_device_memory mdev;
599
0
    union { long l; void *p; } mdev_storage[20];
600
0
    uint row_raster = bitmap_raster(width * depth);
601
0
    ulong size_from_mem_device;
602
0
    gs_logical_operation_t lop = lop_sanitize(olop);
603
0
    bool uses_d = rop3_uses_D(lop);
604
0
    bool uses_s = rop3_uses_S(lop);
605
0
    bool uses_t = rop3_uses_T(lop);
606
0
    bool expand_s, expand_t;
607
0
    byte *row = 0;
608
0
    union { long l; void *p; } dest_buffer[16];
609
0
    byte *source_row = 0;
610
0
    uint source_row_raster = 0; /* init to quiet compiler warning */
611
0
    union { long l; void *p; } source_buffer[16];
612
0
    byte *texture_row = 0;
613
0
    uint texture_row_raster;
614
0
    union { long l; void *p; } texture_buffer[16];
615
0
    gx_color_index source_colors[2];
616
0
    const gx_color_index *real_scolors = scolors;
617
0
    gx_color_index texture_colors[2];
618
0
    const gx_color_index *real_tcolors = tcolors;
619
0
    gx_strip_bitmap rop_texture;
620
0
    const gx_strip_bitmap *real_texture = textures;
621
0
    gs_int_rect rect;
622
0
    gs_get_bits_params_t bit_params;
623
0
    gs_get_bits_params_t expand_params;
624
0
    gs_get_bits_params_t no_expand_params;
625
0
    gs_get_bits_params_t no_expand_t_params;
626
0
    int max_height;
627
0
    int block_height, loop_height;
628
0
    int code;
629
0
    int py;
630
0
    gx_device_memory *tdev = (gx_device_memory *)dev;
631
632
/*
633
 * Allocate a temporary row buffer.  Free variables: mem, block_height.
634
 * Labels used: out.
635
 */
636
0
#define ALLOC_BUF(buf, prebuf, size, cname)\
637
0
        BEGIN\
638
0
          uint num_bytes = (size) * block_height;\
639
0
\
640
0
          if (num_bytes <= sizeof(prebuf))\
641
0
            buf = (byte *)prebuf;\
642
0
          else {\
643
0
            buf = gs_alloc_bytes(mem, num_bytes, cname);\
644
0
            if (buf == 0) {\
645
0
              code = gs_note_error(gs_error_VMerror);\
646
0
              goto out;\
647
0
            }\
648
0
          }\
649
0
        END
650
651
    /* We know the device is a memory device, so we can store the
652
     * result directly into its scan lines, unless it is planar. */
653
0
    if (!tdev->is_planar || tdev->color_info.num_components <= 1) {
654
0
        if ((rop_depth == 24) && (dev_proc(dev, dev_spec_op)(dev,
655
0
                                      gxdso_is_std_cmyk_1bit, NULL, 0) > 0)) {
656
0
            pack = pack_cmyk_1bit_from_standard;
657
0
        } else {
658
0
            pack = pack_from_standard;
659
0
        }
660
0
    } else {
661
0
        pack = pack_planar_from_standard;
662
0
    }
663
#ifdef DEBUG
664
    if (gs_debug_c('b'))
665
        trace_copy_rop("mem_default_strip_copy_rop",
666
                       dev, sdata, sourcex, sraster,
667
                       id, scolors, textures, tcolors,
668
                       x, y, width, height, phase_x, phase_y, lop);
669
#endif
670
0
    if (mdproto == 0)
671
0
        return_error(gs_error_rangecheck);
672
0
    if (sdata == 0) {
673
0
        fit_fill(dev, x, y, width, height);
674
0
    } else {
675
0
        fit_copy(dev, sdata, sourcex, sraster, id, x, y, width, height);
676
0
    }
677
    /* Compute max_height conservatively. */
678
0
    max_height = max_rop_bitmap / (width * rop_depth);
679
0
    if (max_height == 0)
680
0
        max_height = 1;
681
0
    block_height = min(height, max_height);
682
0
    expand_s = scolors == 0 && uses_s;
683
0
    expand_t = tcolors == 0 && uses_t;
684
0
    no_expand_params.options = no_expand_options;
685
0
    no_expand_t_params.options = no_expand_t_options;
686
0
    if (expand_t) {
687
        /*
688
         * We don't want to wrap around more than once in Y when
689
         * copying the texture to the intermediate buffer.
690
         */
691
0
        if (textures && textures->size.y < block_height)
692
0
            block_height = textures->size.y;
693
0
    }
694
0
    gs_make_mem_device(&mdev, mdproto, mem, -1, NULL);
695
0
    gx_device_retain((gx_device *)&mdev, true); /* prevent freeing */
696
0
    mdev.width = width;
697
0
    mdev.height = block_height;
698
0
    mdev.color_info.num_components = rop_depth >> 3;
699
0
    if (gdev_mem_data_size(&mdev, width, block_height, &size_from_mem_device) >= 0 &&
700
0
        size_from_mem_device <= sizeof(mdev_storage)) {
701
        /* Use the locally allocated storage. */
702
0
        mdev.base = (byte *)mdev_storage;
703
0
        if ((code = gdev_mem_bits_size(&mdev, mdev.width, mdev.height, &size_from_mem_device)) < 0)
704
0
            return code;
705
0
        mdev.line_ptrs = (byte **) (mdev.base + size_from_mem_device);
706
0
    } else {
707
0
        mdev.bitmap_memory = mem;
708
0
    }
709
0
    code = (*dev_proc(&mdev, open_device))((gx_device *)&mdev);
710
0
    if (code < 0)
711
0
        return code;
712
0
    ALLOC_BUF(row, dest_buffer, row_raster, "copy_rop row");
713
    /* We may need intermediate buffers for all 3 operands. */
714
0
    if (expand_s) {
715
0
        source_row_raster = bitmap_raster(width * rop_depth);
716
0
        ALLOC_BUF(source_row, source_buffer, source_row_raster,
717
0
                  "copy_rop source_row");
718
0
    }
719
0
    if (scolors && uses_s) {
720
0
        unpack_colors_to_standard(dev, source_colors, scolors, rop_depth);
721
0
        real_scolors = source_colors;
722
0
    }
723
0
    if (expand_t && textures) {
724
0
        texture_row_raster = bitmap_raster(textures->rep_width * rop_depth);
725
0
        ALLOC_BUF(texture_row, texture_buffer, texture_row_raster,
726
0
                  "copy_rop texture_row");
727
0
        rop_texture = *textures;
728
0
        rop_texture.data = texture_row;
729
0
        rop_texture.raster = texture_row_raster;
730
0
        rop_texture.size.x = rop_texture.rep_width;
731
0
        rop_texture.id = gs_no_bitmap_id;
732
0
        real_texture = &rop_texture;
733
0
        if (rop_texture.size.y > rop_texture.rep_height)
734
0
            rop_texture.size.y = rop_texture.rep_height;   /* we only allocated one row_raster, no reps */
735
0
    }
736
0
    if (tcolors && uses_t) {
737
0
        unpack_colors_to_standard(dev, texture_colors, tcolors, rop_depth);
738
0
        real_tcolors = texture_colors;
739
0
    }
740
0
    expand_params.options = expand_options;
741
0
    expand_params.x_offset = 0;
742
0
    rect.p.x = x;
743
0
    rect.q.x = x + width;
744
0
    for (py = y; py < y + height; py += loop_height) {
745
0
        int sx = sourcex;
746
0
        const byte *source_data = sdata + (py - y) * sraster;
747
0
        uint source_raster = sraster;
748
749
0
        if (block_height > y + height - py)
750
0
            block_height = y + height - py;
751
0
        rect.p.y = py;
752
0
        if (expand_t) {
753
0
            int rep_y = (phase_y + py) % rop_texture.rep_height;
754
755
0
            loop_height = min(block_height, rop_texture.size.y - rep_y);
756
0
            rect.q.y = py + loop_height;
757
0
            expand_params.data[0] = texture_row;
758
0
            gx_get_bits_copy(dev, 0, textures->rep_width, loop_height,
759
0
                             &expand_params, &no_expand_t_params,
760
0
                             textures->data + rep_y * textures->raster,
761
0
                             textures->raster);
762
            /*
763
             * Compensate for the addition of rep_y * raster
764
             * in the subsidiary strip_copy_rop call.
765
             */
766
0
            rop_texture.data = texture_row - rep_y * rop_texture.raster;
767
0
        } else {
768
0
            loop_height = block_height;
769
0
            rect.q.y = py + block_height;
770
0
        }
771
0
        if (uses_d) {
772
0
            bit_params.options = expand_options;
773
0
            bit_params.data[0] = scan_line_base(&mdev, 0);
774
0
            bit_params.x_offset = 0;
775
0
            bit_params.raster = mdev.raster;
776
0
            code = (*dev_proc(dev, get_bits_rectangle))
777
0
                (dev, &rect, &bit_params);
778
0
            if (code < 0)
779
0
                break;
780
0
        }
781
        /* Convert the source and texture to standard format. */
782
0
        if (expand_s) {
783
0
            expand_params.data[0] = source_row;
784
0
            gx_get_bits_copy(dev, sx, width, loop_height, &expand_params,
785
0
                             &no_expand_params, source_data, sraster);
786
0
            sx = 0;
787
0
            source_data = source_row;
788
0
            source_raster = source_row_raster;
789
0
        }
790
0
        code = (*dev_proc(&mdev, strip_copy_rop2))
791
0
            ((gx_device *)&mdev, source_data, sx, source_raster,
792
0
             gx_no_bitmap_id, real_scolors, real_texture, real_tcolors,
793
0
             0, 0, width, loop_height, phase_x + x, phase_y + py, lop, 0);
794
0
        if (code < 0)
795
0
            break;
796
        /* Convert the result back to the device's format. */
797
0
        {
798
0
            int i;
799
0
            const byte *unpacked = scan_line_base(&mdev, 0);
800
801
0
            for (i = 0; i < loop_height; unpacked += mdev.raster, ++i) {
802
0
                pack(tdev, py + i, x, unpacked, width, depth, rop_depth);
803
0
            }
804
0
        }
805
0
    }
806
0
out:
807
0
    if (texture_row != 0 && texture_row != (byte *)texture_buffer)
808
0
        gs_free_object(mem, texture_row, "copy_rop texture_row");
809
0
    if (source_row != 0 && source_row != (byte *)source_buffer)
810
0
        gs_free_object(mem, source_row, "copy_rop source_row");
811
0
    if (row != 0 && row != (byte *)dest_buffer)
812
0
        gs_free_object(mem, row, "copy_rop row");
813
0
    (*dev_proc(&mdev, close_device)) ((gx_device *) & mdev);
814
0
    return code;
815
0
}
816
817
int
818
mem_default_strip_copy_rop2(gx_device * dev,
819
                            const byte * sdata, int sourcex,
820
                            uint sraster, gx_bitmap_id id,
821
                            const gx_color_index * scolors,
822
                            const gx_strip_bitmap * textures,
823
                            const gx_color_index * tcolors,
824
                            int x, int y, int width, int height,
825
                            int phase_x, int phase_y,
826
                            gs_logical_operation_t lop,
827
                            uint planar_height)
828
0
{
829
0
    if (planar_height != 0)
830
0
    {
831
0
        dmlprintf(dev->memory, "mem_default_strip_copy_rop2 should never be called!\n");
832
0
        return_error(gs_error_Fatal);
833
0
    }
834
0
    return do_strip_copy_rop(dev, sdata, sourcex, sraster, id, scolors,
835
0
                             textures, tcolors, x, y, width, height,
836
0
                             phase_x, phase_y, lop);
837
0
}
838
839
/* ---------------- Internal routines ---------------- */
840
841
typedef enum {
842
    transform_pixel_region_portrait,
843
    transform_pixel_region_landscape,
844
    transform_pixel_region_skew
845
} transform_pixel_region_posture;
846
847
typedef struct mem_transform_pixel_region_state_s mem_transform_pixel_region_state_t;
848
849
typedef int (mem_transform_pixel_region_render_fn)(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs);
850
851
struct mem_transform_pixel_region_state_s
852
{
853
    gs_memory_t *mem;
854
    gx_dda_fixed_point pixels;
855
    gx_dda_fixed_point rows;
856
    gs_int_rect clip;
857
    int w;
858
    int h;
859
    int spp;
860
    transform_pixel_region_posture posture;
861
    mem_transform_pixel_region_render_fn *render;
862
    void *passthru;
863
#ifdef WITH_CAL
864
    cal_context *cal_ctx;
865
    cal_doubler *cal_dbl;
866
#endif
867
};
868
869
static void
870
get_portrait_y_extent(mem_transform_pixel_region_state_t *state, int *iy, int *ih)
871
0
{
872
0
    fixed y0, y1;
873
0
    gx_dda_fixed row = state->rows.y;
874
875
0
    y0 = dda_current(row);
876
0
    dda_next(row);
877
0
    y1 = dda_current(row);
878
879
0
    if (y1 < y0) {
880
0
        fixed t = y1; y1 = y0; y0 = t;
881
0
    }
882
883
0
    *iy = fixed2int_pixround_perfect(y0);
884
0
    *ih = fixed2int_pixround_perfect(y1) - *iy;
885
0
}
886
887
static void
888
get_landscape_x_extent(mem_transform_pixel_region_state_t *state, int *ix, int *iw)
889
0
{
890
0
    fixed x0, x1;
891
0
    gx_dda_fixed row = state->rows.x;
892
893
0
    x0 = dda_current(row);
894
0
    dda_next(row);
895
0
    x1 = dda_current(row);
896
897
0
    if (x1 < x0) {
898
0
        fixed t = x1; x1 = x0; x0 = t;
899
0
    }
900
901
0
    *ix = fixed2int_pixround_perfect(x0);
902
0
    *iw = fixed2int_pixround_perfect(x1) - *ix;
903
0
}
904
905
static inline int
906
template_mem_transform_pixel_region_render_portrait(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs, int spp)
907
0
{
908
0
    gx_device_memory *mdev = (gx_device_memory *)dev;
909
0
    gx_dda_fixed_point pnext;
910
0
    int vci, vdi;
911
0
    int irun;     /* int x/rrun */
912
0
    int w = state->w;
913
0
    int h = state->h;
914
0
    const byte *data = buffer[0] + data_x * spp;
915
0
    const byte *bufend = NULL;
916
0
    const byte *run;
917
0
    int k;
918
0
    gx_color_value *conc = &cmapper->conc[0];
919
0
    gx_cmapper_fn *mapper = cmapper->set_color;
920
0
    byte *out;
921
0
    byte *out_row;
922
0
    int minx, maxx;
923
924
0
    if (h == 0)
925
0
        return 0;
926
927
    /* Clip on y */
928
0
    get_portrait_y_extent(state, &vci, &vdi);
929
0
    if (vci < state->clip.p.y)
930
0
        vdi += vci - state->clip.p.y, vci = state->clip.p.y;
931
0
    if (vci+vdi > state->clip.q.y)
932
0
        vdi = state->clip.q.y - vci;
933
0
    if (vdi <= 0)
934
0
        return 0;
935
936
0
    pnext = state->pixels;
937
0
    dda_translate(pnext.x,  (-fixed_epsilon));
938
0
    irun = fixed2int_var_rounded(dda_current(pnext.x));
939
0
    if_debug5m('b', dev->memory, "[b]y=%d data_x=%d w=%d xt=%f yt=%f\n",
940
0
               vci, data_x, w, fixed2float(dda_current(pnext.x)), fixed2float(dda_current(pnext.y)));
941
942
0
    minx = state->clip.p.x;
943
0
    maxx = state->clip.q.x;
944
0
    out_row = mdev->base + mdev->raster * vci;
945
0
    bufend = data + w * spp;
946
0
    while (data < bufend) {
947
        /* Find the length of the next run. It will either end when we hit
948
         * the end of the source data, or when the pixel data differs. */
949
0
        run = data + spp;
950
0
        while (1) {
951
0
            dda_next(pnext.x);
952
0
            if (run >= bufend)
953
0
                break;
954
0
            if (memcmp(run, data, spp))
955
0
                break;
956
0
            run += spp;
957
0
        }
958
        /* So we have a run of pixels from data to run that are all the same. */
959
        /* This needs to be sped up */
960
0
        for (k = 0; k < spp; k++) {
961
0
            conc[k] = gx_color_value_from_byte(data[k]);
962
0
        }
963
0
        mapper(cmapper);
964
        /* Fill the region between irun and fixed2int_var_rounded(pnext.x) */
965
0
        {
966
0
            int xi = irun;
967
0
            int wi = (irun = fixed2int_var_rounded(dda_current(pnext.x))) - xi;
968
969
0
            if (wi < 0)
970
0
                xi += wi, wi = -wi;
971
972
0
            if (xi < minx)
973
0
                wi += xi - minx, xi = minx;
974
0
            if (xi+wi > maxx)
975
0
                wi = maxx - xi;
976
0
            if (wi > 0) {
977
                /* assert(color_is_pure(&cmapper->devc)); */
978
0
                out = out_row;
979
0
                for (h = vdi; h > 0; h--, out += mdev->raster) {
980
0
                    gx_color_index color = cmapper->devc.colors.pure;
981
0
                    int xii = xi * spp;
982
0
                    int wii = wi;
983
0
                    do {
984
                        /* Excuse the double shifts below, that's to stop the
985
                         * C compiler complaining if the color index type is
986
                         * 32 bits. */
987
0
                        switch(spp)
988
0
                        {
989
0
                        case 8: out[xii++] = ((color>>28)>>28) & 0xff;
990
0
                        case 7: out[xii++] = ((color>>24)>>24) & 0xff;
991
0
                        case 6: out[xii++] = ((color>>24)>>16) & 0xff;
992
0
                        case 5: out[xii++] = ((color>>24)>>8) & 0xff;
993
0
                        case 4: out[xii++] = (color>>24) & 0xff;
994
0
                        case 3: out[xii++] = (color>>16) & 0xff;
995
0
                        case 2: out[xii++] = (color>>8) & 0xff;
996
0
                        case 1: out[xii++] = color & 0xff;
997
0
                        }
998
0
                    } while (--wii != 0);
999
0
                }
1000
0
            }
1001
0
        }
1002
0
        data = run;
1003
0
    }
1004
0
    return 0;
1005
0
}
1006
1007
static int
1008
mem_transform_pixel_region_render_portrait_1(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1009
0
{
1010
0
    return template_mem_transform_pixel_region_render_portrait(dev, state, buffer, data_x, cmapper, pgs, 1);
1011
0
}
1012
1013
static int
1014
mem_transform_pixel_region_render_portrait_3(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1015
0
{
1016
0
    return template_mem_transform_pixel_region_render_portrait(dev, state, buffer, data_x, cmapper, pgs, 3);
1017
0
}
1018
1019
static int
1020
mem_transform_pixel_region_render_portrait_4(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1021
0
{
1022
0
    return template_mem_transform_pixel_region_render_portrait(dev, state, buffer, data_x, cmapper, pgs, 4);
1023
0
}
1024
1025
static int
1026
mem_transform_pixel_region_render_portrait_n(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1027
0
{
1028
0
    return template_mem_transform_pixel_region_render_portrait(dev, state, buffer, data_x, cmapper, pgs, state->spp);
1029
0
}
1030
1031
static inline int
1032
template_mem_transform_pixel_region_render_portrait_planar(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs, int spp)
1033
0
{
1034
0
    gx_device_memory *mdev = (gx_device_memory *)dev;
1035
0
    gx_dda_fixed_point pnext;
1036
0
    int vci, vdi;
1037
0
    int irun;     /* int x/rrun */
1038
0
    int w = state->w;
1039
0
    int h = state->h;
1040
0
    const byte *data = buffer[0] + data_x * spp;
1041
0
    const byte *bufend = NULL;
1042
0
    const byte *run;
1043
0
    int k;
1044
0
    gx_color_value *conc = &cmapper->conc[0];
1045
0
    gx_cmapper_fn *mapper = cmapper->set_color;
1046
0
    int minx, maxx;
1047
1048
0
    if (h == 0)
1049
0
        return 0;
1050
1051
    /* Clip on y */
1052
0
    get_portrait_y_extent(state, &vci, &vdi);
1053
0
    if (vci < state->clip.p.y)
1054
0
        vdi += vci - state->clip.p.y, vci = state->clip.p.y;
1055
0
    if (vci+vdi > state->clip.q.y)
1056
0
        vdi = state->clip.q.y - vci;
1057
0
    if (vdi <= 0)
1058
0
        return 0;
1059
1060
0
    pnext = state->pixels;
1061
0
    dda_translate(pnext.x,  (-fixed_epsilon));
1062
0
    irun = fixed2int_var_rounded(dda_current(pnext.x));
1063
0
    if_debug5m('b', dev->memory, "[b]y=%d data_x=%d w=%d xt=%f yt=%f\n",
1064
0
               vci, data_x, w, fixed2float(dda_current(pnext.x)), fixed2float(dda_current(pnext.y)));
1065
1066
0
    minx = state->clip.p.x;
1067
0
    maxx = state->clip.q.x;
1068
0
    bufend = data + w * spp;
1069
0
    while (data < bufend) {
1070
        /* Find the length of the next run. It will either end when we hit
1071
         * the end of the source data, or when the pixel data differs. */
1072
0
        run = data + spp;
1073
0
        while (1) {
1074
0
            dda_next(pnext.x);
1075
0
            if (run >= bufend)
1076
0
                break;
1077
0
            if (memcmp(run, data, spp))
1078
0
                break;
1079
0
            run += spp;
1080
0
        }
1081
        /* So we have a run of pixels from data to run that are all the same. */
1082
        /* This needs to be sped up */
1083
0
        for (k = 0; k < spp; k++) {
1084
0
            conc[k] = gx_color_value_from_byte(data[k]);
1085
0
        }
1086
0
        mapper(cmapper);
1087
        /* Fill the region between irun and fixed2int_var_rounded(pnext.x) */
1088
0
        {
1089
0
            int xi = irun;
1090
0
            int wi = (irun = fixed2int_var_rounded(dda_current(pnext.x))) - xi;
1091
1092
0
            if (wi < 0)
1093
0
                xi += wi, wi = -wi;
1094
1095
0
            if (xi < minx)
1096
0
                wi += xi - minx, xi = minx;
1097
0
            if (xi+wi > maxx)
1098
0
                wi = maxx - xi;
1099
0
            if (wi > 0) {
1100
                /* assert(color_is_pure(&cmapper->devc)); */
1101
0
                gx_color_index color = cmapper->devc.colors.pure;
1102
0
                for (k = 0; k < spp; k++) {
1103
0
                    unsigned char c = (color>>mdev->planes[k].shift) & ((1<<mdev->planes[k].depth)-1);
1104
0
                    for (h = 0; h < vdi; h++) {
1105
0
                        byte *out = mdev->line_ptrs[vci + h + k*mdev->height] + xi;
1106
0
                        memset(out, c, wi);
1107
0
                    }
1108
0
                }
1109
0
            }
1110
0
        }
1111
0
        data = run;
1112
0
    }
1113
0
    return 0;
1114
0
}
1115
1116
static int
1117
mem_transform_pixel_region_render_portrait_1p(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1118
0
{
1119
0
    return template_mem_transform_pixel_region_render_portrait_planar(dev, state, buffer, data_x, cmapper, pgs, 1);
1120
0
}
1121
1122
static int
1123
mem_transform_pixel_region_render_portrait_3p(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1124
0
{
1125
0
    return template_mem_transform_pixel_region_render_portrait_planar(dev, state, buffer, data_x, cmapper, pgs, 3);
1126
0
}
1127
1128
static int
1129
mem_transform_pixel_region_render_portrait_4p(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1130
0
{
1131
0
    return template_mem_transform_pixel_region_render_portrait_planar(dev, state, buffer, data_x, cmapper, pgs, 4);
1132
0
}
1133
1134
static int
1135
mem_transform_pixel_region_render_portrait_np(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1136
0
{
1137
0
    return template_mem_transform_pixel_region_render_portrait_planar(dev, state, buffer, data_x, cmapper, pgs, state->spp);
1138
0
}
1139
1140
static int
1141
mem_transform_pixel_region_render_portrait_planar(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1142
0
{
1143
0
    switch(state->spp) {
1144
0
    case 1:
1145
0
        return mem_transform_pixel_region_render_portrait_1p(dev, state, buffer, data_x, cmapper, pgs);
1146
0
    case 3:
1147
0
        return mem_transform_pixel_region_render_portrait_3p(dev, state, buffer, data_x, cmapper, pgs);
1148
0
    case 4:
1149
0
        return mem_transform_pixel_region_render_portrait_4p(dev, state, buffer, data_x, cmapper, pgs);
1150
0
    default:
1151
0
        return mem_transform_pixel_region_render_portrait_np(dev, state, buffer, data_x, cmapper, pgs);
1152
0
    }
1153
0
}
1154
1155
static int
1156
mem_transform_pixel_region_render_portrait(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1157
0
{
1158
0
    switch(state->spp) {
1159
0
    case 1:
1160
0
        return mem_transform_pixel_region_render_portrait_1(dev, state, buffer, data_x, cmapper, pgs);
1161
0
    case 3:
1162
0
        return mem_transform_pixel_region_render_portrait_3(dev, state, buffer, data_x, cmapper, pgs);
1163
0
    case 4:
1164
0
        return mem_transform_pixel_region_render_portrait_4(dev, state, buffer, data_x, cmapper, pgs);
1165
0
    default:
1166
0
        return mem_transform_pixel_region_render_portrait_n(dev, state, buffer, data_x, cmapper, pgs);
1167
0
    }
1168
0
}
1169
1170
static inline int
1171
template_mem_transform_pixel_region_render_portrait_1to1(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs, int spp)
1172
0
{
1173
0
    gx_device_memory *mdev = (gx_device_memory *)dev;
1174
0
    gx_dda_fixed_point pnext;
1175
0
    int vci, vdi;
1176
0
    int w = state->w;
1177
0
    int h = state->h;
1178
0
    int left, right, oleft;
1179
1180
0
    if (h == 0)
1181
0
        return 0;
1182
1183
    /* Clip on y */
1184
0
    get_portrait_y_extent(state, &vci, &vdi);
1185
0
    if (vci < state->clip.p.y)
1186
0
        vdi += vci - state->clip.p.y, vci = state->clip.p.y;
1187
0
    if (vci+vdi > state->clip.q.y)
1188
0
        vdi = state->clip.q.y - vci;
1189
0
    if (vdi <= 0)
1190
0
        return 0;
1191
1192
0
    pnext = state->pixels;
1193
0
    dda_translate(pnext.x,  (-fixed_epsilon));
1194
0
    left = fixed2int_var_rounded(dda_current(pnext.x));
1195
0
    if_debug5m('b', dev->memory, "[b]y=%d data_x=%d w=%d xt=%f yt=%f\n",
1196
0
               vci, data_x, w, fixed2float(dda_current(pnext.x)), fixed2float(dda_current(pnext.y)));
1197
0
    right = fixed2int_var_rounded(dda_current(pnext.x)) + w;
1198
1199
0
    if (left > right) {
1200
0
        int tmp = left; left = right; right = tmp;
1201
0
    }
1202
0
    oleft = left;
1203
0
    if (left < state->clip.p.x)
1204
0
        left = state->clip.p.x;
1205
0
    if (right > state->clip.q.x)
1206
0
        right = state->clip.q.x;
1207
0
    if (left < right) {
1208
0
        byte *out = mdev->base + mdev->raster * vci + left * spp;
1209
0
        const byte *data = buffer[0] + (data_x + left - oleft) * spp;
1210
0
        right = (right-left)*spp;
1211
0
        do {
1212
0
            memcpy(out, data, right);
1213
0
            out += mdev->raster;
1214
0
        } while (--vdi);
1215
0
    }
1216
1217
0
    return 0;
1218
0
}
1219
1220
static int
1221
mem_transform_pixel_region_render_portrait_1to1_1(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1222
0
{
1223
0
    return template_mem_transform_pixel_region_render_portrait_1to1(dev, state, buffer, data_x, cmapper, pgs, 1);
1224
0
}
1225
1226
static int
1227
mem_transform_pixel_region_render_portrait_1to1_3(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1228
0
{
1229
0
    return template_mem_transform_pixel_region_render_portrait_1to1(dev, state, buffer, data_x, cmapper, pgs, 3);
1230
0
}
1231
1232
static int
1233
mem_transform_pixel_region_render_portrait_1to1_4(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1234
0
{
1235
0
    return template_mem_transform_pixel_region_render_portrait_1to1(dev, state, buffer, data_x, cmapper, pgs, 4);
1236
0
}
1237
1238
static int
1239
mem_transform_pixel_region_render_portrait_1to1_n(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1240
0
{
1241
0
    return template_mem_transform_pixel_region_render_portrait_1to1(dev, state, buffer, data_x, cmapper, pgs, state->spp);
1242
0
}
1243
1244
static int
1245
mem_transform_pixel_region_render_portrait_1to1(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1246
0
{
1247
0
    if (!cmapper->direct)
1248
0
        return mem_transform_pixel_region_render_portrait(dev, state, buffer, data_x, cmapper, pgs);
1249
0
    switch(state->spp) {
1250
0
    case 1:
1251
0
        return mem_transform_pixel_region_render_portrait_1to1_1(dev, state, buffer, data_x, cmapper, pgs);
1252
0
    case 3:
1253
0
        return mem_transform_pixel_region_render_portrait_1to1_3(dev, state, buffer, data_x, cmapper, pgs);
1254
0
    case 4:
1255
0
        return mem_transform_pixel_region_render_portrait_1to1_4(dev, state, buffer, data_x, cmapper, pgs);
1256
0
    default:
1257
0
        return mem_transform_pixel_region_render_portrait_1to1_n(dev, state, buffer, data_x, cmapper, pgs);
1258
0
    }
1259
0
}
1260
1261
#ifdef WITH_CAL
1262
static inline int
1263
template_mem_transform_pixel_region_render_portrait_1to2(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs, int spp)
1264
{
1265
    gx_device_memory *mdev = (gx_device_memory *)dev;
1266
    gx_dda_fixed_point pnext;
1267
    int vci, vdi;
1268
    int w = state->w;
1269
    int h = state->h;
1270
    int oleft, left, right;
1271
1272
    if (h == 0)
1273
        return 0;
1274
1275
    /* Clip on y */
1276
    get_portrait_y_extent(state, &vci, &vdi);
1277
    if (vci < state->clip.p.y)
1278
        vdi += vci - state->clip.p.y, vci = state->clip.p.y;
1279
    if (vci+vdi > state->clip.q.y)
1280
        vdi = state->clip.q.y - vci;
1281
    if (vdi <= 0)
1282
        return 0;
1283
1284
    pnext = state->pixels;
1285
    dda_translate(pnext.x,  (-fixed_epsilon));
1286
    left = fixed2int_var_rounded(dda_current(pnext.x));
1287
    if_debug5m('b', dev->memory, "[b]y=%d data_x=%d w=%d xt=%f yt=%f\n",
1288
               vci, data_x, w, fixed2float(dda_current(pnext.x)), fixed2float(dda_current(pnext.y)));
1289
    right = fixed2int_var_rounded(dda_current(pnext.x)) + w * 2;
1290
1291
    if (left > right) {
1292
        int tmp = left; left = right; right = tmp;
1293
    }
1294
    oleft = left;
1295
    if (left < state->clip.p.x)
1296
        left = state->clip.p.x;
1297
    if (right > state->clip.q.x)
1298
        right = state->clip.q.x;
1299
    if (left < right) {
1300
        byte *out[2];
1301
        const byte *in = buffer[0] + (data_x + left - oleft) * spp;
1302
        int lines_out;
1303
        out[0] = mdev->base + left * spp + mdev->raster * vci;
1304
        out[1] = out[0] + (vdi > 1 ? mdev->raster : 0);
1305
        lines_out = cal_doubler_process(state->cal_dbl, dev->memory,
1306
                                        &in, &out[0]);
1307
        (void)lines_out;
1308
        /* assert(lines_out == 2) */
1309
    }
1310
1311
    return 0;
1312
}
1313
1314
static int
1315
mem_transform_pixel_region_render_portrait_1to2_1(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1316
{
1317
    return template_mem_transform_pixel_region_render_portrait_1to2(dev, state, buffer, data_x, cmapper, pgs, 1);
1318
}
1319
1320
static int
1321
mem_transform_pixel_region_render_portrait_1to2_3(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1322
{
1323
    return template_mem_transform_pixel_region_render_portrait_1to2(dev, state, buffer, data_x, cmapper, pgs, 3);
1324
}
1325
1326
static int
1327
mem_transform_pixel_region_render_portrait_1to2_4(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1328
{
1329
    return template_mem_transform_pixel_region_render_portrait_1to2(dev, state, buffer, data_x, cmapper, pgs, 4);
1330
}
1331
1332
static int
1333
mem_transform_pixel_region_render_portrait_1to2_n(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1334
{
1335
    return template_mem_transform_pixel_region_render_portrait_1to2(dev, state, buffer, data_x, cmapper, pgs, state->spp);
1336
}
1337
1338
static int
1339
mem_transform_pixel_region_render_portrait_1to2(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1340
{
1341
    if (!cmapper->direct)
1342
        return mem_transform_pixel_region_render_portrait(dev, state, buffer, data_x, cmapper, pgs);
1343
    switch(state->spp) {
1344
    case 1:
1345
        return mem_transform_pixel_region_render_portrait_1to2_1(dev, state, buffer, data_x, cmapper, pgs);
1346
    case 3:
1347
        return mem_transform_pixel_region_render_portrait_1to2_3(dev, state, buffer, data_x, cmapper, pgs);
1348
    case 4:
1349
        return mem_transform_pixel_region_render_portrait_1to2_4(dev, state, buffer, data_x, cmapper, pgs);
1350
    default:
1351
        return mem_transform_pixel_region_render_portrait_1to2_n(dev, state, buffer, data_x, cmapper, pgs);
1352
    }
1353
}
1354
1355
static inline int
1356
template_mem_transform_pixel_region_render_portrait_1to4(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs, int spp)
1357
{
1358
    gx_device_memory *mdev = (gx_device_memory *)dev;
1359
    gx_dda_fixed_point pnext;
1360
    int vci, vdi;
1361
    int w = state->w;
1362
    int h = state->h;
1363
    int oleft, left, right;
1364
1365
    if (h == 0)
1366
        return 0;
1367
1368
    /* Clip on y */
1369
    get_portrait_y_extent(state, &vci, &vdi);
1370
    if (vci < state->clip.p.y)
1371
        vdi += vci - state->clip.p.y, vci = state->clip.p.y;
1372
    if (vci+vdi > state->clip.q.y)
1373
        vdi = state->clip.q.y - vci;
1374
    if (vdi <= 0)
1375
        return 0;
1376
1377
    pnext = state->pixels;
1378
    dda_translate(pnext.x,  (-fixed_epsilon));
1379
    left = fixed2int_var_rounded(dda_current(pnext.x));
1380
    if_debug5m('b', dev->memory, "[b]y=%d data_x=%d w=%d xt=%f yt=%f\n",
1381
               vci, data_x, w, fixed2float(dda_current(pnext.x)), fixed2float(dda_current(pnext.y)));
1382
    right = fixed2int_var_rounded(dda_current(pnext.x)) + w * 4 * spp;
1383
1384
    if (left > right) {
1385
        int tmp = left; left = right; right = tmp;
1386
    }
1387
    oleft = left;
1388
    if (left < state->clip.p.x)
1389
        left = state->clip.p.x;
1390
    if (right > state->clip.q.x)
1391
        right = state->clip.q.x;
1392
    if (left < right) {
1393
        byte *out[4];
1394
        const byte *in = buffer[0] + (data_x + left - oleft) * spp;
1395
        int lines_out;
1396
        out[0] = mdev->base + left * spp + mdev->raster * vci;
1397
        out[1] = out[0] + (vdi > 1 ? mdev->raster : 0);
1398
        out[2] = out[1] + (vdi > 2 ? mdev->raster : 0);
1399
        out[3] = out[2] + (vdi > 3 ? mdev->raster : 0);
1400
        lines_out = cal_doubler_process(state->cal_dbl, dev->memory,
1401
                                        &in, &out[0]);
1402
        (void)lines_out;
1403
        /* assert(lines_out == 4) */
1404
    }
1405
1406
    return 0;
1407
}
1408
1409
static int
1410
mem_transform_pixel_region_render_portrait_1to4_1(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1411
{
1412
    return template_mem_transform_pixel_region_render_portrait_1to4(dev, state, buffer, data_x, cmapper, pgs, 1);
1413
}
1414
1415
static int
1416
mem_transform_pixel_region_render_portrait_1to4_3(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1417
{
1418
    return template_mem_transform_pixel_region_render_portrait_1to4(dev, state, buffer, data_x, cmapper, pgs, 3);
1419
}
1420
1421
static int
1422
mem_transform_pixel_region_render_portrait_1to4_4(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1423
{
1424
    return template_mem_transform_pixel_region_render_portrait_1to4(dev, state, buffer, data_x, cmapper, pgs, 4);
1425
}
1426
1427
static int
1428
mem_transform_pixel_region_render_portrait_1to4_n(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1429
{
1430
    return template_mem_transform_pixel_region_render_portrait_1to4(dev, state, buffer, data_x, cmapper, pgs, state->spp);
1431
}
1432
1433
static int
1434
mem_transform_pixel_region_render_portrait_1to4(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1435
{
1436
    if (!cmapper->direct)
1437
        return mem_transform_pixel_region_render_portrait(dev, state, buffer, data_x, cmapper, pgs);
1438
    switch(state->spp) {
1439
    case 1:
1440
        return mem_transform_pixel_region_render_portrait_1to4_1(dev, state, buffer, data_x, cmapper, pgs);
1441
    case 3:
1442
        return mem_transform_pixel_region_render_portrait_1to4_3(dev, state, buffer, data_x, cmapper, pgs);
1443
    case 4:
1444
        return mem_transform_pixel_region_render_portrait_1to4_4(dev, state, buffer, data_x, cmapper, pgs);
1445
    default:
1446
        return mem_transform_pixel_region_render_portrait_1to4_n(dev, state, buffer, data_x, cmapper, pgs);
1447
    }
1448
}
1449
1450
static inline int
1451
template_mem_transform_pixel_region_render_portrait_1to8(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs, int spp)
1452
{
1453
    gx_device_memory *mdev = (gx_device_memory *)dev;
1454
    gx_dda_fixed_point pnext;
1455
    int vci, vdi;
1456
    int w = state->w;
1457
    int h = state->h;
1458
    int oleft, left, right;
1459
1460
    if (h == 0)
1461
        return 0;
1462
1463
    /* Clip on y */
1464
    get_portrait_y_extent(state, &vci, &vdi);
1465
    if (vci < state->clip.p.y)
1466
        vdi += vci - state->clip.p.y, vci = state->clip.p.y;
1467
    if (vci+vdi > state->clip.q.y)
1468
        vdi = state->clip.q.y - vci;
1469
    if (vdi <= 0)
1470
        return 0;
1471
1472
    pnext = state->pixels;
1473
    dda_translate(pnext.x,  (-fixed_epsilon));
1474
    left = fixed2int_var_rounded(dda_current(pnext.x));
1475
    if_debug5m('b', dev->memory, "[b]y=%d data_x=%d w=%d xt=%f yt=%f\n",
1476
               vci, data_x, w, fixed2float(dda_current(pnext.x)), fixed2float(dda_current(pnext.y)));
1477
    right = fixed2int_var_rounded(dda_current(pnext.x)) + w * 8;
1478
1479
    if (left > right) {
1480
        int tmp = left; left = right; right = tmp;
1481
    }
1482
    oleft = left;
1483
    if (left < state->clip.p.x)
1484
        left = state->clip.p.x;
1485
    if (right > state->clip.q.x)
1486
        right = state->clip.q.x;
1487
    if (left < right) {
1488
        byte *out[8];
1489
        const byte *in = buffer[0] + (data_x + left - oleft) * spp;
1490
        int lines_out;
1491
        out[0] = mdev->base + left * spp + mdev->raster * vci;
1492
        out[1] = out[0] + (vdi > 1 ? mdev->raster : 0);
1493
        out[2] = out[1] + (vdi > 2 ? mdev->raster : 0);
1494
        out[3] = out[2] + (vdi > 3 ? mdev->raster : 0);
1495
        out[4] = out[3] + (vdi > 4 ? mdev->raster : 0);
1496
        out[5] = out[4] + (vdi > 5 ? mdev->raster : 0);
1497
        out[6] = out[5] + (vdi > 6 ? mdev->raster : 0);
1498
        out[7] = out[6] + (vdi > 7 ? mdev->raster : 0);
1499
        lines_out = cal_doubler_process(state->cal_dbl, dev->memory,
1500
                                        &in, &out[0]);
1501
        (void)lines_out;
1502
        /* assert(lines_out == 8) */
1503
    }
1504
1505
    return 0;
1506
}
1507
1508
static int
1509
mem_transform_pixel_region_render_portrait_1to8_1(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1510
{
1511
    return template_mem_transform_pixel_region_render_portrait_1to8(dev, state, buffer, data_x, cmapper, pgs, 1);
1512
}
1513
1514
static int
1515
mem_transform_pixel_region_render_portrait_1to8_3(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1516
{
1517
    return template_mem_transform_pixel_region_render_portrait_1to8(dev, state, buffer, data_x, cmapper, pgs, 3);
1518
}
1519
1520
static int
1521
mem_transform_pixel_region_render_portrait_1to8_4(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1522
{
1523
    return template_mem_transform_pixel_region_render_portrait_1to8(dev, state, buffer, data_x, cmapper, pgs, 4);
1524
}
1525
1526
static int
1527
mem_transform_pixel_region_render_portrait_1to8_n(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1528
{
1529
    return template_mem_transform_pixel_region_render_portrait_1to8(dev, state, buffer, data_x, cmapper, pgs, state->spp);
1530
}
1531
1532
static int
1533
mem_transform_pixel_region_render_portrait_1to8(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1534
{
1535
    if (!cmapper->direct)
1536
        return mem_transform_pixel_region_render_portrait(dev, state, buffer, data_x, cmapper, pgs);
1537
    switch(state->spp) {
1538
    case 1:
1539
        return mem_transform_pixel_region_render_portrait_1to8_1(dev, state, buffer, data_x, cmapper, pgs);
1540
    case 3:
1541
        return mem_transform_pixel_region_render_portrait_1to8_3(dev, state, buffer, data_x, cmapper, pgs);
1542
    case 4:
1543
        return mem_transform_pixel_region_render_portrait_1to8_4(dev, state, buffer, data_x, cmapper, pgs);
1544
    default:
1545
        return mem_transform_pixel_region_render_portrait_1to8_n(dev, state, buffer, data_x, cmapper, pgs);
1546
    }
1547
}
1548
#endif
1549
1550
static inline int
1551
template_mem_transform_pixel_region_render_landscape(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs, int spp)
1552
0
{
1553
0
    gx_device_memory *mdev = (gx_device_memory *)dev;
1554
0
    gx_dda_fixed_point pnext;
1555
0
    int vci, vdi;
1556
0
    int irun;     /* int x/rrun */
1557
0
    int w = state->w;
1558
0
    int h = state->h;
1559
0
    const byte *data = buffer[0] + data_x * spp;
1560
0
    const byte *bufend = NULL;
1561
0
    const byte *run;
1562
0
    int k;
1563
0
    gx_color_value *conc = &cmapper->conc[0];
1564
0
    gx_cmapper_fn *mapper = cmapper->set_color;
1565
0
    byte *out;
1566
0
    byte *out_row;
1567
0
    int miny, maxy;
1568
1569
0
    if (h == 0)
1570
0
        return 0;
1571
1572
    /* Clip on x */
1573
0
    get_landscape_x_extent(state, &vci, &vdi);
1574
0
    if (vci < state->clip.p.x)
1575
0
        vdi += vci - state->clip.p.x, vci = state->clip.p.x;
1576
0
    if (vci+vdi > state->clip.q.x)
1577
0
        vdi = state->clip.q.x - vci;
1578
0
    if (vdi <= 0)
1579
0
        return 0;
1580
1581
0
    pnext = state->pixels;
1582
0
    dda_translate(pnext.x,  (-fixed_epsilon));
1583
0
    irun = fixed2int_var_rounded(dda_current(pnext.y));
1584
0
    if_debug5m('b', dev->memory, "[b]y=%d data_x=%d w=%d xt=%f yt=%f\n",
1585
0
               vci, data_x, w, fixed2float(dda_current(pnext.x)), fixed2float(dda_current(pnext.y)));
1586
1587
0
    miny = state->clip.p.y;
1588
0
    maxy = state->clip.q.y;
1589
0
    out_row = mdev->base + vci * spp;
1590
0
    bufend = data + w * spp;
1591
0
    while (data < bufend) {
1592
        /* Find the length of the next run. It will either end when we hit
1593
         * the end of the source data, or when the pixel data differs. */
1594
0
        run = data + spp;
1595
0
        while (1) {
1596
0
            dda_next(pnext.y);
1597
0
            if (run >= bufend)
1598
0
                break;
1599
0
            if (memcmp(run, data, spp))
1600
0
                break;
1601
0
            run += spp;
1602
0
        }
1603
        /* So we have a run of pixels from data to run that are all the same. */
1604
        /* This needs to be sped up */
1605
0
        for (k = 0; k < spp; k++) {
1606
0
            conc[k] = gx_color_value_from_byte(data[k]);
1607
0
        }
1608
0
        mapper(cmapper);
1609
        /* Fill the region between irun and fixed2int_var_rounded(pnext.y) */
1610
0
        {              /* 90 degree rotated rectangle */
1611
0
            int yi = irun;
1612
0
            int hi = (irun = fixed2int_var_rounded(dda_current(pnext.y))) - yi;
1613
1614
0
            if (hi < 0)
1615
0
                yi += hi, hi = -hi;
1616
1617
0
            if (yi < miny)
1618
0
                hi += yi - miny, yi = miny;
1619
0
            if (yi+hi > maxy)
1620
0
                hi = maxy - yi;
1621
0
            if (hi > 0) {
1622
                /* assert(color_is_pure(&cmapper->devc)); */
1623
0
                out = out_row + mdev->raster * yi;
1624
0
                for (h = hi; h > 0; h--, out += mdev->raster) {
1625
0
                    gx_color_index color = cmapper->devc.colors.pure;
1626
0
                    int xii = 0;
1627
0
                    int wii = vdi;
1628
0
                    do {
1629
                        /* Excuse the double shifts below, that's to stop the
1630
                         * C compiler complaining if the color index type is
1631
                         * 32 bits. */
1632
0
                        switch(spp)
1633
0
                        {
1634
0
                        case 8: out[xii++] = ((color>>28)>>28) & 0xff;
1635
0
                        case 7: out[xii++] = ((color>>24)>>24) & 0xff;
1636
0
                        case 6: out[xii++] = ((color>>24)>>16) & 0xff;
1637
0
                        case 5: out[xii++] = ((color>>24)>>8) & 0xff;
1638
0
                        case 4: out[xii++] = (color>>24) & 0xff;
1639
0
                        case 3: out[xii++] = (color>>16) & 0xff;
1640
0
                        case 2: out[xii++] = (color>>8) & 0xff;
1641
0
                        case 1: out[xii++] = color & 0xff;
1642
0
                        }
1643
0
                    } while (--wii != 0);
1644
0
                }
1645
0
            }
1646
0
        }
1647
0
        data = run;
1648
0
    }
1649
0
    return 1;
1650
0
}
1651
1652
static int
1653
mem_transform_pixel_region_render_landscape_1(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1654
0
{
1655
0
    return template_mem_transform_pixel_region_render_landscape(dev, state, buffer, data_x, cmapper, pgs, 1);
1656
0
}
1657
1658
static int
1659
mem_transform_pixel_region_render_landscape_3(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1660
0
{
1661
0
    return template_mem_transform_pixel_region_render_landscape(dev, state, buffer, data_x, cmapper, pgs, 3);
1662
0
}
1663
1664
static int
1665
mem_transform_pixel_region_render_landscape_4(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1666
0
{
1667
0
    return template_mem_transform_pixel_region_render_landscape(dev, state, buffer, data_x, cmapper, pgs, 4);
1668
0
}
1669
1670
static int
1671
mem_transform_pixel_region_render_landscape_n(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1672
0
{
1673
0
    return template_mem_transform_pixel_region_render_landscape(dev, state, buffer, data_x, cmapper, pgs, state->spp);
1674
0
}
1675
1676
static int
1677
mem_transform_pixel_region_render_landscape(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1678
0
{
1679
0
    switch (state->spp) {
1680
0
    case 1:
1681
0
        return mem_transform_pixel_region_render_landscape_1(dev, state, buffer, data_x, cmapper, pgs);
1682
0
    case 3:
1683
0
        return mem_transform_pixel_region_render_landscape_3(dev, state, buffer, data_x, cmapper, pgs);
1684
0
    case 4:
1685
0
        return mem_transform_pixel_region_render_landscape_4(dev, state, buffer, data_x, cmapper, pgs);
1686
0
    default:
1687
0
        return mem_transform_pixel_region_render_landscape_n(dev, state, buffer, data_x, cmapper, pgs);
1688
0
    }
1689
0
}
1690
1691
static inline int
1692
template_mem_transform_pixel_region_render_landscape_planar(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs, int spp)
1693
0
{
1694
0
    gx_device_memory *mdev = (gx_device_memory *)dev;
1695
0
    gx_dda_fixed_point pnext;
1696
0
    int vci, vdi;
1697
0
    int irun;     /* int x/rrun */
1698
0
    int w = state->w;
1699
0
    int h = state->h;
1700
0
    const byte *data = buffer[0] + data_x * spp;
1701
0
    const byte *bufend = NULL;
1702
0
    const byte *run;
1703
0
    int k;
1704
0
    gx_color_value *conc = &cmapper->conc[0];
1705
0
    gx_cmapper_fn *mapper = cmapper->set_color;
1706
0
    byte *out;
1707
0
    int miny, maxy;
1708
1709
0
    if (h == 0)
1710
0
        return 0;
1711
1712
    /* Clip on x */
1713
0
    get_landscape_x_extent(state, &vci, &vdi);
1714
0
    if (vci < state->clip.p.x)
1715
0
        vdi += vci - state->clip.p.x, vci = state->clip.p.x;
1716
0
    if (vci+vdi > state->clip.q.x)
1717
0
        vdi = state->clip.q.x - vci;
1718
0
    if (vdi <= 0)
1719
0
        return 0;
1720
1721
0
    pnext = state->pixels;
1722
0
    dda_translate(pnext.x,  (-fixed_epsilon));
1723
0
    irun = fixed2int_var_rounded(dda_current(pnext.y));
1724
0
    if_debug5m('b', dev->memory, "[b]y=%d data_x=%d w=%d xt=%f yt=%f\n",
1725
0
               vci, data_x, w, fixed2float(dda_current(pnext.x)), fixed2float(dda_current(pnext.y)));
1726
1727
0
    miny = state->clip.p.y;
1728
0
    maxy = state->clip.q.y;
1729
0
    bufend = data + w * spp;
1730
0
    while (data < bufend) {
1731
        /* Find the length of the next run. It will either end when we hit
1732
         * the end of the source data, or when the pixel data differs. */
1733
0
        run = data + spp;
1734
0
        while (1) {
1735
0
            dda_next(pnext.y);
1736
0
            if (run >= bufend)
1737
0
                break;
1738
0
            if (memcmp(run, data, spp))
1739
0
                break;
1740
0
            run += spp;
1741
0
        }
1742
        /* So we have a run of pixels from data to run that are all the same. */
1743
        /* This needs to be sped up */
1744
0
        for (k = 0; k < spp; k++) {
1745
0
            conc[k] = gx_color_value_from_byte(data[k]);
1746
0
        }
1747
0
        mapper(cmapper);
1748
        /* Fill the region between irun and fixed2int_var_rounded(pnext.y) */
1749
0
        {              /* 90 degree rotated rectangle */
1750
0
            int yi = irun;
1751
0
            int hi = (irun = fixed2int_var_rounded(dda_current(pnext.y))) - yi;
1752
1753
0
            if (hi < 0)
1754
0
                yi += hi, hi = -hi;
1755
1756
0
            if (yi < miny)
1757
0
                hi += yi - miny, yi = miny;
1758
0
            if (yi+hi > maxy)
1759
0
                hi = maxy - yi;
1760
0
            if (hi > 0) {
1761
                /* assert(color_is_pure(&cmapper->devc)); */
1762
0
                gx_color_index color = cmapper->devc.colors.pure;
1763
0
                for (k = 0; k < spp; k++) {
1764
0
                    unsigned char c = (color>>mdev->planes[k].shift) & ((1<<mdev->planes[k].depth)-1);
1765
0
                    for (h = 0; h < hi; h++) {
1766
0
                        out = mdev->line_ptrs[yi + h + k * mdev->height] + vci;
1767
0
                        memset(out, c, vdi);
1768
0
                    }
1769
0
                }
1770
0
            }
1771
0
        }
1772
0
        data = run;
1773
0
    }
1774
0
    return 1;
1775
0
}
1776
1777
static int
1778
mem_transform_pixel_region_render_landscape_1p(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1779
0
{
1780
0
    return template_mem_transform_pixel_region_render_landscape_planar(dev, state, buffer, data_x, cmapper, pgs, 1);
1781
0
}
1782
1783
static int
1784
mem_transform_pixel_region_render_landscape_3p(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1785
0
{
1786
0
    return template_mem_transform_pixel_region_render_landscape_planar(dev, state, buffer, data_x, cmapper, pgs, 3);
1787
0
}
1788
1789
static int
1790
mem_transform_pixel_region_render_landscape_4p(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1791
0
{
1792
0
    return template_mem_transform_pixel_region_render_landscape_planar(dev, state, buffer, data_x, cmapper, pgs, 4);
1793
0
}
1794
1795
static int
1796
mem_transform_pixel_region_render_landscape_np(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1797
0
{
1798
0
    return template_mem_transform_pixel_region_render_landscape_planar(dev, state, buffer, data_x, cmapper, pgs, state->spp);
1799
0
}
1800
1801
static int
1802
mem_transform_pixel_region_render_landscape_planar(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1803
0
{
1804
0
    switch (state->spp) {
1805
0
    case 1:
1806
0
        return mem_transform_pixel_region_render_landscape_1p(dev, state, buffer, data_x, cmapper, pgs);
1807
0
    case 3:
1808
0
        return mem_transform_pixel_region_render_landscape_3p(dev, state, buffer, data_x, cmapper, pgs);
1809
0
    case 4:
1810
0
        return mem_transform_pixel_region_render_landscape_4p(dev, state, buffer, data_x, cmapper, pgs);
1811
0
    default:
1812
0
        return mem_transform_pixel_region_render_landscape_np(dev, state, buffer, data_x, cmapper, pgs);
1813
0
    }
1814
0
}
1815
1816
static int
1817
mem_transform_pixel_region_begin(gx_device *dev, int w, int h, int spp,
1818
                      const gx_dda_fixed_point *pixels, const gx_dda_fixed_point *rows,
1819
                      const gs_int_rect *clip, transform_pixel_region_posture posture,
1820
                      mem_transform_pixel_region_state_t **statep)
1821
0
{
1822
0
    gx_device_memory *mdev = (gx_device_memory *)dev;
1823
0
    mem_transform_pixel_region_state_t *state;
1824
0
    gs_memory_t *mem = dev->memory->non_gc_memory;
1825
0
    *statep = state = (mem_transform_pixel_region_state_t *)gs_alloc_bytes(mem, sizeof(mem_transform_pixel_region_state_t), "mem_transform_pixel_region_state_t");
1826
0
    if (state == NULL)
1827
0
        return gs_error_VMerror;
1828
0
    state->mem = mem;
1829
0
    state->rows = *rows;
1830
0
    state->pixels = *pixels;
1831
0
    state->clip = *clip;
1832
0
    if (state->clip.p.x < 0)
1833
0
        state->clip.p.x = 0;
1834
0
    if (state->clip.q.x > dev->width)
1835
0
        state->clip.q.x = dev->width;
1836
0
    if (state->clip.p.y < 0)
1837
0
        state->clip.p.y = 0;
1838
0
    if (state->clip.q.y > dev->height)
1839
0
        state->clip.q.y = dev->height;
1840
0
    state->w = w;
1841
0
    state->h = h;
1842
0
    state->spp = spp;
1843
0
    state->posture = posture;
1844
#ifdef WITH_CAL
1845
    state->cal_ctx = NULL;
1846
    state->cal_dbl = NULL;
1847
#endif
1848
1849
0
    if (state->posture == transform_pixel_region_portrait) {
1850
#ifdef WITH_CAL
1851
        int factor;
1852
        if (mdev->is_planar) {
1853
            goto planar;
1854
        } else if (pixels->x.step.dQ == fixed_1*8 && pixels->x.step.dR == 0 && rows->y.step.dQ == fixed_1*8 && rows->y.step.dR == 0) {
1855
            state->render = mem_transform_pixel_region_render_portrait_1to8;
1856
            factor = 8;
1857
            goto use_doubler;
1858
        } else if (pixels->x.step.dQ == fixed_1*4 && pixels->x.step.dR == 0 && rows->y.step.dQ == fixed_1*4 && rows->y.step.dR == 0) {
1859
            state->render = mem_transform_pixel_region_render_portrait_1to4;
1860
            factor = 4;
1861
            goto use_doubler;
1862
        } else if (pixels->x.step.dQ == fixed_1*2 && pixels->x.step.dR == 0 && rows->y.step.dQ == fixed_1*2 && rows->y.step.dR == 0) {
1863
            unsigned int in_lines;
1864
            int l, r;
1865
            factor = 2;
1866
            state->render = mem_transform_pixel_region_render_portrait_1to2;
1867
        use_doubler:
1868
            l = fixed2int_var_rounded(dda_current(pixels->x));
1869
            r = fixed2int_var_rounded(dda_current(pixels->x) - fixed_epsilon) + w * factor;
1870
            if (l > r) {
1871
                int t = l; l = r; r = t;
1872
            }
1873
            if (l < state->clip.p.x || r > state->clip.q.x)
1874
                goto no_cal;
1875
            state->cal_dbl = cal_doubler_init(mem->gs_lib_ctx->core->cal_ctx,
1876
                                              mem,
1877
                                              w,
1878
                                              h,
1879
                                              factor,
1880
                                              CAL_DOUBLE_NEAREST,
1881
                                              spp,
1882
                                              &in_lines);
1883
            /* assert(in_lines == 1) */
1884
            if (state->cal_dbl == NULL)
1885
                goto no_cal;
1886
        } else
1887
no_cal:
1888
#endif
1889
0
        if (mdev->is_planar)
1890
#ifdef WITH_CAL
1891
planar:
1892
#endif
1893
0
            state->render = mem_transform_pixel_region_render_portrait_planar;
1894
0
        else if (pixels->x.step.dQ == fixed_1 && pixels->x.step.dR == 0)
1895
0
            state->render = mem_transform_pixel_region_render_portrait_1to1;
1896
0
        else
1897
0
            state->render = mem_transform_pixel_region_render_portrait;
1898
0
    } else if (mdev->is_planar)
1899
0
        state->render = mem_transform_pixel_region_render_landscape_planar;
1900
0
    else
1901
0
        state->render = mem_transform_pixel_region_render_landscape;
1902
1903
0
    return 0;
1904
0
}
1905
1906
static void
1907
step_to_next_line(mem_transform_pixel_region_state_t *state)
1908
0
{
1909
0
    fixed x = dda_current(state->rows.x);
1910
0
    fixed y = dda_current(state->rows.y);
1911
0
    dda_next(state->rows.x);
1912
0
    dda_next(state->rows.y);
1913
0
    x = dda_current(state->rows.x) - x;
1914
0
    y = dda_current(state->rows.y) - y;
1915
0
    dda_translate(state->pixels.x, x);
1916
0
    dda_translate(state->pixels.y, y);
1917
0
}
1918
1919
static int
1920
mem_transform_pixel_region_data_needed(gx_device *dev, mem_transform_pixel_region_state_t *state)
1921
0
{
1922
0
    if (state->posture == transform_pixel_region_portrait) {
1923
0
        int iy, ih;
1924
1925
0
        get_portrait_y_extent(state, &iy, &ih);
1926
1927
0
        if (iy + ih < state->clip.p.y || iy >= state->clip.q.y) {
1928
            /* Skip this line. */
1929
0
            step_to_next_line(state);
1930
0
            return 0;
1931
0
        }
1932
0
    } else if (state->posture == transform_pixel_region_landscape) {
1933
0
        int ix, iw;
1934
1935
0
        get_landscape_x_extent(state, &ix, &iw);
1936
1937
0
        if (ix + iw < state->clip.p.x || ix >= state->clip.q.x) {
1938
            /* Skip this line. */
1939
0
            step_to_next_line(state);
1940
0
            return 0;
1941
0
        }
1942
0
    }
1943
1944
0
    return 1;
1945
0
}
1946
1947
static int
1948
mem_transform_pixel_region_process_data(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs)
1949
0
{
1950
0
    int ret = state->render(dev, state, buffer, data_x, cmapper, pgs);
1951
1952
0
    step_to_next_line(state);
1953
1954
0
    return ret;
1955
0
}
1956
1957
static int
1958
mem_transform_pixel_region_end(gx_device *dev, mem_transform_pixel_region_state_t *state)
1959
0
{
1960
0
    if (state)
1961
0
        gs_free_object(state->mem->non_gc_memory, state, "mem_transform_pixel_region_state_t");
1962
0
    return 0;
1963
0
}
1964
1965
int mem_transform_pixel_region(gx_device *dev, transform_pixel_region_reason reason, transform_pixel_region_data *data)
1966
0
{
1967
0
    mem_transform_pixel_region_state_t *state = (mem_transform_pixel_region_state_t *)data->state;
1968
0
    transform_pixel_region_posture posture;
1969
1970
    /* Pass through */
1971
0
    if (reason == transform_pixel_region_begin) {
1972
0
        const gx_dda_fixed_point *rows = data->u.init.rows;
1973
0
        const gx_dda_fixed_point *pixels = data->u.init.pixels;
1974
0
        if (rows->x.step.dQ == 0 && rows->x.step.dR == 0 && pixels->y.step.dQ == 0 && pixels->y.step.dR == 0)
1975
0
            posture = transform_pixel_region_portrait;
1976
0
        else if (rows->y.step.dQ == 0 && rows->y.step.dR == 0 && pixels->x.step.dQ == 0 && pixels->x.step.dR == 0)
1977
0
            posture = transform_pixel_region_landscape;
1978
0
        else
1979
0
            posture = transform_pixel_region_skew;
1980
1981
0
        if (posture == transform_pixel_region_skew || dev->color_info.depth != data->u.init.spp*8 || data->u.init.lop != 0xf0) {
1982
0
            mem_transform_pixel_region_state_t *state = (mem_transform_pixel_region_state_t *)gs_alloc_bytes(dev->memory->non_gc_memory, sizeof(mem_transform_pixel_region_state_t), "mem_transform_pixel_region_state_t");
1983
0
            if (state == NULL)
1984
0
                return gs_error_VMerror;
1985
0
            state->render = NULL;
1986
0
            if (gx_default_transform_pixel_region(dev, transform_pixel_region_begin, data) < 0) {
1987
0
                gs_free_object(dev->memory->non_gc_memory, state, "mem_transform_pixel_region_state_t");
1988
0
                return gs_error_VMerror;
1989
0
            }
1990
0
            state->passthru = data->state;
1991
0
            data->state = state;
1992
0
            return 0;
1993
0
        }
1994
0
    } else if (state->render == NULL) {
1995
0
        int ret;
1996
0
        data->state = state->passthru;
1997
0
        ret = gx_default_transform_pixel_region(dev, reason, data);
1998
0
        data->state = state;
1999
0
        if (reason == transform_pixel_region_end) {
2000
0
            gs_free_object(dev->memory->non_gc_memory, state, "mem_transform_pixel_region_state_t");
2001
0
            data->state = NULL;
2002
0
        }
2003
0
        return ret;
2004
0
    }
2005
2006
    /* We can handle this case natively */
2007
0
    switch(reason)
2008
0
    {
2009
0
    case transform_pixel_region_begin:
2010
0
        return mem_transform_pixel_region_begin(dev, data->u.init.w, data->u.init.h, data->u.init.spp, data->u.init.pixels, data->u.init.rows, data->u.init.clip, posture, (mem_transform_pixel_region_state_t **)&data->state);
2011
0
    case transform_pixel_region_data_needed:
2012
0
        return mem_transform_pixel_region_data_needed(dev, state);
2013
0
    case transform_pixel_region_process_data:
2014
0
        return mem_transform_pixel_region_process_data(dev, state, data->u.process_data.buffer, data->u.process_data.data_x, data->u.process_data.cmapper, data->u.process_data.pgs);
2015
0
    case transform_pixel_region_end:
2016
0
        data->state = NULL;
2017
0
        return mem_transform_pixel_region_end(dev, state);
2018
0
    default:
2019
0
        return gs_error_unknownerror;
2020
0
    }
2021
0
}