Overview

The CUPS PPD API provides read-only access the data in PostScript Printer Description ("PPD") files which are used for all printers with a driver. With it you can display printer options to users, mark option choices and check for conflicting choices, and output marked choices in PostScript output. The ppd_file_t structure contains all of the information in a PPD file.

Loading a PPD File

The ppdOpenFile function "opens" a PPD file and loads it into memory. For example, the following code opens the current printer's PPD file in a CUPS filter:

#include <cups/ppd.h>

ppd_file_t *ppd = ppdOpenFile(getenv("PPD"));

The return value is a pointer to a new ppd_file_t structure or NULL if the PPD file does not exist or cannot be loaded. The ppdClose function frees the memory used by the structure:

#include <cups/ppd.h>

ppd_file_t *ppd;

ppdClose(ppd);

Options and Groups

PPD files support multiple options, which are stored in arrays of ppd_option_t and ppd_choice_t structures.

Each option in turn is associated with a group stored in a ppd_group_t structure. Groups can be specified in the PPD file; if an option is not associated with a group then it is put in an automatically-generated "General" group. Groups can also have sub-groups, however CUPS currently ignores sub-groups because of past abuses of this functionality.

Options are selected by marking them using one of three functions. The first is ppdMarkDefaults which selects all of the default options in the PPD file:

#include <cups/ppd.h>

ppd_file_t *ppd;

ppdMarkDefaults(ppd);

The second is ppdMarkOption which selects a single option choice in the PPD file. For example, the following code selects the manual feed media source:

#include <cups/ppd.h>

ppd_file_t *ppd;

ppdMarkOption(ppd, "InputSlot", "ManualFeed");

The last function is cupsMarkOptions which selects multiple option choices in the PPD file from an array of CUPS options, mapping IPP attributes like "media" and "sides" to their corresponding PPD options. You typically use this function in a print filter with cupsParseOptions and ppdMarkDefaults to select all of the option choices needed for the job, for example:

#include <cups/ppd.h>

ppd_file_t *ppd = ppdOpenFile(getenv("PPD"));
cups_option_t *options = NULL;
int num_options = cupsParseOptions(argv[5], 0, &options);

ppdMarkDefaults(ppd);
cupsMarkOptions(ppd, num_options, options);

Constraints

PPD files support specification of conflict conditions, called constraints, between different options. Constraints are stored in an array of ppd_const_t structures which specify the options and choices that conflict with each other. The ppdConflicts function tells you how many of the selected options are incompatible.

Page Sizes

Page sizes are special options which have physical dimensions and margins associated with them. The size information is stored in ppd_size_t structures and is available by looking up the named size with the ppdPageSize function. The page size and margins are returned in units called points; there are 72 points per inch. If you pass NULL for the size, the currently selected size is returned:

#include <cups/ppd.h>

ppd_file_t *ppd;
ppd_size_t *size = ppdPageSize(ppd, NULL);

Besides the standard page sizes listed in a PPD file, some printers support variable or custom page sizes. Custom page sizes are supported if the variables_sizes member of the ppd_file_t structure is non-zero. The custom_min, custom_max, and custom_margins members of the ppd_file_t structure define the limits of the printable area. To get the resulting media size, use a page size string of the form "Custom.widthxlength", where "width" and "length" are in points. Custom page size names can also be specified in inches ("Custom.widthxheightin"), centimeters ("Custom.widthxheightcm"), or millimeters ("Custom.widthxheightmm"):

#include <cups/ppd.h>

ppd_file_t *ppd;

/* Get an 576x720 point custom page size */
ppd_size_t *size = ppdPageSize(ppd, "Custom.576x720");

/* Get an 8x10 inch custom page size */
ppd_size_t *size = ppdPageSize(ppd, "Custom.8x10in");

/* Get a 100x200 millimeter custom page size */
ppd_size_t *size = ppdPageSize(ppd, "Custom.100x200mm");

/* Get a 12.7x34.5 centimeter custom page size */
ppd_size_t *size = ppdPageSize(ppd, "Custom.12.7x34.5cm");

Attributes

Every PPD file is composed of one or more attributes. Most of these attributes are used to define groups, options, choices, and page sizes, however several informations attributes are available which you may need to access in your program or filter. Attributes normally look like one of the following examples in a PPD file:

*name: "value"
*name spec: "value"
*name spec/text: "value"

The ppdFindAttr and ppdFindNextAttr functions find the first and next instances, respectively, of the named attribute with the given "spec" string and return a ppd_attr_t structure. If you provide a NULL specifier string, all attributes with the given name will be returned. For example, the following code lists all of the Product attributes in a PPD file:

#include <cups/ppd.h>

ppd_file_t *ppd;
ppd_attr_t *attr;

for (attr = ppdFindAttr(ppd, "Product", NULL);
     attr != NULL;
     attr = ppdFindNextAttr(ppd, "Product", NULL))
  puts(attr->value);