Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/base/gdevmem.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2022 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
/* 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
216
ENUM_PTRS_WITH(device_memory_enum_ptrs, gx_device_memory *mptr)
36
72
{
37
72
    return ENUM_USING(st_device_forward, vptr, sizeof(gx_device_forward), index - 4);
38
0
}
39
36
case 0: ENUM_RETURN((mptr->foreign_bits ? NULL : (void *)mptr->base));
40
36
case 1: ENUM_RETURN((mptr->foreign_line_pointers ? NULL : (void *)mptr->line_ptrs));
41
36
ENUM_STRING_PTR(2, gx_device_memory, palette);
42
36
case 3: ENUM_RETURN(mptr->owner);
43
216
ENUM_PTRS_END
44
static
45
36
RELOC_PTRS_WITH(device_memory_reloc_ptrs, gx_device_memory *mptr)
46
36
{
47
36
    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->is_planar)
54
0
            h *= mptr->color_info.num_components;
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
36
    } else if (!mptr->foreign_line_pointers) {
63
0
        RELOC_PTR(gx_device_memory, line_ptrs);
64
0
    }
65
36
    RELOC_CONST_STRING_PTR(gx_device_memory, palette);
66
36
    RELOC_PTR(gx_device_memory, owner);
67
36
    RELOC_USING(st_device_forward, vptr, sizeof(gx_device_forward));
68
36
}
69
36
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
63.1M
{
105
63.1M
    return ((uint)bits_per_pixel > 64 ? &mem_x_device :
106
63.1M
            mem_devices[bits_per_pixel]);
107
63.1M
}
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
89.8M
{
143
89.8M
    return ((uint)bits_per_pixel > 64 ? NULL : mem_fns[bits_per_pixel]);
144
89.8M
}
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
152M
{
169
    /*
170
     * We use the draw_thin_line procedure to mark memory devices.
171
     * See gdevmem.h.
172
     */
173
152M
    return (dev_proc(dev, draw_thin_line) == mem_draw_thin_line);
174
152M
}
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
59.6M
{
182
    /* Can never fail */
183
59.6M
    (void)gx_device_init((gx_device *) dev, (const gx_device *)mdproto,
184
59.6M
                         mem, true);
185
59.6M
    dev->stype = &st_device_memory;
186
59.6M
    switch (page_device) {
187
428
        case -1:
188
428
            set_dev_proc(dev, get_page_device, gx_default_get_page_device);
189
428
            break;
190
681k
        case 1:
191
681k
            set_dev_proc(dev, get_page_device, gx_page_device_get_page_device);
192
681k
            break;
193
59.6M
    }
194
    /* Preload the black and white cache. */
195
59.6M
    if (target == NULL) {
196
433
        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
433
        } else {
201
433
            dev->cached_colors.black = 0;
202
433
            dev->cached_colors.white = (1 << dev->color_info.depth) - 1;
203
433
        }
204
433
        dev->graphics_type_tag = GS_UNKNOWN_TAG;
205
59.6M
    } else {
206
59.6M
        gx_device_set_target((gx_device_forward *)dev, target);
207
        /* Forward the color mapping operations to the target. */
208
59.6M
        gx_device_forward_color_procs((gx_device_forward *) dev);
209
59.6M
        gx_device_copy_color_procs((gx_device *)dev, target);
210
59.6M
        dev->color_info.separable_and_linear = target->color_info.separable_and_linear;
211
59.6M
        dev->cached_colors = target->cached_colors;
212
59.6M
        dev->graphics_type_tag = target->graphics_type_tag; /* initialize to same as target */
213
214
59.6M
        set_dev_proc(dev, put_image, gx_forward_put_image);
215
59.6M
    }
216
59.6M
    if (dev->color_info.depth == 1) {
217
12.7M
        gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
218
12.7M
        uchar k;
219
220
12.7M
        if (target != 0) {
221
26.9M
            for (k = 0; k < target->color_info.num_components; k++) {
222
14.1M
                cv[k] = 0;
223
14.1M
            }
224
12.7M
        }
225
12.7M
       gdev_mem_mono_set_inverted(dev, (target == NULL ||
226
12.7M
                                   (*dev_proc(dev, encode_color))((gx_device *)dev, cv) != 0));
227
12.7M
    }
228
59.6M
    set_dev_proc(dev, dev_spec_op, mem_spec_op);
229
59.6M
    check_device_separable((gx_device *)dev);
230
59.6M
    gx_device_fill_in_procs((gx_device *)dev);
231
59.6M
    dev->band_y = 0;
232
59.6M
    dev->owner = target;
233
59.6M
}
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
3.62M
{
332
    /* Can never fail */
333
3.62M
    (void)gx_device_init((gx_device *)dev,
334
3.62M
                         (const gx_device *)&mem_mono_device,
335
3.62M
                         mem, true);
336
3.62M
    set_dev_proc(dev, get_page_device, gx_default_get_page_device);
337
3.62M
    gx_device_set_target((gx_device_forward *)dev, target);
338
3.62M
    dev->raster = gx_device_raster((gx_device *)dev, 1);
339
3.62M
    gdev_mem_mono_set_inverted(dev, true);
340
3.62M
    check_device_separable((gx_device *)dev);
341
3.62M
    gx_device_fill_in_procs((gx_device *)dev);
342
    /* Should this be forwarding, monochrome profile, or not set? MJV */
343
3.62M
    set_dev_proc(dev, get_profile, gx_forward_get_profile);
344
3.62M
    set_dev_proc(dev, set_graphics_type_tag, gx_forward_set_graphics_type_tag);
345
3.62M
    set_dev_proc(dev, dev_spec_op, mem_spec_op);
346
3.62M
    dev->owner = target;
347
    /* initialize to same tag as target */
348
3.62M
    dev->graphics_type_tag = target ? target->graphics_type_tag : GS_UNKNOWN_TAG;
349
3.62M
}
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
16.4M
{
355
16.4M
    if (black_is_1)
356
13.8M
        dev->palette = mem_mono_b_w_palette;
357
2.58M
    else
358
2.58M
        dev->palette = mem_mono_w_b_palette;
359
16.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 ulong
372
 */
373
int
374
gdev_mem_bits_size(const gx_device_memory * dev, int width, int height, ulong *psize)
375
8.04M
{
376
8.04M
    int num_planes;
377
8.04M
    gx_render_plane_t plane1;
378
8.04M
    const gx_render_plane_t *planes;
379
8.04M
    ulong size;
380
8.04M
    int pi;
381
382
8.04M
    if (dev->is_planar) {
383
406k
        num_planes = dev->color_info.num_components;
384
406k
        planes = dev->planes;
385
406k
    } else
386
7.64M
        planes = &plane1, plane1.depth = dev->color_info.depth, num_planes = 1;
387
20.3M
    for (size = 0, pi = 0; pi < num_planes; ++pi)
388
12.3M
        size += bitmap_raster_pad_align(width * planes[pi].depth, dev->pad, dev->log2_align_mod);
389
8.04M
    if (height != 0)
390
8.04M
        if (size > (max_ulong - ARCH_ALIGN_PTR_MOD) / (ulong)height)
391
0
            return_error(gs_error_VMerror);
392
8.04M
    size = ROUND_UP(size * height, ARCH_ALIGN_PTR_MOD);
393
8.04M
    if (dev->log2_align_mod > log2_align_bitmap_mod)
394
0
        size += 1<<dev->log2_align_mod;
395
8.04M
    *psize = size;
396
8.04M
    return 0;
397
8.04M
}
398
ulong
399
gdev_mem_line_ptrs_size(const gx_device_memory * dev, int width, int height)
400
5.39M
{
401
5.39M
    int num_planes = 1;
402
5.39M
    if (dev->is_planar)
403
284k
        num_planes = dev->color_info.num_components;
404
5.39M
    return (ulong)height * sizeof(byte *) * num_planes;
405
5.39M
}
406
int
407
gdev_mem_data_size(const gx_device_memory * dev, int width, int height, ulong *psize)
408
5.28M
{
409
5.28M
    ulong bits_size;
410
5.28M
    ulong line_ptrs_size = gdev_mem_line_ptrs_size(dev, width, height);
411
412
5.28M
    if (gdev_mem_bits_size(dev, width, height, &bits_size) < 0 ||
413
5.28M
        bits_size > max_ulong - line_ptrs_size)
414
0
        return_error(gs_error_VMerror);
415
5.28M
    *psize = bits_size + line_ptrs_size;
416
5.28M
    return 0;
417
5.28M
}
418
/*
419
 * Do the inverse computation: given a width (in pixels) and a buffer size,
420
 * compute the maximum height.
421
 */
422
int
423
gdev_mem_max_height(const gx_device_memory * dev, int width, ulong size,
424
                    bool page_uses_transparency)
425
681k
{
426
681k
    int height;
427
681k
    ulong max_height;
428
681k
    ulong data_size;
429
681k
    bool deep = device_is_deep((const gx_device *)dev);
430
431
681k
    if (page_uses_transparency) {
432
        /*
433
         * If the device is using PDF 1.4 transparency then we will need to
434
         * also allocate image buffers for doing the blending operations.
435
         * We can only estimate the space requirements.  However since it
436
         * is only an estimate, we may exceed our desired buffer space while
437
         * processing the file.
438
         */
439
19.2k
        max_height = size / (bitmap_raster_pad_align(width
440
19.2k
            * dev->color_info.depth + ESTIMATED_PDF14_ROW_SPACE(width, dev->color_info.num_components, deep ? 16 : 8),
441
19.2k
                dev->pad, dev->log2_align_mod) + sizeof(byte *) * (dev->is_planar ? dev->color_info.num_components : 1));
442
19.2k
        height = (int)min(max_height, max_int);
443
662k
    } else {
444
        /* For non PDF 1.4 transparency, we can do an exact calculation */
445
662k
        max_height = size /
446
662k
            (bitmap_raster_pad_align(width * dev->color_info.depth, dev->pad, dev->log2_align_mod) +
447
662k
             sizeof(byte *) * (dev->is_planar ? dev->color_info.num_components : 1));
448
662k
        height = (int)min(max_height, max_int);
449
        /*
450
         * Because of alignment rounding, the just-computed height might
451
         * be too large by a small amount.  Adjust it the easy way.
452
         */
453
682k
        do {
454
682k
            gdev_mem_data_size(dev, width, height, &data_size);
455
682k
            if (data_size <= size)
456
662k
                break;
457
20.3k
            --height;
458
20.3k
        } while (data_size > size);
459
662k
    }
460
0
    return height;
461
681k
}
462
463
/* Open a memory device, allocating the data area if appropriate, */
464
/* and create the scan line table. */
465
int
466
mem_open(gx_device * dev)
467
1.97M
{
468
1.97M
    gx_device_memory *const mdev = (gx_device_memory *)dev;
469
470
    /* Check that we aren't trying to open a planar device as chunky. */
471
1.97M
    if (mdev->is_planar)
472
0
        return_error(gs_error_rangecheck);
473
1.97M
    return gdev_mem_open_scan_lines(mdev, dev->height);
474
1.97M
}
475
int
476
gdev_mem_open_scan_lines(gx_device_memory *mdev, int setup_height)
477
1.97M
{
478
1.97M
    return gdev_mem_open_scan_lines_interleaved(mdev, setup_height, 0);
479
1.97M
}
480
int
481
gdev_mem_open_scan_lines_interleaved(gx_device_memory *mdev,
482
                                     int setup_height,
483
                                     int interleaved)
484
1.97M
{
485
1.97M
    bool line_pointers_adjacent = true;
486
1.97M
    ulong size;
487
488
1.97M
    if (setup_height < 0 || setup_height > mdev->height)
489
0
        return_error(gs_error_rangecheck);
490
1.97M
    if (mdev->bitmap_memory != NULL) {
491
7.21k
        int align;
492
        /* Allocate the data now. */
493
7.21k
        if (gdev_mem_bitmap_size(mdev, &size) < 0)
494
0
            return_error(gs_error_VMerror);
495
496
7.21k
        if ((uint) size != size)  /* ulong may be bigger than uint */
497
0
            return_error(gs_error_limitcheck);
498
7.21k
        mdev->base = gs_alloc_bytes(mdev->bitmap_memory, (uint)size,
499
7.21k
                                    "mem_open");
500
7.21k
        if (mdev->base == NULL)
501
0
            return_error(gs_error_VMerror);
502
7.21k
#ifdef PACIFY_VALGRIND
503
        /* If we end up writing the bitmap to the clist, we can get valgrind errors
504
         * because we write and read the padding at the end of each raster line.
505
         * Easiest to set the entire block.
506
         */
507
7.21k
        memset(mdev->base, 0x00, size);
508
7.21k
#endif
509
7.21k
        align = 1<<mdev->log2_align_mod;
510
7.21k
        mdev->base += (-(int)(intptr_t)mdev->base) & (align-1);
511
7.21k
        mdev->foreign_bits = false;
512
1.96M
    } else if (mdev->line_pointer_memory != NULL) {
513
        /* Allocate the line pointers now. */
514
515
0
        mdev->line_ptrs = (byte **)
516
0
            gs_alloc_byte_array(mdev->line_pointer_memory, mdev->height,
517
0
                                sizeof(byte *) * (mdev->is_planar ? mdev->color_info.num_components : 1),
518
0
                                "gdev_mem_open_scan_lines");
519
0
        if (mdev->line_ptrs == NULL)
520
0
            return_error(gs_error_VMerror);
521
0
        mdev->foreign_line_pointers = false;
522
0
        line_pointers_adjacent = false;
523
0
    }
524
1.97M
    if (line_pointers_adjacent) {
525
1.97M
        int code;
526
527
1.97M
        if (mdev->base == NULL)
528
0
            return_error(gs_error_rangecheck);
529
530
1.97M
        code = gdev_mem_bits_size(mdev, mdev->width, mdev->height, &size);
531
1.97M
        if (code < 0)
532
0
            return code;
533
534
1.97M
        mdev->line_ptrs = (byte **)(mdev->base + size);
535
1.97M
    }
536
1.97M
    mdev->raster = gx_device_raster((gx_device *)mdev, 1);
537
1.97M
    return gdev_mem_set_line_ptrs_interleaved(mdev, NULL, 0, NULL,
538
1.97M
                                              setup_height,
539
1.97M
                                              interleaved);
540
1.97M
}
541
/*
542
 * Set up the scan line pointers of a memory device.
543
 * See gxdevmem.h for the detailed specification.
544
 * Sets or uses line_ptrs, base, raster; uses width, color_info.depth,
545
 * num_planes, plane_depths, plane_depth.
546
 */
547
int
548
gdev_mem_set_line_ptrs(gx_device_memory *mdev, byte *base, int raster,
549
                       byte **line_ptrs, int setup_height)
550
59.4M
{
551
59.4M
    return gdev_mem_set_line_ptrs_interleaved(mdev, base, raster, line_ptrs, setup_height, 0);
552
59.4M
}
553
int
554
gdev_mem_set_line_ptrs_interleaved(gx_device_memory * mdev, byte * base,
555
                                   int raster, byte **line_ptrs,
556
                                   int setup_height, int interleaved)
557
61.4M
{
558
61.4M
    int num_planes = (mdev->is_planar ? mdev->color_info.num_components : 0);
559
61.4M
    byte **pline;
560
61.4M
    byte *data;
561
61.4M
    int pi;
562
61.4M
    int plane_raster;
563
564
    /* If we are supplied with line_ptrs, then assume that we don't have
565
     * any already, and take them on. */
566
61.4M
    if (line_ptrs)
567
59.4M
        mdev->line_ptrs = line_ptrs;
568
61.4M
    pline = mdev->line_ptrs;
569
570
    /* If we are supplied a base, then we are supplied a raster. Assume that
571
     * we don't have any buffer already, and take these on. Assume that the
572
     * base has been allocated with sufficient padding to allow for any
573
     * alignment required. */
574
61.4M
    if (base == NULL) {
575
1.97M
        base = mdev->base;
576
1.97M
        raster = mdev->raster;
577
59.4M
    } else {
578
59.4M
        mdev->base = base;
579
59.4M
        mdev->raster = raster;
580
59.4M
    }
581
582
    /* Now, pad and align as required. */
583
61.4M
    if (mdev->log2_align_mod > log2_align_bitmap_mod) {
584
0
        int align = 1<<mdev->log2_align_mod;
585
0
        align = (-(int)(intptr_t)base) & (align-1);
586
0
        data = base + align;
587
61.4M
    } else {
588
61.4M
        data = mdev->base;
589
61.4M
    }
590
591
61.4M
    if (num_planes) {
592
462k
        if (base && !mdev->plane_depth)
593
0
            return_error(gs_error_rangecheck);
594
61.0M
    } else {
595
61.0M
        num_planes = 1;
596
61.0M
    }
597
598
61.4M
    if (interleaved)
599
0
        plane_raster = raster, raster *= num_planes;
600
61.4M
    else
601
61.4M
        plane_raster = raster * mdev->height;
602
124M
    for (pi = 0; pi < num_planes; ++pi) {
603
62.8M
        byte **pptr = pline;
604
62.8M
        byte **pend = pptr + setup_height;
605
62.8M
        byte *scan_line = data;
606
607
282M
        while (pptr < pend) {
608
219M
            *pptr++ = scan_line;
609
219M
            scan_line += raster;
610
219M
        }
611
62.8M
        data += plane_raster;
612
62.8M
        pline += setup_height;  /* not mdev->height, see gxdevmem.h */
613
62.8M
    }
614
615
61.4M
    return 0;
616
61.4M
}
617
618
/* Return the initial transformation matrix */
619
void
620
mem_get_initial_matrix(gx_device * dev, gs_matrix * pmat)
621
335k
{
622
335k
    gx_device_memory * const mdev = (gx_device_memory *)dev;
623
624
335k
    pmat->xx = mdev->initial_matrix.xx;
625
335k
    pmat->xy = mdev->initial_matrix.xy;
626
335k
    pmat->yx = mdev->initial_matrix.yx;
627
335k
    pmat->yy = mdev->initial_matrix.yy;
628
335k
    pmat->tx = mdev->initial_matrix.tx;
629
335k
    pmat->ty = mdev->initial_matrix.ty;
630
335k
}
631
632
/* Close a memory device, freeing the data area if appropriate. */
633
int
634
mem_close(gx_device * dev)
635
60.7M
{
636
60.7M
    gx_device_memory * const mdev = (gx_device_memory *)dev;
637
638
60.7M
    if (mdev->bitmap_memory != 0) {
639
280
        gs_free_object(mdev->bitmap_memory, mdev->base, "mem_close");
640
        /*
641
         * The following assignment is strictly for the benefit of one
642
         * client that is sloppy about using is_open properly.
643
         */
644
280
        mdev->base = 0;
645
60.7M
    } else if (mdev->line_pointer_memory != 0) {
646
0
        gs_free_object(mdev->line_pointer_memory, mdev->line_ptrs,
647
0
                       "mem_close");
648
0
        mdev->line_ptrs = 0;  /* ibid. */
649
0
    }
650
60.7M
    return 0;
651
60.7M
}
652
653
/* Copy bits to a client. */
654
#undef chunk
655
#define chunk byte
656
int
657
mem_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect,
658
                       gs_get_bits_params_t * params)
659
58.4M
{
660
58.4M
    gx_device_memory * const mdev = (gx_device_memory *)dev;
661
58.4M
    gs_get_bits_options_t options = params->options;
662
58.4M
    int x = prect->p.x, w = prect->q.x - x, y = prect->p.y, h = prect->q.y - y;
663
664
58.4M
    if (options == 0) {
665
0
        params->options =
666
0
            (GB_ALIGN_STANDARD | GB_ALIGN_ANY) |
667
0
            (GB_RETURN_COPY | GB_RETURN_POINTER) |
668
0
            (GB_OFFSET_0 | GB_OFFSET_SPECIFIED | GB_OFFSET_ANY) |
669
0
            (GB_RASTER_STANDARD | GB_RASTER_SPECIFIED | GB_RASTER_ANY) |
670
0
            GB_PACKING_CHUNKY | GB_COLORS_NATIVE | GB_ALPHA_NONE;
671
0
        return_error(gs_error_rangecheck);
672
0
    }
673
58.4M
    if (mdev->line_ptrs == NULL)
674
0
        return_error(gs_error_rangecheck);
675
58.4M
    if ((w <= 0) | (h <= 0)) {
676
0
        if ((w | h) < 0)
677
0
            return_error(gs_error_rangecheck);
678
0
        return 0;
679
0
    }
680
58.4M
    if (x < 0 || w > dev->width - x ||
681
58.4M
        y < 0 || h > dev->height - y
682
58.4M
        )
683
0
        return_error(gs_error_rangecheck);
684
58.4M
    {
685
58.4M
        gs_get_bits_params_t copy_params;
686
58.4M
        byte **base = &scan_line_base(mdev, y);
687
58.4M
        int code;
688
689
58.4M
        copy_params.options =
690
58.4M
            GB_COLORS_NATIVE | GB_PACKING_CHUNKY | GB_ALPHA_NONE |
691
58.4M
            (mdev->raster ==
692
58.4M
             bitmap_raster(mdev->width * mdev->color_info.depth) ?
693
58.4M
             GB_RASTER_STANDARD : GB_RASTER_SPECIFIED);
694
58.4M
        copy_params.raster = mdev->raster;
695
58.4M
        code = gx_get_bits_return_pointer(dev, x, h, params,
696
58.4M
                                          &copy_params, base);
697
58.4M
        if (code >= 0)
698
47.6M
            return code;
699
10.7M
        return gx_get_bits_copy(dev, x, w, h, params, &copy_params, *base,
700
10.7M
                                gx_device_raster(dev, true));
701
58.4M
    }
702
58.4M
}
703
704
#if !ARCH_IS_BIG_ENDIAN
705
706
/*
707
 * Swap byte order in a rectangular subset of a bitmap.  If store = true,
708
 * assume the rectangle will be overwritten, so don't swap any bytes where
709
 * it doesn't matter.  The caller has already done a fit_fill or fit_copy.
710
 * Note that the coordinates are specified in bits, not in terms of the
711
 * actual device depth.
712
 */
713
void
714
mem_swap_byte_rect(byte * base, uint raster, int x, int w, int h, bool store)
715
0
{
716
0
    int xbit = x & 31;
717
718
0
    if (store) {
719
0
        if (xbit + w > 64) { /* Operation spans multiple words. */
720
            /* Just swap the words at the left and right edges. */
721
0
            if (xbit != 0)
722
0
                mem_swap_byte_rect(base, raster, x, 1, h, false);
723
0
            x += w - 1;
724
0
            xbit = x & 31;
725
0
            if (xbit == 31)
726
0
                return;
727
0
            w = 1;
728
0
        }
729
0
    }
730
    /* Swap the entire rectangle (or what's left of it). */
731
0
    {
732
0
        byte *row = base + ((x >> 5) << 2);
733
0
        int nw = (xbit + w + 31) >> 5;
734
0
        int ny;
735
736
0
        for (ny = h; ny > 0; row += raster, --ny) {
737
0
            int nx = nw;
738
0
            bits32 *pw = (bits32 *) row;
739
740
0
            do {
741
0
                bits32 v = *pw;
742
743
0
                *pw++ = (v >> 24) + ((v >> 8) & 0xff00) +
744
0
                    ((v & 0xff00) << 8) + (v << 24);
745
0
            }
746
0
            while (--nx);
747
0
        }
748
0
    }
749
0
}
750
751
/* Copy a word-oriented rectangle to the client, swapping bytes as needed. */
752
int
753
mem_word_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect,
754
                       gs_get_bits_params_t * params)
755
0
{
756
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
757
0
    byte *src;
758
0
    uint dev_raster = gx_device_raster(dev, 1);
759
0
    int x = prect->p.x;
760
0
    int w = prect->q.x - x;
761
0
    int y = prect->p.y;
762
0
    int h = prect->q.y - y;
763
0
    int bit_x, bit_w;
764
0
    int code;
765
766
0
    fit_fill_xywh(dev, x, y, w, h);
767
0
    if (w <= 0 || h <= 0) {
768
        /*
769
         * It's easiest to just keep going with an empty rectangle.
770
         * We pass the original rectangle to mem_get_bits_rectangle.
771
         */
772
0
        x = y = w = h = 0;
773
0
    }
774
0
    bit_x = x * dev->color_info.depth;
775
0
    bit_w = w * dev->color_info.depth;
776
777
0
    if(mdev->line_ptrs == NULL)
778
0
        return_error(gs_error_rangecheck);
779
780
0
    src = scan_line_base(mdev, y);
781
0
    mem_swap_byte_rect(src, dev_raster, bit_x, bit_w, h, false);
782
0
    code = mem_get_bits_rectangle(dev, prect, params);
783
0
    mem_swap_byte_rect(src, dev_raster, bit_x, bit_w, h, false);
784
0
    return code;
785
0
}
786
787
#endif /* !ARCH_IS_BIG_ENDIAN */
788
789
/* Map a r-g-b color to a color index for a mapped color memory device */
790
/* (2, 4, or 8 bits per pixel.) */
791
/* This requires searching the palette. */
792
gx_color_index
793
mem_mapped_map_rgb_color(gx_device * dev, const gx_color_value cv[])
794
0
{
795
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
796
0
    byte br = gx_color_value_to_byte(cv[0]);
797
798
0
    register const byte *pptr = mdev->palette.data;
799
0
    int cnt = mdev->palette.size;
800
0
    const byte *which = 0;  /* initialized only to pacify gcc */
801
0
    int best = 256 * 3;
802
803
0
    if (mdev->color_info.num_components != 1) {
804
        /* not 1 component, assume three */
805
        /* The comparison is rather simplistic, treating differences in */
806
        /* all components as equal. Better choices would be 'distance'  */
807
        /* in HLS space or other, but these would be much slower. */
808
        /* At least exact matches will be found.      */
809
0
        byte bg = gx_color_value_to_byte(cv[1]);
810
0
        byte bb = gx_color_value_to_byte(cv[2]);
811
812
0
        while ((cnt -= 3) >= 0) {
813
0
            register int diff = *pptr - br;
814
815
0
            if (diff < 0)
816
0
                diff = -diff;
817
0
            if (diff < best) { /* quick rejection */
818
0
                    int dg = pptr[1] - bg;
819
820
0
                if (dg < 0)
821
0
                    dg = -dg;
822
0
                if ((diff += dg) < best) { /* quick rejection */
823
0
                    int db = pptr[2] - bb;
824
825
0
                    if (db < 0)
826
0
                        db = -db;
827
0
                    if ((diff += db) < best)
828
0
                        which = pptr, best = diff;
829
0
                }
830
0
            }
831
0
            if (diff == 0) /* can't get any better than 0 diff */
832
0
                break;
833
0
            pptr += 3;
834
0
        }
835
0
    } else {
836
        /* Gray scale conversion. The palette is made of three equal  */
837
        /* components, so this case is simpler.       */
838
0
        while ((cnt -= 3) >= 0) {
839
0
            register int diff = *pptr - br;
840
841
0
            if (diff < 0)
842
0
                diff = -diff;
843
0
            if (diff < best) { /* quick rejection */
844
0
                which = pptr, best = diff;
845
0
            }
846
0
            if (diff == 0)
847
0
                break;
848
0
            pptr += 3;
849
0
        }
850
0
    }
851
0
    return (gx_color_index) ((which - mdev->palette.data) / 3);
852
0
}
853
854
/* Map a color index to a r-g-b color for a mapped color memory device. */
855
int
856
mem_mapped_map_color_rgb(gx_device * dev, gx_color_index color,
857
                         gx_color_value prgb[3])
858
0
{
859
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
860
0
    const byte *pptr = mdev->palette.data;
861
862
0
    if (pptr == NULL) {
863
0
        color = color * gx_max_color_value / ((1<<mdev->color_info.depth)-1);
864
0
        prgb[0] = color;
865
0
        prgb[1] = color;
866
0
        prgb[2] = color;
867
0
    } else {
868
0
        pptr += (int)color * 3;
869
870
0
        prgb[0] = gx_color_value_from_byte(pptr[0]);
871
0
        prgb[1] = gx_color_value_from_byte(pptr[1]);
872
0
        prgb[2] = gx_color_value_from_byte(pptr[2]);
873
0
    }
874
0
    return 0;
875
0
}
876
877
/*
878
 * Implement draw_thin_line using a distinguished procedure that serves
879
 * as the common marker for all memory devices.
880
 */
881
int
882
mem_draw_thin_line(gx_device *dev, fixed fx0, fixed fy0, fixed fx1, fixed fy1,
883
                   const gx_drawing_color *pdcolor,
884
                   gs_logical_operation_t lop,
885
                   fixed adjustx, fixed adjusty)
886
7.13M
{
887
7.13M
    return gx_default_draw_thin_line(dev, fx0, fy0, fx1, fy1, pdcolor, lop,
888
7.13M
                                     adjustx, adjusty);
889
7.13M
}
890
891
void mem_initialize_device_procs(gx_device *dev)
892
63.2M
{
893
63.2M
    set_dev_proc(dev, get_initial_matrix, mem_get_initial_matrix);
894
63.2M
    set_dev_proc(dev, sync_output, gx_default_sync_output);
895
63.2M
    set_dev_proc(dev, output_page, gx_default_output_page);
896
63.2M
    set_dev_proc(dev, close_device, mem_close);
897
63.2M
    set_dev_proc(dev, get_params, gx_default_get_params);
898
63.2M
    set_dev_proc(dev, put_params, gx_default_put_params);
899
63.2M
    set_dev_proc(dev, get_page_device, gx_forward_get_page_device);
900
63.2M
    set_dev_proc(dev, get_alpha_bits, gx_default_get_alpha_bits);
901
63.2M
    set_dev_proc(dev, fill_path, gx_default_fill_path);
902
63.2M
    set_dev_proc(dev, stroke_path, gx_default_stroke_path);
903
63.2M
    set_dev_proc(dev, fill_mask, gx_default_fill_mask);
904
63.2M
    set_dev_proc(dev, fill_trapezoid, gx_default_fill_trapezoid);
905
63.2M
    set_dev_proc(dev, fill_parallelogram, gx_default_fill_parallelogram);
906
63.2M
    set_dev_proc(dev, fill_triangle, gx_default_fill_triangle);
907
63.2M
    set_dev_proc(dev, draw_thin_line, mem_draw_thin_line);
908
63.2M
    set_dev_proc(dev, get_clipping_box, gx_default_get_clipping_box);
909
63.2M
    set_dev_proc(dev, begin_typed_image, gx_default_begin_typed_image);
910
63.2M
    set_dev_proc(dev, composite, gx_default_composite);
911
63.2M
    set_dev_proc(dev, get_hardware_params, gx_default_get_hardware_params);
912
63.2M
    set_dev_proc(dev, text_begin, gx_default_text_begin);
913
63.2M
    set_dev_proc(dev, transform_pixel_region, mem_transform_pixel_region);
914
915
    /* Defaults that may well get overridden. */
916
63.2M
    set_dev_proc(dev, open_device, mem_open);
917
63.2M
    set_dev_proc(dev, copy_alpha, gx_default_copy_alpha);
918
63.2M
    set_dev_proc(dev, map_cmyk_color, gx_default_map_cmyk_color);
919
63.2M
    set_dev_proc(dev, strip_tile_rectangle, gx_default_strip_tile_rectangle);
920
63.2M
    set_dev_proc(dev, get_bits_rectangle, mem_get_bits_rectangle);
921
63.2M
}
922
923
void mem_dev_initialize_device_procs(gx_device *dev)
924
63.2M
{
925
63.2M
    int depth = dev->color_info.depth;
926
63.2M
    const gdev_mem_functions *fns;
927
928
63.2M
    if (dev->is_planar)
929
0
        depth /= dev->color_info.num_components;
930
63.2M
    fns = gdev_mem_functions_for_bits(depth);
931
932
63.2M
    mem_initialize_device_procs(dev);
933
934
63.2M
    set_dev_proc(dev, map_rgb_color, fns->map_rgb_color);
935
63.2M
    set_dev_proc(dev, map_color_rgb, fns->map_color_rgb);
936
63.2M
    set_dev_proc(dev, fill_rectangle, fns->fill_rectangle);
937
63.2M
    set_dev_proc(dev, copy_mono, fns->copy_mono);
938
63.2M
    set_dev_proc(dev, copy_color, fns->copy_color);
939
63.2M
    set_dev_proc(dev, copy_alpha, fns->copy_alpha);
940
63.2M
    set_dev_proc(dev, strip_copy_rop2, fns->strip_copy_rop2);
941
63.2M
    set_dev_proc(dev, strip_tile_rectangle, fns->strip_tile_rectangle);
942
63.2M
}
943
944
void mem_word_dev_initialize_device_procs(gx_device *dev)
945
0
{
946
0
    const gdev_mem_functions *fns =
947
0
                gdev_mem_word_functions_for_bits(dev->color_info.depth);
948
949
0
    mem_initialize_device_procs(dev);
950
951
0
    set_dev_proc(dev, map_rgb_color, fns->map_rgb_color);
952
0
    set_dev_proc(dev, map_color_rgb, fns->map_color_rgb);
953
0
    set_dev_proc(dev, fill_rectangle, fns->fill_rectangle);
954
0
    set_dev_proc(dev, copy_mono, fns->copy_mono);
955
0
    set_dev_proc(dev, copy_color, fns->copy_color);
956
0
    set_dev_proc(dev, copy_alpha, fns->copy_alpha);
957
0
    set_dev_proc(dev, strip_copy_rop2, fns->strip_copy_rop2);
958
0
    set_dev_proc(dev, strip_tile_rectangle, fns->strip_tile_rectangle);
959
0
}