1 /*
2  * Raster file routines for CUPS.
3  *
4  * Copyright 2007-2019 by Apple Inc.
5  * Copyright 1997-2006 by Easy Software Products.
6  *
7  * This file is part of the CUPS Imaging library.
8  *
9  * Licensed under Apache License v2.0.  See the file "LICENSE" for more
10  * information.
11  */
12 
13 /*
14  * Include necessary headers...
15  */
16 
17 #include "raster-private.h"
18 #include "debug-internal.h"
19 #ifdef HAVE_STDINT_H
20 #  include <stdint.h>
21 #endif /* HAVE_STDINT_H */
22 
23 
24 /*
25  * Private structures...
26  */
27 
28 typedef void (*_cups_copyfunc_t)(void *dst, const void *src, size_t bytes);
29 
30 
31 /*
32  * Local globals...
33  */
34 
35 static const char * const apple_media_types[] =
36 {					/* media-type values for Apple Raster */
37   "auto",
38   "stationery",
39   "transparency",
40   "envelope",
41   "cardstock",
42   "labels",
43   "stationery-letterhead",
44   "disc",
45   "photographic-matte",
46   "photographic-satin",
47   "photographic-semi-gloss",
48   "photographic-glossy",
49   "photographic-high-gloss",
50   "other"
51 };
52 
53 #ifdef DEBUG
54 static const char * const cups_modes[] =
55 {					/* Open modes */
56   "CUPS_RASTER_READ",
57   "CUPS_RASTER_WRITE",
58   "CUPS_RASTER_WRITE_COMPRESSED",
59   "CUPS_RASTER_WRITE_PWG",
60   "CUPS_RASTER_WRITE_APPLE"
61 };
62 #endif /* DEBUG */
63 
64 
65 /*
66  * Local functions...
67  */
68 
69 static ssize_t	cups_raster_io(cups_raster_t *r, unsigned char *buf, size_t bytes);
70 static ssize_t	cups_raster_read(cups_raster_t *r, unsigned char *buf, size_t bytes);
71 static int	cups_raster_update(cups_raster_t *r);
72 static ssize_t	cups_raster_write(cups_raster_t *r, const unsigned char *pixels);
73 static void	cups_swap(unsigned char *buf, size_t bytes);
74 static void	cups_swap_copy(unsigned char *dst, const unsigned char *src, size_t bytes);
75 
76 
77 /*
78  * '_cupsRasterColorSpaceString()' - Return the colorspace name for a
79  *                                   cupsColorSpace value.
80  */
81 
82 const char *
_cupsRasterColorSpaceString(cups_cspace_t cspace)83 _cupsRasterColorSpaceString(
84     cups_cspace_t cspace)		/* I - cupsColorSpace value */
85 {
86   static const char * const cups_color_spaces[] =
87   {					/* Color spaces */
88     "W",
89     "RGB",
90     "RGBA",
91     "K",
92     "CMY",
93     "YMC",
94     "CMYK",
95     "YMCK",
96     "KCMY",
97     "KCMYcm",
98     "GMCK",
99     "GMCS",
100     "WHITE",
101     "GOLD",
102     "SILVER",
103     "CIEXYZ",
104     "CIELab",
105     "RGBW",
106     "SW",
107     "SRGB",
108     "ADOBERGB",
109     "21",
110     "22",
111     "23",
112     "24",
113     "25",
114     "26",
115     "27",
116     "28",
117     "29",
118     "30",
119     "31",
120     "ICC1",
121     "ICC2",
122     "ICC3",
123     "ICC4",
124     "ICC5",
125     "ICC6",
126     "ICC7",
127     "ICC8",
128     "ICC9",
129     "ICCA",
130     "ICCB",
131     "ICCC",
132     "ICCD",
133     "ICCE",
134     "ICCF",
135     "47",
136     "DEVICE1",
137     "DEVICE2",
138     "DEVICE3",
139     "DEVICE4",
140     "DEVICE5",
141     "DEVICE6",
142     "DEVICE7",
143     "DEVICE8",
144     "DEVICE9",
145     "DEVICEA",
146     "DEVICEB",
147     "DEVICEC",
148     "DEVICED",
149     "DEVICEE",
150     "DEVICEF"
151   };
152 
153   if (cspace < CUPS_CSPACE_W || cspace > CUPS_CSPACE_DEVICEF)
154     return ("Unknown");
155   else
156     return (cups_color_spaces[cspace]);
157 }
158 
159 
160 /*
161  * '_cupsRasterDelete()' - Free a raster stream.
162  *
163  * The file descriptor associated with the raster stream must be closed
164  * separately as needed.
165  */
166 
167 void
_cupsRasterDelete(cups_raster_t * r)168 _cupsRasterDelete(cups_raster_t *r)	/* I - Stream to free */
169 {
170   if (r != NULL)
171   {
172     if (r->buffer)
173       free(r->buffer);
174 
175     if (r->pixels)
176       free(r->pixels);
177 
178     free(r);
179   }
180 }
181 
182 
183 /*
184  * '_cupsRasterInitPWGHeader()' - Initialize a page header for PWG Raster output.
185  *
186  * The "media" argument specifies the media to use.
187  *
188  * The "type" argument specifies a "pwg-raster-document-type-supported" value
189  * that controls the color space and bit depth of the raster data.
190  *
191  * The "xres" and "yres" arguments specify the raster resolution in dots per
192  * inch.
193  *
194  * The "sheet_back" argument specifies a "pwg-raster-document-sheet-back" value
195  * to apply for the back side of a page.  Pass @code NULL@ for the front side.
196  *
197  * @since CUPS 2.2/macOS 10.12@
198  */
199 
200 int					/* O - 1 on success, 0 on failure */
_cupsRasterInitPWGHeader(cups_page_header2_t * h,pwg_media_t * media,const char * type,int xdpi,int ydpi,const char * sides,const char * sheet_back)201 _cupsRasterInitPWGHeader(
202     cups_page_header2_t *h,		/* I - Page header */
203     pwg_media_t         *media,		/* I - PWG media information */
204     const char          *type,		/* I - PWG raster type string */
205     int                 xdpi,		/* I - Cross-feed direction (horizontal) resolution */
206     int                 ydpi,		/* I - Feed direction (vertical) resolution */
207     const char          *sides,		/* I - IPP "sides" option value */
208     const char          *sheet_back)	/* I - Transform for back side or @code NULL@ for none */
209 {
210   if (!h || !media || !type || xdpi <= 0 || ydpi <= 0)
211   {
212     _cupsRasterAddError("%s", strerror(EINVAL));
213     return (0);
214   }
215 
216  /*
217   * Initialize the page header...
218   */
219 
220   memset(h, 0, sizeof(cups_page_header2_t));
221 
222   strlcpy(h->cupsPageSizeName, media->pwg, sizeof(h->cupsPageSizeName));
223 
224   h->PageSize[0] = (unsigned)(72 * media->width / 2540);
225   h->PageSize[1] = (unsigned)(72 * media->length / 2540);
226 
227   /* This never gets written but is needed for some applications */
228   h->cupsPageSize[0] = 72.0f * media->width / 2540.0f;
229   h->cupsPageSize[1] = 72.0f * media->length / 2540.0f;
230 
231   h->ImagingBoundingBox[2] = h->PageSize[0];
232   h->ImagingBoundingBox[3] = h->PageSize[1];
233 
234   h->HWResolution[0] = (unsigned)xdpi;
235   h->HWResolution[1] = (unsigned)ydpi;
236 
237   h->cupsWidth  = (unsigned)(media->width * xdpi / 2540);
238   h->cupsHeight = (unsigned)(media->length * ydpi / 2540);
239 
240   if (h->cupsWidth > 0x00ffffff || h->cupsHeight > 0x00ffffff)
241   {
242     _cupsRasterAddError("Raster dimensions too large.");
243     return (0);
244   }
245 
246   h->cupsInteger[CUPS_RASTER_PWG_ImageBoxRight]  = h->cupsWidth;
247   h->cupsInteger[CUPS_RASTER_PWG_ImageBoxBottom] = h->cupsHeight;
248 
249  /*
250   * Colorspace and bytes per line...
251   */
252 
253   if (!strcmp(type, "adobe-rgb_8"))
254   {
255     h->cupsBitsPerColor = 8;
256     h->cupsBitsPerPixel = 24;
257     h->cupsColorSpace   = CUPS_CSPACE_ADOBERGB;
258   }
259   else if (!strcmp(type, "adobe-rgb_16"))
260   {
261     h->cupsBitsPerColor = 16;
262     h->cupsBitsPerPixel = 48;
263     h->cupsColorSpace   = CUPS_CSPACE_ADOBERGB;
264   }
265   else if (!strcmp(type, "black_1"))
266   {
267     h->cupsBitsPerColor = 1;
268     h->cupsBitsPerPixel = 1;
269     h->cupsColorSpace   = CUPS_CSPACE_K;
270   }
271   else if (!strcmp(type, "black_8"))
272   {
273     h->cupsBitsPerColor = 8;
274     h->cupsBitsPerPixel = 8;
275     h->cupsColorSpace   = CUPS_CSPACE_K;
276   }
277   else if (!strcmp(type, "black_16"))
278   {
279     h->cupsBitsPerColor = 16;
280     h->cupsBitsPerPixel = 16;
281     h->cupsColorSpace   = CUPS_CSPACE_K;
282   }
283   else if (!strcmp(type, "cmyk_8"))
284   {
285     h->cupsBitsPerColor = 8;
286     h->cupsBitsPerPixel = 32;
287     h->cupsColorSpace   = CUPS_CSPACE_CMYK;
288   }
289   else if (!strcmp(type, "cmyk_16"))
290   {
291     h->cupsBitsPerColor = 16;
292     h->cupsBitsPerPixel = 64;
293     h->cupsColorSpace   = CUPS_CSPACE_CMYK;
294   }
295   else if (!strncmp(type, "device", 6) && type[6] >= '1' && type[6] <= '9')
296   {
297     int ncolors, bits;			/* Number of colors and bits */
298 
299 
300     if (sscanf(type, "device%d_%d", &ncolors, &bits) != 2 || ncolors > 15 || (bits != 8 && bits != 16))
301     {
302       _cupsRasterAddError("Unsupported raster type \'%s\'.", type);
303       return (0);
304     }
305 
306     h->cupsBitsPerColor = (unsigned)bits;
307     h->cupsBitsPerPixel = (unsigned)(ncolors * bits);
308     h->cupsColorSpace   = (cups_cspace_t)(CUPS_CSPACE_DEVICE1 + ncolors - 1);
309   }
310   else if (!strcmp(type, "rgb_8"))
311   {
312     h->cupsBitsPerColor = 8;
313     h->cupsBitsPerPixel = 24;
314     h->cupsColorSpace   = CUPS_CSPACE_RGB;
315   }
316   else if (!strcmp(type, "rgb_16"))
317   {
318     h->cupsBitsPerColor = 16;
319     h->cupsBitsPerPixel = 48;
320     h->cupsColorSpace   = CUPS_CSPACE_RGB;
321   }
322   else if (!strcmp(type, "sgray_1"))
323   {
324     h->cupsBitsPerColor = 1;
325     h->cupsBitsPerPixel = 1;
326     h->cupsColorSpace   = CUPS_CSPACE_SW;
327   }
328   else if (!strcmp(type, "sgray_8"))
329   {
330     h->cupsBitsPerColor = 8;
331     h->cupsBitsPerPixel = 8;
332     h->cupsColorSpace   = CUPS_CSPACE_SW;
333   }
334   else if (!strcmp(type, "sgray_16"))
335   {
336     h->cupsBitsPerColor = 16;
337     h->cupsBitsPerPixel = 16;
338     h->cupsColorSpace   = CUPS_CSPACE_SW;
339   }
340   else if (!strcmp(type, "srgb_8"))
341   {
342     h->cupsBitsPerColor = 8;
343     h->cupsBitsPerPixel = 24;
344     h->cupsColorSpace   = CUPS_CSPACE_SRGB;
345   }
346   else if (!strcmp(type, "srgb_16"))
347   {
348     h->cupsBitsPerColor = 16;
349     h->cupsBitsPerPixel = 48;
350     h->cupsColorSpace   = CUPS_CSPACE_SRGB;
351   }
352   else
353   {
354     _cupsRasterAddError("Unsupported raster type \'%s\'.", type);
355     return (0);
356   }
357 
358   h->cupsColorOrder   = CUPS_ORDER_CHUNKED;
359   h->cupsNumColors    = h->cupsBitsPerPixel / h->cupsBitsPerColor;
360   h->cupsBytesPerLine = (h->cupsWidth * h->cupsBitsPerPixel + 7) / 8;
361 
362  /*
363   * Duplex support...
364   */
365 
366   h->cupsInteger[CUPS_RASTER_PWG_CrossFeedTransform] = 1;
367   h->cupsInteger[CUPS_RASTER_PWG_FeedTransform]      = 1;
368 
369   if (sides)
370   {
371     if (!strcmp(sides, "two-sided-long-edge"))
372     {
373       h->Duplex = 1;
374     }
375     else if (!strcmp(sides, "two-sided-short-edge"))
376     {
377       h->Duplex = 1;
378       h->Tumble = 1;
379     }
380     else if (strcmp(sides, "one-sided"))
381     {
382       _cupsRasterAddError("Unsupported sides value \'%s\'.", sides);
383       return (0);
384     }
385 
386     if (sheet_back)
387     {
388       if (!strcmp(sheet_back, "flipped"))
389       {
390         if (h->Tumble)
391           h->cupsInteger[CUPS_RASTER_PWG_CrossFeedTransform] = 0xffffffffU;
392         else
393           h->cupsInteger[CUPS_RASTER_PWG_FeedTransform] = 0xffffffffU;
394       }
395       else if (!strcmp(sheet_back, "manual-tumble"))
396       {
397         if (h->Tumble)
398         {
399           h->cupsInteger[CUPS_RASTER_PWG_CrossFeedTransform] = 0xffffffffU;
400           h->cupsInteger[CUPS_RASTER_PWG_FeedTransform]      = 0xffffffffU;
401         }
402       }
403       else if (!strcmp(sheet_back, "rotated"))
404       {
405         if (!h->Tumble)
406         {
407           h->cupsInteger[CUPS_RASTER_PWG_CrossFeedTransform] = 0xffffffffU;
408           h->cupsInteger[CUPS_RASTER_PWG_FeedTransform]      = 0xffffffffU;
409         }
410       }
411       else if (strcmp(sheet_back, "normal"))
412       {
413 	_cupsRasterAddError("Unsupported sheet_back value \'%s\'.", sheet_back);
414 	return (0);
415       }
416     }
417   }
418 
419   return (1);
420 }
421 
422 
423 /*
424  * '_cupsRasterNew()' - Create a raster stream using a callback function.
425  *
426  * This function associates a raster stream with the given callback function and
427  * context pointer.
428  *
429  * When writing raster data, the @code CUPS_RASTER_WRITE@,
430  * @code CUPS_RASTER_WRITE_COMPRESS@, or @code CUPS_RASTER_WRITE_PWG@ mode can
431  * be used - compressed and PWG output is generally 25-50% smaller but adds a
432  * 100-300% execution time overhead.
433  */
434 
435 cups_raster_t *				/* O - New stream */
_cupsRasterNew(cups_raster_iocb_t iocb,void * ctx,cups_mode_t mode)436 _cupsRasterNew(
437     cups_raster_iocb_t iocb,		/* I - Read/write callback */
438     void               *ctx,		/* I - Context pointer for callback */
439     cups_mode_t        mode)		/* I - Mode - @code CUPS_RASTER_READ@,
440 	                                       @code CUPS_RASTER_WRITE@,
441 					       @code CUPS_RASTER_WRITE_COMPRESSED@,
442 					       or @code CUPS_RASTER_WRITE_PWG@ */
443 {
444   cups_raster_t	*r;			/* New stream */
445 
446 
447   DEBUG_printf(("_cupsRasterOpenIO(iocb=%p, ctx=%p, mode=%s)", (void *)iocb, ctx, cups_modes[mode]));
448 
449   _cupsRasterClearError();
450 
451   if ((r = calloc(sizeof(cups_raster_t), 1)) == NULL)
452   {
453     _cupsRasterAddError("Unable to allocate memory for raster stream: %s\n",
454                         strerror(errno));
455     DEBUG_puts("1_cupsRasterOpenIO: Returning NULL.");
456     return (NULL);
457   }
458 
459   r->ctx  = ctx;
460   r->iocb = iocb;
461   r->mode = mode;
462 
463   if (mode == CUPS_RASTER_READ)
464   {
465    /*
466     * Open for read - get sync word...
467     */
468 
469     if (cups_raster_io(r, (unsigned char *)&(r->sync), sizeof(r->sync)) !=
470             sizeof(r->sync))
471     {
472       _cupsRasterAddError("Unable to read header from raster stream: %s\n",
473                           strerror(errno));
474       free(r);
475       DEBUG_puts("1_cupsRasterOpenIO: Unable to read header, returning NULL.");
476       return (NULL);
477     }
478 
479     if (r->sync != CUPS_RASTER_SYNC &&
480         r->sync != CUPS_RASTER_REVSYNC &&
481         r->sync != CUPS_RASTER_SYNCv1 &&
482         r->sync != CUPS_RASTER_REVSYNCv1 &&
483         r->sync != CUPS_RASTER_SYNCv2 &&
484         r->sync != CUPS_RASTER_REVSYNCv2 &&
485         r->sync != CUPS_RASTER_SYNCapple &&
486         r->sync != CUPS_RASTER_REVSYNCapple)
487     {
488       _cupsRasterAddError("Unknown raster format %08x!\n", r->sync);
489       free(r);
490       DEBUG_puts("1_cupsRasterOpenIO: Unknown format, returning NULL.");
491       return (NULL);
492     }
493 
494     if (r->sync == CUPS_RASTER_SYNCv2 ||
495         r->sync == CUPS_RASTER_REVSYNCv2 ||
496         r->sync == CUPS_RASTER_SYNCapple ||
497         r->sync == CUPS_RASTER_REVSYNCapple)
498       r->compressed = 1;
499 
500     DEBUG_printf(("1_cupsRasterOpenIO: sync=%08x", r->sync));
501 
502     if (r->sync == CUPS_RASTER_REVSYNC ||
503         r->sync == CUPS_RASTER_REVSYNCv1 ||
504         r->sync == CUPS_RASTER_REVSYNCv2 ||
505         r->sync == CUPS_RASTER_REVSYNCapple)
506       r->swapped = 1;
507 
508     if (r->sync == CUPS_RASTER_SYNCapple ||
509         r->sync == CUPS_RASTER_REVSYNCapple)
510     {
511       unsigned char	header[8];	/* File header */
512 
513       if (cups_raster_io(r, (unsigned char *)header, sizeof(header)) !=
514 	      sizeof(header))
515       {
516 	_cupsRasterAddError("Unable to read header from raster stream: %s\n",
517 			    strerror(errno));
518 	free(r);
519 	DEBUG_puts("1_cupsRasterOpenIO: Unable to read header, returning NULL.");
520 	return (NULL);
521       }
522     }
523 
524 #ifdef DEBUG
525     r->iostart = r->iocount;
526 #endif /* DEBUG */
527   }
528   else
529   {
530    /*
531     * Open for write - put sync word...
532     */
533 
534     switch (mode)
535     {
536       default :
537       case CUPS_RASTER_WRITE :
538           r->sync = CUPS_RASTER_SYNC;
539 	  break;
540 
541       case CUPS_RASTER_WRITE_COMPRESSED :
542           r->compressed = 1;
543           r->sync       = CUPS_RASTER_SYNCv2;
544 	  break;
545 
546       case CUPS_RASTER_WRITE_PWG :
547           r->compressed = 1;
548           r->sync       = htonl(CUPS_RASTER_SYNC_PWG);
549           r->swapped    = r->sync != CUPS_RASTER_SYNC_PWG;
550 	  break;
551 
552       case CUPS_RASTER_WRITE_APPLE :
553           r->compressed     = 1;
554           r->sync           = htonl(CUPS_RASTER_SYNCapple);
555           r->swapped        = r->sync != CUPS_RASTER_SYNCapple;
556           r->apple_page_count = 0xffffffffU;
557 	  break;
558     }
559 
560     if (cups_raster_io(r, (unsigned char *)&(r->sync), sizeof(r->sync)) < (ssize_t)sizeof(r->sync))
561     {
562       _cupsRasterAddError("Unable to write raster stream header: %s\n",
563                           strerror(errno));
564       free(r);
565       DEBUG_puts("1_cupsRasterOpenIO: Unable to write header, returning NULL.");
566       return (NULL);
567     }
568   }
569 
570   DEBUG_printf(("1_cupsRasterOpenIO: compressed=%d, swapped=%d, returning %p", r->compressed, r->swapped, (void *)r));
571 
572   return (r);
573 }
574 
575 
576 /*
577  * '_cupsRasterReadHeader()' - Read a raster page header.
578  */
579 
580 unsigned				/* O - 1 on success, 0 on fail */
_cupsRasterReadHeader(cups_raster_t * r)581 _cupsRasterReadHeader(
582     cups_raster_t *r)			/* I - Raster stream */
583 {
584   size_t	len;			/* Length for read/swap */
585 
586 
587   DEBUG_printf(("3_cupsRasterReadHeader(r=%p), r->mode=%s", (void *)r, r ? cups_modes[r->mode] : ""));
588 
589   if (r == NULL || r->mode != CUPS_RASTER_READ)
590     return (0);
591 
592   DEBUG_printf(("4_cupsRasterReadHeader: r->iocount=" CUPS_LLFMT, CUPS_LLCAST r->iocount));
593 
594   memset(&(r->header), 0, sizeof(r->header));
595 
596  /*
597   * Read the header...
598   */
599 
600   switch (r->sync)
601   {
602     default :
603        /*
604 	* Get the length of the raster header...
605 	*/
606 
607 	if (r->sync == CUPS_RASTER_SYNCv1 || r->sync == CUPS_RASTER_REVSYNCv1)
608 	  len = sizeof(cups_page_header_t);
609 	else
610 	  len = sizeof(cups_page_header2_t);
611 
612 	DEBUG_printf(("4_cupsRasterReadHeader: len=%d", (int)len));
613 
614        /*
615         * Read it...
616         */
617 
618 	if (cups_raster_read(r, (unsigned char *)&(r->header), len) < (ssize_t)len)
619 	{
620 	  DEBUG_printf(("4_cupsRasterReadHeader: EOF, r->iocount=" CUPS_LLFMT, CUPS_LLCAST r->iocount));
621 	  return (0);
622 	}
623 
624        /*
625 	* Swap bytes as needed...
626 	*/
627 
628 	if (r->swapped)
629 	{
630 	  unsigned	*s,		/* Current word */
631 			temp;		/* Temporary copy */
632 
633 
634 	  DEBUG_puts("4_cupsRasterReadHeader: Swapping header bytes.");
635 
636 	  for (len = 81, s = &(r->header.AdvanceDistance);
637 	       len > 0;
638 	       len --, s ++)
639 	  {
640 	    temp = *s;
641 	    *s   = ((temp & 0xff) << 24) |
642 		   ((temp & 0xff00) << 8) |
643 		   ((temp & 0xff0000) >> 8) |
644 		   ((temp & 0xff000000) >> 24);
645 
646 	    DEBUG_printf(("4_cupsRasterReadHeader: %08x => %08x", temp, *s));
647 	  }
648 	}
649         break;
650 
651     case CUPS_RASTER_SYNCapple :
652     case CUPS_RASTER_REVSYNCapple :
653         {
654           unsigned char	appleheader[32];	/* Raw header */
655           static const unsigned rawcspace[] =
656           {
657             CUPS_CSPACE_SW,
658             CUPS_CSPACE_SRGB,
659             CUPS_CSPACE_CIELab,
660             CUPS_CSPACE_ADOBERGB,
661             CUPS_CSPACE_W,
662             CUPS_CSPACE_RGB,
663             CUPS_CSPACE_CMYK
664           };
665           static const unsigned rawnumcolors[] =
666           {
667             1,
668             3,
669             3,
670             3,
671             1,
672             3,
673             4
674           };
675 
676 	  if (cups_raster_read(r, appleheader, sizeof(appleheader)) < (ssize_t)sizeof(appleheader))
677 	  {
678 	    DEBUG_printf(("4_cupsRasterReadHeader: EOF, r->iocount=" CUPS_LLFMT, CUPS_LLCAST r->iocount));
679 	    return (0);
680 	  }
681 
682 	  strlcpy(r->header.MediaClass, "PwgRaster", sizeof(r->header.MediaClass));
683 					      /* PwgRaster */
684           r->header.cupsBitsPerPixel = appleheader[0];
685           r->header.cupsColorSpace   = appleheader[1] >= (sizeof(rawcspace) / sizeof(rawcspace[0])) ? CUPS_CSPACE_DEVICE1 : rawcspace[appleheader[1]];
686           r->header.cupsNumColors    = appleheader[1] >= (sizeof(rawnumcolors) / sizeof(rawnumcolors[0])) ? 1 : rawnumcolors[appleheader[1]];
687           r->header.cupsBitsPerColor = r->header.cupsBitsPerPixel / r->header.cupsNumColors;
688           r->header.cupsWidth        = ((((((unsigned)appleheader[12] << 8) | (unsigned)appleheader[13]) << 8) | (unsigned)appleheader[14]) << 8) | (unsigned)appleheader[15];
689           r->header.cupsHeight       = ((((((unsigned)appleheader[16] << 8) | (unsigned)appleheader[17]) << 8) | (unsigned)appleheader[18]) << 8) | (unsigned)appleheader[19];
690           r->header.cupsBytesPerLine = r->header.cupsWidth * r->header.cupsBitsPerPixel / 8;
691           r->header.cupsColorOrder   = CUPS_ORDER_CHUNKED;
692           r->header.HWResolution[0]  = r->header.HWResolution[1] = ((((((unsigned)appleheader[20] << 8) | (unsigned)appleheader[21]) << 8) | (unsigned)appleheader[22]) << 8) | (unsigned)appleheader[23];
693 
694           if (r->header.HWResolution[0] > 0)
695           {
696 	    r->header.PageSize[0]     = (unsigned)(r->header.cupsWidth * 72 / r->header.HWResolution[0]);
697 	    r->header.PageSize[1]     = (unsigned)(r->header.cupsHeight * 72 / r->header.HWResolution[1]);
698 	    r->header.cupsPageSize[0] = (float)(r->header.cupsWidth * 72.0 / r->header.HWResolution[0]);
699 	    r->header.cupsPageSize[1] = (float)(r->header.cupsHeight * 72.0 / r->header.HWResolution[1]);
700           }
701 
702           r->header.cupsInteger[CUPS_RASTER_PWG_TotalPageCount]   = r->apple_page_count;
703           r->header.cupsInteger[CUPS_RASTER_PWG_AlternatePrimary] = 0xffffff;
704           r->header.cupsInteger[CUPS_RASTER_PWG_PrintQuality]     = appleheader[3];
705 
706           if (appleheader[2] >= 2)
707             r->header.Duplex = 1;
708           if (appleheader[2] == 2)
709             r->header.Tumble = 1;
710 
711           r->header.MediaPosition = appleheader[5];
712 
713           if (appleheader[4] < (int)(sizeof(apple_media_types) / sizeof(apple_media_types[0])))
714             strlcpy(r->header.MediaType, apple_media_types[appleheader[4]], sizeof(r->header.MediaType));
715           else
716             strlcpy(r->header.MediaType, "other", sizeof(r->header.MediaType));
717         }
718         break;
719   }
720 
721  /*
722   * Update the header and row count...
723   */
724 
725   if (!cups_raster_update(r))
726     return (0);
727 
728   DEBUG_printf(("4_cupsRasterReadHeader: cupsColorSpace=%s", _cupsRasterColorSpaceString(r->header.cupsColorSpace)));
729   DEBUG_printf(("4_cupsRasterReadHeader: cupsBitsPerColor=%u", r->header.cupsBitsPerColor));
730   DEBUG_printf(("4_cupsRasterReadHeader: cupsBitsPerPixel=%u", r->header.cupsBitsPerPixel));
731   DEBUG_printf(("4_cupsRasterReadHeader: cupsBytesPerLine=%u", r->header.cupsBytesPerLine));
732   DEBUG_printf(("4_cupsRasterReadHeader: cupsWidth=%u", r->header.cupsWidth));
733   DEBUG_printf(("4_cupsRasterReadHeader: cupsHeight=%u", r->header.cupsHeight));
734   DEBUG_printf(("4_cupsRasterReadHeader: r->bpp=%d", r->bpp));
735 
736   return (r->header.cupsBitsPerPixel > 0 && r->header.cupsBitsPerPixel <= 240 && r->header.cupsBitsPerColor > 0 && r->header.cupsBitsPerColor <= 16 && r->header.cupsBytesPerLine > 0 && r->header.cupsBytesPerLine <= 0x7fffffff && r->header.cupsHeight != 0 && (r->header.cupsBytesPerLine % r->bpp) == 0);
737 }
738 
739 
740 /*
741  * '_cupsRasterReadPixels()' - Read raster pixels.
742  *
743  * For best performance, filters should read one or more whole lines.
744  * The "cupsBytesPerLine" value from the page header can be used to allocate
745  * the line buffer and as the number of bytes to read.
746  */
747 
748 unsigned				/* O - Number of bytes read */
_cupsRasterReadPixels(cups_raster_t * r,unsigned char * p,unsigned len)749 _cupsRasterReadPixels(
750     cups_raster_t *r,			/* I - Raster stream */
751     unsigned char *p,			/* I - Pointer to pixel buffer */
752     unsigned      len)			/* I - Number of bytes to read */
753 {
754   ssize_t	bytes;			/* Bytes read */
755   unsigned	cupsBytesPerLine;	/* cupsBytesPerLine value */
756   unsigned	remaining;		/* Bytes remaining */
757   unsigned char	*ptr,			/* Pointer to read buffer */
758 		byte,			/* Byte from file */
759 		*temp;			/* Pointer into buffer */
760   unsigned	count;			/* Repetition count */
761 
762 
763   DEBUG_printf(("_cupsRasterReadPixels(r=%p, p=%p, len=%u)", (void *)r, (void *)p, len));
764 
765   if (r == NULL || r->mode != CUPS_RASTER_READ || r->remaining == 0 ||
766       r->header.cupsBytesPerLine == 0)
767   {
768     DEBUG_puts("1_cupsRasterReadPixels: Returning 0.");
769     return (0);
770   }
771 
772   DEBUG_printf(("1_cupsRasterReadPixels: compressed=%d, remaining=%u", r->compressed, r->remaining));
773 
774   if (!r->compressed)
775   {
776    /*
777     * Read without compression...
778     */
779 
780     r->remaining -= len / r->header.cupsBytesPerLine;
781 
782     if (cups_raster_io(r, p, len) < (ssize_t)len)
783     {
784       DEBUG_puts("1_cupsRasterReadPixels: Read error, returning 0.");
785       return (0);
786     }
787 
788    /*
789     * Swap bytes as needed...
790     */
791 
792     if (r->swapped &&
793         (r->header.cupsBitsPerColor == 16 ||
794          r->header.cupsBitsPerPixel == 12 ||
795          r->header.cupsBitsPerPixel == 16))
796       cups_swap(p, len);
797 
798    /*
799     * Return...
800     */
801 
802     DEBUG_printf(("1_cupsRasterReadPixels: Returning %u", len));
803 
804     return (len);
805   }
806 
807  /*
808   * Read compressed data...
809   */
810 
811   remaining        = len;
812   cupsBytesPerLine = r->header.cupsBytesPerLine;
813 
814   while (remaining > 0 && r->remaining > 0)
815   {
816     if (r->count == 0)
817     {
818      /*
819       * Need to read a new row...
820       */
821 
822       if (remaining == cupsBytesPerLine)
823 	ptr = p;
824       else
825 	ptr = r->pixels;
826 
827      /*
828       * Read using a modified PackBits compression...
829       */
830 
831       if (!cups_raster_read(r, &byte, 1))
832       {
833 	DEBUG_puts("1_cupsRasterReadPixels: Read error, returning 0.");
834 	return (0);
835       }
836 
837       r->count = (unsigned)byte + 1;
838 
839       if (r->count > 1)
840 	ptr = r->pixels;
841 
842       temp  = ptr;
843       bytes = (ssize_t)cupsBytesPerLine;
844 
845       while (bytes > 0)
846       {
847        /*
848 	* Get a new repeat count...
849 	*/
850 
851         if (!cups_raster_read(r, &byte, 1))
852 	{
853 	  DEBUG_puts("1_cupsRasterReadPixels: Read error, returning 0.");
854 	  return (0);
855 	}
856 
857         if (byte == 128)
858         {
859          /*
860           * Clear to end of line...
861           */
862 
863           switch (r->header.cupsColorSpace)
864           {
865             case CUPS_CSPACE_W :
866             case CUPS_CSPACE_RGB :
867             case CUPS_CSPACE_SW :
868             case CUPS_CSPACE_SRGB :
869             case CUPS_CSPACE_RGBW :
870             case CUPS_CSPACE_ADOBERGB :
871                 memset(temp, 0xff, (size_t)bytes);
872                 break;
873             default :
874                 memset(temp, 0x00, (size_t)bytes);
875                 break;
876           }
877 
878           temp += bytes;
879           bytes = 0;
880         }
881 	else if (byte & 128)
882 	{
883 	 /*
884 	  * Copy N literal pixels...
885 	  */
886 
887 	  count = (unsigned)(257 - byte) * r->bpp;
888 
889           if (count > (unsigned)bytes)
890 	    count = (unsigned)bytes;
891 
892           if (!cups_raster_read(r, temp, count))
893 	  {
894 	    DEBUG_puts("1_cupsRasterReadPixels: Read error, returning 0.");
895 	    return (0);
896 	  }
897 
898 	  temp  += count;
899 	  bytes -= (ssize_t)count;
900 	}
901 	else
902 	{
903 	 /*
904 	  * Repeat the next N bytes...
905 	  */
906 
907           count = ((unsigned)byte + 1) * r->bpp;
908           if (count > (unsigned)bytes)
909 	    count = (unsigned)bytes;
910 
911           if (count < r->bpp)
912 	    break;
913 
914 	  bytes -= (ssize_t)count;
915 
916           if (!cups_raster_read(r, temp, r->bpp))
917 	  {
918 	    DEBUG_puts("1_cupsRasterReadPixels: Read error, returning 0.");
919 	    return (0);
920 	  }
921 
922 	  temp  += r->bpp;
923 	  count -= r->bpp;
924 
925 	  while (count > 0)
926 	  {
927 	    memcpy(temp, temp - r->bpp, r->bpp);
928 	    temp  += r->bpp;
929 	    count -= r->bpp;
930           }
931 	}
932       }
933 
934      /*
935       * Swap bytes as needed...
936       */
937 
938       if ((r->header.cupsBitsPerColor == 16 ||
939            r->header.cupsBitsPerPixel == 12 ||
940            r->header.cupsBitsPerPixel == 16) &&
941           r->swapped)
942       {
943         DEBUG_puts("1_cupsRasterReadPixels: Swapping bytes.");
944         cups_swap(ptr, (size_t)cupsBytesPerLine);
945       }
946 
947      /*
948       * Update pointers...
949       */
950 
951       if (remaining >= cupsBytesPerLine)
952       {
953 	bytes       = (ssize_t)cupsBytesPerLine;
954         r->pcurrent = r->pixels;
955 	r->count --;
956 	r->remaining --;
957       }
958       else
959       {
960 	bytes       = (ssize_t)remaining;
961         r->pcurrent = r->pixels + bytes;
962       }
963 
964      /*
965       * Copy data as needed...
966       */
967 
968       if (ptr != p)
969         memcpy(p, ptr, (size_t)bytes);
970     }
971     else
972     {
973      /*
974       * Copy fragment from buffer...
975       */
976 
977       if ((unsigned)(bytes = (int)(r->pend - r->pcurrent)) > remaining)
978         bytes = (ssize_t)remaining;
979 
980       memcpy(p, r->pcurrent, (size_t)bytes);
981       r->pcurrent += bytes;
982 
983       if (r->pcurrent >= r->pend)
984       {
985         r->pcurrent = r->pixels;
986 	r->count --;
987 	r->remaining --;
988       }
989     }
990 
991     remaining -= (unsigned)bytes;
992     p         += bytes;
993   }
994 
995   DEBUG_printf(("1_cupsRasterReadPixels: Returning %u", len));
996 
997   return (len);
998 }
999 
1000 
1001 /*
1002  * '_cupsRasterWriteHeader()' - Write a raster page header.
1003  */
1004 
1005 unsigned				/* O - 1 on success, 0 on failure */
_cupsRasterWriteHeader(cups_raster_t * r)1006 _cupsRasterWriteHeader(
1007     cups_raster_t *r)			/* I - Raster stream */
1008 {
1009   DEBUG_printf(("_cupsRasterWriteHeader(r=%p)", (void *)r));
1010 
1011   DEBUG_printf(("1_cupsRasterWriteHeader: cupsColorSpace=%s", _cupsRasterColorSpaceString(r->header.cupsColorSpace)));
1012   DEBUG_printf(("1_cupsRasterWriteHeader: cupsBitsPerColor=%u", r->header.cupsBitsPerColor));
1013   DEBUG_printf(("1_cupsRasterWriteHeader: cupsBitsPerPixel=%u", r->header.cupsBitsPerPixel));
1014   DEBUG_printf(("1_cupsRasterWriteHeader: cupsBytesPerLine=%u", r->header.cupsBytesPerLine));
1015   DEBUG_printf(("1_cupsRasterWriteHeader: cupsWidth=%u", r->header.cupsWidth));
1016   DEBUG_printf(("1_cupsRasterWriteHeader: cupsHeight=%u", r->header.cupsHeight));
1017 
1018  /*
1019   * Compute the number of raster lines in the page image...
1020   */
1021 
1022   if (!cups_raster_update(r))
1023   {
1024     DEBUG_puts("1_cupsRasterWriteHeader: Unable to update parameters, returning 0.");
1025     return (0);
1026   }
1027 
1028   if (r->mode == CUPS_RASTER_WRITE_APPLE)
1029   {
1030     r->rowheight = r->header.HWResolution[0] / r->header.HWResolution[1];
1031 
1032     if (r->header.HWResolution[0] != (r->rowheight * r->header.HWResolution[1]))
1033       return (0);
1034   }
1035   else
1036     r->rowheight = 1;
1037 
1038  /*
1039   * Write the raster header...
1040   */
1041 
1042   if (r->mode == CUPS_RASTER_WRITE_PWG)
1043   {
1044    /*
1045     * PWG raster data is always network byte order with much of the page header
1046     * zeroed.
1047     */
1048 
1049     cups_page_header2_t	fh;		/* File page header */
1050 
1051     memset(&fh, 0, sizeof(fh));
1052     strlcpy(fh.MediaClass, "PwgRaster", sizeof(fh.MediaClass));
1053     strlcpy(fh.MediaColor, r->header.MediaColor, sizeof(fh.MediaColor));
1054     strlcpy(fh.MediaType, r->header.MediaType, sizeof(fh.MediaType));
1055     strlcpy(fh.OutputType, r->header.OutputType, sizeof(fh.OutputType));
1056     strlcpy(fh.cupsRenderingIntent, r->header.cupsRenderingIntent,
1057             sizeof(fh.cupsRenderingIntent));
1058     strlcpy(fh.cupsPageSizeName, r->header.cupsPageSizeName,
1059             sizeof(fh.cupsPageSizeName));
1060 
1061     fh.CutMedia              = htonl(r->header.CutMedia);
1062     fh.Duplex                = htonl(r->header.Duplex);
1063     fh.HWResolution[0]       = htonl(r->header.HWResolution[0]);
1064     fh.HWResolution[1]       = htonl(r->header.HWResolution[1]);
1065     fh.ImagingBoundingBox[0] = htonl(r->header.ImagingBoundingBox[0]);
1066     fh.ImagingBoundingBox[1] = htonl(r->header.ImagingBoundingBox[1]);
1067     fh.ImagingBoundingBox[2] = htonl(r->header.ImagingBoundingBox[2]);
1068     fh.ImagingBoundingBox[3] = htonl(r->header.ImagingBoundingBox[3]);
1069     fh.InsertSheet           = htonl(r->header.InsertSheet);
1070     fh.Jog                   = htonl(r->header.Jog);
1071     fh.LeadingEdge           = htonl(r->header.LeadingEdge);
1072     fh.ManualFeed            = htonl(r->header.ManualFeed);
1073     fh.MediaPosition         = htonl(r->header.MediaPosition);
1074     fh.MediaWeight           = htonl(r->header.MediaWeight);
1075     fh.NumCopies             = htonl(r->header.NumCopies);
1076     fh.Orientation           = htonl(r->header.Orientation);
1077     fh.PageSize[0]           = htonl(r->header.PageSize[0]);
1078     fh.PageSize[1]           = htonl(r->header.PageSize[1]);
1079     fh.Tumble                = htonl(r->header.Tumble);
1080     fh.cupsWidth             = htonl(r->header.cupsWidth);
1081     fh.cupsHeight            = htonl(r->header.cupsHeight);
1082     fh.cupsBitsPerColor      = htonl(r->header.cupsBitsPerColor);
1083     fh.cupsBitsPerPixel      = htonl(r->header.cupsBitsPerPixel);
1084     fh.cupsBytesPerLine      = htonl(r->header.cupsBytesPerLine);
1085     fh.cupsColorOrder        = htonl(r->header.cupsColorOrder);
1086     fh.cupsColorSpace        = htonl(r->header.cupsColorSpace);
1087     fh.cupsNumColors         = htonl(r->header.cupsNumColors);
1088     fh.cupsInteger[0]        = htonl(r->header.cupsInteger[0]);
1089     fh.cupsInteger[1]        = htonl(r->header.cupsInteger[1]);
1090     fh.cupsInteger[2]        = htonl(r->header.cupsInteger[2]);
1091     fh.cupsInteger[3]        = htonl((unsigned)(r->header.cupsImagingBBox[0] * r->header.HWResolution[0] / 72.0));
1092     fh.cupsInteger[4]        = htonl((unsigned)(r->header.cupsImagingBBox[1] * r->header.HWResolution[1] / 72.0));
1093     fh.cupsInteger[5]        = htonl((unsigned)(r->header.cupsImagingBBox[2] * r->header.HWResolution[0] / 72.0));
1094     fh.cupsInteger[6]        = htonl((unsigned)(r->header.cupsImagingBBox[3] * r->header.HWResolution[1] / 72.0));
1095     fh.cupsInteger[7]        = htonl(0xffffff);
1096 
1097     return (cups_raster_io(r, (unsigned char *)&fh, sizeof(fh)) == sizeof(fh));
1098   }
1099   else if (r->mode == CUPS_RASTER_WRITE_APPLE)
1100   {
1101    /*
1102     * Raw raster data is always network byte order with most of the page header
1103     * zeroed.
1104     */
1105 
1106     int			i;		/* Looping var */
1107     unsigned char	appleheader[32];/* Raw page header */
1108     unsigned		height = r->header.cupsHeight * r->rowheight;
1109 					/* Computed page height */
1110 
1111     if (r->apple_page_count == 0xffffffffU)
1112     {
1113      /*
1114       * Write raw page count from raster page header...
1115       */
1116 
1117       r->apple_page_count = r->header.cupsInteger[0];
1118 
1119       appleheader[0] = 'A';
1120       appleheader[1] = 'S';
1121       appleheader[2] = 'T';
1122       appleheader[3] = 0;
1123       appleheader[4] = (unsigned char)(r->apple_page_count >> 24);
1124       appleheader[5] = (unsigned char)(r->apple_page_count >> 16);
1125       appleheader[6] = (unsigned char)(r->apple_page_count >> 8);
1126       appleheader[7] = (unsigned char)(r->apple_page_count);
1127 
1128       if (cups_raster_io(r, appleheader, 8) != 8)
1129         return (0);
1130     }
1131 
1132     memset(appleheader, 0, sizeof(appleheader));
1133 
1134     appleheader[0]  = (unsigned char)r->header.cupsBitsPerPixel;
1135     appleheader[1]  = r->header.cupsColorSpace == CUPS_CSPACE_SRGB ? 1 :
1136                         r->header.cupsColorSpace == CUPS_CSPACE_CIELab ? 2 :
1137                         r->header.cupsColorSpace == CUPS_CSPACE_ADOBERGB ? 3 :
1138                         r->header.cupsColorSpace == CUPS_CSPACE_W ? 4 :
1139                         r->header.cupsColorSpace == CUPS_CSPACE_RGB ? 5 :
1140                         r->header.cupsColorSpace == CUPS_CSPACE_CMYK ? 6 : 0;
1141     appleheader[2]  = r->header.Duplex ? (r->header.Tumble ? 2 : 3) : 1;
1142     appleheader[3]  = (unsigned char)(r->header.cupsInteger[CUPS_RASTER_PWG_PrintQuality]);
1143     appleheader[5]  = (unsigned char)(r->header.MediaPosition);
1144     appleheader[12] = (unsigned char)(r->header.cupsWidth >> 24);
1145     appleheader[13] = (unsigned char)(r->header.cupsWidth >> 16);
1146     appleheader[14] = (unsigned char)(r->header.cupsWidth >> 8);
1147     appleheader[15] = (unsigned char)(r->header.cupsWidth);
1148     appleheader[16] = (unsigned char)(height >> 24);
1149     appleheader[17] = (unsigned char)(height >> 16);
1150     appleheader[18] = (unsigned char)(height >> 8);
1151     appleheader[19] = (unsigned char)(height);
1152     appleheader[20] = (unsigned char)(r->header.HWResolution[0] >> 24);
1153     appleheader[21] = (unsigned char)(r->header.HWResolution[0] >> 16);
1154     appleheader[22] = (unsigned char)(r->header.HWResolution[0] >> 8);
1155     appleheader[23] = (unsigned char)(r->header.HWResolution[0]);
1156 
1157     for (i = 0; i < (int)(sizeof(apple_media_types) / sizeof(apple_media_types[0])); i ++)
1158     {
1159       if (!strcmp(r->header.MediaType, apple_media_types[i]))
1160       {
1161         appleheader[4] = (unsigned char)i;
1162         break;
1163       }
1164     }
1165 
1166     return (cups_raster_io(r, appleheader, sizeof(appleheader)) == sizeof(appleheader));
1167   }
1168   else
1169     return (cups_raster_io(r, (unsigned char *)&(r->header), sizeof(r->header))
1170 		== sizeof(r->header));
1171 }
1172 
1173 
1174 /*
1175  * '_cupsRasterWritePixels()' - Write raster pixels.
1176  *
1177  * For best performance, filters should write one or more whole lines.
1178  * The "cupsBytesPerLine" value from the page header can be used to allocate
1179  * the line buffer and as the number of bytes to write.
1180  */
1181 
1182 unsigned				/* O - Number of bytes written */
_cupsRasterWritePixels(cups_raster_t * r,unsigned char * p,unsigned len)1183 _cupsRasterWritePixels(
1184     cups_raster_t *r,			/* I - Raster stream */
1185     unsigned char *p,			/* I - Bytes to write */
1186     unsigned      len)			/* I - Number of bytes to write */
1187 {
1188   ssize_t	bytes;			/* Bytes read */
1189   unsigned	remaining;		/* Bytes remaining */
1190 
1191 
1192   DEBUG_printf(("_cupsRasterWritePixels(r=%p, p=%p, len=%u), remaining=%u", (void *)r, (void *)p, len, r->remaining));
1193 
1194   if (r == NULL || r->mode == CUPS_RASTER_READ || r->remaining == 0)
1195     return (0);
1196 
1197   if (!r->compressed)
1198   {
1199    /*
1200     * Without compression, just write the raster data raw unless the data needs
1201     * to be swapped...
1202     */
1203 
1204     r->remaining -= len / r->header.cupsBytesPerLine;
1205 
1206     if (r->swapped &&
1207         (r->header.cupsBitsPerColor == 16 ||
1208          r->header.cupsBitsPerPixel == 12 ||
1209          r->header.cupsBitsPerPixel == 16))
1210     {
1211       unsigned char	*bufptr;	/* Pointer into write buffer */
1212 
1213      /*
1214       * Allocate a write buffer as needed...
1215       */
1216 
1217       if ((size_t)len > r->bufsize)
1218       {
1219 	if (r->buffer)
1220 	  bufptr = realloc(r->buffer, len);
1221 	else
1222 	  bufptr = malloc(len);
1223 
1224 	if (!bufptr)
1225 	  return (0);
1226 
1227 	r->buffer  = bufptr;
1228 	r->bufsize = len;
1229       }
1230 
1231      /*
1232       * Byte swap the pixels and write them...
1233       */
1234 
1235       cups_swap_copy(r->buffer, p, len);
1236 
1237       bytes = cups_raster_io(r, r->buffer, len);
1238     }
1239     else
1240       bytes = cups_raster_io(r, p, len);
1241 
1242     if (bytes < (ssize_t)len)
1243       return (0);
1244     else
1245       return (len);
1246   }
1247 
1248  /*
1249   * Otherwise, compress each line...
1250   */
1251 
1252   for (remaining = len; remaining > 0; remaining -= (unsigned)bytes, p += bytes)
1253   {
1254    /*
1255     * Figure out the number of remaining bytes on the current line...
1256     */
1257 
1258     if ((bytes = (ssize_t)remaining) > (ssize_t)(r->pend - r->pcurrent))
1259       bytes = (ssize_t)(r->pend - r->pcurrent);
1260 
1261     if (r->count > 0)
1262     {
1263      /*
1264       * Check to see if this line is the same as the previous line...
1265       */
1266 
1267       if (memcmp(p, r->pcurrent, (size_t)bytes))
1268       {
1269         if (cups_raster_write(r, r->pixels) <= 0)
1270 	  return (0);
1271 
1272 	r->count = 0;
1273       }
1274       else
1275       {
1276        /*
1277         * Mark more bytes as the same...
1278 	*/
1279 
1280         r->pcurrent += bytes;
1281 
1282 	if (r->pcurrent >= r->pend)
1283 	{
1284 	 /*
1285           * Increase the repeat count...
1286 	  */
1287 
1288 	  r->count += r->rowheight;
1289 	  r->pcurrent = r->pixels;
1290 
1291 	 /*
1292           * Flush out this line if it is the last one...
1293 	  */
1294 
1295 	  r->remaining --;
1296 
1297 	  if (r->remaining == 0)
1298 	  {
1299 	    if (cups_raster_write(r, r->pixels) <= 0)
1300 	      return (0);
1301 	    else
1302 	      return (len);
1303 	  }
1304 	  else if (r->count > (256 - r->rowheight))
1305 	  {
1306 	    if (cups_raster_write(r, r->pixels) <= 0)
1307 	      return (0);
1308 
1309 	    r->count = 0;
1310 	  }
1311 	}
1312 
1313 	continue;
1314       }
1315     }
1316 
1317     if (r->count == 0)
1318     {
1319      /*
1320       * Copy the raster data to the buffer...
1321       */
1322 
1323       memcpy(r->pcurrent, p, (size_t)bytes);
1324 
1325       r->pcurrent += bytes;
1326 
1327       if (r->pcurrent >= r->pend)
1328       {
1329        /*
1330         * Increase the repeat count...
1331 	*/
1332 
1333 	r->count += r->rowheight;
1334 	r->pcurrent = r->pixels;
1335 
1336        /*
1337         * Flush out this line if it is the last one...
1338 	*/
1339 
1340 	r->remaining --;
1341 
1342 	if (r->remaining == 0)
1343 	{
1344 	  if (cups_raster_write(r, r->pixels) <= 0)
1345 	    return (0);
1346 	}
1347       }
1348     }
1349   }
1350 
1351   return (len);
1352 }
1353 
1354 
1355 /*
1356  * 'cups_raster_io()' - Read/write bytes from a context, handling interruptions.
1357  */
1358 
1359 static ssize_t				/* O - Bytes read/write or -1 */
cups_raster_io(cups_raster_t * r,unsigned char * buf,size_t bytes)1360 cups_raster_io(cups_raster_t *r,	/* I - Raster stream */
1361                unsigned char *buf,	/* I - Buffer for read/write */
1362                size_t        bytes)	/* I - Number of bytes to read/write */
1363 {
1364   ssize_t	count,			/* Number of bytes read/written */
1365 		total;			/* Total bytes read/written */
1366 
1367 
1368   DEBUG_printf(("5cups_raster_io(r=%p, buf=%p, bytes=" CUPS_LLFMT ")", (void *)r, (void *)buf, CUPS_LLCAST bytes));
1369 
1370   for (total = 0; total < (ssize_t)bytes; total += count, buf += count)
1371   {
1372     count = (*r->iocb)(r->ctx, buf, bytes - (size_t)total);
1373 
1374     DEBUG_printf(("6cups_raster_io: count=%d, total=%d", (int)count, (int)total));
1375     if (count == 0)
1376       break;
1377 //    {
1378 //      DEBUG_puts("6cups_raster_io: Returning 0.");
1379 //      return (0);
1380 //    }
1381     else if (count < 0)
1382     {
1383       DEBUG_puts("6cups_raster_io: Returning -1 on error.");
1384       return (-1);
1385     }
1386 
1387 #ifdef DEBUG
1388     r->iocount += (size_t)count;
1389 #endif /* DEBUG */
1390   }
1391 
1392   DEBUG_printf(("6cups_raster_io: iocount=" CUPS_LLFMT, CUPS_LLCAST r->iocount));
1393   DEBUG_printf(("6cups_raster_io: Returning " CUPS_LLFMT ".", CUPS_LLCAST total));
1394 
1395   return (total);
1396 }
1397 
1398 
1399 /*
1400  * 'cups_raster_read()' - Read through the raster buffer.
1401  */
1402 
1403 static ssize_t				/* O - Number of bytes read */
cups_raster_read(cups_raster_t * r,unsigned char * buf,size_t bytes)1404 cups_raster_read(cups_raster_t *r,	/* I - Raster stream */
1405                  unsigned char *buf,	/* I - Buffer */
1406                  size_t        bytes)	/* I - Number of bytes to read */
1407 {
1408   ssize_t	count,			/* Number of bytes read */
1409 		remaining,		/* Remaining bytes in buffer */
1410 		total;			/* Total bytes read */
1411 
1412 
1413   DEBUG_printf(("4cups_raster_read(r=%p, buf=%p, bytes=" CUPS_LLFMT "), offset=" CUPS_LLFMT, (void *)r, (void *)buf, CUPS_LLCAST bytes, CUPS_LLCAST (r->iostart + r->bufptr - r->buffer)));
1414 
1415   if (!r->compressed)
1416     return (cups_raster_io(r, buf, bytes));
1417 
1418  /*
1419   * Allocate a read buffer as needed...
1420   */
1421 
1422   count = (ssize_t)(2 * r->header.cupsBytesPerLine);
1423   if (count < 65536)
1424     count = 65536;
1425 
1426   if ((size_t)count > r->bufsize)
1427   {
1428     ssize_t offset = r->bufptr - r->buffer;
1429 					/* Offset to current start of buffer */
1430     ssize_t end = r->bufend - r->buffer;/* Offset to current end of buffer */
1431     unsigned char *rptr;		/* Pointer in read buffer */
1432 
1433     if (r->buffer)
1434       rptr = realloc(r->buffer, (size_t)count);
1435     else
1436       rptr = malloc((size_t)count);
1437 
1438     if (!rptr)
1439       return (0);
1440 
1441     r->buffer  = rptr;
1442     r->bufptr  = rptr + offset;
1443     r->bufend  = rptr + end;
1444     r->bufsize = (size_t)count;
1445   }
1446 
1447  /*
1448   * Loop until we have read everything...
1449   */
1450 
1451   for (total = 0, remaining = (int)(r->bufend - r->bufptr);
1452        total < (ssize_t)bytes;
1453        total += count, buf += count)
1454   {
1455     count = (ssize_t)bytes - total;
1456 
1457     DEBUG_printf(("5cups_raster_read: count=" CUPS_LLFMT ", remaining=" CUPS_LLFMT ", buf=%p, bufptr=%p, bufend=%p", CUPS_LLCAST count, CUPS_LLCAST remaining, (void *)buf, (void *)r->bufptr, (void *)r->bufend));
1458 
1459     if (remaining == 0)
1460     {
1461       if (count < 16)
1462       {
1463        /*
1464         * Read into the raster buffer and then copy...
1465 	*/
1466 
1467 #ifdef DEBUG
1468         r->iostart += (size_t)(r->bufend - r->buffer);
1469 #endif /* DEBUG */
1470 
1471         remaining = (*r->iocb)(r->ctx, r->buffer, r->bufsize);
1472 	if (remaining <= 0)
1473 	  return (0);
1474 
1475 	r->bufptr = r->buffer;
1476 	r->bufend = r->buffer + remaining;
1477 
1478 #ifdef DEBUG
1479         r->iocount += (size_t)remaining;
1480 #endif /* DEBUG */
1481       }
1482       else
1483       {
1484        /*
1485         * Read directly into "buf"...
1486 	*/
1487 
1488 	count = (*r->iocb)(r->ctx, buf, (size_t)count);
1489 
1490 	if (count <= 0)
1491 	  return (0);
1492 
1493 #ifdef DEBUG
1494 	r->iostart += (size_t)count;
1495         r->iocount += (size_t)count;
1496 #endif /* DEBUG */
1497 
1498 	continue;
1499       }
1500     }
1501 
1502    /*
1503     * Copy bytes from raster buffer to "buf"...
1504     */
1505 
1506     if (count > remaining)
1507       count = remaining;
1508 
1509     if (count == 1)
1510     {
1511      /*
1512       * Copy 1 byte...
1513       */
1514 
1515       *buf = *(r->bufptr)++;
1516       remaining --;
1517     }
1518     else if (count < 128)
1519     {
1520      /*
1521       * Copy up to 127 bytes without using memcpy(); this is
1522       * faster because it avoids an extra function call and is
1523       * often further optimized by the compiler...
1524       */
1525 
1526       unsigned char	*bufptr;	/* Temporary buffer pointer */
1527 
1528       remaining -= count;
1529 
1530       for (bufptr = r->bufptr; count > 0; count --, total ++)
1531 	*buf++ = *bufptr++;
1532 
1533       r->bufptr = bufptr;
1534     }
1535     else
1536     {
1537      /*
1538       * Use memcpy() for a large read...
1539       */
1540 
1541       memcpy(buf, r->bufptr, (size_t)count);
1542       r->bufptr += count;
1543       remaining -= count;
1544     }
1545   }
1546 
1547   DEBUG_printf(("5cups_raster_read: Returning %ld", (long)total));
1548 
1549   return (total);
1550 }
1551 
1552 
1553 /*
1554  * 'cups_raster_update()' - Update the raster header and row count for the
1555  *                          current page.
1556  */
1557 
1558 static int				/* O - 1 on success, 0 on failure */
cups_raster_update(cups_raster_t * r)1559 cups_raster_update(cups_raster_t *r)	/* I - Raster stream */
1560 {
1561   if (r->sync == CUPS_RASTER_SYNCv1 || r->sync == CUPS_RASTER_REVSYNCv1 ||
1562       r->header.cupsNumColors == 0)
1563   {
1564    /*
1565     * Set the "cupsNumColors" field according to the colorspace...
1566     */
1567 
1568     switch (r->header.cupsColorSpace)
1569     {
1570       case CUPS_CSPACE_W :
1571       case CUPS_CSPACE_K :
1572       case CUPS_CSPACE_WHITE :
1573       case CUPS_CSPACE_GOLD :
1574       case CUPS_CSPACE_SILVER :
1575       case CUPS_CSPACE_SW :
1576           r->header.cupsNumColors = 1;
1577 	  break;
1578 
1579       case CUPS_CSPACE_RGB :
1580       case CUPS_CSPACE_CMY :
1581       case CUPS_CSPACE_YMC :
1582       case CUPS_CSPACE_CIEXYZ :
1583       case CUPS_CSPACE_CIELab :
1584       case CUPS_CSPACE_SRGB :
1585       case CUPS_CSPACE_ADOBERGB :
1586       case CUPS_CSPACE_ICC1 :
1587       case CUPS_CSPACE_ICC2 :
1588       case CUPS_CSPACE_ICC3 :
1589       case CUPS_CSPACE_ICC4 :
1590       case CUPS_CSPACE_ICC5 :
1591       case CUPS_CSPACE_ICC6 :
1592       case CUPS_CSPACE_ICC7 :
1593       case CUPS_CSPACE_ICC8 :
1594       case CUPS_CSPACE_ICC9 :
1595       case CUPS_CSPACE_ICCA :
1596       case CUPS_CSPACE_ICCB :
1597       case CUPS_CSPACE_ICCC :
1598       case CUPS_CSPACE_ICCD :
1599       case CUPS_CSPACE_ICCE :
1600       case CUPS_CSPACE_ICCF :
1601           r->header.cupsNumColors = 3;
1602 	  break;
1603 
1604       case CUPS_CSPACE_RGBA :
1605       case CUPS_CSPACE_RGBW :
1606       case CUPS_CSPACE_CMYK :
1607       case CUPS_CSPACE_YMCK :
1608       case CUPS_CSPACE_KCMY :
1609       case CUPS_CSPACE_GMCK :
1610       case CUPS_CSPACE_GMCS :
1611           r->header.cupsNumColors = 4;
1612 	  break;
1613 
1614       case CUPS_CSPACE_KCMYcm :
1615           if (r->header.cupsBitsPerPixel < 8)
1616             r->header.cupsNumColors = 6;
1617 	  else
1618             r->header.cupsNumColors = 4;
1619 	  break;
1620 
1621       case CUPS_CSPACE_DEVICE1 :
1622       case CUPS_CSPACE_DEVICE2 :
1623       case CUPS_CSPACE_DEVICE3 :
1624       case CUPS_CSPACE_DEVICE4 :
1625       case CUPS_CSPACE_DEVICE5 :
1626       case CUPS_CSPACE_DEVICE6 :
1627       case CUPS_CSPACE_DEVICE7 :
1628       case CUPS_CSPACE_DEVICE8 :
1629       case CUPS_CSPACE_DEVICE9 :
1630       case CUPS_CSPACE_DEVICEA :
1631       case CUPS_CSPACE_DEVICEB :
1632       case CUPS_CSPACE_DEVICEC :
1633       case CUPS_CSPACE_DEVICED :
1634       case CUPS_CSPACE_DEVICEE :
1635       case CUPS_CSPACE_DEVICEF :
1636           r->header.cupsNumColors = r->header.cupsColorSpace -
1637 	                            CUPS_CSPACE_DEVICE1 + 1;
1638 	  break;
1639 
1640       default :
1641           /* Unknown color space */
1642           return (0);
1643     }
1644   }
1645 
1646  /*
1647   * Set the number of bytes per pixel/color...
1648   */
1649 
1650   if (r->header.cupsColorOrder == CUPS_ORDER_CHUNKED)
1651     r->bpp = (r->header.cupsBitsPerPixel + 7) / 8;
1652   else
1653     r->bpp = (r->header.cupsBitsPerColor + 7) / 8;
1654 
1655   if (r->bpp == 0)
1656     r->bpp = 1;
1657 
1658  /*
1659   * Set the number of remaining rows...
1660   */
1661 
1662   if (r->header.cupsColorOrder == CUPS_ORDER_PLANAR)
1663     r->remaining = r->header.cupsHeight * r->header.cupsNumColors;
1664   else
1665     r->remaining = r->header.cupsHeight;
1666 
1667  /*
1668   * Allocate the compression buffer...
1669   */
1670 
1671   if (r->compressed)
1672   {
1673     if (r->pixels != NULL)
1674       free(r->pixels);
1675 
1676     if ((r->pixels = calloc(r->header.cupsBytesPerLine, 1)) == NULL)
1677     {
1678       r->pcurrent = NULL;
1679       r->pend     = NULL;
1680       r->count    = 0;
1681 
1682       return (0);
1683     }
1684 
1685     r->pcurrent = r->pixels;
1686     r->pend     = r->pixels + r->header.cupsBytesPerLine;
1687     r->count    = 0;
1688   }
1689 
1690   return (1);
1691 }
1692 
1693 
1694 /*
1695  * 'cups_raster_write()' - Write a row of compressed raster data...
1696  */
1697 
1698 static ssize_t				/* O - Number of bytes written */
cups_raster_write(cups_raster_t * r,const unsigned char * pixels)1699 cups_raster_write(
1700     cups_raster_t       *r,		/* I - Raster stream */
1701     const unsigned char *pixels)	/* I - Pixel data to write */
1702 {
1703   const unsigned char	*start,		/* Start of sequence */
1704 			*ptr,		/* Current pointer in sequence */
1705 			*pend,		/* End of raster buffer */
1706 			*plast;		/* Pointer to last pixel */
1707   unsigned char		*wptr;		/* Pointer into write buffer */
1708   unsigned		bpp,		/* Bytes per pixel */
1709 			count;		/* Count */
1710   _cups_copyfunc_t	cf;		/* Copy function */
1711 
1712 
1713   DEBUG_printf(("3cups_raster_write(r=%p, pixels=%p)", (void *)r, (void *)pixels));
1714 
1715  /*
1716   * Determine whether we need to swap bytes...
1717   */
1718 
1719   if (r->swapped && (r->header.cupsBitsPerColor == 16 || r->header.cupsBitsPerPixel == 12 || r->header.cupsBitsPerPixel == 16))
1720   {
1721     DEBUG_puts("4cups_raster_write: Swapping bytes when writing.");
1722     cf = (_cups_copyfunc_t)cups_swap_copy;
1723   }
1724   else
1725     cf = (_cups_copyfunc_t)memcpy;
1726 
1727   /*
1728   * Allocate a write buffer as needed...
1729   */
1730 
1731   count = r->header.cupsBytesPerLine * 2;
1732   if (count < 65536)
1733     count = 65536;
1734 
1735   if ((size_t)count > r->bufsize)
1736   {
1737     if (r->buffer)
1738       wptr = realloc(r->buffer, count);
1739     else
1740       wptr = malloc(count);
1741 
1742     if (!wptr)
1743     {
1744       DEBUG_printf(("4cups_raster_write: Unable to allocate " CUPS_LLFMT " bytes for raster buffer: %s", CUPS_LLCAST count, strerror(errno)));
1745       return (-1);
1746     }
1747 
1748     r->buffer  = wptr;
1749     r->bufsize = count;
1750   }
1751 
1752  /*
1753   * Write the row repeat count...
1754   */
1755 
1756   bpp     = r->bpp;
1757   pend    = pixels + r->header.cupsBytesPerLine;
1758   plast   = pend - bpp;
1759   wptr    = r->buffer;
1760   *wptr++ = (unsigned char)(r->count - 1);
1761 
1762  /*
1763   * Write using a modified PackBits compression...
1764   */
1765 
1766   for (ptr = pixels; ptr < pend;)
1767   {
1768     start = ptr;
1769     ptr += bpp;
1770 
1771     if (ptr == pend)
1772     {
1773      /*
1774       * Encode a single pixel at the end...
1775       */
1776 
1777       *wptr++ = 0;
1778       (*cf)(wptr, start, bpp);
1779       wptr += bpp;
1780     }
1781     else if (!memcmp(start, ptr, bpp))
1782     {
1783      /*
1784       * Encode a sequence of repeating pixels...
1785       */
1786 
1787       for (count = 2; count < 128 && ptr < plast; count ++, ptr += bpp)
1788         if (memcmp(ptr, ptr + bpp, bpp))
1789 	  break;
1790 
1791       *wptr++ = (unsigned char)(count - 1);
1792       (*cf)(wptr, ptr, bpp);
1793       wptr += bpp;
1794       ptr  += bpp;
1795     }
1796     else
1797     {
1798      /*
1799       * Encode a sequence of non-repeating pixels...
1800       */
1801 
1802       for (count = 1; count < 128 && ptr < plast; count ++, ptr += bpp)
1803         if (!memcmp(ptr, ptr + bpp, bpp))
1804 	  break;
1805 
1806       if (ptr >= plast && count < 128)
1807       {
1808         count ++;
1809 	ptr += bpp;
1810       }
1811 
1812       *wptr++ = (unsigned char)(257 - count);
1813 
1814       count *= bpp;
1815       (*cf)(wptr, start, count);
1816       wptr += count;
1817     }
1818   }
1819 
1820   DEBUG_printf(("4cups_raster_write: Writing " CUPS_LLFMT " bytes.", CUPS_LLCAST (wptr - r->buffer)));
1821 
1822   return (cups_raster_io(r, r->buffer, (size_t)(wptr - r->buffer)));
1823 }
1824 
1825 
1826 /*
1827  * 'cups_swap()' - Swap bytes in raster data...
1828  */
1829 
1830 static void
cups_swap(unsigned char * buf,size_t bytes)1831 cups_swap(unsigned char *buf,		/* I - Buffer to swap */
1832           size_t        bytes)		/* I - Number of bytes to swap */
1833 {
1834   unsigned char	even, odd;		/* Temporary variables */
1835 
1836 
1837   bytes /= 2;
1838 
1839   while (bytes > 0)
1840   {
1841     even   = buf[0];
1842     odd    = buf[1];
1843     buf[0] = odd;
1844     buf[1] = even;
1845 
1846     buf += 2;
1847     bytes --;
1848   }
1849 }
1850 
1851 
1852 /*
1853  * 'cups_swap_copy()' - Copy and swap bytes in raster data...
1854  */
1855 
1856 static void
cups_swap_copy(unsigned char * dst,const unsigned char * src,size_t bytes)1857 cups_swap_copy(
1858     unsigned char       *dst,		/* I - Destination */
1859     const unsigned char *src,		/* I - Source */
1860     size_t              bytes)		/* I - Number of bytes to swap */
1861 {
1862   bytes /= 2;
1863 
1864   while (bytes > 0)
1865   {
1866     dst[0] = src[1];
1867     dst[1] = src[0];
1868 
1869     dst += 2;
1870     src += 2;
1871     bytes --;
1872   }
1873 }
1874