Coverage Report

Created: 2025-06-10 07:19

/src/ghostpdl/base/gsstate.c
Line
Count
Source (jump to first uncovered line)
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
/* Miscellaneous graphics state operators for Ghostscript library */
18
#include "gx.h"
19
#include "memory_.h"
20
#include "gserrors.h"
21
#include "gsstruct.h"
22
#include "gsutil.h"             /* for gs_next_ids */
23
#include "gzstate.h"
24
#include "gxcspace.h"           /* here for gscolor2.h */
25
#include "gscolor2.h"
26
#include "gscoord.h"            /* for gs_initmatrix */
27
#include "gscie.h"
28
#include "gxclipsr.h"
29
#include "gxcmap.h"
30
#include "gxdevice.h"
31
#include "gxpcache.h"
32
#include "gzht.h"
33
#include "gzline.h"
34
#include "gspath.h"
35
#include "gzpath.h"
36
#include "gzcpath.h"
37
#include "gsovrc.h"
38
#include "gxcolor2.h"
39
#include "gscolor3.h" /* for gs_smoothness() */
40
#include "gxpcolor.h"
41
#include "gsicc_manage.h"
42
#include "gxdevsop.h"
43
44
/* Forward references */
45
static gs_gstate *gstate_alloc(gs_memory_t *, client_name_t,
46
                               const gs_gstate *);
47
static gs_gstate *gstate_clone_for_gsave(gs_gstate *,
48
                                         client_name_t);
49
static gs_gstate *gstate_clone_for_gstate(const gs_gstate *, gs_memory_t *,
50
                                          client_name_t);
51
static void gstate_free_contents(gs_gstate *);
52
static int gstate_copy(gs_gstate *, const gs_gstate *,
53
                        gs_gstate_copy_reason_t, client_name_t);
54
static void clip_stack_rc_adjust(gx_clip_stack_t *cs, int delta, client_name_t cname);
55
56
/*
57
 * Graphics state storage management is complicated.  There are many
58
 * different classes of storage associated with a graphics state:
59
 *
60
 * (1) The gstate object itself.  This includes some objects physically
61
 *      embedded within the gstate object, but because of garbage collection
62
 *      requirements, there are no embedded objects that can be
63
 *      referenced by non-transient pointers.  We assume that the gstate
64
 *      stack "owns" its gstates and that we can free the top gstate when
65
 *      doing a restore.
66
 *
67
 * (2) Objects that are referenced directly by the gstate and whose lifetime
68
 *      is independent of the gstate.  These are garbage collected, not
69
 *      reference counted, so we don't need to do anything special with them
70
 *      when manipulating gstates.  Currently this includes:
71
 *              font
72
 *
73
 * (3) Objects that are referenced directly by the gstate, may be shared
74
 *      among gstates, and should disappear when no gstates reference them.
75
 *      These fall into two groups:
76
 *
77
 *   (3a) Objects that are logically connected to individual gstates.
78
 *      We use reference counting to manage these.  Currently these are:
79
 *              halftone, dev_ht(4), cie_render, black_generation,
80
 *              undercolor_removal, set_transfer.*, cie_joint_caches,
81
 *              clip_stack, {opacity,shape}.mask
82
 *      effective_transfer.* may point to some of the same objects as
83
 *      set_transfer.*, but don't contribute to the reference count.
84
 *      Similarly, dev_color may point to the dev_ht object.  For
85
 *      simplicity, we initialize all of these pointers to 0 and then
86
 *      allocate the object itself when needed.
87
 *
88
 *   (3b) Objects whose lifetimes are associated with something else.
89
 *      Currently these are:
90
 *              pattern_cache, which is associated with the entire
91
 *                stack, is allocated when first needed, and currently
92
 *                is never freed;
93
 *              view_clip, which is associated with the current
94
 *                save level (effectively, with the gstate sub-stack
95
 *                back to the save) and is managed specially;
96
 *
97
 * (4) Objects that are referenced directly by exactly one gstate and that
98
 *      are not referenced (except transiently) from any other object.
99
 *      These fall into two groups:
100
 *
101
 *   (4b) Objects allocated individually, for the given reason:
102
 *              line_params.dash.pattern (variable-length),
103
 *              color_space, path, clip_path, effective_clip.path,
104
 *              ccolor, dev_color
105
 *                  (may be referenced from image enumerators or elsewhere)
106
 *
107
 *   (4b) The "client data" for a gstate.  For the interpreter, this is
108
 *      the refs associated with the gstate, such as the screen procedures.
109
 *      Client-supplied procedures manage client data.
110
 *
111
 * (5) Objects referenced indirectly from gstate objects of category (4),
112
 *      including objects that may also be referenced directly by the gstate.
113
 *      The individual routines that manipulate these are responsible
114
 *      for doing the right kind of reference counting or whatever.
115
 *      Currently:
116
 *              devices, path, clip_path, and (if different from both clip_path
117
 *                and view_clip) effective_clip.path require
118
 *                gx_path_assign/free, which uses a reference count;
119
 *              color_space and ccolor require cs_adjust_color/cspace_count
120
 *                or cs_adjust_counts, which use a reference count;
121
 *              dev_color has no references to storage that it owns.
122
 *      We count on garbage collection or restore to deallocate
123
 *        sub-objects of halftone.
124
 *
125
 * Note that when after a gsave, the existing gstate references the related
126
 * objects that we allocate at the same time, and the newly allocated gstate
127
 * references the old related objects.  Similarly, during a grestore, we
128
 * free the related objects referenced by the current gstate, but after the
129
 * grestore, we free the saved gstate, not the current one.  However, when
130
 * we allocate gstates off-stack, the newly allocated gstate does reference
131
 * the newly allocated component objects.  Note also that setgstate /
132
 * currentgstate may produce gstates in which different allocators own
133
 * different sub-objects; this is OK, because restore guarantees that there
134
 * won't be any dangling pointers (as long as we don't allow pointers from
135
 * global gstates to local objects).
136
 */
137
138
/*
139
 * Define these elements of the graphics state that are allocated
140
 * individually for each state, except for line_params.dash.pattern.
141
 * Note that effective_clip_shared is not on the list.
142
 */
143
typedef struct gs_gstate_parts_s {
144
    gx_path *path;
145
    gx_clip_path *clip_path;
146
    gx_clip_path *effective_clip_path;
147
    struct {
148
        gs_client_color *ccolor;
149
        gx_device_color *dev_color;
150
    } color[2];
151
} gs_gstate_parts;
152
153
#define GSTATE_ASSIGN_PARTS(pto, pfrom)\
154
8.56M
  ((pto)->path = (pfrom)->path, (pto)->clip_path = (pfrom)->clip_path,\
155
8.56M
   (pto)->effective_clip_path = (pfrom)->effective_clip_path,\
156
8.56M
   (pto)->color[0].ccolor = (pfrom)->color[0].ccolor,\
157
8.56M
   (pto)->color[0].dev_color = (pfrom)->color[0].dev_color,\
158
8.56M
   (pto)->color[1].ccolor = (pfrom)->color[1].ccolor,\
159
8.56M
   (pto)->color[1].dev_color = (pfrom)->color[1].dev_color)
160
161
extern_st(st_gs_gstate); /* for gstate_alloc() */
162
163
/* Copy client data, using the copy_for procedure if available, */
164
/* the copy procedure otherwise. */
165
static int
166
gstate_copy_client_data(const gs_gstate * pgs, void *dto, void *dfrom,
167
                        gs_gstate_copy_reason_t reason)
168
8.48M
{
169
8.48M
    return (pgs->client_procs.copy_for != 0 ?
170
0
            (*pgs->client_procs.copy_for) (dto, dfrom, reason) :
171
8.48M
            (*pgs->client_procs.copy) (dto, dfrom));
172
8.48M
}
173
174
/* ------ Operations on the entire graphics state ------ */
175
176
/*
177
 * Allocate a path for the graphics state.  We use stable memory because
178
 * some PostScript files have Type 3 fonts whose BuildChar procedure
179
 * uses the sequence save ... setcachedevice ... restore, and the path
180
 * built between the setcachedevice and the restore must not be freed.
181
 * If it weren't for this, we don't think stable memory would be needed.
182
 */
183
static gs_memory_t *
184
gstate_path_memory(gs_memory_t *mem)
185
4.30M
{
186
4.30M
    return gs_memory_stable(mem);
187
4.30M
}
188
189
/* Allocate and initialize a graphics state. */
190
gs_gstate *
191
gs_gstate_alloc(gs_memory_t * mem)
192
14.5k
{
193
14.5k
    gs_gstate *pgs = gstate_alloc(mem, "gs_gstate_alloc", NULL);
194
14.5k
    gs_memory_t *path_mem = gstate_path_memory(mem);
195
14.5k
    int code;
196
197
14.5k
    if (pgs == 0)
198
0
        return 0;
199
14.5k
    GS_STATE_INIT_VALUES(pgs, 1.0);
200
    /* Need to set up at least enough to make gs_gstate_free happy */
201
14.5k
    pgs->saved = 0;
202
14.5k
    pgs->clip_stack = NULL;
203
14.5k
    pgs->view_clip = NULL;
204
14.5k
    pgs->font = NULL;
205
14.5k
    pgs->root_font = NULL;
206
14.5k
    pgs->show_gstate = NULL;
207
14.5k
    pgs->device = NULL;
208
209
    /*
210
     * Just enough of the state is initialized at this point
211
     * that it's OK to call gs_gstate_free if an allocation fails.
212
     */
213
214
14.5k
    code = gs_gstate_initialize(pgs, mem);
215
14.5k
    if (code < 0)
216
0
        goto fail;
217
218
    /* Finish initializing the color rendering state. */
219
220
14.5k
    rc_alloc_struct_1(pgs->halftone, gs_halftone, &st_halftone, mem,
221
14.5k
                      goto fail, "gs_gstate_alloc(halftone)");
222
14.5k
    pgs->halftone->type = ht_type_none;
223
224
    /* Initialize other things not covered by initgraphics */
225
226
14.5k
    pgs->clip_stack = 0;
227
14.5k
    pgs->view_clip = gx_cpath_alloc(path_mem, "gs_gstate_alloc(view_clip)");
228
14.5k
    if (pgs->view_clip == NULL)
229
0
        goto fail;
230
14.5k
    pgs->view_clip->rule = 0;   /* no clipping */
231
14.5k
    pgs->effective_clip_id = pgs->clip_path->id;
232
14.5k
    pgs->effective_view_clip_id = gs_no_id;
233
14.5k
    pgs->in_cachedevice = 0;
234
14.5k
    pgs->device = 0;            /* setting device adjusts refcts */
235
14.5k
    code = gs_nulldevice(pgs);
236
14.5k
    if (code < 0)
237
0
        goto fail;
238
14.5k
    gs_setfillconstantalpha(pgs, 1.0);
239
14.5k
    gs_setstrokeconstantalpha(pgs, 1.0);
240
14.5k
    gs_setalphaisshape(pgs, false);
241
14.5k
    gs_settransfer(pgs, gs_identity_transfer);
242
14.5k
    gs_setflat(pgs, 1.0);
243
14.5k
    gs_setfilladjust(pgs, 0.3, 0.3);
244
14.5k
    gs_setlimitclamp(pgs, false);
245
14.5k
    gs_setstrokeadjust(pgs, true);
246
14.5k
    pgs->font = 0;              /* Not right, but acceptable until the */
247
    /* PostScript code does the first setfont. */
248
14.5k
    pgs->root_font = 0;         /* ditto */
249
14.5k
    pgs->in_charpath = (gs_char_path_mode) 0;
250
14.5k
    pgs->show_gstate = 0;
251
14.5k
    pgs->level = 0;
252
14.5k
    if (gs_initgraphics(pgs) >= 0)
253
14.5k
        return pgs;
254
    /* Something went very wrong. */
255
0
fail:
256
0
    gs_gstate_free(pgs);
257
0
    return 0;
258
14.5k
}
259
260
/* Set the client data in a graphics state. */
261
/* This should only be done to a newly created state. */
262
void
263
gs_gstate_set_client(gs_gstate * pgs, void *pdata,
264
                    const gs_gstate_client_procs * pprocs, bool client_has_pattern_streams)
265
60.0k
{
266
60.0k
    pgs->client_data = pdata;
267
60.0k
    pgs->client_procs = *pprocs;
268
60.0k
    pgs->have_pattern_streams = client_has_pattern_streams;
269
60.0k
}
270
271
/* Get the client data from a graphics state. */
272
#undef gs_gstate_client_data     /* gzstate.h makes this a macro */
273
void *
274
gs_gstate_client_data(const gs_gstate * pgs)
275
6.53M
{
276
6.53M
    return pgs->client_data;
277
6.53M
}
278
279
/* Free the chain of gstates.*/
280
void
281
gs_gstate_free_chain(gs_gstate * pgs)
282
1.82k
{
283
1.82k
   gs_gstate *saved = pgs, *tmp;
284
285
3.65k
   while(saved != 0) {
286
1.82k
       tmp = saved->saved;
287
1.82k
       gs_gstate_free(saved);
288
1.82k
       saved = tmp;
289
1.82k
   }
290
1.82k
}
291
292
/* Free a graphics state. */
293
void
294
gs_gstate_free(gs_gstate * pgs)
295
63.2k
{
296
63.2k
    if (pgs == NULL)
297
312
        return;
298
62.9k
    gstate_free_contents(pgs);
299
62.9k
    gs_free_object(pgs->memory, pgs, "gs_gstate_free");
300
62.9k
}
301
302
/* Save the graphics state. */
303
int
304
gs_gsave(gs_gstate * pgs)
305
4.22M
{
306
4.22M
    gs_gstate *pnew = gstate_clone_for_gsave(pgs, "gs_gsave");
307
308
4.22M
    if (pnew == NULL)
309
0
        return_error(gs_error_VMerror);
310
    /* As of PLRM3, the interaction between gsave and the clip stack is
311
     * now clear. gsave stores the clip stack into the saved graphics
312
     * state, but then clears it in the current graphics state.
313
     *
314
     * Ordinarily, reference count rules would indicate an rc_decrement()
315
     * on pgs->clip_stack, but gstate_clone() has an exception for
316
     * the clip_stack field.
317
     */
318
4.22M
    pgs->clip_stack = NULL;
319
4.22M
    pgs->saved = pnew;
320
4.22M
    if (pgs->show_gstate == pgs)
321
0
        pgs->show_gstate = pnew->show_gstate = pnew;
322
4.22M
    pgs->trans_flags.xstate_change = false;
323
4.22M
    pgs->level++;
324
4.22M
    if_debug2m('g', pgs->memory, "[g]gsave -> "PRI_INTPTR", level = %d\n",
325
4.22M
              (intptr_t)pnew, pgs->level);
326
4.22M
    return 0;
327
4.22M
}
328
329
/*
330
 * Save the graphics state for a 'save'.
331
 * We cut the stack below the new gstate, and return the old one.
332
 * In addition to an ordinary gsave, we create a new view clip path.
333
 */
334
int
335
gs_gsave_for_save(gs_gstate * pgs, gs_gstate ** psaved)
336
95.8k
{
337
95.8k
    int code;
338
95.8k
    gx_clip_path *old_cpath = pgs->view_clip;
339
95.8k
    gx_clip_path *new_cpath;
340
341
95.8k
    if (old_cpath) {
342
95.8k
        new_cpath =
343
95.8k
            gx_cpath_alloc_shared(old_cpath, pgs->memory,
344
95.8k
                                  "gs_gsave_for_save(view_clip)");
345
95.8k
        if (new_cpath == 0)
346
0
            return_error(gs_error_VMerror);
347
95.8k
    } else {
348
0
        new_cpath = 0;
349
0
    }
350
95.8k
    code = gs_gsave(pgs);
351
95.8k
    if (code < 0)
352
0
        goto fail;
353
95.8k
    if (pgs->effective_clip_path == pgs->view_clip)
354
0
        pgs->effective_clip_path = new_cpath;
355
95.8k
    pgs->view_clip = new_cpath;
356
    /* Cut the stack so we can't grestore past here. */
357
95.8k
    *psaved = pgs->saved;
358
95.8k
    pgs->saved = 0;
359
360
95.8k
    code = gs_gsave(pgs);
361
95.8k
    if (code < 0) {
362
0
        pgs->saved = *psaved;
363
0
        *psaved = NULL;
364
0
        gs_grestore(pgs);
365
0
        return code;
366
0
    }
367
95.8k
    return code;
368
0
fail:
369
0
    if (new_cpath)
370
0
        gx_cpath_free(new_cpath, "gs_gsave_for_save(view_clip)");
371
0
    return code;
372
95.8k
}
373
374
/* Restore the graphics state. Can fully empty graphics stack */
375
int     /* return 0 if ok, 1 if stack was empty */
376
gs_grestore_only(gs_gstate * pgs)
377
4.21M
{
378
4.21M
    gs_gstate *saved = pgs->saved;
379
4.21M
    gs_gstate tmp_gstate;
380
4.21M
    void *pdata = pgs->client_data;
381
4.21M
    void *sdata;
382
383
4.21M
    if_debug2m('g', pgs->memory, "[g]grestore "PRI_INTPTR", level was %d\n",
384
4.21M
               (intptr_t)saved, pgs->level);
385
4.21M
    if (!saved)
386
0
        return 1;
387
4.21M
    sdata = saved->client_data;
388
4.21M
    if (saved->pattern_cache == 0)
389
4.94k
        saved->pattern_cache = pgs->pattern_cache;
390
    /* Swap back the client data pointers. */
391
4.21M
    pgs->client_data = sdata;
392
4.21M
    saved->client_data = pdata;
393
4.21M
    if (pdata != 0 && sdata != 0)
394
4.21M
        gstate_copy_client_data(pgs, pdata, sdata, copy_for_grestore);
395
4.21M
    gstate_free_contents(pgs);
396
4.21M
    tmp_gstate = *pgs;              /* temp after contents freed (with pointers zeroed) */
397
4.21M
    *pgs = *saved;
398
4.21M
    if (pgs->show_gstate == saved)
399
0
        pgs->show_gstate = pgs;
400
4.21M
    *saved = tmp_gstate;            /* restore "freed" state (pointers zeroed after contents freed) */
401
4.21M
    gs_free_object(pgs->memory, saved, "gs_grestore");
402
403
4.21M
    return 0;
404
4.21M
}
405
406
/* Restore the graphics state per PostScript semantics */
407
int
408
gs_grestore(gs_gstate * pgs)
409
4.20M
{
410
4.20M
    int code;
411
4.20M
    if (!pgs->saved)
412
0
        return gs_gsave(pgs);   /* shouldn't ever happen */
413
4.20M
    code = gs_grestore_only(pgs);
414
4.20M
    if (code < 0)
415
0
        return code;
416
417
    /* Wraparound: make sure there are always >= 1 saves on stack */
418
4.20M
    if (pgs->saved)
419
3.18M
        return 0;
420
1.01M
    return gs_gsave(pgs);
421
4.20M
}
422
423
/* Restore the graphics state for a 'restore', splicing the old stack */
424
/* back on.  Note that we actually do a grestoreall + 2 grestores. */
425
int
426
gs_grestoreall_for_restore(gs_gstate * pgs, gs_gstate * saved)
427
95.8k
{
428
95.8k
    int code;
429
430
177k
    while (pgs->saved->saved) {
431
81.4k
        code = gs_grestore(pgs);
432
81.4k
        if (code < 0)
433
0
            return code;
434
81.4k
    }
435
    /* Make sure we don't leave dangling pointers in the caches. */
436
95.8k
    if (pgs->pattern_cache)
437
95.8k
        (*pgs->pattern_cache->free_all) (pgs->pattern_cache);
438
95.8k
    pgs->saved->saved = saved;
439
95.8k
    code = gs_grestore(pgs);
440
95.8k
    if (code < 0)
441
0
        return code;
442
95.8k
    if (pgs->view_clip) {
443
95.8k
        gx_cpath_free(pgs->view_clip, "gs_grestoreall_for_restore");
444
95.8k
        pgs->view_clip = 0;
445
95.8k
    }
446
95.8k
    return gs_grestore(pgs);
447
95.8k
}
448
449
/* Restore to the bottommost graphics state (at this save level). */
450
int
451
gs_grestoreall(gs_gstate * pgs)
452
7
{
453
7
    if (!pgs->saved)            /* shouldn't happen */
454
0
        return gs_gsave(pgs);
455
7
    while (pgs->saved->saved) {
456
0
        int code = gs_grestore(pgs);
457
458
0
        if (code < 0)
459
0
            return code;
460
0
    }
461
7
    return gs_grestore(pgs);
462
7
}
463
464
/* Allocate and return a new graphics state. */
465
gs_gstate *
466
gs_gstate_copy(const gs_gstate * pgs, gs_memory_t * mem)
467
57.9k
{
468
57.9k
    gs_gstate *pnew;
469
470
57.9k
    pnew = gstate_clone_for_gstate(pgs, mem, "gs_gstate");
471
57.9k
    if (pnew == NULL)
472
0
        return NULL;
473
57.9k
    clip_stack_rc_adjust(pnew->clip_stack, 1, "gs_gstate_copy");
474
57.9k
    pnew->saved = NULL;
475
    /*
476
     * Prevent dangling references from the show_gstate pointer.  If
477
     * this context is its own show_gstate, set the pointer in the clone
478
     * to point to the clone; otherwise, set the pointer in the clone to
479
     * NULL, and let gs_setgstate fix it up.
480
     */
481
57.9k
    pnew->show_gstate =
482
57.9k
        (pgs->show_gstate == pgs ? pnew : NULL);
483
57.9k
    return pnew;
484
57.9k
}
485
486
/* Copy one previously allocated graphics state to another. */
487
int
488
gs_copygstate(gs_gstate * pto, const gs_gstate * pfrom)
489
0
{
490
0
    return gstate_copy(pto, pfrom, copy_for_copygstate, "gs_copygstate");
491
0
}
492
493
/* Copy the current graphics state to a previously allocated one. */
494
int
495
gs_currentgstate(gs_gstate * pto, const gs_gstate * pgs)
496
0
{
497
0
    int code =
498
0
        gstate_copy(pto, pgs, copy_for_currentgstate, "gs_currentgstate");
499
500
0
    if (code >= 0)
501
0
        pto->view_clip = 0;
502
0
    return code;
503
0
}
504
505
/* Restore the current graphics state from a previously allocated one. */
506
int
507
gs_setgstate(gs_gstate * pgs, const gs_gstate * pfrom)
508
3.94k
{
509
    /*
510
     * The implementation is the same as currentgstate,
511
     * except we must preserve the saved pointer, the level,
512
     * the view clip, and possibly the show_gstate.
513
     */
514
3.94k
    gs_gstate *saved_show = pgs->show_gstate;
515
3.94k
    int level = pgs->level;
516
3.94k
    gx_clip_path *view_clip = pgs->view_clip;
517
3.94k
    int code;
518
519
3.94k
    pgs->view_clip = 0;         /* prevent refcount decrementing */
520
3.94k
    code = gstate_copy(pgs, pfrom, copy_for_setgstate, "gs_setgstate");
521
3.94k
    if (code < 0)
522
0
        return code;
523
3.94k
    pgs->level = level;
524
3.94k
    pgs->view_clip = view_clip;
525
3.94k
    pgs->show_gstate =
526
3.94k
        (pgs->show_gstate == pfrom ? pgs : saved_show);
527
3.94k
    return 0;
528
3.94k
}
529
530
/* Get the allocator pointer of a graphics state. */
531
/* This is provided only for the interpreter */
532
/* and for color space implementation. */
533
gs_memory_t *
534
gs_gstate_memory(const gs_gstate * pgs)
535
14.2k
{
536
14.2k
    return pgs->memory;
537
14.2k
}
538
539
/* Get the saved pointer of the graphics state. */
540
/* This is provided only for Level 2 grestore. */
541
gs_gstate *
542
gs_gstate_saved(const gs_gstate * pgs)
543
2.12M
{
544
2.12M
    return pgs->saved;
545
2.12M
}
546
547
/* Swap the saved pointer of the graphics state. */
548
/* This is provided only for save/restore. */
549
gs_gstate *
550
gs_gstate_swap_saved(gs_gstate * pgs, gs_gstate * new_saved)
551
0
{
552
0
    gs_gstate *saved = pgs->saved;
553
554
0
    pgs->saved = new_saved;
555
0
    return saved;
556
0
}
557
558
/* Swap the memory pointer of the graphics state. */
559
/* This is provided only for the interpreter. */
560
gs_memory_t *
561
gs_gstate_swap_memory(gs_gstate * pgs, gs_memory_t * mem)
562
0
{
563
0
    gs_memory_t *memory = pgs->memory;
564
565
0
    pgs->memory = mem;
566
0
    return memory;
567
0
}
568
569
/* ------ Operations on components ------ */
570
571
/*
572
 * Push an overprint compositor onto the current device. Note that if
573
 * the current device already is an overprint compositor, the
574
 * composite will update its parameters but not create a new
575
 * compositor device.
576
 */
577
int
578
gs_gstate_update_overprint(gs_gstate * pgs, const gs_overprint_params_t * pparams)
579
55.9k
{
580
55.9k
    gs_composite_t *    pct = 0;
581
55.9k
    int                 code;
582
55.9k
    gx_device *         dev = pgs->device;
583
55.9k
    gx_device *         ovptdev;
584
585
55.9k
    code = gs_create_overprint(&pct, pparams, pgs->memory);
586
55.9k
    if (code >= 0) {
587
55.9k
        code = dev_proc(dev, composite)( dev,
588
55.9k
                                                   &ovptdev,
589
55.9k
                                                   pct,
590
55.9k
                                                   pgs,
591
55.9k
                                                   pgs->memory,
592
55.9k
                                                   NULL);
593
55.9k
        if (code >= 0 || code == gs_error_handled){
594
55.9k
            if (code == 1) {
595
0
                gx_set_device_only(pgs, ovptdev);
596
                /* Get rid of extra reference */
597
0
                rc_decrement(ovptdev, "gs_gstate_update_overprint(ovptdev)");
598
0
            }
599
55.9k
            code = 0;
600
55.9k
        }
601
55.9k
    }
602
55.9k
    if (pct != 0)
603
55.9k
        gs_free_object(pgs->memory, pct, "gs_gstate_update_overprint");
604
605
    /* the following hack handles devices that don't support compositors */
606
55.9k
    if (code == gs_error_unknownerror && !pparams->retain_any_comps)
607
0
        code = 0;
608
55.9k
    return code;
609
55.9k
}
610
611
/*
612
 * Reset the overprint mode for the current color space and color. This
613
 * routine should be called  whenever the current device (i.e.: color
614
 * model), overprint, overprint mode, color space, or color are modified.
615
 *
616
 * The need reason this routine must be called for changes in the current
617
 * color and must consider the current color involves the Pattern color
618
 * space. In that space, the "color" (pattern) can determine if the base
619
 * color space is used (PatternType 1 with PaintType 2), or may provide
620
 * is own color space (PatternType 1 with PaintType 1, PatternType 2).
621
 *
622
 * The most general situation (PatternType 1 with PaintType 1) cannot be
623
 * handled properly due to limitations of the pattern cache mechanism,
624
 * so in this case overprint is effectively disable by making all color
625
 * components "drawn".
626
 */
627
int
628
gs_do_set_overprint(gs_gstate * pgs)
629
27.9k
{
630
27.9k
    const gs_color_space *  pcs = gs_currentcolorspace_inline(pgs);
631
27.9k
    const gs_client_color * pcc = gs_currentcolor_inline(pgs);
632
27.9k
    int                     code = 0;
633
634
27.9k
    if (cs_num_components(pcs) < 0 && pcc->pattern != 0)
635
0
        code = pcc->pattern->type->procs.set_color(pcc, pgs);
636
27.9k
    else {
637
27.9k
        gx_device* dev = pgs->device;
638
27.9k
        cmm_dev_profile_t* dev_profile;
639
27.9k
        gs_color_space_index pcs_index = gs_color_space_get_index(pcs);
640
641
27.9k
        dev_proc(dev, get_profile)(dev, &dev_profile);
642
27.9k
        if (dev_profile->overprint_control == gs_overprint_control_disable)
643
0
            return code;
644
645
        /* Transparency device that supports spots and where we have
646
           sep or devicen colors needs special consideration if the device
647
           is in a additive blend mode.  This could
648
           be written more compactly, but it would be unreadable. */
649
27.9k
        if (dev_proc(dev, dev_spec_op)(dev, gxdso_pdf14_sep_device, NULL, 0) &&
650
27.9k
            (dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE)) {
651
0
            if (pcs_index == gs_color_space_index_Separation) {
652
0
                if (!(pcs->params.separation.color_type == SEP_MIX ||
653
0
                      pcs->params.separation.color_type == SEP_ENUM)) {
654
                    /* Sep color is not a spot color.  We can't do OP and trans */
655
0
                    return code;
656
0
                }
657
0
            } else if (pcs_index == gs_color_space_index_DeviceN) {
658
0
                if (pcs->params.device_n.color_type != SEP_PURE_SPOT) {
659
                    /* DeviceN has process colors  We can't do OP and trans. */
660
0
                    return code;
661
0
                }
662
0
            }
663
0
        }
664
665
        /* If we have a CIE-based space, use the ICC equivalent space */
666
27.9k
        if (gs_color_space_is_PSCIE(pcs) && pcs->icc_equivalent != NULL)
667
0
            pcs = pcs->icc_equivalent;
668
669
        /* The spaces that do not allow opm (e.g. ones that are not ICC or DeviceCMYK)
670
           will blow away any true setting later. But we have to be prepared
671
           in case this is a CMYK ICC space for example. Hence we set effective mode
672
           to mode here (Bug 698721)*/
673
27.9k
        pgs->color[0].effective_opm = pgs->overprint_mode;
674
675
27.9k
        if_debug2m(gs_debug_flag_overprint, pgs->memory,
676
27.9k
            "[overprint] gs_do_set_overprint. Preset effective mode. pgs->color[0].effective_opm = %d pgs->color[1].effective_opm = %d\n",
677
27.9k
            pgs->color[0].effective_opm, pgs->color[1].effective_opm);
678
679
27.9k
        pcs->type->set_overprint(pcs, pgs);
680
27.9k
    }
681
27.9k
    return code;
682
27.9k
}
683
684
/* setoverprint (non-stroke case) interpreter code
685
   ensures that this is called when appropriate. This
686
   should only be coming when we are doing PS files.
687
   As they don't have separate stroke and fill overprint
688
   controls */
689
void
690
gs_setoverprint(gs_gstate * pgs, bool ovp)
691
135k
{
692
135k
    pgs->overprint = ovp;
693
135k
    pgs->stroke_overprint = ovp;
694
135k
}
695
696
/* currentoverprint */
697
bool
698
gs_currentoverprint(const gs_gstate * pgs)
699
67.5k
{
700
67.5k
    return pgs->overprint;
701
67.5k
}
702
703
/* setstrokeoverprint */
704
void
705
gs_setstrokeoverprint(gs_gstate * pgs, bool ovp)
706
23.7k
{
707
23.7k
    pgs->stroke_overprint = ovp;
708
23.7k
}
709
710
/* currentstrokeoverprint */
711
bool
712
gs_currentstrokeoverprint(const gs_gstate * pgs)
713
0
{
714
0
    return pgs->stroke_overprint;
715
0
}
716
717
/* setstrokeoverprint */
718
void
719
gs_setfilloverprint(gs_gstate * pgs, bool ovp)
720
24.9k
{
721
24.9k
    pgs->overprint = ovp;
722
24.9k
}
723
724
/* currentstrokeoverprint */
725
bool
726
gs_currentfilloverprint(const gs_gstate * pgs)
727
0
{
728
0
    return pgs->overprint;
729
0
}
730
731
/* setoverprintmode */
732
int
733
gs_setoverprintmode(gs_gstate * pgs, int mode)
734
18.4k
{
735
18.4k
    if (mode < 0 || mode > 1)
736
0
        return_error(gs_error_rangecheck);
737
18.4k
    pgs->overprint_mode = mode;
738
739
18.4k
    return 0;
740
18.4k
}
741
742
/* currentoverprintmode */
743
int
744
gs_currentoverprintmode(const gs_gstate * pgs)
745
0
{
746
0
    return pgs->overprint_mode;
747
0
}
748
749
void
750
gs_setcpsimode(gs_memory_t *mem, bool mode)
751
0
{
752
0
    gs_lib_ctx_t *libctx = gs_lib_ctx_get_interp_instance(mem);
753
754
0
    libctx->core->CPSI_mode = mode;
755
0
}
756
757
/* currentcpsimode */
758
bool
759
gs_currentcpsimode(const gs_memory_t * mem)
760
37.2M
{
761
37.2M
    gs_lib_ctx_t *libctx = gs_lib_ctx_get_interp_instance(mem);
762
763
37.2M
    return libctx->core->CPSI_mode;
764
37.2M
}
765
766
/* The edgebuffer based scanconverter can only cope with values of 0
767
 * or 0.5 (i.e. 'center of pixel' or 'any part of pixel'). These
768
 * are the only values required for correct behaviour according to
769
 * the PDF and PS specs. Therefore, if we are using the edgebuffer
770
 * based scan converter, force these values. */
771
static void
772
sanitize_fill_adjust(gs_gstate * pgs)
773
24.1k
{
774
24.1k
    int scanconverter = gs_getscanconverter(pgs->memory);
775
24.1k
    if (scanconverter >= GS_SCANCONVERTER_EDGEBUFFER || (GS_SCANCONVERTER_DEFAULT_IS_EDGEBUFFER && scanconverter == GS_SCANCONVERTER_DEFAULT)) {
776
24.1k
        fixed adjust = (pgs->fill_adjust.x >= float2fixed(0.25) || pgs->fill_adjust.y >= float2fixed(0.25) ? fixed_half : 0);
777
24.1k
        pgs->fill_adjust.x = adjust;
778
24.1k
        pgs->fill_adjust.y = adjust;
779
24.1k
    }
780
24.1k
}
781
782
void
783
gs_setscanconverter(gs_gstate * gs, int converter)
784
0
{
785
0
    gs_lib_ctx_t *libctx = gs_lib_ctx_get_interp_instance(gs->memory);
786
787
0
    libctx->core->scanconverter = converter;
788
789
0
    sanitize_fill_adjust(gs);
790
0
}
791
792
/* getscanconverter */
793
int
794
gs_getscanconverter(const gs_memory_t * mem)
795
2.32M
{
796
2.32M
    gs_lib_ctx_t *libctx = gs_lib_ctx_get_interp_instance(mem);
797
798
2.32M
    return libctx->core->scanconverter;
799
2.32M
}
800
801
/* setrenderingintent
802
 *
803
 *  Use ICC numbers from Table 18 (section 6.1.11) rather than the PDF order
804
 *  to reduce re-coding and confusion.
805
 *    Perceptual            0
806
 *    Relative Colorimetric 1
807
 *    Saturation            2
808
 *    AbsoluteColorimetric  3
809
 */
810
int
811
4.23k
gs_setrenderingintent(gs_gstate *pgs, int ri) {
812
4.23k
    if (ri < 0 || ri > 3)
813
0
        return_error(gs_error_rangecheck);
814
4.23k
    pgs->renderingintent = ri;
815
4.23k
    return 0;
816
4.23k
}
817
818
/* currentrenderingintent */
819
int
820
gs_currentrenderingintent(const gs_gstate * pgs)
821
0
{
822
0
    return pgs->renderingintent;
823
0
}
824
825
int
826
0
gs_setblackptcomp(gs_gstate *pgs, bool bkpt) {
827
0
    pgs->blackptcomp = bkpt;
828
0
    return 0;
829
0
}
830
831
/* currentrenderingintent */
832
bool
833
gs_currentblackptcomp(const gs_gstate * pgs)
834
0
{
835
0
    return pgs->blackptcomp;
836
0
}
837
838
/*
839
 * Reset most of the graphics state.
840
 */
841
int
842
gs_initgraphics(gs_gstate * pgs)
843
75.4k
{
844
75.4k
    int code;
845
75.4k
    const gs_gstate gstate_initial = {
846
75.4k
            gs_gstate_initial(1.0)
847
75.4k
        };
848
75.4k
    gs_matrix m;
849
75.4k
    gs_make_identity(&m);
850
851
75.4k
    gs_initmatrix(pgs);
852
75.4k
    if ((code = gs_newpath(pgs)) < 0 ||
853
75.4k
        (code = gs_initclip(pgs)) < 0 ||
854
75.4k
        (code = gs_setlinewidth(pgs, 1.0)) < 0 ||
855
75.4k
        (code = gs_setlinestartcap(pgs, gstate_initial.line_params.start_cap)) < 0 ||
856
75.4k
        (code = gs_setlineendcap(pgs, gstate_initial.line_params.end_cap)) < 0 ||
857
75.4k
        (code = gs_setlinedashcap(pgs, gstate_initial.line_params.dash_cap)) < 0 ||
858
75.4k
        (code = gs_setlinejoin(pgs, gstate_initial.line_params.join)) < 0 ||
859
75.4k
        (code = gs_setcurvejoin(pgs, gstate_initial.line_params.curve_join)) < 0 ||
860
75.4k
        (code = gs_setdash(pgs, (float *)0, 0, 0.0)) < 0 ||
861
75.4k
        (gs_setdashadapt(pgs, false),
862
75.4k
         (code = gs_setdotlength(pgs, 0.0, false))) < 0 ||
863
75.4k
        (code = gs_setdotorientation(pgs)) < 0 ||
864
75.4k
        (code = gs_setmiterlimit(pgs, gstate_initial.line_params.miter_limit)) < 0
865
75.4k
        )
866
0
        return code;
867
75.4k
    gs_init_rop(pgs);
868
    /* Initialize things so that gx_remap_color won't crash. */
869
75.4k
    if (pgs->icc_manager->default_gray == 0x00) {
870
9.57k
        gs_color_space  *pcs1, *pcs2;
871
872
9.57k
        pcs1 = gs_cspace_new_DeviceGray(pgs->memory);
873
9.57k
        if (pcs1 == NULL)
874
0
            return_error(gs_error_unknownerror);
875
876
9.57k
        if (pgs->color[0].color_space != NULL) {
877
0
            gs_setcolorspace(pgs, pcs1);
878
0
            rc_decrement_cs(pcs1, "gs_initgraphics");
879
9.57k
        } else {
880
9.57k
            pgs->color[0].color_space = pcs1;
881
9.57k
            gs_setcolorspace(pgs, pcs1);
882
9.57k
        }
883
9.57k
        code = gx_set_dev_color(pgs);
884
9.57k
        if (code < 0)
885
0
            return code;
886
887
9.57k
        gs_swapcolors_quick(pgs); /* To color 1 */
888
889
9.57k
        pcs2 = gs_cspace_new_DeviceGray(pgs->memory);
890
9.57k
        if (pcs2 == NULL)
891
0
            return_error(gs_error_unknownerror);
892
893
9.57k
        if (pgs->color[0].color_space != NULL) {
894
0
            gs_setcolorspace(pgs, pcs2);
895
0
            rc_decrement_cs(pcs2, "gs_initgraphics");
896
9.57k
        } else {
897
9.57k
            pgs->color[0].color_space = pcs2;
898
9.57k
            gs_setcolorspace(pgs, pcs2);
899
9.57k
        }
900
9.57k
        code = gx_set_dev_color(pgs);
901
902
9.57k
        gs_swapcolors_quick(pgs); /* To color 0 */
903
904
9.57k
        if (code < 0)
905
0
            return code;
906
907
65.8k
    } else {
908
65.8k
        gs_color_space  *pcs1, *pcs2;
909
910
65.8k
        pcs1 = gs_cspace_new_ICC(pgs->memory, pgs, 1);
911
65.8k
        if (pcs1 == NULL)
912
0
            return_error(gs_error_unknownerror);
913
914
65.8k
        if (pgs->color[0].color_space != NULL) {
915
60.8k
            gs_setcolorspace(pgs, pcs1);
916
60.8k
            rc_decrement_cs(pcs1, "gs_initgraphics");
917
60.8k
        } else {
918
4.94k
            pgs->color[0].color_space = pcs1;
919
4.94k
            gs_setcolorspace(pgs, pcs1);
920
4.94k
        }
921
65.8k
        code = gx_set_dev_color(pgs);
922
65.8k
        if (code < 0)
923
0
            return code;
924
925
65.8k
        gs_swapcolors_quick(pgs); /* To color 1 */
926
65.8k
        pcs2 = gs_cspace_new_ICC(pgs->memory, pgs, 1);
927
65.8k
        if (pcs2 == NULL)
928
0
            return_error(gs_error_unknownerror);
929
930
65.8k
        if (pgs->color[0].color_space != NULL) {
931
60.8k
            gs_setcolorspace(pgs, pcs2);
932
60.8k
            rc_decrement_cs(pcs2, "gs_initgraphics");
933
60.8k
        } else {
934
4.94k
            pgs->color[0].color_space = pcs2;
935
4.94k
            gs_setcolorspace(pgs, pcs2);
936
4.94k
        }
937
65.8k
        code = gx_set_dev_color(pgs);
938
939
65.8k
        gs_swapcolors_quick(pgs); /* To color 0 */
940
941
65.8k
        if (code < 0)
942
0
            return code;
943
65.8k
    }
944
75.4k
    pgs->in_cachedevice = 0;
945
946
75.4k
    code = gs_settextspacing(pgs, (double)0.0);
947
75.4k
    if (code < 0)
948
0
        goto exit;
949
75.4k
    code = gs_settextleading(pgs, (double)0.0);
950
75.4k
    if (code < 0)
951
0
        goto exit;
952
953
75.4k
    gs_settextrenderingmode(pgs, 0);
954
955
75.4k
    code = gs_setwordspacing(pgs, (double)0.0);
956
75.4k
    if (code < 0)
957
0
        goto exit;
958
75.4k
    code = gs_settexthscaling(pgs, (double)100.0);
959
75.4k
    if (code < 0)
960
0
        goto exit;
961
962
75.4k
    gs_setaccuratecurves(pgs, true);
963
964
75.4k
    code = gs_setstrokeconstantalpha(pgs, 1.0);
965
75.4k
    if (code < 0)
966
0
        goto exit;
967
75.4k
    code = gs_setfillconstantalpha(pgs, 1.0);
968
75.4k
    if (code < 0)
969
0
        goto exit;
970
75.4k
    code = gs_setalphaisshape(pgs, 0);
971
75.4k
    if (code < 0)
972
0
        goto exit;
973
75.4k
    code = gs_setblendmode(pgs, BLEND_MODE_Compatible);
974
75.4k
    if (code < 0)
975
0
        goto exit;
976
75.4k
    code = gs_settextknockout(pgs, true);
977
75.4k
    if (code < 0)
978
0
        goto exit;
979
75.4k
    code = gs_setsmoothness(pgs, 0.02); /* Match gs code */
980
75.4k
    if (code < 0)
981
0
        goto exit;
982
983
75.4k
    code = gs_settextmatrix(pgs, &m);
984
75.4k
    if (code < 0)
985
0
        goto exit;
986
987
75.4k
    code = gs_settextlinematrix(pgs, &m);
988
75.4k
    if (code < 0)
989
0
        goto exit;
990
75.4k
exit:
991
75.4k
    return code;
992
75.4k
}
993
994
/* setfilladjust */
995
int
996
gs_setfilladjust(gs_gstate * pgs, double adjust_x, double adjust_y)
997
24.1k
{
998
24.1k
#define CLAMP_TO_HALF(v)\
999
48.2k
    ((v) <= 0 ? fixed_0 : (v) >= 0.5 ? fixed_half : float2fixed(v));
1000
1001
24.1k
    pgs->fill_adjust.x = CLAMP_TO_HALF(adjust_x);
1002
24.1k
    pgs->fill_adjust.y = CLAMP_TO_HALF(adjust_y);
1003
1004
24.1k
    sanitize_fill_adjust(pgs);
1005
1006
24.1k
    return 0;
1007
24.1k
#undef CLAMP_TO_HALF
1008
24.1k
}
1009
1010
/* currentfilladjust */
1011
int
1012
gs_currentfilladjust(const gs_gstate * pgs, gs_point * adjust)
1013
15.3k
{
1014
15.3k
    adjust->x = fixed2float(pgs->fill_adjust.x);
1015
15.3k
    adjust->y = fixed2float(pgs->fill_adjust.y);
1016
15.3k
    return 0;
1017
15.3k
}
1018
1019
/* setlimitclamp */
1020
void
1021
gs_setlimitclamp(gs_gstate * pgs, bool clamp)
1022
29.0k
{
1023
29.0k
    pgs->clamp_coordinates = clamp;
1024
29.0k
}
1025
1026
/* currentlimitclamp */
1027
bool
1028
gs_currentlimitclamp(const gs_gstate * pgs)
1029
0
{
1030
0
    return pgs->clamp_coordinates;
1031
0
}
1032
1033
/* settextrenderingmode */
1034
void
1035
gs_settextrenderingmode(gs_gstate * pgs, uint trm)
1036
121k
{
1037
121k
    pgs->text_rendering_mode = trm;
1038
121k
}
1039
1040
/* currenttextrenderingmode */
1041
uint
1042
gs_currenttextrenderingmode(const gs_gstate * pgs)
1043
1.90M
{
1044
1.90M
    return pgs->text_rendering_mode;
1045
1.90M
}
1046
1047
double
1048
gs_currenttextspacing(const gs_gstate *pgs)
1049
1.25M
{
1050
1.25M
    return pgs->textspacing;
1051
1.25M
}
1052
1053
int
1054
gs_settextspacing(gs_gstate *pgs, double Tc)
1055
115k
{
1056
115k
    int code = 0;
1057
115k
    gs_fixed_point dxy;
1058
1059
115k
    code = gs_distance_transform2fixed(&pgs->ctm, Tc, 1, &dxy);
1060
115k
    if (code < 0)
1061
10
        return code;
1062
1063
115k
    pgs->textspacing = (float)Tc;
1064
115k
    return 0;
1065
115k
}
1066
1067
double
1068
gs_currenttextleading(const gs_gstate *pgs)
1069
0
{
1070
0
    return pgs->textleading;
1071
0
}
1072
1073
int
1074
gs_settextleading(gs_gstate *pgs, double TL)
1075
105k
{
1076
105k
    pgs->textleading = (float)TL;
1077
105k
    return 0;
1078
105k
}
1079
1080
double
1081
gs_currenttextrise(const gs_gstate *pgs)
1082
0
{
1083
0
    return pgs->textrise;
1084
0
}
1085
1086
int
1087
gs_settextrise(gs_gstate *pgs, double Ts)
1088
327
{
1089
327
    pgs->textrise = (float)Ts;
1090
327
    return 0;
1091
327
}
1092
1093
double
1094
gs_currentwordspacing(const gs_gstate *pgs)
1095
1.25M
{
1096
1.25M
    return pgs->wordspacing;
1097
1.25M
}
1098
1099
int
1100
gs_setwordspacing(gs_gstate *pgs, double Tw)
1101
83.8k
{
1102
83.8k
    pgs->wordspacing = (float)Tw;
1103
83.8k
    return 0;
1104
83.8k
}
1105
1106
int
1107
gs_settexthscaling(gs_gstate *pgs, double Tz)
1108
91.1k
{
1109
91.1k
    pgs->texthscaling = (float)Tz;
1110
91.1k
    return 0;
1111
91.1k
}
1112
1113
double
1114
gs_currenttexthscaling(const gs_gstate *pgs)
1115
0
{
1116
0
    return pgs->texthscaling;
1117
0
}
1118
1119
int
1120
gs_setPDFfontsize(gs_gstate *pgs, double Tf)
1121
115k
{
1122
115k
    pgs->PDFfontsize = (float)Tf;
1123
115k
    return 0;
1124
115k
}
1125
1126
double
1127
gs_currentPDFfontsize(const gs_gstate *pgs)
1128
0
{
1129
0
    return pgs->PDFfontsize;
1130
0
}
1131
1132
int
1133
gs_settextlinematrix(gs_gstate *pgs, gs_matrix *m)
1134
525k
{
1135
525k
    pgs->textlinematrix.xx = m->xx;
1136
525k
    pgs->textlinematrix.xy = m->xy;
1137
525k
    pgs->textlinematrix.yx = m->yx;
1138
525k
    pgs->textlinematrix.yy = m->yy;
1139
525k
    pgs->textlinematrix.tx = m->tx;
1140
525k
    pgs->textlinematrix.ty = m->ty;
1141
525k
    return 0;
1142
525k
}
1143
int
1144
gs_gettextlinematrix(gs_gstate *pgs, gs_matrix *m)
1145
0
{
1146
0
    m->xx = pgs->textlinematrix.xx;
1147
0
    m->xy = pgs->textlinematrix.xy;
1148
0
    m->yx = pgs->textlinematrix.yx;
1149
0
    m->yy = pgs->textlinematrix.yy;
1150
0
    m->tx = pgs->textlinematrix.tx;
1151
0
    m->ty = pgs->textlinematrix.ty;
1152
0
    return 0;
1153
0
}
1154
1155
int
1156
gs_settextmatrix(gs_gstate *pgs, gs_matrix *m)
1157
525k
{
1158
525k
    pgs->textmatrix.xx = m->xx;
1159
525k
    pgs->textmatrix.xy = m->xy;
1160
525k
    pgs->textmatrix.yx = m->yx;
1161
525k
    pgs->textmatrix.yy = m->yy;
1162
525k
    pgs->textmatrix.tx = m->tx;
1163
525k
    pgs->textmatrix.ty = m->ty;
1164
525k
    return 0;
1165
525k
}
1166
int
1167
gs_gettextmatrix(gs_gstate *pgs, gs_matrix *m)
1168
0
{
1169
0
    m->xx = pgs->textmatrix.xx;
1170
0
    m->xy = pgs->textmatrix.xy;
1171
0
    m->yx = pgs->textmatrix.yx;
1172
0
    m->yy = pgs->textmatrix.yy;
1173
0
    m->tx = pgs->textmatrix.tx;
1174
0
    m->ty = pgs->textmatrix.ty;
1175
0
    return 0;
1176
0
}
1177
1178
1179
/* sethpglpathmode */
1180
void
1181
gs_sethpglpathmode(gs_gstate * pgs, bool path)
1182
0
{
1183
0
    pgs->hpgl_path_mode = path;
1184
0
}
1185
1186
/* currenthpglpathmode */
1187
bool
1188
gs_currenthpglpathmode(const gs_gstate * pgs)
1189
0
{
1190
0
    return pgs->hpgl_path_mode;
1191
0
}
1192
1193
/* ------ Internal routines ------ */
1194
1195
/* Free the privately allocated parts of a gstate. */
1196
static void
1197
gstate_free_parts(gs_gstate * parts, gs_memory_t * mem, client_name_t cname)
1198
8.56M
{
1199
8.56M
    gs_free_object(mem, parts->color[1].dev_color, cname);
1200
8.56M
    gs_free_object(mem, parts->color[1].ccolor, cname);
1201
8.56M
    gs_free_object(mem, parts->color[0].dev_color, cname);
1202
8.56M
    gs_free_object(mem, parts->color[0].ccolor, cname);
1203
8.56M
    parts->color[1].dev_color = 0;
1204
8.56M
    parts->color[1].ccolor = 0;
1205
8.56M
    parts->color[0].dev_color = 0;
1206
8.56M
    parts->color[0].ccolor = 0;
1207
8.56M
    if (!parts->effective_clip_shared && parts->effective_clip_path) {
1208
0
        gx_cpath_free(parts->effective_clip_path, cname);
1209
0
        parts->effective_clip_path = 0;
1210
0
    }
1211
8.56M
    gx_cpath_free(parts->clip_path, cname);
1212
8.56M
    parts->clip_path = 0;
1213
8.56M
    if (parts->path) {
1214
4.29M
        gx_path_free(parts->path, cname);
1215
4.29M
        parts->path = 0;
1216
4.29M
    }
1217
8.56M
}
1218
1219
static inline void
1220
gstate_parts_init_dev_color(gx_device_color *dc)
1221
8.58M
{
1222
8.58M
    gx_device_color_type dct = dc->type;
1223
8.58M
    gs_graphics_type_tag_t gtt = dc->tag;
1224
8.58M
    memset(dc, 0x00, sizeof(gx_device_color));
1225
8.58M
    dc->type = dct;
1226
8.58M
    dc->tag = gtt;
1227
8.58M
}
1228
1229
/* Allocate the privately allocated parts of a gstate. */
1230
static int
1231
gstate_alloc_parts(gs_gstate * parts, const gs_gstate * shared,
1232
                   gs_memory_t * mem, client_name_t cname)
1233
4.29M
{
1234
4.29M
    gs_memory_t *path_mem = gstate_path_memory(mem);
1235
1236
4.29M
    parts->path =
1237
4.29M
        (shared ?
1238
4.27M
         gx_path_alloc_shared(shared->path, path_mem,
1239
4.27M
                              "gstate_alloc_parts(path)") :
1240
4.29M
         gx_path_alloc(path_mem, "gstate_alloc_parts(path)"));
1241
4.29M
    parts->clip_path =
1242
4.29M
        (shared ?
1243
4.27M
         gx_cpath_alloc_shared(shared->clip_path, mem,
1244
4.27M
                               "gstate_alloc_parts(clip_path)") :
1245
4.29M
         gx_cpath_alloc(mem, "gstate_alloc_parts(clip_path)"));
1246
4.29M
    if (!shared || shared->effective_clip_shared) {
1247
4.29M
        parts->effective_clip_path = parts->clip_path;
1248
4.29M
        parts->effective_clip_shared = true;
1249
4.29M
    } else {
1250
0
        parts->effective_clip_path =
1251
0
            gx_cpath_alloc_shared(shared->effective_clip_path, mem,
1252
0
                                  "gstate_alloc_parts(effective_clip_path)");
1253
0
        parts->effective_clip_shared = false;
1254
0
    }
1255
4.29M
    parts->color[0].color_space = NULL;
1256
4.29M
    parts->color[1].color_space = NULL;
1257
4.29M
    parts->color[0].ccolor =
1258
4.29M
        gs_alloc_struct(mem, gs_client_color, &st_client_color, cname);
1259
4.29M
    parts->color[1].ccolor =
1260
4.29M
        gs_alloc_struct(mem, gs_client_color, &st_client_color, cname);
1261
4.29M
    parts->color[0].dev_color =
1262
4.29M
        gs_alloc_struct(mem, gx_device_color, &st_device_color, cname);
1263
4.29M
    parts->color[1].dev_color =
1264
4.29M
        gs_alloc_struct(mem, gx_device_color, &st_device_color, cname);
1265
4.29M
    if (parts->path == 0 || parts->clip_path == 0 ||
1266
4.29M
        parts->effective_clip_path == 0 ||
1267
4.29M
        parts->color[0].ccolor == 0 || parts->color[0].dev_color == 0 ||
1268
4.29M
        parts->color[1].ccolor == 0 || parts->color[1].dev_color == 0
1269
4.29M
        ) {
1270
0
        gstate_free_parts(parts, mem, cname);
1271
0
        return_error(gs_error_VMerror);
1272
0
    }
1273
4.29M
    gstate_parts_init_dev_color(parts->color[0].dev_color);
1274
4.29M
    gstate_parts_init_dev_color(parts->color[1].dev_color);
1275
4.29M
    return 0;
1276
4.29M
}
1277
1278
/*
1279
 * Allocate a gstate and its contents.
1280
 * If pfrom is not NULL, the path, clip_path, and (if distinct from both
1281
 * clip_path and view_clip) effective_clip_path share the segments of
1282
 * pfrom's corresponding path(s).
1283
 */
1284
static gs_gstate *
1285
gstate_alloc(gs_memory_t * mem, client_name_t cname, const gs_gstate * pfrom)
1286
4.29M
{
1287
4.29M
    gs_gstate *pgs =
1288
4.29M
        gs_alloc_struct(mem, gs_gstate, &st_gs_gstate, cname);
1289
1290
4.29M
    if (pgs == NULL)
1291
0
        return NULL;
1292
4.29M
    memset(pgs, 0x00, sizeof(gs_gstate));
1293
4.29M
    if (gstate_alloc_parts(pgs, pfrom, mem, cname) < 0) {
1294
0
        gs_free_object(mem, pgs, cname);
1295
0
        return NULL;
1296
0
    }
1297
4.29M
    pgs->memory = mem;
1298
4.29M
    return pgs;
1299
4.29M
}
1300
1301
/* Copy the dash pattern from one gstate to another. */
1302
static int
1303
gstate_copy_dash(gs_memory_t *mem, gx_dash_params *dash , const gs_gstate * pfrom)
1304
14.7k
{
1305
14.7k
    return gx_set_dash(dash, pfrom->line_params.dash.pattern,
1306
14.7k
                      pfrom->line_params.dash.pattern_size,
1307
14.7k
                      pfrom->line_params.dash.offset, mem);
1308
14.7k
}
1309
1310
typedef struct {
1311
    gs_gstate_parts  parts;
1312
    gx_dash_params   dash;
1313
} gs_gstate_clone_data;
1314
1315
static gs_gstate *
1316
gstate_clone_core(const gs_gstate               *pfrom,
1317
                        gs_memory_t             *mem,
1318
                        client_name_t            cname,
1319
                        gs_gstate_clone_data    *clone_data,
1320
                        gs_gstate_copy_reason_t  reason)
1321
4.27M
{
1322
4.27M
    gs_gstate *pgs = gstate_alloc(mem, cname, pfrom);
1323
4.27M
    void *pdata = NULL;
1324
1325
4.27M
    if (pgs == NULL)
1326
0
        return NULL;
1327
4.27M
    if (pfrom->client_data != NULL) {
1328
4.27M
        pdata = (*pfrom->client_procs.alloc) (mem);
1329
1330
4.27M
        if (pdata == NULL ||
1331
4.27M
            gstate_copy_client_data(pfrom, pdata, pfrom->client_data,
1332
4.27M
                                    reason) < 0)
1333
0
            goto failEarly;
1334
4.27M
    }
1335
    /* Copy the dash and dash pattern if necessary. */
1336
4.27M
    clone_data->dash = gs_currentlineparams_inline(pfrom)->dash;
1337
4.27M
    if (clone_data->dash.pattern) {
1338
14.6k
        int code;
1339
1340
14.6k
        clone_data->dash.pattern = NULL; /* Ensures a fresh allocation */
1341
14.6k
        code = gstate_copy_dash(mem, &clone_data->dash, pfrom);
1342
14.6k
        if (code < 0)
1343
0
            goto fail;
1344
14.6k
    }
1345
    /* Some records within pgs are allocated. We copy pfrom into pgs
1346
     * wholesale (to avoid problems with the structure being updated and
1347
     * us having to keep it in sync), so we copy those allocated regions
1348
     * out first. The caller of this routine will then put them back
1349
     * into either pgs or pfrom as appropriate. */
1350
4.27M
    GSTATE_ASSIGN_PARTS(&clone_data->parts, pgs);
1351
4.27M
    *pgs = *pfrom;
1352
4.27M
    pgs->client_data = pdata;
1353
1354
4.27M
    gs_gstate_copied(pgs);
1355
    /* Don't do anything to clip_stack. */
1356
1357
4.27M
    rc_increment(pgs->device);
1358
4.27M
    *clone_data->parts.color[0].ccolor    = *pgs->color[0].ccolor;
1359
4.27M
    *clone_data->parts.color[0].dev_color = *pgs->color[0].dev_color;
1360
4.27M
    *clone_data->parts.color[1].ccolor    = *pgs->color[1].ccolor;
1361
4.27M
    *clone_data->parts.color[1].dev_color = *pgs->color[1].dev_color;
1362
4.27M
    cs_adjust_counts_icc(pgs, 1);
1363
4.27M
    cs_adjust_swappedcounts_icc(pgs, 1);
1364
1365
4.27M
    return pgs;
1366
1367
0
  fail:
1368
0
    gs_free_object(mem, clone_data->dash.pattern, cname);
1369
0
    if (pdata != NULL)
1370
0
        (*pfrom->client_procs.free) (pdata, mem, pgs);
1371
0
  failEarly:
1372
0
    gstate_free_parts(pgs, mem, cname);
1373
0
    gs_free_object(mem, pgs, cname);
1374
1375
0
    return NULL;
1376
0
}
1377
1378
1379
/* Clone an existing graphics state for use in gsave. The clone refers
1380
 * to the old contents, and the old state refers to the new contents. */
1381
/* Return NULL if the allocation fails. */
1382
static gs_gstate *
1383
gstate_clone_for_gsave(gs_gstate     *pfrom,
1384
                       client_name_t  cname)
1385
4.22M
{
1386
4.22M
    gs_gstate_clone_data clone_data;
1387
4.22M
    gs_gstate *pgs = gstate_clone_core(pfrom, pfrom->memory, cname,
1388
4.22M
                                       &clone_data, copy_for_gsave);
1389
1390
4.22M
    if (pgs == NULL)
1391
0
        return NULL;
1392
1393
    /* Newly allocated parts go back into pfrom, not pgs! */
1394
4.22M
    GSTATE_ASSIGN_PARTS(pfrom, &clone_data.parts);
1395
4.22M
    gs_currentlineparams_inline(pfrom)->dash = clone_data.dash;
1396
1397
4.22M
    return pgs;
1398
4.22M
}
1399
1400
/* Clone an existing graphics state. The view_clip is not copied. */
1401
/* Return NULL if the allocation fails. */
1402
static gs_gstate *
1403
gstate_clone_for_gstate(const gs_gstate     *pfrom,
1404
                              gs_memory_t   *mem,
1405
                              client_name_t  cname)
1406
57.9k
{
1407
57.9k
    gs_gstate_clone_data clone_data;
1408
57.9k
    gs_gstate *pgs = gstate_clone_core(pfrom, mem, cname, &clone_data,
1409
57.9k
                                       copy_for_gstate);
1410
1411
57.9k
    if (pgs == NULL)
1412
0
        return NULL;
1413
57.9k
    GSTATE_ASSIGN_PARTS(pgs, &clone_data.parts);
1414
57.9k
    pgs->view_clip = NULL;
1415
57.9k
    gs_currentlineparams_inline(pgs)->dash = clone_data.dash;
1416
57.9k
    pgs->memory = mem;
1417
1418
57.9k
    return pgs;
1419
57.9k
}
1420
1421
/* Adjust reference counters for the whole clip stack */
1422
/* accessible from the given point */
1423
static void
1424
clip_stack_rc_adjust(gx_clip_stack_t *cs, int delta, client_name_t cname)
1425
8.62M
{
1426
8.62M
    gx_clip_stack_t *p = cs;
1427
1428
8.62M
    while(p) {
1429
0
        gx_clip_stack_t *q = p;
1430
0
        p = p->next;
1431
0
        rc_adjust(q, delta, cname);
1432
0
    }
1433
8.62M
}
1434
1435
/*
1436
 * Finalization for graphics states. This is where we handle RC for those
1437
 * elements.
1438
 */
1439
void
1440
gs_gstate_finalize(const gs_memory_t *cmem,void *vptr)
1441
4.29M
{
1442
4.29M
    gs_gstate *pgs = (gs_gstate *)vptr;
1443
4.29M
    (void)cmem; /* unused */
1444
1445
4.29M
    if (cmem == NULL)
1446
0
        return;     /* place for breakpoint */
1447
4.29M
    gstate_free_contents(pgs);
1448
4.29M
}
1449
1450
/* Release the composite parts of a graphics state, */
1451
/* but not the state itself. */
1452
static void
1453
gstate_free_contents(gs_gstate * pgs)
1454
8.56M
{
1455
8.56M
    gs_memory_t *mem = pgs->memory;
1456
8.56M
    const char *const cname = "gstate_free_contents";
1457
1458
8.56M
    rc_decrement(pgs->device, cname);
1459
8.56M
    pgs->device = 0;
1460
8.56M
    clip_stack_rc_adjust(pgs->clip_stack, -1, cname);
1461
8.56M
    pgs->clip_stack = 0;
1462
8.56M
    if (pgs->view_clip != NULL && pgs->level == 0) {
1463
14.5k
        gx_cpath_free(pgs->view_clip, cname);
1464
14.5k
        pgs->view_clip = NULL;
1465
14.5k
    }
1466
8.56M
    if (pgs->client_data != 0)
1467
4.28M
        (*pgs->client_procs.free) (pgs->client_data, mem, pgs);
1468
8.56M
    pgs->client_data = 0;
1469
8.56M
    cs_adjust_counts_icc(pgs, -1);
1470
8.56M
    cs_adjust_swappedcounts_icc(pgs, -1);
1471
8.56M
    pgs->color[0].color_space = 0;
1472
8.56M
    pgs->color[1].color_space = 0;
1473
8.56M
    gs_free_object(mem, pgs->line_params.dash.pattern, cname);
1474
8.56M
    pgs->line_params.dash.pattern = 0;
1475
8.56M
    gstate_free_parts(pgs, mem, cname);     /* this also clears pointers to freed elements */
1476
8.56M
    gs_gstate_release(pgs);
1477
8.56M
}
1478
1479
/* Copy one gstate to another. */
1480
static int
1481
gstate_copy(gs_gstate * pto, const gs_gstate * pfrom,
1482
            gs_gstate_copy_reason_t reason, client_name_t cname)
1483
3.94k
{
1484
3.94k
    gs_gstate_parts parts;
1485
1486
3.94k
    GSTATE_ASSIGN_PARTS(&parts, pto);
1487
    /* Copy the dash pattern if necessary. */
1488
3.94k
    if (pfrom->line_params.dash.pattern || pto->line_params.dash.pattern) {
1489
20
        int code = gstate_copy_dash(pto->memory,
1490
20
                             &(gs_currentlineparams_inline(pto)->dash), pfrom);
1491
1492
20
        if (code < 0)
1493
0
            return code;
1494
20
    }
1495
    /*
1496
     * It's OK to decrement the counts before incrementing them,
1497
     * because anything that is going to survive has a count of
1498
     * at least 2 (pto and somewhere else) initially.
1499
     * Handle references from contents.
1500
     */
1501
3.94k
    cs_adjust_counts_icc(pto, -1);
1502
3.94k
    cs_adjust_swappedcounts_icc(pto, -1);
1503
3.94k
    gx_path_assign_preserve(pto->path, pfrom->path);
1504
3.94k
    gx_cpath_assign_preserve(pto->clip_path, pfrom->clip_path);
1505
    /*
1506
     * effective_clip_shared will be copied, but we need to do the
1507
     * right thing with effective_clip_path.
1508
     */
1509
3.94k
    if (pfrom->effective_clip_shared) {
1510
        /*
1511
         * pfrom->effective_clip_path is either pfrom->view_clip or
1512
         * pfrom->clip_path.
1513
         */
1514
3.94k
        parts.effective_clip_path =
1515
3.94k
            (pfrom->effective_clip_path == pfrom->view_clip ?
1516
3.94k
             pto->view_clip : parts.clip_path);
1517
3.94k
    } else
1518
0
        gx_cpath_assign_preserve(pto->effective_clip_path,
1519
0
                                 pfrom->effective_clip_path);
1520
3.94k
    *parts.color[0].ccolor    = *pfrom->color[0].ccolor;
1521
3.94k
    *parts.color[0].dev_color = *pfrom->color[0].dev_color;
1522
3.94k
    *parts.color[1].ccolor    = *pfrom->color[1].ccolor;
1523
3.94k
    *parts.color[1].dev_color = *pfrom->color[1].dev_color;
1524
    /* Handle references from gstate object. */
1525
3.94k
    rc_pre_assign(pto->device, pfrom->device, cname);
1526
3.94k
    if (pto->clip_stack != pfrom->clip_stack) {
1527
0
        clip_stack_rc_adjust(pfrom->clip_stack, 1, cname);
1528
0
        clip_stack_rc_adjust(pto->clip_stack, -1, cname);
1529
0
    }
1530
3.94k
    {
1531
3.94k
        struct gx_pattern_cache_s *pcache = pto->pattern_cache;
1532
3.94k
        void *pdata = pto->client_data;
1533
3.94k
        gs_memory_t *mem = pto->memory;
1534
3.94k
        gs_gstate *saved = pto->saved;
1535
3.94k
        float *pattern = pto->line_params.dash.pattern;
1536
1537
3.94k
        gs_gstate_pre_assign(pto, (const gs_gstate *)pfrom);
1538
3.94k
        *pto = *pfrom;
1539
3.94k
        pto->client_data = pdata;
1540
3.94k
        pto->memory = mem;
1541
3.94k
        pto->saved = saved;
1542
3.94k
        pto->line_params.dash.pattern = pattern;
1543
3.94k
        if (pto->pattern_cache == 0)
1544
0
            pto->pattern_cache = pcache;
1545
3.94k
        if (pfrom->client_data != 0) {
1546
            /* We need to break 'const' here. */
1547
3.84k
            gstate_copy_client_data((gs_gstate *) pfrom, pdata,
1548
3.84k
                                    pfrom->client_data, reason);
1549
3.84k
        }
1550
3.94k
    }
1551
3.94k
    GSTATE_ASSIGN_PARTS(pto, &parts);
1552
3.94k
    cs_adjust_counts_icc(pto, 1);
1553
3.94k
    cs_adjust_swappedcounts_icc(pto, 1);
1554
3.94k
    pto->show_gstate =
1555
3.94k
        (pfrom->show_gstate == pfrom ? pto : 0);
1556
3.94k
    return 0;
1557
3.94k
}
1558
1559
/* Accessories. */
1560
gs_id gx_get_clip_path_id(gs_gstate *pgs)
1561
0
{
1562
0
    return pgs->clip_path->id;
1563
0
}
1564
1565
void gs_swapcolors_quick(const gs_gstate *cpgs)
1566
2.16M
{
1567
2.16M
    union {
1568
2.16M
        const gs_gstate *cpgs;
1569
2.16M
        gs_gstate *pgs;
1570
2.16M
    } const_breaker;
1571
2.16M
    gs_gstate *pgs;
1572
2.16M
    struct gx_cie_joint_caches_s *tmp_cie;
1573
2.16M
    gs_devicen_color_map          tmp_ccm;
1574
2.16M
    gs_client_color              *tmp_cc;
1575
2.16M
    int                           tmp;
1576
2.16M
    gx_device_color              *tmp_dc;
1577
2.16M
    gs_color_space               *tmp_cs;
1578
1579
    /* Break const just once, neatly, here rather than
1580
     * hackily in every caller. */
1581
2.16M
    const_breaker.cpgs = cpgs;
1582
2.16M
    pgs = const_breaker.pgs;
1583
1584
2.16M
    tmp_cc               = pgs->color[0].ccolor;
1585
2.16M
    pgs->color[0].ccolor = pgs->color[1].ccolor;
1586
2.16M
    pgs->color[1].ccolor = tmp_cc;
1587
1588
2.16M
    tmp_dc                  = pgs->color[0].dev_color;
1589
2.16M
    pgs->color[0].dev_color = pgs->color[1].dev_color;
1590
2.16M
    pgs->color[1].dev_color = tmp_dc;
1591
1592
2.16M
    tmp_cs                    = pgs->color[0].color_space;
1593
2.16M
    pgs->color[0].color_space = pgs->color[1].color_space;
1594
2.16M
    pgs->color[1].color_space = tmp_cs;
1595
1596
    /* Overprint and effective_op vary with stroke/fill and cs */
1597
2.16M
    tmp                         = pgs->color[0].effective_opm;
1598
2.16M
    pgs->color[0].effective_opm = pgs->color[1].effective_opm;
1599
2.16M
    pgs->color[1].effective_opm = tmp;
1600
1601
    /* Swap the bits of the gs_gstate that depend on the current color */
1602
2.16M
    tmp_cie                   = pgs->cie_joint_caches;
1603
2.16M
    pgs->cie_joint_caches     = pgs->cie_joint_caches_alt;
1604
2.16M
    pgs->cie_joint_caches_alt = tmp_cie;
1605
1606
2.16M
    tmp_ccm                      = pgs->color_component_map;
1607
2.16M
    pgs->color_component_map     = pgs->color_component_map_alt;
1608
2.16M
    pgs->color_component_map_alt = tmp_ccm;
1609
1610
2.16M
    pgs->is_fill_color = !(pgs->is_fill_color); /* used by overprint for fill_stroke */
1611
2.16M
}
1612
1613
int
1614
gs_clip_bounds_in_user_space(gs_gstate *pgs, gs_rect *ubox)
1615
5.24k
{
1616
5.24k
    gx_clip_path *clip_path;
1617
5.24k
    gs_rect dbox;
1618
5.24k
    int code;
1619
1620
5.24k
    code = gx_effective_clip_path(pgs, &clip_path);
1621
5.24k
    if (code < 0)
1622
0
        return code;
1623
1624
5.24k
    dbox.p.x = fixed2float(clip_path->outer_box.p.x);
1625
5.24k
    dbox.p.y = fixed2float(clip_path->outer_box.p.y);
1626
5.24k
    dbox.q.x = fixed2float(clip_path->outer_box.q.x);
1627
5.24k
    dbox.q.y = fixed2float(clip_path->outer_box.q.y);
1628
5.24k
    return gs_bbox_transform_inverse(&dbox, &ctm_only(pgs), ubox);
1629
5.24k
}