]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Save work on PPD support.
authorMichael R Sweet <michael.r.sweet@gmail.com>
Mon, 22 Apr 2019 22:27:46 +0000 (18:27 -0400)
committerMichael R Sweet <michael.r.sweet@gmail.com>
Mon, 22 Apr 2019 22:27:46 +0000 (18:27 -0400)
test/ippeveprinter.c

index ba7aea0dc5042ab750d8987917c095444c0cb01e..9d00f8d269bb0918e0e77fb487cff03561a9de90 100644 (file)
@@ -570,9 +570,6 @@ main(int  argc,                             /* I - Number of command-line args */
   * Apply defaults as needed...
   */
 
-  if (!docformats)
-    docformats = _cupsArrayNewStrings("application/pdf,image/jpeg,image/pwg-raster", ',');
-
   if (!serverport)
   {
 #ifdef _WIN32
@@ -636,13 +633,18 @@ main(int  argc,                           /* I - Number of command-line args */
   */
 
   if (!docformats)
-    docformats = _cupsArrayNewStrings("image/pwg-raster", ',');
+    docformats = _cupsArrayNewStrings(ppm_color > 0 ? "image/jpeg,image/pwg-raster,image/urf": "image/pwg-raster,image/urf", ',');
 
   if (attrfile)
     attrs = load_ippserver_attributes(servername, serverport, attrfile, docformats);
 #if !CUPS_LITE
   else if (ppdfile)
+  {
     attrs = load_ppd_attributes(ppdfile, docformats);
+
+    if (!command)
+      command = "ippeveps";
+  }
 #endif /* !CUPS_LITE */
   else
     attrs = load_legacy_attributes(make, model, ppm, ppm_color, duplex, docformats);
@@ -4501,38 +4503,625 @@ load_ppd_attributes(
     const char   *ppdfile,             /* I - PPD filename */
     cups_array_t *docformats)          /* I - document-format-supported values */
 {
-  (void)ppdfile;
-  (void)docformats;
-
-#if 0
-  static const char * const overrides[] =
+  int          i, j;                   /* Looping vars */
+  ipp_t                *attrs;                 /* Attributes */
+  ipp_attribute_t *attr;               /* Current attribute */
+  ipp_t                *col;                   /* Current collection value */
+  ppd_file_t   *ppd;                   /* PPD data */
+  ppd_attr_t   *ppd_attr;              /* PPD attribute */
+  ppd_size_t   *ppd_size;              /* Default PPD size */
+  pwg_size_t   *pwg_size,              /* Current PWG size */
+               *default_size = NULL;   /* Default PWG size */
+  pwg_map_t    *pwg_map;               /* Mapping from PWG to PPD keywords */
+  _ppd_cache_t *pc;                    /* PPD cache */
+  _pwg_finishings_t *finishings;       /* Current finishings value */
+  const char   *template;              /* Current finishings-template value */
+  int          num_margins;            /* Number of media-xxx-margin-supported values */
+  int          margins[10];            /* media-xxx-margin-supported values */
+  int          xres,                   /* Default horizontal resolution */
+               yres;                   /* Default vertical resolution */
+  int          num_urf;                /* Number of urf-supported values */
+  const char   *urf[10];               /* urf-supported values */
+  char         urf_rs[32];             /* RS value */
+  static const int     orientation_requested_supported[4] =
+  {                                    /* orientation-requested-supported values */
+    IPP_ORIENT_PORTRAIT,
+    IPP_ORIENT_LANDSCAPE,
+    IPP_ORIENT_REVERSE_LANDSCAPE,
+    IPP_ORIENT_REVERSE_PORTRAIT
+  };
+  static const char * const overrides_supported[] =
   {                                    /* overrides-supported */
-    "document-number",
+    "document-numbers",
+    "media",
+    "media-col",
+    "orientation-requested",
     "pages"
   };
+  static const char * const print_color_mode_supported[] =
+  {                                    /* print-color-mode-supported values */
+    "monochrome"
+  };
+  static const char * const print_color_mode_supported_color[] =
+  {                                    /* print-color-mode-supported values */
+    "auto",
+    "color",
+    "monochrome"
+  };
+  static const int     print_quality_supported[] =
+  {                                    /* print-quality-supported values */
+    IPP_QUALITY_DRAFT,
+    IPP_QUALITY_NORMAL,
+    IPP_QUALITY_HIGH
+  };
+  static const char * const printer_supply[] =
+  {                                    /* printer-supply values */
+    "index=1;class=receptacleThatIsFilled;type=wasteToner;unit=percent;"
+        "maxcapacity=100;level=25;colorantname=unknown;",
+    "index=2;class=supplyThatIsConsumed;type=toner;unit=percent;"
+        "maxcapacity=100;level=75;colorantname=black;"
+  };
+  static const char * const printer_supply_color[] =
+  {                                    /* printer-supply values */
+    "index=1;class=receptacleThatIsFilled;type=wasteInk;unit=percent;"
+        "maxcapacity=100;level=25;colorantname=unknown;",
+    "index=2;class=supplyThatIsConsumed;type=ink;unit=percent;"
+        "maxcapacity=100;level=75;colorantname=black;",
+    "index=3;class=supplyThatIsConsumed;type=ink;unit=percent;"
+        "maxcapacity=100;level=50;colorantname=cyan;",
+    "index=4;class=supplyThatIsConsumed;type=ink;unit=percent;"
+        "maxcapacity=100;level=33;colorantname=magenta;",
+    "index=5;class=supplyThatIsConsumed;type=ink;unit=percent;"
+        "maxcapacity=100;level=67;colorantname=yellow;"
+  };
+  static const char * const printer_supply_description[] =
+  {                                    /* printer-supply-description values */
+    "Toner Waste Tank",
+    "Black Toner"
+  };
+  static const char * const printer_supply_description_color[] =
+  {                                    /* printer-supply-description values */
+    "Ink Waste Tank",
+    "Black Ink",
+    "Cyan Ink",
+    "Magenta Ink",
+    "Yellow Ink"
+  };
+  static const char * const pwg_raster_document_type_supported[] =
+  {
+    "black_1",
+    "sgray_8"
+  };
+  static const char * const pwg_raster_document_type_supported_color[] =
+  {
+    "black_1",
+    "sgray_8",
+    "srgb_8",
+    "srgb_16"
+  };
+  static const char * const sides_supported[] =
+  {                                    /* sides-supported values */
+    "one-sided",
+    "two-sided-long-edge",
+    "two-sided-short-edge"
+  };
+
+
+ /*
+  * Open the PPD file...
+  */
+
+  if ((ppd = ppdOpenFile(ppdfile)) == NULL)
+  {
+    ppd_status_t       status;         /* Load error */
+
+    status = ppdLastError(&i);
+    _cupsLangPrintf(stderr, _("ippeveprinter: Unable to open \"%s\": %s on line %d."), ppdfile, ppdErrorString(status), i);
+    return (NULL);
+  }
+
+  ppdMarkDefaults(ppd);
+
+  pc = _ppdCacheCreateWithPPD(ppd);
+
+  if ((ppd_size = ppdPageSize(ppd, NULL)) != NULL)
+  {
+   /*
+    * Look up default size...
+    */
+
+    for (i = 0, pwg_size = pc->sizes; i < pc->num_sizes; i ++, pwg_size ++)
+    {
+      if (!strcmp(pwg_size->map.ppd, ppd_size->name))
+      {
+        default_size = pwg_size;
+        break;
+      }
+    }
+  }
+
+  if (!default_size)
+  {
+   /*
+    * Default to A4 or Letter...
+    */
+
+    for (i = 0, pwg_size = pc->sizes; i < pc->num_sizes; i ++, pwg_size ++)
+    {
+      if (!strcmp(pwg_size->map.ppd, "Letter") || !strcmp(pwg_size->map.ppd, "A4"))
+      {
+        default_size = pwg_size;
+        break;
+      }
+    }
+
+    if (!default_size)
+      default_size = pc->sizes;                /* Last resort: first size */
+  }
+
+  if ((ppd_attr = ppdFindAttr(ppd, "DefaultResolution", NULL)) != NULL)
+  {
+   /*
+    * Use the PPD-defined default resolution...
+    */
+
+    if ((i = sscanf(ppd_attr->value, "%dx%d", &xres, &yres)) == 1)
+      yres = xres;
+    else if (i < 0)
+      xres = yres = 300;
+  }
+  else
+  {
+   /*
+    * Use default of 300dpi...
+    */
+
+    xres = yres = 300;
+  }
+
+  snprintf(urf_rs, sizeof(urf_rs), "RS%d", yres < xres ? yres : xres);
+
+  num_urf = 0;
+  urf[num_urf ++] = "V1.4";
+  urf[num_urf ++] = "CP1";
+  urf[num_urf ++] = urf_rs;
+  urf[num_urf ++] = "W8";
+  if (pc->sides_2sided_long)
+    urf[num_urf ++] = "DM1";
+  if (ppd->color_device)
+    urf[num_urf ++] = "SRGB24";
+
+ /*
+  * PostScript printers accept PDF via one of the CUPS PDF to PostScript
+  * filters...
+  */
+
+  cupsArrayAdd(docformats, "application/pdf");
+
+ /*
+  * Create the attributes...
+  */
+
+  attrs = ippNew();
+
+  /* color-supported */
+  ippAddBoolean(attrs, IPP_TAG_PRINTER, "color-supported", (char)ppd->color_device);
+
+  /* copies-default */
+  ippAddInteger(attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "copies-default", 1);
+
+  /* copies-supported */
+  ippAddRange(attrs, IPP_TAG_PRINTER, "copies-supported", 1, 999);
 
   /* document-password-supported */
-  if (!ippFindAttribute(printer->attrs, "document-password-supported", IPP_TAG_ZERO))
-    ippAddInteger(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "document-password-supported", 127);
+  ippAddInteger(attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "document-password-supported", 127);
+
+  /* finishing-template-supported */
+  attr = ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "finishing-template-supported", cupsArrayCount(pc->templates) + 1, NULL, NULL);
+  ippSetString(attrs, &attr, 0, "none");
+  for (i = 1, template = (const char *)cupsArrayFirst(pc->templates); template; i ++, template = (const char *)cupsArrayNext(pc->templates))
+    ippSetString(attrs, &attr, i, template);
+
+  /* finishings-col-database */
+  attr = ippAddCollections(attrs, IPP_TAG_PRINTER, "finishings-col-database", cupsArrayCount(pc->templates) + 1, NULL);
+
+  col = ippNew();
+  ippAddString(col, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "finishing-template", NULL, "none");
+  ippSetCollection(attrs, &attr, 0, col);
+  ippDelete(col);
+
+  for (i = 1, template = (const char *)cupsArrayFirst(pc->templates); template; i ++, template = (const char *)cupsArrayNext(pc->templates))
+  {
+    col = ippNew();
+    ippAddString(col, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "finishing-template", NULL, template);
+    ippSetCollection(attrs, &attr, i, col);
+    ippDelete(col);
+  }
+
+  /* finishings-col-default */
+  col = ippNew();
+  ippAddString(col, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "finishing-template", NULL, "none");
+  ippAddCollection(attrs, IPP_TAG_PRINTER, "finishings-col-default", col);
+  ippDelete(col);
+
+  /* finishings-col-ready */
+  attr = ippAddCollections(attrs, IPP_TAG_PRINTER, "finishings-col-ready", cupsArrayCount(pc->templates) + 1, NULL);
+
+  col = ippNew();
+  ippAddString(col, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "finishing-template", NULL, "none");
+  ippSetCollection(attrs, &attr, 0, col);
+  ippDelete(col);
+
+  for (i = 1, template = (const char *)cupsArrayFirst(pc->templates); template; i ++, template = (const char *)cupsArrayNext(pc->templates))
+  {
+    col = ippNew();
+    ippAddString(col, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "finishing-template", NULL, template);
+    ippSetCollection(attrs, &attr, i, col);
+    ippDelete(col);
+  }
+
+  /* finishings-col-supported */
+  ippAddString(attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "finishings-col-supported", NULL, "finishing-template");
+
+  /* finishings-default */
+  ippAddInteger(attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "finishings-default", IPP_FINISHINGS_NONE);
+
+  /* finishings-ready */
+  attr = ippAddIntegers(attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "finishings-ready", cupsArrayCount(pc->finishings) + 1, NULL);
+  ippSetInteger(attrs, &attr, 0, IPP_FINISHINGS_NONE);
+  for (i = 1, finishings = (_pwg_finishings_t *)cupsArrayFirst(pc->finishings); finishings; i ++, finishings = (_pwg_finishings_t *)cupsArrayNext(pc->finishings))
+    ippSetInteger(attrs, &attr, i, finishings->value);
+
+  /* finishings-supported */
+  attr = ippAddIntegers(attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "finishings-supported", cupsArrayCount(pc->finishings) + 1, NULL);
+  ippSetInteger(attrs, &attr, 0, IPP_FINISHINGS_NONE);
+  for (i = 1, finishings = (_pwg_finishings_t *)cupsArrayFirst(pc->finishings); finishings; i ++, finishings = (_pwg_finishings_t *)cupsArrayNext(pc->finishings))
+    ippSetInteger(attrs, &attr, i, finishings->value);
+
+  /* media-bottom-margin-supported */
+  for (i = 0, num_margins = 0, pwg_size = pc->sizes; i < pc->num_sizes && num_margins < (int)(sizeof(margins) / sizeof(margins[0])); i ++, pwg_size ++)
+  {
+    for (j = 0; j < num_margins; j ++)
+    {
+      if (margins[j] == pwg_size->bottom)
+        break;
+    }
+
+    if (j >= num_margins)
+      margins[num_margins ++] = pwg_size->bottom;
+  }
+
+  for (i = 0; i < (num_margins - 1); i ++)
+  {
+    for (j = i + 1; j < num_margins; j ++)
+    {
+      if (margins[i] > margins[j])
+      {
+        int mtemp = margins[i];
+
+        margins[i] = margins[j];
+        margins[j] = mtemp;
+      }
+    }
+  }
+
+  ippAddIntegers(attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-bottom-margin-supported", num_margins, margins);
+
+  /* media-col-database */
+  attr = ippAddCollections(attrs, IPP_TAG_PRINTER, "media-col-database", pc->num_sizes, NULL);
+  for (i = 0, pwg_size = pc->sizes; i < pc->num_sizes; i ++, pwg_size ++)
+  {
+    col = create_media_col(pwg_size->map.pwg, NULL, NULL, pwg_size->width, pwg_size->length, pwg_size->bottom, pwg_size->left, pwg_size->right, pwg_size->top);
+    ippSetCollection(attrs, &attr, i, col);
+    ippDelete(col);
+  }
+
+  /* media-col-default */
+  col = create_media_col(default_size->map.pwg, NULL, NULL, default_size->width, default_size->length, default_size->bottom, default_size->left, default_size->right, default_size->top);
+  ippAddCollection(attrs, IPP_TAG_PRINTER, "media-col-default", col);
+  ippDelete(col);
+
+  /* media-col-ready */
+  col = create_media_col(default_size->map.pwg, pc->num_sources > 0 ? pc->sources[0].pwg : NULL, pc->num_types > 0 ? pc->types[0].pwg : NULL, default_size->width, default_size->length, default_size->bottom, default_size->left, default_size->right, default_size->top);
+  ippAddCollection(attrs, IPP_TAG_PRINTER, "media-col-ready", col);
+  ippDelete(col);
+
+  /* media-default */
+  ippAddString(attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default", NULL, default_size->map.pwg);
+
+  /* media-left-margin-supported */
+  for (i = 0, num_margins = 0, pwg_size = pc->sizes; i < pc->num_sizes && num_margins < (int)(sizeof(margins) / sizeof(margins[0])); i ++, pwg_size ++)
+  {
+    for (j = 0; j < num_margins; j ++)
+    {
+      if (margins[j] == pwg_size->left)
+        break;
+    }
+
+    if (j >= num_margins)
+      margins[num_margins ++] = pwg_size->left;
+  }
+
+  for (i = 0; i < (num_margins - 1); i ++)
+  {
+    for (j = i + 1; j < num_margins; j ++)
+    {
+      if (margins[i] > margins[j])
+      {
+        int mtemp = margins[i];
+
+        margins[i] = margins[j];
+        margins[j] = mtemp;
+      }
+    }
+  }
+
+  ippAddIntegers(attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-left-margin-supported", num_margins, margins);
+
+  /* media-ready */
+  ippAddString(attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-ready", NULL, default_size->map.pwg);
+
+  /* media-right-margin-supported */
+  for (i = 0, num_margins = 0, pwg_size = pc->sizes; i < pc->num_sizes && num_margins < (int)(sizeof(margins) / sizeof(margins[0])); i ++, pwg_size ++)
+  {
+    for (j = 0; j < num_margins; j ++)
+    {
+      if (margins[j] == pwg_size->right)
+        break;
+    }
+
+    if (j >= num_margins)
+      margins[num_margins ++] = pwg_size->right;
+  }
+
+  for (i = 0; i < (num_margins - 1); i ++)
+  {
+    for (j = i + 1; j < num_margins; j ++)
+    {
+      if (margins[i] > margins[j])
+      {
+        int mtemp = margins[i];
+
+        margins[i] = margins[j];
+        margins[j] = mtemp;
+      }
+    }
+  }
+
+  ippAddIntegers(attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-right-margin-supported", num_margins, margins);
+
+  /* media-supported */
+  attr = ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-supported", pc->num_sizes, NULL, NULL);
+  for (i = 0, pwg_size = pc->sizes; i < pc->num_sizes; i ++, pwg_size ++)
+    ippSetString(attrs, &attr, i, pwg_size->map.pwg);
+
+  /* media-size-supported */
+  attr = ippAddCollections(attrs, IPP_TAG_PRINTER, "media-size-supported", pc->num_sizes, NULL);
+  for (i = 0, pwg_size = pc->sizes; i < pc->num_sizes; i ++, pwg_size ++)
+  {
+    col = create_media_size(pwg_size->width, pwg_size->length);
+    ippSetCollection(attrs, &attr, i, col);
+    ippDelete(col);
+  }
+
+  /* media-source-supported */
+  if (pc->num_sources > 0)
+  {
+    attr = ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-source-supported", pc->num_sources, NULL,  NULL);
+    for (i = 0, pwg_map = pc->sources; i < pc->num_sources; i ++, pwg_map ++)
+      ippSetString(attrs, &attr, i, pwg_map->pwg);
+  }
+  else
+  {
+    ippAddString(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "media-source-supported", NULL, "auto");
+  }
+
+  /* media-top-margin-supported */
+  for (i = 0, num_margins = 0, pwg_size = pc->sizes; i < pc->num_sizes && num_margins < (int)(sizeof(margins) / sizeof(margins[0])); i ++, pwg_size ++)
+  {
+    for (j = 0; j < num_margins; j ++)
+    {
+      if (margins[j] == pwg_size->top)
+        break;
+    }
+
+    if (j >= num_margins)
+      margins[num_margins ++] = pwg_size->top;
+  }
+
+  for (i = 0; i < (num_margins - 1); i ++)
+  {
+    for (j = i + 1; j < num_margins; j ++)
+    {
+      if (margins[i] > margins[j])
+      {
+        int mtemp = margins[i];
+
+        margins[i] = margins[j];
+        margins[j] = mtemp;
+      }
+    }
+  }
+
+  ippAddIntegers(attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-top-margin-supported", num_margins, margins);
+
+  /* media-type-supported */
+  if (pc->num_types > 0)
+  {
+    attr = ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-type-supported", pc->num_types, NULL,  NULL);
+    for (i = 0, pwg_map = pc->types; i < pc->num_types; i ++, pwg_map ++)
+      ippSetString(attrs, &attr, i, pwg_map->pwg);
+  }
+  else
+  {
+    ippAddString(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "media-type-supported", NULL, "auto");
+  }
+
+  /* orientation-requested-default */
+  ippAddInteger(attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "orientation-requested-default", IPP_ORIENT_PORTRAIT);
+
+  /* orientation-requested-supported */
+  ippAddIntegers(attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "orientation-requested-supported", (int)(sizeof(orientation_requested_supported) / sizeof(orientation_requested_supported[0])), orientation_requested_supported);
+
+  /* output-bin-default */
+  if (pc->num_bins > 0)
+    ippAddString(attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "output-bin-default", NULL, pc->bins->pwg);
+  else
+    ippAddString(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "output-bin-default", NULL, "face-down");
+
+  /* output-bin-supported */
+  if (pc->num_bins > 0)
+  {
+    attr = ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "output-bin-supported", pc->num_bins, NULL,  NULL);
+    for (i = 0, pwg_map = pc->bins; i < pc->num_bins; i ++, pwg_map ++)
+      ippSetString(attrs, &attr, i, pwg_map->pwg);
+  }
+  else
+  {
+    ippAddString(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "output-bin-supported", NULL, "face-down");
+  }
 
   /* overrides-supported */
-  if (!ippFindAttribute(printer->attrs, "overrides-supported", IPP_TAG_ZERO))
-    ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "overrides-supported", (int)(sizeof(overrides) / sizeof(overrides[0])), NULL, overrides);
+  ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "overrides-supported", (int)(sizeof(overrides_supported) / sizeof(overrides_supported[0])), NULL, overrides_supported);
 
   /* page-ranges-supported */
-  if (!ippFindAttribute(printer->attrs, "page-ranges-supported", IPP_TAG_ZERO))
-    ippAddBoolean(printer->attrs, IPP_TAG_PRINTER, "page-ranges-supported", 1);
+  ippAddBoolean(attrs, IPP_TAG_PRINTER, "page-ranges-supported", 1);
+
   /* pages-per-minute */
-  ippAddInteger(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
-                "pages-per-minute", ppm);
+  ippAddInteger(attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "pages-per-minute", ppd->throughput);
 
   /* pages-per-minute-color */
+  if (ppd->color_device)
+    ippAddInteger(attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "pages-per-minute-color", ppd->throughput);
+
+  /* print-color-mode-default */
+  ippAddString(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "print-color-mode-default", NULL, ppd->color_device ? "auto" : "monochrome");
+
+  /* print-color-mode-supported */
+  if (ppd->color_device)
+    ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "print-color-mode-supported", (int)(sizeof(print_color_mode_supported_color) / sizeof(print_color_mode_supported_color[0])), NULL, print_color_mode_supported_color);
+  else
+    ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "print-color-mode-supported", (int)(sizeof(print_color_mode_supported) / sizeof(print_color_mode_supported[0])), NULL, print_color_mode_supported);
+
+  /* print-content-optimize-default */
+  ippAddString(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "print-content-optimize-default", NULL, "auto");
+
+  /* print-content-optimize-supported */
+  ippAddString(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "print-content-optimize-supported", NULL, "auto");
+
+  /* print-quality-default */
+  ippAddInteger(attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "print-quality-default", IPP_QUALITY_NORMAL);
+
+  /* print-quality-supported */
+  ippAddIntegers(attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "print-quality-supported", (int)(sizeof(print_quality_supported) / sizeof(print_quality_supported[0])), print_quality_supported);
+
+  /* print-rendering-intent-default */
+  ippAddString(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "print-rendering-intent-default", NULL, "auto");
+
+  /* print-rendering-intent-supported */
+  ippAddString(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "print-rendering-intent-supported", NULL, "auto");
+
+  /* printer-device-id */
+  if ((ppd_attr = ppdFindAttr(ppd, "1284DeviceId", NULL)) != NULL)
+  {
+   /*
+    * Use the device ID string from the PPD...
+    */
+
+    ippAddString(attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-device-id", NULL, ppd_attr->value);
+  }
+  else
+  {
+   /*
+    * Synthesize a device ID string...
+    */
+
+    char       device_id[1024];                /* Device ID string */
+
+    snprintf(device_id, sizeof(device_id), "MFG:%s;MDL:%s;CMD:PS;", ppd->manufacturer, ppd->modelname);
+
+    ippAddString(attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-device-id", NULL, device_id);
+  }
+
+  /* printer-input-tray */
+#if 0
   if (ppm_color > 0)
-    ippAddInteger(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
-                  "pages-per-minute-color", ppm_color);
+  {
+    attr = ippAddOctetString(attrs, IPP_TAG_PRINTER, "printer-input-tray", printer_input_tray_color[0], strlen(printer_input_tray_color[0]));
+    for (i = 1; i < (int)(sizeof(printer_input_tray_color) / sizeof(printer_input_tray_color[0])); i ++)
+      ippSetOctetString(attrs, &attr, i, printer_input_tray_color[i], strlen(printer_input_tray_color[i]));
+  }
+  else
+  {
+    attr = ippAddOctetString(attrs, IPP_TAG_PRINTER, "printer-input-tray", printer_input_tray[0], strlen(printer_input_tray[0]));
+    for (i = 1; i < (int)(sizeof(printer_input_tray) / sizeof(printer_input_tray[0])); i ++)
+      ippSetOctetString(attrs, &attr, i, printer_input_tray[i], strlen(printer_input_tray[i]));
+  }
 #endif /* 0 */
 
-  return (NULL);
+  /* printer-make-and-model */
+  ippAddString(attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-make-and-model", NULL, ppd->nickname);
+
+  /* printer-resolution-default */
+  ippAddResolution(attrs, IPP_TAG_PRINTER, "printer-resolution-default", IPP_RES_PER_INCH, xres, yres);
+
+  /* printer-resolution-supported */
+  ippAddResolution(attrs, IPP_TAG_PRINTER, "printer-resolution-supported", IPP_RES_PER_INCH, xres, yres);
+
+  /* printer-supply and printer-supply-description */
+  if (ppd->color_device)
+  {
+    attr = ippAddOctetString(attrs, IPP_TAG_PRINTER, "printer-supply", printer_supply_color[0], strlen(printer_supply_color[0]));
+    for (i = 1; i < (int)(sizeof(printer_supply_color) / sizeof(printer_supply_color[0])); i ++)
+      ippSetOctetString(attrs, &attr, i, printer_supply_color[i], strlen(printer_supply_color[i]));
+
+    ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_TEXT), "printer-supply-description", (int)(sizeof(printer_supply_description_color) / sizeof(printer_supply_description_color[0])), NULL, printer_supply_description_color);
+  }
+  else
+  {
+    attr = ippAddOctetString(attrs, IPP_TAG_PRINTER, "printer-supply", printer_supply[0], strlen(printer_supply[0]));
+    for (i = 1; i < (int)(sizeof(printer_supply) / sizeof(printer_supply[0])); i ++)
+      ippSetOctetString(attrs, &attr, i, printer_supply[i], strlen(printer_supply[i]));
+
+    ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_TEXT), "printer-supply-description", (int)(sizeof(printer_supply_description) / sizeof(printer_supply_description[0])), NULL, printer_supply_description);
+  }
+
+  /* pwg-raster-document-xxx-supported */
+  if (cupsArrayFind(docformats, (void *)"image/pwg-raster"))
+  {
+    ippAddResolution(attrs, IPP_TAG_PRINTER, "pwg-raster-document-resolution-supported", IPP_RES_PER_INCH, xres, yres);
+
+    if (pc->sides_2sided_long)
+      ippAddString(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "pwg-raster-document-sheet-back", NULL, "normal");
+
+    if (ppd->color_device)
+      ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "pwg-raster-document-type-supported", (int)(sizeof(pwg_raster_document_type_supported_color) / sizeof(pwg_raster_document_type_supported_color[0])), NULL, pwg_raster_document_type_supported_color);
+    else
+      ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "pwg-raster-document-type-supported", (int)(sizeof(pwg_raster_document_type_supported) / sizeof(pwg_raster_document_type_supported[0])), NULL, pwg_raster_document_type_supported);
+  }
+
+  /* sides-default */
+  ippAddString(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "sides-default", NULL, "one-sided");
+
+  /* sides-supported */
+  if (pc->sides_2sided_long)
+    ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "sides-supported", (int)(sizeof(sides_supported) / sizeof(sides_supported[0])), NULL, sides_supported);
+  else
+    ippAddString(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "sides-supported", NULL, "one-sided");
+
+  /* urf-supported */
+  if (cupsArrayFind(docformats, (void *)"image/urf"))
+    ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "urf-supported", num_urf, NULL, urf);
+
+ /*
+  * Free the PPD file and return the attributes...
+  */
+
+  _ppdCacheDestroy(pc);
+
+  ppdClose(ppd);
+
+  return (attrs);
 }
 #endif /* !CUPS_LITE */