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