Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1991, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
 
17
/* $Id: gdevbit.c,v 1.10 2004/06/23 18:57:15 stefan Exp $ */
18
/* "Plain bits" devices to measure rendering time. */
19
#include "math_.h"
20
#include "gdevprn.h"
21
#include "gsparam.h"
22
#include "gscrd.h"
23
#include "gscrdp.h"
24
#include "gxlum.h"
25
#include "gdevdcrd.h"
26
 
27
/* Define the device parameters. */
28
#ifndef X_DPI
29
#  define X_DPI 72
30
#endif
31
#ifndef Y_DPI
32
#  define Y_DPI 72
33
#endif
34
 
35
/* The device descriptor */
36
private dev_proc_map_rgb_color(bit_mono_map_color);
37
private dev_proc_map_color_rgb(bit_map_color_rgb);
38
private dev_proc_map_cmyk_color(bit_map_cmyk_color);
39
private dev_proc_get_params(bit_get_params);
40
private dev_proc_put_params(bit_put_params);
41
private dev_proc_print_page(bit_print_page);
42
 
43
#define bit_procs(encode_color)\
44
{	gdev_prn_open,\
45
	gx_default_get_initial_matrix,\
46
	NULL,	/* sync_output */\
47
	gdev_prn_output_page,\
48
	gdev_prn_close,\
49
	encode_color,	/* map_rgb_color */\
50
	bit_map_color_rgb,	/* map_color_rgb */\
51
	NULL,	/* fill_rectangle */\
52
	NULL,	/* tile_rectangle */\
53
	NULL,	/* copy_mono */\
54
	NULL,	/* copy_color */\
55
	NULL,	/* draw_line */\
56
	NULL,	/* get_bits */\
57
	bit_get_params,\
58
	bit_put_params,\
59
	encode_color,	/* map_cmyk_color */\
60
	NULL,	/* get_xfont_procs */\
61
	NULL,	/* get_xfont_device */\
62
	NULL,	/* map_rgb_alpha_color */\
63
	gx_page_device_get_page_device,	/* get_page_device */\
64
	NULL,	/* get_alpha_bits */\
65
	NULL,	/* copy_alpha */\
66
	NULL,	/* get_band */\
67
	NULL,	/* copy_rop */\
68
	NULL,	/* fill_path */\
69
	NULL,	/* stroke_path */\
70
	NULL,	/* fill_mask */\
71
	NULL,	/* fill_trapezoid */\
72
	NULL,	/* fill_parallelogram */\
73
	NULL,	/* fill_triangle */\
74
	NULL,	/* draw_thin_line */\
75
	NULL,	/* begin_image */\
76
	NULL,	/* image_data */\
77
	NULL,	/* end_image */\
78
	NULL,	/* strip_tile_rectangle */\
79
	NULL,	/* strip_copy_rop */\
80
	NULL,	/* get_clipping_box */\
81
	NULL,	/* begin_typed_image */\
82
	NULL,	/* get_bits_rectangle */\
83
	NULL,	/* map_color_rgb_alpha */\
84
	NULL,	/* create_compositor */\
85
	NULL,	/* get_hardware_params */\
86
	NULL,	/* text_begin */\
87
	NULL,	/* finish_copydevice */\
88
	NULL,	/* begin_transparency_group */\
89
	NULL,	/* end_transparency_group */\
90
	NULL,	/* begin_transparency_mask */\
91
	NULL,	/* end_transparency_mask */\
92
	NULL,	/* discard_transparency_layer */\
93
	NULL,	/* get_color_mapping_procs */\
94
	NULL,	/* get_color_comp_index */\
95
	encode_color,		/* encode_color */\
96
	bit_map_color_rgb	/* decode_color */\
97
}
98
 
99
/*
100
 * The following macro is used in get_params and put_params to determine the
101
 * num_components for the current device. It works using the device name
102
 * character after "bit" which is either '\0', 'r', or 'c'. Any new devices
103
 * that are added to this module must modify this macro to return the
104
 * correct num_components. This is needed to support the ForceMono
105
 * parameter, which alters dev->num_components.
106
 */
107
#define REAL_NUM_COMPONENTS(dev) (dev->dname[3] == 'c' ? 4 : \
108
				  dev->dname[3] == 'r' ? 3 : 1)
109
 
110
private const gx_device_procs bitmono_procs =
111
bit_procs(bit_mono_map_color);
112
const gx_device_printer gs_bit_device =
113
{prn_device_body(gx_device_printer, bitmono_procs, "bit",
114
		 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
115
		 X_DPI, Y_DPI,
116
		 0, 0, 0, 0,    /* margins */
117
		 1, 1, 1, 0, 2, 1, bit_print_page)
118
};
119
 
120
private const gx_device_procs bitrgb_procs =
121
bit_procs(gx_default_rgb_map_rgb_color);
122
const gx_device_printer gs_bitrgb_device =
123
{prn_device_body(gx_device_printer, bitrgb_procs, "bitrgb",
124
		 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
125
		 X_DPI, Y_DPI,
126
		 0, 0, 0, 0,	/* margins */
127
		 3, 4, 1, 1, 2, 2, bit_print_page)
128
};
129
 
130
private const gx_device_procs bitcmyk_procs =
131
bit_procs(bit_map_cmyk_color);
132
const gx_device_printer gs_bitcmyk_device =
133
{prn_device_body(gx_device_printer, bitcmyk_procs, "bitcmyk",
134
		 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
135
		 X_DPI, Y_DPI,
136
		 0, 0, 0, 0,	/* margins */
137
		 4, 4, 1, 1, 2, 2, bit_print_page)
138
};
139
 
140
/* Map gray to color. */
141
/* Note that 1-bit monochrome is a special case. */
142
private gx_color_index
143
bit_mono_map_color(gx_device * dev, const gx_color_value cv[])
144
{
145
    int bpc = dev->color_info.depth;
146
    int drop = sizeof(gx_color_value) * 8 - bpc;
147
    gx_color_value gray = cv[0];
148
 
149
    return (bpc == 1 ? gx_max_color_value - gray : gray) >> drop;
150
}
151
 
152
/* Map color to RGB.  This has 3 separate cases, but since it is rarely */
153
/* used, we do a case test rather than providing 3 separate routines. */
154
private int
155
bit_map_color_rgb(gx_device * dev, gx_color_index color, gx_color_value cv[4])
156
{
157
    int depth = dev->color_info.depth;
158
    int ncomp = REAL_NUM_COMPONENTS(dev);
159
    int bpc = depth / ncomp;
160
    uint mask = (1 << bpc) - 1;
161
 
162
#define cvalue(c) ((gx_color_value)((ulong)(c) * gx_max_color_value / mask))
163
 
164
    switch (ncomp) {
165
	case 1:		/* gray */
166
	    cv[0] =
167
		(depth == 1 ? (color ? 0 : gx_max_color_value) :
168
		 cvalue(color));
169
	    break;
170
	case 3:		/* RGB */
171
	    {
172
		gx_color_index cshift = color;
173
 
174
		cv[2] = cvalue(cshift & mask);
175
		cshift >>= bpc;
176
		cv[1] = cvalue(cshift & mask);
177
		cv[0] = cvalue(cshift >> bpc);
178
	    }
179
	    break;
180
	case 4:		/* CMYK */
181
	    /* Map CMYK back to RGB. */
182
	    {
183
		gx_color_index cshift = color;
184
		uint c, m, y, k;
185
 
186
		k = cshift & mask;
187
		cshift >>= bpc;
188
		y = cshift & mask;
189
		cshift >>= bpc;
190
		m = cshift & mask;
191
		c = cshift >> bpc;
192
		/* We use our improved conversion rule.... */
193
		cv[0] = cvalue((mask - c) * (mask - k) / mask);
194
		cv[1] = cvalue((mask - m) * (mask - k) / mask);
195
		cv[2] = cvalue((mask - y) * (mask - k) / mask);
196
	    }
197
	    break;
198
    }
199
    return 0;
200
#undef cvalue
201
}
202
 
203
/* Map CMYK to color. */
204
private gx_color_index
205
bit_map_cmyk_color(gx_device * dev, const gx_color_value cv[])
206
{
207
    int bpc = dev->color_info.depth / 4;
208
    int drop = sizeof(gx_color_value) * 8 - bpc;
209
    gx_color_index color =
210
    (((((((gx_color_index) cv[0] >> drop) << bpc) +
211
	(cv[1] >> drop)) << bpc) +
212
      (cv[2] >> drop)) << bpc) +
213
    (cv[3] >> drop);
214
 
215
    return (color == gx_no_color_index ? color ^ 1 : color);
216
}
217
 
218
/* Get parameters.  We provide a default CRD. */
219
private int
220
bit_get_params(gx_device * pdev, gs_param_list * plist)
221
{
222
    int code, ecode;
223
    /*
224
     * The following is a hack to get the original num_components.
225
     * See comment above.
226
     */
227
    int real_ncomps = REAL_NUM_COMPONENTS(pdev);
228
    int ncomps = pdev->color_info.num_components;
229
    int forcemono = (ncomps == real_ncomps ? 0 : 1);
230
 
231
    /*
232
     * Temporarily set num_components back to the "real" value to avoid
233
     * confusing those that rely on it.
234
     */
235
    pdev->color_info.num_components = real_ncomps;
236
 
237
    ecode = gdev_prn_get_params(pdev, plist);
238
    code = sample_device_crd_get_params(pdev, plist, "CRDDefault");
239
	if (code < 0)
240
	    ecode = code;
241
    if ((code = param_write_int(plist, "ForceMono", &forcemono)) < 0) {
242
	ecode = code;
243
    }
244
 
245
    /* Restore the working num_components */
246
    pdev->color_info.num_components = ncomps;
247
 
248
    return ecode;
249
}
250
 
251
/* Set parameters.  We allow setting the number of bits per component. */
252
/* Also, ForceMono=1 forces monochrome output from RGB/CMYK devices. */
253
private int
254
bit_put_params(gx_device * pdev, gs_param_list * plist)
255
{
256
    gx_device_color_info save_info;
257
    int ncomps = pdev->color_info.num_components;
258
    int real_ncomps = REAL_NUM_COMPONENTS(pdev);
259
    int bpc = pdev->color_info.depth / real_ncomps;
260
    int v;
261
    int ecode = 0;
262
    int code;
263
    static const byte depths[4][16] = {
264
	{1, 2, 0, 4, 8, 0, 0, 8, 0, 0, 0, 16, 0, 0, 0, 16},
265
	{0},
266
	{4, 8, 0, 16, 16, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, 48},
267
	{4, 8, 0, 16, 32, 0, 0, 32, 0, 0, 0, 48, 0, 0, 0, 64}
268
    };
269
    const char *vname;
270
 
271
    /*
272
     * Temporarily set num_components back to the "real" value to avoid
273
     * confusing those that rely on it.
274
     */
275
    pdev->color_info.num_components = real_ncomps;
276
 
277
    if ((code = param_read_int(plist, (vname = "GrayValues"), &v)) != 1 ||
278
	(code = param_read_int(plist, (vname = "RedValues"), &v)) != 1 ||
279
	(code = param_read_int(plist, (vname = "GreenValues"), &v)) != 1 ||
280
	(code = param_read_int(plist, (vname = "BlueValues"), &v)) != 1
281
	) {
282
	if (code < 0)
283
	    ecode = code;
284
	else
285
	    switch (v) {
286
		case   2: bpc = 1; break;
287
		case   4: bpc = 2; break;
288
		case  16: bpc = 4; break;
289
		case  32: bpc = 5; break;
290
		case 256: bpc = 8; break;
291
		case 4096: bpc = 12; break;
292
		case 65536: bpc = 16; break;
293
		default:
294
		    param_signal_error(plist, vname,
295
				       ecode = gs_error_rangecheck);
296
	    }
297
    }
298
 
299
    switch (code = param_read_int(plist, (vname = "ForceMono"), &v)) {
300
    case 0:
301
	if (v == 1) {
302
	    ncomps = 1;
303
	    break;
304
	}
305
	else if (v == 0) {
306
	    ncomps = real_ncomps;
307
	    break;
308
	}
309
	code = gs_error_rangecheck;
310
    default:
311
	ecode = code;
312
	param_signal_error(plist, vname, ecode);
313
    case 1:
314
	break;
315
    }
316
    if (ecode < 0)
317
	return ecode;
318
 
319
    /*
320
     * Save the color_info in case gdev_prn_put_params fails, and for
321
     * comparison.  Note that depth is computed from real_ncomps.
322
     */
323
    save_info = pdev->color_info;
324
    pdev->color_info.depth = depths[real_ncomps - 1][bpc - 1];
325
    pdev->color_info.max_gray = pdev->color_info.max_color =
326
	(pdev->color_info.dither_grays =
327
	 pdev->color_info.dither_colors =
328
	 (1 << bpc)) - 1;
329
    ecode = gdev_prn_put_params(pdev, plist);
330
    if (ecode < 0) {
331
	pdev->color_info = save_info;
332
	return ecode;
333
    }
334
    /* Now restore/change num_components. This is done after other	*/
335
    /* processing since it is used in gx_default_put_params		*/
336
    pdev->color_info.num_components = ncomps;
337
    if (pdev->color_info.depth != save_info.depth ||
338
	pdev->color_info.num_components != save_info.num_components
339
	) {
340
	gs_closedevice(pdev);
341
    }
342
    /* Reset the map_cmyk_color procedure if appropriate. */
343
    if (dev_proc(pdev, map_cmyk_color) == cmyk_1bit_map_cmyk_color ||
344
	dev_proc(pdev, map_cmyk_color) == cmyk_8bit_map_cmyk_color ||
345
	dev_proc(pdev, map_cmyk_color) == bit_map_cmyk_color) {
346
	set_dev_proc(pdev, map_cmyk_color,
347
		     pdev->color_info.depth == 4 ? cmyk_1bit_map_cmyk_color :
348
		     pdev->color_info.depth == 32 ? cmyk_8bit_map_cmyk_color :
349
		     bit_map_cmyk_color);
350
    }
351
    /* Reset the sparable and linear shift, masks, bits. */
352
    set_linear_color_bits_mask_shift(pdev);
353
    pdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN;
354
    return 0;
355
}
356
 
357
/* Send the page to the printer. */
358
private int
359
bit_print_page(gx_device_printer * pdev, FILE * prn_stream)
360
{				/* Just dump the bits on the file. */
361
    /* If the file is 'nul', don't even do the writes. */
362
    int line_size = gdev_mem_bytes_per_scan_line((gx_device *) pdev);
363
    byte *in = gs_alloc_bytes(pdev->memory, line_size, "bit_print_page(in)");
364
    byte *data;
365
    int nul = !strcmp(pdev->fname, "nul");
366
    int lnum = 0, bottom = pdev->height;
367
 
368
    if (in == 0)
369
	return_error(gs_error_VMerror);
370
    for (; lnum < bottom; ++lnum) {
371
	gdev_prn_get_bits(pdev, lnum, in, &data);
372
	if (!nul)
373
	    fwrite(data, 1, line_size, prn_stream);
374
    }
375
    gs_free_object(pdev->memory, in, "bit_print_page(in)");
376
    return 0;
377
}