Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/base/gdevdgbr.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
/* Default implementation of device get_bits[_rectangle] */
17
#include "memory_.h"
18
#include "gx.h"
19
#include "gserrors.h"
20
#include "gxdevice.h"
21
#include "gxdevmem.h"
22
#include "gxgetbit.h"
23
#include "gxlum.h"
24
#include "gdevmem.h"
25
#include "gxdevsop.h"
26
27
/*
28
 * Determine whether we can satisfy a request by simply using the stored
29
 * representation.  dev is used only for color_info.{num_components, depth}.
30
 */
31
static bool
32
requested_includes_stored(const gx_device *dev,
33
                          const gs_get_bits_params_t *requested,
34
                          const gs_get_bits_params_t *stored)
35
160M
{
36
160M
    gs_get_bits_options_t both = requested->options & stored->options;
37
38
160M
    if (!(both & GB_PACKING_ALL))
39
474k
        return false;
40
160M
    if (stored->options & GB_SELECT_PLANES) {
41
        /*
42
         * The device only provides a subset of the planes.
43
         * Make sure it provides all the requested ones.
44
         */
45
0
        int i;
46
0
        int n = (stored->options & GB_PACKING_BIT_PLANAR ?
47
0
                 dev->color_info.depth : dev->color_info.num_components);
48
49
0
        if (!(requested->options & GB_SELECT_PLANES) ||
50
0
            !(both & (GB_PACKING_PLANAR | GB_PACKING_BIT_PLANAR))
51
0
            )
52
0
            return false;
53
0
        for (i = 0; i < n; ++i)
54
0
            if (requested->data[i] && !stored->data[i])
55
0
                return false;
56
0
    }
57
160M
    if (both & GB_COLORS_NATIVE)
58
160M
        return true;
59
0
    if (both & GB_COLORS_STANDARD_ALL) {
60
0
        if ((both & GB_ALPHA_ALL) && (both & GB_DEPTH_ALL))
61
0
            return true;
62
0
    }
63
0
    return false;
64
0
}
65
66
/*
67
 * Try to implement get_bits_rectangle by returning a pointer.
68
 * Note that dev is used only for computing the default raster
69
 * and for color_info.depth.
70
 * This routine does not check x or h for validity.
71
 */
72
int
73
gx_get_bits_return_pointer(gx_device * dev, int x, int h,
74
                           gs_get_bits_params_t *params,
75
                           const gs_get_bits_params_t *stored,
76
                           byte **stored_base)
77
160M
{
78
160M
    gs_get_bits_options_t options = params->options;
79
160M
    gs_get_bits_options_t both = options & stored->options;
80
81
160M
    if (!(options & GB_RETURN_POINTER) ||
82
160M
        !requested_includes_stored(dev, params, stored)
83
160M
        )
84
41.9M
        return -1;
85
    /*
86
     * See whether we can return the bits in place.  Note that even if
87
     * OFFSET_ANY isn't set, x_offset and x don't have to be equal: their
88
     * bit offsets only have to match modulo align_bitmap_mod * 8 (to
89
     * preserve alignment) if ALIGN_ANY isn't set, or mod 8 (since
90
     * byte alignment is always required) if ALIGN_ANY is set.
91
     */
92
118M
    {
93
118M
        int depth = dev->color_info.depth;
94
        /*
95
         * For PLANAR devices, we assume that each plane consists of
96
         * depth/num_components bits.  This is wrong in general, but if
97
         * the device wants something else, it should implement
98
         * get_bits_rectangle itself.
99
         */
100
118M
        uint dev_raster = gx_device_raster(dev, true);
101
118M
        uint raster =
102
118M
            (options & (GB_RASTER_STANDARD | GB_RASTER_ANY) ? dev_raster :
103
118M
             params->raster);
104
118M
        byte *base;
105
106
118M
        if (h <= 1 || raster == dev_raster) {
107
118M
            int x_offset =
108
118M
                (options & GB_OFFSET_ANY ? x :
109
118M
                 options & GB_OFFSET_0 ? 0 : params->x_offset);
110
111
118M
            if (x_offset == x) {
112
118M
                base = stored_base[0];
113
118M
                params->x_offset = x;
114
118M
            } else {
115
0
                uint align_mod =
116
0
                    (options & GB_ALIGN_ANY ? 8 : align_bitmap_mod * 8);
117
0
                int bit_offset = x - x_offset;
118
0
                int bytes;
119
120
0
                if (bit_offset & (align_mod - 1))
121
0
                    return -1; /* can't align */
122
0
                if (depth & (depth - 1)) {
123
                    /* step = lcm(depth, align_mod) */
124
0
                    int step = depth / igcd(depth, align_mod) * align_mod;
125
126
0
                    bytes = bit_offset / step * step;
127
0
                } else {
128
                    /* Use a faster algorithm if depth is a power of 2. */
129
0
                    bytes = bit_offset & (-depth & -(int)align_mod);
130
0
                }
131
0
                base = stored_base[0] + arith_rshift(bytes, 3);
132
0
                params->x_offset = (bit_offset - bytes) / depth;
133
0
            }
134
118M
            params->options =
135
118M
                GB_ALIGN_STANDARD | GB_RETURN_POINTER | GB_RASTER_STANDARD |
136
118M
                (stored->options & ~GB_PACKING_ALL) /*see below for PACKING*/ |
137
118M
                (params->x_offset == 0 ? GB_OFFSET_0 : GB_OFFSET_SPECIFIED);
138
118M
            if (both & GB_PACKING_CHUNKY) {
139
111M
                params->options |= GB_PACKING_CHUNKY;
140
111M
                params->data[0] = base;
141
111M
            } else {
142
7.38M
                int n =
143
7.38M
                    (stored->options & GB_PACKING_BIT_PLANAR ?
144
0
                       (params->options |= GB_PACKING_BIT_PLANAR,
145
0
                        dev->color_info.depth) :
146
7.38M
                       (params->options |= GB_PACKING_PLANAR,
147
7.38M
                        dev->num_planar_planes));
148
7.38M
                int i;
149
150
44.3M
                for (i = 0; i < n; ++i) {
151
36.9M
                    if (!(both & GB_SELECT_PLANES) || stored->data[i] != 0) {
152
36.9M
                        params->data[i] = base;
153
36.9M
                    }
154
36.9M
                    if (i < n-1) {
155
29.5M
                        base += stored_base[dev->height]-stored_base[0];
156
29.5M
                        stored_base += dev->height;
157
29.5M
                    }
158
36.9M
                }
159
7.38M
            }
160
118M
            return 0;
161
118M
        }
162
118M
    }
163
0
    return -1;
164
118M
}
165
166
/*
167
 * Implement gx_get_bits_copy (see below) for the case of converting
168
 * 4-bit CMYK to 24-bit RGB with standard mapping, used heavily by PCL.
169
 */
170
static void
171
gx_get_bits_copy_cmyk_1bit(byte *dest_line, uint dest_raster,
172
                           const byte *src_line, uint src_raster,
173
                           int src_bit, int w, int h)
174
0
{
175
0
    for (; h > 0; dest_line += dest_raster, src_line += src_raster, --h) {
176
0
        const byte *src = src_line;
177
0
        byte *dest = dest_line;
178
0
        bool hi = (src_bit & 4) != 0;  /* last nibble processed was hi */
179
0
        int i;
180
181
0
        for (i = w; i > 0; dest += 3, --i) {
182
0
            uint pixel =
183
0
                ((hi = !hi)? *src >> 4 : *src++ & 0xf);
184
185
0
            if (pixel & 1)
186
0
                dest[0] = dest[1] = dest[2] = 0;
187
0
            else {
188
0
                dest[0] = (byte)((pixel >> 3) - 1);
189
0
                dest[1] = (byte)(((pixel >> 2) & 1) - 1);
190
0
                dest[2] = (byte)(((pixel >> 1) & 1) - 1);
191
0
            }
192
0
        }
193
0
    }
194
0
}
195
196
/*
197
 * Convert pixels between representations, primarily for get_bits_rectangle.
198
 * stored indicates how the data are actually stored, and includes:
199
 *      - one option from the GB_PACKING group;
200
 *      - if h > 1, one option from the GB_RASTER group;
201
 *      - optionally (and normally), GB_COLORS_NATIVE;
202
 *      - optionally, one option each from the GB_COLORS_STANDARD, GB_DEPTH,
203
 *      and GB_ALPHA groups.
204
 * Note that dev is used only for color mapping.  This routine assumes that
205
 * the stored data are aligned.
206
 *
207
 * Note: this routine does not check x, w, h for validity.
208
 *
209
 * The code for converting between standard and native colors has been
210
 * factored out into single-use procedures strictly for readability.
211
 * A good optimizing compiler would compile them in-line.
212
 */
213
static int
214
    gx_get_bits_native_to_std(gx_device * dev, int x, int w, int h,
215
                              gs_get_bits_params_t * params,
216
                              const gs_get_bits_params_t *stored,
217
                              const byte * src_base, uint dev_raster,
218
                              int x_offset, uint raster, uint std_raster);
219
int
220
gx_get_bits_copy(gx_device * dev, int x, int w, int h,
221
                 gs_get_bits_params_t * params,
222
                 const gs_get_bits_params_t *stored,
223
                 const byte * src_base, uint dev_raster)
224
41.4M
{
225
41.4M
    gs_get_bits_options_t options = params->options;
226
41.4M
    gs_get_bits_options_t stored_options = stored->options;
227
41.4M
    int x_offset = (options & GB_OFFSET_0 ? 0 : params->x_offset);
228
41.4M
    int depth = dev->color_info.depth;
229
41.4M
    int bit_x = x * depth;
230
41.4M
    const byte *src = src_base;
231
    /*
232
     * If the stored representation matches a requested representation,
233
     * we can copy the data without any transformations.
234
     */
235
41.4M
    bool direct_copy = requested_includes_stored(dev, params, stored);
236
41.4M
    int code = 0;
237
238
    /*
239
     * The request must include either GB_PACKING_CHUNKY or
240
     * GB_PACKING_PLANAR + GB_SELECT_PLANES, GB_RETURN_COPY,
241
     * and an offset and raster specification.  In the planar case,
242
     * the request must include GB_ALIGN_STANDARD, the stored
243
     * representation must include GB_PACKING_CHUNKY, and both must
244
     * include GB_COLORS_NATIVE.
245
     */
246
41.4M
    if ((~options & GB_RETURN_COPY) ||
247
41.4M
        !(options & (GB_OFFSET_0 | GB_OFFSET_SPECIFIED)) ||
248
41.4M
        !(options & (GB_RASTER_STANDARD | GB_RASTER_SPECIFIED))
249
41.4M
        )
250
0
        return_error(gs_error_rangecheck);
251
41.4M
    if (options & GB_PACKING_CHUNKY) {
252
41.4M
        byte *data = params->data[0];
253
41.4M
        int end_bit = (x_offset + w) * depth;
254
41.4M
        uint std_raster =
255
41.4M
            (options & GB_ALIGN_STANDARD ? bitmap_raster(end_bit) :
256
41.4M
             (end_bit + 7) >> 3);
257
41.4M
        uint raster =
258
41.4M
            (options & GB_RASTER_STANDARD ? std_raster : params->raster);
259
41.4M
        int dest_bit_x = x_offset * depth;
260
41.4M
        int skew = bit_x - dest_bit_x;
261
262
        /*
263
         * If the bit positions line up, use bytes_copy_rectangle.
264
         * Since bytes_copy_rectangle doesn't require alignment,
265
         * the bit positions only have to match within a byte,
266
         * not within align_bitmap_mod bytes.
267
         */
268
41.4M
        if (!(skew & 7) && direct_copy) {
269
41.4M
            int bit_w = w * depth;
270
271
41.4M
            bytes_copy_rectangle(data + (dest_bit_x >> 3), raster,
272
41.4M
                                 src + (bit_x >> 3), dev_raster,
273
41.4M
                              ((bit_x + bit_w + 7) >> 3) - (bit_x >> 3), h);
274
41.4M
        } else if (direct_copy) {
275
            /*
276
             * Use the logic already in mem_mono_copy_mono to copy the
277
             * bits to the destination.  We do this one line at a time,
278
             * to avoid having to allocate a line pointer table.
279
             */
280
0
            gx_device_memory tdev;
281
0
            byte *line_ptr = data;
282
0
            int bit_w = w * depth;
283
284
0
            tdev.line_ptrs = &tdev.base;
285
0
            for (; h > 0; line_ptr += raster, src += dev_raster, --h) {
286
                /* Make sure the destination is aligned. */
287
0
                int align = ALIGNMENT_MOD(line_ptr, align_bitmap_mod);
288
289
0
                tdev.base = line_ptr - align;
290
                /* set up parameters required by copy_mono's fit_copy */
291
0
                tdev.width = dest_bit_x + (align << 3) + bit_w;
292
0
                tdev.height = 1;
293
0
                code = mem_mono_copy_mono((gx_device *) & tdev, src, bit_x,
294
0
                                          dev_raster, gx_no_bitmap_id,
295
0
                                          dest_bit_x + (align << 3), 0, bit_w, 1,
296
0
                                          (gx_color_index) 0, (gx_color_index) 1);
297
0
                if (code < 0)
298
0
                    break;
299
0
            }
300
0
        } else if (options & ~stored_options & GB_COLORS_NATIVE) {
301
            /* Convert standard colors to native. */
302
0
            return_error(gs_error_rangecheck);
303
0
        } else {
304
            /* Convert native colors to standard. */
305
0
            code = gx_get_bits_native_to_std(dev, x, w, h, params, stored,
306
0
                                             src_base, dev_raster,
307
0
                                             x_offset, raster, std_raster);
308
0
            options = params->options;
309
0
        }
310
41.4M
        params->options =
311
41.4M
            (options & (GB_COLORS_ALL | GB_ALPHA_ALL)) | GB_PACKING_CHUNKY |
312
41.4M
            (options & GB_COLORS_NATIVE ? 0 : options & GB_DEPTH_ALL) |
313
41.4M
            (options & GB_ALIGN_STANDARD ? GB_ALIGN_STANDARD : GB_ALIGN_ANY) |
314
41.4M
            GB_RETURN_COPY |
315
41.4M
            (x_offset == 0 ? GB_OFFSET_0 : GB_OFFSET_SPECIFIED) |
316
41.4M
            (raster == std_raster ? GB_RASTER_STANDARD : GB_RASTER_SPECIFIED);
317
41.4M
    } else if (!(~options &
318
0
                 (GB_PACKING_PLANAR | GB_SELECT_PLANES | GB_ALIGN_STANDARD)) &&
319
0
               (stored_options & GB_PACKING_CHUNKY) &&
320
0
               ((options & stored_options) & GB_COLORS_NATIVE)
321
0
               ) {
322
0
        uchar num_planes = dev->color_info.num_components;
323
0
        int dest_depth = depth / num_planes;
324
0
        bits_plane_t source, dest;
325
0
        int plane = -1;
326
0
        uchar i;
327
328
        /* Make sure only one plane is being requested. */
329
0
        for (i = 0; i < num_planes; ++i)
330
0
            if (params->data[i] != 0) {
331
0
                if (plane >= 0)
332
0
                    return_error(gs_error_rangecheck); /* > 1 plane */
333
0
                plane = i;
334
0
            }
335
        /* Ensure at least one plane is requested */
336
0
        if (plane < 0)
337
0
            return_error(gs_error_rangecheck); /* No planes */
338
0
        source.data.read = src_base;
339
0
        source.raster = dev_raster;
340
0
        source.depth = depth;
341
0
        source.x = x;
342
0
        dest.data.write = params->data[plane];
343
0
        dest.raster =
344
0
            (options & GB_RASTER_STANDARD ?
345
0
             bitmap_raster((x_offset + w) * dest_depth) : params->raster);
346
0
        if (dev->color_info.separable_and_linear == GX_CINFO_SEP_LIN)
347
0
            dest.depth = dev->color_info.comp_bits[plane];
348
0
        else
349
0
            dest.depth = dest_depth;
350
0
        dest.x = x_offset;
351
0
        return bits_extract_plane(&dest, &source,
352
0
                                  (num_planes - 1 - plane) * dest_depth,
353
0
                                  w, h);
354
0
    } else
355
0
        return_error(gs_error_rangecheck);
356
41.4M
    return code;
357
41.4M
}
358
359
/*
360
 * Convert native colors to standard.  Only GB_DEPTH_8 is supported.
361
 */
362
static int
363
gx_get_bits_native_to_std(gx_device * dev, int x, int w, int h,
364
                          gs_get_bits_params_t * params,
365
                          const gs_get_bits_params_t *stored,
366
                          const byte * src_base, uint dev_raster,
367
                          int x_offset, uint raster, uint std_raster)
368
0
{
369
0
    int depth = dev->color_info.depth;
370
0
    int src_bit_offset = x * depth;
371
0
    const byte *src_line = src_base + (src_bit_offset >> 3);
372
0
    gs_get_bits_options_t options = params->options;
373
0
    int ncomp =
374
0
        (options & (GB_ALPHA_FIRST | GB_ALPHA_LAST) ? 4 : 3);
375
0
    byte *dest_line = params->data[0] + x_offset * ncomp;
376
0
    byte *mapped[16];
377
0
    int dest_bytes;
378
0
    int i;
379
380
0
    if (!(options & GB_DEPTH_8)) {
381
        /*
382
         * We don't support general depths yet, or conversion between
383
         * different formats.  Punt.
384
         */
385
0
        return_error(gs_error_rangecheck);
386
0
    }
387
388
    /* Pick the representation that's most likely to be useful. */
389
0
    if (options & GB_COLORS_RGB)
390
0
        params->options = options &= ~GB_COLORS_STANDARD_ALL | GB_COLORS_RGB,
391
0
            dest_bytes = 3;
392
0
    else if (options & GB_COLORS_CMYK)
393
0
        params->options = options &= ~GB_COLORS_STANDARD_ALL | GB_COLORS_CMYK,
394
0
            dest_bytes = 4;
395
0
    else if (options & GB_COLORS_GRAY)
396
0
        params->options = options &= ~GB_COLORS_STANDARD_ALL | GB_COLORS_GRAY,
397
0
            dest_bytes = 1;
398
0
    else
399
0
        return_error(gs_error_rangecheck);
400
    /* Recompute the destination raster based on the color space. */
401
0
    if (options & GB_RASTER_STANDARD) {
402
0
        uint end_byte = (x_offset + w) * dest_bytes;
403
404
0
        raster = std_raster =
405
0
            (options & GB_ALIGN_STANDARD ?
406
0
             bitmap_raster(end_byte << 3) : end_byte);
407
0
    }
408
    /* Check for the one special case we care about, namely that we have a
409
     * device that uses cmyk_1bit_map_cmyk_color, or equivalent. We do not
410
     * check function pointers directly, as this is defeated by forwarding
411
     * devices, but rather use a dev_spec_op. */
412
0
    if (((options & (GB_COLORS_RGB | GB_ALPHA_FIRST | GB_ALPHA_LAST))
413
0
           == GB_COLORS_RGB) &&
414
0
        (dev_proc(dev, dev_spec_op)(dev, gxdso_is_std_cmyk_1bit, NULL, 0) > 0)) {
415
0
        gx_get_bits_copy_cmyk_1bit(dest_line, raster,
416
0
                                   src_line, dev_raster,
417
0
                                   src_bit_offset & 7, w, h);
418
0
        return 0;
419
0
    }
420
0
    if (options & (GB_ALPHA_FIRST | GB_ALPHA_LAST))
421
0
        ++dest_bytes;
422
    /* Clear the color translation cache. */
423
0
    for (i = (depth > 4 ? 16 : 1 << depth); --i >= 0; )
424
0
        mapped[i] = 0;
425
0
    for (; h > 0; dest_line += raster, src_line += dev_raster, --h) {
426
0
        const byte *src = src_line;
427
0
        int bit = src_bit_offset & 7;
428
0
        byte *dest = dest_line;
429
430
0
        for (i = 0; i < w; ++i) {
431
0
            gx_color_index pixel = 0;
432
0
            gx_color_value rgba[4];
433
434
0
            if (sizeof(pixel) > 4) {
435
0
                if (sample_load_next64((uint64_t *)&pixel, &src, &bit, depth) < 0)
436
0
                    return_error(gs_error_rangecheck);
437
0
            }
438
0
            else {
439
0
                if (sample_load_next32((uint32_t *)&pixel, &src, &bit, depth) < 0)
440
0
                    return_error(gs_error_rangecheck);
441
0
            }
442
0
            if (pixel < 16) {
443
0
                if (mapped[pixel]) {
444
                    /* Use the value from the cache. */
445
0
                    memcpy(dest, mapped[pixel], dest_bytes);
446
0
                    dest += dest_bytes;
447
0
                    continue;
448
0
                }
449
0
                mapped[pixel] = dest;
450
0
            }
451
0
            (*dev_proc(dev, map_color_rgb)) (dev, pixel, rgba);
452
0
            if (options & GB_ALPHA_FIRST)
453
0
                *dest++ = 0xff;
454
            /* Convert to the requested color space. */
455
0
            if (options & GB_COLORS_RGB) {
456
0
                dest[0] = gx_color_value_to_byte(rgba[0]);
457
0
                dest[1] = gx_color_value_to_byte(rgba[1]);
458
0
                dest[2] = gx_color_value_to_byte(rgba[2]);
459
0
                dest += 3;
460
0
            } else if (options & GB_COLORS_CMYK) {
461
                /* Use the standard RGB to CMYK algorithm, */
462
                /* with maximum black generation and undercolor removal. */
463
0
                gx_color_value white = max(rgba[0], max(rgba[1], rgba[2]));
464
465
0
                dest[0] = gx_color_value_to_byte(white - rgba[0]);
466
0
                dest[1] = gx_color_value_to_byte(white - rgba[1]);
467
0
                dest[2] = gx_color_value_to_byte(white - rgba[2]);
468
0
                dest[3] = gx_color_value_to_byte(gx_max_color_value - white);
469
0
                dest += 4;
470
0
            } else { /* GB_COLORS_GRAY */
471
                /* Use the standard RGB to Gray algorithm. */
472
0
                *dest++ = gx_color_value_to_byte(
473
0
                                ((rgba[0] * (ulong) lum_red_weight) +
474
0
                                 (rgba[1] * (ulong) lum_green_weight) +
475
0
                                 (rgba[2] * (ulong) lum_blue_weight) +
476
0
                                   (lum_all_weights / 2))
477
0
                                / lum_all_weights);
478
0
            }
479
0
            if (options & GB_ALPHA_LAST)
480
0
                *dest++ = 0xff;
481
0
        }
482
0
    }
483
0
    return 0;
484
0
}
485
486
/* ------ Default implementations of get_bits_rectangle ------ */
487
488
int
489
gx_default_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect,
490
                       gs_get_bits_params_t * params)
491
0
{
492
0
    return_error(gs_error_unknownerror);
493
0
}
494
495
int gx_blank_get_bits_rectangle(gx_device *dev, const gs_int_rect *prect,
496
                                gs_get_bits_params_t *params)
497
0
{
498
0
    int supported = GB_COLORS_NATIVE |
499
0
                    GB_ALPHA_NONE |
500
0
                    GB_DEPTH_8 |
501
0
                    GB_PACKING_CHUNKY |
502
0
                    GB_RETURN_COPY |
503
0
                    GB_ALIGN_STANDARD |
504
0
                    GB_OFFSET_0 |
505
0
                    GB_RASTER_STANDARD;
506
0
    unsigned char *ptr = params->data[0];
507
0
    int bytes = (prect->q.x - prect->p.x) * dev->color_info.num_components;
508
0
    int col = dev->color_info.num_components > 3 ? 0 : 0xff;
509
0
    int raster = bitmap_raster(dev->width * dev->color_info.num_components);
510
0
    int y;
511
512
0
    if ((params->options & supported) != supported)
513
0
        return_error(gs_error_unknownerror);
514
515
0
    params->options = supported;
516
517
0
    for (y = prect->p.y; y < prect->q.y; y++) {
518
0
        memset(ptr, col, bytes);
519
0
        ptr += raster;
520
0
    }
521
522
0
    return 0;
523
0
}