xref: /plan9/sys/src/cmd/gs/src/gxdcolor.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1996, 2000 Aladdin Enterprises.  All rights reserved.
2 
3   This software is provided AS-IS with no warranty, either express or
4   implied.
5 
6   This software is distributed under license and may not be copied,
7   modified or distributed except as expressly authorized under the terms
8   of the license contained in the file LICENSE in this distribution.
9 
10   For more information about licensing, please refer to
11   http://www.ghostscript.com/licensing/. For information on
12   commercial licensing, go to http://www.artifex.com/licensing/ or
13   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15 */
16 
17 /*$Id: gxdcolor.c,v 1.13 2005/06/20 08:59:23 igor Exp $ */
18 /* Pure and null device color implementation */
19 #include "gx.h"
20 #include "memory_.h"
21 #include "gserrors.h"
22 #include "gsbittab.h"
23 #include "gxdcolor.h"
24 #include "gxdevice.h"
25 #include "gxdevcli.h"
26 
27 /* Define the standard device color types. */
28 
29 /* 'none' means the color is not defined. */
30 private dev_color_proc_save_dc(gx_dc_no_save_dc);
31 private dev_color_proc_get_dev_halftone(gx_dc_no_get_dev_halftone);
32 private dev_color_proc_load(gx_dc_no_load);
33 private dev_color_proc_fill_rectangle(gx_dc_no_fill_rectangle);
34 private dev_color_proc_fill_masked(gx_dc_no_fill_masked);
35 private dev_color_proc_equal(gx_dc_no_equal);
36 private dev_color_proc_write(gx_dc_no_write);
37 private dev_color_proc_read(gx_dc_no_read);
38 private dev_color_proc_get_nonzero_comps(gx_dc_no_get_nonzero_comps);
39 const gx_device_color_type_t gx_dc_type_data_none = {
40     &st_bytes,
41     gx_dc_no_save_dc, gx_dc_no_get_dev_halftone, gx_dc_no_get_phase,
42     gx_dc_no_load, gx_dc_no_fill_rectangle, gx_dc_no_fill_masked,
43     gx_dc_no_equal, gx_dc_no_write, gx_dc_no_read, gx_dc_no_get_nonzero_comps
44 };
45 #undef gx_dc_type_none
46 const gx_device_color_type_t *const gx_dc_type_none = &gx_dc_type_data_none;
47 #define gx_dc_type_none (&gx_dc_type_data_none)
48 
49 /* 'null' means the color has no effect when used for drawing. */
50 private dev_color_proc_load(gx_dc_null_load);
51 private dev_color_proc_fill_rectangle(gx_dc_null_fill_rectangle);
52 private dev_color_proc_fill_masked(gx_dc_null_fill_masked);
53 private dev_color_proc_equal(gx_dc_null_equal);
54 private dev_color_proc_read(gx_dc_null_read);
55 const gx_device_color_type_t gx_dc_type_data_null = {
56     &st_bytes,
57     gx_dc_no_save_dc, gx_dc_no_get_dev_halftone, gx_dc_no_get_phase,
58     gx_dc_null_load, gx_dc_null_fill_rectangle, gx_dc_null_fill_masked,
59     gx_dc_null_equal, gx_dc_no_write, gx_dc_null_read, gx_dc_no_get_nonzero_comps
60 };
61 #undef gx_dc_type_null
62 const gx_device_color_type_t *const gx_dc_type_null = &gx_dc_type_data_null;
63 #define gx_dc_type_null (&gx_dc_type_data_null)
64 
65 private dev_color_proc_save_dc(gx_dc_pure_save_dc);
66 private dev_color_proc_load(gx_dc_pure_load);
67 private dev_color_proc_fill_rectangle(gx_dc_pure_fill_rectangle);
68 private dev_color_proc_fill_masked(gx_dc_pure_fill_masked);
69 private dev_color_proc_equal(gx_dc_pure_equal);
70 private dev_color_proc_write(gx_dc_pure_write);
71 private dev_color_proc_read(gx_dc_pure_read);
72 const gx_device_color_type_t gx_dc_type_data_pure = {
73     &st_bytes,
74     gx_dc_pure_save_dc, gx_dc_no_get_dev_halftone, gx_dc_no_get_phase,
75     gx_dc_pure_load, gx_dc_pure_fill_rectangle, gx_dc_pure_fill_masked,
76     gx_dc_pure_equal, gx_dc_pure_write, gx_dc_pure_read,
77     gx_dc_pure_get_nonzero_comps
78 };
79 #undef gx_dc_type_pure
80 const gx_device_color_type_t *const gx_dc_type_pure = &gx_dc_type_data_pure;
81 #define gx_dc_type_pure (&gx_dc_type_data_pure)
82 
83 /*
84  * Get the black and white pixel values of a device.
85  */
86 gx_color_index
gx_device_black(gx_device * dev)87 gx_device_black(gx_device *dev)
88 {
89     if (dev->cached_colors.black == gx_no_color_index) {
90 	const gx_cm_color_map_procs * cm_procs = dev_proc(dev, get_color_mapping_procs)(dev);
91         int i, ncomps = dev->color_info.num_components;
92         frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
93         gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
94 
95     	/* Get color components for black (gray = 0) */
96     	cm_procs->map_gray(dev, frac_0, cm_comps);
97 
98         for (i = 0; i < ncomps; i++)
99             cv[i] = frac2cv(cm_comps[i]);
100 
101 	dev->cached_colors.black = dev_proc(dev, encode_color)(dev, cv);
102     }
103     return dev->cached_colors.black;
104 }
105 gx_color_index
gx_device_white(gx_device * dev)106 gx_device_white(gx_device *dev)
107 {
108     if (dev->cached_colors.white == gx_no_color_index) {
109 	const gx_cm_color_map_procs * cm_procs = dev_proc(dev, get_color_mapping_procs)(dev);
110         int i, ncomps = dev->color_info.num_components;
111         frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
112         gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
113 
114     	/* Get color components for white (gray = 1) */
115     	cm_procs->map_gray(dev, frac_1, cm_comps);
116 
117         for (i = 0; i < ncomps; i++)
118             cv[i] = frac2cv(cm_comps[i]);
119 
120 	dev->cached_colors.white = dev_proc(dev, encode_color)(dev, cv);
121     }
122     return dev->cached_colors.white;
123 }
124 
125 /* Clear the color cache. */
126 void
gx_device_decache_colors(gx_device * dev)127 gx_device_decache_colors(gx_device *dev)
128 {
129     dev->cached_colors.black = dev->cached_colors.white = gx_no_color_index;
130 }
131 
132 /* Set a null RasterOp source. */
133 private const gx_rop_source_t gx_rop_no_source_0 = {gx_rop_no_source_body(0)};
134 private const gx_rop_source_t gx_rop_no_source_1 = {gx_rop_no_source_body(1)};
135 void
gx_set_rop_no_source(const gx_rop_source_t ** psource,gx_rop_source_t * pno_source,gx_device * dev)136 gx_set_rop_no_source(const gx_rop_source_t **psource,
137 		     gx_rop_source_t *pno_source, gx_device *dev)
138 {
139     gx_color_index black;
140 
141 top:
142     black = dev->cached_colors.black;
143     if (black == 0)
144 	*psource = &gx_rop_no_source_0;
145     else if (black == 1)
146 	*psource = &gx_rop_no_source_1;
147     else if (black == gx_no_color_index) {	/* cache not loaded */
148 	discard(gx_device_black(dev));
149 	goto top;
150     } else {
151 	*pno_source = gx_rop_no_source_0;
152 	gx_rop_source_set_color(pno_source, black);
153 	*psource = pno_source;
154     }
155 }
156 
157 /*
158  * Test device colors for equality.  Testing for equality is done
159  * for determining when cache values, etc. can be used.  Thus these
160  * routines should err toward false responses if there is any question
161  * about the equality of the two device colors.
162  */
163 bool
gx_device_color_equal(const gx_device_color * pdevc1,const gx_device_color * pdevc2)164 gx_device_color_equal(const gx_device_color *pdevc1,
165 		      const gx_device_color *pdevc2)
166 {
167     return pdevc1->type->equal(pdevc1, pdevc2);
168 }
169 
170 /*
171  * Return a device color type index. This index is used by the command
172  * list processor to identify a device color type, as the type pointer
173  * itself is meaningful only within a single address space.
174  *
175  * Currently, we ignore the pattern device colors as they cannot be
176  * passed through the command list.
177  *
178  * Returns gs_error_unknownerror for an unrecognized type.
179  */
180 private  const gx_device_color_type_t * dc_color_type_table[] = {
181     gx_dc_type_none,            /* unset device color */
182     gx_dc_type_null,            /* blank (transparent) device color */
183     gx_dc_type_pure,            /* pure device color */
184     /* gx_dc_type_pattern, */   /* patterns - not used in command list */
185     gx_dc_type_ht_binary,       /* binary halftone device colors */
186     gx_dc_type_ht_colored,      /* general halftone device colors */
187     gx_dc_type_wts              /* well-tempered screen device colors */
188 };
189 
190 int
gx_get_dc_type_index(const gx_device_color * pdevc)191 gx_get_dc_type_index(const gx_device_color * pdevc)
192 {
193     const gx_device_color_type_t *  type = pdevc->type;
194     int                             num_types, i;
195 
196     num_types = sizeof(dc_color_type_table) / sizeof(dc_color_type_table[0]);
197     for (i = 0; i < num_types && type != dc_color_type_table[i]; i++)
198         ;
199 
200     return i < num_types ? i : gs_error_unknownerror;
201 }
202 
203 /* map a device color type index into the associated method vector */
204 const gx_device_color_type_t *
gx_get_dc_type_from_index(int i)205 gx_get_dc_type_from_index(int i)
206 {
207     if ( i >= 0                                                          &&
208          i < sizeof(dc_color_type_table) / sizeof(dc_color_type_table[0])  )
209         return dc_color_type_table[i];
210     else
211         return 0;
212 }
213 
214 /* ------ Canonical get_phase methods ------ */
215 bool
gx_dc_no_get_phase(const gx_device_color * pdevc,gs_int_point * pphase)216 gx_dc_no_get_phase(const gx_device_color * pdevc, gs_int_point * pphase)
217 {
218     return false;
219 }
220 
221 bool
gx_dc_ht_get_phase(const gx_device_color * pdevc,gs_int_point * pphase)222 gx_dc_ht_get_phase(const gx_device_color * pdevc, gs_int_point * pphase)
223 {
224     *pphase = pdevc->phase;
225     return true;
226 }
227 
228 /* ------ Undefined color ------ */
229 private void
gx_dc_no_save_dc(const gx_device_color * pdevc,gx_device_color_saved * psdc)230 gx_dc_no_save_dc(const gx_device_color * pdevc, gx_device_color_saved * psdc)
231 {
232     psdc->type = pdevc->type;
233 }
234 
235 private const gx_device_halftone *
gx_dc_no_get_dev_halftone(const gx_device_color * pdevc)236 gx_dc_no_get_dev_halftone(const gx_device_color * pdevc)
237 {
238     return 0;
239 }
240 
241 private int
gx_dc_no_load(gx_device_color * pdevc,const gs_imager_state * ignore_pis,gx_device * ignore_dev,gs_color_select_t ignore_select)242 gx_dc_no_load(gx_device_color *pdevc, const gs_imager_state *ignore_pis,
243 	      gx_device *ignore_dev, gs_color_select_t ignore_select)
244 {
245     return 0;
246 }
247 
248 private int
gx_dc_no_fill_rectangle(const gx_device_color * pdevc,int x,int y,int w,int h,gx_device * dev,gs_logical_operation_t lop,const gx_rop_source_t * source)249 gx_dc_no_fill_rectangle(const gx_device_color *pdevc, int x, int y,
250 			int w, int h, gx_device *dev,
251 			gs_logical_operation_t lop,
252 			const gx_rop_source_t *source)
253 {
254     gx_device_color filler;
255 
256     if (w <= 0 || h <= 0)
257 	return 0;
258     if (lop_uses_T(lop))
259 	return_error(gs_error_Fatal);
260     set_nonclient_dev_color(&filler, 0);   /* any valid value for dev will do */
261     return gx_dc_pure_fill_rectangle(&filler, x, y, w, h, dev, lop, source);
262 }
263 
264 private int
gx_dc_no_fill_masked(const gx_device_color * pdevc,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_device * dev,gs_logical_operation_t lop,bool invert)265 gx_dc_no_fill_masked(const gx_device_color *pdevc, const byte *data,
266 		     int data_x, int raster, gx_bitmap_id id,
267 		     int x, int y, int w, int h, gx_device *dev,
268 		     gs_logical_operation_t lop, bool invert)
269 {
270     if (w <= 0 || h <= 0)
271 	return 0;
272     return_error(gs_error_Fatal);
273 }
274 
275 private bool
gx_dc_no_equal(const gx_device_color * pdevc1,const gx_device_color * pdevc2)276 gx_dc_no_equal(const gx_device_color *pdevc1, const gx_device_color *pdevc2)
277 {
278     return false;
279 }
280 
281 private int
gx_dc_no_write(const gx_device_color * pdevc,const gx_device_color_saved * psdc,const gx_device * dev,byte * data,uint * psize)282 gx_dc_no_write(
283     const gx_device_color *         pdevc,      /* ignored */
284     const gx_device_color_saved *   psdc,       /* ignored */
285     const gx_device *               dev,        /* ignored */
286     byte *                          data,       /* ignored */
287     uint *                          psize )
288 {
289     *psize = 0;
290     return psdc != 0 && psdc->type == pdevc->type ? 1 : 0;
291 }
292 
293 private int
gx_dc_no_read(gx_device_color * pdevc,const gs_imager_state * pis,const gx_device_color * prior_devc,const gx_device * dev,const byte * pdata,uint size,gs_memory_t * mem)294 gx_dc_no_read(
295     gx_device_color *       pdevc,
296     const gs_imager_state * pis,                /* ignored */
297     const gx_device_color * prior_devc,         /* ignored */
298     const gx_device *       dev,                /* ignored */
299     const byte *            pdata,              /* ignored */
300     uint                    size,               /* ignored */
301     gs_memory_t *           mem )               /* ignored */
302 {
303     pdevc->type = gx_dc_type_none;
304     return 0;
305 }
306 
307 private int
gx_dc_no_get_nonzero_comps(const gx_device_color * pdevc_ignored,const gx_device * dev_ignored,gx_color_index * pcomp_bits_ignored)308 gx_dc_no_get_nonzero_comps(
309     const gx_device_color * pdevc_ignored,
310     const gx_device *       dev_ignored,
311     gx_color_index *        pcomp_bits_ignored )
312 {
313     return 0;
314 }
315 
316 /* ------ Null color ------ */
317 
318 private int
gx_dc_null_load(gx_device_color * pdevc,const gs_imager_state * ignore_pis,gx_device * ignore_dev,gs_color_select_t ignore_select)319 gx_dc_null_load(gx_device_color *pdevc, const gs_imager_state *ignore_pis,
320 		gx_device *ignore_dev, gs_color_select_t ignore_select)
321 {
322     return 0;
323 }
324 
325 private int
gx_dc_null_fill_rectangle(const gx_device_color * pdevc,int x,int y,int w,int h,gx_device * dev,gs_logical_operation_t lop,const gx_rop_source_t * source)326 gx_dc_null_fill_rectangle(const gx_device_color * pdevc, int x, int y,
327 			  int w, int h, gx_device * dev,
328 			  gs_logical_operation_t lop,
329 			  const gx_rop_source_t * source)
330 {
331     return 0;
332 }
333 
334 private int
gx_dc_null_fill_masked(const gx_device_color * pdevc,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_device * dev,gs_logical_operation_t lop,bool invert)335 gx_dc_null_fill_masked(const gx_device_color * pdevc, const byte * data,
336 		       int data_x, int raster, gx_bitmap_id id,
337 		       int x, int y, int w, int h, gx_device * dev,
338 		       gs_logical_operation_t lop, bool invert)
339 {
340     return 0;
341 }
342 
343 private bool
gx_dc_null_equal(const gx_device_color * pdevc1,const gx_device_color * pdevc2)344 gx_dc_null_equal(const gx_device_color * pdevc1, const gx_device_color * pdevc2)
345 {
346     return pdevc2->type == pdevc1->type;
347 }
348 
349 private int
gx_dc_null_read(gx_device_color * pdevc,const gs_imager_state * pis,const gx_device_color * prior_devc,const gx_device * dev,const byte * pdata,uint size,gs_memory_t * mem)350 gx_dc_null_read(
351     gx_device_color *       pdevc,
352     const gs_imager_state * pis,                /* ignored */
353     const gx_device_color * prior_devc,         /* ignored */
354     const gx_device *       dev,                /* ignored */
355     const byte *            pdata,              /* ignored */
356     uint                    size,               /* ignored */
357     gs_memory_t *           mem )               /* ignored */
358 {
359     pdevc->type = gx_dc_type_null;
360     return 0;
361 }
362 
363 /* ------ Pure color ------ */
364 
365 private void
gx_dc_pure_save_dc(const gx_device_color * pdevc,gx_device_color_saved * psdc)366 gx_dc_pure_save_dc(const gx_device_color * pdevc, gx_device_color_saved * psdc)
367 {
368     psdc->type = pdevc->type;
369     psdc->colors.pure = pdevc->colors.pure;
370 }
371 
372 private int
gx_dc_pure_load(gx_device_color * pdevc,const gs_imager_state * ignore_pis,gx_device * ignore_dev,gs_color_select_t ignore_select)373 gx_dc_pure_load(gx_device_color * pdevc, const gs_imager_state * ignore_pis,
374 		gx_device * ignore_dev, gs_color_select_t ignore_select)
375 {
376     return 0;
377 }
378 
379 /* Fill a rectangle with a pure color. */
380 /* Note that we treat this as "texture" for RasterOp. */
381 private int
gx_dc_pure_fill_rectangle(const gx_device_color * pdevc,int x,int y,int w,int h,gx_device * dev,gs_logical_operation_t lop,const gx_rop_source_t * source)382 gx_dc_pure_fill_rectangle(const gx_device_color * pdevc, int x, int y,
383 		  int w, int h, gx_device * dev, gs_logical_operation_t lop,
384 			  const gx_rop_source_t * source)
385 {
386     if (source == NULL && lop_no_S_is_T(lop))
387 	return (*dev_proc(dev, fill_rectangle)) (dev, x, y, w, h,
388 						 pdevc->colors.pure);
389     {
390 	gx_color_index colors[2];
391 	gx_rop_source_t no_source;
392 
393 	colors[0] = colors[1] = pdevc->colors.pure;
394 	if (source == NULL)
395 	    set_rop_no_source(source, no_source, dev);
396 	return (*dev_proc(dev, strip_copy_rop))
397 	    (dev, source->sdata, source->sourcex, source->sraster,
398 	     source->id, (source->use_scolors ? source->scolors : NULL),
399 	     NULL /*arbitrary */ , colors, x, y, w, h, 0, 0, lop);
400     }
401 }
402 
403 /* Fill a mask with a pure color. */
404 /* Note that there is no source in this case: the mask is the source. */
405 private int
gx_dc_pure_fill_masked(const gx_device_color * pdevc,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_device * dev,gs_logical_operation_t lop,bool invert)406 gx_dc_pure_fill_masked(const gx_device_color * pdevc, const byte * data,
407 	int data_x, int raster, gx_bitmap_id id, int x, int y, int w, int h,
408 		   gx_device * dev, gs_logical_operation_t lop, bool invert)
409 {
410     if (lop_no_S_is_T(lop)) {
411 	gx_color_index color0, color1;
412 
413 	if (invert)
414 	    color0 = pdevc->colors.pure, color1 = gx_no_color_index;
415 	else
416 	    color1 = pdevc->colors.pure, color0 = gx_no_color_index;
417 	return (*dev_proc(dev, copy_mono))
418 	    (dev, data, data_x, raster, id, x, y, w, h, color0, color1);
419     } {
420 	gx_color_index scolors[2];
421 	gx_color_index tcolors[2];
422 
423 	scolors[0] = gx_device_black(dev);
424 	scolors[1] = gx_device_white(dev);
425 	tcolors[0] = tcolors[1] = pdevc->colors.pure;
426 	return (*dev_proc(dev, strip_copy_rop))
427 	    (dev, data, data_x, raster, id, scolors,
428 	     NULL, tcolors, x, y, w, h, 0, 0,
429 	     (invert ? rop3_invert_S(lop) : lop) | lop_S_transparent);
430     }
431 }
432 
433 private bool
gx_dc_pure_equal(const gx_device_color * pdevc1,const gx_device_color * pdevc2)434 gx_dc_pure_equal(const gx_device_color * pdevc1, const gx_device_color * pdevc2)
435 {
436     return pdevc2->type == pdevc1->type &&
437 	gx_dc_pure_color(pdevc1) == gx_dc_pure_color(pdevc2);
438 }
439 
440 /*
441  * Serialize a pure color.
442  *
443  * Operands:
444  *
445  *  pdevc       pointer to device color to be serialized
446  *
447  *  psdc        pointer ot saved version of last serialized color (for
448  *              this band); this is ignored
449  *
450  *  dev         pointer to the current device, used to retrieve process
451  *              color model information
452  *
453  *  pdata       pointer to buffer in which to write the data
454  *
455  *  psize       pointer to a location that, on entry, contains the size of
456  *              the buffer pointed to by pdata; on return, the size of
457  *              the data required or actually used will be written here.
458  *
459  * Returns:
460  *
461  *  1, with *psize set to 0, if *pdevc and *psdc represent the same color
462  *
463  *  0, with *psize set to the amount of data written, if everything OK
464  *
465  *  gs_error_rangecheck, with *psize set to the size of buffer required,
466  *  if *psize was not large enough
467  *
468  *  < 0, != gs_error_rangecheck, in the event of some other error; in this
469  *  case *psize is not changed.
470  */
471 private int
gx_dc_pure_write(const gx_device_color * pdevc,const gx_device_color_saved * psdc,const gx_device * dev,byte * pdata,uint * psize)472 gx_dc_pure_write(
473     const gx_device_color *         pdevc,
474     const gx_device_color_saved *   psdc,       /* ignored */
475     const gx_device *               dev,
476     byte *                          pdata,
477     uint *                          psize )
478 {
479     if ( psdc != 0                              &&
480          psdc->type == pdevc->type              &&
481          psdc->colors.pure == pdevc->colors.pure  ) {
482         *psize = 0;
483         return 1;
484     } else
485         return gx_dc_write_color(pdevc->colors.pure, dev, pdata, psize);
486 }
487 
488 /*
489  * Reconstruct a pure device color from its serial representation.
490  *
491  * Operands:
492  *
493  *  pdevc       pointer to the location in which to write the
494  *              reconstructed device color
495  *
496  *  pis         pointer to the current imager state (ignored here)
497  *
498  *  prior_devc  pointer to the current device color (this is provided
499  *              separately because the device color is not part of the
500  *              imager state; it is ignored here)
501  *
502  *  dev         pointer to the current device, used to retrieve process
503  *              color model information
504  *
505  *  pdata       pointer to the buffer to be read
506  *
507  *  size        size of the buffer to be read; this should be large
508  *              enough to hold the entire color description
509  *
510  *  mem         pointer to the memory to be used for allocations
511  *              (ignored here)
512  *
513  * Returns:
514  *
515  *  # of bytes read if everthing OK, < 0 in the event of an error
516  */
517 private int
gx_dc_pure_read(gx_device_color * pdevc,const gs_imager_state * pis,const gx_device_color * prior_devc,const gx_device * dev,const byte * pdata,uint size,gs_memory_t * mem)518 gx_dc_pure_read(
519     gx_device_color *       pdevc,
520     const gs_imager_state * pis,                /* ignored */
521     const gx_device_color * prior_devc,         /* ignored */
522     const gx_device *       dev,
523     const byte *            pdata,
524     uint                    size,
525     gs_memory_t *           mem )               /* ignored */
526 {
527     pdevc->type = gx_dc_type_pure;
528     return gx_dc_read_color(&pdevc->colors.pure, dev, pdata, size);
529 }
530 
531 int
gx_dc_pure_get_nonzero_comps(const gx_device_color * pdevc,const gx_device * dev,gx_color_index * pcomp_bits)532 gx_dc_pure_get_nonzero_comps(
533     const gx_device_color * pdevc,
534     const gx_device *       dev,
535     gx_color_index *        pcomp_bits )
536 {
537     int                     code;
538     gx_color_value          cvals[GX_DEVICE_COLOR_MAX_COMPONENTS];
539 
540     code = dev_proc(dev, decode_color)( (gx_device *)dev,
541                                          pdevc->colors.pure,
542                                          cvals );
543     if (code >= 0) {
544         int             i, ncomps = dev->color_info.num_components;
545         gx_color_index  mask = 0x1, comp_bits = 0;
546 
547         for (i = 0; i < ncomps; i++, mask <<= 1) {
548             if (cvals[i] != 0)
549                 comp_bits |= mask;
550         }
551         *pcomp_bits = comp_bits;
552         code = 0;
553     }
554 
555     return code;
556 }
557 
558 /* ------ Halftone color initialization ------ */
559 
560 void
gx_complete_halftone(gx_device_color * pdevc,int num_comps,gx_device_halftone * pdht)561 gx_complete_halftone(gx_device_color *pdevc, int num_comps, gx_device_halftone *pdht)
562 {
563     int i, mask = 0;
564 
565     pdevc->type = gx_dc_type_ht_colored;
566     pdevc->colors.colored.c_ht = pdht;
567     pdevc->colors.colored.num_components = num_comps;
568     pdevc->colors.colored.alpha = max_ushort;
569     for (i = 0; i < num_comps; i++)
570         mask |= ((pdevc->colors.colored.c_level[i] != 0 ? 1 : 0) << i);
571     pdevc->colors.colored.plane_mask = mask;
572 }
573 
574 /* ------ Default implementations ------ */
575 
576 /* Fill a mask with a color by parsing the mask into rectangles. */
577 int
gx_dc_default_fill_masked(const gx_device_color * pdevc,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_device * dev,gs_logical_operation_t lop,bool invert)578 gx_dc_default_fill_masked(const gx_device_color * pdevc, const byte * data,
579 	int data_x, int raster, gx_bitmap_id id, int x, int y, int w, int h,
580 		   gx_device * dev, gs_logical_operation_t lop, bool invert)
581 {
582     int lbit = data_x & 7;
583     const byte *row = data + (data_x >> 3);
584     uint one = (invert ? 0 : 0xff);
585     uint zero = one ^ 0xff;
586     int iy;
587 
588     for (iy = 0; iy < h; ++iy, row += raster) {
589 	const byte *p = row;
590 	int bit = lbit;
591 	int left = w;
592 	int l0;
593 
594 	while (left) {
595 	    int run, code;
596 
597 	    /* Skip a run of zeros. */
598 	    run = byte_bit_run_length[bit][*p ^ one];
599 	    if (run) {
600 		if (run < 8) {
601 		    if (run >= left)
602 			break;	/* end of row while skipping */
603 		    bit += run, left -= run;
604 		} else if ((run -= 8) >= left)
605 		    break;	/* end of row while skipping */
606 		else {
607 		    left -= run;
608 		    ++p;
609 		    while (left > 8 && *p == zero)
610 			left -= 8, ++p;
611 		    run = byte_bit_run_length_0[*p ^ one];
612 		    if (run >= left)	/* run < 8 unless very last byte */
613 			break;	/* end of row while skipping */
614 		    else
615 			bit = run & 7, left -= run;
616 		}
617 	    }
618 	    l0 = left;
619 	    /* Scan a run of ones, and then paint it. */
620 	    run = byte_bit_run_length[bit][*p ^ zero];
621 	    if (run < 8) {
622 		if (run >= left)
623 		    left = 0;
624 		else
625 		    bit += run, left -= run;
626 	    } else if ((run -= 8) >= left)
627 		left = 0;
628 	    else {
629 		left -= run;
630 		++p;
631 		while (left > 8 && *p == one)
632 		    left -= 8, ++p;
633 		run = byte_bit_run_length_0[*p ^ zero];
634 		if (run >= left)	/* run < 8 unless very last byte */
635 		    left = 0;
636 		else
637 		    bit = run & 7, left -= run;
638 	    }
639 	    code = gx_device_color_fill_rectangle(pdevc,
640 			  x + w - l0, y + iy, l0 - left, 1, dev, lop, NULL);
641 	    if (code < 0)
642 		return code;
643 	}
644     }
645     return 0;
646 }
647 
648 /* ------ Serialization identification support ------ */
649 
650 /*
651  * Utility to write a color index.  Currently, a very simple mechanism
652  * is used, much simpler than that used by other command-list writers. This
653  * should be sufficient for most situations.
654  *
655  * Operands:
656  *
657  *  color       color to be serialized.
658  *
659  *  dev         pointer to the current device, used to retrieve process
660  *              color model information
661  *
662  *  pdata       pointer to buffer in which to write the data
663  *
664  *  psize       pointer to a location that, on entry, contains the size of
665  *              the buffer pointed to by pdata; on return, the size of
666  *              the data required or actually used will be written here.
667  *
668  * Returns:
669  *
670  *  0, with *psize set to the amount of data written, if everything OK
671  *
672  *  gs_error_rangecheck, with *psize set to the size of buffer required,
673  *  if *psize was not large enough
674  *
675  *  < 0, != gs_error_rangecheck, in the event of some other error; in this
676  *  case *psize is not changed.
677  */
678 int
gx_dc_write_color(gx_color_index color,const gx_device * dev,byte * pdata,uint * psize)679 gx_dc_write_color(
680     gx_color_index      color,
681     const gx_device *   dev,
682     byte *              pdata,
683     uint *              psize )
684 {
685     int                 depth = dev->color_info.depth;
686     int                 num_bytes = (depth + 8) >> 3;   /* NB: +8, not +7 */
687 
688     /* gx_no_color_index is encoded as a single byte */
689     if (color == gx_no_color_index)
690         num_bytes = 1;
691 
692     /* check for adequate space */
693     if (*psize < num_bytes) {
694         *psize = num_bytes;
695         return gs_error_rangecheck;
696     }
697     *psize = num_bytes;
698 
699     /* gx_no_color_index is a single byte of 0xff */
700     if (color == gx_no_color_index) {
701         *psize = 1;
702         *pdata = 0xff;
703     } else {
704         if (depth < 8 * arch_sizeof_color_index)
705             color &= ((gx_color_index)1 << depth) - 1;
706         while (--num_bytes >= 0) {
707             pdata[num_bytes] = color & 0xff;
708             color >>= 8;
709         }
710     }
711     return 0;
712 }
713 
714 /*
715  * Utility to reconstruct device color from its serial representation.
716  *
717  * Operands:
718  *
719  *  pcolor      pointer to the location in which to write the
720  *              reconstucted color
721  *
722  *  dev         pointer to the current device, used to retrieve process
723  *              color model information
724  *
725  *  pdata       pointer to the buffer to be read
726  *
727  *  size        size of the buffer to be read; this is expected to be
728  *              large enough for the full color
729  *
730  * Returns: # of bytes read, or < 0 in the event of an error
731  */
732 int
gx_dc_read_color(gx_color_index * pcolor,const gx_device * dev,const byte * pdata,int size)733 gx_dc_read_color(
734     gx_color_index *    pcolor,
735     const gx_device *   dev,
736     const byte *        pdata,
737     int                 size )
738 {
739     gx_color_index      color = 0;
740     int                 depth = dev->color_info.depth;
741     int                 i, num_bytes = (depth + 8) >> 3;   /* NB: +8, not +7 */
742 
743     /* check that enough data has been provided */
744     if (size < 1 || (pdata[0] != 0xff && size < num_bytes))
745         return gs_error_rangecheck;
746 
747     /* check of gx_no_color_index */
748     if (pdata[0] == 0xff) {
749         *pcolor = gx_no_color_index;
750         return 1;
751     }
752 
753     /* num_bytes > arch_sizeof_color_index, discard first byte */
754     for (i = (num_bytes >= arch_sizeof_color_index ? 1 : 0); i < num_bytes; i++)
755         color = (color << 8) | pdata[i];
756     *pcolor = color;
757     return num_bytes;
758 }
759