Coverage Report

Created: 2026-07-24 07:44

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