Coverage Report

Created: 2025-11-16 07:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/base/gsbitops.c
Line
Count
Source
1
/* Copyright (C) 2001-2023 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
/* Bitmap filling, copying, and transforming operations */
18
#include "stdio_.h"
19
#include "memory_.h"
20
#include "gdebug.h"
21
#include "gserrors.h"
22
#include "gstypes.h"
23
#include "gsbittab.h"
24
#include "gxbitops.h"
25
#include "gxcindex.h"
26
27
/* ---------------- Bit-oriented operations ---------------- */
28
29
/* Define masks for little-endian operation. */
30
/* masks[i] has the first i bits off and the rest on. */
31
#if !ARCH_IS_BIG_ENDIAN
32
const bits16 mono_copy_masks[17] = {
33
    0xffff, 0xff7f, 0xff3f, 0xff1f,
34
    0xff0f, 0xff07, 0xff03, 0xff01,
35
    0xff00, 0x7f00, 0x3f00, 0x1f00,
36
    0x0f00, 0x0700, 0x0300, 0x0100,
37
    0x0000
38
};
39
const bits32 mono_fill_masks[33] = {
40
#define mask(n)\
41
  (((bits32)~0xff | (0xff >> (n & 7))) << (n & -8))
42
    mask( 0),mask( 1),mask( 2),mask( 3),mask( 4),mask( 5),mask( 6),mask( 7),
43
    mask( 8),mask( 9),mask(10),mask(11),mask(12),mask(13),mask(14),mask(15),
44
    mask(16),mask(17),mask(18),mask(19),mask(20),mask(21),mask(22),mask(23),
45
    mask(24),mask(25),mask(26),mask(27),mask(28),mask(29),mask(30),mask(31),
46
    0
47
#undef mask
48
};
49
#endif
50
51
/* Fill a rectangle of bits with an 8x1 pattern. */
52
/* The pattern argument must consist of the pattern in every byte, */
53
/* e.g., if the desired pattern is 0xaa, the pattern argument must */
54
/* have the value 0xaaaa (if ints are short) or 0xaaaaaaaa. */
55
#undef chunk
56
812M
#define chunk mono_fill_chunk
57
#undef mono_masks
58
692M
#define mono_masks mono_fill_masks
59
void
60
bits_fill_rectangle(byte * dest, int dest_bit, uint draster,
61
                    mono_fill_chunk pattern, int width_bits, int height)
62
345M
{
63
345M
    uint bit;
64
345M
    chunk right_mask;
65
345M
    int line_count = height;
66
345M
    chunk *ptr;
67
345M
    int last_bit;
68
69
345M
#define FOR_EACH_LINE(stat)\
70
694M
        do { stat } while ( inc_ptr(ptr, draster), --line_count )
71
72
345M
    dest += (dest_bit >> 3) & -chunk_align_bytes;
73
345M
    ptr = (chunk *) dest;
74
345M
    bit = dest_bit & chunk_align_bit_mask;
75
345M
    last_bit = width_bits + bit - (chunk_bits + 1);
76
77
345M
    if (last_bit < 0) {   /* <=1 chunk */
78
225M
        set_mono_thin_mask(right_mask, width_bits, bit);
79
225M
        if (pattern == 0)
80
162M
            FOR_EACH_LINE(*ptr &= ~right_mask;);
81
63.5M
        else if (pattern == (mono_fill_chunk)(-1))
82
33.0M
            FOR_EACH_LINE(*ptr |= right_mask;);
83
30.5M
        else
84
30.5M
            FOR_EACH_LINE(
85
225M
                *ptr = (*ptr & ~right_mask) | (pattern & right_mask); );
86
225M
    } else {
87
119M
        chunk mask;
88
119M
        int last = last_bit >> chunk_log2_bits;
89
90
119M
        set_mono_left_mask(mask, bit);
91
119M
        set_mono_right_mask(right_mask, (last_bit & chunk_bit_mask) + 1);
92
119M
        switch (last) {
93
68.3M
            case 0:   /* 2 chunks */
94
68.3M
                if (pattern == 0)
95
38.7M
                    FOR_EACH_LINE(*ptr &= ~mask; ptr[1] &= ~right_mask;);
96
29.6M
                else if (pattern == (mono_fill_chunk)(-1))
97
5.53M
                    FOR_EACH_LINE(*ptr |= mask; ptr[1] |= right_mask;);
98
24.0M
                else
99
24.0M
                    FOR_EACH_LINE(
100
68.3M
                        *ptr = (*ptr & ~mask) | (pattern & mask);
101
68.3M
                        ptr[1] = (ptr[1] & ~right_mask) | (pattern & right_mask); );
102
68.3M
                break;
103
11.2M
            case 1:   /* 3 chunks */
104
11.2M
                if (pattern == 0)
105
5.03M
                    FOR_EACH_LINE( *ptr &= ~mask;
106
11.2M
                                   ptr[1] = 0;
107
11.2M
                                   ptr[2] &= ~right_mask; );
108
6.20M
                else if (pattern == (mono_fill_chunk)(-1))
109
794k
                    FOR_EACH_LINE( *ptr |= mask;
110
6.20M
                                   ptr[1] = ~(chunk) 0;
111
6.20M
                                   ptr[2] |= right_mask; );
112
5.40M
                else
113
5.40M
                    FOR_EACH_LINE( *ptr = (*ptr & ~mask) | (pattern & mask);
114
11.2M
                                    ptr[1] = pattern;
115
11.2M
                                    ptr[2] = (ptr[2] & ~right_mask) | (pattern & right_mask); );
116
11.2M
                break;
117
40.2M
            default:{   /* >3 chunks */
118
40.2M
                    uint byte_count = (last_bit >> 3) & -chunk_bytes;
119
120
40.2M
                    if (pattern == 0)
121
21.7M
                        FOR_EACH_LINE( *ptr &= ~mask;
122
40.2M
                                       memset(ptr + 1, 0, byte_count);
123
40.2M
                                       ptr[last + 1] &= ~right_mask; );
124
18.4M
                    else if (pattern == (mono_fill_chunk)(-1))
125
3.51M
                        FOR_EACH_LINE( *ptr |= mask;
126
18.4M
                                       memset(ptr + 1, 0xff, byte_count);
127
18.4M
                                       ptr[last + 1] |= right_mask; );
128
14.9M
                    else
129
14.9M
                        FOR_EACH_LINE(
130
40.2M
                                *ptr = (*ptr & ~mask) | (pattern & mask);
131
40.2M
                                memset(ptr + 1, (byte) pattern, byte_count);
132
40.2M
                                ptr[last + 1] = (ptr[last + 1] & ~right_mask) |
133
40.2M
                                                (pattern & right_mask);   );
134
40.2M
                }
135
119M
        }
136
119M
    }
137
345M
#undef FOR_EACH_LINE
138
345M
}
139
140
/*
141
 * Similar to bits_fill_rectangle, but with an additional source mask.
142
 * The src_mask variable is 1 for those bits of the original that are
143
 * to be retained. The mask argument must consist of the requisite value
144
 * in every byte, in the same manner as the pattern.
145
 */
146
void
147
bits_fill_rectangle_masked(byte * dest, int dest_bit, uint draster,
148
                    mono_fill_chunk pattern, mono_fill_chunk src_mask,
149
                    int width_bits, int height)
150
819k
{
151
819k
    uint bit;
152
819k
    chunk right_mask;
153
819k
    int line_count = height;
154
819k
    chunk *ptr;
155
819k
    int last_bit;
156
157
819k
#define FOR_EACH_LINE(stat)\
158
7.58M
        do { stat } while ( inc_ptr(ptr, draster), --line_count )
159
160
819k
    dest += (dest_bit >> 3) & -chunk_align_bytes;
161
819k
    ptr = (chunk *) dest;
162
819k
    bit = dest_bit & chunk_align_bit_mask;
163
819k
    last_bit = width_bits + bit - (chunk_bits + 1);
164
165
819k
    if (last_bit < 0) {   /* <=1 chunk */
166
784k
        set_mono_thin_mask(right_mask, width_bits, bit);
167
784k
        right_mask &= ~src_mask;
168
784k
        if (pattern == 0)
169
69.0k
            FOR_EACH_LINE(*ptr &= ~right_mask;);
170
715k
        else if (pattern == (mono_fill_chunk)(-1))
171
55.3k
            FOR_EACH_LINE(*ptr |= right_mask;);
172
660k
        else
173
660k
            FOR_EACH_LINE(
174
784k
                *ptr = (*ptr & ~right_mask) | (pattern & right_mask); );
175
784k
    } else {
176
34.6k
        chunk mask;
177
34.6k
        int last = last_bit >> chunk_log2_bits;
178
179
34.6k
        set_mono_left_mask(mask, bit);
180
34.6k
        set_mono_right_mask(right_mask, (last_bit & chunk_bit_mask) + 1);
181
34.6k
        mask &= ~src_mask;
182
34.6k
        right_mask &= ~src_mask;
183
34.6k
        switch (last) {
184
16.6k
            case 0:   /* 2 chunks */
185
16.6k
                if (pattern == 0)
186
17
                    FOR_EACH_LINE(*ptr &= ~mask; ptr[1] &= ~right_mask;);
187
16.6k
                else if (pattern == (mono_fill_chunk)(-1))
188
0
                    FOR_EACH_LINE(*ptr |= mask; ptr[1] |= right_mask;);
189
16.6k
                else
190
16.6k
                    FOR_EACH_LINE(
191
16.6k
                        *ptr = (*ptr & ~mask) | (pattern & mask);
192
16.6k
                        ptr[1] = (ptr[1] & ~right_mask) | (pattern & right_mask); );
193
16.6k
                break;
194
1.18k
            case 1:   /* 3 chunks */
195
1.18k
                if (pattern == 0)
196
7
                    FOR_EACH_LINE( *ptr &= ~mask;
197
1.18k
                                   ptr[1] &= src_mask;
198
1.18k
                                   ptr[2] &= ~right_mask; );
199
1.17k
                else if (pattern == (mono_fill_chunk)(-1))
200
0
                    FOR_EACH_LINE( *ptr |= mask;
201
1.17k
                                   ptr[1] |= ~src_mask;
202
1.17k
                                   ptr[2] |= right_mask; );
203
1.17k
                else
204
1.17k
                    FOR_EACH_LINE( *ptr = (*ptr & ~mask) | (pattern & mask);
205
1.18k
                                    ptr[1] =(ptr[1] & src_mask) | pattern;
206
1.18k
                                    ptr[2] = (ptr[2] & ~right_mask) | (pattern & right_mask); );
207
1.18k
                break;
208
16.7k
            default:{   /* >3 chunks */
209
16.7k
                    int     i;
210
211
16.7k
                    if (pattern == 0)
212
16.7k
                        FOR_EACH_LINE( *ptr++ &= ~mask;
213
16.7k
                                       for (i = 0; i < last; i++)
214
16.7k
                                           *ptr++ &= src_mask;
215
16.7k
                                       *ptr &= ~right_mask; );
216
28
                    else if (pattern == (mono_fill_chunk)(-1))
217
0
                        FOR_EACH_LINE( *ptr++ |= mask;
218
28
                                       for (i = 0; i < last; i++)
219
28
                                           *ptr++ |= ~src_mask;
220
28
                                        *ptr |= right_mask; );
221
28
                    else
222
28
                        FOR_EACH_LINE(
223
                            /* note: we know (pattern & ~src_mask) == pattern */
224
16.7k
                            *ptr = (*ptr & ~mask) | (pattern & mask);
225
16.7k
                            ++ptr;
226
16.7k
                            for (i = 0; i < last; i++, ptr++)
227
16.7k
                                *ptr = (*ptr & src_mask) | pattern;
228
16.7k
                            *ptr = (*ptr & ~right_mask) | (pattern & right_mask); );
229
16.7k
                }
230
34.6k
        }
231
34.6k
    }
232
819k
#undef FOR_EACH_LINE
233
819k
}
234
235
/* Replicate a bitmap horizontally in place. */
236
void
237
bits_replicate_horizontally(byte * data, uint width, uint height,
238
                 uint raster, uint replicated_width, uint replicated_raster)
239
3.10M
{
240
    /* The current algorithm is extremely inefficient! */
241
3.10M
    const byte *orig_row = data + (height - 1) * raster;
242
3.10M
    byte *tile_row = data + (height - 1) * replicated_raster;
243
3.10M
    uint y;
244
245
3.10M
    if (!(width & 7)) {
246
25.0k
        uint src_bytes = width >> 3;
247
25.0k
        uint dest_bytes = replicated_width >> 3;
248
249
1.02M
        for (y = height; y-- > 0;
250
1.00M
             orig_row -= raster, tile_row -= replicated_raster
251
1.00M
             ) {
252
1.00M
            uint move = src_bytes;
253
1.00M
            const byte *from = orig_row;
254
1.00M
            byte *to = tile_row + dest_bytes - src_bytes;
255
256
1.00M
            memmove(to, from, move);
257
2.00M
            while (to - tile_row >= move) {
258
1.00M
                from = to;
259
1.00M
                to -= move;
260
1.00M
                memmove(to, from, move);
261
1.00M
                move <<= 1;
262
1.00M
            }
263
1.00M
            if (to != tile_row)
264
1.00M
                memmove(tile_row, to, to - tile_row);
265
1.00M
        }
266
3.08M
    } else {
267
        /*
268
         * This algorithm is inefficient, but probably not worth improving.
269
         */
270
3.08M
        uint bit_count = width & (uint)(-(int)width);  /* lowest bit: 1, 2, or 4 */
271
3.08M
        uint left_mask = (0xff00 >> bit_count) & 0xff;
272
273
41.6M
        for (y = height; y-- > 0;
274
38.5M
             orig_row -= raster, tile_row -= replicated_raster
275
38.5M
             ) {
276
38.5M
            uint sx;
277
278
589M
            for (sx = width; sx > 0;) {
279
550M
                uint bits, dx;
280
281
550M
                sx -= bit_count;
282
550M
                bits = (orig_row[sx >> 3] << (sx & 7)) & left_mask;
283
35.3G
                for (dx = sx + replicated_width; dx >= width;) {
284
34.7G
                    byte *dp;
285
34.7G
                    int dbit;
286
287
34.7G
                    dx -= width;
288
34.7G
                    dbit = dx & 7;
289
34.7G
                    dp = tile_row + (dx >> 3);
290
34.7G
                    *dp = (*dp & ~(left_mask >> dbit)) | (bits >> dbit);
291
34.7G
                }
292
550M
            }
293
38.5M
        }
294
3.08M
    }
295
3.10M
}
296
297
/* Replicate a bitmap vertically in place. */
298
void
299
bits_replicate_vertically(byte * data, uint height, uint raster,
300
                          uint replicated_height)
301
3.16k
{
302
3.16k
    byte *dest = data;
303
3.16k
    uint h = replicated_height;
304
3.16k
    uint size = raster * height;
305
306
6.33k
    while (h > height) {
307
3.16k
        memcpy(dest + size, dest, size);
308
3.16k
        dest += size;
309
3.16k
        h -= height;
310
3.16k
    }
311
3.16k
}
312
313
/* Find the bounding box of a bitmap. */
314
/* Assume bits beyond the width are zero. */
315
void
316
bits_bounding_box(const byte * data, uint height, uint raster,
317
                  gs_int_rect * pbox)
318
7.53M
{
319
7.53M
    register const ulong *lp;
320
7.53M
    static const byte first_1[16] = {
321
7.53M
        4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0
322
7.53M
    };
323
7.53M
    static const byte last_1[16] = {
324
7.53M
        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4
325
7.53M
    };
326
327
    /* Count trailing blank rows. */
328
    /* Since the raster is a multiple of sizeof(long), */
329
    /* we don't need to scan by bytes, only by longs. */
330
331
7.53M
    lp = (const ulong *)(data + raster * height);
332
122M
    while ((const byte *)lp > data && !lp[-1])
333
114M
        --lp;
334
7.53M
    if ((const byte *)lp == data) {
335
766k
        pbox->p.x = pbox->q.x = pbox->p.y = pbox->q.y = 0;
336
766k
        return;
337
766k
    }
338
6.77M
    pbox->q.y = height = ((const byte *)lp - data + raster - 1) / raster;
339
340
    /* Count leading blank rows. */
341
342
6.77M
    lp = (const ulong *)data;
343
112M
    while (!*lp)
344
106M
        ++lp;
345
6.77M
    {
346
6.77M
        uint n = ((const byte *)lp - data) / raster;
347
348
6.77M
        pbox->p.y = n;
349
6.77M
        if (n)
350
6.77M
            height -= n, data += n * raster;
351
6.77M
    }
352
353
    /* Find the left and right edges. */
354
    /* We know that the first and last rows are non-blank. */
355
356
6.77M
    {
357
6.77M
        uint raster_longs = raster >> ARCH_LOG2_SIZEOF_LONG;
358
6.77M
        uint left = raster_longs - 1, right = 0;
359
6.77M
        ulong llong = 0, rlong = 0;
360
6.77M
        const byte *q;
361
6.77M
        uint h, n;
362
363
133M
        for (q = data, h = height; h-- > 0; q += raster) { /* Work from the left edge by longs. */
364
126M
            for (lp = (const ulong *)q, n = 0;
365
127M
                 n < left && !*lp; lp++, n++
366
126M
                );
367
126M
            if (n < left)
368
428k
                left = n, llong = *lp;
369
126M
            else
370
126M
                llong |= *lp;
371
            /* Work from the right edge by longs. */
372
126M
            for (lp = (const ulong *)(q + raster - sizeof(long)),
373
126M
                 n = raster_longs - 1;
374
375
143M
                 n > right && !*lp; lp--, n--
376
126M
                );
377
126M
            if (n > right)
378
120k
                right = n, rlong = *lp;
379
126M
            else
380
126M
                rlong |= *lp;
381
126M
        }
382
383
        /* Do binary subdivision on edge longs.  We assume that */
384
        /* sizeof(long) = 4 or 8. */
385
#if ARCH_SIZEOF_LONG > 8
386
        Error_longs_are_too_large();
387
#endif
388
389
#if ARCH_IS_BIG_ENDIAN
390
#  define last_bits(n) ((1L << (n)) - 1)
391
#  define shift_out_last(x,n) ((x) >>= (n))
392
#  define right_justify_last(x,n) DO_NOTHING
393
#else
394
40.6M
#  define last_bits(n) (-1L << ((ARCH_SIZEOF_LONG * 8) - (n)))
395
28.5M
#  define shift_out_last(x,n) ((x) <<= (n))
396
13.5M
#  define right_justify_last(x,n) (x) >>= ((ARCH_SIZEOF_LONG * 8) - (n))
397
6.77M
#endif
398
399
6.77M
        left <<= ARCH_LOG2_SIZEOF_LONG + 3;
400
6.77M
#if ARCH_SIZEOF_LONG == 8
401
6.77M
        if (llong & ~last_bits(32))
402
6.69M
            shift_out_last(llong, 32);
403
72.8k
        else
404
72.8k
            left += 32;
405
6.77M
#endif
406
6.77M
        if (llong & ~last_bits(16))
407
6.39M
            shift_out_last(llong, 16);
408
376k
        else
409
376k
            left += 16;
410
6.77M
        if (llong & ~last_bits(8))
411
2.79M
            shift_out_last(llong, 8);
412
3.97M
        else
413
3.97M
            left += 8;
414
6.77M
        right_justify_last(llong, 8);
415
6.77M
        if (llong & 0xf0)
416
4.59M
            left += first_1[(byte) llong >> 4];
417
2.17M
        else
418
2.17M
            left += first_1[(byte) llong] + 4;
419
420
6.77M
        right <<= ARCH_LOG2_SIZEOF_LONG + 3;
421
6.77M
#if ARCH_SIZEOF_LONG == 8
422
6.77M
        if (!(rlong & last_bits(32)))
423
6.05M
            shift_out_last(rlong, 32);
424
718k
        else
425
718k
            right += 32;
426
6.77M
#endif
427
6.77M
        if (!(rlong & last_bits(16)))
428
3.06M
            shift_out_last(rlong, 16);
429
3.70M
        else
430
3.70M
            right += 16;
431
6.77M
        if (!(rlong & last_bits(8)))
432
3.55M
            shift_out_last(rlong, 8);
433
3.21M
        else
434
3.21M
            right += 8;
435
6.77M
        right_justify_last(rlong, 8);
436
6.77M
        if (!(rlong & 0xf))
437
3.69M
            right += last_1[(byte) rlong >> 4];
438
3.07M
        else
439
3.07M
            right += last_1[(uint) rlong & 0xf] + 4;
440
441
6.77M
        pbox->p.x = left;
442
6.77M
        pbox->q.x = right;
443
6.77M
    }
444
6.77M
}
445
446
/* Extract a plane from a pixmap. */
447
int
448
bits_extract_plane(const bits_plane_t *dest /*write*/,
449
    const bits_plane_t *source /*read*/, int shift, int width, int height)
450
0
{
451
0
    int source_depth = source->depth;
452
0
    int source_bit = source->x * source_depth;
453
0
    const byte *source_row = source->data.read + (source_bit >> 3);
454
0
    int dest_depth = dest->depth;
455
0
    uint plane_mask = (1 << dest_depth) - 1;
456
0
    int dest_bit = dest->x * dest_depth;
457
0
    byte *dest_row = dest->data.write + (dest_bit >> 3);
458
0
    enum {
459
0
        EXTRACT_SLOW = 0,
460
0
        EXTRACT_4_TO_1,
461
0
        EXTRACT_32_TO_8
462
0
    } loop_case = EXTRACT_SLOW;
463
0
    int y;
464
465
0
    source_bit &= 7;
466
0
    dest_bit &= 7;
467
    /* Check for the fast CMYK cases. */
468
0
    if (!(source_bit | dest_bit)) {
469
0
        switch (source_depth) {
470
0
        case 4:
471
0
            loop_case =
472
0
                (dest_depth == 1 && !(source->raster & 3) &&
473
0
                 !(source->x & 1) ? EXTRACT_4_TO_1 :
474
0
                 EXTRACT_SLOW);
475
0
            break;
476
0
        case 32:
477
0
            if (dest_depth == 8 && !(shift & 7)) {
478
0
                loop_case = EXTRACT_32_TO_8;
479
0
                source_row += 3 - (shift >> 3);
480
0
            }
481
0
            break;
482
0
        }
483
0
    }
484
0
    for (y = 0; y < height;
485
0
         ++y, source_row += source->raster, dest_row += dest->raster
486
0
        ) {
487
0
        int x;
488
489
0
        switch (loop_case) {
490
0
        case EXTRACT_4_TO_1: {
491
0
            const byte *src = source_row;
492
0
            byte *dst = dest_row;
493
494
            /* Do groups of 8 pixels. */
495
0
            for (x = width; x >= 8; src += 4, x -= 8) {
496
0
                bits32 sword =
497
0
                    (*(const bits32 *)src >> shift) & 0x11111111;
498
499
0
                *dst++ =
500
0
                    byte_acegbdfh_to_abcdefgh[(
501
#if ARCH_IS_BIG_ENDIAN
502
                    (sword >> 21) | (sword >> 14) | (sword >> 7) | sword
503
#else
504
0
                    (sword << 3) | (sword >> 6) | (sword >> 15) | (sword >> 24)
505
0
#endif
506
0
                                        ) & 0xff];
507
0
            }
508
0
            if (x) {
509
                /* Do the final 1-7 pixels. */
510
0
                uint test = 0x10 << shift, store = 0x80;
511
512
0
                do {
513
0
                    *dst = (*src & test ? *dst | store : *dst & ~store);
514
0
                    if (test >= 0x10)
515
0
                        test >>= 4;
516
0
                    else
517
0
                        test <<= 4, ++src;
518
0
                    store >>= 1;
519
0
                } while (--x > 0);
520
0
            }
521
0
            break;
522
0
        }
523
0
        case EXTRACT_32_TO_8: {
524
0
            const byte *src = source_row;
525
0
            byte *dst = dest_row;
526
527
0
            for (x = width; x > 0; src += 4, --x)
528
0
                *dst++ = *src;
529
0
            break;
530
0
        }
531
0
        default: {
532
0
            const byte *sptr = source_row;
533
0
            int sbit = source_bit;
534
0
            byte *dptr = dest_row;
535
0
            int dbit = dest_bit;
536
0
            byte dbbyte = (dbit ? (byte)(*dptr & (0xff00 >> dbit)) : 0);
537
538
0
            dbbyte = (dbit ? (byte)(*dptr & (0xff00 >> dbit)) : 0);
539
0
            for (x = width; x > 0; --x) {
540
0
                gx_color_index color;
541
0
                uint pixel;
542
543
0
                if (sizeof(color) > 4) {
544
0
                    if (sample_load_next64((uint64_t *)&color, &sptr, &sbit, source_depth) < 0)
545
0
                        return_error(gs_error_rangecheck);
546
0
                }
547
0
                else {
548
0
                    if (sample_load_next32((uint32_t *)&color, &sptr, &sbit, source_depth) < 0)
549
0
                        return_error(gs_error_rangecheck);
550
0
                }
551
0
                pixel = (color >> shift) & plane_mask;
552
0
                if (sample_store_next8(pixel, &dptr, &dbit, dest_depth, &dbbyte) < 0)
553
0
                    return_error(gs_error_rangecheck);
554
0
            }
555
0
            sample_store_flush(dptr, dbit, dbbyte);
556
0
        }
557
0
        }
558
0
    }
559
0
    return 0;
560
0
}
561
562
/* Expand a plane into a pixmap. */
563
int
564
bits_expand_plane(const bits_plane_t *dest /*write*/,
565
    const bits_plane_t *source /*read*/, int shift, int width, int height)
566
0
{
567
    /*
568
     * Eventually we will optimize this just like bits_extract_plane.
569
     */
570
0
    int source_depth = source->depth;
571
0
    int source_bit = source->x * source_depth;
572
0
    const byte *source_row = source->data.read + (source_bit >> 3);
573
0
    int dest_depth = dest->depth;
574
0
    int dest_bit = dest->x * dest_depth;
575
0
    byte *dest_row = dest->data.write + (dest_bit >> 3);
576
0
    enum {
577
0
        EXPAND_SLOW = 0,
578
0
        EXPAND_1_TO_4,
579
0
        EXPAND_8_TO_32
580
0
    } loop_case = EXPAND_SLOW;
581
0
    int y;
582
583
0
    source_bit &= 7;
584
    /* Check for the fast CMYK cases. */
585
0
    if (!(source_bit || (dest_bit & 31) || (dest->raster & 3))) {
586
0
        switch (dest_depth) {
587
0
        case 4:
588
0
            if (source_depth == 1)
589
0
                loop_case = EXPAND_1_TO_4;
590
0
            break;
591
0
        case 32:
592
0
            if (source_depth == 8 && !(shift & 7))
593
0
                loop_case = EXPAND_8_TO_32;
594
0
            break;
595
0
        }
596
0
    }
597
0
    dest_bit &= 7;
598
0
    switch (loop_case) {
599
600
0
    case EXPAND_8_TO_32: {
601
#if ARCH_IS_BIG_ENDIAN
602
#  define word_shift (shift)
603
#else
604
0
        int word_shift = 24 - shift;
605
0
#endif
606
0
        for (y = 0; y < height;
607
0
             ++y, source_row += source->raster, dest_row += dest->raster
608
0
             ) {
609
0
            int x;
610
0
            const byte *src = source_row;
611
0
            bits32 *dst = (bits32 *)dest_row;
612
613
0
            for (x = width; x > 0; --x)
614
0
                *dst++ = (bits32)(*src++) << word_shift;
615
0
        }
616
0
#undef word_shift
617
0
    }
618
0
        break;
619
620
0
    case EXPAND_1_TO_4:
621
0
    default:
622
0
        for (y = 0; y < height;
623
0
             ++y, source_row += source->raster, dest_row += dest->raster
624
0
             ) {
625
0
            int x;
626
0
            const byte *sptr = source_row;
627
0
            int sbit = source_bit;
628
0
            byte *dptr = dest_row;
629
0
            int dbit = dest_bit;
630
0
            byte dbbyte = (dbit ? (byte)(*dptr & (0xff00 >> dbit)) : 0);
631
632
0
            dbbyte = (dbit ? (byte)(*dptr & (0xff00 >> dbit)) : 0);
633
0
            for (x = width; x > 0; --x) {
634
0
                uint color;
635
0
                gx_color_index pixel;
636
637
0
                if (sample_load_next8(&color, &sptr, &sbit, source_depth) < 0)
638
0
                    return_error(gs_error_rangecheck);
639
640
0
                pixel = (gx_color_index)color << shift;
641
0
                if (sizeof(pixel) > 4) {
642
0
                    if (sample_store_next64(pixel, &dptr, &dbit, dest_depth, &dbbyte) < 0)
643
0
                        return_error(gs_error_rangecheck);
644
0
                }
645
0
                else {
646
0
                    if (sample_store_next32(pixel, &dptr, &dbit, dest_depth, &dbbyte) < 0)
647
0
                        return_error(gs_error_rangecheck);
648
0
                }
649
0
            }
650
0
            sample_store_flush(dptr, dbit, dbbyte);
651
0
        }
652
0
        break;
653
654
0
    }
655
0
    return 0;
656
0
}
657
658
/* ---------------- Byte-oriented operations ---------------- */
659
660
/* Fill a rectangle of bytes. */
661
void
662
bytes_fill_rectangle(byte * dest, uint raster,
663
                     byte value, int width_bytes, int height)
664
145M
{
665
358M
    while (height-- > 0) {
666
212M
        memset(dest, value, width_bytes);
667
212M
        dest += raster;
668
212M
    }
669
145M
}
670
671
/* Copy a rectangle of bytes. */
672
void
673
bytes_copy_rectangle(byte * dest, uint dest_raster,
674
             const byte * src, uint src_raster, int width_bytes, int height)
675
56.0M
{
676
112M
    while (height-- > 0) {
677
56.1M
        memcpy(dest, src, width_bytes);
678
56.1M
        src += src_raster;
679
56.1M
        dest += dest_raster;
680
56.1M
    }
681
56.0M
}
682
683
int
684
bytes_rectangle_is_const(const byte * src, uint src_raster,
685
                         int width_bytes, int height)
686
30
{
687
30
    int i;
688
30
    char c;
689
690
30
    if (width_bytes == 0 || height == 0)
691
0
        return -1;
692
30
    c = *src;
693
30
    while (height-- > 0) {
694
30
        const byte *s = src;
695
30
        src += src_raster;
696
682
        for (i = width_bytes; i > 0; i--)
697
682
            if (*s++ != c)
698
30
                return -1;
699
30
    }
700
0
    return c;
701
30
}
702
703
/* Copy a rectangle of bytes zeroing any padding bytes. */
704
void
705
bytes_copy_rectangle_zero_padding(byte * dest, uint dest_raster,
706
             const byte * src, uint src_raster, int width_bytes, int height)
707
6.50M
{
708
6.50M
    int padlen = dest_raster;
709
6.50M
    if (padlen < 0)
710
0
        padlen = -padlen;
711
6.50M
    padlen -= width_bytes;
712
6.50M
    if (padlen == 0)
713
12.8k
    {
714
849k
        while (height-- > 0) {
715
836k
            memcpy(dest, src, width_bytes);
716
836k
            src += src_raster;
717
836k
            dest += dest_raster;
718
836k
        }
719
6.48M
    } else {
720
122M
        while (height-- > 0) {
721
115M
            memcpy(dest, src, width_bytes);
722
115M
            memset(dest+width_bytes, 0, padlen);
723
115M
            src += src_raster;
724
115M
            dest += dest_raster;
725
115M
        }
726
6.48M
    }
727
6.50M
}
728
729
/* Copy a rectangle of bytes zeroing any padding bytes, copying
730
 * the last row with no padding. */
731
void
732
bytes_copy_rectangle_zero_padding_last_short(byte * dest, uint dest_raster,
733
             const byte * src, uint src_raster, int width_bytes, int height)
734
24.1M
{
735
24.1M
    int padlen = dest_raster;
736
24.1M
    if (padlen < 0)
737
0
        padlen = -padlen;
738
24.1M
    padlen -= width_bytes;
739
24.1M
    if (padlen == 0)
740
23.8M
    {
741
309M
        while (height-- > 0) {
742
285M
            memcpy(dest, src, width_bytes);
743
285M
            src += src_raster;
744
285M
            dest += dest_raster;
745
285M
        }
746
23.8M
    } else {
747
5.62M
        while (--height > 0) {
748
5.40M
            memcpy(dest, src, width_bytes);
749
5.40M
            memset(dest+width_bytes, 0, padlen);
750
5.40M
            src += src_raster;
751
5.40M
            dest += dest_raster;
752
5.40M
        }
753
221k
        if (height >= 0)
754
221k
            memcpy(dest, src, width_bytes);
755
221k
    }
756
24.1M
}