xref: /plan9/sys/src/cmd/gs/src/gxpcmap.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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