1 /* Copyright (C) 2001-2019 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., 1305 Grant Avenue - Suite 200, Novato,
13 CA 94945, U.S.A., +1(415)492-9861, for further information.
14 */
15
16
17 /* PatternType 2 implementation */
18 #include "gx.h"
19 #include "gserrors.h"
20 #include "gscspace.h"
21 #include "gsshade.h"
22 #include "gsmatrix.h" /* for gspcolor.h */
23 #include "gsstate.h" /* for set/currentfilladjust */
24 #include "gxcolor2.h"
25 #include "gxdcolor.h"
26 #include "gsptype2.h"
27 #include "gxpcolor.h"
28 #include "gxstate.h" /* for gs_gstate_memory */
29 #include "gzpath.h"
30 #include "gzcpath.h"
31 #include "gzstate.h"
32 #include "gxdevsop.h"
33
34 /* GC descriptors */
35 private_st_pattern2_template();
36 public_st_pattern2_instance();
37
38 /* GC procedures */
ENUM_PTRS_BEGIN(pattern2_instance_enum_ptrs)39 static ENUM_PTRS_BEGIN(pattern2_instance_enum_ptrs) {
40 if (index < st_pattern2_template_max_ptrs) {
41 gs_ptr_type_t ptype =
42 ENUM_SUPER_ELT(gs_pattern2_instance_t, st_pattern2_template,
43 templat, 0);
44
45 if (ptype)
46 return ptype;
47 return ENUM_OBJ(NULL); /* don't stop early */
48 }
49 ENUM_PREFIX(st_pattern_instance, st_pattern2_template_max_ptrs);
50 }
51 ENUM_PTRS_END
RELOC_PTRS_BEGIN(pattern2_instance_reloc_ptrs)52 static RELOC_PTRS_BEGIN(pattern2_instance_reloc_ptrs) {
53 RELOC_PREFIX(st_pattern_instance);
54 RELOC_SUPER(gs_pattern2_instance_t, st_pattern2_template, templat);
55 } RELOC_PTRS_END
56
57 /* Define a PatternType 2 pattern. */
58 static pattern_proc_uses_base_space(gs_pattern2_uses_base_space);
59 static pattern_proc_make_pattern(gs_pattern2_make_pattern);
60 static pattern_proc_get_pattern(gs_pattern2_get_pattern);
61 static pattern_proc_remap_color(gs_pattern2_remap_color);
62 static pattern_proc_set_color(gs_pattern2_set_color);
63 static const gs_pattern_type_t gs_pattern2_type = {
64 2, {
65 gs_pattern2_uses_base_space, gs_pattern2_make_pattern,
66 gs_pattern2_get_pattern, gs_pattern2_remap_color,
67 gs_pattern2_set_color,
68 }
69 };
70
71 /* Initialize a PatternType 2 pattern. */
72 void
gs_pattern2_init(gs_pattern2_template_t * ppat)73 gs_pattern2_init(gs_pattern2_template_t * ppat)
74 {
75 gs_pattern_common_init((gs_pattern_template_t *)ppat, &gs_pattern2_type);
76 }
77
78 /* Test whether a PatternType 2 pattern uses a base space. */
79 static bool
gs_pattern2_uses_base_space(const gs_pattern_template_t * ptemp)80 gs_pattern2_uses_base_space(const gs_pattern_template_t *ptemp)
81 {
82 return false;
83 }
84
85 /* Make an instance of a PatternType 2 pattern. */
86 static int
gs_pattern2_make_pattern(gs_client_color * pcc,const gs_pattern_template_t * pcp,const gs_matrix * pmat,gs_gstate * pgs,gs_memory_t * mem)87 gs_pattern2_make_pattern(gs_client_color * pcc,
88 const gs_pattern_template_t * pcp,
89 const gs_matrix * pmat, gs_gstate * pgs,
90 gs_memory_t * mem)
91 {
92 const gs_pattern2_template_t *ptemp =
93 (const gs_pattern2_template_t *)pcp;
94 int code = gs_make_pattern_common(pcc, pcp, pmat, pgs, mem,
95 &st_pattern2_instance);
96 gs_pattern2_instance_t *pinst;
97
98 if (code < 0)
99 return code;
100 pinst = (gs_pattern2_instance_t *)pcc->pattern;
101 pinst->templat = *ptemp;
102 pinst->shfill = false;
103 return 0;
104 }
105
106 /* Get the template of a PatternType 2 pattern instance. */
107 static const gs_pattern_template_t *
gs_pattern2_get_pattern(const gs_pattern_instance_t * pinst)108 gs_pattern2_get_pattern(const gs_pattern_instance_t *pinst)
109 {
110 return (const gs_pattern_template_t *)
111 &((const gs_pattern2_instance_t *)pinst)->templat;
112 }
113
114 /* Set the 'shfill' flag to a PatternType 2 pattern instance. */
115 int
gs_pattern2_set_shfill(gs_client_color * pcc)116 gs_pattern2_set_shfill(gs_client_color * pcc)
117 {
118 gs_pattern2_instance_t *pinst;
119
120 if (pcc->pattern->type != &gs_pattern2_type)
121 return_error(gs_error_unregistered); /* Must not happen. */
122 pinst = (gs_pattern2_instance_t *)pcc->pattern;
123 pinst->shfill = true;
124 return 0;
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 static dev_color_proc_get_dev_halftone(gx_dc_pattern2_get_dev_halftone);
135 static dev_color_proc_load(gx_dc_pattern2_load);
136 static dev_color_proc_fill_rectangle(gx_dc_pattern2_fill_rectangle);
137 static dev_color_proc_equal(gx_dc_pattern2_equal);
138 static 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_cannot_write, gx_dc_cannot_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 static 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 static int
gx_dc_pattern2_load(gx_device_color * pdevc,const gs_gstate * ignore_pgs,gx_device * ignore_dev,gs_color_select_t ignore_select)172 gx_dc_pattern2_load(gx_device_color *pdevc, const gs_gstate *ignore_pgs,
173 gx_device *ignore_dev, gs_color_select_t ignore_select)
174 {
175 return 0;
176 }
177
178 /* Remap a PatternType 2 color. */
179 static int
gs_pattern2_remap_color(const gs_client_color * pc,const gs_color_space * pcs,gx_device_color * pdc,const gs_gstate * pgs,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_gstate * pgs,
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 must also update
195 * any overprint information and make sure that the graphic state
196 * stored in the pattern instance has the proper color map and overprint
197 * information.
198 */
199 static int
gs_pattern2_set_color(const gs_client_color * pcc,gs_gstate * pgs)200 gs_pattern2_set_color(const gs_client_color * pcc, gs_gstate * pgs)
201 {
202 gs_pattern2_instance_t * pinst = (gs_pattern2_instance_t *)pcc->pattern;
203 gs_color_space * pcs = pinst->templat.Shading->params.ColorSpace;
204 int code;
205 uchar k, num_comps;
206
207 /* Shading patterns can't use opm */
208 pgs->color[!pgs->is_fill_color].effective_opm = 0;
209
210 pinst->saved->overprint_mode = pgs->overprint_mode;
211 pinst->saved->overprint = pgs->overprint;
212
213 num_comps = pgs->device->color_info.num_components;
214 for (k = 0; k < num_comps; k++) {
215 pgs->color_component_map.color_map[k] =
216 pinst->saved->color_component_map.color_map[k];
217 }
218 code = pcs->type->set_overprint(pcs, pgs);
219 return code;
220 }
221
222 /* Fill a rectangle with a PatternType 2 color. */
223 /* WARNING: This function doesn't account the shading BBox
224 to allow the clipent to optimize the clipping
225 with changing the order of clip paths and rects.
226 The client must clip with the shading BBox before calling this function. */
227 static 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)228 gx_dc_pattern2_fill_rectangle(const gx_device_color * pdevc, int x, int y,
229 int w, int h, gx_device * dev,
230 gs_logical_operation_t lop,
231 const gx_rop_source_t * source)
232 {
233 if (dev_proc(dev, dev_spec_op)(dev, gxdso_pattern_is_cpath_accum, NULL, 0)) {
234 /* Performing a conversion of imagemask into a clipping path.
235 Fall back to the device procedure. */
236 return dev_proc(dev, fill_rectangle)(dev, x, y, w, h, (gx_color_index)0/*any*/);
237 } else {
238 gs_fixed_rect rect;
239 gs_pattern2_instance_t *pinst =
240 (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
241
242 rect.p.x = int2fixed(x);
243 rect.p.y = int2fixed(y);
244 rect.q.x = int2fixed(x + w);
245 rect.q.y = int2fixed(y + h);
246 return gs_shading_do_fill_rectangle(pinst->templat.Shading, &rect, dev,
247 (gs_gstate *)pinst->saved, !pinst->shfill);
248 }
249 }
250
251 /* Compare two PatternType 2 colors for equality. */
252 static bool
gx_dc_pattern2_equal(const gx_device_color * pdevc1,const gx_device_color * pdevc2)253 gx_dc_pattern2_equal(const gx_device_color * pdevc1,
254 const gx_device_color * pdevc2)
255 {
256 return pdevc2->type == pdevc1->type &&
257 pdevc1->ccolor.pattern == pdevc2->ccolor.pattern;
258 }
259
260 /*
261 * Currently patterns cannot be passed through the command list,
262 * however vector devices need to save a color for comparing
263 * it with another color, which appears later.
264 * We provide a minimal support, which is necessary
265 * for the current implementation of pdfwrite.
266 * It is not sufficient for restoring the pattern from the saved color.
267 */
268 static void
gx_dc_pattern2_save_dc(const gx_device_color * pdevc,gx_device_color_saved * psdc)269 gx_dc_pattern2_save_dc(
270 const gx_device_color * pdevc,
271 gx_device_color_saved * psdc )
272 {
273 gs_pattern2_instance_t * pinst = (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
274
275 psdc->type = pdevc->type;
276 psdc->colors.pattern2.id = pinst->pattern_id;
277 psdc->colors.pattern2.shfill = pinst->shfill;
278 }
279
280 /* Transform a shading bounding box into device space. */
281 /* This is just a bridge to an old code. */
282 int
gx_dc_pattern2_shade_bbox_transform2fixed(const gs_rect * rect,const gs_gstate * pgs,gs_fixed_rect * rfixed)283 gx_dc_pattern2_shade_bbox_transform2fixed(const gs_rect * rect, const gs_gstate * pgs,
284 gs_fixed_rect * rfixed)
285 {
286 gs_rect dev_rect;
287 int code = gs_bbox_transform(rect, &ctm_only(pgs), &dev_rect);
288
289 if (code >= 0) {
290 rfixed->p.x = float2fixed(dev_rect.p.x);
291 rfixed->p.y = float2fixed(dev_rect.p.y);
292 rfixed->q.x = float2fixed(dev_rect.q.x);
293 rfixed->q.y = float2fixed(dev_rect.q.y);
294 }
295 return code;
296 }
297
298 /* Get a shading bbox. Returns 1 on success. */
299 int
gx_dc_pattern2_get_bbox(const gx_device_color * pdevc,gs_fixed_rect * bbox)300 gx_dc_pattern2_get_bbox(const gx_device_color * pdevc, gs_fixed_rect *bbox)
301 {
302 gs_pattern2_instance_t *pinst =
303 (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
304 int code;
305
306 if (!pinst->templat.Shading->params.have_BBox)
307 return 0;
308 code = gx_dc_pattern2_shade_bbox_transform2fixed(
309 &pinst->templat.Shading->params.BBox, (gs_gstate *)pinst->saved, bbox);
310 if (code < 0)
311 return code;
312 return 1;
313 }
314
315 int
gx_dc_pattern2_color_has_bbox(const gx_device_color * pdevc)316 gx_dc_pattern2_color_has_bbox(const gx_device_color * pdevc)
317 {
318 gs_pattern2_instance_t *pinst = (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
319 const gs_shading_t *psh = pinst->templat.Shading;
320
321 return psh->params.have_BBox;
322 }
323
324 /* Create a path from a PatternType 2 shading BBox to a path. */
325 static int
gx_dc_shading_path_add_box(gx_path * ppath,const gx_device_color * pdevc)326 gx_dc_shading_path_add_box(gx_path *ppath, const gx_device_color * pdevc)
327 {
328 gs_pattern2_instance_t *pinst = (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
329 const gs_shading_t *psh = pinst->templat.Shading;
330
331 if (!psh->params.have_BBox)
332 return_error(gs_error_unregistered); /* Do not call in this case. */
333 else {
334 gs_gstate *pgs = pinst->saved;
335
336 return gs_shading_path_add_box(ppath, &psh->params.BBox, &pgs->ctm);
337 }
338 }
339
340 /* Intersect a clipping path a shading BBox. */
341 int
gx_dc_pattern2_clip_with_bbox(const gx_device_color * pdevc,gx_device * pdev,gx_clip_path * cpath_local,const gx_clip_path ** ppcpath1)342 gx_dc_pattern2_clip_with_bbox(const gx_device_color * pdevc, gx_device * pdev,
343 gx_clip_path *cpath_local, const gx_clip_path **ppcpath1)
344 {
345 if (gx_dc_is_pattern2_color(pdevc) && gx_dc_pattern2_color_has_bbox(pdevc) &&
346 (*dev_proc(pdev, dev_spec_op))(pdev, gxdso_pattern_shading_area, NULL, 0) == 0) {
347 gs_pattern2_instance_t *pinst = (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
348 gx_path box_path;
349 gs_memory_t *mem = (*ppcpath1 != NULL ? (*ppcpath1)->path.memory : pdev->memory);
350 int code;
351
352 gx_path_init_local(&box_path, mem);
353 code = gx_dc_shading_path_add_box(&box_path, pdevc);
354 if (code != gs_error_limitcheck) {
355 /* Ignore huge BBox causing limitcheck - bug 689027. */
356 if (code >= 0) {
357 gx_cpath_init_local_shared(cpath_local, *ppcpath1, mem);
358 code = gx_cpath_intersect(cpath_local, &box_path, gx_rule_winding_number, (gs_gstate *)pinst->saved);
359 if (code < 0) {
360 gx_path_free(&box_path, "gx_default_fill_path(path_bbox)");
361 return code;
362 }
363 *ppcpath1 = cpath_local;
364 }
365 }
366 gx_path_free(&box_path, "gx_default_fill_path(path_bbox)");
367 }
368 return 0;
369 }
370
371 /* Intersect a clipping path a shading BBox. */
372 int
gx_dc_pattern2_clip_with_bbox_simple(const gx_device_color * pdevc,gx_device * pdev,gx_clip_path * cpath_local)373 gx_dc_pattern2_clip_with_bbox_simple(const gx_device_color * pdevc, gx_device * pdev,
374 gx_clip_path *cpath_local)
375 {
376 int code = 0;
377
378 if (gx_dc_is_pattern2_color(pdevc) && gx_dc_pattern2_color_has_bbox(pdevc) &&
379 (*dev_proc(pdev, dev_spec_op))(pdev, gxdso_pattern_shading_area, NULL, 0) == 0) {
380 gs_pattern2_instance_t *pinst = (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
381 gx_path box_path;
382 gs_memory_t *mem = cpath_local->path.memory;
383
384 gx_path_init_local(&box_path, mem);
385 code = gx_dc_shading_path_add_box(&box_path, pdevc);
386 if (code == gs_error_limitcheck) {
387 /* Ignore huge BBox - bug 689027. */
388 code = 0;
389 } else if (code >= 0) {
390 code = gx_cpath_intersect(cpath_local, &box_path, gx_rule_winding_number, (gs_gstate *)pinst->saved);
391 }
392 gx_path_free(&box_path, "gx_default_fill_path(path_bbox)");
393 }
394 return code;
395 }
396
397 /* Check whether color is a shading with BBox. */
398 int
gx_dc_pattern2_is_rectangular_cell(const gx_device_color * pdevc,gx_device * pdev,gs_fixed_rect * rect)399 gx_dc_pattern2_is_rectangular_cell(const gx_device_color * pdevc, gx_device * pdev, gs_fixed_rect *rect)
400 {
401 if (gx_dc_is_pattern2_color(pdevc) && gx_dc_pattern2_color_has_bbox(pdevc) &&
402 (*dev_proc(pdev, dev_spec_op))(pdev, gxdso_pattern_shading_area, NULL, 0) == 0) {
403 gs_pattern2_instance_t *pinst = (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
404 const gs_shading_t *psh = pinst->templat.Shading;
405 gs_fixed_point p, q;
406
407 if (is_xxyy(&ctm_only(pinst->saved)))
408 if (psh->params.have_BBox) {
409 int code = gs_point_transform2fixed(&pinst->saved->ctm,
410 psh->params.BBox.p.x, psh->params.BBox.p.y, &p);
411 if (code < 0)
412 return code;
413 code = gs_point_transform2fixed(&pinst->saved->ctm,
414 psh->params.BBox.q.x, psh->params.BBox.q.y, &q);
415 if (code < 0)
416 return code;
417 if (p.x > q.x) {
418 p.x ^= q.x; q.x ^= p.x; p.x ^= q.x;
419 }
420 if (p.y > q.y) {
421 p.y ^= q.y; q.y ^= p.y; p.y ^= q.y;
422 }
423 rect->p = p;
424 rect->q = q;
425 return 1;
426 }
427 }
428 return 0;
429 }
430
431 /* Get a shading color space. */
432 const gs_color_space *
gx_dc_pattern2_get_color_space(const gx_device_color * pdevc)433 gx_dc_pattern2_get_color_space(const gx_device_color * pdevc)
434 {
435 gs_pattern2_instance_t *pinst =
436 (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
437 const gs_shading_t *psh = pinst->templat.Shading;
438
439 return psh->params.ColorSpace;
440 }
441
442 /* Check device color for a possibly self-overlapping shading. */
443 bool
gx_dc_pattern2_can_overlap(const gx_device_color * pdevc)444 gx_dc_pattern2_can_overlap(const gx_device_color *pdevc)
445 {
446 gs_pattern2_instance_t * pinst;
447
448 if (pdevc->type != &gx_dc_pattern2)
449 return false;
450 pinst = (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
451 switch (pinst->templat.Shading->head.type) {
452 case 3: case 6: case 7:
453 return true;
454 default:
455 return false;
456 }
457 }
458
459 /* Check whether a pattern color has a background. */
gx_dc_pattern2_has_background(const gx_device_color * pdevc)460 bool gx_dc_pattern2_has_background(const gx_device_color *pdevc)
461 {
462 gs_pattern2_instance_t * pinst;
463 const gs_shading_t *Shading;
464
465 if (pdevc->type != &gx_dc_pattern2)
466 return false;
467 pinst = (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
468 Shading = pinst->templat.Shading;
469 return !pinst->shfill && Shading->params.Background != NULL;
470 }
471