1 /* Copyright (C) 2001-2012 Artifex Software, Inc.
2    All Rights Reserved.
3 
4    This software is provided AS-IS with no warranty, either express or
5    implied.
6 
7    This software is distributed under license and may not be copied,
8    modified or distributed except as expressly authorized under the terms
9    of the license contained in the file LICENSE in this distribution.
10 
11    Refer to licensing information at http://www.artifex.com or contact
12    Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134, San Rafael,
13    CA  94903, U.S.A., +1(415)492-9861, for further information.
14 */
15 
16 /* Functions for managing the device filter stack */
17 
18 #include "ctype_.h"
19 #include "memory_.h"		/* for memchr, memcpy */
20 #include "string_.h"
21 #include "gx.h"
22 #include "gp.h"
23 #include "gscdefs.h"		/* for gs_lib_device_list */
24 #include "gserrors.h"
25 #include "gsfname.h"
26 #include "gsstruct.h"
27 #include "gspath.h"		/* gs_initclip prototype */
28 #include "gspaint.h"		/* gs_erasepage prototype */
29 #include "gsmatrix.h"		/* for gscoord.h */
30 #include "gscoord.h"		/* for gs_initmatrix */
31 #include "gzstate.h"
32 #include "gxcmap.h"
33 #include "gxdevice.h"
34 #include "gxdevmem.h"
35 #include "gxiodev.h"
36 
37 #include "gsdfilt.h"
38 
39 gs_private_st_ptrs3(st_gs_device_filter_stack, gs_device_filter_stack_t,
40                     "gs_device_filter_stack",
41                     gs_device_filter_stack_enum_ptrs,
42                     gs_device_filter_stack_reloc_ptrs,
43                     next, df, next_device);
44 
45 gs_public_st_simple(st_gs_device_filter, gs_device_filter_t,
46                     "gs_device_filter");
47 
48 int
gs_push_device_filter(gs_memory_t * mem,gs_state * pgs,gs_device_filter_t * df)49 gs_push_device_filter(gs_memory_t *mem, gs_state *pgs, gs_device_filter_t *df)
50 {
51     gs_device_filter_stack_t *dfs;
52     gx_device *new_dev = NULL;
53     int code;
54 
55     dfs = gs_alloc_struct(mem, gs_device_filter_stack_t,
56                           &st_gs_device_filter_stack, "gs_push_device_filter");
57     if (dfs == NULL)
58         return_error(gs_error_VMerror);
59     rc_increment(pgs->device);
60     dfs->next_device = pgs->device;
61     code = df->push(df, mem, pgs, &new_dev, pgs->device);
62     if (code < 0) {
63         gs_free_object(mem, dfs, "gs_push_device_filter");
64         return code;
65     }
66     dfs->next = pgs->dfilter_stack;
67     pgs->dfilter_stack = dfs;
68     dfs->df = df;
69     rc_init(dfs, mem, 1);
70     gs_setdevice_no_init(pgs, new_dev);
71     rc_decrement_only(new_dev, "gs_push_device_filter");
72     return code;
73 }
74 
75 int
gs_pop_device_filter(gs_memory_t * mem,gs_state * pgs)76 gs_pop_device_filter(gs_memory_t *mem, gs_state *pgs)
77 {
78     gs_device_filter_stack_t *dfs_tos = pgs->dfilter_stack;
79     gx_device *tos_device = pgs->device;
80     gs_device_filter_t *df;
81     int code;
82 
83     if (dfs_tos == NULL)
84         return_error(gs_error_rangecheck);
85     df = dfs_tos->df;
86     pgs->dfilter_stack = dfs_tos->next;
87     code = df->prepop(df, mem, pgs, tos_device);
88     rc_increment(tos_device);
89     gs_setdevice_no_init(pgs, dfs_tos->next_device);
90     rc_decrement_only(dfs_tos->next_device, "gs_pop_device_filter");
91     dfs_tos->df = NULL;
92     rc_decrement_only(dfs_tos, "gs_pop_device_filter");
93     code = df->postpop(df, mem, pgs, tos_device);
94     rc_decrement_only(tos_device, "gs_pop_device_filter");
95     return code;
96 }
97 
98 int
gs_clear_device_filters(gs_memory_t * mem,gs_state * pgs)99 gs_clear_device_filters(gs_memory_t *mem, gs_state *pgs)
100 {
101     int code;
102 
103     while (pgs->dfilter_stack != NULL) {
104         if ((code = gs_pop_device_filter(mem, pgs)) < 0)
105             return code;
106     }
107     return 0;
108 }
109