Coverage Report

Created: 2025-11-16 07:40

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