xref: /plan9/sys/src/cmd/gs/src/gdevbit.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
17dd7cddfSDavid du Colombier /* Copyright (C) 1991, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises.  All rights reserved.
27dd7cddfSDavid du Colombier 
3*593dc095SDavid du Colombier   This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier   implied.
57dd7cddfSDavid du Colombier 
6*593dc095SDavid du Colombier   This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier   modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier   of the license contained in the file LICENSE in this distribution.
97dd7cddfSDavid du Colombier 
10*593dc095SDavid du Colombier   For more information about licensing, please refer to
11*593dc095SDavid du Colombier   http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier   commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier 
17*593dc095SDavid du Colombier /* $Id: gdevbit.c,v 1.10 2004/06/23 18:57:15 stefan Exp $ */
187dd7cddfSDavid du Colombier /* "Plain bits" devices to measure rendering time. */
197dd7cddfSDavid du Colombier #include "math_.h"
207dd7cddfSDavid du Colombier #include "gdevprn.h"
217dd7cddfSDavid du Colombier #include "gsparam.h"
227dd7cddfSDavid du Colombier #include "gscrd.h"
237dd7cddfSDavid du Colombier #include "gscrdp.h"
247dd7cddfSDavid du Colombier #include "gxlum.h"
257dd7cddfSDavid du Colombier #include "gdevdcrd.h"
267dd7cddfSDavid du Colombier 
277dd7cddfSDavid du Colombier /* Define the device parameters. */
287dd7cddfSDavid du Colombier #ifndef X_DPI
297dd7cddfSDavid du Colombier #  define X_DPI 72
307dd7cddfSDavid du Colombier #endif
317dd7cddfSDavid du Colombier #ifndef Y_DPI
327dd7cddfSDavid du Colombier #  define Y_DPI 72
337dd7cddfSDavid du Colombier #endif
347dd7cddfSDavid du Colombier 
357dd7cddfSDavid du Colombier /* The device descriptor */
36*593dc095SDavid du Colombier private dev_proc_map_rgb_color(bit_mono_map_color);
377dd7cddfSDavid du Colombier private dev_proc_map_color_rgb(bit_map_color_rgb);
387dd7cddfSDavid du Colombier private dev_proc_map_cmyk_color(bit_map_cmyk_color);
397dd7cddfSDavid du Colombier private dev_proc_get_params(bit_get_params);
407dd7cddfSDavid du Colombier private dev_proc_put_params(bit_put_params);
417dd7cddfSDavid du Colombier private dev_proc_print_page(bit_print_page);
427dd7cddfSDavid du Colombier 
43*593dc095SDavid du Colombier #define bit_procs(encode_color)\
447dd7cddfSDavid du Colombier {	gdev_prn_open,\
457dd7cddfSDavid du Colombier 	gx_default_get_initial_matrix,\
467dd7cddfSDavid du Colombier 	NULL,	/* sync_output */\
477dd7cddfSDavid du Colombier 	gdev_prn_output_page,\
487dd7cddfSDavid du Colombier 	gdev_prn_close,\
49*593dc095SDavid du Colombier 	encode_color,	/* map_rgb_color */\
50*593dc095SDavid du Colombier 	bit_map_color_rgb,	/* map_color_rgb */\
517dd7cddfSDavid du Colombier 	NULL,	/* fill_rectangle */\
527dd7cddfSDavid du Colombier 	NULL,	/* tile_rectangle */\
537dd7cddfSDavid du Colombier 	NULL,	/* copy_mono */\
547dd7cddfSDavid du Colombier 	NULL,	/* copy_color */\
557dd7cddfSDavid du Colombier 	NULL,	/* draw_line */\
567dd7cddfSDavid du Colombier 	NULL,	/* get_bits */\
577dd7cddfSDavid du Colombier 	bit_get_params,\
587dd7cddfSDavid du Colombier 	bit_put_params,\
59*593dc095SDavid du Colombier 	encode_color,	/* map_cmyk_color */\
607dd7cddfSDavid du Colombier 	NULL,	/* get_xfont_procs */\
617dd7cddfSDavid du Colombier 	NULL,	/* get_xfont_device */\
627dd7cddfSDavid du Colombier 	NULL,	/* map_rgb_alpha_color */\
63*593dc095SDavid du Colombier 	gx_page_device_get_page_device,	/* get_page_device */\
64*593dc095SDavid du Colombier 	NULL,	/* get_alpha_bits */\
65*593dc095SDavid du Colombier 	NULL,	/* copy_alpha */\
66*593dc095SDavid du Colombier 	NULL,	/* get_band */\
67*593dc095SDavid du Colombier 	NULL,	/* copy_rop */\
68*593dc095SDavid du Colombier 	NULL,	/* fill_path */\
69*593dc095SDavid du Colombier 	NULL,	/* stroke_path */\
70*593dc095SDavid du Colombier 	NULL,	/* fill_mask */\
71*593dc095SDavid du Colombier 	NULL,	/* fill_trapezoid */\
72*593dc095SDavid du Colombier 	NULL,	/* fill_parallelogram */\
73*593dc095SDavid du Colombier 	NULL,	/* fill_triangle */\
74*593dc095SDavid du Colombier 	NULL,	/* draw_thin_line */\
75*593dc095SDavid du Colombier 	NULL,	/* begin_image */\
76*593dc095SDavid du Colombier 	NULL,	/* image_data */\
77*593dc095SDavid du Colombier 	NULL,	/* end_image */\
78*593dc095SDavid du Colombier 	NULL,	/* strip_tile_rectangle */\
79*593dc095SDavid du Colombier 	NULL,	/* strip_copy_rop */\
80*593dc095SDavid du Colombier 	NULL,	/* get_clipping_box */\
81*593dc095SDavid du Colombier 	NULL,	/* begin_typed_image */\
82*593dc095SDavid du Colombier 	NULL,	/* get_bits_rectangle */\
83*593dc095SDavid du Colombier 	NULL,	/* map_color_rgb_alpha */\
84*593dc095SDavid du Colombier 	NULL,	/* create_compositor */\
85*593dc095SDavid du Colombier 	NULL,	/* get_hardware_params */\
86*593dc095SDavid du Colombier 	NULL,	/* text_begin */\
87*593dc095SDavid du Colombier 	NULL,	/* finish_copydevice */\
88*593dc095SDavid du Colombier 	NULL,	/* begin_transparency_group */\
89*593dc095SDavid du Colombier 	NULL,	/* end_transparency_group */\
90*593dc095SDavid du Colombier 	NULL,	/* begin_transparency_mask */\
91*593dc095SDavid du Colombier 	NULL,	/* end_transparency_mask */\
92*593dc095SDavid du Colombier 	NULL,	/* discard_transparency_layer */\
93*593dc095SDavid du Colombier 	NULL,	/* get_color_mapping_procs */\
94*593dc095SDavid du Colombier 	NULL,	/* get_color_comp_index */\
95*593dc095SDavid du Colombier 	encode_color,		/* encode_color */\
96*593dc095SDavid du Colombier 	bit_map_color_rgb	/* decode_color */\
977dd7cddfSDavid du Colombier }
987dd7cddfSDavid du Colombier 
997dd7cddfSDavid du Colombier /*
1007dd7cddfSDavid du Colombier  * The following macro is used in get_params and put_params to determine the
1017dd7cddfSDavid du Colombier  * num_components for the current device. It works using the device name
1027dd7cddfSDavid du Colombier  * character after "bit" which is either '\0', 'r', or 'c'. Any new devices
1037dd7cddfSDavid du Colombier  * that are added to this module must modify this macro to return the
1047dd7cddfSDavid du Colombier  * correct num_components. This is needed to support the ForceMono
1057dd7cddfSDavid du Colombier  * parameter, which alters dev->num_components.
1067dd7cddfSDavid du Colombier  */
1077dd7cddfSDavid du Colombier #define REAL_NUM_COMPONENTS(dev) (dev->dname[3] == 'c' ? 4 : \
1087dd7cddfSDavid du Colombier 				  dev->dname[3] == 'r' ? 3 : 1)
1097dd7cddfSDavid du Colombier 
1107dd7cddfSDavid du Colombier private const gx_device_procs bitmono_procs =
111*593dc095SDavid du Colombier bit_procs(bit_mono_map_color);
1127dd7cddfSDavid du Colombier const gx_device_printer gs_bit_device =
1137dd7cddfSDavid du Colombier {prn_device_body(gx_device_printer, bitmono_procs, "bit",
1147dd7cddfSDavid du Colombier 		 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
1157dd7cddfSDavid du Colombier 		 X_DPI, Y_DPI,
1167dd7cddfSDavid du Colombier 		 0, 0, 0, 0,    /* margins */
1177dd7cddfSDavid du Colombier 		 1, 1, 1, 0, 2, 1, bit_print_page)
1187dd7cddfSDavid du Colombier };
1197dd7cddfSDavid du Colombier 
1207dd7cddfSDavid du Colombier private const gx_device_procs bitrgb_procs =
121*593dc095SDavid du Colombier bit_procs(gx_default_rgb_map_rgb_color);
1227dd7cddfSDavid du Colombier const gx_device_printer gs_bitrgb_device =
1237dd7cddfSDavid du Colombier {prn_device_body(gx_device_printer, bitrgb_procs, "bitrgb",
1247dd7cddfSDavid du Colombier 		 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
1257dd7cddfSDavid du Colombier 		 X_DPI, Y_DPI,
1267dd7cddfSDavid du Colombier 		 0, 0, 0, 0,	/* margins */
1277dd7cddfSDavid du Colombier 		 3, 4, 1, 1, 2, 2, bit_print_page)
1287dd7cddfSDavid du Colombier };
1297dd7cddfSDavid du Colombier 
1307dd7cddfSDavid du Colombier private const gx_device_procs bitcmyk_procs =
131*593dc095SDavid du Colombier bit_procs(bit_map_cmyk_color);
1327dd7cddfSDavid du Colombier const gx_device_printer gs_bitcmyk_device =
1337dd7cddfSDavid du Colombier {prn_device_body(gx_device_printer, bitcmyk_procs, "bitcmyk",
1347dd7cddfSDavid du Colombier 		 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
1357dd7cddfSDavid du Colombier 		 X_DPI, Y_DPI,
1367dd7cddfSDavid du Colombier 		 0, 0, 0, 0,	/* margins */
1377dd7cddfSDavid du Colombier 		 4, 4, 1, 1, 2, 2, bit_print_page)
1387dd7cddfSDavid du Colombier };
1397dd7cddfSDavid du Colombier 
1407dd7cddfSDavid du Colombier /* Map gray to color. */
1417dd7cddfSDavid du Colombier /* Note that 1-bit monochrome is a special case. */
1427dd7cddfSDavid du Colombier private gx_color_index
bit_mono_map_color(gx_device * dev,const gx_color_value cv[])143*593dc095SDavid du Colombier bit_mono_map_color(gx_device * dev, const gx_color_value cv[])
1447dd7cddfSDavid du Colombier {
1457dd7cddfSDavid du Colombier     int bpc = dev->color_info.depth;
1467dd7cddfSDavid du Colombier     int drop = sizeof(gx_color_value) * 8 - bpc;
147*593dc095SDavid du Colombier     gx_color_value gray = cv[0];
1487dd7cddfSDavid du Colombier 
1497dd7cddfSDavid du Colombier     return (bpc == 1 ? gx_max_color_value - gray : gray) >> drop;
1507dd7cddfSDavid du Colombier }
1517dd7cddfSDavid du Colombier 
1527dd7cddfSDavid du Colombier /* Map color to RGB.  This has 3 separate cases, but since it is rarely */
1537dd7cddfSDavid du Colombier /* used, we do a case test rather than providing 3 separate routines. */
1547dd7cddfSDavid du Colombier private int
bit_map_color_rgb(gx_device * dev,gx_color_index color,gx_color_value cv[4])155*593dc095SDavid du Colombier bit_map_color_rgb(gx_device * dev, gx_color_index color, gx_color_value cv[4])
1567dd7cddfSDavid du Colombier {
1577dd7cddfSDavid du Colombier     int depth = dev->color_info.depth;
1587dd7cddfSDavid du Colombier     int ncomp = REAL_NUM_COMPONENTS(dev);
1597dd7cddfSDavid du Colombier     int bpc = depth / ncomp;
1607dd7cddfSDavid du Colombier     uint mask = (1 << bpc) - 1;
1617dd7cddfSDavid du Colombier 
1627dd7cddfSDavid du Colombier #define cvalue(c) ((gx_color_value)((ulong)(c) * gx_max_color_value / mask))
1637dd7cddfSDavid du Colombier 
1647dd7cddfSDavid du Colombier     switch (ncomp) {
1657dd7cddfSDavid du Colombier 	case 1:		/* gray */
166*593dc095SDavid du Colombier 	    cv[0] =
1677dd7cddfSDavid du Colombier 		(depth == 1 ? (color ? 0 : gx_max_color_value) :
1687dd7cddfSDavid du Colombier 		 cvalue(color));
1697dd7cddfSDavid du Colombier 	    break;
1707dd7cddfSDavid du Colombier 	case 3:		/* RGB */
1717dd7cddfSDavid du Colombier 	    {
1727dd7cddfSDavid du Colombier 		gx_color_index cshift = color;
1737dd7cddfSDavid du Colombier 
174*593dc095SDavid du Colombier 		cv[2] = cvalue(cshift & mask);
1757dd7cddfSDavid du Colombier 		cshift >>= bpc;
176*593dc095SDavid du Colombier 		cv[1] = cvalue(cshift & mask);
177*593dc095SDavid du Colombier 		cv[0] = cvalue(cshift >> bpc);
1787dd7cddfSDavid du Colombier 	    }
1797dd7cddfSDavid du Colombier 	    break;
1807dd7cddfSDavid du Colombier 	case 4:		/* CMYK */
1817dd7cddfSDavid du Colombier 	    /* Map CMYK back to RGB. */
1827dd7cddfSDavid du Colombier 	    {
1837dd7cddfSDavid du Colombier 		gx_color_index cshift = color;
1847dd7cddfSDavid du Colombier 		uint c, m, y, k;
1857dd7cddfSDavid du Colombier 
1867dd7cddfSDavid du Colombier 		k = cshift & mask;
1877dd7cddfSDavid du Colombier 		cshift >>= bpc;
1887dd7cddfSDavid du Colombier 		y = cshift & mask;
1897dd7cddfSDavid du Colombier 		cshift >>= bpc;
1907dd7cddfSDavid du Colombier 		m = cshift & mask;
1917dd7cddfSDavid du Colombier 		c = cshift >> bpc;
1927dd7cddfSDavid du Colombier 		/* We use our improved conversion rule.... */
193*593dc095SDavid du Colombier 		cv[0] = cvalue((mask - c) * (mask - k) / mask);
194*593dc095SDavid du Colombier 		cv[1] = cvalue((mask - m) * (mask - k) / mask);
195*593dc095SDavid du Colombier 		cv[2] = cvalue((mask - y) * (mask - k) / mask);
1967dd7cddfSDavid du Colombier 	    }
1977dd7cddfSDavid du Colombier 	    break;
1987dd7cddfSDavid du Colombier     }
1997dd7cddfSDavid du Colombier     return 0;
2007dd7cddfSDavid du Colombier #undef cvalue
2017dd7cddfSDavid du Colombier }
2027dd7cddfSDavid du Colombier 
2037dd7cddfSDavid du Colombier /* Map CMYK to color. */
2047dd7cddfSDavid du Colombier private gx_color_index
bit_map_cmyk_color(gx_device * dev,const gx_color_value cv[])205*593dc095SDavid du Colombier bit_map_cmyk_color(gx_device * dev, const gx_color_value cv[])
2067dd7cddfSDavid du Colombier {
2077dd7cddfSDavid du Colombier     int bpc = dev->color_info.depth / 4;
2087dd7cddfSDavid du Colombier     int drop = sizeof(gx_color_value) * 8 - bpc;
2097dd7cddfSDavid du Colombier     gx_color_index color =
210*593dc095SDavid du Colombier     (((((((gx_color_index) cv[0] >> drop) << bpc) +
211*593dc095SDavid du Colombier 	(cv[1] >> drop)) << bpc) +
212*593dc095SDavid du Colombier       (cv[2] >> drop)) << bpc) +
213*593dc095SDavid du Colombier     (cv[3] >> drop);
2147dd7cddfSDavid du Colombier 
2157dd7cddfSDavid du Colombier     return (color == gx_no_color_index ? color ^ 1 : color);
2167dd7cddfSDavid du Colombier }
2177dd7cddfSDavid du Colombier 
2187dd7cddfSDavid du Colombier /* Get parameters.  We provide a default CRD. */
2197dd7cddfSDavid du Colombier private int
bit_get_params(gx_device * pdev,gs_param_list * plist)2207dd7cddfSDavid du Colombier bit_get_params(gx_device * pdev, gs_param_list * plist)
2217dd7cddfSDavid du Colombier {
2227dd7cddfSDavid du Colombier     int code, ecode;
2237dd7cddfSDavid du Colombier     /*
2247dd7cddfSDavid du Colombier      * The following is a hack to get the original num_components.
2257dd7cddfSDavid du Colombier      * See comment above.
2267dd7cddfSDavid du Colombier      */
2277dd7cddfSDavid du Colombier     int real_ncomps = REAL_NUM_COMPONENTS(pdev);
2287dd7cddfSDavid du Colombier     int ncomps = pdev->color_info.num_components;
2297dd7cddfSDavid du Colombier     int forcemono = (ncomps == real_ncomps ? 0 : 1);
2307dd7cddfSDavid du Colombier 
2317dd7cddfSDavid du Colombier     /*
2327dd7cddfSDavid du Colombier      * Temporarily set num_components back to the "real" value to avoid
2337dd7cddfSDavid du Colombier      * confusing those that rely on it.
2347dd7cddfSDavid du Colombier      */
2357dd7cddfSDavid du Colombier     pdev->color_info.num_components = real_ncomps;
2367dd7cddfSDavid du Colombier 
2377dd7cddfSDavid du Colombier     ecode = gdev_prn_get_params(pdev, plist);
2387dd7cddfSDavid du Colombier     code = sample_device_crd_get_params(pdev, plist, "CRDDefault");
2397dd7cddfSDavid du Colombier 	if (code < 0)
2407dd7cddfSDavid du Colombier 	    ecode = code;
2417dd7cddfSDavid du Colombier     if ((code = param_write_int(plist, "ForceMono", &forcemono)) < 0) {
2427dd7cddfSDavid du Colombier 	ecode = code;
2437dd7cddfSDavid du Colombier     }
2447dd7cddfSDavid du Colombier 
2457dd7cddfSDavid du Colombier     /* Restore the working num_components */
2467dd7cddfSDavid du Colombier     pdev->color_info.num_components = ncomps;
2477dd7cddfSDavid du Colombier 
2487dd7cddfSDavid du Colombier     return ecode;
2497dd7cddfSDavid du Colombier }
2507dd7cddfSDavid du Colombier 
2517dd7cddfSDavid du Colombier /* Set parameters.  We allow setting the number of bits per component. */
2527dd7cddfSDavid du Colombier /* Also, ForceMono=1 forces monochrome output from RGB/CMYK devices. */
2537dd7cddfSDavid du Colombier private int
bit_put_params(gx_device * pdev,gs_param_list * plist)2547dd7cddfSDavid du Colombier bit_put_params(gx_device * pdev, gs_param_list * plist)
2557dd7cddfSDavid du Colombier {
2567dd7cddfSDavid du Colombier     gx_device_color_info save_info;
2577dd7cddfSDavid du Colombier     int ncomps = pdev->color_info.num_components;
2587dd7cddfSDavid du Colombier     int real_ncomps = REAL_NUM_COMPONENTS(pdev);
2597dd7cddfSDavid du Colombier     int bpc = pdev->color_info.depth / real_ncomps;
2607dd7cddfSDavid du Colombier     int v;
2617dd7cddfSDavid du Colombier     int ecode = 0;
2627dd7cddfSDavid du Colombier     int code;
263*593dc095SDavid du Colombier     static const byte depths[4][16] = {
264*593dc095SDavid du Colombier 	{1, 2, 0, 4, 8, 0, 0, 8, 0, 0, 0, 16, 0, 0, 0, 16},
2657dd7cddfSDavid du Colombier 	{0},
266*593dc095SDavid du Colombier 	{4, 8, 0, 16, 16, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, 48},
267*593dc095SDavid du Colombier 	{4, 8, 0, 16, 32, 0, 0, 32, 0, 0, 0, 48, 0, 0, 0, 64}
2687dd7cddfSDavid du Colombier     };
2697dd7cddfSDavid du Colombier     const char *vname;
2707dd7cddfSDavid du Colombier 
2717dd7cddfSDavid du Colombier     /*
2727dd7cddfSDavid du Colombier      * Temporarily set num_components back to the "real" value to avoid
2737dd7cddfSDavid du Colombier      * confusing those that rely on it.
2747dd7cddfSDavid du Colombier      */
2757dd7cddfSDavid du Colombier     pdev->color_info.num_components = real_ncomps;
2767dd7cddfSDavid du Colombier 
2777dd7cddfSDavid du Colombier     if ((code = param_read_int(plist, (vname = "GrayValues"), &v)) != 1 ||
2787dd7cddfSDavid du Colombier 	(code = param_read_int(plist, (vname = "RedValues"), &v)) != 1 ||
2797dd7cddfSDavid du Colombier 	(code = param_read_int(plist, (vname = "GreenValues"), &v)) != 1 ||
2807dd7cddfSDavid du Colombier 	(code = param_read_int(plist, (vname = "BlueValues"), &v)) != 1
2817dd7cddfSDavid du Colombier 	) {
2827dd7cddfSDavid du Colombier 	if (code < 0)
2837dd7cddfSDavid du Colombier 	    ecode = code;
2847dd7cddfSDavid du Colombier 	else
2857dd7cddfSDavid du Colombier 	    switch (v) {
2867dd7cddfSDavid du Colombier 		case   2: bpc = 1; break;
2877dd7cddfSDavid du Colombier 		case   4: bpc = 2; break;
2887dd7cddfSDavid du Colombier 		case  16: bpc = 4; break;
2897dd7cddfSDavid du Colombier 		case  32: bpc = 5; break;
2907dd7cddfSDavid du Colombier 		case 256: bpc = 8; break;
291*593dc095SDavid du Colombier 		case 4096: bpc = 12; break;
292*593dc095SDavid du Colombier 		case 65536: bpc = 16; break;
2937dd7cddfSDavid du Colombier 		default:
2947dd7cddfSDavid du Colombier 		    param_signal_error(plist, vname,
2957dd7cddfSDavid du Colombier 				       ecode = gs_error_rangecheck);
2967dd7cddfSDavid du Colombier 	    }
2977dd7cddfSDavid du Colombier     }
2987dd7cddfSDavid du Colombier 
2997dd7cddfSDavid du Colombier     switch (code = param_read_int(plist, (vname = "ForceMono"), &v)) {
3007dd7cddfSDavid du Colombier     case 0:
3017dd7cddfSDavid du Colombier 	if (v == 1) {
3027dd7cddfSDavid du Colombier 	    ncomps = 1;
3037dd7cddfSDavid du Colombier 	    break;
3047dd7cddfSDavid du Colombier 	}
3057dd7cddfSDavid du Colombier 	else if (v == 0) {
3067dd7cddfSDavid du Colombier 	    ncomps = real_ncomps;
3077dd7cddfSDavid du Colombier 	    break;
3087dd7cddfSDavid du Colombier 	}
3097dd7cddfSDavid du Colombier 	code = gs_error_rangecheck;
3107dd7cddfSDavid du Colombier     default:
3117dd7cddfSDavid du Colombier 	ecode = code;
3127dd7cddfSDavid du Colombier 	param_signal_error(plist, vname, ecode);
3137dd7cddfSDavid du Colombier     case 1:
3147dd7cddfSDavid du Colombier 	break;
3157dd7cddfSDavid du Colombier     }
3167dd7cddfSDavid du Colombier     if (ecode < 0)
3177dd7cddfSDavid du Colombier 	return ecode;
3187dd7cddfSDavid du Colombier 
3197dd7cddfSDavid du Colombier     /*
3207dd7cddfSDavid du Colombier      * Save the color_info in case gdev_prn_put_params fails, and for
3217dd7cddfSDavid du Colombier      * comparison.  Note that depth is computed from real_ncomps.
3227dd7cddfSDavid du Colombier      */
3237dd7cddfSDavid du Colombier     save_info = pdev->color_info;
3247dd7cddfSDavid du Colombier     pdev->color_info.depth = depths[real_ncomps - 1][bpc - 1];
3257dd7cddfSDavid du Colombier     pdev->color_info.max_gray = pdev->color_info.max_color =
3267dd7cddfSDavid du Colombier 	(pdev->color_info.dither_grays =
3277dd7cddfSDavid du Colombier 	 pdev->color_info.dither_colors =
3287dd7cddfSDavid du Colombier 	 (1 << bpc)) - 1;
3297dd7cddfSDavid du Colombier     ecode = gdev_prn_put_params(pdev, plist);
3307dd7cddfSDavid du Colombier     if (ecode < 0) {
3317dd7cddfSDavid du Colombier 	pdev->color_info = save_info;
3327dd7cddfSDavid du Colombier 	return ecode;
3337dd7cddfSDavid du Colombier     }
3347dd7cddfSDavid du Colombier     /* Now restore/change num_components. This is done after other	*/
3357dd7cddfSDavid du Colombier     /* processing since it is used in gx_default_put_params		*/
3367dd7cddfSDavid du Colombier     pdev->color_info.num_components = ncomps;
3377dd7cddfSDavid du Colombier     if (pdev->color_info.depth != save_info.depth ||
3387dd7cddfSDavid du Colombier 	pdev->color_info.num_components != save_info.num_components
3397dd7cddfSDavid du Colombier 	) {
3407dd7cddfSDavid du Colombier 	gs_closedevice(pdev);
3417dd7cddfSDavid du Colombier     }
3427dd7cddfSDavid du Colombier     /* Reset the map_cmyk_color procedure if appropriate. */
3437dd7cddfSDavid du Colombier     if (dev_proc(pdev, map_cmyk_color) == cmyk_1bit_map_cmyk_color ||
3447dd7cddfSDavid du Colombier 	dev_proc(pdev, map_cmyk_color) == cmyk_8bit_map_cmyk_color ||
3457dd7cddfSDavid du Colombier 	dev_proc(pdev, map_cmyk_color) == bit_map_cmyk_color) {
3467dd7cddfSDavid du Colombier 	set_dev_proc(pdev, map_cmyk_color,
3477dd7cddfSDavid du Colombier 		     pdev->color_info.depth == 4 ? cmyk_1bit_map_cmyk_color :
3487dd7cddfSDavid du Colombier 		     pdev->color_info.depth == 32 ? cmyk_8bit_map_cmyk_color :
3497dd7cddfSDavid du Colombier 		     bit_map_cmyk_color);
3507dd7cddfSDavid du Colombier     }
351*593dc095SDavid du Colombier     /* Reset the sparable and linear shift, masks, bits. */
352*593dc095SDavid du Colombier     set_linear_color_bits_mask_shift(pdev);
353*593dc095SDavid du Colombier     pdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN;
3547dd7cddfSDavid du Colombier     return 0;
3557dd7cddfSDavid du Colombier }
3567dd7cddfSDavid du Colombier 
3577dd7cddfSDavid du Colombier /* Send the page to the printer. */
3587dd7cddfSDavid du Colombier private int
bit_print_page(gx_device_printer * pdev,FILE * prn_stream)3597dd7cddfSDavid du Colombier bit_print_page(gx_device_printer * pdev, FILE * prn_stream)
3607dd7cddfSDavid du Colombier {				/* Just dump the bits on the file. */
3617dd7cddfSDavid du Colombier     /* If the file is 'nul', don't even do the writes. */
3627dd7cddfSDavid du Colombier     int line_size = gdev_mem_bytes_per_scan_line((gx_device *) pdev);
3637dd7cddfSDavid du Colombier     byte *in = gs_alloc_bytes(pdev->memory, line_size, "bit_print_page(in)");
3647dd7cddfSDavid du Colombier     byte *data;
3657dd7cddfSDavid du Colombier     int nul = !strcmp(pdev->fname, "nul");
3667dd7cddfSDavid du Colombier     int lnum = 0, bottom = pdev->height;
3677dd7cddfSDavid du Colombier 
3687dd7cddfSDavid du Colombier     if (in == 0)
3697dd7cddfSDavid du Colombier 	return_error(gs_error_VMerror);
3707dd7cddfSDavid du Colombier     for (; lnum < bottom; ++lnum) {
3717dd7cddfSDavid du Colombier 	gdev_prn_get_bits(pdev, lnum, in, &data);
3727dd7cddfSDavid du Colombier 	if (!nul)
3737dd7cddfSDavid du Colombier 	    fwrite(data, 1, line_size, prn_stream);
3747dd7cddfSDavid du Colombier     }
3757dd7cddfSDavid du Colombier     gs_free_object(pdev->memory, in, "bit_print_page(in)");
3767dd7cddfSDavid du Colombier     return 0;
3777dd7cddfSDavid du Colombier }
378