]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | /* |
2 | * "$Id: gdevcups.c 4493 2005-02-18 02:09:53Z mike $" | |
3 | * | |
4 | * GNU Ghostscript raster output driver for the Common UNIX Printing | |
5 | * System (CUPS). | |
6 | * | |
7 | * Copyright 1993-2005 by Easy Software Products. | |
8 | * | |
9 | * These coded instructions, statements, and computer programs are the | |
10 | * property of Easy Software Products and are protected by Federal | |
11 | * copyright law. Distribution and use rights are outlined in the file | |
12 | * "LICENSE.txt" which should have been included with this file. If this | |
13 | * file is missing or damaged please contact Easy Software Products | |
14 | * at: | |
15 | * | |
16 | * Attn: CUPS Licensing Information | |
17 | * Easy Software Products | |
18 | * 44141 Airport View Drive, Suite 204 | |
19 | * Hollywood, Maryland 20636 USA | |
20 | * | |
21 | * Voice: (301) 373-9600 | |
22 | * EMail: cups-info@cups.org | |
23 | * WWW: http://www.cups.org/ | |
24 | * | |
25 | * This code and any derivative of it may be used and distributed | |
26 | * freely under the terms of the GNU General Public License when | |
27 | * used with GNU Ghostscript or its derivatives. Use of the code | |
28 | * (or any derivative of it) with software other than GNU | |
29 | * GhostScript (or its derivatives) is governed by the CUPS license | |
30 | * agreement. | |
31 | * | |
32 | * Contents: | |
33 | * | |
34 | * cups_close() - Close the output file. | |
35 | * cups_get_matrix() - Generate the default page matrix. | |
36 | * cups_get_params() - Get pagedevice parameters. | |
37 | * cups_get_space_params() - Get space parameters from the RIP_CACHE env var. | |
38 | * cups_map_color_rgb() - Map a color index to an RGB color. | |
39 | * cups_map_cielab() - Map CIE Lab transformation... | |
40 | * cups_map_rgb_color() - Map an RGB color to a color index. We map the | |
41 | * RGB color to the output colorspace & bits (we | |
42 | * figure out the format when we output a page). | |
43 | * cups_open() - Open the output file and initialize things. | |
44 | * cups_print_pages() - Send one or more pages to the output file. | |
45 | * cups_put_params() - Set pagedevice parameters. | |
46 | * cups_set_color_info() - Set the color information structure based on | |
47 | * the required output. | |
48 | * cups_print_chunked() - Print a page of chunked pixels. | |
49 | * cups_print_banded() - Print a page of banded pixels. | |
50 | * cups_print_planar() - Print a page of planar pixels. | |
51 | */ | |
52 | ||
53 | /* | |
54 | * Include necessary headers... | |
55 | */ | |
56 | ||
57 | #include "std.h" /* to stop stdlib.h redefining types */ | |
58 | #include "gdevprn.h" | |
59 | #include "gsparam.h" | |
60 | #include "gsexit.h" | |
61 | ||
62 | #include <stdlib.h> | |
63 | #include <ctype.h> | |
64 | #include <cups/raster.h> | |
65 | #include <cups/ppd.h> | |
66 | #include <math.h> | |
67 | ||
68 | #undef private | |
69 | #define private | |
70 | ||
71 | ||
72 | /* | |
73 | * Check if we are compiling against CUPS 1.2. If so, enable | |
74 | * certain extended attributes and use a different page header | |
75 | * structure and write function... | |
76 | */ | |
77 | ||
78 | #ifdef CUPS_RASTER_SYNCv1 | |
79 | # define cups_page_header_t cups_page_header2_t | |
80 | # define cupsRasterWriteHeader cupsRasterWriteHeader2 | |
81 | #endif /* CUPS_RASTER_SYNCv1 */ | |
82 | ||
83 | ||
84 | /* | |
85 | * Newer versions of Ghostscript don't provide gs_exit() function anymore. | |
86 | * It has been renamed to gs_to_exit()... | |
87 | */ | |
88 | ||
89 | #ifdef dev_t_proc_encode_color | |
90 | # define gs_exit gs_to_exit | |
91 | #endif /* dev_t_proc_encode_color */ | |
92 | ||
93 | ||
94 | /* | |
95 | * CIE XYZ color constants... | |
96 | */ | |
97 | ||
98 | #define D65_X (0.412453 + 0.357580 + 0.180423) | |
99 | #define D65_Y (0.212671 + 0.715160 + 0.072169) | |
100 | #define D65_Z (0.019334 + 0.119193 + 0.950227) | |
101 | ||
102 | ||
103 | /* | |
104 | * Size of a tile in pixels... | |
105 | */ | |
106 | ||
107 | #define CUPS_TILE_SIZE 256 | |
108 | ||
109 | ||
110 | /* | |
111 | * Size of profile LUTs... | |
112 | */ | |
113 | ||
114 | #ifdef dev_t_proc_encode_color | |
115 | # define CUPS_MAX_VALUE frac_1 | |
116 | #else | |
117 | # define CUPS_MAX_VALUE gx_max_color_value | |
118 | #endif /* dev_t_proc_encode_color */ | |
119 | ||
120 | ||
121 | /* | |
122 | * Macros... | |
123 | */ | |
124 | ||
125 | #define x_dpi (pdev->HWResolution[0]) | |
126 | #define y_dpi (pdev->HWResolution[1]) | |
127 | #define cups ((gx_device_cups *)pdev) | |
128 | ||
129 | /* | |
130 | * Macros from <macros.h>; we can't include <macros.h> because it also | |
131 | * defines DEBUG, one of our flags to insert various debugging code. | |
132 | */ | |
133 | ||
134 | #ifndef max | |
135 | # define max(a,b) ((a)<(b) ? (b) : (a)) | |
136 | #endif /* !max */ | |
137 | ||
138 | #ifndef min | |
139 | # define min(a,b) ((a)>(b) ? (b) : (a)) | |
140 | #endif /* !min */ | |
141 | ||
142 | #ifndef abs | |
143 | # define abs(x) ((x)>=0 ? (x) : -(x)) | |
144 | #endif /* !abs */ | |
145 | ||
146 | ||
147 | /* | |
148 | * Procedures | |
149 | */ | |
150 | ||
151 | private dev_proc_close_device(cups_close); | |
152 | private dev_proc_get_initial_matrix(cups_get_matrix); | |
153 | private int cups_get_params(gx_device *, gs_param_list *); | |
154 | private dev_proc_open_device(cups_open); | |
155 | private int cups_print_pages(gx_device_printer *, FILE *, int); | |
156 | private int cups_put_params(gx_device *, gs_param_list *); | |
157 | private void cups_set_color_info(gx_device *); | |
158 | private dev_proc_sync_output(cups_sync_output); | |
159 | private prn_dev_proc_get_space_params(cups_get_space_params); | |
160 | ||
161 | #ifdef dev_t_proc_encode_color | |
162 | private cm_map_proc_gray(cups_map_gray); | |
163 | private cm_map_proc_rgb(cups_map_rgb); | |
164 | private cm_map_proc_cmyk(cups_map_cmyk); | |
165 | private dev_proc_decode_color(cups_decode_color); | |
166 | private dev_proc_encode_color(cups_encode_color); | |
167 | private dev_proc_get_color_mapping_procs(cups_get_color_mapping_procs); | |
168 | ||
169 | static const gx_cm_color_map_procs cups_color_mapping_procs = | |
170 | { | |
171 | cups_map_gray, | |
172 | cups_map_rgb, | |
173 | cups_map_cmyk | |
174 | }; | |
175 | #else | |
176 | private dev_proc_map_cmyk_color(cups_map_cmyk_color); | |
177 | private dev_proc_map_color_rgb(cups_map_color_rgb); | |
178 | private dev_proc_map_rgb_color(cups_map_rgb_color); | |
179 | #endif /* dev_t_proc_encode_color */ | |
180 | ||
181 | ||
182 | /* | |
183 | * The device descriptors... | |
184 | */ | |
185 | ||
186 | typedef struct gx_device_cups_s | |
187 | { | |
188 | gx_device_common; /* Standard GhostScript device stuff */ | |
189 | gx_prn_device_common; /* Standard printer device stuff */ | |
190 | int page; /* Page number */ | |
191 | cups_raster_t *stream; /* Raster stream */ | |
192 | cups_page_header_t header; /* PostScript page device info */ | |
193 | int landscape; /* Non-zero if this is landscape */ | |
194 | } gx_device_cups; | |
195 | ||
196 | private gx_device_procs cups_procs = | |
197 | { | |
198 | cups_open, | |
199 | cups_get_matrix, | |
200 | cups_sync_output, | |
201 | gdev_prn_output_page, | |
202 | cups_close, | |
203 | #ifdef dev_t_proc_encode_color | |
204 | NULL, /* map_rgb_color */ | |
205 | NULL, /* map_color_rgb */ | |
206 | #else | |
207 | cups_map_rgb_color, | |
208 | cups_map_color_rgb, | |
209 | #endif /* dev_t_proc_encode_color */ | |
210 | NULL, /* fill_rectangle */ | |
211 | NULL, /* tile_rectangle */ | |
212 | NULL, /* copy_mono */ | |
213 | NULL, /* copy_color */ | |
214 | NULL, /* draw_line */ | |
215 | gx_default_get_bits, | |
216 | cups_get_params, | |
217 | cups_put_params, | |
218 | #ifdef dev_t_proc_encode_color | |
219 | NULL, /* map_cmyk_color */ | |
220 | #else | |
221 | cups_map_cmyk_color, | |
222 | #endif /* dev_t_proc_encode_color */ | |
223 | NULL, /* get_xfont_procs */ | |
224 | NULL, /* get_xfont_device */ | |
225 | NULL, /* map_rgb_alpha_color */ | |
226 | gx_page_device_get_page_device, | |
227 | NULL, /* get_alpha_bits */ | |
228 | NULL, /* copy_alpha */ | |
229 | NULL, /* get_band */ | |
230 | NULL, /* copy_rop */ | |
231 | NULL, /* fill_path */ | |
232 | NULL, /* stroke_path */ | |
233 | NULL, /* fill_mask */ | |
234 | NULL, /* fill_trapezoid */ | |
235 | NULL, /* fill_parallelogram */ | |
236 | NULL, /* fill_triangle */ | |
237 | NULL, /* draw_thin_line */ | |
238 | NULL, /* begin_image */ | |
239 | NULL, /* image_data */ | |
240 | NULL, /* end_image */ | |
241 | NULL, /* strip_tile_rectangle */ | |
242 | NULL /* strip_copy_rop */ | |
243 | #ifdef dev_t_proc_encode_color | |
244 | , | |
245 | NULL, /* get_clipping_box */ | |
246 | NULL, /* begin_typed_image */ | |
247 | NULL, /* get_bits_rectangle */ | |
248 | NULL, /* map_color_rgb_alpha */ | |
249 | NULL, /* create_compositor */ | |
250 | NULL, /* get_hardware_params */ | |
251 | NULL, /* text_begin */ | |
252 | NULL, /* finish_copydevice */ | |
253 | NULL, /* begin_transparency_group */ | |
254 | NULL, /* end_transparency_group */ | |
255 | NULL, /* begin_transparency_mask */ | |
256 | NULL, /* end_transparency_mask */ | |
257 | NULL, /* discard_transparency_layer */ | |
258 | cups_get_color_mapping_procs, | |
259 | NULL, /* get_color_comp_index */ | |
260 | cups_encode_color, | |
261 | cups_decode_color | |
262 | #endif /* dev_t_proc_encode_color */ | |
263 | }; | |
264 | ||
265 | #define prn_device_body_copies(dtype, procs, dname, w10, h10, xdpi, ydpi, lo, to, lm, bm, rm, tm, ncomp, depth, mg, mc, dg, dc, print_pages)\ | |
266 | std_device_full_body_type(dtype, &procs, dname, &st_device_printer,\ | |
267 | (int)((long)(w10) * (xdpi) / 10),\ | |
268 | (int)((long)(h10) * (ydpi) / 10),\ | |
269 | xdpi, ydpi,\ | |
270 | ncomp, depth, mg, mc, dg, dc,\ | |
271 | -(lo) * (xdpi), -(to) * (ydpi),\ | |
272 | (lm) * 72.0, (bm) * 72.0,\ | |
273 | (rm) * 72.0, (tm) * 72.0\ | |
274 | ),\ | |
275 | prn_device_body_copies_rest_(print_pages) | |
276 | ||
277 | gx_device_cups gs_cups_device = | |
278 | { | |
279 | prn_device_body_copies(gx_device_cups,/* type */ | |
280 | cups_procs, /* procedures */ | |
281 | "cups", /* device name */ | |
282 | 85, /* initial width */ | |
283 | 110, /* initial height */ | |
284 | 100, /* initial x resolution */ | |
285 | 100, /* initial y resolution */ | |
286 | 0, /* initial left offset */ | |
287 | 0, /* initial top offset */ | |
288 | 0, /* initial left margin */ | |
289 | 0, /* initial bottom margin */ | |
290 | 0, /* initial right margin */ | |
291 | 0, /* initial top margin */ | |
292 | 1, /* number of color components */ | |
293 | 1, /* number of color bits */ | |
294 | 1, /* maximum gray value */ | |
295 | 0, /* maximum color value */ | |
296 | 2, /* number of gray values */ | |
297 | 0, /* number of color values */ | |
298 | cups_print_pages), | |
299 | /* print procedure */ | |
300 | 0, /* page */ | |
301 | NULL, /* stream */ | |
302 | { /* header */ | |
303 | "", /* MediaClass */ | |
304 | "", /* MediaColor */ | |
305 | "", /* MediaType */ | |
306 | "", /* OutputType */ | |
307 | 0, /* AdvanceDistance */ | |
308 | CUPS_ADVANCE_NONE, /* AdvanceMedia */ | |
309 | CUPS_FALSE, /* Collate */ | |
310 | CUPS_CUT_NONE, /* CutMedia */ | |
311 | CUPS_FALSE, /* Duplex */ | |
312 | { 100, 100 }, /* HWResolution */ | |
313 | { 0, 0, 612, 792 }, /* ImagingBoundingBox */ | |
314 | CUPS_FALSE, /* InsertSheet */ | |
315 | CUPS_JOG_NONE, /* Jog */ | |
316 | CUPS_EDGE_TOP, /* LeadingEdge */ | |
317 | { 0, 0 }, /* Margins */ | |
318 | CUPS_FALSE, /* ManualFeed */ | |
319 | 0, /* MediaPosition */ | |
320 | 0, /* MediaWeight */ | |
321 | CUPS_FALSE, /* MirrorPrint */ | |
322 | CUPS_FALSE, /* NegativePrint */ | |
323 | 1, /* NumCopies */ | |
324 | CUPS_ORIENT_0, /* Orientation */ | |
325 | CUPS_FALSE, /* OutputFaceUp */ | |
326 | { 612, 792 }, /* PageSize */ | |
327 | CUPS_FALSE, /* Separations */ | |
328 | CUPS_FALSE, /* TraySwitch */ | |
329 | CUPS_FALSE, /* Tumble */ | |
330 | 850, /* cupsWidth */ | |
331 | 1100, /* cupsHeight */ | |
332 | 0, /* cupsMediaType */ | |
333 | 1, /* cupsBitsPerColor */ | |
334 | 1, /* cupsBitsPerPixel */ | |
335 | 107, /* cupsBytesPerLine */ | |
336 | CUPS_ORDER_CHUNKED, /* cupsColorOrder */ | |
337 | CUPS_CSPACE_K, /* cupsColorSpace */ | |
338 | 0, /* cupsCompression */ | |
339 | 0, /* cupsRowCount */ | |
340 | 0, /* cupsRowFeed */ | |
341 | 0 /* cupsRowStep */ | |
342 | } | |
343 | }; | |
344 | ||
345 | /* | |
346 | * Globals... | |
347 | */ | |
348 | ||
349 | static gx_color_value cupsDecodeLUT[256]; | |
350 | /* Output color to RGB value LUT */ | |
351 | static unsigned char cupsEncodeLUT[gx_max_color_value + 1]; | |
352 | /* RGB value to output color LUT */ | |
353 | ||
354 | static ppd_file_t *cupsPPD = 0; /* PPD file for this device */ | |
355 | static char *cupsProfile = NULL; | |
356 | /* Current simple color profile string */ | |
357 | static int cupsHaveProfile = 0; | |
358 | /* Has a color profile been defined? */ | |
359 | static int cupsMatrix[3][3][CUPS_MAX_VALUE + 1]; | |
360 | /* Color transform matrix LUT */ | |
361 | static int cupsDensity[CUPS_MAX_VALUE + 1]; | |
362 | /* Density LUT */ | |
363 | static unsigned char cupsRevLower1[16] = | |
364 | { /* Lower 1-bit reversal table */ | |
365 | 0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e, | |
366 | 0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f | |
367 | }, | |
368 | cupsRevUpper1[16] = | |
369 | { /* Upper 1-bit reversal table */ | |
370 | 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, | |
371 | 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0 | |
372 | }, | |
373 | cupsRevLower2[16] = | |
374 | { /* Lower 2-bit reversal table */ | |
375 | 0x00, 0x04, 0x08, 0x0c, 0x01, 0x05, 0x09, 0x0d, | |
376 | 0x02, 0x06, 0x0a, 0x0e, 0x03, 0x07, 0x0b, 0x0f | |
377 | }, | |
378 | cupsRevUpper2[16] = | |
379 | { /* Upper 2-bit reversal table */ | |
380 | 0x00, 0x40, 0x80, 0xc0, 0x10, 0x50, 0x90, 0xd0, | |
381 | 0x20, 0x60, 0xa0, 0xe0, 0x30, 0x70, 0xb0, 0xf0 | |
382 | }; | |
383 | ||
384 | ||
385 | /* | |
386 | * Local functions... | |
387 | */ | |
388 | ||
389 | static double cups_map_cielab(double, double); | |
390 | static void cups_print_chunked(gx_device_printer *, unsigned char *, | |
391 | unsigned char *, int); | |
392 | static void cups_print_banded(gx_device_printer *, unsigned char *, | |
393 | unsigned char *, int); | |
394 | static void cups_print_planar(gx_device_printer *, unsigned char *, | |
395 | unsigned char *, int); | |
396 | ||
397 | /*static void cups_set_margins(gx_device *);*/ | |
398 | ||
399 | ||
400 | /* | |
401 | * 'cups_close()' - Close the output file. | |
402 | */ | |
403 | ||
404 | private int | |
405 | cups_close(gx_device *pdev) /* I - Device info */ | |
406 | { | |
407 | #ifdef DEBUG | |
408 | fprintf(stderr, "DEBUG2: cups_close(%p)\n", pdev); | |
409 | #endif /* DEBUG */ | |
410 | ||
411 | if (cups->stream != NULL) | |
412 | { | |
413 | cupsRasterClose(cups->stream); | |
414 | cups->stream = NULL; | |
415 | } | |
416 | ||
417 | #if 0 /* Can't do this here because put_params() might close the device */ | |
418 | if (cupsPPD != NULL) | |
419 | { | |
420 | ppdClose(cupsPPD); | |
421 | cupsPPD = NULL; | |
422 | } | |
423 | ||
424 | if (cupsProfile != NULL) | |
425 | { | |
426 | free(cupsProfile); | |
427 | cupsProfile = NULL; | |
428 | } | |
429 | #endif /* 0 */ | |
430 | ||
431 | return (gdev_prn_close(pdev)); | |
432 | } | |
433 | ||
434 | ||
435 | #ifdef dev_t_proc_encode_color | |
436 | /* | |
437 | * 'cups_decode_color()' - Decode a color value. | |
438 | */ | |
439 | ||
440 | private int /* O - Status (0 = OK) */ | |
441 | cups_decode_color(gx_device *pdev, /* I - Device info */ | |
442 | gx_color_index ci, /* I - Color index */ | |
443 | gx_color_value *cv) /* O - Colors */ | |
444 | { | |
445 | int i; /* Looping var */ | |
446 | int shift; /* Bits to shift */ | |
447 | int mask; /* Bits to mask */ | |
448 | ||
449 | ||
450 | if (cups->header.cupsColorSpace == CUPS_CSPACE_KCMYcm && | |
451 | cups->header.cupsBitsPerColor == 1) | |
452 | { | |
453 | /* | |
454 | * KCMYcm data is represented internally by Ghostscript as CMYK... | |
455 | */ | |
456 | ||
457 | cv[0] = (ci & 0x20) ? frac_1 : frac_0; | |
458 | cv[1] = (ci & 0x12) ? frac_1 : frac_0; | |
459 | cv[2] = (ci & 0x09) ? frac_1 : frac_0; | |
460 | cv[3] = (ci & 0x04) ? frac_1 : frac_0; | |
461 | } | |
462 | else | |
463 | { | |
464 | shift = cups->header.cupsBitsPerColor; | |
465 | mask = (1 << shift) - 1; | |
466 | ||
467 | for (i = cups->color_info.num_components - 1; i > 0; i --, ci >>= shift) | |
468 | cv[i] = cupsDecodeLUT[ci & mask]; | |
469 | ||
470 | cv[0] = cupsDecodeLUT[ci & mask]; | |
471 | } | |
472 | ||
473 | return (0); | |
474 | } | |
475 | ||
476 | ||
477 | /* | |
478 | * 'cups_encode_color()' - Encode a color value. | |
479 | */ | |
480 | ||
481 | private gx_color_index /* O - Color index */ | |
482 | cups_encode_color(gx_device *pdev, | |
483 | /* I - Device info */ | |
484 | const gx_color_value *cv) | |
485 | /* I - Colors */ | |
486 | { | |
487 | int i; /* Looping var */ | |
488 | gx_color_index ci; /* Color index */ | |
489 | int shift; /* Bits to shift */ | |
490 | ||
491 | ||
492 | /* | |
493 | * Encode the color index... | |
494 | */ | |
495 | ||
496 | shift = cups->header.cupsBitsPerColor; | |
497 | ||
498 | for (ci = cupsEncodeLUT[cv[0]], i = 1; | |
499 | i < cups->color_info.num_components; | |
500 | i ++) | |
501 | ci = (ci << shift) | cupsEncodeLUT[cv[i]]; | |
502 | ||
503 | /* | |
504 | * Handle 6-color output... | |
505 | */ | |
506 | ||
507 | if (cups->header.cupsColorSpace == CUPS_CSPACE_KCMYcm && | |
508 | cups->header.cupsBitsPerColor == 1) | |
509 | { | |
510 | /* | |
511 | * Welcome to hackville, where we map CMYK data to the | |
512 | * light inks in draft mode... Map blue to light magenta and | |
513 | * cyan and green to light cyan and yellow... | |
514 | */ | |
515 | ||
516 | ci <<= 2; /* Leave room for light inks */ | |
517 | ||
518 | if (ci == 0x18) /* Blue */ | |
519 | ci = 0x11; /* == cyan + light magenta */ | |
520 | else if (ci == 0x14) /* Green */ | |
521 | ci = 0x06; /* == light cyan + yellow */ | |
522 | } | |
523 | ||
524 | /* | |
525 | * Range check the return value... | |
526 | */ | |
527 | ||
528 | if (ci == gx_no_color_index) | |
529 | ci --; | |
530 | ||
531 | /* | |
532 | * Return the color index... | |
533 | */ | |
534 | ||
535 | return (ci); | |
536 | } | |
537 | ||
538 | ||
539 | /* | |
540 | * 'cups_get_color_mapping_procs()' - Get the list of color mapping procedures. | |
541 | */ | |
542 | ||
543 | private const gx_cm_color_map_procs * /* O - List of device procedures */ | |
544 | cups_get_color_mapping_procs(const gx_device *pdev) | |
545 | /* I - Device info */ | |
546 | { | |
547 | return (&cups_color_mapping_procs); | |
548 | } | |
549 | #endif /* dev_t_proc_encode_color */ | |
550 | ||
551 | ||
552 | /* | |
553 | * 'cups_get_matrix()' - Generate the default page matrix. | |
554 | */ | |
555 | ||
556 | private void | |
557 | cups_get_matrix(gx_device *pdev, /* I - Device info */ | |
558 | gs_matrix *pmat) /* O - Physical transform matrix */ | |
559 | { | |
560 | #ifdef DEBUG | |
561 | fprintf(stderr, "DEBUG2: cups_get_matrix(%p, %p)\n", pdev, pmat); | |
562 | #endif /* DEBUG */ | |
563 | ||
564 | /* | |
565 | * Set the raster width and height... | |
566 | */ | |
567 | ||
568 | cups->header.cupsWidth = cups->width; | |
569 | cups->header.cupsHeight = cups->height; | |
570 | ||
571 | /* | |
572 | * Set the transform matrix... | |
573 | */ | |
574 | ||
575 | fprintf(stderr, "DEBUG: cups->header.Duplex = %d\n", cups->header.Duplex); | |
576 | fprintf(stderr, "DEBUG: cups->page = %d\n", cups->page); | |
577 | ||
578 | if (cupsPPD) | |
579 | { | |
580 | fprintf(stderr, "DEBUG: cupsPPD = %p\n", cupsPPD); | |
581 | fprintf(stderr, "DEBUG: cupsPPD->flip_duplex = %d\n", cupsPPD->flip_duplex); | |
582 | } | |
583 | ||
584 | if (cups->landscape) | |
585 | { | |
586 | /* | |
587 | * Do landscape orientation... | |
588 | */ | |
589 | ||
590 | if (cups->header.Duplex && !cups->header.Tumble && | |
591 | cupsPPD && cupsPPD->flip_duplex && !(cups->page & 1)) | |
592 | { | |
593 | pmat->xx = 0.0; | |
594 | pmat->xy = (float)cups->header.HWResolution[0] / 72.0; | |
595 | pmat->yx = -(float)cups->header.HWResolution[1] / 72.0; | |
596 | pmat->yy = 0.0; | |
597 | pmat->tx = -(float)cups->header.HWResolution[0] * pdev->HWMargins[2] / 72.0; | |
598 | pmat->ty = (float)cups->header.HWResolution[1] * | |
599 | ((float)cups->header.PageSize[0] - pdev->HWMargins[3]) / 72.0; | |
600 | } | |
601 | else | |
602 | { | |
603 | pmat->xx = 0.0; | |
604 | pmat->xy = (float)cups->header.HWResolution[0] / 72.0; | |
605 | pmat->yx = (float)cups->header.HWResolution[1] / 72.0; | |
606 | pmat->yy = 0.0; | |
607 | pmat->tx = -(float)cups->header.HWResolution[0] * pdev->HWMargins[0] / 72.0; | |
608 | pmat->ty = -(float)cups->header.HWResolution[1] * pdev->HWMargins[1] / 72.0; | |
609 | } | |
610 | } | |
611 | else if (cups->header.Duplex && !cups->header.Tumble && | |
612 | cupsPPD && cupsPPD->flip_duplex && !(cups->page & 1)) | |
613 | { | |
614 | pmat->xx = (float)cups->header.HWResolution[0] / 72.0; | |
615 | pmat->xy = 0.0; | |
616 | pmat->yx = 0.0; | |
617 | pmat->yy = (float)cups->header.HWResolution[1] / 72.0; | |
618 | pmat->tx = -(float)cups->header.HWResolution[0] * pdev->HWMargins[2] / 72.0; | |
619 | pmat->ty = -(float)cups->header.HWResolution[1] * pdev->HWMargins[3] / 72.0; | |
620 | } | |
621 | else | |
622 | { | |
623 | pmat->xx = (float)cups->header.HWResolution[0] / 72.0; | |
624 | pmat->xy = 0.0; | |
625 | pmat->yx = 0.0; | |
626 | pmat->yy = -(float)cups->header.HWResolution[1] / 72.0; | |
627 | pmat->tx = -(float)cups->header.HWResolution[0] * pdev->HWMargins[0] / 72.0; | |
628 | pmat->ty = (float)cups->header.HWResolution[1] * | |
629 | ((float)cups->header.PageSize[1] - pdev->HWMargins[3]) / 72.0; | |
630 | } | |
631 | ||
632 | fprintf(stderr, "DEBUG: width = %d, height = %d\n", cups->width, | |
633 | cups->height); | |
634 | fprintf(stderr, "DEBUG: PageSize = [ %d %d ], HWResolution = [ %d %d ]\n", | |
635 | cups->header.PageSize[0], cups->header.PageSize[1], | |
636 | cups->header.HWResolution[0], cups->header.HWResolution[1]); | |
637 | fprintf(stderr, "DEBUG: HWMargins = [ %.3f %.3f %.3f %.3f ]\n", | |
638 | pdev->HWMargins[0], pdev->HWMargins[1], pdev->HWMargins[2], | |
639 | pdev->HWMargins[3]); | |
640 | fprintf(stderr, "DEBUG: matrix = [ %.3f %.3f %.3f %.3f %.3f %.3f ]\n", | |
641 | pmat->xx, pmat->xy, pmat->yx, pmat->yy, pmat->tx, pmat->ty); | |
642 | } | |
643 | ||
644 | ||
645 | /* | |
646 | * 'cups_get_params()' - Get pagedevice parameters. | |
647 | */ | |
648 | ||
649 | private int /* O - Error status */ | |
650 | cups_get_params(gx_device *pdev, /* I - Device info */ | |
651 | gs_param_list *plist) /* I - Parameter list */ | |
652 | { | |
653 | #ifdef CUPS_RASTER_SYNCv1 | |
654 | int i; /* Looping var */ | |
655 | char name[255]; /* Attribute name */ | |
656 | #endif /* CUPS_RASTER_SYNCv1 */ | |
657 | int code; /* Return code */ | |
658 | gs_param_string s; /* Temporary string value */ | |
659 | bool b; /* Temporary boolean value */ | |
660 | ||
661 | ||
662 | #ifdef DEBUG | |
663 | fprintf(stderr, "DEBUG2: cups_get_params(%p, %p)\n", pdev, plist); | |
664 | #endif /* DEBUG */ | |
665 | ||
666 | /* | |
667 | * First process the "standard" page device parameters... | |
668 | */ | |
669 | ||
670 | #ifdef DEBUG | |
671 | fputs("DEBUG2: before gdev_prn_get_params()\n", stderr); | |
672 | #endif /* DEBUG */ | |
673 | ||
674 | if ((code = gdev_prn_get_params(pdev, plist)) < 0) | |
675 | return (code); | |
676 | ||
677 | #ifdef DEBUG | |
678 | fputs("DEBUG2: after gdev_prn_get_params()\n", stderr); | |
679 | #endif /* DEBUG */ | |
680 | ||
681 | /* | |
682 | * Then write the CUPS parameters... | |
683 | */ | |
684 | ||
685 | #ifdef DEBUG | |
686 | fputs("DEBUG2: Adding MediaClass\n", stderr); | |
687 | #endif /* DEBUG */ | |
688 | ||
689 | param_string_from_string(s, cups->header.MediaClass); | |
690 | if ((code = param_write_string(plist, "MediaClass", &s)) < 0) | |
691 | return (code); | |
692 | ||
693 | #ifdef DEBUG | |
694 | fputs("DEBUG2: Adding AdvanceDistance\n", stderr); | |
695 | #endif /* DEBUG */ | |
696 | ||
697 | if ((code = param_write_int(plist, "AdvanceDistance", | |
698 | (int *)&(cups->header.AdvanceDistance))) < 0) | |
699 | return (code); | |
700 | ||
701 | #ifdef DEBUG | |
702 | fputs("DEBUG2: Adding AdvanceDistance\n", stderr); | |
703 | #endif /* DEBUG */ | |
704 | ||
705 | if ((code = param_write_int(plist, "AdvanceMedia", | |
706 | (int *)&(cups->header.AdvanceMedia))) < 0) | |
707 | return (code); | |
708 | ||
709 | #ifdef DEBUG | |
710 | fputs("DEBUG2: Adding Collate\n", stderr); | |
711 | #endif /* DEBUG */ | |
712 | ||
713 | b = cups->header.Collate; | |
714 | if ((code = param_write_bool(plist, "Collate", &b)) < 0) | |
715 | return (code); | |
716 | ||
717 | #ifdef DEBUG | |
718 | fputs("DEBUG2: Adding CutMedia\n", stderr); | |
719 | #endif /* DEBUG */ | |
720 | ||
721 | if ((code = param_write_int(plist, "CutMedia", | |
722 | (int *)&(cups->header.CutMedia))) < 0) | |
723 | return (code); | |
724 | ||
725 | #ifdef DEBUG | |
726 | fputs("DEBUG2: Adding InsertSheet\n", stderr); | |
727 | #endif /* DEBUG */ | |
728 | ||
729 | b = cups->header.InsertSheet; | |
730 | if ((code = param_write_bool(plist, "InsertSheet", &b)) < 0) | |
731 | return (code); | |
732 | ||
733 | #ifdef DEBUG | |
734 | fputs("DEBUG2: Adding Jog\n", stderr); | |
735 | #endif /* DEBUG */ | |
736 | ||
737 | if ((code = param_write_int(plist, "Jog", | |
738 | (int *)&(cups->header.Jog))) < 0) | |
739 | return (code); | |
740 | ||
741 | #ifdef DEBUG | |
742 | fputs("DEBUG2: Adding LeadingEdge\n", stderr); | |
743 | #endif /* DEBUG */ | |
744 | ||
745 | if ((code = param_write_int(plist, "LeadingEdge", | |
746 | (int *)&(cups->header.LeadingEdge))) < 0) | |
747 | return (code); | |
748 | ||
749 | #ifdef DEBUG | |
750 | fputs("DEBUG2: Adding ManualFeed\n", stderr); | |
751 | #endif /* DEBUG */ | |
752 | ||
753 | b = cups->header.ManualFeed; | |
754 | if ((code = param_write_bool(plist, "ManualFeed", &b)) < 0) | |
755 | return (code); | |
756 | ||
757 | #ifdef DEBUG | |
758 | fputs("DEBUG2: Adding MediaPosition\n", stderr); | |
759 | #endif /* DEBUG */ | |
760 | ||
761 | if ((code = param_write_int(plist, "MediaPosition", | |
762 | (int *)&(cups->header.MediaPosition))) < 0) | |
763 | return (code); | |
764 | ||
765 | #ifdef DEBUG | |
766 | fputs("DEBUG2: Adding MirrorPrint\n", stderr); | |
767 | #endif /* DEBUG */ | |
768 | ||
769 | b = cups->header.MirrorPrint; | |
770 | if ((code = param_write_bool(plist, "MirrorPrint", &b)) < 0) | |
771 | return (code); | |
772 | ||
773 | #ifdef DEBUG | |
774 | fputs("DEBUG2: Adding NegativePrint\n", stderr); | |
775 | #endif /* DEBUG */ | |
776 | ||
777 | b = cups->header.NegativePrint; | |
778 | if ((code = param_write_bool(plist, "NegativePrint", &b)) < 0) | |
779 | return (code); | |
780 | ||
781 | #ifdef DEBUG | |
782 | fputs("DEBUG2: Adding OutputFaceUp\n", stderr); | |
783 | #endif /* DEBUG */ | |
784 | ||
785 | b = cups->header.OutputFaceUp; | |
786 | if ((code = param_write_bool(plist, "OutputFaceUp", &b)) < 0) | |
787 | return (code); | |
788 | ||
789 | #ifdef DEBUG | |
790 | fputs("DEBUG2: Adding Separations\n", stderr); | |
791 | #endif /* DEBUG */ | |
792 | ||
793 | b = cups->header.Separations; | |
794 | if ((code = param_write_bool(plist, "Separations", &b)) < 0) | |
795 | return (code); | |
796 | ||
797 | #ifdef DEBUG | |
798 | fputs("DEBUG2: Adding TraySwitch\n", stderr); | |
799 | #endif /* DEBUG */ | |
800 | ||
801 | b = cups->header.TraySwitch; | |
802 | if ((code = param_write_bool(plist, "TraySwitch", &b)) < 0) | |
803 | return (code); | |
804 | ||
805 | #ifdef DEBUG | |
806 | fputs("DEBUG2: Adding Tumble\n", stderr); | |
807 | #endif /* DEBUG */ | |
808 | ||
809 | b = cups->header.Tumble; | |
810 | if ((code = param_write_bool(plist, "Tumble", &b)) < 0) | |
811 | return (code); | |
812 | ||
813 | #ifdef DEBUG | |
814 | fputs("DEBUG2: Adding cupsWidth\n", stderr); | |
815 | #endif /* DEBUG */ | |
816 | ||
817 | if ((code = param_write_int(plist, "cupsWidth", | |
818 | (int *)&(cups->header.cupsWidth))) < 0) | |
819 | return (code); | |
820 | ||
821 | #ifdef DEBUG | |
822 | fputs("DEBUG2: Adding cupsHeight\n", stderr); | |
823 | #endif /* DEBUG */ | |
824 | ||
825 | if ((code = param_write_int(plist, "cupsHeight", | |
826 | (int *)&(cups->header.cupsHeight))) < 0) | |
827 | return (code); | |
828 | ||
829 | #ifdef DEBUG | |
830 | fputs("DEBUG2: Adding cupsMediaType\n", stderr); | |
831 | #endif /* DEBUG */ | |
832 | ||
833 | if ((code = param_write_int(plist, "cupsMediaType", | |
834 | (int *)&(cups->header.cupsMediaType))) < 0) | |
835 | return (code); | |
836 | ||
837 | #ifdef DEBUG | |
838 | fputs("DEBUG2: Adding cupsBitsPerColor\n", stderr); | |
839 | #endif /* DEBUG */ | |
840 | ||
841 | if ((code = param_write_int(plist, "cupsBitsPerColor", | |
842 | (int *)&(cups->header.cupsBitsPerColor))) < 0) | |
843 | return (code); | |
844 | ||
845 | #ifdef DEBUG | |
846 | fputs("DEBUG2: Adding cupsBitsPerPixel\n", stderr); | |
847 | #endif /* DEBUG */ | |
848 | ||
849 | if ((code = param_write_int(plist, "cupsBitsPerPixel", | |
850 | (int *)&(cups->header.cupsBitsPerPixel))) < 0) | |
851 | return (code); | |
852 | ||
853 | #ifdef DEBUG | |
854 | fputs("DEBUG2: Adding cupsBytesPerLine\n", stderr); | |
855 | #endif /* DEBUG */ | |
856 | ||
857 | if ((code = param_write_int(plist, "cupsBytesPerLine", | |
858 | (int *)&(cups->header.cupsBytesPerLine))) < 0) | |
859 | return (code); | |
860 | ||
861 | #ifdef DEBUG | |
862 | fputs("DEBUG2: Adding cupsColorOrder\n", stderr); | |
863 | #endif /* DEBUG */ | |
864 | ||
865 | if ((code = param_write_int(plist, "cupsColorOrder", | |
866 | (int *)&(cups->header.cupsColorOrder))) < 0) | |
867 | return (code); | |
868 | ||
869 | #ifdef DEBUG | |
870 | fputs("DEBUG2: Adding cupsColorSpace\n", stderr); | |
871 | #endif /* DEBUG */ | |
872 | ||
873 | if ((code = param_write_int(plist, "cupsColorSpace", | |
874 | (int *)&(cups->header.cupsColorSpace))) < 0) | |
875 | return (code); | |
876 | ||
877 | #ifdef DEBUG | |
878 | fputs("DEBUG2: Adding cupsCompression\n", stderr); | |
879 | #endif /* DEBUG */ | |
880 | ||
881 | if ((code = param_write_int(plist, "cupsCompression", | |
882 | (int *)&(cups->header.cupsCompression))) < 0) | |
883 | return (code); | |
884 | ||
885 | #ifdef DEBUG | |
886 | fputs("DEBUG2: Adding cupsRowCount\n", stderr); | |
887 | #endif /* DEBUG */ | |
888 | ||
889 | if ((code = param_write_int(plist, "cupsRowCount", | |
890 | (int *)&(cups->header.cupsRowCount))) < 0) | |
891 | return (code); | |
892 | ||
893 | #ifdef DEBUG | |
894 | fputs("DEBUG2: Adding cupsRowFeed\n", stderr); | |
895 | #endif /* DEBUG */ | |
896 | ||
897 | if ((code = param_write_int(plist, "cupsRowFeed", | |
898 | (int *)&(cups->header.cupsRowFeed))) < 0) | |
899 | return (code); | |
900 | ||
901 | #ifdef DEBUG | |
902 | fputs("DEBUG2: Adding cupsRowStep\n", stderr); | |
903 | #endif /* DEBUG */ | |
904 | ||
905 | if ((code = param_write_int(plist, "cupsRowStep", | |
906 | (int *)&(cups->header.cupsRowStep))) < 0) | |
907 | return (code); | |
908 | ||
909 | #ifdef CUPS_RASTER_SYNCv1 | |
910 | # ifdef DEBUG | |
911 | fputs("DEBUG2: Adding cupsNumColors\n", stderr); | |
912 | # endif /* DEBUG */ | |
913 | ||
914 | if ((code = param_write_int(plist, "cupsNumColors", | |
915 | (int *)&(cups->header.cupsNumColors))) < 0) | |
916 | return (code); | |
917 | ||
918 | # ifdef DEBUG | |
919 | fputs("DEBUG2: Adding cupsInteger\n", stderr); | |
920 | # endif /* DEBUG */ | |
921 | ||
922 | for (i = 0; i < 16; i ++) | |
923 | { | |
924 | sprintf(name, "cupsInteger%d", i); | |
925 | if ((code = param_write_int(plist, name, | |
926 | (int *)(cups->header.cupsInteger + i))) < 0) | |
927 | return (code); | |
928 | } | |
929 | ||
930 | # ifdef DEBUG | |
931 | fputs("DEBUG2: Adding cupsReal\n", stderr); | |
932 | # endif /* DEBUG */ | |
933 | ||
934 | for (i = 0; i < 16; i ++) | |
935 | { | |
936 | sprintf(name, "cupsReal%d", i); | |
937 | if ((code = param_write_float(plist, name, | |
938 | cups->header.cupsReal + i)) < 0) | |
939 | return (code); | |
940 | } | |
941 | ||
942 | # ifdef DEBUG | |
943 | fputs("DEBUG2: Adding cupsString\n", stderr); | |
944 | # endif /* DEBUG */ | |
945 | ||
946 | for (i = 0; i < 16; i ++) | |
947 | { | |
948 | sprintf(name, "cupsReal%d", i); | |
949 | param_string_from_string(s, cups->header.cupsString[i]); | |
950 | if ((code = param_write_string(plist, name, &s)) < 0) | |
951 | return (code); | |
952 | } | |
953 | ||
954 | # ifdef DEBUG | |
955 | fputs("DEBUG2: Adding cupsMarkerType\n", stderr); | |
956 | # endif /* DEBUG */ | |
957 | ||
958 | param_string_from_string(s, cups->header.cupsMarkerType); | |
959 | if ((code = param_write_string(plist, "cupsMarkerType", &s)) < 0) | |
960 | return (code); | |
961 | ||
962 | # ifdef DEBUG | |
963 | fputs("DEBUG2: Adding cupsRenderingIntent\n", stderr); | |
964 | # endif /* DEBUG */ | |
965 | ||
966 | param_string_from_string(s, cups->header.cupsRenderingIntent); | |
967 | if ((code = param_write_string(plist, "cupsRenderingIntent", &s)) < 0) | |
968 | return (code); | |
969 | #endif /* CUPS_RASTER_SYNCv1 */ | |
970 | ||
971 | #ifdef DEBUG | |
972 | fputs("DEBUG2: Leaving cups_get_params()\n", stderr); | |
973 | #endif /* DEBUG */ | |
974 | ||
975 | return (0); | |
976 | } | |
977 | ||
978 | ||
979 | /* | |
980 | * 'cups_get_space_params()' - Get space parameters from the RIP_CACHE env var. | |
981 | */ | |
982 | ||
983 | void | |
984 | cups_get_space_params(const gx_device_printer *pdev, | |
985 | /* I - Printer device */ | |
986 | gdev_prn_space_params *space_params) | |
987 | /* O - Space parameters */ | |
988 | { | |
989 | float cache_size; /* Size of tile cache in bytes */ | |
990 | char *cache_env, /* Cache size environment variable */ | |
991 | cache_units[255]; /* Cache size units */ | |
992 | ||
993 | ||
994 | #ifdef DEBUG | |
995 | fprintf(stderr, "DEBUG2: cups_get_space_params(%p, %p)\n", pdev, space_params); | |
996 | #endif /* DEBUG */ | |
997 | ||
998 | if ((cache_env = getenv("RIP_MAX_CACHE")) != NULL) | |
999 | { | |
1000 | switch (sscanf(cache_env, "%f%254s", &cache_size, cache_units)) | |
1001 | { | |
1002 | case 0 : | |
1003 | cache_size = 8 * 1024 * 1024; | |
1004 | break; | |
1005 | case 1 : | |
1006 | cache_size *= 4 * CUPS_TILE_SIZE * CUPS_TILE_SIZE; | |
1007 | break; | |
1008 | case 2 : | |
1009 | if (tolower(cache_units[0]) == 'g') | |
1010 | cache_size *= 1024 * 1024 * 1024; | |
1011 | else if (tolower(cache_units[0]) == 'm') | |
1012 | cache_size *= 1024 * 1024; | |
1013 | else if (tolower(cache_units[0]) == 'k') | |
1014 | cache_size *= 1024; | |
1015 | else if (tolower(cache_units[0]) == 't') | |
1016 | cache_size *= 4 * CUPS_TILE_SIZE * CUPS_TILE_SIZE; | |
1017 | break; | |
1018 | } | |
1019 | } | |
1020 | else | |
1021 | cache_size = 8 * 1024 * 1024; | |
1022 | ||
1023 | fprintf(stderr, "DEBUG: cache_size = %.0f\n", cache_size); | |
1024 | ||
1025 | space_params->MaxBitmap = (int)cache_size; | |
1026 | space_params->BufferSpace = (int)cache_size / 10; | |
1027 | } | |
1028 | ||
1029 | ||
1030 | /* | |
1031 | * 'cups_map_cielab()' - Map CIE Lab transformation... | |
1032 | */ | |
1033 | ||
1034 | static double /* O - Adjusted color value */ | |
1035 | cups_map_cielab(double x, /* I - Raw color value */ | |
1036 | double xn) /* I - Whitepoint color value */ | |
1037 | { | |
1038 | double x_xn; /* Fraction of whitepoint */ | |
1039 | ||
1040 | ||
1041 | x_xn = x / xn; | |
1042 | ||
1043 | if (x_xn > 0.008856) | |
1044 | return (cbrt(x_xn)); | |
1045 | else | |
1046 | return (7.787 * x_xn + 16.0 / 116.0); | |
1047 | } | |
1048 | ||
1049 | ||
1050 | #ifdef dev_t_proc_encode_color | |
1051 | /* | |
1052 | * 'cups_map_cmyk()' - Map a CMYK color value to device colors. | |
1053 | */ | |
1054 | ||
1055 | private void | |
1056 | cups_map_cmyk(gx_device *pdev, /* I - Device info */ | |
1057 | frac c, /* I - Cyan value */ | |
1058 | frac m, /* I - Magenta value */ | |
1059 | frac y, /* I - Yellow value */ | |
1060 | frac k, /* I - Black value */ | |
1061 | frac *out) /* O - Device colors */ | |
1062 | { | |
1063 | int c0, c1, c2; /* Temporary color values */ | |
1064 | float rr, rg, rb, /* Real RGB colors */ | |
1065 | ciex, ciey, ciez, /* CIE XYZ colors */ | |
1066 | ciey_yn, /* Normalized luminance */ | |
1067 | ciel, ciea, cieb; /* CIE Lab colors */ | |
1068 | ||
1069 | ||
1070 | #ifdef DEBUG | |
1071 | fprintf(stderr, "DEBUG2: cups_map_cmyk(%p, %d, %d, %d, %d, %p)\n", | |
1072 | pdev, c, m, y, k, out); | |
1073 | #endif /* DEBUG */ | |
1074 | ||
1075 | /* | |
1076 | * Convert the CMYK color to the destination colorspace... | |
1077 | */ | |
1078 | ||
1079 | switch (cups->header.cupsColorSpace) | |
1080 | { | |
1081 | case CUPS_CSPACE_W : | |
1082 | c0 = frac_1 - (c * 31 + m * 61 + y * 8) / 100 - k; | |
1083 | ||
1084 | if (c0 < 0) | |
1085 | out[0] = 0; | |
1086 | else if (c0 > frac_1) | |
1087 | out[0] = (frac)cupsDensity[frac_1]; | |
1088 | else | |
1089 | out[0] = (frac)cupsDensity[c0]; | |
1090 | break; | |
1091 | ||
1092 | case CUPS_CSPACE_RGBA : | |
1093 | out[3] = frac_1; | |
1094 | ||
1095 | case CUPS_CSPACE_RGB : | |
1096 | c0 = frac_1 - c - k; | |
1097 | c1 = frac_1 - m - k; | |
1098 | c2 = frac_1 - y - k; | |
1099 | ||
1100 | if (c0 < 0) | |
1101 | out[0] = 0; | |
1102 | else if (c0 > frac_1) | |
1103 | out[0] = (frac)cupsDensity[frac_1]; | |
1104 | else | |
1105 | out[0] = (frac)cupsDensity[c0]; | |
1106 | ||
1107 | if (c1 < 0) | |
1108 | out[1] = 0; | |
1109 | else if (c1 > frac_1) | |
1110 | out[1] = (frac)cupsDensity[frac_1]; | |
1111 | else | |
1112 | out[1] = (frac)cupsDensity[c1]; | |
1113 | ||
1114 | if (c2 < 0) | |
1115 | out[2] = 0; | |
1116 | else if (c2 > frac_1) | |
1117 | out[2] = (frac)cupsDensity[frac_1]; | |
1118 | else | |
1119 | out[2] = (frac)cupsDensity[c2]; | |
1120 | break; | |
1121 | ||
1122 | default : | |
1123 | case CUPS_CSPACE_K : | |
1124 | c0 = (c * 31 + m * 61 + y * 8) / 100 + k; | |
1125 | ||
1126 | if (c0 < 0) | |
1127 | out[0] = 0; | |
1128 | else if (c0 > frac_1) | |
1129 | out[0] = (frac)cupsDensity[frac_1]; | |
1130 | else | |
1131 | out[0] = (frac)cupsDensity[c0]; | |
1132 | break; | |
1133 | ||
1134 | case CUPS_CSPACE_CMY : | |
1135 | c0 = c + k; | |
1136 | c1 = m + k; | |
1137 | c2 = y + k; | |
1138 | ||
1139 | if (c0 < 0) | |
1140 | out[0] = 0; | |
1141 | else if (c0 > frac_1) | |
1142 | out[0] = (frac)cupsDensity[frac_1]; | |
1143 | else | |
1144 | out[0] = (frac)cupsDensity[c0]; | |
1145 | ||
1146 | if (c1 < 0) | |
1147 | out[1] = 0; | |
1148 | else if (c1 > frac_1) | |
1149 | out[1] = (frac)cupsDensity[frac_1]; | |
1150 | else | |
1151 | out[1] = (frac)cupsDensity[c1]; | |
1152 | ||
1153 | if (c2 < 0) | |
1154 | out[2] = 0; | |
1155 | else if (c2 > frac_1) | |
1156 | out[2] = (frac)cupsDensity[frac_1]; | |
1157 | else | |
1158 | out[2] = (frac)cupsDensity[c2]; | |
1159 | break; | |
1160 | ||
1161 | case CUPS_CSPACE_YMC : | |
1162 | c0 = y + k; | |
1163 | c1 = m + k; | |
1164 | c2 = c + k; | |
1165 | ||
1166 | if (c0 < 0) | |
1167 | out[0] = 0; | |
1168 | else if (c0 > frac_1) | |
1169 | out[0] = (frac)cupsDensity[frac_1]; | |
1170 | else | |
1171 | out[0] = (frac)cupsDensity[c0]; | |
1172 | ||
1173 | if (c1 < 0) | |
1174 | out[1] = 0; | |
1175 | else if (c1 > frac_1) | |
1176 | out[1] = (frac)cupsDensity[frac_1]; | |
1177 | else | |
1178 | out[1] = (frac)cupsDensity[c1]; | |
1179 | ||
1180 | if (c2 < 0) | |
1181 | out[2] = 0; | |
1182 | else if (c2 > frac_1) | |
1183 | out[2] = (frac)cupsDensity[frac_1]; | |
1184 | else | |
1185 | out[2] = (frac)cupsDensity[c2]; | |
1186 | break; | |
1187 | ||
1188 | case CUPS_CSPACE_CMYK : | |
1189 | if (c < 0) | |
1190 | out[0] = 0; | |
1191 | else if (c > frac_1) | |
1192 | out[0] = (frac)cupsDensity[frac_1]; | |
1193 | else | |
1194 | out[0] = (frac)cupsDensity[c]; | |
1195 | ||
1196 | if (m < 0) | |
1197 | out[1] = 0; | |
1198 | else if (m > frac_1) | |
1199 | out[1] = (frac)cupsDensity[frac_1]; | |
1200 | else | |
1201 | out[1] = (frac)cupsDensity[m]; | |
1202 | ||
1203 | if (y < 0) | |
1204 | out[2] = 0; | |
1205 | else if (y > frac_1) | |
1206 | out[2] = (frac)cupsDensity[frac_1]; | |
1207 | else | |
1208 | out[2] = (frac)cupsDensity[y]; | |
1209 | ||
1210 | if (k < 0) | |
1211 | out[3] = 0; | |
1212 | else if (k > frac_1) | |
1213 | out[3] = (frac)cupsDensity[frac_1]; | |
1214 | else | |
1215 | out[3] = (frac)cupsDensity[k]; | |
1216 | break; | |
1217 | ||
1218 | case CUPS_CSPACE_YMCK : | |
1219 | case CUPS_CSPACE_GMCK : | |
1220 | case CUPS_CSPACE_GMCS : | |
1221 | if (y < 0) | |
1222 | out[0] = 0; | |
1223 | else if (y > frac_1) | |
1224 | out[0] = (frac)cupsDensity[frac_1]; | |
1225 | else | |
1226 | out[0] = (frac)cupsDensity[y]; | |
1227 | ||
1228 | if (m < 0) | |
1229 | out[1] = 0; | |
1230 | else if (m > frac_1) | |
1231 | out[1] = (frac)cupsDensity[frac_1]; | |
1232 | else | |
1233 | out[1] = (frac)cupsDensity[m]; | |
1234 | ||
1235 | if (c < 0) | |
1236 | out[2] = 0; | |
1237 | else if (c > frac_1) | |
1238 | out[2] = (frac)cupsDensity[frac_1]; | |
1239 | else | |
1240 | out[2] = (frac)cupsDensity[c]; | |
1241 | ||
1242 | if (k < 0) | |
1243 | out[3] = 0; | |
1244 | else if (k > frac_1) | |
1245 | out[3] = (frac)cupsDensity[frac_1]; | |
1246 | else | |
1247 | out[3] = (frac)cupsDensity[k]; | |
1248 | break; | |
1249 | ||
1250 | case CUPS_CSPACE_KCMYcm : | |
1251 | case CUPS_CSPACE_KCMY : | |
1252 | if (k < 0) | |
1253 | out[0] = 0; | |
1254 | else if (k > frac_1) | |
1255 | out[0] = (frac)cupsDensity[frac_1]; | |
1256 | else | |
1257 | out[0] = (frac)cupsDensity[k]; | |
1258 | ||
1259 | if (c < 0) | |
1260 | out[1] = 0; | |
1261 | else if (c > frac_1) | |
1262 | out[1] = (frac)cupsDensity[frac_1]; | |
1263 | else | |
1264 | out[1] = (frac)cupsDensity[c]; | |
1265 | ||
1266 | if (m < 0) | |
1267 | out[2] = 0; | |
1268 | else if (m > frac_1) | |
1269 | out[2] = (frac)cupsDensity[frac_1]; | |
1270 | else | |
1271 | out[2] = (frac)cupsDensity[m]; | |
1272 | ||
1273 | if (y < 0) | |
1274 | out[3] = 0; | |
1275 | else if (y > frac_1) | |
1276 | out[3] = (frac)cupsDensity[frac_1]; | |
1277 | else | |
1278 | out[3] = (frac)cupsDensity[y]; | |
1279 | break; | |
1280 | ||
1281 | # ifdef CUPS_RASTER_HAVE_COLORIMETRIC | |
1282 | case CUPS_CSPACE_CIEXYZ : | |
1283 | case CUPS_CSPACE_CIELab : | |
1284 | case CUPS_CSPACE_ICC1 : | |
1285 | case CUPS_CSPACE_ICC2 : | |
1286 | case CUPS_CSPACE_ICC3 : | |
1287 | case CUPS_CSPACE_ICC4 : | |
1288 | case CUPS_CSPACE_ICC5 : | |
1289 | case CUPS_CSPACE_ICC6 : | |
1290 | case CUPS_CSPACE_ICC7 : | |
1291 | case CUPS_CSPACE_ICC8 : | |
1292 | case CUPS_CSPACE_ICC9 : | |
1293 | case CUPS_CSPACE_ICCA : | |
1294 | case CUPS_CSPACE_ICCB : | |
1295 | case CUPS_CSPACE_ICCC : | |
1296 | case CUPS_CSPACE_ICCD : | |
1297 | case CUPS_CSPACE_ICCE : | |
1298 | case CUPS_CSPACE_ICCF : | |
1299 | /* | |
1300 | * Convert CMYK to sRGB... | |
1301 | */ | |
1302 | ||
1303 | c0 = frac_1 - c - k; | |
1304 | c1 = frac_1 - m - k; | |
1305 | c2 = frac_1 - y - k; | |
1306 | ||
1307 | if (c0 < 0) | |
1308 | c0 = 0; | |
1309 | else if (c0 > frac_1) | |
1310 | c0 = frac_1; | |
1311 | ||
1312 | if (c1 < 0) | |
1313 | c1 = 0; | |
1314 | else if (c1 > frac_1) | |
1315 | c1 = frac_1; | |
1316 | ||
1317 | if (c2 < 0) | |
1318 | c2 = 0; | |
1319 | else if (c2 > frac_1) | |
1320 | c2 = frac_1; | |
1321 | ||
1322 | /* | |
1323 | * Convert sRGB to linear RGB... | |
1324 | */ | |
1325 | ||
1326 | rr = pow((double)c0 / (double)frac_1, 0.58823529412); | |
1327 | rg = pow((double)c1 / (double)frac_1, 0.58823529412); | |
1328 | rb = pow((double)c2 / (double)frac_1, 0.58823529412); | |
1329 | ||
1330 | /* | |
1331 | * Convert to CIE XYZ... | |
1332 | */ | |
1333 | ||
1334 | ciex = 0.412453 * rr + 0.357580 * rg + 0.180423 * rb; | |
1335 | ciey = 0.212671 * rr + 0.715160 * rg + 0.072169 * rb; | |
1336 | ciez = 0.019334 * rr + 0.119193 * rg + 0.950227 * rb; | |
1337 | ||
1338 | if (cups->header.cupsColorSpace == CUPS_CSPACE_CIEXYZ) | |
1339 | { | |
1340 | /* | |
1341 | * Convert to an integer XYZ color value... | |
1342 | */ | |
1343 | ||
1344 | if (ciex > 1.0) | |
1345 | c0 = frac_1; | |
1346 | else if (ciex > 0.0) | |
1347 | c0 = (int)(ciex * frac_1); | |
1348 | else | |
1349 | c0 = 0; | |
1350 | ||
1351 | if (ciey > 1.0) | |
1352 | c1 = frac_1; | |
1353 | else if (ciey > 0.0) | |
1354 | c1 = (int)(ciey * frac_1); | |
1355 | else | |
1356 | c1 = 0; | |
1357 | ||
1358 | if (ciez > 1.0) | |
1359 | c2 = frac_1; | |
1360 | else if (ciez > 0.0) | |
1361 | c2 = (int)(ciez * frac_1); | |
1362 | else | |
1363 | c2 = 0; | |
1364 | } | |
1365 | else | |
1366 | { | |
1367 | /* | |
1368 | * Convert CIE XYZ to Lab... | |
1369 | */ | |
1370 | ||
1371 | ciey_yn = ciey / D65_Y; | |
1372 | ||
1373 | if (ciey_yn > 0.008856) | |
1374 | ciel = 116 * cbrt(ciey_yn) - 16; | |
1375 | else | |
1376 | ciel = 903.3 * ciey_yn; | |
1377 | ||
1378 | ciea = 500 * (cups_map_cielab(ciex, D65_X) - | |
1379 | cups_map_cielab(ciey, D65_Y)); | |
1380 | cieb = 200 * (cups_map_cielab(ciey, D65_Y) - | |
1381 | cups_map_cielab(ciez, D65_Z)); | |
1382 | ||
1383 | /* | |
1384 | * Scale the L value and bias the a and b values by 128 | |
1385 | * so that all values are in the range of 0 to 255. | |
1386 | */ | |
1387 | ||
1388 | ciel *= 2.55; | |
1389 | ciea += 128; | |
1390 | cieb += 128; | |
1391 | ||
1392 | /* | |
1393 | * Convert to frac values... | |
1394 | */ | |
1395 | ||
1396 | if (ciel < 0.0) | |
1397 | c0 = 0; | |
1398 | else if (ciel < 255.0) | |
1399 | c0 = (int)(ciel * frac_1 / 255.0); | |
1400 | else | |
1401 | c0 = frac_1; | |
1402 | ||
1403 | if (ciea < 0.0) | |
1404 | c1 = 0; | |
1405 | else if (ciea < 255.0) | |
1406 | c1 = (int)(ciea * frac_1 / 255.0); | |
1407 | else | |
1408 | c1 = frac_1; | |
1409 | ||
1410 | if (cieb < 0.0) | |
1411 | c2 = 0; | |
1412 | else if (cieb < 255.0) | |
1413 | c2 = (int)(cieb * frac_1 / 255.0); | |
1414 | else | |
1415 | c2 = frac_1; | |
1416 | } | |
1417 | ||
1418 | /* | |
1419 | * Put the final color value together... | |
1420 | */ | |
1421 | ||
1422 | out[0] = c0; | |
1423 | out[1] = c1; | |
1424 | out[2] = c2; | |
1425 | break; | |
1426 | # endif /* CUPS_RASTER_HAVE_COLORIMETRIC */ | |
1427 | } | |
1428 | ||
1429 | switch (cups->color_info.num_components) | |
1430 | { | |
1431 | default : | |
1432 | case 1 : | |
1433 | #ifdef DEBUG | |
1434 | fprintf(stderr, "DEBUG2: \\=== COLOR %d\n", out[0]); | |
1435 | #endif /* DEBUG */ | |
1436 | break; | |
1437 | ||
1438 | case 3 : | |
1439 | #ifdef DEBUG | |
1440 | fprintf(stderr, "DEBUG2: \\=== COLOR %d, %d, %d\n", | |
1441 | out[0], out[1], out[2]); | |
1442 | #endif /* DEBUG */ | |
1443 | break; | |
1444 | ||
1445 | case 4 : | |
1446 | #ifdef DEBUG | |
1447 | fprintf(stderr, "DEBUG2: \\=== COLOR %d, %d, %d, %d\n", | |
1448 | out[0], out[1], out[2], out[3]); | |
1449 | #endif /* DEBUG */ | |
1450 | break; | |
1451 | } | |
1452 | } | |
1453 | ||
1454 | ||
1455 | /* | |
1456 | * 'cups_map_gray()' - Map a grayscale value to device colors. | |
1457 | */ | |
1458 | ||
1459 | private void | |
1460 | cups_map_gray(gx_device *pdev, /* I - Device info */ | |
1461 | frac g, /* I - Grayscale value */ | |
1462 | frac *out) /* O - Device colors */ | |
1463 | { | |
1464 | #ifdef DEBUG | |
1465 | fprintf(stderr, "DEBUG2: cups_map_gray(%p, %d, %p)\n", | |
1466 | pdev, g, out); | |
1467 | #endif /* DEBUG */ | |
1468 | ||
1469 | /* | |
1470 | * Just use the CMYK mapper... | |
1471 | */ | |
1472 | ||
1473 | cups_map_cmyk(pdev, 0, 0, 0, frac_1 - g, out); | |
1474 | } | |
1475 | ||
1476 | ||
1477 | /* | |
1478 | * 'cups_map_rgb()' - Map a RGB color value to device colors. | |
1479 | */ | |
1480 | ||
1481 | private void | |
1482 | cups_map_rgb(gx_device *pdev, | |
1483 | /* I - Device info */ | |
1484 | const gs_imager_state *pis,/* I - Device state */ | |
1485 | frac r, /* I - Red value */ | |
1486 | frac g, /* I - Green value */ | |
1487 | frac b, /* I - Blue value */ | |
1488 | frac *out)/* O - Device colors */ | |
1489 | { | |
1490 | frac c, m, y, k; /* CMYK values */ | |
1491 | frac mk; /* Maximum K value */ | |
1492 | int tc, tm, ty; /* Temporary color values */ | |
1493 | ||
1494 | ||
1495 | #ifdef DEBUG | |
1496 | fprintf(stderr, "DEBUG2: cups_map_rgb(%p, %p, %d, %d, %d, %p)\n", | |
1497 | pdev, pis, r, g, b, out); | |
1498 | #endif /* DEBUG */ | |
1499 | ||
1500 | /* | |
1501 | * Compute CMYK values... | |
1502 | */ | |
1503 | ||
1504 | c = frac_1 - r; | |
1505 | m = frac_1 - g; | |
1506 | y = frac_1 - b; | |
1507 | k = min(c, min(m, y)); | |
1508 | ||
1509 | if ((mk = max(c, max(m, y))) > k) | |
1510 | k = (int)((float)k * (float)k * (float)k / ((float)mk * (float)mk)); | |
1511 | ||
1512 | c -= k; | |
1513 | m -= k; | |
1514 | y -= k; | |
1515 | ||
1516 | /* | |
1517 | * Do color correction as needed... | |
1518 | */ | |
1519 | ||
1520 | if (cupsHaveProfile) | |
1521 | { | |
1522 | /* | |
1523 | * Color correct CMY... | |
1524 | */ | |
1525 | ||
1526 | tc = cupsMatrix[0][0][c] + | |
1527 | cupsMatrix[0][1][m] + | |
1528 | cupsMatrix[0][2][y]; | |
1529 | tm = cupsMatrix[1][0][c] + | |
1530 | cupsMatrix[1][1][m] + | |
1531 | cupsMatrix[1][2][y]; | |
1532 | ty = cupsMatrix[2][0][c] + | |
1533 | cupsMatrix[2][1][m] + | |
1534 | cupsMatrix[2][2][y]; | |
1535 | ||
1536 | if (tc < 0) | |
1537 | c = 0; | |
1538 | else if (tc > frac_1) | |
1539 | c = frac_1; | |
1540 | else | |
1541 | c = (frac)tc; | |
1542 | ||
1543 | if (tm < 0) | |
1544 | m = 0; | |
1545 | else if (tm > frac_1) | |
1546 | m = frac_1; | |
1547 | else | |
1548 | m = (frac)tm; | |
1549 | ||
1550 | if (ty < 0) | |
1551 | y = 0; | |
1552 | else if (ty > frac_1) | |
1553 | y = frac_1; | |
1554 | else | |
1555 | y = (frac)ty; | |
1556 | } | |
1557 | ||
1558 | /* | |
1559 | * Use the CMYK mapping function to produce the device colors... | |
1560 | */ | |
1561 | ||
1562 | cups_map_cmyk(pdev, c, m, y, k, out); | |
1563 | } | |
1564 | #else | |
1565 | /* | |
1566 | * 'cups_map_cmyk_color()' - Map a CMYK color to a color index. | |
1567 | * | |
1568 | * This function is only called when a 4 or 6 color colorspace is | |
1569 | * selected for output. CMYK colors are *not* corrected but *are* | |
1570 | * density adjusted. | |
1571 | */ | |
1572 | ||
1573 | private gx_color_index /* O - Color index */ | |
1574 | cups_map_cmyk_color(gx_device *pdev, | |
1575 | /* I - Device info */ | |
1576 | gx_color_value c, /* I - Cyan value */ | |
1577 | gx_color_value m, /* I - Magenta value */ | |
1578 | gx_color_value y, /* I - Yellow value */ | |
1579 | gx_color_value k) /* I - Black value */ | |
1580 | { | |
1581 | gx_color_index i; /* Temporary index */ | |
1582 | gx_color_value ic, im, iy, ik; /* Integral CMYK values */ | |
1583 | ||
1584 | ||
1585 | # ifdef DEBUG | |
1586 | fprintf(stderr, "DEBUG2: cups_map_cmyk_color(%p, %d, %d, %d, %d)\n", pdev, | |
1587 | c, m, y, k); | |
1588 | # endif /* DEBUG */ | |
1589 | ||
1590 | /* | |
1591 | * Setup the color info data as needed... | |
1592 | */ | |
1593 | ||
1594 | if (pdev->color_info.num_components == 0) | |
1595 | cups_set_color_info(pdev); | |
1596 | ||
1597 | /* | |
1598 | * Density correct... | |
1599 | */ | |
1600 | ||
1601 | if (cupsHaveProfile) | |
1602 | { | |
1603 | c = cupsDensity[c]; | |
1604 | m = cupsDensity[m]; | |
1605 | y = cupsDensity[y]; | |
1606 | k = cupsDensity[k]; | |
1607 | } | |
1608 | ||
1609 | ic = cupsEncodeLUT[c]; | |
1610 | im = cupsEncodeLUT[m]; | |
1611 | iy = cupsEncodeLUT[y]; | |
1612 | ik = cupsEncodeLUT[k]; | |
1613 | ||
1614 | /* | |
1615 | * Convert the CMYK color to a color index... | |
1616 | */ | |
1617 | ||
1618 | switch (cups->header.cupsColorSpace) | |
1619 | { | |
1620 | default : | |
1621 | switch (cups->header.cupsBitsPerColor) | |
1622 | { | |
1623 | default : | |
1624 | i = (((((ic << 1) | im) << 1) | iy) << 1) | ik; | |
1625 | break; | |
1626 | case 2 : | |
1627 | i = (((((ic << 2) | im) << 2) | iy) << 2) | ik; | |
1628 | break; | |
1629 | case 4 : | |
1630 | i = (((((ic << 4) | im) << 4) | iy) << 4) | ik; | |
1631 | break; | |
1632 | case 8 : | |
1633 | i = (((((ic << 8) | im) << 8) | iy) << 8) | ik; | |
1634 | break; | |
1635 | } | |
1636 | break; | |
1637 | ||
1638 | case CUPS_CSPACE_YMCK : | |
1639 | case CUPS_CSPACE_GMCK : | |
1640 | case CUPS_CSPACE_GMCS : | |
1641 | switch (cups->header.cupsBitsPerColor) | |
1642 | { | |
1643 | default : | |
1644 | i = (((((iy << 1) | im) << 1) | ic) << 1) | ik; | |
1645 | break; | |
1646 | case 2 : | |
1647 | i = (((((iy << 2) | im) << 2) | ic) << 2) | ik; | |
1648 | break; | |
1649 | case 4 : | |
1650 | i = (((((iy << 4) | im) << 4) | ic) << 4) | ik; | |
1651 | break; | |
1652 | case 8 : | |
1653 | i = (((((iy << 8) | im) << 8) | ic) << 8) | ik; | |
1654 | break; | |
1655 | } | |
1656 | break; | |
1657 | ||
1658 | case CUPS_CSPACE_KCMYcm : | |
1659 | if (cups->header.cupsBitsPerColor == 1) | |
1660 | { | |
1661 | if (ik) | |
1662 | i = 32; | |
1663 | else | |
1664 | i = 0; | |
1665 | ||
1666 | if (ic && im) | |
1667 | i |= 17; | |
1668 | else if (ic && iy) | |
1669 | i |= 6; | |
1670 | else if (im && iy) | |
1671 | i |= 12; | |
1672 | else if (ic) | |
1673 | i |= 16; | |
1674 | else if (im) | |
1675 | i |= 8; | |
1676 | else if (iy) | |
1677 | i |= 4; | |
1678 | break; | |
1679 | } | |
1680 | ||
1681 | case CUPS_CSPACE_KCMY : | |
1682 | switch (cups->header.cupsBitsPerColor) | |
1683 | { | |
1684 | default : | |
1685 | i = (((((ik << 1) | ic) << 1) | im) << 1) | iy; | |
1686 | break; | |
1687 | case 2 : | |
1688 | i = (((((ik << 2) | ic) << 2) | im) << 2) | iy; | |
1689 | break; | |
1690 | case 4 : | |
1691 | i = (((((ik << 4) | ic) << 4) | im) << 4) | iy; | |
1692 | break; | |
1693 | case 8 : | |
1694 | i = (((((ik << 8) | ic) << 8) | im) << 8) | iy; | |
1695 | break; | |
1696 | } | |
1697 | break; | |
1698 | } | |
1699 | ||
1700 | # ifdef DEBUG | |
1701 | fprintf(stderr, "DEBUG2: CMYK (%d,%d,%d,%d) -> CMYK %08x (%d,%d,%d,%d)\n", | |
1702 | c, m, y, k, (unsigned)i, ic, im, iy, ik); | |
1703 | # endif /* DEBUG */ | |
1704 | ||
1705 | /* | |
1706 | * Make sure we don't get a CMYK color of 255, 255, 255, 255... | |
1707 | */ | |
1708 | ||
1709 | if (i == gx_no_color_index) | |
1710 | i --; | |
1711 | ||
1712 | return (i); | |
1713 | } | |
1714 | ||
1715 | ||
1716 | /* | |
1717 | * 'cups_map_color_rgb()' - Map a color index to an RGB color. | |
1718 | */ | |
1719 | ||
1720 | private int | |
1721 | cups_map_color_rgb(gx_device *pdev,/* I - Device info */ | |
1722 | gx_color_index color,/* I - Color index */ | |
1723 | gx_color_value prgb[3]) | |
1724 | /* O - RGB values */ | |
1725 | { | |
1726 | unsigned char c0, c1, c2, c3; /* Color index components */ | |
1727 | gx_color_value k, divk; /* Black & divisor */ | |
1728 | ||
1729 | ||
1730 | # ifdef DEBUG | |
1731 | fprintf(stderr, "DEBUG2: cups_map_color_rgb(%p, %d, %p)\n", pdev, | |
1732 | (unsigned)color, prgb); | |
1733 | # endif /* DEBUG */ | |
1734 | ||
1735 | /* | |
1736 | * Setup the color info data as needed... | |
1737 | */ | |
1738 | ||
1739 | if (pdev->color_info.num_components == 0) | |
1740 | cups_set_color_info(pdev); | |
1741 | ||
1742 | # ifdef DEBUG | |
1743 | fprintf(stderr, "DEBUG2: COLOR %08x = ", (unsigned)color); | |
1744 | # endif /* DEBUG */ | |
1745 | ||
1746 | /* | |
1747 | * Extract the color components from the color index... | |
1748 | */ | |
1749 | ||
1750 | switch (cups->header.cupsBitsPerColor) | |
1751 | { | |
1752 | default : | |
1753 | c3 = color & 1; | |
1754 | color >>= 1; | |
1755 | c2 = color & 1; | |
1756 | color >>= 1; | |
1757 | c1 = color & 1; | |
1758 | color >>= 1; | |
1759 | c0 = color; | |
1760 | break; | |
1761 | case 2 : | |
1762 | c3 = color & 3; | |
1763 | color >>= 2; | |
1764 | c2 = color & 3; | |
1765 | color >>= 2; | |
1766 | c1 = color & 3; | |
1767 | color >>= 2; | |
1768 | c0 = color; | |
1769 | break; | |
1770 | case 4 : | |
1771 | c3 = color & 15; | |
1772 | color >>= 4; | |
1773 | c2 = color & 15; | |
1774 | color >>= 4; | |
1775 | c1 = color & 15; | |
1776 | color >>= 4; | |
1777 | c0 = color; | |
1778 | break; | |
1779 | case 8 : | |
1780 | c3 = color & 255; | |
1781 | color >>= 8; | |
1782 | c2 = color & 255; | |
1783 | color >>= 8; | |
1784 | c1 = color & 255; | |
1785 | color >>= 8; | |
1786 | c0 = color; | |
1787 | break; | |
1788 | } | |
1789 | ||
1790 | /* | |
1791 | * Convert the color components to RGB... | |
1792 | */ | |
1793 | ||
1794 | switch (cups->header.cupsColorSpace) | |
1795 | { | |
1796 | case CUPS_CSPACE_K : | |
1797 | case CUPS_CSPACE_WHITE : | |
1798 | case CUPS_CSPACE_GOLD : | |
1799 | case CUPS_CSPACE_SILVER : | |
1800 | prgb[0] = | |
1801 | prgb[1] = | |
1802 | prgb[2] = cupsDecodeLUT[c3]; | |
1803 | break; | |
1804 | ||
1805 | case CUPS_CSPACE_W : | |
1806 | prgb[0] = | |
1807 | prgb[1] = | |
1808 | prgb[2] = cupsDecodeLUT[c3]; | |
1809 | break; | |
1810 | ||
1811 | case CUPS_CSPACE_RGB : | |
1812 | prgb[0] = cupsDecodeLUT[c1]; | |
1813 | prgb[1] = cupsDecodeLUT[c2]; | |
1814 | prgb[2] = cupsDecodeLUT[c3]; | |
1815 | break; | |
1816 | ||
1817 | case CUPS_CSPACE_RGBA : | |
1818 | prgb[0] = cupsDecodeLUT[c0]; | |
1819 | prgb[1] = cupsDecodeLUT[c1]; | |
1820 | prgb[2] = cupsDecodeLUT[c2]; | |
1821 | break; | |
1822 | ||
1823 | case CUPS_CSPACE_CMY : | |
1824 | prgb[0] = cupsDecodeLUT[c1]; | |
1825 | prgb[1] = cupsDecodeLUT[c2]; | |
1826 | prgb[2] = cupsDecodeLUT[c3]; | |
1827 | break; | |
1828 | ||
1829 | case CUPS_CSPACE_YMC : | |
1830 | prgb[0] = cupsDecodeLUT[c3]; | |
1831 | prgb[1] = cupsDecodeLUT[c2]; | |
1832 | prgb[2] = cupsDecodeLUT[c1]; | |
1833 | break; | |
1834 | ||
1835 | case CUPS_CSPACE_KCMY : | |
1836 | case CUPS_CSPACE_KCMYcm : | |
1837 | k = cupsDecodeLUT[c0]; | |
1838 | divk = gx_max_color_value - k; | |
1839 | if (divk == 0) | |
1840 | { | |
1841 | prgb[0] = 0; | |
1842 | prgb[1] = 0; | |
1843 | prgb[2] = 0; | |
1844 | } | |
1845 | else | |
1846 | { | |
1847 | prgb[0] = gx_max_color_value + divk - | |
1848 | gx_max_color_value * c1 / divk; | |
1849 | prgb[1] = gx_max_color_value + divk - | |
1850 | gx_max_color_value * c2 / divk; | |
1851 | prgb[2] = gx_max_color_value + divk - | |
1852 | gx_max_color_value * c3 / divk; | |
1853 | } | |
1854 | break; | |
1855 | ||
1856 | case CUPS_CSPACE_CMYK : | |
1857 | k = cupsDecodeLUT[c3]; | |
1858 | divk = gx_max_color_value - k; | |
1859 | if (divk == 0) | |
1860 | { | |
1861 | prgb[0] = 0; | |
1862 | prgb[1] = 0; | |
1863 | prgb[2] = 0; | |
1864 | } | |
1865 | else | |
1866 | { | |
1867 | prgb[0] = gx_max_color_value + divk - | |
1868 | gx_max_color_value * c0 / divk; | |
1869 | prgb[1] = gx_max_color_value + divk - | |
1870 | gx_max_color_value * c1 / divk; | |
1871 | prgb[2] = gx_max_color_value + divk - | |
1872 | gx_max_color_value * c2 / divk; | |
1873 | } | |
1874 | break; | |
1875 | ||
1876 | case CUPS_CSPACE_YMCK : | |
1877 | case CUPS_CSPACE_GMCK : | |
1878 | case CUPS_CSPACE_GMCS : | |
1879 | k = cupsDecodeLUT[c3]; | |
1880 | divk = gx_max_color_value - k; | |
1881 | if (divk == 0) | |
1882 | { | |
1883 | prgb[0] = 0; | |
1884 | prgb[1] = 0; | |
1885 | prgb[2] = 0; | |
1886 | } | |
1887 | else | |
1888 | { | |
1889 | prgb[0] = gx_max_color_value + divk - | |
1890 | gx_max_color_value * c2 / divk; | |
1891 | prgb[1] = gx_max_color_value + divk - | |
1892 | gx_max_color_value * c1 / divk; | |
1893 | prgb[2] = gx_max_color_value + divk - | |
1894 | gx_max_color_value * c0 / divk; | |
1895 | } | |
1896 | break; | |
1897 | ||
1898 | # ifdef CUPS_RASTER_HAVE_COLORIMETRIC | |
1899 | case CUPS_CSPACE_CIEXYZ : | |
1900 | case CUPS_CSPACE_CIELab : | |
1901 | case CUPS_CSPACE_ICC1 : | |
1902 | case CUPS_CSPACE_ICC2 : | |
1903 | case CUPS_CSPACE_ICC3 : | |
1904 | case CUPS_CSPACE_ICC4 : | |
1905 | case CUPS_CSPACE_ICC5 : | |
1906 | case CUPS_CSPACE_ICC6 : | |
1907 | case CUPS_CSPACE_ICC7 : | |
1908 | case CUPS_CSPACE_ICC8 : | |
1909 | case CUPS_CSPACE_ICC9 : | |
1910 | case CUPS_CSPACE_ICCA : | |
1911 | case CUPS_CSPACE_ICCB : | |
1912 | case CUPS_CSPACE_ICCC : | |
1913 | case CUPS_CSPACE_ICCD : | |
1914 | case CUPS_CSPACE_ICCE : | |
1915 | case CUPS_CSPACE_ICCF : | |
1916 | break; | |
1917 | # endif /* CUPS_RASTER_HAVE_COLORIMETRIC */ | |
1918 | } | |
1919 | ||
1920 | # ifdef DEBUG | |
1921 | fprintf(stderr, "%d,%d,%d\n", prgb[0], prgb[1], prgb[2]); | |
1922 | # endif /* DEBUG */ | |
1923 | ||
1924 | return (0); | |
1925 | } | |
1926 | ||
1927 | ||
1928 | /* | |
1929 | * 'cups_map_rgb_color()' - Map an RGB color to a color index. We map the | |
1930 | * RGB color to the output colorspace & bits (we | |
1931 | * figure out the format when we output a page). | |
1932 | */ | |
1933 | ||
1934 | private gx_color_index /* O - Color index */ | |
1935 | cups_map_rgb_color(gx_device *pdev,/* I - Device info */ | |
1936 | gx_color_value r, /* I - Red value */ | |
1937 | gx_color_value g, /* I - Green value */ | |
1938 | gx_color_value b) /* I - Blue value */ | |
1939 | { | |
1940 | gx_color_index i; /* Temporary index */ | |
1941 | gx_color_value ic, im, iy, ik; /* Integral CMYK values */ | |
1942 | gx_color_value mk; /* Maximum K value */ | |
1943 | int tc, tm, ty; /* Temporary color values */ | |
1944 | float rr, rg, rb, /* Real RGB colors */ | |
1945 | ciex, ciey, ciez, | |
1946 | /* CIE XYZ colors */ | |
1947 | ciey_yn, /* Normalized luminance */ | |
1948 | ciel, ciea, cieb; | |
1949 | /* CIE Lab colors */ | |
1950 | ||
1951 | ||
1952 | # ifdef DEBUG | |
1953 | fprintf(stderr, "DEBUG2: cups_map_rgb_color(%p, %d, %d, %d)\n", pdev, r, g, b); | |
1954 | # endif /* DEBUG */ | |
1955 | ||
1956 | /* | |
1957 | * Setup the color info data as needed... | |
1958 | */ | |
1959 | ||
1960 | if (pdev->color_info.num_components == 0) | |
1961 | cups_set_color_info(pdev); | |
1962 | ||
1963 | /* | |
1964 | * Do color correction as needed... | |
1965 | */ | |
1966 | ||
1967 | if (cupsHaveProfile) | |
1968 | { | |
1969 | /* | |
1970 | * Compute CMYK values... | |
1971 | */ | |
1972 | ||
1973 | ic = gx_max_color_value - r; | |
1974 | im = gx_max_color_value - g; | |
1975 | iy = gx_max_color_value - b; | |
1976 | ik = min(ic, min(im, iy)); | |
1977 | ||
1978 | if ((mk = max(ic, max(im, iy))) > ik) | |
1979 | ik = (int)((float)ik * (float)ik * (float)ik / ((float)mk * (float)mk)); | |
1980 | ||
1981 | ic -= ik; | |
1982 | im -= ik; | |
1983 | iy -= ik; | |
1984 | ||
1985 | /* | |
1986 | * Color correct CMY... | |
1987 | */ | |
1988 | ||
1989 | tc = cupsMatrix[0][0][ic] + | |
1990 | cupsMatrix[0][1][im] + | |
1991 | cupsMatrix[0][2][iy] + | |
1992 | ik; | |
1993 | tm = cupsMatrix[1][0][ic] + | |
1994 | cupsMatrix[1][1][im] + | |
1995 | cupsMatrix[1][2][iy] + | |
1996 | ik; | |
1997 | ty = cupsMatrix[2][0][ic] + | |
1998 | cupsMatrix[2][1][im] + | |
1999 | cupsMatrix[2][2][iy] + | |
2000 | ik; | |
2001 | ||
2002 | /* | |
2003 | * Density correct combined CMYK... | |
2004 | */ | |
2005 | ||
2006 | if (tc < 0) | |
2007 | r = gx_max_color_value; | |
2008 | else if (tc > gx_max_color_value) | |
2009 | r = gx_max_color_value - cupsDensity[gx_max_color_value]; | |
2010 | else | |
2011 | r = gx_max_color_value - cupsDensity[tc]; | |
2012 | ||
2013 | if (tm < 0) | |
2014 | g = gx_max_color_value; | |
2015 | else if (tm > gx_max_color_value) | |
2016 | g = gx_max_color_value - cupsDensity[gx_max_color_value]; | |
2017 | else | |
2018 | g = gx_max_color_value - cupsDensity[tm]; | |
2019 | ||
2020 | if (ty < 0) | |
2021 | b = gx_max_color_value; | |
2022 | else if (ty > gx_max_color_value) | |
2023 | b = gx_max_color_value - cupsDensity[gx_max_color_value]; | |
2024 | else | |
2025 | b = gx_max_color_value - cupsDensity[ty]; | |
2026 | } | |
2027 | ||
2028 | /* | |
2029 | * Convert the RGB color to a color index... | |
2030 | */ | |
2031 | ||
2032 | switch (cups->header.cupsColorSpace) | |
2033 | { | |
2034 | case CUPS_CSPACE_W : | |
2035 | i = cupsEncodeLUT[(r * 31 + g * 61 + b * 8) / 100]; | |
2036 | break; | |
2037 | ||
2038 | case CUPS_CSPACE_RGB : | |
2039 | ic = cupsEncodeLUT[r]; | |
2040 | im = cupsEncodeLUT[g]; | |
2041 | iy = cupsEncodeLUT[b]; | |
2042 | ||
2043 | switch (cups->header.cupsBitsPerColor) | |
2044 | { | |
2045 | default : | |
2046 | i = (((ic << 1) | im) << 1) | iy; | |
2047 | break; | |
2048 | case 2 : | |
2049 | i = (((ic << 2) | im) << 2) | iy; | |
2050 | break; | |
2051 | case 4 : | |
2052 | i = (((ic << 4) | im) << 4) | iy; | |
2053 | break; | |
2054 | case 8 : | |
2055 | i = (((ic << 8) | im) << 8) | iy; | |
2056 | break; | |
2057 | } | |
2058 | break; | |
2059 | ||
2060 | case CUPS_CSPACE_RGBA : | |
2061 | ic = cupsEncodeLUT[r]; | |
2062 | im = cupsEncodeLUT[g]; | |
2063 | iy = cupsEncodeLUT[b]; | |
2064 | ||
2065 | switch (cups->header.cupsBitsPerColor) | |
2066 | { | |
2067 | default : | |
2068 | i = (((((ic << 1) | im) << 1) | iy) << 1) | 0x01; | |
2069 | break; | |
2070 | case 2 : | |
2071 | i = (((((ic << 2) | im) << 2) | iy) << 2) | 0x03; | |
2072 | break; | |
2073 | case 4 : | |
2074 | i = (((((ic << 4) | im) << 4) | iy) << 4) | 0x0f; | |
2075 | break; | |
2076 | case 8 : | |
2077 | i = (((((ic << 8) | im) << 8) | iy) << 8) | 0xff; | |
2078 | break; | |
2079 | } | |
2080 | break; | |
2081 | ||
2082 | default : | |
2083 | i = cupsEncodeLUT[gx_max_color_value - (r * 31 + g * 61 + b * 8) / 100]; | |
2084 | break; | |
2085 | ||
2086 | case CUPS_CSPACE_CMY : | |
2087 | ic = cupsEncodeLUT[gx_max_color_value - r]; | |
2088 | im = cupsEncodeLUT[gx_max_color_value - g]; | |
2089 | iy = cupsEncodeLUT[gx_max_color_value - b]; | |
2090 | ||
2091 | switch (cups->header.cupsBitsPerColor) | |
2092 | { | |
2093 | default : | |
2094 | i = (((ic << 1) | im) << 1) | iy; | |
2095 | break; | |
2096 | case 2 : | |
2097 | i = (((ic << 2) | im) << 2) | iy; | |
2098 | break; | |
2099 | case 4 : | |
2100 | i = (((ic << 4) | im) << 4) | iy; | |
2101 | break; | |
2102 | case 8 : | |
2103 | i = (((ic << 8) | im) << 8) | iy; | |
2104 | break; | |
2105 | } | |
2106 | break; | |
2107 | ||
2108 | case CUPS_CSPACE_YMC : | |
2109 | ic = cupsEncodeLUT[gx_max_color_value - r]; | |
2110 | im = cupsEncodeLUT[gx_max_color_value - g]; | |
2111 | iy = cupsEncodeLUT[gx_max_color_value - b]; | |
2112 | ||
2113 | switch (cups->header.cupsBitsPerColor) | |
2114 | { | |
2115 | default : | |
2116 | i = (((iy << 1) | im) << 1) | ic; | |
2117 | break; | |
2118 | case 2 : | |
2119 | i = (((iy << 2) | im) << 2) | ic; | |
2120 | break; | |
2121 | case 4 : | |
2122 | i = (((iy << 4) | im) << 4) | ic; | |
2123 | break; | |
2124 | case 8 : | |
2125 | i = (((iy << 8) | im) << 8) | ic; | |
2126 | break; | |
2127 | } | |
2128 | break; | |
2129 | ||
2130 | case CUPS_CSPACE_CMYK : | |
2131 | ic = gx_max_color_value - r; | |
2132 | im = gx_max_color_value - g; | |
2133 | iy = gx_max_color_value - b; | |
2134 | ik = min(ic, min(im, iy)); | |
2135 | ||
2136 | if ((mk = max(ic, max(im, iy))) > ik) | |
2137 | ik = (int)((float)ik * (float)ik * (float)ik / | |
2138 | ((float)mk * (float)mk)); | |
2139 | ||
2140 | ic = cupsEncodeLUT[ic - ik]; | |
2141 | im = cupsEncodeLUT[im - ik]; | |
2142 | iy = cupsEncodeLUT[iy - ik]; | |
2143 | ik = cupsEncodeLUT[ik]; | |
2144 | ||
2145 | switch (cups->header.cupsBitsPerColor) | |
2146 | { | |
2147 | default : | |
2148 | i = (((((ic << 1) | im) << 1) | iy) << 1) | ik; | |
2149 | break; | |
2150 | case 2 : | |
2151 | i = (((((ic << 2) | im) << 2) | iy) << 2) | ik; | |
2152 | break; | |
2153 | case 4 : | |
2154 | i = (((((ic << 4) | im) << 4) | iy) << 4) | ik; | |
2155 | break; | |
2156 | case 8 : | |
2157 | i = (((((ic << 8) | im) << 8) | iy) << 8) | ik; | |
2158 | break; | |
2159 | } | |
2160 | ||
2161 | # ifdef DEBUG | |
2162 | fprintf(stderr, "DEBUG2: CMY (%d,%d,%d) -> CMYK %08x (%d,%d,%d,%d)\n", | |
2163 | r, g, b, (unsigned)i, ic, im, iy, ik); | |
2164 | # endif /* DEBUG */ | |
2165 | break; | |
2166 | ||
2167 | case CUPS_CSPACE_YMCK : | |
2168 | case CUPS_CSPACE_GMCK : | |
2169 | case CUPS_CSPACE_GMCS : | |
2170 | ic = gx_max_color_value - r; | |
2171 | im = gx_max_color_value - g; | |
2172 | iy = gx_max_color_value - b; | |
2173 | ik = min(ic, min(im, iy)); | |
2174 | ||
2175 | if ((mk = max(ic, max(im, iy))) > ik) | |
2176 | ik = (int)((float)ik * (float)ik * (float)ik / | |
2177 | ((float)mk * (float)mk)); | |
2178 | ||
2179 | ic = cupsEncodeLUT[ic - ik]; | |
2180 | im = cupsEncodeLUT[im - ik]; | |
2181 | iy = cupsEncodeLUT[iy - ik]; | |
2182 | ik = cupsEncodeLUT[ik]; | |
2183 | ||
2184 | switch (cups->header.cupsBitsPerColor) | |
2185 | { | |
2186 | default : | |
2187 | i = (((((iy << 1) | im) << 1) | ic) << 1) | ik; | |
2188 | break; | |
2189 | case 2 : | |
2190 | i = (((((iy << 2) | im) << 2) | ic) << 2) | ik; | |
2191 | break; | |
2192 | case 4 : | |
2193 | i = (((((iy << 4) | im) << 4) | ic) << 4) | ik; | |
2194 | break; | |
2195 | case 8 : | |
2196 | i = (((((iy << 8) | im) << 8) | ic) << 8) | ik; | |
2197 | break; | |
2198 | } | |
2199 | break; | |
2200 | ||
2201 | case CUPS_CSPACE_KCMYcm : | |
2202 | if (cups->header.cupsBitsPerColor == 1) | |
2203 | { | |
2204 | ic = gx_max_color_value - r; | |
2205 | im = gx_max_color_value - g; | |
2206 | iy = gx_max_color_value - b; | |
2207 | ik = min(ic, min(im, iy)); | |
2208 | ||
2209 | if ((mk = max(ic, max(im, iy))) > ik) | |
2210 | ik = (int)((float)ik * (float)ik * (float)ik / | |
2211 | ((float)mk * (float)mk)); | |
2212 | ||
2213 | ic = cupsEncodeLUT[ic - ik]; | |
2214 | im = cupsEncodeLUT[im - ik]; | |
2215 | iy = cupsEncodeLUT[iy - ik]; | |
2216 | ik = cupsEncodeLUT[ik]; | |
2217 | if (ik) | |
2218 | i = 32; | |
2219 | else if (ic && im) | |
2220 | i = 17; | |
2221 | else if (ic && iy) | |
2222 | i = 6; | |
2223 | else if (im && iy) | |
2224 | i = 12; | |
2225 | else if (ic) | |
2226 | i = 16; | |
2227 | else if (im) | |
2228 | i = 8; | |
2229 | else if (iy) | |
2230 | i = 4; | |
2231 | else | |
2232 | i = 0; | |
2233 | break; | |
2234 | } | |
2235 | ||
2236 | case CUPS_CSPACE_KCMY : | |
2237 | ic = gx_max_color_value - r; | |
2238 | im = gx_max_color_value - g; | |
2239 | iy = gx_max_color_value - b; | |
2240 | ik = min(ic, min(im, iy)); | |
2241 | ||
2242 | if ((mk = max(ic, max(im, iy))) > ik) | |
2243 | ik = (int)((float)ik * (float)ik * (float)ik / | |
2244 | ((float)mk * (float)mk)); | |
2245 | ||
2246 | ic = cupsEncodeLUT[ic - ik]; | |
2247 | im = cupsEncodeLUT[im - ik]; | |
2248 | iy = cupsEncodeLUT[iy - ik]; | |
2249 | ik = cupsEncodeLUT[ik]; | |
2250 | ||
2251 | switch (cups->header.cupsBitsPerColor) | |
2252 | { | |
2253 | default : | |
2254 | i = (((((ik << 1) | ic) << 1) | im) << 1) | iy; | |
2255 | break; | |
2256 | case 2 : | |
2257 | i = (((((ik << 2) | ic) << 2) | im) << 2) | iy; | |
2258 | break; | |
2259 | case 4 : | |
2260 | i = (((((ik << 4) | ic) << 4) | im) << 4) | iy; | |
2261 | break; | |
2262 | case 8 : | |
2263 | i = (((((ik << 8) | ic) << 8) | im) << 8) | iy; | |
2264 | break; | |
2265 | } | |
2266 | break; | |
2267 | ||
2268 | # ifdef CUPS_RASTER_HAVE_COLORIMETRIC | |
2269 | case CUPS_CSPACE_CIEXYZ : | |
2270 | case CUPS_CSPACE_CIELab : | |
2271 | case CUPS_CSPACE_ICC1 : | |
2272 | case CUPS_CSPACE_ICC2 : | |
2273 | case CUPS_CSPACE_ICC3 : | |
2274 | case CUPS_CSPACE_ICC4 : | |
2275 | case CUPS_CSPACE_ICC5 : | |
2276 | case CUPS_CSPACE_ICC6 : | |
2277 | case CUPS_CSPACE_ICC7 : | |
2278 | case CUPS_CSPACE_ICC8 : | |
2279 | case CUPS_CSPACE_ICC9 : | |
2280 | case CUPS_CSPACE_ICCA : | |
2281 | case CUPS_CSPACE_ICCB : | |
2282 | case CUPS_CSPACE_ICCC : | |
2283 | case CUPS_CSPACE_ICCD : | |
2284 | case CUPS_CSPACE_ICCE : | |
2285 | case CUPS_CSPACE_ICCF : | |
2286 | /* | |
2287 | * Convert sRGB to linear RGB... | |
2288 | */ | |
2289 | ||
2290 | rr = pow((double)r / (double)gx_max_color_value, 0.58823529412); | |
2291 | rg = pow((double)g / (double)gx_max_color_value, 0.58823529412); | |
2292 | rb = pow((double)b / (double)gx_max_color_value, 0.58823529412); | |
2293 | ||
2294 | /* | |
2295 | * Convert to CIE XYZ... | |
2296 | */ | |
2297 | ||
2298 | ciex = 0.412453 * rr + 0.357580 * rg + 0.180423 * rb; | |
2299 | ciey = 0.212671 * rr + 0.715160 * rg + 0.072169 * rb; | |
2300 | ciez = 0.019334 * rr + 0.119193 * rg + 0.950227 * rb; | |
2301 | ||
2302 | if (cups->header.cupsColorSpace == CUPS_CSPACE_CIEXYZ) | |
2303 | { | |
2304 | /* | |
2305 | * Convert to an integer XYZ color value... | |
2306 | */ | |
2307 | ||
2308 | if (ciex > 1.0) | |
2309 | ic = 255; | |
2310 | else if (ciex > 0.0) | |
2311 | ic = (int)(ciex * 255.0); | |
2312 | else | |
2313 | ic = 0; | |
2314 | ||
2315 | if (ciey > 1.0) | |
2316 | im = 255; | |
2317 | else if (ciey > 0.0) | |
2318 | im = (int)(ciey * 255.0); | |
2319 | else | |
2320 | im = 0; | |
2321 | ||
2322 | if (ciez > 1.0) | |
2323 | iy = 255; | |
2324 | else if (ciez > 0.0) | |
2325 | iy = (int)(ciez * 255.0); | |
2326 | else | |
2327 | iy = 0; | |
2328 | } | |
2329 | else | |
2330 | { | |
2331 | /* | |
2332 | * Convert CIE XYZ to Lab... | |
2333 | */ | |
2334 | ||
2335 | ciey_yn = ciey / D65_Y; | |
2336 | ||
2337 | if (ciey_yn > 0.008856) | |
2338 | ciel = 116 * cbrt(ciey_yn) - 16; | |
2339 | else | |
2340 | ciel = 903.3 * ciey_yn; | |
2341 | ||
2342 | ciea = 500 * (cups_map_cielab(ciex, D65_X) - | |
2343 | cups_map_cielab(ciey, D65_Y)); | |
2344 | cieb = 200 * (cups_map_cielab(ciey, D65_Y) - | |
2345 | cups_map_cielab(ciez, D65_Z)); | |
2346 | ||
2347 | /* | |
2348 | * Scale the L value and bias the a and b values by 128 | |
2349 | * so that all values are in the range of 0 to 255. | |
2350 | */ | |
2351 | ||
2352 | ciel *= 2.55; | |
2353 | ciea += 128; | |
2354 | cieb += 128; | |
2355 | ||
2356 | /* | |
2357 | * Convert to 8-bit values... | |
2358 | */ | |
2359 | ||
2360 | if (ciel < 0.0) | |
2361 | ic = 0; | |
2362 | else if (ciel < 255.0) | |
2363 | ic = ciel; | |
2364 | else | |
2365 | ic = 255; | |
2366 | ||
2367 | if (ciea < 0.0) | |
2368 | im = 0; | |
2369 | else if (ciea < 255.0) | |
2370 | im = ciea; | |
2371 | else | |
2372 | im = 255; | |
2373 | ||
2374 | if (cieb < 0.0) | |
2375 | iy = 0; | |
2376 | else if (cieb < 255.0) | |
2377 | iy = cieb; | |
2378 | else | |
2379 | iy = 255; | |
2380 | } | |
2381 | ||
2382 | /* | |
2383 | * Put the final color value together... | |
2384 | */ | |
2385 | ||
2386 | switch (cups->header.cupsBitsPerColor) | |
2387 | { | |
2388 | default : | |
2389 | i = (((ic << 1) | im) << 1) | iy; | |
2390 | break; | |
2391 | case 2 : | |
2392 | i = (((ic << 2) | im) << 2) | iy; | |
2393 | break; | |
2394 | case 4 : | |
2395 | i = (((ic << 4) | im) << 4) | iy; | |
2396 | break; | |
2397 | case 8 : | |
2398 | i = (((ic << 8) | im) << 8) | iy; | |
2399 | break; | |
2400 | } | |
2401 | break; | |
2402 | # endif /* CUPS_RASTER_HAVE_COLORIMETRIC */ | |
2403 | } | |
2404 | ||
2405 | # ifdef DEBUG | |
2406 | fprintf(stderr, "DEBUG2: RGB %d,%d,%d = %08x\n", r, g, b, (unsigned)i); | |
2407 | # endif /* DEBUG */ | |
2408 | ||
2409 | return (i); | |
2410 | } | |
2411 | #endif /* dev_t_proc_encode_color */ | |
2412 | ||
2413 | ||
2414 | /* | |
2415 | * 'cups_open()' - Open the output file and initialize things. | |
2416 | */ | |
2417 | ||
2418 | private int /* O - Error status */ | |
2419 | cups_open(gx_device *pdev) /* I - Device info */ | |
2420 | { | |
2421 | int code; /* Return status */ | |
2422 | ||
2423 | ||
2424 | #ifdef DEBUG | |
2425 | fprintf(stderr, "DEBUG2: cups_open(%p)\n", pdev); | |
2426 | #endif /* DEBUG */ | |
2427 | ||
2428 | cups->printer_procs.get_space_params = cups_get_space_params; | |
2429 | ||
2430 | if (cups->page == 0) | |
2431 | { | |
2432 | fputs("INFO: Processing page 1...\n", stderr); | |
2433 | cups->page = 1; | |
2434 | } | |
2435 | ||
2436 | cups_set_color_info(pdev); | |
2437 | ||
2438 | if ((code = gdev_prn_open(pdev)) != 0) | |
2439 | return (code); | |
2440 | ||
2441 | if (cupsPPD == NULL) | |
2442 | cupsPPD = ppdOpenFile(getenv("PPD")); | |
2443 | ||
2444 | return (0); | |
2445 | } | |
2446 | ||
2447 | ||
2448 | /* | |
2449 | * 'cups_print_pages()' - Send one or more pages to the output file. | |
2450 | */ | |
2451 | ||
2452 | private int /* O - 0 if everything is OK */ | |
2453 | cups_print_pages(gx_device_printer *pdev, | |
2454 | /* I - Device info */ | |
2455 | FILE *fp, /* I - Output file */ | |
2456 | int num_copies) | |
2457 | /* I - Number of copies */ | |
2458 | { | |
2459 | int copy; /* Copy number */ | |
2460 | int srcbytes; /* Byte width of scanline */ | |
2461 | unsigned char *src, /* Scanline data */ | |
2462 | *dst; /* Bitmap data */ | |
2463 | ||
2464 | ||
2465 | (void)fp; /* reference unused file pointer to prevent compiler warning */ | |
2466 | ||
2467 | #ifdef DEBUG | |
2468 | fprintf(stderr, "DEBUG2: cups_print_pages(%p, %p, %d)\n", pdev, fp, | |
2469 | num_copies); | |
2470 | #endif /* DEBUG */ | |
2471 | ||
2472 | /* | |
2473 | * Figure out the number of bytes per line... | |
2474 | */ | |
2475 | ||
2476 | switch (cups->header.cupsColorOrder) | |
2477 | { | |
2478 | case CUPS_ORDER_CHUNKED : | |
2479 | cups->header.cupsBytesPerLine = (cups->header.cupsBitsPerPixel * | |
2480 | cups->header.cupsWidth + 7) / 8; | |
2481 | break; | |
2482 | ||
2483 | case CUPS_ORDER_BANDED : | |
2484 | if (cups->header.cupsColorSpace == CUPS_CSPACE_KCMYcm && | |
2485 | cups->header.cupsBitsPerColor == 1) | |
2486 | cups->header.cupsBytesPerLine = (cups->header.cupsBitsPerColor * | |
2487 | cups->header.cupsWidth + 7) / 8 * 6; | |
2488 | else | |
2489 | cups->header.cupsBytesPerLine = (cups->header.cupsBitsPerColor * | |
2490 | cups->header.cupsWidth + 7) / 8 * | |
2491 | cups->color_info.num_components; | |
2492 | break; | |
2493 | ||
2494 | case CUPS_ORDER_PLANAR : | |
2495 | cups->header.cupsBytesPerLine = (cups->header.cupsBitsPerColor * | |
2496 | cups->header.cupsWidth + 7) / 8; | |
2497 | break; | |
2498 | } | |
2499 | ||
2500 | /* | |
2501 | * Compute the width of a scanline and allocate input/output buffers... | |
2502 | */ | |
2503 | ||
2504 | srcbytes = gdev_prn_raster(pdev); | |
2505 | ||
2506 | #ifdef DEBUG | |
2507 | fprintf(stderr, "DEBUG2: cupsBitsPerPixel = %d, cupsWidth = %d, cupsBytesPerLine = %d, srcbytes = %d\n", | |
2508 | cups->header.cupsBitsPerPixel, cups->header.cupsWidth, | |
2509 | cups->header.cupsBytesPerLine, srcbytes); | |
2510 | #endif /* DEBUG */ | |
2511 | ||
2512 | src = (unsigned char *)gs_malloc(srcbytes, 1, "cups_print_pages"); | |
2513 | ||
2514 | if (src == NULL) /* can't allocate input buffer */ | |
2515 | return_error(gs_error_VMerror); | |
2516 | ||
2517 | /* | |
2518 | * Need an output buffer, too... | |
2519 | */ | |
2520 | ||
2521 | dst = (unsigned char *)gs_malloc(cups->header.cupsBytesPerLine, 2, | |
2522 | "cups_print_pages"); | |
2523 | ||
2524 | if (dst == NULL) /* can't allocate working area */ | |
2525 | return_error(gs_error_VMerror); | |
2526 | ||
2527 | /* | |
2528 | * See if the stream has been initialized yet... | |
2529 | */ | |
2530 | ||
2531 | if (cups->stream == NULL) | |
2532 | { | |
2533 | if ((cups->stream = cupsRasterOpen(fileno(cups->file), | |
2534 | CUPS_RASTER_WRITE)) == NULL) | |
2535 | { | |
2536 | perror("ERROR: Unable to open raster stream - "); | |
2537 | gs_exit(0); | |
2538 | } | |
2539 | } | |
2540 | ||
2541 | /* | |
2542 | * Output a page of graphics... | |
2543 | */ | |
2544 | ||
2545 | if (num_copies < 1) | |
2546 | num_copies = 1; | |
2547 | ||
2548 | if (cupsPPD != NULL && !cupsPPD->manual_copies) | |
2549 | { | |
2550 | cups->header.NumCopies = num_copies; | |
2551 | num_copies = 1; | |
2552 | } | |
2553 | ||
2554 | #ifdef DEBUG | |
2555 | fprintf(stderr, "DEBUG2: cupsWidth = %d, cupsHeight = %d, cupsBytesPerLine = %d\n", | |
2556 | cups->header.cupsWidth, cups->header.cupsHeight, | |
2557 | cups->header.cupsBytesPerLine); | |
2558 | #endif /* DEBUG */ | |
2559 | ||
2560 | for (copy = num_copies; copy > 0; copy --) | |
2561 | { | |
2562 | cupsRasterWriteHeader(cups->stream, &(cups->header)); | |
2563 | ||
2564 | if (pdev->color_info.num_components == 1) | |
2565 | cups_print_chunked(pdev, src, dst, srcbytes); | |
2566 | else | |
2567 | switch (cups->header.cupsColorOrder) | |
2568 | { | |
2569 | case CUPS_ORDER_CHUNKED : | |
2570 | cups_print_chunked(pdev, src, dst, srcbytes); | |
2571 | break; | |
2572 | case CUPS_ORDER_BANDED : | |
2573 | cups_print_banded(pdev, src, dst, srcbytes); | |
2574 | break; | |
2575 | case CUPS_ORDER_PLANAR : | |
2576 | cups_print_planar(pdev, src, dst, srcbytes); | |
2577 | break; | |
2578 | } | |
2579 | } | |
2580 | ||
2581 | /* | |
2582 | * Free temporary storage and return... | |
2583 | */ | |
2584 | ||
2585 | gs_free((char *)src, srcbytes, 1, "cups_print_pages"); | |
2586 | gs_free((char *)dst, cups->header.cupsBytesPerLine, 1, "cups_print_pages"); | |
2587 | ||
2588 | cups->page ++; | |
2589 | fprintf(stderr, "INFO: Processing page %d...\n", cups->page); | |
2590 | ||
2591 | return (0); | |
2592 | } | |
2593 | ||
2594 | ||
2595 | /* | |
2596 | * 'cups_put_params()' - Set pagedevice parameters. | |
2597 | */ | |
2598 | ||
2599 | private int /* O - Error status */ | |
2600 | cups_put_params(gx_device *pdev, /* I - Device info */ | |
2601 | gs_param_list *plist) /* I - Parameter list */ | |
2602 | { | |
2603 | int i; /* Looping var */ | |
2604 | #ifdef CUPS_RASTER_SYNCv1 | |
2605 | char name[255]; /* Name of attribute */ | |
2606 | #endif /* CUPS_RASTER_SYNCv1 */ | |
2607 | float margins[4]; /* Physical margins of print */ | |
2608 | ppd_size_t *size; /* Page size */ | |
2609 | int code; /* Error code */ | |
2610 | int intval; /* Integer value */ | |
2611 | bool boolval; /* Boolean value */ | |
2612 | float floatval; /* Floating point value */ | |
2613 | gs_param_string stringval; /* String value */ | |
2614 | gs_param_float_array arrayval; /* Float array value */ | |
2615 | int size_set; /* Was the size set? */ | |
2616 | int color_set; /* Were the color attrs set? */ | |
2617 | gdev_prn_space_params sp; /* Space parameter data */ | |
2618 | int width, /* New width of page */ | |
2619 | height; /* New height of page */ | |
2620 | ||
2621 | ||
2622 | #ifdef DEBUG | |
2623 | fprintf(stderr, "DEBUG2: cups_put_params(%p, %p)\n", pdev, plist); | |
2624 | #endif /* DEBUG */ | |
2625 | ||
2626 | /* | |
2627 | * Process other options for CUPS... | |
2628 | */ | |
2629 | ||
2630 | #define stringoption(name, sname) \ | |
2631 | if ((code = param_read_string(plist, sname, &stringval)) < 0) \ | |
2632 | { \ | |
2633 | param_signal_error(plist, sname, code); \ | |
2634 | return (code); \ | |
2635 | } \ | |
2636 | else if (code == 0) \ | |
2637 | { \ | |
2638 | strncpy(cups->header.name, (const char *)stringval.data, \ | |
2639 | stringval.size); \ | |
2640 | cups->header.name[stringval.size] = '\0'; \ | |
2641 | } | |
2642 | ||
2643 | #define intoption(name, sname, type) \ | |
2644 | if ((code = param_read_int(plist, sname, &intval)) < 0) \ | |
2645 | { \ | |
2646 | param_signal_error(plist, sname, code); \ | |
2647 | return (code); \ | |
2648 | } \ | |
2649 | else if (code == 0) \ | |
2650 | { \ | |
2651 | fprintf(stderr, "DEBUG: Setting %s to %d...\n", sname, intval); \ | |
2652 | cups->header.name = (type)intval; \ | |
2653 | } | |
2654 | ||
2655 | #define floatoption(name, sname) \ | |
2656 | if ((code = param_read_float(plist, sname, &floatval)) < 0) \ | |
2657 | { \ | |
2658 | param_signal_error(plist, sname, code); \ | |
2659 | return (code); \ | |
2660 | } \ | |
2661 | else if (code == 0) \ | |
2662 | cups->header.name = (unsigned)floatval; | |
2663 | ||
2664 | #define booloption(name, sname) \ | |
2665 | if ((code = param_read_bool(plist, sname, &boolval)) < 0) \ | |
2666 | { \ | |
2667 | if ((code = param_read_null(plist, sname)) < 0) \ | |
2668 | { \ | |
2669 | param_signal_error(plist, sname, code); \ | |
2670 | return (code); \ | |
2671 | } \ | |
2672 | if (code == 0) \ | |
2673 | cups->header.name = CUPS_FALSE; \ | |
2674 | } \ | |
2675 | else if (code == 0) \ | |
2676 | cups->header.name = (cups_bool_t)boolval; | |
2677 | ||
2678 | #define arrayoption(name, sname, count) \ | |
2679 | if ((code = param_read_float_array(plist, sname, &arrayval)) < 0) \ | |
2680 | { \ | |
2681 | if ((code = param_read_null(plist, sname)) < 0) \ | |
2682 | { \ | |
2683 | param_signal_error(plist, sname, code); \ | |
2684 | return (code); \ | |
2685 | } \ | |
2686 | if (code == 0) \ | |
2687 | for (i = 0; i < count; i ++) \ | |
2688 | cups->header.name[i] = 0; \ | |
2689 | } \ | |
2690 | else if (code == 0) \ | |
2691 | { \ | |
2692 | for (i = 0; i < count; i ++) \ | |
2693 | cups->header.name[i] = (unsigned)arrayval.data[i]; \ | |
2694 | } | |
2695 | ||
2696 | size_set = param_read_float_array(plist, ".MediaSize", &arrayval) == 0 || | |
2697 | param_read_float_array(plist, "PageSize", &arrayval) == 0; | |
2698 | color_set = param_read_int(plist, "cupsColorSpace", &intval) == 0 || | |
2699 | param_read_int(plist, "cupsBitsPerColor", &intval) == 0; | |
2700 | ||
2701 | stringoption(MediaClass, "MediaClass") | |
2702 | stringoption(MediaColor, "MediaColor") | |
2703 | stringoption(MediaType, "MediaType") | |
2704 | stringoption(OutputType, "OutputType") | |
2705 | floatoption(AdvanceDistance, "AdvanceDistance") | |
2706 | intoption(AdvanceMedia, "AdvanceMedia", cups_adv_t) | |
2707 | booloption(Collate, "Collate") | |
2708 | intoption(CutMedia, "CutMedia", cups_cut_t) | |
2709 | booloption(Duplex, "Duplex") | |
2710 | arrayoption(ImagingBoundingBox, "ImagingBoundingBox", 4) | |
2711 | booloption(InsertSheet, "InsertSheet") | |
2712 | intoption(Jog, "Jog", cups_jog_t) | |
2713 | intoption(LeadingEdge, "LeadingEdge", cups_edge_t) | |
2714 | arrayoption(Margins, "Margins", 2) | |
2715 | booloption(ManualFeed, "ManualFeed") | |
2716 | intoption(MediaPosition, "cupsMediaPosition", unsigned) /* Compatibility */ | |
2717 | intoption(MediaPosition, "MediaPosition", unsigned) | |
2718 | floatoption(MediaWeight, "MediaWeight") | |
2719 | booloption(MirrorPrint, "MirrorPrint") | |
2720 | booloption(NegativePrint, "NegativePrint") | |
2721 | intoption(Orientation, "Orientation", cups_orient_t) | |
2722 | booloption(OutputFaceUp, "OutputFaceUp") | |
2723 | booloption(Separations, "Separations") | |
2724 | booloption(TraySwitch, "TraySwitch") | |
2725 | booloption(Tumble, "Tumble") | |
2726 | intoption(cupsMediaType, "cupsMediaType", unsigned) | |
2727 | intoption(cupsBitsPerColor, "cupsBitsPerColor", unsigned) | |
2728 | intoption(cupsColorOrder, "cupsColorOrder", cups_order_t) | |
2729 | intoption(cupsColorSpace, "cupsColorSpace", cups_cspace_t) | |
2730 | intoption(cupsCompression, "cupsCompression", unsigned) | |
2731 | intoption(cupsRowCount, "cupsRowCount", unsigned) | |
2732 | intoption(cupsRowFeed, "cupsRowFeed", unsigned) | |
2733 | intoption(cupsRowStep, "cupsRowStep", unsigned) | |
2734 | ||
2735 | #ifdef CUPS_RASTER_SYNCv1 | |
2736 | for (i = 0; i < 16; i ++) | |
2737 | { | |
2738 | sprintf(name, "cupsInteger%d", i); | |
2739 | intoption(cupsInteger[i], name, unsigned) | |
2740 | } | |
2741 | ||
2742 | for (i = 0; i < 16; i ++) | |
2743 | { | |
2744 | sprintf(name, "cupsReal%d", i); | |
2745 | floatoption(cupsReal[i], name) | |
2746 | } | |
2747 | ||
2748 | for (i = 0; i < 16; i ++) | |
2749 | { | |
2750 | sprintf(name, "cupsString%d", i); | |
2751 | stringoption(cupsString[i], name) | |
2752 | } | |
2753 | ||
2754 | stringoption(cupsMarkerType, "cupsMarkerType"); | |
2755 | stringoption(cupsRenderingIntent, "cupsRenderingIntent"); | |
2756 | #endif /* CUPS_RASTER_SYNCv1 */ | |
2757 | ||
2758 | if ((code = param_read_string(plist, "cupsProfile", &stringval)) < 0) | |
2759 | { | |
2760 | param_signal_error(plist, "cupsProfile", code); | |
2761 | return (code); | |
2762 | } | |
2763 | else if (code == 0) | |
2764 | { | |
2765 | if (cupsProfile != NULL) | |
2766 | free(cupsProfile); | |
2767 | ||
2768 | cupsProfile = strdup(stringval.data); | |
2769 | } | |
2770 | ||
2771 | cups_set_color_info(pdev); | |
2772 | ||
2773 | /* | |
2774 | * Then process standard page device options... | |
2775 | */ | |
2776 | ||
2777 | if ((code = gdev_prn_put_params(pdev, plist)) < 0) | |
2778 | return (code); | |
2779 | ||
2780 | /* | |
2781 | * Update margins/sizes as needed... | |
2782 | */ | |
2783 | ||
2784 | if (size_set) | |
2785 | { | |
2786 | /* | |
2787 | * Compute the page margins... | |
2788 | */ | |
2789 | ||
2790 | fprintf(stderr, "DEBUG: Updating PageSize to [%.0f %.0f]...\n", | |
2791 | cups->MediaSize[0], cups->MediaSize[1]); | |
2792 | ||
2793 | memset(margins, 0, sizeof(margins)); | |
2794 | ||
2795 | cups->landscape = 0; | |
2796 | ||
2797 | if (cupsPPD != NULL) | |
2798 | { | |
2799 | /* | |
2800 | * Find the matching page size... | |
2801 | */ | |
2802 | ||
2803 | for (i = cupsPPD->num_sizes, size = cupsPPD->sizes; | |
2804 | i > 0; | |
2805 | i --, size ++) | |
2806 | if (fabs(cups->MediaSize[1] - size->length) < 5.0 && | |
2807 | fabs(cups->MediaSize[0] - size->width) < 5.0) | |
2808 | break; | |
2809 | ||
2810 | if (i > 0) | |
2811 | { | |
2812 | /* | |
2813 | * Standard size... | |
2814 | */ | |
2815 | ||
2816 | fprintf(stderr, "DEBUG: size = %s\n", size->name); | |
2817 | ||
2818 | gx_device_set_media_size(pdev, size->width, size->length); | |
2819 | ||
2820 | margins[0] = size->left / 72.0; | |
2821 | margins[1] = size->bottom / 72.0; | |
2822 | margins[2] = (size->width - size->right) / 72.0; | |
2823 | margins[3] = (size->length - size->top) / 72.0; | |
2824 | } | |
2825 | else | |
2826 | { | |
2827 | /* | |
2828 | * No matching portrait size; look for a matching size in | |
2829 | * landscape orientation... | |
2830 | */ | |
2831 | ||
2832 | for (i = cupsPPD->num_sizes, size = cupsPPD->sizes; | |
2833 | i > 0; | |
2834 | i --, size ++) | |
2835 | if (fabs(cups->MediaSize[0] - size->length) < 5.0 && | |
2836 | fabs(cups->MediaSize[1] - size->width) < 5.0) | |
2837 | break; | |
2838 | ||
2839 | if (i > 0) | |
2840 | { | |
2841 | /* | |
2842 | * Standard size in landscape orientation... | |
2843 | */ | |
2844 | ||
2845 | fprintf(stderr, "DEBUG: landscape size = %s\n", size->name); | |
2846 | ||
2847 | gx_device_set_media_size(pdev, size->length, size->width); | |
2848 | ||
2849 | cups->landscape = 1; | |
2850 | ||
2851 | margins[0] = size->left / 72.0; | |
2852 | margins[1] = size->bottom / 72.0; | |
2853 | margins[2] = (size->width - size->right) / 72.0; | |
2854 | margins[3] = (size->length - size->top) / 72.0; | |
2855 | } | |
2856 | else | |
2857 | { | |
2858 | /* | |
2859 | * Custom size... | |
2860 | */ | |
2861 | ||
2862 | fputs("DEBUG: size = Custom\n", stderr); | |
2863 | ||
2864 | for (i = 0; i < 4; i ++) | |
2865 | margins[i] = cupsPPD->custom_margins[i] / 72.0; | |
2866 | } | |
2867 | } | |
2868 | ||
2869 | fprintf(stderr, "DEBUG: margins[] = [ %f %f %f %f ]\n", | |
2870 | margins[0], margins[1], margins[2], margins[3]); | |
2871 | } | |
2872 | ||
2873 | /* | |
2874 | * Set the margins to update the bitmap size... | |
2875 | */ | |
2876 | ||
2877 | gx_device_set_margins(pdev, margins, false); | |
2878 | } | |
2879 | ||
2880 | /* | |
2881 | * Set CUPS raster header values... | |
2882 | */ | |
2883 | ||
2884 | cups->header.HWResolution[0] = pdev->HWResolution[0]; | |
2885 | cups->header.HWResolution[1] = pdev->HWResolution[1]; | |
2886 | ||
2887 | cups->header.Margins[0] = pdev->HWMargins[0]; | |
2888 | cups->header.Margins[1] = pdev->HWMargins[1]; | |
2889 | ||
2890 | cups->header.PageSize[0] = pdev->MediaSize[0]; | |
2891 | cups->header.PageSize[1] = pdev->MediaSize[1]; | |
2892 | ||
2893 | cups->header.ImagingBoundingBox[0] = pdev->HWMargins[0]; | |
2894 | cups->header.ImagingBoundingBox[1] = pdev->HWMargins[3]; | |
2895 | cups->header.ImagingBoundingBox[2] = pdev->MediaSize[0] - pdev->HWMargins[2]; | |
2896 | cups->header.ImagingBoundingBox[3] = pdev->MediaSize[1] - pdev->HWMargins[1]; | |
2897 | ||
2898 | /* | |
2899 | * Reallocate memory if the size or color depth was changed... | |
2900 | */ | |
2901 | ||
2902 | if (color_set || size_set) | |
2903 | { | |
2904 | /* | |
2905 | * Make sure the page image is the correct size - current Ghostscript | |
2906 | * does not keep track of the margins in the bitmap size... | |
2907 | */ | |
2908 | ||
2909 | if (cups->landscape) | |
2910 | { | |
2911 | width = (pdev->MediaSize[1] - pdev->HWMargins[0] - pdev->HWMargins[2]) * | |
2912 | pdev->HWResolution[0] / 72.0f + 0.499f; | |
2913 | height = (pdev->MediaSize[0] - pdev->HWMargins[1] - pdev->HWMargins[3]) * | |
2914 | pdev->HWResolution[1] / 72.0f + 0.499f; | |
2915 | } | |
2916 | else | |
2917 | { | |
2918 | width = (pdev->MediaSize[0] - pdev->HWMargins[0] - pdev->HWMargins[2]) * | |
2919 | pdev->HWResolution[0] / 72.0f + 0.499f; | |
2920 | height = (pdev->MediaSize[1] - pdev->HWMargins[1] - pdev->HWMargins[3]) * | |
2921 | pdev->HWResolution[1] / 72.0f + 0.499f; | |
2922 | } | |
2923 | ||
2924 | /* | |
2925 | * Don't reallocate memory unless the device has been opened... | |
2926 | */ | |
2927 | ||
2928 | if (pdev->is_open) | |
2929 | { | |
2930 | /* | |
2931 | * Device is open, so reallocate... | |
2932 | */ | |
2933 | ||
2934 | fprintf(stderr, "DEBUG: Reallocating memory, [%.0f %.0f] = %dx%d pixels...\n", | |
2935 | pdev->MediaSize[0], pdev->MediaSize[1], width, height); | |
2936 | ||
2937 | sp = ((gx_device_printer *)pdev)->space_params; | |
2938 | ||
2939 | if ((code = gdev_prn_reallocate_memory(pdev, &sp, width, height)) < 0) | |
2940 | return (code); | |
2941 | } | |
2942 | else | |
2943 | { | |
2944 | /* | |
2945 | * Device isn't yet open, so just save the new width and height... | |
2946 | */ | |
2947 | ||
2948 | fprintf(stderr, "DEBUG: Setting initial media size, [%.0f %.0f] = %dx%d pixels...\n", | |
2949 | pdev->MediaSize[0], pdev->MediaSize[1], width, height); | |
2950 | ||
2951 | pdev->width = width; | |
2952 | pdev->height = height; | |
2953 | } | |
2954 | } | |
2955 | ||
2956 | #ifdef DEBUG | |
2957 | fprintf(stderr, "DEBUG2: ppd = %p\n", cupsPPD); | |
2958 | fprintf(stderr, "DEBUG2: PageSize = [ %.3f %.3f ]\n", | |
2959 | pdev->MediaSize[0], pdev->MediaSize[1]); | |
2960 | fprintf(stderr, "DEBUG2: margins = [ %.3f %.3f %.3f %.3f ]\n", | |
2961 | margins[0], margins[1], margins[2], margins[3]); | |
2962 | fprintf(stderr, "DEBUG2: HWResolution = [ %.3f %.3f ]\n", | |
2963 | pdev->HWResolution[0], pdev->HWResolution[1]); | |
2964 | fprintf(stderr, "DEBUG2: width = %d, height = %d\n", | |
2965 | pdev->width, pdev->height); | |
2966 | fprintf(stderr, "DEBUG2: HWMargins = [ %.3f %.3f %.3f %.3f ]\n", | |
2967 | pdev->HWMargins[0], pdev->HWMargins[1], | |
2968 | pdev->HWMargins[2], pdev->HWMargins[3]); | |
2969 | #endif /* DEBUG */ | |
2970 | ||
2971 | return (0); | |
2972 | } | |
2973 | ||
2974 | ||
2975 | /* | |
2976 | * 'cups_set_color_info()' - Set the color information structure based on | |
2977 | * the required output. | |
2978 | */ | |
2979 | ||
2980 | private void | |
2981 | cups_set_color_info(gx_device *pdev) /* I - Device info */ | |
2982 | { | |
2983 | int i, j, k; /* Looping vars */ | |
2984 | int max_lut; /* Maximum LUT value */ | |
2985 | float d, g; /* Density and gamma correction */ | |
2986 | float m[3][3]; /* Color correction matrix */ | |
2987 | char resolution[41]; /* Resolution string */ | |
2988 | ppd_profile_t *profile; /* Color profile information */ | |
2989 | ||
2990 | ||
2991 | #ifdef DEBUG | |
2992 | fprintf(stderr, "DEBUG2: cups_set_color_info(%p)\n", pdev); | |
2993 | #endif /* DEBUG */ | |
2994 | ||
2995 | switch (cups->header.cupsColorSpace) | |
2996 | { | |
2997 | default : | |
2998 | case CUPS_CSPACE_W : | |
2999 | case CUPS_CSPACE_K : | |
3000 | case CUPS_CSPACE_WHITE : | |
3001 | case CUPS_CSPACE_GOLD : | |
3002 | case CUPS_CSPACE_SILVER : | |
3003 | cups->header.cupsBitsPerPixel = cups->header.cupsBitsPerColor; | |
3004 | cups->color_info.depth = cups->header.cupsBitsPerPixel; | |
3005 | cups->color_info.num_components = 1; | |
3006 | break; | |
3007 | ||
3008 | case CUPS_CSPACE_CMY : | |
3009 | case CUPS_CSPACE_YMC : | |
3010 | case CUPS_CSPACE_RGB : | |
3011 | if (cups->header.cupsColorOrder != CUPS_ORDER_CHUNKED) | |
3012 | cups->header.cupsBitsPerPixel = cups->header.cupsBitsPerColor; | |
3013 | else if (cups->header.cupsBitsPerColor < 8) | |
3014 | cups->header.cupsBitsPerPixel = 4 * cups->header.cupsBitsPerColor; | |
3015 | else | |
3016 | cups->header.cupsBitsPerPixel = 3 * cups->header.cupsBitsPerColor; | |
3017 | ||
3018 | if (cups->header.cupsBitsPerColor < 8) | |
3019 | cups->color_info.depth = 4 * cups->header.cupsBitsPerColor; | |
3020 | else | |
3021 | cups->color_info.depth = 3 * cups->header.cupsBitsPerColor; | |
3022 | ||
3023 | cups->color_info.num_components = 3; | |
3024 | break; | |
3025 | ||
3026 | case CUPS_CSPACE_KCMYcm : | |
3027 | if (cups->header.cupsBitsPerColor == 1) | |
3028 | { | |
3029 | cups->header.cupsBitsPerPixel = 8; | |
3030 | cups->color_info.depth = 8; | |
3031 | cups->color_info.num_components = 4; | |
3032 | break; | |
3033 | } | |
3034 | ||
3035 | case CUPS_CSPACE_CMYK : | |
3036 | case CUPS_CSPACE_YMCK : | |
3037 | case CUPS_CSPACE_KCMY : | |
3038 | case CUPS_CSPACE_GMCK : | |
3039 | case CUPS_CSPACE_GMCS : | |
3040 | if (cups->header.cupsColorOrder != CUPS_ORDER_CHUNKED) | |
3041 | cups->header.cupsBitsPerPixel = cups->header.cupsBitsPerColor; | |
3042 | else | |
3043 | cups->header.cupsBitsPerPixel = 4 * cups->header.cupsBitsPerColor; | |
3044 | ||
3045 | cups->color_info.depth = 4 * cups->header.cupsBitsPerColor; | |
3046 | cups->color_info.num_components = 4; | |
3047 | break; | |
3048 | ||
3049 | #ifdef CUPS_RASTER_HAVE_COLORIMETRIC | |
3050 | case CUPS_CSPACE_CIEXYZ : | |
3051 | case CUPS_CSPACE_CIELab : | |
3052 | case CUPS_CSPACE_ICC1 : | |
3053 | case CUPS_CSPACE_ICC2 : | |
3054 | case CUPS_CSPACE_ICC3 : | |
3055 | case CUPS_CSPACE_ICC4 : | |
3056 | case CUPS_CSPACE_ICC5 : | |
3057 | case CUPS_CSPACE_ICC6 : | |
3058 | case CUPS_CSPACE_ICC7 : | |
3059 | case CUPS_CSPACE_ICC8 : | |
3060 | case CUPS_CSPACE_ICC9 : | |
3061 | case CUPS_CSPACE_ICCA : | |
3062 | case CUPS_CSPACE_ICCB : | |
3063 | case CUPS_CSPACE_ICCC : | |
3064 | case CUPS_CSPACE_ICCD : | |
3065 | case CUPS_CSPACE_ICCE : | |
3066 | case CUPS_CSPACE_ICCF : | |
3067 | /* | |
3068 | * Colorimetric color spaces currently are implemented as 24-bit | |
3069 | * mapping to XYZ or Lab, which are then converted as needed to | |
3070 | * the final representation... | |
3071 | * | |
3072 | * This code enforces a minimum output depth of 8 bits per | |
3073 | * component... | |
3074 | */ | |
3075 | ||
3076 | if (cups->header.cupsBitsPerColor < 8) | |
3077 | cups->header.cupsBitsPerColor = 8; | |
3078 | ||
3079 | if (cups->header.cupsColorOrder != CUPS_ORDER_CHUNKED) | |
3080 | cups->header.cupsBitsPerPixel = cups->header.cupsBitsPerColor; | |
3081 | else | |
3082 | cups->header.cupsBitsPerPixel = 3 * cups->header.cupsBitsPerColor; | |
3083 | ||
3084 | cups->color_info.depth = 24; | |
3085 | cups->color_info.num_components = 3; | |
3086 | break; | |
3087 | #endif /* CUPS_RASTER_HAVE_COLORIMETRIC */ | |
3088 | } | |
3089 | ||
3090 | #ifdef dev_t_proc_encode_color | |
3091 | switch (cups->header.cupsColorSpace) | |
3092 | { | |
3093 | default : | |
3094 | cups->color_info.gray_index = GX_CINFO_COMP_NO_INDEX; | |
3095 | break; | |
3096 | ||
3097 | case CUPS_CSPACE_W : | |
3098 | case CUPS_CSPACE_WHITE : | |
3099 | case CUPS_CSPACE_K : | |
3100 | case CUPS_CSPACE_GOLD : | |
3101 | case CUPS_CSPACE_SILVER : | |
3102 | case CUPS_CSPACE_KCMYcm : | |
3103 | case CUPS_CSPACE_KCMY : | |
3104 | cups->color_info.gray_index = 0; | |
3105 | break; | |
3106 | ||
3107 | case CUPS_CSPACE_CMYK : | |
3108 | case CUPS_CSPACE_YMCK : | |
3109 | case CUPS_CSPACE_GMCK : | |
3110 | case CUPS_CSPACE_GMCS : | |
3111 | cups->color_info.gray_index = 3; | |
3112 | break; | |
3113 | } | |
3114 | ||
3115 | switch (cups->header.cupsColorSpace) | |
3116 | { | |
3117 | default : | |
3118 | case CUPS_CSPACE_W : | |
3119 | case CUPS_CSPACE_WHITE : | |
3120 | case CUPS_CSPACE_RGB : | |
3121 | # ifdef CUPS_RASTER_HAVE_COLORIMETRIC | |
3122 | case CUPS_CSPACE_CIEXYZ : | |
3123 | case CUPS_CSPACE_CIELab : | |
3124 | case CUPS_CSPACE_ICC1 : | |
3125 | case CUPS_CSPACE_ICC2 : | |
3126 | case CUPS_CSPACE_ICC3 : | |
3127 | case CUPS_CSPACE_ICC4 : | |
3128 | case CUPS_CSPACE_ICC5 : | |
3129 | case CUPS_CSPACE_ICC6 : | |
3130 | case CUPS_CSPACE_ICC7 : | |
3131 | case CUPS_CSPACE_ICC8 : | |
3132 | case CUPS_CSPACE_ICC9 : | |
3133 | case CUPS_CSPACE_ICCA : | |
3134 | case CUPS_CSPACE_ICCB : | |
3135 | case CUPS_CSPACE_ICCC : | |
3136 | case CUPS_CSPACE_ICCD : | |
3137 | case CUPS_CSPACE_ICCE : | |
3138 | case CUPS_CSPACE_ICCF : | |
3139 | # endif /* CUPS_RASTER_HAVE_COLORIMETRIC */ | |
3140 | cups->color_info.polarity = GX_CINFO_POLARITY_ADDITIVE; | |
3141 | break; | |
3142 | ||
3143 | case CUPS_CSPACE_K : | |
3144 | case CUPS_CSPACE_GOLD : | |
3145 | case CUPS_CSPACE_SILVER : | |
3146 | case CUPS_CSPACE_CMY : | |
3147 | case CUPS_CSPACE_YMC : | |
3148 | case CUPS_CSPACE_KCMYcm : | |
3149 | case CUPS_CSPACE_CMYK : | |
3150 | case CUPS_CSPACE_YMCK : | |
3151 | case CUPS_CSPACE_KCMY : | |
3152 | case CUPS_CSPACE_GMCK : | |
3153 | case CUPS_CSPACE_GMCS : | |
3154 | cups->color_info.polarity = GX_CINFO_POLARITY_SUBTRACTIVE; | |
3155 | break; | |
3156 | } | |
3157 | ||
3158 | cups->color_info.separable_and_linear = GX_CINFO_SEP_LIN_NONE; | |
3159 | #endif /* dev_t_proc_encode_color */ | |
3160 | ||
3161 | if ((i = cups->header.cupsBitsPerColor) > 8) | |
3162 | i = 8; | |
3163 | ||
3164 | max_lut = (1 << i) - 1; | |
3165 | ||
3166 | switch (cups->color_info.num_components) | |
3167 | { | |
3168 | default : | |
3169 | case 1 : | |
3170 | cups->color_info.max_gray = max_lut; | |
3171 | cups->color_info.max_color = 0; | |
3172 | cups->color_info.dither_grays = max_lut + 1; | |
3173 | cups->color_info.dither_colors = 0; | |
3174 | break; | |
3175 | ||
3176 | case 3 : | |
3177 | cups->color_info.max_gray = 0; | |
3178 | cups->color_info.max_color = max_lut; | |
3179 | cups->color_info.dither_grays = 0; | |
3180 | cups->color_info.dither_colors = max_lut + 1; | |
3181 | break; | |
3182 | ||
3183 | case 4 : | |
3184 | cups->color_info.max_gray = max_lut; | |
3185 | cups->color_info.max_color = max_lut; | |
3186 | cups->color_info.dither_grays = max_lut + 1; | |
3187 | cups->color_info.dither_colors = max_lut + 1; | |
3188 | break; | |
3189 | } | |
3190 | ||
3191 | /* | |
3192 | * Enable/disable CMYK color support... | |
3193 | */ | |
3194 | ||
3195 | #ifdef dev_t_proc_encode_color | |
3196 | cups->color_info.max_components = cups->color_info.num_components; | |
3197 | #endif /* dev_t_proc_encode_color */ | |
3198 | ||
3199 | /* | |
3200 | * Tell Ghostscript to forget any colors it has cached... | |
3201 | */ | |
3202 | ||
3203 | gx_device_decache_colors(pdev); | |
3204 | ||
3205 | /* | |
3206 | * Compute the lookup tables... | |
3207 | */ | |
3208 | ||
3209 | for (i = 0; i <= gx_max_color_value; i ++) | |
3210 | { | |
3211 | cupsEncodeLUT[i] = (max_lut * i + gx_max_color_value / 2) / | |
3212 | gx_max_color_value; | |
3213 | ||
3214 | #ifdef DEBUG | |
3215 | if (i == 0 || cupsEncodeLUT[i] != cupsEncodeLUT[i - 1]) | |
3216 | fprintf(stderr, "DEBUG2: cupsEncodeLUT[%d] = %d\n", i, cupsEncodeLUT[i]); | |
3217 | #endif /* DEBUG */ | |
3218 | } | |
3219 | ||
3220 | for (i = 0; i < cups->color_info.dither_grays; i ++) | |
3221 | cupsDecodeLUT[i] = gx_max_color_value * i / max_lut; | |
3222 | ||
3223 | fprintf(stderr, "DEBUG: num_components = %d, depth = %d\n", | |
3224 | cups->color_info.num_components, cups->color_info.depth); | |
3225 | fprintf(stderr, "DEBUG: cupsColorSpace = %d, cupsColorOrder = %d\n", | |
3226 | cups->header.cupsColorSpace, cups->header.cupsColorOrder); | |
3227 | fprintf(stderr, "DEBUG: cupsBitsPerPixel = %d, cupsBitsPerColor = %d\n", | |
3228 | cups->header.cupsBitsPerPixel, cups->header.cupsBitsPerColor); | |
3229 | fprintf(stderr, "DEBUG: max_gray = %d, dither_grays = %d\n", | |
3230 | cups->color_info.max_gray, cups->color_info.dither_grays); | |
3231 | fprintf(stderr, "DEBUG: max_color = %d, dither_colors = %d\n", | |
3232 | cups->color_info.max_color, cups->color_info.dither_colors); | |
3233 | ||
3234 | /* | |
3235 | * Set the color profile as needed... | |
3236 | */ | |
3237 | ||
3238 | cupsHaveProfile = 0; | |
3239 | ||
3240 | #ifdef dev_t_proc_encode_color | |
3241 | if (cupsProfile) | |
3242 | #else | |
3243 | if (cupsProfile && cups->header.cupsBitsPerColor == 8) | |
3244 | #endif /* dev_t_proc_encode_color */ | |
3245 | { | |
3246 | fprintf(stderr, "DEBUG: Using user-defined profile \"%s\"...\n", cupsProfile); | |
3247 | ||
3248 | if (sscanf(cupsProfile, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f", &d, &g, | |
3249 | m[0] + 0, m[0] + 1, m[0] + 2, | |
3250 | m[1] + 0, m[1] + 1, m[1] + 2, | |
3251 | m[2] + 0, m[2] + 1, m[2] + 2) != 11) | |
3252 | fputs("DEBUG: User-defined profile does not contain 11 integers!\n", stderr); | |
3253 | else | |
3254 | { | |
3255 | cupsHaveProfile = 1; | |
3256 | ||
3257 | d *= 0.001f; | |
3258 | g *= 0.001f; | |
3259 | m[0][0] *= 0.001f; | |
3260 | m[0][1] *= 0.001f; | |
3261 | m[0][2] *= 0.001f; | |
3262 | m[1][0] *= 0.001f; | |
3263 | m[1][1] *= 0.001f; | |
3264 | m[1][2] *= 0.001f; | |
3265 | m[2][0] *= 0.001f; | |
3266 | m[2][1] *= 0.001f; | |
3267 | m[2][2] *= 0.001f; | |
3268 | } | |
3269 | } | |
3270 | #ifdef dev_t_proc_encode_color | |
3271 | else if (cupsPPD) | |
3272 | #else | |
3273 | else if (cupsPPD && cups->header.cupsBitsPerColor == 8) | |
3274 | #endif /* dev_t_proc_encode_color */ | |
3275 | { | |
3276 | /* | |
3277 | * Find the appropriate color profile... | |
3278 | */ | |
3279 | ||
3280 | if (pdev->HWResolution[0] != pdev->HWResolution[1]) | |
3281 | sprintf(resolution, "%.0fx%.0fdpi", pdev->HWResolution[0], | |
3282 | pdev->HWResolution[1]); | |
3283 | else | |
3284 | sprintf(resolution, "%.0fdpi", pdev->HWResolution[0]); | |
3285 | ||
3286 | for (i = 0, profile = cupsPPD->profiles; | |
3287 | i < cupsPPD->num_profiles; | |
3288 | i ++, profile ++) | |
3289 | if ((strcmp(profile->resolution, resolution) == 0 || | |
3290 | profile->resolution[0] == '-') && | |
3291 | (strcmp(profile->media_type, cups->header.MediaType) == 0 || | |
3292 | profile->media_type[0] == '-')) | |
3293 | break; | |
3294 | ||
3295 | /* | |
3296 | * If we found a color profile, use it! | |
3297 | */ | |
3298 | ||
3299 | if (i < cupsPPD->num_profiles) | |
3300 | { | |
3301 | fputs("DEBUG: Using color profile in PPD file!\n", stderr); | |
3302 | ||
3303 | cupsHaveProfile = 1; | |
3304 | ||
3305 | d = profile->density; | |
3306 | g = profile->gamma; | |
3307 | ||
3308 | memcpy(m, profile->matrix, sizeof(m)); | |
3309 | } | |
3310 | } | |
3311 | ||
3312 | if (cupsHaveProfile) | |
3313 | { | |
3314 | for (i = 0; i < 3; i ++) | |
3315 | for (j = 0; j < 3; j ++) | |
3316 | for (k = 0; k <= CUPS_MAX_VALUE; k ++) | |
3317 | { | |
3318 | cupsMatrix[i][j][k] = (int)((float)k * m[i][j] + 0.5); | |
3319 | ||
3320 | #ifdef DEBUG | |
3321 | if ((k & 4095) == 0) | |
3322 | fprintf(stderr, "DEBUG2: cupsMatrix[%d][%d][%d] = %d\n", | |
3323 | i, j, k, cupsMatrix[i][j][k]); | |
3324 | #endif /* DEBUG */ | |
3325 | } | |
3326 | ||
3327 | ||
3328 | for (k = 0; k <= CUPS_MAX_VALUE; k ++) | |
3329 | { | |
3330 | cupsDensity[k] = (int)((float)CUPS_MAX_VALUE * d * | |
3331 | pow((float)k / (float)CUPS_MAX_VALUE, g) + | |
3332 | 0.5); | |
3333 | ||
3334 | #ifdef DEBUG | |
3335 | if ((k & 4095) == 0) | |
3336 | fprintf(stderr, "DEBUG2: cupsDensity[%d] = %d\n", k, cupsDensity[k]); | |
3337 | #endif /* DEBUG */ | |
3338 | } | |
3339 | } | |
3340 | else | |
3341 | { | |
3342 | for (k = 0; k <= CUPS_MAX_VALUE; k ++) | |
3343 | cupsDensity[k] = k; | |
3344 | } | |
3345 | } | |
3346 | ||
3347 | ||
3348 | /* | |
3349 | * 'cups_sync_output()' - Keep the user informed of our status... | |
3350 | */ | |
3351 | ||
3352 | private int /* O - Error status */ | |
3353 | cups_sync_output(gx_device *pdev) /* I - Device info */ | |
3354 | { | |
3355 | fprintf(stderr, "INFO: Processing page %d...\n", cups->page); | |
3356 | ||
3357 | return (0); | |
3358 | } | |
3359 | ||
3360 | ||
3361 | /* | |
3362 | * 'cups_print_chunked()' - Print a page of chunked pixels. | |
3363 | */ | |
3364 | ||
3365 | static void | |
3366 | cups_print_chunked(gx_device_printer *pdev, | |
3367 | /* I - Printer device */ | |
3368 | unsigned char *src, | |
3369 | /* I - Scanline buffer */ | |
3370 | unsigned char *dst, | |
3371 | /* I - Bitmap buffer */ | |
3372 | int srcbytes) | |
3373 | /* I - Number of bytes in src */ | |
3374 | { | |
3375 | int y; /* Looping var */ | |
3376 | unsigned char *srcptr, /* Pointer to data */ | |
3377 | *dstptr; /* Pointer to bits */ | |
3378 | int count; /* Count for loop */ | |
3379 | int flip; /* Flip scanline? */ | |
3380 | ||
3381 | ||
3382 | if (cups->header.Duplex && !cups->header.Tumble && | |
3383 | cupsPPD && cupsPPD->flip_duplex && !(cups->page & 1)) | |
3384 | flip = 1; | |
3385 | else | |
3386 | flip = 0; | |
3387 | ||
3388 | fprintf(stderr, "DEBUG: cups_print_chunked - flip = %d, height = %d\n", | |
3389 | flip, cups->height); | |
3390 | ||
3391 | /* | |
3392 | * Loop through the page bitmap and write chunked pixels, reversing as | |
3393 | * needed... | |
3394 | */ | |
3395 | ||
3396 | for (y = 0; y < cups->height; y ++) | |
3397 | { | |
3398 | /* | |
3399 | * Grab the scanline data... | |
3400 | */ | |
3401 | ||
3402 | if (gdev_prn_get_bits((gx_device_printer *)pdev, y, src, &srcptr) < 0) | |
3403 | { | |
3404 | fprintf(stderr, "ERROR: Unable to get scanline %d!\n", y); | |
3405 | gs_exit(1); | |
3406 | } | |
3407 | ||
3408 | if (flip) | |
3409 | { | |
3410 | /* | |
3411 | * Flip the raster data before writing it... | |
3412 | */ | |
3413 | ||
3414 | if (srcptr[0] == 0 && memcmp(srcptr, srcptr + 1, srcbytes - 1) == 0) | |
3415 | memset(dst, 0, cups->header.cupsBytesPerLine); | |
3416 | else | |
3417 | { | |
3418 | dstptr = dst; | |
3419 | count = srcbytes; | |
3420 | ||
3421 | switch (cups->color_info.depth) | |
3422 | { | |
3423 | case 1 : /* B&W bitmap */ | |
3424 | for (srcptr += srcbytes - 1; | |
3425 | count > 0; | |
3426 | count --, srcptr --, dstptr ++) | |
3427 | { | |
3428 | *dstptr = cupsRevUpper1[*srcptr & 15] | | |
3429 | cupsRevLower1[*srcptr >> 4]; | |
3430 | } | |
3431 | break; | |
3432 | ||
3433 | case 2 : /* 2-bit grayscale */ | |
3434 | for (srcptr += srcbytes - 1; | |
3435 | count > 0; | |
3436 | count --, srcptr --, dstptr ++) | |
3437 | { | |
3438 | *dstptr = cupsRevUpper2[*srcptr & 15] | | |
3439 | cupsRevLower2[*srcptr >> 4]; | |
3440 | } | |
3441 | break; | |
3442 | ||
3443 | case 4 : /* 4-bit grayscale, or RGB, CMY, or CMYK bitmap */ | |
3444 | for (srcptr += srcbytes - 1; | |
3445 | count > 0; | |
3446 | count --, srcptr --, dstptr ++) | |
3447 | *dstptr = (*srcptr >> 4) | (*srcptr << 4); | |
3448 | break; | |
3449 | ||
3450 | case 8 : /* 8-bit grayscale, or 2-bit RGB, CMY, or CMYK image */ | |
3451 | for (srcptr += srcbytes - 1; | |
3452 | count > 0; | |
3453 | count --, srcptr --, dstptr ++) | |
3454 | *dstptr = *srcptr; | |
3455 | break; | |
3456 | ||
3457 | case 16 : /* 4-bit RGB, CMY or CMYK image */ | |
3458 | for (srcptr += srcbytes - 2; | |
3459 | count > 0; | |
3460 | count -= 2, srcptr -= 2, dstptr += 2) | |
3461 | { | |
3462 | dstptr[0] = srcptr[0]; | |
3463 | dstptr[1] = srcptr[1]; | |
3464 | } | |
3465 | break; | |
3466 | ||
3467 | case 24 : /* 8-bit RGB or CMY image */ | |
3468 | for (srcptr += srcbytes - 3; | |
3469 | count > 0; | |
3470 | count -= 3, srcptr -= 3, dstptr += 3) | |
3471 | { | |
3472 | dstptr[0] = srcptr[0]; | |
3473 | dstptr[1] = srcptr[1]; | |
3474 | dstptr[2] = srcptr[2]; | |
3475 | } | |
3476 | break; | |
3477 | ||
3478 | case 32 : /* 4-bit RGB, CMY or CMYK bitmap */ | |
3479 | for (srcptr += srcbytes - 4; | |
3480 | count > 0; | |
3481 | count -= 4, srcptr -= 4, dstptr += 4) | |
3482 | { | |
3483 | dstptr[0] = srcptr[0]; | |
3484 | dstptr[1] = srcptr[1]; | |
3485 | dstptr[2] = srcptr[2]; | |
3486 | dstptr[3] = srcptr[3]; | |
3487 | } | |
3488 | break; | |
3489 | } | |
3490 | } | |
3491 | ||
3492 | /* | |
3493 | * Write the bitmap data to the raster stream... | |
3494 | */ | |
3495 | ||
3496 | cupsRasterWritePixels(cups->stream, dst, cups->header.cupsBytesPerLine); | |
3497 | } | |
3498 | else | |
3499 | { | |
3500 | /* | |
3501 | * Write the scanline data to the raster stream... | |
3502 | */ | |
3503 | ||
3504 | cupsRasterWritePixels(cups->stream, srcptr, cups->header.cupsBytesPerLine); | |
3505 | } | |
3506 | } | |
3507 | } | |
3508 | ||
3509 | ||
3510 | /* | |
3511 | * 'cups_print_banded()' - Print a page of banded pixels. | |
3512 | */ | |
3513 | ||
3514 | static void | |
3515 | cups_print_banded(gx_device_printer *pdev, | |
3516 | /* I - Printer device */ | |
3517 | unsigned char *src, | |
3518 | /* I - Scanline buffer */ | |
3519 | unsigned char *dst, | |
3520 | /* I - Bitmap buffer */ | |
3521 | int srcbytes) | |
3522 | /* I - Number of bytes in src */ | |
3523 | { | |
3524 | int x; /* Looping var */ | |
3525 | int y; /* Looping var */ | |
3526 | int bandbytes; /* Bytes per band */ | |
3527 | unsigned char bit; /* Current bit */ | |
3528 | unsigned char temp; /* Temporary variable */ | |
3529 | unsigned char *srcptr; /* Pointer to data */ | |
3530 | unsigned char *cptr, *mptr, *yptr, /* Pointer to components */ | |
3531 | *kptr, *lcptr, *lmptr; /* ... */ | |
3532 | int flip; /* Flip scanline? */ | |
3533 | ||
3534 | ||
3535 | if (cups->header.Duplex && !cups->header.Tumble && | |
3536 | cupsPPD && cupsPPD->flip_duplex && !(cups->page & 1)) | |
3537 | flip = 1; | |
3538 | else | |
3539 | flip = 0; | |
3540 | ||
3541 | fprintf(stderr, "DEBUG: cups_print_banded - flip = %d, height = %d\n", | |
3542 | flip, cups->height); | |
3543 | ||
3544 | /* | |
3545 | * Loop through the page bitmap and write banded pixels... We have | |
3546 | * to separate each chunked color as needed... | |
3547 | */ | |
3548 | ||
3549 | bandbytes = (cups->header.cupsWidth * cups->header.cupsBitsPerColor + 7) / 8; | |
3550 | ||
3551 | for (y = 0; y < cups->height; y ++) | |
3552 | { | |
3553 | /* | |
3554 | * Grab the scanline data... | |
3555 | */ | |
3556 | ||
3557 | if (gdev_prn_get_bits((gx_device_printer *)pdev, y, src, &srcptr) < 0) | |
3558 | { | |
3559 | fprintf(stderr, "ERROR: Unable to get scanline %d!\n", y); | |
3560 | gs_exit(1); | |
3561 | } | |
3562 | ||
3563 | /* | |
3564 | * Separate the chunked colors into their components... | |
3565 | */ | |
3566 | ||
3567 | if (srcptr[0] == 0 && memcmp(srcptr, srcptr + 1, srcbytes - 1) == 0) | |
3568 | memset(dst, 0, cups->header.cupsBytesPerLine); | |
3569 | else | |
3570 | { | |
3571 | if (flip) | |
3572 | cptr = dst + bandbytes - 1; | |
3573 | else | |
3574 | cptr = dst; | |
3575 | ||
3576 | mptr = cptr + bandbytes; | |
3577 | yptr = mptr + bandbytes; | |
3578 | kptr = yptr + bandbytes; | |
3579 | lcptr = yptr + bandbytes; | |
3580 | lmptr = lcptr + bandbytes; | |
3581 | ||
3582 | switch (cups->header.cupsBitsPerColor) | |
3583 | { | |
3584 | default : | |
3585 | memset(dst, 0, cups->header.cupsBytesPerLine); | |
3586 | ||
3587 | switch (cups->header.cupsColorSpace) | |
3588 | { | |
3589 | default : | |
3590 | for (x = cups->width, bit = flip ? 1 << (x & 7) : 128; | |
3591 | x > 0; | |
3592 | x --, srcptr ++) | |
3593 | { | |
3594 | if (*srcptr & 0x40) | |
3595 | *cptr |= bit; | |
3596 | if (*srcptr & 0x20) | |
3597 | *mptr |= bit; | |
3598 | if (*srcptr & 0x10) | |
3599 | *yptr |= bit; | |
3600 | ||
3601 | if (flip) | |
3602 | { | |
3603 | if (bit < 128) | |
3604 | bit <<= 1; | |
3605 | else | |
3606 | { | |
3607 | cptr --; | |
3608 | mptr --; | |
3609 | yptr --; | |
3610 | bit = 1; | |
3611 | } | |
3612 | } | |
3613 | else | |
3614 | bit >>= 1; | |
3615 | ||
3616 | x --; | |
3617 | if (x == 0) | |
3618 | break; | |
3619 | ||
3620 | if (*srcptr & 0x4) | |
3621 | *cptr |= bit; | |
3622 | if (*srcptr & 0x2) | |
3623 | *mptr |= bit; | |
3624 | if (*srcptr & 0x1) | |
3625 | *yptr |= bit; | |
3626 | ||
3627 | if (flip) | |
3628 | { | |
3629 | if (bit < 128) | |
3630 | bit <<= 1; | |
3631 | else | |
3632 | { | |
3633 | cptr --; | |
3634 | mptr --; | |
3635 | yptr --; | |
3636 | bit = 1; | |
3637 | } | |
3638 | } | |
3639 | else if (bit > 1) | |
3640 | bit >>= 1; | |
3641 | else | |
3642 | { | |
3643 | cptr ++; | |
3644 | mptr ++; | |
3645 | yptr ++; | |
3646 | bit = 128; | |
3647 | } | |
3648 | } | |
3649 | break; | |
3650 | case CUPS_CSPACE_GMCK : | |
3651 | case CUPS_CSPACE_GMCS : | |
3652 | case CUPS_CSPACE_RGBA : | |
3653 | case CUPS_CSPACE_CMYK : | |
3654 | case CUPS_CSPACE_YMCK : | |
3655 | case CUPS_CSPACE_KCMY : | |
3656 | for (x = cups->width, bit = flip ? 1 << (x & 7) : 128; | |
3657 | x > 0; | |
3658 | x --, srcptr ++) | |
3659 | { | |
3660 | if (*srcptr & 0x80) | |
3661 | *cptr |= bit; | |
3662 | if (*srcptr & 0x40) | |
3663 | *mptr |= bit; | |
3664 | if (*srcptr & 0x20) | |
3665 | *yptr |= bit; | |
3666 | if (*srcptr & 0x10) | |
3667 | *kptr |= bit; | |
3668 | ||
3669 | if (flip) | |
3670 | { | |
3671 | if (bit < 128) | |
3672 | bit <<= 1; | |
3673 | else | |
3674 | { | |
3675 | cptr --; | |
3676 | mptr --; | |
3677 | yptr --; | |
3678 | kptr --; | |
3679 | bit = 1; | |
3680 | } | |
3681 | } | |
3682 | else | |
3683 | bit >>= 1; | |
3684 | ||
3685 | x --; | |
3686 | if (x == 0) | |
3687 | break; | |
3688 | ||
3689 | if (*srcptr & 0x8) | |
3690 | *cptr |= bit; | |
3691 | if (*srcptr & 0x4) | |
3692 | *mptr |= bit; | |
3693 | if (*srcptr & 0x2) | |
3694 | *yptr |= bit; | |
3695 | if (*srcptr & 0x1) | |
3696 | *kptr |= bit; | |
3697 | ||
3698 | if (flip) | |
3699 | { | |
3700 | if (bit < 128) | |
3701 | bit <<= 1; | |
3702 | else | |
3703 | { | |
3704 | cptr --; | |
3705 | mptr --; | |
3706 | yptr --; | |
3707 | kptr --; | |
3708 | bit = 1; | |
3709 | } | |
3710 | } | |
3711 | else if (bit > 1) | |
3712 | bit >>= 1; | |
3713 | else | |
3714 | { | |
3715 | cptr ++; | |
3716 | mptr ++; | |
3717 | yptr ++; | |
3718 | kptr ++; | |
3719 | bit = 128; | |
3720 | } | |
3721 | } | |
3722 | break; | |
3723 | case CUPS_CSPACE_KCMYcm : | |
3724 | for (x = cups->width, bit = flip ? 1 << (x & 7) : 128; | |
3725 | x > 0; | |
3726 | x --, srcptr ++) | |
3727 | { | |
3728 | /* | |
3729 | * Note: Because of the way the pointers are setup, | |
3730 | * the following code is correct even though | |
3731 | * the names don't match... | |
3732 | */ | |
3733 | ||
3734 | if (*srcptr & 0x20) | |
3735 | *cptr |= bit; | |
3736 | if (*srcptr & 0x10) | |
3737 | *mptr |= bit; | |
3738 | if (*srcptr & 0x08) | |
3739 | *yptr |= bit; | |
3740 | if (*srcptr & 0x04) | |
3741 | *kptr |= bit; | |
3742 | if (*srcptr & 0x02) | |
3743 | *lcptr |= bit; | |
3744 | if (*srcptr & 0x01) | |
3745 | *lmptr |= bit; | |
3746 | ||
3747 | if (flip) | |
3748 | { | |
3749 | if (bit < 128) | |
3750 | bit <<= 1; | |
3751 | else | |
3752 | { | |
3753 | cptr --; | |
3754 | mptr --; | |
3755 | yptr --; | |
3756 | kptr --; | |
3757 | lcptr --; | |
3758 | lmptr --; | |
3759 | bit = 1; | |
3760 | } | |
3761 | } | |
3762 | else if (bit > 1) | |
3763 | bit >>= 1; | |
3764 | else | |
3765 | { | |
3766 | cptr ++; | |
3767 | mptr ++; | |
3768 | yptr ++; | |
3769 | kptr ++; | |
3770 | lcptr ++; | |
3771 | lmptr ++; | |
3772 | bit = 128; | |
3773 | } | |
3774 | } | |
3775 | break; | |
3776 | } | |
3777 | break; | |
3778 | ||
3779 | case 2 : | |
3780 | memset(dst, 0, cups->header.cupsBytesPerLine); | |
3781 | ||
3782 | switch (cups->header.cupsColorSpace) | |
3783 | { | |
3784 | default : | |
3785 | for (x = cups->width, bit = flip ? 3 << (2 * (x & 3)) : 0xc0; | |
3786 | x > 0; | |
3787 | x --, srcptr ++) | |
3788 | switch (bit) | |
3789 | { | |
3790 | case 0xc0 : | |
3791 | if ((temp = *srcptr & 0x30) != 0) | |
3792 | *cptr |= temp << 2; | |
3793 | if ((temp = *srcptr & 0x0c) != 0) | |
3794 | *mptr |= temp << 4; | |
3795 | if ((temp = *srcptr & 0x03) != 0) | |
3796 | *yptr |= temp << 6; | |
3797 | ||
3798 | if (flip) | |
3799 | { | |
3800 | bit = 0x03; | |
3801 | cptr --; | |
3802 | mptr --; | |
3803 | yptr --; | |
3804 | } | |
3805 | else | |
3806 | bit = 0x30; | |
3807 | break; | |
3808 | case 0x30 : | |
3809 | if ((temp = *srcptr & 0x30) != 0) | |
3810 | *cptr |= temp; | |
3811 | if ((temp = *srcptr & 0x0c) != 0) | |
3812 | *mptr |= temp << 2; | |
3813 | if ((temp = *srcptr & 0x03) != 0) | |
3814 | *yptr |= temp << 4; | |
3815 | ||
3816 | if (flip) | |
3817 | bit = 0xc0; | |
3818 | else | |
3819 | bit = 0x0c; | |
3820 | break; | |
3821 | case 0x0c : | |
3822 | if ((temp = *srcptr & 0x30) != 0) | |
3823 | *cptr |= temp >> 2; | |
3824 | if ((temp = *srcptr & 0x0c) != 0) | |
3825 | *mptr |= temp; | |
3826 | if ((temp = *srcptr & 0x03) != 0) | |
3827 | *yptr |= temp << 2; | |
3828 | ||
3829 | if (flip) | |
3830 | bit = 0x30; | |
3831 | else | |
3832 | bit = 0x03; | |
3833 | break; | |
3834 | case 0x03 : | |
3835 | if ((temp = *srcptr & 0x30) != 0) | |
3836 | *cptr |= temp >> 4; | |
3837 | if ((temp = *srcptr & 0x0c) != 0) | |
3838 | *mptr |= temp >> 2; | |
3839 | if ((temp = *srcptr & 0x03) != 0) | |
3840 | *yptr |= temp; | |
3841 | ||
3842 | if (flip) | |
3843 | bit = 0x0c; | |
3844 | else | |
3845 | { | |
3846 | bit = 0xc0; | |
3847 | cptr ++; | |
3848 | mptr ++; | |
3849 | yptr ++; | |
3850 | } | |
3851 | break; | |
3852 | } | |
3853 | break; | |
3854 | case CUPS_CSPACE_GMCK : | |
3855 | case CUPS_CSPACE_GMCS : | |
3856 | case CUPS_CSPACE_RGBA : | |
3857 | case CUPS_CSPACE_CMYK : | |
3858 | case CUPS_CSPACE_YMCK : | |
3859 | case CUPS_CSPACE_KCMY : | |
3860 | case CUPS_CSPACE_KCMYcm : | |
3861 | for (x = cups->width, bit = flip ? 3 << (2 * (x & 3)) : 0xc0; | |
3862 | x > 0; | |
3863 | x --, srcptr ++) | |
3864 | switch (bit) | |
3865 | { | |
3866 | case 0xc0 : | |
3867 | if ((temp = *srcptr & 0xc0) != 0) | |
3868 | *cptr |= temp; | |
3869 | if ((temp = *srcptr & 0x30) != 0) | |
3870 | *mptr |= temp << 2; | |
3871 | if ((temp = *srcptr & 0x0c) != 0) | |
3872 | *yptr |= temp << 4; | |
3873 | if ((temp = *srcptr & 0x03) != 0) | |
3874 | *kptr |= temp << 6; | |
3875 | ||
3876 | if (flip) | |
3877 | { | |
3878 | bit = 0x03; | |
3879 | cptr --; | |
3880 | mptr --; | |
3881 | yptr --; | |
3882 | kptr --; | |
3883 | } | |
3884 | else | |
3885 | bit = 0x30; | |
3886 | break; | |
3887 | case 0x30 : | |
3888 | if ((temp = *srcptr & 0xc0) != 0) | |
3889 | *cptr |= temp >> 2; | |
3890 | if ((temp = *srcptr & 0x30) != 0) | |
3891 | *mptr |= temp; | |
3892 | if ((temp = *srcptr & 0x0c) != 0) | |
3893 | *yptr |= temp << 2; | |
3894 | if ((temp = *srcptr & 0x03) != 0) | |
3895 | *kptr |= temp << 4; | |
3896 | ||
3897 | if (flip) | |
3898 | bit = 0xc0; | |
3899 | else | |
3900 | bit = 0x0c; | |
3901 | break; | |
3902 | case 0x0c : | |
3903 | if ((temp = *srcptr & 0xc0) != 0) | |
3904 | *cptr |= temp >> 4; | |
3905 | if ((temp = *srcptr & 0x30) != 0) | |
3906 | *mptr |= temp >> 2; | |
3907 | if ((temp = *srcptr & 0x0c) != 0) | |
3908 | *yptr |= temp; | |
3909 | if ((temp = *srcptr & 0x03) != 0) | |
3910 | *kptr |= temp << 2; | |
3911 | ||
3912 | if (flip) | |
3913 | bit = 0x30; | |
3914 | else | |
3915 | bit = 0x03; | |
3916 | break; | |
3917 | case 0x03 : | |
3918 | if ((temp = *srcptr & 0xc0) != 0) | |
3919 | *cptr |= temp >> 6; | |
3920 | if ((temp = *srcptr & 0x30) != 0) | |
3921 | *mptr |= temp >> 4; | |
3922 | if ((temp = *srcptr & 0x0c) != 0) | |
3923 | *yptr |= temp >> 2; | |
3924 | if ((temp = *srcptr & 0x03) != 0) | |
3925 | *kptr |= temp; | |
3926 | ||
3927 | if (flip) | |
3928 | bit = 0x0c; | |
3929 | else | |
3930 | { | |
3931 | bit = 0xc0; | |
3932 | cptr ++; | |
3933 | mptr ++; | |
3934 | yptr ++; | |
3935 | kptr ++; | |
3936 | } | |
3937 | break; | |
3938 | } | |
3939 | break; | |
3940 | } | |
3941 | break; | |
3942 | ||
3943 | case 4 : | |
3944 | memset(dst, 0, cups->header.cupsBytesPerLine); | |
3945 | ||
3946 | switch (cups->header.cupsColorSpace) | |
3947 | { | |
3948 | default : | |
3949 | for (x = cups->width, bit = flip && (x & 1) ? 0xf0 : 0x0f; | |
3950 | x > 0; | |
3951 | x --, srcptr += 2) | |
3952 | switch (bit) | |
3953 | { | |
3954 | case 0xf0 : | |
3955 | if ((temp = srcptr[0] & 0x0f) != 0) | |
3956 | *cptr |= temp << 4; | |
3957 | if ((temp = srcptr[1] & 0xf0) != 0) | |
3958 | *mptr |= temp; | |
3959 | if ((temp = srcptr[1] & 0x0f) != 0) | |
3960 | *yptr |= temp << 4; | |
3961 | ||
3962 | bit = 0x0f; | |
3963 | ||
3964 | if (flip) | |
3965 | { | |
3966 | cptr --; | |
3967 | mptr --; | |
3968 | yptr --; | |
3969 | } | |
3970 | break; | |
3971 | case 0x0f : | |
3972 | if ((temp = srcptr[0] & 0x0f) != 0) | |
3973 | *cptr |= temp; | |
3974 | if ((temp = srcptr[1] & 0xf0) != 0) | |
3975 | *mptr |= temp >> 4; | |
3976 | if ((temp = srcptr[1] & 0x0f) != 0) | |
3977 | *yptr |= temp; | |
3978 | ||
3979 | bit = 0xf0; | |
3980 | ||
3981 | if (!flip) | |
3982 | { | |
3983 | cptr ++; | |
3984 | mptr ++; | |
3985 | yptr ++; | |
3986 | } | |
3987 | break; | |
3988 | } | |
3989 | break; | |
3990 | case CUPS_CSPACE_GMCK : | |
3991 | case CUPS_CSPACE_GMCS : | |
3992 | case CUPS_CSPACE_RGBA : | |
3993 | case CUPS_CSPACE_CMYK : | |
3994 | case CUPS_CSPACE_YMCK : | |
3995 | case CUPS_CSPACE_KCMY : | |
3996 | case CUPS_CSPACE_KCMYcm : | |
3997 | for (x = cups->width, bit = flip && (x & 1) ? 0xf0 : 0x0f; | |
3998 | x > 0; | |
3999 | x --, srcptr += 2) | |
4000 | switch (bit) | |
4001 | { | |
4002 | case 0xf0 : | |
4003 | if ((temp = srcptr[0] & 0xf0) != 0) | |
4004 | *cptr |= temp; | |
4005 | if ((temp = srcptr[0] & 0x0f) != 0) | |
4006 | *mptr |= temp << 4; | |
4007 | if ((temp = srcptr[1] & 0xf0) != 0) | |
4008 | *yptr |= temp; | |
4009 | if ((temp = srcptr[1] & 0x0f) != 0) | |
4010 | *kptr |= temp << 4; | |
4011 | ||
4012 | bit = 0x0f; | |
4013 | ||
4014 | if (flip) | |
4015 | { | |
4016 | cptr --; | |
4017 | mptr --; | |
4018 | yptr --; | |
4019 | kptr --; | |
4020 | } | |
4021 | break; | |
4022 | case 0x0f : | |
4023 | if ((temp = srcptr[0] & 0xf0) != 0) | |
4024 | *cptr |= temp >> 4; | |
4025 | if ((temp = srcptr[0] & 0x0f) != 0) | |
4026 | *mptr |= temp; | |
4027 | if ((temp = srcptr[1] & 0xf0) != 0) | |
4028 | *yptr |= temp >> 4; | |
4029 | if ((temp = srcptr[1] & 0x0f) != 0) | |
4030 | *kptr |= temp; | |
4031 | ||
4032 | bit = 0xf0; | |
4033 | ||
4034 | if (!flip) | |
4035 | { | |
4036 | cptr ++; | |
4037 | mptr ++; | |
4038 | yptr ++; | |
4039 | kptr ++; | |
4040 | } | |
4041 | break; | |
4042 | } | |
4043 | break; | |
4044 | } | |
4045 | break; | |
4046 | ||
4047 | case 8 : | |
4048 | switch (cups->header.cupsColorSpace) | |
4049 | { | |
4050 | default : | |
4051 | if (flip) | |
4052 | for (x = cups->width; x > 0; x --) | |
4053 | { | |
4054 | *cptr-- = *srcptr++; | |
4055 | *mptr-- = *srcptr++; | |
4056 | *yptr-- = *srcptr++; | |
4057 | } | |
4058 | else | |
4059 | for (x = cups->width; x > 0; x --) | |
4060 | { | |
4061 | *cptr++ = *srcptr++; | |
4062 | *mptr++ = *srcptr++; | |
4063 | *yptr++ = *srcptr++; | |
4064 | } | |
4065 | break; | |
4066 | case CUPS_CSPACE_GMCK : | |
4067 | case CUPS_CSPACE_GMCS : | |
4068 | case CUPS_CSPACE_RGBA : | |
4069 | case CUPS_CSPACE_CMYK : | |
4070 | case CUPS_CSPACE_YMCK : | |
4071 | case CUPS_CSPACE_KCMY : | |
4072 | case CUPS_CSPACE_KCMYcm : | |
4073 | if (flip) | |
4074 | for (x = cups->width; x > 0; x --) | |
4075 | { | |
4076 | *cptr-- = *srcptr++; | |
4077 | *mptr-- = *srcptr++; | |
4078 | *yptr-- = *srcptr++; | |
4079 | *kptr-- = *srcptr++; | |
4080 | } | |
4081 | else | |
4082 | for (x = cups->width; x > 0; x --) | |
4083 | { | |
4084 | *cptr++ = *srcptr++; | |
4085 | *mptr++ = *srcptr++; | |
4086 | *yptr++ = *srcptr++; | |
4087 | *kptr++ = *srcptr++; | |
4088 | } | |
4089 | break; | |
4090 | } | |
4091 | break; | |
4092 | } | |
4093 | } | |
4094 | ||
4095 | /* | |
4096 | * Write the bitmap data to the raster stream... | |
4097 | */ | |
4098 | ||
4099 | cupsRasterWritePixels(cups->stream, dst, cups->header.cupsBytesPerLine); | |
4100 | } | |
4101 | } | |
4102 | ||
4103 | ||
4104 | /* | |
4105 | * 'cups_print_planar()' - Print a page of planar pixels. | |
4106 | */ | |
4107 | ||
4108 | static void | |
4109 | cups_print_planar(gx_device_printer *pdev, | |
4110 | /* I - Printer device */ | |
4111 | unsigned char *src, | |
4112 | /* I - Scanline buffer */ | |
4113 | unsigned char *dst, | |
4114 | /* I - Bitmap buffer */ | |
4115 | int srcbytes) | |
4116 | /* I - Number of bytes in src */ | |
4117 | { | |
4118 | int x; /* Looping var */ | |
4119 | int y; /* Looping var */ | |
4120 | int z; /* Looping var */ | |
4121 | unsigned char srcbit; /* Current source bit */ | |
4122 | unsigned char dstbit; /* Current destination bit */ | |
4123 | unsigned char temp; /* Temporary variable */ | |
4124 | unsigned char *srcptr; /* Pointer to data */ | |
4125 | unsigned char *dstptr; /* Pointer to bitmap */ | |
4126 | ||
4127 | ||
4128 | /**** NOTE: Currently planar output doesn't support flipped duplex!!! ****/ | |
4129 | ||
4130 | /* | |
4131 | * Loop through the page bitmap and write planar pixels... We have | |
4132 | * to separate each chunked color as needed... | |
4133 | */ | |
4134 | ||
4135 | for (z = 0; z < pdev->color_info.num_components; z ++) | |
4136 | for (y = 0; y < cups->height; y ++) | |
4137 | { | |
4138 | /* | |
4139 | * Grab the scanline data... | |
4140 | */ | |
4141 | ||
4142 | if (gdev_prn_get_bits((gx_device_printer *)pdev, y, src, &srcptr) < 0) | |
4143 | { | |
4144 | fprintf(stderr, "ERROR: Unable to get scanline %d!\n", y); | |
4145 | gs_exit(1); | |
4146 | } | |
4147 | ||
4148 | /* | |
4149 | * Pull the individual color planes out of the pixels... | |
4150 | */ | |
4151 | ||
4152 | if (srcptr[0] == 0 && memcmp(srcptr, srcptr + 1, srcbytes - 1) == 0) | |
4153 | memset(dst, 0, cups->header.cupsBytesPerLine); | |
4154 | else | |
4155 | switch (cups->header.cupsBitsPerColor) | |
4156 | { | |
4157 | default : | |
4158 | memset(dst, 0, cups->header.cupsBytesPerLine); | |
4159 | ||
4160 | switch (cups->header.cupsColorSpace) | |
4161 | { | |
4162 | default : | |
4163 | for (dstptr = dst, x = cups->width, srcbit = 64 >> z, | |
4164 | dstbit = 128; | |
4165 | x > 0; | |
4166 | x --) | |
4167 | { | |
4168 | if (*srcptr & srcbit) | |
4169 | *dstptr |= dstbit; | |
4170 | ||
4171 | if (srcbit >= 16) | |
4172 | srcbit >>= 4; | |
4173 | else | |
4174 | { | |
4175 | srcbit = 64 >> z; | |
4176 | srcptr ++; | |
4177 | } | |
4178 | ||
4179 | if (dstbit > 1) | |
4180 | dstbit >>= 1; | |
4181 | else | |
4182 | { | |
4183 | dstbit = 128; | |
4184 | dstptr ++; | |
4185 | } | |
4186 | } | |
4187 | break; | |
4188 | case CUPS_CSPACE_GMCK : | |
4189 | case CUPS_CSPACE_GMCS : | |
4190 | case CUPS_CSPACE_RGBA : | |
4191 | case CUPS_CSPACE_CMYK : | |
4192 | case CUPS_CSPACE_YMCK : | |
4193 | case CUPS_CSPACE_KCMY : | |
4194 | for (dstptr = dst, x = cups->width, srcbit = 128 >> z, | |
4195 | dstbit = 128; | |
4196 | x > 0; | |
4197 | x --) | |
4198 | { | |
4199 | if (*srcptr & srcbit) | |
4200 | *dstptr |= dstbit; | |
4201 | ||
4202 | if (srcbit >= 16) | |
4203 | srcbit >>= 4; | |
4204 | else | |
4205 | { | |
4206 | srcbit = 128 >> z; | |
4207 | srcptr ++; | |
4208 | } | |
4209 | ||
4210 | if (dstbit > 1) | |
4211 | dstbit >>= 1; | |
4212 | else | |
4213 | { | |
4214 | dstbit = 128; | |
4215 | dstptr ++; | |
4216 | } | |
4217 | } | |
4218 | break; | |
4219 | case CUPS_CSPACE_KCMYcm : | |
4220 | for (dstptr = dst, x = cups->width, srcbit = 32 >> z, | |
4221 | dstbit = 128; | |
4222 | x > 0; | |
4223 | x --, srcptr ++) | |
4224 | { | |
4225 | if (*srcptr & srcbit) | |
4226 | *dstptr |= dstbit; | |
4227 | ||
4228 | if (dstbit > 1) | |
4229 | dstbit >>= 1; | |
4230 | else | |
4231 | { | |
4232 | dstbit = 128; | |
4233 | dstptr ++; | |
4234 | } | |
4235 | } | |
4236 | break; | |
4237 | } | |
4238 | break; | |
4239 | ||
4240 | case 2 : | |
4241 | memset(dst, 0, cups->header.cupsBytesPerLine); | |
4242 | ||
4243 | switch (cups->header.cupsColorSpace) | |
4244 | { | |
4245 | default : | |
4246 | for (dstptr = dst, x = cups->width, srcbit = 48 >> (z * 2), | |
4247 | dstbit = 0xc0; | |
4248 | x > 0; | |
4249 | x --, srcptr ++) | |
4250 | { | |
4251 | if ((temp = *srcptr & srcbit) != 0) | |
4252 | { | |
4253 | if (srcbit == dstbit) | |
4254 | *dstptr |= temp; | |
4255 | else | |
4256 | { | |
4257 | switch (srcbit) | |
4258 | { | |
4259 | case 0x30 : | |
4260 | temp >>= 4; | |
4261 | break; | |
4262 | case 0x0c : | |
4263 | temp >>= 2; | |
4264 | break; | |
4265 | } | |
4266 | ||
4267 | switch (dstbit) | |
4268 | { | |
4269 | case 0xc0 : | |
4270 | *dstptr |= temp << 6; | |
4271 | break; | |
4272 | case 0x30 : | |
4273 | *dstptr |= temp << 4; | |
4274 | break; | |
4275 | case 0x0c : | |
4276 | *dstptr |= temp << 2; | |
4277 | break; | |
4278 | case 0x03 : | |
4279 | *dstptr |= temp; | |
4280 | break; | |
4281 | } | |
4282 | } | |
4283 | } | |
4284 | ||
4285 | if (dstbit > 0x03) | |
4286 | dstbit >>= 2; | |
4287 | else | |
4288 | { | |
4289 | dstbit = 0xc0; | |
4290 | dstptr ++; | |
4291 | } | |
4292 | } | |
4293 | break; | |
4294 | case CUPS_CSPACE_GMCK : | |
4295 | case CUPS_CSPACE_GMCS : | |
4296 | case CUPS_CSPACE_RGBA : | |
4297 | case CUPS_CSPACE_CMYK : | |
4298 | case CUPS_CSPACE_YMCK : | |
4299 | case CUPS_CSPACE_KCMY : | |
4300 | case CUPS_CSPACE_KCMYcm : | |
4301 | for (dstptr = dst, x = cups->width, srcbit = 192 >> (z * 2), | |
4302 | dstbit = 0xc0; | |
4303 | x > 0; | |
4304 | x --, srcptr ++) | |
4305 | { | |
4306 | if ((temp = *srcptr & srcbit) != 0) | |
4307 | { | |
4308 | if (srcbit == dstbit) | |
4309 | *dstptr |= temp; | |
4310 | else | |
4311 | { | |
4312 | switch (srcbit) | |
4313 | { | |
4314 | case 0xc0 : | |
4315 | temp >>= 6; | |
4316 | break; | |
4317 | case 0x30 : | |
4318 | temp >>= 4; | |
4319 | break; | |
4320 | case 0x0c : | |
4321 | temp >>= 2; | |
4322 | break; | |
4323 | } | |
4324 | ||
4325 | switch (dstbit) | |
4326 | { | |
4327 | case 0xc0 : | |
4328 | *dstptr |= temp << 6; | |
4329 | break; | |
4330 | case 0x30 : | |
4331 | *dstptr |= temp << 4; | |
4332 | break; | |
4333 | case 0x0c : | |
4334 | *dstptr |= temp << 2; | |
4335 | break; | |
4336 | case 0x03 : | |
4337 | *dstptr |= temp; | |
4338 | break; | |
4339 | } | |
4340 | } | |
4341 | } | |
4342 | ||
4343 | if (dstbit > 0x03) | |
4344 | dstbit >>= 2; | |
4345 | else | |
4346 | { | |
4347 | dstbit = 0xc0; | |
4348 | dstptr ++; | |
4349 | } | |
4350 | } | |
4351 | break; | |
4352 | } | |
4353 | break; | |
4354 | ||
4355 | case 4 : | |
4356 | memset(dst, 0, cups->header.cupsBytesPerLine); | |
4357 | ||
4358 | switch (cups->header.cupsColorSpace) | |
4359 | { | |
4360 | default : | |
4361 | if (z > 0) | |
4362 | srcptr ++; | |
4363 | ||
4364 | if (z == 1) | |
4365 | srcbit = 0xf0; | |
4366 | else | |
4367 | srcbit = 0x0f; | |
4368 | ||
4369 | for (dstptr = dst, x = cups->width, dstbit = 0xf0; | |
4370 | x > 0; | |
4371 | x --, srcptr += 2) | |
4372 | { | |
4373 | if ((temp = *srcptr & srcbit) != 0) | |
4374 | { | |
4375 | if (srcbit == dstbit) | |
4376 | *dstptr |= temp; | |
4377 | else | |
4378 | { | |
4379 | if (srcbit == 0xf0) | |
4380 | temp >>= 4; | |
4381 | ||
4382 | if (dstbit == 0xf0) | |
4383 | *dstptr |= temp << 4; | |
4384 | else | |
4385 | *dstptr |= temp; | |
4386 | } | |
4387 | } | |
4388 | ||
4389 | if (dstbit == 0xf0) | |
4390 | dstbit = 0x0f; | |
4391 | else | |
4392 | { | |
4393 | dstbit = 0xf0; | |
4394 | dstptr ++; | |
4395 | } | |
4396 | } | |
4397 | break; | |
4398 | case CUPS_CSPACE_GMCK : | |
4399 | case CUPS_CSPACE_GMCS : | |
4400 | case CUPS_CSPACE_RGBA : | |
4401 | case CUPS_CSPACE_CMYK : | |
4402 | case CUPS_CSPACE_YMCK : | |
4403 | case CUPS_CSPACE_KCMY : | |
4404 | case CUPS_CSPACE_KCMYcm : | |
4405 | if (z > 1) | |
4406 | srcptr ++; | |
4407 | ||
4408 | if (z & 1) | |
4409 | srcbit = 0x0f; | |
4410 | else | |
4411 | srcbit = 0xf0; | |
4412 | ||
4413 | for (dstptr = dst, x = cups->width, dstbit = 0xf0; | |
4414 | x > 0; | |
4415 | x --, srcptr += 2) | |
4416 | { | |
4417 | if ((temp = *srcptr & srcbit) != 0) | |
4418 | { | |
4419 | if (srcbit == dstbit) | |
4420 | *dstptr |= temp; | |
4421 | else | |
4422 | { | |
4423 | if (srcbit == 0xf0) | |
4424 | temp >>= 4; | |
4425 | ||
4426 | if (dstbit == 0xf0) | |
4427 | *dstptr |= temp << 4; | |
4428 | else | |
4429 | *dstptr |= temp; | |
4430 | } | |
4431 | } | |
4432 | ||
4433 | if (dstbit == 0xf0) | |
4434 | dstbit = 0x0f; | |
4435 | else | |
4436 | { | |
4437 | dstbit = 0xf0; | |
4438 | dstptr ++; | |
4439 | } | |
4440 | } | |
4441 | break; | |
4442 | } | |
4443 | break; | |
4444 | ||
4445 | case 8 : | |
4446 | for (srcptr += z, dstptr = dst, x = cups->header.cupsBytesPerLine; | |
4447 | x > 0; | |
4448 | srcptr += pdev->color_info.num_components, x --) | |
4449 | *dstptr++ = *srcptr; | |
4450 | break; | |
4451 | } | |
4452 | ||
4453 | /* | |
4454 | * Write the bitmap data to the raster stream... | |
4455 | */ | |
4456 | ||
4457 | cupsRasterWritePixels(cups->stream, dst, cups->header.cupsBytesPerLine); | |
4458 | } | |
4459 | } | |
4460 | ||
4461 | ||
4462 | /* | |
4463 | * End of "$Id: gdevcups.c 4493 2005-02-18 02:09:53Z mike $". | |
4464 | */ |