Coverage Report

Created: 2025-08-28 07:06

/src/ghostpdl/base/gxifast.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
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.35M
{
57
2.35M
    fixed ox = dda_current(penum->dda.pixel0.x);
58
2.35M
    fixed oy = dda_current(penum->dda.pixel0.y);
59
60
2.35M
    if (penum->use_rop || penum->spp != 1 || penum->bps != 1)
61
1.88M
        return 0;
62
467k
    switch (penum->posture) {
63
269k
        case image_portrait:
64
269k
            {     /* Use fast portrait algorithm. */
65
269k
                long dev_width =
66
269k
                    fixed2long_pixround(ox + penum->x_extent.x) -
67
269k
                    fixed2long_pixround(ox);
68
69
269k
                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
114k
                    long line_size =
75
114k
                        bitmap_raster(any_abs(dev_width)) + align_bitmap_mod;
76
77
114k
                    if (penum->adjust != 0 || line_size > max_uint)
78
48.3k
                        return 0;
79
                    /* Must buffer a scan line. */
80
66.4k
                    penum->line_width = any_abs(dev_width);
81
66.4k
                    penum->line_size = (uint) line_size;
82
66.4k
                    penum->line = gs_alloc_bytes(penum->memory,
83
66.4k
                                            penum->line_size, "image line");
84
66.4k
                    if (penum->line == 0) {
85
0
                        return gs_error_VMerror;
86
0
                    }
87
66.4k
                }
88
269k
                if_debug2m('b', penum->memory, "[b]render=simple, unpack=copy; rect.w=%d, dev_width=%ld\n",
89
221k
                           penum->rect.w, dev_width);
90
221k
                *render_fn = image_render_simple;
91
221k
                break;
92
269k
            }
93
102k
        case image_landscape:
94
102k
            {     /* Use fast landscape algorithm. */
95
102k
                long dev_width =
96
102k
                    fixed2long_pixround(oy + penum->x_extent.y) -
97
102k
                    fixed2long_pixround(oy);
98
102k
                long line_size =
99
102k
                    (dev_width = any_abs(dev_width),
100
102k
                     bitmap_raster(dev_width) * 8 +
101
102k
                     ROUND_UP(dev_width, 8) * align_bitmap_mod);
102
103
102k
                if ((dev_width != penum->rect.w && penum->adjust != 0) ||
104
102k
                    line_size > max_uint
105
102k
                    )
106
1
                    return 0;
107
                /* Must buffer a group of 8N scan lines. */
108
102k
                penum->line_width = dev_width;
109
102k
                penum->line_size = (uint) line_size;
110
102k
                penum->line = gs_alloc_bytes(penum->memory,
111
102k
                                             penum->line_size, "image line");
112
102k
                if (penum->line == 0) {
113
0
                    return gs_error_VMerror;
114
0
                }
115
102k
#ifdef PACIFY_VALGRIND
116
102k
                memset(penum->line, 0, penum->line_size); /* For the number of scan lined < 8 */
117
102k
#endif
118
102k
                penum->xi_next = penum->line_xy = fixed2int_var_rounded(ox);
119
102k
                if_debug3m('b', penum->memory,
120
102k
                           "[b]render=landscape, unpack=copy; rect.w=%d, dev_width=%ld, line_size=%ld\n",
121
102k
                           penum->rect.w, dev_width, line_size);
122
102k
                *render_fn = image_render_landscape;
123
                /* Precompute values needed for rasterizing. */
124
102k
                penum->dxy =
125
102k
                    float2fixed(penum->matrix.xy +
126
102k
                                fixed2float(fixed_epsilon) / 2);
127
102k
                break;
128
102k
            }
129
95.8k
        default:
130
95.8k
            return 0;
131
467k
    }
132
    /* Precompute values needed for rasterizing. */
133
323k
    penum->dxx =
134
323k
        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
323k
    penum->unpack = sample_unpack_copy;
141
323k
    penum->unpack_bps = 8;
142
323k
    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
323k
    return 0;
166
467k
}
167
168
/* ------ Rendering procedures ------ */
169
170
#define DC_IS_NULL(pdc)\
171
152M
  (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
950M
#  define INCS(stat) DO_NOTHING
207
2.37M
#  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
8.61M
{
212
8.61M
    memset(line + (line_x >> 3), value, raster - (line_x >> 3));
213
8.61M
}
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
8.61M
{
220
8.61M
    int dbitx = data_x & 7;
221
8.61M
    byte sbit = 0x80 >> dbitx;
222
8.61M
    byte sbitmask = 0xff >> dbitx;
223
8.61M
    uint wx = dbitx + w;
224
8.61M
    gx_dda_fixed xl;
225
8.61M
    gx_dda_step_fixed dxx4, dxx8, dxx16, dxx24, dxx32;
226
8.61M
    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
8.61M
    const byte *endp = psrc + (wx >> 3);
240
8.61M
    int endx = ~wx & 7;
241
8.61M
    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
8.61M
    const byte *stop = endp;
249
8.61M
    int stopx;
250
8.61M
    byte stopbit = endbit;
251
8.61M
    byte data;
252
8.61M
    byte one = ~zero;
253
8.61M
    fixed xl0;
254
8.61M
#ifdef PACIFY_VALGRIND
255
8.61M
    byte vbits;
256
8.61M
#endif
257
258
8.61M
    if (w == 0)
259
0
        return;
260
8.61M
    INCS(calls);
261
262
    /* Scan backward for the last transition. */
263
8.61M
    if (stopbit == 0x80)
264
898k
        --stop, stopbit = 1;
265
7.71M
    else
266
7.71M
        stopbit <<= 1;
267
    /* Now (stop, stopbit) give the last bit of the row. */
268
8.61M
#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
8.61M
    VALGRIND_GET_VBITS(stop,&vbits,1);
290
8.61M
    if ((vbits & stopbit)==0) { /* At least our stop bit must be addressable already! */
291
8.61M
      byte zero = 0;
292
8.61M
      VALGRIND_SET_VBITS(stop,&zero,1);
293
8.61M
    }
294
8.61M
#endif
295
8.61M
    {
296
8.61M
        byte stopmask = (-stopbit << 1) & 0xff;
297
8.61M
        byte last = *stop;
298
299
8.61M
        if (stop == psrc)  /* only 1 input byte */
300
7.40M
            stopmask &= sbitmask;
301
8.61M
        if (last & stopbit) {
302
            /* The last bit is a 1: look for a 0-to-1 transition. */
303
848k
            if (~last & stopmask) { /* Transition in last byte. */
304
164k
                last |= stopbit - 1;
305
683k
            } else {   /* No transition in the last byte. */
306
147M
                while (stop > psrc && stop[-1] == 0xff)
307
146M
                    --stop;
308
683k
                if (stop == psrc ||
309
683k
                    (stop == psrc + 1 && !(~*psrc & sbitmask))
310
683k
                    ) {
311
                    /* The input is all 1s.  Clear the row and exit. */
312
335k
                    INCS(all1s);
313
335k
                    fill_row(line, line_x, raster, one);
314
335k
                    goto end;
315
335k
                }
316
347k
                last = *--stop;
317
347k
            }
318
512k
            stopx = byte_bit_run_length_0[byte_reverse_bits[last]] - 1;
319
7.76M
        } else {
320
            /* The last bit is a 0: look for a 1-to-0 transition. */
321
7.76M
            if (last & stopmask) { /* Transition in last byte. */
322
1.08M
                last &= -stopbit;
323
6.68M
            } else {   /* No transition in the last byte. */
324
42.8M
                while (stop > psrc && stop[-1] == 0)
325
36.1M
                    --stop;
326
6.68M
                if (stop == psrc ||
327
6.68M
                    (stop == psrc + 1 && !(*psrc & sbitmask))
328
6.68M
                    ) {
329
                    /* The input is all 0s.  Clear the row and exit. */
330
6.55M
                    INCS(all0s);
331
6.55M
                    fill_row(line, line_x, raster, zero);
332
6.55M
                    goto end;
333
6.55M
                }
334
135k
                last = *--stop;
335
135k
            }
336
1.21M
            stopx = byte_bit_run_length_0[byte_reverse_bits[last ^ 0xff]] - 1;
337
1.21M
        }
338
1.72M
        if (stopx < 0)
339
83.6k
            stopx = 7, ++stop;
340
1.72M
        stopbit = 1 << stopx;
341
1.72M
    }
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
1.72M
    if (x_extent < min_int + 0x100)
350
0
      x_extent += 0x100;
351
352
    /* Set up the DDAs. */
353
1.72M
    xl0 =
354
1.72M
        (x_extent >= 0 ?
355
750k
         fixed_fraction(fixed_pre_pixround(xcur)) :
356
1.72M
         fixed_fraction(fixed_pre_pixround(xcur + x_extent)) - x_extent);
357
1.72M
    xl0 += int2fixed(line_x);
358
    /* We should never get a negative x10 here. If we do, all bets are off. */
359
1.72M
    if (xl0 < 0)
360
0
        xl0 = 0, x_extent = 0;
361
1.72M
    dda_init(xl, xl0, x_extent, w);
362
1.72M
    dxx4 = xl.step;
363
1.72M
    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
1.72M
    dxx8 = dxx4;
369
1.72M
    dda_step_add(dxx4, dxx8);
370
1.72M
    dxx8 = dxx4;
371
1.72M
    dda_step_add(dxx8, dxx4);
372
1.72M
    dxx16 = dxx8;
373
1.72M
    dda_step_add(dxx16, dxx8);
374
1.72M
    dxx24 = dxx16;
375
1.72M
    dda_step_add(dxx24, dxx8);
376
1.72M
    dxx32 = dxx24;
377
1.72M
    dda_step_add(dxx32, dxx8);
378
379
    /*
380
     * Loop invariants:
381
     *      data = *psrc;
382
     *      sbit = 1 << n, 0<=n<=7.
383
     */
384
133M
    for (data = *psrc;;) {
385
133M
        int x0, n, bit;
386
133M
        byte *bp;
387
133M
        static const byte lmasks[9] = {
388
133M
            0xff, 0x7f, 0x3f, 0x1f, 0xf, 7, 3, 1, 0
389
133M
        };
390
133M
        static const byte rmasks[9] = {
391
133M
            0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
392
133M
        };
393
394
133M
        INCS(runs);
395
396
        /* Scan a run of zeros. */
397
133M
        data ^= 0xff;   /* invert */
398
395M
        while (data & sbit) {
399
261M
            dda_next(xl);
400
261M
            sbit >>= 1;
401
261M
            INCS(lbit0);
402
261M
        }
403
133M
        if (!sbit) {   /* Scan a run of zero bytes. */
404
39.6M
sw:     if ((data = psrc[1]) != 0) {
405
35.9M
                psrc++;
406
35.9M
                INCS(byte00);
407
35.9M
            } else if ((data = psrc[2]) != 0) {
408
1.14M
                dda_state_next(xl.state, dxx8);
409
1.14M
                psrc += 2;
410
1.14M
                INCS(byte01);
411
2.52M
            } else if ((data = psrc[3]) != 0) {
412
287k
                dda_state_next(xl.state, dxx16);
413
287k
                psrc += 3;
414
287k
                INCS(byte02);
415
2.23M
            } else if ((data = psrc[4]) != 0) {
416
136k
                dda_state_next(xl.state, dxx24);
417
136k
                psrc += 4;
418
136k
                INCS(byte03);
419
2.10M
            } else {
420
2.10M
                dda_state_next(xl.state, dxx32);
421
2.10M
                psrc += 4;
422
2.10M
                INCS(byte04);
423
2.10M
                goto sw;
424
2.10M
            }
425
37.5M
            if (data > 0xf)
426
33.4M
                sbit = 0x80;
427
4.05M
            else {
428
4.05M
                sbit = 0x08;
429
4.05M
                dda_state_next(xl.state, dxx4);
430
4.05M
            }
431
37.5M
            data ^= 0xff; /* invert */
432
69.7M
            while (data & sbit) {
433
32.2M
                dda_next(xl);
434
32.2M
                sbit >>= 1;
435
32.2M
                INCS(rbit0);
436
32.2M
            }
437
37.5M
        }
438
133M
        x0 = dda_current_fixed2int(xl);
439
133M
        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
512k
            n = fixed2int((int64_t)xl0 + (int64_t)x_extent) - x0;
446
133M
        } else {   /* Scan a run of ones. */
447
            /* We know the current bit is a one. */
448
133M
            data ^= 0xff; /* un-invert */
449
265M
            do {
450
265M
                dda_next(xl);
451
265M
                sbit >>= 1;
452
265M
                INCS(lbit1);
453
265M
            }
454
265M
            while (data & sbit);
455
133M
            if (!sbit) { /* Scan a run of 0xff bytes. */
456
73.8M
                while ((data = *++psrc) == 0xff) {
457
33.2M
                    dda_state_next(xl.state, dxx8);
458
33.2M
                    INCS(byte1);
459
33.2M
                }
460
40.6M
                if (data < 0xf0)
461
34.9M
                    sbit = 0x80;
462
5.71M
                else {
463
5.71M
                    sbit = 0x08;
464
5.71M
                    dda_state_next(xl.state, dxx4);
465
5.71M
                }
466
75.8M
                while (data & sbit) {
467
35.1M
                    dda_next(xl);
468
35.1M
                    sbit >>= 1;
469
35.1M
                    INCS(rbit1);
470
35.1M
                }
471
40.6M
            }
472
133M
            n = dda_current_fixed2int(xl) - x0;
473
133M
        }
474
475
        /* Fill the run in the scan line. */
476
133M
        if (n < 0)
477
1.70M
            x0 += n, n = -n;
478
133M
        bp = line + (x0 >> 3);
479
133M
        bit = x0 & 7;
480
133M
        if ((n += bit) <= 8) {
481
116M
            *bp ^= lmasks[bit] - lmasks[n];
482
116M
            INCS(thin);
483
116M
        } else if ((n -= 8) <= 8) {
484
15.4M
            *bp ^= lmasks[bit];
485
15.4M
            bp[1] ^= rmasks[n];
486
15.4M
            INCS(thin2);
487
15.4M
        } else {
488
2.37M
            *bp++ ^= lmasks[bit];
489
2.37M
            if (n >= 56) {
490
950k
                int nb = n >> 3;
491
492
950k
                memset(bp, one, nb);
493
950k
                bp += nb;
494
950k
                INCS(nwide);
495
950k
                ADDS(bwide, nb);
496
1.42M
            } else {
497
1.42M
                ADDS(bfill, n >> 3);
498
4.53M
                while ((n -= 8) >= 0)
499
3.10M
                    *bp++ = one;
500
1.42M
                INCS(nfill);
501
1.42M
            }
502
2.37M
            *bp ^= rmasks[n & 7];
503
2.37M
        }
504
133M
        if (psrc >= stop && sbit == stopbit)
505
1.72M
            break;
506
133M
    }
507
8.61M
 end:
508
8.61M
    {
509
8.61M
#ifdef PACIFY_VALGRIND
510
8.61M
    VALGRIND_SET_VBITS(stop,&vbits,1);
511
8.61M
#endif
512
8.61M
    }
513
8.61M
}
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
44.3M
{
520
44.3M
    const gx_device_color *pdc0;
521
44.3M
    const gx_device_color *pdc1;
522
44.3M
    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
44.3M
    if (penum->map[0].table.lookup4x1to32[0])
529
283k
        pdc0 = penum->icolor1, pdc1 = penum->icolor0;
530
44.0M
    else
531
44.0M
        pdc0 = penum->icolor0, pdc1 = penum->icolor1;
532
44.3M
    data -= align;
533
44.3M
    dx += align << 3;
534
44.3M
    if (gx_dc_is_pure(pdc0) && gx_dc_is_pure(pdc1)) {
535
        /* Just use copy_mono. */
536
4.57M
        dev_proc_copy_mono((*copy_mono)) =
537
4.57M
            (h == 1 || (raster & (align_bitmap_mod - 1)) == 0 ?
538
4.57M
             dev_proc(dev, copy_mono) : gx_copy_mono_unaligned);
539
4.57M
        return (*copy_mono)
540
4.57M
            (dev, data, dx, raster, gx_no_bitmap_id,
541
4.57M
             x, y, w, h, pdc0->colors.pure, pdc1->colors.pure);
542
4.57M
    }
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
39.7M
    {
550
39.7M
        const gx_device_color *pdc;
551
39.7M
        bool invert;
552
553
39.7M
        if (DC_IS_NULL(pdc1)) {
554
47.6k
            pdc = pdc0;
555
47.6k
            invert = true;
556
39.7M
        } else {
557
39.7M
            if (!DC_IS_NULL(pdc0)) {
558
101k
                int code = gx_device_color_fill_rectangle
559
101k
                    (pdc0, x, y, w, h, dev, lop_default, NULL);
560
561
101k
                if (code < 0)
562
0
                    return code;
563
101k
            }
564
39.7M
            pdc = pdc1;
565
39.7M
            invert = false;
566
39.7M
        }
567
39.7M
        return (*pdc->type->fill_masked)
568
39.7M
            (pdc, data, dx, raster, gx_no_bitmap_id, x, y, w, h,
569
39.7M
             dev, lop_default, invert);
570
571
39.7M
    }
572
39.7M
}
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
18.7M
{
580
18.7M
    dev_proc_copy_mono((*copy_mono)) = dev_proc(dev, copy_mono);
581
18.7M
    const fixed dxx = penum->dxx;
582
18.7M
    const byte *line;
583
18.7M
    uint line_width, line_size;
584
18.7M
    int line_x;
585
18.7M
    fixed xcur = dda_current(penum->dda.pixel0.x);
586
18.7M
    int ix = fixed2int_pixround(xcur);
587
18.7M
    int ixr;
588
18.7M
    const int iy = penum->yci, ih = penum->hci;
589
18.7M
    gx_device_color * const pdc0 = penum->icolor0;
590
18.7M
    gx_device_color * const pdc1 = penum->icolor1;
591
18.7M
    int dy;
592
18.7M
    int code;
593
594
18.7M
    if (h == 0)
595
502k
        return 0;
596
18.2M
    if ((!DC_IS_NULL(pdc0) &&
597
18.2M
         (code = gx_color_load(pdc0, penum->pgs, dev)) < 0) ||
598
18.2M
        (!DC_IS_NULL(pdc1) &&
599
18.2M
         (code = gx_color_load(pdc1, penum->pgs, dev)) < 0)
600
18.2M
        )
601
0
        return code;
602
18.2M
    if (penum->line == 0) { /* A direct BitBlt is possible. */
603
16.8M
        line = buffer;
604
16.8M
        line_size = (w + 7) >> 3;
605
16.8M
        line_width = w;
606
16.8M
        line_x = 0;
607
16.8M
    } else if (copy_mono == mem_mono_copy_mono &&
608
1.48M
               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
1.48M
               (pdc0->colors.pure ^ pdc1->colors.pure) == 1 &&
611
1.48M
               !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
1.48M
               ix >= 0 &&
618
1.48M
               (ixr = fixed2int_pixround(xcur + penum->x_extent.x) - 1) <
619
1.83k
                 dev->width &&
620
1.48M
               iy >= 0 && iy + ih <= dev->height
621
1.48M
        ) {
622
        /* Do the operation directly into the memory device bitmap. */
623
1.83k
        int line_ix;
624
1.83k
        int ib_left = ix >> 3, ib_right = ixr >> 3;
625
1.83k
        byte *scan_line = scan_line_base((gx_device_memory *) dev, iy);
626
1.83k
        byte save_left, save_right, mask;
627
628
1.83k
        line_x = ix & (align_bitmap_mod * 8 - 1);
629
1.83k
        line_ix = ix - line_x;
630
1.83k
        line_size = (ixr >> 3) + 1 - (line_ix >> 3);
631
1.83k
        line_width = ixr + 1 - ix;
632
        /* We must save and restore any unmodified bits in */
633
        /* the two edge bytes. */
634
1.83k
        save_left = scan_line[ib_left];
635
1.83k
        save_right = scan_line[ib_right];
636
1.83k
        image_simple_expand(scan_line + (line_ix >> 3), line_x,
637
1.83k
                            line_size, buffer, data_x, w, xcur,
638
1.83k
                            penum->x_extent.x,
639
1.83k
                            (byte)((pdc0->colors.pure == 0) !=
640
1.83k
                             (penum->map[0].table.lookup4x1to32[0] == 0) ?
641
1.71k
                             0xff : 0));
642
1.83k
        if (ix & 7)
643
1.83k
            mask = (byte) (0xff00 >> (ix & 7)),
644
1.83k
                scan_line[ib_left] =
645
1.83k
                (save_left & mask) + (scan_line[ib_left] & ~mask);
646
1.83k
        if ((ixr + 1) & 7)
647
1.69k
            mask = (byte) (0xff00 >> ((ixr + 1) & 7)),
648
1.69k
                scan_line[ib_right] =
649
1.69k
                (scan_line[ib_right] & mask) + (save_right & ~mask);
650
1.83k
        if (ih <= 1)
651
0
            return 1;
652
        /****** MAY BE UNALIGNED ******/
653
1.83k
        line = scan_line + (line_ix >> 3);
654
15.1k
        for (dy = 1; dy < ih; dy++) {
655
13.3k
            int code = (*copy_mono)
656
13.3k
                (dev, line, line_x, line_size, gx_no_bitmap_id,
657
13.3k
                 ix, iy + dy, line_width, 1,
658
13.3k
                 (gx_color_index)0, (gx_color_index)1);
659
660
13.3k
            if (code < 0)
661
0
                return code;
662
13.3k
        }
663
1.83k
        return 0;
664
1.48M
    } else {
665
1.48M
        line = penum->line;
666
1.48M
        line_size = penum->line_size;
667
1.48M
        line_width = penum->line_width;
668
1.48M
        line_x = ix & (align_bitmap_mod * 8 - 1);
669
1.48M
        image_simple_expand(penum->line, line_x, line_size,
670
1.48M
                            buffer, data_x, w, xcur,
671
1.48M
                            penum->x_extent.x, 0);
672
1.48M
    }
673
674
    /* Finally, transfer the scan line to the device. */
675
18.2M
    if (dxx < 0)
676
267k
        ix -= line_width;
677
56.3M
    for (dy = 0; dy < ih; dy++) {
678
38.0M
        int code = copy_portrait(penum, line, line_x, line_size,
679
38.0M
                                 ix, iy + dy, line_width, 1, dev);
680
681
38.0M
        if (code < 0)
682
0
            return code;
683
38.0M
    }
684
685
18.2M
    return 1;
686
18.2M
}
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
1.23M
{
695
1.23M
    byte *line = penum->line;
696
1.23M
    uint raster = bitmap_raster(penum->line_width);
697
1.23M
    int ix = penum->xci, iw = penum->wci;
698
1.23M
    int xinc, xmod;
699
1.23M
    byte *row;
700
1.23M
    const byte *orig_row = 0;
701
1.23M
    bool y_neg = (is_fneg(penum->matrix.xy));
702
703
1.23M
    if (is_fneg(penum->matrix.yx))
704
410
        ix += iw, iw = -iw, xinc = -1;
705
1.23M
    else
706
1.23M
        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
1.23M
    if (ix != penum->xi_next || h == 0) {
713
204k
        int xi = penum->xi_next;
714
204k
        int code =
715
204k
            (xinc > 0 ?
716
204k
             copy_landscape(penum, penum->line_xy, xi, y_neg, dev) :
717
204k
             copy_landscape(penum, xi, penum->line_xy, y_neg, dev));
718
719
204k
        if (code < 0)
720
0
            return code;
721
204k
        penum->line_xy = penum->xi_next = ix;
722
204k
        if (h == 0)
723
204k
            return code;
724
204k
    }
725
50.7M
    for (; iw != 0; iw -= xinc) {
726
49.7M
        if (xinc < 0)
727
47.8M
            --ix;
728
49.7M
        xmod = ix & 7;
729
49.7M
        row = line + xmod * raster;
730
49.7M
        if (orig_row == 0) {
731
7.12M
            image_simple_expand(row, 0, raster,
732
7.12M
                                buffer, data_x, w,
733
7.12M
                                dda_current(penum->dda.pixel0.y),
734
7.12M
                                penum->x_extent.y, 0);
735
7.12M
            orig_row = row;
736
7.12M
        } else
737
42.6M
            memcpy(row, orig_row, raster);
738
49.7M
        if (xinc > 0) {
739
1.90M
            ++ix;
740
1.90M
            if (xmod == 7) {
741
243k
                int code =
742
243k
                    copy_landscape(penum, penum->line_xy, ix, y_neg, dev);
743
744
243k
                if (code < 0)
745
0
                    return code;
746
243k
                orig_row = 0;
747
243k
                penum->line_xy = ix;
748
243k
            }
749
47.8M
        } else {
750
47.8M
            if (xmod == 0) {
751
5.97M
                int code =
752
5.97M
                    copy_landscape(penum, ix, penum->line_xy, y_neg, dev);
753
754
5.97M
                if (code < 0)
755
0
                    return code;
756
5.97M
                orig_row = 0;
757
5.97M
                penum->line_xy = ix;
758
5.97M
            }
759
47.8M
        }
760
49.7M
    }
761
1.03M
    penum->xi_next = ix;
762
1.03M
    return 0;
763
1.03M
}
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
6.42M
{
770
6.42M
    byte *line = penum->line;
771
6.42M
    uint line_width = penum->line_width;
772
6.42M
    uint raster = bitmap_raster(line_width);
773
6.42M
    byte *flipped = line + raster * 8;
774
6.42M
    int w = x1 - x0;
775
6.42M
    int y = fixed2int_pixround(dda_current(penum->dda.pixel0.y));
776
777
6.42M
    if (w == 0 || line_width == 0)
778
124k
        return 0;
779
    /* Flip the buffered data from raster x 8 to align_bitmap_mod x */
780
    /* line_width. */
781
6.30M
    if (line_width > 0) {
782
6.30M
        int i = (line_width-1)>>3;
783
784
6.30M
#ifdef PACIFY_VALGRIND
785
6.30M
        if (line_width & 7) {
786
6.29M
            memflip8x8_eol(line + i, raster,
787
6.29M
                           flipped + (i << (log2_align_bitmap_mod + 3)),
788
6.29M
                           align_bitmap_mod,
789
6.29M
                           line_width & 7);
790
6.29M
            i--;
791
6.29M
        }
792
6.30M
#endif
793
794
13.8M
        for (; i >= 0; --i)
795
7.58M
            memflip8x8(line + i, raster,
796
7.58M
                       flipped + (i << (log2_align_bitmap_mod + 3)),
797
7.58M
                       align_bitmap_mod);
798
6.30M
    }
799
    /* Transfer the scan lines to the device. */
800
6.30M
    if (w < 0)
801
0
        x0 = x1, w = -w;
802
6.30M
    if (y_neg)
803
6.30M
        y -= line_width;
804
6.30M
    return copy_portrait(penum, flipped, x0 & 7, align_bitmap_mod,
805
6.30M
                         x0, y, w, line_width, dev);
806
6.42M
}