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