Coverage Report

Created: 2022-04-16 11:23

/src/ghostpdl/base/gsdevice.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
17
/* Device operators for Ghostscript library */
18
#include "ctype_.h"
19
#include "memory_.h"    /* for memchr, memcpy */
20
#include "string_.h"
21
#include "gx.h"
22
#include "gp.h"
23
#include "gscdefs.h"    /* for gs_lib_device_list */
24
#include "gserrors.h"
25
#include "gsfname.h"
26
#include "gsstruct.h"
27
#include "gspath.h"   /* gs_initclip prototype */
28
#include "gspaint.h"    /* gs_erasepage prototype */
29
#include "gsmatrix.h"   /* for gscoord.h */
30
#include "gscoord.h"    /* for gs_initmatrix */
31
#include "gzstate.h"
32
#include "gxcmap.h"
33
#include "gxdevice.h"
34
#include "gxdevmem.h"
35
#include "gxdevsop.h"
36
#include "gxiodev.h"
37
#include "gxcspace.h"
38
#include "gsicc_manage.h"
39
#include "gscms.h"
40
#include "gxgetbit.h"
41
42
/* Include the extern for the device list. */
43
extern_gs_lib_device_list();
44
45
/*
46
 * Finalization for devices: do any special finalization first, then
47
 * close the device if it is open, and finally free the structure
48
 * descriptor if it is dynamic.
49
 */
50
void
51
gx_device_finalize(const gs_memory_t *cmem, void *vptr)
52
2.73M
{
53
2.73M
    gx_device * const dev = (gx_device *)vptr;
54
2.73M
    (void)cmem; /* unused */
55
56
2.73M
    discard(gs_closedevice(dev));
57
58
2.73M
    if (dev->icc_struct != NULL) {
59
48.2k
        rc_decrement(dev->icc_struct, "gx_device_finalize(icc_profile)");
60
48.2k
    }
61
62
    /* Deal with subclassed devices. Ordinarily these should not be a problem, we
63
     * will never see them, but if ths is a end of job restore we can end up
64
     * with the 'child' device(s) being freed before their parents. We need to make
65
     * sure we don't leave any dangling pointers in that case.
66
     */
67
2.73M
    if (dev->child)
68
0
        dev->child->parent = dev->parent;
69
2.73M
    if (dev->parent)
70
0
        dev->parent->child = dev->child;
71
2.73M
    if (dev->PageList) {
72
0
        rc_decrement(dev->PageList, "gx_device_finalize(PageList)");
73
0
        dev->PageList = 0;
74
0
    }
75
2.73M
    if (dev->NupControl) {
76
0
        rc_decrement(dev->NupControl, "gx_device_finalize(NupControl)");
77
0
        dev->NupControl = 0;
78
0
    }
79
80
2.73M
    if (dev->finalize)
81
2.73M
        dev->finalize(dev);
82
83
2.73M
    if (dev->stype_is_dynamic)
84
683
        gs_free_const_object(dev->memory->non_gc_memory, dev->stype,
85
683
                             "gx_device_finalize");
86
87
#ifdef DEBUG
88
    /* Slightly ugly hack: because the garbage collector makes no promises
89
     * about the order objects can be garbage collected, it is possible for
90
     * a forwarding device to remain in existence (awaiting garbage collection
91
     * itself) after it's target marked as free memory by the garbage collector.
92
     * In such a case, the normal reference counting is fine (since the garbage
93
     * collector leaves the object contents alone until is has completed its
94
     * sweep), but the reference counting debugging attempts to access the
95
     * memory header to output type information - and the header has been
96
     * overwritten by the garbage collector, causing a crash.
97
     * Setting the rc memory to NULL here should be safe, since the memory
98
     * is now in the hands of the garbage collector, and means we can check in
99
     * debugging code to ensure we don't try to use values that not longer exist
100
     * in the memmory header.
101
     * In the non-gc case, finalize is the very last thing to happen before the
102
     * memory is actually freed, so the rc.memory pointer is moot.
103
     * See rc_object_type_name()
104
     */
105
    if (gs_debug_c('^'))
106
        dev->rc.memory = NULL;
107
#endif
108
2.73M
}
109
110
/* "Free" a device locally allocated on the stack, by finalizing it. */
111
void
112
gx_device_free_local(gx_device *dev)
113
0
{
114
0
    gx_device_finalize(dev->memory, dev);
115
0
}
116
117
/* GC procedures */
118
static
119
0
ENUM_PTRS_WITH(device_enum_ptrs, gx_device *dev) return 0;
120
0
case 0:ENUM_RETURN(gx_device_enum_ptr(dev->parent));
121
0
case 1:ENUM_RETURN(gx_device_enum_ptr(dev->child));
122
0
ENUM_PTRS_END
123
0
static RELOC_PTRS_WITH(device_reloc_ptrs, gx_device *dev)
124
0
{
125
0
    dev->parent = gx_device_reloc_ptr(dev->parent, gcst);
126
0
    dev->child = gx_device_reloc_ptr(dev->child, gcst);
127
0
}
128
0
RELOC_PTRS_END
129
static
130
4.20k
ENUM_PTRS_WITH(device_forward_enum_ptrs, gx_device_forward *fdev) return 0;
131
1.40k
case 0: ENUM_RETURN(gx_device_enum_ptr(fdev->target));
132
4.20k
ENUM_PTRS_END
133
1.40k
static RELOC_PTRS_WITH(device_forward_reloc_ptrs, gx_device_forward *fdev)
134
1.40k
{
135
1.40k
    fdev->target = gx_device_reloc_ptr(fdev->target, gcst);
136
1.40k
}
137
1.40k
RELOC_PTRS_END
138
139
/*
140
 * Structure descriptors.  These must follow the procedures, because
141
 * we can't conveniently forward-declare the procedures.
142
 * (See gxdevice.h for details.)
143
 */
144
public_st_device();
145
public_st_device_forward();
146
public_st_device_null();
147
148
/* GC utilities */
149
/* Enumerate or relocate a device pointer for a client. */
150
gx_device *
151
gx_device_enum_ptr(gx_device * dev)
152
395k
{
153
395k
    if (dev == 0 || dev->memory == 0)
154
4.20k
        return 0;
155
391k
    return dev;
156
395k
}
157
gx_device *
158
gx_device_reloc_ptr(gx_device * dev, gc_state_t * gcst)
159
395k
{
160
395k
    if (dev == 0 || dev->memory == 0)
161
4.20k
        return dev;
162
391k
    return RELOC_OBJ(dev);  /* gcst implicit */
163
395k
}
164
165
/* Flush buffered output to the device */
166
int
167
gs_flushpage(gs_gstate * pgs)
168
683
{
169
683
    gx_device *dev = gs_currentdevice(pgs);
170
171
683
    return (*dev_proc(dev, sync_output)) (dev);
172
683
}
173
174
/* Make the device output the accumulated page description */
175
int
176
gs_copypage(gs_gstate * pgs)
177
0
{
178
0
    return gs_output_page(pgs, 1, 0);
179
0
}
180
int
181
gs_output_page(gs_gstate * pgs, int num_copies, int flush)
182
1.23k
{
183
1.23k
    gx_device *dev = gs_currentdevice(pgs);
184
1.23k
    cmm_dev_profile_t *dev_profile;
185
1.23k
    int code;
186
187
    /* for devices that hook 'fill_path' in order to pick up gs_gstate */
188
    /* values such as dev_ht (such as tiffsep1), make a dummy call here   */
189
    /* to make sure that it has been called at least once     */
190
1.23k
    code = gs_gsave(pgs);
191
1.23k
    if (code < 0)
192
0
        return code;
193
1.23k
    if (((code = gs_newpath(pgs)) < 0) ||
194
1.23k
        ((code = gs_moveto(pgs, 0.0, 0.0)) < 0) ||
195
1.23k
    ((code = gs_setgray(pgs, 0.0)) < 0) ||
196
1.23k
    ((code = gs_fill(pgs)) < 0))
197
0
    {
198
0
        gs_grestore(pgs);
199
0
        return code;
200
0
    }
201
1.23k
    code = gs_grestore(pgs);
202
1.23k
    if (code < 0)
203
0
        return code;
204
205
1.23k
    if (dev->IgnoreNumCopies)
206
0
        num_copies = 1;
207
1.23k
    if ((code = (*dev_proc(dev, output_page)) (dev, num_copies, flush)) < 0)
208
9
        return code;
209
210
1.22k
    code = dev_proc(dev, get_profile)(dev, &(dev_profile));
211
1.22k
    if (code < 0)
212
0
        return code;
213
1.22k
    if (dev_profile->graydetection && !dev_profile->pageneutralcolor) {
214
0
        dev_profile->pageneutralcolor = true;             /* start detecting again */
215
0
        code = gsicc_mcm_begin_monitor(pgs->icc_link_cache, dev);
216
0
    }
217
1.22k
    return code;
218
1.22k
}
219
220
/*
221
 * Do generic work for output_page.  All output_page procedures must call
222
 * this as the last thing they do, unless an error has occurred earlier.
223
 */
224
int
225
gx_finish_output_page(gx_device *dev, int num_copies, int flush)
226
1.22k
{
227
1.22k
    dev->PageCount += num_copies;
228
1.22k
    return 0;
229
1.22k
}
230
231
/* Copy scan lines from an image device */
232
int
233
gs_copyscanlines(gx_device * dev, int start_y, byte * data, uint size,
234
                 int *plines_copied, uint * pbytes_copied)
235
0
{
236
0
    uint line_size = gx_device_raster(dev, 0);
237
0
    uint count = size / line_size;
238
0
    uint i;
239
0
    byte *dest = data;
240
0
    gs_int_rect rect;
241
0
    gs_get_bits_params_t params;
242
243
0
    rect.p.x = 0;
244
0
    rect.q.x = dev->width;
245
0
    params.x_offset = 0;
246
0
    params.raster = bitmap_raster(dev->width * dev->color_info.depth);
247
248
0
    for (i = 0; i < count; i++, dest += line_size) {
249
0
        int code;
250
251
0
        rect.p.y = start_y+i;
252
0
        rect.q.y = start_y+i+1;
253
254
0
        params.options = (GB_ALIGN_ANY |
255
0
                          GB_RETURN_COPY |
256
0
                          GB_OFFSET_0 |
257
0
                          GB_RASTER_STANDARD | GB_PACKING_CHUNKY |
258
0
                          GB_COLORS_NATIVE | GB_ALPHA_NONE);
259
0
        params.data[0] = dest;
260
0
        code = (*dev_proc(dev, get_bits_rectangle))(dev, &rect, &params);
261
0
        if (code < 0) {
262
            /* Might just be an overrun. */
263
0
            if (start_y + i == dev->height)
264
0
                break;
265
0
            return_error(code);
266
0
        }
267
0
    }
268
0
    if (plines_copied != NULL)
269
0
        *plines_copied = i;
270
0
    if (pbytes_copied != NULL)
271
0
        *pbytes_copied = i * line_size;
272
0
    return 0;
273
0
}
274
275
/* Get the current device from the graphics state. */
276
gx_device *
277
gs_currentdevice(const gs_gstate * pgs)
278
136k
{
279
136k
    return pgs->device;
280
136k
}
281
282
/* Get the name of a device. */
283
const char *
284
gs_devicename(const gx_device * dev)
285
0
{
286
0
    return dev->dname;
287
0
}
288
289
/* Get the initial matrix of a device. */
290
void
291
gs_deviceinitialmatrix(gx_device * dev, gs_matrix * pmat)
292
2.63M
{
293
2.63M
    fill_dev_proc(dev, get_initial_matrix, gx_default_get_initial_matrix);
294
2.63M
    (*dev_proc(dev, get_initial_matrix)) (dev, pmat);
295
2.63M
}
296
297
/* Get the N'th device from the known device list */
298
const gx_device *
299
gs_getdevice(int index)
300
13.6k
{
301
13.6k
    const gx_device *const *list;
302
13.6k
    int count = gs_lib_device_list(&list, NULL);
303
304
13.6k
    if (index < 0 || index >= count)
305
1.36k
        return 0;    /* index out of range */
306
12.2k
    return list[index];
307
13.6k
}
308
309
/* Get the default device from the known device list */
310
const gx_device *
311
gs_getdefaultlibdevice(gs_memory_t *mem)
312
0
{
313
0
    const gx_device *const *list;
314
0
    int count = gs_lib_device_list(&list, NULL);
315
0
    const char *name, *end, *fin;
316
0
    int i;
317
318
    /* Search the compiled in device list for a known device name */
319
    /* In the case the lib ctx hasn't been initialised */
320
0
    if (mem && mem->gs_lib_ctx && mem->gs_lib_ctx->default_device_list) {
321
0
        name = mem->gs_lib_ctx->default_device_list;
322
0
        fin = name + strlen(name);
323
0
    }
324
0
    else {
325
0
        name = gs_dev_defaults;
326
0
        fin = name + strlen(name);
327
0
    }
328
329
    /* iterate through each name in the string */
330
0
    while (name < fin) {
331
332
      /* split a name from any whitespace */
333
0
      while ((name < fin) && (*name == ' ' || *name == '\t'))
334
0
        name++;
335
0
      end = name;
336
0
      while ((end < fin) && (*end != ' ') && (*end != '\t'))
337
0
        end++;
338
339
      /* return any matches */
340
0
      for (i = 0; i < count; i++)
341
0
        if ((end - name) == strlen(list[i]->dname))
342
0
          if (!memcmp(name, list[i]->dname, end - name))
343
0
            return gs_getdevice(i);
344
345
      /* otherwise, try the next device name */
346
0
      name = end;
347
0
    }
348
349
    /* Fall back to the first device in the list. */
350
0
    return gs_getdevice(0);
351
0
}
352
353
const gx_device *
354
gs_getdefaultdevice(void)
355
0
{
356
0
    return gs_getdefaultlibdevice(NULL);
357
0
}
358
359
/* Fill in the GC structure descriptor for a device. */
360
static void
361
gx_device_make_struct_type(gs_memory_struct_type_t *st,
362
                           const gx_device *dev)
363
683
{
364
683
    if (dev->stype)
365
683
        *st = *dev->stype;
366
0
    else if (dev_proc(dev, get_page_device) == gx_forward_get_page_device)
367
0
        *st = st_device_forward;
368
0
    else
369
0
        *st = st_device;
370
683
    st->ssize = dev->params_size;
371
683
}
372
373
/* Clone an existing device. */
374
int
375
gs_copydevice2(gx_device ** pnew_dev, const gx_device * dev, bool keep_open,
376
               gs_memory_t * mem)
377
48.9k
{
378
48.9k
    gx_device *new_dev;
379
48.9k
    const gs_memory_struct_type_t *std = dev->stype;
380
48.9k
    const gs_memory_struct_type_t *new_std;
381
48.9k
    gs_memory_struct_type_t *a_std = 0;
382
48.9k
    int code;
383
384
48.9k
    if (dev->stype_is_dynamic) {
385
        /*
386
         * We allocated the stype for this device previously.
387
         * Just allocate a new stype and copy the old one into it.
388
         */
389
0
        a_std = (gs_memory_struct_type_t *)
390
0
            gs_alloc_bytes_immovable(mem->non_gc_memory, sizeof(*std),
391
0
                                     "gs_copydevice(stype)");
392
0
        if (!a_std)
393
0
            return_error(gs_error_VMerror);
394
0
        *a_std = *std;
395
0
        new_std = a_std;
396
48.9k
    } else if (std != 0 && std->ssize == dev->params_size) {
397
        /* Use the static stype. */
398
48.2k
        new_std = std;
399
48.2k
    } else {
400
        /* We need to figure out or adjust the stype. */
401
683
        a_std = (gs_memory_struct_type_t *)
402
683
            gs_alloc_bytes_immovable(mem->non_gc_memory, sizeof(*std),
403
683
                                     "gs_copydevice(stype)");
404
683
        if (!a_std)
405
0
            return_error(gs_error_VMerror);
406
683
        gx_device_make_struct_type(a_std, dev);
407
683
        new_std = a_std;
408
683
    }
409
    /*
410
     * Because command list devices have complicated internal pointer
411
     * structures, we allocate all device instances as immovable.
412
     */
413
48.9k
    new_dev = gs_alloc_struct_immovable(mem, gx_device, new_std,
414
48.9k
                                        "gs_copydevice(device)");
415
48.9k
    if (new_dev == 0) {
416
0
        gs_free_object(mem->non_gc_memory, a_std, "gs_copydevice(stype)");
417
0
        return_error(gs_error_VMerror);
418
0
    }
419
48.9k
    code = gx_device_init(new_dev, dev, mem, false);
420
48.9k
    new_dev->stype = new_std;
421
48.9k
    new_dev->stype_is_dynamic = new_std != std;
422
    /*
423
     * keep_open is very dangerous.  On the other hand, so is copydevice in
424
     * general, since it just copies the bits without any regard to pointers
425
     * (including self-pointers) that they may contain.
426
     */
427
48.9k
    new_dev->is_open = dev->is_open && keep_open;
428
48.9k
    if (code < 0) {
429
0
        gs_free_object(mem, new_dev, "gs_copydevice(device)");
430
#if 0 /* gs_free_object above calls gx_device_finalize,
431
         which closes the device and releases its stype, i.e. a_std. */
432
        if (a_std)
433
            gs_free_object(dev->memory->non_gc_memory, a_std, "gs_copydevice(stype)");
434
#endif
435
0
        return code;
436
0
    }
437
    /* We really want to be able to interrogate the device for capabilities
438
     * and/or preferences right from when it is created, so set dev_spec_op
439
     * now (if not already set).
440
     */
441
48.9k
    fill_dev_proc(new_dev, dev_spec_op, gx_default_dev_spec_op);
442
48.9k
    *pnew_dev = new_dev;
443
48.9k
    return 0;
444
48.9k
}
445
int
446
gs_copydevice(gx_device ** pnew_dev, const gx_device * dev, gs_memory_t * mem)
447
48.2k
{
448
48.2k
    return gs_copydevice2(pnew_dev, dev, false, mem);
449
48.2k
}
450
451
/* Open a device if not open already.  Return 0 if the device was open, */
452
/* 1 if it was closed. */
453
int
454
gs_opendevice(gx_device *dev)
455
3.94k
{
456
3.94k
    if (dev->is_open)
457
0
        return 0;
458
3.94k
    check_device_separable(dev);
459
3.94k
    gx_device_fill_in_procs(dev);
460
3.94k
    {
461
3.94k
        int code = (*dev_proc(dev, open_device))(dev);
462
463
3.94k
        if (code < 0)
464
0
            return_error(code);
465
3.94k
        dev->is_open = true;
466
3.94k
        return 1;
467
3.94k
    }
468
3.94k
}
469
470
static void
471
gs_gstate_update_device(gs_gstate *pgs, gx_device *dev)
472
17.5k
{
473
17.5k
    gx_set_cmap_procs(pgs, dev);
474
17.5k
    gx_unset_both_dev_colors(pgs);
475
17.5k
}
476
477
int
478
gs_gstate_putdeviceparams(gs_gstate *pgs, gx_device *dev, gs_param_list *plist)
479
0
{
480
0
    int code;
481
0
    gx_device *dev2;
482
483
0
    if (dev)
484
0
       dev2 = dev;
485
0
    else
486
0
       dev2 = pgs->device;
487
488
0
    code = gs_putdeviceparams(dev2, plist);
489
0
    if (code >= 0)
490
0
        gs_gstate_update_device(pgs, dev2);
491
0
    return code;
492
0
}
493
494
/* Set the device in the graphics state */
495
int
496
gs_setdevice(gs_gstate * pgs, gx_device * dev)
497
0
{
498
0
    int code = gs_setdevice_no_erase(pgs, dev);
499
500
0
    if (code == 1)
501
0
        code = gs_erasepage(pgs);
502
0
    return code;
503
0
}
504
int
505
gs_setdevice_no_erase(gs_gstate * pgs, gx_device * dev)
506
8.42k
{
507
8.42k
    int open_code = 0, code;
508
8.42k
    gs_lib_ctx_t *libctx = gs_lib_ctx_get_interp_instance(pgs->memory);
509
510
    /* If the ICC manager is not yet initialized, set it up now.  But only
511
       if we have file io capability now */
512
8.42k
    if (libctx->io_device_table != NULL) {
513
7.74k
        cmm_dev_profile_t *dev_profile;
514
7.74k
        if (pgs->icc_manager->lab_profile == NULL) {  /* pick one not set externally */
515
1.35k
            code = gsicc_init_iccmanager(pgs);
516
1.35k
            if (code < 0)
517
0
                return(code);
518
1.35k
        }
519
        /* Also, if the device profile is not yet set then take care of that
520
           before we start filling pages, if we can */
521
        /* Although device methods should not be NULL, they are not completely filled in until
522
         * gx_device_fill_in_procs is called, and its possible for us to get here before this
523
         * happens, so we *must* make sure the method is not NULL before we use it.
524
         */
525
7.74k
        if (dev->procs.get_profile != NULL) {
526
6.39k
            code = dev_proc(dev, get_profile)(dev, &dev_profile);
527
6.39k
            if (code < 0) {
528
0
                return(code);
529
0
            }
530
6.39k
            if (dev_profile == NULL ||
531
6.39k
                dev_profile->device_profile[gsDEFAULTPROFILE] == NULL) {
532
0
                if ((code = gsicc_init_device_profile_struct(dev, NULL,
533
0
                                                        gsDEFAULTPROFILE)) < 0)
534
0
                    return(code);
535
                /* set the intent too */
536
0
                if ((code = gsicc_set_device_profile_intent(dev, gsRINOTSPECIFIED,
537
0
                                                       gsDEFAULTPROFILE)) < 0)
538
0
                    return(code);
539
0
            }
540
6.39k
        }
541
7.74k
    }
542
543
    /* Initialize the device */
544
8.42k
    if (!dev->is_open) {
545
3.94k
        gx_device_fill_in_procs(dev);
546
547
        /* If we have not yet done so, and if we can, set the device profile
548
         * Doing so *before* the device is opened means that a device which
549
         * opens other devices can pass a profile on - for example, pswrite
550
         * also opens a bbox device
551
         */
552
3.94k
        if (libctx->io_device_table != NULL) {
553
3.26k
            cmm_dev_profile_t *dev_profile;
554
            /* Although device methods should not be NULL, they are not completely filled in until
555
             * gx_device_fill_in_procs is called, and its possible for us to get here before this
556
             * happens, so we *must* make sure the method is not NULL before we use it.
557
             */
558
3.26k
            if (dev->procs.get_profile != NULL) {
559
3.26k
                code = dev_proc(dev, get_profile)(dev, &dev_profile);
560
3.26k
                if (code < 0) {
561
0
                    return(code);
562
0
                }
563
3.26k
                if (dev_profile == NULL ||
564
3.26k
                    dev_profile->device_profile[gsDEFAULTPROFILE] == NULL) {
565
669
                    if ((code = gsicc_init_device_profile_struct(dev, NULL,
566
669
                                                            gsDEFAULTPROFILE)) < 0)
567
0
                        return(code);
568
669
                }
569
3.26k
            }
570
3.26k
        }
571
572
3.94k
        if (gs_device_is_memory(dev)) {
573
            /* Set the target to the current device. */
574
0
            gx_device *odev = gs_currentdevice_inline(pgs);
575
576
0
            while (odev != 0 && gs_device_is_memory(odev))
577
0
                odev = ((gx_device_memory *)odev)->target;
578
0
            gx_device_set_target(((gx_device_forward *)dev), odev);
579
0
        }
580
3.94k
        code = open_code = gs_opendevice(dev);
581
3.94k
        if (code < 0)
582
0
            return code;
583
3.94k
    }
584
8.42k
    gs_setdevice_no_init(pgs, dev);
585
8.42k
    pgs->ctm_default_set = false;
586
8.42k
    if ((code = gs_initmatrix(pgs)) < 0 ||
587
8.42k
        (code = gs_initclip(pgs)) < 0
588
8.42k
        )
589
0
        return code;
590
    /* If we were in a charpath or a setcachedevice, */
591
    /* we aren't any longer. */
592
8.42k
    pgs->in_cachedevice = 0;
593
8.42k
    pgs->in_charpath = (gs_char_path_mode) 0;
594
8.42k
    return open_code;
595
8.42k
}
596
int
597
gs_setdevice_no_init(gs_gstate * pgs, gx_device * dev)
598
17.5k
{
599
    /*
600
     * Just set the device, possibly changing color space but no other
601
     * device parameters.
602
     *
603
     * Make sure we don't close the device if dev == pgs->device
604
     * This could be done by allowing the rc_assign to close the
605
     * old 'dev' if the rc goes to 0 (via the device structure's
606
     * finalization procedure), but then the 'code' from the dev
607
     * closedevice would not be propagated up. We want to allow
608
     * the code to be handled, particularly for the pdfwrite
609
     * device.
610
     */
611
17.5k
    if (pgs->device != NULL && pgs->device->rc.ref_count == 1 &&
612
17.5k
        pgs->device != dev) {
613
683
        int code = gs_closedevice(pgs->device);
614
615
683
        if (code < 0)
616
0
            return code;
617
683
    }
618
17.5k
    rc_assign(pgs->device, dev, "gs_setdevice_no_init");
619
17.5k
    gs_gstate_update_device(pgs, dev);
620
17.5k
    return 0;
621
17.5k
}
622
623
/* Initialize a just-allocated device. */
624
int
625
gx_device_init(gx_device * dev, const gx_device * proto, gs_memory_t * mem,
626
               bool internal)
627
2.88M
{
628
2.88M
    memcpy(dev, proto, proto->params_size);
629
2.88M
    dev->initialize_device_procs = proto->initialize_device_procs;
630
2.88M
    if (dev->initialize_device_procs != NULL)
631
2.88M
        dev->initialize_device_procs(dev);
632
2.88M
    dev->memory = mem;    /* must precede initialize_device call so devices can use it */
633
2.88M
    if (dev->procs.initialize_device) {
634
44.6k
        int code = dev->procs.initialize_device(dev);
635
44.6k
        if (code < 0)
636
0
            return code;
637
44.6k
    }
638
2.88M
    dev->retained = !internal;
639
2.88M
    rc_init(dev, mem, (internal ? 0 : 1));
640
2.88M
    rc_increment(dev->icc_struct);
641
642
2.88M
    return 0;
643
2.88M
}
644
645
void
646
gx_device_init_on_stack(gx_device * dev, const gx_device * proto,
647
                        gs_memory_t * mem)
648
583k
{
649
583k
    memcpy(dev, proto, proto->params_size);
650
583k
    dev->initialize_device_procs = proto->initialize_device_procs;
651
583k
    dev->initialize_device_procs(dev);
652
583k
    if (dev->procs.initialize_device) {
653
        /* A condition of devices inited on the stack is that they can
654
         * never fail to initialize! */
655
0
        (void)dev->procs.initialize_device(dev);
656
0
    }
657
583k
    gx_device_fill_in_procs(dev);
658
583k
    dev->memory = mem;
659
583k
    dev->retained = 0;
660
583k
    dev->pad = proto->pad;
661
583k
    dev->log2_align_mod = proto->log2_align_mod;
662
583k
    dev->is_planar = proto->is_planar;
663
583k
    rc_init(dev, NULL, 0);
664
583k
}
665
666
/* Make a null device. */
667
void
668
gs_make_null_device(gx_device_null *dev_null, gx_device *dev,
669
                    gs_memory_t * mem)
670
8.45k
{
671
    /* Can never fail */
672
8.45k
    (void)gx_device_init((gx_device *)dev_null,
673
8.45k
                         (const gx_device *)&gs_null_device,
674
8.45k
                         mem, true);
675
8.45k
    gx_device_fill_in_procs((gx_device *)dev_null);
676
8.45k
    gx_device_set_target((gx_device_forward *)dev_null, dev);
677
8.45k
    if (dev) {
678
        /* The gx_device_copy_color_params() call below should
679
           probably copy over these new-style color mapping procs, as
680
           well as the old-style (map_rgb_color and friends). However,
681
           the change was made here instead, to minimize the potential
682
           impact of the patch.
683
        */
684
8.45k
        gx_device *dn = (gx_device *)dev_null;
685
8.45k
        set_dev_proc(dn, get_color_mapping_procs, gx_forward_get_color_mapping_procs);
686
8.45k
        set_dev_proc(dn, get_color_comp_index, gx_forward_get_color_comp_index);
687
8.45k
        set_dev_proc(dn, encode_color, gx_forward_encode_color);
688
8.45k
        set_dev_proc(dn, decode_color, gx_forward_decode_color);
689
8.45k
        set_dev_proc(dn, get_profile, gx_forward_get_profile);
690
8.45k
        set_dev_proc(dn, set_graphics_type_tag, gx_forward_set_graphics_type_tag);
691
8.45k
        set_dev_proc(dn, begin_transparency_group, gx_default_begin_transparency_group);
692
8.45k
        set_dev_proc(dn, end_transparency_group, gx_default_end_transparency_group);
693
8.45k
        set_dev_proc(dn, begin_transparency_mask, gx_default_begin_transparency_mask);
694
8.45k
        set_dev_proc(dn, end_transparency_mask, gx_default_end_transparency_mask);
695
8.45k
        set_dev_proc(dn, discard_transparency_layer, gx_default_discard_transparency_layer);
696
8.45k
        set_dev_proc(dn, push_transparency_state, gx_default_push_transparency_state);
697
8.45k
        set_dev_proc(dn, pop_transparency_state, gx_default_pop_transparency_state);
698
8.45k
        set_dev_proc(dn, put_image, gx_default_put_image);
699
8.45k
        set_dev_proc(dn, copy_planes, gx_default_copy_planes);
700
8.45k
        set_dev_proc(dn, copy_alpha_hl_color, gx_default_no_copy_alpha_hl_color);
701
8.45k
        dn->graphics_type_tag = dev->graphics_type_tag; /* initialize to same as target */
702
8.45k
        gx_device_copy_color_params(dn, dev);
703
8.45k
    }
704
8.45k
}
705
706
/* Is a null device ? */
707
bool gs_is_null_device(gx_device *dev)
708
202k
{
709
    /* Assuming null_fill_path isn't used elswhere. */
710
202k
    return dev->procs.fill_path == gs_null_device.procs.fill_path;
711
202k
}
712
713
/* Mark a device as retained or not retained. */
714
void
715
gx_device_retain(gx_device *dev, bool retained)
716
2.78M
{
717
2.78M
    int delta = (int)retained - (int)dev->retained;
718
719
2.78M
    if (delta) {
720
2.78M
        dev->retained = retained; /* do first in case dev is freed */
721
2.78M
        rc_adjust_only(dev, delta, "gx_device_retain");
722
2.78M
    }
723
2.78M
}
724
725
/* Select a null device. */
726
int
727
gs_nulldevice(gs_gstate * pgs)
728
3.26k
{
729
3.26k
    int code = 0;
730
3.26k
    gs_gstate *spgs;
731
3.26k
    bool saveLockSafety = false;
732
3.26k
    if (pgs->device == NULL || !gx_device_is_null(pgs->device)) {
733
3.26k
        gx_device *ndev;
734
3.26k
        code = gs_copydevice(&ndev, (const gx_device *)&gs_null_device,
735
3.26k
                                 pgs->memory);
736
737
3.26k
        if (code < 0)
738
0
            return code;
739
3.26k
        if (gs_currentdevice_inline(pgs) != NULL)
740
1.91k
            saveLockSafety = gs_currentdevice_inline(pgs)->LockSafetyParams;
741
        /*
742
         * Internal devices have a reference count of 0, not 1,
743
         * aside from references from graphics states.
744
         */
745
        /* There is some strange use of the null device in the code.  I need
746
           to sort out how the icc profile is best handled with this device.
747
           It seems to inherit properties from the current device if there
748
           is one */
749
3.26k
        rc_init(ndev, pgs->memory, 0);
750
3.26k
        if (pgs->device != NULL) {
751
1.91k
            if ((code = dev_proc(pgs->device, get_profile)(pgs->device,
752
1.91k
                                               &(ndev->icc_struct))) < 0)
753
0
                return code;
754
1.91k
            rc_increment(ndev->icc_struct);
755
1.91k
            set_dev_proc(ndev, get_profile, gx_default_get_profile);
756
1.91k
        }
757
758
3.26k
        if (gs_setdevice_no_erase(pgs, ndev) < 0) {
759
0
            gs_free_object(pgs->memory, ndev, "gs_copydevice(device)");
760
            /* We are out of options: find the device we installed in
761
               the initial graphics state, and put that in place.
762
               We just need something so we can end this job cleanly.
763
             */
764
0
            spgs = pgs->saved;
765
0
            if (spgs != NULL) {
766
0
                while (spgs->saved) spgs = spgs->saved;
767
0
                gs_currentdevice_inline(pgs) = gs_currentdevice_inline(spgs);
768
0
                rc_increment(gs_currentdevice_inline(pgs));
769
0
            }
770
0
            code = gs_note_error(gs_error_Fatal);
771
0
        }
772
3.26k
        if (gs_currentdevice_inline(pgs) != NULL)
773
3.26k
            gs_currentdevice_inline(pgs)->LockSafetyParams = saveLockSafety;
774
3.26k
    }
775
3.26k
    return code;
776
3.26k
}
777
778
/* Close a device.  The client is responsible for ensuring that */
779
/* this device is not current in any graphics state. */
780
int
781
gs_closedevice(gx_device * dev)
782
2.73M
{
783
2.73M
    int code = 0;
784
785
2.73M
    if (dev->is_open) {
786
14.1k
        code = (*dev_proc(dev, close_device))(dev);
787
14.1k
        dev->is_open = false;
788
14.1k
        if (code < 0)
789
0
            return_error(code);
790
14.1k
    }
791
2.73M
    return code;
792
2.73M
}
793
794
/*
795
 * Just set the device without any reinitializing.
796
 * (For internal use only.)
797
 */
798
void
799
gx_set_device_only(gs_gstate * pgs, gx_device * dev)
800
134k
{
801
134k
    rc_assign(pgs->device, dev, "gx_set_device_only");
802
134k
}
803
804
/* Compute the size of one scan line for a device. */
805
/* If pad = 0 return the line width in bytes. If pad = 1,
806
 * return the actual raster value (the number of bytes to offset from
807
 * a byte on one scanline to the same byte on the scanline below.) */
808
uint
809
gx_device_raster(const gx_device * dev, bool pad)
810
5.78M
{
811
5.78M
    int depth = dev->color_info.depth;
812
5.78M
    ulong bits = (ulong) dev->width * depth;
813
5.78M
    ulong raster;
814
5.78M
    int l2align;
815
816
5.78M
    if (dev->is_planar) {
817
0
        int num_components = dev->color_info.num_components;
818
        /* bpc accounts for unused bits, e.g. depth==4, num_comp==3, or depth==8, num_comps==5 */
819
0
        int bpc = depth / num_components;
820
821
        /* depth can be <= num_components if planar and MEM_SET_PARAMS has changed it */
822
0
        if (depth <= num_components || bpc >= 8) {
823
0
            bits /= num_components;
824
0
        } else {
825
            /* depth is original depth, not the plane_depth since it is > num_components */
826
0
            bits /= (depth / bpc);
827
0
        }
828
0
    }
829
5.78M
    raster = (uint)((bits + 7) >> 3);
830
5.78M
    if (!pad)
831
2.57M
        return raster;
832
3.20M
    l2align = dev->log2_align_mod;
833
3.20M
    if (l2align < log2_align_bitmap_mod)
834
3.20M
        l2align = log2_align_bitmap_mod;
835
3.20M
    return (uint)(((bits + (8 << l2align) - 1) >> (l2align + 3)) << l2align);
836
5.78M
}
837
838
uint
839
gx_device_raster_chunky(const gx_device * dev, bool pad)
840
0
{
841
0
    ulong bits = (ulong) dev->width * dev->color_info.depth;
842
0
    ulong raster;
843
0
    int l2align;
844
845
0
    raster = (uint)((bits + 7) >> 3);
846
0
    if (!pad)
847
0
        return raster;
848
0
    l2align = dev->log2_align_mod;
849
0
    if (l2align < log2_align_bitmap_mod)
850
0
        l2align = log2_align_bitmap_mod;
851
0
    return (uint)(((bits + (8 << l2align) - 1) >> (l2align + 3)) << l2align);
852
0
}
853
uint
854
gx_device_raster_plane(const gx_device * dev, const gx_render_plane_t *render_plane)
855
2.57M
{
856
2.57M
    ulong bpc = (render_plane && render_plane->index >= 0 ?
857
2.57M
        render_plane->depth : dev->color_info.depth/(dev->is_planar ? dev->color_info.num_components : 1));
858
2.57M
    ulong bits = (ulong) dev->width * bpc;
859
2.57M
    int l2align;
860
861
2.57M
    l2align = dev->log2_align_mod;
862
2.57M
    if (l2align < log2_align_bitmap_mod)
863
2.57M
        l2align = log2_align_bitmap_mod;
864
2.57M
    return (uint)(((bits + (8 << l2align) - 1) >> (l2align + 3)) << l2align);
865
2.57M
}
866
867
/* Adjust the resolution for devices that only have a fixed set of */
868
/* geometries, so that the apparent size in inches remains constant. */
869
/* If fit=1, the resolution is adjusted so that the entire image fits; */
870
/* if fit=0, one dimension fits, but the other one is clipped. */
871
int
872
gx_device_adjust_resolution(gx_device * dev,
873
                            int actual_width, int actual_height, int fit)
874
0
{
875
0
    double width_ratio = (double)actual_width / dev->width;
876
0
    double height_ratio = (double)actual_height / dev->height;
877
0
    double ratio =
878
0
    (fit ? min(width_ratio, height_ratio) :
879
0
     max(width_ratio, height_ratio));
880
881
0
    dev->HWResolution[0] *= ratio;
882
0
    dev->HWResolution[1] *= ratio;
883
0
    gx_device_set_width_height(dev, actual_width, actual_height);
884
0
    return 0;
885
0
}
886
887
/* Set the HWMargins to values defined in inches. */
888
/* If move_origin is true, also reset the Margins. */
889
/* Note that this assumes a printer-type device (Y axis inverted). */
890
void
891
gx_device_set_margins(gx_device * dev, const float *margins /*[4] */ ,
892
                      bool move_origin)
893
3.72k
{
894
3.72k
    int i;
895
896
18.6k
    for (i = 0; i < 4; ++i)
897
14.9k
        dev->HWMargins[i] = margins[i] * 72.0;
898
3.72k
    if (move_origin) {
899
0
        dev->Margins[0] = -margins[0] * dev->HWResolution[0];
900
0
        dev->Margins[1] = -margins[3] * dev->HWResolution[1];
901
0
    }
902
3.72k
}
903
904
static void
905
gx_device_set_hwsize_from_media(gx_device *dev)
906
5.42k
{
907
5.42k
    int rot = (dev->LeadingEdge & 1);
908
5.42k
    double rot_media_x = rot ? dev->MediaSize[1] : dev->MediaSize[0];
909
5.42k
    double rot_media_y = rot ? dev->MediaSize[0] : dev->MediaSize[1];
910
5.42k
    gx_device *parent = dev;
911
5.42k
    int hwsize[2];
912
913
    /* Try the spec_op to give the device to control it */
914
5.42k
    hwsize[0] = (int)(rot_media_x * dev->HWResolution[0] / 72.0 + 0.5);
915
5.42k
    hwsize[1] = (int)(rot_media_y * dev->HWResolution[1] / 72.0 + 0.5);
916
917
5.42k
    while (parent->parent != NULL) {
918
0
        parent = parent->parent;
919
0
    }
920
5.42k
    if (dev_proc(parent, dev_spec_op)(parent, gxdso_set_HWSize, &hwsize, sizeof(hwsize)) <= 0) {
921
        /* just do the default setting */
922
5.42k
        dev->width = hwsize[0];
923
5.42k
        dev->height = hwsize[1];
924
5.42k
    }
925
5.42k
}
926
927
static void
928
gx_device_set_media_from_hwsize(gx_device *dev)
929
1.01k
{
930
1.01k
    int rot = (dev->LeadingEdge & 1);
931
1.01k
    double x = dev->width * 72.0 / dev->HWResolution[0];
932
1.01k
    double y = dev->height * 72.0 / dev->HWResolution[1];
933
934
1.01k
    if (rot) {
935
0
        dev->MediaSize[1] = x;
936
0
        dev->MediaSize[0] = y;
937
1.01k
    } else {
938
1.01k
        dev->MediaSize[0] = x;
939
1.01k
        dev->MediaSize[1] = y;
940
1.01k
    }
941
1.01k
}
942
943
/* Set the width and height, updating MediaSize to remain consistent. */
944
void
945
gx_device_set_width_height(gx_device * dev, int width, int height)
946
1.01k
{
947
1.01k
    dev->width = width;
948
1.01k
    dev->height = height;
949
1.01k
    gx_device_set_media_from_hwsize(dev);
950
1.01k
}
951
952
/* Set the resolution, updating width and height to remain consistent. */
953
void
954
gx_device_set_resolution(gx_device * dev, double x_dpi, double y_dpi)
955
683
{
956
683
    dev->HWResolution[0] = x_dpi;
957
683
    dev->HWResolution[1] = y_dpi;
958
683
    gx_device_set_hwsize_from_media(dev);
959
683
}
960
961
/* Set the MediaSize, updating width and height to remain consistent. */
962
void
963
gx_device_set_media_size(gx_device * dev, double media_width, double media_height)
964
4.73k
{
965
4.73k
    dev->MediaSize[0] = media_width;
966
4.73k
    dev->MediaSize[1] = media_height;
967
4.73k
    gx_device_set_hwsize_from_media(dev);
968
4.73k
}
969
970
/*
971
 * Copy the color mapping procedures from the target if they are
972
 * standard ones (saving a level of procedure call at mapping time).
973
 */
974
void
975
gx_device_copy_color_procs(gx_device *dev, const gx_device *target)
976
2.97M
{
977
2.97M
    dev_proc_map_cmyk_color((*from_cmyk)) =
978
2.97M
        dev_proc(dev, map_cmyk_color);
979
2.97M
    dev_proc_map_rgb_color((*from_rgb)) =
980
2.97M
        dev_proc(dev, map_rgb_color);
981
2.97M
    dev_proc_map_color_rgb((*to_rgb)) =
982
2.97M
        dev_proc(dev, map_color_rgb);
983
984
    /* The logic in this function seems a bit stale; it sets the
985
       old-style color procs, but not the new ones
986
       (get_color_mapping_procs, get_color_comp_index, encode_color,
987
       and decode_color). It should probably copy those as well.
988
    */
989
2.97M
    if (from_cmyk == gx_forward_map_cmyk_color ||
990
2.97M
        from_cmyk == cmyk_1bit_map_cmyk_color ||
991
2.97M
        from_cmyk == cmyk_8bit_map_cmyk_color) {
992
2.97M
        from_cmyk = dev_proc(target, map_cmyk_color);
993
2.97M
        set_dev_proc(dev, map_cmyk_color,
994
2.97M
                     (from_cmyk == cmyk_1bit_map_cmyk_color ||
995
2.97M
                      from_cmyk == cmyk_8bit_map_cmyk_color ?
996
2.97M
                      from_cmyk : gx_forward_map_cmyk_color));
997
2.97M
    }
998
2.97M
    if (from_rgb == gx_forward_map_rgb_color ||
999
2.97M
        from_rgb == gx_default_rgb_map_rgb_color) {
1000
2.97M
        from_rgb = dev_proc(target, map_rgb_color);
1001
2.97M
        set_dev_proc(dev, map_rgb_color,
1002
2.97M
                     (from_rgb == gx_default_rgb_map_rgb_color ?
1003
2.97M
                      from_rgb : gx_forward_map_rgb_color));
1004
2.97M
    }
1005
2.97M
    if (to_rgb == gx_forward_map_color_rgb ||
1006
2.97M
        to_rgb == cmyk_1bit_map_color_rgb ||
1007
2.97M
        to_rgb == cmyk_8bit_map_color_rgb) {
1008
2.97M
        to_rgb = dev_proc(target, map_color_rgb);
1009
2.97M
        set_dev_proc(dev, map_color_rgb,
1010
2.97M
                     (to_rgb == cmyk_1bit_map_color_rgb ||
1011
2.97M
                      to_rgb == cmyk_8bit_map_color_rgb ?
1012
2.97M
                      to_rgb : gx_forward_map_color_rgb));
1013
2.97M
    }
1014
2.97M
}
1015
1016
16.9k
#define COPY_PARAM(p) dev->p = target->p
1017
1018
/*
1019
 * Copy the color-related device parameters back from the target:
1020
 * color_info and color mapping procedures.
1021
 */
1022
void
1023
gx_device_copy_color_params(gx_device *dev, const gx_device *target)
1024
8.45k
{
1025
8.45k
        COPY_PARAM(color_info);
1026
8.45k
        COPY_PARAM(cached_colors);
1027
8.45k
        gx_device_copy_color_procs(dev, target);
1028
8.45k
}
1029
1030
/*
1031
 * Copy device parameters back from a target.  This copies all standard
1032
 * parameters related to page size and resolution, plus color_info
1033
 * and (if appropriate) color mapping procedures.
1034
 */
1035
void
1036
gx_device_copy_params(gx_device *dev, const gx_device *target)
1037
0
{
1038
0
#define COPY_ARRAY_PARAM(p) memcpy(dev->p, target->p, sizeof(dev->p))
1039
0
        COPY_PARAM(width);
1040
0
        COPY_PARAM(height);
1041
0
        COPY_ARRAY_PARAM(MediaSize);
1042
0
        COPY_ARRAY_PARAM(ImagingBBox);
1043
0
        COPY_PARAM(ImagingBBox_set);
1044
0
        COPY_ARRAY_PARAM(HWResolution);
1045
0
        COPY_ARRAY_PARAM(Margins);
1046
0
        COPY_ARRAY_PARAM(HWMargins);
1047
0
        COPY_PARAM(PageCount);
1048
0
        COPY_PARAM(MaxPatternBitmap);
1049
0
#undef COPY_ARRAY_PARAM
1050
0
        gx_device_copy_color_params(dev, target);
1051
0
}
1052
1053
#undef COPY_PARAM
1054
1055
/*
1056
 * Parse the output file name detecting and validating any %nnd format
1057
 * for inserting the page count.  If a format is present, store a pointer
1058
 * to its last character in *pfmt, otherwise store 0 there.
1059
 * Note that we assume devices have already been scanned, and any % must
1060
 * precede a valid format character.
1061
 *
1062
 * If there was a format, then return the max_width
1063
 */
1064
static int
1065
gx_parse_output_format(gs_parsed_file_name_t *pfn, const char **pfmt)
1066
4.43k
{
1067
4.43k
    bool have_format = false, field;
1068
4.43k
    int width[2], int_width = sizeof(int) * 3, w = 0;
1069
4.43k
    uint i;
1070
1071
    /* Scan the file name for a format string, and validate it if present. */
1072
4.43k
    width[0] = width[1] = 0;
1073
44.3k
    for (i = 0; i < pfn->len; ++i)
1074
39.9k
        if (pfn->fname[i] == '%') {
1075
0
            if (i + 1 < pfn->len && pfn->fname[i + 1] == '%') {
1076
0
                i++;
1077
0
                continue;
1078
0
            }
1079
0
            if (have_format) /* more than one % */
1080
0
                return_error(gs_error_undefinedfilename);
1081
0
            have_format = true;
1082
0
            field = -1; /* -1..3 for the 5 components of "%[flags][width][.precision][l]type" */
1083
0
            for (;;)
1084
0
                if (++i == pfn->len)
1085
0
                    return_error(gs_error_undefinedfilename);
1086
0
                else {
1087
0
                    switch (field) {
1088
0
                        case -1: /* flags */
1089
0
                            if (strchr(" #+-", pfn->fname[i]))
1090
0
                                continue;
1091
0
                            else
1092
0
                                field++;
1093
                            /* falls through */
1094
0
                        default: /* width (field = 0) and precision (field = 1) */
1095
0
                            if (strchr("0123456789", pfn->fname[i])) {
1096
0
                                width[field] = width[field] * 10 + pfn->fname[i] - '0';
1097
0
                                continue;
1098
0
                            } else if (0 == field && '.' == pfn->fname[i]) {
1099
0
                                field++;
1100
0
                                continue;
1101
0
                            } else
1102
0
                                field = 2;
1103
                            /* falls through */
1104
0
                        case 2: /* "long" indicator */
1105
0
                            field++;
1106
0
                            if ('l' == pfn->fname[i]) {
1107
0
                                int_width = sizeof(long) * 3;
1108
0
                                continue;
1109
0
                            }
1110
                            /* falls through */
1111
0
                        case 3: /* type */
1112
0
                            if (strchr("diuoxX", pfn->fname[i])) {
1113
0
                                *pfmt = &pfn->fname[i];
1114
0
                                break;
1115
0
                            } else
1116
0
                                return_error(gs_error_undefinedfilename);
1117
0
                    }
1118
0
                    break;
1119
0
                }
1120
0
        }
1121
4.43k
    if (have_format) {
1122
        /* Calculate a conservative maximum width. */
1123
0
        w = max(width[0], width[1]);
1124
0
        w = max(w, int_width) + 5;
1125
0
    }
1126
4.43k
    return w;
1127
4.43k
}
1128
1129
/*
1130
 * Parse the output file name for a device, recognizing "-" and "|command",
1131
 * and also detecting and validating any %nnd format for inserting the
1132
 * page count.  If a format is present, store a pointer to its last
1133
 * character in *pfmt, otherwise store 0 there.  Note that an empty name
1134
 * is currently allowed.
1135
 */
1136
int
1137
gx_parse_output_file_name(gs_parsed_file_name_t *pfn, const char **pfmt,
1138
                          const char *fname, uint fnlen, gs_memory_t *memory)
1139
4.43k
{
1140
4.43k
    int code;
1141
1142
4.43k
    *pfmt = 0;
1143
4.43k
    pfn->memory = 0;
1144
4.43k
    pfn->iodev = NULL;
1145
4.43k
    pfn->fname = NULL;    /* irrelevant since length = 0 */
1146
4.43k
    pfn->len = 0;
1147
4.43k
    if (fnlen == 0)      /* allow null name */
1148
0
        return 0;
1149
    /*
1150
     * If the file name begins with a %, it might be either an IODevice
1151
     * or a %nnd format.  Check (carefully) for this case.
1152
     */
1153
4.43k
    code = gs_parse_file_name(pfn, fname, fnlen, memory);
1154
4.43k
    if (code < 0) {
1155
0
        if (fname[0] == '%') {
1156
            /* not a recognized iodev -- may be a leading format descriptor */
1157
0
            pfn->len = fnlen;
1158
0
            pfn->fname = fname;
1159
0
            code = gx_parse_output_format(pfn, pfmt);
1160
0
        }
1161
0
        if (code < 0)
1162
0
            return code;
1163
0
    }
1164
4.43k
    if (!pfn->iodev) {
1165
4.43k
        if ( (pfn->len == 1) && (pfn->fname[0] == '-') ) {
1166
0
            pfn->iodev = gs_findiodevice(memory, (const byte *)"%stdout", 7);
1167
0
            pfn->fname = NULL;
1168
4.43k
        } else if (pfn->fname[0] == '|') {
1169
0
            pfn->iodev = gs_findiodevice(memory, (const byte *)"%pipe", 5);
1170
0
            pfn->fname++, pfn->len--;
1171
0
        } else
1172
4.43k
            pfn->iodev = iodev_default(memory);
1173
4.43k
        if (!pfn->iodev)
1174
0
            return_error(gs_error_undefinedfilename);
1175
4.43k
    }
1176
4.43k
    if (!pfn->fname)
1177
0
        return 0;
1178
4.43k
    code = gx_parse_output_format(pfn, pfmt);
1179
4.43k
    if (code < 0)
1180
0
        return code;
1181
4.43k
    if (strlen(pfn->iodev->dname) + pfn->len + code >= gp_file_name_sizeof)
1182
0
        return_error(gs_error_undefinedfilename);
1183
4.43k
    return 0;
1184
4.43k
}
1185
1186
/* Check if we write each page into separate file. */
1187
bool
1188
gx_outputfile_is_separate_pages(const char *fname, gs_memory_t *memory)
1189
0
{
1190
0
    const char *fmt;
1191
0
    gs_parsed_file_name_t parsed;
1192
0
    int code = gx_parse_output_file_name(&parsed, &fmt, fname,
1193
0
                                         strlen(fname), memory);
1194
1195
0
    return (code >= 0 && fmt != 0);
1196
0
}
1197
1198
/* Delete the current output file for a device (file must be closed first) */
1199
int gx_device_delete_output_file(const gx_device * dev, const char *fname)
1200
0
{
1201
0
    gs_parsed_file_name_t parsed;
1202
0
    const char *fmt;
1203
0
    char *pfname = (char *)gs_alloc_bytes(dev->memory, gp_file_name_sizeof, "gx_device_delete_output_file(pfname)");
1204
0
    int code;
1205
0
    size_t len;
1206
1207
0
    if (pfname == NULL) {
1208
0
        code = gs_note_error(gs_error_VMerror);
1209
0
        goto done;
1210
0
    }
1211
1212
0
    len = strlen(fname);
1213
0
    code = gx_parse_output_file_name(&parsed, &fmt, fname, len,
1214
0
                                         dev->memory);
1215
0
    if (code < 0) {
1216
0
        goto done;
1217
0
    }
1218
1219
0
    if (parsed.iodev && !strcmp(parsed.iodev->dname, "%stdout%"))
1220
0
        goto done;
1221
1222
0
    if (fmt) {           /* filename includes "%nnd" */
1223
0
        long count1 = dev->PageCount + 1;
1224
1225
0
        while (*fmt != 'l' && *fmt != '%')
1226
0
            --fmt;
1227
0
        if (*fmt == 'l')
1228
0
            gs_snprintf(pfname, len, parsed.fname, count1);
1229
0
        else
1230
0
            gs_snprintf(pfname, len, parsed.fname, (int)count1);
1231
0
    } else if (parsed.len && strchr(parsed.fname, '%')) /* filename with "%%" but no "%nnd" */
1232
0
        gs_snprintf(pfname, len, parsed.fname);
1233
0
    else
1234
0
        pfname[0] = 0; /* 0 to use "fname", not "pfname" */
1235
0
    if (pfname[0]) {
1236
0
        parsed.fname = pfname;
1237
0
        parsed.len = strlen(parsed.fname);
1238
0
    }
1239
0
    if (parsed.iodev)
1240
0
        code = parsed.iodev->procs.delete_file((gx_io_device *)(parsed.iodev), (const char *)parsed.fname);
1241
0
    else
1242
0
        code = gs_note_error(gs_error_invalidfileaccess);
1243
1244
0
done:
1245
0
    if (pfname != NULL)
1246
0
        gs_free_object(dev->memory, pfname, "gx_device_delete_output_file(pfname)");
1247
1248
0
    return(code);
1249
0
}
1250
1251
static int
1252
noclose(FILE *f)
1253
0
{
1254
0
    return 0;
1255
0
}
1256
1257
/* Open the output file for a device. */
1258
int
1259
gx_device_open_output_file(const gx_device * dev, char *fname,
1260
                           bool binary, bool positionable, gp_file ** pfile)
1261
645
{
1262
645
    gs_parsed_file_name_t parsed;
1263
645
    const char *fmt;
1264
645
    char *pfname = (char *)gs_alloc_bytes(dev->memory, gp_file_name_sizeof, "gx_device_open_output_file(pfname)");
1265
645
    int code;
1266
1267
645
    if (pfname == NULL) {
1268
0
        code = gs_note_error(gs_error_VMerror);
1269
0
        goto done;
1270
0
    }
1271
1272
645
    if (strlen(fname) == 0) {
1273
0
        code = gs_note_error(gs_error_undefinedfilename);
1274
0
        emprintf1(dev->memory, "Device '%s' requires an output file but no file was specified.\n", dev->dname);
1275
0
        goto done;
1276
0
    }
1277
645
    code = gx_parse_output_file_name(&parsed, &fmt, fname, strlen(fname), dev->memory);
1278
645
    if (code < 0) {
1279
0
        goto done;
1280
0
    }
1281
1282
645
    if (parsed.iodev && !strcmp(parsed.iodev->dname, "%stdout%")) {
1283
0
        if (parsed.fname) {
1284
0
            code = gs_note_error(gs_error_undefinedfilename);
1285
0
            goto done;
1286
0
        }
1287
0
        *pfile = gp_file_FILE_alloc(dev->memory);
1288
0
        if (*pfile == NULL) {
1289
0
            code = gs_note_error(gs_error_VMerror);
1290
0
            goto done;
1291
0
        }
1292
0
        gp_file_FILE_set(*pfile, dev->memory->gs_lib_ctx->core->fstdout, noclose);
1293
        /* Force stdout to binary. */
1294
0
        code = gp_setmode_binary_impl(dev->memory->gs_lib_ctx->core->fstdout, true);
1295
0
        goto done;
1296
645
    } else if (parsed.iodev && !strcmp(parsed.iodev->dname, "%pipe%")) {
1297
0
        positionable = false;
1298
0
    }
1299
645
    if (fmt) {           /* filename includes "%nnd" */
1300
0
        long count1 = dev->PageCount + 1;
1301
1302
0
        while (*fmt != 'l' && *fmt != '%')
1303
0
            --fmt;
1304
0
        if (*fmt == 'l')
1305
0
            gs_snprintf(pfname, gp_file_name_sizeof, parsed.fname, count1);
1306
0
        else
1307
0
            gs_snprintf(pfname, gp_file_name_sizeof, parsed.fname, (int)count1);
1308
645
    } else if (parsed.len && strchr(parsed.fname, '%'))  /* filename with "%%" but no "%nnd" */
1309
0
        gs_snprintf(pfname, gp_file_name_sizeof, parsed.fname);
1310
645
    else
1311
645
        pfname[0] = 0; /* 0 to use "fname", not "pfname" */
1312
645
    if (pfname[0]) {
1313
0
        parsed.fname = pfname;
1314
0
        parsed.len = strlen(parsed.fname);
1315
0
    }
1316
645
    if (parsed.iodev &&
1317
645
        (positionable || parsed.iodev != iodev_default(dev->memory))) {
1318
0
        char fmode[4];
1319
1320
0
        if (!parsed.fname) {
1321
0
            code = gs_note_error(gs_error_undefinedfilename);
1322
0
            goto done;
1323
0
        }
1324
0
        strcpy(fmode, gp_fmode_wb);
1325
0
        if (positionable)
1326
0
            strcat(fmode, "+");
1327
0
        code = parsed.iodev->procs.gp_fopen(parsed.iodev, parsed.fname, fmode,
1328
0
                                            pfile, NULL, 0, dev->memory);
1329
0
        if (code)
1330
0
            emprintf1(dev->memory,
1331
0
                      "**** Could not open the file %s .\n",
1332
0
                      parsed.fname);
1333
645
    } else {
1334
645
        *pfile = gp_open_printer(dev->memory, (pfname[0] ? pfname : fname), binary);
1335
645
        if (!(*pfile)) {
1336
0
            emprintf1(dev->memory, "**** Could not open the file '%s'.\n", (pfname[0] ? pfname : fname));
1337
1338
0
            code = gs_note_error(gs_error_invalidfileaccess);
1339
0
        }
1340
645
    }
1341
1342
645
done:
1343
645
    if (pfname != NULL)
1344
645
        gs_free_object(dev->memory, pfname, "gx_device_open_output_file(pfname)");
1345
1346
645
    return(code);
1347
645
}
1348
1349
/* Close the output file for a device. */
1350
int
1351
gx_device_close_output_file(const gx_device * dev, const char *fname,
1352
                            gp_file *file)
1353
645
{
1354
645
    gs_parsed_file_name_t parsed;
1355
645
    const char *fmt;
1356
645
    int code = gx_parse_output_file_name(&parsed, &fmt, fname, strlen(fname),
1357
645
                                         dev->memory);
1358
1359
645
    if (code < 0)
1360
0
        return code;
1361
645
    if (parsed.iodev) {
1362
645
        if (!strcmp(parsed.iodev->dname, "%stdout%"))
1363
0
            return 0;
1364
        /* NOTE: fname is unsubstituted if the name has any %nnd formats. */
1365
645
        if (parsed.iodev != iodev_default(dev->memory))
1366
0
            return parsed.iodev->procs.fclose(parsed.iodev, file);
1367
645
    }
1368
645
    gp_close_printer(file, (parsed.fname ? parsed.fname : fname));
1369
645
    return 0;
1370
645
}
1371
1372
bool gx_color_info_equal(const gx_device_color_info * p1, const gx_device_color_info * p2)
1373
0
{
1374
0
    if (p1->anti_alias.graphics_bits != p2->anti_alias.graphics_bits)
1375
0
        return false;
1376
0
    if (p1->anti_alias.text_bits != p2->anti_alias.text_bits)
1377
0
        return false;
1378
0
    if (p1->black_component != p2->black_component)
1379
0
        return false;
1380
0
    if (strcmp(p1->cm_name, p2->cm_name) != 0)
1381
0
        return false;
1382
0
    if (p1->depth != p2->depth)
1383
0
        return false;
1384
0
    if (p1->dither_colors != p2->dither_colors)
1385
0
        return false;
1386
0
    if (p1->dither_grays != p2->dither_grays)
1387
0
        return false;
1388
0
    if (p1->gray_index != p2->gray_index)
1389
0
        return false;
1390
0
    if (p1->max_color != p2->max_color)
1391
0
        return false;
1392
0
    if (p1->max_components != p2->max_components)
1393
0
        return false;
1394
0
    if (p1->opmsupported != p2->opmsupported)
1395
0
        return false;
1396
0
    if (p1->polarity != p2->polarity)
1397
0
        return false;
1398
0
    if (p1->process_comps != p2->process_comps)
1399
0
        return false;
1400
0
    if (p1->separable_and_linear != p2->separable_and_linear)
1401
0
        return false;
1402
0
    if (p1->use_antidropout_downscaler != p2->use_antidropout_downscaler)
1403
0
        return false;
1404
0
    return true;
1405
0
}
1406
1407
int gx_callout(gx_device *dev, int id, int size, void *data)
1408
0
{
1409
0
    return gs_lib_ctx_callout(dev->memory, dev->dname,
1410
0
                              id, size, data);
1411
0
}
1412
1413
/* compare two space_params, we can't do this with memcmp since there is padding in the structure */
1414
int
1415
gdev_space_params_cmp(const gdev_space_params sp1,
1416
7.45k
                      const gdev_space_params sp2) {
1417
7.45k
  if (sp1.MaxBitmap != sp2.MaxBitmap)
1418
0
    return(1);
1419
7.45k
  if (sp1.BufferSpace != sp2.BufferSpace)
1420
0
    return(1);
1421
7.45k
  if (sp1.band.BandWidth != sp2.band.BandWidth)
1422
0
    return(1);
1423
7.45k
  if (sp1.band.BandHeight != sp2.band.BandHeight)
1424
0
    return(1);
1425
7.45k
  if (sp1.band.BandBufferSpace != sp2.band.BandBufferSpace)
1426
0
    return(1);
1427
7.45k
  if (sp1.band.tile_cache_size != sp2.band.tile_cache_size)
1428
0
    return(1);
1429
7.45k
  if (sp1.params_are_read_only != sp2.params_are_read_only)
1430
0
    return(1);
1431
7.45k
  if (sp1.banding_type != sp2.banding_type)
1432
0
    return(1);
1433
1434
7.45k
  return(0);
1435
7.45k
}
1436
1437
static void
1438
release_nts_lock(gx_device *dev)
1439
0
{
1440
0
    (void)gs_lib_ctx_nts_adjust(dev->memory, -1);
1441
0
}
1442
1443
int gx_init_non_threadsafe_device(gx_device *dev)
1444
0
{
1445
0
    int code;
1446
1447
0
    if (dev == NULL || dev->finalize != NULL)
1448
0
        return gs_error_unknownerror;
1449
1450
0
    code = gs_lib_ctx_nts_adjust(dev->memory, 1);
1451
0
    if (code < 0)
1452
0
        return code;
1453
1454
0
    dev->finalize = release_nts_lock;
1455
1456
0
    return 0;
1457
0
}