]> git.ipfire.org Git - thirdparty/cups.git/blob - pstoraster/gdevcups.c
Copyright update...
[thirdparty/cups.git] / pstoraster / gdevcups.c
1 /*
2 * "$Id: gdevcups.c,v 1.48 2002/01/02 17:59:09 mike Exp $"
3 *
4 * GNU Ghostscript raster output driver for the Common UNIX Printing
5 * System (CUPS).
6 *
7 * Copyright 1993-2002 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-3111 USA
20 *
21 * Voice: (301) 373-9603
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_map_color_rgb() - Map a color index to an RGB color.
38 * cups_map_rgb_color() - Map an RGB color to a color index. We map the
39 * RGB color to the output colorspace & bits (we
40 * figure out the format when we output a page).
41 * cups_open() - Open the output file and initialize things.
42 * cups_print_pages() - Send one or more pages to the output file.
43 * cups_put_params() - Set pagedevice parameters.
44 * cups_set_color_info() - Set the color information structure based on
45 * the required output.
46 * cups_print_chunked() - Print a page of chunked pixels.
47 * cups_print_banded() - Print a page of banded pixels.
48 * cups_print_planar() - Print a page of planar pixels.
49 */
50
51 /*
52 * Include necessary headers...
53 */
54
55 #include "std.h" /* to stop stdlib.h redefining types */
56 #include "gdevprn.h"
57 #include "gsparam.h"
58 #include "gsexit.h"
59
60 #include <stdlib.h>
61 #include <filter/raster.h>
62 #include <cups/ppd.h>
63 #include <math.h>
64
65 #undef private
66 #define private
67
68
69 /*
70 * Globals...
71 */
72
73 extern const char *cupsProfile;
74
75
76 /*
77 * Macros...
78 */
79
80 #define x_dpi (pdev->HWResolution[0])
81 #define y_dpi (pdev->HWResolution[1])
82 #define cups ((gx_device_cups *)pdev)
83
84 /*
85 * Macros from <macros.h>; we can't include <macros.h> because it also
86 * defines DEBUG, one of our flags to insert various debugging code.
87 */
88
89 #ifndef max
90 # define max(a,b) ((a)<(b) ? (b) : (a))
91 #endif /* !max */
92
93 #ifndef min
94 # define min(a,b) ((a)>(b) ? (b) : (a))
95 #endif /* !min */
96
97 #ifndef abs
98 # define abs(x) ((x)>=0 ? (x) : -(x))
99 #endif /* !abs */
100
101
102 /*
103 * Procedures
104 */
105
106 private dev_proc_close_device(cups_close);
107 private dev_proc_get_initial_matrix(cups_get_matrix);
108 private int cups_get_params(gx_device *, gs_param_list *);
109 private dev_proc_map_cmyk_color(cups_map_cmyk_color);
110 private dev_proc_map_color_rgb(cups_map_color_rgb);
111 private dev_proc_map_rgb_color(cups_map_rgb_color);
112 private dev_proc_open_device(cups_open);
113 private int cups_print_pages(gx_device_printer *, FILE *, int);
114 private int cups_put_params(gx_device *, gs_param_list *);
115 private void cups_set_color_info(gx_device *);
116 private dev_proc_sync_output(cups_sync_output);
117
118 /*
119 * The device descriptors...
120 */
121
122 typedef struct gx_device_cups_s
123 {
124 gx_device_common; /* Standard GhostScript device stuff */
125 gx_prn_device_common; /* Standard printer device stuff */
126 int page; /* Page number */
127 cups_raster_t *stream; /* Raster stream */
128 ppd_file_t *ppd; /* PPD file for this printer */
129 cups_page_header_t header; /* PostScript page device info */
130 } gx_device_cups;
131
132 private gx_device_procs cups_procs =
133 {
134 cups_open,
135 cups_get_matrix,
136 cups_sync_output,
137 gdev_prn_output_page,
138 cups_close,
139 cups_map_rgb_color,
140 cups_map_color_rgb,
141 NULL, /* fill_rectangle */
142 NULL, /* tile_rectangle */
143 NULL, /* copy_mono */
144 NULL, /* copy_color */
145 NULL, /* draw_line */
146 gx_default_get_bits,
147 cups_get_params,
148 cups_put_params,
149 NULL, /* map_cmyk_color */
150 NULL, /* get_xfont_procs */
151 NULL, /* get_xfont_device */
152 NULL, /* map_rgb_alpha_color */
153 gx_page_device_get_page_device,
154 NULL, /* get_alpha_bits */
155 NULL, /* copy_alpha */
156 NULL, /* get_band */
157 NULL, /* copy_rop */
158 NULL, /* fill_path */
159 NULL, /* stroke_path */
160 NULL, /* fill_mask */
161 NULL, /* fill_trapezoid */
162 NULL, /* fill_parallelogram */
163 NULL, /* fill_triangle */
164 NULL, /* draw_thin_line */
165 NULL, /* begin_image */
166 NULL, /* image_data */
167 NULL, /* end_image */
168 NULL, /* strip_tile_rectangle */
169 NULL /* strip_copy_rop */
170 };
171
172 gx_device_cups gs_cups_device =
173 {
174 prn_device_body_copies(gx_device_cups, cups_procs, "cups", 85, 110, 100, 100,
175 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, cups_print_pages),
176 0, /* page */
177 NULL, /* stream */
178 NULL, /* ppd */
179 { /* header */
180 "", /* MediaClass */
181 "", /* MediaColor */
182 "", /* MediaType */
183 "", /* OutputType */
184 0, /* AdvanceDistance */
185 CUPS_ADVANCE_NONE, /* AdvanceMedia */
186 CUPS_FALSE, /* Collate */
187 CUPS_CUT_NONE, /* CutMedia */
188 CUPS_FALSE, /* Duplex */
189 { 100, 100 }, /* HWResolution */
190 { 0, 0, 612, 792 }, /* ImagingBoundingBox */
191 CUPS_FALSE, /* InsertSheet */
192 CUPS_JOG_NONE, /* Jog */
193 CUPS_EDGE_TOP, /* LeadingEdge */
194 { 0, 0 }, /* Margins */
195 CUPS_FALSE, /* ManualFeed */
196 0, /* MediaPosition */
197 0, /* MediaWeight */
198 CUPS_FALSE, /* MirrorPrint */
199 CUPS_FALSE, /* NegativePrint */
200 1, /* NumCopies */
201 CUPS_ORIENT_0, /* Orientation */
202 CUPS_FALSE, /* OutputFaceUp */
203 { 612, 792 }, /* PageSize */
204 CUPS_FALSE, /* Separations */
205 CUPS_FALSE, /* TraySwitch */
206 CUPS_FALSE, /* Tumble */
207 850, /* cupsWidth */
208 1100, /* cupsHeight */
209 0, /* cupsMediaType */
210 1, /* cupsBitsPerColor */
211 1, /* cupsBitsPerPixel */
212 107, /* cupsBytesPerLine */
213 CUPS_ORDER_CHUNKED, /* cupsColorOrder */
214 CUPS_CSPACE_K, /* cupsColorSpace */
215 0, /* cupsCompression */
216 0, /* cupsRowCount */
217 0, /* cupsRowFeed */
218 0 /* cupsRowStep */
219 }
220 };
221
222 /*
223 * Color lookup tables...
224 */
225
226 static gx_color_value lut_color_rgb[256];
227 static unsigned char lut_rgb_color[gx_max_color_value + 1];
228 static int cupsHaveProfile = 0;
229 static int cupsMatrix[3][3][gx_max_color_value + 1];
230 static int cupsDensity[gx_max_color_value + 1];
231 static unsigned char rev_lower1[16] =
232 {
233 0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e,
234 0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f
235 },
236 rev_upper1[16] =
237 {
238 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
239 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0
240 },
241 rev_lower2[16] = /* 2-bit colors */
242 {
243 0x00, 0x04, 0x08, 0x0c, 0x01, 0x05, 0x09, 0x0d,
244 0x02, 0x06, 0x0a, 0x0e, 0x03, 0x07, 0x0b, 0x0f
245 },
246 rev_upper2[16] = /* 2-bit colors */
247 {
248 0x00, 0x40, 0x80, 0xc0, 0x10, 0x50, 0x90, 0xd0,
249 0x20, 0x60, 0xa0, 0xe0, 0x30, 0x70, 0xb0, 0xf0
250 };
251
252
253 /*
254 * Local functions...
255 */
256
257 static void cups_print_chunked(gx_device_printer *, unsigned char *,
258 unsigned char *, int);
259 static void cups_print_banded(gx_device_printer *, unsigned char *,
260 unsigned char *, int);
261 static void cups_print_planar(gx_device_printer *, unsigned char *,
262 unsigned char *, int);
263
264 /*static void cups_set_margins(gx_device *);*/
265
266
267 /*
268 * 'cups_close()' - Close the output file.
269 */
270
271 private int
272 cups_close(gx_device *pdev) /* I - Device info */
273 {
274 #ifdef DEBUG
275 fprintf(stderr, "DEBUG: cups_close(%p)\n", pdev);
276 #endif /* DEBUG */
277
278 if (cups->stream != NULL)
279 {
280 cupsRasterClose(cups->stream);
281 cups->stream = NULL;
282 }
283
284 #if 0 /* Can't do this here because put_params() might close the device */
285 if (cups->ppd != NULL)
286 {
287 ppdClose(cups->ppd);
288 cups->ppd = NULL;
289 }
290 #endif /* 0 */
291
292 return (gdev_prn_close(pdev));
293 }
294
295
296 /*
297 * 'cups_get_matrix()' - Generate the default page matrix.
298 */
299
300 private void
301 cups_get_matrix(gx_device *pdev, /* I - Device info */
302 gs_matrix *pmat) /* O - Physical transform matrix */
303 {
304 #ifdef DEBUG
305 fprintf(stderr, "DEBUG: cups_get_matrix(%p, %p)\n", pdev, pmat);
306 #endif /* DEBUG */
307
308 /*
309 * Set the raster width and height...
310 */
311
312 cups->header.cupsWidth = cups->width;
313 cups->header.cupsHeight = cups->height;
314
315 /*
316 * Set the transform matrix...
317 */
318
319 fprintf(stderr, "DEBUG: cups->header.Duplex = %d\n", cups->header.Duplex);
320 fprintf(stderr, "DEBUG: cups->page = %d\n", cups->page);
321 if (cups->ppd)
322 {
323 fprintf(stderr, "DEBUG: cups->ppd = %p\n", cups->ppd);
324 fprintf(stderr, "DEBUG: cups->ppd->flip_duplex = %d\n", cups->ppd->flip_duplex);
325 }
326
327 if (cups->header.Duplex && !cups->header.Tumble &&
328 cups->ppd && cups->ppd->flip_duplex && !(cups->page & 1))
329 {
330 pmat->xx = (float)cups->header.HWResolution[0] / 72.0;
331 pmat->xy = 0.0;
332 pmat->yx = 0.0;
333 pmat->yy = (float)cups->header.HWResolution[1] / 72.0;
334 pmat->tx = -(float)cups->header.HWResolution[0] * pdev->HWMargins[2] / 72.0;
335 pmat->ty = -(float)cups->header.HWResolution[1] * pdev->HWMargins[3] / 72.0;
336 }
337 else
338 {
339 pmat->xx = (float)cups->header.HWResolution[0] / 72.0;
340 pmat->xy = 0.0;
341 pmat->yx = 0.0;
342 pmat->yy = -(float)cups->header.HWResolution[1] / 72.0;
343 pmat->tx = -(float)cups->header.HWResolution[0] * pdev->HWMargins[0] / 72.0;
344 pmat->ty = (float)cups->header.HWResolution[1] *
345 ((float)cups->header.PageSize[1] - pdev->HWMargins[3]) / 72.0;
346 }
347
348 fprintf(stderr, "DEBUG: width = %d, height = %d\n", cups->width,
349 cups->height);
350 fprintf(stderr, "DEBUG: PageSize = [ %d %d ], HWResolution = [ %d %d ]\n",
351 cups->header.PageSize[0], cups->header.PageSize[1],
352 cups->header.HWResolution[0], cups->header.HWResolution[1]);
353 fprintf(stderr, "DEBUG: HWMargins = [ %.3f %.3f %.3f %.3f ]\n",
354 pdev->HWMargins[0], pdev->HWMargins[1], pdev->HWMargins[2],
355 pdev->HWMargins[3]);
356 fprintf(stderr, "DEBUG: matrix = [ %.3f %.3f %.3f %.3f %.3f %.3f ]\n",
357 pmat->xx, pmat->xy, pmat->yx, pmat->yy, pmat->tx, pmat->ty);
358 }
359
360
361 /*
362 * 'cups_get_params()' - Get pagedevice parameters.
363 */
364
365 private int /* O - Error status */
366 cups_get_params(gx_device *pdev, /* I - Device info */
367 gs_param_list *plist) /* I - Parameter list */
368 {
369 int code; /* Return code */
370 gs_param_string s; /* Temporary string value */
371 bool b; /* Temporary boolean value */
372
373
374 #ifdef DEBUG
375 fprintf(stderr, "DEBUG: cups_get_params(%p, %p)\n", pdev, plist);
376 #endif /* DEBUG */
377
378 /*
379 * First process the "standard" page device parameters...
380 */
381
382 #ifdef DEBUG
383 fputs("DEBUG: before gdev_prn_get_params()\n", stderr);
384 #endif /* DEBUG */
385
386 if ((code = gdev_prn_get_params(pdev, plist)) < 0)
387 return (code);
388
389 #ifdef DEBUG
390 fputs("DEBUG: after gdev_prn_get_params()\n", stderr);
391 #endif /* DEBUG */
392
393 /*
394 * Then write the CUPS parameters...
395 */
396
397 #ifdef DEBUG
398 fputs("DEBUG: MediaClass\n", stderr);
399 #endif /* DEBUG */
400
401 param_string_from_string(s, cups->header.MediaClass);
402 if ((code = param_write_string(plist, "MediaClass", &s)) < 0)
403 return (code);
404
405 #ifdef DEBUG
406 fputs("DEBUG: AdvanceDistance\n", stderr);
407 #endif /* DEBUG */
408
409 if ((code = param_write_int(plist, "AdvanceDistance",
410 (int *)&(cups->header.AdvanceDistance))) < 0)
411 return (code);
412
413 #ifdef DEBUG
414 fputs("DEBUG: AdvanceDistance\n", stderr);
415 #endif /* DEBUG */
416
417 if ((code = param_write_int(plist, "AdvanceMedia",
418 (int *)&(cups->header.AdvanceMedia))) < 0)
419 return (code);
420
421 #ifdef DEBUG
422 fputs("DEBUG: Collate\n", stderr);
423 #endif /* DEBUG */
424
425 b = cups->header.Collate;
426 if ((code = param_write_bool(plist, "Collate", &b)) < 0)
427 return (code);
428
429 #ifdef DEBUG
430 fputs("DEBUG: CutMedia\n", stderr);
431 #endif /* DEBUG */
432
433 if ((code = param_write_int(plist, "CutMedia",
434 (int *)&(cups->header.CutMedia))) < 0)
435 return (code);
436
437 #ifdef DEBUG
438 fputs("DEBUG: InsertSheet\n", stderr);
439 #endif /* DEBUG */
440
441 b = cups->header.InsertSheet;
442 if ((code = param_write_bool(plist, "InsertSheet", &b)) < 0)
443 return (code);
444
445 #ifdef DEBUG
446 fputs("DEBUG: Jog\n", stderr);
447 #endif /* DEBUG */
448
449 if ((code = param_write_int(plist, "Jog",
450 (int *)&(cups->header.Jog))) < 0)
451 return (code);
452
453 #ifdef DEBUG
454 fputs("DEBUG: LeadingEdge\n", stderr);
455 #endif /* DEBUG */
456
457 if ((code = param_write_int(plist, "LeadingEdge",
458 (int *)&(cups->header.LeadingEdge))) < 0)
459 return (code);
460
461 #ifdef DEBUG
462 fputs("DEBUG: ManualFeed\n", stderr);
463 #endif /* DEBUG */
464
465 b = cups->header.ManualFeed;
466 if ((code = param_write_bool(plist, "ManualFeed", &b)) < 0)
467 return (code);
468
469 #ifdef DEBUG
470 fputs("DEBUG: MediaPosition\n", stderr);
471 #endif /* DEBUG */
472
473 if ((code = param_write_int(plist, "MediaPosition",
474 (int *)&(cups->header.MediaPosition))) < 0)
475 return (code);
476
477 #ifdef DEBUG
478 fputs("DEBUG: MirrorPrint\n", stderr);
479 #endif /* DEBUG */
480
481 b = cups->header.MirrorPrint;
482 if ((code = param_write_bool(plist, "MirrorPrint", &b)) < 0)
483 return (code);
484
485 #ifdef DEBUG
486 fputs("DEBUG: NegativePrint\n", stderr);
487 #endif /* DEBUG */
488
489 b = cups->header.NegativePrint;
490 if ((code = param_write_bool(plist, "NegativePrint", &b)) < 0)
491 return (code);
492
493 #ifdef DEBUG
494 fputs("DEBUG: OutputFaceUp\n", stderr);
495 #endif /* DEBUG */
496
497 b = cups->header.OutputFaceUp;
498 if ((code = param_write_bool(plist, "OutputFaceUp", &b)) < 0)
499 return (code);
500
501 #ifdef DEBUG
502 fputs("DEBUG: Separations\n", stderr);
503 #endif /* DEBUG */
504
505 b = cups->header.Separations;
506 if ((code = param_write_bool(plist, "Separations", &b)) < 0)
507 return (code);
508
509 #ifdef DEBUG
510 fputs("DEBUG: TraySwitch\n", stderr);
511 #endif /* DEBUG */
512
513 b = cups->header.TraySwitch;
514 if ((code = param_write_bool(plist, "TraySwitch", &b)) < 0)
515 return (code);
516
517 #ifdef DEBUG
518 fputs("DEBUG: Tumble\n", stderr);
519 #endif /* DEBUG */
520
521 b = cups->header.Tumble;
522 if ((code = param_write_bool(plist, "Tumble", &b)) < 0)
523 return (code);
524
525 #ifdef DEBUG
526 fputs("DEBUG: cupsWidth\n", stderr);
527 #endif /* DEBUG */
528
529 if ((code = param_write_int(plist, "cupsWidth",
530 (int *)&(cups->header.cupsWidth))) < 0)
531 return (code);
532
533 #ifdef DEBUG
534 fputs("DEBUG: cupsHeight\n", stderr);
535 #endif /* DEBUG */
536
537 if ((code = param_write_int(plist, "cupsHeight",
538 (int *)&(cups->header.cupsHeight))) < 0)
539 return (code);
540
541 #ifdef DEBUG
542 fputs("DEBUG: cupsMediaType\n", stderr);
543 #endif /* DEBUG */
544
545 if ((code = param_write_int(plist, "cupsMediaType",
546 (int *)&(cups->header.cupsMediaType))) < 0)
547 return (code);
548
549 #ifdef DEBUG
550 fputs("DEBUG: cupsBitsPerColor\n", stderr);
551 #endif /* DEBUG */
552
553 if ((code = param_write_int(plist, "cupsBitsPerColor",
554 (int *)&(cups->header.cupsBitsPerColor))) < 0)
555 return (code);
556
557 #ifdef DEBUG
558 fputs("DEBUG: cupsBitsPerPixel\n", stderr);
559 #endif /* DEBUG */
560
561 if ((code = param_write_int(plist, "cupsBitsPerPixel",
562 (int *)&(cups->header.cupsBitsPerPixel))) < 0)
563 return (code);
564
565 #ifdef DEBUG
566 fputs("DEBUG: cupsBytesPerLine\n", stderr);
567 #endif /* DEBUG */
568
569 if ((code = param_write_int(plist, "cupsBytesPerLine",
570 (int *)&(cups->header.cupsBytesPerLine))) < 0)
571 return (code);
572
573 #ifdef DEBUG
574 fputs("DEBUG: cupsColorOrder\n", stderr);
575 #endif /* DEBUG */
576
577 if ((code = param_write_int(plist, "cupsColorOrder",
578 (int *)&(cups->header.cupsColorOrder))) < 0)
579 return (code);
580
581 #ifdef DEBUG
582 fputs("DEBUG: cupsColorSpace\n", stderr);
583 #endif /* DEBUG */
584
585 if ((code = param_write_int(plist, "cupsColorSpace",
586 (int *)&(cups->header.cupsColorSpace))) < 0)
587 return (code);
588
589 #ifdef DEBUG
590 fputs("DEBUG: cupsCompression\n", stderr);
591 #endif /* DEBUG */
592
593 if ((code = param_write_int(plist, "cupsCompression",
594 (int *)&(cups->header.cupsCompression))) < 0)
595 return (code);
596
597 #ifdef DEBUG
598 fputs("DEBUG: cupsRowCount\n", stderr);
599 #endif /* DEBUG */
600
601 if ((code = param_write_int(plist, "cupsRowCount",
602 (int *)&(cups->header.cupsRowCount))) < 0)
603 return (code);
604
605 #ifdef DEBUG
606 fputs("DEBUG: cupsRowFeed\n", stderr);
607 #endif /* DEBUG */
608
609 if ((code = param_write_int(plist, "cupsRowFeed",
610 (int *)&(cups->header.cupsRowFeed))) < 0)
611 return (code);
612
613 #ifdef DEBUG
614 fputs("DEBUG: cupsRowStep\n", stderr);
615 #endif /* DEBUG */
616
617 if ((code = param_write_int(plist, "cupsRowStep",
618 (int *)&(cups->header.cupsRowStep))) < 0)
619 return (code);
620
621 #ifdef DEBUG
622 fputs("DEBUG: Leaving cups_get_params()\n", stderr);
623 #endif /* DEBUG */
624
625 return (0);
626 }
627
628
629 /*
630 * 'cups_map_cmyk_color()' - Map a CMYK color to a color index.
631 *
632 * This function is only called when a 4 or 6 color colorspace is
633 * selected for output. CMYK colors are *not* corrected but *are*
634 * density adjusted.
635 */
636
637 private gx_color_index /* O - Color index */
638 cups_map_cmyk_color(gx_device *pdev, /* I - Device info */
639 gx_color_value c, /* I - Cyan value */
640 gx_color_value m, /* I - Magenta value */
641 gx_color_value y, /* I - Yellow value */
642 gx_color_value k) /* I - Black value */
643 {
644 gx_color_index i; /* Temporary index */
645 gx_color_value ic, im, iy, ik; /* Integral CMYK values */
646
647
648 #ifdef DEBUG
649 fprintf(stderr, "DEBUG: cups_map_cmyk_color(%p, %d, %d, %d, %d)\n", pdev,
650 c, m, y, k);
651 #endif /* DEBUG */
652
653 /*
654 * Setup the color info data as needed...
655 */
656
657 if (pdev->color_info.num_components == 0)
658 cups_set_color_info(pdev);
659
660 /*
661 * Density correct...
662 */
663
664 c = cupsDensity[c];
665 m = cupsDensity[m];
666 y = cupsDensity[y];
667 k = cupsDensity[k];
668
669 ic = lut_rgb_color[c];
670 im = lut_rgb_color[m];
671 iy = lut_rgb_color[y];
672 ik = lut_rgb_color[k];
673
674 /*
675 * Convert the CMYK color to a color index...
676 */
677
678 switch (cups->header.cupsColorSpace)
679 {
680 default :
681 switch (cups->header.cupsBitsPerColor)
682 {
683 default :
684 i = (((((ic << 1) | im) << 1) | iy) << 1) | ik;
685 break;
686 case 2 :
687 i = (((((ic << 2) | im) << 2) | iy) << 2) | ik;
688 break;
689 case 4 :
690 i = (((((ic << 4) | im) << 4) | iy) << 4) | ik;
691 break;
692 case 8 :
693 i = (((((ic << 8) | im) << 8) | iy) << 8) | ik;
694 break;
695 }
696 break;
697
698 case CUPS_CSPACE_YMCK :
699 case CUPS_CSPACE_GMCK :
700 case CUPS_CSPACE_GMCS :
701 switch (cups->header.cupsBitsPerColor)
702 {
703 default :
704 i = (((((iy << 1) | im) << 1) | ic) << 1) | ik;
705 break;
706 case 2 :
707 i = (((((iy << 2) | im) << 2) | ic) << 2) | ik;
708 break;
709 case 4 :
710 i = (((((iy << 4) | im) << 4) | ic) << 4) | ik;
711 break;
712 case 8 :
713 i = (((((iy << 8) | im) << 8) | ic) << 8) | ik;
714 break;
715 }
716 break;
717
718 case CUPS_CSPACE_KCMYcm :
719 if (cups->header.cupsBitsPerColor == 1)
720 {
721 if (ik)
722 i = 32;
723 else
724 i = 0;
725
726 if (ic && im)
727 i |= 17;
728 else if (ic && iy)
729 i |= 6;
730 else if (im && iy)
731 i |= 12;
732 else if (ic)
733 i |= 16;
734 else if (im)
735 i |= 8;
736 else if (iy)
737 i |= 4;
738 break;
739 }
740
741 case CUPS_CSPACE_KCMY :
742 switch (cups->header.cupsBitsPerColor)
743 {
744 default :
745 i = (((((ik << 1) | ic) << 1) | im) << 1) | iy;
746 break;
747 case 2 :
748 i = (((((ik << 2) | ic) << 2) | im) << 2) | iy;
749 break;
750 case 4 :
751 i = (((((ik << 4) | ic) << 4) | im) << 4) | iy;
752 break;
753 case 8 :
754 i = (((((ik << 8) | ic) << 8) | im) << 8) | iy;
755 break;
756 }
757 break;
758 }
759
760 if (gs_log_errors > 1)
761 fprintf(stderr, "DEBUG: CMYK (%d,%d,%d,%d) -> CMYK %8x (%d,%d,%d,%d)\n",
762 c, m, y, k, i, ic, im, iy, ik);
763
764 return (i);
765 }
766
767
768 /*
769 * 'cups_map_color_rgb()' - Map a color index to an RGB color.
770 */
771
772 private int
773 cups_map_color_rgb(gx_device *pdev, /* I - Device info */
774 gx_color_index color, /* I - Color index */
775 gx_color_value prgb[3]) /* O - RGB values */
776 {
777 unsigned char c0, c1, c2, c3; /* Color index components */
778 gx_color_value k, divk; /* Black & divisor */
779
780
781 #ifdef DEBUG
782 fprintf(stderr, "DEBUG: cups_map_color_rgb(%p, %d, %8x)\n", pdev,
783 color, prgb);
784 #endif /* DEBUG */
785
786 /*
787 * Setup the color info data as needed...
788 */
789
790 if (pdev->color_info.num_components == 0)
791 cups_set_color_info(pdev);
792
793 #ifdef DEBUG
794 fprintf(stderr, "DEBUG: COLOR %8x = ", color);
795 #endif /* DEBUG */
796
797 /*
798 * Extract the color components from the color index...
799 */
800
801 switch (cups->header.cupsBitsPerColor)
802 {
803 default :
804 c3 = color & 1;
805 color >>= 1;
806 c2 = color & 1;
807 color >>= 1;
808 c1 = color & 1;
809 color >>= 1;
810 c0 = color;
811 break;
812 case 2 :
813 c3 = color & 3;
814 color >>= 2;
815 c2 = color & 3;
816 color >>= 2;
817 c1 = color & 3;
818 color >>= 2;
819 c0 = color;
820 break;
821 case 4 :
822 c3 = color & 15;
823 color >>= 4;
824 c2 = color & 15;
825 color >>= 4;
826 c1 = color & 15;
827 color >>= 4;
828 c0 = color;
829 break;
830 case 8 :
831 c3 = color & 255;
832 color >>= 8;
833 c2 = color & 255;
834 color >>= 8;
835 c1 = color & 255;
836 color >>= 8;
837 c0 = color;
838 break;
839 }
840
841 /*
842 * Convert the color components to RGB...
843 */
844
845 switch (cups->header.cupsColorSpace)
846 {
847 case CUPS_CSPACE_K :
848 case CUPS_CSPACE_WHITE :
849 case CUPS_CSPACE_GOLD :
850 case CUPS_CSPACE_SILVER :
851 prgb[0] =
852 prgb[1] =
853 prgb[2] = lut_color_rgb[c3];
854 break;
855
856 case CUPS_CSPACE_W :
857 prgb[0] =
858 prgb[1] =
859 prgb[2] = lut_color_rgb[c3];
860 break;
861
862 case CUPS_CSPACE_RGB :
863 prgb[0] = lut_color_rgb[c1];
864 prgb[1] = lut_color_rgb[c2];
865 prgb[2] = lut_color_rgb[c3];
866 break;
867
868 case CUPS_CSPACE_RGBA :
869 prgb[0] = lut_color_rgb[c0];
870 prgb[1] = lut_color_rgb[c1];
871 prgb[2] = lut_color_rgb[c2];
872 break;
873
874 case CUPS_CSPACE_CMY :
875 prgb[0] = lut_color_rgb[c1];
876 prgb[1] = lut_color_rgb[c2];
877 prgb[2] = lut_color_rgb[c3];
878 break;
879
880 case CUPS_CSPACE_YMC :
881 prgb[0] = lut_color_rgb[c3];
882 prgb[1] = lut_color_rgb[c2];
883 prgb[2] = lut_color_rgb[c1];
884 break;
885
886 case CUPS_CSPACE_KCMY :
887 case CUPS_CSPACE_KCMYcm :
888 k = lut_color_rgb[c0];
889 divk = gx_max_color_value - k;
890 if (divk == 0)
891 {
892 prgb[0] = 0;
893 prgb[1] = 0;
894 prgb[2] = 0;
895 }
896 else
897 {
898 prgb[0] = gx_max_color_value + divk -
899 gx_max_color_value * c1 / divk;
900 prgb[1] = gx_max_color_value + divk -
901 gx_max_color_value * c2 / divk;
902 prgb[2] = gx_max_color_value + divk -
903 gx_max_color_value * c3 / divk;
904 }
905 break;
906
907 case CUPS_CSPACE_CMYK :
908 k = lut_color_rgb[c3];
909 divk = gx_max_color_value - k;
910 if (divk == 0)
911 {
912 prgb[0] = 0;
913 prgb[1] = 0;
914 prgb[2] = 0;
915 }
916 else
917 {
918 prgb[0] = gx_max_color_value + divk -
919 gx_max_color_value * c0 / divk;
920 prgb[1] = gx_max_color_value + divk -
921 gx_max_color_value * c1 / divk;
922 prgb[2] = gx_max_color_value + divk -
923 gx_max_color_value * c2 / divk;
924 }
925 break;
926
927 case CUPS_CSPACE_YMCK :
928 case CUPS_CSPACE_GMCK :
929 case CUPS_CSPACE_GMCS :
930 k = lut_color_rgb[c3];
931 divk = gx_max_color_value - k;
932 if (divk == 0)
933 {
934 prgb[0] = 0;
935 prgb[1] = 0;
936 prgb[2] = 0;
937 }
938 else
939 {
940 prgb[0] = gx_max_color_value + divk -
941 gx_max_color_value * c2 / divk;
942 prgb[1] = gx_max_color_value + divk -
943 gx_max_color_value * c1 / divk;
944 prgb[2] = gx_max_color_value + divk -
945 gx_max_color_value * c0 / divk;
946 }
947 break;
948 }
949
950 #ifdef DEBUG
951 fprintf(stderr, "%d,%d,%d\n", prgb[0], prgb[1], prgb[2]);
952 #endif /* DEBUG */
953
954 return (0);
955 }
956
957
958 /*
959 * 'cups_map_rgb_color()' - Map an RGB color to a color index. We map the
960 * RGB color to the output colorspace & bits (we
961 * figure out the format when we output a page).
962 */
963
964 private gx_color_index /* O - Color index */
965 cups_map_rgb_color(gx_device *pdev, /* I - Device info */
966 gx_color_value r, /* I - Red value */
967 gx_color_value g, /* I - Green value */
968 gx_color_value b) /* I - Blue value */
969 {
970 gx_color_index i; /* Temporary index */
971 gx_color_value ic, im, iy, ik; /* Integral CMYK values */
972 gx_color_value mk; /* Maximum K value */
973 int tc, tm, ty; /* Temporary color values */
974
975
976 #ifdef DEBUG
977 fprintf(stderr, "DEBUG: cups_map_rgb_color(%p, %d, %d, %d)\n", pdev, r, g, b);
978 #endif /* DEBUG */
979
980 /*
981 * Setup the color info data as needed...
982 */
983
984 if (pdev->color_info.num_components == 0)
985 cups_set_color_info(pdev);
986
987 /*
988 * Do color correction as needed...
989 */
990
991 if (cupsHaveProfile)
992 {
993 /*
994 * Compute CMYK values...
995 */
996
997 ic = gx_max_color_value - r;
998 im = gx_max_color_value - g;
999 iy = gx_max_color_value - b;
1000 ik = min(ic, min(im, iy));
1001
1002 if ((mk = max(ic, max(im, iy))) > ik)
1003 ik = (int)((float)ik * (float)ik * (float)ik / ((float)mk * (float)mk));
1004
1005 ic -= ik;
1006 im -= ik;
1007 iy -= ik;
1008
1009 /*
1010 * Color correct CMY...
1011 */
1012
1013 tc = cupsMatrix[0][0][ic] +
1014 cupsMatrix[0][1][im] +
1015 cupsMatrix[0][2][iy] +
1016 ik;
1017 tm = cupsMatrix[1][0][ic] +
1018 cupsMatrix[1][1][im] +
1019 cupsMatrix[1][2][iy] +
1020 ik;
1021 ty = cupsMatrix[2][0][ic] +
1022 cupsMatrix[2][1][im] +
1023 cupsMatrix[2][2][iy] +
1024 ik;
1025
1026 /*
1027 * Density correct combined CMYK...
1028 */
1029
1030 if (tc < 0)
1031 r = gx_max_color_value;
1032 else if (tc > gx_max_color_value)
1033 r = gx_max_color_value - cupsDensity[gx_max_color_value];
1034 else
1035 r = gx_max_color_value - cupsDensity[tc];
1036
1037 if (tm < 0)
1038 g = gx_max_color_value;
1039 else if (tm > gx_max_color_value)
1040 g = gx_max_color_value - cupsDensity[gx_max_color_value];
1041 else
1042 g = gx_max_color_value - cupsDensity[tm];
1043
1044 if (ty < 0)
1045 b = gx_max_color_value;
1046 else if (ty > gx_max_color_value)
1047 b = gx_max_color_value - cupsDensity[gx_max_color_value];
1048 else
1049 b = gx_max_color_value - cupsDensity[ty];
1050 }
1051
1052 /*
1053 * Convert the RGB color to a color index...
1054 */
1055
1056 switch (cups->header.cupsColorSpace)
1057 {
1058 case CUPS_CSPACE_W :
1059 i = lut_rgb_color[(r * 31 + g * 61 + b * 8) / 100];
1060 break;
1061
1062 case CUPS_CSPACE_RGB :
1063 ic = lut_rgb_color[r];
1064 im = lut_rgb_color[g];
1065 iy = lut_rgb_color[b];
1066
1067 switch (cups->header.cupsBitsPerColor)
1068 {
1069 default :
1070 i = (((ic << 1) | im) << 1) | iy;
1071 break;
1072 case 2 :
1073 i = (((ic << 2) | im) << 2) | iy;
1074 break;
1075 case 4 :
1076 i = (((ic << 4) | im) << 4) | iy;
1077 break;
1078 case 8 :
1079 i = (((ic << 8) | im) << 8) | iy;
1080 break;
1081 }
1082 break;
1083
1084 case CUPS_CSPACE_RGBA :
1085 ic = lut_rgb_color[r];
1086 im = lut_rgb_color[g];
1087 iy = lut_rgb_color[b];
1088
1089 switch (cups->header.cupsBitsPerColor)
1090 {
1091 default :
1092 i = (((((ic << 1) | im) << 1) | iy) << 1) | 0x01;
1093 break;
1094 case 2 :
1095 i = (((((ic << 2) | im) << 2) | iy) << 2) | 0x03;
1096 break;
1097 case 4 :
1098 i = (((((ic << 4) | im) << 4) | iy) << 4) | 0x0f;
1099 break;
1100 case 8 :
1101 i = (((((ic << 8) | im) << 8) | iy) << 8) | 0xff;
1102 break;
1103 }
1104 break;
1105
1106 default :
1107 i = lut_rgb_color[gx_max_color_value - (r * 31 + g * 61 + b * 8) / 100];
1108 break;
1109
1110 case CUPS_CSPACE_CMY :
1111 ic = lut_rgb_color[gx_max_color_value - r];
1112 im = lut_rgb_color[gx_max_color_value - g];
1113 iy = lut_rgb_color[gx_max_color_value - b];
1114
1115 switch (cups->header.cupsBitsPerColor)
1116 {
1117 default :
1118 i = (((ic << 1) | im) << 1) | iy;
1119 break;
1120 case 2 :
1121 i = (((ic << 2) | im) << 2) | iy;
1122 break;
1123 case 4 :
1124 i = (((ic << 4) | im) << 4) | iy;
1125 break;
1126 case 8 :
1127 i = (((ic << 8) | im) << 8) | iy;
1128 break;
1129 }
1130 break;
1131
1132 case CUPS_CSPACE_YMC :
1133 ic = lut_rgb_color[gx_max_color_value - r];
1134 im = lut_rgb_color[gx_max_color_value - g];
1135 iy = lut_rgb_color[gx_max_color_value - b];
1136
1137 switch (cups->header.cupsBitsPerColor)
1138 {
1139 default :
1140 i = (((iy << 1) | im) << 1) | ic;
1141 break;
1142 case 2 :
1143 i = (((iy << 2) | im) << 2) | ic;
1144 break;
1145 case 4 :
1146 i = (((iy << 4) | im) << 4) | ic;
1147 break;
1148 case 8 :
1149 i = (((iy << 8) | im) << 8) | ic;
1150 break;
1151 }
1152 break;
1153
1154 case CUPS_CSPACE_CMYK :
1155 ic = gx_max_color_value - r;
1156 im = gx_max_color_value - g;
1157 iy = gx_max_color_value - b;
1158 ik = min(ic, min(im, iy));
1159
1160 if ((mk = max(ic, max(im, iy))) > ik)
1161 ik = (int)((float)ik * (float)ik * (float)ik /
1162 ((float)mk * (float)mk));
1163
1164 ic = lut_rgb_color[ic - ik];
1165 im = lut_rgb_color[im - ik];
1166 iy = lut_rgb_color[iy - ik];
1167 ik = lut_rgb_color[ik];
1168
1169 switch (cups->header.cupsBitsPerColor)
1170 {
1171 default :
1172 i = (((((ic << 1) | im) << 1) | iy) << 1) | ik;
1173 break;
1174 case 2 :
1175 i = (((((ic << 2) | im) << 2) | iy) << 2) | ik;
1176 break;
1177 case 4 :
1178 i = (((((ic << 4) | im) << 4) | iy) << 4) | ik;
1179 break;
1180 case 8 :
1181 i = (((((ic << 8) | im) << 8) | iy) << 8) | ik;
1182 break;
1183 }
1184
1185 if (gs_log_errors > 1)
1186 fprintf(stderr, "DEBUG: CMY (%d,%d,%d) -> CMYK %8x (%d,%d,%d,%d)\n",
1187 r, g, b, i, ic, im, iy, ik);
1188 break;
1189
1190 case CUPS_CSPACE_YMCK :
1191 case CUPS_CSPACE_GMCK :
1192 case CUPS_CSPACE_GMCS :
1193 ic = gx_max_color_value - r;
1194 im = gx_max_color_value - g;
1195 iy = gx_max_color_value - b;
1196 ik = min(ic, min(im, iy));
1197
1198 if ((mk = max(ic, max(im, iy))) > ik)
1199 ik = (int)((float)ik * (float)ik * (float)ik /
1200 ((float)mk * (float)mk));
1201
1202 ic = lut_rgb_color[ic - ik];
1203 im = lut_rgb_color[im - ik];
1204 iy = lut_rgb_color[iy - ik];
1205 ik = lut_rgb_color[ik];
1206
1207 switch (cups->header.cupsBitsPerColor)
1208 {
1209 default :
1210 i = (((((iy << 1) | im) << 1) | ic) << 1) | ik;
1211 break;
1212 case 2 :
1213 i = (((((iy << 2) | im) << 2) | ic) << 2) | ik;
1214 break;
1215 case 4 :
1216 i = (((((iy << 4) | im) << 4) | ic) << 4) | ik;
1217 break;
1218 case 8 :
1219 i = (((((iy << 8) | im) << 8) | ic) << 8) | ik;
1220 break;
1221 }
1222 break;
1223
1224 case CUPS_CSPACE_KCMYcm :
1225 if (cups->header.cupsBitsPerColor == 1)
1226 {
1227 ic = gx_max_color_value - r;
1228 im = gx_max_color_value - g;
1229 iy = gx_max_color_value - b;
1230 ik = min(ic, min(im, iy));
1231
1232 if ((mk = max(ic, max(im, iy))) > ik)
1233 ik = (int)((float)ik * (float)ik * (float)ik /
1234 ((float)mk * (float)mk));
1235
1236 ic = lut_rgb_color[ic - ik];
1237 im = lut_rgb_color[im - ik];
1238 iy = lut_rgb_color[iy - ik];
1239 ik = lut_rgb_color[ik];
1240 if (ik)
1241 i = 32;
1242 else if (ic && im)
1243 i = 17;
1244 else if (ic && iy)
1245 i = 6;
1246 else if (im && iy)
1247 i = 12;
1248 else if (ic)
1249 i = 16;
1250 else if (im)
1251 i = 8;
1252 else if (iy)
1253 i = 4;
1254 else
1255 i = 0;
1256 break;
1257 }
1258
1259 case CUPS_CSPACE_KCMY :
1260 ic = gx_max_color_value - r;
1261 im = gx_max_color_value - g;
1262 iy = gx_max_color_value - b;
1263 ik = min(ic, min(im, iy));
1264
1265 if ((mk = max(ic, max(im, iy))) > ik)
1266 ik = (int)((float)ik * (float)ik * (float)ik /
1267 ((float)mk * (float)mk));
1268
1269 ic = lut_rgb_color[ic - ik];
1270 im = lut_rgb_color[im - ik];
1271 iy = lut_rgb_color[iy - ik];
1272 ik = lut_rgb_color[ik];
1273
1274 switch (cups->header.cupsBitsPerColor)
1275 {
1276 default :
1277 i = (((((ik << 1) | ic) << 1) | im) << 1) | iy;
1278 break;
1279 case 2 :
1280 i = (((((ik << 2) | ic) << 2) | im) << 2) | iy;
1281 break;
1282 case 4 :
1283 i = (((((ik << 4) | ic) << 4) | im) << 4) | iy;
1284 break;
1285 case 8 :
1286 i = (((((ik << 8) | ic) << 8) | im) << 8) | iy;
1287 break;
1288 }
1289 break;
1290 }
1291
1292 #ifdef DEBUG
1293 fprintf(stderr, "DEBUG: RGB %d,%d,%d = %8x\n", r, g, b, i);
1294 #endif /* DEBUG */
1295
1296 return (i);
1297 }
1298
1299
1300 /*
1301 * 'cups_open()' - Open the output file and initialize things.
1302 */
1303
1304 private int /* O - Error status */
1305 cups_open(gx_device *pdev) /* I - Device info */
1306 {
1307 int code; /* Return status */
1308
1309
1310 #ifdef DEBUG
1311 fprintf(stderr, "DEBUG: cups_open(%p)\n", pdev);
1312 #endif /* DEBUG */
1313
1314 if (cups->page == 0)
1315 {
1316 fputs("INFO: Processing page 1...\n", stderr);
1317 cups->page = 1;
1318 }
1319
1320 if (pdev->color_info.num_components == 0)
1321 cups_set_color_info(pdev);
1322
1323 if ((code = gdev_prn_open(pdev)) != 0)
1324 return (code);
1325
1326 if (cups->ppd == NULL)
1327 cups->ppd = ppdOpenFile(getenv("PPD"));
1328
1329 return (0);
1330 }
1331
1332
1333 /*
1334 * 'cups_print_pages()' - Send one or more pages to the output file.
1335 */
1336
1337 private int /* O - 0 if everything is OK */
1338 cups_print_pages(gx_device_printer *pdev, /* I - Device info */
1339 FILE *fp, /* I - Output file */
1340 int num_copies) /* I - Number of copies */
1341 {
1342 int copy; /* Copy number */
1343 int srcbytes; /* Byte width of scanline */
1344 unsigned char *src, /* Scanline data */
1345 *dst; /* Bitmap data */
1346
1347
1348 (void)fp; /* reference unused file pointer to prevent compiler warning */
1349
1350 #ifdef DEBUG
1351 fprintf(stderr, "DEBUG: cups_print_pages(%p, %p, %d)\n", pdev, fp,
1352 num_copies);
1353 #endif /* DEBUG */
1354
1355 /*
1356 * Figure out the number of bytes per line...
1357 */
1358
1359 switch (cups->header.cupsColorOrder)
1360 {
1361 case CUPS_ORDER_CHUNKED :
1362 cups->header.cupsBytesPerLine = (cups->header.cupsBitsPerPixel *
1363 cups->header.cupsWidth + 7) / 8;
1364 break;
1365
1366 case CUPS_ORDER_BANDED :
1367 if (cups->header.cupsColorSpace == CUPS_CSPACE_KCMYcm &&
1368 cups->header.cupsBitsPerColor == 1)
1369 cups->header.cupsBytesPerLine = (cups->header.cupsBitsPerColor *
1370 cups->header.cupsWidth + 7) / 8 * 6;
1371 else
1372 cups->header.cupsBytesPerLine = (cups->header.cupsBitsPerColor *
1373 cups->header.cupsWidth + 7) / 8 *
1374 cups->color_info.num_components;
1375 break;
1376
1377 case CUPS_ORDER_PLANAR :
1378 cups->header.cupsBytesPerLine = (cups->header.cupsBitsPerColor *
1379 cups->header.cupsWidth + 7) / 8;
1380 break;
1381 }
1382
1383 /*
1384 * Compute the width of a scanline and allocate input/output buffers...
1385 */
1386
1387 srcbytes = gdev_prn_raster(pdev);
1388
1389 #ifdef DEBUG
1390 fprintf(stderr, "DEBUG: cupsBitsPerPixel = %d, cupsWidth = %d, cupsBytesPerLine = %d, srcbytes = %d\n",
1391 cups->header.cupsBitsPerPixel, cups->header.cupsWidth,
1392 cups->header.cupsBytesPerLine, srcbytes);
1393 #endif /* DEBUG */
1394
1395 src = (unsigned char *)gs_malloc(srcbytes, 1, "cups_print_pages");
1396
1397 if (src == NULL) /* can't allocate input buffer */
1398 return_error(gs_error_VMerror);
1399
1400 /*
1401 * Need an output buffer, too...
1402 */
1403
1404 dst = (unsigned char *)gs_malloc(cups->header.cupsBytesPerLine, 2,
1405 "cups_print_pages");
1406
1407 if (dst == NULL) /* can't allocate working area */
1408 return_error(gs_error_VMerror);
1409
1410 /*
1411 * See if the stream has been initialized yet...
1412 */
1413
1414 if (cups->stream == NULL)
1415 {
1416 if ((cups->stream = cupsRasterOpen(1, CUPS_RASTER_WRITE)) == NULL)
1417 {
1418 perror("ERROR: Unable to open raster stream - ");
1419 gs_exit(0);
1420 }
1421 }
1422
1423 /*
1424 * Output a page of graphics...
1425 */
1426
1427 if (num_copies < 1)
1428 num_copies = 1;
1429
1430 if (cups->ppd != NULL && !cups->ppd->manual_copies)
1431 {
1432 cups->header.NumCopies = num_copies;
1433 num_copies = 1;
1434 }
1435
1436 #ifdef DEBUG
1437 fprintf(stderr, "DEBUG: cupsWidth = %d, cupsHeight = %d, cupsBytesPerLine = %d\n",
1438 cups->header.cupsWidth, cups->header.cupsHeight,
1439 cups->header.cupsBytesPerLine);
1440 #endif /* DEBUG */
1441
1442 for (copy = num_copies; copy > 0; copy --)
1443 {
1444 cupsRasterWriteHeader(cups->stream, &(cups->header));
1445
1446 if (pdev->color_info.num_components == 1)
1447 cups_print_chunked(pdev, src, dst, srcbytes);
1448 else
1449 switch (cups->header.cupsColorOrder)
1450 {
1451 case CUPS_ORDER_CHUNKED :
1452 cups_print_chunked(pdev, src, dst, srcbytes);
1453 break;
1454 case CUPS_ORDER_BANDED :
1455 cups_print_banded(pdev, src, dst, srcbytes);
1456 break;
1457 case CUPS_ORDER_PLANAR :
1458 cups_print_planar(pdev, src, dst, srcbytes);
1459 break;
1460 }
1461 }
1462
1463 /*
1464 * Free temporary storage and return...
1465 */
1466
1467 gs_free((char *)src, srcbytes, 1, "cups_print_pages");
1468 gs_free((char *)dst, cups->header.cupsBytesPerLine, 1, "cups_print_pages");
1469
1470 cups->page ++;
1471 fprintf(stderr, "INFO: Processing page %d...\n", cups->page);
1472
1473 return (0);
1474 }
1475
1476
1477 /*
1478 * 'cups_put_params()' - Set pagedevice parameters.
1479 */
1480
1481 private int /* O - Error status */
1482 cups_put_params(gx_device *pdev, /* I - Device info */
1483 gs_param_list *plist) /* I - Parameter list */
1484 {
1485 int i; /* Looping var */
1486 float margins[4]; /* Physical margins of print */
1487 ppd_size_t *size; /* Page size */
1488 int code; /* Error code */
1489 int intval; /* Integer value */
1490 bool boolval; /* Boolean value */
1491 float floatval; /* Floating point value */
1492 gs_param_string stringval; /* String value */
1493 gs_param_float_array arrayval; /* Float array value */
1494 int old_depth; /* Old color depth */
1495 int size_set; /* Was the size set? */
1496 gdev_prn_space_params sp; /* Space parameter data */
1497
1498
1499 #ifdef DEBUG
1500 fprintf(stderr, "DEBUG: cups_put_params(%p, %p)\n", pdev, plist);
1501 #endif /* DEBUG */
1502
1503 /*
1504 * Process other options for CUPS...
1505 */
1506
1507 #define stringoption(name, sname) \
1508 if ((code = param_read_string(plist, sname, &stringval)) < 0) \
1509 { \
1510 param_signal_error(plist, sname, code); \
1511 return (code); \
1512 } \
1513 else if (code == 0) \
1514 { \
1515 strncpy(cups->header.name, (const char *)stringval.data, \
1516 stringval.size); \
1517 cups->header.name[stringval.size] = '\0'; \
1518 }
1519
1520 #define intoption(name, sname, type) \
1521 if ((code = param_read_int(plist, sname, &intval)) < 0) \
1522 { \
1523 param_signal_error(plist, sname, code); \
1524 return (code); \
1525 } \
1526 else if (code == 0) \
1527 { \
1528 fprintf(stderr, "DEBUG: Setting %s to %d...\n", sname, intval); \
1529 cups->header.name = (type)intval; \
1530 }
1531
1532 #define floatoption(name, sname) \
1533 if ((code = param_read_float(plist, sname, &floatval)) < 0) \
1534 { \
1535 param_signal_error(plist, sname, code); \
1536 return (code); \
1537 } \
1538 else if (code == 0) \
1539 cups->header.name = (unsigned)floatval;
1540
1541 #define booloption(name, sname) \
1542 if ((code = param_read_bool(plist, sname, &boolval)) < 0) \
1543 { \
1544 if ((code = param_read_null(plist, sname)) < 0) \
1545 { \
1546 param_signal_error(plist, sname, code); \
1547 return (code); \
1548 } \
1549 if (code == 0) \
1550 cups->header.name = CUPS_FALSE; \
1551 } \
1552 else if (code == 0) \
1553 cups->header.name = (cups_bool_t)boolval;
1554
1555 #define arrayoption(name, sname, count) \
1556 if ((code = param_read_float_array(plist, sname, &arrayval)) < 0) \
1557 { \
1558 if ((code = param_read_null(plist, sname)) < 0) \
1559 { \
1560 param_signal_error(plist, sname, code); \
1561 return (code); \
1562 } \
1563 if (code == 0) \
1564 for (i = 0; i < count; i ++) \
1565 cups->header.name[i] = 0; \
1566 } \
1567 else if (code == 0) \
1568 { \
1569 for (i = 0; i < count; i ++) \
1570 cups->header.name[i] = (unsigned)arrayval.data[i]; \
1571 }
1572
1573 old_depth = pdev->color_info.depth;
1574 size_set = param_read_float_array(plist, "PageSize", &arrayval) == 0;
1575
1576 stringoption(MediaClass, "MediaClass")
1577 stringoption(MediaColor, "MediaColor")
1578 stringoption(MediaType, "MediaType")
1579 stringoption(OutputType, "OutputType")
1580 floatoption(AdvanceDistance, "AdvanceDistance")
1581 intoption(AdvanceMedia, "AdvanceMedia", cups_adv_t)
1582 booloption(Collate, "Collate")
1583 intoption(CutMedia, "CutMedia", cups_cut_t)
1584 booloption(Duplex, "Duplex")
1585 arrayoption(ImagingBoundingBox, "ImagingBoundingBox", 4)
1586 booloption(InsertSheet, "InsertSheet")
1587 intoption(Jog, "Jog", cups_jog_t)
1588 intoption(LeadingEdge, "LeadingEdge", cups_edge_t)
1589 arrayoption(Margins, "Margins", 2)
1590 booloption(ManualFeed, "ManualFeed")
1591 intoption(MediaPosition, "cupsMediaPosition", unsigned) /* Compatibility */
1592 intoption(MediaPosition, "MediaPosition", unsigned)
1593 floatoption(MediaWeight, "MediaWeight")
1594 booloption(MirrorPrint, "MirrorPrint")
1595 booloption(NegativePrint, "NegativePrint")
1596 intoption(NumCopies, "NumCopies", unsigned)
1597 intoption(Orientation, "Orientation", cups_orient_t)
1598 booloption(OutputFaceUp, "OutputFaceUp")
1599 booloption(Separations, "Separations")
1600 booloption(TraySwitch, "TraySwitch")
1601 booloption(Tumble, "Tumble")
1602 intoption(cupsMediaType, "cupsMediaType", unsigned)
1603 intoption(cupsBitsPerColor, "cupsBitsPerColor", unsigned)
1604 intoption(cupsColorOrder, "cupsColorOrder", cups_order_t)
1605 intoption(cupsColorSpace, "cupsColorSpace", cups_cspace_t)
1606 intoption(cupsCompression, "cupsCompression", unsigned)
1607 intoption(cupsRowCount, "cupsRowCount", unsigned)
1608 intoption(cupsRowFeed, "cupsRowFeed", unsigned)
1609 intoption(cupsRowStep, "cupsRowStep", unsigned)
1610
1611 cups_set_color_info(pdev);
1612
1613 /*
1614 * Compute the page margins...
1615 */
1616
1617 if (cups->ppd != NULL)
1618 {
1619 /*
1620 * Pull the margins from the first size entry; since the margins are not
1621 * like the bounding box we have to adjust the top and right values
1622 * accordingly.
1623 */
1624
1625 for (i = cups->ppd->num_sizes, size = cups->ppd->sizes;
1626 i > 0;
1627 i --, size ++)
1628 if ((fabs(cups->PageSize[1] - size->length) < 18.0 &&
1629 fabs(cups->PageSize[0] - size->width) < 18.0) ||
1630 (fabs(cups->PageSize[0] - size->length) < 18.0 &&
1631 fabs(cups->PageSize[1] - size->width) < 18.0))
1632 break;
1633
1634 if (i == 0 && !cups->ppd->variable_sizes)
1635 {
1636 i = 1;
1637 size = cups->ppd->sizes;
1638 }
1639
1640 if (i > 0)
1641 {
1642 /*
1643 * Standard size...
1644 */
1645
1646 fprintf(stderr, "DEBUG: size = %s\n", size->name);
1647
1648 margins[0] = size->left / 72.0;
1649 margins[1] = size->bottom / 72.0;
1650 margins[2] = (size->width - size->right) / 72.0;
1651 margins[3] = (size->length - size->top) / 72.0;
1652 }
1653 else
1654 {
1655 /*
1656 * Custom size...
1657 */
1658
1659 fputs("DEBUG: size = Custom\n", stderr);
1660
1661 for (i = 0; i < 4; i ++)
1662 margins[i] = cups->ppd->custom_margins[i] / 72.0;
1663 }
1664
1665 fprintf(stderr, "DEBUG: margins[] = [ %f %f %f %f ]\n",
1666 margins[0], margins[1], margins[2], margins[3]);
1667 }
1668 else
1669 {
1670 /*
1671 * Set default margins of 0.0...
1672 */
1673
1674 memset(margins, 0, sizeof(margins));
1675 }
1676
1677 /*
1678 * Set the margins to update the bitmap size...
1679 */
1680
1681 gx_device_set_margins(pdev, margins, false);
1682
1683 /*
1684 * Then process standard page device options...
1685 */
1686
1687 if ((code = gdev_prn_put_params(pdev, plist)) < 0)
1688 return (code);
1689
1690 cups->header.HWResolution[0] = pdev->HWResolution[0];
1691 cups->header.HWResolution[1] = pdev->HWResolution[1];
1692
1693 cups->header.PageSize[0] = pdev->PageSize[0];
1694 cups->header.PageSize[1] = pdev->PageSize[1];
1695
1696 /*
1697 * Reallocate memory if the size or color depth was changed...
1698 */
1699
1700 if (old_depth != pdev->color_info.depth || size_set)
1701 {
1702 fputs("DEBUG: Reallocating memory...\n", stderr);
1703 sp = ((gx_device_printer *)pdev)->space_params;
1704
1705 if ((code = gdev_prn_reallocate_memory(pdev, &sp, pdev->width,
1706 pdev->height)) < 0)
1707 return (code);
1708 }
1709
1710 #ifdef DEBUG
1711 fprintf(stderr, "DEBUG: ppd = %8x\n", cups->ppd);
1712 fprintf(stderr, "DEBUG: PageSize = [ %.3f %.3f ]\n",
1713 pdev->PageSize[0], pdev->PageSize[1]);
1714 fprintf(stderr, "DEBUG: margins = [ %.3f %.3f %.3f %.3f ]\n",
1715 margins[0], margins[1], margins[2], margins[3]);
1716 fprintf(stderr, "DEBUG: HWResolution = [ %.3f %.3f ]\n",
1717 pdev->HWResolution[0], pdev->HWResolution[1]);
1718 fprintf(stderr, "DEBUG: width = %d, height = %d\n",
1719 pdev->width, pdev->height);
1720 fprintf(stderr, "DEBUG: HWMargins = [ %.3f %.3f %.3f %.3f ]\n",
1721 pdev->HWMargins[0], pdev->HWMargins[1],
1722 pdev->HWMargins[2], pdev->HWMargins[3]);
1723 #endif /* DEBUG */
1724
1725 return (0);
1726 }
1727
1728
1729 /*
1730 * 'cups_set_color_info()' - Set the color information structure based on
1731 * the required output.
1732 */
1733
1734 private void
1735 cups_set_color_info(gx_device *pdev) /* I - Device info */
1736 {
1737 int i, j, k; /* Looping vars */
1738 float d, g; /* Density and gamma correction */
1739 float m[3][3]; /* Color correction matrix */
1740 char resolution[41]; /* Resolution string */
1741 ppd_profile_t *profile; /* Color profile information */
1742
1743
1744 #ifdef DEBUG
1745 fprintf(stderr, "DEBUG: cups_set_color_info(%p)\n", pdev);
1746 #endif /* DEBUG */
1747
1748 switch (cups->header.cupsColorSpace)
1749 {
1750 default :
1751 case CUPS_CSPACE_W :
1752 case CUPS_CSPACE_K :
1753 case CUPS_CSPACE_WHITE :
1754 case CUPS_CSPACE_GOLD :
1755 case CUPS_CSPACE_SILVER :
1756 cups->header.cupsBitsPerPixel = cups->header.cupsBitsPerColor;
1757 cups->color_info.depth = cups->header.cupsBitsPerPixel;
1758 cups->color_info.num_components = 1;
1759 break;
1760
1761 case CUPS_CSPACE_CMY :
1762 case CUPS_CSPACE_YMC :
1763 case CUPS_CSPACE_RGB :
1764 if (cups->header.cupsColorOrder != CUPS_ORDER_CHUNKED)
1765 cups->header.cupsBitsPerPixel = cups->header.cupsBitsPerColor;
1766 else if (cups->header.cupsBitsPerColor < 8)
1767 cups->header.cupsBitsPerPixel = 4 * cups->header.cupsBitsPerColor;
1768 else
1769 cups->header.cupsBitsPerPixel = 3 * cups->header.cupsBitsPerColor;
1770
1771 if (cups->header.cupsBitsPerColor < 8)
1772 cups->color_info.depth = 4 * cups->header.cupsBitsPerColor;
1773 else
1774 cups->color_info.depth = 3 * cups->header.cupsBitsPerColor;
1775
1776 cups->color_info.num_components = 3;
1777 break;
1778
1779 case CUPS_CSPACE_KCMYcm :
1780 if (cups->header.cupsBitsPerColor == 1)
1781 {
1782 cups->header.cupsBitsPerPixel = 8;
1783 cups->color_info.depth = 8;
1784 cups->color_info.num_components = 4;
1785 break;
1786 }
1787
1788 case CUPS_CSPACE_CMYK :
1789 case CUPS_CSPACE_YMCK :
1790 case CUPS_CSPACE_KCMY :
1791 case CUPS_CSPACE_GMCK :
1792 case CUPS_CSPACE_GMCS :
1793 if (cups->header.cupsColorOrder != CUPS_ORDER_CHUNKED)
1794 cups->header.cupsBitsPerPixel = cups->header.cupsBitsPerColor;
1795 else
1796 cups->header.cupsBitsPerPixel = 4 * cups->header.cupsBitsPerColor;
1797
1798 cups->color_info.depth = 4 * cups->header.cupsBitsPerColor;
1799 cups->color_info.num_components = 4;
1800 break;
1801 }
1802
1803 if (cups->color_info.num_components > 1)
1804 {
1805 cups->color_info.max_gray = (1 << cups->header.cupsBitsPerColor) - 1;
1806 cups->color_info.max_color = (1 << cups->header.cupsBitsPerColor) - 1;
1807 cups->color_info.dither_grays = (1 << cups->header.cupsBitsPerColor);
1808 cups->color_info.dither_colors = (1 << cups->header.cupsBitsPerColor);
1809 }
1810 else
1811 {
1812 cups->color_info.max_gray = (1 << cups->header.cupsBitsPerColor) - 1;
1813 cups->color_info.max_color = 0;
1814 cups->color_info.dither_grays = (1 << cups->header.cupsBitsPerColor);
1815 cups->color_info.dither_colors = 0;
1816 }
1817
1818 /*
1819 * Enable/disable CMYK color support...
1820 */
1821
1822 if (cups->color_info.num_components == 4)
1823 cups->procs.map_cmyk_color = cups_map_cmyk_color;
1824 else
1825 cups->procs.map_cmyk_color = NULL;
1826
1827 /*
1828 * Compute the lookup tables...
1829 */
1830
1831 for (i = 0; i <= gx_max_color_value; i ++)
1832 lut_rgb_color[i] = cups->color_info.max_gray * i / gx_max_color_value;
1833
1834 for (i = 0; i < cups->color_info.dither_grays; i ++)
1835 lut_color_rgb[i] = gx_max_color_value * i / cups->color_info.max_gray;
1836
1837 #ifdef DEBUG
1838 fprintf(stderr, "DEBUG: num_components = %d, depth = %d\n",
1839 cups->color_info.num_components, cups->color_info.depth);
1840 fprintf(stderr, "DEBUG: cupsColorSpace = %d, cupsColorOrder = %d\n",
1841 cups->header.cupsColorSpace, cups->header.cupsColorOrder);
1842 fprintf(stderr, "DEBUG: cupsBitsPerPixel = %d, cupsBitsPerColor = %d\n",
1843 cups->header.cupsBitsPerPixel, cups->header.cupsBitsPerColor);
1844 fprintf(stderr, "DEBUG: max_gray = %d, dither_grays = %d\n",
1845 cups->color_info.max_gray, cups->color_info.dither_grays);
1846 fprintf(stderr, "DEBUG: max_color = %d, dither_colors = %d\n",
1847 cups->color_info.max_color, cups->color_info.dither_colors);
1848 #endif /* DEBUG */
1849
1850 /*
1851 * Set the color profile as needed...
1852 */
1853
1854 cupsHaveProfile = 0;
1855
1856 if (cupsProfile && cups->header.cupsBitsPerColor == 8)
1857 {
1858 fprintf(stderr, "DEBUG: Using user-defined profile \"%s\"...\n", cupsProfile);
1859
1860 if (sscanf(cupsProfile, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f", &d, &g,
1861 m[0] + 0, m[0] + 1, m[0] + 2,
1862 m[1] + 0, m[1] + 1, m[1] + 2,
1863 m[2] + 0, m[2] + 1, m[2] + 2) != 11)
1864 fputs("DEBUG: User-defined profile does not contain 11 integers!\n", stderr);
1865 else
1866 {
1867 cupsHaveProfile = 1;
1868
1869 d *= 0.001f;
1870 g *= 0.001f;
1871 m[0][0] *= 0.001f;
1872 m[0][1] *= 0.001f;
1873 m[0][2] *= 0.001f;
1874 m[1][0] *= 0.001f;
1875 m[1][1] *= 0.001f;
1876 m[1][2] *= 0.001f;
1877 m[2][0] *= 0.001f;
1878 m[2][1] *= 0.001f;
1879 m[2][2] *= 0.001f;
1880 }
1881 }
1882 else if (cups->ppd != NULL && cups->header.cupsBitsPerColor == 8)
1883 {
1884 /*
1885 * Find the appropriate color profile...
1886 */
1887
1888 if (pdev->HWResolution[0] != pdev->HWResolution[1])
1889 sprintf(resolution, "%.0fx%.0fdpi", pdev->HWResolution[0],
1890 pdev->HWResolution[1]);
1891 else
1892 sprintf(resolution, "%.0fdpi", pdev->HWResolution[0]);
1893
1894 for (i = 0, profile = cups->ppd->profiles;
1895 i < cups->ppd->num_profiles;
1896 i ++, profile ++)
1897 if ((strcmp(profile->resolution, resolution) == 0 ||
1898 profile->resolution[0] == '-') &&
1899 (strcmp(profile->media_type, cups->header.MediaType) == 0 ||
1900 profile->media_type[0] == '-'))
1901 break;
1902
1903 /*
1904 * If we found a color profile, use it!
1905 */
1906
1907 if (i < cups->ppd->num_profiles)
1908 {
1909 #ifdef DEBUG
1910 fputs("DEBUG: Using color profile!\n", stderr);
1911 #endif /* DEBUG */
1912
1913 cupsHaveProfile = 1;
1914
1915 d = profile->density;
1916 g = profile->gamma;
1917
1918 memcpy(m, profile->matrix, sizeof(m));
1919 }
1920 }
1921
1922 if (cupsHaveProfile)
1923 {
1924 for (i = 0; i < 3; i ++)
1925 for (j = 0; j < 3; j ++)
1926 for (k = 0; k <= gx_max_color_value; k ++)
1927 {
1928 cupsMatrix[i][j][k] = (int)((float)k * m[i][j] + 0.5);
1929
1930 #ifdef DEBUG
1931 if ((k & 4095) == 0)
1932 fprintf(stderr, "DEBUG: cupsMatrix[%d][%d][%d] = %d\n",
1933 i, j, k, cupsMatrix[i][j][k]);
1934 #endif /* DEBUG */
1935 }
1936
1937
1938 for (k = 0; k <= gx_max_color_value; k ++)
1939 {
1940 cupsDensity[k] = (int)((float)gx_max_color_value * d *
1941 pow((float)k / (float)gx_max_color_value, g) +
1942 0.5);
1943
1944 #ifdef DEBUG
1945 if ((k & 4095) == 0)
1946 fprintf(stderr, "DEBUG: cupsDensity[%d] = %d\n", k, cupsDensity[k]);
1947 #endif /* DEBUG */
1948 }
1949 }
1950 }
1951
1952
1953 /*
1954 * 'cups_sync_output()' - Keep the user informed of our status...
1955 */
1956
1957 private int /* O - Error status */
1958 cups_sync_output(gx_device *pdev) /* I - Device info */
1959 {
1960 fprintf(stderr, "INFO: Processing page %d...\n", cups->page);
1961
1962 return (0);
1963 }
1964
1965
1966 /*
1967 * 'cups_print_chunked()' - Print a page of chunked pixels.
1968 */
1969
1970 static void
1971 cups_print_chunked(gx_device_printer *pdev, /* I - Printer device */
1972 unsigned char *src, /* I - Scanline buffer */
1973 unsigned char *dst, /* I - Bitmap buffer */
1974 int srcbytes) /* I - Number of bytes in src */
1975 {
1976 int y; /* Looping var */
1977 unsigned char *srcptr, /* Pointer to data */
1978 *dstptr; /* Pointer to bits */
1979 int count; /* Count for loop */
1980 int flip; /* Flip scanline? */
1981
1982
1983 if (cups->header.Duplex && !cups->header.Tumble &&
1984 cups->ppd && cups->ppd->flip_duplex && !(cups->page & 1))
1985 flip = 1;
1986 else
1987 flip = 0;
1988
1989 fprintf(stderr, "DEBUG: cups_print_chunked - flip = %d\n", flip);
1990
1991 /*
1992 * Loop through the page bitmap and write chunked pixels, reversing as
1993 * needed...
1994 */
1995
1996 for (y = 0; y < cups->height; y ++)
1997 {
1998 /*
1999 * Grab the scanline data...
2000 */
2001
2002 if (gdev_prn_get_bits((gx_device_printer *)pdev, y, src, &srcptr) < 0)
2003 {
2004 fprintf(stderr, "ERROR: Unable to get scanline %d!\n", y);
2005 gs_exit(1);
2006 }
2007
2008 if (flip)
2009 {
2010 /*
2011 * Flip the raster data before writing it...
2012 */
2013
2014 if (srcptr[0] == 0 && memcmp(srcptr, srcptr + 1, srcbytes - 1) == 0)
2015 memset(dst, 0, cups->header.cupsBytesPerLine);
2016 else
2017 {
2018 dstptr = dst;
2019 count = srcbytes;
2020
2021 switch (cups->color_info.depth)
2022 {
2023 case 1 : /* B&W bitmap */
2024 for (srcptr += srcbytes - 1;
2025 count > 0;
2026 count --, srcptr --, dstptr ++)
2027 {
2028 *dstptr = rev_upper1[*srcptr & 15] |
2029 rev_lower1[*srcptr >> 4];
2030 }
2031 break;
2032
2033 case 2 : /* 2-bit grayscale */
2034 for (srcptr += srcbytes - 1;
2035 count > 0;
2036 count --, srcptr --, dstptr ++)
2037 {
2038 *dstptr = rev_upper2[*srcptr & 15] |
2039 rev_lower2[*srcptr >> 4];
2040 }
2041 break;
2042
2043 case 4 : /* 4-bit grayscale, or RGB, CMY, or CMYK bitmap */
2044 for (srcptr += srcbytes - 1;
2045 count > 0;
2046 count --, srcptr --, dstptr ++)
2047 *dstptr = (*srcptr >> 4) | (*srcptr << 4);
2048 break;
2049
2050 case 8 : /* 8-bit grayscale, or 2-bit RGB, CMY, or CMYK image */
2051 for (srcptr += srcbytes - 1;
2052 count > 0;
2053 count --, srcptr --, dstptr ++)
2054 *dstptr = *srcptr;
2055 break;
2056
2057 case 16 : /* 4-bit RGB, CMY or CMYK image */
2058 for (srcptr += srcbytes - 2;
2059 count > 0;
2060 count -= 2, srcptr -= 2, dstptr += 2)
2061 {
2062 dstptr[0] = srcptr[0];
2063 dstptr[1] = srcptr[1];
2064 }
2065 break;
2066
2067 case 24 : /* 8-bit RGB or CMY image */
2068 for (srcptr += srcbytes - 3;
2069 count > 0;
2070 count -= 3, srcptr -= 3, dstptr += 3)
2071 {
2072 dstptr[0] = srcptr[0];
2073 dstptr[1] = srcptr[1];
2074 dstptr[2] = srcptr[2];
2075 }
2076 break;
2077
2078 case 32 : /* 4-bit RGB, CMY or CMYK bitmap */
2079 for (srcptr += srcbytes - 4;
2080 count > 0;
2081 count -= 4, srcptr -= 4, dstptr += 4)
2082 {
2083 dstptr[0] = srcptr[0];
2084 dstptr[1] = srcptr[1];
2085 dstptr[2] = srcptr[2];
2086 dstptr[3] = srcptr[3];
2087 }
2088 break;
2089 }
2090 }
2091
2092 /*
2093 * Write the bitmap data to the raster stream...
2094 */
2095
2096 cupsRasterWritePixels(cups->stream, dst, cups->header.cupsBytesPerLine);
2097 }
2098 else
2099 {
2100 /*
2101 * Write the scanline data to the raster stream...
2102 */
2103
2104 cupsRasterWritePixels(cups->stream, srcptr, cups->header.cupsBytesPerLine);
2105 }
2106 }
2107 }
2108
2109
2110 /*
2111 * 'cups_print_banded()' - Print a page of banded pixels.
2112 */
2113
2114 static void
2115 cups_print_banded(gx_device_printer *pdev, /* I - Printer device */
2116 unsigned char *src, /* I - Scanline buffer */
2117 unsigned char *dst, /* I - Bitmap buffer */
2118 int srcbytes) /* I - Number of bytes in src */
2119 {
2120 int x; /* Looping var */
2121 int y; /* Looping var */
2122 int bandbytes; /* Bytes per band */
2123 unsigned char bit; /* Current bit */
2124 unsigned char temp; /* Temporary variable */
2125 unsigned char *srcptr; /* Pointer to data */
2126 unsigned char *cptr, *mptr, *yptr, *kptr; /* Pointer to components */
2127 unsigned char *lcptr, *lmptr; /* ... */
2128 int flip; /* Flip scanline? */
2129
2130
2131 if (cups->header.Duplex && !cups->header.Tumble &&
2132 cups->ppd && cups->ppd->flip_duplex && !(cups->page & 1))
2133 flip = 1;
2134 else
2135 flip = 0;
2136
2137 fprintf(stderr, "DEBUG: cups_print_banded - flip = %d\n", flip);
2138
2139 /*
2140 * Loop through the page bitmap and write banded pixels... We have
2141 * to separate each chunked color as needed...
2142 */
2143
2144 bandbytes = (cups->header.cupsWidth * cups->header.cupsBitsPerColor + 7) / 8;
2145
2146 for (y = 0; y < cups->height; y ++)
2147 {
2148 /*
2149 * Grab the scanline data...
2150 */
2151
2152 if (gdev_prn_get_bits((gx_device_printer *)pdev, y, src, &srcptr) < 0)
2153 {
2154 fprintf(stderr, "ERROR: Unable to get scanline %d!\n", y);
2155 gs_exit(1);
2156 }
2157
2158 /*
2159 * Separate the chunked colors into their components...
2160 */
2161
2162 if (srcptr[0] == 0 && memcmp(srcptr, srcptr + 1, srcbytes - 1) == 0)
2163 memset(dst, 0, cups->header.cupsBytesPerLine);
2164 else
2165 {
2166 if (flip)
2167 cptr = dst + bandbytes - 1;
2168 else
2169 cptr = dst;
2170
2171 mptr = cptr + bandbytes;
2172 yptr = mptr + bandbytes;
2173 kptr = yptr + bandbytes;
2174 lcptr = yptr + bandbytes;
2175 lmptr = lcptr + bandbytes;
2176
2177 switch (cups->header.cupsBitsPerColor)
2178 {
2179 default :
2180 memset(dst, 0, cups->header.cupsBytesPerLine);
2181
2182 switch (cups->header.cupsColorSpace)
2183 {
2184 default :
2185 for (x = cups->width, bit = flip ? 1 << (x & 7) : 128;
2186 x > 0;
2187 x --, srcptr ++)
2188 {
2189 if (*srcptr & 0x40)
2190 *cptr |= bit;
2191 if (*srcptr & 0x20)
2192 *mptr |= bit;
2193 if (*srcptr & 0x10)
2194 *yptr |= bit;
2195
2196 if (flip)
2197 {
2198 if (bit < 128)
2199 bit <<= 1;
2200 else
2201 {
2202 cptr --;
2203 mptr --;
2204 yptr --;
2205 bit = 1;
2206 }
2207 }
2208 else
2209 bit >>= 1;
2210
2211 x --;
2212 if (x == 0)
2213 break;
2214
2215 if (*srcptr & 0x4)
2216 *cptr |= bit;
2217 if (*srcptr & 0x2)
2218 *mptr |= bit;
2219 if (*srcptr & 0x1)
2220 *yptr |= bit;
2221
2222 if (flip)
2223 {
2224 if (bit < 128)
2225 bit <<= 1;
2226 else
2227 {
2228 cptr --;
2229 mptr --;
2230 yptr --;
2231 bit = 1;
2232 }
2233 }
2234 else if (bit > 1)
2235 bit >>= 1;
2236 else
2237 {
2238 cptr ++;
2239 mptr ++;
2240 yptr ++;
2241 bit = 128;
2242 }
2243 }
2244 break;
2245 case CUPS_CSPACE_GMCK :
2246 case CUPS_CSPACE_GMCS :
2247 case CUPS_CSPACE_RGBA :
2248 case CUPS_CSPACE_CMYK :
2249 case CUPS_CSPACE_YMCK :
2250 case CUPS_CSPACE_KCMY :
2251 for (x = cups->width, bit = flip ? 1 << (x & 7) : 128;
2252 x > 0;
2253 x --, srcptr ++)
2254 {
2255 if (*srcptr & 0x80)
2256 *cptr |= bit;
2257 if (*srcptr & 0x40)
2258 *mptr |= bit;
2259 if (*srcptr & 0x20)
2260 *yptr |= bit;
2261 if (*srcptr & 0x10)
2262 *kptr |= bit;
2263
2264 if (flip)
2265 {
2266 if (bit < 128)
2267 bit <<= 1;
2268 else
2269 {
2270 cptr --;
2271 mptr --;
2272 yptr --;
2273 kptr --;
2274 bit = 1;
2275 }
2276 }
2277 else
2278 bit >>= 1;
2279
2280 x --;
2281 if (x == 0)
2282 break;
2283
2284 if (*srcptr & 0x8)
2285 *cptr |= bit;
2286 if (*srcptr & 0x4)
2287 *mptr |= bit;
2288 if (*srcptr & 0x2)
2289 *yptr |= bit;
2290 if (*srcptr & 0x1)
2291 *kptr |= bit;
2292
2293 if (flip)
2294 {
2295 if (bit < 128)
2296 bit <<= 1;
2297 else
2298 {
2299 cptr --;
2300 mptr --;
2301 yptr --;
2302 kptr --;
2303 bit = 1;
2304 }
2305 }
2306 else if (bit > 1)
2307 bit >>= 1;
2308 else
2309 {
2310 cptr ++;
2311 mptr ++;
2312 yptr ++;
2313 kptr ++;
2314 bit = 128;
2315 }
2316 }
2317 break;
2318 case CUPS_CSPACE_KCMYcm :
2319 for (x = cups->width, bit = flip ? 1 << (x & 7) : 128;
2320 x > 0;
2321 x --, srcptr ++)
2322 {
2323 /*
2324 * Note: Because of the way the pointers are setup,
2325 * the following code is correct even though
2326 * the names don't match...
2327 */
2328
2329 if (*srcptr & 0x20)
2330 *cptr |= bit;
2331 if (*srcptr & 0x10)
2332 *mptr |= bit;
2333 if (*srcptr & 0x08)
2334 *yptr |= bit;
2335 if (*srcptr & 0x04)
2336 *kptr |= bit;
2337 if (*srcptr & 0x02)
2338 *lcptr |= bit;
2339 if (*srcptr & 0x01)
2340 *lmptr |= bit;
2341
2342 if (flip)
2343 {
2344 if (bit < 128)
2345 bit <<= 1;
2346 else
2347 {
2348 cptr --;
2349 mptr --;
2350 yptr --;
2351 kptr --;
2352 lcptr --;
2353 lmptr --;
2354 bit = 1;
2355 }
2356 }
2357 else if (bit > 1)
2358 bit >>= 1;
2359 else
2360 {
2361 cptr ++;
2362 mptr ++;
2363 yptr ++;
2364 kptr ++;
2365 lcptr ++;
2366 lmptr ++;
2367 bit = 128;
2368 }
2369 }
2370 break;
2371 }
2372 break;
2373
2374 case 2 :
2375 memset(dst, 0, cups->header.cupsBytesPerLine);
2376
2377 switch (cups->header.cupsColorSpace)
2378 {
2379 default :
2380 for (x = cups->width, bit = flip ? 3 << (2 * (x & 3)) : 0xc0;
2381 x > 0;
2382 x --, srcptr ++)
2383 switch (bit)
2384 {
2385 case 0xc0 :
2386 if ((temp = *srcptr & 0x30) != 0)
2387 *cptr |= temp << 2;
2388 if ((temp = *srcptr & 0x0c) != 0)
2389 *mptr |= temp << 4;
2390 if ((temp = *srcptr & 0x03) != 0)
2391 *yptr |= temp << 6;
2392
2393 if (flip)
2394 {
2395 bit = 0x03;
2396 cptr --;
2397 mptr --;
2398 yptr --;
2399 }
2400 else
2401 bit = 0x30;
2402 break;
2403 case 0x30 :
2404 if ((temp = *srcptr & 0x30) != 0)
2405 *cptr |= temp;
2406 if ((temp = *srcptr & 0x0c) != 0)
2407 *mptr |= temp << 2;
2408 if ((temp = *srcptr & 0x03) != 0)
2409 *yptr |= temp << 4;
2410
2411 if (flip)
2412 bit = 0xc0;
2413 else
2414 bit = 0x0c;
2415 break;
2416 case 0x0c :
2417 if ((temp = *srcptr & 0x30) != 0)
2418 *cptr |= temp >> 2;
2419 if ((temp = *srcptr & 0x0c) != 0)
2420 *mptr |= temp;
2421 if ((temp = *srcptr & 0x03) != 0)
2422 *yptr |= temp << 2;
2423
2424 if (flip)
2425 bit = 0x30;
2426 else
2427 bit = 0x03;
2428 break;
2429 case 0x03 :
2430 if ((temp = *srcptr & 0x30) != 0)
2431 *cptr |= temp >> 4;
2432 if ((temp = *srcptr & 0x0c) != 0)
2433 *mptr |= temp >> 2;
2434 if ((temp = *srcptr & 0x03) != 0)
2435 *yptr |= temp;
2436
2437 if (flip)
2438 bit = 0x0c;
2439 else
2440 {
2441 bit = 0xc0;
2442 cptr ++;
2443 mptr ++;
2444 yptr ++;
2445 }
2446 break;
2447 }
2448 break;
2449 case CUPS_CSPACE_GMCK :
2450 case CUPS_CSPACE_GMCS :
2451 case CUPS_CSPACE_RGBA :
2452 case CUPS_CSPACE_CMYK :
2453 case CUPS_CSPACE_YMCK :
2454 case CUPS_CSPACE_KCMY :
2455 case CUPS_CSPACE_KCMYcm :
2456 for (x = cups->width, bit = flip ? 3 << (2 * (x & 3)) : 0xc0;
2457 x > 0;
2458 x --, srcptr ++)
2459 switch (bit)
2460 {
2461 case 0xc0 :
2462 if ((temp = *srcptr & 0xc0) != 0)
2463 *cptr |= temp;
2464 if ((temp = *srcptr & 0x30) != 0)
2465 *mptr |= temp << 2;
2466 if ((temp = *srcptr & 0x0c) != 0)
2467 *yptr |= temp << 4;
2468 if ((temp = *srcptr & 0x03) != 0)
2469 *kptr |= temp << 6;
2470
2471 if (flip)
2472 {
2473 bit = 0x03;
2474 cptr --;
2475 mptr --;
2476 yptr --;
2477 kptr --;
2478 }
2479 else
2480 bit = 0x30;
2481 break;
2482 case 0x30 :
2483 if ((temp = *srcptr & 0xc0) != 0)
2484 *cptr |= temp >> 2;
2485 if ((temp = *srcptr & 0x30) != 0)
2486 *mptr |= temp;
2487 if ((temp = *srcptr & 0x0c) != 0)
2488 *yptr |= temp << 2;
2489 if ((temp = *srcptr & 0x03) != 0)
2490 *kptr |= temp << 4;
2491
2492 if (flip)
2493 bit = 0xc0;
2494 else
2495 bit = 0x0c;
2496 break;
2497 case 0x0c :
2498 if ((temp = *srcptr & 0xc0) != 0)
2499 *cptr |= temp >> 4;
2500 if ((temp = *srcptr & 0x30) != 0)
2501 *mptr |= temp >> 2;
2502 if ((temp = *srcptr & 0x0c) != 0)
2503 *yptr |= temp;
2504 if ((temp = *srcptr & 0x03) != 0)
2505 *kptr |= temp << 2;
2506
2507 if (flip)
2508 bit = 0x30;
2509 else
2510 bit = 0x03;
2511 break;
2512 case 0x03 :
2513 if ((temp = *srcptr & 0xc0) != 0)
2514 *cptr |= temp >> 6;
2515 if ((temp = *srcptr & 0x30) != 0)
2516 *mptr |= temp >> 4;
2517 if ((temp = *srcptr & 0x0c) != 0)
2518 *yptr |= temp >> 2;
2519 if ((temp = *srcptr & 0x03) != 0)
2520 *kptr |= temp;
2521
2522 if (flip)
2523 bit = 0x0c;
2524 else
2525 {
2526 bit = 0xc0;
2527 cptr ++;
2528 mptr ++;
2529 yptr ++;
2530 kptr ++;
2531 }
2532 break;
2533 }
2534 break;
2535 }
2536 break;
2537
2538 case 4 :
2539 memset(dst, 0, cups->header.cupsBytesPerLine);
2540
2541 switch (cups->header.cupsColorSpace)
2542 {
2543 default :
2544 for (x = cups->width, bit = flip && (x & 1) ? 0xf0 : 0x0f;
2545 x > 0;
2546 x --, srcptr += 2)
2547 switch (bit)
2548 {
2549 case 0xf0 :
2550 if ((temp = srcptr[0] & 0x0f) != 0)
2551 *cptr |= temp << 4;
2552 if ((temp = srcptr[1] & 0xf0) != 0)
2553 *mptr |= temp;
2554 if ((temp = srcptr[1] & 0x0f) != 0)
2555 *yptr |= temp << 4;
2556
2557 bit = 0x0f;
2558
2559 if (flip)
2560 {
2561 cptr --;
2562 mptr --;
2563 yptr --;
2564 }
2565 break;
2566 case 0x0f :
2567 if ((temp = srcptr[0] & 0x0f) != 0)
2568 *cptr |= temp;
2569 if ((temp = srcptr[1] & 0xf0) != 0)
2570 *mptr |= temp >> 4;
2571 if ((temp = srcptr[1] & 0x0f) != 0)
2572 *yptr |= temp;
2573
2574 bit = 0xf0;
2575
2576 if (!flip)
2577 {
2578 cptr ++;
2579 mptr ++;
2580 yptr ++;
2581 }
2582 break;
2583 }
2584 break;
2585 case CUPS_CSPACE_GMCK :
2586 case CUPS_CSPACE_GMCS :
2587 case CUPS_CSPACE_RGBA :
2588 case CUPS_CSPACE_CMYK :
2589 case CUPS_CSPACE_YMCK :
2590 case CUPS_CSPACE_KCMY :
2591 case CUPS_CSPACE_KCMYcm :
2592 for (x = cups->width, bit = flip && (x & 1) ? 0xf0 : 0x0f;
2593 x > 0;
2594 x --, srcptr += 2)
2595 switch (bit)
2596 {
2597 case 0xf0 :
2598 if ((temp = srcptr[0] & 0xf0) != 0)
2599 *cptr |= temp;
2600 if ((temp = srcptr[0] & 0x0f) != 0)
2601 *mptr |= temp << 4;
2602 if ((temp = srcptr[1] & 0xf0) != 0)
2603 *yptr |= temp;
2604 if ((temp = srcptr[1] & 0x0f) != 0)
2605 *kptr |= temp << 4;
2606
2607 bit = 0x0f;
2608
2609 if (flip)
2610 {
2611 cptr --;
2612 mptr --;
2613 yptr --;
2614 kptr --;
2615 }
2616 break;
2617 case 0x0f :
2618 if ((temp = srcptr[0] & 0xf0) != 0)
2619 *cptr |= temp >> 4;
2620 if ((temp = srcptr[0] & 0x0f) != 0)
2621 *mptr |= temp;
2622 if ((temp = srcptr[1] & 0xf0) != 0)
2623 *yptr |= temp >> 4;
2624 if ((temp = srcptr[1] & 0x0f) != 0)
2625 *kptr |= temp;
2626
2627 bit = 0xf0;
2628
2629 if (!flip)
2630 {
2631 cptr ++;
2632 mptr ++;
2633 yptr ++;
2634 kptr ++;
2635 }
2636 break;
2637 }
2638 break;
2639 }
2640 break;
2641
2642 case 8 :
2643 switch (cups->header.cupsColorSpace)
2644 {
2645 default :
2646 if (flip)
2647 for (x = cups->width; x > 0; x --)
2648 {
2649 *cptr-- = *srcptr++;
2650 *mptr-- = *srcptr++;
2651 *yptr-- = *srcptr++;
2652 }
2653 else
2654 for (x = cups->width; x > 0; x --)
2655 {
2656 *cptr++ = *srcptr++;
2657 *mptr++ = *srcptr++;
2658 *yptr++ = *srcptr++;
2659 }
2660 break;
2661 case CUPS_CSPACE_GMCK :
2662 case CUPS_CSPACE_GMCS :
2663 case CUPS_CSPACE_RGBA :
2664 case CUPS_CSPACE_CMYK :
2665 case CUPS_CSPACE_YMCK :
2666 case CUPS_CSPACE_KCMY :
2667 case CUPS_CSPACE_KCMYcm :
2668 if (flip)
2669 for (x = cups->width; x > 0; x --)
2670 {
2671 *cptr-- = *srcptr++;
2672 *mptr-- = *srcptr++;
2673 *yptr-- = *srcptr++;
2674 *kptr-- = *srcptr++;
2675 }
2676 else
2677 for (x = cups->width; x > 0; x --)
2678 {
2679 *cptr++ = *srcptr++;
2680 *mptr++ = *srcptr++;
2681 *yptr++ = *srcptr++;
2682 *kptr++ = *srcptr++;
2683 }
2684 break;
2685 }
2686 break;
2687 }
2688 }
2689
2690 /*
2691 * Write the bitmap data to the raster stream...
2692 */
2693
2694 cupsRasterWritePixels(cups->stream, dst, cups->header.cupsBytesPerLine);
2695 }
2696 }
2697
2698
2699 /*
2700 * 'cups_print_planar()' - Print a page of planar pixels.
2701 */
2702
2703 static void
2704 cups_print_planar(gx_device_printer *pdev, /* I - Printer device */
2705 unsigned char *src, /* I - Scanline buffer */
2706 unsigned char *dst, /* I - Bitmap buffer */
2707 int srcbytes) /* I - Number of bytes in src */
2708 {
2709 int x; /* Looping var */
2710 int y; /* Looping var */
2711 int z; /* Looping var */
2712 unsigned char srcbit; /* Current source bit */
2713 unsigned char dstbit; /* Current destination bit */
2714 unsigned char temp; /* Temporary variable */
2715 unsigned char *srcptr; /* Pointer to data */
2716 unsigned char *dstptr; /* Pointer to bitmap */
2717
2718
2719 /**** NOTE: Currently planar output doesn't support flipped duplex!!! ****/
2720
2721 /*
2722 * Loop through the page bitmap and write planar pixels... We have
2723 * to separate each chunked color as needed...
2724 */
2725
2726 for (z = 0; z < pdev->color_info.num_components; z ++)
2727 for (y = 0; y < cups->height; y ++)
2728 {
2729 /*
2730 * Grab the scanline data...
2731 */
2732
2733 if (gdev_prn_get_bits((gx_device_printer *)pdev, y, src, &srcptr) < 0)
2734 {
2735 fprintf(stderr, "ERROR: Unable to get scanline %d!\n", y);
2736 gs_exit(1);
2737 }
2738
2739 /*
2740 * Pull the individual color planes out of the pixels...
2741 */
2742
2743 if (srcptr[0] == 0 && memcmp(srcptr, srcptr + 1, srcbytes - 1) == 0)
2744 memset(dst, 0, cups->header.cupsBytesPerLine);
2745 else
2746 switch (cups->header.cupsBitsPerColor)
2747 {
2748 default :
2749 memset(dst, 0, cups->header.cupsBytesPerLine);
2750
2751 switch (cups->header.cupsColorSpace)
2752 {
2753 default :
2754 for (dstptr = dst, x = cups->width, srcbit = 64 >> z,
2755 dstbit = 128;
2756 x > 0;
2757 x --)
2758 {
2759 if (*srcptr & srcbit)
2760 *dstptr |= dstbit;
2761
2762 if (srcbit >= 16)
2763 srcbit >>= 4;
2764 else
2765 {
2766 srcbit = 64 >> z;
2767 srcptr ++;
2768 }
2769
2770 if (dstbit > 1)
2771 dstbit >>= 1;
2772 else
2773 {
2774 dstbit = 128;
2775 dstptr ++;
2776 }
2777 }
2778 break;
2779 case CUPS_CSPACE_GMCK :
2780 case CUPS_CSPACE_GMCS :
2781 case CUPS_CSPACE_RGBA :
2782 case CUPS_CSPACE_CMYK :
2783 case CUPS_CSPACE_YMCK :
2784 case CUPS_CSPACE_KCMY :
2785 for (dstptr = dst, x = cups->width, srcbit = 128 >> z,
2786 dstbit = 128;
2787 x > 0;
2788 x --)
2789 {
2790 if (*srcptr & srcbit)
2791 *dstptr |= dstbit;
2792
2793 if (srcbit >= 16)
2794 srcbit >>= 4;
2795 else
2796 {
2797 srcbit = 128 >> z;
2798 srcptr ++;
2799 }
2800
2801 if (dstbit > 1)
2802 dstbit >>= 1;
2803 else
2804 {
2805 dstbit = 128;
2806 dstptr ++;
2807 }
2808 }
2809 break;
2810 case CUPS_CSPACE_KCMYcm :
2811 for (dstptr = dst, x = cups->width, srcbit = 32 >> z,
2812 dstbit = 128;
2813 x > 0;
2814 x --, srcptr ++)
2815 {
2816 if (*srcptr & srcbit)
2817 *dstptr |= dstbit;
2818
2819 if (dstbit > 1)
2820 dstbit >>= 1;
2821 else
2822 {
2823 dstbit = 128;
2824 dstptr ++;
2825 }
2826 }
2827 break;
2828 }
2829 break;
2830
2831 case 2 :
2832 memset(dst, 0, cups->header.cupsBytesPerLine);
2833
2834 switch (cups->header.cupsColorSpace)
2835 {
2836 default :
2837 for (dstptr = dst, x = cups->width, srcbit = 48 >> (z * 2),
2838 dstbit = 0xc0;
2839 x > 0;
2840 x --, srcptr ++)
2841 {
2842 if ((temp = *srcptr & srcbit) != 0)
2843 {
2844 if (srcbit == dstbit)
2845 *dstptr |= temp;
2846 else
2847 {
2848 switch (srcbit)
2849 {
2850 case 0x30 :
2851 temp >>= 4;
2852 break;
2853 case 0x0c :
2854 temp >>= 2;
2855 break;
2856 }
2857
2858 switch (dstbit)
2859 {
2860 case 0xc0 :
2861 *dstptr |= temp << 6;
2862 break;
2863 case 0x30 :
2864 *dstptr |= temp << 4;
2865 break;
2866 case 0x0c :
2867 *dstptr |= temp << 2;
2868 break;
2869 case 0x03 :
2870 *dstptr |= temp;
2871 break;
2872 }
2873 }
2874 }
2875
2876 if (dstbit > 0x03)
2877 dstbit >>= 2;
2878 else
2879 {
2880 dstbit = 0xc0;
2881 dstptr ++;
2882 }
2883 }
2884 break;
2885 case CUPS_CSPACE_GMCK :
2886 case CUPS_CSPACE_GMCS :
2887 case CUPS_CSPACE_RGBA :
2888 case CUPS_CSPACE_CMYK :
2889 case CUPS_CSPACE_YMCK :
2890 case CUPS_CSPACE_KCMY :
2891 case CUPS_CSPACE_KCMYcm :
2892 for (dstptr = dst, x = cups->width, srcbit = 192 >> (z * 2),
2893 dstbit = 0xc0;
2894 x > 0;
2895 x --, srcptr ++)
2896 {
2897 if ((temp = *srcptr & srcbit) != 0)
2898 {
2899 if (srcbit == dstbit)
2900 *dstptr |= temp;
2901 else
2902 {
2903 switch (srcbit)
2904 {
2905 case 0xc0 :
2906 temp >>= 6;
2907 break;
2908 case 0x30 :
2909 temp >>= 4;
2910 break;
2911 case 0x0c :
2912 temp >>= 2;
2913 break;
2914 }
2915
2916 switch (dstbit)
2917 {
2918 case 0xc0 :
2919 *dstptr |= temp << 6;
2920 break;
2921 case 0x30 :
2922 *dstptr |= temp << 4;
2923 break;
2924 case 0x0c :
2925 *dstptr |= temp << 2;
2926 break;
2927 case 0x03 :
2928 *dstptr |= temp;
2929 break;
2930 }
2931 }
2932 }
2933
2934 if (dstbit > 0x03)
2935 dstbit >>= 2;
2936 else
2937 {
2938 dstbit = 0xc0;
2939 dstptr ++;
2940 }
2941 }
2942 break;
2943 }
2944 break;
2945
2946 case 4 :
2947 memset(dst, 0, cups->header.cupsBytesPerLine);
2948
2949 switch (cups->header.cupsColorSpace)
2950 {
2951 default :
2952 if (z > 0)
2953 srcptr ++;
2954
2955 if (z == 1)
2956 srcbit = 0xf0;
2957 else
2958 srcbit = 0x0f;
2959
2960 for (dstptr = dst, x = cups->width, dstbit = 0xf0;
2961 x > 0;
2962 x --, srcptr += 2)
2963 {
2964 if ((temp = *srcptr & srcbit) != 0)
2965 {
2966 if (srcbit == dstbit)
2967 *dstptr |= temp;
2968 else
2969 {
2970 if (srcbit == 0xf0)
2971 temp >>= 4;
2972
2973 if (dstbit == 0xf0)
2974 *dstptr |= temp << 4;
2975 else
2976 *dstptr |= temp;
2977 }
2978 }
2979
2980 if (dstbit == 0xf0)
2981 dstbit = 0x0f;
2982 else
2983 {
2984 dstbit = 0xf0;
2985 dstptr ++;
2986 }
2987 }
2988 break;
2989 case CUPS_CSPACE_GMCK :
2990 case CUPS_CSPACE_GMCS :
2991 case CUPS_CSPACE_RGBA :
2992 case CUPS_CSPACE_CMYK :
2993 case CUPS_CSPACE_YMCK :
2994 case CUPS_CSPACE_KCMY :
2995 case CUPS_CSPACE_KCMYcm :
2996 if (z > 1)
2997 srcptr ++;
2998
2999 if (z & 1)
3000 srcbit = 0x0f;
3001 else
3002 srcbit = 0xf0;
3003
3004 for (dstptr = dst, x = cups->width, dstbit = 0xf0;
3005 x > 0;
3006 x --, srcptr += 2)
3007 {
3008 if ((temp = *srcptr & srcbit) != 0)
3009 {
3010 if (srcbit == dstbit)
3011 *dstptr |= temp;
3012 else
3013 {
3014 if (srcbit == 0xf0)
3015 temp >>= 4;
3016
3017 if (dstbit == 0xf0)
3018 *dstptr |= temp << 4;
3019 else
3020 *dstptr |= temp;
3021 }
3022 }
3023
3024 if (dstbit == 0xf0)
3025 dstbit = 0x0f;
3026 else
3027 {
3028 dstbit = 0xf0;
3029 dstptr ++;
3030 }
3031 }
3032 break;
3033 }
3034 break;
3035
3036 case 8 :
3037 for (srcptr += z, dstptr = dst, x = cups->header.cupsBytesPerLine;
3038 x > 0;
3039 srcptr += pdev->color_info.num_components, x --)
3040 *dstptr++ = *srcptr;
3041 break;
3042 }
3043
3044 /*
3045 * Write the bitmap data to the raster stream...
3046 */
3047
3048 cupsRasterWritePixels(cups->stream, dst, cups->header.cupsBytesPerLine);
3049 }
3050 }
3051
3052
3053 /*
3054 * End of "$Id: gdevcups.c,v 1.48 2002/01/02 17:59:09 mike Exp $".
3055 */