1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com/
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
14
/* $Id: gsptype2.c 8655 2008-04-21 14:53:38Z leonardo $ */
15
/* PatternType 2 implementation */
20
#include "gsmatrix.h" /* for gspcolor.h */
21
#include "gsstate.h" /* for set/currentfilladjust */
26
#include "gxstate.h" /* for gs_state_memory */
32
private_st_pattern2_template();
33
private_st_pattern2_instance();
36
static ENUM_PTRS_BEGIN(pattern2_instance_enum_ptrs) {
37
if (index < st_pattern2_template_max_ptrs) {
39
ENUM_SUPER_ELT(gs_pattern2_instance_t, st_pattern2_template,
44
return ENUM_OBJ(NULL); /* don't stop early */
46
ENUM_PREFIX(st_pattern_instance, st_pattern2_template_max_ptrs);
49
static RELOC_PTRS_BEGIN(pattern2_instance_reloc_ptrs) {
50
RELOC_PREFIX(st_pattern_instance);
51
RELOC_SUPER(gs_pattern2_instance_t, st_pattern2_template, template);
54
/* Define a PatternType 2 pattern. */
55
static pattern_proc_uses_base_space(gs_pattern2_uses_base_space);
56
static pattern_proc_make_pattern(gs_pattern2_make_pattern);
57
static pattern_proc_get_pattern(gs_pattern2_get_pattern);
58
static pattern_proc_remap_color(gs_pattern2_remap_color);
59
static pattern_proc_set_color(gs_pattern2_set_color);
60
static const gs_pattern_type_t gs_pattern2_type = {
62
gs_pattern2_uses_base_space, gs_pattern2_make_pattern,
63
gs_pattern2_get_pattern, gs_pattern2_remap_color,
64
gs_pattern2_set_color,
68
/* Initialize a PatternType 2 pattern. */
70
gs_pattern2_init(gs_pattern2_template_t * ppat)
72
gs_pattern_common_init((gs_pattern_template_t *)ppat, &gs_pattern2_type);
75
/* Test whether a PatternType 2 pattern uses a base space. */
77
gs_pattern2_uses_base_space(const gs_pattern_template_t *ptemp)
82
/* Make an instance of a PatternType 2 pattern. */
84
gs_pattern2_make_pattern(gs_client_color * pcc,
85
const gs_pattern_template_t * pcp,
86
const gs_matrix * pmat, gs_state * pgs,
89
const gs_pattern2_template_t *ptemp =
90
(const gs_pattern2_template_t *)pcp;
91
int code = gs_make_pattern_common(pcc, pcp, pmat, pgs, mem,
92
&st_pattern2_instance);
93
gs_pattern2_instance_t *pinst;
97
pinst = (gs_pattern2_instance_t *)pcc->pattern;
98
pinst->template = *ptemp;
99
pinst->shfill = false;
103
/* Get the template of a PatternType 2 pattern instance. */
104
static const gs_pattern_template_t *
105
gs_pattern2_get_pattern(const gs_pattern_instance_t *pinst)
107
return (const gs_pattern_template_t *)
108
&((const gs_pattern2_instance_t *)pinst)->template;
111
/* Set the 'shfill' flag to a PatternType 2 pattern instance. */
113
gs_pattern2_set_shfill(gs_client_color * pcc)
115
gs_pattern2_instance_t *pinst;
117
if (pcc->pattern->type != &gs_pattern2_type)
118
return_error(gs_error_unregistered); /* Must not happen. */
119
pinst = (gs_pattern2_instance_t *)pcc->pattern;
120
pinst->shfill = true;
125
/* ---------------- Rendering ---------------- */
128
gs_private_st_ptrs_add0(st_dc_pattern2, gx_device_color, "dc_pattern2",
129
dc_pattern2_enum_ptrs, dc_pattern2_reloc_ptrs,
130
st_client_color, ccolor);
132
static dev_color_proc_get_dev_halftone(gx_dc_pattern2_get_dev_halftone);
133
static dev_color_proc_load(gx_dc_pattern2_load);
134
static dev_color_proc_fill_rectangle(gx_dc_pattern2_fill_rectangle);
135
static dev_color_proc_equal(gx_dc_pattern2_equal);
136
static dev_color_proc_save_dc(gx_dc_pattern2_save_dc);
138
* Define the PatternType 2 Pattern device color type. This is public only
139
* for testing when writing PDF or PostScript.
141
const gx_device_color_type_t gx_dc_pattern2 = {
143
gx_dc_pattern2_save_dc, gx_dc_pattern2_get_dev_halftone,
145
gx_dc_pattern2_load, gx_dc_pattern2_fill_rectangle,
146
gx_dc_default_fill_masked, gx_dc_pattern2_equal,
147
gx_dc_cannot_write, gx_dc_cannot_read,
148
gx_dc_pattern_get_nonzero_comps
151
/* Check device color for Pattern Type 2. */
153
gx_dc_is_pattern2_color(const gx_device_color *pdevc)
155
return pdevc->type == &gx_dc_pattern2;
159
* The device halftone used by a PatternType 2 patter is that current in
160
* the graphic state at the time of the makepattern call.
162
static const gx_device_halftone *
163
gx_dc_pattern2_get_dev_halftone(const gx_device_color * pdevc)
165
return ((gs_pattern2_instance_t *)pdevc->ccolor.pattern)->saved->dev_ht;
168
/* Load a PatternType 2 color into the cache. (No effect.) */
170
gx_dc_pattern2_load(gx_device_color *pdevc, const gs_imager_state *ignore_pis,
171
gx_device *ignore_dev, gs_color_select_t ignore_select)
176
/* Remap a PatternType 2 color. */
178
gs_pattern2_remap_color(const gs_client_color * pc, const gs_color_space * pcs,
179
gx_device_color * pdc, const gs_imager_state * pis,
180
gx_device * dev, gs_color_select_t select)
182
/* We don't do any actual color mapping now. */
183
pdc->type = &gx_dc_pattern2;
185
pdc->ccolor_valid = true;
190
* Perform actions required at set_color time. Since PatternType 2
191
* patterns specify a color space, we must update the overprint
192
* information as required by that color space. We temporarily disable
193
* overprint_mode, as it is never applicable when using shading patterns.
196
gs_pattern2_set_color(const gs_client_color * pcc, gs_state * pgs)
198
gs_pattern2_instance_t * pinst = (gs_pattern2_instance_t *)pcc->pattern;
199
gs_color_space * pcs = pinst->template.Shading->params.ColorSpace;
200
int code, save_overprint_mode = pgs->overprint_mode;
202
pgs->overprint_mode = 0;
203
code = pcs->type->set_overprint(pcs, pgs);
204
pgs->overprint_mode = save_overprint_mode;
208
/* Fill a rectangle with a PatternType 2 color. */
209
/* WARNING: This function doesn't account the shading BBox
210
to allow the clipent to optimize the clipping
211
with changing the order of clip patrhs and rects.
212
The client must clip with the shading BBOx before calling this function. */
214
gx_dc_pattern2_fill_rectangle(const gx_device_color * pdevc, int x, int y,
215
int w, int h, gx_device * dev,
216
gs_logical_operation_t lop,
217
const gx_rop_source_t * source)
219
if (dev_proc(dev, pattern_manage)(dev, gs_no_id, NULL, pattern_manage__is_cpath_accum)) {
220
/* Performing a conversion of imagemask into a clipping path.
221
Fall back to the device procedure. */
222
return dev_proc(dev, fill_rectangle)(dev, x, y, w, h, (gx_color_index)0/*any*/);
225
gs_pattern2_instance_t *pinst =
226
(gs_pattern2_instance_t *)pdevc->ccolor.pattern;
228
rect.p.x = int2fixed(x);
229
rect.p.y = int2fixed(y);
230
rect.q.x = int2fixed(x + w);
231
rect.q.y = int2fixed(y + h);
232
return gs_shading_do_fill_rectangle(pinst->template.Shading, &rect, dev,
233
(gs_imager_state *)pinst->saved, !pinst->shfill);
237
/* Compare two PatternType 2 colors for equality. */
239
gx_dc_pattern2_equal(const gx_device_color * pdevc1,
240
const gx_device_color * pdevc2)
242
return pdevc2->type == pdevc1->type &&
243
pdevc1->ccolor.pattern == pdevc2->ccolor.pattern;
247
* Currently patterns cannot be passed through the command list,
248
* however vector devices need to save a color for comparing
249
* it with another color, which appears later.
250
* We provide a minimal support, which is necessary
251
* for the current implementation of pdfwrite.
252
* It is not sufficient for restoring the pattern from the saved color.
255
gx_dc_pattern2_save_dc(
256
const gx_device_color * pdevc,
257
gx_device_color_saved * psdc )
259
gs_pattern2_instance_t * pinst = (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
261
psdc->type = pdevc->type;
262
psdc->colors.pattern2.id = pinst->pattern_id;
263
psdc->colors.pattern2.shfill = pinst->shfill;
266
/* Transform a shading bounding box into device space. */
267
/* This is just a bridge to an old code. */
269
gx_dc_pattern2_shade_bbox_transform2fixed(const gs_rect * rect, const gs_imager_state * pis,
270
gs_fixed_rect * rfixed)
273
int code = gs_bbox_transform(rect, &ctm_only(pis), &dev_rect);
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);
284
/* Get a shading bbox. Returns 1 on success. */
286
gx_dc_pattern2_get_bbox(const gx_device_color * pdevc, gs_fixed_rect *bbox)
288
gs_pattern2_instance_t *pinst =
289
(gs_pattern2_instance_t *)pdevc->ccolor.pattern;
292
if (!pinst->template.Shading->params.have_BBox)
294
code = gx_dc_pattern2_shade_bbox_transform2fixed(
295
&pinst->template.Shading->params.BBox, (gs_imager_state *)pinst->saved, bbox);
302
gx_dc_pattern2_color_has_bbox(const gx_device_color * pdevc)
304
gs_pattern2_instance_t *pinst = (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
305
const gs_shading_t *psh = pinst->template.Shading;
307
return psh->params.have_BBox;
310
/* Create a path from a PatternType 2 shading BBox to a path. */
312
gx_dc_shading_path_add_box(gx_path *ppath, const gx_device_color * pdevc)
314
gs_pattern2_instance_t *pinst = (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
315
const gs_shading_t *psh = pinst->template.Shading;
317
if (!psh->params.have_BBox)
318
return_error(gs_error_unregistered); /* Do not call in this case. */
320
gs_state *pis = pinst->saved;
322
return gs_shading_path_add_box(ppath, &psh->params.BBox, &pis->ctm);
326
/* Intersect a clipping path a shading BBox. */
328
gx_dc_pattern2_clip_with_bbox_simple(const gx_device_color * pdevc, gx_device * pdev,
329
gx_clip_path *cpath_local)
333
if (gx_dc_is_pattern2_color(pdevc) && gx_dc_pattern2_color_has_bbox(pdevc) &&
334
(*dev_proc(pdev, pattern_manage))(pdev, gs_no_id, NULL, pattern_manage__shading_area) == 0) {
335
gs_pattern2_instance_t *pinst = (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
337
gs_memory_t *mem = cpath_local->path.memory;
339
gx_path_init_local(&box_path, mem);
340
code = gx_dc_shading_path_add_box(&box_path, pdevc);
341
if (code == gs_error_limitcheck) {
342
/* Ignore huge BBox - bug 689027. */
344
} else if (code >= 0) {
345
code = gx_cpath_intersect(cpath_local, &box_path, gx_rule_winding_number, (gs_imager_state *)pinst->saved);
347
gx_path_free(&box_path, "gx_default_fill_path(path_bbox)");
352
/* Check whether color is a shading with BBox. */
354
gx_dc_pattern2_is_rectangular_cell(const gx_device_color * pdevc, gx_device * pdev, gs_fixed_rect *rect)
356
if (gx_dc_is_pattern2_color(pdevc) && gx_dc_pattern2_color_has_bbox(pdevc) &&
357
(*dev_proc(pdev, pattern_manage))(pdev, gs_no_id, NULL, pattern_manage__shading_area) == 0) {
358
gs_pattern2_instance_t *pinst = (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
359
const gs_shading_t *psh = pinst->template.Shading;
362
if (is_xxyy(&ctm_only(pinst->saved)))
363
if (psh->params.have_BBox) {
364
int code = gs_point_transform2fixed(&pinst->saved->ctm,
365
psh->params.BBox.p.x, psh->params.BBox.p.y, &p);
368
code = gs_point_transform2fixed(&pinst->saved->ctm,
369
psh->params.BBox.q.x, psh->params.BBox.q.y, &q);
373
p.x ^= q.x; q.x ^= p.x; p.x ^= q.x;
376
p.y ^= q.y; q.y ^= p.y; p.y ^= q.y;
387
/* Get a shading color space. */
388
const gs_color_space *
389
gx_dc_pattern2_get_color_space(const gx_device_color * pdevc)
391
gs_pattern2_instance_t *pinst =
392
(gs_pattern2_instance_t *)pdevc->ccolor.pattern;
393
const gs_shading_t *psh = pinst->template.Shading;
395
return psh->params.ColorSpace;
399
/* Check device color for a possibly self-overlapping shading. */
401
gx_dc_pattern2_can_overlap(const gx_device_color *pdevc)
403
gs_pattern2_instance_t * pinst;
405
if (pdevc->type != &gx_dc_pattern2)
407
pinst = (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
408
switch (pinst->template.Shading->head.type) {
409
case 3: case 6: case 7:
416
/* Check whether a pattern color has a background. */
417
bool gx_dc_pattern2_has_background(const gx_device_color *pdevc)
419
gs_pattern2_instance_t * pinst;
420
const gs_shading_t *Shading;
422
if (pdevc->type != &gx_dc_pattern2)
424
pinst = (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
425
Shading = pinst->template.Shading;
426
return !pinst->shfill && Shading->params.Background != NULL;