/* Copyright (C) 1998 artofcode LLC. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA, 02111-1307. */ /*$Id: gsclipsr.c,v 1.2.6.1.2.1 2003/01/17 00:49:02 giles Exp $ */ /* clipsave/cliprestore */ #include "gx.h" #include "gserrors.h" #include "gsclipsr.h" #include "gsstruct.h" #include "gxclipsr.h" #include "gxfixed.h" /* for gxpath.h */ #include "gxpath.h" #include "gzstate.h" /* Structure descriptors */ private_st_clip_stack(); /* * When we free a clip stack entry, free the associated clip path, * and iterate down the list. We do this iteratively so that we don't * take a level of recursion for each node on the list. */ private void rc_free_clip_stack(gs_memory_t * mem, void *vstack, client_name_t cname) { gx_clip_stack_t *stack = (gx_clip_stack_t *)vstack; gx_clip_stack_t *next; do { gx_clip_path *pcpath = stack->clip_path; next = stack->next; gs_free_object(stack->rc.memory, stack, cname); gx_cpath_free(pcpath, "rc_free_clip_stack"); } while ((stack = next) != 0 && !--(stack->rc.ref_count)); } /* clipsave */ int gs_clipsave(gs_state *pgs) { gs_memory_t *mem = pgs->memory; gx_clip_path *copy = gx_cpath_alloc_shared(pgs->clip_path, mem, "gs_clipsave(clip_path)"); gx_clip_stack_t *stack = gs_alloc_struct(mem, gx_clip_stack_t, &st_clip_stack, "gs_clipsave(stack)"); if (copy == 0 || stack == 0) { gs_free_object(mem, stack, "gs_clipsave(stack)"); gs_free_object(mem, copy, "gs_clipsave(clip_path)"); return_error(gs_error_VMerror); } rc_init_free(stack, mem, 1, rc_free_clip_stack); stack->clip_path = copy; stack->next = pgs->clip_stack; pgs->clip_stack = stack; return 0; } /* cliprestore */ int gs_cliprestore(gs_state *pgs) { gx_clip_stack_t *stack = pgs->clip_stack; if (stack) { gx_clip_stack_t *next = stack->next; gx_clip_path *pcpath = stack->clip_path; int code; if (stack->rc.ref_count == 1) { /* Use assign_free rather than assign_preserve. */ gs_free_object(stack->rc.memory, stack, "cliprestore"); code = gx_cpath_assign_free(pgs->clip_path, pcpath); } else { code = gx_cpath_assign_preserve(pgs->clip_path, pcpath); if (code < 0) return code; --(stack->rc.ref_count); } pgs->clip_stack = next; return code; } else { return gx_cpath_assign_preserve(pgs->clip_path, pgs->saved->clip_path); } }