Home | History | Annotate | Download | only in filter
      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
     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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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
   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 */
   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