Imported Upstream version 2.2.7
[platform/upstream/cups.git] / filter / raster.c
index bacf5ba..edb650d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Raster file routines for CUPS.
  *
- * Copyright 2007-2016 by Apple Inc.
+ * Copyright 2007-2018 by Apple Inc.
  * Copyright 1997-2006 by Easy Software Products.
  *
  * This file is part of the CUPS Imaging library.
@@ -50,11 +50,96 @@ struct _cups_raster_s                       /**** Raster stream data ****/
                        *bufend;        /* End of current (read) buffer */
   size_t               bufsize;        /* Buffer size */
 #ifdef DEBUG
-  size_t               iocount;        /* Number of bytes read/written */
+  size_t               iostart,        /* Start of read/write buffer */
+                       iocount;        /* Number of bytes read/written */
 #endif /* DEBUG */
   unsigned             apple_page_count;/* Apple raster page count */
 };
 
+typedef void (*_cups_copyfunc_t)(void *dst, const void *src, size_t bytes);
+
+
+/*
+ * Local globals...
+ */
+
+#ifdef DEBUG
+  static const char * const cups_color_spaces[] =
+  {                                    /* Color spaces */
+    "CUPS_CSPACE_W",
+    "CUPS_CSPACE_RGB",
+    "CUPS_CSPACE_RGBA",
+    "CUPS_CSPACE_K",
+    "CUPS_CSPACE_CMY",
+    "CUPS_CSPACE_YMC",
+    "CUPS_CSPACE_CMYK",
+    "CUPS_CSPACE_YMCK",
+    "CUPS_CSPACE_KCMY",
+    "CUPS_CSPACE_KCMYcm",
+    "CUPS_CSPACE_GMCK",
+    "CUPS_CSPACE_GMCS",
+    "CUPS_CSPACE_WHITE",
+    "CUPS_CSPACE_GOLD",
+    "CUPS_CSPACE_SILVER",
+    "CUPS_CSPACE_CIEXYZ",
+    "CUPS_CSPACE_CIELab",
+    "CUPS_CSPACE_RGBW",
+    "CUPS_CSPACE_SW",
+    "CUPS_CSPACE_SRGB",
+    "CUPS_CSPACE_ADOBERGB",
+    "21",
+    "22",
+    "23",
+    "24",
+    "25",
+    "26",
+    "27",
+    "28",
+    "29",
+    "30",
+    "31",
+    "CUPS_CSPACE_ICC1",
+    "CUPS_CSPACE_ICC2",
+    "CUPS_CSPACE_ICC3",
+    "CUPS_CSPACE_ICC4",
+    "CUPS_CSPACE_ICC5",
+    "CUPS_CSPACE_ICC6",
+    "CUPS_CSPACE_ICC7",
+    "CUPS_CSPACE_ICC8",
+    "CUPS_CSPACE_ICC9",
+    "CUPS_CSPACE_ICCA",
+    "CUPS_CSPACE_ICCB",
+    "CUPS_CSPACE_ICCC",
+    "CUPS_CSPACE_ICCD",
+    "CUPS_CSPACE_ICCE",
+    "CUPS_CSPACE_ICCF",
+    "47",
+    "CUPS_CSPACE_DEVICE1",
+    "CUPS_CSPACE_DEVICE2",
+    "CUPS_CSPACE_DEVICE3",
+    "CUPS_CSPACE_DEVICE4",
+    "CUPS_CSPACE_DEVICE5",
+    "CUPS_CSPACE_DEVICE6",
+    "CUPS_CSPACE_DEVICE7",
+    "CUPS_CSPACE_DEVICE8",
+    "CUPS_CSPACE_DEVICE9",
+    "CUPS_CSPACE_DEVICEA",
+    "CUPS_CSPACE_DEVICEB",
+    "CUPS_CSPACE_DEVICEC",
+    "CUPS_CSPACE_DEVICED",
+    "CUPS_CSPACE_DEVICEE",
+    "CUPS_CSPACE_DEVICEF"
+  };
+  static const char * const cups_modes[] =
+  {                                    /* Open modes */
+    "CUPS_RASTER_READ",
+    "CUPS_RASTER_WRITE",
+    "CUPS_RASTER_WRITE_COMPRESSED",
+    "CUPS_RASTER_WRITE_PWG",
+    "CUPS_RASTER_WRITE_APPLE"
+  };
+#endif /* DEBUG */
+
 
 /*
  * Local functions...
@@ -62,13 +147,12 @@ struct _cups_raster_s                      /**** Raster stream data ****/
 
 static ssize_t cups_raster_io(cups_raster_t *r, unsigned char *buf, size_t bytes);
 static unsigned        cups_raster_read_header(cups_raster_t *r);
-static ssize_t cups_raster_read(cups_raster_t *r, unsigned char *buf,
-                                size_t bytes);
+static ssize_t cups_raster_read(cups_raster_t *r, unsigned char *buf, size_t bytes);
 static int     cups_raster_update(cups_raster_t *r);
-static ssize_t cups_raster_write(cups_raster_t *r,
-                                 const unsigned char *pixels);
+static ssize_t cups_raster_write(cups_raster_t *r, const unsigned char *pixels);
 static ssize_t cups_read_fd(void *ctx, unsigned char *buf, size_t bytes);
 static void    cups_swap(unsigned char *buf, size_t bytes);
+static void    cups_swap_copy(unsigned char *dst, const unsigned char *src, size_t bytes);
 static ssize_t cups_write_fd(void *ctx, unsigned char *buf, size_t bytes);
 
 
@@ -356,6 +440,8 @@ cupsRasterOpen(int         fd,              /* I - File descriptor */
                                               @code CUPS_RASTER_WRITE_COMPRESSED@,
                                               or @code CUPS_RASTER_WRITE_PWG@ */
 {
+  DEBUG_printf(("cupsRasterOpen(fd=%d, mode=%s)", fd, cups_modes[mode]));
+
   if (mode == CUPS_RASTER_READ)
     return (cupsRasterOpenIO(cups_read_fd, (void *)((intptr_t)fd), mode));
   else
@@ -387,12 +473,15 @@ cupsRasterOpenIO(
   cups_raster_t        *r;                     /* New stream */
 
 
+  DEBUG_printf(("cupsRasterOpenIO(iocb=%p, ctx=%p, mode=%s)", (void *)iocb, ctx, cups_modes[mode]));
+
   _cupsRasterClearError();
 
   if ((r = calloc(sizeof(cups_raster_t), 1)) == NULL)
   {
     _cupsRasterAddError("Unable to allocate memory for raster stream: %s\n",
                         strerror(errno));
+    DEBUG_puts("1cupsRasterOpenIO: Returning NULL.");
     return (NULL);
   }
 
@@ -412,6 +501,7 @@ cupsRasterOpenIO(
       _cupsRasterAddError("Unable to read header from raster stream: %s\n",
                           strerror(errno));
       free(r);
+      DEBUG_puts("1cupsRasterOpenIO: Unable to read header, returning NULL.");
       return (NULL);
     }
 
@@ -426,6 +516,7 @@ cupsRasterOpenIO(
     {
       _cupsRasterAddError("Unknown raster format %08x!\n", r->sync);
       free(r);
+      DEBUG_puts("1cupsRasterOpenIO: Unknown format, returning NULL.");
       return (NULL);
     }
 
@@ -435,6 +526,8 @@ cupsRasterOpenIO(
         r->sync == CUPS_RASTER_REVSYNCapple)
       r->compressed = 1;
 
+    DEBUG_printf(("1cupsRasterOpenIO: sync=%08x", r->sync));
+
     if (r->sync == CUPS_RASTER_REVSYNC ||
         r->sync == CUPS_RASTER_REVSYNCv1 ||
         r->sync == CUPS_RASTER_REVSYNCv2 ||
@@ -452,12 +545,14 @@ cupsRasterOpenIO(
        _cupsRasterAddError("Unable to read header from raster stream: %s\n",
                            strerror(errno));
        free(r);
+       DEBUG_puts("1cupsRasterOpenIO: Unable to read header, returning NULL.");
        return (NULL);
       }
-
     }
 
-    DEBUG_printf(("1cupsRasterOpenIO: r->swapped=%d, r->sync=%08x\n", r->swapped, r->sync));
+#ifdef DEBUG
+    r->iostart = r->iocount;
+#endif /* DEBUG */
   }
   else
   {
@@ -496,10 +591,13 @@ cupsRasterOpenIO(
       _cupsRasterAddError("Unable to write raster stream header: %s\n",
                           strerror(errno));
       free(r);
+      DEBUG_puts("1cupsRasterOpenIO: Unable to write header, returning NULL.");
       return (NULL);
     }
   }
 
+  DEBUG_printf(("1cupsRasterOpenIO: compressed=%d, swapped=%d, returning %p", r->compressed, r->swapped, (void *)r));
+
   return (r);
 }
 
@@ -522,6 +620,8 @@ cupsRasterReadHeader(
     cups_raster_t      *r,             /* I - Raster stream */
     cups_page_header_t *h)             /* I - Pointer to header data */
 {
+  DEBUG_printf(("cupsRasterReadHeader(r=%p, h=%p)", (void *)r, (void *)h));
+
  /*
   * Get the raster header...
   */
@@ -529,6 +629,7 @@ cupsRasterReadHeader(
   if (!cups_raster_read_header(r))
   {
     memset(h, 0, sizeof(cups_page_header_t));
+    DEBUG_puts("1cupsRasterReadHeader: Unable to read page header, returning 0.");
     return (0);
   }
 
@@ -538,6 +639,14 @@ cupsRasterReadHeader(
 
   memcpy(h, &(r->header), sizeof(cups_page_header_t));
 
+  DEBUG_printf(("1cupsRasterReadHeader: cupsColorSpace=%s", cups_color_spaces[h->cupsColorSpace]));
+  DEBUG_printf(("1cupsRasterReadHeader: cupsBitsPerColor=%u", h->cupsBitsPerColor));
+  DEBUG_printf(("1cupsRasterReadHeader: cupsBitsPerPixel=%u", h->cupsBitsPerPixel));
+  DEBUG_printf(("1cupsRasterReadHeader: cupsBytesPerLine=%u", h->cupsBytesPerLine));
+  DEBUG_printf(("1cupsRasterReadHeader: cupsWidth=%u", h->cupsWidth));
+  DEBUG_printf(("1cupsRasterReadHeader: cupsHeight=%u", h->cupsHeight));
+
+  DEBUG_puts("1cupsRasterReadHeader: Returning 1.");
   return (1);
 }
 
@@ -563,6 +672,7 @@ cupsRasterReadHeader2(
   if (!cups_raster_read_header(r))
   {
     memset(h, 0, sizeof(cups_page_header2_t));
+    DEBUG_puts("1cupsRasterReadHeader2: Unable to read header, returning 0.");
     return (0);
   }
 
@@ -572,6 +682,14 @@ cupsRasterReadHeader2(
 
   memcpy(h, &(r->header), sizeof(cups_page_header2_t));
 
+  DEBUG_printf(("1cupsRasterReadHeader2: cupsColorSpace=%s", cups_color_spaces[h->cupsColorSpace]));
+  DEBUG_printf(("1cupsRasterReadHeader2: cupsBitsPerColor=%u", h->cupsBitsPerColor));
+  DEBUG_printf(("1cupsRasterReadHeader2: cupsBitsPerPixel=%u", h->cupsBitsPerPixel));
+  DEBUG_printf(("1cupsRasterReadHeader2: cupsBytesPerLine=%u", h->cupsBytesPerLine));
+  DEBUG_printf(("1cupsRasterReadHeader2: cupsWidth=%u", h->cupsWidth));
+  DEBUG_printf(("1cupsRasterReadHeader2: cupsHeight=%u", h->cupsHeight));
+
+  DEBUG_puts("1cupsRasterReadHeader2: Returning 1.");
   return (1);
 }
 
@@ -777,7 +895,10 @@ cupsRasterReadPixels(cups_raster_t *r,     /* I - Raster stream */
            r->header.cupsBitsPerPixel == 12 ||
            r->header.cupsBitsPerPixel == 16) &&
           r->swapped)
-        cups_swap(ptr, (size_t)bytes);
+      {
+        DEBUG_puts("1cupsRasterReadPixels: Swapping bytes.");
+        cups_swap(ptr, (size_t)cupsBytesPerLine);
+      }
 
      /*
       * Update pointers...
@@ -847,8 +968,20 @@ cupsRasterWriteHeader(
     cups_raster_t      *r,             /* I - Raster stream */
     cups_page_header_t *h)             /* I - Raster page header */
 {
+  DEBUG_printf(("cupsRasterWriteHeader(r=%p, h=%p)", (void *)r, (void *)h));
+
   if (r == NULL || r->mode == CUPS_RASTER_READ)
+  {
+    DEBUG_puts("1cupsRasterWriteHeader: Returning 0.");
     return (0);
+  }
+
+  DEBUG_printf(("1cupsRasterWriteHeader: cupsColorSpace=%s", cups_color_spaces[h->cupsColorSpace]));
+  DEBUG_printf(("1cupsRasterWriteHeader: cupsBitsPerColor=%u", h->cupsBitsPerColor));
+  DEBUG_printf(("1cupsRasterWriteHeader: cupsBitsPerPixel=%u", h->cupsBitsPerPixel));
+  DEBUG_printf(("1cupsRasterWriteHeader: cupsBytesPerLine=%u", h->cupsBytesPerLine));
+  DEBUG_printf(("1cupsRasterWriteHeader: cupsWidth=%u", h->cupsWidth));
+  DEBUG_printf(("1cupsRasterWriteHeader: cupsHeight=%u", h->cupsHeight));
 
  /*
   * Make a copy of the header, and compute the number of raster
@@ -859,7 +992,20 @@ cupsRasterWriteHeader(
   memcpy(&(r->header), h, sizeof(cups_page_header_t));
 
   if (!cups_raster_update(r))
+  {
+    DEBUG_puts("1cupsRasterWriteHeader: Unable to update parameters, returning 0.");
     return (0);
+  }
+
+  if (r->mode == CUPS_RASTER_WRITE_APPLE)
+  {
+    r->rowheight = h->HWResolution[0] / h->HWResolution[1];
+
+    if (h->HWResolution[0] != (r->rowheight * h->HWResolution[1]))
+      return (0);
+  }
+  else
+    r->rowheight = 1;
 
  /*
   * Write the raster header...
@@ -1019,8 +1165,20 @@ cupsRasterWriteHeader2(
     cups_raster_t       *r,            /* I - Raster stream */
     cups_page_header2_t *h)            /* I - Raster page header */
 {
+  DEBUG_printf(("cupsRasterWriteHeader(r=%p, h=%p)", (void *)r, (void *)h));
+
   if (r == NULL || r->mode == CUPS_RASTER_READ)
+  {
+    DEBUG_puts("1cupsRasterWriteHeader2: Returning 0.");
     return (0);
+  }
+
+  DEBUG_printf(("1cupsRasterWriteHeader2: cupsColorSpace=%s", cups_color_spaces[h->cupsColorSpace]));
+  DEBUG_printf(("1cupsRasterWriteHeader2: cupsBitsPerColor=%u", h->cupsBitsPerColor));
+  DEBUG_printf(("1cupsRasterWriteHeader2: cupsBitsPerPixel=%u", h->cupsBitsPerPixel));
+  DEBUG_printf(("1cupsRasterWriteHeader2: cupsBytesPerLine=%u", h->cupsBytesPerLine));
+  DEBUG_printf(("1cupsRasterWriteHeader2: cupsWidth=%u", h->cupsWidth));
+  DEBUG_printf(("1cupsRasterWriteHeader2: cupsHeight=%u", h->cupsHeight));
 
  /*
   * Make a copy of the header, and compute the number of raster
@@ -1030,7 +1188,10 @@ cupsRasterWriteHeader2(
   memcpy(&(r->header), h, sizeof(cups_page_header2_t));
 
   if (!cups_raster_update(r))
+  {
+    DEBUG_puts("1cupsRasterWriteHeader: Unable to update parameters, returning 0.");
     return (0);
+  }
 
   if (r->mode == CUPS_RASTER_WRITE_APPLE)
   {
@@ -1202,7 +1363,6 @@ cupsRasterWritePixels(cups_raster_t *r,   /* I - Raster stream */
          r->header.cupsBitsPerPixel == 16))
     {
       unsigned char    *bufptr;        /* Pointer into write buffer */
-      unsigned         count;          /* Remaining count */
 
      /*
       * Allocate a write buffer as needed...
@@ -1223,21 +1383,10 @@ cupsRasterWritePixels(cups_raster_t *r, /* I - Raster stream */
       }
 
      /*
-      * Byte swap the pixels...
+      * Byte swap the pixels and write them...
       */
 
-      for (bufptr = r->buffer, count = len; count > 1; count -= 2, bufptr += 2)
-      {
-        bufptr[1] = *p++;
-        bufptr[0] = *p++;
-      }
-
-      if (count)                       /* This should never happen... */
-        *bufptr = *p;
-
-     /*
-      * Write the byte-swapped buffer...
-      */
+      cups_swap_copy(r->buffer, p, len);
 
       bytes = cups_raster_io(r, r->buffer, len);
     }
@@ -1368,7 +1517,7 @@ cups_raster_read_header(
   size_t       len;                    /* Length for read/swap */
 
 
-  DEBUG_printf(("3cups_raster_read_header(r=%p), r->mode=%d", (void *)r, r ? r->mode : 0));
+  DEBUG_printf(("3cups_raster_read_header(r=%p), r->mode=%s", (void *)r, r ? cups_modes[r->mode] : ""));
 
   if (r == NULL || r->mode != CUPS_RASTER_READ)
     return (0);
@@ -1523,10 +1672,7 @@ cups_raster_io(cups_raster_t *r, /* I - Raster stream */
 
     DEBUG_printf(("6cups_raster_io: count=%d, total=%d", (int)count, (int)total));
     if (count == 0)
-    {
-      DEBUG_puts("6cups_raster_io: Returning 0.");
-      return (0);
-    }
+      break;
     else if (count < 0)
     {
       DEBUG_puts("6cups_raster_io: Returning -1 on error.");
@@ -1538,6 +1684,7 @@ cups_raster_io(cups_raster_t *r,  /* I - Raster stream */
 #endif /* DEBUG */
   }
 
+  DEBUG_printf(("6cups_raster_io: iocount=" CUPS_LLFMT, CUPS_LLCAST r->iocount));
   DEBUG_printf(("6cups_raster_io: Returning " CUPS_LLFMT ".", CUPS_LLCAST total));
 
   return (total);
@@ -1558,7 +1705,7 @@ cups_raster_read(cups_raster_t *r,        /* I - Raster stream */
                total;                  /* Total bytes read */
 
 
-  DEBUG_printf(("5cups_raster_read(r=%p, buf=%p, bytes=" CUPS_LLFMT ")", (void *)r, (void *)buf, CUPS_LLCAST bytes));
+  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)));
 
   if (!r->compressed)
     return (cups_raster_io(r, buf, bytes));
@@ -1602,7 +1749,7 @@ cups_raster_read(cups_raster_t *r,        /* I - Raster stream */
   {
     count = (ssize_t)bytes - total;
 
-    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));
+    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));
 
     if (remaining == 0)
     {
@@ -1612,6 +1759,10 @@ cups_raster_read(cups_raster_t *r,       /* I - Raster stream */
         * Read into the raster buffer and then copy...
        */
 
+#ifdef DEBUG
+        r->iostart += (size_t)(r->bufend - r->buffer);
+#endif /* DEBUG */
+
         remaining = (*r->iocb)(r->ctx, r->buffer, r->bufsize);
        if (remaining <= 0)
          return (0);
@@ -1635,6 +1786,7 @@ cups_raster_read(cups_raster_t *r,        /* I - Raster stream */
          return (0);
 
 #ifdef DEBUG
+       r->iostart += (size_t)count;
         r->iocount += (size_t)count;
 #endif /* DEBUG */
 
@@ -1687,7 +1839,7 @@ cups_raster_read(cups_raster_t *r,        /* I - Raster stream */
     }
   }
 
-  DEBUG_printf(("6cups_raster_read: Returning %ld", (long)total));
+  DEBUG_printf(("5cups_raster_read: Returning %ld", (long)total));
 
   return (total);
 }
@@ -1850,11 +2002,24 @@ cups_raster_write(
   unsigned char                *wptr;          /* Pointer into write buffer */
   unsigned             bpp,            /* Bytes per pixel */
                        count;          /* Count */
+  _cups_copyfunc_t     cf;             /* Copy function */
 
 
   DEBUG_printf(("3cups_raster_write(r=%p, pixels=%p)", (void *)r, (void *)pixels));
 
  /*
+  * Determine whether we need to swap bytes...
+  */
+
+  if (r->swapped && (r->header.cupsBitsPerColor == 16 || r->header.cupsBitsPerPixel == 12 || r->header.cupsBitsPerPixel == 16))
+  {
+    DEBUG_puts("4cups_raster_write: Swapping bytes when writing.");
+    cf = (_cups_copyfunc_t)cups_swap_copy;
+  }
+  else
+    cf = (_cups_copyfunc_t)memcpy;
+
+  /*
   * Allocate a write buffer as needed...
   */
 
@@ -1905,8 +2070,8 @@ cups_raster_write(
       */
 
       *wptr++ = 0;
-      for (count = bpp; count > 0; count --)
-        *wptr++ = *start++;
+      (*cf)(wptr, start, bpp);
+      wptr += bpp;
     }
     else if (!memcmp(start, ptr, bpp))
     {
@@ -1919,8 +2084,9 @@ cups_raster_write(
          break;
 
       *wptr++ = (unsigned char)(count - 1);
-      for (count = bpp; count > 0; count --)
-        *wptr++ = *ptr++;
+      (*cf)(wptr, ptr, bpp);
+      wptr += bpp;
+      ptr  += bpp;
     }
     else
     {
@@ -1941,7 +2107,7 @@ cups_raster_write(
       *wptr++ = (unsigned char)(257 - count);
 
       count *= bpp;
-      memcpy(wptr, start, count);
+      (*cf)(wptr, start, count);
       wptr += count;
     }
   }
@@ -1973,11 +2139,11 @@ cups_read_fd(void          *ctx,        /* I - File descriptor as pointer */
 #endif /* WIN32 */
     if (errno != EINTR && errno != EAGAIN)
     {
-      DEBUG_printf(("4cups_read_fd: %s", strerror(errno)));
+      DEBUG_printf(("8cups_read_fd: %s", strerror(errno)));
       return (-1);
     }
 
-  DEBUG_printf(("4cups_read_fd: Returning %d bytes.", (int)count));
+  DEBUG_printf(("8cups_read_fd: Returning %d bytes.", (int)count));
 
   return (count);
 }
@@ -2010,6 +2176,30 @@ cups_swap(unsigned char *buf,            /* I - Buffer to swap */
 
 
 /*
+ * 'cups_swap_copy()' - Copy and swap bytes in raster data...
+ */
+
+static void
+cups_swap_copy(
+    unsigned char       *dst,          /* I - Destination */
+    const unsigned char *src,          /* I - Source */
+    size_t              bytes)         /* I - Number of bytes to swap */
+{
+  bytes /= 2;
+
+  while (bytes > 0)
+  {
+    dst[0] = src[1];
+    dst[1] = src[0];
+
+    dst += 2;
+    src += 2;
+    bytes --;
+  }
+}
+
+
+/*
  * 'cups_write_fd()' - Write bytes to a file.
  */
 
@@ -2030,7 +2220,7 @@ cups_write_fd(void          *ctx, /* I - File descriptor pointer */
 #endif /* WIN32 */
     if (errno != EINTR && errno != EAGAIN)
     {
-      DEBUG_printf(("4cups_write_fd: %s", strerror(errno)));
+      DEBUG_printf(("8cups_write_fd: %s", strerror(errno)));
       return (-1);
     }