Coverage Report

Created: 2025-06-10 07:17

/src/ghostpdl/base/gdevm2.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
/* 2-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
/* ================ Standard (byte-oriented) device ================ */
24
25
#undef chunk
26
#define chunk byte
27
#define fpat(byt) mono_fill_make_pattern(byt)
28
29
/* Procedures */
30
declare_mem_procs(mem_mapped2_copy_mono, mem_mapped2_copy_color, mem_mapped2_fill_rectangle);
31
32
/* The device descriptor. */
33
const gx_device_memory mem_mapped2_device =
34
    mem_device("image2", 2, 0, mem_dev_initialize_device_procs);
35
36
const gdev_mem_functions gdev_mem_fns_2 =
37
{
38
    mem_mapped_map_rgb_color,
39
    mem_mapped_map_color_rgb,
40
    mem_mapped2_fill_rectangle,
41
    mem_mapped2_copy_mono,
42
    mem_mapped2_copy_color,
43
    gx_default_copy_alpha,
44
    gx_default_strip_tile_rectangle,
45
    mem_gray_strip_copy_rop2,
46
    mem_get_bits_rectangle
47
};
48
49
/* Convert x coordinate to byte offset in scan line. */
50
#undef x_to_byte
51
0
#define x_to_byte(x) ((x) >> 2)
52
53
/* Define the 2-bit fill patterns. */
54
static const mono_fill_chunk tile_patterns[4] = {
55
    fpat(0x00), fpat(0x55), fpat(0xaa), fpat(0xff)
56
};
57
58
/* Fill a rectangle with a color. */
59
static int
60
mem_mapped2_fill_rectangle(gx_device * dev,
61
                           int x, int y, int w, int h, gx_color_index color)
62
0
{
63
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
64
65
0
    fit_fill(dev, x, y, w, h);
66
0
    bits_fill_rectangle(scan_line_base(mdev, y), x << 1, mdev->raster,
67
0
                        tile_patterns[color], w << 1, h);
68
0
    return 0;
69
0
}
70
71
/* Copy a bitmap. */
72
static int
73
mem_mapped2_copy_mono(gx_device * dev,
74
                      const byte * base, int sourcex, int sraster,
75
                      gx_bitmap_id id, int x, int y, int w, int h,
76
                      gx_color_index zero, gx_color_index one)
77
0
{
78
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
79
0
    const byte *line;
80
0
    int first_bit;
81
0
    byte first_mask, b0, b1, bxor, left_mask, right_mask;
82
0
    static const byte btab[4] = {0, 0x55, 0xaa, 0xff};
83
0
    static const byte bmask[4] = {0xc0, 0x30, 0xc, 3};
84
0
    static const byte lmask[4] = {0, 0xc0, 0xf0, 0xfc};
85
86
0
    declare_scan_ptr(dest);
87
88
0
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
89
0
    setup_rect(dest);
90
0
    line = base + (sourcex >> 3);
91
0
    first_bit = 0x80 >> (sourcex & 7);
92
0
    first_mask = bmask[x & 3];
93
0
    left_mask = lmask[x & 3];
94
0
    right_mask = ~lmask[(x + w) & 3];
95
0
    if ((x & 3) + w <= 3)
96
0
        left_mask = right_mask = left_mask | right_mask;
97
0
    b0 = btab[zero & 3];
98
0
    b1 = btab[one & 3];
99
0
    bxor = b0 ^ b1;
100
0
    while (h-- > 0) {
101
0
        register byte *pptr = (byte *) dest;
102
0
        const byte *sptr = line;
103
0
        register int sbyte = *sptr++;
104
0
        register int bit = first_bit;
105
0
        register byte mask = first_mask;
106
0
        int count = w;
107
108
        /* We have 4 cases, of which only 2 really matter. */
109
0
        if (one != gx_no_color_index) {
110
0
            if (zero != gx_no_color_index) { /* Copying an opaque bitmap. */
111
0
                byte data = (*pptr & left_mask) | (b0 & ~left_mask);
112
113
0
                for ( ; ; ) {
114
0
                    if (sbyte & bit)
115
0
                        data ^= bxor & mask;
116
0
                    if ((bit >>= 1) == 0)
117
0
                        bit = 0x80, sbyte = *sptr++;
118
0
                    if ((mask >>= 2) == 0)
119
0
                        mask = 0xc0, *pptr++ = data, data = b0;
120
0
                    if (--count <= 0)
121
0
                        break;
122
0
                }
123
0
                if (mask != 0xc0)
124
0
                    *pptr =
125
0
                        (*pptr & right_mask) | (data & ~right_mask);
126
0
            } else {   /* Filling a mask. */
127
0
                for ( ; ; ) {
128
0
                    if (sbyte & bit)
129
0
                        *pptr = (*pptr & ~mask) | (b1 & mask);
130
0
                    if (--count <= 0)
131
0
                        break;
132
0
                    if ((bit >>= 1) == 0)
133
0
                        bit = 0x80, sbyte = *sptr++;
134
0
                    if ((mask >>= 2) == 0)
135
0
                        mask = 0xc0, pptr++;
136
0
                }
137
0
            }
138
0
        } else {   /* Some other case. */
139
0
            for ( ; ; ) {
140
0
                if (!(sbyte & bit)) {
141
0
                    if (zero != gx_no_color_index)
142
0
                        *pptr = (*pptr & ~mask) | (b0 & mask);
143
0
                }
144
0
                if (--count <= 0)
145
0
                    break;
146
0
                if ((bit >>= 1) == 0)
147
0
                    bit = 0x80, sbyte = *sptr++;
148
0
                if ((mask >>= 2) == 0)
149
0
                    mask = 0xc0, pptr++;
150
0
            }
151
0
        }
152
0
        line += sraster;
153
0
        inc_ptr(dest, draster);
154
0
    }
155
0
    return 0;
156
0
}
157
158
/* Copy a color bitmap. */
159
static int
160
mem_mapped2_copy_color(gx_device * dev,
161
                       const byte * base, int sourcex, int sraster,
162
                       gx_bitmap_id id, int x, int y, int w, int h)
163
0
{
164
0
    int code;
165
166
0
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
167
    /* Use monobit copy_mono. */
168
    /* Patch the width in the device temporarily. */
169
0
    dev->width <<= 1;
170
0
    code = mem_mono_copy_mono(dev, base, sourcex << 1, sraster, id,
171
0
                              x << 1, y, w << 1, h,
172
0
                              (gx_color_index) 0, (gx_color_index) 1);
173
    /* Restore the correct width. */
174
0
    dev->width >>= 1;
175
0
    return code;
176
0
}
177
178
/* ================ "Word"-oriented device ================ */
179
180
/* Note that on a big-endian machine, this is the same as the */
181
/* standard byte-oriented-device. */
182
183
#if !ARCH_IS_BIG_ENDIAN
184
185
/* Procedures */
186
declare_mem_procs(mem2_word_copy_mono, mem2_word_copy_color, mem2_word_fill_rectangle);
187
188
/* Here is the device descriptor. */
189
const gx_device_memory mem_mapped2_word_device =
190
    mem_device("image2w", 2, 0, mem_word_dev_initialize_device_procs);
191
192
const gdev_mem_functions gdev_mem_fns_2w =
193
{
194
    mem_mapped_map_rgb_color,
195
    mem_mapped_map_color_rgb,
196
    mem2_word_fill_rectangle,
197
    mem2_word_copy_mono,
198
    mem2_word_copy_color,
199
    gx_default_copy_alpha,
200
    gx_default_strip_tile_rectangle,
201
    gx_no_strip_copy_rop2,
202
    mem_word_get_bits_rectangle
203
};
204
205
/* Fill a rectangle with a color. */
206
static int
207
mem2_word_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
208
                         gx_color_index color)
209
0
{
210
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
211
0
    byte *base;
212
0
    size_t raster;
213
214
0
    fit_fill(dev, x, y, w, h);
215
0
    base = scan_line_base(mdev, y);
216
0
    raster = mdev->raster;
217
0
    mem_swap_byte_rect(base, raster, x << 1, w << 1, h, true);
218
0
    bits_fill_rectangle(base, x << 1, raster,
219
0
                        tile_patterns[color], w << 1, h);
220
0
    mem_swap_byte_rect(base, raster, x << 1, w << 1, h, true);
221
0
    return 0;
222
0
}
223
224
/* Copy a bitmap. */
225
static int
226
mem2_word_copy_mono(gx_device * dev,
227
                    const byte * base, int sourcex, int sraster,
228
                    gx_bitmap_id id, int x, int y, int w, int h,
229
                    gx_color_index zero, gx_color_index one)
230
0
{
231
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
232
0
    byte *row;
233
0
    size_t raster;
234
0
    bool store;
235
236
0
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
237
0
    row = scan_line_base(mdev, y);
238
0
    raster = mdev->raster;
239
0
    store = (zero != gx_no_color_index && one != gx_no_color_index);
240
0
    mem_swap_byte_rect(row, raster, x << 1, w << 1, h, store);
241
0
    mem_mapped2_copy_mono(dev, base, sourcex, sraster, id,
242
0
                          x, y, w, h, zero, one);
243
0
    mem_swap_byte_rect(row, raster, x << 1, w << 1, h, false);
244
0
    return 0;
245
0
}
246
247
/* Copy a color bitmap. */
248
static int
249
mem2_word_copy_color(gx_device * dev,
250
                     const byte * base, int sourcex, int sraster,
251
                     gx_bitmap_id id, int x, int y, int w, int h)
252
0
{
253
0
    int code;
254
255
0
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
256
    /* Use monobit copy_mono. */
257
    /* Patch the width in the device temporarily. */
258
0
    dev->width <<= 1;
259
0
    code = gdev_mem_word_functions_for_bits(1)->copy_mono
260
0
        (dev, base, sourcex << 1, sraster, id,
261
0
         x << 1, y, w << 1, h, (gx_color_index) 0, (gx_color_index) 1);
262
    /* Restore the correct width. */
263
0
    dev->width >>= 1;
264
0
    return code;
265
0
}
266
267
#endif /* !ARCH_IS_BIG_ENDIAN */