Coverage Report

Created: 2025-06-10 06:49

/src/ghostpdl/base/gdevm64.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
/* 64-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 debugging statistics. */
24
/* #define COLLECT_STATS_MEM64 */
25
26
#ifdef COLLECT_STATS_MEM64
27
struct stats_mem64_s {
28
    long
29
        fill, fwide, fgray[101], fsetc, fcolor[101], fnarrow[5],
30
        fprevc[257];
31
    double ftotal;
32
} stats_mem64;
33
static int prev_count = 0;
34
static gx_color_index prev_colors[256];
35
# define INCR(v) (++(stats_mem64.v))
36
#else
37
0
# define INCR(v) DO_NOTHING
38
#endif
39
40
/* ================ Standard (byte-oriented) device ================ */
41
42
#undef chunk
43
#define chunk byte
44
0
#define PIXEL_SIZE 2
45
46
/* Procedures */
47
declare_mem_procs(mem_true64_copy_mono, mem_true64_copy_color, mem_true64_fill_rectangle);
48
49
/* The device descriptor. */
50
const gx_device_memory mem_true64_device =
51
    mem_device("image64", 64, 0, mem_dev_initialize_device_procs);
52
53
const gdev_mem_functions gdev_mem_fns_64 =
54
{
55
    gx_default_rgb_map_rgb_color,
56
    gx_default_rgb_map_color_rgb,
57
    mem_true64_fill_rectangle,
58
    mem_true64_copy_mono,
59
    mem_true64_copy_color,
60
    gx_default_copy_alpha,
61
    gx_default_strip_tile_rectangle,
62
    mem_default_strip_copy_rop2,
63
    mem_get_bits_rectangle
64
};
65
66
/* Convert x coordinate to byte offset in scan line. */
67
#undef x_to_byte
68
0
#define x_to_byte(x) ((x) << 3)
69
70
/* Put a 64-bit color into the bitmap. */
71
#define put8(ptr, abcd, efgh)\
72
0
        (ptr)[0] = abcd, (ptr)[1] = efgh
73
/* Free variables: [m]dev, abcd, degh. */
74
#if ARCH_IS_BIG_ENDIAN
75
/* Unpack a color into 32 bit chunks. */
76
#  define declare_unpack_color(abcd, efgh, color)\
77
        bits32 abcd = (bits32)((color) >> 32);\
78
        bits32 efgh = (bits32)(color)
79
#else
80
/* Unpack a color into 32 bit chunks. */
81
#  define declare_unpack_color(abcd, efgh, color)\
82
0
        bits32 abcd = (bits32)((0x000000ff & (((color) >> 28) >> 28)) |\
83
0
                               (0x0000ff00 & (((color) >> 24) >> 16)) |\
84
0
                               (0x00ff0000 & ((color) >> 24)) |\
85
0
                               (0xff000000 & ((color) >> 8)));\
86
0
        bits32 efgh = (bits32)((0x000000ff & ((color) >> 24)) |\
87
0
                               (0x0000ff00 & ((color) >> 8)) |\
88
0
                               (0x00ff0000 & ((color) << 8)) |\
89
0
                               (0xff000000 & ((color) << 24)))
90
#endif
91
0
#define dest32 ((bits32 *)dest)
92
93
/* Fill a rectangle with a color. */
94
static int
95
mem_true64_fill_rectangle(gx_device * dev,
96
                          int x, int y, int w, int h, gx_color_index color)
97
0
{
98
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
99
0
    declare_scan_ptr(dest);
100
0
    declare_unpack_color(abcd, efgh, color);
101
102
    /*
103
     * In order to avoid testing w > 0 and h > 0 twice, we defer
104
     * executing setup_rect, and use fit_fill_xywh instead of
105
     * fit_fill.
106
     */
107
0
    fit_fill_xywh(dev, x, y, w, h);
108
0
    INCR(fill);
109
#ifdef COLLECT_STATS_MEM64
110
    stats_mem64.ftotal += w;
111
#endif
112
0
    if (h <= 0)
113
0
        return 0;
114
0
    if (w >= 5) {
115
0
        INCR(fwide);
116
0
        setup_rect(dest);
117
#ifdef COLLECT_STATS_MEM64
118
        {
119
            int ci;
120
            for (ci = 0; ci < prev_count; ++ci)
121
                if (prev_colors[ci] == color)
122
                    break;
123
            INCR(fprevc[ci]);
124
            if (ci == prev_count) {
125
                if (ci < countof(prev_colors))
126
                    ++prev_count;
127
                else
128
                    --ci;
129
            }
130
            if (ci) {
131
                memmove(&prev_colors[1], &prev_colors[0],
132
                        ci * sizeof(prev_colors[0]));
133
                prev_colors[0] = color;
134
            }
135
        }
136
#endif
137
0
        INCR(fcolor[min(w, 100)]);
138
0
        while (h-- > 0) {
139
0
            register bits32 *pptr = dest32;
140
0
            int w1 = w;
141
142
0
            while (w1 >= 4) {
143
0
                put8(pptr, abcd, efgh);
144
0
                put8(pptr + 2, abcd, efgh);
145
0
                put8(pptr + 4, abcd, efgh);
146
0
                put8(pptr + 6, abcd, efgh);
147
0
                pptr += 4 * PIXEL_SIZE;
148
0
                w1 -= 4;
149
0
            }
150
0
            switch (w1) {
151
0
                case 1:
152
0
                    put8(pptr, abcd, efgh);
153
0
                    break;
154
0
                case 2:
155
0
                    put8(pptr, abcd, efgh);
156
0
                    put8(pptr + 2, abcd, efgh);
157
0
                    break;
158
0
                case 3:
159
0
                    put8(pptr, abcd, efgh);
160
0
                    put8(pptr + 2, abcd, efgh);
161
0
                    put8(pptr + 4, abcd, efgh);
162
0
                    break;
163
0
                case 0:
164
0
                    ;
165
0
            }
166
0
            inc_ptr(dest, draster);
167
0
        }
168
0
    } else {   /* w < 5 */
169
0
        INCR(fnarrow[max(w, 0)]);
170
0
        setup_rect(dest);
171
0
        switch (w) {
172
0
            case 4:
173
0
                do {
174
0
                    put8(dest32, abcd, efgh);
175
0
                    put8(dest32 + 2, abcd, efgh);
176
0
                    put8(dest32 + 4, abcd, efgh);
177
0
                    put8(dest32 + 6, abcd, efgh);
178
0
                    inc_ptr(dest, draster);
179
0
                }
180
0
                while (--h);
181
0
                break;
182
0
            case 3:
183
0
                do {
184
0
                    put8(dest32, abcd, efgh);
185
0
                    put8(dest32 + 2, abcd, efgh);
186
0
                    put8(dest32 + 4, abcd, efgh);
187
0
                    inc_ptr(dest, draster);
188
0
                }
189
0
                while (--h);
190
0
                break;
191
0
            case 2:
192
0
                do {
193
0
                    put8(dest32, abcd, efgh);
194
0
                    put8(dest32 + 2, abcd, efgh);
195
0
                    inc_ptr(dest, draster);
196
0
                }
197
0
                while (--h);
198
0
                break;
199
0
            case 1:
200
0
                do {
201
0
                    put8(dest32, abcd, efgh);
202
0
                    inc_ptr(dest, draster);
203
0
                }
204
0
                while (--h);
205
0
                break;
206
0
            case 0:
207
0
            default:
208
0
                ;
209
0
        }
210
0
    }
211
0
    return 0;
212
0
}
213
214
/* Copy a monochrome bitmap. */
215
static int
216
mem_true64_copy_mono(gx_device * dev,
217
               const byte * base, int sourcex, int sraster, gx_bitmap_id id,
218
        int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
219
0
{
220
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
221
0
    const byte *line;
222
0
    int sbit;
223
0
    int first_bit;
224
225
0
    declare_scan_ptr(dest);
226
227
0
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
228
0
    setup_rect(dest);
229
0
    line = base + (sourcex >> 3);
230
0
    sbit = sourcex & 7;
231
0
    first_bit = 0x80 >> sbit;
232
0
    if (zero != gx_no_color_index) { /* Loop for halftones or inverted masks */
233
        /* (never used). */
234
0
        declare_unpack_color(abcd0, efgh0, zero);
235
0
        declare_unpack_color(abcd1, efgh1, one);
236
0
        while (h-- > 0) {
237
0
            register bits32 *pptr = dest32;
238
0
            const byte *sptr = line;
239
0
            register int sbyte = *sptr++;
240
0
            register int bit = first_bit;
241
0
            int count = w;
242
243
0
            do {
244
0
                if (sbyte & bit) {
245
0
                    if (one != gx_no_color_index)
246
0
                        put8(pptr, abcd1, efgh1);
247
0
                } else
248
0
                    put8(pptr, abcd0, efgh0);
249
0
                pptr += PIXEL_SIZE;
250
0
                if ((bit >>= 1) == 0)
251
0
                    bit = 0x80, sbyte = *sptr++;
252
0
            }
253
0
            while (--count > 0);
254
0
            line += sraster;
255
0
            inc_ptr(dest, draster);
256
0
        }
257
0
    } else if (one != gx_no_color_index) { /* Loop for character and pattern masks. */
258
        /* This is used heavily. */
259
0
        declare_unpack_color(abcd1, efgh1, one);
260
0
        int first_mask = first_bit << 1;
261
0
        int first_count, first_skip;
262
263
0
        if (sbit + w > 8)
264
0
            first_mask -= 1,
265
0
                first_count = 8 - sbit;
266
0
        else
267
0
            first_mask -= first_mask >> w,
268
0
                first_count = w;
269
0
        first_skip = first_count * PIXEL_SIZE;
270
0
        while (h-- > 0) {
271
0
            register bits32 *pptr = dest32;
272
0
            const byte *sptr = line;
273
0
            register int sbyte = *sptr++ & first_mask;
274
0
            int count = w - first_count;
275
276
0
            if (sbyte) {
277
0
                register int bit = first_bit;
278
279
0
                do {
280
0
                    if (sbyte & bit)
281
0
                        put8(pptr, abcd1, efgh1);
282
0
                    pptr += PIXEL_SIZE;
283
0
                }
284
0
                while ((bit >>= 1) & first_mask);
285
0
            } else
286
0
                pptr += first_skip;
287
0
            while (count >= 8) {
288
0
                sbyte = *sptr++;
289
0
                if (sbyte & 0xf0) {
290
0
                    if (sbyte & 0x80)
291
0
                        put8(pptr, abcd1, efgh1);
292
0
                    if (sbyte & 0x40)
293
0
                        put8(pptr + 2, abcd1, efgh1);
294
0
                    if (sbyte & 0x20)
295
0
                        put8(pptr + 4, abcd1, efgh1);
296
0
                    if (sbyte & 0x10)
297
0
                        put8(pptr + 6, abcd1, efgh1);
298
0
                }
299
0
                if (sbyte & 0xf) {
300
0
                    if (sbyte & 8)
301
0
                        put8(pptr + 8, abcd1, efgh1);
302
0
                    if (sbyte & 4)
303
0
                        put8(pptr + 10, abcd1, efgh1);
304
0
                    if (sbyte & 2)
305
0
                        put8(pptr + 12, abcd1, efgh1);
306
0
                    if (sbyte & 1)
307
0
                        put8(pptr + 14, abcd1, efgh1);
308
0
                }
309
0
                pptr += 8 * PIXEL_SIZE;
310
0
                count -= 8;
311
0
            }
312
0
            if (count > 0) {
313
0
                register int bit = 0x80;
314
315
0
                sbyte = *sptr++;
316
0
                do {
317
0
                    if (sbyte & bit)
318
0
                        put8(pptr, abcd1, efgh1);
319
0
                    pptr += PIXEL_SIZE;
320
0
                    bit >>= 1;
321
0
                }
322
0
                while (--count > 0);
323
0
            }
324
0
            line += sraster;
325
0
            inc_ptr(dest, draster);
326
0
        }
327
0
    }
328
0
    return 0;
329
0
}
330
331
/* Copy a color bitmap. */
332
static int
333
mem_true64_copy_color(gx_device * dev,
334
               const byte * base, int sourcex, int sraster, gx_bitmap_id id,
335
                      int x, int y, int w, int h)
336
0
{
337
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
338
339
0
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
340
0
    mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h);
341
0
    return 0;
342
0
}
343
344
/* ================ "Word"-oriented device ================ */
345
346
/* Note that on a big-endian machine, this is the same as the */
347
/* standard byte-oriented-device. */
348
349
#if !ARCH_IS_BIG_ENDIAN
350
351
/* Procedures */
352
declare_mem_procs(mem64_word_copy_mono, mem64_word_copy_color, mem64_word_fill_rectangle);
353
354
/* Here is the device descriptor. */
355
const gx_device_memory mem_true64_word_device =
356
    mem_device("image64w", 64, 0, mem_word_dev_initialize_device_procs);
357
358
const gdev_mem_functions gdev_mem_fns_64w =
359
{
360
    gx_default_rgb_map_rgb_color,
361
    gx_default_rgb_map_color_rgb,
362
    mem64_word_fill_rectangle,
363
    mem64_word_copy_mono,
364
    mem64_word_copy_color,
365
    gx_default_copy_alpha,
366
    gx_default_strip_tile_rectangle,
367
    gx_no_strip_copy_rop2,
368
    mem_word_get_bits_rectangle
369
};
370
371
/* Fill a rectangle with a color. */
372
static int
373
mem64_word_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
374
                          gx_color_index color)
375
0
{
376
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
377
0
    byte *base;
378
0
    size_t raster;
379
380
0
    fit_fill(dev, x, y, w, h);
381
0
    base = scan_line_base(mdev, y);
382
0
    raster = mdev->raster;
383
0
    mem_swap_byte_rect(base, raster, x * 64, w * 64, h, true);
384
0
    mem_true64_fill_rectangle(dev, x, y, w, h, color);
385
0
    mem_swap_byte_rect(base, raster, x * 64, w * 64, h, false);
386
0
    return 0;
387
0
}
388
389
/* Copy a bitmap. */
390
static int
391
mem64_word_copy_mono(gx_device * dev,
392
               const byte * base, int sourcex, int sraster, gx_bitmap_id id,
393
        int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
394
0
{
395
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
396
0
    byte *row;
397
0
    size_t raster;
398
0
    bool store;
399
400
0
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
401
0
    row = scan_line_base(mdev, y);
402
0
    raster = mdev->raster;
403
0
    store = (zero != gx_no_color_index && one != gx_no_color_index);
404
0
    mem_swap_byte_rect(row, raster, x * 64, w * 64, h, store);
405
0
    mem_true64_copy_mono(dev, base, sourcex, sraster, id,
406
0
                         x, y, w, h, zero, one);
407
0
    mem_swap_byte_rect(row, raster, x * 64, w * 64, h, false);
408
0
    return 0;
409
0
}
410
411
/* Copy a color bitmap. */
412
static int
413
mem64_word_copy_color(gx_device * dev,
414
               const byte * base, int sourcex, int sraster, gx_bitmap_id id,
415
                      int x, int y, int w, int h)
416
0
{
417
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
418
0
    byte *row;
419
0
    size_t raster;
420
421
0
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
422
0
    row = scan_line_base(mdev, y);
423
0
    raster = mdev->raster;
424
0
    mem_swap_byte_rect(row, raster, x * 64, w * 64, h, true);
425
0
    bytes_copy_rectangle(row + x * PIXEL_SIZE, raster, base + sourcex * PIXEL_SIZE,
426
0
                                sraster, w * PIXEL_SIZE, h);
427
0
    mem_swap_byte_rect(row, raster, x * 64, w * 64, h, false);
428
0
    return 0;
429
0
}
430
431
#endif /* !ARCH_IS_BIG_ENDIAN */