diff options
Diffstat (limited to 'base/gsclipsr.c')
-rw-r--r-- | base/gsclipsr.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/base/gsclipsr.c b/base/gsclipsr.c new file mode 100644 index 00000000..587ee0f5 --- /dev/null +++ b/base/gsclipsr.c @@ -0,0 +1,95 @@ +/* Copyright (C) 2001-2019 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or + implied. + + This software is distributed under license and may not be copied, + modified or distributed except as expressly authorized under the terms + of the license contained in the file LICENSE in this distribution. + + Refer to licensing information at http://www.artifex.com or contact + Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, + CA 94945, U.S.A., +1(415)492-9861, for further information. +*/ + + +/* 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 and the associated clip path. + */ +static 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; + + if (stack->rc.ref_count <= 1 ) { + gx_clip_path *pcpath = stack->clip_path; + + gs_free_object(stack->rc.memory, stack, cname); + gx_cpath_free(pcpath, "rc_free_clip_stack"); + } +} + +/* clipsave */ +int +gs_clipsave(gs_gstate *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_gstate *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); + } +} |