Coverage Report

Created: 2025-11-16 07:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/base/gxifast.c
Line
Count
Source
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
17
/* Fast monochrome image rendering */
18
#include "gx.h"
19
#include "memory_.h"
20
#include "gpcheck.h"
21
#include "gsbittab.h"
22
#include "gserrors.h"
23
#include "gxfixed.h"
24
#include "gxarith.h"
25
#include "gxmatrix.h"
26
#include "gsccolor.h"
27
#include "gspaint.h"
28
#include "gsutil.h"
29
#include "gxdevice.h"
30
#include "gxcmap.h"
31
#include "gxdcolor.h"
32
#include "gxgstate.h"
33
#include "gxdevmem.h"
34
#include "gdevmem.h"    /* for mem_mono_device */
35
#include "gxcpath.h"
36
#include "gximage.h"
37
#include "gzht.h"
38
39
#include "valgrind.h"
40
41
/* Conditionally include statistics code. */
42
/* #define COLLECT_STATS_IFAST */
43
44
/* ------ Strategy procedure ------ */
45
46
/* Check the prototype. */
47
iclass_proc(gs_image_class_1_simple);
48
49
/* Use special fast logic for portrait or landscape black-and-white images. */
50
static irender_proc(image_render_skip);
51
static irender_proc(image_render_simple);
52
static irender_proc(image_render_landscape);
53
54
int
55
gs_image_class_1_simple(gx_image_enum * penum, irender_proc_t *render_fn)
56
2.87M
{
57
2.87M
    fixed ox = dda_current(penum->dda.pixel0.x);
58
2.87M
    fixed oy = dda_current(penum->dda.pixel0.y);
59
60
2.87M
    if (penum->use_rop || penum->spp != 1 || penum->bps != 1)
61
2.21M
        return 0;
62
655k
    switch (penum->posture) {
63
352k
        case image_portrait:
64
352k
            {     /* Use fast portrait algorithm. */
65
352k
                long dev_width =
66
352k
                    fixed2long_pixround(ox + penum->x_extent.x) -
67
352k
                    fixed2long_pixround(ox);
68
69
352k
                if (dev_width != penum->rect.w) {
70
                    /*
71
                     * Add an extra align_bitmap_mod of padding so that
72
                     * we can align scaled rows with the device.
73
                     */
74
143k
                    long line_size =
75
143k
                        bitmap_raster(any_abs(dev_width)) + align_bitmap_mod;
76
77
143k
                    if (penum->adjust != 0 || line_size > max_uint)
78
48.5k
                        return 0;
79
                    /* Must buffer a scan line. */
80
95.3k
                    penum->line_width = any_abs(dev_width);
81
95.3k
                    penum->line_size = (uint) line_size;
82
95.3k
                    penum->line = gs_alloc_bytes(penum->memory,
83
95.3k
                                            penum->line_size, "image line");
84
95.3k
                    if (penum->line == 0) {
85
0
                        return gs_error_VMerror;
86
0
                    }
87
95.3k
                }
88
352k
                if_debug2m('b', penum->memory, "[b]render=simple, unpack=copy; rect.w=%d, dev_width=%ld\n",
89
303k
                           penum->rect.w, dev_width);
90
303k
                *render_fn = image_render_simple;
91
303k
                break;
92
352k
            }
93
171k
        case image_landscape:
94
171k
            {     /* Use fast landscape algorithm. */
95
171k
                long dev_width =
96
171k
                    fixed2long_pixround(oy + penum->x_extent.y) -
97
171k
                    fixed2long_pixround(oy);
98
171k
                long line_size =
99
171k
                    (dev_width = any_abs(dev_width),
100
171k
                     bitmap_raster(dev_width) * 8 +
101
171k
                     ROUND_UP(dev_width, 8) * align_bitmap_mod);
102
103
171k
                if ((dev_width != penum->rect.w && penum->adjust != 0) ||
104
171k
                    line_size > max_uint
105
171k
                    )
106
1
                    return 0;
107
                /* Must buffer a group of 8N scan lines. */
108
171k
                penum->line_width = dev_width;
109
171k
                penum->line_size = (uint) line_size;
110
171k
                penum->line = gs_alloc_bytes(penum->memory,
111
171k
                                             penum->line_size, "image line");
112
171k
                if (penum->line == 0) {
113
0
                    return gs_error_VMerror;
114
0
                }
115
171k
#ifdef PACIFY_VALGRIND
116
171k
                memset(penum->line, 0, penum->line_size); /* For the number of scan lined < 8 */
117
171k
#endif
118
171k
                penum->xi_next = penum->line_xy = fixed2int_var_rounded(ox);
119
171k
                if_debug3m('b', penum->memory,
120
171k
                           "[b]render=landscape, unpack=copy; rect.w=%d, dev_width=%ld, line_size=%ld\n",
121
171k
                           penum->rect.w, dev_width, line_size);
122
171k
                *render_fn = image_render_landscape;
123
                /* Precompute values needed for rasterizing. */
124
171k
                penum->dxy =
125
171k
                    float2fixed(penum->matrix.xy +
126
171k
                                fixed2float(fixed_epsilon) / 2);
127
171k
                break;
128
171k
            }
129
131k
        default:
130
131k
            return 0;
131
655k
    }
132
    /* Precompute values needed for rasterizing. */
133
475k
    penum->dxx =
134
475k
        float2fixed(penum->matrix.xx + fixed2float(fixed_epsilon) / 2);
135
    /*
136
     * We don't want to spread the samples, but we have to reset unpack_bps
137
     * to prevent the buffer pointer from being incremented by 8 bytes per
138
     * input byte.
139
     */
140
475k
    penum->unpack = sample_unpack_copy;
141
475k
    penum->unpack_bps = 8;
142
475k
    if (penum->use_mask_color) {
143
        /*
144
         * Set the masked color as 'no_color' to make it transparent
145
         *  according to the mask color range and the decoding.
146
         */
147
0
        penum->masked = true;
148
0
        if (penum->mask_color.values[0] == 1) {
149
            /* if v0 == 1, 1 is transparent since v1 must be == 1 to be a valid range */
150
0
            set_nonclient_dev_color(penum->map[0].inverted ? penum->icolor0 : penum->icolor1,
151
0
                        gx_no_color_index);
152
0
        } else if (penum->mask_color.values[1] == 0) {
153
            /* if v1 == 0, 0 is transparent since v0 must be == 0 to be a valid range */
154
0
            set_nonclient_dev_color(penum->map[0].inverted ? penum->icolor1 : penum->icolor0,
155
0
                        gx_no_color_index);
156
0
        } else {
157
            /*
158
             * The only other possible in-range value is v0 = 0, v1 = 1.
159
             * The image is completely transparent!
160
             */
161
0
            *render_fn = image_render_skip;
162
0
        }
163
0
        penum->map[0].decoding = sd_none;
164
0
    }
165
475k
    return 0;
166
655k
}
167
168
/* ------ Rendering procedures ------ */
169
170
#define DC_IS_NULL(pdc)\
171
150M
  (gx_dc_is_pure(pdc) && (pdc)->colors.pure == gx_no_color_index)
172
173
/* Skip over a completely transparent image. */
174
static int
175
image_render_skip(gx_image_enum * penum, const byte * buffer, int data_x,
176
                  uint w, int h, gx_device * dev)
177
0
{
178
0
    return h;
179
0
}
180
181
/*
182
 * Scale (and possibly reverse) one scan line of a monobit image.
183
 * This is used for both portrait and landscape image processing.
184
 * We pass in an x offset (0 <= line_x < align_bitmap_mod * 8) so that
185
 * we can align the result with the eventual device X.
186
 *
187
 * To be precise, the input to this routine is the w bits starting at
188
 * bit data_x in buffer.  These w bits expand to abs(x_extent) bits,
189
 * either inverted (zero = 0xff) or not (zero = 0), starting at bit
190
 * line_x in line which corresponds to coordinate
191
 * fixed2int_pixround(xcur + min(x_extent, 0)).  Note that the entire
192
 * bytes containing the first and last output bits are affected: the
193
 * other bits in those bytes are set to zero (i.e., the value of the
194
 * 'zero' argument).
195
 */
196
#ifdef COLLECT_STATS_IFAST
197
struct stats_image_fast_s {
198
    long
199
         calls, all0s, all1s, runs, lbit0, byte00, byte01, byte02, byte03,
200
         byte04, rbit0, lbit1, byte1, rbit1, thin, thin2, nwide, bwide,
201
         nfill, bfill;
202
} stats_image_fast;
203
#  define INCS(stat) ++stats_image_fast.stat
204
#  define ADDS(stat, n) stats_image_fast.stat += n
205
#else
206
1.18G
#  define INCS(stat) DO_NOTHING
207
3.08M
#  define ADDS(stat, n) DO_NOTHING
208
#endif
209
static inline void
210
fill_row(byte *line, int line_x, uint raster, int value)
211
4.06M
{
212
4.06M
    memset(line + (line_x >> 3), value, raster - (line_x >> 3));
213
4.06M
}
214
215
static void
216
image_simple_expand(byte * line, int line_x, uint raster,
217
                    const byte * buffer, int data_x, uint w,
218
                    fixed xcur, fixed x_extent, byte zero /* 0 or 0xff */ )
219
4.06M
{
220
4.06M
    int dbitx = data_x & 7;
221
4.06M
    byte sbit = 0x80 >> dbitx;
222
4.06M
    byte sbitmask = 0xff >> dbitx;
223
4.06M
    uint wx = dbitx + w;
224
4.06M
    gx_dda_fixed xl;
225
4.06M
    gx_dda_step_fixed dxx4, dxx8, dxx16, dxx24, dxx32;
226
4.06M
    register const byte *psrc = buffer + (data_x >> 3);
227
228
    /*
229
     * The following 3 variables define the end of the input data row.
230
     * We would put them in a struct, except that no compiler that we
231
     * know of will optimize individual struct members as though they
232
     * were simple variables (e.g., by putting them in registers).
233
     *
234
     * endp points to the byte that contains the bit just beyond the
235
     * end of the row.  endx gives the bit number of this bit within
236
     * the byte, with 0 being the *least* significant bit.  endbit is
237
     * a mask for this bit.
238
     */
239
4.06M
    const byte *endp = psrc + (wx >> 3);
240
4.06M
    int endx = ~wx & 7;
241
4.06M
    byte endbit = 1 << endx;
242
243
    /*
244
     * The following 3 variables do the same for start of the last run
245
     * of the input row (think of it as a pointer to just beyond the
246
     * end of the next-to-last run).
247
     */
248
4.06M
    const byte *stop = endp;
249
4.06M
    int stopx;
250
4.06M
    byte stopbit = endbit;
251
4.06M
    byte data;
252
4.06M
    byte one = ~zero;
253
4.06M
    fixed xl0;
254
4.06M
#ifdef PACIFY_VALGRIND
255
4.06M
    byte vbits;
256
4.06M
#endif
257
258
4.06M
    if (w == 0)
259
0
        return;
260
4.06M
    INCS(calls);
261
262
    /* Scan backward for the last transition. */
263
4.06M
    if (stopbit == 0x80)
264
1.16M
        --stop, stopbit = 1;
265
2.89M
    else
266
2.89M
        stopbit <<= 1;
267
    /* Now (stop, stopbit) give the last bit of the row. */
268
4.06M
#ifdef PACIFY_VALGRIND
269
    /* Here, we are dealing with a row of bits, rather than bytes.
270
     * If the width of the bits is not a multiple of 8, we don't
271
     * fill out the last byte, and valgrind (correctly) tracks the
272
     * bits in that last byte as being a mix of defined and undefined.
273
     * When we are scanning through the row bitwise, everything works
274
     * fine, but our "skip whole bytes" code can confuse valgrind.
275
     * We know that we won't match the "data == 0xff" for the final
276
     * byte (i.e. the undefinedness of some of the bits doesn't matter
277
     * to the correctness of the routine), but valgrind is not smart
278
     * enough to realise that we know this. Accordingly, we get a false
279
     * positive "undefined memory read".
280
     * How do we fix this? Well, one way would be to read in the
281
     * partial last byte, and explicitly set the undefined bits to
282
     * be 0.
283
     *   *stop &= ~(stopbit-1);
284
     * Unfortunately, stop is a const *, so we can't do that (we could
285
     * break const, but it is just conceivable that the caller might
286
     * pass the next string of bits out in a later call, and so we
287
     * might be corrupting valid data).
288
     * Instead, we make a call to a valgrind helper. */
289
4.06M
    VALGRIND_GET_VBITS(stop,&vbits,1);
290
4.06M
    if ((vbits & stopbit)==0) { /* At least our stop bit must be addressable already! */
291
4.06M
      byte zero = 0;
292
4.06M
      VALGRIND_SET_VBITS(stop,&zero,1);
293
4.06M
    }
294
4.06M
#endif
295
4.06M
    {
296
4.06M
        byte stopmask = (-stopbit << 1) & 0xff;
297
4.06M
        byte last = *stop;
298
299
4.06M
        if (stop == psrc)  /* only 1 input byte */
300
2.53M
            stopmask &= sbitmask;
301
4.06M
        if (last & stopbit) {
302
            /* The last bit is a 1: look for a 0-to-1 transition. */
303
1.09M
            if (~last & stopmask) { /* Transition in last byte. */
304
200k
                last |= stopbit - 1;
305
896k
            } else {   /* No transition in the last byte. */
306
195M
                while (stop > psrc && stop[-1] == 0xff)
307
194M
                    --stop;
308
896k
                if (stop == psrc ||
309
444k
                    (stop == psrc + 1 && !(~*psrc & sbitmask))
310
896k
                    ) {
311
                    /* The input is all 1s.  Clear the row and exit. */
312
452k
                    INCS(all1s);
313
452k
                    fill_row(line, line_x, raster, one);
314
452k
                    goto end;
315
452k
                }
316
444k
                last = *--stop;
317
444k
            }
318
644k
            stopx = byte_bit_run_length_0[byte_reverse_bits[last]] - 1;
319
2.97M
        } else {
320
            /* The last bit is a 0: look for a 1-to-0 transition. */
321
2.97M
            if (last & stopmask) { /* Transition in last byte. */
322
1.87M
                last &= -stopbit;
323
1.87M
            } else {   /* No transition in the last byte. */
324
42.1M
                while (stop > psrc && stop[-1] == 0)
325
41.0M
                    --stop;
326
1.09M
                if (stop == psrc ||
327
160k
                    (stop == psrc + 1 && !(*psrc & sbitmask))
328
1.09M
                    ) {
329
                    /* The input is all 0s.  Clear the row and exit. */
330
938k
                    INCS(all0s);
331
938k
                    fill_row(line, line_x, raster, zero);
332
938k
                    goto end;
333
938k
                }
334
160k
                last = *--stop;
335
160k
            }
336
2.03M
            stopx = byte_bit_run_length_0[byte_reverse_bits[last ^ 0xff]] - 1;
337
2.03M
        }
338
2.67M
        if (stopx < 0)
339
103k
            stopx = 7, ++stop;
340
2.67M
        stopbit = 1 << stopx;
341
2.67M
    }
342
343
    /* Pre-clear the row. */
344
0
    fill_row(line, line_x, raster, zero);
345
346
347
    /* Extreme negative values of x_extent cause the xl0 calculation
348
     * to explode. Workaround this here. */
349
2.67M
    if (x_extent < min_int + 0x100)
350
0
      x_extent += 0x100;
351
352
    /* Set up the DDAs. */
353
2.67M
    xl0 =
354
2.67M
        (x_extent >= 0 ?
355
1.04M
         fixed_fraction(fixed_pre_pixround(xcur)) :
356
2.67M
         fixed_fraction(fixed_pre_pixround(xcur + x_extent)) - x_extent);
357
2.67M
    xl0 += int2fixed(line_x);
358
    /* We should never get a negative x10 here. If we do, all bets are off. */
359
2.67M
    if (xl0 < 0)
360
0
        xl0 = 0, x_extent = 0;
361
2.67M
    dda_init(xl, xl0, x_extent, w);
362
2.67M
    dxx4 = xl.step;
363
2.67M
    dda_step_add(dxx4, xl.step);
364
    /* egcc - 2.91.66 generates incorrect code for
365
     * dda_step_add(dxx4, dxx4);
366
     * Using the temp variable.
367
     */
368
2.67M
    dxx8 = dxx4;
369
2.67M
    dda_step_add(dxx4, dxx8);
370
2.67M
    dxx8 = dxx4;
371
2.67M
    dda_step_add(dxx8, dxx4);
372
2.67M
    dxx16 = dxx8;
373
2.67M
    dda_step_add(dxx16, dxx8);
374
2.67M
    dxx24 = dxx16;
375
2.67M
    dda_step_add(dxx24, dxx8);
376
2.67M
    dxx32 = dxx24;
377
2.67M
    dda_step_add(dxx32, dxx8);
378
379
    /*
380
     * Loop invariants:
381
     *      data = *psrc;
382
     *      sbit = 1 << n, 0<=n<=7.
383
     */
384
169M
    for (data = *psrc;;) {
385
169M
        int x0, n, bit;
386
169M
        byte *bp;
387
169M
        static const byte lmasks[9] = {
388
169M
            0xff, 0x7f, 0x3f, 0x1f, 0xf, 7, 3, 1, 0
389
169M
        };
390
169M
        static const byte rmasks[9] = {
391
169M
            0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
392
169M
        };
393
394
169M
        INCS(runs);
395
396
        /* Scan a run of zeros. */
397
169M
        data ^= 0xff;   /* invert */
398
498M
        while (data & sbit) {
399
329M
            dda_next(xl);
400
329M
            sbit >>= 1;
401
329M
            INCS(lbit0);
402
329M
        }
403
169M
        if (!sbit) {   /* Scan a run of zero bytes. */
404
49.8M
sw:     if ((data = psrc[1]) != 0) {
405
45.2M
                psrc++;
406
45.2M
                INCS(byte00);
407
45.2M
            } else if ((data = psrc[2]) != 0) {
408
1.43M
                dda_state_next(xl.state, dxx8);
409
1.43M
                psrc += 2;
410
1.43M
                INCS(byte01);
411
3.18M
            } else if ((data = psrc[3]) != 0) {
412
380k
                dda_state_next(xl.state, dxx16);
413
380k
                psrc += 3;
414
380k
                INCS(byte02);
415
2.80M
            } else if ((data = psrc[4]) != 0) {
416
164k
                dda_state_next(xl.state, dxx24);
417
164k
                psrc += 4;
418
164k
                INCS(byte03);
419
2.63M
            } else {
420
2.63M
                dda_state_next(xl.state, dxx32);
421
2.63M
                psrc += 4;
422
2.63M
                INCS(byte04);
423
2.63M
                goto sw;
424
2.63M
            }
425
47.2M
            if (data > 0xf)
426
42.1M
                sbit = 0x80;
427
5.08M
            else {
428
5.08M
                sbit = 0x08;
429
5.08M
                dda_state_next(xl.state, dxx4);
430
5.08M
            }
431
47.2M
            data ^= 0xff; /* invert */
432
87.9M
            while (data & sbit) {
433
40.6M
                dda_next(xl);
434
40.6M
                sbit >>= 1;
435
40.6M
                INCS(rbit0);
436
40.6M
            }
437
47.2M
        }
438
169M
        x0 = dda_current_fixed2int(xl);
439
169M
        if (psrc >= stop && sbit == stopbit) {
440
            /*
441
             * We've scanned the last run of 0s.
442
             * Prepare to fill the final run of 1s.
443
             * Use int64_t to avoid overflow.
444
             */
445
644k
            n = fixed2int((int64_t)xl0 + (int64_t)x_extent) - x0;
446
168M
        } else {   /* Scan a run of ones. */
447
            /* We know the current bit is a one. */
448
168M
            data ^= 0xff; /* un-invert */
449
334M
            do {
450
334M
                dda_next(xl);
451
334M
                sbit >>= 1;
452
334M
                INCS(lbit1);
453
334M
            }
454
334M
            while (data & sbit);
455
168M
            if (!sbit) { /* Scan a run of 0xff bytes. */
456
94.9M
                while ((data = *++psrc) == 0xff) {
457
44.0M
                    dda_state_next(xl.state, dxx8);
458
44.0M
                    INCS(byte1);
459
44.0M
                }
460
50.9M
                if (data < 0xf0)
461
43.6M
                    sbit = 0x80;
462
7.25M
                else {
463
7.25M
                    sbit = 0x08;
464
7.25M
                    dda_state_next(xl.state, dxx4);
465
7.25M
                }
466
95.4M
                while (data & sbit) {
467
44.4M
                    dda_next(xl);
468
44.4M
                    sbit >>= 1;
469
44.4M
                    INCS(rbit1);
470
44.4M
                }
471
50.9M
            }
472
168M
            n = dda_current_fixed2int(xl) - x0;
473
168M
        }
474
475
        /* Fill the run in the scan line. */
476
169M
        if (n < 0)
477
2.75M
            x0 += n, n = -n;
478
169M
        bp = line + (x0 >> 3);
479
169M
        bit = x0 & 7;
480
169M
        if ((n += bit) <= 8) {
481
146M
            *bp ^= lmasks[bit] - lmasks[n];
482
146M
            INCS(thin);
483
146M
        } else if ((n -= 8) <= 8) {
484
19.5M
            *bp ^= lmasks[bit];
485
19.5M
            bp[1] ^= rmasks[n];
486
19.5M
            INCS(thin2);
487
19.5M
        } else {
488
3.08M
            *bp++ ^= lmasks[bit];
489
3.08M
            if (n >= 56) {
490
1.22M
                int nb = n >> 3;
491
492
1.22M
                memset(bp, one, nb);
493
1.22M
                bp += nb;
494
1.22M
                INCS(nwide);
495
1.22M
                ADDS(bwide, nb);
496
1.85M
            } else {
497
1.85M
                ADDS(bfill, n >> 3);
498
5.95M
                while ((n -= 8) >= 0)
499
4.10M
                    *bp++ = one;
500
1.85M
                INCS(nfill);
501
1.85M
            }
502
3.08M
            *bp ^= rmasks[n & 7];
503
3.08M
        }
504
169M
        if (psrc >= stop && sbit == stopbit)
505
2.67M
            break;
506
169M
    }
507
4.06M
 end:
508
4.06M
    {
509
4.06M
#ifdef PACIFY_VALGRIND
510
4.06M
    VALGRIND_SET_VBITS(stop,&vbits,1);
511
4.06M
#endif
512
4.06M
    }
513
4.06M
}
514
515
/* Copy one rendered scan line to the device. */
516
static int
517
copy_portrait(gx_image_enum * penum, const byte * data, int dx, int raster,
518
              int x, int y, int w, int h, gx_device * dev)
519
30.8M
{
520
30.8M
    const gx_device_color *pdc0;
521
30.8M
    const gx_device_color *pdc1;
522
30.8M
    uint align = ALIGNMENT_MOD(data, align_bitmap_mod);
523
524
    /*
525
     * We know that the lookup table maps 1 bit to 1 bit,
526
     * so it can only have 2 states: straight-through or invert.
527
     */
528
30.8M
    if (penum->map[0].table.lookup4x1to32[0])
529
1.39M
        pdc0 = penum->icolor1, pdc1 = penum->icolor0;
530
29.4M
    else
531
29.4M
        pdc0 = penum->icolor0, pdc1 = penum->icolor1;
532
30.8M
    data -= align;
533
30.8M
    dx += align << 3;
534
30.8M
    if (gx_dc_is_pure(pdc0) && gx_dc_is_pure(pdc1)) {
535
        /* Just use copy_mono. */
536
6.80M
        dev_proc_copy_mono((*copy_mono)) =
537
6.80M
            (h == 1 || (raster & (align_bitmap_mod - 1)) == 0 ?
538
6.80M
             dev_proc(dev, copy_mono) : gx_copy_mono_unaligned);
539
6.80M
        return (*copy_mono)
540
6.80M
            (dev, data, dx, raster, gx_no_bitmap_id,
541
6.80M
             x, y, w, h, pdc0->colors.pure, pdc1->colors.pure);
542
6.80M
    }
543
    /*
544
     * At least one color isn't pure: if the other one is transparent, use
545
     * the opaque color's fill_masked procedure.  Note that we use a
546
     * slightly unusual representation for transparent here (per
547
     * gx_begin_image1): a pure color with pixel value gx_no_color_index.
548
     */
549
24.0M
    {
550
24.0M
        const gx_device_color *pdc;
551
24.0M
        bool invert;
552
553
24.0M
        if (DC_IS_NULL(pdc1)) {
554
55.5k
            pdc = pdc0;
555
55.5k
            invert = true;
556
23.9M
        } else {
557
23.9M
            if (!DC_IS_NULL(pdc0)) {
558
234k
                int code = gx_device_color_fill_rectangle
559
234k
                    (pdc0, x, y, w, h, dev, lop_default, NULL);
560
561
234k
                if (code < 0)
562
0
                    return code;
563
234k
            }
564
23.9M
            pdc = pdc1;
565
23.9M
            invert = false;
566
23.9M
        }
567
24.0M
        return (*pdc->type->fill_masked)
568
24.0M
            (pdc, data, dx, raster, gx_no_bitmap_id, x, y, w, h,
569
24.0M
             dev, lop_default, invert);
570
571
24.0M
    }
572
24.0M
}
573
574
/* Rendering procedure for a monobit image with no */
575
/* skew or rotation and pure colors. */
576
static int
577
image_render_simple(gx_image_enum * penum, const byte * buffer, int data_x,
578
                    uint w, int h, gx_device * dev)
579
26.2M
{
580
26.2M
    dev_proc_copy_mono((*copy_mono)) = dev_proc(dev, copy_mono);
581
26.2M
    const fixed dxx = penum->dxx;
582
26.2M
    const byte *line;
583
26.2M
    uint line_width, line_size;
584
26.2M
    int line_x;
585
26.2M
    fixed xcur = dda_current(penum->dda.pixel0.x);
586
26.2M
    int ix = fixed2int_pixround(xcur);
587
26.2M
    int ixr;
588
26.2M
    const int iy = penum->yci, ih = penum->hci;
589
26.2M
    gx_device_color * const pdc0 = penum->icolor0;
590
26.2M
    gx_device_color * const pdc1 = penum->icolor1;
591
26.2M
    int dy;
592
26.2M
    int code;
593
594
26.2M
    if (h == 0)
595
682k
        return 0;
596
25.6M
    if ((!DC_IS_NULL(pdc0) &&
597
1.11M
         (code = gx_color_load(pdc0, penum->pgs, dev)) < 0) ||
598
25.6M
        (!DC_IS_NULL(pdc1) &&
599
25.6M
         (code = gx_color_load(pdc1, penum->pgs, dev)) < 0)
600
25.6M
        )
601
0
        return code;
602
25.6M
    if (penum->line == 0) { /* A direct BitBlt is possible. */
603
23.6M
        line = buffer;
604
23.6M
        line_size = (w + 7) >> 3;
605
23.6M
        line_width = w;
606
23.6M
        line_x = 0;
607
23.6M
    } else if (copy_mono == mem_mono_copy_mono &&
608
320k
               dxx > 0 && gx_dc_is_pure(pdc1) && gx_dc_is_pure(pdc0) &&
609
               /* We know the colors must be (0,1) or (1,0). */
610
250k
               (pdc0->colors.pure ^ pdc1->colors.pure) == 1 &&
611
4.08k
               !penum->clip_image &&
612
               /*
613
                * Even if clip_image is false, the clipping rectangle
614
                * might lie partly outside the device coordinate space
615
                * if the Margins values are non-zero.
616
                */
617
2.56k
               ix >= 0 &&
618
2.56k
               (ixr = fixed2int_pixround(xcur + penum->x_extent.x) - 1) <
619
2.56k
                 dev->width &&
620
2.56k
               iy >= 0 && iy + ih <= dev->height
621
1.96M
        ) {
622
        /* Do the operation directly into the memory device bitmap. */
623
2.56k
        int line_ix;
624
2.56k
        int ib_left = ix >> 3, ib_right = ixr >> 3;
625
2.56k
        byte *scan_line = scan_line_base((gx_device_memory *) dev, iy);
626
2.56k
        byte save_left, save_right, mask;
627
628
2.56k
        line_x = ix & (align_bitmap_mod * 8 - 1);
629
2.56k
        line_ix = ix - line_x;
630
2.56k
        line_size = (ixr >> 3) + 1 - (line_ix >> 3);
631
2.56k
        line_width = ixr + 1 - ix;
632
        /* We must save and restore any unmodified bits in */
633
        /* the two edge bytes. */
634
2.56k
        save_left = scan_line[ib_left];
635
2.56k
        save_right = scan_line[ib_right];
636
2.56k
        image_simple_expand(scan_line + (line_ix >> 3), line_x,
637
2.56k
                            line_size, buffer, data_x, w, xcur,
638
2.56k
                            penum->x_extent.x,
639
2.56k
                            (byte)((pdc0->colors.pure == 0) !=
640
2.56k
                             (penum->map[0].table.lookup4x1to32[0] == 0) ?
641
2.43k
                             0xff : 0));
642
2.56k
        if (ix & 7)
643
2.56k
            mask = (byte) (0xff00 >> (ix & 7)),
644
2.56k
                scan_line[ib_left] =
645
2.56k
                (save_left & mask) + (scan_line[ib_left] & ~mask);
646
2.56k
        if ((ixr + 1) & 7)
647
2.40k
            mask = (byte) (0xff00 >> ((ixr + 1) & 7)),
648
2.40k
                scan_line[ib_right] =
649
2.40k
                (scan_line[ib_right] & mask) + (save_right & ~mask);
650
2.56k
        if (ih <= 1)
651
0
            return 1;
652
        /****** MAY BE UNALIGNED ******/
653
2.56k
        line = scan_line + (line_ix >> 3);
654
22.8k
        for (dy = 1; dy < ih; dy++) {
655
20.3k
            int code = (*copy_mono)
656
20.3k
                (dev, line, line_x, line_size, gx_no_bitmap_id,
657
20.3k
                 ix, iy + dy, line_width, 1,
658
20.3k
                 (gx_color_index)0, (gx_color_index)1);
659
660
20.3k
            if (code < 0)
661
0
                return code;
662
20.3k
        }
663
2.56k
        return 0;
664
1.96M
    } else {
665
1.96M
        line = penum->line;
666
1.96M
        line_size = penum->line_size;
667
1.96M
        line_width = penum->line_width;
668
1.96M
        line_x = ix & (align_bitmap_mod * 8 - 1);
669
1.96M
        image_simple_expand(penum->line, line_x, line_size,
670
1.96M
                            buffer, data_x, w, xcur,
671
1.96M
                            penum->x_extent.x, 0);
672
1.96M
    }
673
674
    /* Finally, transfer the scan line to the device. */
675
25.5M
    if (dxx < 0)
676
422k
        ix -= line_width;
677
55.8M
    for (dy = 0; dy < ih; dy++) {
678
30.2M
        int code = copy_portrait(penum, line, line_x, line_size,
679
30.2M
                                 ix, iy + dy, line_width, 1, dev);
680
681
30.2M
        if (code < 0)
682
0
            return code;
683
30.2M
    }
684
685
25.5M
    return 1;
686
25.5M
}
687
688
/* Rendering procedure for a 90 degree rotated monobit image */
689
/* with pure colors.  We buffer and then flip 8 scan lines at a time. */
690
static int copy_landscape(gx_image_enum *, int, int, bool, gx_device *);
691
static int
692
image_render_landscape(gx_image_enum * penum, const byte * buffer, int data_x,
693
                       uint w, int h, gx_device * dev)
694
2.06M
{
695
2.06M
    byte *line = penum->line;
696
2.06M
    uint raster = bitmap_raster(penum->line_width);
697
2.06M
    int ix = penum->xci, iw = penum->wci;
698
2.06M
    int xinc, xmod;
699
2.06M
    byte *row;
700
2.06M
    const byte *orig_row = 0;
701
2.06M
    bool y_neg = (is_fneg(penum->matrix.xy));
702
703
2.06M
    if (is_fneg(penum->matrix.yx))
704
1.36k
        ix += iw, iw = -iw, xinc = -1;
705
2.06M
    else
706
2.06M
        xinc = 1;
707
    /*
708
     * Because of clipping, there may be discontinuous jumps in the values
709
     * of ix (xci).  If this happens, or if we are at the end of the data or
710
     * a client has requested flushing, flush the flipping buffer.
711
     */
712
2.06M
    if (ix != penum->xi_next || h == 0) {
713
344k
        int xi = penum->xi_next;
714
344k
        int code =
715
344k
            (xinc > 0 ?
716
343k
             copy_landscape(penum, penum->line_xy, xi, y_neg, dev) :
717
344k
             copy_landscape(penum, xi, penum->line_xy, y_neg, dev));
718
719
344k
        if (code < 0)
720
0
            return code;
721
344k
        penum->line_xy = penum->xi_next = ix;
722
344k
        if (h == 0)
723
343k
            return code;
724
344k
    }
725
6.36M
    for (; iw != 0; iw -= xinc) {
726
4.64M
        if (xinc < 0)
727
90.0k
            --ix;
728
4.64M
        xmod = ix & 7;
729
4.64M
        row = line + xmod * raster;
730
4.64M
        if (orig_row == 0) {
731
2.10M
            image_simple_expand(row, 0, raster,
732
2.10M
                                buffer, data_x, w,
733
2.10M
                                dda_current(penum->dda.pixel0.y),
734
2.10M
                                penum->x_extent.y, 0);
735
2.10M
            orig_row = row;
736
2.10M
        } else
737
2.54M
            memcpy(row, orig_row, raster);
738
4.64M
        if (xinc > 0) {
739
4.55M
            ++ix;
740
4.55M
            if (xmod == 7) {
741
579k
                int code =
742
579k
                    copy_landscape(penum, penum->line_xy, ix, y_neg, dev);
743
744
579k
                if (code < 0)
745
0
                    return code;
746
579k
                orig_row = 0;
747
579k
                penum->line_xy = ix;
748
579k
            }
749
4.55M
        } else {
750
90.0k
            if (xmod == 0) {
751
11.2k
                int code =
752
11.2k
                    copy_landscape(penum, ix, penum->line_xy, y_neg, dev);
753
754
11.2k
                if (code < 0)
755
0
                    return code;
756
11.2k
                orig_row = 0;
757
11.2k
                penum->line_xy = ix;
758
11.2k
            }
759
90.0k
        }
760
4.64M
    }
761
1.72M
    penum->xi_next = ix;
762
1.72M
    return 0;
763
1.72M
}
764
765
/* Flip and copy one group of scan lines. */
766
static int
767
copy_landscape(gx_image_enum * penum, int x0, int x1, bool y_neg,
768
               gx_device * dev)
769
934k
{
770
934k
    byte *line = penum->line;
771
934k
    uint line_width = penum->line_width;
772
934k
    uint raster = bitmap_raster(line_width);
773
934k
    byte *flipped = line + raster * 8;
774
934k
    int w = x1 - x0;
775
934k
    int y = fixed2int_pixround(dda_current(penum->dda.pixel0.y));
776
777
934k
    if (w == 0 || line_width == 0)
778
330k
        return 0;
779
    /* Flip the buffered data from raster x 8 to align_bitmap_mod x */
780
    /* line_width. */
781
603k
    if (line_width > 0) {
782
603k
        int i = (line_width-1)>>3;
783
784
603k
#ifdef PACIFY_VALGRIND
785
603k
        if (line_width & 7) {
786
599k
            memflip8x8_eol(line + i, raster,
787
599k
                           flipped + (i << (log2_align_bitmap_mod + 3)),
788
599k
                           align_bitmap_mod,
789
599k
                           line_width & 7);
790
599k
            i--;
791
599k
        }
792
603k
#endif
793
794
244M
        for (; i >= 0; --i)
795
243M
            memflip8x8(line + i, raster,
796
243M
                       flipped + (i << (log2_align_bitmap_mod + 3)),
797
243M
                       align_bitmap_mod);
798
603k
    }
799
    /* Transfer the scan lines to the device. */
800
603k
    if (w < 0)
801
0
        x0 = x1, w = -w;
802
603k
    if (y_neg)
803
568k
        y -= line_width;
804
603k
    return copy_portrait(penum, flipped, x0 & 7, align_bitmap_mod,
805
603k
                         x0, y, w, line_width, dev);
806
934k
}