Coverage Report

Created: 2025-06-10 07:17

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