Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/base/gdevm8.c
Line
Count
Source (jump to first uncovered line)
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
/* 8-bit-per-pixel "memory" (stored bitmap) device */
17
#include "memory_.h"
18
#include "gx.h"
19
#include "gxdevice.h"
20
#include "gxdevmem.h"           /* semi-public definitions */
21
#include "gdevmem.h"            /* private definitions */
22
23
#define mem_gray8_strip_copy_rop2 mem_gray8_rgb24_strip_copy_rop2
24
25
/* ================ Standard (byte-oriented) device ================ */
26
27
#undef chunk
28
#define chunk byte
29
30
/* Procedures */
31
declare_mem_procs(mem_mapped8_copy_mono, mem_mapped8_copy_color, mem_mapped8_fill_rectangle);
32
33
/* The device descriptor. */
34
const gx_device_memory mem_mapped8_device =
35
    mem_device("image8", 8, 0, mem_dev_initialize_device_procs);
36
37
const gdev_mem_functions gdev_mem_fns_8 =
38
{
39
    mem_mapped_map_rgb_color,
40
    mem_mapped_map_color_rgb,
41
    mem_mapped8_fill_rectangle,
42
    mem_mapped8_copy_mono,
43
    mem_mapped8_copy_color,
44
    gx_default_copy_alpha,
45
    gx_default_strip_tile_rectangle,
46
    mem_gray8_strip_copy_rop2,
47
    mem_get_bits_rectangle
48
};
49
50
/* Convert x coordinate to byte offset in scan line. */
51
#undef x_to_byte
52
3.94M
#define x_to_byte(x) (x)
53
54
/* Fill a rectangle with a color. */
55
static int
56
mem_mapped8_fill_rectangle(gx_device * dev,
57
                           int x, int y, int w, int h, gx_color_index color)
58
137M
{
59
137M
    gx_device_memory * const mdev = (gx_device_memory *)dev;
60
61
137M
    fit_fill(dev, x, y, w, h);
62
123M
    bytes_fill_rectangle(scan_line_base(mdev, y) + x, mdev->raster,
63
123M
                         (byte) color, w, h);
64
123M
    return 0;
65
137M
}
66
67
/* Copy a monochrome bitmap. */
68
/* We split up this procedure because of limitations in the bcc32 compiler. */
69
static void mapped8_copy01(chunk *, const byte *, int, int, uint,
70
                            int, int, byte, byte);
71
static void mapped8_copyN1(chunk *, const byte *, int, int, uint,
72
                            int, int, byte);
73
static void mapped8_copy0N(chunk *, const byte *, int, int, uint,
74
                            int, int, byte);
75
static int
76
mem_mapped8_copy_mono(gx_device * dev,
77
               const byte * base, int sourcex, int sraster, gx_bitmap_id id,
78
        int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
79
3.56M
{
80
3.56M
    gx_device_memory * const mdev = (gx_device_memory *)dev;
81
3.56M
    const byte *line;
82
3.56M
    int first_bit;
83
84
3.56M
    declare_scan_ptr(dest);
85
3.56M
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
86
3.56M
    setup_rect(dest);
87
3.56M
    line = base + (sourcex >> 3);
88
3.56M
    first_bit = sourcex & 7;
89
7.12M
#define is_color(c) ((int)(c) != (int)gx_no_color_index)
90
3.56M
    if (is_color(one)) {
91
3.55M
        if (is_color(zero))
92
308k
            mapped8_copy01(dest, line, first_bit, sraster, draster,
93
308k
                           w, h, (byte) zero, (byte) one);
94
3.24M
        else
95
3.24M
            mapped8_copyN1(dest, line, first_bit, sraster, draster,
96
3.24M
                           w, h, (byte) one);
97
3.55M
    } else if (is_color(zero))
98
7.41k
        mapped8_copy0N(dest, line, first_bit, sraster, draster,
99
7.41k
                       w, h, (byte) zero);
100
3.56M
#undef is_color
101
3.56M
    return 0;
102
3.56M
}
103
/* Halftone coloring */
104
static void
105
mapped8_copy01(chunk * dest, const byte * line, int first_bit,
106
               int sraster, uint draster, int w, int h, byte b0, byte b1)
107
308k
{
108
782k
    while ( h-- > 0 ) {
109
474k
        register byte *pptr = dest;
110
474k
        const byte *sptr = line;
111
474k
        register int sbyte = *sptr++;
112
474k
        register uint bit;
113
474k
        int count = w + first_bit - 8; /* How many bits after first byte */
114
474k
        if (count >= 0) {
115
467k
            switch (first_bit) {
116
447k
                case 0:
117
447k
                    goto enter0;
118
524
                case 1:
119
524
                    goto enter1;
120
1.29k
                case 2:
121
1.29k
                    goto enter2;
122
13.0k
                case 3:
123
13.0k
                    goto enter3;
124
1.14k
                case 4:
125
1.14k
                    goto enter4;
126
996
                case 5:
127
996
                    goto enter5;
128
92
                case 6:
129
92
                    goto enter6;
130
2.32k
                default:
131
2.32k
                    goto enter7;
132
467k
            }
133
61.0M
            do {
134
61.0M
                sbyte = *sptr++;
135
                /* In true gs fashion: Do not be tempted to replace the
136
                 * following lines with: *pptr++ = (condition ? b1 : b0);
137
                 * without good reason as gcc on ARM takes 4 cycles to do that
138
                 * rather than 3 cycles to do the form here. */
139
61.4M
                enter0: if (sbyte & 128) *pptr++ = b1; else *pptr++ = b0;
140
61.4M
                enter1: if (sbyte &  64) *pptr++ = b1; else *pptr++ = b0;
141
61.4M
                enter2: if (sbyte &  32) *pptr++ = b1; else *pptr++ = b0;
142
61.5M
                enter3: if (sbyte &  16) *pptr++ = b1; else *pptr++ = b0;
143
61.5M
                enter4: if (sbyte &   8) *pptr++ = b1; else *pptr++ = b0;
144
61.5M
                enter5: if (sbyte &   4) *pptr++ = b1; else *pptr++ = b0;
145
61.5M
                enter6: if (sbyte &   2) *pptr++ = b1; else *pptr++ = b0;
146
61.5M
                enter7: if (sbyte &   1) *pptr++ = b1; else *pptr++ = b0;
147
61.5M
                count -= 8;
148
61.5M
            } while (count >= 0);
149
467k
            bit = 128;
150
467k
            count += 8;
151
467k
            if (count > 0)
152
306k
                sbyte = *sptr++;
153
467k
        } else {
154
            /* Less than 1 byte to do */
155
6.99k
            bit = 0x80>>first_bit;
156
6.99k
            count += 8-first_bit;
157
6.99k
        }
158
2.03M
        while (count > 0) {
159
1.56M
            if (sbyte & bit) *pptr++ = b1; else *pptr++ = b0;
160
1.56M
            bit >>= 1;
161
1.56M
            count--;
162
1.56M
        }
163
474k
        line += sraster;
164
474k
        inc_ptr(dest, draster);
165
474k
    }
166
308k
}
167
/* Stenciling */
168
static void
169
mapped8_copyN1(chunk * dest, const byte * line, int first_bit,
170
               int sraster, uint draster, int w, int h, byte b1)
171
3.24M
{
172
48.6M
    while ( h-- > 0 ) {
173
45.4M
        register byte *pptr = dest;
174
45.4M
        const byte *sptr = line;
175
45.4M
        register int sbyte = *sptr++;
176
45.4M
        register uint bit;
177
45.4M
        int count = w + first_bit - 8; /* How many bits after first byte */
178
45.4M
        if (count >= 0) {
179
40.2M
            switch (first_bit) {
180
40.1M
                case 0:
181
40.1M
                    goto enter0;
182
25.9k
                case 1:
183
25.9k
                    goto enter1;
184
16.4k
                case 2:
185
16.4k
                    goto enter2;
186
29.5k
                case 3:
187
29.5k
                    goto enter3;
188
21.5k
                case 4:
189
21.5k
                    goto enter4;
190
21.2k
                case 5:
191
21.2k
                    goto enter5;
192
8.78k
                case 6:
193
8.78k
                    goto enter6;
194
27.2k
                default:
195
27.2k
                    goto enter7;
196
40.2M
            }
197
36.6M
            do {
198
36.6M
                sbyte = *sptr++;
199
76.7M
                enter0: if (sbyte & 128)
200
21.8M
                            *pptr = b1;
201
76.7M
                        pptr++;
202
76.8M
                enter1: if (sbyte & 64)
203
22.3M
                            *pptr = b1;
204
76.8M
                        pptr++;
205
76.8M
                enter2: if (sbyte & 32)
206
19.9M
                            *pptr = b1;
207
76.8M
                        pptr++;
208
76.8M
                enter3: if (sbyte & 16)
209
18.7M
                            *pptr = b1;
210
76.8M
                        pptr++;
211
76.8M
                enter4: if (sbyte & 8)
212
18.9M
                            *pptr = b1;
213
76.8M
                        pptr++;
214
76.9M
                enter5: if (sbyte & 4)
215
19.3M
                            *pptr = b1;
216
76.9M
                        pptr++;
217
76.9M
                enter6: if (sbyte & 2)
218
22.1M
                            *pptr = b1;
219
76.9M
                        pptr++;
220
76.9M
                enter7: if (sbyte & 1)
221
30.9M
                            *pptr = b1;
222
76.9M
                        pptr++;
223
76.9M
                count -= 8;
224
76.9M
            } while (count >= 0);
225
40.2M
            bit = 128;
226
40.2M
            count += 8;
227
40.2M
            if (count > 0)
228
                /* read the byte containing the trailing bits */
229
34.4M
                sbyte = *sptr++;
230
40.2M
        } else {
231
            /* Less than 1 byte to do */
232
5.16M
            bit = 0x80>>first_bit;
233
5.16M
            count += 8-first_bit;
234
5.16M
        }
235
180M
        while (count > 0) {
236
135M
            if (sbyte & bit) *pptr = b1;
237
135M
            pptr++;
238
135M
            bit >>= 1;
239
135M
            count--;
240
135M
        }
241
45.4M
        line += sraster;
242
45.4M
        inc_ptr(dest, draster);
243
45.4M
    }
244
3.24M
}
245
/* Reverse stenciling */
246
static void
247
mapped8_copy0N(chunk * dest, const byte * line, int first_bit,
248
               int sraster, uint draster, int w, int h, byte b0)
249
7.41k
{
250
14.8k
    while ( h-- > 0 ) {
251
7.41k
        register byte *pptr = dest;
252
7.41k
        const byte *sptr = line;
253
7.41k
        register int sbyte = *sptr++;
254
7.41k
        register uint bit;
255
7.41k
        int count = w + first_bit - 8; /* How many bits after first byte */
256
7.41k
        if (count >= 0) {
257
7.39k
            switch (first_bit) {
258
4.97k
                case 0:
259
4.97k
                    goto enter0;
260
749
                case 1:
261
749
                    goto enter1;
262
11
                case 2:
263
11
                    goto enter2;
264
5
                case 3:
265
5
                    goto enter3;
266
0
                case 4:
267
0
                    goto enter4;
268
0
                case 5:
269
0
                    goto enter5;
270
15
                case 6:
271
15
                    goto enter6;
272
1.63k
                default:
273
1.63k
                    goto enter7;
274
7.39k
            }
275
1.12M
            do {
276
1.12M
                enter0: if (!(sbyte & 128))
277
71.1k
                            *pptr = b0;
278
1.12M
                        pptr++;
279
1.12M
                enter1: if (!(sbyte & 64))
280
71.3k
                           *pptr = b0;
281
1.12M
                        pptr++;
282
1.12M
                enter2: if (!(sbyte & 32))
283
70.1k
                            *pptr = b0;
284
1.12M
                        pptr++;
285
1.12M
                enter3: if (!(sbyte & 16))
286
71.1k
                            *pptr = b0;
287
1.12M
                        pptr++;
288
1.12M
                enter4: if (!(sbyte & 8))
289
73.5k
                            *pptr = b0;
290
1.12M
                        pptr++;
291
1.12M
                enter5: if (!(sbyte & 4))
292
73.4k
                            *pptr = b0;
293
1.12M
                        pptr++;
294
1.12M
                enter6: if (!(sbyte & 2))
295
72.4k
                            *pptr = b0;
296
1.12M
                        pptr++;
297
1.12M
                enter7: if (!(sbyte & 1))
298
72.4k
                            *pptr = b0;
299
1.12M
                        pptr++;
300
1.12M
                sbyte = *sptr++;
301
1.12M
                count -= 8;
302
1.12M
            } while (count >= 0);
303
7.39k
            bit = 128;
304
7.39k
            count += 8;
305
7.39k
        } else {
306
            /* Less than 1 byte to do */
307
24
            bit = 0x80>>first_bit;
308
24
            count += 8-first_bit;
309
24
        }
310
45.7k
        while (count > 0) {
311
38.3k
            if (!(sbyte & bit)) *pptr = b0;
312
38.3k
            pptr++;
313
38.3k
            bit >>= 1;
314
38.3k
            count--;
315
38.3k
        }
316
7.41k
        line += sraster;
317
7.41k
        inc_ptr(dest, draster);
318
7.41k
    }
319
7.41k
}
320
321
/* Copy a color bitmap. */
322
static int
323
mem_mapped8_copy_color(gx_device * dev,
324
               const byte * base, int sourcex, int sraster, gx_bitmap_id id,
325
                       int x, int y, int w, int h)
326
203k
{
327
203k
    gx_device_memory * const mdev = (gx_device_memory *)dev;
328
329
203k
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
330
127k
    mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h);
331
127k
    return 0;
332
203k
}
333
334
/* ================ "Word"-oriented device ================ */
335
336
/* Note that on a big-endian machine, this is the same as the */
337
/* standard byte-oriented-device. */
338
339
#if !ARCH_IS_BIG_ENDIAN
340
341
/* Procedures */
342
declare_mem_procs(mem8_word_copy_mono, mem8_word_copy_color, mem8_word_fill_rectangle);
343
344
/* Here is the device descriptor. */
345
const gx_device_memory mem_mapped8_word_device =
346
    mem_device("image8w", 8, 0, mem_word_dev_initialize_device_procs);
347
348
const gdev_mem_functions gdev_mem_fns_8w =
349
{
350
    gx_default_rgb_map_rgb_color,
351
    gx_default_rgb_map_color_rgb,
352
    mem8_word_fill_rectangle,
353
    mem8_word_copy_mono,
354
    mem8_word_copy_color,
355
    gx_default_copy_alpha,
356
    gx_default_strip_tile_rectangle,
357
    gx_no_strip_copy_rop2,
358
    mem_word_get_bits_rectangle
359
};
360
361
/* Fill a rectangle with a color. */
362
static int
363
mem8_word_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
364
                         gx_color_index color)
365
0
{
366
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
367
0
    byte *base;
368
0
    size_t raster;
369
370
0
    fit_fill(dev, x, y, w, h);
371
0
    base = scan_line_base(mdev, y);
372
0
    raster = mdev->raster;
373
0
    mem_swap_byte_rect(base, raster, x << 3, w << 3, h, true);
374
0
    bytes_fill_rectangle(base + x, raster, (byte) color, w, h);
375
0
    mem_swap_byte_rect(base, raster, x << 3, w << 3, h, true);
376
0
    return 0;
377
0
}
378
379
/* Copy a bitmap. */
380
static int
381
mem8_word_copy_mono(gx_device * dev,
382
               const byte * base, int sourcex, int sraster, gx_bitmap_id id,
383
        int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
384
0
{
385
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
386
0
    byte *row;
387
0
    size_t raster;
388
0
    bool store;
389
390
0
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
391
0
    row = scan_line_base(mdev, y);
392
0
    raster = mdev->raster;
393
0
    store = (zero != gx_no_color_index && one != gx_no_color_index);
394
0
    mem_swap_byte_rect(row, raster, x << 3, w << 3, h, store);
395
0
    mem_mapped8_copy_mono(dev, base, sourcex, sraster, id,
396
0
                          x, y, w, h, zero, one);
397
0
    mem_swap_byte_rect(row, raster, x << 3, w << 3, h, false);
398
0
    return 0;
399
0
}
400
401
/* Copy a color bitmap. */
402
static int
403
mem8_word_copy_color(gx_device * dev,
404
               const byte * base, int sourcex, int sraster, gx_bitmap_id id,
405
                     int x, int y, int w, int h)
406
0
{
407
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
408
0
    byte *row;
409
0
    size_t raster;
410
411
0
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
412
0
    row = scan_line_base(mdev, y);
413
0
    raster = mdev->raster;
414
0
    mem_swap_byte_rect(row, raster, x << 3, w << 3, h, true);
415
0
    mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h);
416
0
    mem_swap_byte_rect(row, raster, x << 3, w << 3, h, false);
417
0
    return 0;
418
0
}
419
420
#endif /* !ARCH_IS_BIG_ENDIAN */