]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
First part of better media support (Issue #5167)
authorMichael Sweet <michael.r.sweet@gmail.com>
Wed, 29 Nov 2017 17:49:55 +0000 (12:49 -0500)
committerMichael Sweet <michael.r.sweet@gmail.com>
Wed, 29 Nov 2017 23:07:19 +0000 (18:07 -0500)
cups/dest-localization.c:
- Fix localization of borderless/non-borderless media.

cups/dest-options:
- Add support for borderless size names (still needs work)

cups/ppd-cache.c:
- Fix PageSize support in PPD generator - borderless media and custom page sizes.

cups/testppd.c:
- Need to request media-col-database for PPD generator.

cups/dest-localization.c
cups/dest-options.c
cups/ppd-cache.c
cups/testppd.c

index 1eef3ea7a8798a11206fb6e8ca68593ab5beab80..9950d6badd146caae43ee06f683f9c37e9f8c30f 100644 (file)
@@ -91,7 +91,7 @@ cupsLocalizeDestMedia(
     return (lsize);
   }
 
-  pwg  = pwgMediaForSize(size->width, size->length);
+  pwg = pwgMediaForSize(size->width, size->length);
 
   if (pwg->ppd)
     lsize = _cupsLangString(lang, pwg->ppd);
@@ -159,28 +159,28 @@ cupsLocalizeDestMedia(
 
   if (!lsource && !ltype)
   {
-    if (size->bottom || size->left || size->right || size->top)
+    if (!size->bottom && !size->left && !size->right && !size->top)
       snprintf(name, sizeof(name), _cupsLangString(lang, _("%s (Borderless)")), lsize);
     else
       strlcpy(name, lsize, sizeof(name));
   }
   else if (!lsource)
   {
-    if (size->bottom || size->left || size->right || size->top)
+    if (!size->bottom && !size->left && !size->right && !size->top)
       snprintf(name, sizeof(name), _cupsLangString(lang, _("%s (Borderless, %s)")), lsize, ltype);
     else
       snprintf(name, sizeof(name), _cupsLangString(lang, _("%s (%s)")), lsize, ltype);
   }
   else if (!ltype)
   {
-    if (size->bottom || size->left || size->right || size->top)
+    if (!size->bottom && !size->left && !size->right && !size->top)
       snprintf(name, sizeof(name), _cupsLangString(lang, _("%s (Borderless, %s)")), lsize, lsource);
     else
       snprintf(name, sizeof(name), _cupsLangString(lang, _("%s (%s)")), lsize, lsource);
   }
   else
   {
-    if (size->bottom || size->left || size->right || size->top)
+    if (!size->bottom && !size->left && !size->right && !size->top)
       snprintf(name, sizeof(name), _cupsLangString(lang, _("%s (Borderless, %s, %s)")), lsize, ltype, lsource);
     else
       snprintf(name, sizeof(name), _cupsLangString(lang, _("%s (%s, %s)")), lsize, ltype, lsource);
index b849f70c7afb2cd3e05fbee0240ada805480121c..de4841b0eb57f76394c1759c63df65746b408bf0 100644 (file)
@@ -122,10 +122,10 @@ cupsCheckDestSupported(
     */
 
     pwg_media_t        *pwg;           /* Current PWG media size info */
-    int                        min_width,      /* Minimum width */
-                       min_length,     /* Minimum length */
-                       max_width,      /* Maximum width */
-                       max_length;     /* Maximum length */
+    int                min_width,      /* Minimum width */
+               min_length,     /* Minimum length */
+               max_width,      /* Maximum width */
+               max_length;     /* Maximum length */
 
    /*
     * Get the minimum and maximum size...
@@ -2021,7 +2021,9 @@ cups_get_media_db(http_t       *http,     /* I - Connection to destination */
     * Return the matching size...
     */
 
-    if (best->size_name)
+    if (!best->bottom && !best->left && !best->right && !best->top)
+      snprintf(size->media, sizeof(size->media), "%s.Borderless", pwg->ppd);
+    else if (best->size_name)
       strlcpy(size->media, best->size_name, sizeof(size->media));
     else if (best->key)
       strlcpy(size->media, best->key, sizeof(size->media));
index 042ba73cc492251c195a20d4edadc33cf00f6bf2..9ff0e310b339fcf40650ed128dd9843f3e981800 100644 (file)
@@ -28,8 +28,9 @@
 
 static int     cups_get_url(http_t **http, const char *url, char *name, size_t namesize);
 static void    pwg_add_finishing(cups_array_t *finishings, ipp_finishings_t template, const char *name, const char *value);
-static int     pwg_compare_finishings(_pwg_finishings_t *a,
-                                      _pwg_finishings_t *b);
+static int     pwg_compare_finishings(_pwg_finishings_t *a, _pwg_finishings_t *b);
+static int     pwg_compare_sizes(cups_size_t *a, cups_size_t *b);
+static cups_size_t *pwg_copy_size(cups_size_t *size);
 static void    pwg_free_finishings(_pwg_finishings_t *f);
 static void    pwg_ppdize_name(const char *ipp, char *name, size_t namesize);
 static void    pwg_ppdize_resolution(ipp_attribute_t *attr, int element, int *xres, int *yres, char *name, size_t namesize);
@@ -3000,12 +3001,14 @@ _ppdCreateFromIPP(char   *buffer,       /* I - Filename buffer */
                  ipp_t  *response)     /* I - Get-Printer-Attributes response */
 {
   cups_file_t          *fp;            /* PPD file */
-  cups_array_t         *sizes;         /* Media sizes we've added */
+  cups_array_t         *sizes;         /* Media sizes supported by printer */
+  cups_size_t          *size;          /* Current media size */
   ipp_attribute_t      *attr,          /* xxx-supported */
                        *defattr,       /* xxx-default */
                         *quality,      /* print-quality-supported */
                        *x_dim, *y_dim; /* Media dimensions */
-  ipp_t                        *media_size;    /* Media size collection */
+  ipp_t                        *media_col,     /* Media collection */
+                       *media_size;    /* Media size collection */
   char                 make[256],      /* Make and model */
                        *model,         /* Model name */
                        ppdname[PPD_MAX_NAME];
@@ -3016,6 +3019,11 @@ _ppdCreateFromIPP(char   *buffer,        /* I - Filename buffer */
                        left,           /* Largest left margin */
                        right,          /* Largest right margin */
                        top,            /* Largest top margin */
+                       max_length = 0, /* Maximum custom size */
+                       max_width = 0,
+                       min_length = INT_MAX,
+                                       /* Minimum custom size */
+                       min_width = INT_MAX,
                        is_apple = 0,   /* Does the printer support Apple raster? */
                        is_pdf = 0,     /* Does the printer support PDF? */
                        is_pwg = 0;     /* Does the printer support PWG Raster? */
@@ -3290,135 +3298,319 @@ _ppdCreateFromIPP(char   *buffer,     /* I - Filename buffer */
   else
     strlcpy(ppdname, "Unknown", sizeof(ppdname));
 
-  if ((attr = ippFindAttribute(response, "media-size-supported", IPP_TAG_BEGIN_COLLECTION)) == NULL)
-    attr = ippFindAttribute(response, "media-supported", IPP_TAG_ZERO);
-  if (attr)
-  {
-    cupsFilePrintf(fp, "*OpenUI *PageSize: PickOne\n"
-                      "*OrderDependency: 10 AnySetup *PageSize\n"
-                       "*DefaultPageSize: %s\n", ppdname);
-
-    sizes = cupsArrayNew3((cups_array_func_t)strcmp, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
+  sizes = cupsArrayNew3((cups_array_func_t)pwg_compare_sizes, NULL, NULL, 0, (cups_acopy_func_t)pwg_copy_size, (cups_afree_func_t)free);
 
+  if ((attr = ippFindAttribute(response, "media-col-database", IPP_TAG_BEGIN_COLLECTION)) != NULL)
+  {
     for (i = 0, count = ippGetCount(attr); i < count; i ++)
     {
-      if (ippGetValueTag(attr) == IPP_TAG_BEGIN_COLLECTION)
-      {
-       media_size = ippGetCollection(attr, i);
-       x_dim      = ippFindAttribute(media_size, "x-dimension", IPP_TAG_INTEGER);
-       y_dim      = ippFindAttribute(media_size, "y-dimension", IPP_TAG_INTEGER);
+      cups_size_t      temp;           /* Current size */
+      ipp_attribute_t  *margin;        /* media-xxx-margin attribute */
 
-       pwg = pwgMediaForSize(ippGetInteger(x_dim, 0), ippGetInteger(y_dim, 0));
-      }
-      else
-        pwg = pwgMediaForPWG(ippGetString(attr, i, NULL));
+      media_col   = ippGetCollection(attr, i);
+      media_size  = ippGetCollection(ippFindAttribute(media_col, "media-size", IPP_TAG_BEGIN_COLLECTION), 0);
+      x_dim       = ippFindAttribute(media_size, "x-dimension", IPP_TAG_ZERO);
+      y_dim       = ippFindAttribute(media_size, "y-dimension", IPP_TAG_ZERO);
+      pwg         = pwgMediaForSize(ippGetInteger(x_dim, 0), ippGetInteger(y_dim, 0));
 
       if (pwg)
       {
-        char   twidth[256],            /* Width string */
-               tlength[256];           /* Length string */
+       temp.width  = pwg->width;
+       temp.length = pwg->length;
 
-        if (cupsArrayFind(sizes, (void *)pwg->ppd))
-        {
-          cupsFilePrintf(fp, "*%% warning: Duplicate size '%s' reported by printer.\n", pwg->ppd);
-          continue;
-        }
+       if ((margin = ippFindAttribute(media_col, "media-bottom-margin", IPP_TAG_INTEGER)) != NULL)
+         temp.bottom = ippGetInteger(margin, 0);
+       else
+         temp.bottom = bottom;
 
-        cupsArrayAdd(sizes, (void *)pwg->ppd);
+       if ((margin = ippFindAttribute(media_col, "media-left-margin", IPP_TAG_INTEGER)) != NULL)
+         temp.left = ippGetInteger(margin, 0);
+       else
+         temp.left = left;
+
+       if ((margin = ippFindAttribute(media_col, "media-right-margin", IPP_TAG_INTEGER)) != NULL)
+         temp.right = ippGetInteger(margin, 0);
+       else
+         temp.right = right;
 
-        _cupsStrFormatd(twidth, twidth + sizeof(twidth), pwg->width * 72.0 / 2540.0, loc);
-        _cupsStrFormatd(tlength, tlength + sizeof(tlength), pwg->length * 72.0 / 2540.0, loc);
+       if ((margin = ippFindAttribute(media_col, "media-top-margin", IPP_TAG_INTEGER)) != NULL)
+         temp.top = ippGetInteger(margin, 0);
+       else
+         temp.top = top;
 
-        cupsFilePrintf(fp, "*PageSize %s: \"<</PageSize[%s %s]>>setpagedevice\"\n", pwg->ppd, twidth, tlength);
+       if (temp.bottom == 0 && temp.left == 0 && temp.right == 0 && temp.top == 0)
+         snprintf(temp.media, sizeof(temp.media), "%s.Borderless", pwg->ppd);
+       else
+         strlcpy(temp.media, pwg->ppd, sizeof(temp.media));
+
+       if (!cupsArrayFind(sizes, &temp))
+         cupsArrayAdd(sizes, &temp);
       }
-    }
-    cupsFilePuts(fp, "*CloseUI: *PageSize\n");
+      else if (ippGetValueTag(x_dim) == IPP_TAG_RANGE || ippGetValueTag(y_dim) == IPP_TAG_RANGE)
+      {
+       /*
+       * Custom size - record the min/max values...
+       */
 
-    cupsArrayDelete(sizes);
-    sizes = cupsArrayNew3((cups_array_func_t)strcmp, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
+       int lower, upper;               /* Range values */
 
-    cupsFilePrintf(fp, "*OpenUI *PageRegion: PickOne\n"
-                       "*OrderDependency: 10 AnySetup *PageRegion\n"
-                       "*DefaultPageRegion: %s\n", ppdname);
-    for (i = 0, count = ippGetCount(attr); i < count; i ++)
+       if (ippGetValueTag(x_dim) == IPP_TAG_RANGE)
+         lower = ippGetRange(x_dim, 0, &upper);
+       else
+         lower = upper = ippGetInteger(x_dim, 0);
+
+       if (lower < min_width)
+         min_width = lower;
+       if (upper > max_width)
+         max_width = upper;
+
+       if (ippGetValueTag(y_dim) == IPP_TAG_RANGE)
+         lower = ippGetRange(y_dim, 0, &upper);
+       else
+         lower = upper = ippGetInteger(y_dim, 0);
+
+       if (lower < min_length)
+         min_length = lower;
+       if (upper > max_length)
+         max_length = upper;
+      }
+    }
+
+    if ((max_width == 0 || max_length == 0) && (attr = ippFindAttribute(response, "media-size-supported", IPP_TAG_BEGIN_COLLECTION)) != NULL)
     {
-      if (ippGetValueTag(attr) == IPP_TAG_BEGIN_COLLECTION)
+     /*
+      * Some printers don't list custom size support in media-col-database...
+      */
+
+      for (i = 0, count = ippGetCount(attr); i < count; i ++)
       {
-       media_size = ippGetCollection(attr, i);
-       x_dim      = ippFindAttribute(media_size, "x-dimension", IPP_TAG_INTEGER);
-       y_dim      = ippFindAttribute(media_size, "y-dimension", IPP_TAG_INTEGER);
+       media_size  = ippGetCollection(attr, i);
+       x_dim       = ippFindAttribute(media_size, "x-dimension", IPP_TAG_ZERO);
+       y_dim       = ippFindAttribute(media_size, "y-dimension", IPP_TAG_ZERO);
+
+       if (ippGetValueTag(x_dim) == IPP_TAG_RANGE || ippGetValueTag(y_dim) == IPP_TAG_RANGE)
+       {
+        /*
+         * Custom size - record the min/max values...
+         */
 
-       pwg = pwgMediaForSize(ippGetInteger(x_dim, 0), ippGetInteger(y_dim, 0));
+         int lower, upper;             /* Range values */
+
+         if (ippGetValueTag(x_dim) == IPP_TAG_RANGE)
+           lower = ippGetRange(x_dim, 0, &upper);
+         else
+           lower = upper = ippGetInteger(x_dim, 0);
+
+         if (lower < min_width)
+           min_width = lower;
+         if (upper > max_width)
+           max_width = upper;
+
+         if (ippGetValueTag(y_dim) == IPP_TAG_RANGE)
+           lower = ippGetRange(y_dim, 0, &upper);
+         else
+           lower = upper = ippGetInteger(y_dim, 0);
+
+         if (lower < min_length)
+           min_length = lower;
+         if (upper > max_length)
+           max_length = upper;
+       }
       }
-      else
-        pwg = pwgMediaForPWG(ippGetString(attr, i, NULL));
+    }
+  }
+  else if ((attr = ippFindAttribute(response, "media-size-supported", IPP_TAG_BEGIN_COLLECTION)) != NULL)
+  {
+    for (i = 0, count = ippGetCount(attr); i < count; i ++)
+    {
+      cups_size_t      temp;           /* Current size */
+
+      media_size  = ippGetCollection(attr, i);
+      x_dim       = ippFindAttribute(media_size, "x-dimension", IPP_TAG_ZERO);
+      y_dim       = ippFindAttribute(media_size, "y-dimension", IPP_TAG_ZERO);
+      pwg         = pwgMediaForSize(ippGetInteger(x_dim, 0), ippGetInteger(y_dim, 0));
 
       if (pwg)
       {
-        char   twidth[256],            /* Width string */
-               tlength[256];           /* Length string */
+       temp.width  = pwg->width;
+       temp.length = pwg->length;
+       temp.bottom = bottom;
+       temp.left   = left;
+       temp.right  = right;
+       temp.top    = top;
+
+       if (temp.bottom == 0 && temp.left == 0 && temp.right == 0 && temp.top == 0)
+         snprintf(temp.media, sizeof(temp.media), "%s.Borderless", pwg->ppd);
+       else
+         strlcpy(temp.media, pwg->ppd, sizeof(temp.media));
 
-        if (cupsArrayFind(sizes, (void *)pwg->ppd))
-          continue;
+       if (!cupsArrayFind(sizes, &temp))
+         cupsArrayAdd(sizes, &temp);
+      }
+      else if (ippGetValueTag(x_dim) == IPP_TAG_RANGE || ippGetValueTag(y_dim) == IPP_TAG_RANGE)
+      {
+       /*
+       * Custom size - record the min/max values...
+       */
 
-        cupsArrayAdd(sizes, (void *)pwg->ppd);
+       int lower, upper;               /* Range values */
 
-        _cupsStrFormatd(twidth, twidth + sizeof(twidth), pwg->width * 72.0 / 2540.0, loc);
-        _cupsStrFormatd(tlength, tlength + sizeof(tlength), pwg->length * 72.0 / 2540.0, loc);
+       if (ippGetValueTag(x_dim) == IPP_TAG_RANGE)
+         lower = ippGetRange(x_dim, 0, &upper);
+       else
+         lower = upper = ippGetInteger(x_dim, 0);
 
-        cupsFilePrintf(fp, "*PageRegion %s: \"<</PageSize[%s %s]>>setpagedevice\"\n", pwg->ppd, twidth, tlength);
-      }
-    }
-    cupsFilePuts(fp, "*CloseUI: *PageRegion\n");
+       if (lower < min_width)
+         min_width = lower;
+       if (upper > max_width)
+         max_width = upper;
 
-    cupsArrayDelete(sizes);
-    sizes = cupsArrayNew3((cups_array_func_t)strcmp, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
+       if (ippGetValueTag(y_dim) == IPP_TAG_RANGE)
+         lower = ippGetRange(y_dim, 0, &upper);
+       else
+         lower = upper = ippGetInteger(y_dim, 0);
 
-    cupsFilePrintf(fp, "*DefaultImageableArea: %s\n"
-                      "*DefaultPaperDimension: %s\n", ppdname, ppdname);
+       if (lower < min_length)
+         min_length = lower;
+       if (upper > max_length)
+         max_length = upper;
+      }
+    }
+  }
+  else if ((attr = ippFindAttribute(response, "media-supported", IPP_TAG_ZERO)) != NULL)
+  {
     for (i = 0, count = ippGetCount(attr); i < count; i ++)
     {
-      if (ippGetValueTag(attr) == IPP_TAG_BEGIN_COLLECTION)
+      const char       *pwg_size = ippGetString(attr, i, NULL);
+                                       /* PWG size name */
+      cups_size_t      temp;           /* Current size */
+
+      if ((pwg = pwgMediaForPWG(pwg_size)) != NULL)
       {
-       media_size = ippGetCollection(attr, i);
-       x_dim      = ippFindAttribute(media_size, "x-dimension", IPP_TAG_INTEGER);
-       y_dim      = ippFindAttribute(media_size, "y-dimension", IPP_TAG_INTEGER);
+        if (strstr(pwg_size, "_max_") || strstr(pwg_size, "_max."))
+        {
+          if (pwg->width > max_width)
+            max_width = pwg->width;
+          if (pwg->length > max_length)
+            max_length = pwg->length;
+        }
+        else if (strstr(pwg_size, "_min_") || strstr(pwg_size, "_min."))
+        {
+          if (pwg->width < min_width)
+            min_width = pwg->width;
+          if (pwg->length < min_length)
+            min_length = pwg->length;
+        }
+        else
+        {
+         temp.width  = pwg->width;
+         temp.length = pwg->length;
+         temp.bottom = bottom;
+         temp.left   = left;
+         temp.right  = right;
+         temp.top    = top;
+
+         if (temp.bottom == 0 && temp.left == 0 && temp.right == 0 && temp.top == 0)
+           snprintf(temp.media, sizeof(temp.media), "%s.Borderless", pwg->ppd);
+         else
+           strlcpy(temp.media, pwg->ppd, sizeof(temp.media));
 
-       pwg = pwgMediaForSize(ippGetInteger(x_dim, 0), ippGetInteger(y_dim, 0));
+         if (!cupsArrayFind(sizes, &temp))
+           cupsArrayAdd(sizes, &temp);
+       }
       }
-      else
-        pwg = pwgMediaForPWG(ippGetString(attr, i, NULL));
+    }
+  }
 
-      if (pwg)
-      {
-        char   tleft[256],             /* Left string */
+  if (cupsArrayCount(sizes) > 0)
+  {
+   /*
+    * List all of the standard sizes...
+    */
+
+    char       tleft[256],             /* Left string */
                tbottom[256],           /* Bottom string */
                tright[256],            /* Right string */
                ttop[256],              /* Top string */
                twidth[256],            /* Width string */
                tlength[256];           /* Length string */
 
-        if (cupsArrayFind(sizes, (void *)pwg->ppd))
-          continue;
+    cupsFilePrintf(fp, "*OpenUI *PageSize: PickOne\n"
+                      "*OrderDependency: 10 AnySetup *PageSize\n"
+                       "*DefaultPageSize: %s\n", ppdname);
+    for (size = (cups_size_t *)cupsArrayFirst(sizes); size; size = (cups_size_t *)cupsArrayNext(sizes))
+    {
+      _cupsStrFormatd(twidth, twidth + sizeof(twidth), size->width * 72.0 / 2540.0, loc);
+      _cupsStrFormatd(tlength, tlength + sizeof(tlength), size->length * 72.0 / 2540.0, loc);
 
-        cupsArrayAdd(sizes, (void *)pwg->ppd);
+      cupsFilePrintf(fp, "*PageSize %s: \"<</PageSize[%s %s]>>setpagedevice\"\n", size->media, twidth, tlength);
+    }
+    cupsFilePuts(fp, "*CloseUI: *PageSize\n");
 
-        _cupsStrFormatd(tleft, tleft + sizeof(tleft), left * 72.0 / 2540.0, loc);
-        _cupsStrFormatd(tbottom, tbottom + sizeof(tbottom), bottom * 72.0 / 2540.0, loc);
-        _cupsStrFormatd(tright, tright + sizeof(tright), (pwg->width - right) * 72.0 / 2540.0, loc);
-        _cupsStrFormatd(ttop, ttop + sizeof(ttop), (pwg->length - top) * 72.0 / 2540.0, loc);
-        _cupsStrFormatd(twidth, twidth + sizeof(twidth), pwg->width * 72.0 / 2540.0, loc);
-        _cupsStrFormatd(tlength, tlength + sizeof(tlength), pwg->length * 72.0 / 2540.0, loc);
+    cupsFilePrintf(fp, "*OpenUI *PageRegion: PickOne\n"
+                       "*OrderDependency: 10 AnySetup *PageRegion\n"
+                       "*DefaultPageRegion: %s\n", ppdname);
+    for (size = (cups_size_t *)cupsArrayFirst(sizes); size; size = (cups_size_t *)cupsArrayNext(sizes))
+    {
+      _cupsStrFormatd(twidth, twidth + sizeof(twidth), size->width * 72.0 / 2540.0, loc);
+      _cupsStrFormatd(tlength, tlength + sizeof(tlength), size->length * 72.0 / 2540.0, loc);
 
-        cupsFilePrintf(fp, "*ImageableArea %s: \"%s %s %s %s\"\n", pwg->ppd, tleft, tbottom, tright, ttop);
-        cupsFilePrintf(fp, "*PaperDimension %s: \"%s %s\"\n", pwg->ppd, twidth, tlength);
-      }
+      cupsFilePrintf(fp, "*PageRegion %s: \"<</PageSize[%s %s]>>setpagedevice\"\n", size->media, twidth, tlength);
+    }
+    cupsFilePuts(fp, "*CloseUI: *PageRegion\n");
+
+    cupsFilePrintf(fp, "*DefaultImageableArea: %s\n"
+                      "*DefaultPaperDimension: %s\n", ppdname, ppdname);
+
+    for (size = (cups_size_t *)cupsArrayFirst(sizes); size; size = (cups_size_t *)cupsArrayNext(sizes))
+    {
+      _cupsStrFormatd(tleft, tleft + sizeof(tleft), size->left * 72.0 / 2540.0, loc);
+      _cupsStrFormatd(tbottom, tbottom + sizeof(tbottom), size->bottom * 72.0 / 2540.0, loc);
+      _cupsStrFormatd(tright, tright + sizeof(tright), (size->width - size->right) * 72.0 / 2540.0, loc);
+      _cupsStrFormatd(ttop, ttop + sizeof(ttop), (size->length - size->top) * 72.0 / 2540.0, loc);
+      _cupsStrFormatd(twidth, twidth + sizeof(twidth), size->width * 72.0 / 2540.0, loc);
+      _cupsStrFormatd(tlength, tlength + sizeof(tlength), size->length * 72.0 / 2540.0, loc);
+
+      cupsFilePrintf(fp, "*ImageableArea %s: \"%s %s %s %s\"\n", size->media, tleft, tbottom, tright, ttop);
+      cupsFilePrintf(fp, "*PaperDimension %s: \"%s %s\"\n", size->media, twidth, tlength);
     }
 
     cupsArrayDelete(sizes);
+
+   /*
+    * Custom size support...
+    */
+
+    if (max_width > 0 && min_width < INT_MAX && max_length > 0 && min_length < INT_MAX)
+    {
+      char     tmax[256], tmin[256];   /* Min/max values */
+
+      _cupsStrFormatd(tleft, tleft + sizeof(tleft), left * 72.0 / 2540.0, loc);
+      _cupsStrFormatd(tbottom, tbottom + sizeof(tbottom), bottom * 72.0 / 2540.0, loc);
+      _cupsStrFormatd(tright, tright + sizeof(tright), right * 72.0 / 2540.0, loc);
+      _cupsStrFormatd(ttop, ttop + sizeof(ttop), top * 72.0 / 2540.0, loc);
+
+      cupsFilePrintf(fp, "*HWMargins: \"%s %s %s %s\"\n", tleft, tbottom, tright, ttop);
+
+      _cupsStrFormatd(tmax, tmax + sizeof(tmax), max_width * 72.0 / 2540.0, loc);
+      _cupsStrFormatd(tmin, tmin + sizeof(tmin), min_width * 72.0 / 2540.0, loc);
+      cupsFilePrintf(fp, "*ParamCustomPageSize Width: 1 points %s %s\n", tmin, tmax);
+
+      _cupsStrFormatd(tmax, tmax + sizeof(tmax), max_length * 72.0 / 2540.0, loc);
+      _cupsStrFormatd(tmin, tmin + sizeof(tmin), min_length * 72.0 / 2540.0, loc);
+      cupsFilePrintf(fp, "*ParamCustomPageSize Height: 2 points %s %s\n", tmin, tmax);
+
+      cupsFilePuts(fp, "*ParamCustomPageSize WidthOffset: 3 points 0 0\n");
+      cupsFilePuts(fp, "*ParamCustomPageSize HeightOffset: 4 points 0 0\n");
+      cupsFilePuts(fp, "*ParamCustomPageSize Orientation: 5 int 0 3\n");
+      cupsFilePuts(fp, "*CustomPageSize True: \"pop pop pop <</PageSize[5 -2 roll]/ImagingBBox null>>setpagedevice\"\n");
+    }
   }
   else
+  {
+    cupsArrayDelete(sizes);
     goto bad_ppd;
+  }
 
  /*
   * InputSlot...
@@ -4413,9 +4605,9 @@ _pwgMediaTypeForType(
 
 const char *                           /* O - PageSize name */
 _pwgPageSizeForMedia(
-    pwg_media_t *media,                /* I - Media */
-    char         *name,                        /* I - PageSize name buffer */
-    size_t       namesize)             /* I - Size of name buffer */
+    pwg_media_t *media,                        /* I - Media */
+    char        *name,                 /* I - PageSize name buffer */
+    size_t      namesize)              /* I - Size of name buffer */
 {
   const char   *sizeptr,               /* Pointer to size in PWG name */
                *dimptr;                /* Pointer to dimensions in PWG name */
@@ -4559,6 +4751,35 @@ pwg_compare_finishings(
 }
 
 
+/*
+ * 'pwg_compare_sizes()' - Compare two media sizes...
+ */
+
+static int                             /* O - Result of comparison */
+pwg_compare_sizes(cups_size_t *a,      /* I - First media size */
+                  cups_size_t *b)      /* I - Second media size */
+{
+  return (strcmp(a->media, b->media));
+}
+
+
+/*
+ * 'pwg_copy_size()' - Copy a media size.
+ */
+
+static cups_size_t *                   /* O - New media size */
+pwg_copy_size(cups_size_t *size)       /* I - Media size to copy */
+{
+  cups_size_t  *newsize = (cups_size_t *)calloc(1, sizeof(cups_size_t));
+                                       /* New media size */
+
+  if (newsize)
+    memcpy(newsize, size, sizeof(cups_size_t));
+
+  return (newsize);
+}
+
+
 /*
  * 'pwg_free_finishings()' - Free a finishings value.
  */
index 5ebc549a3cea7695560edbc0cbd07e0021ee3418..0e3668f54af2f0b3849eb1a4edbefd6c49a661e8 100644 (file)
@@ -870,6 +870,13 @@ main(int  argc,                            /* I - Number of command-line arguments */
                host[256],              /* Hostname */
                resource[256];          /* Resource path */
     int                port;                   /* Port number */
+    static const char * const pattrs[] =/* Requested printer attributes */
+    {
+      "job-template",
+      "printer-defaults",
+      "printer-description",
+      "media-col-database"
+    };
 
     if (httpSeparateURI(HTTP_URI_CODING_ALL, argv[1], scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK)
     {
@@ -886,6 +893,7 @@ main(int  argc,                             /* I - Number of command-line arguments */
 
     request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, argv[1]);
+    ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]), NULL, pattrs);
     response = cupsDoRequest(http, request, resource);
 
     if (_ppdCreateFromIPP(buffer, sizeof(buffer), response))