1 /* Copyright (C) 1999 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: gsptype2.c,v 1.19 2005/05/25 15:57:58 igor Exp $ */
18 /* PatternType 2 implementation */
19 #include "gx.h"
20 #include "gserrors.h"
21 #include "gscspace.h"
22 #include "gsshade.h"
23 #include "gsmatrix.h" /* for gspcolor.h */
24 #include "gsstate.h" /* for set/currentfilladjust */
25 #include "gxcolor2.h"
26 #include "gxdcolor.h"
27 #include "gsptype2.h"
28 #include "gxpcolor.h"
29 #include "gxstate.h" /* for gs_state_memory */
30 #include "gzpath.h"
31 #include "gzstate.h"
32
33 /* GC descriptors */
34 private_st_pattern2_template();
35 private_st_pattern2_instance();
36
37 /* GC procedures */
ENUM_PTRS_BEGIN(pattern2_instance_enum_ptrs)38 private ENUM_PTRS_BEGIN(pattern2_instance_enum_ptrs) {
39 if (index < st_pattern2_template_max_ptrs) {
40 gs_ptr_type_t ptype =
41 ENUM_SUPER_ELT(gs_pattern2_instance_t, st_pattern2_template,
42 template, 0);
43
44 if (ptype)
45 return ptype;
46 return ENUM_OBJ(NULL); /* don't stop early */
47 }
48 ENUM_PREFIX(st_pattern_instance, st_pattern2_template_max_ptrs);
49 }
50 ENUM_PTRS_END
RELOC_PTRS_BEGIN(pattern2_instance_reloc_ptrs)51 private RELOC_PTRS_BEGIN(pattern2_instance_reloc_ptrs) {
52 RELOC_PREFIX(st_pattern_instance);
53 RELOC_SUPER(gs_pattern2_instance_t, st_pattern2_template, template);
54 } RELOC_PTRS_END
55
56 /* Define a PatternType 2 pattern. */
57 private pattern_proc_uses_base_space(gs_pattern2_uses_base_space);
58 private pattern_proc_make_pattern(gs_pattern2_make_pattern);
59 private pattern_proc_get_pattern(gs_pattern2_get_pattern);
60 private pattern_proc_remap_color(gs_pattern2_remap_color);
61 private pattern_proc_set_color(gs_pattern2_set_color);
62 private const gs_pattern_type_t gs_pattern2_type = {
63 2, {
64 gs_pattern2_uses_base_space, gs_pattern2_make_pattern,
65 gs_pattern2_get_pattern, gs_pattern2_remap_color,
66 gs_pattern2_set_color,
67 }
68 };
69
70 /* Initialize a PatternType 2 pattern. */
71 void
gs_pattern2_init(gs_pattern2_template_t * ppat)72 gs_pattern2_init(gs_pattern2_template_t * ppat)
73 {
74 gs_pattern_common_init((gs_pattern_template_t *)ppat, &gs_pattern2_type);
75 }
76
77 /* Test whether a PatternType 2 pattern uses a base space. */
78 private bool
gs_pattern2_uses_base_space(const gs_pattern_template_t * ptemp)79 gs_pattern2_uses_base_space(const gs_pattern_template_t *ptemp)
80 {
81 return false;
82 }
83
84 /* Make an instance of a PatternType 2 pattern. */
85 private int
gs_pattern2_make_pattern(gs_client_color * pcc,const gs_pattern_template_t * pcp,const gs_matrix * pmat,gs_state * pgs,gs_memory_t * mem)86 gs_pattern2_make_pattern(gs_client_color * pcc,
87 const gs_pattern_template_t * pcp,
88 const gs_matrix * pmat, gs_state * pgs,
89 gs_memory_t * mem)
90 {
91 const gs_pattern2_template_t *ptemp =
92 (const gs_pattern2_template_t *)pcp;
93 int code = gs_make_pattern_common(pcc, pcp, pmat, pgs, mem,
94 &st_pattern2_instance);
95 gs_pattern2_instance_t *pinst;
96
97 if (code < 0)
98 return code;
99 pinst = (gs_pattern2_instance_t *)pcc->pattern;
100 pinst->template = *ptemp;
101 pinst->shfill = false;
102 return 0;
103 }
104
105 /* Get the template of a PatternType 2 pattern instance. */
106 private const gs_pattern_template_t *
gs_pattern2_get_pattern(const gs_pattern_instance_t * pinst)107 gs_pattern2_get_pattern(const gs_pattern_instance_t *pinst)
108 {
109 return (const gs_pattern_template_t *)
110 &((const gs_pattern2_instance_t *)pinst)->template;
111 }
112
113 /* Set the 'shfill' flag to a PatternType 2 pattern instance. */
114 int
gs_pattern2_set_shfill(gs_client_color * pcc)115 gs_pattern2_set_shfill(gs_client_color * pcc)
116 {
117 gs_pattern2_instance_t *pinst;
118
119 if (pcc->pattern->type != &gs_pattern2_type)
120 return_error(gs_error_unregistered); /* Must not happen. */
121 pinst = (gs_pattern2_instance_t *)pcc->pattern;
122 pinst->shfill = true;
123 return 0;
124 }
125
126
127 /* ---------------- Rendering ---------------- */
128
129 /* GC descriptor */
130 gs_private_st_ptrs_add0(st_dc_pattern2, gx_device_color, "dc_pattern2",
131 dc_pattern2_enum_ptrs, dc_pattern2_reloc_ptrs,
132 st_client_color, ccolor);
133
134 private dev_color_proc_get_dev_halftone(gx_dc_pattern2_get_dev_halftone);
135 private dev_color_proc_load(gx_dc_pattern2_load);
136 private dev_color_proc_fill_rectangle(gx_dc_pattern2_fill_rectangle);
137 private dev_color_proc_equal(gx_dc_pattern2_equal);
138 private dev_color_proc_save_dc(gx_dc_pattern2_save_dc);
139 /*
140 * Define the PatternType 2 Pattern device color type. This is public only
141 * for testing when writing PDF or PostScript.
142 */
143 const gx_device_color_type_t gx_dc_pattern2 = {
144 &st_dc_pattern2,
145 gx_dc_pattern2_save_dc, gx_dc_pattern2_get_dev_halftone,
146 gx_dc_ht_get_phase,
147 gx_dc_pattern2_load, gx_dc_pattern2_fill_rectangle,
148 gx_dc_default_fill_masked, gx_dc_pattern2_equal,
149 gx_dc_pattern_write, gx_dc_pattern_read,
150 gx_dc_pattern_get_nonzero_comps
151 };
152
153 /* Check device color for Pattern Type 2. */
154 bool
gx_dc_is_pattern2_color(const gx_device_color * pdevc)155 gx_dc_is_pattern2_color(const gx_device_color *pdevc)
156 {
157 return pdevc->type == &gx_dc_pattern2;
158 }
159
160 /*
161 * The device halftone used by a PatternType 2 patter is that current in
162 * the graphic state at the time of the makepattern call.
163 */
164 private const gx_device_halftone *
gx_dc_pattern2_get_dev_halftone(const gx_device_color * pdevc)165 gx_dc_pattern2_get_dev_halftone(const gx_device_color * pdevc)
166 {
167 return ((gs_pattern2_instance_t *)pdevc->ccolor.pattern)->saved->dev_ht;
168 }
169
170 /* Load a PatternType 2 color into the cache. (No effect.) */
171 private int
gx_dc_pattern2_load(gx_device_color * pdevc,const gs_imager_state * ignore_pis,gx_device * ignore_dev,gs_color_select_t ignore_select)172 gx_dc_pattern2_load(gx_device_color *pdevc, const gs_imager_state *ignore_pis,
173 gx_device *ignore_dev, gs_color_select_t ignore_select)
174 {
175 return 0;
176 }
177
178 /* Remap a PatternType 2 color. */
179 private int
gs_pattern2_remap_color(const gs_client_color * pc,const gs_color_space * pcs,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)180 gs_pattern2_remap_color(const gs_client_color * pc, const gs_color_space * pcs,
181 gx_device_color * pdc, const gs_imager_state * pis,
182 gx_device * dev, gs_color_select_t select)
183 {
184 /* We don't do any actual color mapping now. */
185 pdc->type = &gx_dc_pattern2;
186 pdc->ccolor = *pc;
187 pdc->ccolor_valid = true;
188 return 0;
189 }
190
191 /*
192 * Perform actions required at set_color time. Since PatternType 2
193 * patterns specify a color space, we must update the overprint
194 * information as required by that color space. We temporarily disable
195 * overprint_mode, as it is never applicable when using shading patterns.
196 */
197 private int
gs_pattern2_set_color(const gs_client_color * pcc,gs_state * pgs)198 gs_pattern2_set_color(const gs_client_color * pcc, gs_state * pgs)
199 {
200 gs_pattern2_instance_t * pinst = (gs_pattern2_instance_t *)pcc->pattern;
201 gs_color_space * pcs = pinst->template.Shading->params.ColorSpace;
202 int code, save_overprint_mode = pgs->overprint_mode;
203
204 pgs->overprint_mode = 0;
205 code = pcs->type->set_overprint(pcs, pgs);
206 pgs->overprint_mode = save_overprint_mode;
207 return code;
208 }
209
210 /* Fill path or rect, and with a PatternType 2 color. */
211 int
gx_dc_pattern2_fill_path(const gx_device_color * pdevc,gx_path * ppath,gs_fixed_rect * rect,gx_device * dev)212 gx_dc_pattern2_fill_path(const gx_device_color * pdevc,
213 gx_path * ppath, gs_fixed_rect * rect,
214 gx_device * dev)
215 {
216 gs_pattern2_instance_t *pinst =
217 (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
218
219 return gs_shading_fill_path_adjusted(pinst->template.Shading, ppath, rect, dev,
220 (gs_imager_state *)pinst->saved, !pinst->shfill);
221 }
222
223 /* Fill a rectangle with a PatternType 2 color. */
224 private int
gx_dc_pattern2_fill_rectangle(const gx_device_color * pdevc,int x,int y,int w,int h,gx_device * dev,gs_logical_operation_t lop,const gx_rop_source_t * source)225 gx_dc_pattern2_fill_rectangle(const gx_device_color * pdevc, int x, int y,
226 int w, int h, gx_device * dev,
227 gs_logical_operation_t lop,
228 const gx_rop_source_t * source)
229 {
230 gs_fixed_rect rect;
231 rect.p.x = int2fixed(x);
232 rect.p.y = int2fixed(y);
233 rect.q.x = int2fixed(x + w);
234 rect.q.y = int2fixed(y + h);
235 return gx_dc_pattern2_fill_path(pdevc, NULL, &rect, dev);
236 }
237
238 /* Compare two PatternType 2 colors for equality. */
239 private bool
gx_dc_pattern2_equal(const gx_device_color * pdevc1,const gx_device_color * pdevc2)240 gx_dc_pattern2_equal(const gx_device_color * pdevc1,
241 const gx_device_color * pdevc2)
242 {
243 return pdevc2->type == pdevc1->type &&
244 pdevc1->ccolor.pattern == pdevc2->ccolor.pattern;
245 }
246
247 /*
248 * Currently patterns cannot be passed through the command list,
249 * however vector devices need to save a color for comparing
250 * it with another color, which appears later.
251 * We provide a minimal support, which is necessary
252 * for the current implementation of pdfwrite.
253 * It is not sufficient for restoring the pattern from the saved color.
254 */
255 private void
gx_dc_pattern2_save_dc(const gx_device_color * pdevc,gx_device_color_saved * psdc)256 gx_dc_pattern2_save_dc(
257 const gx_device_color * pdevc,
258 gx_device_color_saved * psdc )
259 {
260 gs_pattern2_instance_t * pinst = (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
261
262 psdc->type = pdevc->type;
263 psdc->colors.pattern2.id = pinst->pattern_id;
264 }
265
266 /* Transform a shading bounding box into device space. */
267 /* This is just a bridge to an old code. */
268 int
gx_dc_pattern2_shade_bbox_transform2fixed(const gs_rect * rect,const gs_imager_state * pis,gs_fixed_rect * rfixed)269 gx_dc_pattern2_shade_bbox_transform2fixed(const gs_rect * rect, const gs_imager_state * pis,
270 gs_fixed_rect * rfixed)
271 {
272 gs_rect dev_rect;
273 int code = gs_bbox_transform(rect, &ctm_only(pis), &dev_rect);
274
275 if (code >= 0) {
276 rfixed->p.x = float2fixed(dev_rect.p.x);
277 rfixed->p.y = float2fixed(dev_rect.p.y);
278 rfixed->q.x = float2fixed(dev_rect.q.x);
279 rfixed->q.y = float2fixed(dev_rect.q.y);
280 }
281 return code;
282 }
283
284 /* Get a shading bbox. Returns 1 on success. */
285 int
gx_dc_pattern2_get_bbox(const gx_device_color * pdevc,gs_fixed_rect * bbox)286 gx_dc_pattern2_get_bbox(const gx_device_color * pdevc, gs_fixed_rect *bbox)
287 {
288 gs_pattern2_instance_t *pinst =
289 (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
290 int code;
291
292 if (!pinst->template.Shading->params.have_BBox)
293 return 0;
294 code = gx_dc_pattern2_shade_bbox_transform2fixed(
295 &pinst->template.Shading->params.BBox, (gs_imager_state *)pinst->saved, bbox);
296 if (code < 0)
297 return code;
298 return 1;
299 }
300
301 /* Check device color for a possibly self-overlapping shading. */
302 bool
gx_dc_pattern2_can_overlap(const gx_device_color * pdevc)303 gx_dc_pattern2_can_overlap(const gx_device_color *pdevc)
304 {
305 gs_pattern2_instance_t * pinst;
306
307 if (pdevc->type != &gx_dc_pattern2)
308 return false;
309 pinst = (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
310 switch (pinst->template.Shading->head.type) {
311 case 3: case 6: case 7:
312 return true;
313 default:
314 return false;
315 }
316 }
317
318 /* Check whether a pattern color has a background. */
gx_dc_pattern2_has_background(const gx_device_color * pdevc)319 bool gx_dc_pattern2_has_background(const gx_device_color *pdevc)
320 {
321 gs_pattern2_instance_t * pinst;
322 const gs_shading_t *Shading;
323
324 if (pdevc->type != &gx_dc_pattern2)
325 return false;
326 pinst = (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
327 Shading = pinst->template.Shading;
328 return !pinst->shfill && Shading->params.Background != NULL;
329 }
330