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