Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1999 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: gsptype1.c,v 1.23 2005/06/15 18:40:07 igor Exp $ */
18
/* PatternType 1 pattern implementation */
19
#include "math_.h"
20
#include "gx.h"
21
#include "gserrors.h"
22
#include "gsrop.h"
23
#include "gsstruct.h"
24
#include "gsutil.h"		/* for gs_next_ids */
25
#include "gxarith.h"
26
#include "gxfixed.h"
27
#include "gxmatrix.h"
28
#include "gxcoord.h"		/* for gs_concat, gx_tr'_to_fixed */
29
#include "gxcspace.h"		/* for gscolor2.h */
30
#include "gxcolor2.h"
31
#include "gxdcolor.h"
32
#include "gxdevice.h"
33
#include "gxdevmem.h"
34
#include "gxclip2.h"
35
#include "gspath.h"
36
#include "gxpath.h"
37
#include "gxpcolor.h"
38
#include "gxp1impl.h"		/* requires gxpcolor.h */
39
#include "gzstate.h"
40
#include "gsimage.h"
41
#include "gsiparm4.h"
42
#include "gsovrc.h"
43
 
44
/* Temporary switches for experimanting with Adobe compatibility. */
45
#define ADJUST_SCALE_FOR_THIN_LINES 0	/* Old code = 0 */
46
#define ADJUST_SCALE_BY_GS_TRADITION 0	/* Old code = 1 */
47
#define ADJUST_AS_ADOBE 1		/* Old code = 0 *//* This one is closer to Adobe. */
48
 
49
/* GC descriptors */
50
private_st_pattern1_template();
51
private_st_pattern1_instance();
52
 
53
/* GC procedures */
54
private ENUM_PTRS_BEGIN(pattern1_instance_enum_ptrs) {
55
    if (index < st_pattern1_template_max_ptrs) {
56
	gs_ptr_type_t ptype =
57
	    ENUM_SUPER_ELT(gs_pattern1_instance_t, st_pattern1_template,
58
			   template, 0);
59
 
60
	if (ptype)
61
	    return ptype;
62
	return ENUM_OBJ(NULL);	/* don't stop early */
63
    }
64
    ENUM_PREFIX(st_pattern_instance, st_pattern1_template_max_ptrs);
65
} ENUM_PTRS_END
66
private RELOC_PTRS_BEGIN(pattern1_instance_reloc_ptrs) {
67
    RELOC_PREFIX(st_pattern_instance);
68
    RELOC_SUPER(gs_pattern1_instance_t, st_pattern1_template, template);
69
} RELOC_PTRS_END
70
 
71
/* Define a PatternType 1 pattern. */
72
private pattern_proc_uses_base_space(gs_pattern1_uses_base_space);
73
private pattern_proc_make_pattern(gs_pattern1_make_pattern);
74
private pattern_proc_get_pattern(gs_pattern1_get_pattern);
75
private pattern_proc_set_color(gs_pattern1_set_color);
76
private const gs_pattern_type_t gs_pattern1_type = {
77
    1, {
78
	gs_pattern1_uses_base_space, gs_pattern1_make_pattern,
79
	gs_pattern1_get_pattern, gs_pattern1_remap_color,
80
	gs_pattern1_set_color
81
    }
82
};
83
 
84
/*
85
 * Build a PatternType 1 Pattern color space.
86
 */
87
int
88
gs_cspace_build_Pattern1(gs_color_space ** ppcspace,
89
		    const gs_color_space * pbase_cspace, gs_memory_t * pmem)
90
{
91
    gs_color_space *pcspace = 0;
92
    int code;
93
 
94
    if (pbase_cspace != 0) {
95
	if (gs_color_space_num_components(pcspace) < 0)		/* Pattern space */
96
	    return_error(gs_error_rangecheck);
97
    }
98
    code = gs_cspace_alloc(&pcspace, &gs_color_space_type_Pattern, pmem);
99
    if (code < 0)
100
	return code;
101
    if (pbase_cspace != 0) {
102
	pcspace->params.pattern.has_base_space = true;
103
	gs_cspace_init_from((gs_color_space *) & (pcspace->params.pattern.base_space),
104
			    pbase_cspace
105
	    );
106
    } else
107
	pcspace->params.pattern.has_base_space = false;
108
    *ppcspace = pcspace;
109
    return 0;
110
}
111
 
112
/* Initialize a PatternType 1 pattern template. */
113
void
114
gs_pattern1_init(gs_pattern1_template_t * ppat)
115
{
116
    gs_pattern_common_init((gs_pattern_template_t *)ppat, &gs_pattern1_type);
117
}
118
 
119
/* Make an instance of a PatternType 1 pattern. */
120
private int compute_inst_matrix(gs_pattern1_instance_t * pinst,
121
	const gs_state * saved, gs_rect * pbbox, int width, int height);
122
int
123
gs_makepattern(gs_client_color * pcc, const gs_pattern1_template_t * pcp,
124
	       const gs_matrix * pmat, gs_state * pgs, gs_memory_t * mem)
125
{
126
    return gs_pattern1_make_pattern(pcc, (const gs_pattern_template_t *)pcp,
127
				    pmat, pgs, mem);
128
}
129
private int
130
gs_pattern1_make_pattern(gs_client_color * pcc,
131
			 const gs_pattern_template_t * ptemp,
132
			 const gs_matrix * pmat, gs_state * pgs,
133
			 gs_memory_t * mem)
134
{
135
    const gs_pattern1_template_t *pcp = (const gs_pattern1_template_t *)ptemp;
136
    gs_pattern1_instance_t inst;
137
    gs_pattern1_instance_t *pinst;
138
    gs_state *saved;
139
    gs_rect bbox;
140
    gs_fixed_rect cbox;
141
    gx_device * pdev = pgs->device;
142
    int dev_width = pdev->width;
143
    int dev_height = pdev->height;
144
    int code = gs_make_pattern_common(pcc, (const gs_pattern_template_t *)pcp,
145
				      pmat, pgs, mem,
146
				      &st_pattern1_instance);
147
 
148
    if (code < 0)
149
	return code;
150
    if (mem == 0)
151
	mem = gs_state_memory(pgs);
152
    pinst = (gs_pattern1_instance_t *)pcc->pattern;
153
    *(gs_pattern_instance_t *)&inst = *(gs_pattern_instance_t *)pinst;
154
    saved = inst.saved;
155
    switch (pcp->PaintType) {
156
	case 1:		/* colored */
157
	    gs_set_logical_op(saved, lop_default);
158
	    break;
159
	case 2:		/* uncolored */
160
	    gx_set_device_color_1(saved);
161
	    break;
162
	default:
163
	    code = gs_note_error(gs_error_rangecheck);
164
	    goto fsaved;
165
    }
166
    inst.template = *pcp;
167
    code = compute_inst_matrix(&inst, saved, &bbox, dev_width, dev_height);
168
    if (code < 0)
169
	goto fsaved;
170
 
171
#define mat inst.step_matrix
172
    if_debug6('t', "[t]step_matrix=[%g %g %g %g %g %g]\n",
173
	      mat.xx, mat.xy, mat.yx, mat.yy, mat.tx, mat.ty);
174
    if_debug4('t', "[t]bbox=(%g,%g),(%g,%g)\n",
175
	      bbox.p.x, bbox.p.y, bbox.q.x, bbox.q.y);
176
    {
177
	float bbw = bbox.q.x - bbox.p.x;
178
	float bbh = bbox.q.y - bbox.p.y;
179
 
180
	/* If the step and the size agree to within 1/2 pixel, */
181
	/* make them the same. */
182
	if (ADJUST_SCALE_BY_GS_TRADITION) {
183
	    inst.size.x = (int)(bbw + 0.8);		/* 0.8 is arbitrary */
184
	    inst.size.y = (int)(bbh + 0.8);
185
	} else {
186
	    inst.size.x = (int)ceil(bbw);
187
	    inst.size.y = (int)ceil(bbh);
188
	}
189
 
190
	if (inst.size.x == 0 || inst.size.y == 0) {
191
	    /*
192
	     * The pattern is empty: the stepping matrix doesn't matter.
193
	     */
194
	    gs_make_identity(&mat);
195
	    bbox.p.x = bbox.p.y = bbox.q.x = bbox.q.y = 0;
196
	} else {
197
	    /* Check for singular stepping matrix. */
198
	    if (fabs(mat.xx * mat.yy - mat.xy * mat.yx) < 1.0e-6) {
199
		code = gs_note_error(gs_error_rangecheck);
200
		goto fsaved;
201
	    }
202
	    if (ADJUST_SCALE_BY_GS_TRADITION &&
203
	        mat.xy == 0 && mat.yx == 0 &&
204
		fabs(fabs(mat.xx) - bbw) < 0.5 &&
205
		fabs(fabs(mat.yy) - bbh) < 0.5
206
		) {
207
		gs_scale(saved, fabs(inst.size.x / mat.xx),
208
			 fabs(inst.size.y / mat.yy));
209
		code = compute_inst_matrix(&inst, saved, &bbox,
210
						dev_width, dev_height);
211
		if (code < 0)
212
		    goto fsaved;
213
		if (ADJUST_SCALE_FOR_THIN_LINES) {
214
		    /* To allow thin lines at a cell boundary 
215
		       to be painted inside the cell,
216
		       we adjust the scale so that 
217
		       the scaled width is in fixed_1 smaller */
218
		    gs_scale(saved, (fabs(inst.size.x) - 1.0 / fixed_scale) / fabs(inst.size.x),
219
				    (fabs(inst.size.y) - 1.0 / fixed_scale) / fabs(inst.size.y));
220
		}
221
		if_debug2('t',
222
			  "[t]adjusted XStep & YStep to size=(%d,%d)\n",
223
			  inst.size.x, inst.size.y);
224
		if_debug4('t', "[t]bbox=(%g,%g),(%g,%g)\n",
225
			  bbox.p.x, bbox.p.y, bbox.q.x, bbox.q.y);
226
	    } else if (ADJUST_AS_ADOBE) {
227
		if (mat.xy == 0 && mat.yx == 0 &&
228
		    fabs(fabs(mat.xx) - bbw) < 0.5 &&
229
		    fabs(fabs(mat.yy) - bbh) < 0.5
230
		    ) {
231
		    if (inst.step_matrix.xx <= 2) { 
232
			/* Prevent a degradation - see -r72 mspro.pdf */
233
			gs_scale(saved, fabs(inst.size.x / mat.xx), 1);
234
			inst.step_matrix.xx = (float)inst.size.x;
235
		    } else {
236
			inst.step_matrix.xx = (float)floor(inst.step_matrix.xx + 0.5);
237
			/* To allow thin lines at a cell boundary 
238
			   to be painted inside the cell,
239
			   we adjust the scale so that 
240
			   the scaled width is in fixed_1 smaller */
241
			if (bbw >= inst.size.x - 1.0 / fixed_scale)
242
			    gs_scale(saved, (fabs(inst.size.x) - 1.0 / fixed_scale) / fabs(inst.size.x), 1);
243
		    }
244
		    if (inst.step_matrix.yy <= 2) {
245
			gs_scale(saved, 1, fabs(inst.size.y / mat.yy));
246
			inst.step_matrix.yy = (float)inst.size.y;
247
		    } else {
248
			inst.step_matrix.yy = (float)floor(inst.step_matrix.yy + 0.5);
249
			if (bbh >= inst.size.y - 1.0 / fixed_scale)
250
			    gs_scale(saved, 1, (fabs(inst.size.y) - 1.0 / fixed_scale) / fabs(inst.size.y));
251
		    }
252
		    code = gs_bbox_transform(&inst.template.BBox, &ctm_only(saved), &bbox);
253
		    if (code < 0)
254
			goto fsaved;
255
		}
256
	    }
257
	}
258
    }
259
    if ((code = gs_bbox_transform_inverse(&bbox, &mat, &inst.bbox)) < 0)
260
	goto fsaved;
261
    if_debug4('t', "[t]ibbox=(%g,%g),(%g,%g)\n",
262
	      inst.bbox.p.x, inst.bbox.p.y, inst.bbox.q.x, inst.bbox.q.y);
263
    inst.is_simple = (fabs(mat.xx) == inst.size.x && mat.xy == 0 &&
264
		      mat.yx == 0 && fabs(mat.yy) == inst.size.y);
265
    if_debug6('t',
266
	      "[t]is_simple? xstep=(%g,%g) ystep=(%g,%g) size=(%d,%d)\n",
267
	      inst.step_matrix.xx, inst.step_matrix.xy,
268
	      inst.step_matrix.yx, inst.step_matrix.yy,
269
	      inst.size.x, inst.size.y);
270
    /* Absent other information, instances always require a mask. */
271
    inst.uses_mask = true;
272
    gx_translate_to_fixed(saved, float2fixed_rounded(mat.tx - bbox.p.x),
273
			         float2fixed_rounded(mat.ty - bbox.p.y));
274
    mat.tx = bbox.p.x;
275
    mat.ty = bbox.p.y;
276
#undef mat
277
    cbox.p.x = fixed_0;
278
    cbox.p.y = fixed_0;
279
    cbox.q.x = int2fixed(inst.size.x);
280
    cbox.q.y = int2fixed(inst.size.y);
281
    code = gx_clip_to_rectangle(saved, &cbox);
282
    if (code < 0)
283
	goto fsaved;
284
    inst.id = gs_next_ids(mem, 1);
285
    *pinst = inst;
286
    return 0;
287
#undef mat
288
  fsaved:gs_state_free(saved);
289
    gs_free_object(mem, pinst, "gs_makepattern");
290
    return code;
291
}
292
 
293
/*
294
 * Clamp the bound box for a pattern to the region of the pattern that will
295
 * actually be on our page.  We need to do this becuase some applications
296
 * create patterns which specify a bounding box which is much larger than
297
 * the page.  We allocate a buffer for holding the pattern.  We need to
298
 * prevent this buffer from getting too large.
299
 */
300
private int
301
clamp_pattern_bbox(gs_pattern1_instance_t * pinst, gs_rect * pbbox,
302
		    int width, int height, const gs_matrix * pmat)
303
{
304
    double xstep = pinst->template.XStep;
305
    double ystep = pinst->template.YStep;
306
    double xmin = pbbox->q.x;
307
    double xmax = pbbox->p.x;
308
    double ymin = pbbox->q.y;
309
    double ymax = pbbox->p.y;
310
    int ixpat, iypat, iystart;
311
    double xpat, ypat;
312
    double xlower, xupper, ylower, yupper;
313
    double xdev, ydev;
314
    gs_rect dev_page, pat_page;
315
    gs_point dev_pat_origin, dev_step;
316
    int code;
317
 
318
    /*
319
     * Scan across the page.  We determine the region to be scanned
320
     * by working in the pattern coordinate space.  This is logically
321
     * simpler since XStep and YStep are on axis in the pattern space.
322
     */
323
    /*
324
     * Convert the page dimensions from device coordinates into the
325
     * pattern coordinate frame.
326
     */
327
    dev_page.p.x = dev_page.p.y = 0;
328
    dev_page.q.x = width;
329
    dev_page.q.y = height;
330
    code = gs_bbox_transform_inverse(&dev_page, pmat, &pat_page);
331
    if (code < 0)
332
	return code;
333
    /*
334
     * Determine the location of the pattern origin in device coordinates.
335
     */
336
    gs_point_transform(0.0, 0.0, pmat, &dev_pat_origin);
337
    /*
338
     * Determine our starting point.  We start with a postion that puts the
339
     * pattern below and to the left of the page (in pattern space) and scan
340
     * until the pattern is above and right of the page.
341
     */
342
    ixpat = (int) floor((pat_page.p.x - pinst->template.BBox.q.x) / xstep);
343
    iystart = (int) floor((pat_page.p.y - pinst->template.BBox.q.y) / ystep);
344
 
345
    /* Now do the scan */
346
    for (; ; ixpat++) {
347
        xpat = ixpat * xstep;
348
	for (iypat = iystart; ; iypat++) {
349
            ypat = iypat * ystep;
350
            /*
351
	     * Calculate the shift in the pattern's location.
352
	     */
353
	    gs_point_transform(xpat, ypat, pmat, &dev_step);
354
	    xdev = dev_step.x - dev_pat_origin.x;
355
	    ydev = dev_step.y - dev_pat_origin.y;
356
	    /*
357
	     * Check if the pattern bounding box intersects the page.
358
	     */
359
	    xlower = (xdev + pbbox->p.x > 0) ? pbbox->p.x : -xdev;
360
	    xupper = (xdev + pbbox->q.x < width) ? pbbox->q.x : -xdev + width;
361
	    ylower = (ydev + pbbox->p.y > 0) ? pbbox->p.y : -ydev;
362
	    yupper = (ydev + pbbox->q.y < height) ? pbbox->q.y : -ydev + height;
363
	    if (xlower < xupper && ylower < yupper) {
364
		/*
365
		 * The pattern intersects the page.  Expand required area if
366
		 * needed.
367
		 */
368
		if (xlower < xmin)
369
		    xmin = xlower;
370
		if (xupper > xmax)
371
		    xmax = xupper;
372
		if (ylower < ymin)
373
		    ymin = ylower;
374
		if (yupper > ymax)
375
		    ymax = yupper;
376
	    }
377
	    if (ypat > pat_page.q.y - pinst->template.BBox.p.y)
378
	        break;
379
	}
380
	if (xpat > pat_page.q.x - pinst->template.BBox.p.x)
381
	    break;
382
    }
383
    /* Update the bounding box. */
384
    if (xmin < xmax && ymin < ymax) {
385
	pbbox->p.x = xmin;
386
	pbbox->q.x = xmax;
387
	pbbox->p.y = ymin;
388
	pbbox->q.y = ymax;
389
    } else {
390
	/* The pattern is never on the page.  Set bbox = 1, 1 */
391
	pbbox->p.x = pbbox->p.y = 0;
392
	pbbox->q.x = pbbox->q.y = 1;
393
    }
394
    return 0;
395
}
396
 
397
/* Compute the stepping matrix and device space instance bounding box */
398
/* from the step values and the saved matrix. */
399
private int
400
compute_inst_matrix(gs_pattern1_instance_t * pinst, const gs_state * saved,
401
			    gs_rect * pbbox, int width, int height)
402
{
403
    double xx = pinst->template.XStep * saved->ctm.xx;
404
    double xy = pinst->template.XStep * saved->ctm.xy;
405
    double yx = pinst->template.YStep * saved->ctm.yx;
406
    double yy = pinst->template.YStep * saved->ctm.yy;
407
    int code;
408
 
409
    /* Adjust the stepping matrix so all coefficients are >= 0. */
410
    if (xx == 0 || yy == 0) {	/* We know that both xy and yx are non-zero. */
411
	double temp;
412
 
413
	temp = xx, xx = yx, yx = temp;
414
	temp = xy, xy = yy, yy = temp;
415
    }
416
    if (xx < 0)
417
	xx = -xx, xy = -xy;
418
    if (yy < 0)
419
	yx = -yx, yy = -yy;
420
    /* Now xx > 0, yy > 0. */
421
    pinst->step_matrix.xx = xx;
422
    pinst->step_matrix.xy = xy;
423
    pinst->step_matrix.yx = yx;
424
    pinst->step_matrix.yy = yy;
425
    pinst->step_matrix.tx = saved->ctm.tx;
426
    pinst->step_matrix.ty = saved->ctm.ty;
427
    code = gs_bbox_transform(&pinst->template.BBox, &ctm_only(saved), pbbox);
428
    /*
429
     * Some applications produce patterns that are larger than the page.
430
     * If the bounding box for the pattern is larger than the page. clamp
431
     * the pattern to the page size.
432
     */
433
    if (code >= 0 &&
434
	(pbbox->q.x - pbbox->p.x > width || pbbox->q.y - pbbox->p.y > height))
435
	code = clamp_pattern_bbox(pinst, pbbox, width,
436
					height, &ctm_only(saved));
437
 
438
    return code;
439
}
440
 
441
/* Test whether a PatternType 1 pattern uses a base space. */
442
private bool
443
gs_pattern1_uses_base_space(const gs_pattern_template_t *ptemp)
444
{
445
    return ((const gs_pattern1_template_t *)ptemp)->PaintType == 2;
446
}
447
 
448
/* getpattern for PatternType 1 */
449
/* This is only intended for the benefit of pattern PaintProcs. */
450
private const gs_pattern_template_t *
451
gs_pattern1_get_pattern(const gs_pattern_instance_t *pinst)
452
{
453
    return (const gs_pattern_template_t *)
454
	&((const gs_pattern1_instance_t *)pinst)->template;
455
}
456
 
457
/*
458
 * Perform actions required at setcolor time. This procedure resets the
459
 * overprint information (almost) as required by the pattern. The logic
460
 * behind this operation is a bit convoluted:
461
 *
462
 *  1. Both PatternType 1 and 2 "colors" occur within the pattern color
463
 *     space.
464
 *
465
 *  2. Nominally, the set of drawn components is a property of the color
466
 *     space, and is set at the time setcolorspace is called. This is
467
 *     not the case for patterns, so overprint information must be set
468
 *     at setcolor time for them.
469
 *
470
 *  3. PatternType 2 color spaces incorporate their own color space, so
471
 *     the set of drawn components is determined by that color space.
472
 *     For PatternType 1 color spaces, the PaintType determines the
473
 *     appropriate color space to use. If PaintType is 2 (uncolored),
474
 *     the pattern makes use of the base color space of the current
475
 *     pattern color space, so overprint is set as appropriate for
476
 *     that color space.
477
 *
478
 *  4. For PatternType 1 color spaces with PaintType 1 (colored), the
479
 *     appropriate color space to use is determined by the pattern's
480
 *     PaintProc. This cannot be handled by the current graphic
481
 *     library mechanism, because color space information is lost when
482
 *     the pattern tile is cached (and the pattern tile is essentially
483
 *     always cached). We punt in this case and list all components
484
 *     as drawn components. (This feature could be support by retaining
485
 *     per-component pattern masks, but complete re-design of the
486
 *     pattern mechanism is probably more appropriate.)
487
 *
488
 *  5. Once overprint information has been set for a particular color,
489
 *     it must be reset to the proper value when that color is no
490
 *     longer in use. "Normal" (non-pattern) colors do not have a
491
 *     "set_color" action, both for performance and logical reasons.
492
 *     This does not, however, cause significant difficulty, as the
493
 *     change in color space required to set a normal color will
494
 *     reset the overprint information as required.
495
 */
496
private int
497
gs_pattern1_set_color(const gs_client_color * pcc, gs_state * pgs)
498
{
499
    gs_pattern1_instance_t * pinst = (gs_pattern1_instance_t *)pcc->pattern;
500
    gs_pattern1_template_t * ptmplt = &pinst->template;
501
 
502
    if (ptmplt->PaintType == 2) {
503
        const gs_color_space *  pcs = pgs->color_space;
504
 
505
        pcs = (const gs_color_space *)&(pcs->params.pattern.base_space);
506
        return pcs->type->set_overprint(pcs, pgs);
507
    } else {
508
        gs_overprint_params_t   params;
509
 
510
        params.retain_any_comps = false;
511
        pgs->effective_overprint_mode = 0;
512
        return gs_state_update_overprint(pgs, &params);
513
    }
514
}
515
 
516
 
517
const gs_pattern1_template_t *
518
gs_getpattern(const gs_client_color * pcc)
519
{
520
    const gs_pattern_instance_t *pinst = pcc->pattern;
521
 
522
    return (pinst == 0 || pinst->type != &gs_pattern1_type ? 0 :
523
	    &((const gs_pattern1_instance_t *)pinst)->template);
524
}
525
 
526
/*
527
 *  Code for generating patterns from bitmaps and pixmaps.
528
 */
529
 
530
/*
531
 *  The following structures are realized here only because this is the
532
 *  first location in which they were needed. Otherwise, there is nothing
533
 *  about them that is specific to patterns.
534
 */
535
public_st_gs_bitmap();
536
public_st_gs_tile_bitmap();
537
public_st_gs_depth_bitmap();
538
public_st_gs_tile_depth_bitmap();
539
public_st_gx_strip_bitmap();
540
 
541
/*
542
 *  Structure for holding a gs_depth_bitmap and the corresponding depth and
543
 *  colorspace information.
544
 *
545
 *  The free_proc pointer is needed to hold the original value of the pattern
546
 *  instance free structure. This pointer in the pattern instance will be
547
 *  overwritten with free_pixmap_pattern, which will free the pixmap info
548
 *  structure when it is freed.
549
 */
550
typedef struct pixmap_info_s {
551
    gs_depth_bitmap bitmap;	/* must be first */
552
    const gs_color_space *pcspace;
553
    uint white_index;
554
    void (*free_proc)(gs_memory_t *, void *, client_name_t);
555
} pixmap_info;
556
 
557
gs_private_st_suffix_add1(st_pixmap_info,
558
			  pixmap_info,
559
			  "pixmap info. struct",
560
			  pixmap_enum_ptr,
561
			  pixmap_reloc_ptr,
562
			  st_gs_depth_bitmap,
563
			  pcspace
564
);
565
 
566
#define st_pixmap_info_max_ptrs (1 + st_tile_bitmap_max_ptrs)
567
 
568
/*
569
 *  Free routine for pattern instances created from pixmaps. This overwrites
570
 *  the free procedure originally stored in the pattern instance, and stores
571
 *  the pointer to that procedure in the pixmap_info structure. This procedure
572
 *  will call the original procedure, then free the pixmap_info structure. 
573
 *
574
 *  Note that this routine does NOT release the data in the original pixmap;
575
 *  that remains the responsibility of the client.
576
 */
577
private void
578
free_pixmap_pattern(
579
    gs_memory_t *           pmem,
580
    void *                  pvpinst,
581
    client_name_t           cname
582
)
583
{
584
    gs_pattern1_instance_t *pinst = (gs_pattern1_instance_t *)pvpinst;
585
    pixmap_info *ppmap = pinst->template.client_data;
586
 
587
    ppmap->free_proc(pmem, pvpinst, cname);
588
    gs_free_object(pmem, ppmap, cname);
589
}
590
 
591
/*
592
 *  PaintProcs for bitmap and pixmap patterns.
593
 */
594
private int bitmap_paint(gs_image_enum * pen, gs_data_image_t * pim,
595
			 const gs_depth_bitmap * pbitmap, gs_state * pgs);
596
private int
597
mask_PaintProc(const gs_client_color * pcolor, gs_state * pgs)
598
{
599
    const pixmap_info *ppmap = gs_getpattern(pcolor)->client_data;
600
    const gs_depth_bitmap *pbitmap = &(ppmap->bitmap);
601
    gs_image_enum *pen =
602
    gs_image_enum_alloc(gs_state_memory(pgs), "mask_PaintProc");
603
    gs_image1_t mask;
604
 
605
    if (pen == 0)
606
	return_error(gs_error_VMerror);
607
    gs_image_t_init_mask(&mask, true);
608
    mask.Width = pbitmap->size.x;
609
    mask.Height = pbitmap->size.y;
610
    gs_image_init(pen, &mask, false, pgs);
611
    return bitmap_paint(pen, (gs_data_image_t *) & mask, pbitmap, pgs);
612
}
613
private int
614
image_PaintProc(const gs_client_color * pcolor, gs_state * pgs)
615
{
616
    const pixmap_info *ppmap = gs_getpattern(pcolor)->client_data;
617
    const gs_depth_bitmap *pbitmap = &(ppmap->bitmap);
618
    gs_image_enum *pen =
619
        gs_image_enum_alloc(gs_state_memory(pgs), "image_PaintProc");
620
    gs_color_space cs;
621
    const gs_color_space *pcspace;
622
    gx_image_enum_common_t *pie;
623
    /*
624
     * If the image is transparent then we want to do image type4 processing.
625
     * Otherwise we want to use image type 1 processing.
626
     */
627
    int transparent = ppmap->white_index < (1 << (pbitmap->num_comps * pbitmap->pix_depth));
628
 
629
    /*
630
     * Note: gs_image1_t and gs_image4_t sre nearly identical structure
631
     * definitions.  From our point of view, the only significant difference
632
     * is MaskColor in gs_image4_t.  The fields are generally loaded using
633
     * the gs_image1_t version of the union and then used for either type
634
     * of image processing.
635
     */
636
    union {
637
        gs_image1_t i1;
638
	gs_image4_t i4;
639
    } image;
640
    int code;
641
 
642
    if (pen == 0)
643
	return_error(gs_error_VMerror);
644
 
645
    if (ppmap->pcspace == 0) {
646
        gs_cspace_init_DeviceGray(pgs->memory, &cs);
647
        pcspace = &cs;
648
    } else
649
        pcspace = ppmap->pcspace;
650
    gs_gsave(pgs);
651
    gs_setcolorspace(pgs, pcspace);
652
    if (transparent)
653
        gs_image4_t_init( (gs_image4_t *) &image, pcspace);
654
    else
655
        gs_image_t_init_adjust( (gs_image_t *) &image, pcspace, 0);
656
    image.i1.Width = pbitmap->size.x;
657
    image.i1.Height = pbitmap->size.y;
658
    if (transparent) {
659
        image.i4.MaskColor_is_range = false;
660
        image.i4.MaskColor[0] = ppmap->white_index;
661
    }
662
    image.i1.Decode[0] = 0.0;
663
    image.i1.Decode[1] = (float)((1 << pbitmap->pix_depth) - 1);
664
    image.i1.BitsPerComponent = pbitmap->pix_depth;
665
    /* backwards compatibility */
666
    if (ppmap->pcspace == 0) {
667
	image.i1.Decode[0] = 1.0;
668
	image.i1.Decode[1] = 0.0;
669
    }
670
 
671
    if ( (code = gs_image_begin_typed( (const gs_image_common_t *)&image,
672
                                       pgs,
673
		                       false,
674
                                       &pie )) >= 0 &&
675
         (code = gs_image_enum_init( pen,
676
                                     pie,
677
                                     (gs_data_image_t *)&image,
678
                                     pgs )) >= 0      )
679
	code = bitmap_paint(pen, (gs_data_image_t *) & image, pbitmap, pgs);
680
    gs_grestore(pgs);
681
    return code;
682
}
683
/* Finish painting any kind of bitmap pattern. */
684
private int
685
bitmap_paint(gs_image_enum * pen, gs_data_image_t * pim,
686
	     const gs_depth_bitmap * pbitmap, gs_state * pgs)
687
{
688
    uint raster = pbitmap->raster;
689
    uint nbytes = (pim->Width * pbitmap->pix_depth + 7) >> 3;
690
    uint used;
691
    const byte *dp = pbitmap->data;
692
    int n;
693
    int code = 0, code1;
694
 
695
    if (nbytes == raster)
696
	code = gs_image_next(pen, dp, nbytes * pim->Height, &used);
697
    else
698
	for (n = pim->Height; n > 0 && code >= 0; dp += raster, --n)
699
	    code = gs_image_next(pen, dp, nbytes, &used);
700
    code1 = gs_image_cleanup_and_free_enum(pen);
701
    if (code >= 0 && code1 < 0)
702
	code = code1;
703
    return code;
704
}
705
 
706
/*
707
 * Make a pattern from a bitmap or pixmap. The pattern may be colored or
708
 * uncolored, as determined by the mask operand. This code is intended
709
 * primarily for use by PCL.
710
 *
711
 * See the comment prior to the declaration of this function in gscolor2.h
712
 * for further information.
713
 */
714
int
715
gs_makepixmappattern(
716
			gs_client_color * pcc,
717
			const gs_depth_bitmap * pbitmap,
718
			bool mask,
719
			const gs_matrix * pmat,
720
			long id,
721
			const gs_color_space * pcspace,
722
			uint white_index,
723
			gs_state * pgs,
724
			gs_memory_t * mem
725
)
726
{
727
 
728
    gs_pattern1_template_t pat;
729
    pixmap_info *ppmap;
730
    gs_matrix mat, smat;
731
    int code;
732
 
733
    /* check that the data is legitimate */
734
    if ((mask) || (pcspace == 0)) {
735
	if (pbitmap->pix_depth != 1)
736
	    return_error(gs_error_rangecheck);
737
	pcspace = 0;
738
    } else if (gs_color_space_get_index(pcspace) != gs_color_space_index_Indexed)
739
	return_error(gs_error_rangecheck);
740
    if (pbitmap->num_comps != 1)
741
	return_error(gs_error_rangecheck);
742
 
743
    /* allocate and initialize a pixmap_info structure for the paint proc */
744
    if (mem == 0)
745
	mem = gs_state_memory(pgs);
746
    ppmap = gs_alloc_struct(mem,
747
			    pixmap_info,
748
			    &st_pixmap_info,
749
			    "makepximappattern"
750
	);
751
    if (ppmap == 0)
752
	return_error(gs_error_VMerror);
753
    ppmap->bitmap = *pbitmap;
754
    ppmap->pcspace = pcspace;
755
    ppmap->white_index = white_index;
756
 
757
    /* set up the client pattern structure */
758
    gs_pattern1_init(&pat);
759
    uid_set_UniqueID(&pat.uid, (id == no_UniqueID) ? gs_next_ids(mem, 1) : id);
760
    pat.PaintType = (mask ? 2 : 1);
761
    pat.TilingType = 1;
762
    pat.BBox.p.x = 0;
763
    pat.BBox.p.y = 0;
764
    pat.BBox.q.x = pbitmap->size.x;
765
    pat.BBox.q.y = pbitmap->size.y;
766
    pat.XStep = (float)pbitmap->size.x;
767
    pat.YStep = (float)pbitmap->size.y;
768
    pat.PaintProc = (mask ? mask_PaintProc : image_PaintProc);
769
    pat.client_data = ppmap;
770
 
771
    /* set the ctm to be the identity */
772
    gs_currentmatrix(pgs, &smat);
773
    gs_make_identity(&mat);
774
    gs_setmatrix(pgs, &mat);
775
 
776
    /* build the pattern, restore the previous matrix */
777
    if (pmat == NULL)
778
	pmat = &mat;
779
    if ((code = gs_makepattern(pcc, &pat, pmat, pgs, mem)) != 0)
780
	gs_free_object(mem, ppmap, "makebitmappattern_xform");
781
    else {
782
	/*
783
	 * If this is not a masked pattern and if the white pixel index
784
	 * is outside of the representable range, we don't need to go to
785
	 * the trouble of accumulating a mask that will just be all 1s.
786
	 */
787
	gs_pattern1_instance_t *pinst =
788
	    (gs_pattern1_instance_t *)pcc->pattern;
789
 
790
	if (!mask && (white_index >= (1 << pbitmap->pix_depth)))
791
	    pinst->uses_mask = false;
792
 
793
        /* overwrite the free procedure for the pattern instance */
794
        ppmap->free_proc = pinst->rc.free;
795
        pinst->rc.free = free_pixmap_pattern;
796
 
797
	/*
798
	 * Since the PaintProcs don't reference the saved color space or
799
	 * color, clear these so that there isn't an extra retained
800
	 * reference to the Pattern object.
801
	 */
802
	gs_setgray(pinst->saved, 0.0);
803
 
804
    }
805
    gs_setmatrix(pgs, &smat);
806
    return code;
807
}
808
 
809
/*
810
 *  Backwards compatibility.
811
 */
812
int
813
gs_makebitmappattern_xform(
814
			      gs_client_color * pcc,
815
			      const gx_tile_bitmap * ptile,
816
			      bool mask,
817
			      const gs_matrix * pmat,
818
			      long id,
819
			      gs_state * pgs,
820
			      gs_memory_t * mem
821
)
822
{
823
    gs_depth_bitmap bitmap;
824
 
825
    /* build the bitmap the size of one repetition */
826
    bitmap.data = ptile->data;
827
    bitmap.raster = ptile->raster;
828
    bitmap.size.x = ptile->rep_width;
829
    bitmap.size.y = ptile->rep_height;
830
    bitmap.id = ptile->id;	/* shouldn't matter */
831
    bitmap.pix_depth = 1;
832
    bitmap.num_comps = 1;
833
 
834
    return gs_makepixmappattern(pcc, &bitmap, mask, pmat, id, 0, 0, pgs, mem);
835
}
836
 
837
 
838
/* ------ Color space implementation ------ */
839
 
840
/*
841
 * Defined the Pattern device color types.  We need a masked analogue of
842
 * each of the non-pattern types, to handle uncolored patterns.  We use
843
 * 'masked_fill_rect' instead of 'masked_fill_rectangle' in order to limit
844
 * identifier lengths to 32 characters.
845
 */
846
private dev_color_proc_get_dev_halftone(gx_dc_pattern_get_dev_halftone);
847
private dev_color_proc_load(gx_dc_pattern_load);
848
/*dev_color_proc_fill_rectangle(gx_dc_pattern_fill_rectangle); *//*gxp1fill.h */
849
private dev_color_proc_equal(gx_dc_pattern_equal);
850
private dev_color_proc_load(gx_dc_pure_masked_load);
851
 
852
private dev_color_proc_get_dev_halftone(gx_dc_pure_masked_get_dev_halftone);
853
/*dev_color_proc_fill_rectangle(gx_dc_pure_masked_fill_rect); *//*gxp1fill.h */
854
private dev_color_proc_equal(gx_dc_pure_masked_equal);
855
private dev_color_proc_load(gx_dc_binary_masked_load);
856
 
857
private dev_color_proc_get_dev_halftone(gx_dc_binary_masked_get_dev_halftone);
858
/*dev_color_proc_fill_rectangle(gx_dc_binary_masked_fill_rect); *//*gxp1fill.h */
859
private dev_color_proc_equal(gx_dc_binary_masked_equal);
860
private dev_color_proc_load(gx_dc_colored_masked_load);
861
 
862
private dev_color_proc_get_dev_halftone(gx_dc_colored_masked_get_dev_halftone);
863
/*dev_color_proc_fill_rectangle(gx_dc_colored_masked_fill_rect); *//*gxp1fill.h */
864
private dev_color_proc_equal(gx_dc_colored_masked_equal);
865
 
866
/* The device color types are exported for gxpcmap.c. */
867
gs_private_st_composite(st_dc_pattern, gx_device_color, "dc_pattern",
868
			dc_pattern_enum_ptrs, dc_pattern_reloc_ptrs);
869
const gx_device_color_type_t gx_dc_pattern = {
870
    &st_dc_pattern,
871
    gx_dc_pattern_save_dc, gx_dc_pattern_get_dev_halftone,
872
    gx_dc_ht_get_phase,
873
    gx_dc_pattern_load, gx_dc_pattern_fill_rectangle,
874
    gx_dc_default_fill_masked, gx_dc_pattern_equal,
875
    gx_dc_pattern_write, gx_dc_pattern_read, 
876
    gx_dc_pattern_get_nonzero_comps
877
};
878
 
879
extern_st(st_dc_ht_binary);
880
gs_private_st_composite(st_dc_pure_masked, gx_device_color, "dc_pure_masked",
881
			dc_masked_enum_ptrs, dc_masked_reloc_ptrs);
882
const gx_device_color_type_t gx_dc_pure_masked = {
883
    &st_dc_pure_masked,
884
    gx_dc_pattern_save_dc, gx_dc_pure_masked_get_dev_halftone,
885
    gx_dc_no_get_phase,
886
    gx_dc_pure_masked_load, gx_dc_pure_masked_fill_rect,
887
    gx_dc_default_fill_masked, gx_dc_pure_masked_equal,
888
    gx_dc_pattern_write, gx_dc_pattern_read, 
889
    gx_dc_pure_get_nonzero_comps
890
};
891
 
892
gs_private_st_composite(st_dc_binary_masked, gx_device_color,
893
			"dc_binary_masked", dc_binary_masked_enum_ptrs,
894
			dc_binary_masked_reloc_ptrs);
895
const gx_device_color_type_t gx_dc_binary_masked = {
896
    &st_dc_binary_masked,
897
    gx_dc_pattern_save_dc, gx_dc_binary_masked_get_dev_halftone,
898
    gx_dc_ht_get_phase,
899
    gx_dc_binary_masked_load, gx_dc_binary_masked_fill_rect,
900
    gx_dc_default_fill_masked, gx_dc_binary_masked_equal,
901
    gx_dc_pattern_write, gx_dc_pattern_read, 
902
    gx_dc_ht_binary_get_nonzero_comps
903
};
904
 
905
gs_private_st_composite_only(st_dc_colored_masked, gx_device_color,
906
			     "dc_colored_masked",
907
			     dc_masked_enum_ptrs, dc_masked_reloc_ptrs);
908
const gx_device_color_type_t gx_dc_colored_masked = {
909
    &st_dc_colored_masked,
910
    gx_dc_pattern_save_dc, gx_dc_colored_masked_get_dev_halftone,
911
    gx_dc_ht_get_phase,
912
    gx_dc_colored_masked_load, gx_dc_colored_masked_fill_rect,
913
    gx_dc_default_fill_masked, gx_dc_colored_masked_equal,
914
    gx_dc_pattern_write, gx_dc_pattern_read, 
915
    gx_dc_ht_colored_get_nonzero_comps
916
};
917
 
918
#undef gx_dc_type_pattern
919
const gx_device_color_type_t *const gx_dc_type_pattern = &gx_dc_pattern;
920
#define gx_dc_type_pattern (&gx_dc_pattern)
921
 
922
/* GC procedures */
923
private 
924
ENUM_PTRS_WITH(dc_pattern_enum_ptrs, gx_device_color *cptr)
925
{
926
    return ENUM_USING(st_dc_pure_masked, vptr, size, index - 1);
927
}
928
case 0:
929
{
930
    gx_color_tile *tile = cptr->colors.pattern.p_tile;
931
 
932
    ENUM_RETURN((tile == 0 ? tile : tile - tile->index));
933
}
934
ENUM_PTRS_END
935
private RELOC_PTRS_WITH(dc_pattern_reloc_ptrs, gx_device_color *cptr)
936
{
937
    gx_color_tile *tile = cptr->colors.pattern.p_tile;
938
 
939
    if (tile != 0) {
940
	uint index = tile->index;
941
 
942
	RELOC_TYPED_OFFSET_PTR(gx_device_color, colors.pattern.p_tile, index);
943
    }
944
    RELOC_USING(st_dc_pure_masked, vptr, size);
945
}
946
RELOC_PTRS_END
947
private ENUM_PTRS_WITH(dc_masked_enum_ptrs, gx_device_color *cptr)
948
ENUM_SUPER(gx_device_color, st_client_color, ccolor, 1);
949
case 0:
950
{
951
    gx_color_tile *mask = cptr->mask.m_tile;
952
 
953
    ENUM_RETURN((mask == 0 ? mask : mask - mask->index));
954
}
955
ENUM_PTRS_END
956
private RELOC_PTRS_WITH(dc_masked_reloc_ptrs, gx_device_color *cptr)
957
{
958
    gx_color_tile *mask = cptr->mask.m_tile;
959
 
960
    RELOC_SUPER(gx_device_color, st_client_color, ccolor);
961
    if (mask != 0) {
962
	uint index = mask->index;
963
 
964
	RELOC_TYPED_OFFSET_PTR(gx_device_color, mask.m_tile, index);
965
    }
966
}
967
RELOC_PTRS_END
968
private ENUM_PTRS_BEGIN(dc_binary_masked_enum_ptrs)
969
{
970
    return ENUM_USING(st_dc_ht_binary, vptr, size, index - 2);
971
}
972
case 0:
973
case 1:
974
return ENUM_USING(st_dc_pure_masked, vptr, size, index);
975
ENUM_PTRS_END
976
private RELOC_PTRS_BEGIN(dc_binary_masked_reloc_ptrs)
977
{
978
    RELOC_USING(st_dc_pure_masked, vptr, size);
979
    RELOC_USING(st_dc_ht_binary, vptr, size);
980
}
981
RELOC_PTRS_END
982
 
983
 
984
/*
985
 * Currently patterns cannot be passed through the command list,
986
 * however vector devices need to save a color for comparing
987
 * it with another color, which appears later.
988
 * We provide a minimal support, which is necessary
989
 * for the current implementation of pdfwrite.
990
 * It is not sufficient for restoring the pattern from the saved color.
991
 */
992
void
993
gx_dc_pattern_save_dc(
994
    const gx_device_color * pdevc, 
995
    gx_device_color_saved * psdc )
996
{
997
    psdc->type = pdevc->type;
998
    if (pdevc->ccolor_valid) {
999
	psdc->colors.pattern.id = pdevc->ccolor.pattern->pattern_id;
1000
	psdc->colors.pattern.phase = pdevc->phase;
1001
    } {
1002
	/* The client color has been changed to a non-pattern color,
1003
	   but device color has not been created yet. 
1004
	 */
1005
	psdc->colors.pattern.id = gs_no_id;
1006
	psdc->colors.pattern.phase.x = psdc->colors.pattern.phase.y = 0;
1007
    }
1008
}
1009
 
1010
/*
1011
 * Colored Type 1 patterns cannot provide a halftone, as multiple
1012
 * halftones may be used by the PaintProc procedure. Hence, we can only
1013
 * hope this is a contone device.
1014
 */
1015
private const gx_device_halftone *
1016
gx_dc_pattern_get_dev_halftone(const gx_device_color * pdevc)
1017
{
1018
    return 0;
1019
}
1020
 
1021
/*
1022
 * Uncolored Type 1 halftones make use of the halftone impplied by their
1023
 * base color. Ideally this would be returned via an inhereted method,
1024
 * but the device color structure does not support such an arrangement.
1025
 */
1026
private const gx_device_halftone *
1027
gx_dc_pure_masked_get_dev_halftone(const gx_device_color * pdevc)
1028
{
1029
    return 0;
1030
}
1031
 
1032
private const gx_device_halftone *
1033
gx_dc_binary_masked_get_dev_halftone(const gx_device_color * pdevc)
1034
{
1035
    return pdevc->colors.binary.b_ht;
1036
}
1037
 
1038
private const gx_device_halftone *
1039
gx_dc_colored_masked_get_dev_halftone(const gx_device_color * pdevc)
1040
{
1041
    return pdevc->colors.colored.c_ht;
1042
}
1043
 
1044
 
1045
/* Macros for pattern loading */
1046
#define FINISH_PATTERN_LOAD\
1047
	while ( !gx_pattern_cache_lookup(pdevc, pis, dev, select) )\
1048
	 { code = gx_pattern_load(pdevc, pis, dev, select);\
1049
	   if ( code < 0 ) break;\
1050
	 }\
1051
	return code;
1052
 
1053
/* Ensure that a colored Pattern is loaded in the cache. */
1054
private int
1055
gx_dc_pattern_load(gx_device_color * pdevc, const gs_imager_state * pis,
1056
		   gx_device * dev, gs_color_select_t select)
1057
{
1058
    int code = 0;
1059
 
1060
    FINISH_PATTERN_LOAD
1061
}
1062
/* Ensure that an uncolored Pattern is loaded in the cache. */
1063
private int
1064
gx_dc_pure_masked_load(gx_device_color * pdevc, const gs_imager_state * pis,
1065
		       gx_device * dev, gs_color_select_t select)
1066
{
1067
    int code = (*gx_dc_type_data_pure.load) (pdevc, pis, dev, select);
1068
 
1069
    if (code < 0)
1070
	return code;
1071
    FINISH_PATTERN_LOAD
1072
}
1073
private int
1074
gx_dc_binary_masked_load(gx_device_color * pdevc, const gs_imager_state * pis,
1075
			 gx_device * dev, gs_color_select_t select)
1076
{
1077
    int code = (*gx_dc_type_data_ht_binary.load) (pdevc, pis, dev, select);
1078
 
1079
    if (code < 0)
1080
	return code;
1081
    FINISH_PATTERN_LOAD
1082
}
1083
private int
1084
gx_dc_colored_masked_load(gx_device_color * pdevc, const gs_imager_state * pis,
1085
			  gx_device * dev, gs_color_select_t select)
1086
{
1087
    int code = (*gx_dc_type_data_ht_colored.load) (pdevc, pis, dev, select);
1088
 
1089
    if (code < 0)
1090
	return code;
1091
    FINISH_PATTERN_LOAD
1092
}
1093
 
1094
/* Look up a pattern color in the cache. */
1095
bool
1096
gx_pattern_cache_lookup(gx_device_color * pdevc, const gs_imager_state * pis,
1097
			gx_device * dev, gs_color_select_t select)
1098
{
1099
    gx_pattern_cache *pcache = pis->pattern_cache;
1100
    gx_bitmap_id id = pdevc->mask.id;
1101
 
1102
    if (id == gx_no_bitmap_id) {
1103
	color_set_null_pattern(pdevc);
1104
	return true;
1105
    }
1106
    if (pcache != 0) {
1107
	gx_color_tile *ctile = &pcache->tiles[id % pcache->num_tiles];
1108
	bool internal_accum = true;
1109
	if (pis->have_pattern_streams) {
1110
	    int code = dev_proc(dev, pattern_manage)(dev, id, NULL, pattern_manage__load);
1111
	    internal_accum = (code == 0);
1112
	    if (code < 0)
1113
		return false;
1114
	}
1115
	if (ctile->id == id &&
1116
	    ctile->is_dummy == !internal_accum &&
1117
	    (pdevc->type != &gx_dc_pattern ||
1118
	     ctile->depth == dev->color_info.depth)
1119
	    ) {
1120
	    int px = pis->screen_phase[select].x;
1121
	    int py = pis->screen_phase[select].y;
1122
 
1123
	    if (pdevc->type == &gx_dc_pattern) {	/* colored */
1124
		pdevc->colors.pattern.p_tile = ctile;
1125
		color_set_phase_mod(pdevc, px, py,
1126
				    ctile->tbits.rep_width,
1127
				    ctile->tbits.rep_height);
1128
	    }
1129
	    pdevc->mask.m_tile =
1130
		(ctile->tmask.data == 0 ? (gx_color_tile *) 0 :
1131
		 ctile);
1132
	    pdevc->mask.m_phase.x = -px;
1133
	    pdevc->mask.m_phase.y = -py;
1134
	    return true;
1135
	}
1136
    }
1137
    return false;
1138
}
1139
 
1140
#undef FINISH_PATTERN_LOAD
1141
 
1142
/* Compare two Pattern colors for equality. */
1143
private bool
1144
gx_dc_pattern_equal(const gx_device_color * pdevc1,
1145
		    const gx_device_color * pdevc2)
1146
{
1147
    return pdevc2->type == pdevc1->type &&
1148
	pdevc1->phase.x == pdevc2->phase.x &&
1149
	pdevc1->phase.y == pdevc2->phase.y &&
1150
	pdevc1->mask.id == pdevc2->mask.id;
1151
}
1152
 
1153
/*
1154
 * For shading and colored tiling patterns, it is not possible to say
1155
 * which color components have non-zero values. The following routine
1156
 * indicates this by just returning 1. The procedure is exported for
1157
 * the benefit of gsptype2.c.
1158
 */
1159
int
1160
gx_dc_pattern_get_nonzero_comps(
1161
    const gx_device_color * pdevc_ignored,
1162
    const gx_device *       dev_ignored,
1163
    gx_color_index *        pcomp_bits_ignored )
1164
{
1165
    return 1;
1166
}
1167
 
1168
 
1169
private bool
1170
gx_dc_pure_masked_equal(const gx_device_color * pdevc1,
1171
			const gx_device_color * pdevc2)
1172
{
1173
    return (*gx_dc_type_pure->equal) (pdevc1, pdevc2) &&
1174
	pdevc1->mask.id == pdevc2->mask.id;
1175
}
1176
private bool
1177
gx_dc_binary_masked_equal(const gx_device_color * pdevc1,
1178
			  const gx_device_color * pdevc2)
1179
{
1180
    return (*gx_dc_type_ht_binary->equal) (pdevc1, pdevc2) &&
1181
	pdevc1->mask.id == pdevc2->mask.id;
1182
}
1183
private bool
1184
gx_dc_colored_masked_equal(const gx_device_color * pdevc1,
1185
			   const gx_device_color * pdevc2)
1186
{
1187
    return (*gx_dc_type_ht_colored->equal) (pdevc1, pdevc2) &&
1188
	pdevc1->mask.id == pdevc2->mask.id;
1189
}
1190
 
1191
/* currently, patterns cannot be passed through the command list */
1192
int
1193
gx_dc_pattern_write(
1194
    const gx_device_color *         pdevc,
1195
    const gx_device_color_saved *   psdc,
1196
    const gx_device *               dev,
1197
    byte *                          data,
1198
    uint *                          psize )
1199
{
1200
    return_error(gs_error_unknownerror);
1201
}
1202
 
1203
int
1204
gx_dc_pattern_read(
1205
    gx_device_color *       pdevc,
1206
    const gs_imager_state * pis,
1207
    const gx_device_color * prior_devc,
1208
    const gx_device *       dev,
1209
    const byte *            data,
1210
    uint                    size,
1211
    gs_memory_t *           mem )
1212
{
1213
    return_error(gs_error_unknownerror);
1214
}