]> git.ipfire.org Git - thirdparty/cups.git/blob - pstoraster/gdevcups.c
Load cups into easysw/current.
[thirdparty/cups.git] / pstoraster / gdevcups.c
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 */