xref: /plan9/sys/src/cmd/gs/src/gsclipsr.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1998 Aladdin Enterprises.  All rights reserved.
2 
3   This software is provided AS-IS with no warranty, either express or
4   implied.
5 
6   This software is distributed under license and may not be copied,
7   modified or distributed except as expressly authorized under the terms
8   of the license contained in the file LICENSE in this distribution.
9 
10   For more information about licensing, please refer to
11   http://www.ghostscript.com/licensing/. For information on
12   commercial licensing, go to http://www.artifex.com/licensing/ or
13   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15 */
16 
17 /* $Id: gsclipsr.c,v 1.4 2002/02/21 22:24:52 giles Exp $ */
18 /* clipsave/cliprestore */
19 #include "gx.h"
20 #include "gserrors.h"
21 #include "gsclipsr.h"
22 #include "gsstruct.h"
23 #include "gxclipsr.h"
24 #include "gxfixed.h"		/* for gxpath.h */
25 #include "gxpath.h"
26 #include "gzstate.h"
27 
28 /* Structure descriptors */
29 private_st_clip_stack();
30 
31 /*
32  * When we free a clip stack entry, free the associated clip path,
33  * and iterate down the list.  We do this iteratively so that we don't
34  * take a level of recursion for each node on the list.
35  */
36 private void
rc_free_clip_stack(gs_memory_t * mem,void * vstack,client_name_t cname)37 rc_free_clip_stack(gs_memory_t * mem, void *vstack, client_name_t cname)
38 {
39     gx_clip_stack_t *stack = (gx_clip_stack_t *)vstack;
40     gx_clip_stack_t *next;
41 
42     do {
43 	gx_clip_path *pcpath = stack->clip_path;
44 
45 	next = stack->next;
46 	gs_free_object(stack->rc.memory, stack, cname);
47 	gx_cpath_free(pcpath, "rc_free_clip_stack");
48     } while ((stack = next) != 0 && !--(stack->rc.ref_count));
49 }
50 
51 /* clipsave */
52 int
gs_clipsave(gs_state * pgs)53 gs_clipsave(gs_state *pgs)
54 {
55     gs_memory_t *mem = pgs->memory;
56     gx_clip_path *copy =
57 	gx_cpath_alloc_shared(pgs->clip_path, mem, "gs_clipsave(clip_path)");
58     gx_clip_stack_t *stack =
59 	gs_alloc_struct(mem, gx_clip_stack_t, &st_clip_stack,
60 			"gs_clipsave(stack)");
61 
62     if (copy == 0 || stack == 0) {
63 	gs_free_object(mem, stack, "gs_clipsave(stack)");
64 	gs_free_object(mem, copy, "gs_clipsave(clip_path)");
65 	return_error(gs_error_VMerror);
66     }
67     rc_init_free(stack, mem, 1, rc_free_clip_stack);
68     stack->clip_path = copy;
69     stack->next = pgs->clip_stack;
70     pgs->clip_stack = stack;
71     return 0;
72 }
73 
74 /* cliprestore */
75 int
gs_cliprestore(gs_state * pgs)76 gs_cliprestore(gs_state *pgs)
77 {
78     gx_clip_stack_t *stack = pgs->clip_stack;
79 
80     if (stack) {
81 	gx_clip_stack_t *next = stack->next;
82 	gx_clip_path *pcpath = stack->clip_path;
83 	int code;
84 
85 	if (stack->rc.ref_count == 1) {
86 	    /* Use assign_free rather than assign_preserve. */
87 	    gs_free_object(stack->rc.memory, stack, "cliprestore");
88 	    code = gx_cpath_assign_free(pgs->clip_path, pcpath);
89 	} else {
90 	    code = gx_cpath_assign_preserve(pgs->clip_path, pcpath);
91 	    if (code < 0)
92 		return code;
93 	    --(stack->rc.ref_count);
94 	}
95 	pgs->clip_stack = next;
96 	return code;
97     } else {
98 	return gx_cpath_assign_preserve(pgs->clip_path, pgs->saved->clip_path);
99     }
100 }
101