xref: /plan9/sys/src/cmd/gs/src/gsistate.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1999, 2000 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: gsistate.c,v 1.12 2005/08/30 06:38:44 igor Exp $ */
18 /* Imager state housekeeping */
19 #include "gx.h"
20 #include "gserrors.h"
21 #include "gscspace.h"
22 #include "gscie.h"
23 #include "gsstruct.h"
24 #include "gsutil.h"		/* for gs_next_ids */
25 #include "gxbitmap.h"
26 #include "gxcmap.h"
27 #include "gxdht.h"
28 #include "gxistate.h"
29 #include "gzht.h"
30 #include "gzline.h"
31 #include "gxfmap.h"
32 
33 /******************************************************************************
34  * See gsstate.c for a discussion of graphics/imager state memory management. *
35  ******************************************************************************/
36 
37 /* Imported values */
38 /* The following should include a 'const', but for some reason */
39 /* the Watcom compiler won't accept it, even though it happily accepts */
40 /* the same construct everywhere else. */
41 extern /*const*/ gx_color_map_procs *const cmap_procs_default;
42 
43 /* GC procedures for gx_line_params */
44 private
45 ENUM_PTRS_WITH(line_params_enum_ptrs, gx_line_params *plp) return 0;
46     case 0: return ENUM_OBJ((plp->dash.pattern_size == 0 ?
47 			     NULL : plp->dash.pattern));
48 ENUM_PTRS_END
RELOC_PTRS_WITH(line_params_reloc_ptrs,gx_line_params * plp)49 private RELOC_PTRS_WITH(line_params_reloc_ptrs, gx_line_params *plp)
50 {
51     if (plp->dash.pattern_size)
52 	RELOC_VAR(plp->dash.pattern);
53 } RELOC_PTRS_END
54 private_st_line_params();
55 
56 /*
57  * GC procedures for gs_imager_state
58  *
59  * See comments in gixstate.h before the definition of gs_cr_state_do_rc and
60  * st_cr_state_num_ptrs for an explanation about why the effective_transfer
61  * pointers are handled in this manner.
62  */
63 public_st_imager_state();
64 private
65 ENUM_PTRS_BEGIN(imager_state_enum_ptrs)
66     ENUM_SUPER(gs_imager_state, st_line_params, line_params, st_imager_state_num_ptrs - st_line_params_num_ptrs);
67     ENUM_PTR(0, gs_imager_state, client_data);
68     ENUM_PTR(1, gs_imager_state, opacity.mask);
69     ENUM_PTR(2, gs_imager_state, shape.mask);
70     ENUM_PTR(3, gs_imager_state, transparency_stack);
71 #define E1(i,elt) ENUM_PTR(i+4,gs_imager_state,elt);
gs_cr_state_do_ptrs(E1)72     gs_cr_state_do_ptrs(E1)
73 #undef E1
74 ENUM_PTRS_END
75 private RELOC_PTRS_BEGIN(imager_state_reloc_ptrs)
76 {
77     RELOC_SUPER(gs_imager_state, st_line_params, line_params);
78     RELOC_PTR(gs_imager_state, client_data);
79     RELOC_PTR(gs_imager_state, opacity.mask);
80     RELOC_PTR(gs_imager_state, shape.mask);
81     RELOC_PTR(gs_imager_state, transparency_stack);
82 #define R1(i,elt) RELOC_PTR(gs_imager_state,elt);
83     gs_cr_state_do_ptrs(R1)
84 #undef R1
85     {
86         int i = GX_DEVICE_COLOR_MAX_COMPONENTS - 1;
87 
88         for (; i >= 0; i--)
89             RELOC_PTR(gs_imager_state, effective_transfer[i]);
90     }
91 } RELOC_PTRS_END
92 
93 
94 /* Initialize an imager state, other than the parts covered by */
95 /* gs_imager_state_initial. */
96 int
gs_imager_state_initialize(gs_imager_state * pis,gs_memory_t * mem)97 gs_imager_state_initialize(gs_imager_state * pis, gs_memory_t * mem)
98 {
99     int i;
100     pis->memory = mem;
101     pis->client_data = 0;
102     pis->opacity.mask = 0;
103     pis->shape.mask = 0;
104     pis->transparency_stack = 0;
105     /* Color rendering state */
106     pis->halftone = 0;
107     {
108 	int i;
109 
110 	for (i = 0; i < gs_color_select_count; ++i)
111 	    pis->screen_phase[i].x = pis->screen_phase[i].y = 0;
112     }
113     pis->dev_ht = 0;
114     pis->cie_render = 0;
115     pis->black_generation = 0;
116     pis->undercolor_removal = 0;
117     /* Allocate an initial transfer map. */
118     rc_alloc_struct_n(pis->set_transfer.gray,
119 		      gx_transfer_map, &st_transfer_map,
120 		      mem, return_error(gs_error_VMerror),
121 		      "gs_imager_state_init(transfer)", 1);
122     pis->set_transfer.gray->proc = gs_identity_transfer;
123     pis->set_transfer.gray->id = gs_next_ids(pis->memory, 1);
124     pis->set_transfer.gray->values[0] = frac_0;
125     pis->set_transfer.red =
126 	pis->set_transfer.green =
127 	pis->set_transfer.blue = NULL;
128     for (i = 0; i < GX_DEVICE_COLOR_MAX_COMPONENTS; i++)
129 	pis->effective_transfer[i] = pis->set_transfer.gray;
130     pis->cie_joint_caches = NULL;
131     pis->cmap_procs = cmap_procs_default;
132     pis->pattern_cache = NULL;
133     pis->have_pattern_streams = false;
134     return 0;
135 }
136 
137 /*
138  * Make a temporary copy of a gs_imager_state.  Note that this does not
139  * do all the necessary reference counting, etc.  However, it does
140  * clear out the transparency stack in the destination.
141  */
142 gs_imager_state *
gs_imager_state_copy(const gs_imager_state * pis,gs_memory_t * mem)143 gs_imager_state_copy(const gs_imager_state * pis, gs_memory_t * mem)
144 {
145     gs_imager_state *pis_copy =
146 	gs_alloc_struct(mem, gs_imager_state, &st_imager_state,
147 			"gs_imager_state_copy");
148 
149     if (pis_copy) {
150 	*pis_copy = *pis;
151 	pis_copy->transparency_stack = 0;
152     }
153     return pis_copy;
154 }
155 
156 /* Increment reference counts to note that an imager state has been copied. */
157 void
gs_imager_state_copied(gs_imager_state * pis)158 gs_imager_state_copied(gs_imager_state * pis)
159 {
160     rc_increment(pis->opacity.mask);
161     rc_increment(pis->shape.mask);
162     rc_increment(pis->halftone);
163     rc_increment(pis->dev_ht);
164     rc_increment(pis->cie_render);
165     rc_increment(pis->black_generation);
166     rc_increment(pis->undercolor_removal);
167     rc_increment(pis->set_transfer.gray);
168     rc_increment(pis->set_transfer.red);
169     rc_increment(pis->set_transfer.green);
170     rc_increment(pis->set_transfer.blue);
171     rc_increment(pis->cie_joint_caches);
172 }
173 
174 /* Adjust reference counts before assigning one imager state to another. */
175 void
gs_imager_state_pre_assign(gs_imager_state * pto,const gs_imager_state * pfrom)176 gs_imager_state_pre_assign(gs_imager_state *pto, const gs_imager_state *pfrom)
177 {
178     const char *const cname = "gs_imager_state_pre_assign";
179 
180 #define RCCOPY(element)\
181     rc_pre_assign(pto->element, pfrom->element, cname)
182 
183     RCCOPY(cie_joint_caches);
184     RCCOPY(set_transfer.blue);
185     RCCOPY(set_transfer.green);
186     RCCOPY(set_transfer.red);
187     RCCOPY(set_transfer.gray);
188     RCCOPY(undercolor_removal);
189     RCCOPY(black_generation);
190     RCCOPY(cie_render);
191     RCCOPY(dev_ht);
192     RCCOPY(halftone);
193     RCCOPY(shape.mask);
194     RCCOPY(opacity.mask);
195 #undef RCCOPY
196 }
197 
198 /* Release an imager state. */
199 void
gs_imager_state_release(gs_imager_state * pis)200 gs_imager_state_release(gs_imager_state * pis)
201 {
202     const char *const cname = "gs_imager_state_release";
203     gx_device_halftone *pdht = pis->dev_ht;
204 
205 #define RCDECR(element)\
206     rc_decrement(pis->element, cname)
207 
208     RCDECR(cie_joint_caches);
209     RCDECR(set_transfer.gray);
210     RCDECR(set_transfer.blue);
211     RCDECR(set_transfer.green);
212     RCDECR(set_transfer.red);
213     RCDECR(undercolor_removal);
214     RCDECR(black_generation);
215     RCDECR(cie_render);
216     /*
217      * If we're going to free the device halftone, make sure we free the
218      * dependent structures as well.
219      */
220     if (pdht != 0 && pdht->rc.ref_count == 1) {
221 	gx_device_halftone_release(pdht, pdht->rc.memory);
222     }
223     RCDECR(dev_ht);
224     RCDECR(halftone);
225     RCDECR(shape.mask);
226     RCDECR(opacity.mask);
227 #undef RCDECR
228 }
229