Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_tlsv12/sys/src/cmd/gs/src/gxpcmap.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
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 *
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
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
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
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
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
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
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
368
pattern_cache_choose_all(gx_color_tile * ctile, void *proc_data)
369
{
370
    return true;
371
}
372
private void
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 *
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
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 *
433
gstate_pattern_cache(gs_state * pgs)
434
{
435
    return pgs->pattern_cache;
436
}
437
void
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
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
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
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
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
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
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
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
}