Coverage Report

Created: 2022-04-16 11:23

/src/ghostpdl/psi/zgstate.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2021 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, for further information.
14
*/
15
16
17
/* Graphics state operators */
18
#include "math_.h"
19
#include "ghost.h"
20
#include "oper.h"
21
#include "ialloc.h"
22
#include "icremap.h"
23
#include "idict.h"
24
#include "istruct.h"
25
#include "igstate.h"
26
#include "gsmatrix.h"
27
#include "store.h"
28
#include "gscspace.h"
29
#include "iname.h"
30
31
/* Structure descriptors */
32
private_st_int_gstate();
33
private_st_int_remap_color_info();
34
35
/* ------ Utilities ------ */
36
37
static int
38
zset_real(i_ctx_t *i_ctx_p, int (*set_proc)(gs_gstate *, double))
39
0
{
40
0
    os_ptr op = osp;
41
0
    double param;
42
0
    int code = real_param(op, &param);
43
44
0
    if (code < 0)
45
0
        return_op_typecheck(op);
46
0
    code = set_proc(igs, param);
47
0
    if (code == 0)
48
0
        pop(1);
49
0
    return code;
50
0
}
51
52
static int
53
zcurrent_real(i_ctx_t *i_ctx_p, double (*current_proc)(const gs_gstate *))
54
0
{
55
0
    os_ptr op = osp;
56
57
0
    push(1);
58
0
    make_real(op, current_proc(igs));
59
0
    return 0;
60
0
}
61
62
static int
63
zset_bool(i_ctx_t *i_ctx_p, void (*set_proc)(gs_gstate *, bool))
64
0
{
65
0
    os_ptr op = osp;
66
67
0
    check_type(*op, t_boolean);
68
0
    set_proc(igs, op->value.boolval);
69
0
    pop(1);
70
0
    return 0;
71
0
}
72
73
static int
74
zcurrent_bool(i_ctx_t *i_ctx_p, bool (*current_proc)(const gs_gstate *))
75
0
{
76
0
    os_ptr op = osp;
77
78
0
    push(1);
79
0
    make_bool(op, current_proc(igs));
80
0
    return 0;
81
0
}
82
83
static int
84
zset_uint(i_ctx_t *i_ctx_p, void (*set_proc)(gs_gstate *, uint))
85
0
{
86
0
    os_ptr op = osp;
87
88
0
    check_type(*op, t_integer);
89
0
    set_proc(igs, op->value.intval);
90
0
    pop(1);
91
0
    return 0;
92
0
}
93
94
static int
95
zcurrent_uint(i_ctx_t *i_ctx_p, uint (*current_proc)(const gs_gstate *))
96
0
{
97
0
    os_ptr op = osp;
98
99
0
    push(1);
100
0
    make_int(op, current_proc(igs));
101
0
    return 0;
102
0
}
103
104
/* ------ Operations on the entire graphics state ------ */
105
106
/* "Client" procedures */
107
static void *gs_istate_alloc(gs_memory_t * mem);
108
static int gs_istate_copy(void *to, const void *from);
109
static void gs_istate_free(void *old, gs_memory_t * mem, gs_gstate *pgs);
110
static const gs_gstate_client_procs istate_procs = {
111
    gs_istate_alloc,
112
    gs_istate_copy,
113
    gs_istate_free,
114
    0,      /* copy_for */
115
};
116
117
/* Initialize the graphics stack. */
118
gs_gstate *
119
int_gstate_alloc(const gs_dual_memory_t * dmem)
120
683
{
121
683
    int_gstate *iigs;
122
683
    ref proc0;
123
683
    int_remap_color_info_t *prci;
124
683
    gs_ref_memory_t *lmem = dmem->space_local;
125
683
    gs_ref_memory_t *gmem = dmem->space_global;
126
683
    gs_gstate *pgs = gs_gstate_alloc((gs_memory_t *)lmem);
127
128
683
    if (pgs == NULL)
129
0
        return NULL;
130
131
683
    iigs = gs_alloc_struct((gs_memory_t *)lmem, int_gstate, &st_int_gstate,
132
683
                           "int_gstate_alloc(int_gstate)");
133
683
    if (iigs == NULL)
134
0
        return NULL;
135
23.9k
    int_gstate_map_refs(iigs, make_null);
136
683
    make_empty_array(&iigs->dash_pattern_array, a_all);
137
683
    if (gs_alloc_ref_array(lmem, &proc0, a_readonly + a_executable, 2,
138
683
                       "int_gstate_alloc(proc0)") < 0)
139
0
        return NULL;
140
683
    make_oper(proc0.value.refs, 0, zpop);
141
683
    make_real(proc0.value.refs + 1, 0.0);
142
683
    iigs->black_generation = proc0;
143
683
    iigs->undercolor_removal = proc0;
144
683
    make_false(&iigs->use_cie_color);
145
    /*
146
     * Even though the gstate itself is allocated in local VM, the
147
     * container for the color remapping procedure must be allocated in
148
     * global VM so that the gstate can be copied into global VM.
149
     */
150
683
    prci = gs_alloc_struct((gs_memory_t *)gmem, int_remap_color_info_t,
151
683
                           &st_int_remap_color_info,
152
683
                           "int_gstate_alloc(remap color info)");
153
683
    if (prci == NULL)
154
0
        return NULL;
155
683
    make_struct(&iigs->remap_color_info, imemory_space(gmem), prci);
156
683
    clear_pagedevice(iigs);
157
683
    gs_gstate_set_client(pgs, iigs, &istate_procs, true);
158
    /* PostScript code wants limit clamping enabled. */
159
683
    gs_setlimitclamp(pgs, true);
160
    /*
161
     * gsave and grestore only work properly
162
     * if there are always at least 2 entries on the stack.
163
     * We count on the PostScript initialization code to do a gsave.
164
     */
165
683
    return pgs;
166
683
}
167
168
/* - gsave - */
169
int
170
zgsave(i_ctx_t *i_ctx_p)
171
2
{
172
2
    return gs_gsave(igs);
173
2
}
174
175
/* - grestore - */
176
int
177
zgrestore(i_ctx_t *i_ctx_p)
178
2
{
179
2
    return gs_grestore(igs);
180
2
}
181
182
/* - grestoreall - */
183
int
184
zgrestoreall(i_ctx_t *i_ctx_p)
185
0
{
186
0
    return gs_grestoreall(igs);
187
0
}
188
189
/* - initgraphics - */
190
static int
191
zinitgraphics(i_ctx_t *i_ctx_p)
192
4.36k
{
193
    /*
194
     * Although gs_initgraphics resets the color space to DeviceGray, it does
195
     * not modify the 'interpreter' gstate, which stores a copy of the PostScript
196
     * object used to set the colour space. We could do this here, with effort,
197
     * but instead we choose t do it in gs_cspace.ps and handle it all in PostScript.
198
     */
199
4.36k
     make_empty_array(&istate->dash_pattern_array, a_all);
200
4.36k
     return gs_initgraphics(igs);
201
4.36k
}
202
203
/* ------ Operations on graphics state elements ------ */
204
205
/* <num> setlinewidth - */
206
static int
207
zsetlinewidth(i_ctx_t *i_ctx_p)
208
1
{
209
1
    os_ptr op = osp;
210
        /*
211
         * The Red Book doesn't say anything about this, but Adobe
212
         * interpreters return (or perhaps store) the absolute value
213
         * of the width.
214
         */
215
1
    double width;
216
1
    int code = real_param(op, &width);
217
218
1
    if (code < 0)
219
1
        return_op_typecheck(op);
220
1
    code = gs_setlinewidth(igs, fabs(width));
221
1
    if (code >= 0)
222
1
        pop(1);
223
1
    return code;
224
1
}
225
226
/* - currentlinewidth <num> */
227
static int
228
zcurrentlinewidth(i_ctx_t *i_ctx_p)
229
0
{
230
0
    os_ptr op = osp;
231
232
0
    push(1);
233
0
    make_real(op, gs_currentlinewidth(igs));
234
0
    return 0;
235
0
}
236
237
/* <cap_int> .setlinecap - */
238
static int
239
zsetlinecap(i_ctx_t *i_ctx_p)
240
0
{
241
0
    os_ptr op = osp;
242
0
    int param;
243
0
    int code = int_param(op, max_int, &param);
244
245
0
    if (code < 0 || (code = gs_setlinecap(igs, (gs_line_cap) param)) < 0)
246
0
        return code;
247
0
    pop(1);
248
0
    return 0;
249
0
}
250
251
/* - currentlinecap <cap_int> */
252
static int
253
zcurrentlinecap(i_ctx_t *i_ctx_p)
254
0
{
255
0
    os_ptr op = osp;
256
257
0
    push(1);
258
0
    make_int(op, (int)gs_currentlinecap(igs));
259
0
    return 0;
260
0
}
261
262
/* <join_int> .setlinejoin - */
263
static int
264
zsetlinejoin(i_ctx_t *i_ctx_p)
265
0
{
266
0
    os_ptr op = osp;
267
0
    int param;
268
0
    int code = int_param(op, max_int, &param);
269
270
0
    if (code < 0 || (code = gs_setlinejoin(igs, (gs_line_join) param)) < 0)
271
0
        return code;
272
0
    pop(1);
273
0
    return 0;
274
0
}
275
276
/* - currentlinejoin <join_int> */
277
static int
278
zcurrentlinejoin(i_ctx_t *i_ctx_p)
279
0
{
280
0
    os_ptr op = osp;
281
282
0
    push(1);
283
0
    make_int(op, (int)gs_currentlinejoin(igs));
284
0
    return 0;
285
0
}
286
287
/* <num> setmiterlimit - */
288
static int
289
zsetmiterlimit(i_ctx_t *i_ctx_p)
290
0
{
291
0
    return zset_real(i_ctx_p, gs_setmiterlimit);
292
0
}
293
294
/* - currentmiterlimit <num> */
295
static int
296
zcurrentmiterlimit(i_ctx_t *i_ctx_p)
297
0
{
298
0
    os_ptr op = osp;
299
300
0
    push(1);
301
0
    make_real(op, gs_currentmiterlimit(igs));
302
0
    return 0;
303
0
}
304
305
/* <array> <offset> setdash - */
306
static int
307
zsetdash(i_ctx_t *i_ctx_p)
308
0
{
309
0
    os_ptr op = osp;
310
0
    os_ptr op1 = op - 1;
311
0
    double offset;
312
0
    int code = real_param(op, &offset);
313
0
    uint i, n;
314
0
    gs_memory_t *mem = imemory;
315
0
    float *pattern;
316
317
0
    if (code < 0)
318
0
        return_op_typecheck(op);
319
0
    if (!r_is_array(op1))
320
0
        return_op_typecheck(op1);
321
    /* Adobe interpreters apparently don't check the array for */
322
    /* read access, so we won't either. */
323
    /*check_read(*op1); */
324
    /* Unpack the dash pattern and check it */
325
0
    n = r_size(op1);
326
0
    pattern =
327
0
        (float *)gs_alloc_byte_array(mem, n, sizeof(float), "setdash");
328
329
0
    if (pattern == 0)
330
0
        return_error(gs_error_VMerror);
331
0
    for (i = 0, code = 0; i < n && code >= 0; ++i) {
332
0
        ref element;
333
334
0
        array_get(mem, op1, (long)i, &element);
335
0
        code = float_param(&element, &pattern[i]);
336
0
    }
337
0
    if (code >= 0)
338
0
        code = gs_setdash(igs, pattern, n, offset);
339
0
    gs_free_object(mem, pattern, "setdash");  /* gs_setdash copies this */
340
0
    if (code < 0)
341
0
        return code;
342
0
    ref_assign(&istate->dash_pattern_array, op1);
343
0
    pop(2);
344
0
    return code;
345
0
}
346
347
/* - currentdash <array> <offset> */
348
static int
349
zcurrentdash(i_ctx_t *i_ctx_p)
350
0
{
351
0
    os_ptr op = osp;
352
353
0
    push(2);
354
0
    ref_assign(op - 1, &istate->dash_pattern_array);
355
0
    make_real(op, gs_currentdash_offset(igs));
356
0
    return 0;
357
0
}
358
359
/* <num> setflat - */
360
static int
361
zsetflat(i_ctx_t *i_ctx_p)
362
0
{
363
0
    return zset_real(i_ctx_p, gs_setflat);
364
0
}
365
366
/* - currentflat <num> */
367
static int
368
zcurrentflat(i_ctx_t *i_ctx_p)
369
0
{
370
0
    os_ptr op = osp;
371
372
0
    push(1);
373
0
    make_real(op, gs_currentflat(igs));
374
0
    return 0;
375
0
}
376
377
/* ------ Extensions ------ */
378
379
/* <bool> .setaccuratecurves - */
380
static int
381
zsetaccuratecurves(i_ctx_t *i_ctx_p)
382
0
{
383
0
    return zset_bool(i_ctx_p, gs_setaccuratecurves);
384
0
}
385
386
/* - .currentaccuratecurves <bool> */
387
static int
388
zcurrentaccuratecurves(i_ctx_t *i_ctx_p)
389
0
{
390
0
    return zcurrent_bool(i_ctx_p, gs_currentaccuratecurves);
391
0
}
392
393
/* <join_int|-1> .setcurvejoin - */
394
static int
395
zsetcurvejoin(i_ctx_t *i_ctx_p)
396
0
{
397
0
    os_ptr op = osp;
398
0
    int code;
399
400
0
    check_type(*op, t_integer);
401
0
    if (op->value.intval < -1 || op->value.intval > max_int)
402
0
        return_error(gs_error_rangecheck);
403
0
    code = gs_setcurvejoin(igs, (int)op->value.intval);
404
0
    if (code < 0)
405
0
        return code;
406
0
    pop(1);
407
0
    return 0;
408
0
}
409
410
/* - .currentcurvejoin <join_int|-1> */
411
static int
412
zcurrentcurvejoin(i_ctx_t *i_ctx_p)
413
0
{
414
0
    os_ptr op = osp;
415
416
0
    push(1);
417
0
    make_int(op, gs_currentcurvejoin(igs));
418
0
    return 0;
419
0
}
420
421
/* <adjust.x> <adjust.y> .setfilladjust2 - */
422
static int
423
zsetfilladjust2(i_ctx_t *i_ctx_p)
424
683
{
425
683
    os_ptr op = osp;
426
683
    double adjust[2];
427
683
    int code = num_params(op, 2, adjust);
428
429
683
    if (code < 0)
430
0
        return code;
431
683
    code = gs_setfilladjust(igs, adjust[0], adjust[1]);
432
683
    if (code < 0)
433
0
        return code;
434
683
    pop(2);
435
683
    return 0;
436
683
}
437
438
/* - .currentfilladjust2 <adjust.x> <adjust.y> */
439
static int
440
zcurrentfilladjust2(i_ctx_t *i_ctx_p)
441
0
{
442
0
    os_ptr op = osp;
443
0
    gs_point adjust;
444
445
0
    push(2);
446
0
    gs_currentfilladjust(igs, &adjust);
447
0
    make_real(op - 1, adjust.x);
448
0
    make_real(op, adjust.y);
449
0
    return 0;
450
0
}
451
452
/* <bool> .setdashadapt - */
453
static int
454
zsetdashadapt(i_ctx_t *i_ctx_p)
455
0
{
456
0
    return zset_bool(i_ctx_p, gs_setdashadapt);
457
0
}
458
459
/* - .currentdashadapt <bool> */
460
static int
461
zcurrentdashadapt(i_ctx_t *i_ctx_p)
462
0
{
463
0
    return zcurrent_bool(i_ctx_p, gs_currentdashadapt);
464
0
}
465
466
/* <num> <bool> .setdotlength - */
467
static int
468
zsetdotlength(i_ctx_t *i_ctx_p)
469
0
{
470
0
    os_ptr op = osp;
471
0
    double length;
472
0
    int code = real_param(op - 1, &length);
473
474
0
    if (code < 0)
475
0
        return code;
476
0
    check_type(*op, t_boolean);
477
0
    code = gs_setdotlength(igs, length, op->value.boolval);
478
0
    if (code < 0)
479
0
        return code;
480
0
    pop(2);
481
0
    return 0;
482
0
}
483
484
/* - .currentdotlength <num> <bool> */
485
static int
486
zcurrentdotlength(i_ctx_t *i_ctx_p)
487
0
{
488
0
    os_ptr op = osp;
489
490
0
    push(2);
491
0
    make_real(op - 1, gs_currentdotlength(igs));
492
0
    make_bool(op, gs_currentdotlength_absolute(igs));
493
0
    return 0;
494
0
}
495
496
/* - .setdotorientation - */
497
static int
498
zsetdotorientation(i_ctx_t *i_ctx_p)
499
0
{
500
0
    return gs_setdotorientation(igs);
501
0
}
502
503
/* - .dotorientation - */
504
static int
505
zdotorientation(i_ctx_t *i_ctx_p)
506
0
{
507
0
    return gs_dotorientation(igs);
508
0
}
509
510
/* <bool> .setlimitclamp - */
511
static int
512
zsetlimitclamp(i_ctx_t *i_ctx_p)
513
0
{
514
0
    return zset_bool(i_ctx_p, gs_setlimitclamp);
515
0
}
516
517
/* - .currentlimitclamp <bool> */
518
static int
519
zcurrentlimitclamp(i_ctx_t *i_ctx_p)
520
0
{
521
0
    return zcurrent_bool(i_ctx_p, gs_currentlimitclamp);
522
0
}
523
524
/* <int> .settextrenderingmode - */
525
static int
526
zsettextrenderingmode(i_ctx_t *i_ctx_p)
527
0
{
528
0
    return zset_uint(i_ctx_p, gs_settextrenderingmode);
529
0
}
530
531
/* - .currenttextrenderingmode <int> */
532
static int
533
zcurrenttextrenderingmode(i_ctx_t *i_ctx_p)
534
0
{
535
0
    return zcurrent_uint(i_ctx_p, gs_currenttextrenderingmode);
536
0
}
537
static int
538
zsettextspacing(i_ctx_t *i_ctx_p)
539
0
{
540
0
    return zset_real(i_ctx_p, gs_settextspacing);
541
0
}
542
static int
543
zcurrenttextspacing(i_ctx_t *i_ctx_p)
544
0
{
545
0
    return zcurrent_real(i_ctx_p, gs_currenttextspacing);
546
0
}
547
static int
548
zsettextleading(i_ctx_t *i_ctx_p)
549
0
{
550
0
    return zset_real(i_ctx_p, gs_settextleading);
551
0
}
552
static int
553
zcurrenttextleading(i_ctx_t *i_ctx_p)
554
0
{
555
0
    return zcurrent_real(i_ctx_p, gs_currenttextleading);
556
0
}
557
static int
558
zsettextrise(i_ctx_t *i_ctx_p)
559
0
{
560
0
    return zset_real(i_ctx_p, gs_settextrise);
561
0
}
562
static int
563
zcurrenttextrise(i_ctx_t *i_ctx_p)
564
0
{
565
0
    return zcurrent_real(i_ctx_p, gs_currenttextrise);
566
0
}
567
static int
568
zsetwordspacing(i_ctx_t *i_ctx_p)
569
0
{
570
0
    return zset_real(i_ctx_p, gs_setwordspacing);
571
0
}
572
static int
573
zcurrentwordspacing(i_ctx_t *i_ctx_p)
574
0
{
575
0
    return zcurrent_real(i_ctx_p, gs_currentwordspacing);
576
0
}
577
578
static int
579
zsettexthscaling(i_ctx_t *i_ctx_p)
580
0
{
581
0
    return zset_real(i_ctx_p, gs_settexthscaling);
582
0
}
583
static int
584
zcurrenttexthscaling(i_ctx_t *i_ctx_p)
585
0
{
586
0
    return zcurrent_real(i_ctx_p, gs_currenttexthscaling);
587
0
}
588
589
static int
590
zsetPDFfontsize(i_ctx_t *i_ctx_p)
591
0
{
592
0
    return zset_real(i_ctx_p, gs_setPDFfontsize);
593
0
}
594
static int
595
zcurrentPDFfontsize(i_ctx_t *i_ctx_p)
596
0
{
597
0
    return zcurrent_real(i_ctx_p, gs_currentPDFfontsize);
598
0
}
599
600
601
/* <bool> .sethpglpathmode - */
602
static int
603
zsethpglpathmode(i_ctx_t *i_ctx_p)
604
0
{
605
0
    return zset_bool(i_ctx_p, gs_sethpglpathmode);
606
0
}
607
608
/* - .currenthpglpathmode <int> */
609
static int
610
zcurrenthpglpathmode(i_ctx_t *i_ctx_p)
611
0
{
612
0
    return zcurrent_bool(i_ctx_p, gs_currenthpglpathmode);
613
0
}
614
615
/* ------ Initialization procedure ------ */
616
617
/* We need to split the table because of the 16-element limit. */
618
const op_def zgstate1_op_defs[] = {
619
    {"0.currentaccuratecurves", zcurrentaccuratecurves},
620
    {"0.currentcurvejoin", zcurrentcurvejoin},
621
    {"0currentdash", zcurrentdash},
622
    {"0.currentdashadapt", zcurrentdashadapt},
623
    {"0.currentdotlength", zcurrentdotlength},
624
    {"0.currentfilladjust2", zcurrentfilladjust2},
625
    {"0currentflat", zcurrentflat},
626
    {"0.currentlimitclamp", zcurrentlimitclamp},
627
    {"0currentlinecap", zcurrentlinecap},
628
    {"0currentlinejoin", zcurrentlinejoin},
629
    {"0currentlinewidth", zcurrentlinewidth},
630
    {"0currentmiterlimit", zcurrentmiterlimit},
631
    {"0.dotorientation", zdotorientation},
632
    {"0grestore", zgrestore},
633
    {"0grestoreall", zgrestoreall},
634
    op_def_end(0)
635
};
636
const op_def zgstate2_op_defs[] = {
637
    {"0gsave", zgsave},
638
    {"0initgraphics", zinitgraphics},
639
    {"1.setaccuratecurves", zsetaccuratecurves},
640
    {"1.setcurvejoin", zsetcurvejoin},
641
    {"2setdash", zsetdash},
642
    {"1.setdashadapt", zsetdashadapt},
643
    {"2.setdotlength", zsetdotlength},
644
    {"0.setdotorientation", zsetdotorientation},
645
    {"2.setfilladjust2", zsetfilladjust2},
646
    {"1.setlimitclamp", zsetlimitclamp},
647
    {"1setflat", zsetflat},
648
    {"1.setlinecap", zsetlinecap},
649
    {"1.setlinejoin", zsetlinejoin},
650
    {"1setlinewidth", zsetlinewidth},
651
    {"1setmiterlimit", zsetmiterlimit},
652
    op_def_end(0)
653
};
654
const op_def zgstate3_op_defs[] = {
655
    {"1.settextrenderingmode", zsettextrenderingmode},
656
    {"0.currenttextrenderingmode", zcurrenttextrenderingmode},
657
    {"1.settextspacing", zsettextspacing},
658
    {"0.currenttextspacing", zcurrenttextspacing},
659
    {"1.settextleading", zsettextleading},
660
    {"0.currenttextleading", zcurrenttextleading},
661
    {"1.settextrise", zsettextrise},
662
    {"0.currenttextrise", zcurrenttextrise},
663
    {"1.setwordspacing", zsetwordspacing},
664
    {"0.currentwordspacing", zcurrentwordspacing},
665
    {"1.settexthscaling", zsettexthscaling},
666
    {"0.currenttexthscaling", zcurrenttexthscaling},
667
    {"0.sethpglpathmode", zsethpglpathmode},
668
    {"0.currenthpglpathmode", zcurrenthpglpathmode},
669
    op_def_end(0)
670
};
671
const op_def zgstate4_op_defs[] = {
672
    {"1.setPDFfontsize", zsetPDFfontsize},
673
    {"0.currentPDFfontsize", zcurrentPDFfontsize},
674
    op_def_end(0)
675
};
676
677
/* ------ Internal routines ------ */
678
679
/* Allocate the interpreter's part of a graphics state. */
680
static void *
681
gs_istate_alloc(gs_memory_t * mem)
682
34.5k
{
683
34.5k
    return gs_alloc_struct(mem, int_gstate, &st_int_gstate, "int_gsave");
684
34.5k
}
685
686
/* Copy the interpreter's part of a graphics state. */
687
static int
688
gs_istate_copy(void *to, const void *from)
689
68.5k
{
690
68.5k
    *(int_gstate *) to = *(const int_gstate *)from;
691
68.5k
    return 0;
692
68.5k
}
693
694
/* Free the interpreter's part of a graphics state. */
695
static void
696
gs_istate_free(void *old, gs_memory_t * mem, gs_gstate *pgs)
697
35.2k
{
698
35.2k
    gs_free_object(mem, old, "int_grestore");
699
35.2k
}