• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *   Image file to raster filter for CUPS.
3  *
4  *   Copyright 2007-2011 by Apple Inc.
5  *   Copyright 1993-2007 by Easy Software Products.
6  *
7  *   These coded instructions, statements, and computer programs are the
8  *   property of Apple Inc. and are protected by Federal copyright
9  *   law.  Distribution and use rights are outlined in the file "COPYING"
10  *   which should have been included with this file.
11  *
12  * Contents:
13  *
14  *   main()          - Main entry...
15  *   blank_line()    - Clear a line buffer to the blank value...
16  *   format_CMY()    - Convert image data to CMY.
17  *   format_CMYK()   - Convert image data to CMYK.
18  *   format_K()      - Convert image data to black.
19  *   format_KCMY()   - Convert image data to KCMY.
20  *   format_KCMYcm() - Convert image data to KCMYcm.
21  *   format_RGBA()   - Convert image data to RGBA/RGBW.
22  *   format_W()      - Convert image data to luminance.
23  *   format_YMC()    - Convert image data to YMC.
24  *   format_YMCK()   - Convert image data to YMCK.
25  *   make_lut()      - Make a lookup table given gamma and brightness values.
26  *   raster_cb()     - Validate the page header.
27  */
28 
29 /*
30  * Include necessary headers...
31  */
32 
33 #include "common.h"
34 #include <cupsfilters/raster.h>
35 #include <cupsfilters/colormanager.h>
36 #include <cupsfilters/image-private.h>
37 #include <unistd.h>
38 #include <math.h>
39 #include <signal.h>
40 #include <string.h>
41 
42 
43 /*
44  * Globals...
45  */
46 
47 int	Flip = 0,			/* Flip/mirror pages */
48 	XPosition = 0,			/* Horizontal position on page */
49 	YPosition = 0,			/* Vertical position on page */
50 	Collate = 0,			/* Collate copies? */
51 	Copies = 1;			/* Number of copies */
52 int	Floyd16x16[16][16] =		/* Traditional Floyd ordered dither */
53 	{
54 	  { 0,   128, 32,  160, 8,   136, 40,  168,
55 	    2,   130, 34,  162, 10,  138, 42,  170 },
56 	  { 192, 64,  224, 96,  200, 72,  232, 104,
57 	    194, 66,  226, 98,  202, 74,  234, 106 },
58 	  { 48,  176, 16,  144, 56,  184, 24,  152,
59 	    50,  178, 18,  146, 58,  186, 26,  154 },
60 	  { 240, 112, 208, 80,  248, 120, 216, 88,
61 	    242, 114, 210, 82,  250, 122, 218, 90 },
62 	  { 12,  140, 44,  172, 4,   132, 36,  164,
63 	    14,  142, 46,  174, 6,   134, 38,  166 },
64 	  { 204, 76,  236, 108, 196, 68,  228, 100,
65 	    206, 78,  238, 110, 198, 70,  230, 102 },
66 	  { 60,  188, 28,  156, 52,  180, 20,  148,
67 	    62,  190, 30,  158, 54,  182, 22,  150 },
68 	  { 252, 124, 220, 92,  244, 116, 212, 84,
69 	    254, 126, 222, 94,  246, 118, 214, 86 },
70 	  { 3,   131, 35,  163, 11,  139, 43,  171,
71 	    1,   129, 33,  161, 9,   137, 41,  169 },
72 	  { 195, 67,  227, 99,  203, 75,  235, 107,
73 	    193, 65,  225, 97,  201, 73,  233, 105 },
74 	  { 51,  179, 19,  147, 59,  187, 27,  155,
75 	    49,  177, 17,  145, 57,  185, 25,  153 },
76 	  { 243, 115, 211, 83,  251, 123, 219, 91,
77 	    241, 113, 209, 81,  249, 121, 217, 89 },
78 	  { 15,  143, 47,  175, 7,   135, 39,  167,
79 	    13,  141, 45,  173, 5,   133, 37,  165 },
80 	  { 207, 79,  239, 111, 199, 71,  231, 103,
81 	    205, 77,  237, 109, 197, 69,  229, 101 },
82 	  { 63,  191, 31,  159, 55,  183, 23,  151,
83 	    61,  189, 29,  157, 53,  181, 21,  149 },
84 	  { 254, 127, 223, 95,  247, 119, 215, 87,
85 	    253, 125, 221, 93,  245, 117, 213, 85 }
86 	};
87 int	Floyd8x8[8][8] =
88 	{
89 	  {  0, 32,  8, 40,  2, 34, 10, 42 },
90 	  { 48, 16, 56, 24, 50, 18, 58, 26 },
91 	  { 12, 44,  4, 36, 14, 46,  6, 38 },
92 	  { 60, 28, 52, 20, 62, 30, 54, 22 },
93 	  {  3, 35, 11, 43,  1, 33,  9, 41 },
94 	  { 51, 19, 59, 27, 49, 17, 57, 25 },
95 	  { 15, 47,  7, 39, 13, 45,  5, 37 },
96 	  { 63, 31, 55, 23, 61, 29, 53, 21 }
97 	};
98 int	Floyd4x4[4][4] =
99 	{
100 	  {  0,  8,  2, 10 },
101 	  { 12,  4, 14,  6 },
102 	  {  3, 11,  1,  9 },
103 	  { 15,  7, 13,  5 }
104 	};
105 
106 cups_ib_t	OnPixels[256],		/* On-pixel LUT */
107 		OffPixels[256];		/* Off-pixel LUT */
108 
109 
110 /*
111  * Local functions...
112  */
113 
114 static void	blank_line(cups_page_header2_t *header, unsigned char *row);
115 static void	format_CMY(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
116 static void	format_CMYK(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
117 static void	format_K(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
118 static void	format_KCMYcm(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
119 static void	format_KCMY(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
120 #define		format_RGB format_CMY
121 static void	format_RGBA(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
122 static void	format_W(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
123 static void	format_YMC(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
124 static void	format_YMCK(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
125 static void	make_lut(cups_ib_t *, int, float, float);
126 static int	raster_cb(cups_page_header2_t *header, int preferred_bits);
127 
128 
129 /*
130  * 'main()' - Main entry...
131  */
132 
133 int					/* O - Exit status */
main(int argc,char * argv[])134 main(int  argc,				/* I - Number of command-line arguments */
135      char *argv[])			/* I - Command-line arguments */
136 {
137   int			i;		/* Looping var */
138   cups_image_t		*img;		/* Image to print */
139   float			xprint,		/* Printable area */
140 			yprint,
141 			xinches,	/* Total size in inches */
142 			yinches;
143   float			xsize,		/* Total size in points */
144 			ysize,
145 			xsize2,
146 			ysize2;
147   float			aspect;		/* Aspect ratio */
148   int			xpages,		/* # x pages */
149 			ypages,		/* # y pages */
150 			xpage,		/* Current x page */
151 			ypage,		/* Current y page */
152 			xtemp,		/* Bitmap width in pixels */
153 			ytemp,		/* Bitmap height in pixels */
154 			page;		/* Current page number */
155   int			xc0, yc0,	/* Corners of the page in image coords */
156 			xc1, yc1;
157   ppd_file_t		*ppd;		/* PPD file */
158   ppd_choice_t		*choice;	/* PPD option choice */
159   char			*resolution,	/* Output resolution */
160 			*media_type;	/* Media type */
161   ppd_profile_t		*profile;	/* Color profile */
162   ppd_profile_t		userprofile;	/* User-specified profile */
163   cups_raster_t		*ras;		/* Raster stream */
164   cups_page_header2_t	header;		/* Page header */
165   int			num_options;	/* Number of print options */
166   cups_option_t		*options;	/* Print options */
167   const char		*val;		/* Option value */
168   int			slowcollate,	/* Collate copies the slow way */
169 			slowcopies;	/* Make copies the "slow" way? */
170   float			g;		/* Gamma correction value */
171   float			b;		/* Brightness factor */
172   float			zoom;		/* Zoom facter */
173   int			xppi, yppi;	/* Pixels-per-inch */
174   int			hue, sat;	/* Hue and saturation adjustment */
175   cups_izoom_t		*z;		/* Image zoom buffer */
176   cups_iztype_t		zoom_type;	/* Image zoom type */
177   int			primary,	/* Primary image colorspace */
178 			secondary;	/* Secondary image colorspace */
179   cups_ib_t		*row,		/* Current row */
180 			*r0,		/* Top row */
181 			*r1;		/* Bottom row */
182   int			y,		/* Current Y coordinate on page */
183 			iy,		/* Current Y coordinate in image */
184 			last_iy,	/* Previous Y coordinate in image */
185 			yerr0,		/* Top Y error value */
186 			yerr1;		/* Bottom Y error value */
187   cups_ib_t		lut[256];	/* Gamma/brightness LUT */
188   int			plane,		/* Current color plane */
189 			num_planes;	/* Number of color planes */
190   char			filename[1024];	/* Name of file to print */
191   cm_calibration_t      cm_calibrate;   /* Are we color calibrating the device? */
192   int                   cm_disabled;    /* Color management disabled? */
193   int fillprint = 0;  /* print-scaling = fill */
194   int cropfit = 0;		/* -o crop-to-fit */
195  /*
196   * Make sure status messages are not buffered...
197   */
198 
199   setbuf(stderr, NULL);
200 
201  /*
202   * Ignore broken pipe signals...
203   */
204 
205   signal(SIGPIPE, SIG_IGN);
206 
207  /*
208   * Check command-line...
209   */
210 
211   if (argc < 6 || argc > 7)
212   {
213     fprintf(stderr, "Usage: %s job-id user title copies options [file]\n",
214 	    argv[0]);
215     return (1);
216   }
217 
218   options     = NULL;
219   num_options = cupsParseOptions(argv[5], 0, &options);
220 
221  /*
222   * Copy stdin as needed...
223   */
224 
225   if (argc == 6)
226   {
227     int		fd;		/* File to write to */
228     char	buffer[8192];	/* Buffer to read into */
229     int		bytes;		/* # of bytes to read */
230 
231 
232     if ((fd = cupsTempFd(filename, sizeof(filename))) < 0)
233     {
234       perror("ERROR: Unable to copy print file");
235       return (1);
236     }
237 
238     fprintf(stderr,
239             "DEBUG: imagetoraster - copying to temp print file \"%s\".\n",
240             filename);
241 
242     while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0)
243       bytes = write(fd, buffer, bytes);
244 
245     close(fd);
246   }
247   else
248   {
249     strncpy(filename, argv[6], sizeof(filename) - 1);
250     filename[sizeof(filename) - 1] = '\0';
251   }
252 
253  /*
254   * Process command-line options and write the prolog...
255   */
256 
257   zoom = 1.0;
258   xppi = 0;
259   yppi = 0;
260   hue  = 0;
261   sat  = 100;
262   g    = 1.0;
263   b    = 1.0;
264 
265   Copies = atoi(argv[4]);
266 
267   ppd = SetCommonOptions(num_options, options, 0);
268 
269   if ((val = cupsGetOption("multiple-document-handling", num_options, options)) != NULL)
270   {
271    /*
272     * This IPP attribute is unnecessarily complicated...
273     *
274     *   single-document, separate-documents-collated-copies, and
275     *   single-document-new-sheet all require collated copies.
276     *
277     *   separate-documents-collated-copies allows for uncollated copies.
278     */
279 
280     Collate = strcasecmp(val, "separate-documents-collated-copies") != 0;
281   }
282 
283   if ((val = cupsGetOption("Collate", num_options, options)) != NULL &&
284       strcasecmp(val, "True") == 0)
285     Collate = 1;
286 
287   if ((val = cupsGetOption("gamma", num_options, options)) != NULL)
288   {
289    /*
290     * Get gamma value from 1 to 10000...
291     */
292 
293     g = atoi(val) * 0.001f;
294 
295     if (g < 0.001f)
296       g = 0.001f;
297     else if (g > 10.0f)
298       g = 10.0f;
299   }
300 
301   if ((val = cupsGetOption("brightness", num_options, options)) != NULL)
302   {
303    /*
304     * Get brightness value from 10 to 1000.
305     */
306 
307     b = atoi(val) * 0.01f;
308 
309     if (b < 0.1f)
310       b = 0.1f;
311     else if (b > 10.0f)
312       b = 10.0f;
313   }
314 
315   if ((val = cupsGetOption("ppi", num_options, options)) != NULL)
316   {
317     if (sscanf(val, "%dx%d", &xppi, &yppi) < 2)
318       yppi = xppi;
319     zoom = 0.0;
320   }
321 
322   if ((val = cupsGetOption("position", num_options, options)) != NULL)
323   {
324     if (strcasecmp(val, "center") == 0)
325     {
326       XPosition = 0;
327       YPosition = 0;
328     }
329     else if (strcasecmp(val, "top") == 0)
330     {
331       XPosition = 0;
332       YPosition = 1;
333     }
334     else if (strcasecmp(val, "left") == 0)
335     {
336       XPosition = -1;
337       YPosition = 0;
338     }
339     else if (strcasecmp(val, "right") == 0)
340     {
341       XPosition = 1;
342       YPosition = 0;
343     }
344     else if (strcasecmp(val, "top-left") == 0)
345     {
346       XPosition = -1;
347       YPosition = 1;
348     }
349     else if (strcasecmp(val, "top-right") == 0)
350     {
351       XPosition = 1;
352       YPosition = 1;
353     }
354     else if (strcasecmp(val, "bottom") == 0)
355     {
356       XPosition = 0;
357       YPosition = -1;
358     }
359     else if (strcasecmp(val, "bottom-left") == 0)
360     {
361       XPosition = -1;
362       YPosition = -1;
363     }
364     else if (strcasecmp(val, "bottom-right") == 0)
365     {
366       XPosition = 1;
367       YPosition = -1;
368     }
369   }
370 
371   if ((val = cupsGetOption("saturation", num_options, options)) != NULL)
372     sat = atoi(val);
373 
374   if ((val = cupsGetOption("hue", num_options, options)) != NULL)
375     hue = atoi(val);
376 
377   if ((choice = ppdFindMarkedChoice(ppd, "MirrorPrint")) != NULL)
378   {
379     val = choice->choice;
380     choice->marked = 0;
381   }
382   else
383     val = cupsGetOption("mirror", num_options, options);
384 
385   if (val && (!strcasecmp(val, "true") || !strcasecmp(val, "on") ||
386               !strcasecmp(val, "yes")))
387     Flip = 1;
388 
389  /*
390   * Set the needed options in the page header...
391   */
392 
393   if (cupsRasterInterpretPPD(&header, ppd, num_options, options, raster_cb))
394   {
395     fputs("ERROR: The page setup information was not valid.\n", stderr);
396     fprintf(stderr, "DEBUG: %s\n", cupsRasterErrorString());
397     return (1);
398   }
399 
400  /*
401   * Get the media type and resolution that have been chosen...
402   */
403 
404   if ((choice = ppdFindMarkedChoice(ppd, "MediaType")) != NULL)
405     media_type = choice->choice;
406   else
407     media_type = "";
408 
409   if ((choice = ppdFindMarkedChoice(ppd, "Resolution")) != NULL)
410     resolution = choice->choice;
411   else
412     resolution = "";
413 
414   /* support the "cm-calibration" option */
415   cm_calibrate = cmGetCupsColorCalibrateMode(options, num_options);
416 
417   if (cm_calibrate == CM_CALIBRATION_ENABLED)
418     cm_disabled = 1;
419   else
420     cm_disabled = cmIsPrinterCmDisabled(getenv("PRINTER"));
421 
422  /*
423   * Choose the appropriate colorspace...
424   */
425 
426   switch (header.cupsColorSpace)
427   {
428     case CUPS_CSPACE_W :
429     case CUPS_CSPACE_SW :
430         if (header.cupsBitsPerColor >= 8)
431 	{
432           primary   = CUPS_IMAGE_WHITE;
433 	  secondary = CUPS_IMAGE_WHITE;
434         }
435 	else
436 	{
437           primary   = CUPS_IMAGE_BLACK;
438 	  secondary = CUPS_IMAGE_BLACK;
439 	}
440 	break;
441 
442     default :
443     case CUPS_CSPACE_RGB :
444     case CUPS_CSPACE_RGBA :
445     case CUPS_CSPACE_RGBW :
446     case CUPS_CSPACE_SRGB :
447     case CUPS_CSPACE_ADOBERGB :
448         if (header.cupsBitsPerColor >= 8)
449 	{
450           primary   = CUPS_IMAGE_RGB;
451 	  secondary = CUPS_IMAGE_RGB;
452         }
453 	else
454 	{
455           primary   = CUPS_IMAGE_CMY;
456 	  secondary = CUPS_IMAGE_CMY;
457 	}
458 	break;
459 
460     case CUPS_CSPACE_K :
461     case CUPS_CSPACE_WHITE :
462     case CUPS_CSPACE_GOLD :
463     case CUPS_CSPACE_SILVER :
464         primary   = CUPS_IMAGE_BLACK;
465 	secondary = CUPS_IMAGE_BLACK;
466 	break;
467 
468     case CUPS_CSPACE_CMYK :
469     case CUPS_CSPACE_YMCK :
470     case CUPS_CSPACE_KCMY :
471     case CUPS_CSPACE_KCMYcm :
472     case CUPS_CSPACE_GMCK :
473     case CUPS_CSPACE_GMCS :
474         if (header.cupsBitsPerColor == 1)
475 	{
476           primary   = CUPS_IMAGE_CMY;
477 	  secondary = CUPS_IMAGE_CMY;
478 	}
479 	else
480 	{
481           primary   = CUPS_IMAGE_CMYK;
482 	  secondary = CUPS_IMAGE_CMYK;
483 	}
484 	break;
485 
486     case CUPS_CSPACE_CMY :
487     case CUPS_CSPACE_YMC :
488         primary   = CUPS_IMAGE_CMY;
489 	secondary = CUPS_IMAGE_CMY;
490 	break;
491 
492     case CUPS_CSPACE_CIEXYZ :
493     case CUPS_CSPACE_CIELab :
494     case CUPS_CSPACE_ICC1 :
495     case CUPS_CSPACE_ICC2 :
496     case CUPS_CSPACE_ICC3 :
497     case CUPS_CSPACE_ICC4 :
498     case CUPS_CSPACE_ICC5 :
499     case CUPS_CSPACE_ICC6 :
500     case CUPS_CSPACE_ICC7 :
501     case CUPS_CSPACE_ICC8 :
502     case CUPS_CSPACE_ICC9 :
503     case CUPS_CSPACE_ICCA :
504     case CUPS_CSPACE_ICCB :
505     case CUPS_CSPACE_ICCC :
506     case CUPS_CSPACE_ICCD :
507     case CUPS_CSPACE_ICCE :
508     case CUPS_CSPACE_ICCF :
509     case CUPS_CSPACE_DEVICE1 :
510     case CUPS_CSPACE_DEVICE2 :
511     case CUPS_CSPACE_DEVICE3 :
512     case CUPS_CSPACE_DEVICE4 :
513     case CUPS_CSPACE_DEVICE5 :
514     case CUPS_CSPACE_DEVICE6 :
515     case CUPS_CSPACE_DEVICE7 :
516     case CUPS_CSPACE_DEVICE8 :
517     case CUPS_CSPACE_DEVICE9 :
518     case CUPS_CSPACE_DEVICEA :
519     case CUPS_CSPACE_DEVICEB :
520     case CUPS_CSPACE_DEVICEC :
521     case CUPS_CSPACE_DEVICED :
522     case CUPS_CSPACE_DEVICEE :
523     case CUPS_CSPACE_DEVICEF :
524         fprintf(stderr, "DEBUG: Colorspace %d not supported.\n",
525 	        header.cupsColorSpace);
526 	exit(1);
527 	break;
528   }
529 
530  /*
531   * Find a color profile matching the current options...
532   */
533 
534   if ((val = cupsGetOption("profile", num_options, options)) != NULL &&
535       !cm_disabled)
536   {
537     profile = &userprofile;
538     sscanf(val, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f",
539            &(userprofile.density), &(userprofile.gamma),
540 	   userprofile.matrix[0] + 0, userprofile.matrix[0] + 1,
541 	   userprofile.matrix[0] + 2,
542 	   userprofile.matrix[1] + 0, userprofile.matrix[1] + 1,
543 	   userprofile.matrix[1] + 2,
544 	   userprofile.matrix[2] + 0, userprofile.matrix[2] + 1,
545 	   userprofile.matrix[2] + 2);
546 
547     userprofile.density      *= 0.001f;
548     userprofile.gamma        *= 0.001f;
549     userprofile.matrix[0][0] *= 0.001f;
550     userprofile.matrix[0][1] *= 0.001f;
551     userprofile.matrix[0][2] *= 0.001f;
552     userprofile.matrix[1][0] *= 0.001f;
553     userprofile.matrix[1][1] *= 0.001f;
554     userprofile.matrix[1][2] *= 0.001f;
555     userprofile.matrix[2][0] *= 0.001f;
556     userprofile.matrix[2][1] *= 0.001f;
557     userprofile.matrix[2][2] *= 0.001f;
558   }
559   else if (ppd != NULL && !cm_disabled)
560   {
561     fprintf(stderr, "DEBUG: Searching for profile \"%s/%s\"...\n",
562             resolution, media_type);
563 
564     for (i = 0, profile = ppd->profiles; i < ppd->num_profiles; i ++, profile ++)
565     {
566       fprintf(stderr, "DEBUG: \"%s/%s\" = ", profile->resolution,
567               profile->media_type);
568 
569       if ((strcmp(profile->resolution, resolution) == 0 ||
570            profile->resolution[0] == '-') &&
571           (strcmp(profile->media_type, media_type) == 0 ||
572            profile->media_type[0] == '-'))
573       {
574         fputs("MATCH\n", stderr);
575 	break;
576       }
577       else
578         fputs("no.\n", stderr);
579     }
580 
581    /*
582     * If we found a color profile, use it!
583     */
584 
585     if (i >= ppd->num_profiles)
586       profile = NULL;
587   }
588   else
589     profile = NULL;
590 
591   if (profile)
592     cupsImageSetProfile(profile->density, profile->gamma, profile->matrix);
593 
594   cupsImageSetRasterColorSpace(header.cupsColorSpace);
595 
596  /*
597   * Create a gamma/brightness LUT...
598   */
599 
600   make_lut(lut, primary, g, b);
601 
602  /*
603   * Open the input image to print...
604   */
605 
606   fputs("INFO: Loading print file.\n", stderr);
607 
608   if (header.cupsColorSpace == CUPS_CSPACE_CIEXYZ ||
609       header.cupsColorSpace == CUPS_CSPACE_CIELab ||
610       header.cupsColorSpace >= CUPS_CSPACE_ICC1)
611     img = cupsImageOpen(filename, primary, secondary, sat, hue, NULL);
612   else
613     img = cupsImageOpen(filename, primary, secondary, sat, hue, lut);
614 
615   if(img!=NULL){
616 
617   int margin_defined = 0;
618   int fidelity = 0;
619   int document_large = 0;
620 
621   if(ppd != NULL && (ppd->custom_margins[0]||ppd->custom_margins[1]
622                      ||ppd->custom_margins[2]||ppd->custom_margins[3]))
623     margin_defined = 1;
624 
625   if(PageLength!=PageTop-PageBottom||PageWidth!=PageRight-PageLeft)
626   {
627     margin_defined = 1;
628   }
629 
630   if((val = cupsGetOption("ipp-attribute-fidelity",num_options,options)) != NULL)
631   {
632     if(!strcasecmp(val,"true")||!strcasecmp(val,"yes")||
633         !strcasecmp(val,"on"))
634     {
635       fidelity = 1;
636     }
637   }
638 
639   float w = (float)cupsImageGetWidth(img);
640   float h = (float)cupsImageGetHeight(img);
641   float pw = PageRight-PageLeft;
642   float ph = PageTop-PageBottom;
643   int tempOrientation = Orientation;
644   if((val = cupsGetOption("orientation-requested",num_options,options))!=NULL)
645   {
646     tempOrientation = atoi(val);
647   }
648   else if((val = cupsGetOption("landscape",num_options,options))!=NULL)
649   {
650     if(!strcasecmp(val,"true")||!strcasecmp(val,"yes"))
651     {
652       tempOrientation = 4;
653     }
654   }
655   if(tempOrientation==0)
656   {
657     if(((pw > ph) && (w < h)) || ((pw < ph) && (w > h)))
658     {
659       tempOrientation = 4;
660     }
661   }
662   if(tempOrientation==4||tempOrientation==5)
663   {
664     int tmp = pw;
665     pw = ph;
666     ph = tmp;
667   }
668   if (w * 72.0 / img->xppi > pw || h * 72.0 / img->yppi > ph)
669     document_large = 1;
670 
671   if((val = cupsGetOption("print-scaling",num_options,options)) != NULL)
672   {
673     if(!strcasecmp(val,"auto"))
674     {
675       if(fidelity||document_large)
676       {
677         if(margin_defined)
678           zoom = 1.0;       // fit method
679         else
680           fillprint = 1;    // fill method
681       }
682       else
683         cropfit = 1;        // none method
684     }
685     else if(!strcasecmp(val,"auto-fit"))
686     {
687       if(fidelity||document_large)
688         zoom = 1.0;         // fit method
689       else
690         cropfit = 1;        // none method
691     }
692     else if(!strcasecmp(val,"fill"))
693       fillprint = 1;        // fill method
694     else if(!strcasecmp(val,"fit"))
695       zoom = 1.0;           // fitplot = 1 or fit method
696     else
697       cropfit=1;            // none or crop-to-fit
698   }
699   else{       // print-scaling is not defined, look for alternate options.
700     if ((val = cupsGetOption("scaling", num_options, options)) != NULL)
701     zoom = atoi(val) * 0.01;
702   else if (((val =
703 	     cupsGetOption("fit-to-page", num_options, options)) != NULL) ||
704 	   ((val = cupsGetOption("fitplot", num_options, options)) != NULL))
705   {
706     if (!strcasecmp(val, "yes") || !strcasecmp(val, "on") ||
707 	!strcasecmp(val, "true"))
708       zoom = 1.0;
709     else
710       zoom = 0.0;
711   }
712   else if ((val = cupsGetOption("natural-scaling", num_options, options)) != NULL)
713     zoom = 0.0;
714 
715   if((val = cupsGetOption("fill",num_options,options))!=0) {
716     if(!strcasecmp(val,"true")||!strcasecmp(val,"yes"))
717     {
718       fillprint = 1;
719     }
720   }
721   if((val = cupsGetOption("crop-to-fit",num_options,options))!= NULL){
722     if(!strcasecmp(val,"true")||!strcasecmp(val,"yes"))
723     {
724       cropfit=1;
725     }
726   } }
727   }
728 
729   if(img!=NULL)
730   {
731     if(fillprint||cropfit)
732     {
733       float w = (float)cupsImageGetWidth(img);
734       float h = (float)cupsImageGetHeight(img);
735       /* For cropfit do the math without the unprintable margins to get correct
736 	 centering, for fillprint, fill the printable area */
737       float pw = (cropfit ? PageWidth : PageRight-PageLeft);
738       float ph = (cropfit ? PageLength : PageTop-PageBottom);
739       const char *val;
740       int tempOrientation = Orientation;
741       int flag =3;
742       if((val = cupsGetOption("orientation-requested",num_options,options))!=NULL)
743       {
744         tempOrientation = atoi(val);
745       }
746       else if((val = cupsGetOption("landscape",num_options,options))!=NULL)
747       {
748         if(!strcasecmp(val,"true")||!strcasecmp(val,"yes"))
749         {
750           tempOrientation = 4;
751         }
752       }
753       if(tempOrientation>0)
754       {
755         if(tempOrientation==4||tempOrientation==5)
756         {
757           float temp = pw;
758           pw = ph;
759           ph = temp;
760           flag = 4;
761         }
762       }
763       if(tempOrientation==0)
764       {
765         if(((pw > ph) && (w < h)) || ((pw < ph) && (w > h)))
766         {
767           int temp = pw;
768           pw = ph;
769           ph = temp;
770           flag = 4;
771         }
772       }
773       if(fillprint)
774       {
775         // Final width and height of cropped image.
776         float final_w,final_h;
777         if(w*ph/pw <=h){
778           final_w =w;
779           final_h =w*ph/pw;
780         }
781         else{
782           final_w = h*pw/ph;
783           final_h = h;
784         }
785         // posw and posh are position of the cropped image along width and height.
786         float posw=(w-final_w)/2,posh=(h-final_h)/2;
787         posw = (1+XPosition)*posw;
788         posh = (1-YPosition)*posh;
789         cups_image_t *img2 = cupsImageCrop(img,posw,posh,final_w,final_h);
790         cupsImageClose(img);
791         img = img2;
792       }
793       else
794       {
795         float final_w=w,final_h=h;
796         if (w > pw * img->xppi / 72.0)
797           final_w = pw * img->xppi / 72.0;
798         if (h > ph * img->yppi / 72.0)
799           final_h = ph * img->yppi / 72.0;
800 	float posw=(w-final_w)/2,posh=(h-final_h)/2;
801         posw = (1+XPosition)*posw;
802 	posh = (1-YPosition)*posh;
803 	/* Check whether the unprintable margins hide away a part of the image,
804 	   if so, correct the image cut */
805 	if(flag==4)
806 	{
807 	  float margin, cutoff;
808 	  margin = (PageLength - final_w * 72.0 / img->xppi) / 2;
809 	  if (margin >= PageBottom)
810 	    PageBottom = margin;
811 	  else
812 	  {
813 	    cutoff = (PageBottom - margin) * img->xppi / 72.0;
814 	    final_w -= cutoff;
815 	    posw += cutoff;
816 	  }
817 	  margin = PageBottom + final_w * 72.0 / img->xppi;
818 	  if (margin <= PageTop)
819 	    PageTop = margin;
820 	  else
821 	    final_w -= (margin - PageTop) * img->xppi / 72.0;
822 	  margin = (PageWidth - final_h * 72.0 / img->yppi) / 2;
823 	  if (margin >= PageLeft)
824 	    PageLeft = margin;
825 	  else
826 	  {
827 	    cutoff = (PageLeft - margin) * img->yppi / 72.0;
828 	    final_h -= cutoff;
829 	    posh += cutoff;
830 	  }
831 	  margin = PageLeft + final_h * 72.0 / img->yppi;
832 	  if (margin <= PageRight)
833 	    PageRight = margin;
834 	  else
835 	    final_h -= (margin - PageRight) * img->yppi / 72.0;
836 	}
837 	else
838 	{
839 	  float margin, cutoff;
840 	  margin = (PageLength - final_h * 72.0 / img->yppi) / 2;
841 	  if (margin >= PageBottom)
842 	    PageBottom = margin;
843 	  else
844 	  {
845 	    cutoff = (PageBottom - margin) * img->yppi / 72.0;
846 	    final_h -= cutoff;
847 	    posh += cutoff;
848 	  }
849 	  margin = PageBottom + final_h * 72.0 / img->yppi;
850 	  if (margin <= PageTop)
851 	    PageTop = margin;
852 	  else
853 	    final_h -= (margin - PageTop) * img->yppi / 72.0;
854 	  margin = (PageWidth - final_w * 72.0 / img->xppi) / 2;
855 	  if (margin >= PageLeft)
856 	    PageLeft = margin;
857 	  else
858 	  {
859 	    cutoff = (PageLeft - margin) * img->xppi / 72.0;
860 	    final_w -= cutoff;
861 	    posw += cutoff;
862 	  }
863 	  margin = PageLeft + final_w * 72.0 / img->xppi;
864 	  if (margin <= PageRight)
865 	    PageRight = margin;
866 	  else
867 	    final_w -= (margin - PageRight) * img->xppi / 72.0;
868 	}
869 	if(PageBottom<0) PageBottom = 0;
870 	if(PageLeft<0) PageLeft = 0;
871 	cups_image_t *img2 = cupsImageCrop(img,posw,posh,final_w,final_h);
872 	cupsImageClose(img);
873 	img = img2;
874       }
875     }
876   }
877   if (argc == 6)
878     unlink(filename);
879 
880   if (img == NULL)
881   {
882     fputs("ERROR: The print file could not be opened.\n", stderr);
883     ppdClose(ppd);
884     return (1);
885   }
886 
887  /*
888   * Scale as necessary...
889   */
890 
891   if (zoom == 0.0 && xppi == 0)
892   {
893     xppi = img->xppi;
894     yppi = img->yppi;
895   }
896 
897   if (yppi == 0)
898     yppi = xppi;
899 
900   fprintf(stderr, "DEBUG: Before scaling: xppi=%d, yppi=%d, zoom=%.2f\n",
901           xppi, yppi, zoom);
902 
903   if (xppi > 0)
904   {
905    /*
906     * Scale the image as neccesary to match the desired pixels-per-inch.
907     */
908 
909     if (Orientation & 1)
910     {
911       xprint = (PageTop - PageBottom) / 72.0;
912       yprint = (PageRight - PageLeft) / 72.0;
913     }
914     else
915     {
916       xprint = (PageRight - PageLeft) / 72.0;
917       yprint = (PageTop - PageBottom) / 72.0;
918     }
919 
920     fprintf(stderr, "DEBUG: Before scaling: xprint=%.1f, yprint=%.1f\n",
921             xprint, yprint);
922 
923     xinches = (float)img->xsize / (float)xppi;
924     yinches = (float)img->ysize / (float)yppi;
925 
926     fprintf(stderr, "DEBUG: Image size is %.1f x %.1f inches...\n",
927             xinches, yinches);
928 
929     if ((val = cupsGetOption("natural-scaling", num_options, options)) != NULL)
930     {
931       xinches = xinches * atoi(val) / 100;
932       yinches = yinches * atoi(val) / 100;
933     }
934 
935     if (cupsGetOption("orientation-requested", num_options, options) == NULL &&
936         cupsGetOption("landscape", num_options, options) == NULL)
937     {
938      /*
939       * Rotate the image if it will fit landscape but not portrait...
940       */
941 
942       fputs("DEBUG: Auto orientation...\n", stderr);
943 
944       if ((xinches > xprint || yinches > yprint) &&
945           xinches <= yprint && yinches <= xprint)
946       {
947        /*
948 	* Rotate the image as needed...
949 	*/
950 
951         fputs("DEBUG: Using landscape orientation...\n", stderr);
952 
953 	Orientation = (Orientation + 1) & 3;
954 	xsize       = yprint;
955 	yprint      = xprint;
956 	xprint      = xsize;
957       }
958     }
959   }
960   else
961   {
962    /*
963     * Scale percentage of page size...
964     */
965 
966     xprint = (PageRight - PageLeft) / 72.0;
967     yprint = (PageTop - PageBottom) / 72.0;
968     aspect = (float)img->yppi / (float)img->xppi;
969 
970     fprintf(stderr, "DEBUG: Before scaling: xprint=%.1f, yprint=%.1f\n",
971             xprint, yprint);
972 
973     fprintf(stderr, "DEBUG: img->xppi = %d, img->yppi = %d, aspect = %f\n",
974             img->xppi, img->yppi, aspect);
975 
976     xsize = xprint * zoom;
977     ysize = xsize * img->ysize / img->xsize / aspect;
978 
979     if (ysize > (yprint * zoom))
980     {
981       ysize = yprint * zoom;
982       xsize = ysize * img->xsize * aspect / img->ysize;
983     }
984 
985     xsize2 = yprint * zoom;
986     ysize2 = xsize2 * img->ysize / img->xsize / aspect;
987 
988     if (ysize2 > (xprint * zoom))
989     {
990       ysize2 = xprint * zoom;
991       xsize2 = ysize2 * img->xsize * aspect / img->ysize;
992     }
993 
994     fprintf(stderr, "DEBUG: Portrait size is %.2f x %.2f inches\n", xsize, ysize);
995     fprintf(stderr, "DEBUG: Landscape size is %.2f x %.2f inches\n", xsize2, ysize2);
996 
997     if (cupsGetOption("orientation-requested", num_options, options) == NULL &&
998         cupsGetOption("landscape", num_options, options) == NULL)
999     {
1000      /*
1001       * Choose the rotation with the largest area, but prefer
1002       * portrait if they are equal...
1003       */
1004 
1005       fputs("DEBUG: Auto orientation...\n", stderr);
1006 
1007       if ((xsize * ysize) < (xsize2 * ysize2))
1008       {
1009        /*
1010 	* Do landscape orientation...
1011 	*/
1012 
1013         fputs("DEBUG: Using landscape orientation...\n", stderr);
1014 
1015 	Orientation = 1;
1016 	xinches     = xsize2;
1017 	yinches     = ysize2;
1018 	xprint      = (PageTop - PageBottom) / 72.0;
1019 	yprint      = (PageRight - PageLeft) / 72.0;
1020       }
1021       else
1022       {
1023        /*
1024 	* Do portrait orientation...
1025 	*/
1026 
1027         fputs("DEBUG: Using portrait orientation...\n", stderr);
1028 
1029 	Orientation = 0;
1030 	xinches     = xsize;
1031 	yinches     = ysize;
1032       }
1033     }
1034     else if (Orientation & 1)
1035     {
1036       fputs("DEBUG: Using landscape orientation...\n", stderr);
1037 
1038       xinches     = xsize2;
1039       yinches     = ysize2;
1040       xprint      = (PageTop - PageBottom) / 72.0;
1041       yprint      = (PageRight - PageLeft) / 72.0;
1042     }
1043     else
1044     {
1045       fputs("DEBUG: Using portrait orientation...\n", stderr);
1046 
1047       xinches     = xsize;
1048       yinches     = ysize;
1049       xprint      = (PageRight - PageLeft) / 72.0;
1050       yprint      = (PageTop - PageBottom) / 72.0;
1051     }
1052   }
1053 
1054  /*
1055   * Compute the number of pages to print and the size of the image on each
1056   * page...
1057   */
1058 
1059   xpages = ceil(xinches / xprint);
1060   ypages = ceil(yinches / yprint);
1061 
1062   xprint = xinches / xpages;
1063   yprint = yinches / ypages;
1064 
1065   fprintf(stderr, "DEBUG: xpages = %dx%.2fin, ypages = %dx%.2fin\n",
1066           xpages, xprint, ypages, yprint);
1067 
1068  /*
1069   * Compute the bitmap size...
1070   */
1071 
1072   if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) != NULL &&
1073       strcasecmp(choice->choice, "Custom") == 0)
1074   {
1075     float	width,		/* New width in points */
1076 		length;		/* New length in points */
1077 
1078 
1079    /*
1080     * Use the correct width and length for the current orientation...
1081     */
1082 
1083     if (Orientation & 1)
1084     {
1085       width  = yprint * 72.0;
1086       length = xprint * 72.0;
1087     }
1088     else
1089     {
1090       width  = xprint * 72.0;
1091       length = yprint * 72.0;
1092     }
1093 
1094    /*
1095     * Add margins to page size...
1096     */
1097 
1098     width  += ppd->custom_margins[0] + ppd->custom_margins[2];
1099     length += ppd->custom_margins[1] + ppd->custom_margins[3];
1100 
1101    /*
1102     * Enforce minimums...
1103     */
1104 
1105     if (width < ppd->custom_min[0])
1106       width = ppd->custom_min[0];
1107 
1108     if (length < ppd->custom_min[1])
1109       length = ppd->custom_min[1];
1110 
1111     fprintf(stderr, "DEBUG: Updated custom page size to %.2f x %.2f inches...\n",
1112             width / 72.0, length / 72.0);
1113 
1114    /*
1115     * Set the new custom size...
1116     */
1117 
1118     strcpy(header.cupsPageSizeName, "Custom");
1119 
1120     header.cupsPageSize[0] = width + 0.5;
1121     header.cupsPageSize[1] = length + 0.5;
1122     header.PageSize[0]     = width + 0.5;
1123     header.PageSize[1]     = length + 0.5;
1124 
1125    /*
1126     * Update page variables...
1127     */
1128 
1129     PageWidth  = width;
1130     PageLength = length;
1131     PageLeft   = ppd->custom_margins[0];
1132     PageRight  = width - ppd->custom_margins[2];
1133     PageBottom = ppd->custom_margins[1];
1134     PageTop    = length - ppd->custom_margins[3];
1135 
1136    /*
1137     * Remove margins from page size...
1138     */
1139 
1140     width  -= ppd->custom_margins[0] + ppd->custom_margins[2];
1141     length -= ppd->custom_margins[1] + ppd->custom_margins[3];
1142 
1143    /*
1144     * Set the bitmap size...
1145     */
1146 
1147     header.cupsWidth  = width * header.HWResolution[0] / 72.0;
1148     header.cupsHeight = length * header.HWResolution[1] / 72.0;
1149   } else {
1150    /*
1151     * Set the bitmap size...
1152     */
1153 
1154     header.cupsWidth  = (Orientation & 1 ? yprint : xprint) *
1155       header.HWResolution[0];
1156     header.cupsHeight = (Orientation & 1 ? xprint : yprint) *
1157       header.HWResolution[1];
1158   }
1159   header.cupsBytesPerLine = (header.cupsBitsPerPixel *
1160 			     header.cupsWidth + 7) / 8;
1161 
1162   if (header.cupsColorOrder == CUPS_ORDER_BANDED)
1163     header.cupsBytesPerLine *= header.cupsNumColors;
1164 
1165   header.Margins[0] = PageLeft;
1166   header.Margins[1] = PageBottom;
1167 
1168   fprintf(stderr, "DEBUG: PageSize = [%d %d]\n", header.PageSize[0],
1169           header.PageSize[1]);
1170   fprintf(stderr, "DEBUG: PageLeft = %f, PageRight = %f, PageBottom = %f, PageTop = %f\n",
1171 	  PageLeft, PageRight, PageBottom, PageTop);
1172 
1173   switch (Orientation)
1174   {
1175     default :
1176 	switch (XPosition)
1177 	{
1178 	  case -1 :
1179               header.cupsImagingBBox[0] = PageLeft;
1180 	      header.cupsImagingBBox[2] = PageLeft + xprint * 72;
1181 	      break;
1182 	  default :
1183               header.cupsImagingBBox[0] = (PageRight + PageLeft - xprint * 72) / 2;
1184 	      header.cupsImagingBBox[2] = (PageRight + PageLeft + xprint * 72) / 2;
1185 	      break;
1186 	  case 1 :
1187               header.cupsImagingBBox[0] = PageRight - xprint * 72;
1188 	      header.cupsImagingBBox[2] = PageRight;
1189 	      break;
1190 	}
1191 
1192 	switch (YPosition)
1193 	{
1194 	  case -1 :
1195               header.cupsImagingBBox[1] = PageBottom;
1196 	      header.cupsImagingBBox[3] = PageBottom + yprint * 72;
1197 	      break;
1198 	  default :
1199               header.cupsImagingBBox[1] = (PageTop + PageBottom - yprint * 72) / 2;
1200 	      header.cupsImagingBBox[3] = (PageTop + PageBottom + yprint * 72) / 2;
1201 	      break;
1202 	  case 1 :
1203               header.cupsImagingBBox[1] = PageTop - yprint * 72;
1204 	      header.cupsImagingBBox[3] = PageTop;
1205 	      break;
1206 	}
1207 	break;
1208 
1209     case 1 :
1210 	switch (XPosition)
1211 	{
1212 	  case -1 :
1213               header.cupsImagingBBox[0] = PageLeft;
1214 	      header.cupsImagingBBox[2] = PageLeft + yprint * 72;
1215 	      break;
1216 	  default :
1217               header.cupsImagingBBox[0] = (PageRight + PageLeft - yprint * 72) / 2;
1218 	      header.cupsImagingBBox[2] = (PageRight + PageLeft + yprint * 72) / 2;
1219 	      break;
1220 	  case 1 :
1221               header.cupsImagingBBox[0] = PageRight - yprint * 72;
1222 	      header.cupsImagingBBox[2] = PageRight;
1223 	      break;
1224 	}
1225 
1226 	switch (YPosition)
1227 	{
1228 	  case -1 :
1229               header.cupsImagingBBox[1] = PageBottom;
1230 	      header.cupsImagingBBox[3] = PageBottom + xprint * 72;
1231 	      break;
1232 	  default :
1233               header.cupsImagingBBox[1] = (PageTop + PageBottom - xprint * 72) / 2;
1234 	      header.cupsImagingBBox[3] = (PageTop + PageBottom + xprint * 72) / 2;
1235 	      break;
1236 	  case 1 :
1237               header.cupsImagingBBox[1] = PageTop - xprint * 72;
1238 	      header.cupsImagingBBox[3] = PageTop;
1239 	      break;
1240 	}
1241 	break;
1242 
1243     case 2 :
1244 	switch (XPosition)
1245 	{
1246 	  case 1 :
1247               header.cupsImagingBBox[0] = PageLeft;
1248 	      header.cupsImagingBBox[2] = PageLeft + xprint * 72;
1249 	      break;
1250 	  default :
1251               header.cupsImagingBBox[0] = (PageRight + PageLeft - xprint * 72) / 2;
1252 	      header.cupsImagingBBox[2] = (PageRight + PageLeft + xprint * 72) / 2;
1253 	      break;
1254 	  case -1 :
1255               header.cupsImagingBBox[0] = PageRight - xprint * 72;
1256 	      header.cupsImagingBBox[2] = PageRight;
1257 	      break;
1258 	}
1259 
1260 	switch (YPosition)
1261 	{
1262 	  case 1 :
1263               header.cupsImagingBBox[1] = PageBottom;
1264 	      header.cupsImagingBBox[3] = PageBottom + yprint * 72;
1265 	      break;
1266 	  default :
1267               header.cupsImagingBBox[1] = (PageTop + PageBottom - yprint * 72) / 2;
1268 	      header.cupsImagingBBox[3] = (PageTop + PageBottom + yprint * 72) / 2;
1269 	      break;
1270 	  case -1 :
1271               header.cupsImagingBBox[1] = PageTop - yprint * 72;
1272 	      header.cupsImagingBBox[3] = PageTop;
1273 	      break;
1274 	}
1275 	break;
1276 
1277     case 3 :
1278 	switch (XPosition)
1279 	{
1280 	  case 1 :
1281               header.cupsImagingBBox[0] = PageLeft;
1282 	      header.cupsImagingBBox[2] = PageLeft + yprint * 72;
1283 	      break;
1284 	  default :
1285               header.cupsImagingBBox[0] = (PageRight + PageLeft - yprint * 72) / 2;
1286 	      header.cupsImagingBBox[2] = (PageRight + PageLeft + yprint * 72) / 2;
1287 	      break;
1288 	  case -1 :
1289               header.cupsImagingBBox[0] = PageRight - yprint * 72;
1290 	      header.cupsImagingBBox[2] = PageRight;
1291 	      break;
1292 	}
1293 
1294 	switch (YPosition)
1295 	{
1296 	  case 1 :
1297               header.cupsImagingBBox[1] = PageBottom;
1298 	      header.cupsImagingBBox[3] = PageBottom + xprint * 72;
1299 	      break;
1300 	  default :
1301               header.cupsImagingBBox[1] = (PageTop + PageBottom - xprint * 72) / 2;
1302 	      header.cupsImagingBBox[3] = (PageTop + PageBottom + xprint * 72) / 2;
1303 	      break;
1304 	  case -1 :
1305               header.cupsImagingBBox[1] = PageTop - xprint * 72;
1306 	      header.cupsImagingBBox[3] = PageTop;
1307 	      break;
1308 	}
1309 	break;
1310   }
1311 
1312   header.ImagingBoundingBox[0] = header.cupsImagingBBox[0];
1313   header.ImagingBoundingBox[1] = header.cupsImagingBBox[1];
1314   header.ImagingBoundingBox[2] = header.cupsImagingBBox[2];
1315   header.ImagingBoundingBox[3] = header.cupsImagingBBox[3];
1316 
1317   fprintf(stderr, "DEBUG: Orientation: %d, XPosition: %d, YPosition: %d, ImagingBoundingBox = [%d %d %d %d]\n",
1318 	  Orientation, XPosition, YPosition,
1319 	  header.ImagingBoundingBox[0], header.ImagingBoundingBox[1],
1320 	  header.ImagingBoundingBox[2], header.ImagingBoundingBox[3]);
1321 
1322   if (header.cupsColorOrder == CUPS_ORDER_PLANAR)
1323     num_planes = header.cupsNumColors;
1324   else
1325     num_planes = 1;
1326 
1327   if (header.cupsBitsPerColor >= 8)
1328     zoom_type = CUPS_IZOOM_NORMAL;
1329   else
1330     zoom_type = CUPS_IZOOM_FAST;
1331 
1332  /*
1333   * See if we need to collate, and if so how we need to do it...
1334   */
1335 
1336   if (xpages == 1 && ypages == 1)
1337     Collate = 0;
1338 
1339   slowcollate = Collate && ppdFindOption(ppd, "Collate") == NULL;
1340   if (ppd != NULL)
1341     slowcopies = ppd->manual_copies;
1342   else
1343     slowcopies = 1;
1344 
1345   if (Copies > 1 && !slowcollate && !slowcopies)
1346   {
1347     header.Collate   = (cups_bool_t)Collate;
1348     header.NumCopies = Copies;
1349 
1350     Copies = 1;
1351   }
1352   else
1353     header.NumCopies = 1;
1354 
1355  /*
1356   * Create the dithering lookup tables...
1357   */
1358 
1359   OnPixels[0]    = 0x00;
1360   OnPixels[255]  = 0xff;
1361   OffPixels[0]   = 0x00;
1362   OffPixels[255] = 0xff;
1363 
1364   switch (header.cupsBitsPerColor)
1365   {
1366     case 2 :
1367         for (i = 1; i < 255; i ++)
1368         {
1369           OnPixels[i]  = 0x55 * (i / 85 + 1);
1370           OffPixels[i] = 0x55 * (i / 64);
1371         }
1372         break;
1373     case 4 :
1374         for (i = 1; i < 255; i ++)
1375         {
1376           OnPixels[i]  = 17 * (i / 17 + 1);
1377           OffPixels[i] = 17 * (i / 16);
1378         }
1379         break;
1380   }
1381 
1382  /*
1383   * Output the pages...
1384   */
1385 
1386   fprintf(stderr, "DEBUG: cupsWidth = %d\n", header.cupsWidth);
1387   fprintf(stderr, "DEBUG: cupsHeight = %d\n", header.cupsHeight);
1388   fprintf(stderr, "DEBUG: cupsBitsPerColor = %d\n", header.cupsBitsPerColor);
1389   fprintf(stderr, "DEBUG: cupsBitsPerPixel = %d\n", header.cupsBitsPerPixel);
1390   fprintf(stderr, "DEBUG: cupsBytesPerLine = %d\n", header.cupsBytesPerLine);
1391   fprintf(stderr, "DEBUG: cupsColorOrder = %d\n", header.cupsColorOrder);
1392   fprintf(stderr, "DEBUG: cupsColorSpace = %d\n", header.cupsColorSpace);
1393   fprintf(stderr, "DEBUG: img->colorspace = %d\n", img->colorspace);
1394 
1395   row = malloc(2 * header.cupsBytesPerLine);
1396   ras = cupsRasterOpen(1, CUPS_RASTER_WRITE);
1397 
1398   for (i = 0, page = 1; i < Copies; i ++)
1399     for (xpage = 0; xpage < xpages; xpage ++)
1400       for (ypage = 0; ypage < ypages; ypage ++, page ++)
1401       {
1402         fprintf(stderr, "INFO: Formatting page %d.\n", page);
1403 
1404 	if (Orientation & 1)
1405 	{
1406 	  xc0    = img->xsize * ypage / ypages;
1407 	  xc1    = img->xsize * (ypage + 1) / ypages - 1;
1408 	  yc0    = img->ysize * xpage / xpages;
1409 	  yc1    = img->ysize * (xpage + 1) / xpages - 1;
1410 
1411 	  xtemp = header.HWResolution[0] * yprint;
1412 	  ytemp = header.HWResolution[1] * xprint;
1413 	}
1414 	else
1415 	{
1416 	  xc0    = img->xsize * xpage / xpages;
1417 	  xc1    = img->xsize * (xpage + 1) / xpages - 1;
1418 	  yc0    = img->ysize * ypage / ypages;
1419 	  yc1    = img->ysize * (ypage + 1) / ypages - 1;
1420 
1421 	  xtemp = header.HWResolution[0] * xprint;
1422 	  ytemp = header.HWResolution[1] * yprint;
1423         }
1424 
1425         cupsRasterWriteHeader2(ras, &header);
1426 
1427         for (plane = 0; plane < num_planes; plane ++)
1428 	{
1429 	 /*
1430 	  * Initialize the image "zoom" engine...
1431 	  */
1432 
1433           if (Flip)
1434 	    z = _cupsImageZoomNew(img, xc0, yc0, xc1, yc1, -xtemp, ytemp,
1435 	                          Orientation & 1, zoom_type);
1436           else
1437 	    z = _cupsImageZoomNew(img, xc0, yc0, xc1, yc1, xtemp, ytemp,
1438 	                          Orientation & 1, zoom_type);
1439 
1440          /*
1441 	  * Write leading blank space as needed...
1442 	  */
1443 
1444           if (header.cupsHeight > z->ysize && YPosition <= 0)
1445 	  {
1446 	    blank_line(&header, row);
1447 
1448             y = header.cupsHeight - z->ysize;
1449 	    if (YPosition == 0)
1450 	      y /= 2;
1451 
1452             fprintf(stderr, "DEBUG: Writing %d leading blank lines...\n", y);
1453 
1454 	    for (; y > 0; y --)
1455 	    {
1456 	      if (cupsRasterWritePixels(ras, row, header.cupsBytesPerLine) <
1457 	              header.cupsBytesPerLine)
1458 	      {
1459 		fputs("ERROR: Unable to send raster data to the driver.\n",
1460 		      stderr);
1461 		cupsImageClose(img);
1462 		exit(1);
1463 	      }
1464             }
1465 	  }
1466 
1467          /*
1468 	  * Then write image data...
1469 	  */
1470 
1471 	  for (y = z->ysize, yerr0 = 0, yerr1 = z->ysize, iy = 0, last_iy = -2;
1472                y > 0;
1473                y --)
1474 	  {
1475 	    if (iy != last_iy)
1476 	    {
1477 	      if (zoom_type != CUPS_IZOOM_FAST && (iy - last_iy) > 1)
1478         	_cupsImageZoomFill(z, iy);
1479 
1480               _cupsImageZoomFill(z, iy + z->yincr);
1481 
1482               last_iy = iy;
1483 	    }
1484 
1485            /*
1486 	    * Format this line of raster data for the printer...
1487 	    */
1488 
1489     	    blank_line(&header, row);
1490 
1491             r0 = z->rows[z->row];
1492             r1 = z->rows[1 - z->row];
1493 
1494             switch (header.cupsColorSpace)
1495 	    {
1496 	      case CUPS_CSPACE_W :
1497 	      case CUPS_CSPACE_SW :
1498 	          format_W(&header, row, y, plane, z->xsize, z->ysize,
1499 		           yerr0, yerr1, r0, r1);
1500 		  break;
1501               default :
1502 	      case CUPS_CSPACE_RGB :
1503 	      case CUPS_CSPACE_SRGB :
1504 	      case CUPS_CSPACE_ADOBERGB :
1505 	          format_RGB(&header, row, y, plane, z->xsize, z->ysize,
1506 		             yerr0, yerr1, r0, r1);
1507 		  break;
1508 	      case CUPS_CSPACE_RGBA :
1509 	      case CUPS_CSPACE_RGBW :
1510 	          format_RGBA(&header, row, y, plane, z->xsize, z->ysize,
1511 		              yerr0, yerr1, r0, r1);
1512 		  break;
1513 	      case CUPS_CSPACE_K :
1514 	      case CUPS_CSPACE_WHITE :
1515 	      case CUPS_CSPACE_GOLD :
1516 	      case CUPS_CSPACE_SILVER :
1517 	          format_K(&header, row, y, plane, z->xsize, z->ysize,
1518 		           yerr0, yerr1, r0, r1);
1519 		  break;
1520 	      case CUPS_CSPACE_CMY :
1521 	          format_CMY(&header, row, y, plane, z->xsize, z->ysize,
1522 		             yerr0, yerr1, r0, r1);
1523 		  break;
1524 	      case CUPS_CSPACE_YMC :
1525 	          format_YMC(&header, row, y, plane, z->xsize, z->ysize,
1526 		             yerr0, yerr1, r0, r1);
1527 		  break;
1528 	      case CUPS_CSPACE_CMYK :
1529 	          format_CMYK(&header, row, y, plane, z->xsize, z->ysize,
1530 		              yerr0, yerr1, r0, r1);
1531 		  break;
1532 	      case CUPS_CSPACE_YMCK :
1533 	      case CUPS_CSPACE_GMCK :
1534 	      case CUPS_CSPACE_GMCS :
1535 	          format_YMCK(&header, row, y, plane, z->xsize, z->ysize,
1536 		              yerr0, yerr1, r0, r1);
1537 		  break;
1538 	      case CUPS_CSPACE_KCMYcm :
1539 	          if (header.cupsBitsPerColor == 1)
1540 		  {
1541 	            format_KCMYcm(&header, row, y, plane, z->xsize, z->ysize,
1542 		                  yerr0, yerr1, r0, r1);
1543 		    break;
1544 		  }
1545 	      case CUPS_CSPACE_KCMY :
1546 	          format_KCMY(&header, row, y, plane, z->xsize, z->ysize,
1547 		              yerr0, yerr1, r0, r1);
1548 		  break;
1549 	    }
1550 
1551            /*
1552 	    * Write the raster data to the driver...
1553 	    */
1554 
1555 	    if (cupsRasterWritePixels(ras, row, header.cupsBytesPerLine) <
1556 	                              header.cupsBytesPerLine)
1557 	    {
1558 	      fputs("ERROR: Unable to send raster data to the driver.\n",
1559 	            stderr);
1560 	      cupsImageClose(img);
1561 	      exit(1);
1562 	    }
1563 
1564            /*
1565 	    * Compute the next scanline in the image...
1566 	    */
1567 
1568 	    iy    += z->ystep;
1569 	    yerr0 += z->ymod;
1570 	    yerr1 -= z->ymod;
1571 	    if (yerr1 <= 0)
1572 	    {
1573               yerr0 -= z->ysize;
1574               yerr1 += z->ysize;
1575               iy    += z->yincr;
1576 	    }
1577 	  }
1578 
1579          /*
1580 	  * Write trailing blank space as needed...
1581 	  */
1582 
1583           if (header.cupsHeight > z->ysize && YPosition >= 0)
1584 	  {
1585 	    blank_line(&header, row);
1586 
1587             y = header.cupsHeight - z->ysize;
1588 	    if (YPosition == 0)
1589 	      y = y - y / 2;
1590 
1591             fprintf(stderr, "DEBUG: Writing %d trailing blank lines...\n", y);
1592 
1593 	    for (; y > 0; y --)
1594 	    {
1595 	      if (cupsRasterWritePixels(ras, row, header.cupsBytesPerLine) <
1596 	              header.cupsBytesPerLine)
1597 	      {
1598 		fputs("ERROR: Unable to send raster data to the driver.\n",
1599 		      stderr);
1600 		cupsImageClose(img);
1601 		exit(1);
1602 	      }
1603             }
1604 	  }
1605 
1606          /*
1607 	  * Free memory used for the "zoom" engine...
1608 	  */
1609 
1610           _cupsImageZoomDelete(z);
1611         }
1612       }
1613 
1614  /*
1615   * Close files...
1616   */
1617 
1618   free(row);
1619   cupsRasterClose(ras);
1620   cupsImageClose(img);
1621   ppdClose(ppd);
1622 
1623   return (0);
1624 }
1625 
1626 
1627 /*
1628  * 'blank_line()' - Clear a line buffer to the blank value...
1629  */
1630 
1631 static void
blank_line(cups_page_header2_t * header,unsigned char * row)1632 blank_line(cups_page_header2_t *header,	/* I - Page header */
1633            unsigned char       *row)	/* I - Row buffer */
1634 {
1635   int	count;				/* Remaining bytes */
1636 
1637 
1638   count = header->cupsBytesPerLine;
1639 
1640   switch (header->cupsColorSpace)
1641   {
1642     case CUPS_CSPACE_CIEXYZ :
1643         while (count > 2)
1644 	{
1645 	  *row++ = 242;
1646 	  *row++ = 255;
1647 	  *row++ = 255;
1648 	  count -= 3;
1649 	}
1650 	break;
1651 
1652     case CUPS_CSPACE_CIELab :
1653     case CUPS_CSPACE_ICC1 :
1654     case CUPS_CSPACE_ICC2 :
1655     case CUPS_CSPACE_ICC3 :
1656     case CUPS_CSPACE_ICC4 :
1657     case CUPS_CSPACE_ICC5 :
1658     case CUPS_CSPACE_ICC6 :
1659     case CUPS_CSPACE_ICC7 :
1660     case CUPS_CSPACE_ICC8 :
1661     case CUPS_CSPACE_ICC9 :
1662     case CUPS_CSPACE_ICCA :
1663     case CUPS_CSPACE_ICCB :
1664     case CUPS_CSPACE_ICCC :
1665     case CUPS_CSPACE_ICCD :
1666     case CUPS_CSPACE_ICCE :
1667     case CUPS_CSPACE_ICCF :
1668         while (count > 2)
1669 	{
1670 	  *row++ = 255;
1671 	  *row++ = 128;
1672 	  *row++ = 128;
1673 	  count -= 3;
1674 	}
1675         break;
1676 
1677     case CUPS_CSPACE_K :
1678     case CUPS_CSPACE_CMY :
1679     case CUPS_CSPACE_CMYK :
1680     case CUPS_CSPACE_YMC :
1681     case CUPS_CSPACE_YMCK :
1682     case CUPS_CSPACE_KCMY :
1683     case CUPS_CSPACE_KCMYcm :
1684     case CUPS_CSPACE_GMCK :
1685     case CUPS_CSPACE_GMCS :
1686     case CUPS_CSPACE_WHITE :
1687     case CUPS_CSPACE_GOLD :
1688     case CUPS_CSPACE_SILVER :
1689         memset(row, 0, count);
1690 	break;
1691 
1692     default :
1693         memset(row, 255, count);
1694 	break;
1695   }
1696 }
1697 
1698 
1699 /*
1700  * 'format_CMY()' - Convert image data to CMY.
1701  */
1702 
1703 static void
format_CMY(cups_page_header2_t * header,unsigned char * row,int y,int z,int xsize,int ysize,int yerr0,int yerr1,cups_ib_t * r0,cups_ib_t * r1)1704 format_CMY(cups_page_header2_t *header,	/* I - Page header */
1705             unsigned char      *row,	/* IO - Bitmap data for device */
1706 	    int                y,	/* I - Current row */
1707 	    int                z,	/* I - Current plane */
1708 	    int                xsize,	/* I - Width of image data */
1709 	    int	               ysize,	/* I - Height of image data */
1710 	    int                yerr0,	/* I - Top Y error */
1711 	    int                yerr1,	/* I - Bottom Y error */
1712 	    cups_ib_t          *r0,	/* I - Primary image data */
1713 	    cups_ib_t          *r1)	/* I - Image data for interpolation */
1714 {
1715   cups_ib_t	*ptr,			/* Pointer into row */
1716 		*cptr,			/* Pointer into cyan */
1717 		*mptr,			/* Pointer into magenta */
1718 		*yptr,			/* Pointer into yellow */
1719 		bitmask;		/* Current mask for pixel */
1720   int		bitoffset;		/* Current offset in line */
1721   int		bandwidth;		/* Width of a color band */
1722   int		x,			/* Current X coordinate on page */
1723 		*dither;		/* Pointer into dither array */
1724 
1725 
1726   switch (XPosition)
1727   {
1728     case -1 :
1729         bitoffset = 0;
1730 	break;
1731     default :
1732         bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
1733 	break;
1734     case 1 :
1735         bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
1736 	break;
1737   }
1738 
1739   ptr       = row + bitoffset / 8;
1740   bandwidth = header->cupsBytesPerLine / 3;
1741 
1742   switch (header->cupsColorOrder)
1743   {
1744     case CUPS_ORDER_CHUNKED :
1745         switch (header->cupsBitsPerColor)
1746         {
1747           case 1 :
1748               bitmask = 64 >> (bitoffset & 7);
1749 	      dither  = Floyd16x16[y & 15];
1750 
1751               for (x = xsize ; x > 0; x --)
1752               {
1753 	        if (*r0++ > dither[x & 15])
1754 		  *ptr ^= bitmask;
1755 		bitmask >>= 1;
1756 
1757 	        if (*r0++ > dither[x & 15])
1758 		  *ptr ^= bitmask;
1759 		bitmask >>= 1;
1760 
1761 	        if (*r0++ > dither[x & 15])
1762 		  *ptr ^= bitmask;
1763 
1764                 if (bitmask > 1)
1765 		  bitmask >>= 2;
1766 		else
1767         	{
1768         	  bitmask = 64;
1769         	  ptr ++;
1770         	}
1771               }
1772               break;
1773 
1774           case 2 :
1775 	      dither = Floyd8x8[y & 7];
1776 
1777               for (x = xsize ; x > 0; x --, r0 += 3)
1778               {
1779 	       	if ((r0[0] & 63) > dither[x & 7])
1780         	  *ptr ^= (0x30 & OnPixels[r0[0]]);
1781         	else
1782         	  *ptr ^= (0x30 & OffPixels[r0[0]]);
1783 
1784         	if ((r0[1] & 63) > dither[x & 7])
1785         	  *ptr ^= (0x0c & OnPixels[r0[1]]);
1786         	else
1787         	  *ptr ^= (0x0c & OffPixels[r0[1]]);
1788 
1789         	if ((r0[2] & 63) > dither[x & 7])
1790         	  *ptr++ ^= (0x03 & OnPixels[r0[2]]);
1791         	else
1792         	  *ptr++ ^= (0x03 & OffPixels[r0[2]]);
1793               }
1794               break;
1795 
1796           case 4 :
1797 	      dither = Floyd4x4[y & 3];
1798 
1799               for (x = xsize ; x > 0; x --, r0 += 3)
1800               {
1801         	if ((r0[0] & 15) > dither[x & 3])
1802         	  *ptr++ ^= (0x0f & OnPixels[r0[0]]);
1803         	else
1804         	  *ptr++ ^= (0x0f & OffPixels[r0[0]]);
1805 
1806         	if ((r0[1] & 15) > dither[x & 3])
1807         	  *ptr ^= (0xf0 & OnPixels[r0[1]]);
1808         	else
1809         	  *ptr ^= (0xf0 & OffPixels[r0[1]]);
1810 
1811         	if ((r0[2] & 15) > dither[x & 3])
1812         	  *ptr++ ^= (0x0f & OnPixels[r0[2]]);
1813         	else
1814         	  *ptr++ ^= (0x0f & OffPixels[r0[2]]);
1815               }
1816               break;
1817 
1818           case 8 :
1819               for (x = xsize  * 3; x > 0; x --, r0 ++, r1 ++)
1820         	if (*r0 == *r1)
1821                   *ptr++ = *r0;
1822         	else
1823                   *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
1824               break;
1825         }
1826         break;
1827 
1828     case CUPS_ORDER_BANDED :
1829 	cptr = ptr;
1830 	mptr = ptr + bandwidth;
1831 	yptr = ptr + 2 * bandwidth;
1832 
1833         switch (header->cupsBitsPerColor)
1834         {
1835           case 1 :
1836               bitmask = 0x80 >> (bitoffset & 7);
1837 	      dither  = Floyd16x16[y & 15];
1838 
1839               for (x = xsize; x > 0; x --)
1840               {
1841         	if (*r0++ > dither[x & 15])
1842         	  *cptr ^= bitmask;
1843         	if (*r0++ > dither[x & 15])
1844         	  *mptr ^= bitmask;
1845         	if (*r0++ > dither[x & 15])
1846         	  *yptr ^= bitmask;
1847 
1848                 if (bitmask > 1)
1849 		  bitmask >>= 1;
1850 		else
1851 		{
1852 		  bitmask = 0x80;
1853 		  cptr ++;
1854 		  mptr ++;
1855 		  yptr ++;
1856         	}
1857 	      }
1858               break;
1859 
1860           case 2 :
1861               bitmask = 0xc0 >> (bitoffset & 7);
1862 	      dither  = Floyd8x8[y & 7];
1863 
1864               for (x = xsize; x > 0; x --)
1865               {
1866         	if ((*r0 & 63) > dither[x & 7])
1867         	  *cptr ^= (bitmask & OnPixels[*r0++]);
1868         	else
1869         	  *cptr ^= (bitmask & OffPixels[*r0++]);
1870 
1871         	if ((*r0 & 63) > dither[x & 7])
1872         	  *mptr ^= (bitmask & OnPixels[*r0++]);
1873         	else
1874         	  *mptr ^= (bitmask & OffPixels[*r0++]);
1875 
1876         	if ((*r0 & 63) > dither[x & 7])
1877         	  *yptr ^= (bitmask & OnPixels[*r0++]);
1878         	else
1879         	  *yptr ^= (bitmask & OffPixels[*r0++]);
1880 
1881                 if (bitmask > 3)
1882 		  bitmask >>= 2;
1883 		else
1884 		{
1885 		  bitmask = 0xc0;
1886 
1887 		  cptr ++;
1888 		  mptr ++;
1889 		  yptr ++;
1890         	}
1891 	      }
1892               break;
1893 
1894           case 4 :
1895               bitmask = 0xf0 >> (bitoffset & 7);
1896 	      dither  = Floyd4x4[y & 3];
1897 
1898               for (x = xsize; x > 0; x --)
1899               {
1900         	if ((*r0 & 15) > dither[x & 3])
1901         	  *cptr ^= (bitmask & OnPixels[*r0++]);
1902         	else
1903         	  *cptr ^= (bitmask & OffPixels[*r0++]);
1904 
1905         	if ((*r0 & 15) > dither[x & 3])
1906         	  *mptr ^= (bitmask & OnPixels[*r0++]);
1907         	else
1908         	  *mptr ^= (bitmask & OffPixels[*r0++]);
1909 
1910         	if ((*r0 & 15) > dither[x & 3])
1911         	  *yptr ^= (bitmask & OnPixels[*r0++]);
1912         	else
1913         	  *yptr ^= (bitmask & OffPixels[*r0++]);
1914 
1915                 if (bitmask == 0xf0)
1916 		  bitmask = 0x0f;
1917 		else
1918 		{
1919 		  bitmask = 0xf0;
1920 
1921 		  cptr ++;
1922 		  mptr ++;
1923 		  yptr ++;
1924         	}
1925 	      }
1926               break;
1927 
1928           case 8 :
1929               for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
1930 	      {
1931         	if (r0[0] == r1[0])
1932                   *cptr++ = r0[0];
1933         	else
1934                   *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
1935 
1936         	if (r0[1] == r1[1])
1937                   *mptr++ = r0[1];
1938         	else
1939                   *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
1940 
1941         	if (r0[2] == r1[2])
1942                   *yptr++ = r0[2];
1943         	else
1944                   *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
1945               }
1946               break;
1947         }
1948         break;
1949 
1950     case CUPS_ORDER_PLANAR :
1951         switch (header->cupsBitsPerColor)
1952         {
1953           case 1 :
1954               bitmask = 0x80 >> (bitoffset & 7);
1955 	      dither  = Floyd16x16[y & 15];
1956 
1957               switch (z)
1958 	      {
1959 	        case 0 :
1960         	    for (x = xsize; x > 0; x --, r0 += 3)
1961         	    {
1962         	      if (r0[0] > dither[x & 15])
1963         		*ptr ^= bitmask;
1964 
1965                       if (bitmask > 1)
1966 			bitmask >>= 1;
1967 		      else
1968 		      {
1969 			bitmask = 0x80;
1970 			ptr ++;
1971         	      }
1972 	            }
1973 		    break;
1974 
1975 	        case 1 :
1976         	    for (x = xsize; x > 0; x --, r0 += 3)
1977         	    {
1978         	      if (r0[1] > dither[x & 15])
1979         		*ptr ^= bitmask;
1980 
1981                       if (bitmask > 1)
1982 			bitmask >>= 1;
1983 		      else
1984 		      {
1985 			bitmask = 0x80;
1986 			ptr ++;
1987         	      }
1988 	            }
1989 		    break;
1990 
1991 	        case 2 :
1992         	    for (x = xsize; x > 0; x --, r0 += 3)
1993         	    {
1994         	      if (r0[2] > dither[x & 15])
1995         		*ptr ^= bitmask;
1996 
1997                       if (bitmask > 1)
1998 			bitmask >>= 1;
1999 		      else
2000 		      {
2001 			bitmask = 0x80;
2002 			ptr ++;
2003         	      }
2004 	            }
2005 		    break;
2006 	      }
2007               break;
2008 
2009           case 2 :
2010               bitmask = 0xc0 >> (bitoffset & 7);
2011 	      dither  = Floyd8x8[y & 7];
2012               r0 += z;
2013 
2014               for (x = xsize; x > 0; x --, r0 += 3)
2015               {
2016         	if ((*r0 & 63) > dither[x & 7])
2017         	  *ptr ^= (bitmask & OnPixels[*r0]);
2018         	else
2019         	  *ptr ^= (bitmask & OffPixels[*r0]);
2020 
2021                 if (bitmask > 3)
2022 		  bitmask >>= 2;
2023 		else
2024 		{
2025 		  bitmask = 0xc0;
2026 
2027 		  ptr ++;
2028         	}
2029 	      }
2030               break;
2031 
2032           case 4 :
2033               bitmask = 0xf0 >> (bitoffset & 7);
2034 	      dither  = Floyd4x4[y & 3];
2035               r0 += z;
2036 
2037               for (x = xsize; x > 0; x --, r0 += 3)
2038               {
2039         	if ((*r0 & 15) > dither[x & 3])
2040         	  *ptr ^= (bitmask & OnPixels[*r0]);
2041         	else
2042         	  *ptr ^= (bitmask & OffPixels[*r0]);
2043 
2044                 if (bitmask == 0xf0)
2045 		  bitmask = 0x0f;
2046 		else
2047 		{
2048 		  bitmask = 0xf0;
2049 
2050 		  ptr ++;
2051         	}
2052 	      }
2053               break;
2054 
2055           case 8 :
2056               r0 += z;
2057 	      r1 += z;
2058 
2059               for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
2060 	      {
2061         	if (*r0 == *r1)
2062                   *ptr++ = *r0;
2063         	else
2064                   *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
2065               }
2066               break;
2067         }
2068         break;
2069   }
2070 }
2071 
2072 
2073 /*
2074  * 'format_CMYK()' - Convert image data to CMYK.
2075  */
2076 
2077 static void
format_CMYK(cups_page_header2_t * header,unsigned char * row,int y,int z,int xsize,int ysize,int yerr0,int yerr1,cups_ib_t * r0,cups_ib_t * r1)2078 format_CMYK(cups_page_header2_t *header,/* I - Page header */
2079             unsigned char       *row,	/* IO - Bitmap data for device */
2080 	    int                 y,	/* I - Current row */
2081 	    int                 z,	/* I - Current plane */
2082 	    int                 xsize,	/* I - Width of image data */
2083 	    int	                ysize,	/* I - Height of image data */
2084 	    int                 yerr0,	/* I - Top Y error */
2085 	    int                 yerr1,	/* I - Bottom Y error */
2086 	    cups_ib_t           *r0,	/* I - Primary image data */
2087 	    cups_ib_t           *r1)	/* I - Image data for interpolation */
2088 {
2089   cups_ib_t	*ptr,			/* Pointer into row */
2090 		*cptr,			/* Pointer into cyan */
2091 		*mptr,			/* Pointer into magenta */
2092 		*yptr,			/* Pointer into yellow */
2093 		*kptr,			/* Pointer into black */
2094 		bitmask;		/* Current mask for pixel */
2095   int		bitoffset;		/* Current offset in line */
2096   int		bandwidth;		/* Width of a color band */
2097   int		x,			/* Current X coordinate on page */
2098 		*dither;		/* Pointer into dither array */
2099   int		pc, pm, py;		/* CMY pixels */
2100 
2101 
2102   switch (XPosition)
2103   {
2104     case -1 :
2105         bitoffset = 0;
2106 	break;
2107     default :
2108         bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
2109 	break;
2110     case 1 :
2111         bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
2112 	break;
2113   }
2114 
2115   ptr       = row + bitoffset / 8;
2116   bandwidth = header->cupsBytesPerLine / 4;
2117 
2118   switch (header->cupsColorOrder)
2119   {
2120     case CUPS_ORDER_CHUNKED :
2121         switch (header->cupsBitsPerColor)
2122         {
2123           case 1 :
2124               bitmask = 128 >> (bitoffset & 7);
2125 	      dither  = Floyd16x16[y & 15];
2126 
2127               for (x = xsize ; x > 0; x --)
2128               {
2129 	        pc = *r0++ > dither[x & 15];
2130 		pm = *r0++ > dither[x & 15];
2131 		py = *r0++ > dither[x & 15];
2132 
2133 		if (pc && pm && py)
2134 		{
2135 		  bitmask >>= 3;
2136 		  *ptr ^= bitmask;
2137 		}
2138 		else
2139 		{
2140 		  if (pc)
2141 		    *ptr ^= bitmask;
2142 		  bitmask >>= 1;
2143 
2144 		  if (pm)
2145 		    *ptr ^= bitmask;
2146 		  bitmask >>= 1;
2147 
2148 		  if (py)
2149 		    *ptr ^= bitmask;
2150 		  bitmask >>= 1;
2151                 }
2152 
2153                 if (bitmask > 1)
2154 		  bitmask >>= 1;
2155 		else
2156         	{
2157         	  bitmask = 128;
2158         	  ptr ++;
2159         	}
2160               }
2161               break;
2162 
2163           case 2 :
2164 	      dither = Floyd8x8[y & 7];
2165 
2166               for (x = xsize ; x > 0; x --, r0 += 4)
2167               {
2168 	       	if ((r0[0] & 63) > dither[x & 7])
2169         	  *ptr ^= (0xc0 & OnPixels[r0[0]]);
2170         	else
2171         	  *ptr ^= (0xc0 & OffPixels[r0[0]]);
2172 
2173         	if ((r0[1] & 63) > dither[x & 7])
2174         	  *ptr ^= (0x30 & OnPixels[r0[1]]);
2175         	else
2176         	  *ptr ^= (0x30 & OffPixels[r0[1]]);
2177 
2178         	if ((r0[2] & 63) > dither[x & 7])
2179         	  *ptr ^= (0x0c & OnPixels[r0[2]]);
2180         	else
2181         	  *ptr ^= (0x0c & OffPixels[r0[2]]);
2182 
2183         	if ((r0[3] & 63) > dither[x & 7])
2184         	  *ptr++ ^= (0x03 & OnPixels[r0[3]]);
2185         	else
2186         	  *ptr++ ^= (0x03 & OffPixels[r0[3]]);
2187               }
2188               break;
2189 
2190           case 4 :
2191 	      dither = Floyd4x4[y & 3];
2192 
2193               for (x = xsize ; x > 0; x --, r0 += 4)
2194               {
2195         	if ((r0[0] & 15) > dither[x & 3])
2196         	  *ptr ^= (0xf0 & OnPixels[r0[0]]);
2197         	else
2198         	  *ptr ^= (0xf0 & OffPixels[r0[0]]);
2199 
2200         	if ((r0[1] & 15) > dither[x & 3])
2201         	  *ptr++ ^= (0x0f & OnPixels[r0[1]]);
2202         	else
2203         	  *ptr++ ^= (0x0f & OffPixels[r0[1]]);
2204 
2205         	if ((r0[2] & 15) > dither[x & 3])
2206         	  *ptr ^= (0xf0 & OnPixels[r0[2]]);
2207         	else
2208         	  *ptr ^= (0xf0 & OffPixels[r0[2]]);
2209 
2210         	if ((r0[3] & 15) > dither[x & 3])
2211         	  *ptr++ ^= (0x0f & OnPixels[r0[3]]);
2212         	else
2213         	  *ptr++ ^= (0x0f & OffPixels[r0[3]]);
2214               }
2215               break;
2216 
2217           case 8 :
2218               for (x = xsize  * 4; x > 0; x --, r0 ++, r1 ++)
2219         	if (*r0 == *r1)
2220                   *ptr++ = *r0;
2221         	else
2222                   *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
2223               break;
2224         }
2225         break;
2226 
2227     case CUPS_ORDER_BANDED :
2228 	cptr = ptr;
2229 	mptr = ptr + bandwidth;
2230 	yptr = ptr + 2 * bandwidth;
2231 	kptr = ptr + 3 * bandwidth;
2232 
2233         switch (header->cupsBitsPerColor)
2234         {
2235           case 1 :
2236               bitmask = 0x80 >> (bitoffset & 7);
2237 	      dither  = Floyd16x16[y & 15];
2238 
2239               for (x = xsize; x > 0; x --)
2240               {
2241 	        pc = *r0++ > dither[x & 15];
2242 		pm = *r0++ > dither[x & 15];
2243 		py = *r0++ > dither[x & 15];
2244 
2245 		if (pc && pm && py)
2246 		  *kptr ^= bitmask;
2247 		else
2248 		{
2249 		  if (pc)
2250         	    *cptr ^= bitmask;
2251 		  if (pm)
2252         	    *mptr ^= bitmask;
2253 		  if (py)
2254         	    *yptr ^= bitmask;
2255                 }
2256 
2257                 if (bitmask > 1)
2258 		  bitmask >>= 1;
2259 		else
2260 		{
2261 		  bitmask = 0x80;
2262 		  cptr ++;
2263 		  mptr ++;
2264 		  yptr ++;
2265 		  kptr ++;
2266         	}
2267 	      }
2268               break;
2269 
2270           case 2 :
2271               bitmask = 0xc0 >> (bitoffset & 7);
2272 	      dither  = Floyd8x8[y & 7];
2273 
2274               for (x = xsize; x > 0; x --)
2275               {
2276         	if ((*r0 & 63) > dither[x & 7])
2277         	  *cptr ^= (bitmask & OnPixels[*r0++]);
2278         	else
2279         	  *cptr ^= (bitmask & OffPixels[*r0++]);
2280 
2281         	if ((*r0 & 63) > dither[x & 7])
2282         	  *mptr ^= (bitmask & OnPixels[*r0++]);
2283         	else
2284         	  *mptr ^= (bitmask & OffPixels[*r0++]);
2285 
2286         	if ((*r0 & 63) > dither[x & 7])
2287         	  *yptr ^= (bitmask & OnPixels[*r0++]);
2288         	else
2289         	  *yptr ^= (bitmask & OffPixels[*r0++]);
2290 
2291         	if ((*r0 & 63) > dither[x & 7])
2292         	  *kptr ^= (bitmask & OnPixels[*r0++]);
2293         	else
2294         	  *kptr ^= (bitmask & OffPixels[*r0++]);
2295 
2296                 if (bitmask > 3)
2297 		  bitmask >>= 2;
2298 		else
2299 		{
2300 		  bitmask = 0xc0;
2301 
2302 		  cptr ++;
2303 		  mptr ++;
2304 		  yptr ++;
2305 		  kptr ++;
2306         	}
2307 	      }
2308               break;
2309 
2310           case 4 :
2311               bitmask = 0xf0 >> (bitoffset & 7);
2312 	      dither  = Floyd4x4[y & 3];
2313 
2314               for (x = xsize; x > 0; x --)
2315               {
2316         	if ((*r0 & 15) > dither[x & 3])
2317         	  *cptr ^= (bitmask & OnPixels[*r0++]);
2318         	else
2319         	  *cptr ^= (bitmask & OffPixels[*r0++]);
2320 
2321         	if ((*r0 & 15) > dither[x & 3])
2322         	  *mptr ^= (bitmask & OnPixels[*r0++]);
2323         	else
2324         	  *mptr ^= (bitmask & OffPixels[*r0++]);
2325 
2326         	if ((*r0 & 15) > dither[x & 3])
2327         	  *yptr ^= (bitmask & OnPixels[*r0++]);
2328         	else
2329         	  *yptr ^= (bitmask & OffPixels[*r0++]);
2330 
2331         	if ((*r0 & 15) > dither[x & 3])
2332         	  *kptr ^= (bitmask & OnPixels[*r0++]);
2333         	else
2334         	  *kptr ^= (bitmask & OffPixels[*r0++]);
2335 
2336                 if (bitmask == 0xf0)
2337 		  bitmask = 0x0f;
2338 		else
2339 		{
2340 		  bitmask = 0xf0;
2341 
2342 		  cptr ++;
2343 		  mptr ++;
2344 		  yptr ++;
2345 		  kptr ++;
2346         	}
2347 	      }
2348               break;
2349 
2350           case 8 :
2351               for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
2352 	      {
2353         	if (r0[0] == r1[0])
2354                   *cptr++ = r0[0];
2355         	else
2356                   *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
2357 
2358         	if (r0[1] == r1[1])
2359                   *mptr++ = r0[1];
2360         	else
2361                   *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
2362 
2363         	if (r0[2] == r1[2])
2364                   *yptr++ = r0[2];
2365         	else
2366                   *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
2367 
2368         	if (r0[3] == r1[3])
2369                   *kptr++ = r0[3];
2370         	else
2371                   *kptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
2372               }
2373               break;
2374         }
2375         break;
2376 
2377     case CUPS_ORDER_PLANAR :
2378         switch (header->cupsBitsPerColor)
2379         {
2380           case 1 :
2381               bitmask = 0x80 >> (bitoffset & 7);
2382 	      dither  = Floyd16x16[y & 15];
2383 
2384               for (x = xsize; x > 0; x --)
2385               {
2386 	        pc = *r0++ > dither[x & 15];
2387 		pm = *r0++ > dither[x & 15];
2388 		py = *r0++ > dither[x & 15];
2389 
2390 		if ((pc && pm && py && z == 3) ||
2391 		    (pc && z == 0) || (pm && z == 1) || (py && z == 2))
2392         	  *ptr ^= bitmask;
2393 
2394                 if (bitmask > 1)
2395 		  bitmask >>= 1;
2396 		else
2397 		{
2398 		  bitmask = 0x80;
2399 		  ptr ++;
2400         	}
2401 	      }
2402 	      break;
2403 
2404           case 2 :
2405               bitmask = 0xc0 >> (bitoffset & 7);
2406 	      dither  = Floyd8x8[y & 7];
2407               r0      += z;
2408 
2409               for (x = xsize; x > 0; x --, r0 += 4)
2410               {
2411         	if ((*r0 & 63) > dither[x & 7])
2412         	  *ptr ^= (bitmask & OnPixels[*r0]);
2413         	else
2414         	  *ptr ^= (bitmask & OffPixels[*r0]);
2415 
2416                 if (bitmask > 3)
2417 		  bitmask >>= 2;
2418 		else
2419 		{
2420 		  bitmask = 0xc0;
2421 
2422 		  ptr ++;
2423         	}
2424 	      }
2425               break;
2426 
2427           case 4 :
2428               bitmask = 0xf0 >> (bitoffset & 7);
2429 	      dither  = Floyd4x4[y & 3];
2430               r0 += z;
2431 
2432               for (x = xsize; x > 0; x --, r0 += 4)
2433               {
2434         	if ((*r0 & 15) > dither[x & 3])
2435         	  *ptr ^= (bitmask & OnPixels[*r0]);
2436         	else
2437         	  *ptr ^= (bitmask & OffPixels[*r0]);
2438 
2439                 if (bitmask == 0xf0)
2440 		  bitmask = 0x0f;
2441 		else
2442 		{
2443 		  bitmask = 0xf0;
2444 
2445 		  ptr ++;
2446         	}
2447 	      }
2448               break;
2449 
2450           case 8 :
2451               r0 += z;
2452 	      r1 += z;
2453 
2454               for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
2455 	      {
2456         	if (*r0 == *r1)
2457                   *ptr++ = *r0;
2458         	else
2459                   *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
2460               }
2461               break;
2462         }
2463         break;
2464   }
2465 }
2466 
2467 
2468 /*
2469  * 'format_K()' - Convert image data to black.
2470  */
2471 
2472 static void
format_K(cups_page_header2_t * header,unsigned char * row,int y,int z,int xsize,int ysize,int yerr0,int yerr1,cups_ib_t * r0,cups_ib_t * r1)2473 format_K(cups_page_header2_t *header,	/* I - Page header */
2474          unsigned char       *row,	/* IO - Bitmap data for device */
2475 	 int                 y,		/* I - Current row */
2476 	 int                 z,		/* I - Current plane */
2477 	 int                 xsize,	/* I - Width of image data */
2478 	 int	             ysize,	/* I - Height of image data */
2479 	 int                 yerr0,	/* I - Top Y error */
2480 	 int                 yerr1,	/* I - Bottom Y error */
2481 	 cups_ib_t           *r0,	/* I - Primary image data */
2482 	 cups_ib_t           *r1)	/* I - Image data for interpolation */
2483 {
2484   cups_ib_t	*ptr,			/* Pointer into row */
2485 		bitmask;		/* Current mask for pixel */
2486   int		bitoffset;		/* Current offset in line */
2487   int		x,			/* Current X coordinate on page */
2488 		*dither;		/* Pointer into dither array */
2489 
2490 
2491   (void)z;
2492 
2493   switch (XPosition)
2494   {
2495     case -1 :
2496         bitoffset = 0;
2497 	break;
2498     default :
2499         bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
2500 	break;
2501     case 1 :
2502         bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
2503 	break;
2504   }
2505 
2506   ptr = row + bitoffset / 8;
2507 
2508   switch (header->cupsBitsPerColor)
2509   {
2510     case 1 :
2511         bitmask = 0x80 >> (bitoffset & 7);
2512         dither  = Floyd16x16[y & 15];
2513 
2514         for (x = xsize; x > 0; x --)
2515         {
2516           if (*r0++ > dither[x & 15])
2517             *ptr ^= bitmask;
2518 
2519           if (bitmask > 1)
2520 	    bitmask >>= 1;
2521 	  else
2522 	  {
2523 	    bitmask = 0x80;
2524 	    ptr ++;
2525           }
2526 	}
2527         break;
2528 
2529     case 2 :
2530         bitmask = 0xc0 >> (bitoffset & 7);
2531         dither  = Floyd8x8[y & 7];
2532 
2533         for (x = xsize; x > 0; x --)
2534         {
2535           if ((*r0 & 63) > dither[x & 7])
2536             *ptr ^= (bitmask & OnPixels[*r0++]);
2537           else
2538             *ptr ^= (bitmask & OffPixels[*r0++]);
2539 
2540           if (bitmask > 3)
2541 	    bitmask >>= 2;
2542 	  else
2543 	  {
2544 	    bitmask = 0xc0;
2545 
2546 	    ptr ++;
2547           }
2548 	}
2549         break;
2550 
2551     case 4 :
2552         bitmask = 0xf0 >> (bitoffset & 7);
2553         dither  = Floyd4x4[y & 3];
2554 
2555         for (x = xsize; x > 0; x --)
2556         {
2557           if ((*r0 & 15) > dither[x & 3])
2558             *ptr ^= (bitmask & OnPixels[*r0++]);
2559           else
2560             *ptr ^= (bitmask & OffPixels[*r0++]);
2561 
2562           if (bitmask == 0xf0)
2563 	    bitmask = 0x0f;
2564 	  else
2565 	  {
2566 	    bitmask = 0xf0;
2567 
2568 	    ptr ++;
2569           }
2570 	}
2571         break;
2572 
2573     case 8 :
2574         for (x = xsize; x > 0; x --, r0 ++, r1 ++)
2575 	{
2576           if (*r0 == *r1)
2577             *ptr++ = *r0;
2578           else
2579             *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
2580         }
2581         break;
2582   }
2583 }
2584 
2585 
2586 /*
2587  * 'format_KCMY()' - Convert image data to KCMY.
2588  */
2589 
2590 static void
format_KCMY(cups_page_header2_t * header,unsigned char * row,int y,int z,int xsize,int ysize,int yerr0,int yerr1,cups_ib_t * r0,cups_ib_t * r1)2591 format_KCMY(cups_page_header2_t *header,/* I - Page header */
2592             unsigned char       *row,	/* IO - Bitmap data for device */
2593 	    int                 y,	/* I - Current row */
2594 	    int                 z,	/* I - Current plane */
2595 	    int                 xsize,	/* I - Width of image data */
2596 	    int	                ysize,	/* I - Height of image data */
2597 	    int                 yerr0,	/* I - Top Y error */
2598 	    int                 yerr1,	/* I - Bottom Y error */
2599 	    cups_ib_t           *r0,	/* I - Primary image data */
2600 	    cups_ib_t           *r1)	/* I - Image data for interpolation */
2601 {
2602   cups_ib_t	*ptr,			/* Pointer into row */
2603 		*cptr,			/* Pointer into cyan */
2604 		*mptr,			/* Pointer into magenta */
2605 		*yptr,			/* Pointer into yellow */
2606 		*kptr,			/* Pointer into black */
2607 		bitmask;		/* Current mask for pixel */
2608   int		bitoffset;		/* Current offset in line */
2609   int		bandwidth;		/* Width of a color band */
2610   int		x,			/* Current X coordinate on page */
2611 		*dither;		/* Pointer into dither array */
2612   int		pc, pm, py;		/* CMY pixels */
2613 
2614 
2615   switch (XPosition)
2616   {
2617     case -1 :
2618         bitoffset = 0;
2619 	break;
2620     default :
2621         bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
2622 	break;
2623     case 1 :
2624         bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
2625 	break;
2626   }
2627 
2628   ptr       = row + bitoffset / 8;
2629   bandwidth = header->cupsBytesPerLine / 4;
2630 
2631   switch (header->cupsColorOrder)
2632   {
2633     case CUPS_ORDER_CHUNKED :
2634         switch (header->cupsBitsPerColor)
2635         {
2636           case 1 :
2637               bitmask = 128 >> (bitoffset & 7);
2638               dither  = Floyd16x16[y & 15];
2639 
2640               for (x = xsize ; x > 0; x --)
2641               {
2642 	        pc = *r0++ > dither[x & 15];
2643 		pm = *r0++ > dither[x & 15];
2644 		py = *r0++ > dither[x & 15];
2645 
2646 		if (pc && pm && py)
2647 		{
2648 		  *ptr ^= bitmask;
2649 		  bitmask >>= 3;
2650 		}
2651 		else
2652 		{
2653 		  bitmask >>= 1;
2654 		  if (pc)
2655 		    *ptr ^= bitmask;
2656 
2657 		  bitmask >>= 1;
2658 		  if (pm)
2659 		    *ptr ^= bitmask;
2660 
2661 		  bitmask >>= 1;
2662 		  if (py)
2663 		    *ptr ^= bitmask;
2664                 }
2665 
2666                 if (bitmask > 1)
2667 		  bitmask >>= 1;
2668 		else
2669         	{
2670         	  bitmask = 128;
2671         	  ptr ++;
2672         	}
2673               }
2674               break;
2675 
2676           case 2 :
2677               dither = Floyd8x8[y & 7];
2678 
2679               for (x = xsize ; x > 0; x --, r0 += 4)
2680               {
2681 	       	if ((r0[3] & 63) > dither[x & 7])
2682         	  *ptr ^= (0xc0 & OnPixels[r0[3]]);
2683         	else
2684         	  *ptr ^= (0xc0 & OffPixels[r0[3]]);
2685 
2686         	if ((r0[0] & 63) > dither[x & 7])
2687         	  *ptr ^= (0x30 & OnPixels[r0[0]]);
2688         	else
2689         	  *ptr ^= (0x30 & OffPixels[r0[0]]);
2690 
2691         	if ((r0[1] & 63) > dither[x & 7])
2692         	  *ptr ^= (0x0c & OnPixels[r0[1]]);
2693         	else
2694         	  *ptr ^= (0x0c & OffPixels[r0[1]]);
2695 
2696         	if ((r0[2] & 63) > dither[x & 7])
2697         	  *ptr++ ^= (0x03 & OnPixels[r0[2]]);
2698         	else
2699         	  *ptr++ ^= (0x03 & OffPixels[r0[2]]);
2700               }
2701               break;
2702 
2703           case 4 :
2704               dither = Floyd4x4[y & 3];
2705 
2706               for (x = xsize ; x > 0; x --, r0 += 4)
2707               {
2708         	if ((r0[3] & 15) > dither[x & 3])
2709         	  *ptr ^= (0xf0 & OnPixels[r0[3]]);
2710         	else
2711         	  *ptr ^= (0xf0 & OffPixels[r0[3]]);
2712 
2713         	if ((r0[0] & 15) > dither[x & 3])
2714         	  *ptr++ ^= (0x0f & OnPixels[r0[0]]);
2715         	else
2716         	  *ptr++ ^= (0x0f & OffPixels[r0[0]]);
2717 
2718         	if ((r0[1] & 15) > dither[x & 3])
2719         	  *ptr ^= (0xf0 & OnPixels[r0[1]]);
2720         	else
2721         	  *ptr ^= (0xf0 & OffPixels[r0[1]]);
2722 
2723         	if ((r0[2] & 15) > dither[x & 3])
2724         	  *ptr++ ^= (0x0f & OnPixels[r0[2]]);
2725         	else
2726         	  *ptr++ ^= (0x0f & OffPixels[r0[2]]);
2727               }
2728               break;
2729 
2730           case 8 :
2731               for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
2732 	      {
2733         	if (r0[3] == r1[3])
2734                   *ptr++ = r0[3];
2735         	else
2736                   *ptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
2737 
2738         	if (r0[0] == r1[0])
2739                   *ptr++ = r0[0];
2740         	else
2741                   *ptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
2742 
2743         	if (r0[1] == r1[1])
2744                   *ptr++ = r0[1];
2745         	else
2746                   *ptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
2747 
2748         	if (r0[2] == r1[2])
2749                   *ptr++ = r0[2];
2750         	else
2751                   *ptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
2752               }
2753               break;
2754         }
2755         break;
2756 
2757     case CUPS_ORDER_BANDED :
2758 	kptr = ptr;
2759 	cptr = ptr + bandwidth;
2760 	mptr = ptr + 2 * bandwidth;
2761 	yptr = ptr + 3 * bandwidth;
2762 
2763         switch (header->cupsBitsPerColor)
2764         {
2765           case 1 :
2766               bitmask = 0x80 >> (bitoffset & 7);
2767               dither  = Floyd16x16[y & 15];
2768 
2769               for (x = xsize; x > 0; x --)
2770               {
2771 	        pc = *r0++ > dither[x & 15];
2772 		pm = *r0++ > dither[x & 15];
2773 		py = *r0++ > dither[x & 15];
2774 
2775 		if (pc && pm && py)
2776 		  *kptr ^= bitmask;
2777 		else
2778 		{
2779 		  if (pc)
2780         	    *cptr ^= bitmask;
2781 		  if (pm)
2782         	    *mptr ^= bitmask;
2783 		  if (py)
2784         	    *yptr ^= bitmask;
2785                 }
2786 
2787                 if (bitmask > 1)
2788 		  bitmask >>= 1;
2789 		else
2790 		{
2791 		  bitmask = 0x80;
2792 		  cptr ++;
2793 		  mptr ++;
2794 		  yptr ++;
2795 		  kptr ++;
2796         	}
2797 	      }
2798               break;
2799 
2800           case 2 :
2801               bitmask = 0xc0 >> (bitoffset & 7);
2802               dither  = Floyd8x8[y & 7];
2803 
2804               for (x = xsize; x > 0; x --)
2805               {
2806         	if ((*r0 & 63) > dither[x & 7])
2807         	  *cptr ^= (bitmask & OnPixels[*r0++]);
2808         	else
2809         	  *cptr ^= (bitmask & OffPixels[*r0++]);
2810 
2811         	if ((*r0 & 63) > dither[x & 7])
2812         	  *mptr ^= (bitmask & OnPixels[*r0++]);
2813         	else
2814         	  *mptr ^= (bitmask & OffPixels[*r0++]);
2815 
2816         	if ((*r0 & 63) > dither[x & 7])
2817         	  *yptr ^= (bitmask & OnPixels[*r0++]);
2818         	else
2819         	  *yptr ^= (bitmask & OffPixels[*r0++]);
2820 
2821         	if ((*r0 & 63) > dither[x & 7])
2822         	  *kptr ^= (bitmask & OnPixels[*r0++]);
2823         	else
2824         	  *kptr ^= (bitmask & OffPixels[*r0++]);
2825 
2826                 if (bitmask > 3)
2827 		  bitmask >>= 2;
2828 		else
2829 		{
2830 		  bitmask = 0xc0;
2831 
2832 		  cptr ++;
2833 		  mptr ++;
2834 		  yptr ++;
2835 		  kptr ++;
2836         	}
2837 	      }
2838               break;
2839 
2840           case 4 :
2841               bitmask = 0xf0 >> (bitoffset & 7);
2842               dither  = Floyd4x4[y & 3];
2843 
2844               for (x = xsize; x > 0; x --)
2845               {
2846         	if ((*r0 & 15) > dither[x & 3])
2847         	  *cptr ^= (bitmask & OnPixels[*r0++]);
2848         	else
2849         	  *cptr ^= (bitmask & OffPixels[*r0++]);
2850 
2851         	if ((*r0 & 15) > dither[x & 3])
2852         	  *mptr ^= (bitmask & OnPixels[*r0++]);
2853         	else
2854         	  *mptr ^= (bitmask & OffPixels[*r0++]);
2855 
2856         	if ((*r0 & 15) > dither[x & 3])
2857         	  *yptr ^= (bitmask & OnPixels[*r0++]);
2858         	else
2859         	  *yptr ^= (bitmask & OffPixels[*r0++]);
2860 
2861         	if ((*r0 & 15) > dither[x & 3])
2862         	  *kptr ^= (bitmask & OnPixels[*r0++]);
2863         	else
2864         	  *kptr ^= (bitmask & OffPixels[*r0++]);
2865 
2866                 if (bitmask == 0xf0)
2867 		  bitmask = 0x0f;
2868 		else
2869 		{
2870 		  bitmask = 0xf0;
2871 
2872 		  cptr ++;
2873 		  mptr ++;
2874 		  yptr ++;
2875 		  kptr ++;
2876         	}
2877 	      }
2878               break;
2879 
2880           case 8 :
2881               for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
2882 	      {
2883         	if (r0[0] == r1[0])
2884                   *cptr++ = r0[0];
2885         	else
2886                   *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
2887 
2888         	if (r0[1] == r1[1])
2889                   *mptr++ = r0[1];
2890         	else
2891                   *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
2892 
2893         	if (r0[2] == r1[2])
2894                   *yptr++ = r0[2];
2895         	else
2896                   *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
2897 
2898         	if (r0[3] == r1[3])
2899                   *kptr++ = r0[3];
2900         	else
2901                   *kptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
2902               }
2903               break;
2904         }
2905         break;
2906 
2907     case CUPS_ORDER_PLANAR :
2908         switch (header->cupsBitsPerColor)
2909         {
2910           case 1 :
2911               bitmask = 0x80 >> (bitoffset & 7);
2912               dither  = Floyd16x16[y & 15];
2913 
2914               for (x = xsize; x > 0; x --)
2915               {
2916 	        pc = *r0++ > dither[x & 15];
2917 		pm = *r0++ > dither[x & 15];
2918 		py = *r0++ > dither[x & 15];
2919 
2920 		if ((pc && pm && py && z == 0) ||
2921 		    (pc && z == 1) || (pm && z == 2) || (py && z == 3))
2922         	  *ptr ^= bitmask;
2923 
2924                 if (bitmask > 1)
2925 		  bitmask >>= 1;
2926 		else
2927 		{
2928 		  bitmask = 0x80;
2929 		  ptr ++;
2930         	}
2931 	      }
2932 	      break;
2933 
2934           case 2 :
2935               bitmask = 0xc0 >> (bitoffset & 7);
2936               dither  = Floyd8x8[y & 7];
2937               if (z == 0)
2938 	        r0 += 3;
2939 	      else
2940 	        r0 += z - 1;
2941 
2942               for (x = xsize; x > 0; x --, r0 += 4)
2943               {
2944         	if ((*r0 & 63) > dither[x & 7])
2945         	  *ptr ^= (bitmask & OnPixels[*r0]);
2946         	else
2947         	  *ptr ^= (bitmask & OffPixels[*r0]);
2948 
2949                 if (bitmask > 3)
2950 		  bitmask >>= 2;
2951 		else
2952 		{
2953 		  bitmask = 0xc0;
2954 
2955 		  ptr ++;
2956         	}
2957 	      }
2958               break;
2959 
2960           case 4 :
2961               bitmask = 0xf0 >> (bitoffset & 7);
2962               dither  = Floyd4x4[y & 3];
2963               if (z == 0)
2964 	        r0 += 3;
2965 	      else
2966 	        r0 += z - 1;
2967 
2968               for (x = xsize; x > 0; x --, r0 += 4)
2969               {
2970         	if ((*r0 & 15) > dither[x & 3])
2971         	  *ptr ^= (bitmask & OnPixels[*r0]);
2972         	else
2973         	  *ptr ^= (bitmask & OffPixels[*r0]);
2974 
2975                 if (bitmask == 0xf0)
2976 		  bitmask = 0x0f;
2977 		else
2978 		{
2979 		  bitmask = 0xf0;
2980 
2981 		  ptr ++;
2982         	}
2983 	      }
2984               break;
2985 
2986           case 8 :
2987               if (z == 0)
2988 	      {
2989 	        r0 += 3;
2990 	        r1 += 3;
2991 	      }
2992 	      else
2993 	      {
2994 	        r0 += z - 1;
2995 	        r1 += z - 1;
2996 	      }
2997 
2998               for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
2999 	      {
3000         	if (*r0 == *r1)
3001                   *ptr++ = *r0;
3002         	else
3003                   *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
3004               }
3005               break;
3006         }
3007         break;
3008   }
3009 }
3010 
3011 
3012 /*
3013  * 'format_KCMYcm()' - Convert image data to KCMYcm.
3014  */
3015 
3016 static void
format_KCMYcm(cups_page_header2_t * header,unsigned char * row,int y,int z,int xsize,int ysize,int yerr0,int yerr1,cups_ib_t * r0,cups_ib_t * r1)3017 format_KCMYcm(
3018     cups_page_header2_t *header,	/* I - Page header */
3019     unsigned char       *row,		/* IO - Bitmap data for device */
3020     int                 y,		/* I - Current row */
3021     int                 z,		/* I - Current plane */
3022     int                 xsize,		/* I - Width of image data */
3023     int                 ysize,		/* I - Height of image data */
3024     int                 yerr0,		/* I - Top Y error */
3025     int                 yerr1,		/* I - Bottom Y error */
3026     cups_ib_t           *r0,		/* I - Primary image data */
3027     cups_ib_t           *r1)		/* I - Image data for interpolation */
3028 {
3029   int		pc, pm, py, pk;		/* Cyan, magenta, yellow, and black values */
3030   cups_ib_t	*ptr,			/* Pointer into row */
3031 		*cptr,			/* Pointer into cyan */
3032 		*mptr,			/* Pointer into magenta */
3033 		*yptr,			/* Pointer into yellow */
3034 		*kptr,			/* Pointer into black */
3035 		*lcptr,			/* Pointer into light cyan */
3036 		*lmptr,			/* Pointer into light magenta */
3037 		bitmask;		/* Current mask for pixel */
3038   int		bitoffset;		/* Current offset in line */
3039   int		bandwidth;		/* Width of a color band */
3040   int		x,			/* Current X coordinate on page */
3041 		*dither;		/* Pointer into dither array */
3042 
3043 
3044   switch (XPosition)
3045   {
3046     case -1 :
3047         bitoffset = 0;
3048 	break;
3049     default :
3050         bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
3051 	break;
3052     case 1 :
3053         bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
3054 	break;
3055   }
3056 
3057   ptr       = row + bitoffset / 8;
3058   bandwidth = header->cupsBytesPerLine / 6;
3059 
3060   switch (header->cupsColorOrder)
3061   {
3062     case CUPS_ORDER_CHUNKED :
3063         dither = Floyd16x16[y & 15];
3064 
3065         for (x = xsize ; x > 0; x --)
3066         {
3067 	  pc = *r0++ > dither[x & 15];
3068 	  pm = *r0++ > dither[x & 15];
3069 	  py = *r0++ > dither[x & 15];
3070 	  pk = pc && pm && py;
3071 
3072 	  if (pk)
3073 	    *ptr++ ^= 32;	/* Black */
3074 	  else if (pc && pm)
3075 	    *ptr++ ^= 17;	/* Blue (cyan + light magenta) */
3076 	  else if (pc && py)
3077 	    *ptr++ ^= 6;	/* Green (light cyan + yellow) */
3078 	  else if (pm && py)
3079 	    *ptr++ ^= 12;	/* Red (magenta + yellow) */
3080 	  else if (pc)
3081 	    *ptr++ ^= 16;
3082 	  else if (pm)
3083 	    *ptr++ ^= 8;
3084 	  else if (py)
3085 	    *ptr++ ^= 4;
3086 	  else
3087 	    ptr ++;
3088         }
3089         break;
3090 
3091     case CUPS_ORDER_BANDED :
3092 	kptr  = ptr;
3093 	cptr  = ptr + bandwidth;
3094 	mptr  = ptr + 2 * bandwidth;
3095 	yptr  = ptr + 3 * bandwidth;
3096 	lcptr = ptr + 4 * bandwidth;
3097 	lmptr = ptr + 5 * bandwidth;
3098 
3099         bitmask = 0x80 >> (bitoffset & 7);
3100         dither  = Floyd16x16[y & 15];
3101 
3102         for (x = xsize; x > 0; x --)
3103         {
3104 	  pc = *r0++ > dither[x & 15];
3105 	  pm = *r0++ > dither[x & 15];
3106 	  py = *r0++ > dither[x & 15];
3107 	  pk = pc && pm && py;
3108 
3109 	  if (pk)
3110 	    *kptr ^= bitmask;	/* Black */
3111 	  else if (pc && pm)
3112 	  {
3113 	    *cptr ^= bitmask;	/* Blue (cyan + light magenta) */
3114 	    *lmptr ^= bitmask;
3115 	  }
3116 	  else if (pc && py)
3117 	  {
3118 	    *lcptr ^= bitmask;	/* Green (light cyan + yellow) */
3119 	    *yptr  ^= bitmask;
3120 	  }
3121 	  else if (pm && py)
3122 	  {
3123 	    *mptr ^= bitmask;	/* Red (magenta + yellow) */
3124 	    *yptr ^= bitmask;
3125 	  }
3126 	  else if (pc)
3127 	    *cptr ^= bitmask;
3128 	  else if (pm)
3129 	    *mptr ^= bitmask;
3130 	  else if (py)
3131 	    *yptr ^= bitmask;
3132 
3133           if (bitmask > 1)
3134 	    bitmask >>= 1;
3135 	  else
3136 	  {
3137 	    bitmask = 0x80;
3138 	    cptr ++;
3139 	    mptr ++;
3140 	    yptr ++;
3141 	    kptr ++;
3142 	    lcptr ++;
3143 	    lmptr ++;
3144           }
3145 	}
3146         break;
3147 
3148     case CUPS_ORDER_PLANAR :
3149         bitmask = 0x80 >> (bitoffset & 7);
3150         dither  = Floyd16x16[y & 15];
3151 
3152         for (x = xsize; x > 0; x --)
3153         {
3154 	  pc = *r0++ > dither[x & 15];
3155 	  pm = *r0++ > dither[x & 15];
3156 	  py = *r0++ > dither[x & 15];
3157 	  pk = pc && pm && py;
3158 
3159           if (pk && z == 0)
3160             *ptr ^= bitmask;
3161 	  else if (pc && pm && (z == 1 || z == 5))
3162 	    *ptr ^= bitmask;	/* Blue (cyan + light magenta) */
3163 	  else if (pc && py && (z == 3 || z == 4))
3164 	    *ptr ^= bitmask;	/* Green (light cyan + yellow) */
3165 	  else if (pm && py && (z == 2 || z == 3))
3166 	    *ptr ^= bitmask;	/* Red (magenta + yellow) */
3167 	  else if (pc && z == 1)
3168 	    *ptr ^= bitmask;
3169 	  else if (pm && z == 2)
3170 	    *ptr ^= bitmask;
3171 	  else if (py && z == 3)
3172 	    *ptr ^= bitmask;
3173 
3174           if (bitmask > 1)
3175 	    bitmask >>= 1;
3176 	  else
3177 	  {
3178 	    bitmask = 0x80;
3179 	    ptr ++;
3180           }
3181 	}
3182         break;
3183   }
3184 }
3185 
3186 
3187 /*
3188  * 'format_RGBA()' - Convert image data to RGBA/RGBW.
3189  */
3190 
3191 static void
format_RGBA(cups_page_header2_t * header,unsigned char * row,int y,int z,int xsize,int ysize,int yerr0,int yerr1,cups_ib_t * r0,cups_ib_t * r1)3192 format_RGBA(cups_page_header2_t *header,/* I - Page header */
3193             unsigned char       *row,	/* IO - Bitmap data for device */
3194 	    int                 y,	/* I - Current row */
3195 	    int                 z,	/* I - Current plane */
3196 	    int                 xsize,	/* I - Width of image data */
3197 	    int	                ysize,	/* I - Height of image data */
3198 	    int                 yerr0,	/* I - Top Y error */
3199 	    int                 yerr1,	/* I - Bottom Y error */
3200 	    cups_ib_t           *r0,	/* I - Primary image data */
3201 	    cups_ib_t           *r1)	/* I - Image data for interpolation */
3202 {
3203   cups_ib_t	*ptr,			/* Pointer into row */
3204 		*cptr,			/* Pointer into cyan */
3205 		*mptr,			/* Pointer into magenta */
3206 		*yptr,			/* Pointer into yellow */
3207 		bitmask;		/* Current mask for pixel */
3208   int		bitoffset;		/* Current offset in line */
3209   int		bandwidth;		/* Width of a color band */
3210   int		x,			/* Current X coordinate on page */
3211 		*dither;		/* Pointer into dither array */
3212 
3213 
3214   switch (XPosition)
3215   {
3216     case -1 :
3217         bitoffset = 0;
3218 	break;
3219     default :
3220         bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
3221 	break;
3222     case 1 :
3223         bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
3224 	break;
3225   }
3226 
3227   ptr       = row + bitoffset / 8;
3228   bandwidth = header->cupsBytesPerLine / 4;
3229 
3230   switch (header->cupsColorOrder)
3231   {
3232     case CUPS_ORDER_CHUNKED :
3233         switch (header->cupsBitsPerColor)
3234         {
3235           case 1 :
3236               bitmask = 128 >> (bitoffset & 7);
3237 	      dither  = Floyd16x16[y & 15];
3238 
3239               for (x = xsize ; x > 0; x --)
3240               {
3241 	        if (*r0++ > dither[x & 15])
3242 		  *ptr ^= bitmask;
3243 		bitmask >>= 1;
3244 
3245 	        if (*r0++ > dither[x & 15])
3246 		  *ptr ^= bitmask;
3247 		bitmask >>= 1;
3248 
3249 	        if (*r0++ > dither[x & 15])
3250 		  *ptr ^= bitmask;
3251 
3252                 if (bitmask > 2)
3253 		  bitmask >>= 2;
3254 		else
3255         	{
3256         	  bitmask = 128;
3257         	  ptr ++;
3258         	}
3259               }
3260               break;
3261 
3262           case 2 :
3263 	      dither = Floyd8x8[y & 7];
3264 
3265               for (x = xsize ; x > 0; x --, r0 += 3)
3266               {
3267 	       	if ((r0[0] & 63) > dither[x & 7])
3268         	  *ptr ^= (0xc0 & OnPixels[r0[0]]);
3269         	else
3270         	  *ptr ^= (0xc0 & OffPixels[r0[0]]);
3271 
3272         	if ((r0[1] & 63) > dither[x & 7])
3273         	  *ptr ^= (0x30 & OnPixels[r0[1]]);
3274         	else
3275         	  *ptr ^= (0x30 & OffPixels[r0[1]]);
3276 
3277         	if ((r0[2] & 63) > dither[x & 7])
3278         	  *ptr ^= (0x0c & OnPixels[r0[2]]);
3279         	else
3280         	  *ptr ^= (0x0c & OffPixels[r0[2]]);
3281 
3282                 ptr ++;
3283               }
3284               break;
3285 
3286           case 4 :
3287 	      dither = Floyd4x4[y & 3];
3288 
3289               for (x = xsize ; x > 0; x --, r0 += 3)
3290               {
3291         	if ((r0[0] & 15) > dither[x & 3])
3292         	  *ptr ^= (0xf0 & OnPixels[r0[0]]);
3293         	else
3294         	  *ptr ^= (0xf0 & OffPixels[r0[0]]);
3295 
3296         	if ((r0[1] & 15) > dither[x & 3])
3297         	  *ptr++ ^= (0x0f & OnPixels[r0[1]]);
3298         	else
3299         	  *ptr++ ^= (0x0f & OffPixels[r0[1]]);
3300 
3301         	if ((r0[2] & 15) > dither[x & 3])
3302         	  *ptr ^= (0xf0 & OnPixels[r0[2]]);
3303         	else
3304         	  *ptr ^= (0xf0 & OffPixels[r0[2]]);
3305 
3306                 ptr ++;
3307               }
3308               break;
3309 
3310           case 8 :
3311               for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
3312 	      {
3313         	if (r0[0] == r1[0])
3314                   *ptr++ = r0[0];
3315         	else
3316                   *ptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
3317 
3318         	if (r0[1] == r1[1])
3319                   *ptr++ = r0[1];
3320         	else
3321                   *ptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
3322 
3323         	if (r0[2] == r1[2])
3324                   *ptr++ = r0[2];
3325         	else
3326                   *ptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
3327 
3328                 ptr ++;
3329               }
3330 	      break;
3331         }
3332         break;
3333 
3334     case CUPS_ORDER_BANDED :
3335 	cptr = ptr;
3336 	mptr = ptr + bandwidth;
3337 	yptr = ptr + 2 * bandwidth;
3338 
3339         memset(ptr + 3 * bandwidth, 255, bandwidth);
3340 
3341         switch (header->cupsBitsPerColor)
3342         {
3343           case 1 :
3344               bitmask = 0x80 >> (bitoffset & 7);
3345 	      dither  = Floyd16x16[y & 15];
3346 
3347               for (x = xsize; x > 0; x --)
3348               {
3349         	if (*r0++ > dither[x & 15])
3350         	  *cptr ^= bitmask;
3351         	if (*r0++ > dither[x & 15])
3352         	  *mptr ^= bitmask;
3353         	if (*r0++ > dither[x & 15])
3354         	  *yptr ^= bitmask;
3355 
3356                 if (bitmask > 1)
3357 		  bitmask >>= 1;
3358 		else
3359 		{
3360 		  bitmask = 0x80;
3361 		  cptr ++;
3362 		  mptr ++;
3363 		  yptr ++;
3364         	}
3365 	      }
3366               break;
3367 
3368           case 2 :
3369               bitmask = 0xc0 >> (bitoffset & 7);
3370 	      dither  = Floyd8x8[y & 7];
3371 
3372               for (x = xsize; x > 0; x --)
3373               {
3374         	if ((*r0 & 63) > dither[x & 7])
3375         	  *cptr ^= (bitmask & OnPixels[*r0++]);
3376         	else
3377         	  *cptr ^= (bitmask & OffPixels[*r0++]);
3378 
3379         	if ((*r0 & 63) > dither[x & 7])
3380         	  *mptr ^= (bitmask & OnPixels[*r0++]);
3381         	else
3382         	  *mptr ^= (bitmask & OffPixels[*r0++]);
3383 
3384         	if ((*r0 & 63) > dither[x & 7])
3385         	  *yptr ^= (bitmask & OnPixels[*r0++]);
3386         	else
3387         	  *yptr ^= (bitmask & OffPixels[*r0++]);
3388 
3389                 if (bitmask > 3)
3390 		  bitmask >>= 2;
3391 		else
3392 		{
3393 		  bitmask = 0xc0;
3394 
3395 		  cptr ++;
3396 		  mptr ++;
3397 		  yptr ++;
3398         	}
3399 	      }
3400               break;
3401 
3402           case 4 :
3403               bitmask = 0xf0 >> (bitoffset & 7);
3404 	      dither  = Floyd4x4[y & 3];
3405 
3406               for (x = xsize; x > 0; x --)
3407               {
3408         	if ((*r0 & 15) > dither[x & 3])
3409         	  *cptr ^= (bitmask & OnPixels[*r0++]);
3410         	else
3411         	  *cptr ^= (bitmask & OffPixels[*r0++]);
3412 
3413         	if ((*r0 & 15) > dither[x & 3])
3414         	  *mptr ^= (bitmask & OnPixels[*r0++]);
3415         	else
3416         	  *mptr ^= (bitmask & OffPixels[*r0++]);
3417 
3418         	if ((*r0 & 15) > dither[x & 3])
3419         	  *yptr ^= (bitmask & OnPixels[*r0++]);
3420         	else
3421         	  *yptr ^= (bitmask & OffPixels[*r0++]);
3422 
3423                 if (bitmask == 0xf0)
3424 		  bitmask = 0x0f;
3425 		else
3426 		{
3427 		  bitmask = 0xf0;
3428 
3429 		  cptr ++;
3430 		  mptr ++;
3431 		  yptr ++;
3432         	}
3433 	      }
3434               break;
3435 
3436           case 8 :
3437               for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
3438 	      {
3439         	if (r0[0] == r1[0])
3440                   *cptr++ = r0[0];
3441         	else
3442                   *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
3443 
3444         	if (r0[1] == r1[1])
3445                   *mptr++ = r0[1];
3446         	else
3447                   *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
3448 
3449         	if (r0[2] == r1[2])
3450                   *yptr++ = r0[2];
3451         	else
3452                   *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
3453               }
3454               break;
3455         }
3456         break;
3457 
3458     case CUPS_ORDER_PLANAR :
3459         if (z == 3)
3460 	{
3461           memset(row, 255, header->cupsBytesPerLine);
3462 	  break;
3463         }
3464 
3465         switch (header->cupsBitsPerColor)
3466         {
3467           case 1 :
3468               bitmask = 0x80 >> (bitoffset & 7);
3469 	      dither  = Floyd16x16[y & 15];
3470 
3471               switch (z)
3472 	      {
3473 	        case 0 :
3474         	    for (x = xsize; x > 0; x --, r0 += 3)
3475         	    {
3476         	      if (r0[0] > dither[x & 15])
3477         		*ptr ^= bitmask;
3478 
3479                       if (bitmask > 1)
3480 			bitmask >>= 1;
3481 		      else
3482 		      {
3483 			bitmask = 0x80;
3484 			ptr ++;
3485         	      }
3486 	            }
3487 		    break;
3488 
3489 	        case 1 :
3490         	    for (x = xsize; x > 0; x --, r0 += 3)
3491         	    {
3492         	      if (r0[1] > dither[x & 15])
3493         		*ptr ^= bitmask;
3494 
3495                       if (bitmask > 1)
3496 			bitmask >>= 1;
3497 		      else
3498 		      {
3499 			bitmask = 0x80;
3500 			ptr ++;
3501         	      }
3502 	            }
3503 		    break;
3504 
3505 	        case 2 :
3506         	    for (x = xsize; x > 0; x --, r0 += 3)
3507         	    {
3508         	      if (r0[2] > dither[x & 15])
3509         		*ptr ^= bitmask;
3510 
3511                       if (bitmask > 1)
3512 			bitmask >>= 1;
3513 		      else
3514 		      {
3515 			bitmask = 0x80;
3516 			ptr ++;
3517         	      }
3518 	            }
3519 		    break;
3520 	      }
3521               break;
3522 
3523           case 2 :
3524               bitmask = 0xc0 >> (bitoffset & 7);
3525 	      dither  = Floyd8x8[y & 7];
3526               r0 += z;
3527 
3528               for (x = xsize; x > 0; x --, r0 += 3)
3529               {
3530         	if ((*r0 & 63) > dither[x & 7])
3531         	  *ptr ^= (bitmask & OnPixels[*r0]);
3532         	else
3533         	  *ptr ^= (bitmask & OffPixels[*r0]);
3534 
3535                 if (bitmask > 3)
3536 		  bitmask >>= 2;
3537 		else
3538 		{
3539 		  bitmask = 0xc0;
3540 
3541 		  ptr ++;
3542         	}
3543 	      }
3544               break;
3545 
3546           case 4 :
3547               bitmask = 0xf0 >> (bitoffset & 7);
3548 	      dither  = Floyd4x4[y & 3];
3549               r0 += z;
3550 
3551               for (x = xsize; x > 0; x --, r0 += 3)
3552               {
3553         	if ((*r0 & 15) > dither[x & 3])
3554         	  *ptr ^= (bitmask & OnPixels[*r0]);
3555         	else
3556         	  *ptr ^= (bitmask & OffPixels[*r0]);
3557 
3558                 if (bitmask == 0xf0)
3559 		  bitmask = 0x0f;
3560 		else
3561 		{
3562 		  bitmask = 0xf0;
3563 
3564 		  ptr ++;
3565         	}
3566 	      }
3567               break;
3568 
3569           case 8 :
3570               r0 += z;
3571 	      r1 += z;
3572 
3573               for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
3574 	      {
3575         	if (*r0 == *r1)
3576                   *ptr++ = *r0;
3577         	else
3578                   *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
3579               }
3580               break;
3581         }
3582         break;
3583   }
3584 }
3585 
3586 
3587 /*
3588  * 'format_W()' - Convert image data to luminance.
3589  */
3590 
3591 static void
format_W(cups_page_header2_t * header,unsigned char * row,int y,int z,int xsize,int ysize,int yerr0,int yerr1,cups_ib_t * r0,cups_ib_t * r1)3592 format_W(cups_page_header2_t *header,	/* I - Page header */
3593             unsigned char    *row,	/* IO - Bitmap data for device */
3594 	    int              y,		/* I - Current row */
3595 	    int              z,		/* I - Current plane */
3596 	    int              xsize,	/* I - Width of image data */
3597 	    int	             ysize,	/* I - Height of image data */
3598 	    int              yerr0,	/* I - Top Y error */
3599 	    int              yerr1,	/* I - Bottom Y error */
3600 	    cups_ib_t        *r0,	/* I - Primary image data */
3601 	    cups_ib_t        *r1)	/* I - Image data for interpolation */
3602 {
3603   cups_ib_t	*ptr,			/* Pointer into row */
3604 		bitmask;		/* Current mask for pixel */
3605   int		bitoffset;		/* Current offset in line */
3606   int		x,			/* Current X coordinate on page */
3607 		*dither;		/* Pointer into dither array */
3608 
3609 
3610   (void)z;
3611 
3612   switch (XPosition)
3613   {
3614     case -1 :
3615         bitoffset = 0;
3616 	break;
3617     default :
3618         bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
3619 	break;
3620     case 1 :
3621         bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
3622 	break;
3623   }
3624 
3625   ptr = row + bitoffset / 8;
3626 
3627   switch (header->cupsBitsPerColor)
3628   {
3629     case 1 :
3630         bitmask = 0x80 >> (bitoffset & 7);
3631         dither  = Floyd16x16[y & 15];
3632 
3633         for (x = xsize; x > 0; x --)
3634         {
3635           if (*r0++ > dither[x & 15])
3636             *ptr ^= bitmask;
3637 
3638           if (bitmask > 1)
3639 	    bitmask >>= 1;
3640 	  else
3641 	  {
3642 	    bitmask = 0x80;
3643 	    ptr ++;
3644           }
3645 	}
3646         break;
3647 
3648     case 2 :
3649         bitmask = 0xc0 >> (bitoffset & 7);
3650         dither  = Floyd8x8[y & 7];
3651 
3652         for (x = xsize; x > 0; x --)
3653         {
3654           if ((*r0 & 63) > dither[x & 7])
3655             *ptr ^= (bitmask & OnPixels[*r0++]);
3656           else
3657             *ptr ^= (bitmask & OffPixels[*r0++]);
3658 
3659           if (bitmask > 3)
3660 	    bitmask >>= 2;
3661 	  else
3662 	  {
3663 	    bitmask = 0xc0;
3664 
3665 	    ptr ++;
3666           }
3667 	}
3668         break;
3669 
3670     case 4 :
3671         bitmask = 0xf0 >> (bitoffset & 7);
3672         dither  = Floyd4x4[y & 3];
3673 
3674         for (x = xsize; x > 0; x --)
3675         {
3676           if ((*r0 & 15) > dither[x & 3])
3677             *ptr ^= (bitmask & OnPixels[*r0++]);
3678           else
3679             *ptr ^= (bitmask & OffPixels[*r0++]);
3680 
3681           if (bitmask == 0xf0)
3682 	    bitmask = 0x0f;
3683 	  else
3684 	  {
3685 	    bitmask = 0xf0;
3686 
3687 	    ptr ++;
3688           }
3689 	}
3690         break;
3691 
3692     case 8 :
3693         for (x = xsize; x > 0; x --, r0 ++, r1 ++)
3694 	{
3695           if (*r0 == *r1)
3696             *ptr++ = *r0;
3697           else
3698             *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
3699         }
3700         break;
3701   }
3702 }
3703 
3704 
3705 /*
3706  * 'format_YMC()' - Convert image data to YMC.
3707  */
3708 
3709 static void
format_YMC(cups_page_header2_t * header,unsigned char * row,int y,int z,int xsize,int ysize,int yerr0,int yerr1,cups_ib_t * r0,cups_ib_t * r1)3710 format_YMC(cups_page_header2_t *header,	/* I - Page header */
3711             unsigned char      *row,	/* IO - Bitmap data for device */
3712 	    int                y,	/* I - Current row */
3713 	    int                z,	/* I - Current plane */
3714 	    int                xsize,	/* I - Width of image data */
3715 	    int	               ysize,	/* I - Height of image data */
3716 	    int                yerr0,	/* I - Top Y error */
3717 	    int                yerr1,	/* I - Bottom Y error */
3718 	    cups_ib_t          *r0,	/* I - Primary image data */
3719 	    cups_ib_t          *r1)	/* I - Image data for interpolation */
3720 {
3721   cups_ib_t	*ptr,			/* Pointer into row */
3722 		*cptr,			/* Pointer into cyan */
3723 		*mptr,			/* Pointer into magenta */
3724 		*yptr,			/* Pointer into yellow */
3725 		bitmask;		/* Current mask for pixel */
3726   int		bitoffset;		/* Current offset in line */
3727   int		bandwidth;		/* Width of a color band */
3728   int		x,			/* Current X coordinate on page */
3729 		*dither;		/* Pointer into dither array */
3730 
3731 
3732   switch (XPosition)
3733   {
3734     case -1 :
3735         bitoffset = 0;
3736 	break;
3737     default :
3738         bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
3739 	break;
3740     case 1 :
3741         bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
3742 	break;
3743   }
3744 
3745   ptr       = row + bitoffset / 8;
3746   bandwidth = header->cupsBytesPerLine / 3;
3747 
3748   switch (header->cupsColorOrder)
3749   {
3750     case CUPS_ORDER_CHUNKED :
3751         switch (header->cupsBitsPerColor)
3752         {
3753           case 1 :
3754               bitmask = 64 >> (bitoffset & 7);
3755 	      dither  = Floyd16x16[y & 15];
3756 
3757               for (x = xsize ; x > 0; x --, r0 += 3)
3758               {
3759 	        if (r0[2] > dither[x & 15])
3760 		  *ptr ^= bitmask;
3761 		bitmask >>= 1;
3762 
3763 	        if (r0[1] > dither[x & 15])
3764 		  *ptr ^= bitmask;
3765 		bitmask >>= 1;
3766 
3767 	        if (r0[0] > dither[x & 15])
3768 		  *ptr ^= bitmask;
3769 
3770                 if (bitmask > 1)
3771 		  bitmask >>= 2;
3772 		else
3773         	{
3774         	  bitmask = 64;
3775         	  ptr ++;
3776         	}
3777               }
3778               break;
3779 
3780           case 2 :
3781 	      dither = Floyd8x8[y & 7];
3782 
3783               for (x = xsize ; x > 0; x --, r0 += 3)
3784               {
3785 	       	if ((r0[2] & 63) > dither[x & 7])
3786         	  *ptr ^= (0x30 & OnPixels[r0[2]]);
3787         	else
3788         	  *ptr ^= (0x30 & OffPixels[r0[2]]);
3789 
3790         	if ((r0[1] & 63) > dither[x & 7])
3791         	  *ptr ^= (0x0c & OnPixels[r0[1]]);
3792         	else
3793         	  *ptr ^= (0x0c & OffPixels[r0[1]]);
3794 
3795         	if ((r0[0] & 63) > dither[x & 7])
3796         	  *ptr++ ^= (0x03 & OnPixels[r0[0]]);
3797         	else
3798         	  *ptr++ ^= (0x03 & OffPixels[r0[0]]);
3799               }
3800               break;
3801 
3802           case 4 :
3803 	      dither = Floyd4x4[y & 3];
3804 
3805               for (x = xsize ; x > 0; x --, r0 += 3)
3806               {
3807         	if ((r0[2] & 15) > dither[x & 3])
3808         	  *ptr++ ^= (0x0f & OnPixels[r0[2]]);
3809         	else
3810         	  *ptr++ ^= (0x0f & OffPixels[r0[2]]);
3811 
3812         	if ((r0[1] & 15) > dither[x & 3])
3813         	  *ptr ^= (0xf0 & OnPixels[r0[1]]);
3814         	else
3815         	  *ptr ^= (0xf0 & OffPixels[r0[1]]);
3816 
3817         	if ((r0[0] & 15) > dither[x & 3])
3818         	  *ptr++ ^= (0x0f & OnPixels[r0[0]]);
3819         	else
3820         	  *ptr++ ^= (0x0f & OffPixels[r0[0]]);
3821               }
3822               break;
3823 
3824           case 8 :
3825               for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
3826 	      {
3827         	if (r0[2] == r1[2])
3828                   *ptr++ = r0[2];
3829         	else
3830                   *ptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
3831 
3832         	if (r0[1] == r1[1])
3833                   *ptr++ = r0[1];
3834         	else
3835                   *ptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
3836 
3837         	if (r0[0] == r1[0])
3838                   *ptr++ = r0[0];
3839         	else
3840                   *ptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
3841               }
3842 	      break;
3843         }
3844         break;
3845 
3846     case CUPS_ORDER_BANDED :
3847 	yptr = ptr;
3848 	mptr = ptr + bandwidth;
3849 	cptr = ptr + 2 * bandwidth;
3850 
3851         switch (header->cupsBitsPerColor)
3852         {
3853           case 1 :
3854               bitmask = 0x80 >> (bitoffset & 7);
3855 	      dither  = Floyd16x16[y & 15];
3856 
3857               for (x = xsize; x > 0; x --)
3858               {
3859         	if (*r0++ > dither[x & 15])
3860         	  *cptr ^= bitmask;
3861         	if (*r0++ > dither[x & 15])
3862         	  *mptr ^= bitmask;
3863         	if (*r0++ > dither[x & 15])
3864         	  *yptr ^= bitmask;
3865 
3866                 if (bitmask > 1)
3867 		  bitmask >>= 1;
3868 		else
3869 		{
3870 		  bitmask = 0x80;
3871 		  cptr ++;
3872 		  mptr ++;
3873 		  yptr ++;
3874         	}
3875 	      }
3876               break;
3877 
3878           case 2 :
3879               bitmask = 0xc0 >> (bitoffset & 7);
3880 	      dither  = Floyd8x8[y & 7];
3881 
3882               for (x = xsize; x > 0; x --)
3883               {
3884         	if ((*r0 & 63) > dither[x & 7])
3885         	  *cptr ^= (bitmask & OnPixels[*r0++]);
3886         	else
3887         	  *cptr ^= (bitmask & OffPixels[*r0++]);
3888 
3889         	if ((*r0 & 63) > dither[x & 7])
3890         	  *mptr ^= (bitmask & OnPixels[*r0++]);
3891         	else
3892         	  *mptr ^= (bitmask & OffPixels[*r0++]);
3893 
3894         	if ((*r0 & 63) > dither[x & 7])
3895         	  *yptr ^= (bitmask & OnPixels[*r0++]);
3896         	else
3897         	  *yptr ^= (bitmask & OffPixels[*r0++]);
3898 
3899                 if (bitmask > 3)
3900 		  bitmask >>= 2;
3901 		else
3902 		{
3903 		  bitmask = 0xc0;
3904 
3905 		  cptr ++;
3906 		  mptr ++;
3907 		  yptr ++;
3908         	}
3909 	      }
3910               break;
3911 
3912           case 4 :
3913               bitmask = 0xf0 >> (bitoffset & 7);
3914 	      dither  = Floyd4x4[y & 3];
3915 
3916               for (x = xsize; x > 0; x --)
3917               {
3918         	if ((*r0 & 15) > dither[x & 3])
3919         	  *cptr ^= (bitmask & OnPixels[*r0++]);
3920         	else
3921         	  *cptr ^= (bitmask & OffPixels[*r0++]);
3922 
3923         	if ((*r0 & 15) > dither[x & 3])
3924         	  *mptr ^= (bitmask & OnPixels[*r0++]);
3925         	else
3926         	  *mptr ^= (bitmask & OffPixels[*r0++]);
3927 
3928         	if ((*r0 & 15) > dither[x & 3])
3929         	  *yptr ^= (bitmask & OnPixels[*r0++]);
3930         	else
3931         	  *yptr ^= (bitmask & OffPixels[*r0++]);
3932 
3933                 if (bitmask == 0xf0)
3934 		  bitmask = 0x0f;
3935 		else
3936 		{
3937 		  bitmask = 0xf0;
3938 
3939 		  cptr ++;
3940 		  mptr ++;
3941 		  yptr ++;
3942         	}
3943 	      }
3944               break;
3945 
3946           case 8 :
3947               for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
3948 	      {
3949         	if (r0[0] == r1[0])
3950                   *cptr++ = r0[0];
3951         	else
3952                   *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
3953 
3954         	if (r0[1] == r1[1])
3955                   *mptr++ = r0[1];
3956         	else
3957                   *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
3958 
3959         	if (r0[2] == r1[2])
3960                   *yptr++ = r0[2];
3961         	else
3962                   *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
3963               }
3964               break;
3965         }
3966         break;
3967 
3968     case CUPS_ORDER_PLANAR :
3969         switch (header->cupsBitsPerColor)
3970         {
3971           case 1 :
3972               bitmask = 0x80 >> (bitoffset & 7);
3973 	      dither  = Floyd16x16[y & 15];
3974 
3975               switch (z)
3976 	      {
3977 	        case 2 :
3978         	    for (x = xsize; x > 0; x --, r0 += 3)
3979         	    {
3980         	      if (r0[0] > dither[x & 15])
3981         		*ptr ^= bitmask;
3982 
3983                       if (bitmask > 1)
3984 			bitmask >>= 1;
3985 		      else
3986 		      {
3987 			bitmask = 0x80;
3988 			ptr ++;
3989         	      }
3990 	            }
3991 		    break;
3992 
3993 	        case 1 :
3994         	    for (x = xsize; x > 0; x --, r0 += 3)
3995         	    {
3996         	      if (r0[1] > dither[x & 15])
3997         		*ptr ^= bitmask;
3998 
3999                       if (bitmask > 1)
4000 			bitmask >>= 1;
4001 		      else
4002 		      {
4003 			bitmask = 0x80;
4004 			ptr ++;
4005         	      }
4006 	            }
4007 		    break;
4008 
4009 	        case 0 :
4010         	    for (x = xsize; x > 0; x --, r0 += 3)
4011         	    {
4012         	      if (r0[2] > dither[x & 15])
4013         		*ptr ^= bitmask;
4014 
4015                       if (bitmask > 1)
4016 			bitmask >>= 1;
4017 		      else
4018 		      {
4019 			bitmask = 0x80;
4020 			ptr ++;
4021         	      }
4022 	            }
4023 		    break;
4024 	      }
4025               break;
4026 
4027           case 2 :
4028               bitmask = 0xc0 >> (bitoffset & 7);
4029 	      dither  = Floyd8x8[y & 7];
4030               z       = 2 - z;
4031               r0      += z;
4032 
4033               for (x = xsize; x > 0; x --, r0 += 3)
4034               {
4035         	if ((*r0 & 63) > dither[x & 7])
4036         	  *ptr ^= (bitmask & OnPixels[*r0]);
4037         	else
4038         	  *ptr ^= (bitmask & OffPixels[*r0]);
4039 
4040                 if (bitmask > 3)
4041 		  bitmask >>= 2;
4042 		else
4043 		{
4044 		  bitmask = 0xc0;
4045 
4046 		  ptr ++;
4047         	}
4048 	      }
4049               break;
4050 
4051           case 4 :
4052               bitmask = 0xf0 >> (bitoffset & 7);
4053 	      dither  = Floyd4x4[y & 3];
4054               z       = 2 - z;
4055               r0      += z;
4056 
4057               for (x = xsize; x > 0; x --, r0 += 3)
4058               {
4059         	if ((*r0 & 15) > dither[x & 3])
4060         	  *ptr ^= (bitmask & OnPixels[*r0]);
4061         	else
4062         	  *ptr ^= (bitmask & OffPixels[*r0]);
4063 
4064                 if (bitmask == 0xf0)
4065 		  bitmask = 0x0f;
4066 		else
4067 		{
4068 		  bitmask = 0xf0;
4069 
4070 		  ptr ++;
4071         	}
4072 	      }
4073               break;
4074 
4075           case 8 :
4076               z  = 2 - z;
4077               r0 += z;
4078 	      r1 += z;
4079 
4080               for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
4081 	      {
4082         	if (*r0 == *r1)
4083                   *ptr++ = *r0;
4084         	else
4085                   *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
4086               }
4087               break;
4088         }
4089         break;
4090   }
4091 }
4092 
4093 
4094 /*
4095  * 'format_YMCK()' - Convert image data to YMCK.
4096  */
4097 
4098 static void
format_YMCK(cups_page_header2_t * header,unsigned char * row,int y,int z,int xsize,int ysize,int yerr0,int yerr1,cups_ib_t * r0,cups_ib_t * r1)4099 format_YMCK(cups_page_header2_t *header,/* I - Page header */
4100             unsigned char       *row,	/* IO - Bitmap data for device */
4101 	    int                 y,	/* I - Current row */
4102 	    int                 z,	/* I - Current plane */
4103 	    int                 xsize,	/* I - Width of image data */
4104 	    int	                ysize,	/* I - Height of image data */
4105 	    int                 yerr0,	/* I - Top Y error */
4106 	    int                 yerr1,	/* I - Bottom Y error */
4107 	    cups_ib_t           *r0,	/* I - Primary image data */
4108 	    cups_ib_t           *r1)	/* I - Image data for interpolation */
4109 {
4110   cups_ib_t	*ptr,			/* Pointer into row */
4111 		*cptr,			/* Pointer into cyan */
4112 		*mptr,			/* Pointer into magenta */
4113 		*yptr,			/* Pointer into yellow */
4114 		*kptr,			/* Pointer into black */
4115 		bitmask;		/* Current mask for pixel */
4116   int		bitoffset;		/* Current offset in line */
4117   int		bandwidth;		/* Width of a color band */
4118   int		x,			/* Current X coordinate on page */
4119 		*dither;		/* Pointer into dither array */
4120   int		pc, pm, py;		/* CMY pixels */
4121 
4122 
4123   switch (XPosition)
4124   {
4125     case -1 :
4126         bitoffset = 0;
4127 	break;
4128     default :
4129         bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
4130 	break;
4131     case 1 :
4132         bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
4133 	break;
4134   }
4135 
4136   ptr       = row + bitoffset / 8;
4137   bandwidth = header->cupsBytesPerLine / 4;
4138 
4139   switch (header->cupsColorOrder)
4140   {
4141     case CUPS_ORDER_CHUNKED :
4142         switch (header->cupsBitsPerColor)
4143         {
4144           case 1 :
4145               bitmask = 128 >> (bitoffset & 7);
4146               dither  = Floyd16x16[y & 15];
4147 
4148               for (x = xsize ; x > 0; x --)
4149               {
4150 	        pc = *r0++ > dither[x & 15];
4151 		pm = *r0++ > dither[x & 15];
4152 		py = *r0++ > dither[x & 15];
4153 
4154 		if (pc && pm && py)
4155 		{
4156 		  bitmask >>= 3;
4157 		  *ptr ^= bitmask;
4158 		}
4159 		else
4160 		{
4161 		  if (py)
4162 		    *ptr ^= bitmask;
4163 		  bitmask >>= 1;
4164 
4165 		  if (pm)
4166 		    *ptr ^= bitmask;
4167 		  bitmask >>= 1;
4168 
4169 		  if (pc)
4170 		    *ptr ^= bitmask;
4171 		  bitmask >>= 1;
4172                 }
4173 
4174                 if (bitmask > 1)
4175 		  bitmask >>= 1;
4176 		else
4177         	{
4178         	  bitmask = 128;
4179 
4180         	  ptr ++;
4181         	}
4182               }
4183               break;
4184 
4185           case 2 :
4186               dither = Floyd8x8[y & 7];
4187 
4188               for (x = xsize ; x > 0; x --, r0 += 4)
4189               {
4190 	       	if ((r0[2] & 63) > dither[x & 7])
4191         	  *ptr ^= (0xc0 & OnPixels[r0[2]]);
4192         	else
4193         	  *ptr ^= (0xc0 & OffPixels[r0[2]]);
4194 
4195         	if ((r0[1] & 63) > dither[x & 7])
4196         	  *ptr ^= (0x30 & OnPixels[r0[1]]);
4197         	else
4198         	  *ptr ^= (0x30 & OffPixels[r0[1]]);
4199 
4200         	if ((r0[0] & 63) > dither[x & 7])
4201         	  *ptr ^= (0x0c & OnPixels[r0[0]]);
4202         	else
4203         	  *ptr ^= (0x0c & OffPixels[r0[0]]);
4204 
4205         	if ((r0[3] & 63) > dither[x & 7])
4206         	  *ptr++ ^= (0x03 & OnPixels[r0[3]]);
4207         	else
4208         	  *ptr++ ^= (0x03 & OffPixels[r0[3]]);
4209               }
4210               break;
4211 
4212           case 4 :
4213               dither = Floyd4x4[y & 3];
4214 
4215               for (x = xsize ; x > 0; x --, r0 += 4)
4216               {
4217         	if ((r0[2] & 15) > dither[x & 3])
4218         	  *ptr ^= (0xf0 & OnPixels[r0[2]]);
4219         	else
4220         	  *ptr ^= (0xf0 & OffPixels[r0[2]]);
4221 
4222         	if ((r0[1] & 15) > dither[x & 3])
4223         	  *ptr++ ^= (0x0f & OnPixels[r0[1]]);
4224         	else
4225         	  *ptr++ ^= (0x0f & OffPixels[r0[1]]);
4226 
4227         	if ((r0[0] & 15) > dither[x & 3])
4228         	  *ptr ^= (0xf0 & OnPixels[r0[0]]);
4229         	else
4230         	  *ptr ^= (0xf0 & OffPixels[r0[0]]);
4231 
4232         	if ((r0[3] & 15) > dither[x & 3])
4233         	  *ptr++ ^= (0x0f & OnPixels[r0[3]]);
4234         	else
4235         	  *ptr++ ^= (0x0f & OffPixels[r0[3]]);
4236               }
4237               break;
4238 
4239           case 8 :
4240               for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
4241 	      {
4242         	if (r0[2] == r1[2])
4243                   *ptr++ = r0[2];
4244         	else
4245                   *ptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
4246 
4247         	if (r0[1] == r1[1])
4248                   *ptr++ = r0[1];
4249         	else
4250                   *ptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
4251 
4252         	if (r0[0] == r1[0])
4253                   *ptr++ = r0[0];
4254         	else
4255                   *ptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
4256 
4257         	if (r0[3] == r1[3])
4258                   *ptr++ = r0[3];
4259         	else
4260                   *ptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
4261               }
4262               break;
4263         }
4264         break;
4265 
4266     case CUPS_ORDER_BANDED :
4267 	yptr = ptr;
4268 	mptr = ptr + bandwidth;
4269 	cptr = ptr + 2 * bandwidth;
4270 	kptr = ptr + 3 * bandwidth;
4271 
4272         switch (header->cupsBitsPerColor)
4273         {
4274           case 1 :
4275               bitmask = 0x80 >> (bitoffset & 7);
4276               dither  = Floyd16x16[y & 15];
4277 
4278               for (x = xsize; x > 0; x --)
4279               {
4280 	        pc = *r0++ > dither[x & 15];
4281 		pm = *r0++ > dither[x & 15];
4282 		py = *r0++ > dither[x & 15];
4283 
4284 		if (pc && pm && py)
4285 		  *kptr ^= bitmask;
4286 		else
4287 		{
4288 		  if (pc)
4289         	    *cptr ^= bitmask;
4290 		  if (pm)
4291         	    *mptr ^= bitmask;
4292 		  if (py)
4293         	    *yptr ^= bitmask;
4294                 }
4295 
4296                 if (bitmask > 1)
4297 		  bitmask >>= 1;
4298 		else
4299 		{
4300 		  bitmask = 0x80;
4301 
4302 		  cptr ++;
4303 		  mptr ++;
4304 		  yptr ++;
4305 		  kptr ++;
4306         	}
4307 	      }
4308               break;
4309 
4310           case 2 :
4311               bitmask = 0xc0 >> (bitoffset & 7);
4312               dither  = Floyd8x8[y & 7];
4313 
4314               for (x = xsize; x > 0; x --)
4315               {
4316         	if ((*r0 & 63) > dither[x & 7])
4317         	  *cptr ^= (bitmask & OnPixels[*r0++]);
4318         	else
4319         	  *cptr ^= (bitmask & OffPixels[*r0++]);
4320 
4321         	if ((*r0 & 63) > dither[x & 7])
4322         	  *mptr ^= (bitmask & OnPixels[*r0++]);
4323         	else
4324         	  *mptr ^= (bitmask & OffPixels[*r0++]);
4325 
4326         	if ((*r0 & 63) > dither[x & 7])
4327         	  *yptr ^= (bitmask & OnPixels[*r0++]);
4328         	else
4329         	  *yptr ^= (bitmask & OffPixels[*r0++]);
4330 
4331         	if ((*r0 & 63) > dither[x & 7])
4332         	  *kptr ^= (bitmask & OnPixels[*r0++]);
4333         	else
4334         	  *kptr ^= (bitmask & OffPixels[*r0++]);
4335 
4336                 if (bitmask > 3)
4337 		  bitmask >>= 2;
4338 		else
4339 		{
4340 		  bitmask = 0xc0;
4341 
4342 		  cptr ++;
4343 		  mptr ++;
4344 		  yptr ++;
4345 		  kptr ++;
4346         	}
4347 	      }
4348               break;
4349 
4350           case 4 :
4351               bitmask = 0xf0 >> (bitoffset & 7);
4352               dither  = Floyd4x4[y & 3];
4353 
4354               for (x = xsize; x > 0; x --)
4355               {
4356         	if ((*r0 & 15) > dither[x & 3])
4357         	  *cptr ^= (bitmask & OnPixels[*r0++]);
4358         	else
4359         	  *cptr ^= (bitmask & OffPixels[*r0++]);
4360 
4361         	if ((*r0 & 15) > dither[x & 3])
4362         	  *mptr ^= (bitmask & OnPixels[*r0++]);
4363         	else
4364         	  *mptr ^= (bitmask & OffPixels[*r0++]);
4365 
4366         	if ((*r0 & 15) > dither[x & 3])
4367         	  *yptr ^= (bitmask & OnPixels[*r0++]);
4368         	else
4369         	  *yptr ^= (bitmask & OffPixels[*r0++]);
4370 
4371         	if ((*r0 & 15) > dither[x & 3])
4372         	  *kptr ^= (bitmask & OnPixels[*r0++]);
4373         	else
4374         	  *kptr ^= (bitmask & OffPixels[*r0++]);
4375 
4376                 if (bitmask == 0xf0)
4377 		  bitmask = 0x0f;
4378 		else
4379 		{
4380 		  bitmask = 0xf0;
4381 
4382 		  cptr ++;
4383 		  mptr ++;
4384 		  yptr ++;
4385 		  kptr ++;
4386         	}
4387 	      }
4388               break;
4389 
4390           case 8 :
4391               for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
4392 	      {
4393         	if (r0[0] == r1[0])
4394                   *cptr++ = r0[0];
4395         	else
4396                   *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
4397 
4398         	if (r0[1] == r1[1])
4399                   *mptr++ = r0[1];
4400         	else
4401                   *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
4402 
4403         	if (r0[2] == r1[2])
4404                   *yptr++ = r0[2];
4405         	else
4406                   *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
4407 
4408         	if (r0[3] == r1[3])
4409                   *kptr++ = r0[3];
4410         	else
4411                   *kptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
4412               }
4413               break;
4414         }
4415         break;
4416 
4417     case CUPS_ORDER_PLANAR :
4418         switch (header->cupsBitsPerColor)
4419         {
4420           case 1 :
4421               bitmask = 0x80 >> (bitoffset & 7);
4422               dither  = Floyd16x16[y & 15];
4423 
4424               for (x = xsize; x > 0; x --)
4425               {
4426 	        pc = *r0++ > dither[x & 15];
4427 		pm = *r0++ > dither[x & 15];
4428 		py = *r0++ > dither[x & 15];
4429 
4430 		if ((pc && pm && py && z == 3) ||
4431 		    (pc && z == 2) || (pm && z == 1) || (py && z == 0))
4432         	  *ptr ^= bitmask;
4433 
4434         	if (bitmask > 1)
4435 		  bitmask >>= 1;
4436 		else
4437 		{
4438 		  bitmask = 0x80;
4439 		  ptr ++;
4440         	}
4441 	      }
4442               break;
4443 
4444           case 2 :
4445               bitmask = 0xc0 >> (bitoffset & 7);
4446               dither  = Floyd8x8[y & 7];
4447               if (z == 3)
4448 	        r0 += 3;
4449 	      else
4450 	        r0 += 2 - z;
4451 
4452               for (x = xsize; x > 0; x --, r0 += 4)
4453               {
4454         	if ((*r0 & 63) > dither[x & 7])
4455         	  *ptr ^= (bitmask & OnPixels[*r0]);
4456         	else
4457         	  *ptr ^= (bitmask & OffPixels[*r0]);
4458 
4459                 if (bitmask > 3)
4460 		  bitmask >>= 2;
4461 		else
4462 		{
4463 		  bitmask = 0xc0;
4464 
4465 		  ptr ++;
4466         	}
4467 	      }
4468               break;
4469 
4470           case 4 :
4471               bitmask = 0xf0 >> (bitoffset & 7);
4472               dither  = Floyd4x4[y & 3];
4473               if (z == 3)
4474 	        r0 += 3;
4475 	      else
4476 	        r0 += 2 - z;
4477 
4478               for (x = xsize; x > 0; x --, r0 += 4)
4479               {
4480         	if ((*r0 & 15) > dither[x & 3])
4481         	  *ptr ^= (bitmask & OnPixels[*r0]);
4482         	else
4483         	  *ptr ^= (bitmask & OffPixels[*r0]);
4484 
4485                 if (bitmask == 0xf0)
4486 		  bitmask = 0x0f;
4487 		else
4488 		{
4489 		  bitmask = 0xf0;
4490 
4491 		  ptr ++;
4492         	}
4493 	      }
4494               break;
4495 
4496           case 8 :
4497               if (z == 3)
4498 	      {
4499 	        r0 += 3;
4500 	        r1 += 3;
4501 	      }
4502 	      else
4503 	      {
4504 	        r0 += 2 - z;
4505 	        r1 += 2 - z;
4506 	      }
4507 
4508               for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
4509 	      {
4510         	if (*r0 == *r1)
4511                   *ptr++ = *r0;
4512         	else
4513                   *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
4514               }
4515               break;
4516         }
4517         break;
4518   }
4519 }
4520 
4521 
4522 /*
4523  * 'make_lut()' - Make a lookup table given gamma and brightness values.
4524  */
4525 
4526 static void
make_lut(cups_ib_t * lut,int colorspace,float g,float b)4527 make_lut(cups_ib_t  *lut,		/* I - Lookup table */
4528 	 int        colorspace,		/* I - Colorspace */
4529          float      g,			/* I - Image gamma */
4530          float      b)			/* I - Image brightness */
4531 {
4532   int	i;				/* Looping var */
4533   int	v;				/* Current value */
4534 
4535 
4536   g = 1.0 / g;
4537   b = 1.0 / b;
4538 
4539   for (i = 0; i < 256; i ++)
4540   {
4541     if (colorspace < 0)
4542       v = 255.0 * b * (1.0 - pow(1.0 - (float)i / 255.0, g)) + 0.5;
4543     else
4544       v = 255.0 * (1.0 - b * (1.0 - pow((float)i / 255.0, g))) + 0.5;
4545 
4546     if (v < 0)
4547       *lut++ = 0;
4548     else if (v > 255)
4549       *lut++ = 255;
4550     else
4551       *lut++ = v;
4552   }
4553 }
4554 
4555 
4556 /*
4557  * 'raster_cb()' - Validate the page header.
4558  */
4559 
4560 static int				/* O - 0 if OK, -1 if not */
raster_cb(cups_page_header2_t * header,int preferred_bits)4561 raster_cb(
4562     cups_page_header2_t *header,	/* IO - Raster header */
4563     int                 preferred_bits)	/* I  - Preferred bits per color */
4564 {
4565  /*
4566   * Ensure that colorimetric colorspaces use at least 8 bits per
4567   * component...
4568   */
4569 
4570   if ((header->cupsColorSpace == CUPS_CSPACE_CIEXYZ ||
4571        header->cupsColorSpace == CUPS_CSPACE_CIELab ||
4572        header->cupsColorSpace >= CUPS_CSPACE_ICC1) &&
4573       header->cupsBitsPerColor < 8)
4574     header->cupsBitsPerColor = 8;
4575 
4576   return (0);
4577 }
4578 
4579