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