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