Coverage Report

Created: 2025-04-22 06:20

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