]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Add beta support for AppleRaster (per IANA Printer MIB)
authorMichael R Sweet <michaelrsweet@gmail.com>
Thu, 27 Oct 2016 19:41:51 +0000 (15:41 -0400)
committerMichael R Sweet <michaelrsweet@gmail.com>
Thu, 27 Oct 2016 19:41:51 +0000 (15:41 -0400)
cups/raster.h
filter/raster.c
filter/testraster.c

index 43a9d1581ba7915da93e94ec62bd5f191125c612..ecb94b9e6ef33c6ec420de6b5af53585c3515b92 100644 (file)
@@ -52,6 +52,9 @@ extern "C" {
 #  define CUPS_RASTER_SYNCv2   0x52615332      /* RaS2 */
 #  define CUPS_RASTER_REVSYNCv2        0x32536152      /* 2SaR */
 
+#  define CUPS_RASTER_SYNCapple        0x554E4952      /* UNIR */
+#  define CUPS_RASTER_REVSYNCapple 0x52494E55  /* RINU */
+
 #  define CUPS_RASTER_SYNC_PWG CUPS_RASTER_SYNCv2
 
 /*
@@ -75,6 +78,13 @@ extern "C" {
 
 #  define CUPS_RASTER_HAVE_PWGRASTER 1
 
+/*
+ * The following definition can be used to determine if Apple Raster is
+ * supported (beta).
+ */
+
+#  define CUPS_RASTER_HAVE_APPLERASTER 1
+
 /*
  * The following PWG 5102.4 definitions specify indices into the
  * cupsInteger[] array in the raster header.
@@ -202,7 +212,8 @@ enum cups_mode_e                    /**** cupsRasterOpen modes ****/
   CUPS_RASTER_READ = 0,                        /* Open stream for reading */
   CUPS_RASTER_WRITE = 1,               /* Open stream for writing */
   CUPS_RASTER_WRITE_COMPRESSED = 2,    /* Open stream for compressed writing @since CUPS 1.3/macOS 10.5@ */
-  CUPS_RASTER_WRITE_PWG = 3            /* Open stream for compressed writing in PWG mode @since CUPS 1.5/macOS 10.7@ */
+  CUPS_RASTER_WRITE_PWG = 3,           /* Open stream for compressed writing in PWG Raster mode @since CUPS 1.5/macOS 10.7@ */
+  CUPS_RASTER_WRITE_APPLE = 4          /* Open stream for compressed writing in AppleRaster mode (beta) @private@ */
 };
 
 typedef enum cups_mode_e cups_mode_t;  /**** cupsRasterOpen modes ****/
index dee8eeca07853439b396887ab4c5c893f75739a8..002cfe3a421277e650bff0eb00a54b209e93e612 100644 (file)
@@ -51,6 +51,7 @@ struct _cups_raster_s                 /**** Raster stream data ****/
 #ifdef DEBUG
   size_t               iocount;        /* Number of bytes read/written */
 #endif /* DEBUG */
+  unsigned             apple_page_count;/* Apple raster page count */
 };
 
 
@@ -418,7 +419,9 @@ cupsRasterOpenIO(
         r->sync != CUPS_RASTER_SYNCv1 &&
         r->sync != CUPS_RASTER_REVSYNCv1 &&
         r->sync != CUPS_RASTER_SYNCv2 &&
-        r->sync != CUPS_RASTER_REVSYNCv2)
+        r->sync != CUPS_RASTER_REVSYNCv2 &&
+        r->sync != CUPS_RASTER_SYNCapple &&
+        r->sync != CUPS_RASTER_REVSYNCapple)
     {
       _cupsRasterAddError("Unknown raster format %08x!\n", r->sync);
       free(r);
@@ -426,14 +429,33 @@ cupsRasterOpenIO(
     }
 
     if (r->sync == CUPS_RASTER_SYNCv2 ||
-        r->sync == CUPS_RASTER_REVSYNCv2)
+        r->sync == CUPS_RASTER_REVSYNCv2 ||
+        r->sync == CUPS_RASTER_SYNCapple ||
+        r->sync == CUPS_RASTER_REVSYNCapple)
       r->compressed = 1;
 
     if (r->sync == CUPS_RASTER_REVSYNC ||
         r->sync == CUPS_RASTER_REVSYNCv1 ||
-        r->sync == CUPS_RASTER_REVSYNCv2)
+        r->sync == CUPS_RASTER_REVSYNCv2 ||
+        r->sync == CUPS_RASTER_REVSYNCapple)
       r->swapped = 1;
 
+    if (r->sync == CUPS_RASTER_SYNCapple ||
+        r->sync == CUPS_RASTER_REVSYNCapple)
+    {
+      unsigned char    header[8];      /* File header */
+
+      if (cups_raster_io(r, (unsigned char *)header, sizeof(header)) !=
+             sizeof(header))
+      {
+       _cupsRasterAddError("Unable to read header from raster stream: %s\n",
+                           strerror(errno));
+       free(r);
+       return (NULL);
+      }
+
+    }
+
     DEBUG_printf(("1cupsRasterOpenIO: r->swapped=%d, r->sync=%08x\n", r->swapped, r->sync));
   }
   else
@@ -459,6 +481,13 @@ cupsRasterOpenIO(
           r->sync       = htonl(CUPS_RASTER_SYNC_PWG);
           r->swapped    = r->sync != CUPS_RASTER_SYNC_PWG;
          break;
+
+      case CUPS_RASTER_WRITE_APPLE :
+          r->compressed     = 1;
+          r->sync           = htonl(CUPS_RASTER_SYNCapple);
+          r->swapped        = r->sync != CUPS_RASTER_SYNCapple;
+          r->apple_page_count = 0xffffffffU;
+         break;
     }
 
     if (cups_raster_io(r, (unsigned char *)&(r->sync), sizeof(r->sync)) < (ssize_t)sizeof(r->sync))
@@ -662,7 +691,31 @@ cupsRasterReadPixels(cups_raster_t *r,     /* I - Raster stream */
          return (0);
        }
 
-       if (byte & 128)
+        if (byte == 128)
+        {
+         /*
+          * Clear to end of line...
+          */
+
+          switch (r->header.cupsColorSpace)
+          {
+            case CUPS_CSPACE_W :
+            case CUPS_CSPACE_RGB :
+            case CUPS_CSPACE_SW :
+            case CUPS_CSPACE_SRGB :
+            case CUPS_CSPACE_RGBW :
+            case CUPS_CSPACE_ADOBERGB :
+                memset(temp, 0xff, bytes);
+                break;
+            default :
+                memset(temp, 0x00, bytes);
+                break;
+          }
+
+          temp += bytes;
+          bytes = 0;
+        }
+       else if (byte & 128)
        {
         /*
          * Copy N literal pixels...
@@ -891,6 +944,60 @@ cupsRasterWriteHeader(
 
     return (cups_raster_io(r, (unsigned char *)&fh, sizeof(fh)) == sizeof(fh));
   }
+  else if (r->mode == CUPS_RASTER_WRITE_APPLE)
+  {
+   /*
+    * Raw raster data is always network byte order with most of the page header
+    * zeroed.
+    */
+
+    unsigned char appleheader[64];     /* Raw page header */
+
+    if (r->apple_page_count == 0xffffffffU)
+    {
+     /*
+      * Write raw page count from raster page header...
+      */
+
+      r->apple_page_count = r->header.cupsInteger[0];
+
+      appleheader[0] = 'A';
+      appleheader[1] = 'S';
+      appleheader[2] = 'T';
+      appleheader[3] = 0;
+      appleheader[4] = (unsigned char)(r->apple_page_count >> 24);
+      appleheader[5] = (unsigned char)(r->apple_page_count >> 16);
+      appleheader[6] = (unsigned char)(r->apple_page_count >> 8);
+      appleheader[7] = (unsigned char)(r->apple_page_count);
+
+      if (cups_raster_io(r, appleheader, 8) != 8)
+        return (0);
+    }
+
+    memset(appleheader, 0, sizeof(appleheader));
+
+    appleheader[0]  = (unsigned char)r->header.cupsBitsPerPixel;
+    appleheader[1]  = r->header.cupsColorSpace == CUPS_CSPACE_SRGB ? 1 :
+                        r->header.cupsColorSpace == CUPS_CSPACE_RGBW ? 2 :
+                        r->header.cupsColorSpace == CUPS_CSPACE_ADOBERGB ? 3 :
+                        r->header.cupsColorSpace == CUPS_CSPACE_W ? 4 :
+                        r->header.cupsColorSpace == CUPS_CSPACE_RGB ? 5 :
+                        r->header.cupsColorSpace == CUPS_CSPACE_CMYK ? 6 : 0;
+    appleheader[12] = (unsigned char)(r->header.cupsWidth >> 24);
+    appleheader[13] = (unsigned char)(r->header.cupsWidth >> 16);
+    appleheader[14] = (unsigned char)(r->header.cupsWidth >> 8);
+    appleheader[15] = (unsigned char)(r->header.cupsWidth);
+    appleheader[16] = (unsigned char)(r->header.cupsHeight >> 24);
+    appleheader[17] = (unsigned char)(r->header.cupsHeight >> 16);
+    appleheader[18] = (unsigned char)(r->header.cupsHeight >> 8);
+    appleheader[19] = (unsigned char)(r->header.cupsHeight);
+    appleheader[20] = (unsigned char)(r->header.HWResolution[0] >> 24);
+    appleheader[21] = (unsigned char)(r->header.HWResolution[0] >> 16);
+    appleheader[22] = (unsigned char)(r->header.HWResolution[0] >> 8);
+    appleheader[23] = (unsigned char)(r->header.HWResolution[0]);
+
+    return (cups_raster_io(r, appleheader, sizeof(appleheader)) == sizeof(appleheader));
+  }
   else
     return (cups_raster_io(r, (unsigned char *)&(r->header), sizeof(r->header))
                == sizeof(r->header));
@@ -985,6 +1092,60 @@ cupsRasterWriteHeader2(
 
     return (cups_raster_io(r, (unsigned char *)&fh, sizeof(fh)) == sizeof(fh));
   }
+  else if (r->mode == CUPS_RASTER_WRITE_APPLE)
+  {
+   /*
+    * Raw raster data is always network byte order with most of the page header
+    * zeroed.
+    */
+
+    unsigned char appleheader[64];     /* Raw page header */
+
+    if (r->apple_page_count == 0xffffffffU)
+    {
+     /*
+      * Write raw page count from raster page header...
+      */
+
+      r->apple_page_count = r->header.cupsInteger[0];
+
+      appleheader[0] = 'A';
+      appleheader[1] = 'S';
+      appleheader[2] = 'T';
+      appleheader[3] = 0;
+      appleheader[4] = (unsigned char)(r->apple_page_count >> 24);
+      appleheader[5] = (unsigned char)(r->apple_page_count >> 16);
+      appleheader[6] = (unsigned char)(r->apple_page_count >> 8);
+      appleheader[7] = (unsigned char)(r->apple_page_count);
+
+      if (cups_raster_io(r, appleheader, 8) != 8)
+        return (0);
+    }
+
+    memset(appleheader, 0, sizeof(appleheader));
+
+    appleheader[0]  = (unsigned char)r->header.cupsBitsPerPixel;
+    appleheader[1]  = r->header.cupsColorSpace == CUPS_CSPACE_SRGB ? 1 :
+                        r->header.cupsColorSpace == CUPS_CSPACE_RGBW ? 2 :
+                        r->header.cupsColorSpace == CUPS_CSPACE_ADOBERGB ? 3 :
+                        r->header.cupsColorSpace == CUPS_CSPACE_W ? 4 :
+                        r->header.cupsColorSpace == CUPS_CSPACE_RGB ? 5 :
+                        r->header.cupsColorSpace == CUPS_CSPACE_CMYK ? 6 : 0;
+    appleheader[12] = (unsigned char)(r->header.cupsWidth >> 24);
+    appleheader[13] = (unsigned char)(r->header.cupsWidth >> 16);
+    appleheader[14] = (unsigned char)(r->header.cupsWidth >> 8);
+    appleheader[15] = (unsigned char)(r->header.cupsWidth);
+    appleheader[16] = (unsigned char)(r->header.cupsHeight >> 24);
+    appleheader[17] = (unsigned char)(r->header.cupsHeight >> 16);
+    appleheader[18] = (unsigned char)(r->header.cupsHeight >> 8);
+    appleheader[19] = (unsigned char)(r->header.cupsHeight);
+    appleheader[20] = (unsigned char)(r->header.HWResolution[0] >> 24);
+    appleheader[21] = (unsigned char)(r->header.HWResolution[0] >> 16);
+    appleheader[22] = (unsigned char)(r->header.HWResolution[0] >> 8);
+    appleheader[23] = (unsigned char)(r->header.HWResolution[0]);
+
+    return (cups_raster_io(r, appleheader, sizeof(appleheader)) == sizeof(appleheader));
+  }
   else
     return (cups_raster_io(r, (unsigned char *)&(r->header), sizeof(r->header))
                == sizeof(r->header));
@@ -1201,53 +1362,118 @@ cups_raster_read_header(
 
   DEBUG_printf(("4cups_raster_read_header: r->iocount=" CUPS_LLFMT, CUPS_LLCAST r->iocount));
 
+  memset(&(r->header), 0, sizeof(r->header));
+
  /*
-  * Get the length of the raster header...
+  * Read the header...
   */
 
-  if (r->sync == CUPS_RASTER_SYNCv1 || r->sync == CUPS_RASTER_REVSYNCv1)
-    len = sizeof(cups_page_header_t);
-  else
-    len = sizeof(cups_page_header2_t);
+  switch (r->sync)
+  {
+    default :
+       /*
+       * Get the length of the raster header...
+       */
 
-  DEBUG_printf(("4cups_raster_read_header: len=%d", (int)len));
+       if (r->sync == CUPS_RASTER_SYNCv1 || r->sync == CUPS_RASTER_REVSYNCv1)
+         len = sizeof(cups_page_header_t);
+       else
+         len = sizeof(cups_page_header2_t);
 
- /*
-  * Read the header...
-  */
+       DEBUG_printf(("4cups_raster_read_header: len=%d", (int)len));
 
-  memset(&(r->header), 0, sizeof(r->header));
+       /*
+        * Read it...
+        */
 
-  if (cups_raster_read(r, (unsigned char *)&(r->header), len) < (ssize_t)len)
-  {
-    DEBUG_printf(("4cups_raster_read_header: EOF, r->iocount=" CUPS_LLFMT, CUPS_LLCAST r->iocount));
-    return (0);
-  }
+       if (cups_raster_read(r, (unsigned char *)&(r->header), len) < (ssize_t)len)
+       {
+         DEBUG_printf(("4cups_raster_read_header: EOF, r->iocount=" CUPS_LLFMT, CUPS_LLCAST r->iocount));
+         return (0);
+       }
 
- /*
-  * Swap bytes as needed...
-  */
      /*
+       * Swap bytes as needed...
+       */
 
-  if (r->swapped)
-  {
-    unsigned   *s,                     /* Current word */
-               temp;                   /* Temporary copy */
+       if (r->swapped)
+       {
+         unsigned      *s,             /* Current word */
+                       temp;           /* Temporary copy */
 
 
-    DEBUG_puts("4cups_raster_read_header: Swapping header bytes.");
+         DEBUG_puts("4cups_raster_read_header: Swapping header bytes.");
 
-    for (len = 81, s = &(r->header.AdvanceDistance);
-        len > 0;
-        len --, s ++)
-    {
-      temp = *s;
-      *s   = ((temp & 0xff) << 24) |
-             ((temp & 0xff00) << 8) |
-             ((temp & 0xff0000) >> 8) |
-             ((temp & 0xff000000) >> 24);
+         for (len = 81, s = &(r->header.AdvanceDistance);
+              len > 0;
+              len --, s ++)
+         {
+           temp = *s;
+           *s   = ((temp & 0xff) << 24) |
+                  ((temp & 0xff00) << 8) |
+                  ((temp & 0xff0000) >> 8) |
+                  ((temp & 0xff000000) >> 24);
 
-      DEBUG_printf(("4cups_raster_read_header: %08x => %08x", temp, *s));
-    }
+           DEBUG_printf(("4cups_raster_read_header: %08x => %08x", temp, *s));
+         }
+       }
+        break;
+
+    case CUPS_RASTER_SYNCapple :
+    case CUPS_RASTER_REVSYNCapple :
+        {
+          unsigned char        appleheader[64];        /* Raw header */
+          static const unsigned rawcspace[] =
+          {
+            CUPS_CSPACE_SW,
+            CUPS_CSPACE_SRGB,
+            CUPS_CSPACE_RGBW,
+            CUPS_CSPACE_ADOBERGB,
+            CUPS_CSPACE_W,
+            CUPS_CSPACE_RGB,
+            CUPS_CSPACE_CMYK
+          };
+          static const unsigned rawnumcolors[] =
+          {
+            1,
+            3,
+            4,
+            3,
+            1,
+            3,
+            4
+          };
+
+         if (cups_raster_read(r, appleheader, sizeof(appleheader)) < (ssize_t)sizeof(appleheader))
+         {
+           DEBUG_printf(("4cups_raster_read_header: EOF, r->iocount=" CUPS_LLFMT, CUPS_LLCAST r->iocount));
+           return (0);
+         }
+
+         strlcpy(r->header.MediaClass, "PwgRaster", sizeof(r->header.MediaClass));
+                                             /* PwgRaster */
+          r->header.cupsBitsPerPixel = appleheader[0];
+          r->header.cupsColorSpace   = appleheader[1] >= (sizeof(rawcspace) / sizeof(rawcspace[0])) ? CUPS_CSPACE_DEVICE1 : rawcspace[appleheader[1]];
+          r->header.cupsNumColors    = appleheader[1] >= (sizeof(rawnumcolors) / sizeof(rawnumcolors[0])) ? 1 : rawnumcolors[appleheader[1]];
+          r->header.cupsBitsPerColor = r->header.cupsBitsPerPixel / r->header.cupsNumColors;
+          r->header.cupsWidth        = ((((((unsigned)appleheader[12] << 8) | (unsigned)appleheader[13]) << 8) | (unsigned)appleheader[14]) << 8) | (unsigned)appleheader[15];
+          r->header.cupsHeight       = ((((((unsigned)appleheader[16] << 8) | (unsigned)appleheader[17]) << 8) | (unsigned)appleheader[18]) << 8) | (unsigned)appleheader[19];
+          r->header.cupsBytesPerLine = r->header.cupsWidth * r->header.cupsBitsPerPixel / 8;
+          r->header.cupsColorOrder   = CUPS_ORDER_CHUNKED;
+          r->header.HWResolution[0]  = r->header.HWResolution[1] = ((((((unsigned)appleheader[20] << 8) | (unsigned)appleheader[21]) << 8) | (unsigned)appleheader[22]) << 8) | (unsigned)appleheader[23];
+
+          if (r->header.HWResolution[0] > 0)
+          {
+           r->header.PageSize[0]     = (unsigned)(r->header.cupsWidth * 72 / r->header.HWResolution[0]);
+           r->header.PageSize[1]     = (unsigned)(r->header.cupsHeight * 72 / r->header.HWResolution[1]);
+           r->header.cupsPageSize[0] = (float)(r->header.cupsWidth * 72.0 / r->header.HWResolution[0]);
+           r->header.cupsPageSize[1] = (float)(r->header.cupsHeight * 72.0 / r->header.HWResolution[1]);
+          }
+
+          r->header.cupsInteger[0] = r->apple_page_count;
+          r->header.cupsInteger[7] = 0xffffff;
+        }
+        break;
   }
 
  /*
index 9c3f7650811aacbce99c62a82f3d1ce611c162e7..112876d98966f50dd120b51915823bf4719674e0 100644 (file)
@@ -208,6 +208,7 @@ main(int  argc,                             /* I - Number of command-line args */
     errors += do_raster_tests(CUPS_RASTER_WRITE);
     errors += do_raster_tests(CUPS_RASTER_WRITE_COMPRESSED);
     errors += do_raster_tests(CUPS_RASTER_WRITE_PWG);
+    errors += do_raster_tests(CUPS_RASTER_WRITE_APPLE);
   }
   else
   {
@@ -526,8 +527,9 @@ do_raster_tests(cups_mode_t mode)   /* O - Write mode */
 
   printf("cupsRasterOpen(%s): ",
          mode == CUPS_RASTER_WRITE ? "CUPS_RASTER_WRITE" :
-            mode == CUPS_RASTER_WRITE ? "CUPS_RASTER_WRITE_COMPRESSED" :
-                                        "CUPS_RASTER_WRITE_PWG");
+            mode == CUPS_RASTER_WRITE_COMPRESSED ? "CUPS_RASTER_WRITE_COMPRESSED" :
+            mode == CUPS_RASTER_WRITE_PWG ? "CUPS_RASTER_WRITE_PWG" :
+                                            "CUPS_RASTER_WRITE_APPLE");
   fflush(stdout);
 
   if ((fp = fopen("test.raster", "wb")) == NULL)
@@ -554,15 +556,15 @@ do_raster_tests(cups_mode_t mode) /* O - Write mode */
 
     if (page & 1)
     {
-      header.cupsBytesPerLine *= 2;
+      header.cupsBytesPerLine *= 4;
       header.cupsColorSpace = CUPS_CSPACE_CMYK;
       header.cupsColorOrder = CUPS_ORDER_CHUNKED;
       header.cupsNumColors  = 4;
     }
     else
     {
-      header.cupsColorSpace = CUPS_CSPACE_K;
-      header.cupsColorOrder = CUPS_ORDER_BANDED;
+      header.cupsColorSpace = CUPS_CSPACE_W;
+      header.cupsColorOrder = CUPS_ORDER_CHUNKED;
       header.cupsNumColors  = 1;
     }
 
@@ -678,7 +680,7 @@ do_raster_tests(cups_mode_t mode)   /* O - Write mode */
     expected.cupsHeight       = 256;
     expected.cupsBytesPerLine = 256;
 
-    if (mode == CUPS_RASTER_WRITE_PWG)
+    if (mode >= CUPS_RASTER_WRITE_PWG)
     {
       strlcpy(expected.MediaClass, "PwgRaster", sizeof(expected.MediaClass));
       expected.cupsInteger[7] = 0xffffff;
@@ -686,15 +688,15 @@ do_raster_tests(cups_mode_t mode) /* O - Write mode */
 
     if (page & 1)
     {
-      expected.cupsBytesPerLine *= 2;
+      expected.cupsBytesPerLine *= 4;
       expected.cupsColorSpace = CUPS_CSPACE_CMYK;
       expected.cupsColorOrder = CUPS_ORDER_CHUNKED;
       expected.cupsNumColors  = 4;
     }
     else
     {
-      expected.cupsColorSpace = CUPS_CSPACE_K;
-      expected.cupsColorOrder = CUPS_ORDER_BANDED;
+      expected.cupsColorSpace = CUPS_CSPACE_W;
+      expected.cupsColorOrder = CUPS_ORDER_CHUNKED;
       expected.cupsNumColors  = 1;
     }