Coverage Report

Created: 2022-04-16 11:23

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