1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
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.
14
/* $Id: gdevbit.c 8790 2008-06-09 07:33:57Z leonardo $ */
15
/* "Plain bits" devices to measure rendering time. */
25
#include "gsutil.h" /* for bittags hack */
27
/* Define the device parameters. */
35
/* The device descriptor */
36
static dev_proc_get_color_mapping_procs(bittag_get_color_mapping_procs);
37
static dev_proc_map_rgb_color(bittag_rgb_map_rgb_color);
38
static dev_proc_map_color_rgb(bittag_map_color_rgb);
39
static dev_proc_put_params(bittag_put_params);
40
static dev_proc_map_rgb_color(bit_mono_map_color);
42
static dev_proc_map_rgb_color(bit_forcemono_map_rgb_color);
44
static dev_proc_map_color_rgb(bit_map_color_rgb);
45
static dev_proc_map_cmyk_color(bit_map_cmyk_color);
46
static dev_proc_get_params(bit_get_params);
47
static dev_proc_put_params(bit_put_params);
48
static dev_proc_print_page(bit_print_page);
50
#define bit_procs(encode_color)\
52
gx_default_get_initial_matrix,\
53
NULL, /* sync_output */\
54
gdev_prn_output_page,\
56
encode_color, /* map_rgb_color */\
57
bit_map_color_rgb, /* map_color_rgb */\
58
NULL, /* fill_rectangle */\
59
NULL, /* tile_rectangle */\
60
NULL, /* copy_mono */\
61
NULL, /* copy_color */\
62
NULL, /* draw_line */\
66
encode_color, /* map_cmyk_color */\
67
NULL, /* get_xfont_procs */\
68
NULL, /* get_xfont_device */\
69
NULL, /* map_rgb_alpha_color */\
70
gx_page_device_get_page_device, /* get_page_device */\
71
NULL, /* get_alpha_bits */\
72
NULL, /* copy_alpha */\
75
NULL, /* fill_path */\
76
NULL, /* stroke_path */\
77
NULL, /* fill_mask */\
78
NULL, /* fill_trapezoid */\
79
NULL, /* fill_parallelogram */\
80
NULL, /* fill_triangle */\
81
NULL, /* draw_thin_line */\
82
NULL, /* begin_image */\
83
NULL, /* image_data */\
84
NULL, /* end_image */\
85
NULL, /* strip_tile_rectangle */\
86
NULL, /* strip_copy_rop */\
87
NULL, /* get_clipping_box */\
88
NULL, /* begin_typed_image */\
89
NULL, /* get_bits_rectangle */\
90
NULL, /* map_color_rgb_alpha */\
91
NULL, /* create_compositor */\
92
NULL, /* get_hardware_params */\
93
NULL, /* text_begin */\
94
NULL, /* finish_copydevice */\
95
NULL, /* begin_transparency_group */\
96
NULL, /* end_transparency_group */\
97
NULL, /* begin_transparency_mask */\
98
NULL, /* end_transparency_mask */\
99
NULL, /* discard_transparency_layer */\
100
NULL, /* get_color_mapping_procs */\
101
NULL, /* get_color_comp_index */\
102
encode_color, /* encode_color */\
103
bit_map_color_rgb /* decode_color */\
107
* The following macro is used in get_params and put_params to determine the
108
* num_components for the current device. It works using the device name
109
* character after "bit" which is either '\0', 'r', or 'c'. Any new devices
110
* that are added to this module must modify this macro to return the
111
* correct num_components. This is needed to support the ForceMono
112
* parameter, which alters dev->num_components.
114
#define REAL_NUM_COMPONENTS(dev) (dev->dname[3] == 'c' ? 4 : \
115
dev->dname[3] == 'r' ? 3 : 1)
117
static const gx_device_procs bitmono_procs =
118
bit_procs(bit_mono_map_color);
119
const gx_device_printer gs_bit_device =
120
{prn_device_body(gx_device_printer, bitmono_procs, "bit",
121
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
123
0, 0, 0, 0, /* margins */
124
1, 1, 1, 0, 2, 1, bit_print_page)
127
static const gx_device_procs bitrgb_procs =
128
bit_procs(gx_default_rgb_map_rgb_color);
129
const gx_device_printer gs_bitrgb_device =
130
{prn_device_body(gx_device_printer, bitrgb_procs, "bitrgb",
131
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
133
0, 0, 0, 0, /* margins */
134
3, 4, 1, 1, 2, 2, bit_print_page)
137
static const gx_device_procs bitcmyk_procs =
138
bit_procs(bit_map_cmyk_color);
139
const gx_device_printer gs_bitcmyk_device =
140
{prn_device_body(gx_device_printer, bitcmyk_procs, "bitcmyk",
141
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
143
0, 0, 0, 0, /* margins */
144
4, 4, 1, 1, 2, 2, bit_print_page)
147
static const gx_device_procs bitrgbtags_procs =
149
gdev_prn_open, /* open_device */
150
gx_default_get_initial_matrix, /* initial_matrix */
151
((void *)0), /* sync_output */
152
gdev_prn_output_page, /* output page */
153
gdev_prn_close, /* close_device */
154
bittag_rgb_map_rgb_color, /* map rgb color */
155
bittag_map_color_rgb, /* map color rgb */
156
((void *)0), /* fill_rectangle */
157
((void *)0), /* tile rectangle */
158
((void *)0), /* copy mono */
159
((void *)0), /* copy color */
160
((void *)0), /* obsolete draw line */
161
((void *)0), /* get_bits */
162
gdev_prn_get_params, /* get params */
163
bittag_put_params, /* put params */
164
bittag_rgb_map_rgb_color, /* map_cmyk_color */
165
((void *)0), /* get_xfonts */
166
((void *)0), /* get_xfont_device */
167
((void *)0), /* map_rgb_alpha_color */
168
gx_page_device_get_page_device, /* get_page_device */
169
((void *)0), /* get_alpha_bits */
170
((void *)0), /* copy_alpha */
171
((void *)0), /* get_band */
172
((void *)0), /* copy_rop */
173
((void *)0), /* fill_path */
174
((void *)0), /* stroke_path */
175
((void *)0), /* fill_mask */
176
((void *)0), /* fill_trapezoid */
177
((void *)0), /* fill_parallelogram */
178
((void *)0), /* fill_triangle */
179
((void *)0), /* draw_thin_line */
180
((void *)0), /* begin_image */
181
((void *)0), /* image_data */
182
((void *)0), /* end_image */
183
((void *)0), /* strip_tile_rectangle */
184
((void *)0), /* strip_copy_rop */
185
((void *)0), /* get_clipping_box */
186
((void *)0), /* begin_typed_image */
187
((void *)0), /* get_bits_rectangle */
188
((void *)0), /* map_color_rgb_alpha */
189
((void *)0), /* create_compositor */
190
((void *)0), /* get_hardware_params */
191
((void *)0), /* text_begin */
192
((void *)0), /* finish_copydevice */
193
((void *)0), /* begin_transparency_group */
194
((void *)0), /* end_transparency_group */
195
((void *)0), /* begin_transparency_mask */
196
((void *)0), /* end_transparency_mask */
197
((void *)0), /* discard_transparency_layer */
198
bittag_get_color_mapping_procs, /* get_color_mapping_procs */
199
((void *)0), /* get_color_comp_index */
200
bittag_rgb_map_rgb_color, /* encode_color */
201
bittag_map_color_rgb /* decode_color */
204
const gx_device_printer gs_bitrgbtags_device =
206
sizeof(gx_device_printer),
211
0 , /* stype_is_dynamic */
213
{ 0 } , /* rc header */
216
0, /* max_fill_band */
218
4, /* max_components */
219
4, /* num_components */
220
GX_CINFO_POLARITY_ADDITIVE, /* polarity */
222
GX_CINFO_COMP_NO_INDEX, /* gray index */
224
255 , /* max_colors */
225
256 , /* dither grays */
226
256 , /* dither colors */
227
{ 1, 1 } , /* antialiasing */
228
GX_CINFO_UNKNOWN_SEP_LIN, /* sep and linear */
229
{ 0 } , /* comp shift */
230
{ 0 } , /* comp bits */
231
{ 0 } , /* comp mask */
232
( "DeviceRGB" ), /* color model name */
233
GX_CINFO_OPMODE_UNKNOWN , /* overprint mode */
234
0 /* process comps */
237
((gx_color_index)(~0)),
238
((gx_color_index)(~0))
240
(int)((float)(85) * (X_DPI) / 10 + 0.5),
241
(int)((float)(110) * (Y_DPI) / 10 + 0.5),
244
(float)(((((int)((float)(85) * (X_DPI) / 10 + 0.5)) * 72.0 + 0.5) - 0.5) / (X_DPI)) ,
245
(float)(((((int)((float)(110) * (Y_DPI) / 10 + 0.5)) * 72.0 + 0.5) - 0.5) / (Y_DPI)) },
255
{(float)(-(0) * (X_DPI)),
256
(float)(-(0) * (Y_DPI))},
257
{(float)((0) * 72.0),
260
(float)((0) * 72.0)},
273
gx_default_begin_page,
279
gx_default_print_page_copies,
280
{ gx_default_create_buf_device,
281
gx_default_size_buf_device,
282
gx_default_setup_buf_device,
283
gx_default_destroy_buf_device },
284
gx_default_get_space_params,
285
gx_default_start_render_thread,
286
gx_default_open_render_device,
287
gx_default_close_render_device,
288
gx_default_buffer_page },
315
cmyk_cs_to_rgb_cm(gx_device * dev, frac c, frac m, frac y, frac k, frac out[])
317
color_cmyk_to_rgb(c, m, y, k, NULL, out);
321
private_rgb_cs_to_rgb_cm(gx_device * dev, const gs_imager_state *pis,
322
frac r, frac g, frac b, frac out[])
330
gray_cs_to_rgb_cm(gx_device * dev, frac gray, frac out[])
332
out[0] = out[1] = out[2] = gray;
336
static const gx_cm_color_map_procs bittag_DeviceRGB_procs = {
337
gray_cs_to_rgb_cm, private_rgb_cs_to_rgb_cm, cmyk_cs_to_rgb_cm
340
static const gx_cm_color_map_procs *
341
bittag_get_color_mapping_procs(const gx_device *dev)
343
return &bittag_DeviceRGB_procs;
346
static gx_color_index
347
bittag_rgb_map_rgb_color(gx_device * dev, const gx_color_value cv[])
350
((cv[2]) >> ((sizeof(gx_color_value) * 8) - 8)) +
351
((uint) ((cv[1]) >> ((sizeof(gx_color_value) * 8) - 8)) << 8) +
352
((ulong) ((cv[0]) >> ((sizeof(gx_color_value) * 8) - 8)) << 16) +
353
((ulong)gs_current_object_tag() << 24);
357
bittag_map_color_rgb(gx_device * dev, gx_color_index color, gx_color_value cv[4])
361
int bpc = depth / ncomp;
362
uint mask = (1 << bpc) - 1;
364
#define cvalue(c) ((gx_color_value)((ulong)(c) * gx_max_color_value / mask))
366
gx_color_index cshift = color;
367
cv[2] = cvalue(cshift & mask);
369
cv[1] = cvalue(cshift & mask);
371
cv[0] = cvalue(cshift & mask);
376
/* Map gray to color. */
377
/* Note that 1-bit monochrome is a special case. */
378
static gx_color_index
379
bit_mono_map_color(gx_device * dev, const gx_color_value cv[])
381
int bpc = dev->color_info.depth;
382
int drop = sizeof(gx_color_value) * 8 - bpc;
383
gx_color_value gray = cv[0];
385
return (bpc == 1 ? gx_max_color_value - gray : gray) >> drop;
389
/* Map RGB to gray shade. */
390
/* Only used in CMYK mode when put_params has set ForceMono=1 */
391
static gx_color_index
392
bit_forcemono_map_rgb_color(gx_device * dev, const gx_color_value cv[])
394
gx_color_value color;
395
int bpc = dev->color_info.depth / 4; /* This function is used in CMYK mode */
396
int drop = sizeof(gx_color_value) * 8 - bpc;
397
gx_color_value gray, red, green, blue;
398
red = cv[0]; green = cv[1]; blue = cv[2];
400
if ((red != green) || (green != blue))
401
gray = (red * (unsigned long)lum_red_weight +
402
green * (unsigned long)lum_green_weight +
403
blue * (unsigned long)lum_blue_weight +
404
(lum_all_weights / 2))
407
color = (gx_max_color_value - gray) >> drop; /* color is in K channel */
412
/* Map color to RGB. This has 3 separate cases, but since it is rarely */
413
/* used, we do a case test rather than providing 3 separate routines. */
415
bit_map_color_rgb(gx_device * dev, gx_color_index color, gx_color_value cv[4])
417
int depth = dev->color_info.depth;
418
int ncomp = REAL_NUM_COMPONENTS(dev);
419
int bpc = depth / ncomp;
420
uint mask = (1 << bpc) - 1;
422
#define cvalue(c) ((gx_color_value)((ulong)(c) * gx_max_color_value / mask))
427
(depth == 1 ? (color ? 0 : gx_max_color_value) :
432
gx_color_index cshift = color;
434
cv[2] = cvalue(cshift & mask);
436
cv[1] = cvalue(cshift & mask);
437
cv[0] = cvalue(cshift >> bpc);
441
/* Map CMYK back to RGB. */
443
gx_color_index cshift = color;
452
/* We use our improved conversion rule.... */
453
cv[0] = cvalue((mask - c) * (mask - k) / mask);
454
cv[1] = cvalue((mask - m) * (mask - k) / mask);
455
cv[2] = cvalue((mask - y) * (mask - k) / mask);
463
/* Map CMYK to color. */
464
static gx_color_index
465
bit_map_cmyk_color(gx_device * dev, const gx_color_value cv[])
467
int bpc = dev->color_info.depth / 4;
468
int drop = sizeof(gx_color_value) * 8 - bpc;
469
gx_color_index color =
470
(((((((gx_color_index) cv[0] >> drop) << bpc) +
471
(cv[1] >> drop)) << bpc) +
472
(cv[2] >> drop)) << bpc) +
475
return (color == gx_no_color_index ? color ^ 1 : color);
479
bittag_put_params(gx_device * pdev, gs_param_list * plist)
481
gs_enable_object_tagging();
482
return gdev_prn_put_params(pdev, plist);
484
/* Get parameters. We provide a default CRD. */
486
bit_get_params(gx_device * pdev, gs_param_list * plist)
490
* The following is a hack to get the original num_components.
493
int real_ncomps = REAL_NUM_COMPONENTS(pdev);
494
int ncomps = pdev->color_info.num_components;
495
int forcemono = (ncomps == real_ncomps ? 0 : 1);
498
* Temporarily set num_components back to the "real" value to avoid
499
* confusing those that rely on it.
501
pdev->color_info.num_components = real_ncomps;
503
ecode = gdev_prn_get_params(pdev, plist);
504
code = sample_device_crd_get_params(pdev, plist, "CRDDefault");
507
if ((code = param_write_int(plist, "ForceMono", &forcemono)) < 0) {
511
/* Restore the working num_components */
512
pdev->color_info.num_components = ncomps;
517
/* Set parameters. We allow setting the number of bits per component. */
518
/* Also, ForceMono=1 forces monochrome output from RGB/CMYK devices. */
520
bit_put_params(gx_device * pdev, gs_param_list * plist)
522
gx_device_color_info save_info;
523
int ncomps = pdev->color_info.num_components;
524
int real_ncomps = REAL_NUM_COMPONENTS(pdev);
525
int bpc = pdev->color_info.depth / real_ncomps;
529
static const byte depths[4][16] = {
530
{1, 2, 0, 4, 8, 0, 0, 8, 0, 0, 0, 16, 0, 0, 0, 16},
532
{4, 8, 0, 16, 16, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, 48},
533
{4, 8, 0, 16, 32, 0, 0, 32, 0, 0, 0, 48, 0, 0, 0, 64}
538
* Temporarily set num_components back to the "real" value to avoid
539
* confusing those that rely on it.
541
pdev->color_info.num_components = real_ncomps;
543
if ((code = param_read_int(plist, (vname = "GrayValues"), &v)) != 1 ||
544
(code = param_read_int(plist, (vname = "RedValues"), &v)) != 1 ||
545
(code = param_read_int(plist, (vname = "GreenValues"), &v)) != 1 ||
546
(code = param_read_int(plist, (vname = "BlueValues"), &v)) != 1
552
case 2: bpc = 1; break;
553
case 4: bpc = 2; break;
554
case 16: bpc = 4; break;
555
case 32: bpc = 5; break;
556
case 256: bpc = 8; break;
557
case 4096: bpc = 12; break;
558
case 65536: bpc = 16; break;
560
param_signal_error(plist, vname,
561
ecode = gs_error_rangecheck);
565
switch (code = param_read_int(plist, (vname = "ForceMono"), &v)) {
572
ncomps = real_ncomps;
575
code = gs_error_rangecheck;
578
param_signal_error(plist, vname, ecode);
586
* Save the color_info in case gdev_prn_put_params fails, and for
587
* comparison. Note that depth is computed from real_ncomps.
589
save_info = pdev->color_info;
590
pdev->color_info.depth = depths[real_ncomps - 1][bpc - 1];
591
pdev->color_info.max_gray = pdev->color_info.max_color =
592
(pdev->color_info.dither_grays =
593
pdev->color_info.dither_colors =
595
ecode = gdev_prn_put_params(pdev, plist);
597
pdev->color_info = save_info;
600
/* Now restore/change num_components. This is done after other */
601
/* processing since it is used in gx_default_put_params */
602
pdev->color_info.num_components = ncomps;
603
if (pdev->color_info.depth != save_info.depth ||
604
pdev->color_info.num_components != save_info.num_components
606
gs_closedevice(pdev);
608
/* Reset the map_cmyk_color procedure if appropriate. */
609
if (dev_proc(pdev, map_cmyk_color) == cmyk_1bit_map_cmyk_color ||
610
dev_proc(pdev, map_cmyk_color) == cmyk_8bit_map_cmyk_color ||
611
dev_proc(pdev, map_cmyk_color) == bit_map_cmyk_color) {
612
set_dev_proc(pdev, map_cmyk_color,
613
pdev->color_info.depth == 4 ? cmyk_1bit_map_cmyk_color :
614
pdev->color_info.depth == 32 ? cmyk_8bit_map_cmyk_color :
617
/* Reset the sparable and linear shift, masks, bits. */
618
set_linear_color_bits_mask_shift(pdev);
619
pdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN;
623
/* Send the page to the printer. */
625
bit_print_page(gx_device_printer * pdev, FILE * prn_stream)
626
{ /* Just dump the bits on the file. */
627
/* If the file is 'nul', don't even do the writes. */
628
int line_size = gdev_mem_bytes_per_scan_line((gx_device *) pdev);
629
byte *in = gs_alloc_bytes(pdev->memory, line_size, "bit_print_page(in)");
631
int nul = !strcmp(pdev->fname, "nul") || !strcmp(pdev->fname, "/dev/null");
632
int lnum = 0, bottom = pdev->height;
635
return_error(gs_error_VMerror);
636
for (; lnum < bottom; ++lnum) {
637
gdev_prn_get_bits(pdev, lnum, in, &data);
639
fwrite(data, 1, line_size, prn_stream);
641
gs_free_object(pdev->memory, in, "bit_print_page(in)");