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