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