Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/base/gdevm8.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2022 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.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, 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
22.0k
#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
10.3M
{
59
10.3M
    gx_device_memory * const mdev = (gx_device_memory *)dev;
60
61
10.3M
    fit_fill(dev, x, y, w, h);
62
9.89M
    bytes_fill_rectangle(scan_line_base(mdev, y) + x, mdev->raster,
63
9.89M
                         (byte) color, w, h);
64
9.89M
    return 0;
65
10.3M
}
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
16.4k
{
80
16.4k
    gx_device_memory * const mdev = (gx_device_memory *)dev;
81
16.4k
    const byte *line;
82
16.4k
    int first_bit;
83
84
16.4k
    declare_scan_ptr(dest);
85
16.4k
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
86
16.2k
    setup_rect(dest);
87
16.2k
    line = base + (sourcex >> 3);
88
16.2k
    first_bit = sourcex & 7;
89
32.4k
#define is_color(c) ((int)(c) != (int)gx_no_color_index)
90
16.2k
    if (is_color(one)) {
91
13.9k
        if (is_color(zero))
92
264
            mapped8_copy01(dest, line, first_bit, sraster, draster,
93
264
                           w, h, (byte) zero, (byte) one);
94
13.7k
        else
95
13.7k
            mapped8_copyN1(dest, line, first_bit, sraster, draster,
96
13.7k
                           w, h, (byte) one);
97
13.9k
    } else if (is_color(zero))
98
2.26k
        mapped8_copy0N(dest, line, first_bit, sraster, draster,
99
2.26k
                       w, h, (byte) zero);
100
16.2k
#undef is_color
101
16.2k
    return 0;
102
16.4k
}
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
264
{
108
528
    while ( h-- > 0 ) {
109
264
        register byte *pptr = dest;
110
264
        const byte *sptr = line;
111
264
        register int sbyte = *sptr++;
112
264
        register uint bit;
113
264
        int count = w + first_bit - 8; /* How many bits after first byte */
114
264
        if (count >= 0) {
115
264
            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
264
                case 4:
125
264
                    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
264
            }
133
8.44k
            do {
134
8.44k
                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
8.44k
                enter0: if (sbyte & 128) *pptr++ = b1; else *pptr++ = b0;
140
8.44k
                enter1: if (sbyte &  64) *pptr++ = b1; else *pptr++ = b0;
141
8.44k
                enter2: if (sbyte &  32) *pptr++ = b1; else *pptr++ = b0;
142
8.44k
                enter3: if (sbyte &  16) *pptr++ = b1; else *pptr++ = b0;
143
8.71k
                enter4: if (sbyte &   8) *pptr++ = b1; else *pptr++ = b0;
144
8.71k
                enter5: if (sbyte &   4) *pptr++ = b1; else *pptr++ = b0;
145
8.71k
                enter6: if (sbyte &   2) *pptr++ = b1; else *pptr++ = b0;
146
8.71k
                enter7: if (sbyte &   1) *pptr++ = b1; else *pptr++ = b0;
147
8.71k
                count -= 8;
148
8.71k
            } while (count >= 0);
149
264
            bit = 128;
150
264
            count += 8;
151
264
            if (count > 0)
152
264
                sbyte = *sptr++;
153
264
        } else {
154
            /* Less than 1 byte to do */
155
0
            bit = 0x80>>first_bit;
156
0
            count += 8-first_bit;
157
0
        }
158
1.32k
        while (count > 0) {
159
1.05k
            if (sbyte & bit) *pptr++ = b1; else *pptr++ = b0;
160
1.05k
            bit >>= 1;
161
1.05k
            count--;
162
1.05k
        }
163
264
        line += sraster;
164
264
        inc_ptr(dest, draster);
165
264
    }
166
264
}
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
13.7k
{
172
226k
    while ( h-- > 0 ) {
173
213k
        register byte *pptr = dest;
174
213k
        const byte *sptr = line;
175
213k
        register int sbyte = *sptr++;
176
213k
        register uint bit;
177
213k
        int count = w + first_bit - 8; /* How many bits after first byte */
178
213k
        if (count >= 0) {
179
207k
            switch (first_bit) {
180
207k
                case 0:
181
207k
                    goto enter0;
182
0
                case 1:
183
0
                    goto enter1;
184
0
                case 2:
185
0
                    goto enter2;
186
78
                case 3:
187
78
                    goto enter3;
188
26
                case 4:
189
26
                    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
207k
            }
197
2.38M
            do {
198
2.38M
                sbyte = *sptr++;
199
2.58M
                enter0: if (sbyte & 128)
200
971k
                            *pptr = b1;
201
2.58M
                        pptr++;
202
2.58M
                enter1: if (sbyte & 64)
203
994k
                            *pptr = b1;
204
2.58M
                        pptr++;
205
2.58M
                enter2: if (sbyte & 32)
206
1.00M
                            *pptr = b1;
207
2.58M
                        pptr++;
208
2.58M
                enter3: if (sbyte & 16)
209
1.01M
                            *pptr = b1;
210
2.58M
                        pptr++;
211
2.58M
                enter4: if (sbyte & 8)
212
1.02M
                            *pptr = b1;
213
2.58M
                        pptr++;
214
2.58M
                enter5: if (sbyte & 4)
215
1.02M
                            *pptr = b1;
216
2.58M
                        pptr++;
217
2.58M
                enter6: if (sbyte & 2)
218
1.04M
                            *pptr = b1;
219
2.58M
                        pptr++;
220
2.58M
                enter7: if (sbyte & 1)
221
1.04M
                            *pptr = b1;
222
2.58M
                        pptr++;
223
2.58M
                count -= 8;
224
2.58M
            } while (count >= 0);
225
207k
            bit = 128;
226
207k
            count += 8;
227
207k
            if (count > 0)
228
                /* read the byte containing the trailing bits */
229
192k
                sbyte = *sptr++;
230
207k
        } else {
231
            /* Less than 1 byte to do */
232
5.82k
            bit = 0x80>>first_bit;
233
5.82k
            count += 8-first_bit;
234
5.82k
        }
235
1.07M
        while (count > 0) {
236
862k
            if (sbyte & bit) *pptr = b1;
237
862k
            pptr++;
238
862k
            bit >>= 1;
239
862k
            count--;
240
862k
        }
241
213k
        line += sraster;
242
213k
        inc_ptr(dest, draster);
243
213k
    }
244
13.7k
}
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
2.26k
{
250
4.53k
    while ( h-- > 0 ) {
251
2.26k
        register byte *pptr = dest;
252
2.26k
        const byte *sptr = line;
253
2.26k
        register int sbyte = *sptr++;
254
2.26k
        register uint bit;
255
2.26k
        int count = w + first_bit - 8; /* How many bits after first byte */
256
2.26k
        if (count >= 0) {
257
2.26k
            switch (first_bit) {
258
0
                case 0:
259
0
                    goto enter0;
260
2.26k
                case 1:
261
2.26k
                    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
2.26k
            }
275
20.4k
            do {
276
20.4k
                enter0: if (!(sbyte & 128))
277
14.4k
                            *pptr = b0;
278
20.4k
                        pptr++;
279
22.6k
                enter1: if (!(sbyte & 64))
280
15.7k
                           *pptr = b0;
281
22.6k
                        pptr++;
282
22.6k
                enter2: if (!(sbyte & 32))
283
16.8k
                            *pptr = b0;
284
22.6k
                        pptr++;
285
22.6k
                enter3: if (!(sbyte & 16))
286
16.3k
                            *pptr = b0;
287
22.6k
                        pptr++;
288
22.6k
                enter4: if (!(sbyte & 8))
289
16.5k
                            *pptr = b0;
290
22.6k
                        pptr++;
291
22.6k
                enter5: if (!(sbyte & 4))
292
17.3k
                            *pptr = b0;
293
22.6k
                        pptr++;
294
22.6k
                enter6: if (!(sbyte & 2))
295
15.2k
                            *pptr = b0;
296
22.6k
                        pptr++;
297
22.6k
                enter7: if (!(sbyte & 1))
298
16.3k
                            *pptr = b0;
299
22.6k
                        pptr++;
300
22.6k
                sbyte = *sptr++;
301
22.6k
                count -= 8;
302
22.6k
            } while (count >= 0);
303
2.26k
            bit = 128;
304
2.26k
            count += 8;
305
2.26k
        } else {
306
            /* Less than 1 byte to do */
307
0
            bit = 0x80>>first_bit;
308
0
            count += 8-first_bit;
309
0
        }
310
18.1k
        while (count > 0) {
311
15.8k
            if (!(sbyte & bit)) *pptr = b0;
312
15.8k
            pptr++;
313
15.8k
            bit >>= 1;
314
15.8k
            count--;
315
15.8k
        }
316
2.26k
        line += sraster;
317
2.26k
        inc_ptr(dest, draster);
318
2.26k
    }
319
2.26k
}
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.94k
{
327
1.94k
    gx_device_memory * const mdev = (gx_device_memory *)dev;
328
329
1.94k
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
330
1.94k
    mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h);
331
1.94k
    return 0;
332
1.94k
}
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
    uint 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
    uint 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
    uint 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 */