Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/base/gdevmem.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2024 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
/* Generic "memory" (stored bitmap) device */
17
#include "memory_.h"
18
#include "gx.h"
19
#include "gsdevice.h"
20
#include "gserrors.h"
21
#include "gsrect.h"
22
#include "gsstruct.h"
23
#include "gxarith.h"
24
#include "gxdevice.h"
25
#include "gxgetbit.h"
26
#include "gxdevmem.h"   /* semi-public definitions */
27
#include "gdevmem.h"    /* private definitions */
28
#include "gstrans.h"
29
30
/* Structure descriptor */
31
public_st_device_memory();
32
33
/* GC procedures */
34
static
35
35.7k
ENUM_PTRS_WITH(device_memory_enum_ptrs, gx_device_memory *mptr)
36
11.9k
{
37
11.9k
    return ENUM_USING(st_device_forward, vptr, sizeof(gx_device_forward), index - 4);
38
0
}
39
5.96k
case 0: ENUM_RETURN((mptr->foreign_bits ? NULL : (void *)mptr->base));
40
5.96k
case 1: ENUM_RETURN((mptr->foreign_line_pointers ? NULL : (void *)mptr->line_ptrs));
41
5.96k
ENUM_STRING_PTR(2, gx_device_memory, palette);
42
5.96k
case 3: ENUM_RETURN(mptr->owner);
43
35.7k
ENUM_PTRS_END
44
static
45
5.96k
RELOC_PTRS_WITH(device_memory_reloc_ptrs, gx_device_memory *mptr)
46
5.96k
{
47
5.96k
    if (!mptr->foreign_bits) {
48
0
        byte *base_old = mptr->base;
49
0
        long reloc;
50
0
        int y;
51
0
        int h = mptr->height;
52
53
0
        if (mptr->num_planar_planes > 1)
54
0
            h *= mptr->num_planar_planes;
55
56
0
        RELOC_PTR(gx_device_memory, base);
57
0
        reloc = base_old - mptr->base;
58
0
        for (y = 0; y < h; y++)
59
0
            mptr->line_ptrs[y] -= reloc;
60
        /* Relocate line_ptrs, which also points into the data area. */
61
0
        mptr->line_ptrs = (byte **) ((byte *) mptr->line_ptrs - reloc);
62
5.96k
    } else if (!mptr->foreign_line_pointers) {
63
0
        RELOC_PTR(gx_device_memory, line_ptrs);
64
0
    }
65
5.96k
    RELOC_CONST_STRING_PTR(gx_device_memory, palette);
66
5.96k
    RELOC_PTR(gx_device_memory, owner);
67
5.96k
    RELOC_USING(st_device_forward, vptr, sizeof(gx_device_forward));
68
5.96k
}
69
5.96k
RELOC_PTRS_END
70
71
/* Define the palettes for monobit devices. */
72
static const byte b_w_palette_string[6] = {
73
    0xff, 0xff, 0xff, 0, 0, 0
74
};
75
const gs_const_string mem_mono_b_w_palette = {
76
    b_w_palette_string, 6
77
};
78
static const byte w_b_palette_string[6] = {
79
    0, 0, 0, 0xff, 0xff, 0xff
80
};
81
const gs_const_string mem_mono_w_b_palette = {
82
    w_b_palette_string, 6
83
};
84
85
/* ------ Generic code ------ */
86
87
/* Return the appropriate memory device for a given */
88
/* number of bits per pixel (0 if none suitable).
89
   Greater than 64 occurs for the planar case
90
   which we will then return a mem_x_device */
91
static const gx_device_memory *const mem_devices[65] = {
92
    0, &mem_mono_device, &mem_mapped2_device, 0, &mem_mapped4_device,
93
    0, 0, 0, &mem_mapped8_device,
94
    0, 0, 0, 0, 0, 0, 0, &mem_true16_device,
95
    0, 0, 0, 0, 0, 0, 0, &mem_true24_device,
96
    0, 0, 0, 0, 0, 0, 0, &mem_true32_device,
97
    0, 0, 0, 0, 0, 0, 0, &mem_true40_device,
98
    0, 0, 0, 0, 0, 0, 0, &mem_true48_device,
99
    0, 0, 0, 0, 0, 0, 0, &mem_true56_device,
100
    0, 0, 0, 0, 0, 0, 0, &mem_true64_device
101
};
102
const gx_device_memory *
103
gdev_mem_device_for_bits(int bits_per_pixel)
104
202M
{
105
202M
    return ((uint)bits_per_pixel > 64 ? &mem_x_device :
106
202M
            mem_devices[bits_per_pixel]);
107
202M
}
108
/* Do the same for a word-oriented device. */
109
static const gx_device_memory *const mem_word_devices[65] = {
110
    0, &mem_mono_device, &mem_mapped2_word_device, 0, &mem_mapped4_word_device,
111
    0, 0, 0, &mem_mapped8_word_device,
112
    0, 0, 0, 0, 0, 0, 0, 0 /*no 16-bit word device*/,
113
    0, 0, 0, 0, 0, 0, 0, &mem_true24_word_device,
114
    0, 0, 0, 0, 0, 0, 0, &mem_true32_word_device,
115
    0, 0, 0, 0, 0, 0, 0, &mem_true40_word_device,
116
    0, 0, 0, 0, 0, 0, 0, &mem_true48_word_device,
117
    0, 0, 0, 0, 0, 0, 0, &mem_true56_word_device,
118
    0, 0, 0, 0, 0, 0, 0, &mem_true64_word_device
119
};
120
const gx_device_memory *
121
gdev_mem_word_device_for_bits(int bits_per_pixel)
122
0
{
123
0
    return ((uint)bits_per_pixel > 64 ? (const gx_device_memory *)0 :
124
0
            mem_word_devices[bits_per_pixel]);
125
0
}
126
127
static const gdev_mem_functions *mem_fns[65] = {
128
    NULL, &gdev_mem_fns_1, &gdev_mem_fns_2, NULL,
129
                            &gdev_mem_fns_4, NULL, NULL, NULL,
130
    &gdev_mem_fns_8, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
131
    &gdev_mem_fns_16, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
132
    &gdev_mem_fns_24, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
133
    &gdev_mem_fns_32, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
134
    &gdev_mem_fns_40, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
135
    &gdev_mem_fns_48, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
136
    &gdev_mem_fns_56, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
137
    &gdev_mem_fns_64
138
};
139
140
const gdev_mem_functions *
141
gdev_mem_functions_for_bits(int bits_per_pixel)
142
345M
{
143
345M
    return ((uint)bits_per_pixel > 64 ? NULL : mem_fns[bits_per_pixel]);
144
345M
}
145
146
static const gdev_mem_functions *mem_word_fns[65] = {
147
    NULL, &gdev_mem_fns_1, &gdev_mem_fns_2w, NULL,
148
                            &gdev_mem_fns_4w, NULL, NULL, NULL,
149
    &gdev_mem_fns_8w, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
150
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
151
    &gdev_mem_fns_24w, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
152
    &gdev_mem_fns_32w, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
153
    &gdev_mem_fns_40w, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
154
    &gdev_mem_fns_48w, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
155
    &gdev_mem_fns_56w, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
156
    &gdev_mem_fns_64w
157
};
158
159
const gdev_mem_functions *
160
gdev_mem_word_functions_for_bits(int bits_per_pixel)
161
0
{
162
0
    return ((uint)bits_per_pixel > 64 ? NULL : mem_word_fns[bits_per_pixel]);
163
0
}
164
165
/* Test whether a device is a memory device */
166
bool
167
gs_device_is_memory(const gx_device * dev)
168
433M
{
169
    /*
170
     * We use the draw_thin_line procedure to mark memory devices.
171
     * See gdevmem.h.
172
     */
173
433M
    return (dev_proc(dev, draw_thin_line) == mem_draw_thin_line);
174
433M
}
175
176
/* Make a memory device. */
177
/* Note that the default for monobit devices is white = 0, black = 1. */
178
void
179
gs_make_mem_device(gx_device_memory * dev, const gx_device_memory * mdproto,
180
                   gs_memory_t * mem, int page_device, gx_device * target)
181
161M
{
182
    /* Can never fail */
183
161M
    (void)gx_device_init((gx_device *) dev, (const gx_device *)mdproto,
184
161M
                         mem, true);
185
161M
    dev->stype = &st_device_memory;
186
161M
    switch (page_device) {
187
4.36k
        case -1:
188
4.36k
            set_dev_proc(dev, get_page_device, gx_default_get_page_device);
189
4.36k
            break;
190
1.35M
        case 1:
191
1.35M
            set_dev_proc(dev, get_page_device, gx_page_device_get_page_device);
192
1.35M
            break;
193
161M
    }
194
    /* Preload the black and white cache. */
195
161M
    if (target == NULL) {
196
3.13k
        if (dev->color_info.depth == 1) {
197
            /* The default for black-and-white devices is inverted. */
198
0
            dev->cached_colors.black = 1;
199
0
            dev->cached_colors.white = 0;
200
3.13k
        } else {
201
3.13k
            dev->cached_colors.black = 0;
202
3.13k
            dev->cached_colors.white = (1 << dev->color_info.depth) - 1;
203
3.13k
        }
204
3.13k
        dev->graphics_type_tag = GS_UNKNOWN_TAG;
205
161M
    } else {
206
161M
        gx_device_set_target((gx_device_forward *)dev, target);
207
        /* Forward the color mapping operations to the target. */
208
161M
        gx_device_forward_color_procs((gx_device_forward *) dev);
209
161M
        gx_device_copy_color_procs((gx_device *)dev, target);
210
161M
        dev->color_info.separable_and_linear = target->color_info.separable_and_linear;
211
161M
        dev->cached_colors = target->cached_colors;
212
161M
        dev->graphics_type_tag = target->graphics_type_tag; /* initialize to same as target */
213
214
161M
        set_dev_proc(dev, put_image, gx_forward_put_image);
215
161M
    }
216
161M
    if (dev->color_info.depth == 1) {
217
49.4M
        gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
218
49.4M
        uchar k;
219
220
49.4M
        if (target != 0) {
221
129M
            for (k = 0; k < target->color_info.num_components; k++) {
222
79.8M
                cv[k] = 0;
223
79.8M
            }
224
49.4M
        }
225
49.4M
       gdev_mem_mono_set_inverted(dev, (target == NULL ||
226
49.4M
                                   (*dev_proc(dev, encode_color))((gx_device *)dev, cv) != 0));
227
49.4M
    }
228
161M
    set_dev_proc(dev, dev_spec_op, mem_spec_op);
229
161M
    check_device_separable((gx_device *)dev);
230
161M
    gx_device_fill_in_procs((gx_device *)dev);
231
161M
    dev->band_y = 0;
232
161M
    dev->owner = target;
233
161M
}
234
235
/* Make a memory device using copydevice, this should replace gs_make_mem_device. */
236
/* Note that the default for monobit devices is white = 0, black = 1. */
237
int
238
gs_make_mem_device_with_copydevice(gx_device_memory ** ppdev,
239
                                   const gx_device_memory * mdproto,
240
                                   gs_memory_t * mem,
241
                                   int page_device,
242
                                   gx_device * target)
243
0
{
244
0
    int code;
245
0
    gx_device_memory *pdev;
246
247
0
    if (mem == NULL)
248
0
        return -1;
249
250
0
    code = gs_copydevice((gx_device **)&pdev,
251
0
                         (const gx_device *)mdproto,
252
0
                         mem);
253
0
    if (code < 0)
254
0
        return code;
255
256
0
    switch (page_device) {
257
0
        case -1:
258
0
            set_dev_proc(pdev, get_page_device, gx_default_get_page_device);
259
0
            break;
260
0
        case 1:
261
0
            set_dev_proc(pdev, get_page_device, gx_page_device_get_page_device);
262
0
            break;
263
0
    }
264
    /* Preload the black and white cache. */
265
0
    if (target == NULL) {
266
0
        if (pdev->color_info.depth == 1) {
267
            /* The default for black-and-white devices is inverted. */
268
0
            pdev->cached_colors.black = 1;
269
0
            pdev->cached_colors.white = 0;
270
0
        } else {
271
0
            pdev->cached_colors.black = 0;
272
0
            pdev->cached_colors.white = (1 << pdev->color_info.depth) - 1;
273
0
        }
274
0
        pdev->graphics_type_tag = GS_UNKNOWN_TAG;
275
0
    } else {
276
0
        gx_device_set_target((gx_device_forward *)pdev, target);
277
        /* Forward the color mapping operations to the target. */
278
0
        gx_device_forward_color_procs((gx_device_forward *) pdev);
279
0
        gx_device_copy_color_procs((gx_device *)pdev, target);
280
0
        pdev->cached_colors = target->cached_colors;
281
0
        pdev->graphics_type_tag = target->graphics_type_tag;  /* initialize to same as target */
282
0
    }
283
0
    if (pdev->color_info.depth == 1) {
284
0
        gx_color_value cv[3];
285
286
0
       cv[0] = cv[1] = cv[2] = 0;
287
0
        gdev_mem_mono_set_inverted(pdev, (target == NULL ||
288
0
                                   (*dev_proc(pdev, encode_color))((gx_device *)pdev, cv) != 0));
289
0
    }
290
0
    check_device_separable((gx_device *)pdev);
291
0
    gx_device_fill_in_procs((gx_device *)pdev);
292
0
    pdev->band_y = 0;
293
0
    *ppdev = pdev;
294
0
    return 0;
295
0
}
296
297
/* Make a monobit memory device using copydevice */
298
int
299
gs_make_mem_mono_device_with_copydevice(gx_device_memory ** ppdev, gs_memory_t * mem,
300
                                        gx_device * target)
301
0
{
302
0
    int code;
303
0
    gx_device_memory *pdev;
304
305
0
    if (mem == NULL)
306
0
        return -1;
307
308
0
    code = gs_copydevice((gx_device **)&pdev,
309
0
                         (const gx_device *)&mem_mono_device,
310
0
                         mem);
311
0
    if (code < 0)
312
0
        return code;
313
314
0
    set_dev_proc(pdev, get_page_device, gx_default_get_page_device);
315
0
    gx_device_set_target((gx_device_forward *)pdev, target);
316
    /* Should this be forwarding, monochrome profile, or not set? MJV. */
317
0
    set_dev_proc(pdev, get_profile, gx_forward_get_profile);
318
319
0
    gdev_mem_mono_set_inverted(pdev, true);
320
0
    check_device_separable((gx_device *)pdev);
321
0
    gx_device_fill_in_procs((gx_device *)pdev);
322
0
    *ppdev = pdev;
323
0
    return 0;
324
0
}
325
326
/* Make a monobit memory device.  This is never a page device. */
327
/* Note that white=0, black=1. */
328
void
329
gs_make_mem_mono_device(gx_device_memory * dev, gs_memory_t * mem,
330
                        gx_device * target)
331
13.0M
{
332
    /* Can never fail */
333
13.0M
    (void)gx_device_init((gx_device *)dev,
334
13.0M
                         (const gx_device *)&mem_mono_device,
335
13.0M
                         mem, true);
336
13.0M
    set_dev_proc(dev, get_page_device, gx_default_get_page_device);
337
13.0M
    gx_device_set_target((gx_device_forward *)dev, target);
338
13.0M
    dev->raster = gx_device_raster((gx_device *)dev, 1);
339
13.0M
    gdev_mem_mono_set_inverted(dev, true);
340
13.0M
    check_device_separable((gx_device *)dev);
341
13.0M
    gx_device_fill_in_procs((gx_device *)dev);
342
    /* Should this be forwarding, monochrome profile, or not set? MJV */
343
13.0M
    set_dev_proc(dev, get_profile, gx_forward_get_profile);
344
13.0M
    set_dev_proc(dev, set_graphics_type_tag, gx_forward_set_graphics_type_tag);
345
13.0M
    set_dev_proc(dev, dev_spec_op, mem_spec_op);
346
13.0M
    dev->owner = target;
347
    /* initialize to same tag as target */
348
13.0M
    dev->graphics_type_tag = target ? target->graphics_type_tag : GS_UNKNOWN_TAG;
349
13.0M
}
350
351
/* Define whether a monobit memory device is inverted (black=1). */
352
void
353
gdev_mem_mono_set_inverted(gx_device_memory * dev, bool black_is_1)
354
62.4M
{
355
62.4M
    if (black_is_1)
356
46.4M
        dev->palette = mem_mono_b_w_palette;
357
16.0M
    else
358
16.0M
        dev->palette = mem_mono_w_b_palette;
359
62.4M
}
360
361
/*
362
 * Compute the size of the bitmap storage, including the space for the scan
363
 * line pointer table.  Note that scan lines are padded to a multiple of
364
 * align_bitmap_mod bytes, and additional padding may be needed if the
365
 * pointer table must be aligned to an even larger modulus.
366
 *
367
 * The computation for planar devices is a little messier.  Each plane
368
 * must pad its scan lines, and then we must pad again for the pointer
369
 * tables (one table per plane).
370
 *
371
 * Return VMerror if the size exceeds max size_t
372
 */
373
int
374
gdev_mem_bits_size(const gx_device_memory * dev, int width, int height, size_t *psize)
375
23.6M
{
376
23.6M
    int num_planes;
377
23.6M
    gx_render_plane_t plane1;
378
23.6M
    const gx_render_plane_t *planes;
379
23.6M
    size_t size, alignment = bitmap_raster_pad_align(1, dev->pad, dev->log2_align_mod);
380
23.6M
    int pi;
381
382
23.6M
    if (dev->num_planar_planes > 1) {
383
1.20M
        num_planes = dev->num_planar_planes;
384
1.20M
        planes = dev->planes;
385
1.20M
    } else
386
22.4M
        planes = &plane1, plane1.depth = dev->color_info.depth, num_planes = 1;
387
56.9M
    for (size = 0, pi = 0; pi < num_planes; ++pi) {
388
33.3M
        size_t raster = bitmap_raster_pad_align((size_t)width * planes[pi].depth, dev->pad, dev->log2_align_mod);
389
33.3M
        if ((planes[pi].depth && width > (SIZE_MAX - alignment) / planes[pi].depth) || raster > SIZE_MAX - size)
390
0
            return_error(gs_error_VMerror);
391
33.3M
        size += raster;
392
33.3M
    }
393
23.6M
    if (height != 0)
394
23.6M
        if (size > (SIZE_MAX - ARCH_ALIGN_PTR_MOD) / (ulong)height)
395
0
            return_error(gs_error_VMerror);
396
23.6M
    size = ROUND_UP(size * height, ARCH_ALIGN_PTR_MOD);
397
23.6M
    if (dev->log2_align_mod > log2_align_bitmap_mod)
398
0
        size += 1<<dev->log2_align_mod;
399
23.6M
    *psize = size;
400
23.6M
    return 0;
401
23.6M
}
402
size_t
403
gdev_mem_line_ptrs_size(const gx_device_memory * dev, int width, int height)
404
15.8M
{
405
15.8M
    int num_planes = 1;
406
15.8M
    if (dev->num_planar_planes > 1)
407
938k
        num_planes = dev->num_planar_planes;
408
15.8M
    return (size_t)height * sizeof(byte *) * num_planes;
409
15.8M
}
410
int
411
gdev_mem_data_size(const gx_device_memory * dev, int width, int height, size_t *psize)
412
15.5M
{
413
15.5M
    size_t bits_size;
414
15.5M
    size_t line_ptrs_size = gdev_mem_line_ptrs_size(dev, width, height);
415
416
15.5M
    if (gdev_mem_bits_size(dev, width, height, &bits_size) < 0 ||
417
15.5M
        bits_size > SIZE_MAX - line_ptrs_size)
418
0
        return_error(gs_error_VMerror);
419
15.5M
    *psize = bits_size + line_ptrs_size;
420
15.5M
    return 0;
421
15.5M
}
422
/*
423
 * Do the inverse computation: given a width (in pixels) and a buffer size,
424
 * compute the maximum height.
425
 */
426
int
427
gdev_mem_max_height(const gx_device_memory * dev, int width, size_t size,
428
                    bool page_uses_transparency)
429
1.35M
{
430
1.35M
    int height;
431
1.35M
    size_t max_height;
432
1.35M
    size_t data_size = 0;
433
1.35M
    bool deep = device_is_deep((const gx_device *)dev);
434
435
1.35M
    if (page_uses_transparency) {
436
        /*
437
         * If the device is using PDF 1.4 transparency then we will need to
438
         * also allocate image buffers for doing the blending operations.
439
         * We can only estimate the space requirements.  However since it
440
         * is only an estimate, we may exceed our desired buffer space while
441
         * processing the file.
442
         */
443
            /* FIXME: For a planar device, is dev->color_info.num_components 1 ? Otherwise, aren't we
444
             * calculating this too large? */
445
96.6k
        max_height = size / (bitmap_raster_pad_align(width
446
96.6k
            * dev->color_info.depth + ESTIMATED_PDF14_ROW_SPACE(width, dev->color_info.num_components, deep ? 16 : 8),
447
96.6k
                dev->pad, dev->log2_align_mod) + sizeof(byte *) * (dev->num_planar_planes ? dev->num_planar_planes : 1));
448
96.6k
        height = (int)min(max_height, max_int);
449
1.25M
    } else {
450
        /* For non PDF 1.4 transparency, we can do an exact calculation */
451
1.25M
        max_height = size /
452
1.25M
            (bitmap_raster_pad_align(width * dev->color_info.depth, dev->pad, dev->log2_align_mod) +
453
1.25M
             sizeof(byte *) * (dev->num_planar_planes ? dev->num_planar_planes : 1));
454
1.25M
        height = (int)min(max_height, max_int);
455
        /*
456
         * Because of alignment rounding, the just-computed height might
457
         * be too large by a small amount.  Adjust it the easy way.
458
         */
459
1.61M
        do {
460
1.61M
            gdev_mem_data_size(dev, width, height, &data_size);
461
1.61M
            if (data_size <= size)
462
1.25M
                break;
463
362k
            --height;
464
362k
        } while (data_size > size);
465
1.25M
    }
466
0
    return height;
467
1.35M
}
468
469
/* Open a memory device, allocating the data area if appropriate, */
470
/* and create the scan line table. */
471
int
472
mem_open(gx_device * dev)
473
6.43M
{
474
6.43M
    gx_device_memory *const mdev = (gx_device_memory *)dev;
475
476
    /* Check that we aren't trying to open a planar device as chunky. */
477
6.43M
    if (mdev->num_planar_planes > 1)
478
0
        return_error(gs_error_rangecheck);
479
6.43M
    return gdev_mem_open_scan_lines(mdev, dev->height);
480
6.43M
}
481
int
482
gdev_mem_open_scan_lines(gx_device_memory *mdev, int setup_height)
483
6.43M
{
484
6.43M
    return gdev_mem_open_scan_lines_interleaved(mdev, setup_height, 0);
485
6.43M
}
486
int
487
gdev_mem_open_scan_lines_interleaved(gx_device_memory *mdev,
488
                                     int setup_height,
489
                                     int interleaved)
490
6.43M
{
491
6.43M
    bool line_pointers_adjacent = true;
492
6.43M
    size_t size;
493
494
6.43M
    if (setup_height < 0 || setup_height > mdev->height)
495
0
        return_error(gs_error_rangecheck);
496
6.43M
    if (mdev->bitmap_memory != NULL) {
497
31.0k
        int align;
498
        /* Allocate the data now. */
499
31.0k
        if (gdev_mem_bitmap_size(mdev, &size) < 0)
500
0
            return_error(gs_error_VMerror);
501
502
31.0k
        mdev->base = gs_alloc_bytes(mdev->bitmap_memory, size,
503
31.0k
                                    "mem_open");
504
31.0k
        if (mdev->base == NULL)
505
0
            return_error(gs_error_VMerror);
506
31.0k
#ifdef PACIFY_VALGRIND
507
        /* If we end up writing the bitmap to the clist, we can get valgrind errors
508
         * because we write and read the padding at the end of each raster line.
509
         * Easiest to set the entire block.
510
         */
511
31.0k
        memset(mdev->base, 0x00, size);
512
31.0k
#endif
513
31.0k
        align = 1<<mdev->log2_align_mod;
514
31.0k
        mdev->base += (-(int)(intptr_t)mdev->base) & (align-1);
515
31.0k
        mdev->foreign_bits = false;
516
6.40M
    } else if (mdev->line_pointer_memory != NULL) {
517
        /* Allocate the line pointers now. */
518
519
0
        mdev->line_ptrs = (byte **)
520
0
            gs_alloc_byte_array(mdev->line_pointer_memory, mdev->height,
521
0
                                sizeof(byte *) * (mdev->num_planar_planes ? mdev->num_planar_planes : 1),
522
0
                                "gdev_mem_open_scan_lines");
523
0
        if (mdev->line_ptrs == NULL)
524
0
            return_error(gs_error_VMerror);
525
0
        mdev->foreign_line_pointers = false;
526
0
        line_pointers_adjacent = false;
527
0
    }
528
6.43M
    if (line_pointers_adjacent) {
529
6.43M
        int code;
530
531
6.43M
        if (mdev->base == NULL)
532
0
            return_error(gs_error_rangecheck);
533
534
6.43M
        code = gdev_mem_bits_size(mdev, mdev->width, mdev->height, &size);
535
6.43M
        if (code < 0)
536
0
            return code;
537
538
6.43M
        mdev->line_ptrs = (byte **)(mdev->base + size);
539
6.43M
    }
540
6.43M
    mdev->raster = gx_device_raster((gx_device *)mdev, 1);
541
6.43M
    return gdev_mem_set_line_ptrs_interleaved(mdev, NULL, 0, NULL,
542
6.43M
                                              setup_height,
543
6.43M
                                              interleaved);
544
6.43M
}
545
/*
546
 * Set up the scan line pointers of a memory device.
547
 * See gxdevmem.h for the detailed specification.
548
 * Sets or uses line_ptrs, base, raster; uses width, color_info.depth,
549
 * num_planes, plane_depths, plane_depth.
550
 */
551
int
552
gdev_mem_set_line_ptrs(gx_device_memory *mdev, byte *base, int raster,
553
                       byte **line_ptrs, int setup_height)
554
163M
{
555
163M
    return gdev_mem_set_line_ptrs_interleaved(mdev, base, raster, line_ptrs, setup_height, 0);
556
163M
}
557
int
558
gdev_mem_set_line_ptrs_interleaved(gx_device_memory * mdev, byte * base,
559
                                   int raster, byte **line_ptrs,
560
                                   int setup_height, int interleaved)
561
169M
{
562
169M
    int num_planes = (mdev->num_planar_planes ? mdev->num_planar_planes : 0);
563
169M
    byte **pline;
564
169M
    byte *data;
565
169M
    int pi;
566
169M
    int plane_raster;
567
568
    /* If we are supplied with line_ptrs, then assume that we don't have
569
     * any already, and take them on. */
570
169M
    if (line_ptrs)
571
163M
        mdev->line_ptrs = line_ptrs;
572
169M
    pline = mdev->line_ptrs;
573
574
    /* If we are supplied a base, then we are supplied a raster. Assume that
575
     * we don't have any buffer already, and take these on. Assume that the
576
     * base has been allocated with sufficient padding to allow for any
577
     * alignment required. */
578
169M
    if (base == NULL) {
579
6.43M
        base = mdev->base;
580
6.43M
        raster = mdev->raster;
581
163M
    } else {
582
163M
        mdev->base = base;
583
163M
        mdev->raster = raster;
584
163M
    }
585
586
    /* Now, pad and align as required. */
587
169M
    if (mdev->log2_align_mod > log2_align_bitmap_mod) {
588
0
        int align = 1<<mdev->log2_align_mod;
589
0
        align = (-(int)(intptr_t)base) & (align-1);
590
0
        data = base + align;
591
169M
    } else {
592
169M
        data = mdev->base;
593
169M
    }
594
595
169M
    if (num_planes) {
596
7.52M
        if (base && !mdev->plane_depth)
597
0
            return_error(gs_error_rangecheck);
598
162M
    } else {
599
162M
        num_planes = 1;
600
162M
    }
601
602
169M
    if (interleaved)
603
0
        plane_raster = raster, raster *= num_planes;
604
169M
    else
605
169M
        plane_raster = raster * mdev->height;
606
369M
    for (pi = 0; pi < num_planes; ++pi) {
607
199M
        byte **pptr = pline;
608
199M
        byte **pend = pptr + setup_height;
609
199M
        byte *scan_line = data;
610
611
873M
        while (pptr < pend) {
612
673M
            *pptr++ = scan_line;
613
673M
            scan_line += raster;
614
673M
        }
615
199M
        data += plane_raster;
616
199M
        pline += setup_height;  /* not mdev->height, see gxdevmem.h */
617
199M
    }
618
619
169M
    return 0;
620
169M
}
621
622
/* Return the initial transformation matrix */
623
void
624
mem_get_initial_matrix(gx_device * dev, gs_matrix * pmat)
625
1.65M
{
626
1.65M
    gx_device_memory * const mdev = (gx_device_memory *)dev;
627
628
1.65M
    pmat->xx = mdev->initial_matrix.xx;
629
1.65M
    pmat->xy = mdev->initial_matrix.xy;
630
1.65M
    pmat->yx = mdev->initial_matrix.yx;
631
1.65M
    pmat->yy = mdev->initial_matrix.yy;
632
1.65M
    pmat->tx = mdev->initial_matrix.tx;
633
1.65M
    pmat->ty = mdev->initial_matrix.ty;
634
1.65M
}
635
636
/* Close a memory device, freeing the data area if appropriate. */
637
int
638
mem_close(gx_device * dev)
639
166M
{
640
166M
    gx_device_memory * const mdev = (gx_device_memory *)dev;
641
642
166M
    if (mdev->bitmap_memory != 0) {
643
6.43k
        gs_free_object(mdev->bitmap_memory, mdev->base, "mem_close");
644
        /*
645
         * The following assignment is strictly for the benefit of one
646
         * client that is sloppy about using is_open properly.
647
         */
648
6.43k
        mdev->base = 0;
649
166M
    } else if (mdev->line_pointer_memory != 0) {
650
0
        gs_free_object(mdev->line_pointer_memory, mdev->line_ptrs,
651
0
                       "mem_close");
652
0
        mdev->line_ptrs = 0;  /* ibid. */
653
0
    }
654
166M
    return 0;
655
166M
}
656
657
/* Memory devices shouldn't allow their dimensions to change */
658
static int
659
mem_put_params(gx_device * dev, gs_param_list * plist)
660
6
{
661
6
    int code;
662
6
    int width = dev->width, height = dev->height;
663
6
    float xres = dev->HWResolution[0], yres = dev->HWResolution[1];
664
6
    float medw = dev->MediaSize[0], medh = dev->MediaSize[1];
665
666
6
    code = gx_default_put_params(dev, plist);
667
668
6
    dev->width = width;
669
6
    dev->height = height;
670
6
    dev->HWResolution[0] = xres;
671
6
    dev->HWResolution[1] = yres;
672
6
    dev->MediaSize[0] = medw;
673
6
    dev->MediaSize[1] = medh;
674
675
6
    return code;
676
6
}
677
678
/* Copy bits to a client. */
679
#undef chunk
680
#define chunk byte
681
int
682
mem_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect,
683
                       gs_get_bits_params_t * params)
684
152M
{
685
152M
    gx_device_memory * const mdev = (gx_device_memory *)dev;
686
152M
    gs_get_bits_options_t options = params->options;
687
152M
    int x = prect->p.x, w = prect->q.x - x, y = prect->p.y, h = prect->q.y - y;
688
689
152M
    if (options == 0) {
690
0
        params->options =
691
0
            (GB_ALIGN_STANDARD | GB_ALIGN_ANY) |
692
0
            (GB_RETURN_COPY | GB_RETURN_POINTER) |
693
0
            (GB_OFFSET_0 | GB_OFFSET_SPECIFIED | GB_OFFSET_ANY) |
694
0
            (GB_RASTER_STANDARD | GB_RASTER_SPECIFIED | GB_RASTER_ANY) |
695
0
            GB_PACKING_CHUNKY | GB_COLORS_NATIVE | GB_ALPHA_NONE;
696
0
        return_error(gs_error_rangecheck);
697
0
    }
698
152M
    if (mdev->line_ptrs == NULL)
699
0
        return_error(gs_error_rangecheck);
700
152M
    if ((w <= 0) | (h <= 0)) {
701
0
        if ((w | h) < 0)
702
0
            return_error(gs_error_rangecheck);
703
0
        return 0;
704
0
    }
705
152M
    if (x < 0 || w > dev->width - x ||
706
152M
        y < 0 || h > dev->height - y
707
152M
        )
708
0
        return_error(gs_error_rangecheck);
709
152M
    {
710
152M
        gs_get_bits_params_t copy_params;
711
152M
        byte **base = &scan_line_base(mdev, y);
712
152M
        int code;
713
714
152M
        copy_params.options =
715
152M
            GB_COLORS_NATIVE | GB_PACKING_CHUNKY | GB_ALPHA_NONE |
716
152M
            (mdev->raster ==
717
152M
             bitmap_raster(mdev->width * mdev->color_info.depth) ?
718
152M
             GB_RASTER_STANDARD : GB_RASTER_SPECIFIED);
719
152M
        copy_params.raster = mdev->raster;
720
152M
        code = gx_get_bits_return_pointer(dev, x, h, params,
721
152M
                                          &copy_params, base);
722
152M
        if (code >= 0)
723
111M
            return code;
724
41.4M
        return gx_get_bits_copy(dev, x, w, h, params, &copy_params, *base,
725
41.4M
                                gx_device_raster(dev, true));
726
152M
    }
727
152M
}
728
729
#if !ARCH_IS_BIG_ENDIAN
730
731
/*
732
 * Swap byte order in a rectangular subset of a bitmap.  If store = true,
733
 * assume the rectangle will be overwritten, so don't swap any bytes where
734
 * it doesn't matter.  The caller has already done a fit_fill or fit_copy.
735
 * Note that the coordinates are specified in bits, not in terms of the
736
 * actual device depth.
737
 */
738
void
739
mem_swap_byte_rect(byte * base, size_t raster, int x, int w, int h, bool store)
740
0
{
741
0
    int xbit = x & 31;
742
743
0
    if (store) {
744
0
        if (xbit + w > 64) { /* Operation spans multiple words. */
745
            /* Just swap the words at the left and right edges. */
746
0
            if (xbit != 0)
747
0
                mem_swap_byte_rect(base, raster, x, 1, h, false);
748
0
            x += w - 1;
749
0
            xbit = x & 31;
750
0
            if (xbit == 31)
751
0
                return;
752
0
            w = 1;
753
0
        }
754
0
    }
755
    /* Swap the entire rectangle (or what's left of it). */
756
0
    {
757
0
        byte *row = base + ((x >> 5) << 2);
758
0
        int nw = (xbit + w + 31) >> 5;
759
0
        int ny;
760
761
0
        for (ny = h; ny > 0; row += raster, --ny) {
762
0
            int nx = nw;
763
0
            bits32 *pw = (bits32 *) row;
764
765
0
            do {
766
0
                bits32 v = *pw;
767
768
0
                *pw++ = (v >> 24) + ((v >> 8) & 0xff00) +
769
0
                    ((v & 0xff00) << 8) + (v << 24);
770
0
            }
771
0
            while (--nx);
772
0
        }
773
0
    }
774
0
}
775
776
/* Copy a word-oriented rectangle to the client, swapping bytes as needed. */
777
int
778
mem_word_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect,
779
                       gs_get_bits_params_t * params)
780
0
{
781
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
782
0
    byte *src;
783
0
    size_t dev_raster = gx_device_raster(dev, 1);
784
0
    int x = prect->p.x;
785
0
    int w = prect->q.x - x;
786
0
    int y = prect->p.y;
787
0
    int h = prect->q.y - y;
788
0
    int bit_x, bit_w;
789
0
    int code;
790
791
0
    fit_fill_xywh(dev, x, y, w, h);
792
0
    if (w <= 0 || h <= 0) {
793
        /*
794
         * It's easiest to just keep going with an empty rectangle.
795
         * We pass the original rectangle to mem_get_bits_rectangle.
796
         */
797
0
        x = y = w = h = 0;
798
0
    }
799
0
    bit_x = x * dev->color_info.depth;
800
0
    bit_w = w * dev->color_info.depth;
801
802
0
    if(mdev->line_ptrs == NULL)
803
0
        return_error(gs_error_rangecheck);
804
805
0
    src = scan_line_base(mdev, y);
806
0
    mem_swap_byte_rect(src, dev_raster, bit_x, bit_w, h, false);
807
0
    code = mem_get_bits_rectangle(dev, prect, params);
808
0
    mem_swap_byte_rect(src, dev_raster, bit_x, bit_w, h, false);
809
0
    return code;
810
0
}
811
812
#endif /* !ARCH_IS_BIG_ENDIAN */
813
814
/* Map a r-g-b color to a color index for a mapped color memory device */
815
/* (2, 4, or 8 bits per pixel.) */
816
/* This requires searching the palette. */
817
gx_color_index
818
mem_mapped_map_rgb_color(gx_device * dev, const gx_color_value cv[])
819
0
{
820
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
821
0
    byte br = gx_color_value_to_byte(cv[0]);
822
823
0
    register const byte *pptr = mdev->palette.data;
824
0
    int cnt = mdev->palette.size;
825
0
    const byte *which = 0;  /* initialized only to pacify gcc */
826
0
    int best = 256 * 3;
827
828
0
    if (mdev->color_info.num_components != 1) {
829
        /* not 1 component, assume three */
830
        /* The comparison is rather simplistic, treating differences in */
831
        /* all components as equal. Better choices would be 'distance'  */
832
        /* in HLS space or other, but these would be much slower. */
833
        /* At least exact matches will be found.      */
834
0
        byte bg = gx_color_value_to_byte(cv[1]);
835
0
        byte bb = gx_color_value_to_byte(cv[2]);
836
837
0
        while ((cnt -= 3) >= 0) {
838
0
            register int diff = *pptr - br;
839
840
0
            if (diff < 0)
841
0
                diff = -diff;
842
0
            if (diff < best) { /* quick rejection */
843
0
                    int dg = pptr[1] - bg;
844
845
0
                if (dg < 0)
846
0
                    dg = -dg;
847
0
                if ((diff += dg) < best) { /* quick rejection */
848
0
                    int db = pptr[2] - bb;
849
850
0
                    if (db < 0)
851
0
                        db = -db;
852
0
                    if ((diff += db) < best)
853
0
                        which = pptr, best = diff;
854
0
                }
855
0
            }
856
0
            if (diff == 0) /* can't get any better than 0 diff */
857
0
                break;
858
0
            pptr += 3;
859
0
        }
860
0
    } else {
861
        /* Gray scale conversion. The palette is made of three equal  */
862
        /* components, so this case is simpler.       */
863
0
        while ((cnt -= 3) >= 0) {
864
0
            register int diff = *pptr - br;
865
866
0
            if (diff < 0)
867
0
                diff = -diff;
868
0
            if (diff < best) { /* quick rejection */
869
0
                which = pptr, best = diff;
870
0
            }
871
0
            if (diff == 0)
872
0
                break;
873
0
            pptr += 3;
874
0
        }
875
0
    }
876
0
    return (gx_color_index) ((which - mdev->palette.data) / 3);
877
0
}
878
879
/* Map a color index to a r-g-b color for a mapped color memory device. */
880
int
881
mem_mapped_map_color_rgb(gx_device * dev, gx_color_index color,
882
                         gx_color_value prgb[3])
883
0
{
884
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
885
0
    const byte *pptr = mdev->palette.data;
886
887
0
    if (pptr == NULL) {
888
0
        color = color * gx_max_color_value / ((1<<mdev->color_info.depth)-1);
889
0
        prgb[0] = color;
890
0
        prgb[1] = color;
891
0
        prgb[2] = color;
892
0
    } else {
893
0
        pptr += (int)color * 3;
894
895
0
        prgb[0] = gx_color_value_from_byte(pptr[0]);
896
0
        prgb[1] = gx_color_value_from_byte(pptr[1]);
897
0
        prgb[2] = gx_color_value_from_byte(pptr[2]);
898
0
    }
899
0
    return 0;
900
0
}
901
902
/*
903
 * Implement draw_thin_line using a distinguished procedure that serves
904
 * as the common marker for all memory devices.
905
 */
906
int
907
mem_draw_thin_line(gx_device *dev, fixed fx0, fixed fy0, fixed fx1, fixed fy1,
908
                   const gx_drawing_color *pdcolor,
909
                   gs_logical_operation_t lop,
910
                   fixed adjustx, fixed adjusty)
911
12.2M
{
912
12.2M
    return gx_default_draw_thin_line(dev, fx0, fy0, fx1, fy1, pdcolor, lop,
913
12.2M
                                     adjustx, adjusty);
914
12.2M
}
915
916
void mem_initialize_device_procs(gx_device *dev)
917
174M
{
918
174M
    set_dev_proc(dev, get_initial_matrix, mem_get_initial_matrix);
919
174M
    set_dev_proc(dev, sync_output, gx_default_sync_output);
920
174M
    set_dev_proc(dev, output_page, gx_default_output_page);
921
174M
    set_dev_proc(dev, close_device, mem_close);
922
174M
    set_dev_proc(dev, get_params, gx_default_get_params);
923
174M
    set_dev_proc(dev, put_params, mem_put_params);
924
174M
    set_dev_proc(dev, get_page_device, gx_forward_get_page_device);
925
174M
    set_dev_proc(dev, get_alpha_bits, gx_default_get_alpha_bits);
926
174M
    set_dev_proc(dev, fill_path, gx_default_fill_path);
927
174M
    set_dev_proc(dev, stroke_path, gx_default_stroke_path);
928
174M
    set_dev_proc(dev, fill_mask, gx_default_fill_mask);
929
174M
    set_dev_proc(dev, fill_trapezoid, gx_default_fill_trapezoid);
930
174M
    set_dev_proc(dev, fill_parallelogram, gx_default_fill_parallelogram);
931
174M
    set_dev_proc(dev, fill_triangle, gx_default_fill_triangle);
932
174M
    set_dev_proc(dev, draw_thin_line, mem_draw_thin_line);
933
174M
    set_dev_proc(dev, get_clipping_box, gx_default_get_clipping_box);
934
174M
    set_dev_proc(dev, begin_typed_image, gx_default_begin_typed_image);
935
174M
    set_dev_proc(dev, composite, gx_default_composite);
936
174M
    set_dev_proc(dev, get_hardware_params, gx_default_get_hardware_params);
937
174M
    set_dev_proc(dev, text_begin, gx_default_text_begin);
938
174M
    set_dev_proc(dev, transform_pixel_region, mem_transform_pixel_region);
939
940
    /* Defaults that may well get overridden. */
941
174M
    set_dev_proc(dev, open_device, mem_open);
942
174M
    set_dev_proc(dev, copy_alpha, gx_default_copy_alpha);
943
174M
    set_dev_proc(dev, map_cmyk_color, gx_default_map_cmyk_color);
944
174M
    set_dev_proc(dev, strip_tile_rectangle, gx_default_strip_tile_rectangle);
945
174M
    set_dev_proc(dev, get_bits_rectangle, mem_get_bits_rectangle);
946
174M
}
947
948
void mem_dev_initialize_device_procs(gx_device *dev)
949
174M
{
950
174M
    int depth = dev->color_info.depth;
951
174M
    const gdev_mem_functions *fns;
952
953
174M
    if (dev->num_planar_planes > 1)
954
0
        depth /= dev->num_planar_planes;
955
174M
    fns = gdev_mem_functions_for_bits(depth);
956
957
174M
    mem_initialize_device_procs(dev);
958
959
174M
    set_dev_proc(dev, map_rgb_color, fns->map_rgb_color);
960
174M
    set_dev_proc(dev, map_color_rgb, fns->map_color_rgb);
961
174M
    set_dev_proc(dev, fill_rectangle, fns->fill_rectangle);
962
174M
    set_dev_proc(dev, copy_mono, fns->copy_mono);
963
174M
    set_dev_proc(dev, copy_color, fns->copy_color);
964
174M
    set_dev_proc(dev, copy_alpha, fns->copy_alpha);
965
174M
    set_dev_proc(dev, strip_copy_rop2, fns->strip_copy_rop2);
966
174M
    set_dev_proc(dev, strip_tile_rectangle, fns->strip_tile_rectangle);
967
174M
}
968
969
void mem_word_dev_initialize_device_procs(gx_device *dev)
970
0
{
971
0
    const gdev_mem_functions *fns =
972
0
                gdev_mem_word_functions_for_bits(dev->color_info.depth);
973
974
0
    mem_initialize_device_procs(dev);
975
976
0
    set_dev_proc(dev, map_rgb_color, fns->map_rgb_color);
977
0
    set_dev_proc(dev, map_color_rgb, fns->map_color_rgb);
978
0
    set_dev_proc(dev, fill_rectangle, fns->fill_rectangle);
979
0
    set_dev_proc(dev, copy_mono, fns->copy_mono);
980
0
    set_dev_proc(dev, copy_color, fns->copy_color);
981
0
    set_dev_proc(dev, copy_alpha, fns->copy_alpha);
982
0
    set_dev_proc(dev, strip_copy_rop2, fns->strip_copy_rop2);
983
0
    set_dev_proc(dev, strip_tile_rectangle, fns->strip_tile_rectangle);
984
0
}