Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/base/gsdevice.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2024 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
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
169M
{
53
169M
    gx_device * const dev = (gx_device *)vptr;
54
169M
    (void)cmem; /* unused */
55
56
169M
    discard(gs_closedevice(dev));
57
58
169M
    if (dev->icc_struct != NULL) {
59
2.33M
        rc_decrement(dev->icc_struct, "gx_device_finalize(icc_profile)");
60
2.33M
    }
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
169M
    if (dev->child)
68
0
        dev->child->parent = dev->parent;
69
169M
    if (dev->parent)
70
31.6k
        dev->parent->child = dev->child;
71
169M
    if (dev->PageList) {
72
0
        rc_decrement(dev->PageList, "gx_device_finalize(PageList)");
73
0
        dev->PageList = 0;
74
0
    }
75
169M
    if (dev->NupControl) {
76
0
        rc_decrement(dev->NupControl, "gx_device_finalize(NupControl)");
77
0
        dev->NupControl = 0;
78
0
    }
79
80
169M
    if (dev->finalize)
81
169M
        dev->finalize(dev);
82
83
169M
    if (dev->stype_is_dynamic)
84
99.5k
        gs_free_const_object(dev->memory->non_gc_memory, dev->stype,
85
99.5k
                             "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
169M
}
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
1.37M
ENUM_PTRS_WITH(device_enum_ptrs, gx_device *dev) return 0;
120
457k
case 0:ENUM_RETURN(gx_device_enum_ptr(dev->parent));
121
457k
case 1:ENUM_RETURN(gx_device_enum_ptr(dev->child));
122
1.37M
ENUM_PTRS_END
123
457k
static RELOC_PTRS_WITH(device_reloc_ptrs, gx_device *dev)
124
457k
{
125
457k
    dev->parent = gx_device_reloc_ptr(dev->parent, gcst);
126
457k
    dev->child = gx_device_reloc_ptr(dev->child, gcst);
127
457k
}
128
457k
RELOC_PTRS_END
129
static
130
618k
ENUM_PTRS_WITH(device_forward_enum_ptrs, gx_device_forward *fdev) return 0;
131
208k
case 0: ENUM_RETURN(gx_device_enum_ptr(fdev->target));
132
618k
ENUM_PTRS_END
133
208k
static RELOC_PTRS_WITH(device_forward_reloc_ptrs, gx_device_forward *fdev)
134
208k
{
135
208k
    fdev->target = gx_device_reloc_ptr(fdev->target, gcst);
136
208k
}
137
208k
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
17.7M
{
153
17.7M
    if (dev == 0 || dev->memory == 0)
154
1.52M
        return 0;
155
16.2M
    return dev;
156
17.7M
}
157
gx_device *
158
gx_device_reloc_ptr(gx_device * dev, gc_state_t * gcst)
159
17.7M
{
160
17.7M
    if (dev == 0 || dev->memory == 0)
161
1.52M
        return dev;
162
16.2M
    return RELOC_OBJ(dev);  /* gcst implicit */
163
17.7M
}
164
165
/* Flush buffered output to the device */
166
int
167
gs_flushpage(gs_gstate * pgs)
168
162k
{
169
162k
    gx_device *dev = gs_currentdevice(pgs);
170
171
162k
    return (*dev_proc(dev, sync_output)) (dev);
172
162k
}
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
133k
{
183
133k
    gx_device *dev = gs_currentdevice(pgs);
184
133k
    cmm_dev_profile_t *dev_profile;
185
133k
    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
133k
    code = gs_gsave(pgs);
191
133k
    if (code < 0)
192
0
        return code;
193
133k
    if (((code = gs_newpath(pgs)) < 0) ||
194
133k
        ((code = gs_moveto(pgs, 0.0, 0.0)) < 0) ||
195
133k
    ((code = gs_setgray(pgs, 0.0)) < 0) ||
196
133k
    ((code = gs_fill(pgs)) < 0))
197
0
    {
198
0
        gs_grestore(pgs);
199
0
        return code;
200
0
    }
201
133k
    code = gs_grestore(pgs);
202
133k
    if (code < 0)
203
0
        return code;
204
205
133k
    if (dev->IgnoreNumCopies)
206
0
        num_copies = 1;
207
133k
    if ((code = (*dev_proc(dev, output_page)) (dev, num_copies, flush)) < 0)
208
13.3k
        return code;
209
210
119k
    code = dev_proc(dev, get_profile)(dev, &(dev_profile));
211
119k
    if (code < 0)
212
0
        return code;
213
119k
    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
119k
    return code;
218
119k
}
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
119k
{
227
119k
    dev->PageCount += num_copies;
228
119k
    return 0;
229
119k
}
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
73.9M
{
279
73.9M
    return pgs->device;
280
73.9M
}
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
169M
{
293
169M
    fill_dev_proc(dev, get_initial_matrix, gx_default_get_initial_matrix);
294
169M
    (*dev_proc(dev, get_initial_matrix)) (dev, pmat);
295
169M
}
296
297
/* Get the N'th device from the known device list */
298
const gx_device *
299
gs_getdevice(int index)
300
7.14M
{
301
7.14M
    const gx_device *const *list;
302
7.14M
    int count = gs_lib_device_list(&list, NULL);
303
304
7.14M
    if (index < 0 || index >= count)
305
324k
        return 0;    /* index out of range */
306
6.82M
    return list[index];
307
7.14M
}
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
67.9k
{
364
67.9k
    if (dev->stype)
365
67.9k
        *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
67.9k
    st->ssize = dev->params_size;
371
67.9k
}
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
2.52M
{
378
2.52M
    gx_device *new_dev;
379
2.52M
    const gs_memory_struct_type_t *std = dev->stype;
380
2.52M
    const gs_memory_struct_type_t *new_std;
381
2.52M
    gs_memory_struct_type_t *a_std = 0;
382
2.52M
    int code;
383
384
2.52M
    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
2.52M
    } else if (std != 0 && std->ssize == dev->params_size) {
397
        /* Use the static stype. */
398
2.45M
        new_std = std;
399
2.45M
    } else {
400
        /* We need to figure out or adjust the stype. */
401
67.9k
        a_std = (gs_memory_struct_type_t *)
402
67.9k
            gs_alloc_bytes_immovable(mem->non_gc_memory, sizeof(*std),
403
67.9k
                                     "gs_copydevice(stype)");
404
67.9k
        if (!a_std)
405
0
            return_error(gs_error_VMerror);
406
67.9k
        gx_device_make_struct_type(a_std, dev);
407
67.9k
        new_std = a_std;
408
67.9k
    }
409
    /*
410
     * Because command list devices have complicated internal pointer
411
     * structures, we allocate all device instances as immovable.
412
     */
413
2.52M
    new_dev = gs_alloc_struct_immovable(mem, gx_device, new_std,
414
2.52M
                                        "gs_copydevice(device)");
415
2.52M
    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
2.52M
    code = gx_device_init(new_dev, dev, mem, false);
420
2.52M
    new_dev->stype = new_std;
421
2.52M
    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
2.52M
    new_dev->is_open = dev->is_open && keep_open;
428
2.52M
    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
2.52M
    fill_dev_proc(new_dev, dev_spec_op, gx_default_dev_spec_op);
442
2.52M
    *pnew_dev = new_dev;
443
2.52M
    return 0;
444
2.52M
}
445
int
446
gs_copydevice(gx_device ** pnew_dev, const gx_device * dev, gs_memory_t * mem)
447
2.20M
{
448
2.20M
    return gs_copydevice2(pnew_dev, dev, false, mem);
449
2.20M
}
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
718k
{
456
718k
    if (dev->is_open)
457
0
        return 0;
458
718k
    check_device_separable(dev);
459
718k
    gx_device_fill_in_procs(dev);
460
718k
    {
461
718k
        int code = (*dev_proc(dev, open_device))(dev);
462
463
718k
        if (code < 0)
464
0
            return_error(code);
465
718k
        dev->is_open = true;
466
718k
        return 1;
467
718k
    }
468
718k
}
469
470
static void
471
gs_gstate_update_device(gs_gstate *pgs, gx_device *dev)
472
1.91M
{
473
1.91M
    gx_set_cmap_procs(pgs, dev);
474
1.91M
    gx_unset_both_dev_colors(pgs);
475
1.91M
}
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
1.69M
{
507
1.69M
    int open_code = 0, code;
508
1.69M
    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
1.69M
    if (libctx->io_device_table != NULL) {
513
1.53M
        cmm_dev_profile_t *dev_profile;
514
1.53M
        if (pgs->icc_manager->lab_profile == NULL) {  /* pick one not set externally */
515
257k
            code = gsicc_init_iccmanager(pgs);
516
257k
            if (code < 0)
517
0
                return(code);
518
257k
        }
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
1.53M
        if (dev->procs.get_profile != NULL) {
526
1.27M
            code = dev_proc(dev, get_profile)(dev, &dev_profile);
527
1.27M
            if (code < 0) {
528
0
                return(code);
529
0
            }
530
1.27M
            if (dev_profile == NULL ||
531
1.27M
                dev_profile->device_profile[gsDEFAULTPROFILE] == NULL) {
532
200
                if ((code = gsicc_init_device_profile_struct(dev, NULL,
533
200
                                                        gsDEFAULTPROFILE)) < 0)
534
0
                    return(code);
535
                /* set the intent too */
536
200
                if ((code = gsicc_set_device_profile_intent(dev, gsRINOTSPECIFIED,
537
200
                                                       gsDEFAULTPROFILE)) < 0)
538
0
                    return(code);
539
200
            }
540
1.27M
        }
541
1.53M
    }
542
543
    /* Initialize the device */
544
1.69M
    if (!dev->is_open) {
545
717k
        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
717k
        if (libctx->io_device_table != NULL) {
553
554k
            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
554k
            if (dev->procs.get_profile != NULL) {
559
554k
                code = dev_proc(dev, get_profile)(dev, &dev_profile);
560
554k
                if (code < 0) {
561
0
                    return(code);
562
0
                }
563
554k
                if (dev_profile == NULL ||
564
554k
                    dev_profile->device_profile[gsDEFAULTPROFILE] == NULL) {
565
217k
                    if ((code = gsicc_init_device_profile_struct(dev, NULL,
566
217k
                                                            gsDEFAULTPROFILE)) < 0)
567
0
                        return(code);
568
217k
                }
569
554k
            }
570
554k
        }
571
572
717k
        if (gs_device_is_memory(dev)) {
573
            /* Set the target to the current device. */
574
6
            gx_device *odev = gs_currentdevice_inline(pgs);
575
576
12
            while (odev != 0 && gs_device_is_memory(odev))
577
6
                odev = ((gx_device_memory *)odev)->target;
578
6
            gx_device_set_target(((gx_device_forward *)dev), odev);
579
6
        }
580
717k
        code = open_code = gs_opendevice(dev);
581
717k
        if (code < 0)
582
0
            return code;
583
717k
    }
584
1.69M
    gs_setdevice_no_init(pgs, dev);
585
1.69M
    pgs->ctm_default_set = false;
586
1.69M
    if ((code = gs_initmatrix(pgs)) < 0 ||
587
1.69M
        (code = gs_initclip(pgs)) < 0
588
1.69M
        )
589
0
        return code;
590
    /* If we were in a charpath or a setcachedevice, */
591
    /* we aren't any longer. */
592
1.69M
    pgs->in_cachedevice = 0;
593
1.69M
    pgs->in_charpath = (gs_char_path_mode) 0;
594
1.69M
    return open_code;
595
1.69M
}
596
int
597
gs_setdevice_no_init(gs_gstate * pgs, gx_device * dev)
598
1.91M
{
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
1.91M
    if (pgs->device != NULL && pgs->device->rc.ref_count == 1 &&
612
1.91M
        pgs->device != dev) {
613
162k
        int code = gs_closedevice(pgs->device);
614
615
162k
        if (code < 0)
616
0
            return code;
617
162k
    }
618
1.91M
    rc_assign(pgs->device, dev, "gs_setdevice_no_init");
619
1.91M
    gs_gstate_update_device(pgs, dev);
620
1.91M
    return 0;
621
1.91M
}
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
178M
{
628
178M
    memcpy(dev, proto, proto->params_size);
629
178M
    dev->initialize_device_procs = proto->initialize_device_procs;
630
178M
    if (dev->initialize_device_procs != NULL)
631
178M
        dev->initialize_device_procs(dev);
632
178M
    dev->memory = mem;    /* must precede initialize_device call so devices can use it */
633
178M
    if (dev->procs.initialize_device) {
634
1.86M
        int code = dev->procs.initialize_device(dev);
635
1.86M
        if (code < 0)
636
0
            return code;
637
1.86M
    }
638
178M
    dev->retained = !internal;
639
178M
    rc_init(dev, mem, (internal ? 0 : 1));
640
178M
    rc_increment(dev->icc_struct);
641
642
178M
    return 0;
643
178M
}
644
645
void
646
gx_device_init_on_stack(gx_device * dev, const gx_device * proto,
647
                        gs_memory_t * mem)
648
16.7M
{
649
16.7M
    memcpy(dev, proto, proto->params_size);
650
16.7M
    dev->initialize_device_procs = proto->initialize_device_procs;
651
16.7M
    dev->initialize_device_procs(dev);
652
16.7M
    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
16.7M
    gx_device_fill_in_procs(dev);
658
16.7M
    dev->memory = mem;
659
16.7M
    dev->retained = 0;
660
16.7M
    dev->pad = proto->pad;
661
16.7M
    dev->log2_align_mod = proto->log2_align_mod;
662
16.7M
    dev->num_planar_planes = proto->num_planar_planes;
663
16.7M
    rc_init(dev, NULL, 0);
664
16.7M
}
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
198k
{
671
    /* Can never fail */
672
198k
    (void)gx_device_init((gx_device *)dev_null,
673
198k
                         (const gx_device *)&gs_null_device,
674
198k
                         mem, true);
675
198k
    gx_device_fill_in_procs((gx_device *)dev_null);
676
198k
    gx_device_set_target((gx_device_forward *)dev_null, dev);
677
198k
    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
198k
        gx_device *dn = (gx_device *)dev_null;
685
198k
        set_dev_proc(dn, get_color_mapping_procs, gx_forward_get_color_mapping_procs);
686
198k
        set_dev_proc(dn, get_color_comp_index, gx_forward_get_color_comp_index);
687
198k
        set_dev_proc(dn, encode_color, gx_forward_encode_color);
688
198k
        set_dev_proc(dn, decode_color, gx_forward_decode_color);
689
198k
        set_dev_proc(dn, get_profile, gx_forward_get_profile);
690
198k
        set_dev_proc(dn, set_graphics_type_tag, gx_forward_set_graphics_type_tag);
691
198k
        set_dev_proc(dn, begin_transparency_group, gx_default_begin_transparency_group);
692
198k
        set_dev_proc(dn, end_transparency_group, gx_default_end_transparency_group);
693
198k
        set_dev_proc(dn, begin_transparency_mask, gx_default_begin_transparency_mask);
694
198k
        set_dev_proc(dn, end_transparency_mask, gx_default_end_transparency_mask);
695
198k
        set_dev_proc(dn, discard_transparency_layer, gx_default_discard_transparency_layer);
696
198k
        set_dev_proc(dn, push_transparency_state, gx_default_push_transparency_state);
697
198k
        set_dev_proc(dn, pop_transparency_state, gx_default_pop_transparency_state);
698
198k
        set_dev_proc(dn, put_image, gx_default_put_image);
699
198k
        set_dev_proc(dn, copy_planes, gx_default_copy_planes);
700
198k
        set_dev_proc(dn, copy_alpha_hl_color, gx_default_no_copy_alpha_hl_color);
701
198k
        dn->graphics_type_tag = dev->graphics_type_tag; /* initialize to same as target */
702
198k
        gx_device_copy_color_params(dn, dev);
703
198k
    }
704
198k
}
705
706
/* Is a null device ? */
707
bool gs_is_null_device(gx_device *dev)
708
16.8M
{
709
16.8M
    gx_device ldev;
710
711
16.8M
    ldev.initialize_device_procs = gs_null_device.initialize_device_procs;
712
16.8M
    ldev.initialize_device_procs(&ldev);
713
714
    /* Assuming null_fill_path isn't used elswhere. */
715
16.8M
    return dev->procs.fill_path == ldev.procs.fill_path;
716
16.8M
}
717
718
/* Mark a device as retained or not retained. */
719
void
720
gx_device_retain(gx_device *dev, bool retained)
721
174M
{
722
174M
    int delta = (int)retained - (int)dev->retained;
723
724
174M
    if (delta) {
725
174M
        dev->retained = retained; /* do first in case dev is freed */
726
174M
        rc_adjust_only(dev, delta, "gx_device_retain");
727
174M
    }
728
174M
}
729
730
/* Select a null device. */
731
int
732
gs_nulldevice(gs_gstate * pgs)
733
514k
{
734
514k
    int code = 0;
735
514k
    gs_gstate *spgs;
736
514k
    bool saveLockSafety = false;
737
514k
    if (pgs->device == NULL || !gx_device_is_null(pgs->device)) {
738
513k
        gx_device *ndev;
739
513k
        code = gs_copydevice(&ndev, (const gx_device *)&gs_null_device,
740
513k
                                 pgs->memory);
741
742
513k
        if (code < 0)
743
0
            return code;
744
513k
        if (gs_currentdevice_inline(pgs) != NULL)
745
256k
            saveLockSafety = gs_currentdevice_inline(pgs)->LockSafetyParams;
746
        /*
747
         * Internal devices have a reference count of 0, not 1,
748
         * aside from references from graphics states.
749
         */
750
        /* There is some strange use of the null device in the code.  I need
751
           to sort out how the icc profile is best handled with this device.
752
           It seems to inherit properties from the current device if there
753
           is one */
754
513k
        rc_init(ndev, pgs->memory, 0);
755
513k
        if (pgs->device != NULL) {
756
256k
            if ((code = dev_proc(pgs->device, get_profile)(pgs->device,
757
256k
                                               &(ndev->icc_struct))) < 0)
758
0
                return code;
759
256k
            rc_increment(ndev->icc_struct);
760
256k
            set_dev_proc(ndev, get_profile, gx_default_get_profile);
761
256k
        }
762
763
513k
        if (gs_setdevice_no_erase(pgs, ndev) < 0) {
764
0
            gs_free_object(pgs->memory, ndev, "gs_copydevice(device)");
765
            /* We are out of options: find the device we installed in
766
               the initial graphics state, and put that in place.
767
               We just need something so we can end this job cleanly.
768
             */
769
0
            spgs = pgs->saved;
770
0
            if (spgs != NULL) {
771
0
                while (spgs->saved) spgs = spgs->saved;
772
0
                gs_currentdevice_inline(pgs) = gs_currentdevice_inline(spgs);
773
0
                rc_increment(gs_currentdevice_inline(pgs));
774
0
            }
775
0
            code = gs_note_error(gs_error_Fatal);
776
0
        }
777
513k
        if (gs_currentdevice_inline(pgs) != NULL)
778
513k
            gs_currentdevice_inline(pgs)->LockSafetyParams = saveLockSafety;
779
513k
    }
780
514k
    return code;
781
514k
}
782
783
/* Close a device.  The client is responsible for ensuring that */
784
/* this device is not current in any graphics state. */
785
int
786
gs_closedevice(gx_device * dev)
787
170M
{
788
170M
    int code = 0;
789
790
170M
    if (dev->is_open) {
791
1.20M
        code = (*dev_proc(dev, close_device))(dev);
792
1.20M
        dev->is_open = false;
793
1.20M
        if (code < 0)
794
0
            return_error(code);
795
1.20M
    }
796
170M
    return code;
797
170M
}
798
799
/*
800
 * Just set the device without any reinitializing.
801
 * (For internal use only.)
802
 */
803
void
804
gx_set_device_only(gs_gstate * pgs, gx_device * dev)
805
6.18M
{
806
6.18M
    rc_assign(pgs->device, dev, "gx_set_device_only");
807
6.18M
}
808
809
/* Compute the size of one scan line for a device. */
810
/* If pad = 0 return the line width in bytes. If pad = 1,
811
 * return the actual raster value (the number of bytes to offset from
812
 * a byte on one scanline to the same byte on the scanline below.) */
813
uint
814
gx_device_raster(const gx_device * dev, bool pad)
815
356M
{
816
356M
    int depth = dev->color_info.depth;
817
356M
    ulong bits = (ulong) dev->width * depth;
818
356M
    ulong raster;
819
356M
    int l2align;
820
821
356M
    if (dev->num_planar_planes) {
822
7.40M
        int num_components = dev->num_planar_planes;
823
        /* bpc accounts for unused bits, e.g. depth==4, num_comp==3, or depth==8, num_comps==5 */
824
7.40M
        int bpc = depth / num_components;
825
826
        /* depth can be <= num_components if planar and MEM_SET_PARAMS has changed it */
827
7.40M
        if (depth <= num_components || bpc >= 8) {
828
6.56M
            bits /= num_components;
829
6.56M
        } else {
830
            /* depth is original depth, not the plane_depth since it is > num_components */
831
838k
            bits /= (depth / bpc);
832
838k
        }
833
7.40M
    }
834
356M
    raster = (uint)((bits + 7) >> 3);
835
356M
    if (!pad)
836
164M
        return raster;
837
192M
    l2align = dev->log2_align_mod;
838
192M
    if (l2align < log2_align_bitmap_mod)
839
192M
        l2align = log2_align_bitmap_mod;
840
192M
    return (uint)(((bits + (8 << l2align) - 1) >> (l2align + 3)) << l2align);
841
356M
}
842
843
uint
844
gx_device_raster_chunky(const gx_device * dev, bool pad)
845
8.47k
{
846
8.47k
    ulong bits = (ulong) dev->width * dev->color_info.depth;
847
8.47k
    ulong raster;
848
8.47k
    int l2align;
849
850
8.47k
    raster = (uint)((bits + 7) >> 3);
851
8.47k
    if (!pad)
852
8.47k
        return raster;
853
0
    l2align = dev->log2_align_mod;
854
0
    if (l2align < log2_align_bitmap_mod)
855
0
        l2align = log2_align_bitmap_mod;
856
0
    return (uint)(((bits + (8 << l2align) - 1) >> (l2align + 3)) << l2align);
857
8.47k
}
858
uint
859
gx_device_raster_plane(const gx_device * dev, const gx_render_plane_t *render_plane)
860
160M
{
861
160M
    ulong bpc = (render_plane && render_plane->index >= 0 ?
862
160M
        render_plane->depth : dev->color_info.depth/(dev->num_planar_planes ? dev->num_planar_planes : 1));
863
160M
    ulong bits = (ulong) dev->width * bpc;
864
160M
    int l2align;
865
866
160M
    l2align = dev->log2_align_mod;
867
160M
    if (l2align < log2_align_bitmap_mod)
868
160M
        l2align = log2_align_bitmap_mod;
869
160M
    return (uint)(((bits + (8 << l2align) - 1) >> (l2align + 3)) << l2align);
870
160M
}
871
872
/* Adjust the resolution for devices that only have a fixed set of */
873
/* geometries, so that the apparent size in inches remains constant. */
874
/* If fit=1, the resolution is adjusted so that the entire image fits; */
875
/* if fit=0, one dimension fits, but the other one is clipped. */
876
int
877
gx_device_adjust_resolution(gx_device * dev,
878
                            int actual_width, int actual_height, int fit)
879
0
{
880
0
    double width_ratio = (double)actual_width / dev->width;
881
0
    double height_ratio = (double)actual_height / dev->height;
882
0
    double ratio =
883
0
    (fit ? min(width_ratio, height_ratio) :
884
0
     max(width_ratio, height_ratio));
885
886
0
    dev->HWResolution[0] *= ratio;
887
0
    dev->HWResolution[1] *= ratio;
888
0
    gx_device_set_width_height(dev, actual_width, actual_height);
889
0
    return 0;
890
0
}
891
892
/* Set the HWMargins to values defined in inches. */
893
/* If move_origin is true, also reset the Margins. */
894
/* Note that this assumes a printer-type device (Y axis inverted). */
895
void
896
gx_device_set_margins(gx_device * dev, const float *margins /*[4] */ ,
897
                      bool move_origin)
898
250k
{
899
250k
    int i;
900
901
1.25M
    for (i = 0; i < 4; ++i)
902
1.00M
        dev->HWMargins[i] = margins[i] * 72.0;
903
250k
    if (move_origin) {
904
0
        dev->Margins[0] = -margins[0] * dev->HWResolution[0];
905
0
        dev->Margins[1] = -margins[3] * dev->HWResolution[1];
906
0
    }
907
250k
}
908
909
static void
910
gx_device_set_hwsize_from_media(gx_device *dev)
911
587k
{
912
587k
    int rot = (dev->LeadingEdge & 1);
913
587k
    double rot_media_x = rot ? dev->MediaSize[1] : dev->MediaSize[0];
914
587k
    double rot_media_y = rot ? dev->MediaSize[0] : dev->MediaSize[1];
915
587k
    gx_device *parent = dev;
916
587k
    int hwsize[2];
917
918
    /* Try the spec_op to give the device to control it */
919
587k
    hwsize[0] = (int)(rot_media_x * dev->HWResolution[0] / 72.0 + 0.5);
920
587k
    hwsize[1] = (int)(rot_media_y * dev->HWResolution[1] / 72.0 + 0.5);
921
922
617k
    while (parent->parent != NULL) {
923
30.0k
        parent = parent->parent;
924
30.0k
    }
925
587k
    if (dev_proc(parent, dev_spec_op)(parent, gxdso_set_HWSize, &hwsize, sizeof(hwsize)) <= 0) {
926
        /* just do the default setting */
927
587k
        dev->width = hwsize[0];
928
587k
        dev->height = hwsize[1];
929
587k
    }
930
587k
}
931
932
static void
933
gx_device_set_media_from_hwsize(gx_device *dev)
934
73.4k
{
935
73.4k
    int rot = (dev->LeadingEdge & 1);
936
73.4k
    double x = dev->width * 72.0 / dev->HWResolution[0];
937
73.4k
    double y = dev->height * 72.0 / dev->HWResolution[1];
938
939
73.4k
    if (rot) {
940
0
        dev->MediaSize[1] = x;
941
0
        dev->MediaSize[0] = y;
942
73.4k
    } else {
943
73.4k
        dev->MediaSize[0] = x;
944
73.4k
        dev->MediaSize[1] = y;
945
73.4k
    }
946
73.4k
}
947
948
/* Set the width and height, updating MediaSize to remain consistent. */
949
void
950
gx_device_set_width_height(gx_device * dev, int width, int height)
951
73.4k
{
952
73.4k
    dev->width = width;
953
73.4k
    dev->height = height;
954
73.4k
    gx_device_set_media_from_hwsize(dev);
955
73.4k
}
956
957
/* Set the resolution, updating width and height to remain consistent. */
958
void
959
gx_device_set_resolution(gx_device * dev, double x_dpi, double y_dpi)
960
186k
{
961
186k
    dev->HWResolution[0] = x_dpi;
962
186k
    dev->HWResolution[1] = y_dpi;
963
186k
    gx_device_set_hwsize_from_media(dev);
964
186k
}
965
966
/* Set the MediaSize, updating width and height to remain consistent. */
967
void
968
gx_device_set_media_size(gx_device * dev, double media_width, double media_height)
969
401k
{
970
401k
    dev->MediaSize[0] = media_width;
971
401k
    dev->MediaSize[1] = media_height;
972
401k
    gx_device_set_hwsize_from_media(dev);
973
401k
}
974
975
/*
976
 * Copy the color mapping procedures from the target if they are
977
 * standard ones (saving a level of procedure call at mapping time).
978
 */
979
void
980
gx_device_copy_color_procs(gx_device *dev, const gx_device *target)
981
172M
{
982
172M
    dev_proc_map_cmyk_color((*from_cmyk)) =
983
172M
        dev_proc(dev, map_cmyk_color);
984
172M
    dev_proc_map_rgb_color((*from_rgb)) =
985
172M
        dev_proc(dev, map_rgb_color);
986
172M
    dev_proc_map_color_rgb((*to_rgb)) =
987
172M
        dev_proc(dev, map_color_rgb);
988
989
    /* The logic in this function seems a bit stale; it sets the
990
       old-style color procs, but not the new ones
991
       (get_color_mapping_procs, get_color_comp_index, encode_color,
992
       and decode_color). It should probably copy those as well.
993
    */
994
172M
    if (from_cmyk == gx_forward_map_cmyk_color ||
995
172M
        from_cmyk == cmyk_1bit_map_cmyk_color ||
996
172M
        from_cmyk == cmyk_8bit_map_cmyk_color) {
997
172M
        from_cmyk = dev_proc(target, map_cmyk_color);
998
172M
        set_dev_proc(dev, map_cmyk_color,
999
172M
                     (from_cmyk == cmyk_1bit_map_cmyk_color ||
1000
172M
                      from_cmyk == cmyk_8bit_map_cmyk_color ?
1001
172M
                      from_cmyk : gx_forward_map_cmyk_color));
1002
172M
    }
1003
172M
    if (from_rgb == gx_forward_map_rgb_color ||
1004
172M
        from_rgb == gx_default_rgb_map_rgb_color) {
1005
172M
        from_rgb = dev_proc(target, map_rgb_color);
1006
172M
        set_dev_proc(dev, map_rgb_color,
1007
172M
                     (from_rgb == gx_default_rgb_map_rgb_color ?
1008
172M
                      from_rgb : gx_forward_map_rgb_color));
1009
172M
    }
1010
172M
    if (to_rgb == gx_forward_map_color_rgb ||
1011
172M
        to_rgb == cmyk_1bit_map_color_rgb ||
1012
172M
        to_rgb == cmyk_8bit_map_color_rgb) {
1013
172M
        to_rgb = dev_proc(target, map_color_rgb);
1014
172M
        set_dev_proc(dev, map_color_rgb,
1015
172M
                     (to_rgb == cmyk_1bit_map_color_rgb ||
1016
172M
                      to_rgb == cmyk_8bit_map_color_rgb ?
1017
172M
                      to_rgb : gx_forward_map_color_rgb));
1018
172M
    }
1019
172M
}
1020
1021
640k
#define COPY_PARAM(p) dev->p = target->p
1022
1023
/*
1024
 * Copy the color-related device parameters back from the target:
1025
 * color_info and color mapping procedures.
1026
 */
1027
void
1028
gx_device_copy_color_params(gx_device *dev, const gx_device *target)
1029
319k
{
1030
319k
        COPY_PARAM(color_info);
1031
319k
        COPY_PARAM(cached_colors);
1032
319k
        gx_device_copy_color_procs(dev, target);
1033
319k
}
1034
1035
/*
1036
 * Copy device parameters back from a target.  This copies all standard
1037
 * parameters related to page size and resolution, plus color_info
1038
 * and (if appropriate) color mapping procedures.
1039
 */
1040
void
1041
gx_device_copy_params(gx_device *dev, const gx_device *target)
1042
247
{
1043
1.23k
#define COPY_ARRAY_PARAM(p) memcpy(dev->p, target->p, sizeof(dev->p))
1044
247
        COPY_PARAM(width);
1045
247
        COPY_PARAM(height);
1046
247
        COPY_ARRAY_PARAM(MediaSize);
1047
247
        COPY_ARRAY_PARAM(ImagingBBox);
1048
247
        COPY_PARAM(ImagingBBox_set);
1049
247
        COPY_ARRAY_PARAM(HWResolution);
1050
247
        COPY_ARRAY_PARAM(Margins);
1051
247
        COPY_ARRAY_PARAM(HWMargins);
1052
247
        COPY_PARAM(PageCount);
1053
247
        COPY_PARAM(MaxPatternBitmap);
1054
247
#undef COPY_ARRAY_PARAM
1055
247
        gx_device_copy_color_params(dev, target);
1056
247
}
1057
1058
#undef COPY_PARAM
1059
1060
/*
1061
 * Parse the output file name detecting and validating any %nnd format
1062
 * for inserting the page count.  If a format is present, store a pointer
1063
 * to its last character in *pfmt, otherwise store 0 there.
1064
 * Note that we assume devices have already been scanned, and any % must
1065
 * precede a valid format character.
1066
 *
1067
 * If there was a format, then return the max_width
1068
 */
1069
static int
1070
gx_parse_output_format(gs_parsed_file_name_t *pfn, const char **pfmt)
1071
581k
{
1072
581k
    bool have_format = false, field;
1073
581k
    uint width[2], int_width = sizeof(int) * 3, w = 0;
1074
581k
    uint i;
1075
1076
    /* Scan the file name for a format string, and validate it if present. */
1077
581k
    width[0] = width[1] = 0;
1078
7.23M
    for (i = 0; i < pfn->len; ++i)
1079
6.65M
        if (pfn->fname[i] == '%') {
1080
240
            if (i + 1 < pfn->len && pfn->fname[i + 1] == '%') {
1081
240
                i++;
1082
240
                continue;
1083
240
            }
1084
0
            if (have_format) /* more than one % */
1085
0
                return_error(gs_error_undefinedfilename);
1086
0
            have_format = true;
1087
0
            field = -1; /* -1..3 for the 5 components of "%[flags][width][.precision][l]type" */
1088
0
            for (;;)
1089
0
                if (++i == pfn->len)
1090
0
                    return_error(gs_error_undefinedfilename);
1091
0
                else {
1092
0
                    switch (field) {
1093
0
                        case -1: /* flags */
1094
0
                            if (strchr(" #+-", pfn->fname[i]))
1095
0
                                continue;
1096
0
                            else
1097
0
                                field++;
1098
                            /* falls through */
1099
0
                        default: /* width (field = 0) and precision (field = 1) */
1100
0
                            if (strchr("0123456789", pfn->fname[i])) {
1101
0
                                width[field] = width[field] * 10 + pfn->fname[i] - '0';
1102
0
                                if (width[field] > max_int)
1103
0
                                  return_error(gs_error_undefinedfilename);
1104
0
                                continue;
1105
0
                            } else if (0 == field && '.' == pfn->fname[i]) {
1106
0
                                field++;
1107
0
                                continue;
1108
0
                            } else
1109
0
                                field = 2;
1110
                            /* falls through */
1111
0
                        case 2: /* "long" indicator */
1112
0
                            field++;
1113
0
                            if ('l' == pfn->fname[i]) {
1114
0
                                int_width = sizeof(long) * 3;
1115
0
                                continue;
1116
0
                            }
1117
                            /* falls through */
1118
0
                        case 3: /* type */
1119
0
                            if (strchr("diuoxX", pfn->fname[i])) {
1120
0
                                *pfmt = &pfn->fname[i];
1121
0
                                break;
1122
0
                            } else
1123
0
                                return_error(gs_error_undefinedfilename);
1124
0
                    }
1125
0
                    break;
1126
0
                }
1127
0
        }
1128
581k
    if (have_format) {
1129
        /* Calculate a conservative maximum width. */
1130
0
        w = max(width[0], width[1]);
1131
0
        w = max(w, int_width) + 5;
1132
0
        if (w > max_int)
1133
0
            return_error(gs_error_undefinedfilename);
1134
0
    }
1135
581k
    return (int)w;
1136
581k
}
1137
1138
/*
1139
 * Parse the output file name for a device, recognizing "-" and "|command",
1140
 * and also detecting and validating any %nnd format for inserting the
1141
 * page count.  If a format is present, store a pointer to its last
1142
 * character in *pfmt, otherwise store 0 there.  Note that an empty name
1143
 * is currently allowed.
1144
 */
1145
int
1146
gx_parse_output_file_name(gs_parsed_file_name_t *pfn, const char **pfmt,
1147
                          const char *fname, uint fnlen, gs_memory_t *memory)
1148
581k
{
1149
581k
    int code;
1150
1151
581k
    *pfmt = 0;
1152
581k
    pfn->memory = 0;
1153
581k
    pfn->iodev = NULL;
1154
581k
    pfn->fname = NULL;    /* irrelevant since length = 0 */
1155
581k
    pfn->len = 0;
1156
581k
    if (fnlen == 0)      /* allow null name */
1157
0
        return 0;
1158
    /*
1159
     * If the file name begins with a %, it might be either an IODevice
1160
     * or a %nnd format.  Check (carefully) for this case.
1161
     */
1162
581k
    code = gs_parse_file_name(pfn, fname, fnlen, memory);
1163
581k
    if (code < 0) {
1164
0
        if (fname[0] == '%') {
1165
            /* not a recognized iodev -- may be a leading format descriptor */
1166
0
            pfn->len = fnlen;
1167
0
            pfn->fname = fname;
1168
0
            code = gx_parse_output_format(pfn, pfmt);
1169
0
        }
1170
0
        if (code < 0)
1171
0
            return code;
1172
0
    }
1173
581k
    if (!pfn->iodev) {
1174
581k
        if ( (pfn->len == 1) && (pfn->fname[0] == '-') ) {
1175
0
            pfn->iodev = gs_findiodevice(memory, (const byte *)"%stdout", 7);
1176
0
            pfn->fname = NULL;
1177
581k
        } else if (pfn->fname[0] == '|') {
1178
0
            pfn->iodev = gs_findiodevice(memory, (const byte *)"%pipe", 5);
1179
0
            pfn->fname++, pfn->len--;
1180
0
        } else
1181
581k
            pfn->iodev = iodev_default(memory);
1182
581k
        if (!pfn->iodev)
1183
0
            return_error(gs_error_undefinedfilename);
1184
581k
    }
1185
581k
    if (!pfn->fname)
1186
0
        return 0;
1187
581k
    code = gx_parse_output_format(pfn, pfmt);
1188
581k
    if (code < 0) {
1189
0
        return code;
1190
0
    }
1191
1192
581k
    if (pfn->len >= gp_file_name_sizeof - strlen(pfn->iodev->dname) ||
1193
581k
        code >= gp_file_name_sizeof - strlen(pfn->iodev->dname) - pfn->len) {
1194
0
        return_error(gs_error_undefinedfilename);
1195
0
    }
1196
1197
581k
    return 0;
1198
581k
}
1199
1200
/* Check if we write each page into separate file. */
1201
bool
1202
gx_outputfile_is_separate_pages(const char *fname, gs_memory_t *memory)
1203
78.6k
{
1204
78.6k
    const char *fmt;
1205
78.6k
    gs_parsed_file_name_t parsed;
1206
78.6k
    int code = gx_parse_output_file_name(&parsed, &fmt, fname,
1207
78.6k
                                         strlen(fname), memory);
1208
1209
78.6k
    return (code >= 0 && fmt != 0);
1210
78.6k
}
1211
1212
/* Delete the current output file for a device (file must be closed first) */
1213
int gx_device_delete_output_file(const gx_device * dev, const char *fname)
1214
0
{
1215
0
    gs_parsed_file_name_t parsed;
1216
0
    const char *fmt;
1217
0
    char *pfname = (char *)gs_alloc_bytes(dev->memory, gp_file_name_sizeof, "gx_device_delete_output_file(pfname)");
1218
0
    int code;
1219
0
    size_t len;
1220
1221
0
    if (pfname == NULL) {
1222
0
        code = gs_note_error(gs_error_VMerror);
1223
0
        goto done;
1224
0
    }
1225
1226
0
    len = strlen(fname);
1227
0
    code = gx_parse_output_file_name(&parsed, &fmt, fname, len,
1228
0
                                         dev->memory);
1229
0
    if (code < 0) {
1230
0
        goto done;
1231
0
    }
1232
1233
0
    if (parsed.iodev && !strcmp(parsed.iodev->dname, "%stdout%"))
1234
0
        goto done;
1235
1236
0
    if (fmt) {           /* filename includes "%nnd" */
1237
0
        long count1 = dev->PageCount + 1;
1238
1239
0
        while (*fmt != 'l' && *fmt != '%')
1240
0
            --fmt;
1241
0
        if (*fmt == 'l')
1242
0
            gs_snprintf(pfname, gp_file_name_sizeof, parsed.fname, count1);
1243
0
        else
1244
0
            gs_snprintf(pfname, gp_file_name_sizeof, parsed.fname, (int)count1);
1245
0
    } else if (parsed.len && strchr(parsed.fname, '%')) /* filename with "%%" but no "%nnd" */
1246
0
        gs_snprintf(pfname, gp_file_name_sizeof, parsed.fname);
1247
0
    else
1248
0
        pfname[0] = 0; /* 0 to use "fname", not "pfname" */
1249
0
    if (pfname[0]) {
1250
0
        parsed.fname = pfname;
1251
0
        parsed.len = strlen(parsed.fname);
1252
0
    }
1253
0
    if (parsed.iodev)
1254
0
        code = parsed.iodev->procs.delete_file((gx_io_device *)(parsed.iodev), (const char *)parsed.fname);
1255
0
    else
1256
0
        code = gs_note_error(gs_error_invalidfileaccess);
1257
1258
0
done:
1259
0
    if (pfname != NULL)
1260
0
        gs_free_object(dev->memory, pfname, "gx_device_delete_output_file(pfname)");
1261
1262
0
    return(code);
1263
0
}
1264
1265
static int
1266
noclose(FILE *f)
1267
0
{
1268
0
    return 0;
1269
0
}
1270
1271
/* Open the output file for a device. */
1272
int
1273
gx_device_open_output_file(const gx_device * dev, char *fname,
1274
                           bool binary, bool positionable, gp_file ** pfile)
1275
127k
{
1276
127k
    gs_parsed_file_name_t parsed;
1277
127k
    const char *fmt;
1278
127k
    char *pfname = (char *)gs_alloc_bytes(dev->memory, gp_file_name_sizeof, "gx_device_open_output_file(pfname)");
1279
127k
    int code;
1280
1281
127k
    if (pfname == NULL) {
1282
0
        code = gs_note_error(gs_error_VMerror);
1283
0
        goto done;
1284
0
    }
1285
1286
127k
    if (strlen(fname) == 0) {
1287
0
        code = gs_note_error(gs_error_undefinedfilename);
1288
0
        emprintf1(dev->memory, "Device '%s' requires an output file but no file was specified.\n", dev->dname);
1289
0
        goto done;
1290
0
    }
1291
127k
    code = gx_parse_output_file_name(&parsed, &fmt, fname, strlen(fname), dev->memory);
1292
127k
    if (code < 0) {
1293
0
        goto done;
1294
0
    }
1295
1296
127k
    if (parsed.iodev && !strcmp(parsed.iodev->dname, "%stdout%")) {
1297
0
        if (parsed.fname) {
1298
0
            code = gs_note_error(gs_error_undefinedfilename);
1299
0
            goto done;
1300
0
        }
1301
0
        *pfile = gp_file_FILE_alloc(dev->memory);
1302
0
        if (*pfile == NULL) {
1303
0
            code = gs_note_error(gs_error_VMerror);
1304
0
            goto done;
1305
0
        }
1306
0
        gp_file_FILE_set(*pfile, dev->memory->gs_lib_ctx->core->fstdout, noclose);
1307
        /* Force stdout to binary. */
1308
0
        code = gp_setmode_binary_impl(dev->memory->gs_lib_ctx->core->fstdout, true);
1309
0
        goto done;
1310
127k
    } else if (parsed.iodev && !strcmp(parsed.iodev->dname, "%pipe%")) {
1311
0
        positionable = false;
1312
0
    }
1313
127k
    if (fmt) {           /* filename includes "%nnd" */
1314
0
        long count1 = dev->PageCount + 1;
1315
1316
0
        while (*fmt != 'l' && *fmt != '%')
1317
0
            --fmt;
1318
0
        if (*fmt == 'l')
1319
0
            gs_snprintf(pfname, gp_file_name_sizeof, parsed.fname, count1);
1320
0
        else
1321
0
            gs_snprintf(pfname, gp_file_name_sizeof, parsed.fname, (int)count1);
1322
127k
    } else if (parsed.len && strchr(parsed.fname, '%'))  /* filename with "%%" but no "%nnd" */
1323
3
        gs_snprintf(pfname, gp_file_name_sizeof, parsed.fname);
1324
127k
    else
1325
127k
        pfname[0] = 0; /* 0 to use "fname", not "pfname" */
1326
127k
    if (pfname[0]) {
1327
3
        parsed.fname = pfname;
1328
3
        parsed.len = strlen(parsed.fname);
1329
3
    }
1330
127k
    if (parsed.iodev &&
1331
127k
        (positionable || parsed.iodev != iodev_default(dev->memory))) {
1332
54.9k
        char fmode[4];
1333
1334
54.9k
        if (!parsed.fname) {
1335
0
            code = gs_note_error(gs_error_undefinedfilename);
1336
0
            goto done;
1337
0
        }
1338
54.9k
        strcpy(fmode, gp_fmode_wb);
1339
54.9k
        if (positionable)
1340
54.9k
            strcat(fmode, "+");
1341
54.9k
        code = parsed.iodev->procs.gp_fopen(parsed.iodev, parsed.fname, fmode,
1342
54.9k
                                            pfile, NULL, 0, dev->memory);
1343
54.9k
        if (code)
1344
2
            emprintf1(dev->memory,
1345
54.9k
                      "**** Could not open the file %s .\n",
1346
54.9k
                      parsed.fname);
1347
72.2k
    } else {
1348
72.2k
        *pfile = gp_open_printer(dev->memory, (pfname[0] ? pfname : fname), binary);
1349
72.2k
        if (!(*pfile)) {
1350
0
            emprintf1(dev->memory, "**** Could not open the file '%s'.\n", (pfname[0] ? pfname : fname));
1351
1352
0
            code = gs_note_error(gs_error_invalidfileaccess);
1353
0
        }
1354
72.2k
    }
1355
1356
127k
done:
1357
127k
    if (pfname != NULL)
1358
127k
        gs_free_object(dev->memory, pfname, "gx_device_open_output_file(pfname)");
1359
1360
127k
    return(code);
1361
127k
}
1362
1363
/* Close the output file for a device. */
1364
int
1365
gx_device_close_output_file(const gx_device * dev, const char *fname,
1366
                            gp_file *file)
1367
127k
{
1368
127k
    gs_parsed_file_name_t parsed;
1369
127k
    const char *fmt;
1370
127k
    int code = gx_parse_output_file_name(&parsed, &fmt, fname, strlen(fname),
1371
127k
                                         dev->memory);
1372
1373
127k
    if (code < 0)
1374
0
        return code;
1375
127k
    if (parsed.iodev) {
1376
127k
        if (!strcmp(parsed.iodev->dname, "%stdout%"))
1377
0
            return 0;
1378
        /* NOTE: fname is unsubstituted if the name has any %nnd formats. */
1379
127k
        if (parsed.iodev != iodev_default(dev->memory))
1380
0
            return parsed.iodev->procs.fclose(parsed.iodev, file);
1381
127k
    }
1382
127k
    gp_close_printer(file, (parsed.fname ? parsed.fname : fname));
1383
127k
    return 0;
1384
127k
}
1385
1386
bool gx_color_info_equal(const gx_device_color_info * p1, const gx_device_color_info * p2)
1387
136k
{
1388
136k
    if (p1->anti_alias.graphics_bits != p2->anti_alias.graphics_bits)
1389
0
        return false;
1390
136k
    if (p1->anti_alias.text_bits != p2->anti_alias.text_bits)
1391
0
        return false;
1392
136k
    if (p1->black_component != p2->black_component)
1393
0
        return false;
1394
136k
    if (strcmp(p1->cm_name, p2->cm_name) != 0)
1395
0
        return false;
1396
136k
    if (p1->depth != p2->depth)
1397
23.7k
        return false;
1398
113k
    if (p1->dither_colors != p2->dither_colors)
1399
0
        return false;
1400
113k
    if (p1->dither_grays != p2->dither_grays)
1401
0
        return false;
1402
113k
    if (p1->gray_index != p2->gray_index)
1403
0
        return false;
1404
113k
    if (p1->max_color != p2->max_color)
1405
0
        return false;
1406
113k
    if (p1->max_components != p2->max_components)
1407
0
        return false;
1408
113k
    if (p1->opmsupported != p2->opmsupported)
1409
0
        return false;
1410
113k
    if (p1->polarity != p2->polarity)
1411
0
        return false;
1412
113k
    if (p1->process_comps != p2->process_comps)
1413
0
        return false;
1414
113k
    if (p1->separable_and_linear != p2->separable_and_linear)
1415
0
        return false;
1416
113k
    if (p1->use_antidropout_downscaler != p2->use_antidropout_downscaler)
1417
0
        return false;
1418
113k
    return true;
1419
113k
}
1420
1421
int gx_callout(gx_device *dev, int id, int size, void *data)
1422
0
{
1423
0
    return gs_lib_ctx_callout(dev->memory, dev->dname,
1424
0
                              id, size, data);
1425
0
}
1426
1427
/* compare two space_params, we can't do this with memcmp since there is padding in the structure */
1428
int
1429
gdev_space_params_cmp(const gdev_space_params sp1,
1430
815k
                      const gdev_space_params sp2) {
1431
815k
  if (sp1.MaxBitmap != sp2.MaxBitmap)
1432
0
    return(1);
1433
815k
  if (sp1.BufferSpace != sp2.BufferSpace)
1434
0
    return(1);
1435
815k
  if (sp1.band.BandWidth != sp2.band.BandWidth)
1436
0
    return(1);
1437
815k
  if (sp1.band.BandHeight != sp2.band.BandHeight)
1438
0
    return(1);
1439
815k
  if (sp1.band.BandBufferSpace != sp2.band.BandBufferSpace)
1440
0
    return(1);
1441
815k
  if (sp1.band.tile_cache_size != sp2.band.tile_cache_size)
1442
0
    return(1);
1443
815k
  if (sp1.params_are_read_only != sp2.params_are_read_only)
1444
0
    return(1);
1445
815k
  if (sp1.banding_type != sp2.banding_type)
1446
0
    return(1);
1447
1448
815k
  return(0);
1449
815k
}
1450
1451
static void
1452
release_nts_lock(gx_device *dev)
1453
0
{
1454
0
    (void)gs_lib_ctx_nts_adjust(dev->memory, -1);
1455
0
}
1456
1457
int gx_init_non_threadsafe_device(gx_device *dev)
1458
0
{
1459
0
    int code;
1460
1461
0
    if (dev == NULL || dev->finalize != NULL)
1462
0
        return gs_error_unknownerror;
1463
1464
0
    code = gs_lib_ctx_nts_adjust(dev->memory, 1);
1465
0
    if (code < 0)
1466
0
        return code;
1467
1468
0
    dev->finalize = release_nts_lock;
1469
1470
0
    return 0;
1471
0
}