"Fossies" - the Fresh Open Source Software Archive

Member "cups-2.3rc1/cups/raster-stream.c" (21 May 2019, 47587 Bytes) of package /linux/misc/cups-2.3rc1-source.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "raster-stream.c" see the Fossies "Dox" file reference documentation.

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