1 /* Copyright (C) 1989, 2000 artofcode LLC.  All rights reserved.
2 
3   This program is free software; you can redistribute it and/or modify it
4   under the terms of the GNU General Public License as published by the
5   Free Software Foundation; either version 2 of the License, or (at your
6   option) any later version.
7 
8   This program is distributed in the hope that it will be useful, but
9   WITHOUT ANY WARRANTY; without even the implied warranty of
10   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11   General Public License for more details.
12 
13   You should have received a copy of the GNU General Public License along
14   with this program; if not, write to the Free Software Foundation, Inc.,
15   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
16 
17 */
18 
19 /*$Id: gsstate.c,v 1.11.2.1.2.1 2003/01/17 00:49:03 giles Exp $ */
20 /* Miscellaneous graphics state operators for Ghostscript library */
21 #include "gx.h"
22 #include "memory_.h"
23 #include "gserrors.h"
24 #include "gsstruct.h"
25 #include "gsutil.h"		/* for gs_next_ids */
26 #include "gzstate.h"
27 #include "gxcspace.h"		/* here for gscolor2.h */
28 #include "gsalpha.h"
29 #include "gscolor2.h"
30 #include "gscoord.h"		/* for gs_initmatrix */
31 #include "gscie.h"
32 #include "gscssub.h"
33 #include "gxclipsr.h"
34 #include "gxcmap.h"
35 #include "gxdevice.h"
36 #include "gxpcache.h"
37 #include "gzht.h"
38 #include "gzline.h"
39 #include "gspath.h"
40 #include "gzpath.h"
41 #include "gzcpath.h"
42 
43 /* Forward references */
44 private gs_state *gstate_alloc(P3(gs_memory_t *, client_name_t,
45 				  const gs_state *));
46 private gs_state *gstate_clone(P4(gs_state *, gs_memory_t *, client_name_t,
47 				  gs_state_copy_reason_t));
48 private void gstate_free_contents(P1(gs_state *));
49 private int gstate_copy(P4(gs_state *, const gs_state *,
50 			   gs_state_copy_reason_t, client_name_t));
51 
52 /*
53  * Graphics state storage management is complicated.  There are many
54  * different classes of storage associated with a graphics state:
55  *
56  * (1) The gstate object itself.  This includes some objects physically
57  *      embedded within the gstate object, but because of garbage collection
58  *      requirements, there are no embedded objects that can be
59  *      referenced by non-transient pointers.  We assume that the gstate
60  *      stack "owns" its gstates and that we can free the top gstate when
61  *      doing a restore.
62  *
63  * (2) Objects that are referenced directly by the gstate and whose lifetime
64  *      is independent of the gstate.  These are garbage collected, not
65  *      reference counted, so we don't need to do anything special with them
66  *      when manipulating gstates.  Currently this includes:
67  *              font, device
68  *
69  * (3) Objects that are referenced directly by the gstate, may be shared
70  *      among gstates, and should disappear when no gstates reference them.
71  *      These fall into two groups:
72  *
73  *   (3a) Objects that are logically connected to individual gstates.
74  *      We use reference counting to manage these.  Currently these are:
75  *              halftone, dev_ht, cie_render, black_generation,
76  *              undercolor_removal, set_transfer.*, cie_joint_caches,
77  *		clip_stack, {opacity,shape}.mask
78  *      effective_transfer.* may point to some of the same objects as
79  *      set_transfer.*, but don't contribute to the reference count.
80  *      Similarly, dev_color may point to the dev_ht object.  For
81  *      simplicity, we initialize all of these pointers to 0 and then
82  *      allocate the object itself when needed.
83  *
84  *   (3b) Objects whose lifetimes are associated with something else.
85  *      Currently these are:
86  *              ht_cache, which is associated with the entire gstate
87  *                stack, is allocated with the very first graphics state,
88  *                and currently is never freed;
89  *              pattern_cache, which is associated with the entire
90  *                stack, is allocated when first needed, and currently
91  *                is never freed;
92  *              view_clip, which is associated with the current
93  *                save level (effectively, with the gstate sub-stack
94  *                back to the save) and is managed specially;
95  *		transparency_stack, which is associated with the entire
96  *		  stack but only stored in the topmost graphics state.
97  *
98  * (4) Objects that are referenced directly by exactly one gstate and that
99  *      are not referenced (except transiently) from any other object.
100  *      These fall into two groups:
101  *
102  *   (4b) Objects allocated individually, for the given reason:
103  *              line_params.dash.pattern (variable-length),
104  *              color_space, path, clip_path, effective_clip.path,
105  *              ccolor, dev_color
106  *                  (may be referenced from image enumerators or elsewhere)
107  *
108  *   (4b) The "client data" for a gstate.  For the interpreter, this is
109  *      the refs associated with the gstate, such as the screen procedures.
110  *      Client-supplied procedures manage client data.
111  *
112  * (5) Objects referenced indirectly from gstate objects of category (4),
113  *      including objects that may also be referenced directly by the gstate.
114  *      The individual routines that manipulate these are responsible
115  *      for doing the right kind of reference counting or whatever.
116  *      Currently:
117  *              path, clip_path, and (if different from both clip_path
118  *                and view_clip) effective_clip.path require
119  *                gx_path_assign/free, which uses a reference count;
120  *              color_space and ccolor require cs_adjust_color/cspace_count
121  *                or cs_adjust_counts, which use a reference count;
122  *              dev_color has no references to storage that it owns.
123  *      We count on garbage collection or restore to deallocate
124  *        sub-objects of halftone.
125  *
126  * Note that when after a gsave, the existing gstate references the related
127  * objects that we allocate at the same time, and the newly allocated gstate
128  * references the old related objects.  Similarly, during a grestore, we
129  * free the related objects referenced by the current gstate, but after the
130  * grestore, we free the saved gstate, not the current one.  However, when
131  * we allocate gstates off-stack, the newly allocated gstate does reference
132  * the newly allocated component objects.  Note also that setgstate /
133  * currentgstate may produce gstates in which different allocators own
134  * different sub-objects; this is OK, because restore guarantees that there
135  * won't be any dangling pointers (as long as we don't allow pointers from
136  * global gstates to local objects).
137  */
138 
139 /*
140  * Define these elements of the graphics state that are allocated
141  * individually for each state, except for line_params.dash.pattern.
142  * Note that effective_clip_shared is not on the list.
143  */
144 typedef struct gs_state_parts_s {
145     gx_path *path;
146     gx_clip_path *clip_path;
147     gx_clip_path *effective_clip_path;
148     gs_color_space *color_space;
149     gs_client_color *ccolor;
150     gx_device_color *dev_color;
151 } gs_state_parts;
152 
153 #define GSTATE_ASSIGN_PARTS(pto, pfrom)\
154   ((pto)->path = (pfrom)->path, (pto)->clip_path = (pfrom)->clip_path,\
155    (pto)->effective_clip_path = (pfrom)->effective_clip_path,\
156    (pto)->color_space = (pfrom)->color_space,\
157    (pto)->ccolor = (pfrom)->ccolor, (pto)->dev_color = (pfrom)->dev_color)
158 
159 /* GC descriptors */
160 extern_st(st_imager_state);
161 public_st_gs_state();
162 
163 /* GC procedures for gs_state */
164 private ENUM_PTRS_WITH(gs_state_enum_ptrs, gs_state *gsvptr)
165 ENUM_PREFIX(st_imager_state, gs_state_num_ptrs + 2);
166 #define e1(i,elt) ENUM_PTR(i,gs_state,elt);
167 gs_state_do_ptrs(e1)
168 case gs_state_num_ptrs:	/* handle device specially */
169 ENUM_RETURN(gx_device_enum_ptr(gsvptr->device));
170 case gs_state_num_ptrs + 1:	/* handle device filter stack specially */
171 ENUM_RETURN(gsvptr->dfilter_stack);
172 #undef e1
173 ENUM_PTRS_END
RELOC_PTRS_WITH(gs_state_reloc_ptrs,gs_state * gsvptr)174 private RELOC_PTRS_WITH(gs_state_reloc_ptrs, gs_state *gsvptr)
175 {
176     RELOC_PREFIX(st_imager_state);
177     {
178 #define r1(i,elt) RELOC_PTR(gs_state,elt);
179 	gs_state_do_ptrs(r1)
180 #undef r1
181 	gsvptr->device = gx_device_reloc_ptr(gsvptr->device, gcst);
182 	RELOC_PTR(gs_state, dfilter_stack);
183     }
184 }
185 RELOC_PTRS_END
186 
187 /* Copy client data, using the copy_for procedure if available, */
188 /* the copy procedure otherwise. */
189 private int
gstate_copy_client_data(gs_state * pgs,void * dto,void * dfrom,gs_state_copy_reason_t reason)190 gstate_copy_client_data(gs_state * pgs, void *dto, void *dfrom,
191 			gs_state_copy_reason_t reason)
192 {
193     return (pgs->client_procs.copy_for != 0 ?
194 	    (*pgs->client_procs.copy_for) (dto, dfrom, reason) :
195 	    (*pgs->client_procs.copy) (dto, dfrom));
196 }
197 
198 /* ------ Operations on the entire graphics state ------ */
199 
200 /* Define the initial value of the graphics state. */
201 private const gs_imager_state gstate_initial = {
202     gs_imager_state_initial(1.0)
203 };
204 
205 /*
206  * Allocate a path for the graphics state.  We use stable memory because
207  * some PostScript files have Type 3 fonts whose BuildChar procedure
208  * uses the sequence save ... setcachedevice ... restore, and the path
209  * built between the setcachedevice and the restore must not be freed.
210  * If it weren't for this, we don't think stable memory would be needed.
211  */
212 private gs_memory_t *
gstate_path_memory(gs_memory_t * mem)213 gstate_path_memory(gs_memory_t *mem)
214 {
215     return gs_memory_stable(mem);
216 }
217 
218 /* Allocate and initialize a graphics state. */
219 gs_state *
gs_state_alloc(gs_memory_t * mem)220 gs_state_alloc(gs_memory_t * mem)
221 {
222     gs_state *pgs = gstate_alloc(mem, "gs_state_alloc", NULL);
223     int code;
224 
225     if (pgs == 0)
226 	return 0;
227     pgs->saved = 0;
228     *(gs_imager_state *)pgs = gstate_initial;
229 
230     /*
231      * Just enough of the state is initialized at this point
232      * that it's OK to call gs_state_free if an allocation fails.
233      */
234 
235     code = gs_imager_state_initialize((gs_imager_state *) pgs, mem);
236     if (code < 0)
237 	goto fail;
238 
239     /* Finish initializing the color rendering state. */
240 
241     rc_alloc_struct_1(pgs->halftone, gs_halftone, &st_halftone, mem,
242 		      goto fail, "gs_state_alloc(halftone)");
243     pgs->halftone->type = ht_type_none;
244     pgs->ht_cache = gx_ht_alloc_cache(mem,
245 				      gx_ht_cache_default_tiles(),
246 				      gx_ht_cache_default_bits());
247 
248     /* Initialize other things not covered by initgraphics */
249 
250     pgs->path = gx_path_alloc(gstate_path_memory(mem), "gs_state_alloc(path)");
251     pgs->clip_path = gx_cpath_alloc(mem, "gs_state_alloc(clip_path)");
252     pgs->clip_stack = 0;
253     pgs->view_clip = gx_cpath_alloc(mem, "gs_state_alloc(view_clip)");
254     pgs->view_clip->rule = 0;	/* no clipping */
255     pgs->effective_clip_id = pgs->clip_path->id;
256     pgs->effective_view_clip_id = gs_no_id;
257     pgs->effective_clip_path = pgs->clip_path;
258     pgs->effective_clip_shared = true;
259     /* Initialize things so that gx_remap_color won't crash. */
260     gs_cspace_init_DeviceGray(pgs->color_space);
261     {
262 	int i;
263 
264 	for (i = 0; i < countof(pgs->device_color_spaces.indexed); ++i)
265 	    pgs->device_color_spaces.indexed[i] = 0;
266     }
267     gx_set_device_color_1(pgs);
268     pgs->device = 0;		/* setting device adjusts refcts */
269     gs_nulldevice(pgs);
270     gs_setalpha(pgs, 1.0);
271     gs_settransfer(pgs, gs_identity_transfer);
272     gs_setflat(pgs, 1.0);
273     gs_setfilladjust(pgs, 0.25, 0.25);
274     gs_setlimitclamp(pgs, false);
275     gs_setstrokeadjust(pgs, true);
276     pgs->font = 0;		/* Not right, but acceptable until the */
277     /* PostScript code does the first setfont. */
278     pgs->root_font = 0;		/* ditto */
279     pgs->in_cachedevice = 0;
280     pgs->in_charpath = (gs_char_path_mode) 0;
281     pgs->show_gstate = 0;
282     pgs->level = 0;
283     pgs->dfilter_stack = 0;
284     pgs->transparency_group_stack = 0;
285     if (gs_initgraphics(pgs) >= 0)
286 	return pgs;
287     /* Something went very wrong. */
288 fail:
289     gs_state_free(pgs);
290     return 0;
291 }
292 
293 /* Set the client data in a graphics state. */
294 /* This should only be done to a newly created state. */
295 void
gs_state_set_client(gs_state * pgs,void * pdata,const gs_state_client_procs * pprocs)296 gs_state_set_client(gs_state * pgs, void *pdata,
297 		    const gs_state_client_procs * pprocs)
298 {
299     pgs->client_data = pdata;
300     pgs->client_procs = *pprocs;
301 }
302 
303 /* Get the client data from a graphics state. */
304 #undef gs_state_client_data	/* gzstate.h makes this a macro */
305 void *
gs_state_client_data(const gs_state * pgs)306 gs_state_client_data(const gs_state * pgs)
307 {
308     return pgs->client_data;
309 }
310 
311 /* Free a graphics state. */
312 int
gs_state_free(gs_state * pgs)313 gs_state_free(gs_state * pgs)
314 {
315     gstate_free_contents(pgs);
316     gs_free_object(pgs->memory, pgs, "gs_state_free");
317     return 0;
318 }
319 
320 /* Save the graphics state. */
321 int
gs_gsave(gs_state * pgs)322 gs_gsave(gs_state * pgs)
323 {
324     gs_state *pnew = gstate_clone(pgs, pgs->memory, "gs_gsave",
325 				  copy_for_gsave);
326 
327     if (pnew == 0)
328 	return_error(gs_error_VMerror);
329     /*
330      * It isn't clear from the Adobe documentation whether gsave retains
331      * the current clip stack or clears it.  The following statement
332      * bets on the latter.  If it's the former, this should become
333      *	rc_increment(pnew->clip_stack);
334      */
335     pnew->clip_stack = 0;
336     pgs->saved = pnew;
337     if (pgs->show_gstate == pgs)
338 	pgs->show_gstate = pnew->show_gstate = pnew;
339     pgs->level++;
340     if_debug2('g', "[g]gsave -> 0x%lx, level = %d\n",
341 	      (ulong) pnew, pgs->level);
342     return 0;
343 }
344 
345 /*
346  * Save the graphics state for a 'save'.
347  * We cut the stack below the new gstate, and return the old one.
348  * In addition to an ordinary gsave, we create a new view clip path.
349  */
350 int
gs_gsave_for_save(gs_state * pgs,gs_state ** psaved)351 gs_gsave_for_save(gs_state * pgs, gs_state ** psaved)
352 {
353     int code;
354     gx_clip_path *old_cpath = pgs->view_clip;
355     gx_clip_path *new_cpath;
356     gx_device_color_spaces_t save_spaces;
357     int i;
358 
359     if (old_cpath) {
360 	new_cpath =
361 	    gx_cpath_alloc_shared(old_cpath, pgs->memory,
362 				  "gs_gsave_for_save(view_clip)");
363 	if (new_cpath == 0)
364 	    return_error(gs_error_VMerror);
365     } else {
366 	new_cpath = 0;
367     }
368     code = gs_gsave(pgs);
369     if (code < 0)
370 	goto fail;
371     for (i = 0; i < countof(save_spaces.indexed); ++i) {
372 	gs_color_space *pcs = pgs->device_color_spaces.indexed[i];
373 
374 	if (pcs) {
375 	    pgs->device_color_spaces.indexed[i] = 0;
376 	    code = gs_setsubstitutecolorspace(pgs, (gs_color_space_index)i,
377 					      pcs);
378 	    if (code < 0) {
379 		/*
380 		 * Patch the second saved pointer so we won't try to
381 		 * gsave after the grestore.
382 		 */
383 		if (pgs->saved->saved == 0)
384 		    pgs->saved->saved = pgs;
385 		gs_grestore(pgs);
386 		if (pgs->saved == pgs)
387 		    pgs->saved = 0;
388 		goto fail;
389 	    }
390 	}
391     }
392     if (pgs->effective_clip_path == pgs->view_clip)
393 	pgs->effective_clip_path = new_cpath;
394     pgs->view_clip = new_cpath;
395     /* Cut the stack so we can't grestore past here. */
396     *psaved = pgs->saved;
397     pgs->saved = 0;
398     return code;
399 fail:
400     if (new_cpath)
401 	gx_cpath_free(new_cpath, "gs_gsave_for_save(view_clip)");
402     return code;
403 }
404 
405 /* Restore the graphics state. Can fully empty graphics stack */
406 int	/* return 0 if ok, 1 if stack was empty */
gs_grestore_only(gs_state * pgs)407 gs_grestore_only(gs_state * pgs)
408 {
409     gs_state *saved = pgs->saved;
410     void *pdata = pgs->client_data;
411     void *sdata;
412     gs_transparency_state_t *tstack = pgs->transparency_stack;
413 
414     if_debug2('g', "[g]grestore 0x%lx, level was %d\n",
415 	      (ulong) saved, pgs->level);
416     if (!saved)
417 	return 1;
418     sdata = saved->client_data;
419     if (saved->pattern_cache == 0)
420 	saved->pattern_cache = pgs->pattern_cache;
421     /* Swap back the client data pointers. */
422     pgs->client_data = sdata;
423     saved->client_data = pdata;
424     if (pdata != 0 && sdata != 0)
425 	gstate_copy_client_data(pgs, pdata, sdata, copy_for_grestore);
426     gstate_free_contents(pgs);
427     *pgs = *saved;
428     pgs->transparency_stack = tstack;
429     if (pgs->show_gstate == saved)
430 	pgs->show_gstate = pgs;
431     gs_free_object(pgs->memory, saved, "gs_grestore");
432     return 0;
433 }
434 
435 /* Restore the graphics state per PostScript semantics */
436 int
gs_grestore(gs_state * pgs)437 gs_grestore(gs_state * pgs)
438 {
439     int code;
440     if (!pgs->saved)
441 	return gs_gsave(pgs);	/* shouldn't ever happen */
442     code = gs_grestore_only(pgs);
443     if (code < 0)
444 	return code;
445 
446     /* Wraparound: make sure there are always >= 1 saves on stack */
447     if (pgs->saved)
448 	return 0;
449     return gs_gsave(pgs);
450 }
451 
452 /* Restore the graphics state for a 'restore', splicing the old stack */
453 /* back on.  Note that we actually do a grestoreall + 2 grestores. */
454 int
gs_grestoreall_for_restore(gs_state * pgs,gs_state * saved)455 gs_grestoreall_for_restore(gs_state * pgs, gs_state * saved)
456 {
457     int code;
458     gx_device_color_spaces_t freed_spaces;
459 
460     while (pgs->saved->saved) {
461 	code = gs_grestore(pgs);
462 	if (code < 0)
463 	    return code;
464     }
465     /* Make sure we don't leave dangling pointers in the caches. */
466     gx_ht_clear_cache(pgs->ht_cache);
467     if (pgs->pattern_cache)
468 	(*pgs->pattern_cache->free_all) (pgs->pattern_cache);
469     pgs->saved->saved = saved;
470     freed_spaces = pgs->device_color_spaces;
471     code = gs_grestore(pgs);
472     if (code < 0)
473 	return code;
474     gx_device_color_spaces_free(&freed_spaces, pgs->memory,
475 				"gs_grestoreall_for_restore");
476     if (pgs->view_clip) {
477 	gx_cpath_free(pgs->view_clip, "gs_grestoreall_for_restore");
478 	pgs->view_clip = 0;
479     }
480     return gs_grestore(pgs);
481 }
482 
483 
484 /* Restore to the bottommost graphics state (at this save level). */
485 int
gs_grestoreall(gs_state * pgs)486 gs_grestoreall(gs_state * pgs)
487 {
488     if (!pgs->saved)		/* shouldn't happen */
489 	return gs_gsave(pgs);
490     while (pgs->saved->saved) {
491 	int code = gs_grestore(pgs);
492 
493 	if (code < 0)
494 	    return code;
495     }
496     return gs_grestore(pgs);
497 }
498 
499 /* Allocate and return a new graphics state. */
500 gs_state *
gs_gstate(gs_state * pgs)501 gs_gstate(gs_state * pgs)
502 {
503     gs_state *copied = gs_state_copy(pgs, pgs->memory);
504     int i;
505 
506     if (copied == 0)
507 	return 0;
508     /* Don't capture the substituted color spaces. */
509     for (i = 0; i < countof(copied->device_color_spaces.indexed); ++i)
510 	copied->device_color_spaces.indexed[i] = 0;
511     return copied;
512 }
513 gs_state *
gs_state_copy(gs_state * pgs,gs_memory_t * mem)514 gs_state_copy(gs_state * pgs, gs_memory_t * mem)
515 {
516     gs_state *pnew;
517     /* Prevent 'capturing' the view clip path. */
518     gx_clip_path *view_clip = pgs->view_clip;
519 
520     pgs->view_clip = 0;
521     pnew = gstate_clone(pgs, mem, "gs_gstate", copy_for_gstate);
522     rc_increment(pnew->clip_stack);
523     pgs->view_clip = view_clip;
524     if (pnew == 0)
525 	return 0;
526     pnew->saved = 0;
527     /*
528      * Prevent dangling references from the show_gstate pointer.  If
529      * this context is its own show_gstate, set the pointer in the clone
530      * to point to the clone; otherwise, set the pointer in the clone to
531      * 0, and let gs_setgstate fix it up.
532      */
533     pnew->show_gstate =
534 	(pgs->show_gstate == pgs ? pnew : 0);
535     return pnew;
536 }
537 
538 /* Copy one previously allocated graphics state to another. */
539 int
gs_copygstate(gs_state * pto,const gs_state * pfrom)540 gs_copygstate(gs_state * pto, const gs_state * pfrom)
541 {
542     return gstate_copy(pto, pfrom, copy_for_copygstate, "gs_copygstate");
543 }
544 
545 /* Copy the current graphics state to a previously allocated one. */
546 int
gs_currentgstate(gs_state * pto,const gs_state * pgs)547 gs_currentgstate(gs_state * pto, const gs_state * pgs)
548 {
549     int code =
550 	gstate_copy(pto, pgs, copy_for_currentgstate, "gs_currentgstate");
551 
552     if (code >= 0)
553 	pto->view_clip = 0;
554     return code;
555 }
556 
557 /* Restore the current graphics state from a previously allocated one. */
558 int
gs_setgstate(gs_state * pgs,const gs_state * pfrom)559 gs_setgstate(gs_state * pgs, const gs_state * pfrom)
560 {
561     /*
562      * The implementation is the same as currentgstate,
563      * except we must preserve the saved pointer, the level,
564      * the view clip, and possibly the show_gstate.
565      */
566     gs_state *saved_show = pgs->show_gstate;
567     int level = pgs->level;
568     gx_clip_path *view_clip = pgs->view_clip;
569     gs_transparency_state_t *tstack = pgs->transparency_stack;
570     int code;
571 
572     pgs->view_clip = 0;		/* prevent refcount decrementing */
573     code = gstate_copy(pgs, pfrom, copy_for_setgstate, "gs_setgstate");
574     if (code < 0)
575 	return code;
576     pgs->level = level;
577     pgs->view_clip = view_clip;
578     pgs->show_gstate =
579 	(pgs->show_gstate == pfrom ? pgs : saved_show);
580     pgs->transparency_stack = tstack;
581     return 0;
582 }
583 
584 /* Get the allocator pointer of a graphics state. */
585 /* This is provided only for the interpreter */
586 /* and for color space implementation. */
587 gs_memory_t *
gs_state_memory(const gs_state * pgs)588 gs_state_memory(const gs_state * pgs)
589 {
590     return pgs->memory;
591 }
592 
593 /* Get the saved pointer of the graphics state. */
594 /* This is provided only for Level 2 grestore. */
595 gs_state *
gs_state_saved(const gs_state * pgs)596 gs_state_saved(const gs_state * pgs)
597 {
598     return pgs->saved;
599 }
600 
601 /* Swap the saved pointer of the graphics state. */
602 /* This is provided only for save/restore. */
603 gs_state *
gs_state_swap_saved(gs_state * pgs,gs_state * new_saved)604 gs_state_swap_saved(gs_state * pgs, gs_state * new_saved)
605 {
606     gs_state *saved = pgs->saved;
607 
608     pgs->saved = new_saved;
609     return saved;
610 }
611 
612 /* Swap the memory pointer of the graphics state. */
613 /* This is provided only for the interpreter. */
614 gs_memory_t *
gs_state_swap_memory(gs_state * pgs,gs_memory_t * mem)615 gs_state_swap_memory(gs_state * pgs, gs_memory_t * mem)
616 {
617     gs_memory_t *memory = pgs->memory;
618 
619     pgs->memory = mem;
620     return memory;
621 }
622 
623 /* ------ Operations on components ------ */
624 
625 /* Reset most of the graphics state */
626 int
gs_initgraphics(gs_state * pgs)627 gs_initgraphics(gs_state * pgs)
628 {
629     int code;
630 
631     gs_initmatrix(pgs);
632     if ((code = gs_newpath(pgs)) < 0 ||
633 	(code = gs_initclip(pgs)) < 0 ||
634 	(code = gs_setlinewidth(pgs, 1.0)) < 0 ||
635 	(code = gs_setlinecap(pgs, gstate_initial.line_params.cap)) < 0 ||
636 	(code = gs_setlinejoin(pgs, gstate_initial.line_params.join)) < 0 ||
637 	(code = gs_setcurvejoin(pgs, gstate_initial.line_params.curve_join)) < 0 ||
638 	(code = gs_setdash(pgs, (float *)0, 0, 0.0)) < 0 ||
639 	(gs_setdashadapt(pgs, false),
640 	 (code = gs_setdotlength(pgs, 0.0, false))) < 0 ||
641 	(code = gs_setdotorientation(pgs)) < 0 ||
642 	(code = gs_setgray(pgs, 0.0)) < 0 ||
643 	(code = gs_setmiterlimit(pgs, gstate_initial.line_params.miter_limit)) < 0
644 	)
645 	return code;
646     gs_init_rop(pgs);
647     return 0;
648 }
649 
650 /* setfilladjust */
651 int
gs_setfilladjust(gs_state * pgs,floatp adjust_x,floatp adjust_y)652 gs_setfilladjust(gs_state * pgs, floatp adjust_x, floatp adjust_y)
653 {
654 #define CLAMP_TO_HALF(v)\
655     ((v) <= 0 ? fixed_0 : (v) >= 0.5 ? fixed_half : float2fixed(v));
656 
657     pgs->fill_adjust.x = CLAMP_TO_HALF(adjust_x);
658     pgs->fill_adjust.y = CLAMP_TO_HALF(adjust_y);
659     return 0;
660 #undef CLAMP_TO_HALF
661 }
662 
663 /* currentfilladjust */
664 int
gs_currentfilladjust(const gs_state * pgs,gs_point * adjust)665 gs_currentfilladjust(const gs_state * pgs, gs_point * adjust)
666 {
667     adjust->x = fixed2float(pgs->fill_adjust.x);
668     adjust->y = fixed2float(pgs->fill_adjust.y);
669     return 0;
670 }
671 
672 /* setlimitclamp */
673 void
gs_setlimitclamp(gs_state * pgs,bool clamp)674 gs_setlimitclamp(gs_state * pgs, bool clamp)
675 {
676     pgs->clamp_coordinates = clamp;
677 }
678 
679 /* currentlimitclamp */
680 bool
gs_currentlimitclamp(const gs_state * pgs)681 gs_currentlimitclamp(const gs_state * pgs)
682 {
683     return pgs->clamp_coordinates;
684 }
685 
686 /* ------ Internal routines ------ */
687 
688 /* Free the privately allocated parts of a gstate. */
689 private void
gstate_free_parts(const gs_state * parts,gs_memory_t * mem,client_name_t cname)690 gstate_free_parts(const gs_state * parts, gs_memory_t * mem, client_name_t cname)
691 {
692     gs_free_object(mem, parts->dev_color, cname);
693     gs_free_object(mem, parts->ccolor, cname);
694     gs_free_object(mem, parts->color_space, cname);
695     if (!parts->effective_clip_shared)
696 	gx_cpath_free(parts->effective_clip_path, cname);
697     gx_cpath_free(parts->clip_path, cname);
698     gx_path_free(parts->path, cname);
699 }
700 
701 /* Allocate the privately allocated parts of a gstate. */
702 private int
gstate_alloc_parts(gs_state * parts,const gs_state * shared,gs_memory_t * mem,client_name_t cname)703 gstate_alloc_parts(gs_state * parts, const gs_state * shared,
704 		   gs_memory_t * mem, client_name_t cname)
705 {
706     gs_memory_t *path_mem = gstate_path_memory(mem);
707 
708     parts->path =
709 	(shared ?
710 	 gx_path_alloc_shared(shared->path, path_mem,
711 			      "gstate_alloc_parts(path)") :
712 	 gx_path_alloc(path_mem, "gstate_alloc_parts(path)"));
713     parts->clip_path =
714 	(shared ?
715 	 gx_cpath_alloc_shared(shared->clip_path, mem,
716 			       "gstate_alloc_parts(clip_path)") :
717 	 gx_cpath_alloc(mem, "gstate_alloc_parts(clip_path)"));
718     if (!shared || shared->effective_clip_shared) {
719 	parts->effective_clip_path = parts->clip_path;
720 	parts->effective_clip_shared = true;
721     } else {
722 	parts->effective_clip_path =
723 	    gx_cpath_alloc_shared(shared->effective_clip_path, mem,
724 				  "gstate_alloc_parts(effective_clip_path)");
725 	parts->effective_clip_shared = false;
726     }
727     parts->color_space =
728 	gs_alloc_struct(mem, gs_color_space, &st_color_space, cname);
729     parts->ccolor =
730 	gs_alloc_struct(mem, gs_client_color, &st_client_color, cname);
731     parts->dev_color =
732 	gs_alloc_struct(mem, gx_device_color, &st_device_color, cname);
733     if (parts->path == 0 || parts->clip_path == 0 ||
734 	parts->effective_clip_path == 0 ||
735 	parts->color_space == 0 || parts->ccolor == 0 ||
736 	parts->dev_color == 0
737 	) {
738 	gstate_free_parts(parts, mem, cname);
739 	return_error(gs_error_VMerror);
740     }
741     return 0;
742 }
743 
744 /*
745  * Allocate a gstate and its contents.
746  * If pfrom is not NULL, the path, clip_path, and (if distinct from both
747  * clip_path and view_clip) effective_clip_path share the segments of
748  * pfrom's corresponding path(s).
749  */
750 private gs_state *
gstate_alloc(gs_memory_t * mem,client_name_t cname,const gs_state * pfrom)751 gstate_alloc(gs_memory_t * mem, client_name_t cname, const gs_state * pfrom)
752 {
753     gs_state *pgs =
754 	gs_alloc_struct(mem, gs_state, &st_gs_state, cname);
755 
756     if (pgs == 0)
757 	return 0;
758     if (gstate_alloc_parts(pgs, pfrom, mem, cname) < 0) {
759 	gs_free_object(mem, pgs, cname);
760 	return 0;
761     }
762     pgs->memory = mem;
763     return pgs;
764 }
765 
766 /* Copy the dash pattern from one gstate to another. */
767 private int
gstate_copy_dash(gs_state * pto,const gs_state * pfrom)768 gstate_copy_dash(gs_state * pto, const gs_state * pfrom)
769 {
770     return gs_setdash(pto, pfrom->line_params.dash.pattern,
771 		      pfrom->line_params.dash.pattern_size,
772 		      pfrom->line_params.dash.offset);
773 }
774 
775 /* Clone an existing graphics state. */
776 /* Return 0 if the allocation fails. */
777 /* If reason is for_gsave, the clone refers to the old contents, */
778 /* and we switch the old state to refer to the new contents. */
779 private gs_state *
gstate_clone(gs_state * pfrom,gs_memory_t * mem,client_name_t cname,gs_state_copy_reason_t reason)780 gstate_clone(gs_state * pfrom, gs_memory_t * mem, client_name_t cname,
781 	     gs_state_copy_reason_t reason)
782 {
783     gs_state *pgs = gstate_alloc(mem, cname, pfrom);
784     gs_state_parts parts;
785 
786     if (pgs == 0)
787 	return 0;
788     GSTATE_ASSIGN_PARTS(&parts, pgs);
789     *pgs = *pfrom;
790     pgs->transparency_stack = 0;
791     /* Copy the dash pattern if necessary. */
792     if (pgs->line_params.dash.pattern) {
793 	int code;
794 
795 	pgs->line_params.dash.pattern = 0;	/* force allocation */
796 	code = gstate_copy_dash(pgs, pfrom);
797 	if (code < 0)
798 	    goto fail;
799     }
800     if (pgs->client_data != 0) {
801 	void *pdata = pgs->client_data = (*pgs->client_procs.alloc) (mem);
802 
803 	if (pdata == 0 ||
804 	 gstate_copy_client_data(pgs, pdata, pfrom->client_data, reason) < 0
805 	    )
806 	    goto fail;
807     }
808     gs_imager_state_copied((gs_imager_state *)pgs);
809     /* Don't do anything to clip_stack. */
810     rc_increment(pgs->device);
811     *parts.color_space = *pfrom->color_space;
812     *parts.ccolor = *pfrom->ccolor;
813     *parts.dev_color = *pfrom->dev_color;
814     if (reason == copy_for_gsave) {
815 	float *dfrom = pfrom->line_params.dash.pattern;
816 	float *dto = pgs->line_params.dash.pattern;
817 
818 	GSTATE_ASSIGN_PARTS(pfrom, &parts);
819 	pgs->line_params.dash.pattern = dfrom;
820 	pfrom->line_params.dash.pattern = dto;
821     } else {
822 	GSTATE_ASSIGN_PARTS(pgs, &parts);
823     }
824     cs_adjust_counts(pgs, 1);
825     return pgs;
826   fail:
827     gs_free_object(mem, pgs->line_params.dash.pattern, cname);
828     GSTATE_ASSIGN_PARTS(pgs, &parts);
829     gstate_free_parts(pgs, mem, cname);
830     gs_free_object(mem, pgs, cname);
831     return 0;
832 }
833 
834 /* Release the composite parts of a graphics state, */
835 /* but not the state itself. */
836 private void
gstate_free_contents(gs_state * pgs)837 gstate_free_contents(gs_state * pgs)
838 {
839     gs_memory_t *mem = pgs->memory;
840     const char *const cname = "gstate_free_contents";
841 
842     rc_decrement(pgs->device, cname);
843     rc_decrement(pgs->clip_stack, cname);
844     cs_adjust_counts(pgs, -1);
845     if (pgs->client_data != 0)
846 	(*pgs->client_procs.free) (pgs->client_data, mem);
847     gs_free_object(mem, pgs->line_params.dash.pattern, cname);
848     gstate_free_parts(pgs, mem, cname);
849     gs_imager_state_release((gs_imager_state *)pgs);
850 }
851 
852 /* Copy one gstate to another. */
853 private int
gstate_copy(gs_state * pto,const gs_state * pfrom,gs_state_copy_reason_t reason,client_name_t cname)854 gstate_copy(gs_state * pto, const gs_state * pfrom,
855 	    gs_state_copy_reason_t reason, client_name_t cname)
856 {
857     gs_state_parts parts;
858     gx_device_color_spaces_t saved_spaces;
859 
860     GSTATE_ASSIGN_PARTS(&parts, pto);
861     saved_spaces = pto->device_color_spaces;
862     /* Copy the dash pattern if necessary. */
863     if (pfrom->line_params.dash.pattern || pto->line_params.dash.pattern) {
864 	int code = gstate_copy_dash(pto, pfrom);
865 
866 	if (code < 0)
867 	    return code;
868     }
869     /*
870      * It's OK to decrement the counts before incrementing them,
871      * because anything that is going to survive has a count of
872      * at least 2 (pto and somewhere else) initially.
873      * Handle references from contents.
874      */
875     cs_adjust_counts(pto, -1);
876     gx_path_assign_preserve(pto->path, pfrom->path);
877     gx_cpath_assign_preserve(pto->clip_path, pfrom->clip_path);
878     /*
879      * effective_clip_shared will be copied, but we need to do the
880      * right thing with effective_clip_path.
881      */
882     if (pfrom->effective_clip_shared) {
883 	/*
884 	 * pfrom->effective_clip_path is either pfrom->view_clip or
885 	 * pfrom->clip_path.
886 	 */
887 	parts.effective_clip_path =
888 	    (pfrom->effective_clip_path == pfrom->view_clip ?
889 	     pto->view_clip : parts.clip_path);
890     } else
891 	gx_cpath_assign_preserve(pto->effective_clip_path,
892 				 pfrom->effective_clip_path);
893     *parts.color_space = *pfrom->color_space;
894     *parts.ccolor = *pfrom->ccolor;
895     *parts.dev_color = *pfrom->dev_color;
896     cs_adjust_counts(pto, 1);
897     /* Handle references from gstate object. */
898 #define RCCOPY(element)\
899     rc_pre_assign(pto->element, pfrom->element, cname)
900     RCCOPY(device);
901     RCCOPY(clip_stack);
902     {
903 	struct gx_pattern_cache_s *pcache = pto->pattern_cache;
904 	void *pdata = pto->client_data;
905 	gs_memory_t *mem = pto->memory;
906 	gs_state *saved = pto->saved;
907 	float *pattern = pto->line_params.dash.pattern;
908 
909 	gs_imager_state_pre_assign((gs_imager_state *)pto,
910 				   (gs_imager_state *)pfrom);
911 	*pto = *pfrom;
912 	pto->client_data = pdata;
913 	pto->memory = mem;
914 	pto->saved = saved;
915 	pto->line_params.dash.pattern = pattern;
916 	if (pto->pattern_cache == 0)
917 	    pto->pattern_cache = pcache;
918 	if (pfrom->client_data != 0) {
919 	    /* We need to break 'const' here. */
920 	    gstate_copy_client_data((gs_state *) pfrom, pdata,
921 				    pfrom->client_data, reason);
922 	}
923     }
924     GSTATE_ASSIGN_PARTS(pto, &parts);
925     pto->device_color_spaces = saved_spaces;
926 #undef RCCOPY
927     pto->show_gstate =
928 	(pfrom->show_gstate == pfrom ? pto : 0);
929     return 0;
930 }
931