Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/base/gdevdrop.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2024 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
/* 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->num_planar_planes)
144
0
    {
145
0
        gx_render_plane_t planes[GX_DEVICE_COLOR_MAX_COMPONENTS];
146
0
        uchar num_comp = dev->num_planar_planes;
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
            /* Avoid overflow, CID 427553 */
409
0
            if (chop & 0x80)
410
0
                return;
411
0
            chop <<= 1;
412
0
        }
413
0
        if ((shift -= depth) >= 0)
414
0
            buf += (byte)(pixel << shift);
415
0
        else {
416
0
            switch (depth) {
417
0
            default:            /* 1, 2, 4, 8 */
418
0
                *dp++ = buf;
419
0
                shift += 8;
420
0
                buf = (byte)(pixel << shift);
421
0
                break;
422
0
            case 32:
423
0
                *dp++ = (byte)(pixel >> 24);
424
0
                *dp++ = (byte)(pixel >> 16);
425
                /* fall through */
426
0
            case 16:
427
0
                *dp++ = (byte)(pixel >> 8);
428
0
                *dp++ = (byte)pixel;
429
0
                shift = 0;
430
0
            }
431
0
        }
432
0
    }
433
0
    if (width > 0 && depth <= 8)
434
0
        *dp = (shift == 0 ? buf : buf + (*dp & ((1 << shift) - 1)));
435
0
}
436
437
static void
438
pack_planar_from_standard(gx_device_memory * dev, int y, int destx,
439
                          const byte * src, int width, int depth, int src_depth)
440
0
{
441
    /* This code assumes that all planar planes have the same depth */
442
0
    dev_proc_map_rgb_color((*map)) =
443
0
        (dev->color_info.num_components == 4 ?
444
0
         map_rgb_to_color_via_cmyk : dev_proc(dev, map_rgb_color));
445
0
    int pdepth = dev->plane_depth;
446
0
    int bit_x = destx * pdepth;
447
0
    byte *dp[GX_DEVICE_COLOR_MAX_COMPONENTS];
448
0
    int shift = (~bit_x & 7) + 1;
449
0
    byte buf[GX_DEVICE_COLOR_MAX_COMPONENTS];
450
0
    const byte *sp = src;
451
0
    int x;
452
0
    uchar plane;
453
454
0
    if (pdepth == 1 && dev->color_info.num_components == 4) {
455
0
        pack_planar_cmyk_1bit_from_standard(dev, y, destx, src, width,
456
0
                                            depth, src_depth);
457
0
        return;
458
0
    }
459
460
0
    for (plane = 0; plane < dev->color_info.num_components; plane++) {
461
0
        byte *dest = scan_line_base(dev, y + plane * dev->height);
462
0
        dp[plane] = dest + (bit_x >> 3);
463
0
        buf[plane] = (shift == 8 ? 0 : *dp[plane] & (0xff00 >> shift));
464
0
    }
465
466
0
    for (x = width; --x >= 0;) {
467
0
        byte vr, vg, vb;
468
0
        gx_color_index pixel;
469
0
        byte chop = 0x1;
470
471
0
        vr = *sp++;
472
0
        if (src_depth > 8) {
473
0
            vg = *sp++;
474
0
            vb = *sp++;
475
0
        } else
476
0
            vb = vg = vr;
477
        /*
478
         * We have to map back to some pixel value, even if the color
479
         * isn't accurate.
480
         */
481
0
        for (;;) {
482
0
            gx_color_value cv[3];
483
0
            cv[0] = gx_color_value_from_byte(vr);
484
0
            cv[1] = gx_color_value_from_byte(vg);
485
0
            cv[2] = gx_color_value_from_byte(vb);
486
0
            pixel = (*map) ((gx_device *)dev, cv);
487
0
            if (pixel != gx_no_color_index)
488
0
                break;
489
            /* Reduce the color accuracy and try again. */
490
0
            vr = (vr >= 0x80 ? vr | chop : vr & ~chop);
491
0
            vg = (vg >= 0x80 ? vg | chop : vg & ~chop);
492
0
            vb = (vb >= 0x80 ? vb | chop : vb & ~chop);
493
            /* Avoid overflow, CID 427561 */
494
0
            if (chop & 0x80)
495
0
                return;
496
0
            chop <<= 1;
497
0
        }
498
0
        switch (depth) {
499
0
            case 32:
500
0
                *dp[0]++ = (byte)(pixel >> 24);
501
0
                *dp[1]++ = (byte)(pixel >> 16);
502
0
                *dp[2]++ = (byte)(pixel >> 8);
503
0
                *dp[3]++ = (byte)pixel;
504
0
                shift = 0;
505
0
                break;
506
0
            case 24:
507
0
                *dp[0]++ = (byte)(pixel >> 16);
508
0
                *dp[1]++ = (byte)(pixel >> 8);
509
0
                *dp[2]++ = (byte)pixel;
510
0
                shift = 0;
511
0
                break;
512
0
            case 16:
513
0
                *dp[0]++ = (byte)(pixel >> 8);
514
0
                *dp[1]++ = (byte)pixel;
515
0
                shift = 0;
516
0
                break;
517
0
            default:            /* 1, 2, 4, 8 */
518
0
            {
519
0
                int pmask = (1<<pdepth)-1;
520
521
#ifdef ORIGINAL_CODE_KEPT_FOR_REFERENCE
522
                /* Original code, kept for reference. I believe this copies
523
                 * bits in the wrong order (i.e. the 0th component comes from
524
                 * the lowest bits in pixel, rather than the highest), and
525
                 * gets them from the wrong place (8 bits apart rather than
526
                 * pdepth), but as I have no examples that actually tickle
527
                 * this code, currently, I don't want to throw it away. */
528
                int pshift = 8-pdepth;
529
#else
530
                /* We have pdepth*num_planes bits in 'pixel'. We need to copy
531
                 * them (topmost bits first) into the buffer, packing them at
532
                 * shift position. */
533
0
                int pshift = pdepth*(dev->color_info.num_components-1);
534
0
#endif
535
                /* Can we fit another pdepth bits into our buffer? */
536
0
                shift -= pdepth;
537
0
                if (shift < 0) {
538
                    /* No, so flush the buffer to the planes. */
539
0
                    for (plane = 0; plane < dev->color_info.num_components; plane++)
540
0
                        *dp[plane]++ = buf[plane];
541
0
                    shift += 8;
542
0
                }
543
                /* Copy the next pdepth bits into each planes buffer */
544
#ifdef ORIGINAL_CODE_KEPT_FOR_REFERENCE
545
                for (plane = 0; plane < dev->color_info.num_components; pshift+=8,plane++)
546
                    buf[plane] += (byte)(((pixel>>pshift) & pmask)<<shift);
547
#else
548
0
                for (plane = 0; plane < dev->color_info.num_components; pshift-=pdepth,plane++)
549
0
                    buf[plane] += (byte)(((pixel>>pshift) & pmask)<<shift);
550
0
#endif
551
0
                break;
552
0
            }
553
0
        }
554
0
    }
555
0
    if (width > 0 && depth <= 8) {
556
0
        if (shift == 0)
557
0
            for (plane = 0; plane < dev->color_info.num_components; plane++)
558
0
                *dp[plane] = buf[plane];
559
0
        else {
560
0
            int mask = (1<<shift)-1;
561
0
            for (plane = 0; plane < dev->color_info.num_components; plane++)
562
0
                *dp[plane] = (*dp[plane] & mask) + buf[plane];
563
0
        }
564
0
    }
565
0
}
566
567
/*
568
 * The default implementation for memory devices uses get_bits_rectangle to
569
 * read out the pixels and convert them to standard (8-bit gray or 24-bit
570
 * RGB) representation, the standard memory device implementation to do the
571
 * operation, pack_from_standard to convert them back to the device
572
 * representation, and copy_color to write the pixels back.
573
 */
574
static int
575
do_strip_copy_rop(gx_device * dev,
576
                           const byte * sdata, int sourcex,
577
                           uint sraster, gx_bitmap_id id,
578
                           const gx_color_index * scolors,
579
                           const gx_strip_bitmap * textures,
580
                           const gx_color_index * tcolors,
581
                           int x, int y, int width, int height,
582
                           int phase_x, int phase_y,
583
                           gs_logical_operation_t olop)
584
0
{
585
0
    int depth = dev->color_info.depth;
586
0
    int rop_depth = (gx_device_has_color(dev) ? 24 : 8);
587
0
    void (*pack)(gx_device_memory *, int, int, const byte *, int, int, int);
588
0
    const gx_bitmap_format_t no_expand_options =
589
0
        GB_COLORS_NATIVE | GB_ALPHA_NONE | GB_DEPTH_ALL |
590
0
        GB_PACKING_CHUNKY | GB_RETURN_ALL | GB_ALIGN_STANDARD |
591
0
        GB_OFFSET_0 | GB_OFFSET_ANY | GB_RASTER_STANDARD;
592
0
    const gx_bitmap_format_t no_expand_t_options =
593
0
        GB_COLORS_NATIVE | GB_ALPHA_NONE | GB_DEPTH_ALL |
594
0
        GB_RETURN_ALL | GB_ALIGN_STANDARD |
595
0
        GB_OFFSET_0 | GB_OFFSET_ANY | GB_RASTER_STANDARD |
596
0
        ((textures && textures->num_planes > 1) ? GB_PACKING_PLANAR : GB_PACKING_CHUNKY);
597
0
    const gx_bitmap_format_t expand_options =
598
0
        (rop_depth > 8 ? GB_COLORS_RGB : GB_COLORS_GRAY) |
599
0
        GB_ALPHA_NONE | GB_DEPTH_8 |
600
0
        GB_PACKING_CHUNKY | GB_RETURN_COPY | GB_ALIGN_STANDARD |
601
0
        GB_OFFSET_0 | GB_RASTER_STANDARD;
602
0
    gs_memory_t *mem = dev->memory;
603
0
    const gx_device_memory *mdproto = gdev_mem_device_for_bits(rop_depth);
604
0
    gx_device_memory mdev;
605
0
    union { long l; void *p; } mdev_storage[20];
606
0
    uint row_raster = bitmap_raster(width * depth);
607
0
    size_t size_from_mem_device;
608
0
    gs_logical_operation_t lop = lop_sanitize(olop);
609
0
    bool uses_d = rop3_uses_D(lop);
610
0
    bool uses_s = rop3_uses_S(lop);
611
0
    bool uses_t = rop3_uses_T(lop);
612
0
    bool expand_s, expand_t;
613
0
    byte *row = 0;
614
0
    union { long l; void *p; } dest_buffer[16];
615
0
    byte *source_row = 0;
616
0
    uint source_row_raster = 0; /* init to quiet compiler warning */
617
0
    union { long l; void *p; } source_buffer[16];
618
0
    byte *texture_row = 0;
619
0
    uint texture_row_raster;
620
0
    union { long l; void *p; } texture_buffer[16];
621
0
    gx_color_index source_colors[2];
622
0
    const gx_color_index *real_scolors = scolors;
623
0
    gx_color_index texture_colors[2];
624
0
    const gx_color_index *real_tcolors = tcolors;
625
0
    gx_strip_bitmap rop_texture;
626
0
    const gx_strip_bitmap *real_texture = textures;
627
0
    gs_int_rect rect;
628
0
    gs_get_bits_params_t bit_params;
629
0
    gs_get_bits_params_t expand_params;
630
0
    gs_get_bits_params_t no_expand_params;
631
0
    gs_get_bits_params_t no_expand_t_params;
632
0
    int max_height;
633
0
    int block_height, loop_height;
634
0
    int code;
635
0
    int py;
636
0
    gx_device_memory *tdev = (gx_device_memory *)dev;
637
638
/*
639
 * Allocate a temporary row buffer.  Free variables: mem, block_height.
640
 * Labels used: out.
641
 */
642
0
#define ALLOC_BUF(buf, prebuf, size, cname)\
643
0
        BEGIN\
644
0
          uint num_bytes = (size) * block_height;\
645
0
\
646
0
          if (num_bytes <= sizeof(prebuf))\
647
0
            buf = (byte *)prebuf;\
648
0
          else {\
649
0
            buf = gs_alloc_bytes(mem, num_bytes, cname);\
650
0
            if (buf == 0) {\
651
0
              code = gs_note_error(gs_error_VMerror);\
652
0
              goto out;\
653
0
            }\
654
0
          }\
655
0
        END
656
657
    /* We know the device is a memory device, so we can store the
658
     * result directly into its scan lines, unless it is planar. */
659
0
    if (!tdev->num_planar_planes || tdev->color_info.num_components <= 1) {
660
0
        if ((rop_depth == 24) && (dev_proc(dev, dev_spec_op)(dev,
661
0
                                      gxdso_is_std_cmyk_1bit, NULL, 0) > 0)) {
662
0
            pack = pack_cmyk_1bit_from_standard;
663
0
        } else {
664
0
            pack = pack_from_standard;
665
0
        }
666
0
    } else {
667
0
        pack = pack_planar_from_standard;
668
0
    }
669
#ifdef DEBUG
670
    if (gs_debug_c('b'))
671
        trace_copy_rop("mem_default_strip_copy_rop",
672
                       dev, sdata, sourcex, sraster,
673
                       id, scolors, textures, tcolors,
674
                       x, y, width, height, phase_x, phase_y, lop);
675
#endif
676
0
    if (mdproto == 0)
677
0
        return_error(gs_error_rangecheck);
678
0
    if (sdata == 0) {
679
0
        fit_fill(dev, x, y, width, height);
680
0
    } else {
681
0
        fit_copy(dev, sdata, sourcex, sraster, id, x, y, width, height);
682
0
    }
683
    /* Compute max_height conservatively. */
684
0
    max_height = max_rop_bitmap / (width * rop_depth);
685
0
    if (max_height == 0)
686
0
        max_height = 1;
687
0
    block_height = min(height, max_height);
688
0
    expand_s = scolors == 0 && uses_s;
689
0
    expand_t = tcolors == 0 && uses_t;
690
0
    no_expand_params.options = no_expand_options;
691
0
    no_expand_t_params.options = no_expand_t_options;
692
0
    if (expand_t) {
693
        /*
694
         * We don't want to wrap around more than once in Y when
695
         * copying the texture to the intermediate buffer.
696
         */
697
0
        if (textures && textures->size.y < block_height)
698
0
            block_height = textures->size.y;
699
0
    }
700
0
    gs_make_mem_device(&mdev, mdproto, mem, -1, NULL);
701
0
    gx_device_retain((gx_device *)&mdev, true); /* prevent freeing */
702
0
    mdev.width = width;
703
0
    mdev.height = block_height;
704
0
    mdev.color_info.num_components = rop_depth >> 3;
705
0
    if (gdev_mem_data_size(&mdev, width, block_height, &size_from_mem_device) >= 0 &&
706
0
        size_from_mem_device <= sizeof(mdev_storage)) {
707
        /* Use the locally allocated storage. */
708
0
        mdev.base = (byte *)mdev_storage;
709
0
        if ((code = gdev_mem_bits_size(&mdev, mdev.width, mdev.height, &size_from_mem_device)) < 0)
710
0
            return code;
711
0
        mdev.line_ptrs = (byte **) (mdev.base + size_from_mem_device);
712
0
    } else {
713
0
        mdev.bitmap_memory = mem;
714
0
    }
715
0
    code = (*dev_proc(&mdev, open_device))((gx_device *)&mdev);
716
0
    if (code < 0)
717
0
        return code;
718
0
    ALLOC_BUF(row, dest_buffer, row_raster, "copy_rop row");
719
    /* We may need intermediate buffers for all 3 operands. */
720
0
    if (expand_s) {
721
0
        source_row_raster = bitmap_raster(width * rop_depth);
722
0
        ALLOC_BUF(source_row, source_buffer, source_row_raster,
723
0
                  "copy_rop source_row");
724
0
    }
725
0
    if (scolors && uses_s) {
726
0
        unpack_colors_to_standard(dev, source_colors, scolors, rop_depth);
727
0
        real_scolors = source_colors;
728
0
    }
729
0
    if (expand_t && textures) {
730
0
        texture_row_raster = bitmap_raster(textures->rep_width * rop_depth);
731
0
        ALLOC_BUF(texture_row, texture_buffer, texture_row_raster,
732
0
                  "copy_rop texture_row");
733
0
        rop_texture = *textures;
734
0
        rop_texture.data = texture_row;
735
0
        rop_texture.raster = texture_row_raster;
736
0
        rop_texture.size.x = rop_texture.rep_width;
737
0
        rop_texture.id = gs_no_bitmap_id;
738
0
        real_texture = &rop_texture;
739
0
        if (rop_texture.size.y > rop_texture.rep_height)
740
0
            rop_texture.size.y = rop_texture.rep_height;   /* we only allocated one row_raster, no reps */
741
0
    }
742
0
    if (tcolors && uses_t) {
743
0
        unpack_colors_to_standard(dev, texture_colors, tcolors, rop_depth);
744
0
        real_tcolors = texture_colors;
745
0
    }
746
0
    expand_params.options = expand_options;
747
0
    expand_params.x_offset = 0;
748
0
    rect.p.x = x;
749
0
    rect.q.x = x + width;
750
0
    for (py = y; py < y + height; py += loop_height) {
751
0
        int sx = sourcex;
752
0
        const byte *source_data = sdata + (py - y) * sraster;
753
0
        uint source_raster = sraster;
754
755
0
        if (block_height > y + height - py)
756
0
            block_height = y + height - py;
757
0
        rect.p.y = py;
758
0
        if (expand_t) {
759
0
            int rep_y = (phase_y + py) % rop_texture.rep_height;
760
761
0
            loop_height = min(block_height, rop_texture.size.y - rep_y);
762
0
            rect.q.y = py + loop_height;
763
0
            expand_params.data[0] = texture_row;
764
0
            gx_get_bits_copy(dev, 0, textures->rep_width, loop_height,
765
0
                             &expand_params, &no_expand_t_params,
766
0
                             textures->data + rep_y * textures->raster,
767
0
                             textures->raster);
768
            /*
769
             * Compensate for the addition of rep_y * raster
770
             * in the subsidiary strip_copy_rop call.
771
             */
772
0
            rop_texture.data = texture_row - rep_y * rop_texture.raster;
773
0
        } else {
774
0
            loop_height = block_height;
775
0
            rect.q.y = py + block_height;
776
0
        }
777
0
        if (uses_d) {
778
0
            bit_params.options = expand_options;
779
0
            bit_params.data[0] = scan_line_base(&mdev, 0);
780
0
            bit_params.x_offset = 0;
781
0
            bit_params.raster = mdev.raster;
782
0
            code = (*dev_proc(dev, get_bits_rectangle))
783
0
                (dev, &rect, &bit_params);
784
0
            if (code < 0)
785
0
                break;
786
0
        }
787
        /* Convert the source and texture to standard format. */
788
0
        if (expand_s) {
789
0
            expand_params.data[0] = source_row;
790
0
            gx_get_bits_copy(dev, sx, width, loop_height, &expand_params,
791
0
                             &no_expand_params, source_data, sraster);
792
0
            sx = 0;
793
0
            source_data = source_row;
794
0
            source_raster = source_row_raster;
795
0
        }
796
0
        code = (*dev_proc(&mdev, strip_copy_rop2))
797
0
            ((gx_device *)&mdev, source_data, sx, source_raster,
798
0
             gx_no_bitmap_id, real_scolors, real_texture, real_tcolors,
799
0
             0, 0, width, loop_height, phase_x + x, phase_y + py, lop, 0);
800
0
        if (code < 0)
801
0
            break;
802
        /* Convert the result back to the device's format. */
803
0
        {
804
0
            int i;
805
0
            const byte *unpacked = scan_line_base(&mdev, 0);
806
807
0
            for (i = 0; i < loop_height; unpacked += mdev.raster, ++i) {
808
0
                pack(tdev, py + i, x, unpacked, width, depth, rop_depth);
809
0
            }
810
0
        }
811
0
    }
812
0
out:
813
0
    if (texture_row != 0 && texture_row != (byte *)texture_buffer)
814
0
        gs_free_object(mem, texture_row, "copy_rop texture_row");
815
0
    if (source_row != 0 && source_row != (byte *)source_buffer)
816
0
        gs_free_object(mem, source_row, "copy_rop source_row");
817
0
    if (row != 0 && row != (byte *)dest_buffer)
818
0
        gs_free_object(mem, row, "copy_rop row");
819
0
    (*dev_proc(&mdev, close_device)) ((gx_device *) & mdev);
820
0
    return code;
821
0
}
822
823
int
824
mem_default_strip_copy_rop2(gx_device * dev,
825
                            const byte * sdata, int sourcex,
826
                            uint sraster, gx_bitmap_id id,
827
                            const gx_color_index * scolors,
828
                            const gx_strip_bitmap * textures,
829
                            const gx_color_index * tcolors,
830
                            int x, int y, int width, int height,
831
                            int phase_x, int phase_y,
832
                            gs_logical_operation_t lop,
833
                            uint planar_height)
834
0
{
835
0
    if (planar_height != 0)
836
0
    {
837
0
        dmlprintf(dev->memory, "mem_default_strip_copy_rop2 should never be called!\n");
838
0
        return_error(gs_error_Fatal);
839
0
    }
840
0
    return do_strip_copy_rop(dev, sdata, sourcex, sraster, id, scolors,
841
0
                             textures, tcolors, x, y, width, height,
842
0
                             phase_x, phase_y, lop);
843
0
}
844
845
/* ---------------- Internal routines ---------------- */
846
847
typedef enum {
848
    transform_pixel_region_portrait,
849
    transform_pixel_region_landscape,
850
    transform_pixel_region_skew
851
} transform_pixel_region_posture;
852
853
typedef struct mem_transform_pixel_region_state_s mem_transform_pixel_region_state_t;
854
855
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);
856
857
struct mem_transform_pixel_region_state_s
858
{
859
    gs_memory_t *mem;
860
    gx_dda_fixed_point pixels;
861
    gx_dda_fixed_point rows;
862
    gs_int_rect clip;
863
    int w;
864
    int h;
865
    int spp;
866
    transform_pixel_region_posture posture;
867
    mem_transform_pixel_region_render_fn *render;
868
    void *passthru;
869
#ifdef WITH_CAL
870
    cal_context *cal_ctx;
871
    cal_doubler *cal_dbl;
872
#endif
873
};
874
875
static void
876
get_portrait_y_extent(mem_transform_pixel_region_state_t *state, int *iy, int *ih)
877
12.7M
{
878
12.7M
    fixed y0, y1;
879
12.7M
    gx_dda_fixed row = state->rows.y;
880
881
12.7M
    y0 = dda_current(row);
882
12.7M
    dda_next(row);
883
12.7M
    y1 = dda_current(row);
884
885
12.7M
    if (y1 < y0) {
886
14.3k
        fixed t = y1; y1 = y0; y0 = t;
887
14.3k
    }
888
889
12.7M
    *iy = fixed2int_pixround_perfect(y0);
890
12.7M
    *ih = fixed2int_pixround_perfect(y1) - *iy;
891
12.7M
}
892
893
static void
894
get_landscape_x_extent(mem_transform_pixel_region_state_t *state, int *ix, int *iw)
895
0
{
896
0
    fixed x0, x1;
897
0
    gx_dda_fixed row = state->rows.x;
898
899
0
    x0 = dda_current(row);
900
0
    dda_next(row);
901
0
    x1 = dda_current(row);
902
903
0
    if (x1 < x0) {
904
0
        fixed t = x1; x1 = x0; x0 = t;
905
0
    }
906
907
0
    *ix = fixed2int_pixround_perfect(x0);
908
0
    *iw = fixed2int_pixround_perfect(x1) - *ix;
909
0
}
910
911
static inline int
912
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)
913
800k
{
914
800k
    gx_device_memory *mdev = (gx_device_memory *)dev;
915
800k
    gx_dda_fixed_point pnext;
916
800k
    int vci, vdi;
917
800k
    int irun;     /* int x/rrun */
918
800k
    int w = state->w;
919
800k
    int h = state->h;
920
800k
    const byte *data = buffer[0] + data_x * spp;
921
800k
    const byte *bufend = NULL;
922
800k
    const byte *run;
923
800k
    int k;
924
800k
    gx_color_value *conc = &cmapper->conc[0];
925
800k
    gx_cmapper_fn *mapper = cmapper->set_color;
926
800k
    byte *out;
927
800k
    byte *out_row;
928
800k
    int minx, maxx;
929
930
800k
    if (h == 0)
931
0
        return 0;
932
933
    /* Clip on y */
934
800k
    get_portrait_y_extent(state, &vci, &vdi);
935
800k
    if (vci < state->clip.p.y)
936
807
        vdi += vci - state->clip.p.y, vci = state->clip.p.y;
937
800k
    if (vci+vdi > state->clip.q.y)
938
476
        vdi = state->clip.q.y - vci;
939
800k
    if (vdi <= 0)
940
329
        return 0;
941
942
800k
    pnext = state->pixels;
943
800k
    dda_translate(pnext.x,  (-fixed_epsilon));
944
800k
    irun = fixed2int_var_rounded(dda_current(pnext.x));
945
800k
    if_debug5m('b', dev->memory, "[b]y=%d data_x=%d w=%d xt=%f yt=%f\n",
946
800k
               vci, data_x, w, fixed2float(dda_current(pnext.x)), fixed2float(dda_current(pnext.y)));
947
948
800k
    minx = state->clip.p.x;
949
800k
    maxx = state->clip.q.x;
950
800k
    out_row = mdev->base + mdev->raster * vci;
951
800k
    bufend = data + w * spp;
952
79.1M
    while (data < bufend) {
953
        /* Find the length of the next run. It will either end when we hit
954
         * the end of the source data, or when the pixel data differs. */
955
78.3M
        run = data + spp;
956
873M
        while (1) {
957
873M
            dda_next(pnext.x);
958
873M
            if (run >= bufend)
959
800k
                break;
960
872M
            if (memcmp(run, data, spp))
961
77.5M
                break;
962
795M
            run += spp;
963
795M
        }
964
        /* So we have a run of pixels from data to run that are all the same. */
965
        /* This needs to be sped up */
966
162M
        for (k = 0; k < spp; k++) {
967
83.8M
            conc[k] = gx_color_value_from_byte(data[k]);
968
83.8M
        }
969
78.3M
        mapper(cmapper);
970
        /* Fill the region between irun and fixed2int_var_rounded(pnext.x) */
971
78.3M
        {
972
78.3M
            int xi = irun;
973
78.3M
            int wi = (irun = fixed2int_var_rounded(dda_current(pnext.x))) - xi;
974
975
78.3M
            if (wi < 0)
976
584k
                xi += wi, wi = -wi;
977
978
78.3M
            if (xi < minx)
979
3.53k
                wi += xi - minx, xi = minx;
980
78.3M
            if (xi+wi > maxx)
981
11.7k
                wi = maxx - xi;
982
78.3M
            if (wi > 0) {
983
                /* assert(color_is_pure(&cmapper->devc)); */
984
78.3M
                out = out_row;
985
169M
                for (h = vdi; h > 0; h--, out += mdev->raster) {
986
91.3M
                    gx_color_index color = cmapper->devc.colors.pure;
987
91.3M
                    int xii = xi * spp;
988
91.3M
                    int wii = wi;
989
971M
                    do {
990
                        /* Excuse the double shifts below, that's to stop the
991
                         * C compiler complaining if the color index type is
992
                         * 32 bits. */
993
971M
                        switch(spp)
994
971M
                        {
995
0
                        case 8: out[xii++] = ((color>>28)>>28) & 0xff;
996
0
                        case 7: out[xii++] = ((color>>24)>>24) & 0xff;
997
0
                        case 6: out[xii++] = ((color>>24)>>16) & 0xff;
998
0
                        case 5: out[xii++] = ((color>>24)>>8) & 0xff;
999
0
                        case 4: out[xii++] = (color>>24) & 0xff;
1000
40.6M
                        case 3: out[xii++] = (color>>16) & 0xff;
1001
40.6M
                        case 2: out[xii++] = (color>>8) & 0xff;
1002
971M
                        case 1: out[xii++] = color & 0xff;
1003
971M
                        }
1004
971M
                    } while (--wii != 0);
1005
91.3M
                }
1006
78.3M
            }
1007
78.3M
        }
1008
78.3M
        data = run;
1009
78.3M
    }
1010
800k
    return 0;
1011
800k
}
1012
1013
static int
1014
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)
1015
779k
{
1016
779k
    return template_mem_transform_pixel_region_render_portrait(dev, state, buffer, data_x, cmapper, pgs, 1);
1017
779k
}
1018
1019
static int
1020
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)
1021
21.8k
{
1022
21.8k
    return template_mem_transform_pixel_region_render_portrait(dev, state, buffer, data_x, cmapper, pgs, 3);
1023
21.8k
}
1024
1025
static int
1026
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)
1027
0
{
1028
0
    return template_mem_transform_pixel_region_render_portrait(dev, state, buffer, data_x, cmapper, pgs, 4);
1029
0
}
1030
1031
static int
1032
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)
1033
0
{
1034
0
    return template_mem_transform_pixel_region_render_portrait(dev, state, buffer, data_x, cmapper, pgs, state->spp);
1035
0
}
1036
1037
static inline int
1038
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)
1039
0
{
1040
0
    gx_device_memory *mdev = (gx_device_memory *)dev;
1041
0
    gx_dda_fixed_point pnext;
1042
0
    int vci, vdi;
1043
0
    int irun;     /* int x/rrun */
1044
0
    int w = state->w;
1045
0
    int h = state->h;
1046
0
    const byte *data = buffer[0] + data_x * spp;
1047
0
    const byte *bufend = NULL;
1048
0
    const byte *run;
1049
0
    int k;
1050
0
    gx_color_value *conc = &cmapper->conc[0];
1051
0
    gx_cmapper_fn *mapper = cmapper->set_color;
1052
0
    int minx, maxx;
1053
1054
0
    if (h == 0)
1055
0
        return 0;
1056
1057
    /* Clip on y */
1058
0
    get_portrait_y_extent(state, &vci, &vdi);
1059
0
    if (vci < state->clip.p.y)
1060
0
        vdi += vci - state->clip.p.y, vci = state->clip.p.y;
1061
0
    if (vci+vdi > state->clip.q.y)
1062
0
        vdi = state->clip.q.y - vci;
1063
0
    if (vdi <= 0)
1064
0
        return 0;
1065
1066
0
    pnext = state->pixels;
1067
0
    dda_translate(pnext.x,  (-fixed_epsilon));
1068
0
    irun = fixed2int_var_rounded(dda_current(pnext.x));
1069
0
    if_debug5m('b', dev->memory, "[b]y=%d data_x=%d w=%d xt=%f yt=%f\n",
1070
0
               vci, data_x, w, fixed2float(dda_current(pnext.x)), fixed2float(dda_current(pnext.y)));
1071
1072
0
    minx = state->clip.p.x;
1073
0
    maxx = state->clip.q.x;
1074
0
    bufend = data + w * spp;
1075
0
    while (data < bufend) {
1076
        /* Find the length of the next run. It will either end when we hit
1077
         * the end of the source data, or when the pixel data differs. */
1078
0
        run = data + spp;
1079
0
        while (1) {
1080
0
            dda_next(pnext.x);
1081
0
            if (run >= bufend)
1082
0
                break;
1083
0
            if (memcmp(run, data, spp))
1084
0
                break;
1085
0
            run += spp;
1086
0
        }
1087
        /* So we have a run of pixels from data to run that are all the same. */
1088
        /* This needs to be sped up */
1089
0
        for (k = 0; k < spp; k++) {
1090
0
            conc[k] = gx_color_value_from_byte(data[k]);
1091
0
        }
1092
0
        mapper(cmapper);
1093
        /* Fill the region between irun and fixed2int_var_rounded(pnext.x) */
1094
0
        {
1095
0
            int xi = irun;
1096
0
            int wi = (irun = fixed2int_var_rounded(dda_current(pnext.x))) - xi;
1097
1098
0
            if (wi < 0)
1099
0
                xi += wi, wi = -wi;
1100
1101
0
            if (xi < minx)
1102
0
                wi += xi - minx, xi = minx;
1103
0
            if (xi+wi > maxx)
1104
0
                wi = maxx - xi;
1105
0
            if (wi > 0) {
1106
                /* assert(color_is_pure(&cmapper->devc)); */
1107
0
                gx_color_index color = cmapper->devc.colors.pure;
1108
0
                for (k = 0; k < spp; k++) {
1109
0
                    unsigned char c = (color>>mdev->planes[k].shift) & ((1<<mdev->planes[k].depth)-1);
1110
0
                    for (h = 0; h < vdi; h++) {
1111
0
                        byte *out = mdev->line_ptrs[vci + h + k*mdev->height] + xi;
1112
0
                        memset(out, c, wi);
1113
0
                    }
1114
0
                }
1115
0
            }
1116
0
        }
1117
0
        data = run;
1118
0
    }
1119
0
    return 0;
1120
0
}
1121
1122
static int
1123
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)
1124
0
{
1125
0
    return template_mem_transform_pixel_region_render_portrait_planar(dev, state, buffer, data_x, cmapper, pgs, 1);
1126
0
}
1127
1128
static int
1129
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)
1130
0
{
1131
0
    return template_mem_transform_pixel_region_render_portrait_planar(dev, state, buffer, data_x, cmapper, pgs, 3);
1132
0
}
1133
1134
static int
1135
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)
1136
0
{
1137
0
    return template_mem_transform_pixel_region_render_portrait_planar(dev, state, buffer, data_x, cmapper, pgs, 4);
1138
0
}
1139
1140
static int
1141
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)
1142
0
{
1143
0
    return template_mem_transform_pixel_region_render_portrait_planar(dev, state, buffer, data_x, cmapper, pgs, state->spp);
1144
0
}
1145
1146
static int
1147
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)
1148
0
{
1149
0
    switch(state->spp) {
1150
0
    case 1:
1151
0
        return mem_transform_pixel_region_render_portrait_1p(dev, state, buffer, data_x, cmapper, pgs);
1152
0
    case 3:
1153
0
        return mem_transform_pixel_region_render_portrait_3p(dev, state, buffer, data_x, cmapper, pgs);
1154
0
    case 4:
1155
0
        return mem_transform_pixel_region_render_portrait_4p(dev, state, buffer, data_x, cmapper, pgs);
1156
0
    default:
1157
0
        return mem_transform_pixel_region_render_portrait_np(dev, state, buffer, data_x, cmapper, pgs);
1158
0
    }
1159
0
}
1160
1161
static int
1162
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)
1163
800k
{
1164
800k
    switch(state->spp) {
1165
779k
    case 1:
1166
779k
        return mem_transform_pixel_region_render_portrait_1(dev, state, buffer, data_x, cmapper, pgs);
1167
21.8k
    case 3:
1168
21.8k
        return mem_transform_pixel_region_render_portrait_3(dev, state, buffer, data_x, cmapper, pgs);
1169
0
    case 4:
1170
0
        return mem_transform_pixel_region_render_portrait_4(dev, state, buffer, data_x, cmapper, pgs);
1171
0
    default:
1172
0
        return mem_transform_pixel_region_render_portrait_n(dev, state, buffer, data_x, cmapper, pgs);
1173
800k
    }
1174
800k
}
1175
1176
static inline int
1177
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)
1178
5.55M
{
1179
5.55M
    gx_device_memory *mdev = (gx_device_memory *)dev;
1180
5.55M
    gx_dda_fixed_point pnext;
1181
5.55M
    int vci, vdi;
1182
5.55M
    int w = state->w;
1183
5.55M
    int h = state->h;
1184
5.55M
    int left, right, oleft;
1185
1186
5.55M
    if (h == 0)
1187
0
        return 0;
1188
1189
    /* Clip on y */
1190
5.55M
    get_portrait_y_extent(state, &vci, &vdi);
1191
5.55M
    if (vci < state->clip.p.y)
1192
58
        vdi += vci - state->clip.p.y, vci = state->clip.p.y;
1193
5.55M
    if (vci+vdi > state->clip.q.y)
1194
0
        vdi = state->clip.q.y - vci;
1195
5.55M
    if (vdi <= 0)
1196
58
        return 0;
1197
1198
5.55M
    pnext = state->pixels;
1199
5.55M
    dda_translate(pnext.x,  (-fixed_epsilon));
1200
5.55M
    left = fixed2int_var_rounded(dda_current(pnext.x));
1201
5.55M
    if_debug5m('b', dev->memory, "[b]y=%d data_x=%d w=%d xt=%f yt=%f\n",
1202
5.55M
               vci, data_x, w, fixed2float(dda_current(pnext.x)), fixed2float(dda_current(pnext.y)));
1203
5.55M
    right = fixed2int_var_rounded(dda_current(pnext.x)) + w;
1204
1205
5.55M
    if (left > right) {
1206
0
        int tmp = left; left = right; right = tmp;
1207
0
    }
1208
5.55M
    oleft = left;
1209
5.55M
    if (left < state->clip.p.x)
1210
0
        left = state->clip.p.x;
1211
5.55M
    if (right > state->clip.q.x)
1212
0
        right = state->clip.q.x;
1213
5.55M
    if (left < right) {
1214
5.55M
        byte *out = mdev->base + mdev->raster * vci + left * spp;
1215
5.55M
        const byte *data = buffer[0] + (data_x + left - oleft) * spp;
1216
5.55M
        right = (right-left)*spp;
1217
5.55M
        do {
1218
5.55M
            memcpy(out, data, right);
1219
5.55M
            out += mdev->raster;
1220
5.55M
        } while (--vdi);
1221
5.55M
    }
1222
1223
5.55M
    return 0;
1224
5.55M
}
1225
1226
static int
1227
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)
1228
0
{
1229
0
    return template_mem_transform_pixel_region_render_portrait_1to1(dev, state, buffer, data_x, cmapper, pgs, 1);
1230
0
}
1231
1232
static int
1233
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)
1234
5.55M
{
1235
5.55M
    return template_mem_transform_pixel_region_render_portrait_1to1(dev, state, buffer, data_x, cmapper, pgs, 3);
1236
5.55M
}
1237
1238
static int
1239
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)
1240
0
{
1241
0
    return template_mem_transform_pixel_region_render_portrait_1to1(dev, state, buffer, data_x, cmapper, pgs, 4);
1242
0
}
1243
1244
static int
1245
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)
1246
0
{
1247
0
    return template_mem_transform_pixel_region_render_portrait_1to1(dev, state, buffer, data_x, cmapper, pgs, state->spp);
1248
0
}
1249
1250
static int
1251
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)
1252
6.30M
{
1253
6.30M
    if (!cmapper->direct)
1254
744k
        return mem_transform_pixel_region_render_portrait(dev, state, buffer, data_x, cmapper, pgs);
1255
5.55M
    switch(state->spp) {
1256
0
    case 1:
1257
0
        return mem_transform_pixel_region_render_portrait_1to1_1(dev, state, buffer, data_x, cmapper, pgs);
1258
5.55M
    case 3:
1259
5.55M
        return mem_transform_pixel_region_render_portrait_1to1_3(dev, state, buffer, data_x, cmapper, pgs);
1260
0
    case 4:
1261
0
        return mem_transform_pixel_region_render_portrait_1to1_4(dev, state, buffer, data_x, cmapper, pgs);
1262
0
    default:
1263
0
        return mem_transform_pixel_region_render_portrait_1to1_n(dev, state, buffer, data_x, cmapper, pgs);
1264
5.55M
    }
1265
5.55M
}
1266
1267
#ifdef WITH_CAL
1268
static inline int
1269
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)
1270
{
1271
    gx_device_memory *mdev = (gx_device_memory *)dev;
1272
    gx_dda_fixed_point pnext;
1273
    int vci, vdi;
1274
    int w = state->w;
1275
    int h = state->h;
1276
    int oleft, left, right;
1277
1278
    if (h == 0)
1279
        return 0;
1280
1281
    /* Clip on y */
1282
    get_portrait_y_extent(state, &vci, &vdi);
1283
    if (vci < state->clip.p.y)
1284
        vdi += vci - state->clip.p.y, vci = state->clip.p.y;
1285
    if (vci+vdi > state->clip.q.y)
1286
        vdi = state->clip.q.y - vci;
1287
    if (vdi <= 0)
1288
        return 0;
1289
1290
    pnext = state->pixels;
1291
    dda_translate(pnext.x,  (-fixed_epsilon));
1292
    left = fixed2int_var_rounded(dda_current(pnext.x));
1293
    if_debug5m('b', dev->memory, "[b]y=%d data_x=%d w=%d xt=%f yt=%f\n",
1294
               vci, data_x, w, fixed2float(dda_current(pnext.x)), fixed2float(dda_current(pnext.y)));
1295
    right = fixed2int_var_rounded(dda_current(pnext.x)) + w * 2;
1296
1297
    if (left > right) {
1298
        int tmp = left; left = right; right = tmp;
1299
    }
1300
    oleft = left;
1301
    if (left < state->clip.p.x)
1302
        left = state->clip.p.x;
1303
    if (right > state->clip.q.x)
1304
        right = state->clip.q.x;
1305
    if (left < right) {
1306
        byte *out[2];
1307
        const byte *in = buffer[0] + (data_x + left - oleft) * spp;
1308
        int lines_out;
1309
        out[0] = mdev->base + left * spp + mdev->raster * vci;
1310
        out[1] = out[0] + (vdi > 1 ? mdev->raster : 0);
1311
        lines_out = cal_doubler_process(state->cal_dbl, dev->memory,
1312
                                        &in, &out[0]);
1313
        (void)lines_out;
1314
        /* assert(lines_out == 2) */
1315
    }
1316
1317
    return 0;
1318
}
1319
1320
static int
1321
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)
1322
{
1323
    return template_mem_transform_pixel_region_render_portrait_1to2(dev, state, buffer, data_x, cmapper, pgs, 1);
1324
}
1325
1326
static int
1327
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)
1328
{
1329
    return template_mem_transform_pixel_region_render_portrait_1to2(dev, state, buffer, data_x, cmapper, pgs, 3);
1330
}
1331
1332
static int
1333
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)
1334
{
1335
    return template_mem_transform_pixel_region_render_portrait_1to2(dev, state, buffer, data_x, cmapper, pgs, 4);
1336
}
1337
1338
static int
1339
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)
1340
{
1341
    return template_mem_transform_pixel_region_render_portrait_1to2(dev, state, buffer, data_x, cmapper, pgs, state->spp);
1342
}
1343
1344
static int
1345
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)
1346
{
1347
    if (!cmapper->direct)
1348
        return mem_transform_pixel_region_render_portrait(dev, state, buffer, data_x, cmapper, pgs);
1349
    switch(state->spp) {
1350
    case 1:
1351
        return mem_transform_pixel_region_render_portrait_1to2_1(dev, state, buffer, data_x, cmapper, pgs);
1352
    case 3:
1353
        return mem_transform_pixel_region_render_portrait_1to2_3(dev, state, buffer, data_x, cmapper, pgs);
1354
    case 4:
1355
        return mem_transform_pixel_region_render_portrait_1to2_4(dev, state, buffer, data_x, cmapper, pgs);
1356
    default:
1357
        return mem_transform_pixel_region_render_portrait_1to2_n(dev, state, buffer, data_x, cmapper, pgs);
1358
    }
1359
}
1360
1361
static inline int
1362
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)
1363
{
1364
    gx_device_memory *mdev = (gx_device_memory *)dev;
1365
    gx_dda_fixed_point pnext;
1366
    int vci, vdi;
1367
    int w = state->w;
1368
    int h = state->h;
1369
    int oleft, left, right;
1370
1371
    if (h == 0)
1372
        return 0;
1373
1374
    /* Clip on y */
1375
    get_portrait_y_extent(state, &vci, &vdi);
1376
    if (vci < state->clip.p.y)
1377
        vdi += vci - state->clip.p.y, vci = state->clip.p.y;
1378
    if (vci+vdi > state->clip.q.y)
1379
        vdi = state->clip.q.y - vci;
1380
    if (vdi <= 0)
1381
        return 0;
1382
1383
    pnext = state->pixels;
1384
    dda_translate(pnext.x,  (-fixed_epsilon));
1385
    left = fixed2int_var_rounded(dda_current(pnext.x));
1386
    if_debug5m('b', dev->memory, "[b]y=%d data_x=%d w=%d xt=%f yt=%f\n",
1387
               vci, data_x, w, fixed2float(dda_current(pnext.x)), fixed2float(dda_current(pnext.y)));
1388
    right = fixed2int_var_rounded(dda_current(pnext.x)) + w * 4 * spp;
1389
1390
    if (left > right) {
1391
        int tmp = left; left = right; right = tmp;
1392
    }
1393
    oleft = left;
1394
    if (left < state->clip.p.x)
1395
        left = state->clip.p.x;
1396
    if (right > state->clip.q.x)
1397
        right = state->clip.q.x;
1398
    if (left < right) {
1399
        byte *out[4];
1400
        const byte *in = buffer[0] + (data_x + left - oleft) * spp;
1401
        int lines_out;
1402
        out[0] = mdev->base + left * spp + mdev->raster * vci;
1403
        out[1] = out[0] + (vdi > 1 ? mdev->raster : 0);
1404
        out[2] = out[1] + (vdi > 2 ? mdev->raster : 0);
1405
        out[3] = out[2] + (vdi > 3 ? mdev->raster : 0);
1406
        lines_out = cal_doubler_process(state->cal_dbl, dev->memory,
1407
                                        &in, &out[0]);
1408
        (void)lines_out;
1409
        /* assert(lines_out == 4) */
1410
    }
1411
1412
    return 0;
1413
}
1414
1415
static int
1416
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)
1417
{
1418
    return template_mem_transform_pixel_region_render_portrait_1to4(dev, state, buffer, data_x, cmapper, pgs, 1);
1419
}
1420
1421
static int
1422
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)
1423
{
1424
    return template_mem_transform_pixel_region_render_portrait_1to4(dev, state, buffer, data_x, cmapper, pgs, 3);
1425
}
1426
1427
static int
1428
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)
1429
{
1430
    return template_mem_transform_pixel_region_render_portrait_1to4(dev, state, buffer, data_x, cmapper, pgs, 4);
1431
}
1432
1433
static int
1434
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)
1435
{
1436
    return template_mem_transform_pixel_region_render_portrait_1to4(dev, state, buffer, data_x, cmapper, pgs, state->spp);
1437
}
1438
1439
static int
1440
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)
1441
{
1442
    if (!cmapper->direct)
1443
        return mem_transform_pixel_region_render_portrait(dev, state, buffer, data_x, cmapper, pgs);
1444
    switch(state->spp) {
1445
    case 1:
1446
        return mem_transform_pixel_region_render_portrait_1to4_1(dev, state, buffer, data_x, cmapper, pgs);
1447
    case 3:
1448
        return mem_transform_pixel_region_render_portrait_1to4_3(dev, state, buffer, data_x, cmapper, pgs);
1449
    case 4:
1450
        return mem_transform_pixel_region_render_portrait_1to4_4(dev, state, buffer, data_x, cmapper, pgs);
1451
    default:
1452
        return mem_transform_pixel_region_render_portrait_1to4_n(dev, state, buffer, data_x, cmapper, pgs);
1453
    }
1454
}
1455
1456
static inline int
1457
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)
1458
{
1459
    gx_device_memory *mdev = (gx_device_memory *)dev;
1460
    gx_dda_fixed_point pnext;
1461
    int vci, vdi;
1462
    int w = state->w;
1463
    int h = state->h;
1464
    int oleft, left, right;
1465
1466
    if (h == 0)
1467
        return 0;
1468
1469
    /* Clip on y */
1470
    get_portrait_y_extent(state, &vci, &vdi);
1471
    if (vci < state->clip.p.y)
1472
        vdi += vci - state->clip.p.y, vci = state->clip.p.y;
1473
    if (vci+vdi > state->clip.q.y)
1474
        vdi = state->clip.q.y - vci;
1475
    if (vdi <= 0)
1476
        return 0;
1477
1478
    pnext = state->pixels;
1479
    dda_translate(pnext.x,  (-fixed_epsilon));
1480
    left = fixed2int_var_rounded(dda_current(pnext.x));
1481
    if_debug5m('b', dev->memory, "[b]y=%d data_x=%d w=%d xt=%f yt=%f\n",
1482
               vci, data_x, w, fixed2float(dda_current(pnext.x)), fixed2float(dda_current(pnext.y)));
1483
    right = fixed2int_var_rounded(dda_current(pnext.x)) + w * 8;
1484
1485
    if (left > right) {
1486
        int tmp = left; left = right; right = tmp;
1487
    }
1488
    oleft = left;
1489
    if (left < state->clip.p.x)
1490
        left = state->clip.p.x;
1491
    if (right > state->clip.q.x)
1492
        right = state->clip.q.x;
1493
    if (left < right) {
1494
        byte *out[8];
1495
        const byte *in = buffer[0] + (data_x + left - oleft) * spp;
1496
        int lines_out;
1497
        out[0] = mdev->base + left * spp + mdev->raster * vci;
1498
        out[1] = out[0] + (vdi > 1 ? mdev->raster : 0);
1499
        out[2] = out[1] + (vdi > 2 ? mdev->raster : 0);
1500
        out[3] = out[2] + (vdi > 3 ? mdev->raster : 0);
1501
        out[4] = out[3] + (vdi > 4 ? mdev->raster : 0);
1502
        out[5] = out[4] + (vdi > 5 ? mdev->raster : 0);
1503
        out[6] = out[5] + (vdi > 6 ? mdev->raster : 0);
1504
        out[7] = out[6] + (vdi > 7 ? mdev->raster : 0);
1505
        lines_out = cal_doubler_process(state->cal_dbl, dev->memory,
1506
                                        &in, &out[0]);
1507
        (void)lines_out;
1508
        /* assert(lines_out == 8) */
1509
    }
1510
1511
    return 0;
1512
}
1513
1514
static int
1515
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)
1516
{
1517
    return template_mem_transform_pixel_region_render_portrait_1to8(dev, state, buffer, data_x, cmapper, pgs, 1);
1518
}
1519
1520
static int
1521
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)
1522
{
1523
    return template_mem_transform_pixel_region_render_portrait_1to8(dev, state, buffer, data_x, cmapper, pgs, 3);
1524
}
1525
1526
static int
1527
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)
1528
{
1529
    return template_mem_transform_pixel_region_render_portrait_1to8(dev, state, buffer, data_x, cmapper, pgs, 4);
1530
}
1531
1532
static int
1533
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)
1534
{
1535
    return template_mem_transform_pixel_region_render_portrait_1to8(dev, state, buffer, data_x, cmapper, pgs, state->spp);
1536
}
1537
1538
static int
1539
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)
1540
{
1541
    if (!cmapper->direct)
1542
        return mem_transform_pixel_region_render_portrait(dev, state, buffer, data_x, cmapper, pgs);
1543
    switch(state->spp) {
1544
    case 1:
1545
        return mem_transform_pixel_region_render_portrait_1to8_1(dev, state, buffer, data_x, cmapper, pgs);
1546
    case 3:
1547
        return mem_transform_pixel_region_render_portrait_1to8_3(dev, state, buffer, data_x, cmapper, pgs);
1548
    case 4:
1549
        return mem_transform_pixel_region_render_portrait_1to8_4(dev, state, buffer, data_x, cmapper, pgs);
1550
    default:
1551
        return mem_transform_pixel_region_render_portrait_1to8_n(dev, state, buffer, data_x, cmapper, pgs);
1552
    }
1553
}
1554
#endif
1555
1556
static inline int
1557
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)
1558
0
{
1559
0
    gx_device_memory *mdev = (gx_device_memory *)dev;
1560
0
    gx_dda_fixed_point pnext;
1561
0
    int vci, vdi;
1562
0
    int irun;     /* int x/rrun */
1563
0
    int w = state->w;
1564
0
    int h = state->h;
1565
0
    const byte *data = buffer[0] + data_x * spp;
1566
0
    const byte *bufend = NULL;
1567
0
    const byte *run;
1568
0
    int k;
1569
0
    gx_color_value *conc = &cmapper->conc[0];
1570
0
    gx_cmapper_fn *mapper = cmapper->set_color;
1571
0
    byte *out;
1572
0
    byte *out_row;
1573
0
    int miny, maxy;
1574
1575
0
    if (h == 0)
1576
0
        return 0;
1577
1578
    /* Clip on x */
1579
0
    get_landscape_x_extent(state, &vci, &vdi);
1580
0
    if (vci < state->clip.p.x)
1581
0
        vdi += vci - state->clip.p.x, vci = state->clip.p.x;
1582
0
    if (vci+vdi > state->clip.q.x)
1583
0
        vdi = state->clip.q.x - vci;
1584
0
    if (vdi <= 0)
1585
0
        return 0;
1586
1587
0
    pnext = state->pixels;
1588
0
    dda_translate(pnext.x,  (-fixed_epsilon));
1589
0
    irun = fixed2int_var_rounded(dda_current(pnext.y));
1590
0
    if_debug5m('b', dev->memory, "[b]y=%d data_x=%d w=%d xt=%f yt=%f\n",
1591
0
               vci, data_x, w, fixed2float(dda_current(pnext.x)), fixed2float(dda_current(pnext.y)));
1592
1593
0
    miny = state->clip.p.y;
1594
0
    maxy = state->clip.q.y;
1595
0
    out_row = mdev->base + vci * spp;
1596
0
    bufend = data + w * spp;
1597
0
    while (data < bufend) {
1598
        /* Find the length of the next run. It will either end when we hit
1599
         * the end of the source data, or when the pixel data differs. */
1600
0
        run = data + spp;
1601
0
        while (1) {
1602
0
            dda_next(pnext.y);
1603
0
            if (run >= bufend)
1604
0
                break;
1605
0
            if (memcmp(run, data, spp))
1606
0
                break;
1607
0
            run += spp;
1608
0
        }
1609
        /* So we have a run of pixels from data to run that are all the same. */
1610
        /* This needs to be sped up */
1611
0
        for (k = 0; k < spp; k++) {
1612
0
            conc[k] = gx_color_value_from_byte(data[k]);
1613
0
        }
1614
0
        mapper(cmapper);
1615
        /* Fill the region between irun and fixed2int_var_rounded(pnext.y) */
1616
0
        {              /* 90 degree rotated rectangle */
1617
0
            int yi = irun;
1618
0
            int hi = (irun = fixed2int_var_rounded(dda_current(pnext.y))) - yi;
1619
1620
0
            if (hi < 0)
1621
0
                yi += hi, hi = -hi;
1622
1623
0
            if (yi < miny)
1624
0
                hi += yi - miny, yi = miny;
1625
0
            if (yi+hi > maxy)
1626
0
                hi = maxy - yi;
1627
0
            if (hi > 0) {
1628
                /* assert(color_is_pure(&cmapper->devc)); */
1629
0
                out = out_row + mdev->raster * yi;
1630
0
                for (h = hi; h > 0; h--, out += mdev->raster) {
1631
0
                    gx_color_index color = cmapper->devc.colors.pure;
1632
0
                    int xii = 0;
1633
0
                    int wii = vdi;
1634
0
                    do {
1635
                        /* Excuse the double shifts below, that's to stop the
1636
                         * C compiler complaining if the color index type is
1637
                         * 32 bits. */
1638
0
                        switch(spp)
1639
0
                        {
1640
0
                        case 8: out[xii++] = ((color>>28)>>28) & 0xff;
1641
0
                        case 7: out[xii++] = ((color>>24)>>24) & 0xff;
1642
0
                        case 6: out[xii++] = ((color>>24)>>16) & 0xff;
1643
0
                        case 5: out[xii++] = ((color>>24)>>8) & 0xff;
1644
0
                        case 4: out[xii++] = (color>>24) & 0xff;
1645
0
                        case 3: out[xii++] = (color>>16) & 0xff;
1646
0
                        case 2: out[xii++] = (color>>8) & 0xff;
1647
0
                        case 1: out[xii++] = color & 0xff;
1648
0
                        }
1649
0
                    } while (--wii != 0);
1650
0
                }
1651
0
            }
1652
0
        }
1653
0
        data = run;
1654
0
    }
1655
0
    return 1;
1656
0
}
1657
1658
static int
1659
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)
1660
0
{
1661
0
    return template_mem_transform_pixel_region_render_landscape(dev, state, buffer, data_x, cmapper, pgs, 1);
1662
0
}
1663
1664
static int
1665
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)
1666
0
{
1667
0
    return template_mem_transform_pixel_region_render_landscape(dev, state, buffer, data_x, cmapper, pgs, 3);
1668
0
}
1669
1670
static int
1671
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)
1672
0
{
1673
0
    return template_mem_transform_pixel_region_render_landscape(dev, state, buffer, data_x, cmapper, pgs, 4);
1674
0
}
1675
1676
static int
1677
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)
1678
0
{
1679
0
    return template_mem_transform_pixel_region_render_landscape(dev, state, buffer, data_x, cmapper, pgs, state->spp);
1680
0
}
1681
1682
static int
1683
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)
1684
0
{
1685
0
    switch (state->spp) {
1686
0
    case 1:
1687
0
        return mem_transform_pixel_region_render_landscape_1(dev, state, buffer, data_x, cmapper, pgs);
1688
0
    case 3:
1689
0
        return mem_transform_pixel_region_render_landscape_3(dev, state, buffer, data_x, cmapper, pgs);
1690
0
    case 4:
1691
0
        return mem_transform_pixel_region_render_landscape_4(dev, state, buffer, data_x, cmapper, pgs);
1692
0
    default:
1693
0
        return mem_transform_pixel_region_render_landscape_n(dev, state, buffer, data_x, cmapper, pgs);
1694
0
    }
1695
0
}
1696
1697
static inline int
1698
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)
1699
0
{
1700
0
    gx_device_memory *mdev = (gx_device_memory *)dev;
1701
0
    gx_dda_fixed_point pnext;
1702
0
    int vci, vdi;
1703
0
    int irun;     /* int x/rrun */
1704
0
    int w = state->w;
1705
0
    int h = state->h;
1706
0
    const byte *data = buffer[0] + data_x * spp;
1707
0
    const byte *bufend = NULL;
1708
0
    const byte *run;
1709
0
    int k;
1710
0
    gx_color_value *conc = &cmapper->conc[0];
1711
0
    gx_cmapper_fn *mapper = cmapper->set_color;
1712
0
    byte *out;
1713
0
    int miny, maxy;
1714
1715
0
    if (h == 0)
1716
0
        return 0;
1717
1718
    /* Clip on x */
1719
0
    get_landscape_x_extent(state, &vci, &vdi);
1720
0
    if (vci < state->clip.p.x)
1721
0
        vdi += vci - state->clip.p.x, vci = state->clip.p.x;
1722
0
    if (vci+vdi > state->clip.q.x)
1723
0
        vdi = state->clip.q.x - vci;
1724
0
    if (vdi <= 0)
1725
0
        return 0;
1726
1727
0
    pnext = state->pixels;
1728
0
    dda_translate(pnext.x,  (-fixed_epsilon));
1729
0
    irun = fixed2int_var_rounded(dda_current(pnext.y));
1730
0
    if_debug5m('b', dev->memory, "[b]y=%d data_x=%d w=%d xt=%f yt=%f\n",
1731
0
               vci, data_x, w, fixed2float(dda_current(pnext.x)), fixed2float(dda_current(pnext.y)));
1732
1733
0
    miny = state->clip.p.y;
1734
0
    maxy = state->clip.q.y;
1735
0
    bufend = data + w * spp;
1736
0
    while (data < bufend) {
1737
        /* Find the length of the next run. It will either end when we hit
1738
         * the end of the source data, or when the pixel data differs. */
1739
0
        run = data + spp;
1740
0
        while (1) {
1741
0
            dda_next(pnext.y);
1742
0
            if (run >= bufend)
1743
0
                break;
1744
0
            if (memcmp(run, data, spp))
1745
0
                break;
1746
0
            run += spp;
1747
0
        }
1748
        /* So we have a run of pixels from data to run that are all the same. */
1749
        /* This needs to be sped up */
1750
0
        for (k = 0; k < spp; k++) {
1751
0
            conc[k] = gx_color_value_from_byte(data[k]);
1752
0
        }
1753
0
        mapper(cmapper);
1754
        /* Fill the region between irun and fixed2int_var_rounded(pnext.y) */
1755
0
        {              /* 90 degree rotated rectangle */
1756
0
            int yi = irun;
1757
0
            int hi = (irun = fixed2int_var_rounded(dda_current(pnext.y))) - yi;
1758
1759
0
            if (hi < 0)
1760
0
                yi += hi, hi = -hi;
1761
1762
0
            if (yi < miny)
1763
0
                hi += yi - miny, yi = miny;
1764
0
            if (yi+hi > maxy)
1765
0
                hi = maxy - yi;
1766
0
            if (hi > 0) {
1767
                /* assert(color_is_pure(&cmapper->devc)); */
1768
0
                gx_color_index color = cmapper->devc.colors.pure;
1769
0
                for (k = 0; k < spp; k++) {
1770
0
                    unsigned char c = (color>>mdev->planes[k].shift) & ((1<<mdev->planes[k].depth)-1);
1771
0
                    for (h = 0; h < hi; h++) {
1772
0
                        out = mdev->line_ptrs[yi + h + k * mdev->height] + vci;
1773
0
                        memset(out, c, vdi);
1774
0
                    }
1775
0
                }
1776
0
            }
1777
0
        }
1778
0
        data = run;
1779
0
    }
1780
0
    return 1;
1781
0
}
1782
1783
static int
1784
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)
1785
0
{
1786
0
    return template_mem_transform_pixel_region_render_landscape_planar(dev, state, buffer, data_x, cmapper, pgs, 1);
1787
0
}
1788
1789
static int
1790
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)
1791
0
{
1792
0
    return template_mem_transform_pixel_region_render_landscape_planar(dev, state, buffer, data_x, cmapper, pgs, 3);
1793
0
}
1794
1795
static int
1796
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)
1797
0
{
1798
0
    return template_mem_transform_pixel_region_render_landscape_planar(dev, state, buffer, data_x, cmapper, pgs, 4);
1799
0
}
1800
1801
static int
1802
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)
1803
0
{
1804
0
    return template_mem_transform_pixel_region_render_landscape_planar(dev, state, buffer, data_x, cmapper, pgs, state->spp);
1805
0
}
1806
1807
static int
1808
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)
1809
0
{
1810
0
    switch (state->spp) {
1811
0
    case 1:
1812
0
        return mem_transform_pixel_region_render_landscape_1p(dev, state, buffer, data_x, cmapper, pgs);
1813
0
    case 3:
1814
0
        return mem_transform_pixel_region_render_landscape_3p(dev, state, buffer, data_x, cmapper, pgs);
1815
0
    case 4:
1816
0
        return mem_transform_pixel_region_render_landscape_4p(dev, state, buffer, data_x, cmapper, pgs);
1817
0
    default:
1818
0
        return mem_transform_pixel_region_render_landscape_np(dev, state, buffer, data_x, cmapper, pgs);
1819
0
    }
1820
0
}
1821
1822
static int
1823
mem_transform_pixel_region_begin(gx_device *dev, int w, int h, int spp,
1824
                      const gx_dda_fixed_point *pixels, const gx_dda_fixed_point *rows,
1825
                      const gs_int_rect *clip, transform_pixel_region_posture posture,
1826
                      mem_transform_pixel_region_state_t **statep)
1827
637k
{
1828
637k
    gx_device_memory *mdev = (gx_device_memory *)dev;
1829
637k
    mem_transform_pixel_region_state_t *state;
1830
637k
    gs_memory_t *mem = dev->memory->non_gc_memory;
1831
637k
    *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");
1832
637k
    if (state == NULL)
1833
0
        return gs_error_VMerror;
1834
637k
    state->mem = mem;
1835
637k
    state->rows = *rows;
1836
637k
    state->pixels = *pixels;
1837
637k
    state->clip = *clip;
1838
637k
    if (state->clip.p.x < 0)
1839
0
        state->clip.p.x = 0;
1840
637k
    if (state->clip.q.x > dev->width)
1841
0
        state->clip.q.x = dev->width;
1842
637k
    if (state->clip.p.y < 0)
1843
0
        state->clip.p.y = 0;
1844
637k
    if (state->clip.q.y > dev->height)
1845
0
        state->clip.q.y = dev->height;
1846
637k
    state->w = w;
1847
637k
    state->h = h;
1848
637k
    state->spp = spp;
1849
637k
    state->posture = posture;
1850
#ifdef WITH_CAL
1851
    state->cal_ctx = NULL;
1852
    state->cal_dbl = NULL;
1853
#endif
1854
1855
637k
    if (state->posture == transform_pixel_region_portrait) {
1856
#ifdef WITH_CAL
1857
        int factor;
1858
        if (mdev->num_planar_planes > 1) {
1859
            goto planar;
1860
        } 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) {
1861
            state->render = mem_transform_pixel_region_render_portrait_1to8;
1862
            factor = 8;
1863
            goto use_doubler;
1864
        } 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) {
1865
            state->render = mem_transform_pixel_region_render_portrait_1to4;
1866
            factor = 4;
1867
            goto use_doubler;
1868
        } 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) {
1869
            unsigned int in_lines;
1870
            int l, r;
1871
            factor = 2;
1872
            state->render = mem_transform_pixel_region_render_portrait_1to2;
1873
        use_doubler:
1874
            l = fixed2int_var_rounded(dda_current(pixels->x));
1875
            r = fixed2int_var_rounded(dda_current(pixels->x) - fixed_epsilon) + w * factor;
1876
            if (l > r) {
1877
                int t = l; l = r; r = t;
1878
            }
1879
            if (l < state->clip.p.x || r > state->clip.q.x)
1880
                goto no_cal;
1881
            state->cal_dbl = cal_doubler_init(mem->gs_lib_ctx->core->cal_ctx,
1882
                                              mem,
1883
                                              w,
1884
                                              h,
1885
                                              factor,
1886
                                              CAL_DOUBLE_NEAREST,
1887
                                              spp,
1888
                                              &in_lines);
1889
            /* assert(in_lines == 1) */
1890
            if (state->cal_dbl == NULL)
1891
                goto no_cal;
1892
        } else
1893
no_cal:
1894
#endif
1895
637k
        if (mdev->num_planar_planes > 1)
1896
#ifdef WITH_CAL
1897
planar:
1898
#endif
1899
0
            state->render = mem_transform_pixel_region_render_portrait_planar;
1900
637k
        else if (pixels->x.step.dQ == fixed_1 && pixels->x.step.dR == 0)
1901
636k
            state->render = mem_transform_pixel_region_render_portrait_1to1;
1902
1.46k
        else
1903
1.46k
            state->render = mem_transform_pixel_region_render_portrait;
1904
637k
    } else if (mdev->num_planar_planes > 1)
1905
0
        state->render = mem_transform_pixel_region_render_landscape_planar;
1906
0
    else
1907
0
        state->render = mem_transform_pixel_region_render_landscape;
1908
1909
637k
    return 0;
1910
637k
}
1911
1912
static void
1913
step_to_next_line(mem_transform_pixel_region_state_t *state)
1914
6.35M
{
1915
6.35M
    fixed x = dda_current(state->rows.x);
1916
6.35M
    fixed y = dda_current(state->rows.y);
1917
6.35M
    dda_next(state->rows.x);
1918
6.35M
    dda_next(state->rows.y);
1919
6.35M
    x = dda_current(state->rows.x) - x;
1920
6.35M
    y = dda_current(state->rows.y) - y;
1921
6.35M
    dda_translate(state->pixels.x, x);
1922
6.35M
    dda_translate(state->pixels.y, y);
1923
6.35M
}
1924
1925
static int
1926
mem_transform_pixel_region_data_needed(gx_device *dev, mem_transform_pixel_region_state_t *state)
1927
6.35M
{
1928
6.35M
    if (state->posture == transform_pixel_region_portrait) {
1929
6.35M
        int iy, ih;
1930
1931
6.35M
        get_portrait_y_extent(state, &iy, &ih);
1932
1933
6.35M
        if (iy + ih < state->clip.p.y || iy >= state->clip.q.y) {
1934
            /* Skip this line. */
1935
425
            step_to_next_line(state);
1936
425
            return 0;
1937
425
        }
1938
6.35M
    } else if (state->posture == transform_pixel_region_landscape) {
1939
0
        int ix, iw;
1940
1941
0
        get_landscape_x_extent(state, &ix, &iw);
1942
1943
0
        if (ix + iw < state->clip.p.x || ix >= state->clip.q.x) {
1944
            /* Skip this line. */
1945
0
            step_to_next_line(state);
1946
0
            return 0;
1947
0
        }
1948
0
    }
1949
1950
6.35M
    return 1;
1951
6.35M
}
1952
1953
static int
1954
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)
1955
6.35M
{
1956
6.35M
    int ret = state->render(dev, state, buffer, data_x, cmapper, pgs);
1957
1958
6.35M
    step_to_next_line(state);
1959
1960
6.35M
    return ret;
1961
6.35M
}
1962
1963
static int
1964
mem_transform_pixel_region_end(gx_device *dev, mem_transform_pixel_region_state_t *state)
1965
637k
{
1966
637k
    if (state)
1967
637k
        gs_free_object(state->mem->non_gc_memory, state, "mem_transform_pixel_region_state_t");
1968
637k
    return 0;
1969
637k
}
1970
1971
int mem_transform_pixel_region(gx_device *dev, transform_pixel_region_reason reason, transform_pixel_region_data *data)
1972
13.9M
{
1973
13.9M
    mem_transform_pixel_region_state_t *state = (mem_transform_pixel_region_state_t *)data->state;
1974
13.9M
    transform_pixel_region_posture posture;
1975
1976
    /* Pass through */
1977
13.9M
    if (reason == transform_pixel_region_begin) {
1978
637k
        const gx_dda_fixed_point *rows = data->u.init.rows;
1979
637k
        const gx_dda_fixed_point *pixels = data->u.init.pixels;
1980
637k
        if (rows->x.step.dQ == 0 && rows->x.step.dR == 0 && pixels->y.step.dQ == 0 && pixels->y.step.dR == 0)
1981
637k
            posture = transform_pixel_region_portrait;
1982
3
        else if (rows->y.step.dQ == 0 && rows->y.step.dR == 0 && pixels->x.step.dQ == 0 && pixels->x.step.dR == 0)
1983
0
            posture = transform_pixel_region_landscape;
1984
3
        else
1985
3
            posture = transform_pixel_region_skew;
1986
1987
637k
        if (posture == transform_pixel_region_skew || dev->color_info.depth != data->u.init.spp*8 || data->u.init.lop != 0xf0) {
1988
14
            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");
1989
14
            if (state == NULL)
1990
0
                return gs_error_VMerror;
1991
14
            state->render = NULL;
1992
14
            if (gx_default_transform_pixel_region(dev, transform_pixel_region_begin, data) < 0) {
1993
0
                gs_free_object(dev->memory->non_gc_memory, state, "mem_transform_pixel_region_state_t");
1994
0
                return gs_error_VMerror;
1995
0
            }
1996
14
            state->passthru = data->state;
1997
14
            data->state = state;
1998
14
            return 0;
1999
14
        }
2000
13.3M
    } else if (state->render == NULL) {
2001
5.10k
        int ret;
2002
5.10k
        data->state = state->passthru;
2003
5.10k
        ret = gx_default_transform_pixel_region(dev, reason, data);
2004
5.10k
        data->state = state;
2005
5.10k
        if (reason == transform_pixel_region_end) {
2006
14
            gs_free_object(dev->memory->non_gc_memory, state, "mem_transform_pixel_region_state_t");
2007
14
            data->state = NULL;
2008
14
        }
2009
5.10k
        return ret;
2010
5.10k
    }
2011
2012
    /* We can handle this case natively */
2013
13.9M
    switch(reason)
2014
13.9M
    {
2015
637k
    case transform_pixel_region_begin:
2016
637k
        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);
2017
6.35M
    case transform_pixel_region_data_needed:
2018
6.35M
        return mem_transform_pixel_region_data_needed(dev, state);
2019
6.35M
    case transform_pixel_region_process_data:
2020
6.35M
        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);
2021
637k
    case transform_pixel_region_end:
2022
637k
        data->state = NULL;
2023
637k
        return mem_transform_pixel_region_end(dev, state);
2024
0
    default:
2025
0
        return gs_error_unknownerror;
2026
13.9M
    }
2027
13.9M
}