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