2 * "$Id: gdevcups.c 4493 2005-02-18 02:09:53Z mike $"
4 * GNU Ghostscript raster output driver for the Common UNIX Printing
7 * Copyright 1993-2005 by Easy Software Products.
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
16 * Attn: CUPS Licensing Information
17 * Easy Software Products
18 * 44141 Airport View Drive, Suite 204
19 * Hollywood, Maryland 20636 USA
21 * Voice: (301) 373-9600
22 * EMail: cups-info@cups.org
23 * WWW: http://www.cups.org/
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
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.
54 * Include necessary headers...
57 #include "std.h" /* to stop stdlib.h redefining types */
64 #include <cups/raster.h>
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...
78 #ifdef CUPS_RASTER_SYNCv1
79 # define cups_page_header_t cups_page_header2_t
80 # define cupsRasterWriteHeader cupsRasterWriteHeader2
81 #endif /* CUPS_RASTER_SYNCv1 */
85 * Newer versions of Ghostscript don't provide gs_exit() function anymore.
86 * It has been renamed to gs_to_exit()...
89 #ifdef dev_t_proc_encode_color
90 # define gs_exit gs_to_exit
91 #endif /* dev_t_proc_encode_color */
95 * CIE XYZ color constants...
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)
104 * Size of a tile in pixels...
107 #define CUPS_TILE_SIZE 256
111 * Size of profile LUTs...
114 #ifdef dev_t_proc_encode_color
115 # define CUPS_MAX_VALUE frac_1
117 # define CUPS_MAX_VALUE gx_max_color_value
118 #endif /* dev_t_proc_encode_color */
125 #define x_dpi (pdev->HWResolution[0])
126 #define y_dpi (pdev->HWResolution[1])
127 #define cups ((gx_device_cups *)pdev)
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.
135 # define max(a,b) ((a)<(b) ? (b) : (a))
139 # define min(a,b) ((a)>(b) ? (b) : (a))
143 # define abs(x) ((x)>=0 ? (x) : -(x))
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
);
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
);
169 static const gx_cm_color_map_procs cups_color_mapping_procs
=
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 */
183 * The device descriptors...
186 typedef struct gx_device_cups_s
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 */
196 private gx_device_procs cups_procs
=
201 gdev_prn_output_page
,
203 #ifdef dev_t_proc_encode_color
204 NULL
, /* map_rgb_color */
205 NULL
, /* 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 */
218 #ifdef dev_t_proc_encode_color
219 NULL
, /* 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 */
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
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 */
262 #endif /* dev_t_proc_encode_color */
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),\
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\
275 prn_device_body_copies_rest_(print_pages)
277 gx_device_cups gs_cups_device
=
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 */
299 /* print procedure */
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 */
321 CUPS_FALSE
, /* MirrorPrint */
322 CUPS_FALSE
, /* NegativePrint */
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 */
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 */
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 */
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];
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
369 { /* Upper 1-bit reversal table */
370 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
371 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0
374 { /* Lower 2-bit reversal table */
375 0x00, 0x04, 0x08, 0x0c, 0x01, 0x05, 0x09, 0x0d,
376 0x02, 0x06, 0x0a, 0x0e, 0x03, 0x07, 0x0b, 0x0f
379 { /* Upper 2-bit reversal table */
380 0x00, 0x40, 0x80, 0xc0, 0x10, 0x50, 0x90, 0xd0,
381 0x20, 0x60, 0xa0, 0xe0, 0x30, 0x70, 0xb0, 0xf0
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);
397 /*static void cups_set_margins(gx_device *);*/
401 * 'cups_close()' - Close the output file.
405 cups_close(gx_device
*pdev
) /* I - Device info */
408 fprintf(stderr
, "DEBUG2: cups_close(%p)\n", pdev
);
411 if (cups
->stream
!= NULL
)
413 cupsRasterClose(cups
->stream
);
417 #if 0 /* Can't do this here because put_params() might close the device */
424 if (cupsProfile
!= NULL
)
431 return (gdev_prn_close(pdev
));
435 #ifdef dev_t_proc_encode_color
437 * 'cups_decode_color()' - Decode a color value.
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 */
445 int i
; /* Looping var */
446 int shift
; /* Bits to shift */
447 int mask
; /* Bits to mask */
450 if (cups
->header
.cupsColorSpace
== CUPS_CSPACE_KCMYcm
&&
451 cups
->header
.cupsBitsPerColor
== 1)
454 * KCMYcm data is represented internally by Ghostscript as CMYK...
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
;
464 shift
= cups
->header
.cupsBitsPerColor
;
465 mask
= (1 << shift
) - 1;
467 for (i
= cups
->color_info
.num_components
- 1; i
> 0; i
--, ci
>>= shift
)
468 cv
[i
] = cupsDecodeLUT
[ci
& mask
];
470 cv
[0] = cupsDecodeLUT
[ci
& mask
];
478 * 'cups_encode_color()' - Encode a color value.
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
)
487 int i
; /* Looping var */
488 gx_color_index ci
; /* Color index */
489 int shift
; /* Bits to shift */
493 * Encode the color index...
496 shift
= cups
->header
.cupsBitsPerColor
;
498 for (ci
= cupsEncodeLUT
[cv
[0]], i
= 1;
499 i
< cups
->color_info
.num_components
;
501 ci
= (ci
<< shift
) | cupsEncodeLUT
[cv
[i
]];
504 * Handle 6-color output...
507 if (cups
->header
.cupsColorSpace
== CUPS_CSPACE_KCMYcm
&&
508 cups
->header
.cupsBitsPerColor
== 1)
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...
516 ci
<<= 2; /* Leave room for light inks */
518 if (ci
== 0x18) /* Blue */
519 ci
= 0x11; /* == cyan + light magenta */
520 else if (ci
== 0x14) /* Green */
521 ci
= 0x06; /* == light cyan + yellow */
525 * Range check the return value...
528 if (ci
== gx_no_color_index
)
532 * Return the color index...
540 * 'cups_get_color_mapping_procs()' - Get the list of color mapping procedures.
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 */
547 return (&cups_color_mapping_procs
);
549 #endif /* dev_t_proc_encode_color */
553 * 'cups_get_matrix()' - Generate the default page matrix.
557 cups_get_matrix(gx_device
*pdev
, /* I - Device info */
558 gs_matrix
*pmat
) /* O - Physical transform matrix */
561 fprintf(stderr
, "DEBUG2: cups_get_matrix(%p, %p)\n", pdev
, pmat
);
565 * Set the raster width and height...
568 cups
->header
.cupsWidth
= cups
->width
;
569 cups
->header
.cupsHeight
= cups
->height
;
572 * Set the transform matrix...
575 fprintf(stderr
, "DEBUG: cups->header.Duplex = %d\n", cups
->header
.Duplex
);
576 fprintf(stderr
, "DEBUG: cups->page = %d\n", cups
->page
);
580 fprintf(stderr
, "DEBUG: cupsPPD = %p\n", cupsPPD
);
581 fprintf(stderr
, "DEBUG: cupsPPD->flip_duplex = %d\n", cupsPPD
->flip_duplex
);
587 * Do landscape orientation...
590 if (cups
->header
.Duplex
&& !cups
->header
.Tumble
&&
591 cupsPPD
&& cupsPPD
->flip_duplex
&& !(cups
->page
& 1))
594 pmat
->xy
= (float)cups
->header
.HWResolution
[0] / 72.0;
595 pmat
->yx
= -(float)cups
->header
.HWResolution
[1] / 72.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;
604 pmat
->xy
= (float)cups
->header
.HWResolution
[0] / 72.0;
605 pmat
->yx
= (float)cups
->header
.HWResolution
[1] / 72.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;
611 else if (cups
->header
.Duplex
&& !cups
->header
.Tumble
&&
612 cupsPPD
&& cupsPPD
->flip_duplex
&& !(cups
->page
& 1))
614 pmat
->xx
= (float)cups
->header
.HWResolution
[0] / 72.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;
623 pmat
->xx
= (float)cups
->header
.HWResolution
[0] / 72.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;
632 fprintf(stderr
, "DEBUG: width = %d, height = %d\n", cups
->width
,
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],
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
);
646 * 'cups_get_params()' - Get pagedevice parameters.
649 private int /* O - Error status */
650 cups_get_params(gx_device
*pdev
, /* I - Device info */
651 gs_param_list
*plist
) /* I - Parameter list */
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 */
663 fprintf(stderr
, "DEBUG2: cups_get_params(%p, %p)\n", pdev
, plist
);
667 * First process the "standard" page device parameters...
671 fputs("DEBUG2: before gdev_prn_get_params()\n", stderr
);
674 if ((code
= gdev_prn_get_params(pdev
, plist
)) < 0)
678 fputs("DEBUG2: after gdev_prn_get_params()\n", stderr
);
682 * Then write the CUPS parameters...
686 fputs("DEBUG2: Adding MediaClass\n", stderr
);
689 param_string_from_string(s
, cups
->header
.MediaClass
);
690 if ((code
= param_write_string(plist
, "MediaClass", &s
)) < 0)
694 fputs("DEBUG2: Adding AdvanceDistance\n", stderr
);
697 if ((code
= param_write_int(plist
, "AdvanceDistance",
698 (int *)&(cups
->header
.AdvanceDistance
))) < 0)
702 fputs("DEBUG2: Adding AdvanceDistance\n", stderr
);
705 if ((code
= param_write_int(plist
, "AdvanceMedia",
706 (int *)&(cups
->header
.AdvanceMedia
))) < 0)
710 fputs("DEBUG2: Adding Collate\n", stderr
);
713 b
= cups
->header
.Collate
;
714 if ((code
= param_write_bool(plist
, "Collate", &b
)) < 0)
718 fputs("DEBUG2: Adding CutMedia\n", stderr
);
721 if ((code
= param_write_int(plist
, "CutMedia",
722 (int *)&(cups
->header
.CutMedia
))) < 0)
726 fputs("DEBUG2: Adding InsertSheet\n", stderr
);
729 b
= cups
->header
.InsertSheet
;
730 if ((code
= param_write_bool(plist
, "InsertSheet", &b
)) < 0)
734 fputs("DEBUG2: Adding Jog\n", stderr
);
737 if ((code
= param_write_int(plist
, "Jog",
738 (int *)&(cups
->header
.Jog
))) < 0)
742 fputs("DEBUG2: Adding LeadingEdge\n", stderr
);
745 if ((code
= param_write_int(plist
, "LeadingEdge",
746 (int *)&(cups
->header
.LeadingEdge
))) < 0)
750 fputs("DEBUG2: Adding ManualFeed\n", stderr
);
753 b
= cups
->header
.ManualFeed
;
754 if ((code
= param_write_bool(plist
, "ManualFeed", &b
)) < 0)
758 fputs("DEBUG2: Adding MediaPosition\n", stderr
);
761 if ((code
= param_write_int(plist
, "MediaPosition",
762 (int *)&(cups
->header
.MediaPosition
))) < 0)
766 fputs("DEBUG2: Adding MirrorPrint\n", stderr
);
769 b
= cups
->header
.MirrorPrint
;
770 if ((code
= param_write_bool(plist
, "MirrorPrint", &b
)) < 0)
774 fputs("DEBUG2: Adding NegativePrint\n", stderr
);
777 b
= cups
->header
.NegativePrint
;
778 if ((code
= param_write_bool(plist
, "NegativePrint", &b
)) < 0)
782 fputs("DEBUG2: Adding OutputFaceUp\n", stderr
);
785 b
= cups
->header
.OutputFaceUp
;
786 if ((code
= param_write_bool(plist
, "OutputFaceUp", &b
)) < 0)
790 fputs("DEBUG2: Adding Separations\n", stderr
);
793 b
= cups
->header
.Separations
;
794 if ((code
= param_write_bool(plist
, "Separations", &b
)) < 0)
798 fputs("DEBUG2: Adding TraySwitch\n", stderr
);
801 b
= cups
->header
.TraySwitch
;
802 if ((code
= param_write_bool(plist
, "TraySwitch", &b
)) < 0)
806 fputs("DEBUG2: Adding Tumble\n", stderr
);
809 b
= cups
->header
.Tumble
;
810 if ((code
= param_write_bool(plist
, "Tumble", &b
)) < 0)
814 fputs("DEBUG2: Adding cupsWidth\n", stderr
);
817 if ((code
= param_write_int(plist
, "cupsWidth",
818 (int *)&(cups
->header
.cupsWidth
))) < 0)
822 fputs("DEBUG2: Adding cupsHeight\n", stderr
);
825 if ((code
= param_write_int(plist
, "cupsHeight",
826 (int *)&(cups
->header
.cupsHeight
))) < 0)
830 fputs("DEBUG2: Adding cupsMediaType\n", stderr
);
833 if ((code
= param_write_int(plist
, "cupsMediaType",
834 (int *)&(cups
->header
.cupsMediaType
))) < 0)
838 fputs("DEBUG2: Adding cupsBitsPerColor\n", stderr
);
841 if ((code
= param_write_int(plist
, "cupsBitsPerColor",
842 (int *)&(cups
->header
.cupsBitsPerColor
))) < 0)
846 fputs("DEBUG2: Adding cupsBitsPerPixel\n", stderr
);
849 if ((code
= param_write_int(plist
, "cupsBitsPerPixel",
850 (int *)&(cups
->header
.cupsBitsPerPixel
))) < 0)
854 fputs("DEBUG2: Adding cupsBytesPerLine\n", stderr
);
857 if ((code
= param_write_int(plist
, "cupsBytesPerLine",
858 (int *)&(cups
->header
.cupsBytesPerLine
))) < 0)
862 fputs("DEBUG2: Adding cupsColorOrder\n", stderr
);
865 if ((code
= param_write_int(plist
, "cupsColorOrder",
866 (int *)&(cups
->header
.cupsColorOrder
))) < 0)
870 fputs("DEBUG2: Adding cupsColorSpace\n", stderr
);
873 if ((code
= param_write_int(plist
, "cupsColorSpace",
874 (int *)&(cups
->header
.cupsColorSpace
))) < 0)
878 fputs("DEBUG2: Adding cupsCompression\n", stderr
);
881 if ((code
= param_write_int(plist
, "cupsCompression",
882 (int *)&(cups
->header
.cupsCompression
))) < 0)
886 fputs("DEBUG2: Adding cupsRowCount\n", stderr
);
889 if ((code
= param_write_int(plist
, "cupsRowCount",
890 (int *)&(cups
->header
.cupsRowCount
))) < 0)
894 fputs("DEBUG2: Adding cupsRowFeed\n", stderr
);
897 if ((code
= param_write_int(plist
, "cupsRowFeed",
898 (int *)&(cups
->header
.cupsRowFeed
))) < 0)
902 fputs("DEBUG2: Adding cupsRowStep\n", stderr
);
905 if ((code
= param_write_int(plist
, "cupsRowStep",
906 (int *)&(cups
->header
.cupsRowStep
))) < 0)
909 #ifdef CUPS_RASTER_SYNCv1
911 fputs("DEBUG2: Adding cupsNumColors\n", stderr
);
914 if ((code
= param_write_int(plist
, "cupsNumColors",
915 (int *)&(cups
->header
.cupsNumColors
))) < 0)
919 fputs("DEBUG2: Adding cupsInteger\n", stderr
);
922 for (i
= 0; i
< 16; i
++)
924 sprintf(name
, "cupsInteger%d", i
);
925 if ((code
= param_write_int(plist
, name
,
926 (int *)(cups
->header
.cupsInteger
+ i
))) < 0)
931 fputs("DEBUG2: Adding cupsReal\n", stderr
);
934 for (i
= 0; i
< 16; i
++)
936 sprintf(name
, "cupsReal%d", i
);
937 if ((code
= param_write_float(plist
, name
,
938 cups
->header
.cupsReal
+ i
)) < 0)
943 fputs("DEBUG2: Adding cupsString\n", stderr
);
946 for (i
= 0; i
< 16; i
++)
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)
955 fputs("DEBUG2: Adding cupsMarkerType\n", stderr
);
958 param_string_from_string(s
, cups
->header
.cupsMarkerType
);
959 if ((code
= param_write_string(plist
, "cupsMarkerType", &s
)) < 0)
963 fputs("DEBUG2: Adding cupsRenderingIntent\n", stderr
);
966 param_string_from_string(s
, cups
->header
.cupsRenderingIntent
);
967 if ((code
= param_write_string(plist
, "cupsRenderingIntent", &s
)) < 0)
969 #endif /* CUPS_RASTER_SYNCv1 */
972 fputs("DEBUG2: Leaving cups_get_params()\n", stderr
);
980 * 'cups_get_space_params()' - Get space parameters from the RIP_CACHE env var.
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 */
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 */
995 fprintf(stderr
, "DEBUG2: cups_get_space_params(%p, %p)\n", pdev
, space_params
);
998 if ((cache_env
= getenv("RIP_MAX_CACHE")) != NULL
)
1000 switch (sscanf(cache_env
, "%f%254s", &cache_size
, cache_units
))
1003 cache_size
= 8 * 1024 * 1024;
1006 cache_size
*= 4 * CUPS_TILE_SIZE
* CUPS_TILE_SIZE
;
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')
1015 else if (tolower(cache_units
[0]) == 't')
1016 cache_size
*= 4 * CUPS_TILE_SIZE
* CUPS_TILE_SIZE
;
1021 cache_size
= 8 * 1024 * 1024;
1023 fprintf(stderr
, "DEBUG: cache_size = %.0f\n", cache_size
);
1025 space_params
->MaxBitmap
= (int)cache_size
;
1026 space_params
->BufferSpace
= (int)cache_size
/ 10;
1031 * 'cups_map_cielab()' - Map CIE Lab transformation...
1034 static double /* O - Adjusted color value */
1035 cups_map_cielab(double x
, /* I - Raw color value */
1036 double xn
) /* I - Whitepoint color value */
1038 double x_xn
; /* Fraction of whitepoint */
1043 if (x_xn
> 0.008856)
1044 return (cbrt(x_xn
));
1046 return (7.787 * x_xn
+ 16.0 / 116.0);
1050 #ifdef dev_t_proc_encode_color
1052 * 'cups_map_cmyk()' - Map a CMYK color value to device colors.
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 */
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 */
1071 fprintf(stderr
, "DEBUG2: cups_map_cmyk(%p, %d, %d, %d, %d, %p)\n",
1072 pdev
, c
, m
, y
, k
, out
);
1076 * Convert the CMYK color to the destination colorspace...
1079 switch (cups
->header
.cupsColorSpace
)
1081 case CUPS_CSPACE_W
:
1082 c0
= frac_1
- (c
* 31 + m
* 61 + y
* 8) / 100 - k
;
1086 else if (c0
> frac_1
)
1087 out
[0] = (frac
)cupsDensity
[frac_1
];
1089 out
[0] = (frac
)cupsDensity
[c0
];
1092 case CUPS_CSPACE_RGBA
:
1095 case CUPS_CSPACE_RGB
:
1096 c0
= frac_1
- c
- k
;
1097 c1
= frac_1
- m
- k
;
1098 c2
= frac_1
- y
- k
;
1102 else if (c0
> frac_1
)
1103 out
[0] = (frac
)cupsDensity
[frac_1
];
1105 out
[0] = (frac
)cupsDensity
[c0
];
1109 else if (c1
> frac_1
)
1110 out
[1] = (frac
)cupsDensity
[frac_1
];
1112 out
[1] = (frac
)cupsDensity
[c1
];
1116 else if (c2
> frac_1
)
1117 out
[2] = (frac
)cupsDensity
[frac_1
];
1119 out
[2] = (frac
)cupsDensity
[c2
];
1123 case CUPS_CSPACE_K
:
1124 c0
= (c
* 31 + m
* 61 + y
* 8) / 100 + k
;
1128 else if (c0
> frac_1
)
1129 out
[0] = (frac
)cupsDensity
[frac_1
];
1131 out
[0] = (frac
)cupsDensity
[c0
];
1134 case CUPS_CSPACE_CMY
:
1141 else if (c0
> frac_1
)
1142 out
[0] = (frac
)cupsDensity
[frac_1
];
1144 out
[0] = (frac
)cupsDensity
[c0
];
1148 else if (c1
> frac_1
)
1149 out
[1] = (frac
)cupsDensity
[frac_1
];
1151 out
[1] = (frac
)cupsDensity
[c1
];
1155 else if (c2
> frac_1
)
1156 out
[2] = (frac
)cupsDensity
[frac_1
];
1158 out
[2] = (frac
)cupsDensity
[c2
];
1161 case CUPS_CSPACE_YMC
:
1168 else if (c0
> frac_1
)
1169 out
[0] = (frac
)cupsDensity
[frac_1
];
1171 out
[0] = (frac
)cupsDensity
[c0
];
1175 else if (c1
> frac_1
)
1176 out
[1] = (frac
)cupsDensity
[frac_1
];
1178 out
[1] = (frac
)cupsDensity
[c1
];
1182 else if (c2
> frac_1
)
1183 out
[2] = (frac
)cupsDensity
[frac_1
];
1185 out
[2] = (frac
)cupsDensity
[c2
];
1188 case CUPS_CSPACE_CMYK
:
1191 else if (c
> frac_1
)
1192 out
[0] = (frac
)cupsDensity
[frac_1
];
1194 out
[0] = (frac
)cupsDensity
[c
];
1198 else if (m
> frac_1
)
1199 out
[1] = (frac
)cupsDensity
[frac_1
];
1201 out
[1] = (frac
)cupsDensity
[m
];
1205 else if (y
> frac_1
)
1206 out
[2] = (frac
)cupsDensity
[frac_1
];
1208 out
[2] = (frac
)cupsDensity
[y
];
1212 else if (k
> frac_1
)
1213 out
[3] = (frac
)cupsDensity
[frac_1
];
1215 out
[3] = (frac
)cupsDensity
[k
];
1218 case CUPS_CSPACE_YMCK
:
1219 case CUPS_CSPACE_GMCK
:
1220 case CUPS_CSPACE_GMCS
:
1223 else if (y
> frac_1
)
1224 out
[0] = (frac
)cupsDensity
[frac_1
];
1226 out
[0] = (frac
)cupsDensity
[y
];
1230 else if (m
> frac_1
)
1231 out
[1] = (frac
)cupsDensity
[frac_1
];
1233 out
[1] = (frac
)cupsDensity
[m
];
1237 else if (c
> frac_1
)
1238 out
[2] = (frac
)cupsDensity
[frac_1
];
1240 out
[2] = (frac
)cupsDensity
[c
];
1244 else if (k
> frac_1
)
1245 out
[3] = (frac
)cupsDensity
[frac_1
];
1247 out
[3] = (frac
)cupsDensity
[k
];
1250 case CUPS_CSPACE_KCMYcm
:
1251 case CUPS_CSPACE_KCMY
:
1254 else if (k
> frac_1
)
1255 out
[0] = (frac
)cupsDensity
[frac_1
];
1257 out
[0] = (frac
)cupsDensity
[k
];
1261 else if (c
> frac_1
)
1262 out
[1] = (frac
)cupsDensity
[frac_1
];
1264 out
[1] = (frac
)cupsDensity
[c
];
1268 else if (m
> frac_1
)
1269 out
[2] = (frac
)cupsDensity
[frac_1
];
1271 out
[2] = (frac
)cupsDensity
[m
];
1275 else if (y
> frac_1
)
1276 out
[3] = (frac
)cupsDensity
[frac_1
];
1278 out
[3] = (frac
)cupsDensity
[y
];
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
:
1300 * Convert CMYK to sRGB...
1303 c0
= frac_1
- c
- k
;
1304 c1
= frac_1
- m
- k
;
1305 c2
= frac_1
- y
- k
;
1309 else if (c0
> frac_1
)
1314 else if (c1
> frac_1
)
1319 else if (c2
> frac_1
)
1323 * Convert sRGB to linear RGB...
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);
1331 * Convert to CIE XYZ...
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
;
1338 if (cups
->header
.cupsColorSpace
== CUPS_CSPACE_CIEXYZ
)
1341 * Convert to an integer XYZ color value...
1346 else if (ciex
> 0.0)
1347 c0
= (int)(ciex
* frac_1
);
1353 else if (ciey
> 0.0)
1354 c1
= (int)(ciey
* frac_1
);
1360 else if (ciez
> 0.0)
1361 c2
= (int)(ciez
* frac_1
);
1368 * Convert CIE XYZ to Lab...
1371 ciey_yn
= ciey
/ D65_Y
;
1373 if (ciey_yn
> 0.008856)
1374 ciel
= 116 * cbrt(ciey_yn
) - 16;
1376 ciel
= 903.3 * ciey_yn
;
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
));
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.
1393 * Convert to frac values...
1398 else if (ciel
< 255.0)
1399 c0
= (int)(ciel
* frac_1
/ 255.0);
1405 else if (ciea
< 255.0)
1406 c1
= (int)(ciea
* frac_1
/ 255.0);
1412 else if (cieb
< 255.0)
1413 c2
= (int)(cieb
* frac_1
/ 255.0);
1419 * Put the final color value together...
1426 # endif /* CUPS_RASTER_HAVE_COLORIMETRIC */
1429 switch (cups
->color_info
.num_components
)
1434 fprintf(stderr
, "DEBUG2: \\=== COLOR %d\n", out
[0]);
1440 fprintf(stderr
, "DEBUG2: \\=== COLOR %d, %d, %d\n",
1441 out
[0], out
[1], out
[2]);
1447 fprintf(stderr
, "DEBUG2: \\=== COLOR %d, %d, %d, %d\n",
1448 out
[0], out
[1], out
[2], out
[3]);
1456 * 'cups_map_gray()' - Map a grayscale value to device colors.
1460 cups_map_gray(gx_device
*pdev
, /* I - Device info */
1461 frac g
, /* I - Grayscale value */
1462 frac
*out
) /* O - Device colors */
1465 fprintf(stderr
, "DEBUG2: cups_map_gray(%p, %d, %p)\n",
1470 * Just use the CMYK mapper...
1473 cups_map_cmyk(pdev
, 0, 0, 0, frac_1
- g
, out
);
1478 * 'cups_map_rgb()' - Map a RGB color value to device colors.
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 */
1490 frac c
, m
, y
, k
; /* CMYK values */
1491 frac mk
; /* Maximum K value */
1492 int tc
, tm
, ty
; /* Temporary color values */
1496 fprintf(stderr
, "DEBUG2: cups_map_rgb(%p, %p, %d, %d, %d, %p)\n",
1497 pdev
, pis
, r
, g
, b
, out
);
1501 * Compute CMYK values...
1507 k
= min(c
, min(m
, y
));
1509 if ((mk
= max(c
, max(m
, y
))) > k
)
1510 k
= (int)((float)k
* (float)k
* (float)k
/ ((float)mk
* (float)mk
));
1517 * Do color correction as needed...
1520 if (cupsHaveProfile
)
1523 * Color correct CMY...
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
];
1538 else if (tc
> frac_1
)
1545 else if (tm
> frac_1
)
1552 else if (ty
> frac_1
)
1559 * Use the CMYK mapping function to produce the device colors...
1562 cups_map_cmyk(pdev
, c
, m
, y
, k
, out
);
1566 * 'cups_map_cmyk_color()' - Map a CMYK color to a color index.
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*
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 */
1581 gx_color_index i
; /* Temporary index */
1582 gx_color_value ic
, im
, iy
, ik
; /* Integral CMYK values */
1586 fprintf(stderr
, "DEBUG2: cups_map_cmyk_color(%p, %d, %d, %d, %d)\n", pdev
,
1591 * Setup the color info data as needed...
1594 if (pdev
->color_info
.num_components
== 0)
1595 cups_set_color_info(pdev
);
1598 * Density correct...
1601 if (cupsHaveProfile
)
1609 ic
= cupsEncodeLUT
[c
];
1610 im
= cupsEncodeLUT
[m
];
1611 iy
= cupsEncodeLUT
[y
];
1612 ik
= cupsEncodeLUT
[k
];
1615 * Convert the CMYK color to a color index...
1618 switch (cups
->header
.cupsColorSpace
)
1621 switch (cups
->header
.cupsBitsPerColor
)
1624 i
= (((((ic
<< 1) | im
) << 1) | iy
) << 1) | ik
;
1627 i
= (((((ic
<< 2) | im
) << 2) | iy
) << 2) | ik
;
1630 i
= (((((ic
<< 4) | im
) << 4) | iy
) << 4) | ik
;
1633 i
= (((((ic
<< 8) | im
) << 8) | iy
) << 8) | ik
;
1638 case CUPS_CSPACE_YMCK
:
1639 case CUPS_CSPACE_GMCK
:
1640 case CUPS_CSPACE_GMCS
:
1641 switch (cups
->header
.cupsBitsPerColor
)
1644 i
= (((((iy
<< 1) | im
) << 1) | ic
) << 1) | ik
;
1647 i
= (((((iy
<< 2) | im
) << 2) | ic
) << 2) | ik
;
1650 i
= (((((iy
<< 4) | im
) << 4) | ic
) << 4) | ik
;
1653 i
= (((((iy
<< 8) | im
) << 8) | ic
) << 8) | ik
;
1658 case CUPS_CSPACE_KCMYcm
:
1659 if (cups
->header
.cupsBitsPerColor
== 1)
1681 case CUPS_CSPACE_KCMY
:
1682 switch (cups
->header
.cupsBitsPerColor
)
1685 i
= (((((ik
<< 1) | ic
) << 1) | im
) << 1) | iy
;
1688 i
= (((((ik
<< 2) | ic
) << 2) | im
) << 2) | iy
;
1691 i
= (((((ik
<< 4) | ic
) << 4) | im
) << 4) | iy
;
1694 i
= (((((ik
<< 8) | ic
) << 8) | im
) << 8) | iy
;
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
);
1706 * Make sure we don't get a CMYK color of 255, 255, 255, 255...
1709 if (i
== gx_no_color_index
)
1717 * 'cups_map_color_rgb()' - Map a color index to an RGB color.
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 */
1726 unsigned char c0
, c1
, c2
, c3
; /* Color index components */
1727 gx_color_value k
, divk
; /* Black & divisor */
1731 fprintf(stderr
, "DEBUG2: cups_map_color_rgb(%p, %d, %p)\n", pdev
,
1732 (unsigned)color
, prgb
);
1736 * Setup the color info data as needed...
1739 if (pdev
->color_info
.num_components
== 0)
1740 cups_set_color_info(pdev
);
1743 fprintf(stderr
, "DEBUG2: COLOR %08x = ", (unsigned)color
);
1747 * Extract the color components from the color index...
1750 switch (cups
->header
.cupsBitsPerColor
)
1791 * Convert the color components to RGB...
1794 switch (cups
->header
.cupsColorSpace
)
1796 case CUPS_CSPACE_K
:
1797 case CUPS_CSPACE_WHITE
:
1798 case CUPS_CSPACE_GOLD
:
1799 case CUPS_CSPACE_SILVER
:
1802 prgb
[2] = cupsDecodeLUT
[c3
];
1805 case CUPS_CSPACE_W
:
1808 prgb
[2] = cupsDecodeLUT
[c3
];
1811 case CUPS_CSPACE_RGB
:
1812 prgb
[0] = cupsDecodeLUT
[c1
];
1813 prgb
[1] = cupsDecodeLUT
[c2
];
1814 prgb
[2] = cupsDecodeLUT
[c3
];
1817 case CUPS_CSPACE_RGBA
:
1818 prgb
[0] = cupsDecodeLUT
[c0
];
1819 prgb
[1] = cupsDecodeLUT
[c1
];
1820 prgb
[2] = cupsDecodeLUT
[c2
];
1823 case CUPS_CSPACE_CMY
:
1824 prgb
[0] = cupsDecodeLUT
[c1
];
1825 prgb
[1] = cupsDecodeLUT
[c2
];
1826 prgb
[2] = cupsDecodeLUT
[c3
];
1829 case CUPS_CSPACE_YMC
:
1830 prgb
[0] = cupsDecodeLUT
[c3
];
1831 prgb
[1] = cupsDecodeLUT
[c2
];
1832 prgb
[2] = cupsDecodeLUT
[c1
];
1835 case CUPS_CSPACE_KCMY
:
1836 case CUPS_CSPACE_KCMYcm
:
1837 k
= cupsDecodeLUT
[c0
];
1838 divk
= gx_max_color_value
- k
;
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
;
1856 case CUPS_CSPACE_CMYK
:
1857 k
= cupsDecodeLUT
[c3
];
1858 divk
= gx_max_color_value
- k
;
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
;
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
;
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
;
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
:
1917 # endif /* CUPS_RASTER_HAVE_COLORIMETRIC */
1921 fprintf(stderr
, "%d,%d,%d\n", prgb
[0], prgb
[1], prgb
[2]);
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).
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 */
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 */
1946 /* CIE XYZ colors */
1947 ciey_yn
, /* Normalized luminance */
1949 /* CIE Lab colors */
1953 fprintf(stderr
, "DEBUG2: cups_map_rgb_color(%p, %d, %d, %d)\n", pdev
, r
, g
, b
);
1957 * Setup the color info data as needed...
1960 if (pdev
->color_info
.num_components
== 0)
1961 cups_set_color_info(pdev
);
1964 * Do color correction as needed...
1967 if (cupsHaveProfile
)
1970 * Compute CMYK values...
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
));
1978 if ((mk
= max(ic
, max(im
, iy
))) > ik
)
1979 ik
= (int)((float)ik
* (float)ik
* (float)ik
/ ((float)mk
* (float)mk
));
1986 * Color correct CMY...
1989 tc
= cupsMatrix
[0][0][ic
] +
1990 cupsMatrix
[0][1][im
] +
1991 cupsMatrix
[0][2][iy
] +
1993 tm
= cupsMatrix
[1][0][ic
] +
1994 cupsMatrix
[1][1][im
] +
1995 cupsMatrix
[1][2][iy
] +
1997 ty
= cupsMatrix
[2][0][ic
] +
1998 cupsMatrix
[2][1][im
] +
1999 cupsMatrix
[2][2][iy
] +
2003 * Density correct combined CMYK...
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
];
2011 r
= gx_max_color_value
- cupsDensity
[tc
];
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
];
2018 g
= gx_max_color_value
- cupsDensity
[tm
];
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
];
2025 b
= gx_max_color_value
- cupsDensity
[ty
];
2029 * Convert the RGB color to a color index...
2032 switch (cups
->header
.cupsColorSpace
)
2034 case CUPS_CSPACE_W
:
2035 i
= cupsEncodeLUT
[(r
* 31 + g
* 61 + b
* 8) / 100];
2038 case CUPS_CSPACE_RGB
:
2039 ic
= cupsEncodeLUT
[r
];
2040 im
= cupsEncodeLUT
[g
];
2041 iy
= cupsEncodeLUT
[b
];
2043 switch (cups
->header
.cupsBitsPerColor
)
2046 i
= (((ic
<< 1) | im
) << 1) | iy
;
2049 i
= (((ic
<< 2) | im
) << 2) | iy
;
2052 i
= (((ic
<< 4) | im
) << 4) | iy
;
2055 i
= (((ic
<< 8) | im
) << 8) | iy
;
2060 case CUPS_CSPACE_RGBA
:
2061 ic
= cupsEncodeLUT
[r
];
2062 im
= cupsEncodeLUT
[g
];
2063 iy
= cupsEncodeLUT
[b
];
2065 switch (cups
->header
.cupsBitsPerColor
)
2068 i
= (((((ic
<< 1) | im
) << 1) | iy
) << 1) | 0x01;
2071 i
= (((((ic
<< 2) | im
) << 2) | iy
) << 2) | 0x03;
2074 i
= (((((ic
<< 4) | im
) << 4) | iy
) << 4) | 0x0f;
2077 i
= (((((ic
<< 8) | im
) << 8) | iy
) << 8) | 0xff;
2083 i
= cupsEncodeLUT
[gx_max_color_value
- (r
* 31 + g
* 61 + b
* 8) / 100];
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
];
2091 switch (cups
->header
.cupsBitsPerColor
)
2094 i
= (((ic
<< 1) | im
) << 1) | iy
;
2097 i
= (((ic
<< 2) | im
) << 2) | iy
;
2100 i
= (((ic
<< 4) | im
) << 4) | iy
;
2103 i
= (((ic
<< 8) | im
) << 8) | iy
;
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
];
2113 switch (cups
->header
.cupsBitsPerColor
)
2116 i
= (((iy
<< 1) | im
) << 1) | ic
;
2119 i
= (((iy
<< 2) | im
) << 2) | ic
;
2122 i
= (((iy
<< 4) | im
) << 4) | ic
;
2125 i
= (((iy
<< 8) | im
) << 8) | ic
;
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
));
2136 if ((mk
= max(ic
, max(im
, iy
))) > ik
)
2137 ik
= (int)((float)ik
* (float)ik
* (float)ik
/
2138 ((float)mk
* (float)mk
));
2140 ic
= cupsEncodeLUT
[ic
- ik
];
2141 im
= cupsEncodeLUT
[im
- ik
];
2142 iy
= cupsEncodeLUT
[iy
- ik
];
2143 ik
= cupsEncodeLUT
[ik
];
2145 switch (cups
->header
.cupsBitsPerColor
)
2148 i
= (((((ic
<< 1) | im
) << 1) | iy
) << 1) | ik
;
2151 i
= (((((ic
<< 2) | im
) << 2) | iy
) << 2) | ik
;
2154 i
= (((((ic
<< 4) | im
) << 4) | iy
) << 4) | ik
;
2157 i
= (((((ic
<< 8) | im
) << 8) | iy
) << 8) | ik
;
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
);
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
));
2175 if ((mk
= max(ic
, max(im
, iy
))) > ik
)
2176 ik
= (int)((float)ik
* (float)ik
* (float)ik
/
2177 ((float)mk
* (float)mk
));
2179 ic
= cupsEncodeLUT
[ic
- ik
];
2180 im
= cupsEncodeLUT
[im
- ik
];
2181 iy
= cupsEncodeLUT
[iy
- ik
];
2182 ik
= cupsEncodeLUT
[ik
];
2184 switch (cups
->header
.cupsBitsPerColor
)
2187 i
= (((((iy
<< 1) | im
) << 1) | ic
) << 1) | ik
;
2190 i
= (((((iy
<< 2) | im
) << 2) | ic
) << 2) | ik
;
2193 i
= (((((iy
<< 4) | im
) << 4) | ic
) << 4) | ik
;
2196 i
= (((((iy
<< 8) | im
) << 8) | ic
) << 8) | ik
;
2201 case CUPS_CSPACE_KCMYcm
:
2202 if (cups
->header
.cupsBitsPerColor
== 1)
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
));
2209 if ((mk
= max(ic
, max(im
, iy
))) > ik
)
2210 ik
= (int)((float)ik
* (float)ik
* (float)ik
/
2211 ((float)mk
* (float)mk
));
2213 ic
= cupsEncodeLUT
[ic
- ik
];
2214 im
= cupsEncodeLUT
[im
- ik
];
2215 iy
= cupsEncodeLUT
[iy
- ik
];
2216 ik
= cupsEncodeLUT
[ik
];
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
));
2242 if ((mk
= max(ic
, max(im
, iy
))) > ik
)
2243 ik
= (int)((float)ik
* (float)ik
* (float)ik
/
2244 ((float)mk
* (float)mk
));
2246 ic
= cupsEncodeLUT
[ic
- ik
];
2247 im
= cupsEncodeLUT
[im
- ik
];
2248 iy
= cupsEncodeLUT
[iy
- ik
];
2249 ik
= cupsEncodeLUT
[ik
];
2251 switch (cups
->header
.cupsBitsPerColor
)
2254 i
= (((((ik
<< 1) | ic
) << 1) | im
) << 1) | iy
;
2257 i
= (((((ik
<< 2) | ic
) << 2) | im
) << 2) | iy
;
2260 i
= (((((ik
<< 4) | ic
) << 4) | im
) << 4) | iy
;
2263 i
= (((((ik
<< 8) | ic
) << 8) | im
) << 8) | iy
;
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
:
2287 * Convert sRGB to linear RGB...
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);
2295 * Convert to CIE XYZ...
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
;
2302 if (cups
->header
.cupsColorSpace
== CUPS_CSPACE_CIEXYZ
)
2305 * Convert to an integer XYZ color value...
2310 else if (ciex
> 0.0)
2311 ic
= (int)(ciex
* 255.0);
2317 else if (ciey
> 0.0)
2318 im
= (int)(ciey
* 255.0);
2324 else if (ciez
> 0.0)
2325 iy
= (int)(ciez
* 255.0);
2332 * Convert CIE XYZ to Lab...
2335 ciey_yn
= ciey
/ D65_Y
;
2337 if (ciey_yn
> 0.008856)
2338 ciel
= 116 * cbrt(ciey_yn
) - 16;
2340 ciel
= 903.3 * ciey_yn
;
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
));
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.
2357 * Convert to 8-bit values...
2362 else if (ciel
< 255.0)
2369 else if (ciea
< 255.0)
2376 else if (cieb
< 255.0)
2383 * Put the final color value together...
2386 switch (cups
->header
.cupsBitsPerColor
)
2389 i
= (((ic
<< 1) | im
) << 1) | iy
;
2392 i
= (((ic
<< 2) | im
) << 2) | iy
;
2395 i
= (((ic
<< 4) | im
) << 4) | iy
;
2398 i
= (((ic
<< 8) | im
) << 8) | iy
;
2402 # endif /* CUPS_RASTER_HAVE_COLORIMETRIC */
2406 fprintf(stderr
, "DEBUG2: RGB %d,%d,%d = %08x\n", r
, g
, b
, (unsigned)i
);
2411 #endif /* dev_t_proc_encode_color */
2415 * 'cups_open()' - Open the output file and initialize things.
2418 private int /* O - Error status */
2419 cups_open(gx_device
*pdev
) /* I - Device info */
2421 int code
; /* Return status */
2425 fprintf(stderr
, "DEBUG2: cups_open(%p)\n", pdev
);
2428 cups
->printer_procs
.get_space_params
= cups_get_space_params
;
2430 if (cups
->page
== 0)
2432 fputs("INFO: Processing page 1...\n", stderr
);
2436 cups_set_color_info(pdev
);
2438 if ((code
= gdev_prn_open(pdev
)) != 0)
2441 if (cupsPPD
== NULL
)
2442 cupsPPD
= ppdOpenFile(getenv("PPD"));
2449 * 'cups_print_pages()' - Send one or more pages to the output file.
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 */
2457 /* I - Number of copies */
2459 int copy
; /* Copy number */
2460 int srcbytes
; /* Byte width of scanline */
2461 unsigned char *src
, /* Scanline data */
2462 *dst
; /* Bitmap data */
2465 (void)fp
; /* reference unused file pointer to prevent compiler warning */
2468 fprintf(stderr
, "DEBUG2: cups_print_pages(%p, %p, %d)\n", pdev
, fp
,
2473 * Figure out the number of bytes per line...
2476 switch (cups
->header
.cupsColorOrder
)
2478 case CUPS_ORDER_CHUNKED
:
2479 cups
->header
.cupsBytesPerLine
= (cups
->header
.cupsBitsPerPixel
*
2480 cups
->header
.cupsWidth
+ 7) / 8;
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;
2489 cups
->header
.cupsBytesPerLine
= (cups
->header
.cupsBitsPerColor
*
2490 cups
->header
.cupsWidth
+ 7) / 8 *
2491 cups
->color_info
.num_components
;
2494 case CUPS_ORDER_PLANAR
:
2495 cups
->header
.cupsBytesPerLine
= (cups
->header
.cupsBitsPerColor
*
2496 cups
->header
.cupsWidth
+ 7) / 8;
2501 * Compute the width of a scanline and allocate input/output buffers...
2504 srcbytes
= gdev_prn_raster(pdev
);
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
);
2512 src
= (unsigned char *)gs_malloc(srcbytes
, 1, "cups_print_pages");
2514 if (src
== NULL
) /* can't allocate input buffer */
2515 return_error(gs_error_VMerror
);
2518 * Need an output buffer, too...
2521 dst
= (unsigned char *)gs_malloc(cups
->header
.cupsBytesPerLine
, 2,
2522 "cups_print_pages");
2524 if (dst
== NULL
) /* can't allocate working area */
2525 return_error(gs_error_VMerror
);
2528 * See if the stream has been initialized yet...
2531 if (cups
->stream
== NULL
)
2533 if ((cups
->stream
= cupsRasterOpen(fileno(cups
->file
),
2534 CUPS_RASTER_WRITE
)) == NULL
)
2536 perror("ERROR: Unable to open raster stream - ");
2542 * Output a page of graphics...
2548 if (cupsPPD
!= NULL
&& !cupsPPD
->manual_copies
)
2550 cups
->header
.NumCopies
= num_copies
;
2555 fprintf(stderr
, "DEBUG2: cupsWidth = %d, cupsHeight = %d, cupsBytesPerLine = %d\n",
2556 cups
->header
.cupsWidth
, cups
->header
.cupsHeight
,
2557 cups
->header
.cupsBytesPerLine
);
2560 for (copy
= num_copies
; copy
> 0; copy
--)
2562 cupsRasterWriteHeader(cups
->stream
, &(cups
->header
));
2564 if (pdev
->color_info
.num_components
== 1)
2565 cups_print_chunked(pdev
, src
, dst
, srcbytes
);
2567 switch (cups
->header
.cupsColorOrder
)
2569 case CUPS_ORDER_CHUNKED
:
2570 cups_print_chunked(pdev
, src
, dst
, srcbytes
);
2572 case CUPS_ORDER_BANDED
:
2573 cups_print_banded(pdev
, src
, dst
, srcbytes
);
2575 case CUPS_ORDER_PLANAR
:
2576 cups_print_planar(pdev
, src
, dst
, srcbytes
);
2582 * Free temporary storage and return...
2585 gs_free((char *)src
, srcbytes
, 1, "cups_print_pages");
2586 gs_free((char *)dst
, cups
->header
.cupsBytesPerLine
, 1, "cups_print_pages");
2589 fprintf(stderr
, "INFO: Processing page %d...\n", cups
->page
);
2596 * 'cups_put_params()' - Set pagedevice parameters.
2599 private int /* O - Error status */
2600 cups_put_params(gx_device
*pdev
, /* I - Device info */
2601 gs_param_list
*plist
) /* I - Parameter list */
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 */
2623 fprintf(stderr
, "DEBUG2: cups_put_params(%p, %p)\n", pdev
, plist
);
2627 * Process other options for CUPS...
2630 #define stringoption(name, sname) \
2631 if ((code = param_read_string(plist, sname, &stringval)) < 0) \
2633 param_signal_error(plist, sname, code); \
2636 else if (code == 0) \
2638 strncpy(cups->header.name, (const char *)stringval.data, \
2640 cups->header.name[stringval.size] = '\0'; \
2643 #define intoption(name, sname, type) \
2644 if ((code = param_read_int(plist, sname, &intval)) < 0) \
2646 param_signal_error(plist, sname, code); \
2649 else if (code == 0) \
2651 fprintf(stderr, "DEBUG: Setting %s to %d...\n", sname, intval); \
2652 cups->header.name = (type)intval; \
2655 #define floatoption(name, sname) \
2656 if ((code = param_read_float(plist, sname, &floatval)) < 0) \
2658 param_signal_error(plist, sname, code); \
2661 else if (code == 0) \
2662 cups->header.name = (unsigned)floatval;
2664 #define booloption(name, sname) \
2665 if ((code = param_read_bool(plist, sname, &boolval)) < 0) \
2667 if ((code = param_read_null(plist, sname)) < 0) \
2669 param_signal_error(plist, sname, code); \
2673 cups->header.name = CUPS_FALSE; \
2675 else if (code == 0) \
2676 cups->header.name = (cups_bool_t)boolval;
2678 #define arrayoption(name, sname, count) \
2679 if ((code = param_read_float_array(plist, sname, &arrayval)) < 0) \
2681 if ((code = param_read_null(plist, sname)) < 0) \
2683 param_signal_error(plist, sname, code); \
2687 for (i = 0; i < count; i ++) \
2688 cups->header.name[i] = 0; \
2690 else if (code == 0) \
2692 for (i = 0; i < count; i ++) \
2693 cups->header.name[i] = (unsigned)arrayval.data[i]; \
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;
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)
2735 #ifdef CUPS_RASTER_SYNCv1
2736 for (i
= 0; i
< 16; i
++)
2738 sprintf(name
, "cupsInteger%d", i
);
2739 intoption(cupsInteger
[i
], name
, unsigned)
2742 for (i
= 0; i
< 16; i
++)
2744 sprintf(name
, "cupsReal%d", i
);
2745 floatoption(cupsReal
[i
], name
)
2748 for (i
= 0; i
< 16; i
++)
2750 sprintf(name
, "cupsString%d", i
);
2751 stringoption(cupsString
[i
], name
)
2754 stringoption(cupsMarkerType
, "cupsMarkerType");
2755 stringoption(cupsRenderingIntent
, "cupsRenderingIntent");
2756 #endif /* CUPS_RASTER_SYNCv1 */
2758 if ((code
= param_read_string(plist
, "cupsProfile", &stringval
)) < 0)
2760 param_signal_error(plist
, "cupsProfile", code
);
2765 if (cupsProfile
!= NULL
)
2768 cupsProfile
= strdup(stringval
.data
);
2771 cups_set_color_info(pdev
);
2774 * Then process standard page device options...
2777 if ((code
= gdev_prn_put_params(pdev
, plist
)) < 0)
2781 * Update margins/sizes as needed...
2787 * Compute the page margins...
2790 fprintf(stderr
, "DEBUG: Updating PageSize to [%.0f %.0f]...\n",
2791 cups
->MediaSize
[0], cups
->MediaSize
[1]);
2793 memset(margins
, 0, sizeof(margins
));
2795 cups
->landscape
= 0;
2797 if (cupsPPD
!= NULL
)
2800 * Find the matching page size...
2803 for (i
= cupsPPD
->num_sizes
, size
= cupsPPD
->sizes
;
2806 if (fabs(cups
->MediaSize
[1] - size
->length
) < 5.0 &&
2807 fabs(cups
->MediaSize
[0] - size
->width
) < 5.0)
2816 fprintf(stderr
, "DEBUG: size = %s\n", size
->name
);
2818 gx_device_set_media_size(pdev
, size
->width
, size
->length
);
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;
2828 * No matching portrait size; look for a matching size in
2829 * landscape orientation...
2832 for (i
= cupsPPD
->num_sizes
, size
= cupsPPD
->sizes
;
2835 if (fabs(cups
->MediaSize
[0] - size
->length
) < 5.0 &&
2836 fabs(cups
->MediaSize
[1] - size
->width
) < 5.0)
2842 * Standard size in landscape orientation...
2845 fprintf(stderr
, "DEBUG: landscape size = %s\n", size
->name
);
2847 gx_device_set_media_size(pdev
, size
->length
, size
->width
);
2849 cups
->landscape
= 1;
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;
2862 fputs("DEBUG: size = Custom\n", stderr
);
2864 for (i
= 0; i
< 4; i
++)
2865 margins
[i
] = cupsPPD
->custom_margins
[i
] / 72.0;
2869 fprintf(stderr
, "DEBUG: margins[] = [ %f %f %f %f ]\n",
2870 margins
[0], margins
[1], margins
[2], margins
[3]);
2874 * Set the margins to update the bitmap size...
2877 gx_device_set_margins(pdev
, margins
, false);
2881 * Set CUPS raster header values...
2884 cups
->header
.HWResolution
[0] = pdev
->HWResolution
[0];
2885 cups
->header
.HWResolution
[1] = pdev
->HWResolution
[1];
2887 cups
->header
.Margins
[0] = pdev
->HWMargins
[0];
2888 cups
->header
.Margins
[1] = pdev
->HWMargins
[1];
2890 cups
->header
.PageSize
[0] = pdev
->MediaSize
[0];
2891 cups
->header
.PageSize
[1] = pdev
->MediaSize
[1];
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];
2899 * Reallocate memory if the size or color depth was changed...
2902 if (color_set
|| size_set
)
2905 * Make sure the page image is the correct size - current Ghostscript
2906 * does not keep track of the margins in the bitmap size...
2909 if (cups
->landscape
)
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
;
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
;
2925 * Don't reallocate memory unless the device has been opened...
2931 * Device is open, so reallocate...
2934 fprintf(stderr
, "DEBUG: Reallocating memory, [%.0f %.0f] = %dx%d pixels...\n",
2935 pdev
->MediaSize
[0], pdev
->MediaSize
[1], width
, height
);
2937 sp
= ((gx_device_printer
*)pdev
)->space_params
;
2939 if ((code
= gdev_prn_reallocate_memory(pdev
, &sp
, width
, height
)) < 0)
2945 * Device isn't yet open, so just save the new width and height...
2948 fprintf(stderr
, "DEBUG: Setting initial media size, [%.0f %.0f] = %dx%d pixels...\n",
2949 pdev
->MediaSize
[0], pdev
->MediaSize
[1], width
, height
);
2951 pdev
->width
= width
;
2952 pdev
->height
= height
;
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]);
2976 * 'cups_set_color_info()' - Set the color information structure based on
2977 * the required output.
2981 cups_set_color_info(gx_device
*pdev
) /* I - Device info */
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 */
2992 fprintf(stderr
, "DEBUG2: cups_set_color_info(%p)\n", pdev
);
2995 switch (cups
->header
.cupsColorSpace
)
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;
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
;
3016 cups
->header
.cupsBitsPerPixel
= 3 * cups
->header
.cupsBitsPerColor
;
3018 if (cups
->header
.cupsBitsPerColor
< 8)
3019 cups
->color_info
.depth
= 4 * cups
->header
.cupsBitsPerColor
;
3021 cups
->color_info
.depth
= 3 * cups
->header
.cupsBitsPerColor
;
3023 cups
->color_info
.num_components
= 3;
3026 case CUPS_CSPACE_KCMYcm
:
3027 if (cups
->header
.cupsBitsPerColor
== 1)
3029 cups
->header
.cupsBitsPerPixel
= 8;
3030 cups
->color_info
.depth
= 8;
3031 cups
->color_info
.num_components
= 4;
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
;
3043 cups
->header
.cupsBitsPerPixel
= 4 * cups
->header
.cupsBitsPerColor
;
3045 cups
->color_info
.depth
= 4 * cups
->header
.cupsBitsPerColor
;
3046 cups
->color_info
.num_components
= 4;
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
:
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...
3072 * This code enforces a minimum output depth of 8 bits per
3076 if (cups
->header
.cupsBitsPerColor
< 8)
3077 cups
->header
.cupsBitsPerColor
= 8;
3079 if (cups
->header
.cupsColorOrder
!= CUPS_ORDER_CHUNKED
)
3080 cups
->header
.cupsBitsPerPixel
= cups
->header
.cupsBitsPerColor
;
3082 cups
->header
.cupsBitsPerPixel
= 3 * cups
->header
.cupsBitsPerColor
;
3084 cups
->color_info
.depth
= 24;
3085 cups
->color_info
.num_components
= 3;
3087 #endif /* CUPS_RASTER_HAVE_COLORIMETRIC */
3090 #ifdef dev_t_proc_encode_color
3091 switch (cups
->header
.cupsColorSpace
)
3094 cups
->color_info
.gray_index
= GX_CINFO_COMP_NO_INDEX
;
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;
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;
3115 switch (cups
->header
.cupsColorSpace
)
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
;
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
;
3158 cups
->color_info
.separable_and_linear
= GX_CINFO_SEP_LIN_NONE
;
3159 #endif /* dev_t_proc_encode_color */
3161 if ((i
= cups
->header
.cupsBitsPerColor
) > 8)
3164 max_lut
= (1 << i
) - 1;
3166 switch (cups
->color_info
.num_components
)
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;
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;
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;
3192 * Enable/disable CMYK color support...
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 */
3200 * Tell Ghostscript to forget any colors it has cached...
3203 gx_device_decache_colors(pdev
);
3206 * Compute the lookup tables...
3209 for (i
= 0; i
<= gx_max_color_value
; i
++)
3211 cupsEncodeLUT
[i
] = (max_lut
* i
+ gx_max_color_value
/ 2) /
3215 if (i
== 0 || cupsEncodeLUT
[i
] != cupsEncodeLUT
[i
- 1])
3216 fprintf(stderr
, "DEBUG2: cupsEncodeLUT[%d] = %d\n", i
, cupsEncodeLUT
[i
]);
3220 for (i
= 0; i
< cups
->color_info
.dither_grays
; i
++)
3221 cupsDecodeLUT
[i
] = gx_max_color_value
* i
/ max_lut
;
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
);
3235 * Set the color profile as needed...
3238 cupsHaveProfile
= 0;
3240 #ifdef dev_t_proc_encode_color
3243 if (cupsProfile
&& cups
->header
.cupsBitsPerColor
== 8)
3244 #endif /* dev_t_proc_encode_color */
3246 fprintf(stderr
, "DEBUG: Using user-defined profile \"%s\"...\n", cupsProfile
);
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
);
3255 cupsHaveProfile
= 1;
3270 #ifdef dev_t_proc_encode_color
3273 else if (cupsPPD
&& cups
->header
.cupsBitsPerColor
== 8)
3274 #endif /* dev_t_proc_encode_color */
3277 * Find the appropriate color profile...
3280 if (pdev
->HWResolution
[0] != pdev
->HWResolution
[1])
3281 sprintf(resolution
, "%.0fx%.0fdpi", pdev
->HWResolution
[0],
3282 pdev
->HWResolution
[1]);
3284 sprintf(resolution
, "%.0fdpi", pdev
->HWResolution
[0]);
3286 for (i
= 0, profile
= cupsPPD
->profiles
;
3287 i
< cupsPPD
->num_profiles
;
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] == '-'))
3296 * If we found a color profile, use it!
3299 if (i
< cupsPPD
->num_profiles
)
3301 fputs("DEBUG: Using color profile in PPD file!\n", stderr
);
3303 cupsHaveProfile
= 1;
3305 d
= profile
->density
;
3308 memcpy(m
, profile
->matrix
, sizeof(m
));
3312 if (cupsHaveProfile
)
3314 for (i
= 0; i
< 3; i
++)
3315 for (j
= 0; j
< 3; j
++)
3316 for (k
= 0; k
<= CUPS_MAX_VALUE
; k
++)
3318 cupsMatrix
[i
][j
][k
] = (int)((float)k
* m
[i
][j
] + 0.5);
3321 if ((k
& 4095) == 0)
3322 fprintf(stderr
, "DEBUG2: cupsMatrix[%d][%d][%d] = %d\n",
3323 i
, j
, k
, cupsMatrix
[i
][j
][k
]);
3328 for (k
= 0; k
<= CUPS_MAX_VALUE
; k
++)
3330 cupsDensity
[k
] = (int)((float)CUPS_MAX_VALUE
* d
*
3331 pow((float)k
/ (float)CUPS_MAX_VALUE
, g
) +
3335 if ((k
& 4095) == 0)
3336 fprintf(stderr
, "DEBUG2: cupsDensity[%d] = %d\n", k
, cupsDensity
[k
]);
3342 for (k
= 0; k
<= CUPS_MAX_VALUE
; k
++)
3349 * 'cups_sync_output()' - Keep the user informed of our status...
3352 private int /* O - Error status */
3353 cups_sync_output(gx_device
*pdev
) /* I - Device info */
3355 fprintf(stderr
, "INFO: Processing page %d...\n", cups
->page
);
3362 * 'cups_print_chunked()' - Print a page of chunked pixels.
3366 cups_print_chunked(gx_device_printer
*pdev
,
3367 /* I - Printer device */
3369 /* I - Scanline buffer */
3371 /* I - Bitmap buffer */
3373 /* I - Number of bytes in src */
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? */
3382 if (cups
->header
.Duplex
&& !cups
->header
.Tumble
&&
3383 cupsPPD
&& cupsPPD
->flip_duplex
&& !(cups
->page
& 1))
3388 fprintf(stderr
, "DEBUG: cups_print_chunked - flip = %d, height = %d\n",
3389 flip
, cups
->height
);
3392 * Loop through the page bitmap and write chunked pixels, reversing as
3396 for (y
= 0; y
< cups
->height
; y
++)
3399 * Grab the scanline data...
3402 if (gdev_prn_get_bits((gx_device_printer
*)pdev
, y
, src
, &srcptr
) < 0)
3404 fprintf(stderr
, "ERROR: Unable to get scanline %d!\n", y
);
3411 * Flip the raster data before writing it...
3414 if (srcptr
[0] == 0 && memcmp(srcptr
, srcptr
+ 1, srcbytes
- 1) == 0)
3415 memset(dst
, 0, cups
->header
.cupsBytesPerLine
);
3421 switch (cups
->color_info
.depth
)
3423 case 1 : /* B&W bitmap */
3424 for (srcptr
+= srcbytes
- 1;
3426 count
--, srcptr
--, dstptr
++)
3428 *dstptr
= cupsRevUpper1
[*srcptr
& 15] |
3429 cupsRevLower1
[*srcptr
>> 4];
3433 case 2 : /* 2-bit grayscale */
3434 for (srcptr
+= srcbytes
- 1;
3436 count
--, srcptr
--, dstptr
++)
3438 *dstptr
= cupsRevUpper2
[*srcptr
& 15] |
3439 cupsRevLower2
[*srcptr
>> 4];
3443 case 4 : /* 4-bit grayscale, or RGB, CMY, or CMYK bitmap */
3444 for (srcptr
+= srcbytes
- 1;
3446 count
--, srcptr
--, dstptr
++)
3447 *dstptr
= (*srcptr
>> 4) | (*srcptr
<< 4);
3450 case 8 : /* 8-bit grayscale, or 2-bit RGB, CMY, or CMYK image */
3451 for (srcptr
+= srcbytes
- 1;
3453 count
--, srcptr
--, dstptr
++)
3457 case 16 : /* 4-bit RGB, CMY or CMYK image */
3458 for (srcptr
+= srcbytes
- 2;
3460 count
-= 2, srcptr
-= 2, dstptr
+= 2)
3462 dstptr
[0] = srcptr
[0];
3463 dstptr
[1] = srcptr
[1];
3467 case 24 : /* 8-bit RGB or CMY image */
3468 for (srcptr
+= srcbytes
- 3;
3470 count
-= 3, srcptr
-= 3, dstptr
+= 3)
3472 dstptr
[0] = srcptr
[0];
3473 dstptr
[1] = srcptr
[1];
3474 dstptr
[2] = srcptr
[2];
3478 case 32 : /* 4-bit RGB, CMY or CMYK bitmap */
3479 for (srcptr
+= srcbytes
- 4;
3481 count
-= 4, srcptr
-= 4, dstptr
+= 4)
3483 dstptr
[0] = srcptr
[0];
3484 dstptr
[1] = srcptr
[1];
3485 dstptr
[2] = srcptr
[2];
3486 dstptr
[3] = srcptr
[3];
3493 * Write the bitmap data to the raster stream...
3496 cupsRasterWritePixels(cups
->stream
, dst
, cups
->header
.cupsBytesPerLine
);
3501 * Write the scanline data to the raster stream...
3504 cupsRasterWritePixels(cups
->stream
, srcptr
, cups
->header
.cupsBytesPerLine
);
3511 * 'cups_print_banded()' - Print a page of banded pixels.
3515 cups_print_banded(gx_device_printer
*pdev
,
3516 /* I - Printer device */
3518 /* I - Scanline buffer */
3520 /* I - Bitmap buffer */
3522 /* I - Number of bytes in src */
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? */
3535 if (cups
->header
.Duplex
&& !cups
->header
.Tumble
&&
3536 cupsPPD
&& cupsPPD
->flip_duplex
&& !(cups
->page
& 1))
3541 fprintf(stderr
, "DEBUG: cups_print_banded - flip = %d, height = %d\n",
3542 flip
, cups
->height
);
3545 * Loop through the page bitmap and write banded pixels... We have
3546 * to separate each chunked color as needed...
3549 bandbytes
= (cups
->header
.cupsWidth
* cups
->header
.cupsBitsPerColor
+ 7) / 8;
3551 for (y
= 0; y
< cups
->height
; y
++)
3554 * Grab the scanline data...
3557 if (gdev_prn_get_bits((gx_device_printer
*)pdev
, y
, src
, &srcptr
) < 0)
3559 fprintf(stderr
, "ERROR: Unable to get scanline %d!\n", y
);
3564 * Separate the chunked colors into their components...
3567 if (srcptr
[0] == 0 && memcmp(srcptr
, srcptr
+ 1, srcbytes
- 1) == 0)
3568 memset(dst
, 0, cups
->header
.cupsBytesPerLine
);
3572 cptr
= dst
+ bandbytes
- 1;
3576 mptr
= cptr
+ bandbytes
;
3577 yptr
= mptr
+ bandbytes
;
3578 kptr
= yptr
+ bandbytes
;
3579 lcptr
= yptr
+ bandbytes
;
3580 lmptr
= lcptr
+ bandbytes
;
3582 switch (cups
->header
.cupsBitsPerColor
)
3585 memset(dst
, 0, cups
->header
.cupsBytesPerLine
);
3587 switch (cups
->header
.cupsColorSpace
)
3590 for (x
= cups
->width
, bit
= flip
? 1 << (x
& 7) : 128;
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;
3723 case CUPS_CSPACE_KCMYcm
:
3724 for (x
= cups
->width
, bit
= flip
? 1 << (x
& 7) : 128;
3729 * Note: Because of the way the pointers are setup,
3730 * the following code is correct even though
3731 * the names don't match...
3780 memset(dst
, 0, cups
->header
.cupsBytesPerLine
);
3782 switch (cups
->header
.cupsColorSpace
)
3785 for (x
= cups
->width
, bit
= flip
? 3 << (2 * (x
& 3)) : 0xc0;
3791 if ((temp
= *srcptr
& 0x30) != 0)
3793 if ((temp
= *srcptr
& 0x0c) != 0)
3795 if ((temp
= *srcptr
& 0x03) != 0)
3809 if ((temp
= *srcptr
& 0x30) != 0)
3811 if ((temp
= *srcptr
& 0x0c) != 0)
3813 if ((temp
= *srcptr
& 0x03) != 0)
3822 if ((temp
= *srcptr
& 0x30) != 0)
3824 if ((temp
= *srcptr
& 0x0c) != 0)
3826 if ((temp
= *srcptr
& 0x03) != 0)
3835 if ((temp
= *srcptr
& 0x30) != 0)
3837 if ((temp
= *srcptr
& 0x0c) != 0)
3839 if ((temp
= *srcptr
& 0x03) != 0)
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;
3867 if ((temp
= *srcptr
& 0xc0) != 0)
3869 if ((temp
= *srcptr
& 0x30) != 0)
3871 if ((temp
= *srcptr
& 0x0c) != 0)
3873 if ((temp
= *srcptr
& 0x03) != 0)
3888 if ((temp
= *srcptr
& 0xc0) != 0)
3890 if ((temp
= *srcptr
& 0x30) != 0)
3892 if ((temp
= *srcptr
& 0x0c) != 0)
3894 if ((temp
= *srcptr
& 0x03) != 0)
3903 if ((temp
= *srcptr
& 0xc0) != 0)
3905 if ((temp
= *srcptr
& 0x30) != 0)
3907 if ((temp
= *srcptr
& 0x0c) != 0)
3909 if ((temp
= *srcptr
& 0x03) != 0)
3918 if ((temp
= *srcptr
& 0xc0) != 0)
3920 if ((temp
= *srcptr
& 0x30) != 0)
3922 if ((temp
= *srcptr
& 0x0c) != 0)
3924 if ((temp
= *srcptr
& 0x03) != 0)
3944 memset(dst
, 0, cups
->header
.cupsBytesPerLine
);
3946 switch (cups
->header
.cupsColorSpace
)
3949 for (x
= cups
->width
, bit
= flip
&& (x
& 1) ? 0xf0 : 0x0f;
3955 if ((temp
= srcptr
[0] & 0x0f) != 0)
3957 if ((temp
= srcptr
[1] & 0xf0) != 0)
3959 if ((temp
= srcptr
[1] & 0x0f) != 0)
3972 if ((temp
= srcptr
[0] & 0x0f) != 0)
3974 if ((temp
= srcptr
[1] & 0xf0) != 0)
3976 if ((temp
= srcptr
[1] & 0x0f) != 0)
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;
4003 if ((temp
= srcptr
[0] & 0xf0) != 0)
4005 if ((temp
= srcptr
[0] & 0x0f) != 0)
4007 if ((temp
= srcptr
[1] & 0xf0) != 0)
4009 if ((temp
= srcptr
[1] & 0x0f) != 0)
4023 if ((temp
= srcptr
[0] & 0xf0) != 0)
4025 if ((temp
= srcptr
[0] & 0x0f) != 0)
4027 if ((temp
= srcptr
[1] & 0xf0) != 0)
4029 if ((temp
= srcptr
[1] & 0x0f) != 0)
4048 switch (cups
->header
.cupsColorSpace
)
4052 for (x
= cups
->width
; x
> 0; x
--)
4054 *cptr
-- = *srcptr
++;
4055 *mptr
-- = *srcptr
++;
4056 *yptr
-- = *srcptr
++;
4059 for (x
= cups
->width
; x
> 0; x
--)
4061 *cptr
++ = *srcptr
++;
4062 *mptr
++ = *srcptr
++;
4063 *yptr
++ = *srcptr
++;
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
:
4074 for (x
= cups
->width
; x
> 0; x
--)
4076 *cptr
-- = *srcptr
++;
4077 *mptr
-- = *srcptr
++;
4078 *yptr
-- = *srcptr
++;
4079 *kptr
-- = *srcptr
++;
4082 for (x
= cups
->width
; x
> 0; x
--)
4084 *cptr
++ = *srcptr
++;
4085 *mptr
++ = *srcptr
++;
4086 *yptr
++ = *srcptr
++;
4087 *kptr
++ = *srcptr
++;
4096 * Write the bitmap data to the raster stream...
4099 cupsRasterWritePixels(cups
->stream
, dst
, cups
->header
.cupsBytesPerLine
);
4105 * 'cups_print_planar()' - Print a page of planar pixels.
4109 cups_print_planar(gx_device_printer
*pdev
,
4110 /* I - Printer device */
4112 /* I - Scanline buffer */
4114 /* I - Bitmap buffer */
4116 /* I - Number of bytes in src */
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 */
4128 /**** NOTE: Currently planar output doesn't support flipped duplex!!! ****/
4131 * Loop through the page bitmap and write planar pixels... We have
4132 * to separate each chunked color as needed...
4135 for (z
= 0; z
< pdev
->color_info
.num_components
; z
++)
4136 for (y
= 0; y
< cups
->height
; y
++)
4139 * Grab the scanline data...
4142 if (gdev_prn_get_bits((gx_device_printer
*)pdev
, y
, src
, &srcptr
) < 0)
4144 fprintf(stderr
, "ERROR: Unable to get scanline %d!\n", y
);
4149 * Pull the individual color planes out of the pixels...
4152 if (srcptr
[0] == 0 && memcmp(srcptr
, srcptr
+ 1, srcbytes
- 1) == 0)
4153 memset(dst
, 0, cups
->header
.cupsBytesPerLine
);
4155 switch (cups
->header
.cupsBitsPerColor
)
4158 memset(dst
, 0, cups
->header
.cupsBytesPerLine
);
4160 switch (cups
->header
.cupsColorSpace
)
4163 for (dstptr
= dst
, x
= cups
->width
, srcbit
= 64 >> z
,
4168 if (*srcptr
& srcbit
)
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
,
4199 if (*srcptr
& srcbit
)
4219 case CUPS_CSPACE_KCMYcm
:
4220 for (dstptr
= dst
, x
= cups
->width
, srcbit
= 32 >> z
,
4225 if (*srcptr
& srcbit
)
4241 memset(dst
, 0, cups
->header
.cupsBytesPerLine
);
4243 switch (cups
->header
.cupsColorSpace
)
4246 for (dstptr
= dst
, x
= cups
->width
, srcbit
= 48 >> (z
* 2),
4251 if ((temp
= *srcptr
& srcbit
) != 0)
4253 if (srcbit
== dstbit
)
4270 *dstptr
|= temp
<< 6;
4273 *dstptr
|= temp
<< 4;
4276 *dstptr
|= temp
<< 2;
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),
4306 if ((temp
= *srcptr
& srcbit
) != 0)
4308 if (srcbit
== dstbit
)
4328 *dstptr
|= temp
<< 6;
4331 *dstptr
|= temp
<< 4;
4334 *dstptr
|= temp
<< 2;
4356 memset(dst
, 0, cups
->header
.cupsBytesPerLine
);
4358 switch (cups
->header
.cupsColorSpace
)
4369 for (dstptr
= dst
, x
= cups
->width
, dstbit
= 0xf0;
4373 if ((temp
= *srcptr
& srcbit
) != 0)
4375 if (srcbit
== dstbit
)
4383 *dstptr
|= temp
<< 4;
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
:
4413 for (dstptr
= dst
, x
= cups
->width
, dstbit
= 0xf0;
4417 if ((temp
= *srcptr
& srcbit
) != 0)
4419 if (srcbit
== dstbit
)
4427 *dstptr
|= temp
<< 4;
4446 for (srcptr
+= z
, dstptr
= dst
, x
= cups
->header
.cupsBytesPerLine
;
4448 srcptr
+= pdev
->color_info
.num_components
, x
--)
4449 *dstptr
++ = *srcptr
;
4454 * Write the bitmap data to the raster stream...
4457 cupsRasterWritePixels(cups
->stream
, dst
, cups
->header
.cupsBytesPerLine
);
4463 * End of "$Id: gdevcups.c 4493 2005-02-18 02:09:53Z mike $".