/src/libspectre/ghostscript/base/gxp1fill.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2020 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 1 filling algorithms */ |
18 | | #include "string_.h" |
19 | | #include "math_.h" |
20 | | #include "gx.h" |
21 | | #include "gserrors.h" |
22 | | #include "gsrop.h" |
23 | | #include "gsmatrix.h" |
24 | | #include "gxcspace.h" /* for gscolor2.h */ |
25 | | #include "gxcolor2.h" |
26 | | #include "gxdcolor.h" |
27 | | #include "gxdevcli.h" |
28 | | #include "gxdevmem.h" |
29 | | #include "gxclip2.h" |
30 | | #include "gxpcolor.h" |
31 | | #include "gxp1impl.h" |
32 | | #include "gxcldev.h" |
33 | | #include "gxblend.h" |
34 | | #include "gsicc_cache.h" |
35 | | #include "gxdevsop.h" |
36 | | |
37 | | #include "gdevp14.h" |
38 | | |
39 | 0 | #define fastfloor(x) (((int)(x)) - (((x)<0) && ((x) != (float)(int)(x)))) |
40 | | |
41 | | /* Define the state for tile filling. */ |
42 | | typedef struct tile_fill_state_s { |
43 | | |
44 | | /* Original arguments */ |
45 | | |
46 | | const gx_device_color *pdevc; /* pattern color */ |
47 | | int x0, y0, w0, h0; |
48 | | gs_logical_operation_t lop; |
49 | | const gx_rop_source_t *source; |
50 | | |
51 | | /* Variables set at initialization */ |
52 | | |
53 | | gx_device_tile_clip *cdev; |
54 | | gx_device *pcdev; /* original device or cdev */ |
55 | | const gx_strip_bitmap *tmask; |
56 | | gs_int_point phase; |
57 | | int num_planes; /* negative if not planar */ |
58 | | |
59 | | |
60 | | /* Following are only for uncolored patterns */ |
61 | | |
62 | | dev_color_proc_fill_rectangle((*fill_rectangle)); |
63 | | |
64 | | /* Following are only for colored patterns */ |
65 | | |
66 | | gx_device *orig_dev; |
67 | | int xoff, yoff; /* set dynamically */ |
68 | | |
69 | | } tile_fill_state_t; |
70 | | |
71 | | /* Define the state for tile filling. |
72 | | This is used for when we have |
73 | | transparency */ |
74 | | typedef struct tile_fill_trans_state_s { |
75 | | |
76 | | /* Original arguments */ |
77 | | |
78 | | const gx_device_color *pdevc; /* pattern color */ |
79 | | int x0, y0, w0, h0; |
80 | | |
81 | | /* Variables set at initialization */ |
82 | | |
83 | | gx_device *pcdev; /* original device or &cdev */ |
84 | | gs_int_point phase; |
85 | | |
86 | | int xoff, yoff; /* set dynamically */ |
87 | | |
88 | | } tile_fill_trans_state_t; |
89 | | |
90 | | /* we need some means of detecting if a forwarding clipping device was |
91 | | installed. If the tile state cdev pointer is non-NULL, then the |
92 | | target output device must be the clipping device. */ |
93 | 0 | #define CLIPDEV_INSTALLED (state.cdev != NULL) |
94 | | |
95 | | /* Initialize the filling state. */ |
96 | | static int |
97 | | tile_fill_init(tile_fill_state_t * ptfs, const gx_device_color * pdevc, |
98 | | gx_device * dev, bool set_mask_phase) |
99 | 0 | { |
100 | 0 | gx_color_tile *m_tile = pdevc->mask.m_tile; |
101 | 0 | int px, py; |
102 | 0 | bool is_planar; |
103 | |
|
104 | 0 | ptfs->pdevc = pdevc; |
105 | 0 | is_planar = dev->is_planar; |
106 | 0 | if (is_planar) { |
107 | 0 | ptfs->num_planes = dev->color_info.num_components; |
108 | 0 | } else { |
109 | 0 | ptfs->num_planes = -1; |
110 | 0 | } |
111 | 0 | if (m_tile == 0) { /* no clipping */ |
112 | 0 | ptfs->cdev = NULL; |
113 | 0 | ptfs->pcdev = dev; |
114 | 0 | ptfs->phase = pdevc->phase; |
115 | 0 | return 0; |
116 | 0 | } |
117 | 0 | if ((ptfs->cdev = (gx_device_tile_clip *)gs_alloc_struct(dev->memory, |
118 | 0 | gx_device_tile_clip, |
119 | 0 | &st_device_tile_clip, |
120 | 0 | "tile_fill_init(cdev)")) == NULL) { |
121 | 0 | return_error(gs_error_VMerror); |
122 | 0 | } |
123 | 0 | ptfs->cdev->finalize = NULL; |
124 | 0 | ptfs->pcdev = (gx_device *)ptfs->cdev; |
125 | 0 | ptfs->tmask = &m_tile->tmask; |
126 | 0 | ptfs->phase.x = pdevc->mask.m_phase.x; |
127 | 0 | ptfs->phase.y = pdevc->mask.m_phase.y; |
128 | | /* |
129 | | * For non-simple tiles, the phase will be reset on each pass of the |
130 | | * tile_by_steps loop, but for simple tiles, we must set it now. |
131 | | */ |
132 | 0 | if (set_mask_phase && m_tile->is_simple) { |
133 | 0 | px = imod(-(int)fastfloor(m_tile->step_matrix.tx - ptfs->phase.x + 0.5), |
134 | 0 | m_tile->tmask.rep_width); |
135 | 0 | py = imod(-(int)fastfloor(m_tile->step_matrix.ty - ptfs->phase.y + 0.5), |
136 | 0 | m_tile->tmask.rep_height); |
137 | 0 | } else |
138 | 0 | px = py = 0; |
139 | 0 | return tile_clip_initialize(ptfs->cdev, ptfs->tmask, dev, px, py); |
140 | 0 | } |
141 | | |
142 | | /* |
143 | | * Fill with non-standard X and Y stepping. |
144 | | * ptile is pdevc->colors.pattern.{m,p}_tile. |
145 | | * tbits_or_tmask is whichever of tbits and tmask is supplying |
146 | | * the tile size. |
147 | | * This implementation could be sped up considerably! |
148 | | */ |
149 | | static int |
150 | | tile_by_steps(tile_fill_state_t * ptfs, int x0, int y0, int w0, int h0, |
151 | | const gx_color_tile * ptile, |
152 | | const gx_strip_bitmap * tbits_or_tmask, |
153 | | int (*fill_proc) (const tile_fill_state_t * ptfs, |
154 | | int x, int y, int w, int h)) |
155 | 0 | { |
156 | 0 | int x1 = x0 + w0, y1 = y0 + h0; |
157 | 0 | int i0, i1, j0, j1, i, j; |
158 | 0 | gs_matrix step_matrix; /* translated by phase */ |
159 | 0 | int code; |
160 | | #ifdef DEBUG |
161 | | const gs_memory_t *mem = ptfs->pcdev->memory; |
162 | | #endif |
163 | |
|
164 | 0 | ptfs->x0 = x0, ptfs->w0 = w0; |
165 | 0 | ptfs->y0 = y0, ptfs->h0 = h0; |
166 | 0 | step_matrix = ptile->step_matrix; |
167 | 0 | step_matrix.tx -= ptfs->phase.x; |
168 | 0 | step_matrix.ty -= ptfs->phase.y; |
169 | 0 | { |
170 | 0 | gs_rect bbox; /* bounding box in device space */ |
171 | 0 | gs_rect ibbox; /* bounding box in stepping space */ |
172 | 0 | double bbw = ptile->bbox.q.x - ptile->bbox.p.x; |
173 | 0 | double bbh = ptile->bbox.q.y - ptile->bbox.p.y; |
174 | 0 | double u0, v0, u1, v1; |
175 | |
|
176 | 0 | bbox.p.x = x0, bbox.p.y = y0; |
177 | 0 | bbox.q.x = x1, bbox.q.y = y1; |
178 | 0 | code = gs_bbox_transform_inverse(&bbox, &step_matrix, &ibbox); |
179 | 0 | if (code < 0) |
180 | 0 | return code; |
181 | 0 | if_debug10m('T', mem, |
182 | 0 | "[T]x,y=(%d,%d) w,h=(%d,%d) => (%g,%g),(%g,%g), offset=(%g,%g)\n", |
183 | 0 | x0, y0, w0, h0, |
184 | 0 | ibbox.p.x, ibbox.p.y, ibbox.q.x, ibbox.q.y, |
185 | 0 | step_matrix.tx, step_matrix.ty); |
186 | | /* |
187 | | * If the pattern is partly transparent and XStep/YStep is smaller |
188 | | * than the device space BBox, we need to ensure that we cover |
189 | | * each pixel of the rectangle being filled with *every* pattern |
190 | | * that overlaps it, not just *some* pattern copy. |
191 | | */ |
192 | 0 | u0 = ibbox.p.x - max(ptile->bbox.p.x, 0) - 0.000001; |
193 | 0 | v0 = ibbox.p.y - max(ptile->bbox.p.y, 0) - 0.000001; |
194 | 0 | u1 = ibbox.q.x - min(ptile->bbox.q.x, 0) + 0.000001; |
195 | 0 | v1 = ibbox.q.y - min(ptile->bbox.q.y, 0) + 0.000001; |
196 | 0 | if (!ptile->is_simple) |
197 | 0 | u0 -= bbw, v0 -= bbh, u1 += bbw, v1 += bbh; |
198 | 0 | i0 = (int)fastfloor(u0); |
199 | 0 | j0 = (int)fastfloor(v0); |
200 | 0 | i1 = (int)ceil(u1); |
201 | 0 | j1 = (int)ceil(v1); |
202 | 0 | } |
203 | 0 | if_debug4m('T', mem, "[T]i=(%d,%d) j=(%d,%d)\n", i0, i1, j0, j1); |
204 | 0 | for (i = i0; i < i1; i++) |
205 | 0 | for (j = j0; j < j1; j++) { |
206 | 0 | int x = (int)fastfloor(step_matrix.xx * i + |
207 | 0 | step_matrix.yx * j + step_matrix.tx); |
208 | 0 | int y = (int)fastfloor(step_matrix.xy * i + |
209 | 0 | step_matrix.yy * j + step_matrix.ty); |
210 | 0 | int w = tbits_or_tmask->size.x; |
211 | 0 | int h = tbits_or_tmask->size.y; |
212 | 0 | int xoff, yoff; |
213 | |
|
214 | 0 | if_debug4m('T', mem, "[T]i=%d j=%d x,y=(%d,%d)", i, j, x, y); |
215 | 0 | if (x < x0) |
216 | 0 | xoff = x0 - x, x = x0, w -= xoff; |
217 | 0 | else |
218 | 0 | xoff = 0; |
219 | 0 | if (y < y0) |
220 | 0 | yoff = y0 - y, y = y0, h -= yoff; |
221 | 0 | else |
222 | 0 | yoff = 0; |
223 | 0 | if (x + w > x1) |
224 | 0 | w = x1 - x; |
225 | 0 | if (y + h > y1) |
226 | 0 | h = y1 - y; |
227 | 0 | if_debug6m('T', mem, "=>(%d,%d) w,h=(%d,%d) x/yoff=(%d,%d)\n", |
228 | 0 | x, y, w, h, xoff, yoff); |
229 | 0 | if (w > 0 && h > 0) { |
230 | 0 | if (ptfs->pcdev == (gx_device *)ptfs->cdev) |
231 | 0 | tile_clip_set_phase(ptfs->cdev, |
232 | 0 | imod(xoff - x, ptfs->tmask->rep_width), |
233 | 0 | imod(yoff - y, ptfs->tmask->rep_height)); |
234 | | /* Set the offsets for colored pattern fills */ |
235 | 0 | ptfs->xoff = xoff; |
236 | 0 | ptfs->yoff = yoff; |
237 | 0 | code = (*fill_proc) (ptfs, x, y, w, h); |
238 | 0 | if (code < 0) |
239 | 0 | return code; |
240 | 0 | } |
241 | 0 | } |
242 | 0 | return 0; |
243 | 0 | } |
244 | | |
245 | | /* Fill a rectangle with a colored Pattern. */ |
246 | | /* Note that we treat this as "texture" for RasterOp. */ |
247 | | static int |
248 | | tile_colored_fill(const tile_fill_state_t * ptfs, |
249 | | int x, int y, int w, int h) |
250 | 0 | { |
251 | 0 | gx_color_tile *ptile = ptfs->pdevc->colors.pattern.p_tile; |
252 | 0 | gs_logical_operation_t lop = ptfs->lop; |
253 | 0 | const gx_rop_source_t *source = ptfs->source; |
254 | 0 | gx_device *dev = ptfs->orig_dev; |
255 | 0 | int xoff = ptfs->xoff, yoff = ptfs->yoff; |
256 | 0 | gx_strip_bitmap *bits = &ptile->tbits; |
257 | 0 | const byte *data = bits->data; |
258 | 0 | bool full_transfer = (w == ptfs->w0 && h == ptfs->h0); |
259 | 0 | int code = 0; |
260 | |
|
261 | 0 | if (source == NULL && lop_no_S_is_T(lop) && dev_proc(dev, copy_planes) != gx_default_copy_planes && |
262 | 0 | ptfs->num_planes > 0) { |
263 | 0 | code = (*dev_proc(ptfs->pcdev, copy_planes)) |
264 | 0 | (ptfs->pcdev, data + bits->raster * yoff, xoff, |
265 | 0 | bits->raster, |
266 | 0 | (full_transfer ? bits->id : gx_no_bitmap_id), |
267 | 0 | x, y, w, h, ptile->tbits.rep_height); |
268 | 0 | } else if (source == NULL && lop_no_S_is_T(lop)) { |
269 | 0 | code = (*dev_proc(ptfs->pcdev, copy_color)) |
270 | 0 | (ptfs->pcdev, data + bits->raster * yoff, xoff, |
271 | 0 | bits->raster, |
272 | 0 | (full_transfer ? bits->id : gx_no_bitmap_id), |
273 | 0 | x, y, w, h); |
274 | 0 | } else { |
275 | 0 | gx_strip_bitmap data_tile; |
276 | 0 | gx_bitmap_id source_id; |
277 | 0 | gx_rop_source_t no_source; |
278 | |
|
279 | 0 | if (source == NULL) |
280 | 0 | set_rop_no_source(source, no_source, dev); |
281 | 0 | source_id = (full_transfer ? source->id : gx_no_bitmap_id); |
282 | 0 | data_tile.data = (byte *) data; /* actually const */ |
283 | 0 | data_tile.raster = bits->raster; |
284 | 0 | data_tile.size.x = data_tile.rep_width = ptile->tbits.size.x; |
285 | 0 | data_tile.size.y = data_tile.rep_height = ptile->tbits.size.y; |
286 | 0 | data_tile.id = bits->id; |
287 | 0 | data_tile.shift = data_tile.rep_shift = 0; |
288 | 0 | data_tile.num_planes = (ptfs->num_planes > 1 ? ptfs->num_planes : 1); |
289 | 0 | if (source->planar_height == 0) { |
290 | 0 | code = (*dev_proc(ptfs->pcdev, strip_copy_rop)) |
291 | 0 | (ptfs->pcdev, |
292 | 0 | source->sdata + (y - ptfs->y0) * source->sraster, |
293 | 0 | source->sourcex + (x - ptfs->x0), |
294 | 0 | source->sraster, source_id, |
295 | 0 | (source->use_scolors ? source->scolors : NULL), |
296 | 0 | &data_tile, NULL, |
297 | 0 | x, y, w, h, |
298 | 0 | imod(xoff - x, data_tile.rep_width), |
299 | 0 | imod(yoff - y, data_tile.rep_height), |
300 | 0 | lop); |
301 | 0 | } else { |
302 | 0 | code = (*dev_proc(ptfs->pcdev, strip_copy_rop2)) |
303 | 0 | (ptfs->pcdev, |
304 | 0 | source->sdata + (y - ptfs->y0) * source->sraster, |
305 | 0 | source->sourcex + (x - ptfs->x0), |
306 | 0 | source->sraster, source_id, |
307 | 0 | (source->use_scolors ? source->scolors : NULL), |
308 | 0 | &data_tile, NULL, |
309 | 0 | x, y, w, h, |
310 | 0 | imod(xoff - x, data_tile.rep_width), |
311 | 0 | imod(yoff - y, data_tile.rep_height), |
312 | 0 | lop, |
313 | 0 | source->planar_height); |
314 | 0 | } |
315 | 0 | } |
316 | 0 | return code; |
317 | 0 | } |
318 | | |
319 | | /* Fill a rectangle with a colored Pattern. */ |
320 | | /* Note that we treat this as "texture" for RasterOp. */ |
321 | | static int |
322 | | tile_pattern_clist(const tile_fill_state_t * ptfs, |
323 | | int x, int y, int w, int h) |
324 | 0 | { |
325 | 0 | gx_color_tile *ptile = ptfs->pdevc->colors.pattern.p_tile; |
326 | 0 | gx_device_clist *cdev = ptile->cdev; |
327 | 0 | gx_device_clist_reader *crdev = (gx_device_clist_reader *)cdev; |
328 | 0 | gx_device *dev = ptfs->orig_dev; |
329 | 0 | int code; |
330 | |
|
331 | 0 | crdev->offset_map = NULL; |
332 | 0 | code = crdev->page_info.io_procs->rewind(crdev->page_info.bfile, false, NULL); |
333 | 0 | if (code < 0) return code; |
334 | 0 | code = crdev->page_info.io_procs->rewind(crdev->page_info.cfile, false, NULL); |
335 | 0 | if (code < 0) return code; |
336 | | |
337 | 0 | clist_render_init(cdev); |
338 | | /* Check for and get ICC profile table */ |
339 | 0 | if (crdev->icc_table == NULL) { |
340 | 0 | code = clist_read_icctable(crdev); |
341 | 0 | if (code < 0) |
342 | 0 | return code; |
343 | 0 | } |
344 | | /* Also allocate the icc cache for the clist reader */ |
345 | 0 | if ( crdev->icc_cache_cl == NULL ) |
346 | 0 | crdev->icc_cache_cl = gsicc_cache_new(crdev->memory->thread_safe_memory); |
347 | 0 | if_debug0m('L', dev->memory, "Pattern clist playback begin\n"); |
348 | 0 | code = clist_playback_file_bands(playback_action_render, |
349 | 0 | crdev, &crdev->page_info, dev, 0, 0, ptfs->xoff - x, ptfs->yoff - y); |
350 | 0 | if_debug0m('L', dev->memory, "Pattern clist playback end\n"); |
351 | | /* FIXME: it would be preferable to have this persist, but as |
352 | | * clist_render_init() sets it to NULL, we currently have to |
353 | | * cleanup before returning. Set to NULL for safety |
354 | | */ |
355 | 0 | rc_decrement(crdev->icc_cache_cl, "tile_pattern_clist"); |
356 | 0 | crdev->icc_cache_cl = NULL; |
357 | 0 | return code; |
358 | 0 | } |
359 | | |
360 | | int |
361 | | gx_dc_pattern_fill_rectangle(const gx_device_color * pdevc, int x, int y, |
362 | | int w, int h, gx_device * dev, |
363 | | gs_logical_operation_t lop, |
364 | | const gx_rop_source_t * source) |
365 | 0 | { |
366 | 0 | gx_color_tile *ptile = pdevc->colors.pattern.p_tile; |
367 | 0 | const gx_rop_source_t *rop_source = source; |
368 | 0 | gx_rop_source_t no_source; |
369 | 0 | gx_strip_bitmap *bits; |
370 | 0 | tile_fill_state_t state; |
371 | 0 | int code; |
372 | |
|
373 | 0 | if (ptile == 0) /* null pattern */ |
374 | 0 | return 0; |
375 | 0 | if (rop_source == NULL) |
376 | 0 | set_rop_no_source(rop_source, no_source, dev); |
377 | 0 | bits = &ptile->tbits; |
378 | |
|
379 | 0 | code = tile_fill_init(&state, pdevc, dev, false); /* This _may_ allocate state.cdev */ |
380 | 0 | if (code < 0) |
381 | 0 | return code; |
382 | 0 | if (ptile->is_simple && ptile->cdev == NULL) { |
383 | 0 | int px = |
384 | 0 | imod(-(int)fastfloor(ptile->step_matrix.tx - state.phase.x + 0.5), |
385 | 0 | bits->rep_width); |
386 | 0 | int py = |
387 | 0 | imod(-(int)fastfloor(ptile->step_matrix.ty - state.phase.y + 0.5), |
388 | 0 | bits->rep_height); |
389 | |
|
390 | 0 | if (CLIPDEV_INSTALLED) |
391 | 0 | tile_clip_set_phase(state.cdev, px, py); |
392 | 0 | if (source == NULL && lop_no_S_is_T(lop)) |
393 | 0 | code = (*dev_proc(state.pcdev, strip_tile_rectangle)) |
394 | 0 | (state.pcdev, bits, x, y, w, h, |
395 | 0 | gx_no_color_index, gx_no_color_index, px, py); |
396 | 0 | else if (rop_source->planar_height == 0) |
397 | 0 | code = (*dev_proc(state.pcdev, strip_copy_rop)) |
398 | 0 | (state.pcdev, |
399 | 0 | rop_source->sdata, rop_source->sourcex, |
400 | 0 | rop_source->sraster, rop_source->id, |
401 | 0 | (rop_source->use_scolors ? rop_source->scolors : NULL), |
402 | 0 | bits, NULL, x, y, w, h, px, py, lop); |
403 | 0 | else |
404 | 0 | code = (*dev_proc(state.pcdev, strip_copy_rop2)) |
405 | 0 | (state.pcdev, |
406 | 0 | rop_source->sdata, rop_source->sourcex, |
407 | 0 | rop_source->sraster, rop_source->id, |
408 | 0 | (rop_source->use_scolors ? rop_source->scolors : NULL), |
409 | 0 | bits, NULL, x, y, w, h, px, py, lop, |
410 | 0 | rop_source->planar_height); |
411 | 0 | } else { |
412 | 0 | state.lop = lop; |
413 | 0 | state.source = source; |
414 | 0 | state.orig_dev = dev; |
415 | 0 | if (ptile->cdev == NULL) { |
416 | 0 | code = tile_by_steps(&state, x, y, w, h, ptile, |
417 | 0 | &ptile->tbits, tile_colored_fill); |
418 | 0 | } else { |
419 | 0 | gx_device_clist *cdev = ptile->cdev; |
420 | 0 | gx_device_clist_reader *crdev = (gx_device_clist_reader *)cdev; |
421 | 0 | gx_strip_bitmap tbits; |
422 | |
|
423 | 0 | crdev->yplane.depth = 0; /* Don't know what to set here. */ |
424 | 0 | crdev->yplane.shift = 0; |
425 | 0 | crdev->yplane.index = -1; |
426 | 0 | crdev->pages = NULL; |
427 | 0 | crdev->num_pages = 1; |
428 | 0 | state.orig_dev = dev; |
429 | 0 | tbits = ptile->tbits; |
430 | 0 | tbits.size.x = crdev->width; |
431 | 0 | tbits.size.y = crdev->height; |
432 | 0 | code = tile_by_steps(&state, x, y, w, h, ptile, |
433 | 0 | &tbits, tile_pattern_clist); |
434 | 0 | } |
435 | 0 | } |
436 | 0 | if (CLIPDEV_INSTALLED) { |
437 | 0 | tile_clip_free((gx_device_tile_clip *)state.cdev); |
438 | 0 | state.cdev = NULL; |
439 | 0 | } |
440 | 0 | return code; |
441 | 0 | } |
442 | | |
443 | | /* Fill a rectangle with an uncolored Pattern. */ |
444 | | /* Note that we treat this as "texture" for RasterOp. */ |
445 | | static int |
446 | | tile_masked_fill(const tile_fill_state_t * ptfs, |
447 | | int x, int y, int w, int h) |
448 | 0 | { |
449 | 0 | if (ptfs->source == NULL) |
450 | 0 | return (*ptfs->fill_rectangle) |
451 | 0 | (ptfs->pdevc, x, y, w, h, ptfs->pcdev, ptfs->lop, NULL); |
452 | 0 | else { |
453 | 0 | const gx_rop_source_t *source = ptfs->source; |
454 | 0 | gx_rop_source_t step_source; |
455 | |
|
456 | 0 | step_source.sdata = source->sdata + (y - ptfs->y0) * source->sraster; |
457 | 0 | step_source.sourcex = source->sourcex + (x - ptfs->x0); |
458 | 0 | step_source.sraster = source->sraster; |
459 | 0 | step_source.id = (w == ptfs->w0 && h == ptfs->h0 ? |
460 | 0 | source->id : gx_no_bitmap_id); |
461 | 0 | step_source.scolors[0] = source->scolors[0]; |
462 | 0 | step_source.scolors[1] = source->scolors[1]; |
463 | 0 | step_source.planar_height = source->planar_height; |
464 | 0 | step_source.use_scolors = source->use_scolors; |
465 | 0 | return (*ptfs->fill_rectangle) |
466 | 0 | (ptfs->pdevc, x, y, w, h, ptfs->pcdev, ptfs->lop, &step_source); |
467 | 0 | } |
468 | 0 | } |
469 | | int |
470 | | gx_dc_pure_masked_fill_rect(const gx_device_color * pdevc, |
471 | | int x, int y, int w, int h, gx_device * dev, |
472 | | gs_logical_operation_t lop, |
473 | | const gx_rop_source_t * source) |
474 | 0 | { |
475 | 0 | gx_color_tile *ptile = pdevc->mask.m_tile; |
476 | 0 | tile_fill_state_t state; |
477 | 0 | int code; |
478 | | |
479 | | /* |
480 | | * This routine should never be called if there is no masking, |
481 | | * but we leave the checks below just in case. |
482 | | */ |
483 | 0 | code = tile_fill_init(&state, pdevc, dev, true); |
484 | 0 | if (code < 0) |
485 | 0 | return code; |
486 | 0 | if (state.pcdev == dev || ptile->is_simple) |
487 | 0 | code = (*gx_dc_type_data_pure.fill_rectangle) |
488 | 0 | (pdevc, x, y, w, h, state.pcdev, lop, source); |
489 | 0 | else { |
490 | 0 | state.lop = lop; |
491 | 0 | state.source = source; |
492 | 0 | state.fill_rectangle = gx_dc_type_data_pure.fill_rectangle; |
493 | 0 | code = tile_by_steps(&state, x, y, w, h, ptile, &ptile->tmask, |
494 | 0 | tile_masked_fill); |
495 | 0 | } |
496 | 0 | if (CLIPDEV_INSTALLED) { |
497 | 0 | tile_clip_free((gx_device_tile_clip *)state.cdev); |
498 | 0 | state.cdev = NULL; |
499 | 0 | } |
500 | 0 | return code; |
501 | 0 | } |
502 | | |
503 | | int |
504 | | gx_dc_devn_masked_fill_rect(const gx_device_color * pdevc, |
505 | | int x, int y, int w, int h, gx_device * dev, |
506 | | gs_logical_operation_t lop, |
507 | | const gx_rop_source_t * source) |
508 | 0 | { |
509 | 0 | gx_color_tile *ptile = pdevc->mask.m_tile; |
510 | 0 | tile_fill_state_t state; |
511 | 0 | int code; |
512 | | |
513 | | /* |
514 | | * This routine should never be called if there is no masking, |
515 | | * but we leave the checks below just in case. |
516 | | */ |
517 | 0 | code = tile_fill_init(&state, pdevc, dev, true); |
518 | 0 | if (code < 0) |
519 | 0 | return code; |
520 | 0 | if (state.pcdev == dev || ptile->is_simple) { |
521 | 0 | gx_device_color dcolor = *pdevc; |
522 | |
|
523 | 0 | if (ptile == NULL) { |
524 | 0 | int k; |
525 | | |
526 | | /* Have to set the pdevc to a non mask type since the pattern was stored as non-masking */ |
527 | 0 | dcolor.type = gx_dc_type_devn; |
528 | 0 | for (k = 0; k < GS_CLIENT_COLOR_MAX_COMPONENTS; k++) { |
529 | 0 | dcolor.colors.devn.values[k] = pdevc->colors.devn.values[k]; |
530 | 0 | } |
531 | 0 | } |
532 | 0 | code = (*gx_dc_type_data_devn.fill_rectangle) |
533 | 0 | (&dcolor, x, y, w, h, state.pcdev, lop, source); |
534 | 0 | } else { |
535 | 0 | state.lop = lop; |
536 | 0 | state.source = source; |
537 | 0 | state.fill_rectangle = gx_dc_type_data_devn.fill_rectangle; |
538 | 0 | code = tile_by_steps(&state, x, y, w, h, ptile, &ptile->tmask, |
539 | 0 | tile_masked_fill); |
540 | 0 | } |
541 | 0 | if (CLIPDEV_INSTALLED) { |
542 | 0 | tile_clip_free((gx_device_tile_clip *)state.cdev); |
543 | 0 | state.cdev = NULL; |
544 | 0 | } |
545 | 0 | return code; |
546 | 0 | } |
547 | | |
548 | | int |
549 | | gx_dc_binary_masked_fill_rect(const gx_device_color * pdevc, |
550 | | int x, int y, int w, int h, gx_device * dev, |
551 | | gs_logical_operation_t lop, |
552 | | const gx_rop_source_t * source) |
553 | 0 | { |
554 | 0 | gx_color_tile *ptile = pdevc->mask.m_tile; |
555 | 0 | tile_fill_state_t state; |
556 | 0 | int code; |
557 | |
|
558 | 0 | code = tile_fill_init(&state, pdevc, dev, true); |
559 | 0 | if (code < 0) |
560 | 0 | return code; |
561 | 0 | if (state.pcdev == dev || ptile->is_simple) |
562 | 0 | code = (*gx_dc_type_data_ht_binary.fill_rectangle) |
563 | 0 | (pdevc, x, y, w, h, state.pcdev, lop, source); |
564 | 0 | else { |
565 | 0 | state.lop = lop; |
566 | 0 | state.source = source; |
567 | 0 | state.fill_rectangle = gx_dc_type_data_ht_binary.fill_rectangle; |
568 | 0 | code = tile_by_steps(&state, x, y, w, h, ptile, &ptile->tmask, |
569 | 0 | tile_masked_fill); |
570 | 0 | } |
571 | 0 | if (CLIPDEV_INSTALLED) { |
572 | 0 | tile_clip_free((gx_device_tile_clip *)state.cdev); |
573 | 0 | state.cdev = NULL; |
574 | 0 | } |
575 | 0 | return code; |
576 | 0 | } |
577 | | |
578 | | int |
579 | | gx_dc_colored_masked_fill_rect(const gx_device_color * pdevc, |
580 | | int x, int y, int w, int h, gx_device * dev, |
581 | | gs_logical_operation_t lop, |
582 | | const gx_rop_source_t * source) |
583 | 0 | { |
584 | 0 | gx_color_tile *ptile = pdevc->mask.m_tile; |
585 | 0 | tile_fill_state_t state; |
586 | 0 | int code; |
587 | |
|
588 | 0 | code = tile_fill_init(&state, pdevc, dev, true); |
589 | 0 | if (code < 0) |
590 | 0 | return code; |
591 | 0 | if (state.pcdev == dev || ptile->is_simple) |
592 | 0 | code = (*gx_dc_type_data_ht_colored.fill_rectangle) |
593 | 0 | (pdevc, x, y, w, h, state.pcdev, lop, source); |
594 | 0 | else { |
595 | 0 | state.lop = lop; |
596 | 0 | state.source = source; |
597 | 0 | state.fill_rectangle = gx_dc_type_data_ht_colored.fill_rectangle; |
598 | 0 | code = tile_by_steps(&state, x, y, w, h, ptile, &ptile->tmask, |
599 | 0 | tile_masked_fill); |
600 | 0 | } |
601 | 0 | if (CLIPDEV_INSTALLED) { |
602 | 0 | tile_clip_free((gx_device_tile_clip *)state.cdev); |
603 | 0 | state.cdev = NULL; |
604 | 0 | } |
605 | 0 | return code; |
606 | 0 | } |
607 | | |
608 | | /* |
609 | | * This is somewhat a clone of the tile_by_steps function but one |
610 | | * that performs filling from and to pdf14dev (transparency) buffers. |
611 | | * At some point it may be desirable to do some optimization here. |
612 | | */ |
613 | | static int |
614 | | tile_by_steps_trans(tile_fill_trans_state_t * ptfs, int x0, int y0, int w0, int h0, |
615 | | gx_pattern_trans_t *fill_trans_buffer, const gx_color_tile * ptile, |
616 | | int native16) |
617 | 0 | { |
618 | 0 | int x1 = x0 + w0, y1 = y0 + h0; |
619 | 0 | int i0, i1, j0, j1, i, j; |
620 | 0 | gs_matrix step_matrix; /* translated by phase */ |
621 | 0 | gx_pattern_trans_t *ptrans_pat = ptile->ttrans; |
622 | | #ifdef DEBUG |
623 | | const gs_memory_t *mem = ptile->ttrans->mem; |
624 | | #endif |
625 | 0 | int code; |
626 | |
|
627 | 0 | ptfs->x0 = x0, ptfs->w0 = w0; |
628 | 0 | ptfs->y0 = y0, ptfs->h0 = h0; |
629 | 0 | step_matrix = ptile->step_matrix; |
630 | 0 | step_matrix.tx -= ptfs->phase.x; |
631 | 0 | step_matrix.ty -= ptfs->phase.y; |
632 | 0 | { |
633 | 0 | gs_rect bbox; /* bounding box in device space */ |
634 | 0 | gs_rect ibbox; /* bounding box in stepping space */ |
635 | 0 | double bbw = ptile->bbox.q.x - ptile->bbox.p.x; |
636 | 0 | double bbh = ptile->bbox.q.y - ptile->bbox.p.y; |
637 | 0 | double u0, v0, u1, v1; |
638 | |
|
639 | 0 | bbox.p.x = x0, bbox.p.y = y0; |
640 | 0 | bbox.q.x = x1, bbox.q.y = y1; |
641 | 0 | code = gs_bbox_transform_inverse(&bbox, &step_matrix, &ibbox); |
642 | 0 | if (code < 0) |
643 | 0 | return code; |
644 | 0 | if_debug10m('T', mem, |
645 | 0 | "[T]x,y=(%d,%d) w,h=(%d,%d) => (%g,%g),(%g,%g), offset=(%g,%g)\n", |
646 | 0 | x0, y0, w0, h0, |
647 | 0 | ibbox.p.x, ibbox.p.y, ibbox.q.x, ibbox.q.y, |
648 | 0 | step_matrix.tx, step_matrix.ty); |
649 | | /* |
650 | | * If the pattern is partly transparent and XStep/YStep is smaller |
651 | | * than the device space BBox, we need to ensure that we cover |
652 | | * each pixel of the rectangle being filled with *every* pattern |
653 | | * that overlaps it, not just *some* pattern copy. |
654 | | */ |
655 | 0 | u0 = ibbox.p.x - max(ptile->bbox.p.x, 0) - 0.000001; |
656 | 0 | v0 = ibbox.p.y - max(ptile->bbox.p.y, 0) - 0.000001; |
657 | 0 | u1 = ibbox.q.x - min(ptile->bbox.q.x, 0) + 0.000001; |
658 | 0 | v1 = ibbox.q.y - min(ptile->bbox.q.y, 0) + 0.000001; |
659 | 0 | if (!ptile->is_simple) |
660 | 0 | u0 -= bbw, v0 -= bbh, u1 += bbw, v1 += bbh; |
661 | 0 | i0 = (int)fastfloor(u0); |
662 | 0 | j0 = (int)fastfloor(v0); |
663 | 0 | i1 = (int)ceil(u1); |
664 | 0 | j1 = (int)ceil(v1); |
665 | 0 | } |
666 | 0 | if_debug4m('T', mem, "[T]i=(%d,%d) j=(%d,%d)\n", i0, i1, j0, j1); |
667 | 0 | for (i = i0; i < i1; i++) |
668 | 0 | for (j = j0; j < j1; j++) { |
669 | 0 | int x = (int)fastfloor(step_matrix.xx * i + |
670 | 0 | step_matrix.yx * j + step_matrix.tx); |
671 | 0 | int y = (int)fastfloor(step_matrix.xy * i + |
672 | 0 | step_matrix.yy * j + step_matrix.ty); |
673 | 0 | int w = ptrans_pat->width; |
674 | 0 | int h = ptrans_pat->height; |
675 | 0 | int xoff, yoff; |
676 | 0 | int px, py; |
677 | |
|
678 | 0 | if_debug4m('T', mem, "[T]i=%d j=%d x,y=(%d,%d)", i, j, x, y); |
679 | 0 | if (x < x0) |
680 | 0 | xoff = x0 - x, x = x0, w -= xoff; |
681 | 0 | else |
682 | 0 | xoff = 0; |
683 | 0 | if (y < y0) |
684 | 0 | yoff = y0 - y, y = y0, h -= yoff; |
685 | 0 | else |
686 | 0 | yoff = 0; |
687 | 0 | if (x + w > x1) |
688 | 0 | w = x1 - x; |
689 | 0 | if (y + h > y1) |
690 | 0 | h = y1 - y; |
691 | 0 | if_debug6m('T', mem, "=>(%d,%d) w,h=(%d,%d) x/yoff=(%d,%d)\n", |
692 | 0 | x, y, w, h, xoff, yoff); |
693 | 0 | if (w > 0 && h > 0) { |
694 | |
|
695 | 0 | px = imod(xoff - x, ptile->ttrans->width); |
696 | 0 | py = imod(yoff - y, ptile->ttrans->height); |
697 | | |
698 | | /* Set the offsets for colored pattern fills */ |
699 | 0 | ptfs->xoff = xoff; |
700 | 0 | ptfs->yoff = yoff; |
701 | | |
702 | | /* We only go through blending during tiling, if there was overlap |
703 | | as defined by the step matrix and the bounding box. |
704 | | Ignore if the area is outside the fill_trans_buffer.rect (bug 700719) */ |
705 | 0 | if (x > fill_trans_buffer->rect.q.x || x+w < 0 || |
706 | 0 | y > fill_trans_buffer->rect.q.y || y+h < 0) |
707 | 0 | continue; /* skip the fill (can breakpoint here) */ |
708 | 0 | ptile->ttrans->pat_trans_fill(x, y, x+w, y+h, px, py, ptile, |
709 | 0 | fill_trans_buffer, native16); |
710 | 0 | } |
711 | 0 | } |
712 | 0 | return 0; |
713 | 0 | } |
714 | | |
715 | | static void |
716 | | be_rev_cpy(uint16_t *dst,const uint16_t *src,int n) |
717 | 0 | { |
718 | 0 | for (; n != 0; n--) { |
719 | 0 | uint16_t in = *src++; |
720 | 0 | ((byte *)dst)[0] = in>>8; |
721 | 0 | ((byte *)dst)[1] = in; |
722 | 0 | dst++; |
723 | 0 | } |
724 | 0 | } |
725 | | |
726 | | /* This does the case of tiling with simple tiles. Since it is not commented |
727 | | * anywhere note that simple means that the tile size is the same as the step |
728 | | * matrix size and the cross terms in the step matrix are 0. Hence a simple |
729 | | * case of tile replication. This needs to be optimized. */ |
730 | | /* Our source tile runs (conceptually) from (0,0) to |
731 | | * (ptile->ttrans->width, ptile->ttrans->height). In practise, only a limited |
732 | | * section of this (ptile->rect) may actually be used. */ |
733 | | void |
734 | | tile_rect_trans_simple(int xmin, int ymin, int xmax, int ymax, |
735 | | int px, int py, const gx_color_tile *ptile, |
736 | | gx_pattern_trans_t *fill_trans_buffer, |
737 | | int native16) |
738 | 0 | { |
739 | 0 | int kk, jj, ii, h, w; |
740 | 0 | int buff_out_y_offset, buff_out_x_offset; |
741 | 0 | unsigned char *ptr_out, *ptr_in, *buff_out, *buff_in, *ptr_out_temp; |
742 | 0 | unsigned char *row_ptr; |
743 | 0 | int in_row_offset; |
744 | 0 | int dx, dy; |
745 | 0 | int left_rem_end, left_width, num_full_tiles, right_tile_width; |
746 | 0 | int left_copy_rem_end, left_copy_width, left_copy_offset, left_copy_start; |
747 | 0 | int mid_copy_width, right_copy_width; |
748 | 0 | int tile_width = ptile->ttrans->width; |
749 | 0 | int tile_height = ptile->ttrans->height; |
750 | 0 | int src_planes = fill_trans_buffer->n_chan + (fill_trans_buffer->has_tags ? 1 : 0); |
751 | 0 | pdf14_buf *buf = fill_trans_buffer->buf; |
752 | 0 | bool deep = fill_trans_buffer->deep; |
753 | | |
754 | | /* Update the bbox in the topmost stack entry to reflect the fact that we |
755 | | * have drawn into it. FIXME: This makes the groups too large! */ |
756 | 0 | if (buf->dirty.p.x > xmin) |
757 | 0 | buf->dirty.p.x = xmin; |
758 | 0 | if (buf->dirty.p.y > ymin) |
759 | 0 | buf->dirty.p.y = ymin; |
760 | 0 | if (buf->dirty.q.x < xmax) |
761 | 0 | buf->dirty.q.x = xmax; |
762 | 0 | if (buf->dirty.q.y < ymax) |
763 | 0 | buf->dirty.q.y = ymax; |
764 | 0 | buff_out_y_offset = ymin - fill_trans_buffer->rect.p.y; |
765 | 0 | buff_out_x_offset = xmin - fill_trans_buffer->rect.p.x; |
766 | |
|
767 | 0 | buff_out = fill_trans_buffer->transbytes + |
768 | 0 | buff_out_y_offset * fill_trans_buffer->rowstride + |
769 | 0 | (buff_out_x_offset<<deep); |
770 | |
|
771 | 0 | buff_in = ptile->ttrans->transbytes; |
772 | |
|
773 | 0 | h = ymax - ymin; |
774 | 0 | w = xmax - xmin; |
775 | |
|
776 | 0 | if (h <= 0 || w <= 0) return; |
777 | | |
778 | | /* Calc dx, dy within the entire (conceptual) input tile. */ |
779 | 0 | dx = (xmin + px) % tile_width; |
780 | 0 | dy = (ymin + py) % tile_height; |
781 | | |
782 | | /* To speed this up, the inner loop on the width is implemented with |
783 | | * memcpys where we have a left remainder, full tiles and a right |
784 | | * remainder. Depending upon the rect that we are filling we may have |
785 | | * only one of these three portions, or two or all three. We compute |
786 | | * the parts now outside the loops. */ |
787 | | |
788 | | /* Left remainder part */ |
789 | 0 | left_rem_end = min(dx+w,tile_width); |
790 | 0 | left_width = left_rem_end - dx; |
791 | 0 | left_copy_start = max(dx,ptile->ttrans->rect.p.x); |
792 | 0 | left_copy_rem_end = min(dx+w,ptile->ttrans->rect.q.x); |
793 | 0 | left_copy_width = left_copy_rem_end - left_copy_start; |
794 | 0 | if (left_copy_width < 0) |
795 | 0 | left_copy_width = 0; |
796 | 0 | left_copy_offset = (left_copy_start-ptile->ttrans->rect.p.x)<<deep; |
797 | | |
798 | | /* Now the middle part */ |
799 | 0 | num_full_tiles = (int)fastfloor((float) (w - left_width)/ (float) tile_width); |
800 | 0 | mid_copy_width = ptile->ttrans->rect.q.x - ptile->ttrans->rect.p.x; |
801 | | |
802 | | /* Now the right part */ |
803 | 0 | right_tile_width = w - num_full_tiles*tile_width - left_width; |
804 | 0 | right_copy_width = right_tile_width - ptile->ttrans->rect.p.x; |
805 | 0 | if (right_copy_width > ptile->ttrans->rect.q.x) |
806 | 0 | right_copy_width = ptile->ttrans->rect.q.x; |
807 | 0 | right_copy_width -= ptile->ttrans->rect.p.x; |
808 | 0 | if (right_copy_width < 0) |
809 | 0 | right_copy_width = 0; |
810 | |
|
811 | 0 | if (deep && native16) { |
812 | | /* fill_trans_buffer is in native endian. ptile is in big endian. */ |
813 | | /* Convert as we copy. */ |
814 | 0 | for (kk = 0; kk < src_planes; kk++) { |
815 | |
|
816 | 0 | ptr_out = buff_out + kk * fill_trans_buffer->planestride; |
817 | 0 | ptr_in = buff_in + kk * ptile->ttrans->planestride; |
818 | 0 | if (fill_trans_buffer->has_shape && kk == fill_trans_buffer->n_chan) |
819 | 0 | ptr_out += fill_trans_buffer->planestride; /* tag plane follows shape plane */ |
820 | |
|
821 | 0 | for (jj = 0; jj < h; jj++, ptr_out += fill_trans_buffer->rowstride) { |
822 | |
|
823 | 0 | in_row_offset = ((jj + dy) % ptile->ttrans->height); |
824 | 0 | if (in_row_offset >= ptile->ttrans->rect.q.y) |
825 | 0 | continue; |
826 | 0 | in_row_offset -= ptile->ttrans->rect.p.y; |
827 | 0 | if (in_row_offset < 0) |
828 | 0 | continue; |
829 | 0 | row_ptr = ptr_in + in_row_offset * ptile->ttrans->rowstride; |
830 | | |
831 | | /* This is the case when we have no blending. */ |
832 | 0 | ptr_out_temp = ptr_out; |
833 | | |
834 | | /* Left part */ |
835 | 0 | be_rev_cpy((uint16_t *)ptr_out_temp, (uint16_t *)(row_ptr + left_copy_offset), left_copy_width); |
836 | 0 | ptr_out_temp += left_width<<deep; |
837 | | |
838 | | /* Now the full tiles */ |
839 | |
|
840 | 0 | for ( ii = 0; ii < num_full_tiles; ii++){ |
841 | 0 | be_rev_cpy((uint16_t *)ptr_out_temp, (uint16_t *)row_ptr, mid_copy_width); |
842 | 0 | ptr_out_temp += tile_width<<deep; |
843 | 0 | } |
844 | | |
845 | | /* Now the remainder */ |
846 | 0 | be_rev_cpy((uint16_t *)ptr_out_temp, (uint16_t *)row_ptr, right_copy_width); |
847 | 0 | } |
848 | 0 | } |
849 | 0 | } else { |
850 | 0 | for (kk = 0; kk < src_planes; kk++) { |
851 | |
|
852 | 0 | ptr_out = buff_out + kk * fill_trans_buffer->planestride; |
853 | 0 | ptr_in = buff_in + kk * ptile->ttrans->planestride; |
854 | 0 | if (fill_trans_buffer->has_shape && kk == fill_trans_buffer->n_chan) |
855 | 0 | ptr_out += fill_trans_buffer->planestride; /* tag plane follows shape plane */ |
856 | |
|
857 | 0 | for (jj = 0; jj < h; jj++, ptr_out += fill_trans_buffer->rowstride) { |
858 | |
|
859 | 0 | in_row_offset = ((jj + dy) % ptile->ttrans->height); |
860 | 0 | if (in_row_offset >= ptile->ttrans->rect.q.y) |
861 | 0 | continue; |
862 | 0 | in_row_offset -= ptile->ttrans->rect.p.y; |
863 | 0 | if (in_row_offset < 0) |
864 | 0 | continue; |
865 | 0 | row_ptr = ptr_in + in_row_offset * ptile->ttrans->rowstride; |
866 | | |
867 | | /* This is the case when we have no blending. */ |
868 | 0 | ptr_out_temp = ptr_out; |
869 | | |
870 | | /* Left part */ |
871 | 0 | memcpy( ptr_out_temp, row_ptr + left_copy_offset, left_copy_width<<deep); |
872 | 0 | ptr_out_temp += left_width<<deep; |
873 | | |
874 | | /* Now the full tiles */ |
875 | |
|
876 | 0 | for ( ii = 0; ii < num_full_tiles; ii++){ |
877 | 0 | memcpy( ptr_out_temp, row_ptr, mid_copy_width<<deep); |
878 | 0 | ptr_out_temp += tile_width<<deep; |
879 | 0 | } |
880 | | |
881 | | /* Now the remainder */ |
882 | 0 | memcpy( ptr_out_temp, row_ptr, right_copy_width<<deep); |
883 | 0 | } |
884 | 0 | } |
885 | 0 | } |
886 | | |
887 | | /* If the group we are filling has a shape plane fill that now */ |
888 | | /* Note: Since this was a virgin group push we can just blast it with |
889 | | * 255 */ |
890 | 0 | if (fill_trans_buffer->has_shape) { |
891 | 0 | ptr_out = buff_out + fill_trans_buffer->n_chan * fill_trans_buffer->planestride; |
892 | 0 | for (jj = 0; jj < h; jj++,ptr_out += fill_trans_buffer->rowstride) { |
893 | 0 | memset(ptr_out, 255, w<<deep); |
894 | 0 | } |
895 | 0 | } |
896 | 0 | } |
897 | | |
898 | | /* This does the case of tiling with non simple tiles. In this case, the |
899 | | * tiles may overlap and so we really need to do blending within the existing |
900 | | * buffer. This needs some serious optimization. */ |
901 | | static void |
902 | | do_tile_rect_trans_blend(int xmin, int ymin, int xmax, int ymax, |
903 | | int px, int py, const gx_color_tile *ptile, |
904 | | gx_pattern_trans_t *fill_trans_buffer) |
905 | 0 | { |
906 | 0 | int kk, jj, ii, h, w; |
907 | 0 | int buff_out_y_offset, buff_out_x_offset; |
908 | 0 | unsigned char *buff_out, *buff_in; |
909 | 0 | unsigned char *buff_ptr, *row_ptr_in, *row_ptr_out; |
910 | 0 | unsigned char *tile_ptr; |
911 | 0 | int in_row_offset; |
912 | 0 | int dx, dy; |
913 | 0 | byte src[PDF14_MAX_PLANES]; |
914 | 0 | byte dst[PDF14_MAX_PLANES]; |
915 | 0 | int tile_width = ptile->ttrans->width; |
916 | 0 | int tile_height = ptile->ttrans->height; |
917 | 0 | int num_chan = ptile->ttrans->n_chan; /* Includes alpha */ |
918 | 0 | int tag_offset = fill_trans_buffer->n_chan + (fill_trans_buffer->has_shape ? 1 : 0); |
919 | 0 | pdf14_device *p14dev = (pdf14_device *) fill_trans_buffer->pdev14; |
920 | |
|
921 | 0 | if (fill_trans_buffer->has_tags == 0) |
922 | 0 | tag_offset = 0; |
923 | |
|
924 | 0 | buff_out_y_offset = ymin - fill_trans_buffer->rect.p.y; |
925 | 0 | buff_out_x_offset = xmin - fill_trans_buffer->rect.p.x; |
926 | |
|
927 | 0 | h = ymax - ymin; |
928 | 0 | w = xmax - xmin; |
929 | |
|
930 | 0 | if (h <= 0 || w <= 0) return; |
931 | | |
932 | | /* Calc dx, dy within the entire (conceptual) input tile. */ |
933 | 0 | dx = (xmin + px) % tile_width; |
934 | 0 | dy = (ymin + py) % tile_height; |
935 | |
|
936 | 0 | buff_out = fill_trans_buffer->transbytes + |
937 | 0 | buff_out_y_offset * fill_trans_buffer->rowstride + |
938 | 0 | buff_out_x_offset; |
939 | |
|
940 | 0 | buff_in = ptile->ttrans->transbytes; |
941 | |
|
942 | 0 | for (jj = 0; jj < h; jj++){ |
943 | |
|
944 | 0 | in_row_offset = (jj + dy) % ptile->ttrans->height; |
945 | 0 | if (in_row_offset >= ptile->ttrans->rect.q.y) |
946 | 0 | continue; |
947 | 0 | in_row_offset -= ptile->ttrans->rect.p.y; |
948 | 0 | if (in_row_offset < 0) |
949 | 0 | continue; |
950 | 0 | row_ptr_in = buff_in + in_row_offset * ptile->ttrans->rowstride; |
951 | |
|
952 | 0 | row_ptr_out = buff_out + jj * fill_trans_buffer->rowstride; |
953 | |
|
954 | 0 | for (ii = 0; ii < w; ii++) { |
955 | 0 | int x_in_offset = (dx + ii) % ptile->ttrans->width; |
956 | |
|
957 | 0 | if (x_in_offset >= ptile->ttrans->rect.q.x) |
958 | 0 | continue; |
959 | 0 | x_in_offset -= ptile->ttrans->rect.p.x; |
960 | 0 | if (x_in_offset < 0) |
961 | 0 | continue; |
962 | 0 | tile_ptr = row_ptr_in + x_in_offset; |
963 | 0 | buff_ptr = row_ptr_out + ii; |
964 | | |
965 | | /* We need to blend here. The blending mode from the current |
966 | | imager state is used. |
967 | | */ |
968 | | |
969 | | /* The color values. This needs to be optimized */ |
970 | 0 | for (kk = 0; kk < num_chan; kk++) { |
971 | 0 | dst[kk] = *(buff_ptr + kk * fill_trans_buffer->planestride); |
972 | 0 | src[kk] = *(tile_ptr + kk * ptile->ttrans->planestride); |
973 | 0 | } |
974 | | |
975 | | /* Blend */ |
976 | 0 | art_pdf_composite_pixel_alpha_8(dst, src, ptile->ttrans->n_chan-1, |
977 | 0 | ptile->blending_mode, ptile->ttrans->n_chan-1, |
978 | 0 | ptile->ttrans->blending_procs, p14dev); |
979 | | |
980 | | /* Store the color values */ |
981 | 0 | for (kk = 0; kk < num_chan; kk++) { |
982 | 0 | *(buff_ptr + kk * fill_trans_buffer->planestride) = dst[kk]; |
983 | 0 | } |
984 | | /* Now handle the blending of the tag. NB: dst tag_offset follows shape */ |
985 | 0 | if (tag_offset > 0) { |
986 | 0 | int src_tag = *(tile_ptr + num_chan * ptile->ttrans->planestride); |
987 | 0 | int dst_tag = *(buff_ptr + tag_offset * fill_trans_buffer->planestride); |
988 | |
|
989 | 0 | dst_tag |= src_tag; /* simple blend combines tags */ |
990 | 0 | *(buff_ptr + tag_offset * fill_trans_buffer->planestride) = dst_tag; |
991 | 0 | } |
992 | 0 | } |
993 | 0 | } |
994 | | |
995 | | /* If the group we are filling has a shape plane fill that now */ |
996 | | /* Note: Since this was a virgin group push we can just blast it with |
997 | | * 255 */ |
998 | 0 | if (fill_trans_buffer->has_shape) { |
999 | 0 | buff_ptr = buff_out + fill_trans_buffer->n_chan * fill_trans_buffer->planestride; |
1000 | |
|
1001 | 0 | for (jj = 0; jj < h; jj++) { |
1002 | 0 | memset(buff_ptr, 255, w); |
1003 | 0 | buff_ptr += fill_trans_buffer->rowstride; |
1004 | 0 | } |
1005 | 0 | } |
1006 | 0 | } |
1007 | | |
1008 | | /* In this version, source data is big endian, dest is native endian */ |
1009 | | static void |
1010 | | do_tile_rect_trans_blend_16(int xmin, int ymin, int xmax, int ymax, |
1011 | | int px, int py, const gx_color_tile *ptile, |
1012 | | gx_pattern_trans_t *fill_trans_buffer) |
1013 | 0 | { |
1014 | 0 | int kk, jj, ii, h, w; |
1015 | 0 | int buff_out_y_offset, buff_out_x_offset; |
1016 | 0 | uint16_t *buff_out, *buff_in; |
1017 | 0 | uint16_t *buff_ptr, *row_ptr_in, *row_ptr_out; |
1018 | 0 | uint16_t *tile_ptr; |
1019 | 0 | int in_row_offset; |
1020 | 0 | int dx, dy; |
1021 | 0 | uint16_t src[PDF14_MAX_PLANES]; |
1022 | 0 | uint16_t dst[PDF14_MAX_PLANES]; |
1023 | 0 | int tile_width = ptile->ttrans->width; |
1024 | 0 | int tile_height = ptile->ttrans->height; |
1025 | 0 | int num_chan = ptile->ttrans->n_chan; /* Includes alpha */ |
1026 | 0 | int tag_offset = fill_trans_buffer->n_chan + (fill_trans_buffer->has_shape ? 1 : 0); |
1027 | 0 | pdf14_device *p14dev = (pdf14_device *) fill_trans_buffer->pdev14; |
1028 | |
|
1029 | 0 | if (fill_trans_buffer->has_tags == 0) |
1030 | 0 | tag_offset = 0; |
1031 | |
|
1032 | 0 | buff_out_y_offset = ymin - fill_trans_buffer->rect.p.y; |
1033 | 0 | buff_out_x_offset = xmin - fill_trans_buffer->rect.p.x; |
1034 | |
|
1035 | 0 | h = ymax - ymin; |
1036 | 0 | w = xmax - xmin; |
1037 | |
|
1038 | 0 | if (h <= 0 || w <= 0) return; |
1039 | | |
1040 | | /* Calc dx, dy within the entire (conceptual) input tile. */ |
1041 | 0 | dx = (xmin + px) % tile_width; |
1042 | 0 | dy = (ymin + py) % tile_height; |
1043 | |
|
1044 | 0 | buff_out = (uint16_t *)(void *)(fill_trans_buffer->transbytes + |
1045 | 0 | buff_out_y_offset * fill_trans_buffer->rowstride + |
1046 | 0 | buff_out_x_offset*2); |
1047 | |
|
1048 | 0 | buff_in = (uint16_t *)(void *)ptile->ttrans->transbytes; |
1049 | |
|
1050 | 0 | for (jj = 0; jj < h; jj++){ |
1051 | |
|
1052 | 0 | in_row_offset = (jj + dy) % ptile->ttrans->height; |
1053 | 0 | if (in_row_offset >= ptile->ttrans->rect.q.y) |
1054 | 0 | continue; |
1055 | 0 | in_row_offset -= ptile->ttrans->rect.p.y; |
1056 | 0 | if (in_row_offset < 0) |
1057 | 0 | continue; |
1058 | 0 | row_ptr_in = buff_in + in_row_offset * (ptile->ttrans->rowstride>>1); |
1059 | |
|
1060 | 0 | row_ptr_out = buff_out + jj * (fill_trans_buffer->rowstride>>1); |
1061 | |
|
1062 | 0 | for (ii = 0; ii < w; ii++) { |
1063 | 0 | int x_in_offset = (dx + ii) % ptile->ttrans->width; |
1064 | |
|
1065 | 0 | if (x_in_offset >= ptile->ttrans->rect.q.x) |
1066 | 0 | continue; |
1067 | 0 | x_in_offset -= ptile->ttrans->rect.p.x; |
1068 | 0 | if (x_in_offset < 0) |
1069 | 0 | continue; |
1070 | 0 | tile_ptr = row_ptr_in + x_in_offset; |
1071 | 0 | buff_ptr = row_ptr_out + ii; |
1072 | | |
1073 | | /* We need to blend here. The blending mode from the current |
1074 | | imager state is used. |
1075 | | */ |
1076 | | |
1077 | | /* Data is stored in big endian, but must be processed in native */ |
1078 | 0 | #define GET16_BE2NATIVE(v) \ |
1079 | 0 | ((((byte *)(v))[0]<<8) | (((byte *)(v))[1])) |
1080 | | |
1081 | | /* The color values. This needs to be optimized */ |
1082 | 0 | for (kk = 0; kk < num_chan; kk++) { |
1083 | 0 | dst[kk] = *(buff_ptr + kk * (fill_trans_buffer->planestride>>1)); |
1084 | 0 | src[kk] = GET16_BE2NATIVE(tile_ptr + kk * (ptile->ttrans->planestride>>1)); |
1085 | 0 | } |
1086 | | |
1087 | | /* Blend */ |
1088 | 0 | art_pdf_composite_pixel_alpha_16(dst, src, ptile->ttrans->n_chan-1, |
1089 | 0 | ptile->blending_mode, ptile->ttrans->n_chan-1, |
1090 | 0 | ptile->ttrans->blending_procs, p14dev); |
1091 | | |
1092 | | /* Store the color values */ |
1093 | 0 | for (kk = 0; kk < num_chan; kk++) { |
1094 | 0 | *(buff_ptr + kk * (fill_trans_buffer->planestride>>1)) = dst[kk]; |
1095 | 0 | } |
1096 | | /* Now handle the blending of the tag. NB: dst tag_offset follows shape */ |
1097 | 0 | if (tag_offset > 0) { |
1098 | 0 | int src_tag = GET16_BE2NATIVE(tile_ptr + (num_chan * ptile->ttrans->planestride>>1)); |
1099 | 0 | int dst_tag = *(buff_ptr + (tag_offset * fill_trans_buffer->planestride>>1)); |
1100 | |
|
1101 | 0 | dst_tag |= src_tag; /* simple blend combines tags */ |
1102 | 0 | *(buff_ptr + (tag_offset * fill_trans_buffer->planestride>>1)) = dst_tag; |
1103 | 0 | } |
1104 | 0 | } |
1105 | 0 | } |
1106 | 0 | #undef GET16_BE2NATIVE |
1107 | | |
1108 | | /* If the group we are filling has a shape plane fill that now */ |
1109 | | /* Note: Since this was a virgin group push we can just blast it with |
1110 | | * 255 */ |
1111 | 0 | if (fill_trans_buffer->has_shape) { |
1112 | 0 | buff_ptr = buff_out + fill_trans_buffer->n_chan * (fill_trans_buffer->planestride>>1); |
1113 | |
|
1114 | 0 | for (jj = 0; jj < h; jj++) { |
1115 | 0 | memset(buff_ptr, 255, w*2); |
1116 | 0 | buff_ptr += fill_trans_buffer->rowstride>>1; |
1117 | 0 | } |
1118 | 0 | } |
1119 | 0 | } |
1120 | | |
1121 | | /* In this version, both source and dest data is big endian */ |
1122 | | static void |
1123 | | do_tile_rect_trans_blend_16be(int xmin, int ymin, int xmax, int ymax, |
1124 | | int px, int py, const gx_color_tile *ptile, |
1125 | | gx_pattern_trans_t *fill_trans_buffer) |
1126 | 0 | { |
1127 | 0 | int kk, jj, ii, h, w; |
1128 | 0 | int buff_out_y_offset, buff_out_x_offset; |
1129 | 0 | uint16_t *buff_out, *buff_in; |
1130 | 0 | uint16_t *buff_ptr, *row_ptr_in, *row_ptr_out; |
1131 | 0 | uint16_t *tile_ptr; |
1132 | 0 | int in_row_offset; |
1133 | 0 | int dx, dy; |
1134 | 0 | uint16_t src[PDF14_MAX_PLANES]; |
1135 | 0 | uint16_t dst[PDF14_MAX_PLANES]; |
1136 | 0 | int tile_width = ptile->ttrans->width; |
1137 | 0 | int tile_height = ptile->ttrans->height; |
1138 | 0 | int num_chan = ptile->ttrans->n_chan; /* Includes alpha */ |
1139 | 0 | int tag_offset = fill_trans_buffer->n_chan + (fill_trans_buffer->has_shape ? 1 : 0); |
1140 | 0 | pdf14_device *p14dev = (pdf14_device *) fill_trans_buffer->pdev14; |
1141 | |
|
1142 | 0 | if (fill_trans_buffer->has_tags == 0) |
1143 | 0 | tag_offset = 0; |
1144 | |
|
1145 | 0 | buff_out_y_offset = ymin - fill_trans_buffer->rect.p.y; |
1146 | 0 | buff_out_x_offset = xmin - fill_trans_buffer->rect.p.x; |
1147 | |
|
1148 | 0 | h = ymax - ymin; |
1149 | 0 | w = xmax - xmin; |
1150 | |
|
1151 | 0 | if (h <= 0 || w <= 0) return; |
1152 | | |
1153 | | /* Calc dx, dy within the entire (conceptual) input tile. */ |
1154 | 0 | dx = (xmin + px) % tile_width; |
1155 | 0 | dy = (ymin + py) % tile_height; |
1156 | |
|
1157 | 0 | buff_out = (uint16_t *)(void *)(fill_trans_buffer->transbytes + |
1158 | 0 | buff_out_y_offset * fill_trans_buffer->rowstride + |
1159 | 0 | buff_out_x_offset*2); |
1160 | |
|
1161 | 0 | buff_in = (uint16_t *)(void *)ptile->ttrans->transbytes; |
1162 | |
|
1163 | 0 | for (jj = 0; jj < h; jj++){ |
1164 | |
|
1165 | 0 | in_row_offset = (jj + dy) % ptile->ttrans->height; |
1166 | 0 | if (in_row_offset >= ptile->ttrans->rect.q.y) |
1167 | 0 | continue; |
1168 | 0 | in_row_offset -= ptile->ttrans->rect.p.y; |
1169 | 0 | if (in_row_offset < 0) |
1170 | 0 | continue; |
1171 | 0 | row_ptr_in = buff_in + in_row_offset * (ptile->ttrans->rowstride>>1); |
1172 | |
|
1173 | 0 | row_ptr_out = buff_out + jj * (fill_trans_buffer->rowstride>>1); |
1174 | |
|
1175 | 0 | for (ii = 0; ii < w; ii++) { |
1176 | 0 | int x_in_offset = (dx + ii) % ptile->ttrans->width; |
1177 | |
|
1178 | 0 | if (x_in_offset >= ptile->ttrans->rect.q.x) |
1179 | 0 | continue; |
1180 | 0 | x_in_offset -= ptile->ttrans->rect.p.x; |
1181 | 0 | if (x_in_offset < 0) |
1182 | 0 | continue; |
1183 | 0 | tile_ptr = row_ptr_in + x_in_offset; |
1184 | 0 | buff_ptr = row_ptr_out + ii; |
1185 | | |
1186 | | /* We need to blend here. The blending mode from the current |
1187 | | imager state is used. |
1188 | | */ |
1189 | | |
1190 | | /* Data is stored in big endian, but must be processed in native */ |
1191 | 0 | #define GET16_BE2NATIVE(v) \ |
1192 | 0 | ((((byte *)(v))[0]<<8) | (((byte *)(v))[1])) |
1193 | 0 | #define PUT16_NATIVE2BE(p,v) \ |
1194 | 0 | ((((byte *)(p))[0] = v>>8), (((byte *)(p))[1] = v)) |
1195 | | |
1196 | | /* The color values. This needs to be optimized */ |
1197 | 0 | for (kk = 0; kk < num_chan; kk++) { |
1198 | 0 | dst[kk] = GET16_BE2NATIVE(buff_ptr + kk * (fill_trans_buffer->planestride>>1)); |
1199 | 0 | src[kk] = GET16_BE2NATIVE(tile_ptr + kk * (ptile->ttrans->planestride>>1)); |
1200 | 0 | } |
1201 | | |
1202 | | /* Blend */ |
1203 | 0 | art_pdf_composite_pixel_alpha_16(dst, src, ptile->ttrans->n_chan-1, |
1204 | 0 | ptile->blending_mode, ptile->ttrans->n_chan-1, |
1205 | 0 | ptile->ttrans->blending_procs, p14dev); |
1206 | | |
1207 | | /* Store the color values */ |
1208 | 0 | for (kk = 0; kk < num_chan; kk++) { |
1209 | 0 | PUT16_NATIVE2BE(buff_ptr + kk * (fill_trans_buffer->planestride>>1), dst[kk]); |
1210 | 0 | } |
1211 | | /* Now handle the blending of the tag. NB: dst tag_offset follows shape */ |
1212 | 0 | if (tag_offset > 0) { |
1213 | 0 | int src_tag = GET16_BE2NATIVE(tile_ptr + (num_chan * ptile->ttrans->planestride>>1)); |
1214 | 0 | int dst_tag = GET16_BE2NATIVE(buff_ptr + (tag_offset * fill_trans_buffer->planestride>>1)); |
1215 | |
|
1216 | 0 | dst_tag |= src_tag; /* simple blend combines tags */ |
1217 | 0 | PUT16_NATIVE2BE(buff_ptr + (tag_offset * fill_trans_buffer->planestride>>1), dst_tag); |
1218 | 0 | } |
1219 | 0 | } |
1220 | 0 | } |
1221 | | |
1222 | | /* If the group we are filling has a shape plane fill that now */ |
1223 | | /* Note: Since this was a virgin group push we can just blast it with |
1224 | | * 255 */ |
1225 | 0 | if (fill_trans_buffer->has_shape) { |
1226 | 0 | buff_ptr = buff_out + fill_trans_buffer->n_chan * (fill_trans_buffer->planestride>>1); |
1227 | |
|
1228 | 0 | for (jj = 0; jj < h; jj++) { |
1229 | 0 | memset(buff_ptr, 255, w*2); |
1230 | 0 | buff_ptr += fill_trans_buffer->rowstride>>1; |
1231 | 0 | } |
1232 | 0 | } |
1233 | 0 | } |
1234 | | |
1235 | | void |
1236 | | tile_rect_trans_blend(int xmin, int ymin, int xmax, int ymax, |
1237 | | int px, int py, const gx_color_tile *ptile, |
1238 | | gx_pattern_trans_t *fill_trans_buffer, |
1239 | | int native16) |
1240 | 0 | { |
1241 | 0 | pdf14_buf *buf = fill_trans_buffer->buf; |
1242 | | |
1243 | | /* Update the bbox in the topmost stack entry to reflect the fact that we |
1244 | | * have drawn into it. FIXME: This makes the groups too large! */ |
1245 | 0 | if (buf->dirty.p.x > xmin) |
1246 | 0 | buf->dirty.p.x = xmin; |
1247 | 0 | if (buf->dirty.p.y > ymin) |
1248 | 0 | buf->dirty.p.y = ymin; |
1249 | 0 | if (buf->dirty.q.x < xmax) |
1250 | 0 | buf->dirty.q.x = xmax; |
1251 | 0 | if (buf->dirty.q.y < ymax) |
1252 | 0 | buf->dirty.q.y = ymax; |
1253 | |
|
1254 | 0 | if (!ptile->ttrans->deep) |
1255 | 0 | do_tile_rect_trans_blend(xmin, ymin, xmax, ymax, |
1256 | 0 | px, py, ptile, fill_trans_buffer); |
1257 | 0 | else if (native16) |
1258 | 0 | do_tile_rect_trans_blend_16(xmin, ymin, xmax, ymax, |
1259 | 0 | px, py, ptile, fill_trans_buffer); |
1260 | 0 | else |
1261 | 0 | do_tile_rect_trans_blend_16be(xmin, ymin, xmax, ymax, |
1262 | 0 | px, py, ptile, fill_trans_buffer); |
1263 | 0 | } |
1264 | | |
1265 | | /* This version does a rect fill with the transparency object */ |
1266 | | int |
1267 | | gx_dc_pat_trans_fill_rectangle(const gx_device_color * pdevc, int x, int y, |
1268 | | int w, int h, gx_device * dev, |
1269 | | gs_logical_operation_t lop, |
1270 | | const gx_rop_source_t * source) |
1271 | 0 | { |
1272 | 0 | gx_color_tile *ptile = pdevc->colors.pattern.p_tile; |
1273 | 0 | int code; |
1274 | 0 | gs_int_point phase; |
1275 | 0 | const gx_rop_source_t *rop_source = source; |
1276 | 0 | gx_rop_source_t no_source; |
1277 | |
|
1278 | 0 | if (ptile == 0) /* null pattern */ |
1279 | 0 | return 0; |
1280 | 0 | if (rop_source == NULL) |
1281 | 0 | set_rop_no_source(rop_source, no_source, dev); |
1282 | |
|
1283 | 0 | phase.x = pdevc->phase.x; |
1284 | 0 | phase.y = pdevc->phase.y; |
1285 | |
|
1286 | | #if 0 |
1287 | | if_debug8m('v', ptile->ttrans->mem, |
1288 | | "[v]gx_dc_pat_trans_fill_rectangle, Fill: (%d, %d), %d x %d To Buffer: (%d, %d), %d x %d \n", |
1289 | | x, y, w, h, ptile->ttrans->fill_trans_buffer->rect.p.x, |
1290 | | ptile->ttrans->fill_trans_buffer->rect.p.y, |
1291 | | ptile->ttrans->fill_trans_buffer->rect.q.x - |
1292 | | ptile->ttrans->fill_trans_buffer->rect.p.x, |
1293 | | ptile->ttrans->fill_trans_buffer->rect.q.y - |
1294 | | ptile->ttrans->fill_trans_buffer->rect.p.y); |
1295 | | #endif |
1296 | 0 | code = gx_trans_pattern_fill_rect(x, y, x+w, y+h, ptile, |
1297 | 0 | ptile->ttrans->fill_trans_buffer, phase, |
1298 | 0 | dev, pdevc, 0); |
1299 | 0 | return code; |
1300 | 0 | } |
1301 | | |
1302 | | /* This fills the transparency buffer rectangles with a pattern buffer |
1303 | | that includes transparency */ |
1304 | | int |
1305 | | gx_trans_pattern_fill_rect(int xmin, int ymin, int xmax, int ymax, |
1306 | | gx_color_tile *ptile, |
1307 | | gx_pattern_trans_t *fill_trans_buffer, |
1308 | | gs_int_point phase, gx_device *dev, |
1309 | | const gx_device_color * pdevc, |
1310 | | int native16) |
1311 | 0 | { |
1312 | 0 | tile_fill_trans_state_t state_trans; |
1313 | 0 | tile_fill_state_t state_clist_trans; |
1314 | 0 | int code = 0; |
1315 | 0 | int w = xmax - xmin; |
1316 | 0 | int h = ymax - ymin; |
1317 | |
|
1318 | 0 | if (ptile == 0) /* null pattern */ |
1319 | 0 | return 0; |
1320 | | |
1321 | 0 | fit_fill_xywh(dev, xmin, ymin, w, h); |
1322 | 0 | if (w < 0 || h < 0) |
1323 | 0 | return 0; |
1324 | 0 | xmax = w + xmin; |
1325 | 0 | ymax = h + ymin; |
1326 | | |
1327 | | /* Initialize the fill state */ |
1328 | 0 | state_trans.phase.x = phase.x; |
1329 | 0 | state_trans.phase.y = phase.y; |
1330 | |
|
1331 | 0 | if (ptile->is_simple && ptile->cdev == NULL) { |
1332 | | /* A simple case. Tile is not clist and simple. */ |
1333 | 0 | int px = |
1334 | 0 | imod(-(int)fastfloor(ptile->step_matrix.tx - phase.x + 0.5), |
1335 | 0 | ptile->ttrans->width); |
1336 | 0 | int py = |
1337 | 0 | imod(-(int)fastfloor(ptile->step_matrix.ty - phase.y + 0.5), |
1338 | 0 | ptile->ttrans->height); |
1339 | |
|
1340 | 0 | tile_rect_trans_simple(xmin, ymin, xmax, ymax, px, py, ptile, |
1341 | 0 | fill_trans_buffer, native16); |
1342 | 0 | } else { |
1343 | 0 | if (ptile->cdev == NULL) { |
1344 | | /* No clist for the pattern, but a complex case |
1345 | | This portion transforms the bounding box by the step matrix |
1346 | | and does partial rect fills with tiles that fall into this |
1347 | | transformed bbox */ |
1348 | 0 | code = tile_by_steps_trans(&state_trans, xmin, ymin, xmax-xmin, |
1349 | 0 | ymax-ymin, fill_trans_buffer, ptile, |
1350 | 0 | native16); |
1351 | |
|
1352 | 0 | } else { |
1353 | | /* clist for the trans tile. This uses the pdf14 device as a target |
1354 | | and should blend directly into the buffer. Note that the |
1355 | | pattern can not have a push pdf14 device or a pop pdf14 device |
1356 | | compositor action. Those are removed during the compositor |
1357 | | clist writing operation where we check for the case of a pattern |
1358 | | with a transparency */ |
1359 | 0 | gx_device_clist *cdev = ptile->cdev; |
1360 | 0 | gx_device_clist_reader *crdev = (gx_device_clist_reader *)cdev; |
1361 | 0 | gx_strip_bitmap tbits; |
1362 | |
|
1363 | 0 | code = tile_fill_init(&state_clist_trans, pdevc, dev, false); |
1364 | |
|
1365 | 0 | state_clist_trans.phase.x = phase.x; |
1366 | 0 | state_clist_trans.phase.y = phase.y; |
1367 | 0 | crdev->yplane.depth = 0; |
1368 | 0 | crdev->yplane.shift = 0; |
1369 | 0 | crdev->yplane.index = -1; |
1370 | 0 | crdev->pages = NULL; |
1371 | 0 | crdev->num_pages = 1; |
1372 | 0 | state_clist_trans.orig_dev = dev; |
1373 | 0 | state_clist_trans.pdevc = pdevc; |
1374 | 0 | tbits = ptile->tbits; |
1375 | 0 | tbits.size.x = crdev->width; |
1376 | 0 | tbits.size.y = crdev->height; |
1377 | 0 | if (code >= 0) |
1378 | 0 | code = tile_by_steps(&state_clist_trans, xmin, ymin, xmax-xmin, |
1379 | 0 | ymax-ymin, ptile, &tbits, tile_pattern_clist); |
1380 | |
|
1381 | 0 | if (code >= 0 && (state_clist_trans.cdev != NULL)) { |
1382 | 0 | tile_clip_free((gx_device_tile_clip *)state_clist_trans.cdev); |
1383 | 0 | state_clist_trans.cdev = NULL; |
1384 | 0 | } |
1385 | |
|
1386 | 0 | } |
1387 | 0 | } |
1388 | 0 | return code; |
1389 | 0 | } |