1 /* Copyright (C) 1993, 2000 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: gxpcmap.c,v 1.13 2004/08/04 19:36:12 stefan Exp $ */
18 /* Pattern color mapping for Ghostscript library */
19 #include "math_.h"
20 #include "memory_.h"
21 #include "gx.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 "gxcspace.h" /* for gscolor2.h */
28 #include "gxcolor2.h"
29 #include "gxdcolor.h"
30 #include "gxdevice.h"
31 #include "gxdevmem.h"
32 #include "gxpcolor.h"
33 #include "gxp1impl.h"
34 #include "gzstate.h"
35
36 /* Define the default size of the Pattern cache. */
37 #define max_cached_patterns_LARGE 50
38 #define max_pattern_bits_LARGE 100000
39 #define max_cached_patterns_SMALL 5
40 #define max_pattern_bits_SMALL 1000
41 uint
gx_pat_cache_default_tiles(void)42 gx_pat_cache_default_tiles(void)
43 {
44 #if arch_small_memory
45 return max_cached_patterns_SMALL;
46 #else
47 return (gs_debug_c('.') ? max_cached_patterns_SMALL :
48 max_cached_patterns_LARGE);
49 #endif
50 }
51 ulong
gx_pat_cache_default_bits(void)52 gx_pat_cache_default_bits(void)
53 {
54 #if arch_small_memory
55 return max_pattern_bits_SMALL;
56 #else
57 return (gs_debug_c('.') ? max_pattern_bits_SMALL :
58 max_pattern_bits_LARGE);
59 #endif
60 }
61
62 /* Define the structures for Pattern rendering and caching. */
63 private_st_color_tile();
64 private_st_color_tile_element();
65 private_st_pattern_cache();
66 private_st_device_pattern_accum();
67
68 /* ------ Pattern rendering ------ */
69
70 /* Device procedures */
71 private dev_proc_open_device(pattern_accum_open);
72 private dev_proc_close_device(pattern_accum_close);
73 private dev_proc_fill_rectangle(pattern_accum_fill_rectangle);
74 private dev_proc_copy_mono(pattern_accum_copy_mono);
75 private dev_proc_copy_color(pattern_accum_copy_color);
76 private dev_proc_get_bits_rectangle(pattern_accum_get_bits_rectangle);
77
78 /* The device descriptor */
79 private const gx_device_pattern_accum gs_pattern_accum_device =
80 {std_device_std_body_open(gx_device_pattern_accum, 0,
81 "pattern accumulator",
82 0, 0, 72, 72),
83 {
84 /* NOTE: all drawing procedures must be defaulted, not forwarded. */
85 pattern_accum_open,
86 NULL,
87 NULL,
88 NULL,
89 pattern_accum_close,
90 NULL,
91 NULL,
92 pattern_accum_fill_rectangle,
93 gx_default_tile_rectangle,
94 pattern_accum_copy_mono,
95 pattern_accum_copy_color,
96 NULL,
97 gx_default_get_bits,
98 NULL,
99 NULL,
100 NULL,
101 NULL,
102 NULL,
103 NULL,
104 NULL,
105 NULL,
106 gx_default_copy_alpha,
107 NULL,
108 gx_default_copy_rop,
109 gx_default_fill_path,
110 gx_default_stroke_path,
111 gx_default_fill_mask,
112 gx_default_fill_trapezoid,
113 gx_default_fill_parallelogram,
114 gx_default_fill_triangle,
115 gx_default_draw_thin_line,
116 gx_default_begin_image,
117 gx_default_image_data,
118 gx_default_end_image,
119 gx_default_strip_tile_rectangle,
120 gx_default_strip_copy_rop,
121 gx_get_largest_clipping_box,
122 gx_default_begin_typed_image,
123 pattern_accum_get_bits_rectangle,
124 NULL,
125 gx_default_create_compositor,
126 NULL,
127 gx_default_text_begin,
128 gx_default_finish_copydevice,
129 NULL,
130 NULL,
131 NULL,
132 NULL,
133 NULL,
134 NULL,
135 NULL,
136 NULL,
137 NULL
138 },
139 0, /* target */
140 0, 0, 0, 0 /* bitmap_memory, bits, mask, instance */
141 };
142
143 /* Allocate a pattern accumulator, with an initial refct of 0. */
144 gx_device_pattern_accum *
gx_pattern_accum_alloc(gs_memory_t * mem,client_name_t cname)145 gx_pattern_accum_alloc(gs_memory_t * mem, client_name_t cname)
146 {
147 gx_device_pattern_accum *adev =
148 gs_alloc_struct(mem, gx_device_pattern_accum,
149 &st_device_pattern_accum, cname);
150
151 if (adev == 0)
152 return 0;
153 gx_device_init((gx_device *)adev,
154 (const gx_device *)&gs_pattern_accum_device,
155 mem, true);
156 check_device_separable((gx_device *)adev);
157 gx_device_forward_fill_in_procs((gx_device_forward *)adev);
158 return adev;
159 }
160
161 /*
162 * Initialize a pattern accumulator.
163 * Client must already have set instance and bitmap_memory.
164 *
165 * Note that mask and bits accumulators are only created if necessary.
166 */
167 private int
pattern_accum_open(gx_device * dev)168 pattern_accum_open(gx_device * dev)
169 {
170 gx_device_pattern_accum *const padev = (gx_device_pattern_accum *) dev;
171 const gs_pattern1_instance_t *pinst = padev->instance;
172 gs_memory_t *mem = padev->bitmap_memory;
173 gx_device_memory *mask = 0;
174 gx_device_memory *bits = 0;
175 /*
176 * The client should preset the target, because the device for which the
177 * pattern is being rendered may not (in general, will not) be the same
178 * as the one that was current when the pattern was instantiated.
179 */
180 gx_device *target =
181 (padev->target == 0 ? gs_currentdevice(pinst->saved) :
182 padev->target);
183 int width = pinst->size.x;
184 int height = pinst->size.y;
185 int code = 0;
186 bool mask_open = false;
187
188 /*
189 * C's bizarre coercion rules force us to copy HWResolution in pieces
190 * rather than using a single assignment.
191 */
192 #define PDSET(dev)\
193 ((dev)->width = width, (dev)->height = height,\
194 /*(dev)->HWResolution = target->HWResolution*/\
195 (dev)->HWResolution[0] = target->HWResolution[0],\
196 (dev)->HWResolution[1] = target->HWResolution[1])
197
198 PDSET(padev);
199 padev->color_info = target->color_info;
200
201 if (pinst->uses_mask) {
202 mask = gs_alloc_struct( mem,
203 gx_device_memory,
204 &st_device_memory,
205 "pattern_accum_open(mask)"
206 );
207 if (mask == 0)
208 return_error(gs_error_VMerror);
209 gs_make_mem_mono_device(mask, mem, 0);
210 PDSET(mask);
211 mask->bitmap_memory = mem;
212 mask->base = 0;
213 code = (*dev_proc(mask, open_device)) ((gx_device *) mask);
214 if (code >= 0) {
215 mask_open = true;
216 memset(mask->base, 0, mask->raster * mask->height);
217 }
218 }
219
220 if (code >= 0) {
221 switch (pinst->template.PaintType) {
222 case 2: /* uncolored */
223 gx_device_set_target((gx_device_forward *)padev, target);
224 break;
225 case 1: /* colored */
226 bits = gs_alloc_struct(mem, gx_device_memory,
227 &st_device_memory,
228 "pattern_accum_open(bits)");
229 if (bits == 0)
230 code = gs_note_error(gs_error_VMerror);
231 else {
232 gs_make_mem_device(bits,
233 gdev_mem_device_for_bits(target->color_info.depth),
234 mem, -1, target);
235 PDSET(bits);
236 #undef PDSET
237 bits->color_info = target->color_info;
238 bits->bitmap_memory = mem;
239 code = (*dev_proc(bits, open_device)) ((gx_device *) bits);
240 gx_device_set_target((gx_device_forward *)padev,
241 (gx_device *)bits);
242 }
243 }
244 }
245 if (code < 0) {
246 if (bits != 0)
247 gs_free_object(mem, bits, "pattern_accum_open(bits)");
248 if (mask != 0) {
249 if (mask_open)
250 (*dev_proc(mask, close_device)) ((gx_device *) mask);
251 gs_free_object(mem, mask, "pattern_accum_open(mask)");
252 }
253 return code;
254 }
255 padev->mask = mask;
256 padev->bits = bits;
257 /* Retain the device, so it will survive anomalous grestores. */
258 gx_device_retain(dev, true);
259 return code;
260 }
261
262 /* Close an accumulator and free the bits. */
263 private int
pattern_accum_close(gx_device * dev)264 pattern_accum_close(gx_device * dev)
265 {
266 gx_device_pattern_accum *const padev = (gx_device_pattern_accum *) dev;
267 gs_memory_t *mem = padev->bitmap_memory;
268
269 /*
270 * If bits != 0, it is the target of the device; reference counting
271 * will close and free it.
272 */
273 gx_device_set_target((gx_device_forward *)padev, NULL);
274 padev->bits = 0;
275 if (padev->mask != 0) {
276 (*dev_proc(padev->mask, close_device)) ((gx_device *) padev->mask);
277 gs_free_object(mem, padev->mask, "pattern_accum_close(mask)");
278 padev->mask = 0;
279 }
280 /* Un-retain the device now, so reference counting will free it. */
281 gx_device_retain(dev, false);
282 return 0;
283 }
284
285 /* Fill a rectangle */
286 private int
pattern_accum_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)287 pattern_accum_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
288 gx_color_index color)
289 {
290 gx_device_pattern_accum *const padev = (gx_device_pattern_accum *) dev;
291
292 if (padev->bits)
293 (*dev_proc(padev->target, fill_rectangle))
294 (padev->target, x, y, w, h, color);
295 if (padev->mask)
296 return (*dev_proc(padev->mask, fill_rectangle))
297 ((gx_device *) padev->mask, x, y, w, h, (gx_color_index) 1);
298 else
299 return 0;
300 }
301
302 /* Copy a monochrome bitmap. */
303 private int
pattern_accum_copy_mono(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index color0,gx_color_index color1)304 pattern_accum_copy_mono(gx_device * dev, const byte * data, int data_x,
305 int raster, gx_bitmap_id id, int x, int y, int w, int h,
306 gx_color_index color0, gx_color_index color1)
307 {
308 gx_device_pattern_accum *const padev = (gx_device_pattern_accum *) dev;
309
310 /* opt out early if nothing to render (some may think this a bug) */
311 if (color0 == gx_no_color_index && color1 == gx_no_color_index)
312 return 0;
313 if (padev->bits)
314 (*dev_proc(padev->target, copy_mono))
315 (padev->target, data, data_x, raster, id, x, y, w, h,
316 color0, color1);
317 if (padev->mask) {
318 if (color0 != gx_no_color_index)
319 color0 = 1;
320 if (color1 != gx_no_color_index)
321 color1 = 1;
322 if (color0 == 1 && color1 == 1)
323 return (*dev_proc(padev->mask, fill_rectangle))
324 ((gx_device *) padev->mask, x, y, w, h, (gx_color_index) 1);
325 else
326 return (*dev_proc(padev->mask, copy_mono))
327 ((gx_device *) padev->mask, data, data_x, raster, id, x, y, w, h,
328 color0, color1);
329 } else
330 return 0;
331 }
332
333 /* Copy a color bitmap. */
334 private int
pattern_accum_copy_color(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int w,int h)335 pattern_accum_copy_color(gx_device * dev, const byte * data, int data_x,
336 int raster, gx_bitmap_id id, int x, int y, int w, int h)
337 {
338 gx_device_pattern_accum *const padev = (gx_device_pattern_accum *) dev;
339
340 if (padev->bits)
341 (*dev_proc(padev->target, copy_color))
342 (padev->target, data, data_x, raster, id, x, y, w, h);
343 if (padev->mask)
344 return (*dev_proc(padev->mask, fill_rectangle))
345 ((gx_device *) padev->mask, x, y, w, h, (gx_color_index) 1);
346 else
347 return 0;
348 }
349
350 /* Read back a rectangle of bits. */
351 /****** SHOULD USE MASK TO DEFINE UNREAD AREA *****/
352 private int
pattern_accum_get_bits_rectangle(gx_device * dev,const gs_int_rect * prect,gs_get_bits_params_t * params,gs_int_rect ** unread)353 pattern_accum_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect,
354 gs_get_bits_params_t * params, gs_int_rect ** unread)
355 {
356 gx_device_pattern_accum *const padev = (gx_device_pattern_accum *) dev;
357
358 if (padev->bits)
359 return (*dev_proc(padev->target, get_bits_rectangle))
360 (padev->target, prect, params, unread);
361 return_error(gs_error_Fatal); /* can't happen */
362 }
363
364 /* ------ Color space implementation ------ */
365
366 /* Free all entries in a pattern cache. */
367 private bool
pattern_cache_choose_all(gx_color_tile * ctile,void * proc_data)368 pattern_cache_choose_all(gx_color_tile * ctile, void *proc_data)
369 {
370 return true;
371 }
372 private void
pattern_cache_free_all(gx_pattern_cache * pcache)373 pattern_cache_free_all(gx_pattern_cache * pcache)
374 {
375 gx_pattern_cache_winnow(pcache, pattern_cache_choose_all, NULL);
376 }
377
378 /* Allocate a Pattern cache. */
379 gx_pattern_cache *
gx_pattern_alloc_cache(gs_memory_t * mem,uint num_tiles,ulong max_bits)380 gx_pattern_alloc_cache(gs_memory_t * mem, uint num_tiles, ulong max_bits)
381 {
382 gx_pattern_cache *pcache =
383 gs_alloc_struct(mem, gx_pattern_cache, &st_pattern_cache,
384 "gx_pattern_alloc_cache(struct)");
385 gx_color_tile *tiles =
386 gs_alloc_struct_array(mem, num_tiles, gx_color_tile,
387 &st_color_tile_element,
388 "gx_pattern_alloc_cache(tiles)");
389 uint i;
390
391 if (pcache == 0 || tiles == 0) {
392 gs_free_object(mem, tiles, "gx_pattern_alloc_cache(tiles)");
393 gs_free_object(mem, pcache, "gx_pattern_alloc_cache(struct)");
394 return 0;
395 }
396 pcache->memory = mem;
397 pcache->tiles = tiles;
398 pcache->num_tiles = num_tiles;
399 pcache->tiles_used = 0;
400 pcache->next = 0;
401 pcache->bits_used = 0;
402 pcache->max_bits = max_bits;
403 pcache->free_all = pattern_cache_free_all;
404 for (i = 0; i < num_tiles; tiles++, i++) {
405 tiles->id = gx_no_bitmap_id;
406 /* Clear the pointers to pacify the GC. */
407 uid_set_invalid(&tiles->uid);
408 tiles->tbits.data = 0;
409 tiles->tmask.data = 0;
410 tiles->index = i;
411 }
412 return pcache;
413 }
414 /* Ensure that an imager has a Pattern cache. */
415 private int
ensure_pattern_cache(gs_imager_state * pis)416 ensure_pattern_cache(gs_imager_state * pis)
417 {
418 if (pis->pattern_cache == 0) {
419 gx_pattern_cache *pcache =
420 gx_pattern_alloc_cache(pis->memory,
421 gx_pat_cache_default_tiles(),
422 gx_pat_cache_default_bits());
423
424 if (pcache == 0)
425 return_error(gs_error_VMerror);
426 pis->pattern_cache = pcache;
427 }
428 return 0;
429 }
430
431 /* Get and set the Pattern cache in a gstate. */
432 gx_pattern_cache *
gstate_pattern_cache(gs_state * pgs)433 gstate_pattern_cache(gs_state * pgs)
434 {
435 return pgs->pattern_cache;
436 }
437 void
gstate_set_pattern_cache(gs_state * pgs,gx_pattern_cache * pcache)438 gstate_set_pattern_cache(gs_state * pgs, gx_pattern_cache * pcache)
439 {
440 pgs->pattern_cache = pcache;
441 }
442
443 /* Free a Pattern cache entry. */
444 private void
gx_pattern_cache_free_entry(gx_pattern_cache * pcache,gx_color_tile * ctile)445 gx_pattern_cache_free_entry(gx_pattern_cache * pcache, gx_color_tile * ctile)
446 {
447 if ((ctile->id != gx_no_bitmap_id) && !ctile->is_dummy) {
448 gs_memory_t *mem = pcache->memory;
449 gx_device_memory mdev;
450
451 /*
452 * We must initialize the memory device properly, even though
453 * we aren't using it for drawing.
454 */
455 gs_make_mem_mono_device(&mdev, mem, NULL);
456 if (ctile->tmask.data != 0) {
457 mdev.width = ctile->tmask.size.x;
458 mdev.height = ctile->tmask.size.y;
459 /*mdev.color_info.depth = 1;*/
460 pcache->bits_used -= gdev_mem_bitmap_size(&mdev);
461 gs_free_object(mem, ctile->tmask.data,
462 "free_pattern_cache_entry(mask data)");
463 ctile->tmask.data = 0; /* for GC */
464 }
465 if (ctile->tbits.data != 0) {
466 mdev.width = ctile->tbits.size.x;
467 mdev.height = ctile->tbits.size.y;
468 mdev.color_info.depth = ctile->depth;
469 pcache->bits_used -= gdev_mem_bitmap_size(&mdev);
470 gs_free_object(mem, ctile->tbits.data,
471 "free_pattern_cache_entry(bits data)");
472 ctile->tbits.data = 0; /* for GC */
473 }
474 ctile->id = gx_no_bitmap_id;
475 pcache->tiles_used--;
476 }
477 }
478
479 /*
480 * Add a Pattern cache entry. This is exported for the interpreter.
481 * Note that this does not free any of the data in the accumulator
482 * device, but it may zero out the bitmap_memory pointers to prevent
483 * the accumulated bitmaps from being freed when the device is closed.
484 */
485 private void make_bitmap(gx_strip_bitmap *, const gx_device_memory *, gx_bitmap_id);
486 int
gx_pattern_cache_add_entry(gs_imager_state * pis,gx_device_pattern_accum * padev,gx_color_tile ** pctile)487 gx_pattern_cache_add_entry(gs_imager_state * pis,
488 gx_device_pattern_accum * padev, gx_color_tile ** pctile)
489 {
490 gx_device_memory *mbits = padev->bits;
491 gx_device_memory *mmask = padev->mask;
492 const gs_pattern1_instance_t *pinst = padev->instance;
493 gx_pattern_cache *pcache;
494 ulong used = 0;
495 gx_bitmap_id id = pinst->id;
496 gx_color_tile *ctile;
497 int code = ensure_pattern_cache(pis);
498
499 if (code < 0)
500 return code;
501 pcache = pis->pattern_cache;
502 /*
503 * Check whether the pattern completely fills its box.
504 * If so, we can avoid the expensive masking operations
505 * when using the pattern.
506 */
507 if (mmask != 0) {
508 int y;
509
510 for (y = 0; y < mmask->height; y++) {
511 const byte *row = scan_line_base(mmask, y);
512 int w;
513
514 for (w = mmask->width; w > 8; w -= 8)
515 if (*row++ != 0xff)
516 goto keep;
517 if ((*row | (0xff >> w)) != 0xff)
518 goto keep;
519 }
520 /* We don't need a mask. */
521 mmask = 0;
522 keep:;
523 }
524 if (mbits != 0)
525 used += gdev_mem_bitmap_size(mbits);
526 if (mmask != 0)
527 used += gdev_mem_bitmap_size(mmask);
528 ctile = &pcache->tiles[id % pcache->num_tiles];
529 gx_pattern_cache_free_entry(pcache, ctile);
530 while (pcache->bits_used + used > pcache->max_bits &&
531 pcache->bits_used != 0 /* allow 1 oversized entry (?) */
532 ) {
533 pcache->next = (pcache->next + 1) % pcache->num_tiles;
534 gx_pattern_cache_free_entry(pcache, &pcache->tiles[pcache->next]);
535 }
536 ctile->id = id;
537 ctile->depth = padev->color_info.depth;
538 ctile->uid = pinst->template.uid;
539 ctile->tiling_type = pinst->template.TilingType;
540 ctile->step_matrix = pinst->step_matrix;
541 ctile->bbox = pinst->bbox;
542 ctile->is_simple = pinst->is_simple;
543 ctile->is_dummy = false;
544 if (mbits != 0) {
545 make_bitmap(&ctile->tbits, mbits, gs_next_ids(pis->memory, 1));
546 mbits->bitmap_memory = 0; /* don't free the bits */
547 } else
548 ctile->tbits.data = 0;
549 if (mmask != 0) {
550 make_bitmap(&ctile->tmask, mmask, id);
551 mmask->bitmap_memory = 0; /* don't free the bits */
552 } else
553 ctile->tmask.data = 0;
554 pcache->bits_used += used;
555 pcache->tiles_used++;
556 *pctile = ctile;
557 return 0;
558 }
559
560 /* Add a dummy Pattern cache entry. Stubs a pattern tile for interpreter when
561 device handles high level patterns. */
562 int
gx_pattern_cache_add_dummy_entry(gs_imager_state * pis,gs_pattern1_instance_t * pinst,int depth)563 gx_pattern_cache_add_dummy_entry(gs_imager_state *pis,
564 gs_pattern1_instance_t *pinst, int depth)
565 {
566 gx_color_tile *ctile;
567 gx_pattern_cache *pcache;
568 gx_bitmap_id id = pinst->id;
569 int code = ensure_pattern_cache(pis);
570
571 if (code < 0)
572 return code;
573 pcache = pis->pattern_cache;
574 ctile = &pcache->tiles[id % pcache->num_tiles];
575 gx_pattern_cache_free_entry(pcache, ctile);
576 ctile->id = id;
577 ctile->depth = depth;
578 ctile->uid = pinst->template.uid;
579 ctile->tiling_type = pinst->template.TilingType;
580 ctile->step_matrix = pinst->step_matrix;
581 ctile->bbox = pinst->bbox;
582 ctile->is_simple = pinst->is_simple;
583 ctile->is_dummy = true;
584 memset(&ctile->tbits, 0 , sizeof(ctile->tbits));
585 ctile->tbits.size = pinst->size;
586 ctile->tbits.id = gs_no_bitmap_id;
587 memset(&ctile->tmask, 0 , sizeof(ctile->tmask));
588 pcache->tiles_used++;
589 return 0;
590 }
591 private void
make_bitmap(register gx_strip_bitmap * pbm,const gx_device_memory * mdev,gx_bitmap_id id)592 make_bitmap(register gx_strip_bitmap * pbm, const gx_device_memory * mdev,
593 gx_bitmap_id id)
594 {
595 pbm->data = mdev->base;
596 pbm->raster = mdev->raster;
597 pbm->rep_width = pbm->size.x = mdev->width;
598 pbm->rep_height = pbm->size.y = mdev->height;
599 pbm->id = id;
600 pbm->rep_shift = pbm->shift = 0;
601 }
602
603 /* Purge selected entries from the pattern cache. */
604 void
gx_pattern_cache_winnow(gx_pattern_cache * pcache,bool (* proc)(gx_color_tile * ctile,void * proc_data),void * proc_data)605 gx_pattern_cache_winnow(gx_pattern_cache * pcache,
606 bool(*proc) (gx_color_tile * ctile, void *proc_data), void *proc_data)
607 {
608 uint i;
609
610 if (pcache == 0) /* no cache created yet */
611 return;
612 for (i = 0; i < pcache->num_tiles; ++i) {
613 gx_color_tile *ctile = &pcache->tiles[i];
614
615 if (ctile->id != gx_no_bitmap_id && (*proc) (ctile, proc_data))
616 gx_pattern_cache_free_entry(pcache, ctile);
617 }
618 }
619
620 /* Reload a (non-null) Pattern color into the cache. */
621 /* *pdc is already set, except for colors.pattern.p_tile and mask.m_tile. */
622 int
gx_pattern_load(gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)623 gx_pattern_load(gx_device_color * pdc, const gs_imager_state * pis,
624 gx_device * dev, gs_color_select_t select)
625 {
626 gx_device_pattern_accum *adev;
627 gs_pattern1_instance_t *pinst =
628 (gs_pattern1_instance_t *)pdc->ccolor.pattern;
629 gs_state *saved;
630 gx_color_tile *ctile;
631 gs_memory_t *mem = pis->memory;
632 int code;
633
634 if (gx_pattern_cache_lookup(pdc, pis, dev, select))
635 return 0;
636 /* We REALLY don't like the following cast.... */
637 code = ensure_pattern_cache((gs_imager_state *) pis);
638 if (code < 0)
639 return code;
640 /*
641 * Note that adev is an internal device, so it will be freed when the
642 * last reference to it from a graphics state is deleted.
643 */
644 adev = gx_pattern_accum_alloc(mem, "gx_pattern_load");
645 if (adev == 0)
646 return_error(gs_error_VMerror);
647 gx_device_set_target((gx_device_forward *)adev, dev);
648 adev->instance = pinst;
649 adev->bitmap_memory = mem;
650 code = dev_proc(adev, open_device)((gx_device *)adev);
651 if (code < 0)
652 goto fail;
653 saved = gs_gstate(pinst->saved);
654 if (saved == 0) {
655 code = gs_note_error(gs_error_VMerror);
656 goto fail;
657 }
658 if (saved->pattern_cache == 0)
659 saved->pattern_cache = pis->pattern_cache;
660 gs_setdevice_no_init(saved, (gx_device *)adev);
661 code = (*pinst->template.PaintProc)(&pdc->ccolor, saved);
662 if (code < 0) {
663 dev_proc(adev, close_device)((gx_device *)adev);
664 /* Freeing the state will free the device. */
665 gs_state_free(saved);
666 return code;
667 }
668 /* We REALLY don't like the following cast.... */
669 code = gx_pattern_cache_add_entry((gs_imager_state *)pis, adev, &ctile);
670 if (code >= 0) {
671 if (!gx_pattern_cache_lookup(pdc, pis, dev, select)) {
672 lprintf("Pattern cache lookup failed after insertion!\n");
673 code = gs_note_error(gs_error_Fatal);
674 }
675 }
676 #ifdef DEBUG
677 if (gs_debug_c('B')) {
678 if (adev->mask)
679 debug_dump_bitmap(adev->mask->base, adev->mask->raster,
680 adev->mask->height, "[B]Pattern mask");
681 if (adev->bits)
682 debug_dump_bitmap(((gx_device_memory *) adev->target)->base,
683 ((gx_device_memory *) adev->target)->raster,
684 adev->target->height, "[B]Pattern bits");
685 }
686 #endif
687 /* Free the bookkeeping structures, except for the bits and mask */
688 /* data iff they are still needed. */
689 dev_proc(adev, close_device)((gx_device *)adev);
690 /* Freeing the state will free the device. */
691 gs_state_free(saved);
692 return code;
693 fail:
694 gs_free_object(mem, adev, "gx_pattern_load");
695 return code;
696 }
697
698 /* Remap a PatternType 1 color. */
699 cs_proc_remap_color(gx_remap_Pattern); /* check the prototype */
700 int
gs_pattern1_remap_color(const gs_client_color * pc,const gs_color_space * pcs,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)701 gs_pattern1_remap_color(const gs_client_color * pc, const gs_color_space * pcs,
702 gx_device_color * pdc, const gs_imager_state * pis,
703 gx_device * dev, gs_color_select_t select)
704 {
705 gs_pattern1_instance_t *pinst = (gs_pattern1_instance_t *)pc->pattern;
706 int code;
707
708 /* Save original color space and color info into dev color */
709 pdc->ccolor = *pc;
710 pdc->ccolor_valid = true;
711 if (pinst == 0) {
712 /* Null pattern */
713 color_set_null_pattern(pdc);
714 return 0;
715 }
716 if (pinst->template.PaintType == 2) { /* uncolored */
717 code = (*pcs->params.pattern.base_space.type->remap_color)
718 (pc, (const gs_color_space *)&pcs->params.pattern.base_space,
719 pdc, pis, dev, select);
720 if (code < 0)
721 return code;
722 if (pdc->type == gx_dc_type_pure)
723 pdc->type = &gx_dc_pure_masked;
724 else if (pdc->type == gx_dc_type_ht_binary)
725 pdc->type = &gx_dc_binary_masked;
726 else if (pdc->type == gx_dc_type_ht_colored)
727 pdc->type = &gx_dc_colored_masked;
728 else
729 return_error(gs_error_unregistered);
730 } else
731 color_set_null_pattern(pdc);
732 pdc->mask.id = pinst->id;
733 pdc->mask.m_tile = 0;
734 return gx_pattern_load(pdc, pis, dev, select);
735 }
736