xref: /plan9/sys/src/cmd/gs/src/gsptype1.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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 */
ENUM_PTRS_BEGIN(pattern1_instance_enum_ptrs)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
RELOC_PTRS_BEGIN(pattern1_instance_reloc_ptrs)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
gs_cspace_build_Pattern1(gs_color_space ** ppcspace,const gs_color_space * pbase_cspace,gs_memory_t * pmem)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
gs_pattern1_init(gs_pattern1_template_t * ppat)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
gs_makepattern(gs_client_color * pcc,const gs_pattern1_template_t * pcp,const gs_matrix * pmat,gs_state * pgs,gs_memory_t * mem)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
gs_pattern1_make_pattern(gs_client_color * pcc,const gs_pattern_template_t * ptemp,const gs_matrix * pmat,gs_state * pgs,gs_memory_t * mem)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
clamp_pattern_bbox(gs_pattern1_instance_t * pinst,gs_rect * pbbox,int width,int height,const gs_matrix * pmat)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
compute_inst_matrix(gs_pattern1_instance_t * pinst,const gs_state * saved,gs_rect * pbbox,int width,int height)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
gs_pattern1_uses_base_space(const gs_pattern_template_t * ptemp)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 *
gs_pattern1_get_pattern(const gs_pattern_instance_t * pinst)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
gs_pattern1_set_color(const gs_client_color * pcc,gs_state * pgs)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 *
gs_getpattern(const gs_client_color * pcc)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
free_pixmap_pattern(gs_memory_t * pmem,void * pvpinst,client_name_t cname)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
mask_PaintProc(const gs_client_color * pcolor,gs_state * pgs)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
image_PaintProc(const gs_client_color * pcolor,gs_state * pgs)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
bitmap_paint(gs_image_enum * pen,gs_data_image_t * pim,const gs_depth_bitmap * pbitmap,gs_state * pgs)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
gs_makepixmappattern(gs_client_color * pcc,const gs_depth_bitmap * pbitmap,bool mask,const gs_matrix * pmat,long id,const gs_color_space * pcspace,uint white_index,gs_state * pgs,gs_memory_t * mem)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
gs_makebitmappattern_xform(gs_client_color * pcc,const gx_tile_bitmap * ptile,bool mask,const gs_matrix * pmat,long id,gs_state * pgs,gs_memory_t * mem)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
ENUM_PTRS_WITH(dc_pattern_enum_ptrs,gx_device_color * cptr)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
RELOC_PTRS_WITH(dc_pattern_reloc_ptrs,gx_device_color * cptr)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
RELOC_PTRS_WITH(dc_masked_reloc_ptrs,gx_device_color * cptr)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
ENUM_PTRS_BEGIN(dc_binary_masked_enum_ptrs)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
RELOC_PTRS_BEGIN(dc_binary_masked_reloc_ptrs)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
gx_dc_pattern_save_dc(const gx_device_color * pdevc,gx_device_color_saved * psdc)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 *
gx_dc_pattern_get_dev_halftone(const gx_device_color * pdevc)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 *
gx_dc_pure_masked_get_dev_halftone(const gx_device_color * pdevc)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 *
gx_dc_binary_masked_get_dev_halftone(const gx_device_color * pdevc)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 *
gx_dc_colored_masked_get_dev_halftone(const gx_device_color * pdevc)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
gx_dc_pattern_load(gx_device_color * pdevc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)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
gx_dc_pure_masked_load(gx_device_color * pdevc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)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
gx_dc_binary_masked_load(gx_device_color * pdevc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)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
gx_dc_colored_masked_load(gx_device_color * pdevc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)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
gx_pattern_cache_lookup(gx_device_color * pdevc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)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
gx_dc_pattern_equal(const gx_device_color * pdevc1,const gx_device_color * pdevc2)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
gx_dc_pattern_get_nonzero_comps(const gx_device_color * pdevc_ignored,const gx_device * dev_ignored,gx_color_index * pcomp_bits_ignored)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
gx_dc_pure_masked_equal(const gx_device_color * pdevc1,const gx_device_color * pdevc2)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
gx_dc_binary_masked_equal(const gx_device_color * pdevc1,const gx_device_color * pdevc2)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
gx_dc_colored_masked_equal(const gx_device_color * pdevc1,const gx_device_color * pdevc2)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
gx_dc_pattern_write(const gx_device_color * pdevc,const gx_device_color_saved * psdc,const gx_device * dev,byte * data,uint * psize)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
gx_dc_pattern_read(gx_device_color * pdevc,const gs_imager_state * pis,const gx_device_color * prior_devc,const gx_device * dev,const byte * data,uint size,gs_memory_t * mem)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 }
1215