Coverage Report

Created: 2025-06-10 06:56

/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
5.50k
#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
4.26M
{
59
4.26M
    gx_device_memory * const mdev = (gx_device_memory *)dev;
60
61
4.26M
    fit_fill(dev, x, y, w, h);
62
3.23M
    bytes_fill_rectangle(scan_line_base(mdev, y) + x, mdev->raster,
63
3.23M
                         (byte) color, w, h);
64
3.23M
    return 0;
65
4.26M
}
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
0
{
80
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
81
0
    const byte *line;
82
0
    int first_bit;
83
84
0
    declare_scan_ptr(dest);
85
0
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
86
0
    setup_rect(dest);
87
0
    line = base + (sourcex >> 3);
88
0
    first_bit = sourcex & 7;
89
0
#define is_color(c) ((int)(c) != (int)gx_no_color_index)
90
0
    if (is_color(one)) {
91
0
        if (is_color(zero))
92
0
            mapped8_copy01(dest, line, first_bit, sraster, draster,
93
0
                           w, h, (byte) zero, (byte) one);
94
0
        else
95
0
            mapped8_copyN1(dest, line, first_bit, sraster, draster,
96
0
                           w, h, (byte) one);
97
0
    } else if (is_color(zero))
98
0
        mapped8_copy0N(dest, line, first_bit, sraster, draster,
99
0
                       w, h, (byte) zero);
100
0
#undef is_color
101
0
    return 0;
102
0
}
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
0
{
108
0
    while ( h-- > 0 ) {
109
0
        register byte *pptr = dest;
110
0
        const byte *sptr = line;
111
0
        register int sbyte = *sptr++;
112
0
        register uint bit;
113
0
        int count = w + first_bit - 8; /* How many bits after first byte */
114
0
        if (count >= 0) {
115
0
            switch (first_bit) {
116
0
                case 0:
117
0
                    goto enter0;
118
0
                case 1:
119
0
                    goto enter1;
120
0
                case 2:
121
0
                    goto enter2;
122
0
                case 3:
123
0
                    goto enter3;
124
0
                case 4:
125
0
                    goto enter4;
126
0
                case 5:
127
0
                    goto enter5;
128
0
                case 6:
129
0
                    goto enter6;
130
0
                default:
131
0
                    goto enter7;
132
0
            }
133
0
            do {
134
0
                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
0
                enter0: if (sbyte & 128) *pptr++ = b1; else *pptr++ = b0;
140
0
                enter1: if (sbyte &  64) *pptr++ = b1; else *pptr++ = b0;
141
0
                enter2: if (sbyte &  32) *pptr++ = b1; else *pptr++ = b0;
142
0
                enter3: if (sbyte &  16) *pptr++ = b1; else *pptr++ = b0;
143
0
                enter4: if (sbyte &   8) *pptr++ = b1; else *pptr++ = b0;
144
0
                enter5: if (sbyte &   4) *pptr++ = b1; else *pptr++ = b0;
145
0
                enter6: if (sbyte &   2) *pptr++ = b1; else *pptr++ = b0;
146
0
                enter7: if (sbyte &   1) *pptr++ = b1; else *pptr++ = b0;
147
0
                count -= 8;
148
0
            } while (count >= 0);
149
0
            bit = 128;
150
0
            count += 8;
151
0
            if (count > 0)
152
0
                sbyte = *sptr++;
153
0
        } else {
154
            /* Less than 1 byte to do */
155
0
            bit = 0x80>>first_bit;
156
0
            count += 8-first_bit;
157
0
        }
158
0
        while (count > 0) {
159
0
            if (sbyte & bit) *pptr++ = b1; else *pptr++ = b0;
160
0
            bit >>= 1;
161
0
            count--;
162
0
        }
163
0
        line += sraster;
164
0
        inc_ptr(dest, draster);
165
0
    }
166
0
}
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
0
{
172
0
    while ( h-- > 0 ) {
173
0
        register byte *pptr = dest;
174
0
        const byte *sptr = line;
175
0
        register int sbyte = *sptr++;
176
0
        register uint bit;
177
0
        int count = w + first_bit - 8; /* How many bits after first byte */
178
0
        if (count >= 0) {
179
0
            switch (first_bit) {
180
0
                case 0:
181
0
                    goto enter0;
182
0
                case 1:
183
0
                    goto enter1;
184
0
                case 2:
185
0
                    goto enter2;
186
0
                case 3:
187
0
                    goto enter3;
188
0
                case 4:
189
0
                    goto enter4;
190
0
                case 5:
191
0
                    goto enter5;
192
0
                case 6:
193
0
                    goto enter6;
194
0
                default:
195
0
                    goto enter7;
196
0
            }
197
0
            do {
198
0
                sbyte = *sptr++;
199
0
                enter0: if (sbyte & 128)
200
0
                            *pptr = b1;
201
0
                        pptr++;
202
0
                enter1: if (sbyte & 64)
203
0
                            *pptr = b1;
204
0
                        pptr++;
205
0
                enter2: if (sbyte & 32)
206
0
                            *pptr = b1;
207
0
                        pptr++;
208
0
                enter3: if (sbyte & 16)
209
0
                            *pptr = b1;
210
0
                        pptr++;
211
0
                enter4: if (sbyte & 8)
212
0
                            *pptr = b1;
213
0
                        pptr++;
214
0
                enter5: if (sbyte & 4)
215
0
                            *pptr = b1;
216
0
                        pptr++;
217
0
                enter6: if (sbyte & 2)
218
0
                            *pptr = b1;
219
0
                        pptr++;
220
0
                enter7: if (sbyte & 1)
221
0
                            *pptr = b1;
222
0
                        pptr++;
223
0
                count -= 8;
224
0
            } while (count >= 0);
225
0
            bit = 128;
226
0
            count += 8;
227
0
            if (count > 0)
228
                /* read the byte containing the trailing bits */
229
0
                sbyte = *sptr++;
230
0
        } else {
231
            /* Less than 1 byte to do */
232
0
            bit = 0x80>>first_bit;
233
0
            count += 8-first_bit;
234
0
        }
235
0
        while (count > 0) {
236
0
            if (sbyte & bit) *pptr = b1;
237
0
            pptr++;
238
0
            bit >>= 1;
239
0
            count--;
240
0
        }
241
0
        line += sraster;
242
0
        inc_ptr(dest, draster);
243
0
    }
244
0
}
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
0
{
250
0
    while ( h-- > 0 ) {
251
0
        register byte *pptr = dest;
252
0
        const byte *sptr = line;
253
0
        register int sbyte = *sptr++;
254
0
        register uint bit;
255
0
        int count = w + first_bit - 8; /* How many bits after first byte */
256
0
        if (count >= 0) {
257
0
            switch (first_bit) {
258
0
                case 0:
259
0
                    goto enter0;
260
0
                case 1:
261
0
                    goto enter1;
262
0
                case 2:
263
0
                    goto enter2;
264
0
                case 3:
265
0
                    goto enter3;
266
0
                case 4:
267
0
                    goto enter4;
268
0
                case 5:
269
0
                    goto enter5;
270
0
                case 6:
271
0
                    goto enter6;
272
0
                default:
273
0
                    goto enter7;
274
0
            }
275
0
            do {
276
0
                enter0: if (!(sbyte & 128))
277
0
                            *pptr = b0;
278
0
                        pptr++;
279
0
                enter1: if (!(sbyte & 64))
280
0
                           *pptr = b0;
281
0
                        pptr++;
282
0
                enter2: if (!(sbyte & 32))
283
0
                            *pptr = b0;
284
0
                        pptr++;
285
0
                enter3: if (!(sbyte & 16))
286
0
                            *pptr = b0;
287
0
                        pptr++;
288
0
                enter4: if (!(sbyte & 8))
289
0
                            *pptr = b0;
290
0
                        pptr++;
291
0
                enter5: if (!(sbyte & 4))
292
0
                            *pptr = b0;
293
0
                        pptr++;
294
0
                enter6: if (!(sbyte & 2))
295
0
                            *pptr = b0;
296
0
                        pptr++;
297
0
                enter7: if (!(sbyte & 1))
298
0
                            *pptr = b0;
299
0
                        pptr++;
300
0
                sbyte = *sptr++;
301
0
                count -= 8;
302
0
            } while (count >= 0);
303
0
            bit = 128;
304
0
            count += 8;
305
0
        } else {
306
            /* Less than 1 byte to do */
307
0
            bit = 0x80>>first_bit;
308
0
            count += 8-first_bit;
309
0
        }
310
0
        while (count > 0) {
311
0
            if (!(sbyte & bit)) *pptr = b0;
312
0
            pptr++;
313
0
            bit >>= 1;
314
0
            count--;
315
0
        }
316
0
        line += sraster;
317
0
        inc_ptr(dest, draster);
318
0
    }
319
0
}
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
1.83k
{
327
1.83k
    gx_device_memory * const mdev = (gx_device_memory *)dev;
328
329
1.83k
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
330
1.83k
    mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h);
331
1.83k
    return 0;
332
1.83k
}
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 */