Coverage Report

Created: 2025-06-10 06:49

/src/ghostpdl/base/gsdevmem.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
17
/* Memory device creation for Ghostscript library */
18
#include "math_.h"    /* for fabs */
19
#include "memory_.h"
20
#include "gx.h"
21
#include "gserrors.h"
22
#include "gsdevice.h"   /* for prototypes */
23
#include "gxarith.h"
24
#include "gxdevice.h"
25
#include "gxdevmem.h"
26
27
/* Make a memory (image) device. */
28
/* If colors_size = -16, -24, or -32, this is a true-color device; */
29
/* otherwise, colors_size is the size of the palette in bytes */
30
/* (2^N for gray scale, 3*2^N for RGB color). */
31
/* We separate device allocation and initialization at customer request. */
32
int
33
gs_initialize_wordimagedevice(gx_device_memory * new_dev, const gs_matrix * pmat,
34
              uint width, uint height, const byte * colors, int colors_size,
35
                    bool word_oriented, bool page_device, gs_memory_t * mem)
36
0
{
37
0
    const gx_device_memory *proto_dev;
38
0
    int palette_count = colors_size;
39
0
    int num_components = 1;
40
0
    int pcount;
41
0
    int bits_per_pixel;
42
0
    float x_pixels_per_unit, y_pixels_per_unit;
43
0
    byte palette[256 * 3];
44
0
    bool has_color;
45
0
    int code;
46
0
    gs_rect bbox;
47
48
0
    bbox.p.x = 0;
49
0
    bbox.p.y = 0;
50
0
    bbox.q.x = width;
51
0
    bbox.q.y = height;
52
0
    code = gs_bbox_transform_inverse(&bbox, pmat, &bbox);
53
0
    if (code < 0)
54
0
        return code;
55
56
0
    switch (colors_size) {
57
0
        case 3 * 2:
58
0
            palette_count = 2;
59
0
            num_components = 3;
60
            /* fall through */
61
0
        case 2:
62
0
            bits_per_pixel = 1;
63
0
            break;
64
0
        case 3 * 4:
65
0
            palette_count = 4;
66
0
            num_components = 3;
67
            /* fall through */
68
0
        case 4:
69
0
            bits_per_pixel = 2;
70
0
            break;
71
0
        case 3 * 16:
72
0
            palette_count = 16;
73
0
            num_components = 3;
74
            /* fall through */
75
0
        case 16:
76
0
            bits_per_pixel = 4;
77
0
            break;
78
0
        case 3 * 256:
79
0
            palette_count = 256;
80
0
            num_components = 3;
81
            /* fall through */
82
0
        case 256:
83
0
            bits_per_pixel = 8;
84
0
            break;
85
0
        case -16:
86
0
            bits_per_pixel = 16;
87
0
            palette_count = 0;
88
0
            break;
89
0
        case -24:
90
0
            bits_per_pixel = 24;
91
0
            palette_count = 0;
92
0
            break;
93
0
        case -32:
94
0
            bits_per_pixel = 32;
95
0
            palette_count = 0;
96
0
            break;
97
0
        default:
98
0
            return_error(gs_error_rangecheck);
99
0
    }
100
0
    proto_dev = (word_oriented ?
101
0
                 gdev_mem_word_device_for_bits(bits_per_pixel) :
102
0
                 gdev_mem_device_for_bits(bits_per_pixel));
103
0
    if (proto_dev == 0)   /* no suitable device */
104
0
        return_error(gs_error_rangecheck);
105
0
    pcount = palette_count * 3;
106
    /* Check to make sure the palette contains white and black, */
107
    /* and, if it has any colors, the six primaries. */
108
0
    if (bits_per_pixel <= 8) {
109
0
        const byte *p;
110
0
        byte *q;
111
0
        int primary_mask = 0;
112
0
        int i;
113
114
0
        has_color = false;
115
0
        for (i = 0, p = colors, q = palette;
116
0
             i < palette_count; i++, q += 3
117
0
            ) {
118
0
            int mask = 1;
119
120
0
            switch (num_components) {
121
0
                case 1: /* gray */
122
0
                    q[0] = q[1] = q[2] = *p++;
123
0
                    break;
124
0
                default /* case 3 */ :    /* RGB */
125
0
                    q[0] = p[0], q[1] = p[1], q[2] = p[2];
126
0
                    p += 3;
127
0
            }
128
0
#define shift_mask(b,n)\
129
0
  switch ( b ) { case 0xff: mask <<= n; case 0: break; default: mask = 0; }
130
0
            shift_mask(q[0], 4);
131
0
            shift_mask(q[1], 2);
132
0
            shift_mask(q[2], 1);
133
0
#undef shift_mask
134
0
            primary_mask |= mask;
135
0
            if (q[0] != q[1] || q[0] != q[2])
136
0
                has_color = true;
137
0
        }
138
0
        switch (primary_mask) {
139
0
            case 129:   /* just black and white */
140
0
                if (has_color) /* color but no primaries */
141
0
                    return_error(gs_error_rangecheck);
142
0
            case 255:   /* full color */
143
0
                break;
144
0
            default:
145
0
                return_error(gs_error_rangecheck);
146
0
        }
147
0
    } else
148
0
        has_color = true;
149
    /*
150
     * The initial transformation matrix must map 1 user unit to
151
     * 1/72".  Let W and H be the width and height in pixels, and
152
     * assume the initial matrix is of the form [A 0 0 B X Y].
153
     * Then the size of the image in user units is (W/|A|,H/|B|),
154
     * hence the size in inches is ((W/|A|)/72,(H/|B|)/72), so
155
     * the number of pixels per inch is
156
     * (W/((W/|A|)/72),H/((H/|B|)/72)), or (|A|*72,|B|*72).
157
     * Similarly, if the initial matrix is [0 A B 0 X Y] for a 90
158
     * or 270 degree rotation, the size of the image in user
159
     * units is (W/|B|,H/|A|), so the pixels per inch are
160
     * (|B|*72,|A|*72).  We forbid non-orthogonal transformation
161
     * matrices.
162
     */
163
0
    if (is_fzero2(pmat->xy, pmat->yx))
164
0
        x_pixels_per_unit = pmat->xx, y_pixels_per_unit = pmat->yy;
165
0
    else if (is_fzero2(pmat->xx, pmat->yy))
166
0
        x_pixels_per_unit = pmat->yx, y_pixels_per_unit = pmat->xy;
167
0
    else
168
0
        return_error(gs_error_undefinedresult);
169
    /* All checks done, initialize the device. */
170
0
    if (bits_per_pixel == 1) {
171
        /* Determine the polarity from the palette. */
172
0
        gs_make_mem_device(new_dev, proto_dev, mem,
173
0
                           (page_device ? 1 : -1), 0);
174
        /* This is somewhat bogus, but does the right thing */
175
        /* in the only cases we care about. */
176
0
        gdev_mem_mono_set_inverted(new_dev,
177
0
                               (palette[0] | palette[1] | palette[2]) != 0);
178
0
    } else {
179
0
        byte *dev_palette = gs_alloc_string(mem, pcount,
180
0
                                            "gs_makeimagedevice(palette)");
181
182
0
        if (dev_palette == 0)
183
0
            return_error(gs_error_VMerror);
184
0
        gs_make_mem_device(new_dev, proto_dev, mem,
185
0
                           (page_device ? 1 : -1), 0);
186
0
        new_dev->palette.size = pcount;
187
0
        new_dev->palette.data = dev_palette;
188
0
        memcpy(dev_palette, palette, pcount);
189
0
        if (!has_color) {
190
0
            new_dev->color_info.num_components = 1;
191
0
            new_dev->color_info.max_color = 0;
192
0
            new_dev->color_info.dither_colors = 0;
193
0
            new_dev->color_info.gray_index = 0;
194
0
        }
195
0
    }
196
    /* Memory defice is always initialised as an internal device but */
197
    /* this is an external device */
198
0
    new_dev->retained = true;
199
0
    rc_init(new_dev, new_dev->memory, 1);
200
201
0
    new_dev->initial_matrix = *pmat;
202
0
    new_dev->HWResolution[0] = fabs(x_pixels_per_unit) * 72;
203
0
    new_dev->HWResolution[1] = fabs(y_pixels_per_unit) * 72;
204
0
    gx_device_set_width_height((gx_device *) new_dev, width, height);
205
    /* Set the ImagingBBox so we get a correct clipping region. */
206
0
    {
207
0
        new_dev->ImagingBBox[0] = bbox.p.x;
208
0
        new_dev->ImagingBBox[1] = bbox.p.y;
209
0
        new_dev->ImagingBBox[2] = bbox.q.x;
210
0
        new_dev->ImagingBBox[3] = bbox.q.y;
211
0
        new_dev->ImagingBBox_set = true;
212
0
    }
213
    /* The bitmap will be allocated when the device is opened. */
214
0
    new_dev->is_open = false;
215
0
    new_dev->bitmap_memory = mem;
216
0
    return 0;
217
0
}
218
219
int
220
gs_makewordimagedevice(gx_device ** pnew_dev, const gs_matrix * pmat,
221
               uint width, uint height, const byte * colors, int num_colors,
222
                    bool word_oriented, bool page_device, gs_memory_t * mem)
223
0
{
224
0
    int code;
225
0
    gx_device_memory *pnew =
226
0
    gs_alloc_struct_immovable(mem, gx_device_memory, &st_device_memory,
227
0
                    "gs_makeimagedevice(device)");
228
229
0
    if (pnew == 0)
230
0
        return_error(gs_error_VMerror);
231
232
    /* Bug #697450 "Null pointer dereference in gx_device_finalize()"
233
     * If we have incorrect data passed to gs_initialise_wordimagedevice() then the
234
     * initialisation will fail, crucially it will fail *before* it calls
235
     * gs_make_mem_device() which initialises the device. This means that the
236
     * icc_struct member will be uninitialsed, but the device finalise method
237
     * will unconditionally free that memory. Since its a garbage pointer, bad things happen.
238
     * Apparently we do still need makeimagedevice to be available from
239
     * PostScript, so in here just zero the device memory, which means that
240
     * the finalise routine won't have a problem.
241
     */
242
0
    memset(pnew, 0x00, st_device_memory.ssize);
243
0
    code = gs_initialize_wordimagedevice(pnew, pmat, width, height,
244
0
                                         colors, num_colors, word_oriented,
245
0
                                         page_device, mem);
246
0
    if (code < 0) {
247
0
        gs_free_object(mem, pnew, "gs_makeimagedevice(device)");
248
0
        return code;
249
0
    }
250
0
    *pnew_dev = (gx_device *) pnew;
251
0
    return 0;
252
0
}