/src/ghostpdl/base/gxpcmap.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2025 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 | | /* Pattern color mapping for Ghostscript library */ |
18 | | #include "math_.h" |
19 | | #include "memory_.h" |
20 | | #include "gx.h" |
21 | | #include "gp.h" |
22 | | #include "gserrors.h" |
23 | | #include "gsstruct.h" |
24 | | #include "gsutil.h" /* for gs_next_ids */ |
25 | | #include "gxfixed.h" |
26 | | #include "gxmatrix.h" |
27 | | #include "gspath2.h" |
28 | | #include "gxcspace.h" /* for gscolor2.h */ |
29 | | #include "gxcolor2.h" |
30 | | #include "gxdcolor.h" |
31 | | #include "gxdevice.h" |
32 | | #include "gxdevmem.h" |
33 | | #include "gxpcolor.h" |
34 | | #include "gxp1impl.h" |
35 | | #include "gxclist.h" |
36 | | #include "gxcldev.h" |
37 | | #include "gzstate.h" |
38 | | #include "gxdevsop.h" |
39 | | #include "gdevmpla.h" |
40 | | #include "gdevp14.h" |
41 | | #include "gxgetbit.h" |
42 | | #include "gscoord.h" |
43 | | #include "gsicc_blacktext.h" |
44 | | #include "gscspace.h" |
45 | | |
46 | | #if RAW_PATTERN_DUMP |
47 | | unsigned int global_pat_index = 0; |
48 | | #endif |
49 | | |
50 | | /* Define the default size of the Pattern cache. */ |
51 | 247k | #define max_cached_patterns_LARGE 50 |
52 | 247k | #define max_pattern_bits_LARGE 100000 |
53 | | #define max_cached_patterns_SMALL 5 |
54 | | #define max_pattern_bits_SMALL 1000 |
55 | | uint |
56 | | gx_pat_cache_default_tiles(void) |
57 | 247k | { |
58 | | #if ARCH_SMALL_MEMORY |
59 | | return max_cached_patterns_SMALL; |
60 | | #else |
61 | | #ifdef DEBUG |
62 | | return (gs_debug_c('.') ? max_cached_patterns_SMALL : |
63 | | max_cached_patterns_LARGE); |
64 | | #else |
65 | 247k | return max_cached_patterns_LARGE; |
66 | 247k | #endif |
67 | 247k | #endif |
68 | 247k | } |
69 | | ulong |
70 | | gx_pat_cache_default_bits(void) |
71 | 247k | { |
72 | | #if ARCH_SMALL_MEMORY |
73 | | return max_pattern_bits_SMALL; |
74 | | #else |
75 | | #ifdef DEBUG |
76 | | return (gs_debug_c('.') ? max_pattern_bits_SMALL : |
77 | | max_pattern_bits_LARGE); |
78 | | #else |
79 | 247k | return max_pattern_bits_LARGE; |
80 | 247k | #endif |
81 | 247k | #endif |
82 | 247k | } |
83 | | |
84 | | /* Define the structures for Pattern rendering and caching. */ |
85 | | private_st_color_tile(); |
86 | | private_st_color_tile_element(); |
87 | | private_st_pattern_cache(); |
88 | | private_st_device_pattern_accum(); |
89 | | private_st_pattern_trans(); |
90 | | |
91 | | /* ------ Pattern rendering ------ */ |
92 | | |
93 | | /* Device procedures */ |
94 | | static dev_proc_open_device(pattern_accum_open); |
95 | | static dev_proc_close_device(pattern_accum_close); |
96 | | static dev_proc_fill_rectangle(pattern_accum_fill_rectangle); |
97 | | static dev_proc_copy_mono(pattern_accum_copy_mono); |
98 | | static dev_proc_copy_color(pattern_accum_copy_color); |
99 | | static dev_proc_copy_planes(pattern_accum_copy_planes); |
100 | | static dev_proc_get_bits_rectangle(pattern_accum_get_bits_rectangle); |
101 | | static dev_proc_fill_rectangle_hl_color(pattern_accum_fill_rectangle_hl_color); |
102 | | /* not static for use by clist_dev_spec_op with pattern-clist */ |
103 | | dev_proc_dev_spec_op(pattern_accum_dev_spec_op); |
104 | | |
105 | | /* The device descriptor */ |
106 | | static void |
107 | | pattern_accum_initialize_device_procs(gx_device *dev) |
108 | 22.7k | { |
109 | 22.7k | set_dev_proc(dev, open_device, pattern_accum_open); |
110 | 22.7k | set_dev_proc(dev, close_device, pattern_accum_close); |
111 | 22.7k | set_dev_proc(dev, fill_rectangle, pattern_accum_fill_rectangle); |
112 | 22.7k | set_dev_proc(dev, copy_mono, pattern_accum_copy_mono); |
113 | 22.7k | set_dev_proc(dev, copy_color, pattern_accum_copy_color); |
114 | 22.7k | set_dev_proc(dev, get_clipping_box, gx_get_largest_clipping_box); |
115 | 22.7k | set_dev_proc(dev, get_bits_rectangle, pattern_accum_get_bits_rectangle); |
116 | 22.7k | set_dev_proc(dev, fill_rectangle_hl_color, pattern_accum_fill_rectangle_hl_color); |
117 | 22.7k | set_dev_proc(dev, dev_spec_op, pattern_accum_dev_spec_op); |
118 | 22.7k | set_dev_proc(dev, copy_planes, pattern_accum_copy_planes); |
119 | | |
120 | | /* It would be much nicer if gx_device_init set the following |
121 | | * defaults for us, but that doesn't work for some reason. */ |
122 | 22.7k | set_dev_proc(dev, copy_alpha, gx_default_copy_alpha); |
123 | 22.7k | set_dev_proc(dev, fill_path, gx_default_fill_path); |
124 | 22.7k | set_dev_proc(dev, stroke_path, gx_default_stroke_path); |
125 | 22.7k | set_dev_proc(dev, fill_mask, gx_default_fill_mask); |
126 | 22.7k | set_dev_proc(dev, fill_trapezoid, gx_default_fill_trapezoid); |
127 | 22.7k | set_dev_proc(dev, fill_parallelogram, gx_default_fill_parallelogram); |
128 | 22.7k | set_dev_proc(dev, fill_triangle, gx_default_fill_triangle); |
129 | 22.7k | set_dev_proc(dev, draw_thin_line, gx_default_draw_thin_line); |
130 | 22.7k | set_dev_proc(dev, strip_tile_rectangle, gx_default_strip_tile_rectangle); |
131 | 22.7k | set_dev_proc(dev, begin_typed_image, gx_default_begin_typed_image); |
132 | 22.7k | set_dev_proc(dev, composite, gx_default_composite); |
133 | 22.7k | set_dev_proc(dev, text_begin, gx_default_text_begin); |
134 | 22.7k | set_dev_proc(dev, strip_copy_rop2, gx_default_strip_copy_rop2); |
135 | 22.7k | set_dev_proc(dev, strip_tile_rect_devn, gx_default_strip_tile_rect_devn); |
136 | 22.7k | set_dev_proc(dev, transform_pixel_region, gx_default_transform_pixel_region); |
137 | 22.7k | set_dev_proc(dev, fill_stroke_path, gx_default_fill_stroke_path); |
138 | 22.7k | set_dev_proc(dev, lock_pattern, gx_default_lock_pattern); |
139 | 22.7k | set_dev_proc(dev, copy_alpha_hl_color, gx_default_copy_alpha_hl_color); |
140 | 22.7k | } |
141 | | |
142 | | static const gx_device_pattern_accum gs_pattern_accum_device = |
143 | | {std_device_std_body_type_open(gx_device_pattern_accum, |
144 | | pattern_accum_initialize_device_procs, |
145 | | "pattern accumulator", |
146 | | &st_device_pattern_accum, |
147 | | 0, 0, 72, 72) |
148 | | }; |
149 | | |
150 | | extern dev_proc_open_device(clist_open); |
151 | | |
152 | | int |
153 | | pattern_clist_open_device(gx_device *dev) |
154 | 120k | { |
155 | | /* This function is defiled only for clist_init_bands. */ |
156 | 120k | return clist_open(dev); |
157 | 120k | } |
158 | | |
159 | | static dev_proc_create_buf_device(dummy_create_buf_device) |
160 | 241k | { |
161 | 241k | gx_device_memory *mdev = (gx_device_memory *)*pbdev; |
162 | | |
163 | 241k | gs_make_mem_device(mdev, gdev_mem_device_for_bits(target->color_info.depth), |
164 | 241k | mem, 0, target); |
165 | 241k | return 0; |
166 | 241k | } |
167 | | static dev_proc_size_buf_device(dummy_size_buf_device) |
168 | 0 | { |
169 | 0 | return 0; |
170 | 0 | } |
171 | | static dev_proc_setup_buf_device(dummy_setup_buf_device) |
172 | 0 | { |
173 | 0 | return 0; |
174 | 0 | } |
175 | | static dev_proc_destroy_buf_device(dummy_destroy_buf_device) |
176 | 0 | { |
177 | 0 | } |
178 | | /* Attempt to determine the size of a pattern (the approximate amount that will */ |
179 | | /* be needed in the pattern cache). If we end up using the clist, this is only */ |
180 | | /* a guess -- we use the tile size which will _probably_ be too large. */ |
181 | | static size_t |
182 | | gx_pattern_size_estimate(gs_pattern1_instance_t *pinst, bool has_tags) |
183 | 170k | { |
184 | 170k | gx_device *tdev = pinst->saved->device; |
185 | 170k | int depth = (pinst->templat.PaintType == 2 ? 1 : tdev->color_info.depth); |
186 | 170k | size_t raster; |
187 | 170k | size_t size; |
188 | | |
189 | 170k | if (pinst->size.x == 0 || pinst->size.y == 0) |
190 | 80 | return 0; |
191 | | |
192 | 170k | if (pinst->templat.uses_transparency) { |
193 | | /* if the device has tags, add in an extra tag byte for the pdf14 compositor */ |
194 | 37.0k | raster = ((size_t)pinst->size.x * ((depth/8) + 1 + (has_tags ? 1 : 0))); |
195 | 133k | } else { |
196 | 133k | raster = ((size_t)pinst->size.x * depth + 7) / 8; |
197 | 133k | } |
198 | 170k | size = raster > max_size_t / pinst->size.y ? (max_size_t - 0xFFFF) : raster * pinst->size.y; |
199 | 170k | return size; |
200 | 170k | } |
201 | | |
202 | | static void gx_pattern_accum_finalize_cw(gx_device * dev) |
203 | 120k | { |
204 | 120k | gx_device_clist_writer *cwdev = (gx_device_clist_writer *)dev; |
205 | 120k | rc_decrement_only(cwdev->target, "gx_pattern_accum_finalize_cw"); |
206 | 120k | } |
207 | | |
208 | | bool gx_device_is_pattern_accum(gx_device *dev) |
209 | 6.06M | { |
210 | 6.06M | return dev_proc(dev, open_device) == pattern_accum_open; |
211 | 6.06M | } |
212 | | |
213 | | bool gx_device_is_pattern_clist(gx_device *dev) |
214 | 6.93M | { |
215 | 6.93M | return dev_proc(dev, open_device) == pattern_clist_open_device; |
216 | 6.93M | } |
217 | | |
218 | | /* Allocate a pattern accumulator, with an initial refct of 0. */ |
219 | | gx_device_forward * |
220 | | gx_pattern_accum_alloc(gs_memory_t * mem, gs_memory_t * storage_memory, |
221 | | gs_pattern1_instance_t *pinst, client_name_t cname) |
222 | 143k | { |
223 | 143k | gx_device *tdev = pinst->saved->device; |
224 | 143k | bool has_tags = device_encodes_tags(tdev); |
225 | 143k | size_t size = gx_pattern_size_estimate(pinst, has_tags); |
226 | 143k | gx_device_forward *fdev; |
227 | 143k | int force_no_clist = 0; |
228 | 143k | size_t max_pattern_bitmap = tdev->MaxPatternBitmap == 0 ? MaxPatternBitmap_DEFAULT : |
229 | 143k | tdev->MaxPatternBitmap; |
230 | | |
231 | 143k | pinst->num_planar_planes = tdev->num_planar_planes; |
232 | | /* |
233 | | * If the target device can accumulate a pattern stream and the language |
234 | | * client supports high level patterns (ps and pdf only) we don't need a |
235 | | * raster or clist representation for the pattern, but the code goes |
236 | | * through the motions of creating the device anyway. Later when the |
237 | | * pattern paint procedure is called an error is returned and whatever |
238 | | * has been set up here is destroyed. We try to make sure the same path |
239 | | * is taken in the code even though the device is never used because |
240 | | * there are pathological problems (see Bug689851.pdf) where the pattern |
241 | | * is so large we can't even allocate the memory for the device and the |
242 | | * dummy clist path must be used. None of this discussion is relevant if |
243 | | * the client language does not support high level patterns or the device |
244 | | * cannot accumulate the pattern stream. |
245 | | */ |
246 | 143k | if (pinst->saved->have_pattern_streams == 0 && (*dev_proc(pinst->saved->device, |
247 | 116k | dev_spec_op))((gx_device *)pinst->saved->device, |
248 | 116k | gxdso_pattern_can_accum, pinst, 0) == 1) |
249 | 0 | force_no_clist = 1; /* Set only for first time through */ |
250 | | /* If the blend mode in use is not Normal, then we CANNOT use a tile. What |
251 | | * if the blend mode changes half way through the tile? We simply must use |
252 | | * a clist. */ |
253 | 143k | if (force_no_clist || |
254 | 143k | (((size < max_pattern_bitmap && !pinst->is_clist) |
255 | 143k | || pinst->templat.PaintType != 1) && !pinst->templat.BM_Not_Normal)) { |
256 | 22.7k | gx_device_pattern_accum *adev = gs_alloc_struct_immovable(mem, gx_device_pattern_accum, |
257 | 22.7k | &st_device_pattern_accum, cname); |
258 | 22.7k | if (adev == 0) |
259 | 0 | return 0; |
260 | | #ifdef DEBUG |
261 | | if (pinst->is_clist) |
262 | | emprintf(mem, "not using clist even though clist is requested\n"); |
263 | | #endif |
264 | 22.7k | pinst->is_clist = false; |
265 | 22.7k | (void)gx_device_init((gx_device *)adev, |
266 | 22.7k | (const gx_device *)&gs_pattern_accum_device, |
267 | 22.7k | mem, true); |
268 | 22.7k | adev->instance = pinst; |
269 | 22.7k | adev->bitmap_memory = storage_memory; |
270 | 22.7k | fdev = (gx_device_forward *)adev; |
271 | 120k | } else { |
272 | 120k | gx_device_buf_procs_t buf_procs = {dummy_create_buf_device, |
273 | 120k | dummy_size_buf_device, dummy_setup_buf_device, dummy_destroy_buf_device}; |
274 | 120k | gx_device_clist *cdev; |
275 | 120k | gx_device_clist_writer *cwdev; |
276 | 120k | const int data_size = 1024*128; |
277 | 120k | gx_band_params_t band_params = { 0 }; |
278 | 120k | byte *data = gs_alloc_bytes(mem->non_gc_memory, data_size, cname); |
279 | | |
280 | 120k | if (data == NULL) |
281 | 0 | return 0; |
282 | 120k | pinst->is_clist = true; |
283 | | /* NB: band_params.page_uses_transparency is set in clist_make_accum_device */ |
284 | 120k | band_params.BandWidth = pinst->size.x; |
285 | 120k | band_params.BandHeight = pinst->size.y; |
286 | 120k | band_params.BandBufferSpace = 0; |
287 | | |
288 | 120k | cdev = clist_make_accum_device(mem, tdev, "pattern-clist", data, data_size, |
289 | 120k | &buf_procs, &band_params, true, /* use_memory_clist */ |
290 | 120k | pinst->templat.uses_transparency, pinst); |
291 | 120k | if (cdev == 0) { |
292 | 0 | gs_free_object(tdev->memory->non_gc_memory, data, cname); |
293 | 0 | return 0; |
294 | 0 | } |
295 | 120k | cwdev = (gx_device_clist_writer *)cdev; |
296 | 120k | cwdev->finalize = gx_pattern_accum_finalize_cw; |
297 | 120k | set_dev_proc(cwdev, open_device, pattern_clist_open_device); |
298 | 120k | fdev = (gx_device_forward *)cdev; |
299 | 120k | } |
300 | 143k | fdev->log2_align_mod = tdev->log2_align_mod; |
301 | 143k | fdev->pad = tdev->pad; |
302 | 143k | fdev->num_planar_planes = tdev->num_planar_planes; |
303 | 143k | fdev->graphics_type_tag = tdev->graphics_type_tag; |
304 | 143k | fdev->interpolate_control = tdev->interpolate_control; |
305 | 143k | fdev->non_strict_bounds = tdev->non_strict_bounds; |
306 | 143k | gx_device_forward_fill_in_procs(fdev); |
307 | 143k | return fdev; |
308 | 143k | } |
309 | | |
310 | | gx_pattern_trans_t* |
311 | | new_pattern_trans_buff(gs_memory_t *mem) |
312 | 154k | { |
313 | 154k | gx_pattern_trans_t *result; |
314 | | |
315 | | /* Allocate structure that we will use for the trans pattern */ |
316 | 154k | result = gs_alloc_struct(mem, gx_pattern_trans_t, &st_pattern_trans, "new_pattern_trans_buff"); |
317 | | |
318 | 154k | if (result != NULL) { |
319 | 154k | result->transbytes = NULL; |
320 | 154k | result->pdev14 = NULL; |
321 | 154k | result->mem = NULL; |
322 | 154k | result->fill_trans_buffer = NULL; |
323 | 154k | result->buf = NULL; |
324 | 154k | result->n_chan = 0; |
325 | 154k | result->rect.p.x = result->rect.p.y = result->rect.q.x = result->rect.q.y = 0; |
326 | 154k | } |
327 | | |
328 | 154k | return(result); |
329 | 154k | } |
330 | | |
331 | | /* |
332 | | * Initialize a pattern accumulator. |
333 | | * Client must already have set instance and bitmap_memory. |
334 | | * |
335 | | * Note that mask and bits accumulators are only created if necessary. |
336 | | */ |
337 | | static int |
338 | | pattern_accum_open(gx_device * dev) |
339 | 22.7k | { |
340 | 22.7k | gx_device_pattern_accum *const padev = (gx_device_pattern_accum *) dev; |
341 | 22.7k | const gs_pattern1_instance_t *pinst = padev->instance; |
342 | 22.7k | gs_memory_t *mem = padev->bitmap_memory; |
343 | 22.7k | gx_device_memory *mask = 0; |
344 | 22.7k | gx_device_memory *bits = 0; |
345 | | /* |
346 | | * The client should preset the target, because the device for which the |
347 | | * pattern is being rendered may not (in general, will not) be the same |
348 | | * as the one that was current when the pattern was instantiated. |
349 | | */ |
350 | 22.7k | gx_device *target = |
351 | 22.7k | (padev->target == 0 ? gs_currentdevice(pinst->saved) : |
352 | 22.7k | padev->target); |
353 | 22.7k | int width = pinst->size.x; |
354 | 22.7k | int height = pinst->size.y; |
355 | 22.7k | int code = 0; |
356 | 22.7k | bool mask_open = false; |
357 | | |
358 | | /* |
359 | | * C's bizarre coercion rules force us to copy HWResolution in pieces |
360 | | * rather than using a single assignment. |
361 | | */ |
362 | 22.7k | #define PDSET(dev)\ |
363 | 49.8k | ((dev)->width = width, (dev)->height = height,\ |
364 | | /*(dev)->HWResolution = target->HWResolution*/\ |
365 | 49.8k | (dev)->HWResolution[0] = target->HWResolution[0],\ |
366 | 49.8k | (dev)->HWResolution[1] = target->HWResolution[1]) |
367 | | |
368 | 22.7k | PDSET(padev); |
369 | 22.7k | padev->color_info = target->color_info; |
370 | | /* Bug 689737: If PaintType == 2 (Uncolored tiling pattern), pattern is |
371 | | * 1bpp bitmap. No antialiasing in this case! */ |
372 | 22.7k | if (pinst->templat.PaintType == 2) { |
373 | 232 | padev->color_info.anti_alias.text_bits = 1; |
374 | 232 | padev->color_info.anti_alias.graphics_bits = 1; |
375 | 232 | } |
376 | | /* If we have transparency, then fix the color info |
377 | | now so that the mem device allocates the proper |
378 | | buffer space for the pattern template. We can |
379 | | do this since the transparency code all */ |
380 | 22.7k | if (pinst->templat.uses_transparency) { |
381 | | /* Allocate structure that we will use for the trans pattern */ |
382 | 18.1k | padev->transbuff = new_pattern_trans_buff(mem); |
383 | 18.1k | if (padev->transbuff == NULL) |
384 | 0 | return_error(gs_error_VMerror); |
385 | 18.1k | } else { |
386 | 4.59k | padev->transbuff = NULL; |
387 | 4.59k | } |
388 | 22.7k | if (pinst->uses_mask) { |
389 | 22.7k | mask = gs_alloc_struct( mem, |
390 | 22.7k | gx_device_memory, |
391 | 22.7k | &st_device_memory, |
392 | 22.7k | "pattern_accum_open(mask)" |
393 | 22.7k | ); |
394 | 22.7k | if (mask == 0) |
395 | 0 | return_error(gs_error_VMerror); |
396 | 22.7k | gs_make_mem_mono_device(mask, mem, 0); |
397 | 22.7k | PDSET(mask); |
398 | 22.7k | mask->bitmap_memory = mem; |
399 | 22.7k | mask->base = 0; |
400 | 22.7k | code = (*dev_proc(mask, open_device)) ((gx_device *) mask); |
401 | 22.7k | if (code >= 0) { |
402 | 22.7k | mask_open = true; |
403 | 22.7k | memset(mask->base, 0, (size_t)mask->raster * mask->height); |
404 | 22.7k | } |
405 | 22.7k | } |
406 | | |
407 | 22.7k | if (code >= 0) { |
408 | 22.7k | if (pinst->templat.uses_transparency) { |
409 | | /* In this case, we will grab the buffer created |
410 | | by the graphic state's device (which is pdf14) and |
411 | | we will be tiling that into a transparency group buffer |
412 | | to blend with the pattern accumulator's target. Since |
413 | | all the transparency stuff is planar format, it is |
414 | | best just to keep the data in that form */ |
415 | 18.1k | gx_device_set_target((gx_device_forward *)padev, target); |
416 | 18.1k | } else { |
417 | 4.59k | switch (pinst->templat.PaintType) { |
418 | 232 | case 2: /* uncolored */ |
419 | 232 | gx_device_set_target((gx_device_forward *)padev, target); |
420 | 232 | break; |
421 | 4.36k | case 1: /* colored */ |
422 | 4.36k | bits = gs_alloc_struct(mem, gx_device_memory, |
423 | 4.36k | &st_device_memory, |
424 | 4.36k | "pattern_accum_open(bits)"); |
425 | 4.36k | if (bits == 0) |
426 | 0 | code = gs_note_error(gs_error_VMerror); |
427 | 4.36k | else { |
428 | 4.36k | gs_make_mem_device(bits, |
429 | 4.36k | gdev_mem_device_for_bits(padev->color_info.depth), |
430 | 4.36k | mem, -1, target); |
431 | 4.36k | PDSET(bits); |
432 | 4.36k | #undef PDSET |
433 | 4.36k | bits->color_info = padev->color_info; |
434 | 4.36k | bits->bitmap_memory = mem; |
435 | | |
436 | 4.36k | if (target->num_planar_planes > 0) |
437 | 504 | { |
438 | 504 | gx_render_plane_t planes[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
439 | 504 | uchar num_comp = padev->num_planar_planes; |
440 | 504 | uchar i; |
441 | 504 | int depth = target->color_info.depth / num_comp; |
442 | 2.35k | for (i = 0; i < num_comp; i++) |
443 | 1.85k | { |
444 | 1.85k | planes[i].shift = depth * (num_comp - 1 - i); |
445 | 1.85k | planes[i].depth = depth; |
446 | 1.85k | planes[i].index = i; |
447 | 1.85k | } |
448 | 504 | code = gdev_mem_set_planar(bits, num_comp, planes); |
449 | 504 | } |
450 | 4.36k | if (code >= 0) { |
451 | 4.36k | code = (*dev_proc(bits, open_device)) ((gx_device *) bits); |
452 | 4.36k | gx_device_set_target((gx_device_forward *)padev, |
453 | 4.36k | (gx_device *)bits); |
454 | | /* The update_spot_equivalent_color proc for the bits device |
455 | | should forward to the real target device. This will ensure |
456 | | that the target device can get equivalent CMYK values for |
457 | | spot colors if we are using a separation device and the spot |
458 | | color occurs only in patterns on the page. */ |
459 | 4.36k | bits->procs.update_spot_equivalent_colors = gx_forward_update_spot_equivalent_colors; |
460 | 4.36k | } |
461 | 4.36k | } |
462 | 4.59k | } |
463 | 4.59k | } |
464 | 22.7k | } |
465 | 22.7k | if (code < 0) { |
466 | 0 | if (bits != 0) |
467 | 0 | gs_free_object(mem, bits, "pattern_accum_open(bits)"); |
468 | 0 | if (mask != 0) { |
469 | 0 | if (mask_open) |
470 | 0 | (*dev_proc(mask, close_device)) ((gx_device *) mask); |
471 | 0 | gs_free_object(mem, mask, "pattern_accum_open(mask)"); |
472 | 0 | } |
473 | 0 | return code; |
474 | 0 | } |
475 | 22.7k | padev->mask = mask; |
476 | 22.7k | padev->bits = bits; |
477 | | /* Retain the device, so it will survive anomalous grestores. */ |
478 | 22.7k | gx_device_retain(dev, true); |
479 | 22.7k | return code; |
480 | 22.7k | } |
481 | | |
482 | | /* Close an accumulator and free the bits. */ |
483 | | static int |
484 | | pattern_accum_close(gx_device * dev) |
485 | 45.5k | { |
486 | 45.5k | gx_device_pattern_accum *const padev = (gx_device_pattern_accum *) dev; |
487 | 45.5k | gs_memory_t *mem = padev->bitmap_memory; |
488 | | |
489 | | /* |
490 | | * If bits != 0, it is the target of the device; reference counting |
491 | | * will close and free it. |
492 | | */ |
493 | 45.5k | gx_device_set_target((gx_device_forward *)padev, NULL); |
494 | 45.5k | padev->bits = 0; |
495 | 45.5k | if (padev->mask != 0) { |
496 | 22.7k | (*dev_proc(padev->mask, close_device)) ((gx_device *) padev->mask); |
497 | 22.7k | gs_free_object(mem, padev->mask, "pattern_accum_close(mask)"); |
498 | 22.7k | padev->mask = 0; |
499 | 22.7k | } |
500 | | |
501 | 45.5k | if (padev->transbuff != 0) { |
502 | 16.2k | gs_free_object(mem,padev->target,"pattern_accum_close(transbuff)"); |
503 | 16.2k | padev->transbuff = NULL; |
504 | 16.2k | } |
505 | | |
506 | | /* Un-retain the device now, so reference counting will free it. */ |
507 | 45.5k | gx_device_retain(dev, false); |
508 | 45.5k | return 0; |
509 | 45.5k | } |
510 | | |
511 | | /* _hl_color */ |
512 | | static int |
513 | | pattern_accum_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect, |
514 | | const gs_gstate *pgs, |
515 | | const gx_drawing_color *pdcolor, |
516 | | const gx_clip_path *pcpath) |
517 | 193k | { |
518 | 193k | gx_device_pattern_accum *const padev = (gx_device_pattern_accum *) dev; |
519 | 193k | int code; |
520 | | |
521 | 193k | if (padev->bits) { |
522 | 193k | code = (*dev_proc(padev->target, fill_rectangle_hl_color)) |
523 | 193k | (padev->target, rect, pgs, pdcolor, pcpath); |
524 | 193k | if (code < 0) |
525 | 0 | return code; |
526 | 193k | } |
527 | 193k | if (padev->mask) { |
528 | 191k | int x, y, w, h; |
529 | | |
530 | 191k | x = fixed2int(rect->p.x); |
531 | 191k | y = fixed2int(rect->p.y); |
532 | 191k | w = fixed2int(rect->q.x) - x; |
533 | 191k | h = fixed2int(rect->q.y) - y; |
534 | | |
535 | 191k | return (*dev_proc(padev->mask, fill_rectangle)) |
536 | 191k | ((gx_device *) padev->mask, x, y, w, h, (gx_color_index) 1); |
537 | 191k | } |
538 | 2.25k | return 0; |
539 | 193k | } |
540 | | |
541 | | /* Fill a rectangle */ |
542 | | static int |
543 | | pattern_accum_fill_rectangle(gx_device * dev, int x, int y, int w, int h, |
544 | | gx_color_index color) |
545 | 442k | { |
546 | 442k | gx_device_pattern_accum *const padev = (gx_device_pattern_accum *) dev; |
547 | | |
548 | 442k | if (padev->bits) |
549 | 440k | (*dev_proc(padev->target, fill_rectangle)) |
550 | 440k | (padev->target, x, y, w, h, color); |
551 | 442k | if (padev->mask) |
552 | 403k | return (*dev_proc(padev->mask, fill_rectangle)) |
553 | 403k | ((gx_device *) padev->mask, x, y, w, h, (gx_color_index) 1); |
554 | 38.6k | else |
555 | 38.6k | return 0; |
556 | 442k | } |
557 | | |
558 | | /* Copy a monochrome bitmap. */ |
559 | | static int |
560 | | pattern_accum_copy_mono(gx_device * dev, const byte * data, int data_x, |
561 | | int raster, gx_bitmap_id id, int x, int y, int w, int h, |
562 | | gx_color_index color0, gx_color_index color1) |
563 | 168k | { |
564 | 168k | gx_device_pattern_accum *const padev = (gx_device_pattern_accum *) dev; |
565 | | |
566 | | /* opt out early if nothing to render (some may think this a bug) */ |
567 | 168k | if (color0 == gx_no_color_index && color1 == gx_no_color_index) |
568 | 0 | return 0; |
569 | 168k | if (padev->bits) |
570 | 168k | (*dev_proc(padev->target, copy_mono)) |
571 | 168k | (padev->target, data, data_x, raster, id, x, y, w, h, |
572 | 168k | color0, color1); |
573 | 168k | if (padev->mask) { |
574 | 168k | if (color0 != gx_no_color_index) |
575 | 168k | color0 = 1; |
576 | 168k | if (color1 != gx_no_color_index) |
577 | 168k | color1 = 1; |
578 | 168k | if (color0 == 1 && color1 == 1) |
579 | 168k | return (*dev_proc(padev->mask, fill_rectangle)) |
580 | 168k | ((gx_device *) padev->mask, x, y, w, h, (gx_color_index) 1); |
581 | 52 | else |
582 | 52 | return (*dev_proc(padev->mask, copy_mono)) |
583 | 52 | ((gx_device *) padev->mask, data, data_x, raster, id, x, y, w, h, |
584 | 52 | color0, color1); |
585 | 168k | } else |
586 | 0 | return 0; |
587 | 168k | } |
588 | | |
589 | | /* Copy a color bitmap. */ |
590 | | static int |
591 | | pattern_accum_copy_color(gx_device * dev, const byte * data, int data_x, |
592 | | int raster, gx_bitmap_id id, int x, int y, int w, int h) |
593 | 105k | { |
594 | 105k | gx_device_pattern_accum *const padev = (gx_device_pattern_accum *) dev; |
595 | | |
596 | 105k | if (padev->bits) |
597 | 105k | (*dev_proc(padev->target, copy_color)) |
598 | 105k | (padev->target, data, data_x, raster, id, x, y, w, h); |
599 | 105k | if (padev->mask) |
600 | 105k | return (*dev_proc(padev->mask, fill_rectangle)) |
601 | 105k | ((gx_device *) padev->mask, x, y, w, h, (gx_color_index) 1); |
602 | 0 | else |
603 | 0 | return 0; |
604 | 105k | } |
605 | | |
606 | | /* Copy a color plane. */ |
607 | | static int |
608 | | pattern_accum_copy_planes(gx_device * dev, const byte * data, int data_x, |
609 | | int raster, gx_bitmap_id id, |
610 | | int x, int y, int w, int h, int plane_height) |
611 | 320 | { |
612 | 320 | gx_device_pattern_accum *const padev = (gx_device_pattern_accum *) dev; |
613 | | |
614 | 320 | if (padev->bits) |
615 | 320 | (*dev_proc(padev->target, copy_planes)) |
616 | 320 | (padev->target, data, data_x, raster, id, x, y, w, h, plane_height); |
617 | 320 | if (padev->mask) |
618 | 320 | return (*dev_proc(padev->mask, fill_rectangle)) |
619 | 320 | ((gx_device *) padev->mask, x, y, w, h, (gx_color_index) 1); |
620 | 0 | else |
621 | 0 | return 0; |
622 | 320 | } |
623 | | |
624 | | static int |
625 | | blank_unmasked_bits(gx_device * mask, |
626 | | int polarity, |
627 | | int num_comps, |
628 | | int depth, |
629 | | const gs_int_rect *prect, |
630 | | gs_get_bits_params_t *p) |
631 | 0 | { |
632 | 0 | static const int required_options = GB_COLORS_NATIVE |
633 | 0 | | GB_ALPHA_NONE |
634 | 0 | | GB_RETURN_COPY |
635 | 0 | | GB_ALIGN_STANDARD |
636 | 0 | | GB_OFFSET_0 |
637 | 0 | | GB_RASTER_STANDARD; |
638 | 0 | int raster = p->raster; |
639 | 0 | byte *min; |
640 | 0 | int x0 = prect->p.x; |
641 | 0 | int y0 = prect->p.y; |
642 | 0 | int x, y; |
643 | 0 | int w = prect->q.x - x0; |
644 | 0 | int h = prect->q.y - y0; |
645 | 0 | int code = 0; |
646 | 0 | byte *ptr; |
647 | 0 | int blank = (polarity == GX_CINFO_POLARITY_ADDITIVE ? 255 : 0); |
648 | 0 | gs_int_rect rect; |
649 | 0 | gs_get_bits_params_t params; |
650 | |
|
651 | 0 | if ((p->options & required_options) != required_options) |
652 | 0 | return_error(gs_error_rangecheck); |
653 | | |
654 | 0 | min = gs_alloc_bytes(mask->memory, (w+7)>>3, "blank_unmasked_bits"); |
655 | 0 | if (min == NULL) |
656 | 0 | return_error(gs_error_VMerror); |
657 | | |
658 | 0 | rect.p.x = 0; |
659 | 0 | rect.q.x = mask->width; |
660 | 0 | params.x_offset = 0; |
661 | 0 | params.raster = bitmap_raster(mask->width * mask->color_info.depth); |
662 | |
|
663 | 0 | if (p->options & GB_PACKING_CHUNKY) |
664 | 0 | { |
665 | 0 | if ((depth & 7) != 0 || depth > 64) { |
666 | 0 | code = gs_note_error(gs_error_rangecheck); |
667 | 0 | goto fail; |
668 | 0 | } |
669 | 0 | ptr = p->data[0]; |
670 | 0 | depth >>= 3; |
671 | 0 | raster -= w*depth; |
672 | 0 | for (y = 0; y < h; y++) |
673 | 0 | { |
674 | 0 | byte *mine; |
675 | |
|
676 | 0 | rect.p.y = y+y0; |
677 | 0 | rect.q.y = y+y0+1; |
678 | 0 | params.options = (GB_ALIGN_ANY | |
679 | 0 | (GB_RETURN_COPY | GB_RETURN_POINTER) | |
680 | 0 | GB_OFFSET_0 | |
681 | 0 | GB_RASTER_STANDARD | GB_PACKING_CHUNKY | |
682 | 0 | GB_COLORS_NATIVE | GB_ALPHA_NONE); |
683 | 0 | params.data[0] = min; |
684 | 0 | code = (*dev_proc(mask, get_bits_rectangle))(mask, &rect, |
685 | 0 | ¶ms); |
686 | 0 | if (code < 0) |
687 | 0 | goto fail; |
688 | 0 | mine = params.data[0]; |
689 | 0 | for (x = 0; x < w; x++) |
690 | 0 | { |
691 | 0 | int xx = x+x0; |
692 | 0 | if (((mine[xx>>3]<<(x&7)) & 128) == 0) { |
693 | 0 | switch (depth) |
694 | 0 | { |
695 | 0 | case 8: |
696 | 0 | *ptr++ = blank; |
697 | 0 | case 7: |
698 | 0 | *ptr++ = blank; |
699 | 0 | case 6: |
700 | 0 | *ptr++ = blank; |
701 | 0 | case 5: |
702 | 0 | *ptr++ = blank; |
703 | 0 | case 4: |
704 | 0 | *ptr++ = blank; |
705 | 0 | case 3: |
706 | 0 | *ptr++ = blank; |
707 | 0 | case 2: |
708 | 0 | *ptr++ = blank; |
709 | 0 | case 1: |
710 | 0 | *ptr++ = blank; |
711 | 0 | break; |
712 | 0 | } |
713 | 0 | } else { |
714 | 0 | ptr += depth; |
715 | 0 | } |
716 | 0 | } |
717 | 0 | ptr += raster; |
718 | 0 | } |
719 | 0 | } else { |
720 | | /* Planar, only handle 8 or 16 bits */ |
721 | 0 | int bytes_per_component = (depth/num_comps) >> 3; |
722 | |
|
723 | 0 | if (depth/num_comps != 8 && depth/num_comps != 16) { |
724 | 0 | code = gs_note_error(gs_error_rangecheck); |
725 | 0 | goto fail; |
726 | 0 | } |
727 | 0 | for (y = 0; y < h; y++) |
728 | 0 | { |
729 | 0 | int c; |
730 | 0 | byte *mine; |
731 | |
|
732 | 0 | rect.p.y = y+y0; |
733 | 0 | rect.q.y = y+y0+1; |
734 | 0 | params.options = (GB_ALIGN_ANY | |
735 | 0 | (GB_RETURN_COPY | GB_RETURN_POINTER) | |
736 | 0 | GB_OFFSET_0 | |
737 | 0 | GB_RASTER_STANDARD | GB_PACKING_CHUNKY | |
738 | 0 | GB_COLORS_NATIVE | GB_ALPHA_NONE); |
739 | 0 | params.data[0] = min; |
740 | 0 | code = (*dev_proc(mask, get_bits_rectangle))(mask, &rect, |
741 | 0 | ¶ms); |
742 | 0 | if (code < 0) |
743 | 0 | goto fail; |
744 | 0 | mine = params.data[0]; |
745 | |
|
746 | 0 | for (c = 0; c < num_comps; c++) |
747 | 0 | { |
748 | 0 | if (p->data[c] == NULL) |
749 | 0 | continue; |
750 | 0 | ptr = p->data[c] + raster * y; |
751 | 0 | for (x = 0; x < w; x++) |
752 | 0 | { |
753 | 0 | int xx = x+x0; |
754 | 0 | if (((mine[xx>>3]>>(x&7)) & 1) == 0) { |
755 | 0 | *ptr++ = blank; |
756 | 0 | if (bytes_per_component > 1) |
757 | 0 | *ptr++ = blank; |
758 | 0 | } else { |
759 | 0 | ptr += bytes_per_component; |
760 | 0 | } |
761 | 0 | } |
762 | 0 | } |
763 | 0 | } |
764 | 0 | } |
765 | | |
766 | 0 | fail: |
767 | 0 | gs_free_object(mask->memory, min, "blank_unmasked_bits"); |
768 | |
|
769 | 0 | return code; |
770 | 0 | } |
771 | | |
772 | | /* Read back a rectangle of bits. */ |
773 | | /****** SHOULD USE MASK TO DEFINE UNREAD AREA *****/ |
774 | | static int |
775 | | pattern_accum_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect, |
776 | | gs_get_bits_params_t * params) |
777 | 0 | { |
778 | 0 | gx_device_pattern_accum *const padev = (gx_device_pattern_accum *) dev; |
779 | 0 | int code; |
780 | 0 | gs_get_bits_params_t params2 = *params; |
781 | |
|
782 | 0 | if (padev->bits) { |
783 | 0 | if (padev->mask) |
784 | 0 | params2.options &= ~GB_RETURN_POINTER; |
785 | 0 | code = (*dev_proc(padev->target, get_bits_rectangle)) |
786 | 0 | (padev->target, prect, ¶ms2); |
787 | | /* If we have a mask, then unmarked pixels of the bits |
788 | | * will be undefined. Strictly speaking it makes no |
789 | | * sense for us to return any value here, but the only |
790 | | * caller of this currently is the overprint code, which |
791 | | * uses the the values to parrot back to us. Let's |
792 | | * make sure they are set to the default 'empty' values. |
793 | | */ |
794 | 0 | if (code >= 0 && padev->mask) |
795 | 0 | code = blank_unmasked_bits((gx_device *)padev->mask, |
796 | 0 | padev->target->color_info.polarity, |
797 | 0 | padev->target->color_info.num_components, |
798 | 0 | padev->target->color_info.depth, |
799 | 0 | prect, ¶ms2); |
800 | 0 | return code; |
801 | 0 | } |
802 | | |
803 | 0 | return_error(gs_error_Fatal); /* shouldn't happen */ |
804 | 0 | } |
805 | | |
806 | | /* ------ Color space implementation ------ */ |
807 | | |
808 | | /* Free all entries in a pattern cache. */ |
809 | | static bool |
810 | | pattern_cache_choose_all(gx_color_tile * ctile, void *proc_data) |
811 | 186k | { |
812 | 186k | return true; |
813 | 186k | } |
814 | | static void |
815 | | pattern_cache_free_all(gx_pattern_cache * pcache) |
816 | 1.27M | { |
817 | 1.27M | gx_pattern_cache_winnow(pcache, pattern_cache_choose_all, NULL); |
818 | 1.27M | } |
819 | | |
820 | | /* Allocate a Pattern cache. */ |
821 | | gx_pattern_cache * |
822 | | gx_pattern_alloc_cache(gs_memory_t * mem, uint num_tiles, ulong max_bits) |
823 | 247k | { |
824 | 247k | gx_pattern_cache *pcache = |
825 | 247k | gs_alloc_struct(mem, gx_pattern_cache, &st_pattern_cache, |
826 | 247k | "gx_pattern_alloc_cache(struct)"); |
827 | 247k | gx_color_tile *tiles = |
828 | 247k | gs_alloc_struct_array(mem, num_tiles, gx_color_tile, |
829 | 247k | &st_color_tile_element, |
830 | 247k | "gx_pattern_alloc_cache(tiles)"); |
831 | 247k | uint i; |
832 | | |
833 | 247k | if (pcache == 0 || tiles == 0) { |
834 | 0 | gs_free_object(mem, tiles, "gx_pattern_alloc_cache(tiles)"); |
835 | 0 | gs_free_object(mem, pcache, "gx_pattern_alloc_cache(struct)"); |
836 | 0 | return 0; |
837 | 0 | } |
838 | 247k | pcache->memory = mem; |
839 | 247k | pcache->tiles = tiles; |
840 | 247k | pcache->num_tiles = num_tiles; |
841 | 247k | pcache->tiles_used = 0; |
842 | 247k | pcache->next = 0; |
843 | 247k | pcache->bits_used = 0; |
844 | 247k | pcache->max_bits = max_bits; |
845 | 247k | pcache->free_all = pattern_cache_free_all; |
846 | 12.6M | for (i = 0; i < num_tiles; tiles++, i++) { |
847 | 12.3M | tiles->id = gx_no_bitmap_id; |
848 | | /* Clear the pointers to pacify the GC. */ |
849 | 12.3M | uid_set_invalid(&tiles->uid); |
850 | 12.3M | tiles->bits_used = 0; |
851 | 12.3M | #ifdef PACIFY_VALGRIND |
852 | | /* The following memsets are required to avoid a valgrind warning |
853 | | * in: |
854 | | * gs -I./gs/lib -sOutputFile=out.pgm -dMaxBitmap=10000 |
855 | | * -sDEVICE=pgmraw -r300 -Z: -sDEFAULTPAPERSIZE=letter |
856 | | * -dNOPAUSE -dBATCH -K2000000 -dClusterJob -dJOBSERVER |
857 | | * tests_private/ps/ps3cet/11-14.PS |
858 | | * Setting the individual elements of the structures directly is |
859 | | * not enough, which leads me to believe that we are writing the |
860 | | * entire structs out, padding and all. |
861 | | */ |
862 | 12.3M | memset(&tiles->tbits, 0, sizeof(tiles->tbits)); |
863 | 12.3M | memset(&tiles->tmask, 0, sizeof(tiles->tmask)); |
864 | | #else |
865 | | tiles->tbits.data = 0; |
866 | | tiles->tmask.data = 0; |
867 | | tiles->tmask.rep_width = 0; |
868 | | tiles->tmask.rep_height = 0; |
869 | | tiles->tmask.num_planes = 0; |
870 | | #endif |
871 | 12.3M | tiles->index = i; |
872 | 12.3M | tiles->cdev = NULL; |
873 | 12.3M | tiles->ttrans = NULL; |
874 | 12.3M | tiles->num_planar_planes = 0; |
875 | 12.3M | } |
876 | 247k | return pcache; |
877 | 247k | } |
878 | | /* Ensure that an imager has a Pattern cache. */ |
879 | | static int |
880 | | ensure_pattern_cache(gs_gstate * pgs) |
881 | 566k | { |
882 | 566k | if (pgs->pattern_cache == 0) { |
883 | 85.1k | gx_pattern_cache *pcache = |
884 | 85.1k | gx_pattern_alloc_cache(pgs->memory, |
885 | 85.1k | gx_pat_cache_default_tiles(), |
886 | 85.1k | gx_pat_cache_default_bits()); |
887 | | |
888 | 85.1k | if (pcache == 0) |
889 | 0 | return_error(gs_error_VMerror); |
890 | 85.1k | pgs->pattern_cache = pcache; |
891 | 85.1k | } |
892 | 566k | return 0; |
893 | 566k | } |
894 | | |
895 | | /* Free pattern cache and its components. */ |
896 | | void |
897 | | gx_pattern_cache_free(gx_pattern_cache *pcache) |
898 | 179k | { |
899 | 179k | if (pcache == NULL) |
900 | 94.6k | return; |
901 | 85.1k | pattern_cache_free_all(pcache); |
902 | 85.1k | gs_free_object(pcache->memory, pcache->tiles, "gx_pattern_cache_free"); |
903 | 85.1k | pcache->tiles = NULL; |
904 | 85.1k | gs_free_object(pcache->memory, pcache, "gx_pattern_cache_free"); |
905 | 85.1k | } |
906 | | |
907 | | /* Get and set the Pattern cache in a gstate. */ |
908 | | gx_pattern_cache * |
909 | | gstate_pattern_cache(gs_gstate * pgs) |
910 | 105k | { |
911 | 105k | return pgs->pattern_cache; |
912 | 105k | } |
913 | | void |
914 | | gstate_set_pattern_cache(gs_gstate * pgs, gx_pattern_cache * pcache) |
915 | 162k | { |
916 | 162k | pgs->pattern_cache = pcache; |
917 | 162k | } |
918 | | |
919 | | /* Free a Pattern cache entry. */ |
920 | | /* This will not free a pattern if it is 'locked' which should only be for */ |
921 | | /* a stroke pattern during fill_stroke_path. */ |
922 | | static void |
923 | | gx_pattern_cache_free_entry(gx_pattern_cache * pcache, gx_color_tile * ctile, bool free_dummy) |
924 | 1.65M | { |
925 | 1.65M | gx_device *temp_device; |
926 | | |
927 | 1.65M | if ((ctile->id != gx_no_bitmap_id) && (!ctile->is_dummy || free_dummy) && !ctile->is_locked) { |
928 | 281k | gs_memory_t *mem = pcache->memory; |
929 | | |
930 | | /* |
931 | | * We must initialize the memory device properly, even though |
932 | | * we aren't using it for drawing. |
933 | | */ |
934 | 281k | if (ctile->tmask.data != 0) { |
935 | 67.1k | gs_free_object(mem, ctile->tmask.data, |
936 | 67.1k | "free_pattern_cache_entry(mask data)"); |
937 | 67.1k | ctile->tmask.data = 0; /* for GC */ |
938 | 67.1k | } |
939 | 281k | if (ctile->tbits.data != 0) { |
940 | 51.5k | gs_free_object(mem, ctile->tbits.data, |
941 | 51.5k | "free_pattern_cache_entry(bits data)"); |
942 | 51.5k | ctile->tbits.data = 0; /* for GC */ |
943 | 51.5k | } |
944 | 281k | if (ctile->cdev != NULL) { |
945 | 119k | ctile->cdev->common.do_not_open_or_close_bandfiles = false; /* make sure memfile gets freed/closed */ |
946 | 119k | dev_proc(&ctile->cdev->common, close_device)((gx_device *)&ctile->cdev->common); |
947 | | /* Free up the icc based stuff in the clist device. I am puzzled |
948 | | why the other objects are not released */ |
949 | 119k | clist_free_icc_table(ctile->cdev->common.icc_table, |
950 | 119k | ctile->cdev->common.memory); |
951 | 119k | ctile->cdev->common.icc_table = NULL; |
952 | 119k | rc_decrement(ctile->cdev->common.icc_cache_cl, |
953 | 119k | "gx_pattern_cache_free_entry"); |
954 | 119k | ctile->cdev->common.icc_cache_cl = NULL; |
955 | 119k | ctile->cdev->writer.pinst = NULL; |
956 | 119k | gs_free_object(ctile->cdev->common.memory->non_gc_memory, ctile->cdev->common.cache_chunk, "free tile cache for clist"); |
957 | 119k | ctile->cdev->common.cache_chunk = 0; |
958 | 119k | temp_device = (gx_device *)ctile->cdev; |
959 | 119k | gx_device_retain(temp_device, false); |
960 | 119k | ctile->cdev = NULL; |
961 | 119k | } |
962 | | |
963 | 281k | if (ctile->ttrans != NULL) { |
964 | 107k | if_debug2m('v', mem, |
965 | 107k | "[v*] Freeing trans pattern from cache, uid = %ld id = %ld\n", |
966 | 107k | ctile->uid.id, ctile->id); |
967 | 107k | if ( ctile->ttrans->pdev14 == NULL) { |
968 | | /* This can happen if we came from the clist */ |
969 | 107k | if (ctile->ttrans->mem != NULL) |
970 | 107k | gs_free_object(ctile->ttrans->mem ,ctile->ttrans->transbytes, |
971 | 107k | "free_pattern_cache_entry(transbytes)"); |
972 | 107k | gs_free_object(mem,ctile->ttrans->fill_trans_buffer, |
973 | 107k | "free_pattern_cache_entry(fill_trans_buffer)"); |
974 | 107k | ctile->ttrans->transbytes = NULL; |
975 | 107k | ctile->ttrans->fill_trans_buffer = NULL; |
976 | 107k | } else { |
977 | 0 | dev_proc(ctile->ttrans->pdev14, close_device)((gx_device *)ctile->ttrans->pdev14); |
978 | 0 | temp_device = (gx_device *)(ctile->ttrans->pdev14); |
979 | 0 | gx_device_retain(temp_device, false); |
980 | 0 | rc_decrement(temp_device,"gx_pattern_cache_free_entry"); |
981 | 0 | ctile->ttrans->pdev14 = NULL; |
982 | 0 | ctile->ttrans->transbytes = NULL; /* should be ok due to pdf14_close */ |
983 | 0 | ctile->ttrans->fill_trans_buffer = NULL; /* This is always freed */ |
984 | 0 | } |
985 | | |
986 | 107k | gs_free_object(mem, ctile->ttrans, |
987 | 107k | "free_pattern_cache_entry(ttrans)"); |
988 | 107k | ctile->ttrans = NULL; |
989 | | |
990 | 107k | } |
991 | | |
992 | 281k | pcache->tiles_used--; |
993 | 281k | pcache->bits_used -= ctile->bits_used; |
994 | 281k | ctile->id = gx_no_bitmap_id; |
995 | 281k | } |
996 | 1.65M | } |
997 | | |
998 | | /* |
999 | | Historically, the pattern cache has used a very simple hashing |
1000 | | scheme whereby pattern A goes into slot idx = (A.id % num_tiles). |
1001 | | Unfortunately, now we allow tiles to be 'locked' into the |
1002 | | pattern cache, we might run into the case where we want both |
1003 | | tiles A and B to be in the cache at once where: |
1004 | | (A.id % num_tiles) == (B.id % num_tiles). |
1005 | | |
1006 | | We have a maximum of 2 locked tiles, and one of those can be |
1007 | | placed while the other one is locked. So we only need to cope |
1008 | | with a single 'collision'. |
1009 | | |
1010 | | We therefore allow tiles to either go in at idx or at |
1011 | | (idx + 1) % num_tiles. This means we need to be prepared to |
1012 | | search a bit further for them, hence we now have 2 helper |
1013 | | functions to do this. |
1014 | | */ |
1015 | | |
1016 | | /* We can have at most 1 locked tile while looking for a place to |
1017 | | * put another tile. */ |
1018 | | gx_color_tile * |
1019 | | gx_pattern_cache_find_tile_for_id(gx_pattern_cache *pcache, gs_id id) |
1020 | 2.60M | { |
1021 | 2.60M | gx_color_tile *ctile = &pcache->tiles[id % pcache->num_tiles]; |
1022 | 2.60M | gx_color_tile *ctile2 = &pcache->tiles[(id+1) % pcache->num_tiles]; |
1023 | 2.60M | if (ctile->id == id || ctile->id == gs_no_id) |
1024 | 2.58M | return ctile; |
1025 | 12.4k | if (ctile2->id == id || ctile2->id == gs_no_id) |
1026 | 10.6k | return ctile2; |
1027 | 1.86k | if (!ctile->is_locked) |
1028 | 1.86k | return ctile; |
1029 | 0 | return ctile2; |
1030 | 1.86k | } |
1031 | | |
1032 | | |
1033 | | /* Given the size of a new pattern tile, free entries from the cache until */ |
1034 | | /* enough space is available (or nothing left to free). */ |
1035 | | /* This will allow 1 oversized entry */ |
1036 | | void |
1037 | | gx_pattern_cache_ensure_space(gs_gstate * pgs, size_t needed) |
1038 | 281k | { |
1039 | 281k | int code = ensure_pattern_cache(pgs); |
1040 | 281k | gx_pattern_cache *pcache; |
1041 | 281k | int start_free_id; |
1042 | | |
1043 | 281k | if (code < 0) |
1044 | 0 | return; /* no cache -- just exit */ |
1045 | | |
1046 | 281k | pcache = pgs->pattern_cache; |
1047 | 281k | start_free_id = pcache->next; /* for scan wrap check */ |
1048 | | /* If too large then start freeing entries */ |
1049 | | /* By starting just after 'next', we attempt to first free the oldest entries */ |
1050 | 1.44M | while (pcache->bits_used + needed > pcache->max_bits && |
1051 | 1.44M | pcache->bits_used != 0) { |
1052 | 1.16M | pcache->next = (pcache->next + 1) % pcache->num_tiles; |
1053 | 1.16M | gx_pattern_cache_free_entry(pcache, &pcache->tiles[pcache->next], false); |
1054 | | /* since a pattern may be temporarily locked (stroke pattern for fill_stroke_path) */ |
1055 | | /* we may not have freed all entries even though we've scanned the entire cache. */ |
1056 | | /* The following check for wrapping prevents infinite loop if stroke pattern was */ |
1057 | | /* larger than pcache->max_bits, */ |
1058 | 1.16M | if (pcache->next == start_free_id) |
1059 | 1.12k | break; /* we wrapped -- cache may not be empty */ |
1060 | 1.16M | } |
1061 | 281k | } |
1062 | | |
1063 | | /* Export updating the pattern_cache bits_used and tiles_used for clist reading */ |
1064 | | void |
1065 | | gx_pattern_cache_update_used(gs_gstate *pgs, size_t used) |
1066 | 278k | { |
1067 | 278k | gx_pattern_cache *pcache = pgs->pattern_cache; |
1068 | | |
1069 | 278k | pcache->bits_used += used; |
1070 | 278k | pcache->tiles_used++; |
1071 | 278k | } |
1072 | | |
1073 | | /* |
1074 | | * Add a Pattern cache entry. This is exported for the interpreter. |
1075 | | * Note that this does not free any of the data in the accumulator |
1076 | | * device, but it may zero out the bitmap_memory pointers to prevent |
1077 | | * the accumulated bitmaps from being freed when the device is closed. |
1078 | | */ |
1079 | | static void make_bitmap(gx_strip_bitmap *, const gx_device_memory *, gx_bitmap_id, const gs_memory_t *); |
1080 | | int |
1081 | | gx_pattern_cache_add_entry(gs_gstate * pgs, |
1082 | | gx_device_forward * fdev, gx_color_tile ** pctile) |
1083 | 23.2k | { |
1084 | 23.2k | gx_pattern_cache *pcache; |
1085 | 23.2k | const gs_pattern1_instance_t *pinst; |
1086 | 23.2k | size_t used = 0, mask_used = 0, trans_used = 0; |
1087 | 23.2k | gx_bitmap_id id; |
1088 | 23.2k | gx_color_tile *ctile; |
1089 | 23.2k | int code = ensure_pattern_cache(pgs); |
1090 | 23.2k | gx_device_memory *mmask = NULL; |
1091 | 23.2k | gx_device_memory *mbits = NULL; |
1092 | 23.2k | gx_pattern_trans_t *trans = NULL; |
1093 | 23.2k | int size_b, size_c; |
1094 | | |
1095 | 23.2k | if (code < 0) |
1096 | 0 | return code; |
1097 | 23.2k | pcache = pgs->pattern_cache; |
1098 | | |
1099 | 23.2k | if (dev_proc(fdev, open_device) != pattern_clist_open_device) { |
1100 | 20.4k | gx_device_pattern_accum *padev = (gx_device_pattern_accum *)fdev; |
1101 | | |
1102 | 20.4k | mbits = padev->bits; |
1103 | 20.4k | mmask = padev->mask; |
1104 | 20.4k | pinst = padev->instance; |
1105 | 20.4k | trans = padev->transbuff; |
1106 | | |
1107 | | /* |
1108 | | * Check whether the pattern completely fills its box. |
1109 | | * If so, we can avoid the expensive masking operations |
1110 | | * when using the pattern. |
1111 | | */ |
1112 | | /* Bug 700624: In cases where the mask is completely full, |
1113 | | * but the pattern cells are separated from one another, |
1114 | | * we need to leave gaps between the cells when rendering |
1115 | | * them. Sadly, the graphics library can't cope with this |
1116 | | * in the no-mask case. Therefore, only do the optimisation |
1117 | | * of not sending the mask if the step matrix is suitable. |
1118 | | * |
1119 | | * To do this, we compare the step matrix to the size. My |
1120 | | * belief is that the mask will only ever be full if it's |
1121 | | * orthogonal, cos otherwise the edges will be clipped, |
1122 | | * hence we lose no generality by checking for .xy and .yx |
1123 | | * being 0. |
1124 | | */ |
1125 | 20.4k | if (mmask != 0 && |
1126 | 20.4k | fabsf(pinst->step_matrix.xx) <= pinst->size.x && |
1127 | 20.4k | fabsf(pinst->step_matrix.yy) <= pinst->size.y && |
1128 | 20.4k | pinst->step_matrix.xy == 0 && |
1129 | 20.4k | pinst->step_matrix.yx == 0) { |
1130 | 17.2k | int y; |
1131 | 17.2k | int w_less_8 = mmask->width-8; |
1132 | | |
1133 | 37.4k | for (y = 0; y < mmask->height; y++) { |
1134 | 37.2k | const byte *row = scan_line_base(mmask, y); |
1135 | 37.2k | int w; |
1136 | | |
1137 | 1.54M | for (w = w_less_8; w > 0; w -= 8) |
1138 | 1.52M | if (*row++ != 0xff) |
1139 | 17.0k | goto keep; |
1140 | 20.1k | w += 8; |
1141 | 20.1k | if ((*row | (0xff >> w)) != 0xff) |
1142 | 36 | goto keep; |
1143 | 20.1k | } |
1144 | | /* We don't need a mask. */ |
1145 | 191 | mmask = 0; |
1146 | 17.2k | keep:; |
1147 | 17.2k | } |
1148 | | /* Need to get size of buffers that are being added to the cache */ |
1149 | 20.4k | if (mbits != 0) |
1150 | 4.09k | gdev_mem_bitmap_size(mbits, &used); |
1151 | 20.4k | if (mmask != 0) { |
1152 | 20.2k | gdev_mem_bitmap_size(mmask, &mask_used); |
1153 | 20.2k | used += mask_used; |
1154 | 20.2k | } |
1155 | 20.4k | if (trans != 0) { |
1156 | 16.1k | trans_used = (size_t)trans->planestride*trans->n_chan; |
1157 | 16.1k | used += trans_used; |
1158 | 16.1k | } |
1159 | 20.4k | } else { |
1160 | 2.84k | gx_device_clist *cdev = (gx_device_clist *)fdev; |
1161 | 2.84k | gx_device_clist_writer * cldev = (gx_device_clist_writer *)cdev; |
1162 | | |
1163 | 2.84k | code = clist_end_page(cldev); |
1164 | 2.84k | if (code < 0) |
1165 | 0 | return code; |
1166 | 2.84k | pinst = cdev->writer.pinst; |
1167 | 2.84k | size_b = clist_data_size(cdev, 0); |
1168 | 2.84k | if (size_b < 0) |
1169 | 0 | return_error(gs_error_unregistered); |
1170 | 2.84k | size_c = clist_data_size(cdev, 1); |
1171 | 2.84k | if (size_c < 0) |
1172 | 0 | return_error(gs_error_unregistered); |
1173 | | /* The memfile size is the size, not the size determined by the depth*width*height */ |
1174 | 2.84k | used = size_b + size_c; |
1175 | 2.84k | } |
1176 | 23.2k | id = pinst->id; |
1177 | 23.2k | ctile = gx_pattern_cache_find_tile_for_id(pcache, id); |
1178 | 23.2k | gx_pattern_cache_free_entry(pcache, ctile, false); /* ensure that this cache slot is empty */ |
1179 | 23.2k | ctile->id = id; |
1180 | 23.2k | ctile->num_planar_planes = pinst->num_planar_planes; |
1181 | 23.2k | ctile->depth = fdev->color_info.depth; |
1182 | 23.2k | ctile->uid = pinst->templat.uid; |
1183 | 23.2k | ctile->tiling_type = pinst->templat.TilingType; |
1184 | 23.2k | ctile->step_matrix = pinst->step_matrix; |
1185 | 23.2k | ctile->bbox = pinst->bbox; |
1186 | 23.2k | ctile->is_simple = pinst->is_simple; |
1187 | 23.2k | ctile->has_overlap = pinst->has_overlap; |
1188 | 23.2k | ctile->is_dummy = false; |
1189 | 23.2k | ctile->is_locked = false; |
1190 | 23.2k | ctile->blending_mode = 0; |
1191 | 23.2k | ctile->trans_group_popped = false; |
1192 | 23.2k | if (dev_proc(fdev, open_device) != pattern_clist_open_device) { |
1193 | 20.4k | if (mbits != 0) { |
1194 | 4.09k | make_bitmap(&ctile->tbits, mbits, gs_next_ids(pgs->memory, 1), pgs->memory); |
1195 | 4.09k | mbits->bitmap_memory = 0; /* don't free the bits */ |
1196 | 4.09k | } else |
1197 | 16.3k | ctile->tbits.data = 0; |
1198 | 20.4k | if (mmask != 0) { |
1199 | 20.2k | make_bitmap(&ctile->tmask, mmask, id, pgs->memory); |
1200 | 20.2k | mmask->bitmap_memory = 0; /* don't free the bits */ |
1201 | 20.2k | } else |
1202 | 191 | ctile->tmask.data = 0; |
1203 | 20.4k | if (trans != 0) { |
1204 | 16.1k | if_debug2m('v', pgs->memory, |
1205 | 16.1k | "[v*] Adding trans pattern to cache, uid = %ld id = %ld\n", |
1206 | 16.1k | ctile->uid.id, ctile->id); |
1207 | 16.1k | ctile->ttrans = trans; |
1208 | 16.1k | } |
1209 | | |
1210 | 20.4k | ctile->cdev = NULL; |
1211 | 20.4k | } else { |
1212 | 2.84k | gx_device_clist *cdev = (gx_device_clist *)fdev; |
1213 | 2.84k | gx_device_clist_writer *cwdev = (gx_device_clist_writer *)fdev; |
1214 | | |
1215 | 2.84k | ctile->tbits.data = 0; |
1216 | 2.84k | ctile->tbits.size.x = 0; |
1217 | 2.84k | ctile->tbits.size.y = 0; |
1218 | 2.84k | ctile->tmask.data = 0; |
1219 | 2.84k | ctile->tmask.size.x = 0; |
1220 | 2.84k | ctile->tmask.size.y = 0; |
1221 | 2.84k | ctile->cdev = cdev; |
1222 | | /* Prevent freeing files on pattern_paint_cleanup : */ |
1223 | 2.84k | cwdev->do_not_open_or_close_bandfiles = true; |
1224 | 2.84k | } |
1225 | | /* In the clist case, used is accurate. In the non-clist case, it may |
1226 | | * not be. The important thing is that we account the same for tiles |
1227 | | * going in and coming out of the cache. Therefore we store the used |
1228 | | * figure in the tile so we always remove the same amount. */ |
1229 | 23.2k | ctile->bits_used = used; |
1230 | 23.2k | gx_pattern_cache_update_used(pgs, used); |
1231 | | |
1232 | 23.2k | *pctile = ctile; |
1233 | 23.2k | return 0; |
1234 | 23.2k | } |
1235 | | |
1236 | | /* set or clear the 'is_locked' flag for a tile in the cache. Used by */ |
1237 | | /* fill_stroke_path to make sure a large stroke pattern stays in the */ |
1238 | | /* cache even if the fill is also a pattern. */ |
1239 | | int |
1240 | | gx_pattern_cache_entry_set_lock(gs_gstate *pgs, gs_id id, bool new_lock_value) |
1241 | 2.61k | { |
1242 | 2.61k | gx_color_tile *ctile; |
1243 | 2.61k | int code = ensure_pattern_cache(pgs); |
1244 | | |
1245 | 2.61k | if (code < 0) |
1246 | 0 | return code; |
1247 | 2.61k | ctile = gx_pattern_cache_find_tile_for_id(pgs->pattern_cache, id); |
1248 | 2.61k | if (ctile == NULL) |
1249 | 0 | return_error(gs_error_undefined); |
1250 | 2.61k | ctile->is_locked = new_lock_value; |
1251 | 2.61k | return 0; |
1252 | 2.61k | } |
1253 | | |
1254 | | /* Get entry for reading a pattern from clist. */ |
1255 | | int |
1256 | | gx_pattern_cache_get_entry(gs_gstate * pgs, gs_id id, gx_color_tile ** pctile) |
1257 | 254k | { |
1258 | 254k | gx_pattern_cache *pcache; |
1259 | 254k | gx_color_tile *ctile; |
1260 | 254k | int code = ensure_pattern_cache(pgs); |
1261 | | |
1262 | 254k | if (code < 0) |
1263 | 0 | return code; |
1264 | 254k | pcache = pgs->pattern_cache; |
1265 | 254k | ctile = gx_pattern_cache_find_tile_for_id(pcache, id); |
1266 | 254k | gx_pattern_cache_free_entry(pgs->pattern_cache, ctile, false); |
1267 | 254k | ctile->id = id; |
1268 | 254k | *pctile = ctile; |
1269 | 254k | return 0; |
1270 | 254k | } |
1271 | | |
1272 | | bool |
1273 | | gx_pattern_tile_is_clist(gx_color_tile *ptile) |
1274 | 817k | { |
1275 | 817k | return ptile != NULL && ptile->cdev != NULL; |
1276 | 817k | } |
1277 | | |
1278 | | /* Add a dummy Pattern cache entry. Stubs a pattern tile for interpreter when |
1279 | | device handles high level patterns. */ |
1280 | | int |
1281 | | gx_pattern_cache_add_dummy_entry(gs_gstate *pgs, |
1282 | | gs_pattern1_instance_t *pinst, int depth) |
1283 | 3.69k | { |
1284 | 3.69k | gx_color_tile *ctile; |
1285 | 3.69k | gx_pattern_cache *pcache; |
1286 | 3.69k | gx_bitmap_id id = pinst->id; |
1287 | 3.69k | int code = ensure_pattern_cache(pgs); |
1288 | | |
1289 | 3.69k | if (code < 0) |
1290 | 0 | return code; |
1291 | 3.69k | pcache = pgs->pattern_cache; |
1292 | 3.69k | ctile = gx_pattern_cache_find_tile_for_id(pcache, id); |
1293 | 3.69k | gx_pattern_cache_free_entry(pcache, ctile, false); |
1294 | 3.69k | ctile->id = id; |
1295 | 3.69k | ctile->depth = depth; |
1296 | 3.69k | ctile->uid = pinst->templat.uid; |
1297 | 3.69k | ctile->tiling_type = pinst->templat.TilingType; |
1298 | 3.69k | ctile->step_matrix = pinst->step_matrix; |
1299 | 3.69k | ctile->bbox = pinst->bbox; |
1300 | 3.69k | ctile->is_simple = pinst->is_simple; |
1301 | 3.69k | ctile->has_overlap = pinst->has_overlap; |
1302 | 3.69k | ctile->is_dummy = true; |
1303 | 3.69k | ctile->is_locked = false; |
1304 | 3.69k | memset(&ctile->tbits, 0 , sizeof(ctile->tbits)); |
1305 | 3.69k | ctile->tbits.size = pinst->size; |
1306 | 3.69k | ctile->tbits.id = gs_no_bitmap_id; |
1307 | 3.69k | memset(&ctile->tmask, 0 , sizeof(ctile->tmask)); |
1308 | 3.69k | ctile->cdev = NULL; |
1309 | 3.69k | ctile->ttrans = NULL; |
1310 | 3.69k | ctile->bits_used = 0; |
1311 | 3.69k | pcache->tiles_used++; |
1312 | 3.69k | return 0; |
1313 | 3.69k | } |
1314 | | |
1315 | | #if RAW_PATTERN_DUMP |
1316 | | /* Debug dump of pattern image data. Saved in |
1317 | | interleaved form with global indexing in |
1318 | | file name */ |
1319 | | static void |
1320 | | dump_raw_pattern(int height, int width, int n_chan, int depth, |
1321 | | byte *Buffer, int raster, const gx_device_memory * mdev, |
1322 | | const gs_memory_t *memory) |
1323 | | { |
1324 | | char full_file_name[50]; |
1325 | | gp_file *fid; |
1326 | | int max_bands; |
1327 | | int j, k, m; |
1328 | | int byte_number, bit_position; |
1329 | | unsigned char current_byte; |
1330 | | unsigned char output_val; |
1331 | | bool is_planar; |
1332 | | byte *curr_ptr = Buffer; |
1333 | | int plane_offset; |
1334 | | |
1335 | | is_planar = mdev->num_planar_planes > 0; |
1336 | | max_bands = ( n_chan < 57 ? n_chan : 56); /* Photoshop handles at most 56 bands */ |
1337 | | if (is_planar) { |
1338 | | gs_snprintf(full_file_name, sizeof(full_file_name), "%d)PATTERN_PLANE_%dx%dx%d.raw", global_pat_index, |
1339 | | mdev->raster, height, max_bands); |
1340 | | } else { |
1341 | | gs_snprintf(full_file_name, sizeof(full_file_name), "%d)PATTERN_CHUNK_%dx%dx%d.raw", global_pat_index, |
1342 | | width, height, max_bands); |
1343 | | } |
1344 | | fid = gp_fopen(memory,full_file_name,"wb"); |
1345 | | if (depth >= 8) { |
1346 | | /* Contone data. */ |
1347 | | if (is_planar) { |
1348 | | for (m = 0; m < max_bands; m++) { |
1349 | | curr_ptr = mdev->line_ptrs[m*mdev->height]; |
1350 | | gp_fwrite(curr_ptr, 1, mdev->height * mdev->raster, fid); |
1351 | | } |
1352 | | } else { |
1353 | | /* Just dump it like it is */ |
1354 | | gp_fwrite(Buffer, 1, max_bands * height * width, fid); |
1355 | | } |
1356 | | } else { |
1357 | | /* Binary Data. Lets get to 8 bit for debugging. We have to |
1358 | | worry about planar vs. chunky. Note this assumes 1 bit data |
1359 | | only. */ |
1360 | | if (is_planar) { |
1361 | | plane_offset = mdev->raster * mdev->height; |
1362 | | for (m = 0; m < max_bands; m++) { |
1363 | | curr_ptr = mdev->line_ptrs[m*mdev->height]; |
1364 | | for (j = 0; j < height; j++) { |
1365 | | for (k = 0; k < width; k++) { |
1366 | | byte_number = (int) ceil((( (float) k + 1.0) / 8.0)) - 1; |
1367 | | current_byte = curr_ptr[j*(mdev->raster) + byte_number]; |
1368 | | bit_position = 7 - (k - byte_number*8); |
1369 | | output_val = ((current_byte >> bit_position) & 0x1) * 255; |
1370 | | gp_fwrite(&output_val,1,1,fid); |
1371 | | } |
1372 | | } |
1373 | | } |
1374 | | } else { |
1375 | | for (j = 0; j < height; j++) { |
1376 | | for (k = 0; k < width; k++) { |
1377 | | for (m = 0; m < max_bands; m++) { |
1378 | | /* index current byte */ |
1379 | | byte_number = |
1380 | | (int) ceil((( (float) k * (float) max_bands + |
1381 | | (float) m + 1.0) / 8.0)) - 1; |
1382 | | /* get byte of interest */ |
1383 | | current_byte = |
1384 | | curr_ptr[j*(mdev->raster) + byte_number]; |
1385 | | /* get bit position */ |
1386 | | bit_position = |
1387 | | 7 - (k * max_bands + m - byte_number * 8); |
1388 | | /* extract and create byte */ |
1389 | | output_val = |
1390 | | ((current_byte >> bit_position) & 0x1) * 255; |
1391 | | gp_fwrite(&output_val,1,1,fid); |
1392 | | } |
1393 | | } |
1394 | | } |
1395 | | } |
1396 | | } |
1397 | | gp_fclose(fid); |
1398 | | } |
1399 | | #endif |
1400 | | |
1401 | | static void |
1402 | | make_bitmap(register gx_strip_bitmap * pbm, const gx_device_memory * mdev, |
1403 | | gx_bitmap_id id, const gs_memory_t *memory) |
1404 | 24.3k | { |
1405 | 24.3k | pbm->data = mdev->base; |
1406 | 24.3k | pbm->raster = mdev->raster; |
1407 | 24.3k | pbm->rep_width = pbm->size.x = mdev->width; |
1408 | 24.3k | pbm->rep_height = pbm->size.y = mdev->height; |
1409 | 24.3k | pbm->id = id; |
1410 | 24.3k | pbm->rep_shift = pbm->shift = 0; |
1411 | 24.3k | pbm->num_planes = mdev->num_planar_planes ? mdev->num_planar_planes : 1; |
1412 | | |
1413 | | /* Lets dump this for debug purposes */ |
1414 | | |
1415 | | #if RAW_PATTERN_DUMP |
1416 | | dump_raw_pattern(pbm->rep_height, pbm->rep_width, |
1417 | | mdev->color_info.num_components, |
1418 | | mdev->color_info.depth, |
1419 | | (unsigned char*) mdev->base, |
1420 | | pbm->raster, mdev, memory); |
1421 | | |
1422 | | global_pat_index++; |
1423 | | |
1424 | | #endif |
1425 | | |
1426 | 24.3k | } |
1427 | | |
1428 | | /* Purge selected entries from the pattern cache. */ |
1429 | | void |
1430 | | gx_pattern_cache_winnow(gx_pattern_cache * pcache, |
1431 | | bool(*proc) (gx_color_tile * ctile, void *proc_data), void *proc_data) |
1432 | 1.27M | { |
1433 | 1.27M | uint i; |
1434 | | |
1435 | 1.27M | if (pcache == 0) /* no cache created yet */ |
1436 | 0 | return; |
1437 | 64.8M | for (i = 0; i < pcache->num_tiles; ++i) { |
1438 | 63.5M | gx_color_tile *ctile = &pcache->tiles[i]; |
1439 | | |
1440 | 63.5M | ctile->is_locked = false; /* force freeing */ |
1441 | 63.5M | if (ctile->id != gx_no_bitmap_id && (*proc) (ctile, proc_data)) |
1442 | 186k | gx_pattern_cache_free_entry(pcache, ctile, false); |
1443 | 63.5M | } |
1444 | 1.27M | } |
1445 | | |
1446 | | void |
1447 | | gx_pattern_cache_flush(gx_pattern_cache * pcache) |
1448 | 105k | { |
1449 | 105k | uint i; |
1450 | | |
1451 | 105k | if (pcache == 0) /* no cache created yet */ |
1452 | 0 | return; |
1453 | 5.35M | for (i = 0; i < pcache->num_tiles; ++i) { |
1454 | 5.25M | gx_color_tile *ctile = &pcache->tiles[i]; |
1455 | | |
1456 | 5.25M | ctile->is_locked = false; /* force freeing */ |
1457 | 5.25M | if (ctile->id != gx_no_bitmap_id) |
1458 | 21.6k | gx_pattern_cache_free_entry(pcache, ctile, true); |
1459 | 5.25M | } |
1460 | 105k | } |
1461 | | |
1462 | | /* blank the pattern accumulator device assumed to be in the graphics |
1463 | | state */ |
1464 | | int |
1465 | | gx_erase_colored_pattern(gs_gstate *pgs) |
1466 | 4.09k | { |
1467 | 4.09k | int code; |
1468 | 4.09k | gx_device_pattern_accum *pdev = (gx_device_pattern_accum *)gs_currentdevice(pgs); |
1469 | | |
1470 | 4.09k | if ((code = gs_gsave(pgs)) < 0) |
1471 | 0 | return code; |
1472 | 4.09k | if ((code = gs_setgray(pgs, 1.0)) >= 0) { |
1473 | 4.09k | gs_rect rect; |
1474 | 4.09k | gx_device_memory *mask; |
1475 | 4.09k | static const gs_matrix identity = { 1, 0, 0, 1, 0, 0 }; |
1476 | | |
1477 | 4.09k | pgs->log_op = lop_default; |
1478 | 4.09k | rect.p.x = 0.0; |
1479 | 4.09k | rect.p.y = 0.0; |
1480 | 4.09k | rect.q.x = (double)pdev->width; |
1481 | 4.09k | rect.q.y = (double)pdev->height; |
1482 | | |
1483 | 4.09k | code = gs_setmatrix(pgs, &identity); |
1484 | 4.09k | if (code < 0) { |
1485 | 0 | gs_grestore_only(pgs); |
1486 | 0 | return code; |
1487 | 0 | } |
1488 | | /* we don't want the fill rectangle device call to use the |
1489 | | mask */ |
1490 | 4.09k | mask = pdev->mask; |
1491 | 4.09k | pdev->mask = NULL; |
1492 | 4.09k | code = gs_rectfill(pgs, &rect, 1); |
1493 | | /* restore the mask */ |
1494 | 4.09k | pdev->mask = mask; |
1495 | 4.09k | if (code < 0) { |
1496 | 0 | gs_grestore_only(pgs); |
1497 | 0 | return code; |
1498 | 0 | } |
1499 | 4.09k | } |
1500 | | /* we don't need wraparound here */ |
1501 | 4.09k | gs_grestore_only(pgs); |
1502 | 4.09k | return code; |
1503 | 4.09k | } |
1504 | | |
1505 | | /* Reload a (non-null) Pattern color into the cache. */ |
1506 | | /* *pdc is already set, except for colors.pattern.p_tile and mask.m_tile. */ |
1507 | | int |
1508 | | gx_pattern_load(gx_device_color * pdc, const gs_gstate * pgs, |
1509 | | gx_device * dev, gs_color_select_t select) |
1510 | 28.1k | { |
1511 | 28.1k | gx_device_forward *adev = NULL; |
1512 | 28.1k | gs_pattern1_instance_t *pinst = |
1513 | 28.1k | (gs_pattern1_instance_t *)pdc->ccolor.pattern; |
1514 | 28.1k | gs_gstate *saved; |
1515 | 28.1k | gx_color_tile *ctile; |
1516 | 28.1k | gs_memory_t *mem = pgs->memory; |
1517 | 28.1k | bool has_tags = device_encodes_tags(dev); |
1518 | 28.1k | int code; |
1519 | | |
1520 | 28.1k | if (pgs->pattern_cache == NULL) |
1521 | 0 | if ((code = ensure_pattern_cache((gs_gstate *) pgs))< 0) /* break const for call */ |
1522 | 0 | return code; |
1523 | | |
1524 | 28.1k | if (gx_pattern_cache_lookup(pdc, pgs, dev, select)) |
1525 | 1.13k | return 0; |
1526 | | |
1527 | | /* Get enough space in the cache for this pattern (estimated if it is a clist) */ |
1528 | 27.0k | gx_pattern_cache_ensure_space((gs_gstate *)pgs, gx_pattern_size_estimate(pinst, has_tags)); |
1529 | | /* |
1530 | | * Note that adev is an internal device, so it will be freed when the |
1531 | | * last reference to it from a graphics state is deleted. |
1532 | | */ |
1533 | 27.0k | adev = gx_pattern_accum_alloc(mem, pgs->pattern_cache->memory, pinst, "gx_pattern_load"); |
1534 | 27.0k | if (adev == 0) |
1535 | 0 | return_error(gs_error_VMerror); |
1536 | 27.0k | gx_device_set_target((gx_device_forward *)adev, dev); |
1537 | 27.0k | code = dev_proc(adev, open_device)((gx_device *)adev); |
1538 | 27.0k | if (code < 0) { |
1539 | 0 | gs_free_object(mem, adev, "gx_pattern_load"); |
1540 | 0 | return code; |
1541 | 0 | } |
1542 | 27.0k | saved = gs_gstate_copy(pinst->saved, pinst->saved->memory); |
1543 | 27.0k | if (saved == 0) { |
1544 | 0 | code = gs_note_error(gs_error_VMerror); |
1545 | 0 | goto fail; |
1546 | 0 | } |
1547 | 27.0k | if (saved->pattern_cache == 0) |
1548 | 0 | saved->pattern_cache = pgs->pattern_cache; |
1549 | 27.0k | code = gs_setdevice_no_init(saved, (gx_device *)adev); |
1550 | 27.0k | if (code < 0) |
1551 | 0 | goto fail; |
1552 | 27.0k | if (pinst->templat.uses_transparency) { |
1553 | 18.5k | if_debug1m('v', mem, "gx_pattern_load: pushing the pdf14 compositor device into this graphics state pat_id = %ld\n", pinst->id); |
1554 | 18.5k | if ((code = gs_push_pdf14trans_device(saved, true, false, 0, 0)) < 0) /* spot_color_count taken from pdf14 target values */ |
1555 | 40 | goto fail; |
1556 | 18.4k | saved->device->is_open = true; |
1557 | 18.4k | } else { |
1558 | | /* For colored patterns we clear the pattern device's |
1559 | | background. This is necessary for the anti aliasing code |
1560 | | and (unfortunately) it masks a difficult to fix UMR |
1561 | | affecting pcl patterns, see bug #690487. Note we have to |
1562 | | make a similar change in zpcolor.c where much of this |
1563 | | pattern code is duplicated to support high level stream |
1564 | | patterns. */ |
1565 | 8.51k | if (pinst->templat.PaintType == 1 && !(pinst->is_clist) |
1566 | 8.51k | && dev_proc(pinst->saved->device, dev_spec_op)(pinst->saved->device, gxdso_pattern_can_accum, NULL, 0) == 0) |
1567 | 4.09k | if ((code = gx_erase_colored_pattern(saved)) < 0) |
1568 | 0 | goto fail; |
1569 | 8.51k | } |
1570 | | |
1571 | 26.9k | code = (*pinst->templat.PaintProc)(&pdc->ccolor, saved); |
1572 | 26.9k | if (code < 0) { |
1573 | 3.69k | if (dev_proc(adev, open_device) == pattern_accum_open) { |
1574 | | /* free pattern cache data that never got added to the dictionary */ |
1575 | 2.25k | gx_device_pattern_accum *padev = (gx_device_pattern_accum *) adev; |
1576 | 2.25k | if ((padev->bits != NULL) && (padev->bits->base != NULL)) { |
1577 | 267 | gs_free_object(padev->bits->memory, padev->bits->base, "mem_open"); |
1578 | 267 | } |
1579 | 2.25k | } |
1580 | | /* RJW: At this point, in the non transparency case, |
1581 | | * saved->device == adev. So unretain it, close it, and the |
1582 | | * gs_gstate_free(saved) will remove it. In the transparency case, |
1583 | | * saved->device = the pdf14 device. So we need to unretain it, |
1584 | | * close adev, and finally close saved->device. |
1585 | | */ |
1586 | 3.69k | gx_device_retain(saved->device, false); /* device no longer retained */ |
1587 | 3.69k | if (pinst->templat.uses_transparency) { |
1588 | 1.95k | if (pinst->is_clist == 0) { |
1589 | 1.95k | gs_free_object(((gx_device_pattern_accum *)adev)->bitmap_memory, |
1590 | 1.95k | ((gx_device_pattern_accum *)adev)->transbuff, |
1591 | 1.95k | "gx_pattern_load"); |
1592 | 1.95k | ((gx_device_pattern_accum *)adev)->transbuff = NULL; |
1593 | 1.95k | } |
1594 | 1.95k | dev_proc(adev, close_device)((gx_device *)adev); |
1595 | | /* adev was the target of the pdf14 device, so also is no longer retained */ |
1596 | 1.95k | gx_device_retain((gx_device *)adev, false); /* device no longer retained */ |
1597 | 1.95k | } |
1598 | 3.69k | dev_proc(saved->device, close_device)((gx_device *)saved->device); |
1599 | | /* Freeing the state should now free the device which may be the pdf14 compositor. */ |
1600 | 3.69k | gs_gstate_free_chain(saved); |
1601 | 3.69k | if (code == gs_error_handled) |
1602 | 3.69k | code = 0; |
1603 | 3.69k | return code; |
1604 | 3.69k | } |
1605 | 23.2k | if (pinst->templat.uses_transparency) { |
1606 | | /* if_debug0m('v', saved->memory, "gx_pattern_load: popping the pdf14 compositor device from this graphics state\n"); |
1607 | | if ((code = gs_pop_pdf14trans_device(saved, true)) < 0) |
1608 | | return code; */ |
1609 | 16.5k | if (pinst->is_clist) { |
1610 | | /* Send the compositor command to close the PDF14 device */ |
1611 | 359 | code = gs_pop_pdf14trans_device(saved, true); |
1612 | 359 | if (code < 0) |
1613 | 0 | goto fail; |
1614 | 16.1k | } else { |
1615 | | /* Not a clist, get PDF14 buffer information */ |
1616 | 16.1k | code = |
1617 | 16.1k | pdf14_get_buffer_information(saved->device, |
1618 | 16.1k | ((gx_device_pattern_accum*)adev)->transbuff, |
1619 | 16.1k | saved->memory, |
1620 | 16.1k | true); |
1621 | | /* PDF14 device (and buffer) is destroyed when pattern cache |
1622 | | entry is removed */ |
1623 | 16.1k | if (code < 0) |
1624 | 0 | goto fail; |
1625 | 16.1k | } |
1626 | 16.5k | } |
1627 | | /* We REALLY don't like the following cast.... */ |
1628 | 23.2k | code = gx_pattern_cache_add_entry((gs_gstate *)pgs, |
1629 | 23.2k | adev, &ctile); |
1630 | 23.2k | if (code >= 0) { |
1631 | 23.2k | if (!gx_pattern_cache_lookup(pdc, pgs, dev, select)) { |
1632 | 0 | mlprintf(mem, "Pattern cache lookup failed after insertion!\n"); |
1633 | 0 | code = gs_note_error(gs_error_Fatal); |
1634 | 0 | } |
1635 | 23.2k | } |
1636 | | #ifdef DEBUG |
1637 | | if (gs_debug_c('B') && dev_proc(adev, open_device) == pattern_accum_open) { |
1638 | | gx_device_pattern_accum *pdev = (gx_device_pattern_accum *)adev; |
1639 | | |
1640 | | if (pdev->mask) |
1641 | | debug_dump_bitmap(pdev->memory, |
1642 | | pdev->mask->base, pdev->mask->raster, |
1643 | | pdev->mask->height, "[B]Pattern mask"); |
1644 | | if (pdev->bits) |
1645 | | debug_dump_bitmap(pdev->memory, |
1646 | | ((gx_device_memory *) pdev->target)->base, |
1647 | | ((gx_device_memory *) pdev->target)->raster, |
1648 | | pdev->target->height, "[B]Pattern bits"); |
1649 | | } |
1650 | | #endif |
1651 | | /* Free the bookkeeping structures, except for the bits and mask */ |
1652 | | /* data iff they are still needed. */ |
1653 | 23.2k | dev_proc(adev, close_device)((gx_device *)adev); |
1654 | | /* Free the chain of gstates. Freeing the state will free the device. */ |
1655 | 23.2k | gs_gstate_free_chain(saved); |
1656 | 23.2k | return code; |
1657 | | |
1658 | 40 | fail: |
1659 | 40 | if (dev_proc(adev, open_device) == pattern_accum_open) { |
1660 | | /* free pattern cache data that never got added to the dictionary */ |
1661 | 40 | gx_device_pattern_accum *padev = (gx_device_pattern_accum *) adev; |
1662 | 40 | if ((padev->bits != NULL) && (padev->bits->base != NULL)) { |
1663 | 0 | gs_free_object(padev->bits->memory, padev->bits->base, "mem_open"); |
1664 | 0 | } |
1665 | 40 | } |
1666 | 40 | if (dev_proc(adev, open_device) == pattern_clist_open_device) { |
1667 | 0 | gx_device_clist *cdev = (gx_device_clist *)adev; |
1668 | |
|
1669 | 0 | gs_free_object(cdev->writer.bandlist_memory, cdev->common.data, "gx_pattern_load"); |
1670 | 0 | cdev->common.data = 0; |
1671 | 0 | } |
1672 | 40 | dev_proc(adev, close_device)((gx_device *)adev); |
1673 | 40 | gx_device_set_target(adev, NULL); |
1674 | 40 | gx_device_retain((gx_device *)adev, false); |
1675 | 40 | gs_gstate_free_chain(saved); |
1676 | 40 | return code; |
1677 | 23.2k | } |
1678 | | |
1679 | | /* Remap a PatternType 1 color. */ |
1680 | | cs_proc_remap_color(gx_remap_Pattern); /* check the prototype */ |
1681 | | int |
1682 | | gs_pattern1_remap_color(const gs_client_color * pc, const gs_color_space * pcs, |
1683 | | gx_device_color * pdc, const gs_gstate * pgs, |
1684 | | gx_device * dev, gs_color_select_t select) |
1685 | 28.3k | { |
1686 | 28.3k | gs_pattern1_instance_t *pinst = (gs_pattern1_instance_t *)pc->pattern; |
1687 | 28.3k | int code; |
1688 | | |
1689 | | /* Save original color space and color info into dev color */ |
1690 | 28.3k | pdc->ccolor = *pc; |
1691 | 28.3k | pdc->ccolor_valid = true; |
1692 | 28.3k | if (pinst == 0) { |
1693 | | /* Null pattern */ |
1694 | 0 | color_set_null_pattern(pdc); |
1695 | 0 | return 0; |
1696 | 0 | } |
1697 | 28.3k | if (pinst->templat.PaintType == 2) { /* uncolored */ |
1698 | 454 | if (pcs->base_space) { |
1699 | 262 | if (dev->icc_struct != NULL && dev->icc_struct->blackvector) { |
1700 | 0 | gs_client_color temppc; |
1701 | 0 | gs_color_space *graycs = gs_cspace_new_DeviceGray(pgs->memory); |
1702 | |
|
1703 | 0 | if (graycs == NULL) { |
1704 | 0 | code = (pcs->base_space->type->remap_color) |
1705 | 0 | (pc, pcs->base_space, pdc, pgs, dev, select); |
1706 | 0 | } else { |
1707 | 0 | if (gsicc_is_white_blacktextvec((gs_gstate*) pgs, |
1708 | 0 | dev, (gs_color_space*) pcs, (gs_client_color*) pc)) |
1709 | 0 | temppc.paint.values[0] = 1.0; |
1710 | 0 | else |
1711 | 0 | temppc.paint.values[0] = 0.0; |
1712 | 0 | code = (graycs->type->remap_color) |
1713 | 0 | (&temppc, graycs, pdc, pgs, dev, select); |
1714 | 0 | rc_decrement_cs(graycs, "gs_pattern1_remap_color"); |
1715 | 0 | } |
1716 | 262 | } else { |
1717 | 262 | code = (pcs->base_space->type->remap_color) |
1718 | 262 | (pc, pcs->base_space, pdc, pgs, dev, select); |
1719 | 262 | } |
1720 | 262 | } else |
1721 | 192 | code = gs_note_error(gs_error_unregistered); |
1722 | 454 | if (code < 0) |
1723 | 192 | return code; |
1724 | 262 | if (pdc->type == gx_dc_type_pure) |
1725 | 230 | pdc->type = &gx_dc_pure_masked; |
1726 | 32 | else if (pdc->type == gx_dc_type_ht_binary) |
1727 | 2 | pdc->type = &gx_dc_binary_masked; |
1728 | 30 | else if (pdc->type == gx_dc_type_ht_colored) |
1729 | 10 | pdc->type = &gx_dc_colored_masked; |
1730 | 20 | else if (pdc->type == gx_dc_type_devn) |
1731 | 20 | pdc->type = &gx_dc_devn_masked; |
1732 | 0 | else |
1733 | 0 | return_error(gs_error_unregistered); |
1734 | 262 | } else |
1735 | 27.9k | color_set_null_pattern(pdc); |
1736 | 28.1k | pdc->mask.id = pinst->id; |
1737 | 28.1k | pdc->mask.m_tile = 0; |
1738 | 28.1k | return gx_pattern_load(pdc, pgs, dev, select); |
1739 | 28.3k | } |
1740 | | |
1741 | | int |
1742 | | pattern_accum_dev_spec_op(gx_device *dev, int dso, void *data, int size) |
1743 | 1.09M | { |
1744 | 1.09M | gx_device_pattern_accum *const padev = (gx_device_pattern_accum *)dev; |
1745 | 1.09M | const gs_pattern1_instance_t *pinst = padev->instance; |
1746 | 1.09M | gx_device *target = |
1747 | 1.09M | (padev->target == 0 ? gs_currentdevice(pinst->saved) : |
1748 | 1.09M | padev->target); |
1749 | | |
1750 | 1.09M | if (dso == gxdso_in_pattern_accumulator) |
1751 | 479 | return (pinst->templat.PaintType == 2 ? 2 : 1); |
1752 | 1.09M | if (dso == gxdso_get_dev_param) { |
1753 | 0 | dev_param_req_t *request = (dev_param_req_t *)data; |
1754 | 0 | gs_param_list * plist = (gs_param_list *)request->list; |
1755 | 0 | bool bool_true = 1; |
1756 | |
|
1757 | 0 | if (strcmp(request->Param, "NoInterpolateImagemasks") == 0) { |
1758 | 0 | return param_write_bool(plist, "NoInterpolateImagemasks", &bool_true); |
1759 | 0 | } |
1760 | 0 | } |
1761 | | /* Bug 704670. Pattern accumulator should not allow whatever targets |
1762 | | lie beneath it to do any bbox adjustments. If we are here, the |
1763 | | pattern accumulator is actually drawing into a buffer |
1764 | | and it is not accumulating into a clist device. In this case, if it |
1765 | | was a pattern clist, we would be going to the special op for the clist |
1766 | | device of the pattern, which will have the proper extent and adjust |
1767 | | the bbox. Here we just need to clip to the buffer into which we are drawing */ |
1768 | 1.09M | if (dso == gxdso_restrict_bbox) { |
1769 | 0 | gs_int_rect* ibox = (gs_int_rect*)data; |
1770 | |
|
1771 | 0 | if (ibox->p.y < 0) |
1772 | 0 | ibox->p.y = 0; |
1773 | 0 | if (ibox->q.y > padev->height) |
1774 | 0 | ibox->q.y = padev->height; |
1775 | 0 | if (ibox->p.x < 0) |
1776 | 0 | ibox->p.x = 0; |
1777 | 0 | if (ibox->q.x > padev->width) |
1778 | 0 | ibox->q.x = padev->width; |
1779 | 0 | return 0; |
1780 | 0 | } |
1781 | | |
1782 | 1.09M | return dev_proc(target, dev_spec_op)(target, dso, data, size); |
1783 | 1.09M | } |