1 /* Copyright (C) 2001-2006 Artifex Software, Inc.
2    All Rights Reserved.
3 
4    This software is provided AS-IS with no warranty, either express or
5    implied.
6 
7    This software is distributed under license and may not be copied, modified
8    or distributed except as expressly authorized under the terms of that
9    license.  Refer to licensing information at http://www.artifex.com/
10    or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
11    San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12 */
13 /*$Id: gdevdevn.c 10394 2009-11-27 19:07:02Z ray $ */
14 /* Example DeviceN process color model devices. */
15 
16 #include "math_.h"
17 #include "string_.h"
18 #include "gdevprn.h"
19 #include "gsparam.h"
20 #include "gscrd.h"
21 #include "gscrdp.h"
22 #include "gxlum.h"
23 #include "gdevdcrd.h"
24 #include "gstypes.h"
25 #include "gxdcconv.h"
26 #include "gdevdevn.h"
27 #include "gsequivc.h"
28 #include "gxblend.h"
29 #include "gdevp14.h"
30 
31 /*
32  * Utility routines for common DeviceN related parameters:
33  *   SeparationColorNames, SeparationOrder, and MaxSeparations
34  */
35 
36 /* Convert a gray color space to DeviceN colorants. */
37 void
gray_cs_to_devn_cm(gx_device * dev,int * map,frac gray,frac out[])38 gray_cs_to_devn_cm(gx_device * dev, int * map, frac gray, frac out[])
39 {
40     int i = dev->color_info.num_components - 1;
41 
42     for(; i >= 0; i--)			/* Clear colors */
43         out[i] = frac_0;
44     if ((i = map[3]) != GX_DEVICE_COLOR_MAX_COMPONENTS)
45         out[i] = frac_1 - gray;
46 }
47 
48 /* Convert an RGB color space to DeviceN colorants. */
49 void
rgb_cs_to_devn_cm(gx_device * dev,int * map,const gs_imager_state * pis,frac r,frac g,frac b,frac out[])50 rgb_cs_to_devn_cm(gx_device * dev, int * map,
51 		const gs_imager_state *pis, frac r, frac g, frac b, frac out[])
52 {
53     int i = dev->color_info.num_components - 1;
54     frac cmyk[4];
55 
56     for(; i >= 0; i--)			/* Clear colors */
57         out[i] = frac_0;
58     color_rgb_to_cmyk(r, g, b, pis, cmyk);
59     if ((i = map[0]) != GX_DEVICE_COLOR_MAX_COMPONENTS)
60         out[i] = cmyk[0];
61     if ((i = map[1]) != GX_DEVICE_COLOR_MAX_COMPONENTS)
62         out[i] = cmyk[1];
63     if ((i = map[2]) != GX_DEVICE_COLOR_MAX_COMPONENTS)
64         out[i] = cmyk[2];
65     if ((i = map[3]) != GX_DEVICE_COLOR_MAX_COMPONENTS)
66         out[i] = cmyk[3];
67 }
68 
69 /* Convert a CMYK color space to DeviceN colorants. */
70 void
cmyk_cs_to_devn_cm(gx_device * dev,int * map,frac c,frac m,frac y,frac k,frac out[])71 cmyk_cs_to_devn_cm(gx_device * dev, int * map,
72 		frac c, frac m, frac y, frac k, frac out[])
73 {
74     int i = dev->color_info.num_components - 1;
75 
76     for(; i >= 0; i--)			/* Clear colors */
77         out[i] = frac_0;
78     if ((i = map[0]) != GX_DEVICE_COLOR_MAX_COMPONENTS)
79         out[i] = c;
80     if ((i = map[1]) != GX_DEVICE_COLOR_MAX_COMPONENTS)
81         out[i] = m;
82     if ((i = map[2]) != GX_DEVICE_COLOR_MAX_COMPONENTS)
83         out[i] = y;
84     if ((i = map[3]) != GX_DEVICE_COLOR_MAX_COMPONENTS)
85         out[i] = k;
86 }
87 
88 /*
89  * This utility routine calculates the number of bits required to store
90  * color information.  In general the values are rounded up to an even
91  * byte boundary except those cases in which mulitple pixels can evenly
92  * into a single byte.
93  *
94  * The parameter are:
95  *   ncomp - The number of components (colorants) for the device.  Valid
96  * 	values are 1 to GX_DEVICE_COLOR_MAX_COMPONENTS
97  *   bpc - The number of bits per component.  Valid values are 1, 2, 4, 5,
98  *	and 8.
99  * Input values are not tested for validity.
100  */
101 int
bpc_to_depth(int ncomp,int bpc)102 bpc_to_depth(int ncomp, int bpc)
103 {
104     static const byte depths[4][8] = {
105 	{1, 2, 0, 4, 8, 0, 0, 8},
106 	{2, 4, 0, 8, 16, 0, 0, 16},
107 	{4, 8, 0, 16, 16, 0, 0, 24},
108 	{4, 8, 0, 16, 32, 0, 0, 32}
109     };
110 
111     if (ncomp <=4 && bpc <= 8)
112         return depths[ncomp -1][bpc-1];
113     else
114     	return (ncomp * bpc + 7) & 0xf8;
115 }
116 
117 #define compare_color_names(name, name_size, str, str_size) \
118     (name_size == str_size && \
119 	(strncmp((const char *)name, (const char *)str, name_size) == 0))
120 
121 /*
122  * This routine will check if a name matches any item in a list of process
123  * color model colorant names.
124  */
125 static bool
check_process_color_names(fixed_colorant_names_list plist,const gs_param_string * pstring)126 check_process_color_names(fixed_colorant_names_list plist,
127 			  const gs_param_string * pstring)
128 {
129     if (plist) {
130         uint size = pstring->size;
131 
132 	while( *plist) {
133 	    if (compare_color_names(*plist, strlen(*plist), pstring->data, size)) {
134 		return true;
135 	    }
136 	    plist++;
137 	}
138     }
139     return false;
140 }
141 
142 /*
143  * This routine will check to see if the color component name  match those
144  * of either the process color model colorants or the names on the
145  * SeparationColorNames list.
146  *
147  * Parameters:
148  *   dev - pointer to device data structure.
149  *   pname - pointer to name (zero termination not required)
150  *   nlength - length of the name
151  *
152  * This routine returns a positive value (0 to n) which is the device colorant
153  * number if the name is found.  It returns a negative value if not found.
154  */
155 int
check_pcm_and_separation_names(const gx_device * dev,const gs_devn_params * pparams,const char * pname,int name_size,int component_type)156 check_pcm_and_separation_names(const gx_device * dev,
157 		const gs_devn_params * pparams, const char * pname,
158 		int name_size, int component_type)
159 {
160     fixed_colorant_name * pcolor = pparams->std_colorant_names;
161     int color_component_number = 0;
162     int i;
163 
164     /* Check if the component is in the process color model list. */
165     if (pcolor) {
166 	while( *pcolor) {
167 	    if (compare_color_names(pname, name_size, *pcolor, strlen(*pcolor)))
168 		return color_component_number;
169 	    pcolor++;
170 	    color_component_number++;
171 	}
172     }
173 
174     /* Check if the component is in the separation names list. */
175     {
176 	const gs_separations * separations = &pparams->separations;
177 	int num_spot = separations->num_separations;
178 
179 	for (i=0; i<num_spot; i++) {
180 	    if (compare_color_names((const char *)separations->names[i].data,
181 		  separations->names[i].size, pname, name_size)) {
182 		return color_component_number;
183 	    }
184 	    color_component_number++;
185 	}
186     }
187 
188     return -1;
189 }
190 
191 /*
192  * This routine will check to see if the color component name  match those
193  * that are available amoung the current device's color components.
194  *
195  * Parameters:
196  *   dev - pointer to device data structure.
197  *   pname - pointer to name (zero termination not required)
198  *   nlength - length of the name
199  *   component_type - separation name or not
200  *   pdevn_params - pointer to device's DeviceN paramters
201  *   pequiv_colors - pointer to equivalent color structure (may be NULL)
202  *
203  * This routine returns a positive value (0 to n) which is the device colorant
204  * number if the name is found.  It returns GX_DEVICE_COLOR_MAX_COMPONENTS if
205  * the color component is found but is not being used due to the
206  * SeparationOrder device parameter.  It returns a negative value if not found.
207  *
208  * This routine will also add separations to the device if space is
209  * available.
210  */
211 int
devn_get_color_comp_index(gx_device * dev,gs_devn_params * pdevn_params,equivalent_cmyk_color_params * pequiv_colors,const char * pname,int name_size,int component_type,int auto_spot_colors)212 devn_get_color_comp_index(gx_device * dev, gs_devn_params * pdevn_params,
213 		    equivalent_cmyk_color_params * pequiv_colors,
214 		    const char * pname, int name_size, int component_type,
215 		    int auto_spot_colors)
216 {
217     int num_order = pdevn_params->num_separation_order_names;
218     int color_component_number = 0;
219     int max_spot_colors = GX_DEVICE_MAX_SEPARATIONS - MAX_DEVICE_PROCESS_COLORS;
220 
221     /*
222      * Check if the component is in either the process color model list
223      * or in the SeparationNames list.
224      */
225     color_component_number = check_pcm_and_separation_names(dev, pdevn_params,
226 					pname, name_size, component_type);
227 
228     /* If we have a valid component */
229     if (color_component_number >= 0) {
230         /* Check if the component is in the separation order map. */
231         if (num_order)
232 	    color_component_number =
233 		pdevn_params->separation_order_map[color_component_number];
234 	else
235 	    /*
236 	     * We can have more spot colors than we can image.  We simply
237 	     * ignore the component (i.e. treat it the same as we would
238 	     * treat a component that is not in the separation order map).
239 	     * Note:  Most device do not allow more spot colors than we can
240 	     * image.  (See the options for auto_spot_color in gdevdevn.h.)
241 	     */
242 	    if (color_component_number >= dev->color_info.num_components)
243 	        color_component_number = GX_DEVICE_COLOR_MAX_COMPONENTS;
244 
245         return color_component_number;
246     }
247     /*
248      * The given name does not match any of our current components or
249      * separations.  Check if we should add the spot color to our list.
250      * If the SeparationOrder parameter has been specified then we should
251      * already have our complete list of desired spot colorants.
252      */
253     if (component_type != SEPARATION_NAME ||
254 	    auto_spot_colors == NO_AUTO_SPOT_COLORS ||
255 	    pdevn_params->num_separation_order_names != 0)
256 	return -1;	/* Do not add --> indicate colorant unknown. */
257     /*
258      * Check if we have room for another spot colorant.
259      */
260     if (auto_spot_colors == ENABLE_AUTO_SPOT_COLORS)
261 	max_spot_colors = dev->color_info.num_components -
262 	    pdevn_params->num_std_colorant_names;
263     if (pdevn_params->separations.num_separations < max_spot_colors) {
264 	byte * sep_name;
265 	gs_separations * separations = &pdevn_params->separations;
266 	int sep_num = separations->num_separations++;
267 
268 	/* We have a new spot colorant - put in stable memory to avoid "restore" */
269 	sep_name = gs_alloc_bytes(dev->memory->stable_memory,
270 			name_size, "devn_get_color_comp_index");
271 	memcpy(sep_name, pname, name_size);
272 	separations->names[sep_num].size = name_size;
273 	separations->names[sep_num].data = sep_name;
274 	color_component_number = sep_num + pdevn_params->num_std_colorant_names;
275 	if (color_component_number >= dev->color_info.num_components)
276 	    color_component_number = GX_DEVICE_COLOR_MAX_COMPONENTS;
277 	else
278 	    pdevn_params->separation_order_map[color_component_number] =
279 					       color_component_number;
280 
281 	if (pequiv_colors != NULL) {
282     	    /* Indicate that we need to find equivalent CMYK color. */
283 	    pequiv_colors->color[sep_num].color_info_valid = false;
284 	    pequiv_colors->all_color_info_valid = false;
285 	}
286     }
287 
288     return color_component_number;
289 }
290 
291 #define set_param_array(a, d, s)\
292   (a.data = d, a.size = s, a.persistent = false);
293 
294 /* Get parameters.  We provide a default CRD. */
295 int
devn_get_params(gx_device * pdev,gs_param_list * plist,gs_devn_params * pdevn_params,equivalent_cmyk_color_params * pequiv_colors)296 devn_get_params(gx_device * pdev, gs_param_list * plist,
297     gs_devn_params * pdevn_params, equivalent_cmyk_color_params * pequiv_colors)
298 {
299     int code;
300     bool seprs = false;
301     gs_param_string_array scna;
302     gs_param_string_array sona;
303 
304     set_param_array(scna, NULL, 0);
305     set_param_array(sona, NULL, 0);
306 
307     if ( (code = sample_device_crd_get_params(pdev, plist, "CRDDefault")) < 0 ||
308 	 (code =
309 	    param_write_name_array(plist, "SeparationColorNames", &scna)) < 0 ||
310 	 (code = param_write_name_array(plist, "SeparationOrder", &sona)) < 0 ||
311 	 (code = param_write_bool(plist, "Separations", &seprs)) < 0)
312 	return code;
313 
314     return 0;
315 }
316 #undef set_param_array
317 
318 #define BEGIN_ARRAY_PARAM(pread, pname, pa, psize, e)\
319     BEGIN\
320     switch (code = pread(plist, (param_name = pname), &(pa))) {\
321       case 0:\
322 	if ((pa).size != psize) {\
323 	  ecode = gs_note_error(gs_error_rangecheck);\
324 	  (pa).data = 0;	/* mark as not filled */\
325 	} else
326 #define END_ARRAY_PARAM(pa, e)\
327 	goto e;\
328       default:\
329 	ecode = code;\
330 e:	param_signal_error(plist, param_name, ecode);\
331       case 1:\
332 	(pa).data = 0;		/* mark as not filled */\
333     }\
334     END
335 
336 /*
337  * Utility routine for handling DeviceN related parameters.  This routine
338  * may modify the color_info, devn_params, and the equiv_cmyk_colors fields.
339  *
340  * Note:  This routine does not restore values in case of a problem.  This
341  * is left to the caller.
342  */
343 int
devn_put_params(gx_device * pdev,gs_param_list * plist,gs_devn_params * pdevn_params,equivalent_cmyk_color_params * pequiv_colors)344 devn_put_params(gx_device * pdev, gs_param_list * plist,
345     gs_devn_params * pdevn_params, equivalent_cmyk_color_params * pequiv_colors)
346 {
347     int code = 0, ecode;
348     gs_param_name param_name;
349     int npcmcolors = pdevn_params->num_std_colorant_names;
350     int num_spot = pdevn_params->separations.num_separations;
351     bool num_spot_changed = false;
352     int num_order = pdevn_params->num_separation_order_names;
353     int max_sep = pdevn_params->max_separations;
354     int page_spot_colors = pdevn_params->page_spot_colors;
355     gs_param_string_array scna;		/* SeparationColorNames array */
356     gs_param_string_array sona;		/* SeparationOrder names array */
357 
358     /* Get the SeparationOrder names */
359     BEGIN_ARRAY_PARAM(param_read_name_array, "SeparationOrder",
360 		    			sona, sona.size, sone)
361     {
362 	break;
363     } END_ARRAY_PARAM(sona, sone);
364     if (sona.data != 0 && sona.size > GX_DEVICE_COLOR_MAX_COMPONENTS)
365 	return_error(gs_error_rangecheck);
366 
367     /* Get the SeparationColorNames */
368     BEGIN_ARRAY_PARAM(param_read_name_array, "SeparationColorNames",
369 		    			scna, scna.size, scne)
370     {
371 	break;
372     } END_ARRAY_PARAM(scna, scne);
373     if (scna.data != 0 && scna.size > GX_DEVICE_MAX_SEPARATIONS)
374 	return_error(gs_error_rangecheck);
375 
376     /* Separations are only valid with a subrtractive color model */
377     if (pdev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE) {
378         /*
379          * Process the SeparationColorNames.  Remove any names that already
380 	 * match the process color model colorant names for the device.
381          */
382         if (scna.data != 0) {
383 	    int i;
384 	    int num_names = scna.size;
385 	    fixed_colorant_names_list pcomp_names =
386 	        pdevn_params->std_colorant_names;
387 
388 	    for (i = num_spot = 0; i < num_names; i++) {
389 		/* Verify that the name is not one of our process colorants */
390 	        if (!check_process_color_names(pcomp_names, &scna.data[i])) {
391 		    byte * sep_name;
392 		    int name_size = scna.data[i].size;
393 
394 		    /* We have a new separation */
395 		    sep_name = (byte *)gs_alloc_bytes(pdev->memory,
396 			name_size, "devicen_put_params_no_sep_order");
397 		    memcpy(sep_name, scna.data[i].data, name_size);
398 	            pdevn_params->separations.names[num_spot].size = name_size;
399 	            pdevn_params->separations.names[num_spot].data = sep_name;
400 		    if (pequiv_colors != NULL) {
401 			/* Indicate that we need to find equivalent CMYK color. */
402 			pequiv_colors->color[num_spot].color_info_valid = false;
403 			pequiv_colors->all_color_info_valid = false;
404 		    }
405 		    num_spot++;
406 		}
407 	    }
408 	    pdevn_params->separations.num_separations = num_spot;
409 	    num_spot_changed = true;
410 	    for (i = 0; i < num_spot + npcmcolors; i++)
411 		pdevn_params->separation_order_map[i] = i;
412         }
413         /*
414          * Process the SeparationOrder names.
415          */
416         if (sona.data != 0) {
417 	    int i, comp_num;
418 
419 	    num_order = sona.size;
420 	    for (i = 0; i < num_spot + npcmcolors; i++)
421 		pdevn_params->separation_order_map[i] =
422 		       			GX_DEVICE_COLOR_MAX_COMPONENTS;
423 	    for (i = 0; i < num_order; i++) {
424 	        /*
425 	         * Check if names match either the process color model or
426 	         * SeparationColorNames.  If not then error.
427 	         */
428 	        if ((comp_num = check_pcm_and_separation_names(pdev, pdevn_params,
429 		    (const char *)sona.data[i].data, sona.data[i].size, 0)) < 0) {
430 		    return_error(gs_error_rangecheck);
431 		}
432 		pdevn_params->separation_order_map[comp_num] = i;
433 	    }
434         }
435         /*
436          * Adobe says that MaxSeparations is supposed to be 'read only'
437 	 * however we use this to allow the specification of the maximum
438 	 * number of separations.  Memory is allocated for the specified
439 	 * number of separations.  This allows us to then accept separation
440 	 * colors in color spaces even if they we not specified at the start
441 	 * of the image file.
442          */
443         code = param_read_int(plist, param_name = "MaxSeparations", &max_sep);
444         switch (code) {
445             default:
446 	        param_signal_error(plist, param_name, code);
447             case 1:
448 		break;
449             case 0:
450 	        if (max_sep < 1 || max_sep > GX_DEVICE_COLOR_MAX_COMPONENTS)
451 		    return_error(gs_error_rangecheck);
452         }
453         /*
454          * The PDF interpreter scans the resources for pages to try to
455 	 * determine the number of spot colors.  (Unfortuneately there is
456 	 * no way to determine the number of spot colors for a PS page
457 	 * except to interpret the entire page.)  The spot color count for
458 	 * a PDF page may be high since there may be spot colors in a PDF
459 	 * page's resources that are not used.  However this does give us
460 	 * an upper limit on the number of spot colors.  A value of -1
461 	 * indicates that the number of spot colors in unknown (a PS file).
462          */
463         code = param_read_int(plist, param_name = "PageSpotColors",
464 		       					&page_spot_colors);
465         switch (code) {
466             default:
467 	        param_signal_error(plist, param_name, code);
468             case 1:
469 		break;
470             case 0:
471 	        if (page_spot_colors < -1)
472 		    return_error(gs_error_rangecheck);
473 	        if (page_spot_colors > GX_DEVICE_COLOR_MAX_COMPONENTS - MAX_DEVICE_PROCESS_COLORS)
474 		    page_spot_colors = GX_DEVICE_COLOR_MAX_COMPONENTS - MAX_DEVICE_PROCESS_COLORS;
475                     /* Need to leave room for the process colors in GX_DEVICE_COLOR_MAX_COMPONENTS  */
476         }
477         /*
478          * The DeviceN device can have zero components if nothing has been
479 	 * specified.  This causes some problems so force at least one
480 	 * component until something is specified.
481          */
482         if (!pdev->color_info.num_components)
483 	    pdev->color_info.num_components = 1;
484 	/*
485 	 * Update the number of device components if we have changes in
486 	 * SeparationColorNames, SeparationOrder, or MaxSeparations.
487 	 */
488 	if (num_spot_changed || pdevn_params->max_separations != max_sep ||
489 	    	    pdevn_params->num_separation_order_names != num_order ||
490 		    pdevn_params->page_spot_colors != page_spot_colors) {
491 	    pdevn_params->separations.num_separations = num_spot;
492 	    pdevn_params->num_separation_order_names = num_order;
493     	    pdevn_params->max_separations = max_sep;
494     	    pdevn_params->page_spot_colors = page_spot_colors;
495 	    if (max_sep != 0)
496 		 pdev->color_info.max_components = max_sep;
497 	    /*
498 	     * If we have SeparationOrder specified then the number of
499 	     * components is given by the number of names in the list.
500 	     * Otherwise check if the MaxSeparations parameter has specified
501 	     * a value.  If so then use that value, otherwise use the number
502 	     * of ProcessColorModel components plus the number of
503 	     * SeparationColorNames is used.
504 	     */
505             pdev->color_info.num_components = (num_order)
506 		? num_order
507 		: (pdevn_params->max_separations)
508 			? pdevn_params->max_separations
509 			: (page_spot_colors >= 0)
510 		       		? npcmcolors + num_spot + page_spot_colors
511 	    			: pdev->color_info.max_components;
512             if (pdev->color_info.num_components >
513 		    pdev->color_info.max_components)
514                 pdev->color_info.num_components =
515 		       	pdev->color_info.max_components;
516 #if !USE_COMPRESSED_ENCODING
517 	    /*
518 	     * See earlier comment about the depth and non compressed
519 	     * pixel encoding.
520 	     */
521             pdev->color_info.depth = bpc_to_depth(pdev->color_info.num_components,
522 					pdevn_params->bitspercomponent);
523 #endif
524 	}
525     }
526     return code;
527 }
528 
529 /*
530  * Utility routine for handling DeviceN related parameters in a
531  * standard raster printer type device.
532  */
533 int
devn_printer_put_params(gx_device * pdev,gs_param_list * plist,gs_devn_params * pdevn_params,equivalent_cmyk_color_params * pequiv_colors)534 devn_printer_put_params(gx_device * pdev, gs_param_list * plist,
535     gs_devn_params * pdevn_params, equivalent_cmyk_color_params * pequiv_colors)
536 {
537     int code;
538     /* Save current data in case we have a problem */
539     gx_device_color_info save_info = pdev->color_info;
540     gs_devn_params saved_devn_params = *pdevn_params;
541     equivalent_cmyk_color_params saved_equiv_colors;
542 
543     if (pequiv_colors != NULL)
544         saved_equiv_colors = *pequiv_colors;
545 
546     /* Use utility routine to handle parameters */
547     code = devn_put_params(pdev, plist, pdevn_params, pequiv_colors);
548 
549     /* Check for default printer parameters */
550     if (code >= 0)
551         code = gdev_prn_put_params(pdev, plist);
552 
553     /* If we have an error then restore original data. */
554     if (code < 0) {
555 	pdev->color_info = save_info;
556 	*pdevn_params = saved_devn_params;
557 	if (pequiv_colors != NULL)
558 	   *pequiv_colors = saved_equiv_colors;
559 	return code;
560     }
561 
562     /* If anything changed, then close the device, etc. */
563     if (memcmp(&pdev->color_info, &save_info, sizeof(gx_device_color_info)) ||
564 	memcmp(pdevn_params, &saved_devn_params,
565 					sizeof(gs_devn_params)) ||
566 	(pequiv_colors != NULL &&
567 	    memcmp(pequiv_colors, &saved_equiv_colors,
568 				sizeof(equivalent_cmyk_color_params)))) {
569 	gs_closedevice(pdev);
570         /* Reset the sparable and linear shift, masks, bits. */
571 	set_linear_color_bits_mask_shift(pdev);
572     }
573     /*
574      * Also check for parameters which are being passed from the PDF 1.4
575      * compositior clist write device.  This device needs to pass info
576      * to the PDF 1.4 compositor clist reader device.  However this device
577      * is not crated until the clist is being read.  Thus we have to buffer
578      * this info in the output device.   (This is only needed for devices
579      * which support spot colors.)
580      */
581     code = pdf14_put_devn_params(pdev, pdevn_params, plist);
582     return code;
583 }
584 
585 /*
586  * The following routines are for compressing colorant values into a 64 bit
587  * gx_color_index value.  This is needed since Ghostscript uses an integer type
588  * (usually 64 bit long long) as the representation for a pixel.  This is a
589  * problem for handling output devices which support spot colors.  Ideally these
590  * devices should be able to handle any number of colorants.  This would require
591  * an arbitrarily large number of bits to represent a pixel.
592  *
593  * See comments before devn_encode_compressed_color for more information.
594  */
595 
596 /* GC procedures */
597 static
ENUM_PTRS_WITH(compressed_color_list_enum_ptrs,compressed_color_list_t * plist)598 ENUM_PTRS_WITH(compressed_color_list_enum_ptrs, compressed_color_list_t *plist)
599 {
600     if (index < plist->num_sub_level_ptrs)
601 	ENUM_RETURN(plist->u.sub_level_ptrs[index]);
602     return 0;
603 }
604 ENUM_PTRS_END
605 
RELOC_PTRS_WITH(compressed_color_list_reloc_ptrs,compressed_color_list_t * plist)606 static RELOC_PTRS_WITH(compressed_color_list_reloc_ptrs, compressed_color_list_t *plist)
607 {
608     int i;
609 
610     for (i = 0; i < plist->num_sub_level_ptrs; i++) {
611 	RELOC_PTR(compressed_color_list_t, u.sub_level_ptrs[i]);
612     }
613 }
614 RELOC_PTRS_END
615 
616 gs_private_st_composite(st_compressed_color_list, compressed_color_list_t,
617 		"encode color list", compressed_color_list_enum_ptrs,
618     		compressed_color_list_reloc_ptrs);
619 /*
620  * A routine for debugging the encoded color colorant list.  This routine
621  * dumps the contents of the list.
622  */
623 void
print_compressed_color_list(compressed_color_list_t * pcomp_list,int num_comp)624 print_compressed_color_list(compressed_color_list_t * pcomp_list, int num_comp)
625 {
626     int i, j, comp_num, comp;
627     comp_bit_map_list_t * pcomp_bit_map;
628 
629     if (pcomp_list == NULL)
630 	return;
631 
632     /* Indent our print out for sub levels */
633     for (i = TOP_ENCODED_LEVEL - pcomp_list->level_num_comp; i > 0; i--)
634 	dlprintf("    ");
635     dlprintf1("List level = %d\n", pcomp_list->level_num_comp);
636     /*
637      * Print the colorant bit maps for this level.
638      */
639     for (i = NUM_ENCODE_LIST_ITEMS - 1; i >= pcomp_list->first_bit_map; i--) {
640 	pcomp_bit_map = &(pcomp_list->u.comp_data[i]);
641         /* Indent our print out for sub levels */
642         for (j = TOP_ENCODED_LEVEL - pcomp_list->level_num_comp; j > 0; j--)
643 	    dlprintf("    ");
644         dlprintf4("%3d%4d%4d %d ", i, pcomp_bit_map->num_comp,
645 		pcomp_bit_map->num_non_solid_comp, pcomp_bit_map->solid_not_100);
646 	for (comp_num = num_comp - 1; comp_num >= 0; comp_num--) {
647 	    comp = colorant_present(pcomp_bit_map, colorants, comp_num);
648             dlprintf1("%d", comp);
649 	    if ((comp_num & 7) == 0)	/* Separate into groups of 8 bits */
650                 dlprintf(" ");
651 	}
652         dlprintf("    ");
653 	for (comp_num = num_comp - 1; comp_num >= 0; comp_num--) {
654 	    comp = colorant_present(pcomp_bit_map, solid_colorants, comp_num);
655             dlprintf1("%d", comp);
656 	    if ((comp_num & 7) == 0)	/* Separate into groups of 8 bits */
657                 dlprintf(" ");
658 	}
659         dlprintf("\n");
660     }
661 
662     /*
663      * Print the sub levels.
664      */
665     for (i = 0; i < pcomp_list->num_sub_level_ptrs; i++)
666        print_compressed_color_list(pcomp_list->u.sub_level_ptrs[i], num_comp);
667 
668     return;
669 }
670 
671 /*
672  * Allocate an list level element for our encode color list.
673  */
674 compressed_color_list_t *
alloc_compressed_color_list_elem(gs_memory_t * mem,int num_comps)675 alloc_compressed_color_list_elem(gs_memory_t * mem, int num_comps)
676 {
677     compressed_color_list_t * plist =
678         gs_alloc_struct(mem, compressed_color_list_t, &st_compressed_color_list,
679 			       "alloc_compressed_color_list");
680     if (plist != NULL) {
681 	/* Initialize the data in the element. */
682 	memset(plist, 0, size_of(*plist));
683 	plist->level_num_comp = num_comps;
684 	plist->first_bit_map = NUM_ENCODE_LIST_ITEMS;
685     }
686     return plist;
687 }
688 
689 /*
690  * Free the elements of a compressed color list.
691  */
692 void
free_compressed_color_list(gs_memory_t * mem,compressed_color_list_t * pcomp_list)693 free_compressed_color_list(gs_memory_t * mem,
694 	       	compressed_color_list_t * pcomp_list)
695 {
696     int i;
697 
698     if (pcomp_list == NULL)
699 	return;
700 
701     /* Discard the sub levels. */
702     for (i = 0; i < pcomp_list->num_sub_level_ptrs; i++)
703        free_compressed_color_list(mem, pcomp_list->u.sub_level_ptrs[i]);
704 
705     gs_free_object(mem, pcomp_list, "free_compressed_color_list");
706     return;
707 }
708 
709 /*
710  * Free a set of separation names
711  */
712 void
free_separation_names(gs_memory_t * mem,gs_separations * pseparation)713 free_separation_names(gs_memory_t * mem,
714 	       	gs_separations * pseparation)
715 {
716     int i;
717 
718     /* Discard the sub levels. */
719     for (i = 0; i < pseparation->num_separations; i++)
720         gs_free_object(mem->stable_memory, pseparation->names[i].data,
721 				"free_separation_names");
722     pseparation->num_separations = 0;
723     return;
724 }
725 
726 /*
727  * Add a new set of bit mapped colorant lists to our list of encoded color
728  * colorants.
729  */
730 static bool
sub_level_add_compressed_color_list(gs_memory_t * mem,comp_bit_map_list_t * pnew_comp_bit_map,compressed_color_list_t * pcomp_list,gx_color_index * plist_index)731 sub_level_add_compressed_color_list(gs_memory_t * mem,
732 		comp_bit_map_list_t * pnew_comp_bit_map,
733 		compressed_color_list_t * pcomp_list, gx_color_index * plist_index)
734 {
735     int i, entry_num;
736     int num_non_solid_comp = pnew_comp_bit_map->num_non_solid_comp;
737     bool status;
738 
739     /*
740      * Check if this is the level for the specified number of entries.  If so
741      * then add the bit map to this level (if we have room).
742      */
743     if (num_non_solid_comp >= pcomp_list->level_num_comp) {
744 	entry_num = pcomp_list->first_bit_map - 1;
745 
746 	if (entry_num > pcomp_list->num_sub_level_ptrs) {
747 	    memcpy(&(pcomp_list->u.comp_data[entry_num]), pnew_comp_bit_map,
748 				    size_of(comp_bit_map_list_t));
749 	    pcomp_list->first_bit_map = entry_num;
750 	    *plist_index =
751 		    ((gx_color_index) entry_num) << (NUM_GX_COLOR_INDEX_BITS - 8);
752 	    return true;
753 	}
754 	return false;
755     }
756     /*
757      * Try to insert the bit map into the sub levels.
758      */
759     for (i = 0; i < pcomp_list->num_sub_level_ptrs; i++) {
760 	status = sub_level_add_compressed_color_list(mem, pnew_comp_bit_map,
761 			pcomp_list->u.sub_level_ptrs[i], plist_index);
762 	if (status) {
763 	    *plist_index = (((gx_color_index) i) << (NUM_GX_COLOR_INDEX_BITS - 8))
764 		    + (*plist_index >> 8);
765 	    return true;
766 	}
767     }
768     /*
769      * If we did not add this bit map into a sub level then create a new sub
770      * level and insert it there.
771      */
772     entry_num = pcomp_list->num_sub_level_ptrs;
773     if (entry_num < pcomp_list->first_bit_map) {
774 	pcomp_list->u.sub_level_ptrs[entry_num] =
775 	    alloc_compressed_color_list_elem(mem, pcomp_list->level_num_comp - 1);
776 	if (pcomp_list->u.sub_level_ptrs[entry_num] != NULL) {
777 	    pcomp_list->num_sub_level_ptrs++;
778 	    status = sub_level_add_compressed_color_list(mem, pnew_comp_bit_map,
779 			pcomp_list->u.sub_level_ptrs[entry_num], plist_index);
780 	    if (status) {
781 		*plist_index = (((gx_color_index) i) << (NUM_GX_COLOR_INDEX_BITS - 8))
782 		    + (*plist_index >> 8);
783 		return true;
784 	    }
785 	}
786     }
787     /*
788      * If we get to here then there was no space available in this list element.
789      */
790     return false;
791 }
792 
793 /*
794  * Add a new bit mapped colorant list to our list of encoded color colorants.
795  *
796  * Our simple linear search for entries gets very inefficient if we have many
797  * entries.  So we are doing two things to minimize the number of entries.
798  * We need separate entries for each combination of solid colorants.  if we
799  * do not have many non solid colorants, we use non solid colorants even for
800  * solid colorants.  For small numbers of colorants, we add more colorants
801  * to try to create an entry that can be used for more situations.  We add extra
802  * process color colorants since these are the ones most likely to be mixed
803  * with spot colors.
804  */
805 static bool
add_compressed_color_list(gs_memory_t * mem,comp_bit_map_list_t * pnew_comp_bit_map,compressed_color_list_t * pcomp_list,gx_color_index * plist_index)806 add_compressed_color_list(gs_memory_t * mem,
807 	comp_bit_map_list_t * pnew_comp_bit_map,
808 	compressed_color_list_t * pcomp_list, gx_color_index * plist_index)
809 {
810     int num_comp = pnew_comp_bit_map->num_comp;
811     int num_non_solid = pnew_comp_bit_map->num_non_solid_comp;
812     int num_solid = num_comp - num_non_solid;
813     int comp_num = 0;
814 
815     /*
816      * If we have room for more 'non solid' colorants then convert some of
817      * the solid colorants to using the non solid encodings.
818      */
819     while (num_non_solid < MIN_ENCODED_COMPONENTS && num_solid > 0) {
820 	if (colorant_present(pnew_comp_bit_map, solid_colorants, comp_num)) {
821 	    clear_colorant_present(pnew_comp_bit_map,
822 			    		solid_colorants, comp_num);
823 	    num_solid--;
824 	    num_non_solid++;
825 	}
826 	comp_num++;
827     }
828     if (num_non_solid < MIN_ENCODED_COMPONENTS) {
829         /*
830 	 * For small numbers of colorants, we add more colorants to try to
831 	 * create an entry that can be used for more situations.
832          */
833 	for (comp_num = 0; num_comp < MIN_ENCODED_COMPONENTS; comp_num++) {
834 	    if ((colorant_present(pnew_comp_bit_map, colorants, comp_num)) == 0) {
835 	        set_colorant_present(pnew_comp_bit_map, colorants, comp_num);
836 		num_non_solid++;
837 		num_comp++;
838 	    }
839 	}
840     }
841     pnew_comp_bit_map->num_comp = num_comp;
842     pnew_comp_bit_map->num_non_solid_comp = num_non_solid;
843     return sub_level_add_compressed_color_list(mem, pnew_comp_bit_map,
844 				pcomp_list, plist_index);
845 }
846 
847 /*
848  * Initialize our encode color list.  When we initialize the list, we add two
849  * initial colorant maps.  The first one is good for any image that uses zeven
850  * or fewer colorants.  The second is good for any image which uses seven spot
851  * colors (or less) and no process colors.  These are placed at the start of
852  * the list to minimize the add and search times for these common situations.
853  */
854 static compressed_color_list_t *
init_compressed_color_list(gs_memory_t * mem)855 init_compressed_color_list(gs_memory_t *mem)
856 {
857     /*
858      * Create our first list element.
859      */
860     compressed_color_list_t * plist =
861 	alloc_compressed_color_list_elem(mem, TOP_ENCODED_LEVEL);
862 
863     /*
864      * Add a first colorant bit map to the list.  This bit map covers the first
865      * TOP_ENCODED_LEVEL colorants.  Typically this covers CMYK plus the
866      * first three spot colors.  This bit map should handle many situations.
867      */
868     if (plist != NULL) {
869 	int comp_num;
870         comp_bit_map_list_t comp_bit_map;
871 	gx_color_index temp;
872 
873         /*
874          * Add a first colorant bit map to the list.  This bit map covers the
875 	 * first TOP_ENCODED_LEVEL colorants.  Typically this covers CMYK plus
876 	 * the first three spot colors.  This bit map should handle many
877 	 * situations.
878          */
879 	memset(&comp_bit_map, 0, size_of(comp_bit_map));
880 	for (comp_num = 0; comp_num < TOP_ENCODED_LEVEL; comp_num++)
881 	    set_colorant_present(&comp_bit_map, colorants, comp_num);
882 	comp_bit_map.num_comp =
883 		comp_bit_map.num_non_solid_comp = TOP_ENCODED_LEVEL;
884 	add_compressed_color_list(mem, &comp_bit_map, plist, &temp);
885         /*
886          * Add a second colorant bit map to the list.  This bit map covers the
887 	 * first TOP_ENCODED_LEVEL colorants after the first four colorants.
888 	 * Typically this covers the first seven spot colors.  This bit map is
889 	 * being placed to cover images that use only spot colors.
890          */
891 	memset(&comp_bit_map, 0, size_of(comp_bit_map));
892 	for (comp_num = 4; comp_num < TOP_ENCODED_LEVEL + 4; comp_num++)
893 	    set_colorant_present(&comp_bit_map, colorants, comp_num);
894 	comp_bit_map.num_comp =
895 		comp_bit_map.num_non_solid_comp = TOP_ENCODED_LEVEL;
896 	add_compressed_color_list(mem, &comp_bit_map, plist, &temp);
897     }
898     return plist;
899 }
900 
901 /*
902  * For most combinations of colorants we use 8 bits for saving the colorant
903  * value.  However if we get above 7 colorants (in a pixel, not total) we use
904  * fewer bits.  The constraint is that the size of the index value plus the
905  * the number of colorants being used times size of the colorant value saved
906  * must fit into a gx_color_index value.
907  */
908 int num_comp_bits[MAX_ENCODED_COMPONENTS + 1] = {
909 	8,	/* 0 colorants - not used */
910 	8,	/* 1 colorants */
911 	8,	/* 2 colorants */
912 	8,	/* 3 colorants */
913 	8,	/* 4 colorants */
914 	8,	/* 5 colorants */
915 	8,	/* 6 colorants */
916 	8,	/* 7 colorants */
917 	7,	/* 8 colorants */
918 	6,	/* 9 colorants */
919 	5,	/* 10 colorants */
920 	5,	/* 11 colorants */
921 	4,	/* 12 colorants */
922 	4,	/* 13 colorants */
923 	4	/* 14 colorants */
924 };
925 
926 /*
927  * Values used to decompressed the colorants in our encoded values back into
928  * a gx_color value.  The color value will be (comp_bits * entry) >> 8
929  * The number of bits in comp_bits are defined in the num_comp_bits table.
930  * These values are chosen to expand these bit combinations back to 16 bit values
931  * (after shifting right 8 bits).
932  */
933 #define gx_color_value_factor(num_bits) \
934     ((gx_max_color_value << 8) + 0xff) / ((1 << num_bits) - 1)
935 
936 int comp_bit_factor[MAX_ENCODED_COMPONENTS + 1] = {
937 	gx_color_value_factor(8),		 /*  0 colorants (8 bits) */
938 	gx_color_value_factor(8),		 /*  1 colorants (8 bits) */
939 	gx_color_value_factor(8),		 /*  2 colorants (8 bits) */
940 	gx_color_value_factor(8),		 /*  3 colorants (8 bits) */
941 	gx_color_value_factor(8),		 /*  4 colorants (8 bits) */
942 	gx_color_value_factor(8),		 /*  5 colorants (8 bits) */
943 	gx_color_value_factor(8),		 /*  6 colorants (8 bits) */
944 	gx_color_value_factor(8),		 /*  7 colorants (8 bits) */
945 	gx_color_value_factor(7),		 /*  8 colorants (7 bits) */
946 	gx_color_value_factor(6),		 /*  9 colorants (6 bits) */
947 	gx_color_value_factor(5),		 /* 10 colorants (5 bits) */
948 	gx_color_value_factor(5),		 /* 11 colorants (5 bits) */
949 	gx_color_value_factor(4),		 /* 12 colorants (4 bits) */
950 	gx_color_value_factor(4),		 /* 13 colorants (4 bits) */
951 	gx_color_value_factor(4)		 /* 14 colorants (4 bits) */
952 };
953 #undef gx_color_value_factor
954 
955 /*
956  * Find a given colorant bit map is the list of encoded colorant bit map.
957  *
958  * Note:  This routine is called recursively to search sub levels of the
959  * list.
960  *
961  * The parameters are:
962  *    num_comp - The number of colorants for the device.
963  *    pcomp_list - The current list of encoded colorants.
964  *    pnew_comp_bit_map - Pointer to the bit map found to be encoded.
965  *    plist_index - Pointer to 'encode bits' (return value)
966  *    pcomp_bit_map - Pointer to pointer to the actual bit map found
967  *    			(return value).
968  *    returns true if the bit map is found.
969  */
970 static bool
search_compressed_color_list(int num_comp,compressed_color_list_t * pcomp_list,comp_bit_map_list_t * pnew_comp_bit_map,gx_color_index * plist_index,comp_bit_map_list_t ** pcomp_bit_map)971 search_compressed_color_list(int num_comp, compressed_color_list_t * pcomp_list,
972 	comp_bit_map_list_t * pnew_comp_bit_map, gx_color_index * plist_index,
973 	comp_bit_map_list_t * * pcomp_bit_map)
974 {
975     int i;
976 #if DEVN_ENCODE_COLOR_USING_BIT_MAP_ARRAY
977     int j, num_bit_map_elem;
978 #endif
979     bool found;
980 
981     /*
982      * Search the colorant bit maps for this level of the map.
983      */
984 #if DEVN_ENCODE_COLOR_USING_BIT_MAP_ARRAY
985     num_bit_map_elem = (num_comp + BITS_PER_COMP_BIT_MAP_ELEM - 1) /
986 	    					BITS_PER_COMP_BIT_MAP_ELEM;
987 #endif
988     for (i = NUM_ENCODE_LIST_ITEMS - 1; i >= pcomp_list->first_bit_map; i--) {
989 	*pcomp_bit_map = &(pcomp_list->u.comp_data[i]);
990 	/*
991 	 * Do not try to match if one entry uses a 'solid' set of colorants
992 	 * that is not really solid (i.e. not 100%) and the other is.  It is
993 	 * possible to work if different but it would make some of the logic
994 	 * more difficult.
995 	 */
996 	if (pnew_comp_bit_map->solid_not_100 !=
997 			(*pcomp_bit_map)->solid_not_100)
998 	    continue;
999         /*
1000          * It is a match if the new colorant bit map is a subset of the one
1001 	 * in the list and the solid colorants for new map is a super set of
1002 	 * the solid colorants for the one in the list.  I.e. we can use
1003 	 * the non solid part of the entry for either zero or solid colorants.
1004          */
1005 #if DEVN_ENCODE_COLOR_USING_BIT_MAP_ARRAY
1006 	for (j = 0; j < num_bit_map_elem; j++) {
1007 	    if ((pnew_comp_bit_map->colorants[j] &
1008 		    (*pcomp_bit_map)->colorants[j]) !=
1009 	   		pnew_comp_bit_map->colorants[j])
1010 		break;		/* No match if a colorant is missing. */
1011 	    if ((pnew_comp_bit_map->solid_colorants[j] &
1012 		    (*pcomp_bit_map)->solid_colorants[j]) !=
1013 	   		(*pcomp_bit_map)->solid_colorants[j])
1014 		break;		/* No match if extra solid colorants */
1015 	}
1016 	if (j == num_bit_map_elem) {
1017 #else
1018 	if (((pnew_comp_bit_map->colorants &
1019 		(*pcomp_bit_map)->colorants) ==
1020 		    pnew_comp_bit_map->colorants) &&
1021 		((pnew_comp_bit_map->solid_colorants &
1022 	     	    (*pcomp_bit_map)->solid_colorants) ==
1023 		    (*pcomp_bit_map)->solid_colorants)) {
1024 #endif
1025 	    /*
1026 	     * To prevent possible loss of accuracy, ignore matches in which the
1027 	     * packing will use fewer bits in the encoded colorant values than
1028 	     * is possible for the given number of colorants.
1029 	     */
1030 	    if (num_comp_bits[pnew_comp_bit_map->num_comp] >
1031 	    		num_comp_bits[(*pcomp_bit_map)->num_comp])
1032 		break;
1033 	    /*
1034 	     * We have a match.  Put our object number into the top eight
1035 	     * bits of the encoded gx_color_index and exit.
1036 	     */
1037 	    *plist_index = ((gx_color_index) i) << (NUM_GX_COLOR_INDEX_BITS - 8);
1038 	    return true;
1039 	}
1040     }
1041 
1042     /*
1043      * Search the lower levels (i.e. with fewer colorants to see if we
1044      * can find a match.
1045      */
1046     if (pcomp_list->level_num_comp <= pnew_comp_bit_map->num_non_solid_comp)
1047 	return false;	/* Exit if not enough colorants in the sub levels */
1048 
1049     for (i = 0; i < pcomp_list->num_sub_level_ptrs; i++) {
1050 	found = search_compressed_color_list(num_comp,
1051 			pcomp_list->u.sub_level_ptrs[i],
1052 			pnew_comp_bit_map, plist_index, pcomp_bit_map);
1053 	if (found) {
1054 	    /*
1055 	     * We have a match.  Combine the encode index for the sub level
1056 	     * with our index for this level.
1057 	     */
1058 	    *plist_index = (((gx_color_index) i) << (NUM_GX_COLOR_INDEX_BITS - 8))
1059 		    + (*plist_index >> 8);
1060 	    return true;
1061 	}
1062     }
1063     return false;
1064 }
1065 
1066 /*
1067  * Encode a list of colorant values into a gx_color_index_value.
1068  *
1069  * This routine is designed to pack more than eight 8 bit colorant values into
1070  * a 64 bit gx_color_index value.  It does this piece of magic by keeping a list
1071  * of which colorant combinations are actualy used (i.e. which colorants are non
1072  * zero).  The non zero colorant values and and an 'index' value are packed into
1073  * the output gx_color_index value.
1074  *
1075  * The the different combinations of used colorants are saved into a table
1076  * defined by the comp_bit_map_list_t structure type.  This table is kept as
1077  * a list with 256 elements.  Each element can be either a pair of bit maps which
1078  * indicates the combination of colorants being used or a pointer to a sub list
1079  * for the next lower level of combinations.  There are two bit maps to indicate
1080  * which colorants are specified by the 'index' value.  One bit map indicates
1081  * which colorants are used.  The second bit map is used to indicate a group of
1082  * colorants with the same value.  Normally this second bit map is used to
1083  * indicate which colorants are 'solid' (i.e. 100% and the 'solid_not_100 flag
1084  * is set to false).  However if there is a larger group of colorants with the
1085  * same value (and not solid) then the 'solid_not_100' flag is set to true and
1086  * second bit map is used to indicate the colorants in this group.  In this
1087  * case, the value of the colorant group is stored in the first colorant entry
1088  * in the gx_color_index.
1089  *
1090  * The number of bits allocated to storing the 'index' and the number of bits
1091  * allocated to storing colorant values depends upon the number of colorant
1092  * being used.
1093  *
1094  * 	Number of non zero colorant	Index bits	Bits per colorant
1095  *		0 to 5			   24		   8
1096  *		   6			   16		   8
1097  *		   7			    8		   8
1098  *		   8	       		    8		   7
1099  *		   9			    8		   6
1100  *		  10			    8		   5
1101  *		  11			    8		   5
1102  *		  12			    8		   4
1103  *		  13			    8		   4
1104  *		  14			    8		   4
1105  *	    More than 14		Not encodeable
1106  *
1107  * The 'index' bits can be logically divided into groups of 8 bits.  The
1108  * first (upper) group of 8 bits is used to select either one of 256
1109  * combinations of 7 or more colorant or to select a pointer to a sub
1110  * level.  If a sub level pointer is specified, then the next group of 8
1111  * index bits is used to select either one of 256 combinations of 6 colorants
1112  * of a sub level pointer.  A sub level pointer points to one of 256
1113  * combinations of 5 colorants.  If we have fewer than 5 colorants being
1114  * used, we add extra componnents to bring the total up to 5 colorants.
1115  * This is done to prevent having a bunch of 1 or two colorant combinations.
1116  */
1117 gx_color_index
1118 devn_encode_compressed_color(gx_device *pdev, const gx_color_value colors[],
1119 					gs_devn_params * pdevn_params)
1120 {
1121     int num_comp = pdev->color_info.num_components;
1122     int comp_num, comp_count = 0, solid_comp_count = 0, bit_pos = 0;
1123     int bit_shift, bit_count, group = 0;
1124     int color_resolution = gx_max_color_value / STD_ENCODED_VALUE;
1125     bool found, added;
1126     comp_bit_map_list_t new_comp_bit_map = {0};
1127     comp_bit_map_list_t * pbit_map;
1128     gx_color_index color = 0, list_index;
1129 
1130     /*
1131      * Determine what colorants are being used (non zero).  We bit pack
1132      * this info.  Note:  We treat any colorant value which is less than
1133      * 256 as zero.  Color values are 16 bits and we only keep the top
1134      * eight bits.  Likewise for solid (100%) colors.
1135      */
1136     for (comp_num = 0; comp_num < num_comp; comp_num++) {
1137         if (colors[comp_num] > color_resolution) {
1138 	    set_colorant_present(&new_comp_bit_map, colorants, comp_num);
1139 	    comp_count++;
1140 	    /* Check if the color is solid */
1141             if (colors[comp_num] > (gx_max_color_value - color_resolution)) {
1142 	        set_colorant_present(&new_comp_bit_map,
1143 						solid_colorants, comp_num);
1144 	        solid_comp_count++;
1145 	    }
1146 	}
1147     }
1148     new_comp_bit_map.num_comp = comp_count;
1149     new_comp_bit_map.num_non_solid_comp = comp_count - solid_comp_count;
1150     /*
1151      * We may get less loss of accuracy if instead of checking for zero and
1152      * 100% colorant values, we look for a group of colorants with the same
1153      * colorant value.
1154      */
1155     if (new_comp_bit_map.num_non_solid_comp > TOP_ENCODED_LEVEL &&
1156 		    solid_comp_count < (comp_count / 2)) {
1157 	short group_size[(gx_max_color_value / STD_ENCODED_VALUE) + 1] = {0};
1158 	int value, largest_group_size = 0;
1159 
1160 	/* Scan to determine the size of the largest group */
1161         for (comp_num = 0; comp_num < num_comp; comp_num++) {
1162             value = colors[comp_num] / STD_ENCODED_VALUE;
1163 	    group_size[value]++;
1164 	    if (group_size[value] > largest_group_size) {
1165 		largest_group_size = group_size[value];
1166 		group = value;
1167 	    }
1168         }
1169 	/*
1170 	 * If using this group instead of the solid colorants will improve
1171 	 * our situation, then switch to using this group.
1172 	 */
1173 	if (largest_group_size > (solid_comp_count + 1) &&
1174 		(comp_count - largest_group_size) < MAX_ENCODED_COMPONENTS) {
1175 	    /* Setup the colorant description to use this group */
1176 	    memset(&(new_comp_bit_map.solid_colorants), 0,
1177 			    		size_of(comp_bit_map_t));
1178             for (comp_num = 0; comp_num < num_comp; comp_num++) {
1179                 value = colors[comp_num] / STD_ENCODED_VALUE;
1180 	        if (value == group) {
1181 	            set_colorant_present(&new_comp_bit_map,
1182 						solid_colorants, comp_num);
1183 	        }
1184             }
1185 	    new_comp_bit_map.solid_not_100 = true;
1186 	    new_comp_bit_map.num_non_solid_comp =
1187 		    			comp_count - largest_group_size + 1;
1188 	}
1189     }
1190 
1191     /* Our encoding scheme cannot handle too many non solid colorants. */
1192     if (new_comp_bit_map.num_non_solid_comp > MAX_ENCODED_COMPONENTS)
1193 	return NON_ENCODEABLE_COLOR;
1194 
1195     /*
1196      * We keep a list of which colorant combinations we have used.  Make
1197      * sure that this list has been initialized.
1198      */
1199     if (pdevn_params->compressed_color_list == NULL) {
1200         pdevn_params->compressed_color_list =
1201 		init_compressed_color_list(pdev->memory);
1202         if (pdevn_params->compressed_color_list == NULL)
1203 	    return NON_ENCODEABLE_COLOR;	/* Unable to initialize list */
1204     }
1205 
1206     /*
1207      * Check our list of colorant combinations to see if we already have a
1208      * combination that is useable.  I.e. a combination that includes all of our
1209      * non zero colorants.
1210      */
1211     found = search_compressed_color_list(num_comp,
1212 	    		pdevn_params->compressed_color_list,
1213 	    		&new_comp_bit_map, &list_index, &pbit_map);
1214 
1215     /*
1216      * If our new colorant list was not found then add it to our encode color
1217      * list.
1218      */
1219     if (!found) {
1220 	added = add_compressed_color_list(pdev->memory, &new_comp_bit_map,
1221 				pdevn_params->compressed_color_list, &list_index);
1222 	if (!added)
1223 	    return NON_ENCODEABLE_COLOR;
1224 	pbit_map = &new_comp_bit_map;
1225     }
1226 
1227     /*
1228      * Form the encoded color gx_color_index value.  This is a combination
1229      * of the bits that encode which colorants are used (non zero) and the
1230      * colorant values.
1231      */
1232     bit_count = num_comp_bits[pbit_map->num_non_solid_comp];
1233     bit_shift = sizeof(gx_color_value) * 8 - bit_count;
1234     if (pbit_map->solid_not_100) {
1235 	color = group >> (8 - bit_count);
1236 	bit_pos += bit_count;
1237     }
1238     for (comp_num = 0; comp_num < num_comp; comp_num++) {
1239 	if (colorant_present(pbit_map, colorants, comp_num) &&
1240 	   !colorant_present(pbit_map, solid_colorants, comp_num)) {
1241 	    color |=
1242 		((gx_color_index)(colors[comp_num] >> bit_shift)) << bit_pos;
1243 	    bit_pos += bit_count;
1244 	}
1245     }
1246     color |= list_index;
1247     /*
1248      * Make sure that our color index does not match one of the reserved
1249      * values.
1250      */
1251     if (color == NON_ENCODEABLE_COLOR)
1252 	color -= 1;
1253     else if (color == gx_no_color_index)
1254 	color -= 2;
1255     return color;
1256 }
1257 
1258 /*
1259  * Find the bit map for given bit map index.
1260  */
1261 comp_bit_map_list_t *
1262 find_bit_map(gx_color_index index, compressed_color_list_t * pcomp_list)
1263 {
1264     int loc = (int)(index >> (NUM_GX_COLOR_INDEX_BITS - 8));
1265 
1266     /*
1267      * Search for the level which contains the bit map.  If our index
1268      * for this level is less than the number of sub level pointers for
1269      * this level then we need to go down another level.
1270      */
1271     while (loc < pcomp_list->num_sub_level_ptrs) {
1272 	pcomp_list = pcomp_list->u.sub_level_ptrs[loc];
1273 	index <<= 8;
1274 	loc = (int)(index >> (NUM_GX_COLOR_INDEX_BITS - 8));
1275     }
1276     return &(pcomp_list->u.comp_data[loc]);
1277 }
1278 
1279 /*
1280  * Decode a gx_color_index value back to a list of colorant values.  This
1281  * routine assumes that the gx_color_index value is 'encoded' as described
1282  * for devn_encode_compressed_color.
1283  *
1284  * See comments preceding devn_encode_compressed_color for more information
1285  * about the way that we are compressing colorant values in a gx_color_index.
1286  */
1287 int
1288 devn_decode_compressed_color(gx_device * dev, gx_color_index color,
1289 			gx_color_value * out, gs_devn_params * pdevn_params)
1290 {
1291     int comp_num = 0;
1292     int factor, bit_count, bit_mask;
1293     int ncomp = dev->color_info.num_components;
1294     comp_bit_map_list_t * pbitmap;
1295     gx_color_value solid_color = gx_max_color_value;
1296 
1297     /*
1298      * Set all colorants to max if we get a non encodeable color.  We set the
1299      * values to a max since this will represent another non encodeable color.
1300      * Thus if we have a non decodable color, it will continue to propogate.
1301      */
1302     if (color == NON_ENCODEABLE_COLOR) {
1303         for (; comp_num < ncomp; comp_num++)
1304             out[comp_num] = gx_max_color_value;
1305         return 0;
1306     }
1307     pbitmap = find_bit_map(color, pdevn_params->compressed_color_list);
1308     bit_count = num_comp_bits[pbitmap->num_non_solid_comp];
1309     bit_mask = (1 << bit_count) - 1;
1310     factor = comp_bit_factor[pbitmap->num_non_solid_comp];
1311     if (pbitmap->solid_not_100) {
1312 	solid_color = (factor * ((int)color & bit_mask)) >> 8;
1313 	color >>= bit_count;
1314     }
1315     for (; comp_num < ncomp; comp_num++) {
1316 	if (colorant_present(pbitmap, colorants, comp_num)) {
1317 	    if (colorant_present(pbitmap, solid_colorants, comp_num))
1318                 out[comp_num] = solid_color;
1319 	    else {
1320                 out[comp_num] = (factor * ((int)color & bit_mask)) >> 8;
1321 	        color >>= bit_count;
1322 	    }
1323 	}
1324 	else
1325             out[comp_num] = 0;
1326     }
1327     return 0;
1328 }
1329 
1330 
1331 /*
1332  * Unpack a row of 'compressed color' values.  These values are encoded as
1333  * described for the devn_encode_compressed_color routine.
1334  *
1335  * The routine takes a raster line of data and expands each pixel into a buffer
1336  * of 8 bit values for each colorant.
1337  *
1338  * See comments preceding devn_encode_compressed_color for more information
1339  * about the way that we are encoding colorant values in a gx_color_index.
1340  *
1341  * Note: For simplicity of coding the calling routines, this routine will also
1342  * handle 'uncompressed' bit maps.
1343  */
1344 int
1345 devn_unpack_row(gx_device * dev, int num_comp, gs_devn_params * pdevn_params,
1346 					 int width, byte * in, byte * out)
1347 {
1348     int i, comp_num, pixel_num;
1349 
1350     if (pdevn_params->compressed_color_list == NULL) {
1351         int bytes_pp = dev->color_info.depth >> 3;
1352 
1353         /*
1354          * For 'uncompressed' data, the number of bytes per pixel in the input
1355          * raster line is defined by the device depth.  This may be more than
1356          * the number of actual device components.
1357          */
1358         for (pixel_num = 0; pixel_num < width; pixel_num++) {
1359 	    for (i = 0; i < num_comp; i++)
1360 	        *out++ = *in++;
1361 	    in += bytes_pp - num_comp;
1362         }
1363         return 0;
1364     }
1365     else {
1366         int non_encodeable_count = 0;
1367         int factor, bit_count, bit_mask;
1368         comp_bit_map_list_t * pbitmap;
1369         gx_color_index color;
1370         gx_color_value solid_color = gx_max_color_value;
1371 
1372         for (pixel_num = 0; pixel_num < width; pixel_num++) {
1373 	    /*
1374 	     * Get the encoded color value.
1375 	     */
1376 	    color = ((gx_color_index)(*in++)) << (NUM_GX_COLOR_INDEX_BITS - 8);
1377 	    for (i = NUM_GX_COLOR_INDEX_BITS - 16; i >= 0; i -= 8)
1378 	        color |= ((gx_color_index)(*in++)) << i;
1379             /*
1380              * Set all colorants to zero if we get a non encodeable color.
1381              */
1382             if (color == NON_ENCODEABLE_COLOR) {
1383                 for (comp_num = 0; comp_num < num_comp; comp_num++)
1384                     *out++ = 0;
1385 	        non_encodeable_count++;
1386             }
1387 	    else {
1388     	        pbitmap = find_bit_map(color,
1389 			       	pdevn_params->compressed_color_list);
1390 	        bit_count = num_comp_bits[pbitmap->num_non_solid_comp];
1391 	        bit_mask = (1 << bit_count) - 1;
1392 	        factor = comp_bit_factor[pbitmap->num_non_solid_comp];
1393 	        if (pbitmap->solid_not_100) {
1394 		    solid_color = (factor * ((int)color & bit_mask)) >> 8;
1395 		    color >>= bit_count;
1396 	        }
1397                 for (comp_num = 0; comp_num < num_comp; comp_num++) {
1398 		    if (colorant_present(pbitmap, colorants, comp_num)) {
1399 		        if (colorant_present(pbitmap,
1400 					       	solid_colorants, comp_num))
1401        		            *out++ = solid_color >> 8;
1402 		        else {
1403             	            *out++ = (factor * ((int)color & bit_mask)) >> 16;
1404 	    	            color >>= bit_count;
1405 		        }
1406 		    }
1407 		    else
1408             	        *out++ = 0;
1409        	        }
1410             }
1411         }
1412         return non_encodeable_count;
1413     }
1414 }
1415 
1416 
1417 /* ***************** The spotcmyk and devicen devices ***************** */
1418 
1419 /* Define the device parameters. */
1420 #ifndef X_DPI
1421 #  define X_DPI 72
1422 #endif
1423 #ifndef Y_DPI
1424 #  define Y_DPI 72
1425 #endif
1426 
1427 /* The device descriptor */
1428 static dev_proc_open_device(spotcmyk_prn_open);
1429 static dev_proc_get_params(spotcmyk_get_params);
1430 static dev_proc_put_params(spotcmyk_put_params);
1431 static dev_proc_print_page(spotcmyk_print_page);
1432 static dev_proc_get_color_mapping_procs(get_spotcmyk_color_mapping_procs);
1433 static dev_proc_get_color_mapping_procs(get_devicen_color_mapping_procs);
1434 static dev_proc_get_color_comp_index(spotcmyk_get_color_comp_index);
1435 static dev_proc_encode_color(spotcmyk_encode_color);
1436 static dev_proc_decode_color(spotcmyk_decode_color);
1437 
1438 /*
1439  * A structure definition for a DeviceN type device
1440  */
1441 typedef struct spotcmyk_device_s {
1442     gx_device_common;
1443     gx_prn_device_common;
1444     gs_devn_params devn_params;
1445 } spotcmyk_device;
1446 
1447 /* GC procedures */
1448 
1449 static
1450 ENUM_PTRS_WITH(spotcmyk_device_enum_ptrs, spotcmyk_device *pdev)
1451 {
1452     if (index < pdev->devn_params.separations.num_separations)
1453 	ENUM_RETURN(pdev->devn_params.separations.names[index].data);
1454     ENUM_PREFIX(st_device_printer,
1455 		    pdev->devn_params.separations.num_separations);
1456 }
1457 
1458 ENUM_PTRS_END
1459 static RELOC_PTRS_WITH(spotcmyk_device_reloc_ptrs, spotcmyk_device *pdev)
1460 {
1461     RELOC_PREFIX(st_device_printer);
1462     {
1463 	int i;
1464 
1465 	for (i = 0; i < pdev->devn_params.separations.num_separations; ++i) {
1466 	    RELOC_PTR(spotcmyk_device, devn_params.separations.names[i].data);
1467 	}
1468     }
1469 }
1470 RELOC_PTRS_END
1471 
1472 /* Even though spotcmyk_device_finalize is the same as gx_device_finalize, */
1473 /* we need to implement it separately because st_composite_final */
1474 /* declares all 3 procedures as private. */
1475 static void
1476 spotcmyk_device_finalize(void *vpdev)
1477 {
1478     gx_device_finalize(vpdev);
1479 }
1480 
1481 gs_private_st_composite_final(st_spotcmyk_device, spotcmyk_device,
1482     "spotcmyk_device", spotcmyk_device_enum_ptrs, spotcmyk_device_reloc_ptrs,
1483     spotcmyk_device_finalize);
1484 
1485 /*
1486  * Macro definition for DeviceN procedures
1487  */
1488 #define device_procs(get_color_mapping_procs)\
1489 {	spotcmyk_prn_open,\
1490 	gx_default_get_initial_matrix,\
1491 	NULL,				/* sync_output */\
1492 	gdev_prn_output_page,		/* output_page */\
1493 	gdev_prn_close,			/* close */\
1494 	NULL,				/* map_rgb_color - not used */\
1495 	NULL,				/* map_color_rgb - not used */\
1496 	NULL,				/* fill_rectangle */\
1497 	NULL,				/* tile_rectangle */\
1498 	NULL,				/* copy_mono */\
1499 	NULL,				/* copy_color */\
1500 	NULL,				/* draw_line */\
1501 	NULL,				/* get_bits */\
1502 	spotcmyk_get_params,		/* get_params */\
1503 	spotcmyk_put_params,		/* put_params */\
1504 	NULL,				/* map_cmyk_color - not used */\
1505 	NULL,				/* get_xfont_procs */\
1506 	NULL,				/* get_xfont_device */\
1507 	NULL,				/* map_rgb_alpha_color */\
1508 	gx_page_device_get_page_device,	/* get_page_device */\
1509 	NULL,				/* get_alpha_bits */\
1510 	NULL,				/* copy_alpha */\
1511 	NULL,				/* get_band */\
1512 	NULL,				/* copy_rop */\
1513 	NULL,				/* fill_path */\
1514 	NULL,				/* stroke_path */\
1515 	NULL,				/* fill_mask */\
1516 	NULL,				/* fill_trapezoid */\
1517 	NULL,				/* fill_parallelogram */\
1518 	NULL,				/* fill_triangle */\
1519 	NULL,				/* draw_thin_line */\
1520 	NULL,				/* begin_image */\
1521 	NULL,				/* image_data */\
1522 	NULL,				/* end_image */\
1523 	NULL,				/* strip_tile_rectangle */\
1524 	NULL,				/* strip_copy_rop */\
1525 	NULL,				/* get_clipping_box */\
1526 	NULL,				/* begin_typed_image */\
1527 	NULL,				/* get_bits_rectangle */\
1528 	NULL,				/* map_color_rgb_alpha */\
1529 	NULL,				/* create_compositor */\
1530 	NULL,				/* get_hardware_params */\
1531 	NULL,				/* text_begin */\
1532 	NULL,				/* finish_copydevice */\
1533 	NULL,				/* begin_transparency_group */\
1534 	NULL,				/* end_transparency_group */\
1535 	NULL,				/* begin_transparency_mask */\
1536 	NULL,				/* end_transparency_mask */\
1537 	NULL,				/* discard_transparency_layer */\
1538 	get_color_mapping_procs,	/* get_color_mapping_procs */\
1539 	spotcmyk_get_color_comp_index,	/* get_color_comp_index */\
1540 	spotcmyk_encode_color,		/* encode_color */\
1541 	spotcmyk_decode_color,		/* decode_color */\
1542 	NULL,				/* pattern_manage */\
1543 	NULL				/* fill_rectangle_hl_color */\
1544 }
1545 
1546 fixed_colorant_name DeviceCMYKComponents[] = {
1547 	"Cyan",
1548 	"Magenta",
1549 	"Yellow",
1550 	"Black",
1551 	0		/* List terminator */
1552 };
1553 
1554 
1555 #define spotcmyk_device_body(procs, dname, ncomp, pol, depth, mg, mc, cn)\
1556     std_device_full_body_type_extended(spotcmyk_device, &procs, dname,\
1557 	  &st_spotcmyk_device,\
1558 	  (int)((long)(DEFAULT_WIDTH_10THS) * (X_DPI) / 10),\
1559 	  (int)((long)(DEFAULT_HEIGHT_10THS) * (Y_DPI) / 10),\
1560 	  X_DPI, Y_DPI,\
1561     	  GX_DEVICE_COLOR_MAX_COMPONENTS,	/* MaxComponents */\
1562 	  ncomp,		/* NumComp */\
1563 	  pol,			/* Polarity */\
1564 	  depth, 0,		/* Depth, GrayIndex */\
1565 	  mg, mc,		/* MaxGray, MaxColor */\
1566 	  mg + 1, mc + 1,	/* DitherGray, DitherColor */\
1567 	  GX_CINFO_SEP_LIN,	/* Linear & Separable */\
1568 	  cn,			/* Process color model name */\
1569 	  0, 0,			/* offsets */\
1570 	  0, 0, 0, 0		/* margins */\
1571 	),\
1572 	prn_device_body_rest_(spotcmyk_print_page)
1573 
1574 /*
1575  * Example device with CMYK and spot color support
1576  */
1577 static const gx_device_procs spot_cmyk_procs = device_procs(get_spotcmyk_color_mapping_procs);
1578 
1579 const spotcmyk_device gs_spotcmyk_device =
1580 {
1581     spotcmyk_device_body(spot_cmyk_procs, "spotcmyk", 4, GX_CINFO_POLARITY_SUBTRACTIVE, 4, 1, 1, "DeviceCMYK"),
1582     /* DeviceN device specific parameters */
1583     { 1,			/* Bits per color - must match ncomp, depth, etc. above */
1584       DeviceCMYKComponents,	/* Names of color model colorants */
1585       4,			/* Number colorants for CMYK */
1586       0,			/* MaxSeparations has not been specified */
1587       -1,			/* PageSpotColors has not been specified */
1588       {0},			/* SeparationNames */
1589       0,			/* SeparationOrder names */
1590       {0, 1, 2, 3, 4, 5, 6, 7 }	/* Initial component SeparationOrder */
1591     }
1592 };
1593 
1594 /*
1595  * Example DeviceN color device
1596  */
1597 static const gx_device_procs devicen_procs = device_procs(get_devicen_color_mapping_procs);
1598 
1599 const spotcmyk_device gs_devicen_device =
1600 {
1601     spotcmyk_device_body(devicen_procs, "devicen", 4, GX_CINFO_POLARITY_SUBTRACTIVE, 32, 255, 255, "DeviceCMYK"),
1602     /* DeviceN device specific parameters */
1603     { 8,			/* Bits per color - must match ncomp, depth, etc. above */
1604       NULL,			/* No names for standard DeviceN color model */
1605       0,			/* No standard colorants for DeviceN */
1606       0,			/* MaxSeparations has not been specified */
1607       -1,			/* PageSpotColors has not been specified */
1608       {0},			/* SeparationNames */
1609       0,			/* SeparationOrder names */
1610       {0, 1, 2, 3, 4, 5, 6, 7 }	/* Initial component SeparationOrder */
1611     }
1612 };
1613 
1614 /* Open the psd devices */
1615 int
1616 spotcmyk_prn_open(gx_device * pdev)
1617 {
1618     int code = gdev_prn_open(pdev);
1619 
1620     set_linear_color_bits_mask_shift(pdev);
1621     pdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN;
1622     return code;
1623 }
1624 
1625 /* Color mapping routines for the spotcmyk device */
1626 
1627 static void
1628 gray_cs_to_spotcmyk_cm(gx_device * dev, frac gray, frac out[])
1629 {
1630     int * map = ((spotcmyk_device *) dev)->devn_params.separation_order_map;
1631 
1632     gray_cs_to_devn_cm(dev, map, gray, out);
1633 }
1634 
1635 static void
1636 rgb_cs_to_spotcmyk_cm(gx_device * dev, const gs_imager_state *pis,
1637 				   frac r, frac g, frac b, frac out[])
1638 {
1639     int * map = ((spotcmyk_device *) dev)->devn_params.separation_order_map;
1640 
1641     rgb_cs_to_devn_cm(dev, map, pis, r, g, b, out);
1642 }
1643 
1644 static void
1645 cmyk_cs_to_spotcmyk_cm(gx_device * dev, frac c, frac m, frac y, frac k, frac out[])
1646 {
1647     int * map = ((spotcmyk_device *) dev)->devn_params.separation_order_map;
1648 
1649     cmyk_cs_to_devn_cm(dev, map, c, m, y, k, out);
1650 }
1651 
1652 static const gx_cm_color_map_procs spotCMYK_procs = {
1653     gray_cs_to_spotcmyk_cm, rgb_cs_to_spotcmyk_cm, cmyk_cs_to_spotcmyk_cm
1654 };
1655 
1656 static const gx_cm_color_map_procs *
1657 get_spotcmyk_color_mapping_procs(const gx_device * dev)
1658 {
1659     return &spotCMYK_procs;
1660 }
1661 
1662 /* Also use the spotcmyk procs for the devicen device. */
1663 
1664 static const gx_cm_color_map_procs *
1665 get_devicen_color_mapping_procs(const gx_device * dev)
1666 {
1667     return &spotCMYK_procs;
1668 }
1669 
1670 
1671 /*
1672  * Encode a list of colorant values into a gx_color_index_value.
1673  */
1674 static gx_color_index
1675 spotcmyk_encode_color(gx_device *dev, const gx_color_value colors[])
1676 {
1677     int bpc = ((spotcmyk_device *)dev)->devn_params.bitspercomponent;
1678     int drop = sizeof(gx_color_value) * 8 - bpc;
1679     gx_color_index color = 0;
1680     int i = 0;
1681     int ncomp = dev->color_info.num_components;
1682 
1683     for (; i<ncomp; i++) {
1684 	color <<= bpc;
1685         color |= (colors[i] >> drop);
1686     }
1687     return (color == gx_no_color_index ? color ^ 1 : color);
1688 }
1689 
1690 /*
1691  * Decode a gx_color_index value back to a list of colorant values.
1692  */
1693 static int
1694 spotcmyk_decode_color(gx_device * dev, gx_color_index color, gx_color_value * out)
1695 {
1696     int bpc = ((spotcmyk_device *)dev)->devn_params.bitspercomponent;
1697     int drop = sizeof(gx_color_value) * 8 - bpc;
1698     int mask = (1 << bpc) - 1;
1699     int i = 0;
1700     int ncomp = dev->color_info.num_components;
1701 
1702     for (; i<ncomp; i++) {
1703         out[ncomp - i - 1] = (gx_color_value)((color & mask) << drop);
1704 	color >>= bpc;
1705     }
1706     return 0;
1707 }
1708 
1709 /* Get parameters. */
1710 static int
1711 spotcmyk_get_params(gx_device * pdev, gs_param_list * plist)
1712 {
1713     int code = gdev_prn_get_params(pdev, plist);
1714 
1715     if (code < 0)
1716 	return code;
1717     return devn_get_params(pdev, plist,
1718     	&(((spotcmyk_device *)pdev)->devn_params), NULL);
1719 }
1720 
1721 /* Set parameters. */
1722 static int
1723 spotcmyk_put_params(gx_device * pdev, gs_param_list * plist)
1724 {
1725     return devn_printer_put_params(pdev, plist,
1726 	&(((spotcmyk_device *)pdev)->devn_params), NULL);
1727 }
1728 
1729 /*
1730  * This routine will check to see if the color component name  match those
1731  * that are available amoung the current device's color components.
1732  *
1733  * Parameters:
1734  *   dev - pointer to device data structure.
1735  *   pname - pointer to name (zero termination not required)
1736  *   nlength - length of the name
1737  *
1738  * This routine returns a positive value (0 to n) which is the device colorant
1739  * number if the name is found.  It returns GX_DEVICE_COLOR_MAX_COMPONENTS if
1740  * the colorant is not being used due to a SeparationOrder device parameter.
1741  * It returns a negative value if not found.
1742  */
1743 static int
1744 spotcmyk_get_color_comp_index(gx_device * dev, const char * pname,
1745 					int name_size, int component_type)
1746 {
1747     return devn_get_color_comp_index(dev,
1748 		&(((spotcmyk_device *)dev)->devn_params), NULL,
1749 		pname, name_size, component_type, ENABLE_AUTO_SPOT_COLORS);
1750 }
1751 
1752 
1753 /*
1754  * This routine will extract a specified set of bits from a buffer and pack
1755  * them into a given buffer.
1756  *
1757  * Parameters:
1758  *   source - The source of the data
1759  *   dest - The destination for the data
1760  *   depth - The size of the bits per pixel - must be a multiple of 8
1761  *   first_bit - The location of the first data bit (LSB).
1762  *   bit_width - The number of bits to be extracted.
1763  *   npixel - The number of pixels.
1764  *
1765  * Returns:
1766  *   Length of the output line (in bytes)
1767  *   Data in dest.
1768  */
1769 int
1770 repack_data(byte * source, byte * dest, int depth, int first_bit,
1771 		int bit_width, int npixel)
1772 {
1773     int in_nbyte = depth >> 3;		/* Number of bytes per input pixel */
1774     int out_nbyte = bit_width >> 3;	/* Number of bytes per output pixel */
1775     gx_color_index mask = 1;
1776     gx_color_index data;
1777     int i, j, length = 0;
1778     byte temp;
1779     byte * out = dest;
1780     int in_bit_start = 8 - depth;
1781     int out_bit_start = 8 - bit_width;
1782     int in_byte_loc = in_bit_start, out_byte_loc = out_bit_start;
1783 
1784     mask = (mask << bit_width) - 1;
1785     for (i=0; i<npixel; i++) {
1786         /* Get the pixel data */
1787 	if (!in_nbyte) {		/* Multiple pixels per byte */
1788 	    data = *source;
1789 	    data >>= in_byte_loc;
1790 	    in_byte_loc -= depth;
1791 	    if (in_byte_loc < 0) {	/* If finished with byte */
1792 	        in_byte_loc = in_bit_start;
1793 		source++;
1794 	    }
1795 	}
1796 	else {				/* One or more bytes per pixel */
1797 	    data = *source++;
1798 	    for (j=1; j<in_nbyte; j++)
1799 	        data = (data << 8) + *source++;
1800 	}
1801 	data >>= first_bit;
1802 	data &= mask;
1803 
1804 	/* Put the output data */
1805 	if (!out_nbyte) {		/* Multiple pixels per byte */
1806 	    temp = (byte)(*out & ~(mask << out_byte_loc));
1807 	    *out = (byte)(temp | (data << out_byte_loc));
1808 	    out_byte_loc -= bit_width;
1809 	    if (out_byte_loc < 0) {	/* If finished with byte */
1810 	        out_byte_loc = out_bit_start;
1811 		out++;
1812 	    }
1813 	}
1814 	else {				/* One or more bytes per pixel */
1815 	    *out++ = (byte)(data >> ((out_nbyte - 1) * 8));
1816 	    for (j=1; j<out_nbyte; j++) {
1817 	        *out++ = (byte)(data >> ((out_nbyte - 1 - j) * 8));
1818 	    }
1819 	}
1820     }
1821     /* Return the number of bytes in the destination buffer. */
1822     if (out_byte_loc != out_bit_start) { 	/* If partially filled last byte */
1823 	*out = *out & ((~0) << out_byte_loc);	/* Mask unused part of last byte */
1824 	out++;
1825     }
1826     length = out - dest;
1827     return length;
1828 }
1829 
1830 static int devn_write_pcx_file(gx_device_printer * pdev, char * filename, int ncomp,
1831 			    int bpc, int pcmlinelength);
1832 /*
1833  * This is an example print page routine for a DeviceN device.  This routine
1834  * will handle a DeviceN, a CMYK with spot colors, or an RGB process color model.
1835  *
1836  * This routine creates several output files.  If the process color model is
1837  * RGB or CMYK then a bit image file is created which contains the data for the
1838  * process color model data.  This data is put into the given file stream.
1839  * I.e. into the output file specified by the user.  This file is not created
1840  * for the DeviceN process color model.  A separate bit image file is created
1841  * is created for the data for each of the given spot colors.  The names for
1842  * these files are created by taking the given output file name and appending
1843  * "sn" (where n is the spot color number 0 to ...) to the output file name.
1844  * The results are unknown if the output file is stdout etc.
1845  *
1846  * After the bit image files are created, then a set of PCX format files are
1847  * created from the bit image files.  This files have a ".pcx" appended to the
1848  * end of the files.  Thus a CMYK process color model with two spot colors
1849  * would end up with a total of six files being created.  (xxx, xxxs0, xxxs1,
1850  * xxx.pcx, xxxs0.pcx, and xxxs1.pcx).
1851  *
1852  * I do not assume that any users will actually want to create all of these
1853  * different files.  However I wanted to show an example of how each of the
1854  * spot * colorants could be unpacked from the process color model colorants.
1855  * The bit images files are an easy way to show this without the complication
1856  * of trying to put the data into a specific format.  However I do not have a
1857  * tool which will display the bit image data directly so I needed to convert
1858  * it to a form which I can view.  Thus the PCX format files are being created.
1859  * Note:  The PCX implementation is not complete.  There are many (most)
1860  * combinations of bits per pixel and number of colorants that are not supported.
1861  */
1862 static int
1863 spotcmyk_print_page(gx_device_printer * pdev, FILE * prn_stream)
1864 {
1865     int line_size = gdev_mem_bytes_per_scan_line((gx_device *) pdev);
1866     byte *in = gs_alloc_bytes(pdev->memory, line_size, "spotcmyk_print_page(in)");
1867     byte *buf = gs_alloc_bytes(pdev->memory, line_size + 3, "spotcmyk_print_page(buf)");
1868     const spotcmyk_device * pdevn = (spotcmyk_device *) pdev;
1869     int npcmcolors = pdevn->devn_params.num_std_colorant_names;
1870     int ncomp = pdevn->color_info.num_components;
1871     int depth = pdevn->color_info.depth;
1872     int nspot = pdevn->devn_params.separations.num_separations;
1873     int bpc = pdevn->devn_params.bitspercomponent;
1874     int lnum = 0, bottom = pdev->height;
1875     int width = pdev->width;
1876     FILE * spot_file[GX_DEVICE_COLOR_MAX_COMPONENTS] = {0};
1877     int i, code = 0;
1878     int first_bit;
1879     int pcmlinelength = 0; /* Initialize against indeterminizm in case of pdev->height == 0. */
1880     int linelength[GX_DEVICE_COLOR_MAX_COMPONENTS];
1881     byte *data;
1882     char spotname[gp_file_name_sizeof];
1883 
1884     if (in == NULL || buf == NULL) {
1885 	code = gs_error_VMerror;
1886 	goto prn_done;
1887     }
1888     /*
1889      * Check if the SeparationOrder list has changed the order of the process
1890      * color model colorants. If so then we will treat all colorants as if they
1891      * are spot colors.
1892      */
1893     for (i = 0; i < npcmcolors; i++)
1894 	if (pdevn->devn_params.separation_order_map[i] != i)
1895 	    break;
1896     if (i < npcmcolors || ncomp < npcmcolors) {
1897 	nspot = ncomp;
1898 	npcmcolors = 0;
1899     }
1900 
1901     /* Open the output files for the spot colors */
1902     for(i = 0; i < nspot; i++) {
1903 	sprintf(spotname, "%ss%d", pdevn->fname, i);
1904         spot_file[i] = fopen(spotname, "wb");
1905 	if (spot_file[i] == NULL) {
1906 	    code = gs_error_VMerror;
1907 	    goto prn_done;
1908 	}
1909     }
1910 
1911 
1912     /* Now create the output bit image files */
1913     for (; lnum < bottom; ++lnum) {
1914 	gdev_prn_get_bits(pdev, lnum, in, &data);
1915         /* Now put the pcm data into the output file */
1916 	if (npcmcolors) {
1917 	    first_bit = bpc * (ncomp - npcmcolors);
1918 	    pcmlinelength = repack_data(data, buf, depth, first_bit, bpc * npcmcolors, width);
1919 	    fwrite(buf, 1, pcmlinelength, prn_stream);
1920 	}
1921 	/* Put spot color data into the output files */
1922         for (i = 0; i < nspot; i++) {
1923 	    first_bit = bpc * (nspot - 1 - i);
1924 	    linelength[i] = repack_data(data, buf, depth, first_bit, bpc, width);
1925 	    fwrite(buf, 1, linelength[i], spot_file[i]);
1926         }
1927     }
1928 
1929     /* Close the bit image files */
1930     for(i = 0; i < nspot; i++) {
1931         fclose(spot_file[i]);
1932 	spot_file[i] = NULL;
1933     }
1934 
1935     /* Now convert the bit image files into PCX files */
1936     if (npcmcolors) {
1937 	code = devn_write_pcx_file(pdev, (char *) &pdevn->fname,
1938 				npcmcolors, bpc, pcmlinelength);
1939 	if (code < 0)
1940 	    return code;
1941     }
1942     for(i = 0; i < nspot; i++) {
1943 	sprintf(spotname, "%ss%d", pdevn->fname, i);
1944 	code = devn_write_pcx_file(pdev, spotname, 1, bpc, linelength[i]);
1945 	if (code < 0)
1946 	    return code;
1947     }
1948 
1949 
1950     /* Clean up and exit */
1951   prn_done:
1952     for(i = 0; i < nspot; i++) {
1953 	if (spot_file[i] != NULL)
1954             fclose(spot_file[i]);
1955     }
1956     if (in != NULL)
1957         gs_free_object(pdev->memory, in, "spotcmyk_print_page(in)");
1958     if (buf != NULL)
1959         gs_free_object(pdev->memory, buf, "spotcmyk_print_page(buf)");
1960     return code;
1961 }
1962 
1963 /*
1964  * We are using the PCX output format.  This is done for simplicity.
1965  * Much of the following code was copied from gdevpcx.c.
1966  */
1967 
1968 /* ------ Private definitions ------ */
1969 
1970 /* All two-byte quantities are stored LSB-first! */
1971 #if arch_is_big_endian
1972 #  define assign_ushort(a,v) a = ((v) >> 8) + ((v) << 8)
1973 #else
1974 #  define assign_ushort(a,v) a = (v)
1975 #endif
1976 
1977 typedef struct pcx_header_s {
1978     byte manuf;			/* always 0x0a */
1979     byte version;
1980 #define version_2_5			0
1981 #define version_2_8_with_palette	2
1982 #define version_2_8_without_palette	3
1983 #define version_3_0 /* with palette */	5
1984     byte encoding;		/* 1=RLE */
1985     byte bpp;			/* bits per pixel per plane */
1986     ushort x1;			/* X of upper left corner */
1987     ushort y1;			/* Y of upper left corner */
1988     ushort x2;			/* x1 + width - 1 */
1989     ushort y2;			/* y1 + height - 1 */
1990     ushort hres;		/* horz. resolution (dots per inch) */
1991     ushort vres;		/* vert. resolution (dots per inch) */
1992     byte palette[16 * 3];	/* color palette */
1993     byte reserved;
1994     byte nplanes;		/* number of color planes */
1995     ushort bpl;			/* number of bytes per line (uncompressed) */
1996     ushort palinfo;
1997 #define palinfo_color	1
1998 #define palinfo_gray	2
1999     byte xtra[58];		/* fill out header to 128 bytes */
2000 } pcx_header;
2001 
2002 /* Define the prototype header. */
2003 static const pcx_header pcx_header_prototype =
2004 {
2005     10,				/* manuf */
2006     0,				/* version (variable) */
2007     1,				/* encoding */
2008     0,				/* bpp (variable) */
2009     00, 00,			/* x1, y1 */
2010     00, 00,			/* x2, y2 (variable) */
2011     00, 00,			/* hres, vres (variable) */
2012     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* palette (variable) */
2013      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2014      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2015      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
2016     0,				/* reserved */
2017     0,				/* nplanes (variable) */
2018     00,				/* bpl (variable) */
2019     00,				/* palinfo (variable) */
2020     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* xtra */
2021      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2022      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2023      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
2024 };
2025 
2026 
2027 /* Forward declarations */
2028 static void devn_pcx_write_rle(const byte *, const byte *, int, FILE *);
2029 static int devn_pcx_write_page(gx_device_printer * pdev, FILE * infile,
2030     int linesize, FILE * outfile, pcx_header * phdr, bool planar, int depth);
2031 
2032 static const byte pcx_cmyk_palette[16 * 3] =
2033 {
2034     0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0f, 0x0f, 0x00,
2035     0xff, 0x00, 0xff, 0x0f, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x0f, 0x00, 0x00,
2036     0x00, 0xff, 0xff, 0x00, 0x0f, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x00,
2037     0x00, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x1f, 0x1f, 0x1f, 0x0f, 0x0f, 0x0f,
2038 };
2039 
2040 static const byte pcx_ega_palette[16 * 3] =
2041 {
2042     0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0x00, 0xaa, 0xaa,
2043     0xaa, 0x00, 0x00, 0xaa, 0x00, 0xaa, 0xaa, 0xaa, 0x00, 0xaa, 0xaa, 0xaa,
2044     0x55, 0x55, 0x55, 0x55, 0x55, 0xff, 0x55, 0xff, 0x55, 0x55, 0xff, 0xff,
2045     0xff, 0x55, 0x55, 0xff, 0x55, 0xff, 0xff, 0xff, 0x55, 0xff, 0xff, 0xff
2046 };
2047 
2048 
2049 /*
2050  * This routine will set up the revision and palatte for the output
2051  * file.
2052  *
2053  * Please note that this routine does not currently handle all possible
2054  * combinations of bits and planes.
2055  *
2056  * Input parameters:
2057  *   pdev - Pointer to device data structure
2058  *   file - output file
2059  *   header - The header structure to hold the data.
2060  *   bits_per_plane - The number of bits per plane.
2061  *   num_planes - The number of planes.
2062  */
2063 static bool
2064 devn_setup_pcx_header(gx_device_printer * pdev, pcx_header * phdr, int num_planes, int bits_per_plane)
2065 {
2066     bool planar = true; /* Invalid cases could cause an indeterminizm. */
2067 
2068     *phdr = pcx_header_prototype;
2069     phdr->bpp = bits_per_plane;
2070     phdr->nplanes = num_planes;
2071 
2072     switch (num_planes) {
2073         case 1:
2074 	    switch (bits_per_plane) {
2075 	        case 1:
2076     			phdr->version = version_2_8_with_palette;
2077     			assign_ushort(phdr->palinfo, palinfo_gray);
2078     			memcpy((byte *) phdr->palette, "\000\000\000\377\377\377", 6);
2079 			planar = false;
2080 			break;
2081 		case 2:				/* Not defined */
2082 			break;
2083 		case 4:
2084     			phdr->version = version_2_8_with_palette;
2085     			memcpy((byte *) phdr->palette, pcx_ega_palette, sizeof(pcx_ega_palette));
2086 			planar = true;
2087 			break;
2088 		case 5:				/* Not defined */
2089 			break;
2090 		case 8:
2091     			phdr->version = version_3_0;
2092     			assign_ushort(phdr->palinfo, palinfo_gray);
2093 			planar = false;
2094 			break;
2095 		case 16:			/* Not defined */
2096 			break;
2097 	    }
2098 	    break;
2099 	case 2:
2100 	    switch (bits_per_plane) {
2101 	        case 1:				/* Not defined */
2102 			break;
2103 		case 2:				/* Not defined */
2104 			break;
2105 		case 4:				/* Not defined */
2106 			break;
2107 		case 5:				/* Not defined */
2108 			break;
2109 		case 8:				/* Not defined */
2110 			break;
2111 		case 16:			/* Not defined */
2112 			break;
2113 	    }
2114 	    break;
2115 	case 3:
2116 	    switch (bits_per_plane) {
2117 	        case 1:				/* Not defined */
2118 			break;
2119 		case 2:				/* Not defined */
2120 			break;
2121 		case 4:				/* Not defined */
2122 			break;
2123 		case 5:				/* Not defined */
2124 			break;
2125 		case 8:
2126     			phdr->version = version_3_0;
2127     			assign_ushort(phdr->palinfo, palinfo_color);
2128 			planar = true;
2129 			break;
2130 		case 16:			/* Not defined */
2131 			break;
2132 	    }
2133 	    break;
2134 	case 4:
2135 	    switch (bits_per_plane) {
2136 	        case 1:
2137     			phdr->version = 2;
2138     			memcpy((byte *) phdr->palette, pcx_cmyk_palette,
2139 	   			sizeof(pcx_cmyk_palette));
2140 			planar = false;
2141 			phdr->bpp = 4;
2142 			phdr->nplanes = 1;
2143 			break;
2144 		case 2:				/* Not defined */
2145 			break;
2146 		case 4:				/* Not defined */
2147 			break;
2148 		case 5:				/* Not defined */
2149 			break;
2150 		case 8:				/* Not defined */
2151 			break;
2152 		case 16:			/* Not defined */
2153 			break;
2154 	    }
2155 	    break;
2156     }
2157     return planar;
2158 }
2159 
2160 /* Write a palette on a file. */
2161 static int
2162 pc_write_mono_palette(gx_device * dev, uint max_index, FILE * file)
2163 {
2164     uint i, c;
2165     gx_color_value rgb[3];
2166 
2167     for (i = 0; i < max_index; i++) {
2168 	rgb[0] = rgb[1] = rgb[2] = i << 8;
2169 	for (c = 0; c < 3; c++) {
2170 	    byte b = gx_color_value_to_byte(rgb[c]);
2171 
2172 	    fputc(b, file);
2173 	}
2174     }
2175     return 0;
2176 }
2177 /*
2178  * This routine will send any output data required at the end of a file
2179  * for a particular combination of planes and bits per plane.
2180  *
2181  * Please note that most combinations do not require anything at the end
2182  * of a data file.
2183  *
2184  * Input parameters:
2185  *   pdev - Pointer to device data structure
2186  *   file - output file
2187  *   header - The header structure to hold the data.
2188  *   bits_per_plane - The number of bits per plane.
2189  *   num_planes - The number of planes.
2190  */
2191 static int
2192 devn_finish_pcx_file(gx_device_printer * pdev, FILE * file, pcx_header * header, int num_planes, int bits_per_plane)
2193 {
2194     switch (num_planes) {
2195         case 1:
2196 	    switch (bits_per_plane) {
2197 	        case 1:				/* Do nothing */
2198 			break;
2199 		case 2:				/* Not defined */
2200 			break;
2201 		case 4:				/* Do nothing */
2202 			break;
2203 		case 5:				/* Not defined */
2204 			break;
2205 		case 8:
2206 			fputc(0x0c, file);
2207 			return pc_write_mono_palette((gx_device *) pdev, 256, file);
2208 		case 16:			/* Not defined */
2209 			break;
2210 	    }
2211 	    break;
2212 	case 2:
2213 	    switch (bits_per_plane) {
2214 	        case 1:				/* Not defined */
2215 			break;
2216 		case 2:				/* Not defined */
2217 			break;
2218 		case 4:				/* Not defined */
2219 			break;
2220 		case 5:				/* Not defined */
2221 			break;
2222 		case 8:				/* Not defined */
2223 			break;
2224 		case 16:			/* Not defined */
2225 			break;
2226 	    }
2227 	    break;
2228 	case 3:
2229 	    switch (bits_per_plane) {
2230 	        case 1:				/* Not defined */
2231 			break;
2232 		case 2:				/* Not defined */
2233 			break;
2234 		case 4:				/* Not defined */
2235 			break;
2236 		case 5:				/* Not defined */
2237 			break;
2238 		case 8:				/* Do nothing */
2239 			break;
2240 		case 16:			/* Not defined */
2241 			break;
2242 	    }
2243 	    break;
2244 	case 4:
2245 	    switch (bits_per_plane) {
2246 	        case 1:				/* Do nothing */
2247 			break;
2248 		case 2:				/* Not defined */
2249 			break;
2250 		case 4:				/* Not defined */
2251 			break;
2252 		case 5:				/* Not defined */
2253 			break;
2254 		case 8:				/* Not defined */
2255 			break;
2256 		case 16:			/* Not defined */
2257 			break;
2258 	    }
2259 	    break;
2260     }
2261     return 0;
2262 }
2263 
2264 /* Send the page to the printer. */
2265 static int
2266 devn_write_pcx_file(gx_device_printer * pdev, char * filename, int ncomp,
2267 			    int bpc, int linesize)
2268 {
2269     pcx_header header;
2270     int code;
2271     bool planar;
2272     char outname[gp_file_name_sizeof];
2273     FILE * in;
2274     FILE * out;
2275     int depth = bpc_to_depth(ncomp, bpc);
2276 
2277     in = fopen(filename, "rb");
2278     if (!in)
2279 	return_error(gs_error_invalidfileaccess);
2280     sprintf(outname, "%s.pcx", filename);
2281     out = fopen(outname, "wb");
2282     if (!out) {
2283 	fclose(in);
2284 	return_error(gs_error_invalidfileaccess);
2285     }
2286 
2287     planar = devn_setup_pcx_header(pdev, &header, ncomp, bpc);
2288     code = devn_pcx_write_page(pdev, in, linesize, out, &header, planar, depth);
2289     if (code >= 0)
2290         code = devn_finish_pcx_file(pdev, out, &header, ncomp, bpc);
2291 
2292     fclose(in);
2293     fclose(out);
2294     return code;
2295 }
2296 
2297 /* Write out a page in PCX format. */
2298 /* This routine is used for all formats. */
2299 /* The caller has set header->bpp, nplanes, and palette. */
2300 static int
2301 devn_pcx_write_page(gx_device_printer * pdev, FILE * infile, int linesize, FILE * outfile,
2302 	       pcx_header * phdr, bool planar, int depth)
2303 {
2304     int raster = linesize;
2305     uint rsize = ROUND_UP((pdev->width * phdr->bpp + 7) >> 3, 2);	/* PCX format requires even */
2306     int height = pdev->height;
2307     uint lsize = raster + rsize;
2308     byte *line = gs_alloc_bytes(pdev->memory, lsize, "pcx file buffer");
2309     byte *plane = line + raster;
2310     int y;
2311     int code = 0;		/* return code */
2312 
2313     if (line == 0)		/* can't allocate line buffer */
2314 	return_error(gs_error_VMerror);
2315 
2316     /* Fill in the other variable entries in the header struct. */
2317 
2318     assign_ushort(phdr->x2, pdev->width - 1);
2319     assign_ushort(phdr->y2, height - 1);
2320     assign_ushort(phdr->hres, (int)pdev->x_pixels_per_inch);
2321     assign_ushort(phdr->vres, (int)pdev->y_pixels_per_inch);
2322     assign_ushort(phdr->bpl, (planar || depth == 1 ? rsize :
2323 			      raster + (raster & 1)));
2324 
2325     /* Write the header. */
2326 
2327     if (fwrite((const char *)phdr, 1, 128, outfile) < 128) {
2328 	code = gs_error_ioerror;
2329 	goto pcx_done;
2330     }
2331     /* Write the contents of the image. */
2332     for (y = 0; y < height; y++) {
2333 	byte *row = line;
2334 	byte *end;
2335 
2336 	code = fread(line, sizeof(byte), linesize, infile);
2337 	if (code < 0)
2338 	    break;
2339 	end = row + raster;
2340 	if (!planar) {		/* Just write the bits. */
2341 	    if (raster & 1) {	/* Round to even, with predictable padding. */
2342 		*end = end[-1];
2343 		++end;
2344 	    }
2345 	    devn_pcx_write_rle(row, end, 1, outfile);
2346 	} else
2347 	    switch (depth) {
2348 
2349 		case 4:
2350 		    {
2351 			byte *pend = plane + rsize;
2352 			int shift;
2353 
2354 			for (shift = 0; shift < 4; shift++) {
2355 			    register byte *from, *to;
2356 			    register int bright = 1 << shift;
2357 			    register int bleft = bright << 4;
2358 
2359 			    for (from = row, to = plane;
2360 				 from < end; from += 4
2361 				) {
2362 				*to++ =
2363 				    (from[0] & bleft ? 0x80 : 0) |
2364 				    (from[0] & bright ? 0x40 : 0) |
2365 				    (from[1] & bleft ? 0x20 : 0) |
2366 				    (from[1] & bright ? 0x10 : 0) |
2367 				    (from[2] & bleft ? 0x08 : 0) |
2368 				    (from[2] & bright ? 0x04 : 0) |
2369 				    (from[3] & bleft ? 0x02 : 0) |
2370 				    (from[3] & bright ? 0x01 : 0);
2371 			    }
2372 			    /* We might be one byte short of rsize. */
2373 			    if (to < pend)
2374 				*to = to[-1];
2375 			    devn_pcx_write_rle(plane, pend, 1, outfile);
2376 			}
2377 		    }
2378 		    break;
2379 
2380 		case 24:
2381 		    {
2382 			int pnum;
2383 
2384 			for (pnum = 0; pnum < 3; ++pnum) {
2385 			    devn_pcx_write_rle(row + pnum, row + raster, 3, outfile);
2386 			    if (pdev->width & 1)
2387 				fputc(0, outfile);		/* pad to even */
2388 			}
2389 		    }
2390 		    break;
2391 
2392 		default:
2393 		    code = gs_note_error(gs_error_rangecheck);
2394 		    goto pcx_done;
2395 
2396 	    }
2397 	code = 0;
2398     }
2399 
2400   pcx_done:
2401     gs_free_object(pdev->memory, line, "pcx file buffer");
2402 
2403     return code;
2404 }
2405 
2406 /* ------ Internal routines ------ */
2407 
2408 /* Write one line in PCX run-length-encoded format. */
2409 static void
2410 devn_pcx_write_rle(const byte * from, const byte * end, int step, FILE * file)
2411 {  /*
2412     * The PCX format theoretically allows encoding runs of 63
2413     * identical bytes, but some readers can't handle repetition
2414     * counts greater than 15.
2415     */
2416 #define MAX_RUN_COUNT 15
2417     int max_run = step * MAX_RUN_COUNT;
2418 
2419     while (from < end) {
2420 	byte data = *from;
2421 
2422 	from += step;
2423 	if (data != *from || from == end) {
2424 	    if (data >= 0xc0)
2425 		putc(0xc1, file);
2426 	} else {
2427 	    const byte *start = from;
2428 
2429 	    while ((from < end) && (*from == data))
2430 		from += step;
2431 	    /* Now (from - start) / step + 1 is the run length. */
2432 	    while (from - start >= max_run) {
2433 		putc(0xc0 + MAX_RUN_COUNT, file);
2434 		putc(data, file);
2435 		start += max_run;
2436 	    }
2437 	    if (from > start || data >= 0xc0)
2438 		putc((from - start) / step + 0xc1, file);
2439 	}
2440 	putc(data, file);
2441     }
2442 #undef MAX_RUN_COUNT
2443 }
2444