Coverage Report

Created: 2025-06-24 07:01

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