]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - filter/interpret.c
Mirror fix from trunk.
[thirdparty/cups.git] / filter / interpret.c
index f3c092d92b39cc44908b58341de2c997e69b050a..77157fb97597c64bc3be8939136762c3fe999e72 100644 (file)
@@ -1,25 +1,16 @@
 /*
- * "$Id: interpret.c 6281 2007-02-14 16:32:42Z mike $"
+ * "$Id$"
  *
- *   PPD command interpreter for the Common UNIX Printing System (CUPS).
+ *   PPD command interpreter for CUPS.
  *
+ *   Copyright 2007-2012 by Apple Inc.
  *   Copyright 1993-2007 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
- *   property of Easy Software Products and are protected by Federal
- *   copyright law.  Distribution and use rights are outlined in the file
- *   "LICENSE.txt" which should have been included with this file.  If this
- *   file is missing or damaged please contact Easy Software Products
- *   at:
- *
- *       Attn: CUPS Licensing Information
- *       Easy Software Products
- *       44141 Airport View Drive, Suite 204
- *       Hollywood, Maryland 20636 USA
- *
- *       Voice: (301) 373-9600
- *       EMail: cups-info@cups.org
- *         WWW: http://www.cups.org
+ *   property of Apple Inc. and are protected by Federal copyright
+ *   law.  Distribution and use rights are outlined in the file "LICENSE.txt"
+ *   which should have been included with this file.  If this file is
+ *   file is missing or damaged, see the license at "http://www.cups.org/".
  *
  *   This file is subject to the Apple OS-Developed Software exception.
  *
@@ -49,9 +40,7 @@
  * Include necessary headers...
  */
 
-#include <cups/string.h>
-#include "image-private.h"
-#include <stdlib.h>
+#include <cups/raster-private.h>
 
 
 /*
@@ -131,31 +120,40 @@ static void               DEBUG_stack(_cups_ps_stack_t *st);
 /*
  * 'cupsRasterInterpretPPD()' - Interpret PPD commands to create a page header.
  *
- * This function does not mark the options in the PPD using the "num_options"
- * and "options" arguments.  Instead, mark the options prior to calling
- * cupsRasterInterpretPPD() - this allows you to do per-page options
- * without manipulating the options array.
+ * This function is used by raster image processing (RIP) filters like
+ * cgpdftoraster and imagetoraster when writing CUPS raster data for a page.
+ * It is not used by raster printer driver filters which only read CUPS
+ * raster data.
+ *
+ *
+ * @code cupsRasterInterpretPPD@ does not mark the options in the PPD using
+ * the "num_options" and "options" arguments.  Instead, mark the options with
+ * @code cupsMarkOptions@ and @code ppdMarkOption@ prior to calling it -
+ * this allows for per-page options without manipulating the options array.
  *
  * The "func" argument specifies an optional callback function that is
  * called prior to the computation of the final raster data.  The function
- * can make changes to the cups_page_header2_t data as needed to use a
+ * can make changes to the @link cups_page_header2_t@ data as needed to use a
  * supported raster format and then returns 0 on success and -1 if the
  * requested attributes cannot be supported.
  *
- * cupsRasterInterpretPPD() supports a subset of the PostScript language.
- * Currently only the [, ], <<, >>, {, }, cleartomark, copy, dup, index,
- * pop, roll, setpagedevice, and stopped operators are supported.
  *
- * @since CUPS 1.2@
+ * @code cupsRasterInterpretPPD@ supports a subset of the PostScript language.
+ * Currently only the @code [@, @code ]@, @code <<@, @code >>@, @code {@,
+ * @code }@, @code cleartomark@, @code copy@, @code dup@, @code index@,
+ * @code pop@, @code roll@, @code setpagedevice@, and @code stopped@ operators
+ * are supported.
+ *
+ * @since CUPS 1.2/OS X 10.5@
  */
 
 int                                    /* O - 0 on success, -1 on failure */
 cupsRasterInterpretPPD(
-    cups_page_header2_t *h,            /* O - Page header */
+    cups_page_header2_t *h,            /* O - Page header to create */
     ppd_file_t          *ppd,          /* I - PPD file */
     int                 num_options,   /* I - Number of options */
     cups_option_t       *options,      /* I - Options */
-    cups_interpret_cb_t func)          /* I - Optional page header callback */
+    cups_interpret_cb_t func)          /* I - Optional page header callback (@code NULL@ for none) */
 {
   int          status;                 /* Cummulative status */
   char         *code;                  /* Code to run */
@@ -202,7 +200,16 @@ cupsRasterInterpretPPD(
   h->cupsImagingBBox[2]          = 612.0f;
   h->cupsImagingBBox[3]          = 792.0f;
 
-  strcpy(h->cupsPageSizeName, "Letter");
+  strlcpy(h->cupsPageSizeName, "Letter", sizeof(h->cupsPageSizeName));
+
+#ifdef __APPLE__
+ /*
+  * cupsInteger0 is also used for the total page count on OS X; set an
+  * uncommon default value so we can tell if the driver is using cupsInteger0.
+  */
+
+  h->cupsInteger[0] = 0x80000000;
+#endif /* __APPLE__ */
 
  /*
   * Apply patches and options to the page header...
@@ -256,10 +263,10 @@ cupsRasterInterpretPPD(
   if ((val = cupsGetOption("cupsBorderlessScalingFactor", num_options,
                            options)) != NULL)
   {
-    float sc = atof(val);
+    double sc = atof(val);             /* Scale factor */
 
-    if (sc >= 0.9 && sc <= 1.1)
-      h->cupsBorderlessScalingFactor = sc;
+    if (sc >= 0.1 && sc <= 2.0)
+      h->cupsBorderlessScalingFactor = (float)sc;
   }
 
  /*
@@ -294,20 +301,26 @@ cupsRasterInterpretPPD(
     top    = 792.0f;
   }
 
-  h->PageSize[0]           = h->cupsPageSize[0] *
-                             h->cupsBorderlessScalingFactor;
-  h->PageSize[1]           = h->cupsPageSize[1] *
-                             h->cupsBorderlessScalingFactor;
-  h->Margins[0]            = left * h->cupsBorderlessScalingFactor;
-  h->Margins[1]            = bottom * h->cupsBorderlessScalingFactor;
-  h->ImagingBoundingBox[0] = left * h->cupsBorderlessScalingFactor;
-  h->ImagingBoundingBox[1] = bottom * h->cupsBorderlessScalingFactor;
-  h->ImagingBoundingBox[2] = right * h->cupsBorderlessScalingFactor;
-  h->ImagingBoundingBox[3] = top * h->cupsBorderlessScalingFactor;
-  h->cupsImagingBBox[0]    = left;
-  h->cupsImagingBBox[1]    = bottom;
-  h->cupsImagingBBox[2]    = right;
-  h->cupsImagingBBox[3]    = top;
+  h->PageSize[0]           = (unsigned)(h->cupsPageSize[0] *
+                                        h->cupsBorderlessScalingFactor);
+  h->PageSize[1]           = (unsigned)(h->cupsPageSize[1] *
+                                        h->cupsBorderlessScalingFactor);
+  h->Margins[0]            = (unsigned)(left *
+                                        h->cupsBorderlessScalingFactor);
+  h->Margins[1]            = (unsigned)(bottom *
+                                        h->cupsBorderlessScalingFactor);
+  h->ImagingBoundingBox[0] = (unsigned)(left *
+                                        h->cupsBorderlessScalingFactor);
+  h->ImagingBoundingBox[1] = (unsigned)(bottom *
+                                        h->cupsBorderlessScalingFactor);
+  h->ImagingBoundingBox[2] = (unsigned)(right *
+                                        h->cupsBorderlessScalingFactor);
+  h->ImagingBoundingBox[3] = (unsigned)(top *
+                                        h->cupsBorderlessScalingFactor);
+  h->cupsImagingBBox[0]    = (float)left;
+  h->cupsImagingBBox[1]    = (float)bottom;
+  h->cupsImagingBBox[2]    = (float)right;
+  h->cupsImagingBBox[3]    = (float)top;
 
  /*
   * Use the callback to validate the page header...
@@ -328,7 +341,7 @@ cupsRasterInterpretPPD(
       (h->cupsBitsPerColor != 1 && h->cupsBitsPerColor != 2 &&
        h->cupsBitsPerColor != 4 && h->cupsBitsPerColor != 8 &&
        h->cupsBitsPerColor != 16) ||
-      h->cupsBorderlessScalingFactor < 0.5 ||
+      h->cupsBorderlessScalingFactor < 0.1 ||
       h->cupsBorderlessScalingFactor > 2.0)
   {
     _cupsRasterAddError("Page header uses unsupported values.\n");
@@ -351,6 +364,7 @@ cupsRasterInterpretPPD(
     case CUPS_CSPACE_WHITE :
     case CUPS_CSPACE_GOLD :
     case CUPS_CSPACE_SILVER :
+    case CUPS_CSPACE_SW :
         h->cupsNumColors    = 1;
         h->cupsBitsPerPixel = h->cupsBitsPerColor;
        break;
@@ -412,6 +426,29 @@ cupsRasterInterpretPPD(
 
         h->cupsNumColors = 4;
        break;
+
+    case CUPS_CSPACE_DEVICE1 :
+    case CUPS_CSPACE_DEVICE2 :
+    case CUPS_CSPACE_DEVICE3 :
+    case CUPS_CSPACE_DEVICE4 :
+    case CUPS_CSPACE_DEVICE5 :
+    case CUPS_CSPACE_DEVICE6 :
+    case CUPS_CSPACE_DEVICE7 :
+    case CUPS_CSPACE_DEVICE8 :
+    case CUPS_CSPACE_DEVICE9 :
+    case CUPS_CSPACE_DEVICEA :
+    case CUPS_CSPACE_DEVICEB :
+    case CUPS_CSPACE_DEVICEC :
+    case CUPS_CSPACE_DEVICED :
+    case CUPS_CSPACE_DEVICEE :
+    case CUPS_CSPACE_DEVICEF :
+        h->cupsNumColors = h->cupsColorSpace - CUPS_CSPACE_DEVICE1 + 1;
+
+        if (h->cupsColorOrder == CUPS_ORDER_CHUNKED)
+          h->cupsBitsPerPixel = h->cupsBitsPerColor * h->cupsNumColors;
+       else
+         h->cupsBitsPerPixel = h->cupsBitsPerColor;
+       break;
   }
 
   h->cupsBytesPerLine = (h->cupsBitsPerPixel * h->cupsWidth + 7) / 8;
@@ -468,9 +505,8 @@ _cupsRasterExecPS(
   while ((obj = scan_ps(st, &codeptr)) != NULL)
   {
 #ifdef DEBUG
-    printf("    (%d): ", st->num_objs);
+    DEBUG_printf(("_cupsRasterExecPS: Stack (%d objects)\n", st->num_objs));
     DEBUG_object(obj);
-    putchar('\n');
 #endif /* DEBUG */
 
     switch (obj->type)
@@ -486,7 +522,7 @@ _cupsRasterExecPS(
            _cupsRasterAddError("cleartomark: Stack underflow!\n");
 
 #ifdef DEBUG
-          fputs("    dup: ", stdout);
+          DEBUG_puts("    dup: ");
          DEBUG_stack(st);
 #endif /* DEBUG */
           break;
@@ -498,7 +534,7 @@ _cupsRasterExecPS(
            copy_stack(st, (int)obj->value.number);
 
 #ifdef DEBUG
-            fputs("    copy: ", stdout);
+            DEBUG_puts("_cupsRasterExecPS: copy");
            DEBUG_stack(st);
 #endif /* DEBUG */
           }
@@ -509,7 +545,7 @@ _cupsRasterExecPS(
          copy_stack(st, 1);
 
 #ifdef DEBUG
-          fputs("    dup: ", stdout);
+          DEBUG_puts("_cupsRasterExecPS: dup");
          DEBUG_stack(st);
 #endif /* DEBUG */
           break;
@@ -521,7 +557,7 @@ _cupsRasterExecPS(
            index_stack(st, (int)obj->value.number);
 
 #ifdef DEBUG
-            fputs("    index: ", stdout);
+            DEBUG_puts("_cupsRasterExecPS: index");
            DEBUG_stack(st);
 #endif /* DEBUG */
           }
@@ -532,7 +568,7 @@ _cupsRasterExecPS(
           pop_stack(st);
 
 #ifdef DEBUG
-          fputs("    pop: ", stdout);
+          DEBUG_puts("_cupsRasterExecPS: pop");
          DEBUG_stack(st);
 #endif /* DEBUG */
           break;
@@ -551,7 +587,7 @@ _cupsRasterExecPS(
              roll_stack(st, (int)obj->value.number, c);
 
 #ifdef DEBUG
-              fputs("    roll:", stdout);
+              DEBUG_puts("_cupsRasterExecPS: roll");
              DEBUG_stack(st);
 #endif /* DEBUG */
             }
@@ -563,7 +599,7 @@ _cupsRasterExecPS(
          setpagedevice(st, h, preferred_bits);
 
 #ifdef DEBUG
-          fputs("    setpagedevice: ", stdout);
+          DEBUG_puts("_cupsRasterExecPS: setpagedevice");
          DEBUG_stack(st);
 #endif /* DEBUG */
           break;
@@ -576,11 +612,12 @@ _cupsRasterExecPS(
 
       case CUPS_PS_OTHER :
           _cupsRasterAddError("Unknown operator \"%s\"!\n", obj->value.other);
-          DEBUG_printf(("    Unknown operator \"%s\"!\n", obj->value.other));
+          DEBUG_printf(("_cupsRasterExecPS: Unknown operator \"%s\"!\n",
+                       obj->value.other));
           break;
     }
 
-    if (obj->type == CUPS_PS_OTHER)
+    if (obj && obj->type == CUPS_PS_OTHER)
       break;
   }
 
@@ -595,7 +632,7 @@ _cupsRasterExecPS(
     error_stack(st, "Stack not empty:");
 
 #ifdef DEBUG
-    fputs("    Stack not empty:", stdout);
+    DEBUG_puts("_cupsRasterExecPS: Stack not empty:");
     DEBUG_stack(st);
 #endif /* DEBUG */
 
@@ -783,7 +820,7 @@ error_stack(_cups_ps_stack_t *st,   /* I - Stack */
   _cups_ps_obj_t       *obj;           /* Current object on stack */
 
 
-  _cupsRasterAddError(title);
+  _cupsRasterAddError("%s", title);
 
   for (obj = st->objs, c = st->num_objs; c > 0; c --, obj ++)
     error_object(obj);
@@ -985,6 +1022,9 @@ scan_ps(_cups_ps_stack_t *st,              /* I  - Stack */
       */
 
       for (cur ++; *cur && *cur != '\n' && *cur != '\r'; cur ++);
+
+      if (!*cur)
+        cur --;
     }
     else if (!isspace(*cur & 255))
       break;
@@ -1347,13 +1387,13 @@ setpagedevice(
   * Found the start of the dictionary, empty the stack to this point...
   */
 
-  st->num_objs = obj - st->objs;
+  st->num_objs = (int)(obj - st->objs);
 
  /*
   * Now pull /name and value pairs from the dictionary...
   */
 
-  DEBUG_puts("    Dictionary:");
+  DEBUG_puts("setpagedevice: Dictionary:");
 
   for (obj ++; obj < end; obj ++)
   {
@@ -1368,9 +1408,8 @@ setpagedevice(
     obj ++;
 
 #ifdef DEBUG
-    printf("        /%s ", name);
+    DEBUG_printf(("setpagedevice: /%s ", name));
     DEBUG_object(obj);
-    putchar('\n');
 #endif /* DEBUG */
 
    /*
@@ -1415,9 +1454,19 @@ setpagedevice(
       h->LeadingEdge = (unsigned)obj->value.number;
     else if (!strcmp(name, "ManualFeed") && obj->type == CUPS_PS_BOOLEAN)
       h->ManualFeed = (unsigned)obj->value.boolean;
-    else if ((!strcmp(name, "cupsMediaPosition") || /* Compatibility */
+    else if ((!strcmp(name, "cupsMediaPosition") ||
               !strcmp(name, "MediaPosition")) && obj->type == CUPS_PS_NUMBER)
+    {
+     /*
+      * cupsMediaPosition is supported for backwards compatibility only.
+      * We added it back in the Ghostscript 5.50 days to work around a
+      * bug in Ghostscript WRT handling of MediaPosition and setpagedevice.
+      *
+      * All new development should set MediaPosition...
+      */
+
       h->MediaPosition = (unsigned)obj->value.number;
+    }
     else if (!strcmp(name, "MediaWeight") && obj->type == CUPS_PS_NUMBER)
       h->MediaWeight = (unsigned)obj->value.number;
     else if (!strcmp(name, "MirrorPrint") && obj->type == CUPS_PS_BOOLEAN)
@@ -1435,8 +1484,8 @@ setpagedevice(
       if (obj[1].type == CUPS_PS_NUMBER && obj[2].type == CUPS_PS_NUMBER &&
           obj[3].type == CUPS_PS_END_ARRAY)
       {
-        h->cupsPageSize[0] = obj[1].value.number;
-       h->cupsPageSize[1] = obj[2].value.number;
+        h->cupsPageSize[0] = (float)obj[1].value.number;
+       h->cupsPageSize[1] = (float)obj[2].value.number;
 
         h->PageSize[0] = (unsigned)obj[1].value.number;
        h->PageSize[1] = (unsigned)obj[2].value.number;
@@ -1473,7 +1522,7 @@ setpagedevice(
       h->cupsRowStep = (unsigned)obj->value.number;
     else if (!strcmp(name, "cupsBorderlessScalingFactor") &&
              obj->type == CUPS_PS_NUMBER)
-      h->cupsBorderlessScalingFactor = obj->value.number;
+      h->cupsBorderlessScalingFactor = (float)obj->value.number;
     else if (!strncmp(name, "cupsInteger", 11) && obj->type == CUPS_PS_NUMBER)
     {
       if ((i = atoi(name + 11)) < 0 || i > 15)
@@ -1486,7 +1535,7 @@ setpagedevice(
       if ((i = atoi(name + 8)) < 0 || i > 15)
         return (-1);
 
-      h->cupsReal[i] = obj->value.number;
+      h->cupsReal[i] = (float)obj->value.number;
     }
     else if (!strncmp(name, "cupsString", 10) && obj->type == CUPS_PS_STRING)
     {
@@ -1532,86 +1581,86 @@ DEBUG_object(_cups_ps_obj_t *obj)       /* I - Object to print */
   switch (obj->type)
   {
     case CUPS_PS_NAME :
-       printf("/%s", obj->value.name);
+       DEBUG_printf(("/%s\n", obj->value.name));
        break;
 
     case CUPS_PS_NUMBER :
-       printf("%g", obj->value.number);
+       DEBUG_printf(("%g\n", obj->value.number));
        break;
 
     case CUPS_PS_STRING :
-       printf("(%s)", obj->value.string);
+       DEBUG_printf(("(%s)\n", obj->value.string));
        break;
 
     case CUPS_PS_BOOLEAN :
        if (obj->value.boolean)
-         fputs("true", stdout);
+         DEBUG_puts("true");
        else
-         fputs("false", stdout);
+         DEBUG_puts("false");
        break;
 
     case CUPS_PS_NULL :
-       fputs("null", stdout);
+       DEBUG_puts("null");
        break;
 
     case CUPS_PS_START_ARRAY :
-       fputs("[", stdout);
+       DEBUG_puts("[");
        break;
 
     case CUPS_PS_END_ARRAY :
-       fputs("]", stdout);
+       DEBUG_puts("]");
        break;
 
     case CUPS_PS_START_DICT :
-       fputs("<<", stdout);
+       DEBUG_puts("<<");
        break;
 
     case CUPS_PS_END_DICT :
-       fputs(">>", stdout);
+       DEBUG_puts(">>");
        break;
 
     case CUPS_PS_START_PROC :
-       fputs("{", stdout);
+       DEBUG_puts("{");
        break;
 
     case CUPS_PS_END_PROC :
-       fputs("}", stdout);
+       DEBUG_puts("}");
        break;
 
     case CUPS_PS_CLEARTOMARK :
-       fputs("--cleartomark--", stdout);
+       DEBUG_puts("--cleartomark--");
         break;
 
     case CUPS_PS_COPY :
-       fputs("--copy--", stdout);
+       DEBUG_puts("--copy--");
         break;
 
     case CUPS_PS_DUP :
-       fputs("--dup--", stdout);
+       DEBUG_puts("--dup--");
         break;
 
     case CUPS_PS_INDEX :
-       fputs("--index--", stdout);
+       DEBUG_puts("--index--");
         break;
 
     case CUPS_PS_POP :
-       fputs("--pop--", stdout);
+       DEBUG_puts("--pop--");
         break;
 
     case CUPS_PS_ROLL :
-       fputs("--roll--", stdout);
+       DEBUG_puts("--roll--");
         break;
 
     case CUPS_PS_SETPAGEDEVICE :
-       fputs("--setpagedevice--", stdout);
+       DEBUG_puts("--setpagedevice--");
         break;
 
     case CUPS_PS_STOPPED :
-       fputs("--stopped--", stdout);
+       DEBUG_puts("--stopped--");
         break;
 
     case CUPS_PS_OTHER :
-       printf("--%s--", obj->value.other);
+       DEBUG_printf(("--%s--\n", obj->value.other));
        break;
   }
 }
@@ -1629,16 +1678,11 @@ DEBUG_stack(_cups_ps_stack_t *st)       /* I - Stack */
 
 
   for (obj = st->objs, c = st->num_objs; c > 0; c --, obj ++)
-  {
-    putchar(' ');
     DEBUG_object(obj);
-  }
-
-  putchar('\n');
 }
 #endif /* DEBUG */
 
 
 /*
- * End of "$Id: interpret.c 6281 2007-02-14 16:32:42Z mike $".
+ * End of "$Id$".
  */