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