• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<!DOCTYPE html>
2<html lang="en-US">
3<!-- SECTION: Programming -->
4<head>
5<title>Developing PostScript Printer Drivers</title>
6<meta name="keywords" content="Programming">
7<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
8<meta name="generator" content="codedoc v3.7">
9<meta name="author" content="Unknown">
10<meta name="language" content="en-US">
11<meta name="copyright" content="Unknown">
12<meta name="version" content="0.0">
13<style type="text/css"><!--
14body {
15  background: white;
16  color: black;
17  font-family: sans-serif;
18  font-size: 12pt;
19}
20a {
21  color: black;
22}
23a:link, a:visited {
24  color: #00f;
25}
26a:link:hover, a:visited:hover, a:active {
27  color: #c0c;
28}
29body, p, h1, h2, h3, h4, h5, h6 {
30  font-family: sans-serif;
31  line-height: 1.4;
32}
33h1, h2, h3, h4, h5, h6 {
34  font-weight: bold;
35  page-break-inside: avoid;
36}
37h1 {
38  font-size: 250%;
39  margin: 0;
40}
41h2 {
42  font-size: 250%;
43  margin-top: 1.5em;
44}
45h3 {
46  font-size: 200%;
47  margin-bottom: 0.5em;
48  margin-top: 1.5em;
49}
50h4 {
51  font-size: 150%;
52  margin-bottom: 0.5em;
53  margin-top: 1.5em;
54}
55h5 {
56  font-size: 125%;
57  margin-bottom: 0.5em;
58  margin-top: 1.5em;
59}
60h6 {
61  font-size: 110%;
62  margin-bottom: 0.5em;
63  margin-top: 1.5em;
64}
65img.title {
66  width: 256px;
67}
68div.header h1, div.header p {
69  text-align: center;
70}
71div.contents, div.body, div.footer {
72  page-break-before: always;
73}
74.class, .enumeration, .function, .struct, .typedef, .union {
75  border-bottom: solid 2px gray;
76}
77.description {
78  margin-top: 0.5em;
79}
80.function {
81  margin-bottom: 0;
82}
83blockquote {
84  border: solid thin gray;
85  box-shadow: 3px 3px 5px rgba(127,127,127,0.25);
86  margin: 1em 0;
87  padding: 10px;
88  page-break-inside: avoid;
89}
90p code, li code, p.code, pre, ul.code li {
91  font-family: monospace;
92  hyphens: manual;
93  -webkit-hyphens: manual;
94}
95p.code, pre, ul.code li {
96  background: rgba(127,127,127,0.25);
97  border: thin dotted gray;
98  padding: 10px;
99  page-break-inside: avoid;
100}
101pre {
102  white-space: pre-wrap;
103}
104a:link, a:visited {
105  text-decoration: none;
106}
107span.info {
108  background: black;
109  border: solid thin black;
110  color: white;
111  font-size: 80%;
112  font-style: italic;
113  font-weight: bold;
114  white-space: nowrap;
115}
116h1 span.info, h2 span.info, h3 span.info, h4 span.info {
117  border-top-left-radius: 10px;
118  border-top-right-radius: 10px;
119  float: right;
120  padding: 3px 6px;
121}
122ul.code, ul.contents, ul.subcontents {
123  list-style-type: none;
124  margin: 0;
125  padding-left: 0;
126}
127ul.code li {
128  margin: 0;
129}
130ul.contents > li {
131  margin-top: 1em;
132}
133ul.contents li ul.code, ul.contents li ul.subcontents {
134  padding-left: 2em;
135}
136table {
137  border-collapse: collapse;
138  border-spacing: 0;
139}
140td {
141  border: solid 1px gray;
142  padding: 5px 10px;
143  vertical-align: top;
144}
145td.left {
146  text-align: left;
147}
148td.center {
149  text-align: center;
150}
151td.right {
152  text-align: right;
153}
154th {
155  border-bottom: solid 2px gray;
156  padding: 1px 5px;
157  text-align: center;
158  vertical-align: bottom;
159}
160tr:nth-child(even) {
161  background: rgba(127,127,127,0.25);
162}
163table.list {
164  border-collapse: collapse;
165  width: 100%;
166}
167table.list th {
168  border-bottom: none;
169  border-right: 2px solid gray;
170  font-family: monospace;
171  font-weight: normal;
172  padding: 5px 10px 5px 2px;
173  text-align: right;
174  vertical-align: top;
175}
176table.list td {
177  border: none;
178  padding: 5px 2px 5px 10px;
179  text-align: left;
180  vertical-align: top;
181}
182h2.title, h3.title {
183  border-bottom: solid 2px gray;
184}
185/* Syntax highlighting */
186span.comment {
187  color: darkgreen;
188}
189span.directive {
190  color: purple;
191}
192span.number {
193  color: brown;
194}
195span.reserved {
196  color: darkcyan;
197}
198span.string {
199  color: magenta;
200}
201/* Dark mode overrides */
202@media (prefers-color-scheme: dark) {
203  body {
204    background: black;
205    color: #ccc;
206  }
207  a {
208    color: #ccc;
209  }
210  a:link, a:visited {
211    color: #66f;
212  }
213  a:link:hover, a:visited:hover, a:active {
214    color: #f06;
215  }
216}
217/* Show contents on left side in web browser */
218@media screen and (min-width: 800px) {
219  div.contents {
220    border-right: solid thin gray;
221    bottom: 0px;
222    box-shadow: 3px 3px 5px rgba(127,127,127,0.5);
223    font-size: 10pt;
224    left: 0px;
225    overflow: scroll;
226    padding: 1%;
227    position: fixed;
228    top: 0px;
229    width: 18%;
230  }
231  div.contents h2.title {
232    margin-top: 0px;
233  }
234  div.header, div.body, div.footer {
235    margin-left: 20%;
236    padding: 1% 2%;
237  }
238}
239/* Center title page content vertically */
240@media print {
241  div.header {
242    padding-top: 33%;
243  }
244}
245--></style>
246</head>
247<body>
248<div class="header">
249<!--
250  PostScript printer driver documentation for CUPS.
251
252  Copyright © 2020-2024 by OpenPrinting.
253  Copyright © 2007-2012 by Apple Inc.
254  Copyright © 1997-2007 by Easy Software Products.
255
256  Licensed under Apache License v2.0.  See the file "LICENSE" for more
257  information.
258-->
259
260<h1 class='title'>Developing PostScript Printer Drivers</h1>
261
262<p>This document describes how to develop printer drivers for PostScript printers. Topics include: <a href='#BASICS'>printer driver basics</a>, <a href='#CREATE'>creating new PPD files</a>, <a href='#IMPORT'>importing existing PPD files</a>, <a href='#FILTERS'>using custom filters</a>, <a href='#COLOR'>implementing color management</a>, and <a href='#MACOSX'>adding macOS features</a>.</p>
263
264<div class='summary'><table summary='General Information'>
265<tbody>
266<tr>
267	<th>See Also</th>
268	<td>Programming: <a href='raster-driver.html'>Developing Raster Printer Drivers</a><br>
269	Programming: <a href='api-filter.html'>Filter and Backend Programming</a><br>
270	Programming: <a href='ppd-compiler.html'>Introduction to the PPD Compiler</a><br>
271	Programming: <a href='api-raster.html'>Raster API</a><br>
272	References: <a href='ref-ppdcfile.html'>PPD Compiler Driver Information File Reference</a><br>
273	Specifications: <a href='spec-ppd.html'>CUPS PPD Extensions</a></td>
274</tr>
275</tbody>
276</table></div>
277</div>
278<div class="contents">
279<h2 class="title">Contents</h2>
280<ul class="contents">
281<li><a href="#BASICS">Printer Driver Basics</a></li>
282<li><a href="#CREATING">Creating New PPD Files</a><ul class="subcontents">
283<li><a href="#IMPORT">Importing Existing PPD Files</a></li>
284</ul></li>
285<li><a href="#FILTERS">Using Custom Filters</a></li>
286<li><a href="#COLOR">Implementing Color Management</a></li>
287<li><a href="#MACOSX">Adding macOS Features</a></li>
288</ul>
289</div>
290<div class="body">
291<h2 class='title'><a name='BASICS'>Printer Driver Basics</a></h2>
292
293<p>A CUPS PostScript printer driver consists of a PostScript Printer Description (PPD) file that describes the features and capabilities of the device, zero or more <em>filter</em> programs that prepare print data for the device, and zero or more support files for color management, online help, and so forth. The PPD file includes references to all of the filters and support files used by the driver.</p>
294
295<p>Every time a user prints something the scheduler program, <a href='man-cupsd.html'>cupsd(8)</a>, determines the format of the print job and the programs required to convert that job into something the printer understands. CUPS includes filter programs for many common formats, for example to convert Portable Document Format (PDF) files into device-independent PostScript, and then from device-independent PostScript to device-dependent PostScript. <a href='#FIGURE_1'>Figure 1</a> shows the data flow of a typical print job.</p>
296
297<div class='figure'><table summary='PostScript Filter Chain'>
298<caption>Figure 1: <a name='FIGURE_1'>PostScript Filter Chain</a></caption>
299<tr><td><img src='../images/cups-postscript-chain.png' width='700' height='150' alt='PostScript Filter Chain'></td></tr>
300</table></div>
301
302<p>The optional PostScript filter can be provided to add printer-specific commands to the PostScript output that cannot be represented in the PPD file or to reorganize the output for special printer features. Typically this is used to support advanced job management or finishing functions on the printer. CUPS includes a generic PostScript filter that handles all PPD-defined commands.</p>
303
304<p>The optional port monitor handles interface-specific protocol or encoding issues. For example, many PostScript printers support the Binary Communications Protocol (BCP) and Tagged Binary Communications Protocol (TBCP) to allow applications to print 8-bit ("binary") PostScript jobs. CUPS includes port monitors for BCP and TBCP, and you can supply your own port monitors as needed.</p>
305
306<p>The backend handles communications with the printer, sending print data from the last filter to the printer and relaying back-channel data from the printer to the upstream filters. CUPS includes backend programs for common direct-connect interfaces and network protocols, and you can provide your own backend to support custom interfaces and protocols.</p>
307
308<p>The scheduler also supports a special "command" file format for sending maintenance commands and status queries to a printer or printer driver. Command print jobs typically use a single command filter program defined in the PPD file to generate the appropriate printer commands and handle any responses from the printer. <a href='#FIGURE_2'>Figure 2</a> shows the data flow of a typical command job.</p>
309
310<div class='figure'><table summary='Command Filter Chain'>
311<caption>Figure 2: <a name='FIGURE_2'>Command Filter Chain</a></caption>
312<tr><td><img src='../images/cups-command-chain.png' width='575' height='150' alt='Command Filter Chain'></td></tr>
313</table></div>
314
315<p>PostScript printer drivers typically do not require their own command filter since CUPS includes a generic PostScript command filter that supports all of the standard functions using PPD-defined commands.</p>
316
317
318<h2 class='title'><a name='CREATING'>Creating New PPD Files</a></h2>
319
320<p>We recommend using the CUPS PPD compiler, <a href='man-ppdc.html'>ppdc(1)</a>, to create new PPD files since it manages many of the tedious (and error-prone!) details of paper sizes and localization for you. It also allows you to easily support multiple devices from a single source file. For more information see the "<a href='ppd-compiler.html'>Introduction to the PPD Compiler</a>" document. <a href='#LISTING_1'>Listing 1</a> shows a driver information file for a black-and-white PostScript printer.</p>
321
322<p class='example'>Listing 1: <a name='LISTING_1'>"examples/postscript.drv"</a></p>
323
324<pre class='example'>
325// Include standard font and media definitions
326<a href='ref-ppdcfile.html#_include'>#include</a> &lt;font.defs&gt;
327<a href='ref-ppdcfile.html#_include'>#include</a> &lt;media.defs&gt;
328
329// Specify this is a PostScript printer driver
330<a href='ref-ppdcfile.html#DriverType'>DriverType</a> ps
331
332// List the fonts that are supported, in this case all standard fonts
333<a href='ref-ppdcfile.html#Font'>Font</a> *
334
335// Manufacturer, model name, and version
336<a href='ref-ppdcfile.html#Manufacturer'>Manufacturer</a> "Foo"
337<a href='ref-ppdcfile.html#ModelName'>ModelName</a> "Foo LaserProofer 2000"
338<a href='ref-ppdcfile.html#Version'>Version</a> 1.0
339
340// PostScript printer attributes
341<a href='ref-ppdcfile.html#Attribute'>Attribute</a> DefaultColorSpace "" Gray
342<a href='ref-ppdcfile.html#Attribute'>Attribute</a> LandscapeOrientation "" Minus90
343<a href='ref-ppdcfile.html#Attribute'>Attribute</a> LanguageLevel "" "3"
344<a href='ref-ppdcfile.html#Attribute'>Attribute</a> Product "" "(Foo LaserProofer 2000)"
345<a href='ref-ppdcfile.html#Attribute'>Attribute</a> PSVersion "" "(3010) 0"
346<a href='ref-ppdcfile.html#Attribute'>Attribute</a> TTRasterizer "" Type42
347
348// Supported page sizes
349*<a href='ref-ppdcfile.html#MediaSize'>MediaSize</a> Letter
350<a href='ref-ppdcfile.html#MediaSize'>MediaSize</a> Legal
351<a href='ref-ppdcfile.html#MediaSize'>MediaSize</a> A4
352
353// Query command for page size
354<a href='ref-ppdcfile.html#Attribute'>Attribute</a> "?PageSize" "" "
355      save
356      currentpagedevice /PageSize get aload pop
357      2 copy gt {exch} if (Unknown)
358      23 dict
359              dup [612 792] (Letter) put
360              dup [612 1008] (Legal) put
361              dup [595 842] (A4) put
362              {exch aload pop 4 index sub abs 5 le exch
363               5 index sub abs 5 le and
364              {exch pop exit} {pop} ifelse
365      } bind forall = flush pop pop
366      restore"
367
368// Specify the name of the PPD file we want to generate
369<a href='ref-ppdcfile.html#PCFileName'>PCFileName</a> "fooproof.ppd"
370</pre>
371
372<h3>Required Attributes</h3>
373
374<p>PostScript drivers require the attributes listed in <a href='#TABLE_1'>Table 1</a>. If not specified, the defaults for CUPS drivers are used. A typical PostScript driver information file would include the following attributes:</p>
375
376<pre class='example'>
377<a href='ref-ppdcfile.html#Attribute'>Attribute</a> DefaultColorSpace "" Gray
378<a href='ref-ppdcfile.html#Attribute'>Attribute</a> LandscapeOrientation "" Minus90
379<a href='ref-ppdcfile.html#Attribute'>Attribute</a> LanguageLevel "" "3"
380<a href='ref-ppdcfile.html#Attribute'>Attribute</a> Product "" "(Foo LaserProofer 2000)"
381<a href='ref-ppdcfile.html#Attribute'>Attribute</a> PSVersion "" "(3010) 0"
382<a href='ref-ppdcfile.html#Attribute'>Attribute</a> TTRasterizer "" Type42
383</pre>
384
385<div class='table'><table summary='Required PostScript Printer Driver Attributes'>
386<caption>Table 1: <a name='TABLE_1'>Required PostScript Printer Driver Attributes</a></caption>
387<thead>
388<tr>
389	<th>Attribute</th>
390	<th>Description</th>
391</tr>
392</thead>
393<tbody>
394<tr>
395	<td><tt>DefaultColorSpace</tt></td>
396	<td>The default colorspace:
397	<tt>Gray</tt>, <tt>RGB</tt>, <tt>CMY</tt>, or
398	<tt>CMYK</tt>. If not specified, then <tt>RGB</tt> is
399	assumed.</td>
400</tr>
401<tr>
402	<td><tt>LandscapeOrientation</tt></td>
403	<td>The preferred landscape
404	orientation: <tt>Plus90</tt>, <tt>Minus90</tt>, or
405	<tt>Any</tt>. If not specified, <tt>Plus90</tt> is
406	assumed.</td>
407</tr>
408<tr>
409	<td><tt>LanguageLevel</tt></td>
410	<td>The PostScript language
411	level supported by the device: 1, 2, or 3. If not
412	specified, 2 is assumed.</td>
413</tr>
414<tr>
415	<td><tt>Product</tt></td>
416	<td>The string returned by
417	the PostScript <tt>product</tt> operator, which
418	<i>must</i> include parenthesis to conform with
419	PostScript syntax rules for strings. Multiple
420	<tt>Product</tt> attributes may be specified to support
421	multiple products with the same PPD file. If not
422	specified, "(ESP Ghostscript)" and "(GNU Ghostscript)"
423	are assumed.</td>
424</tr>
425<tr>
426	<td><tt>PSVersion</tt></td>
427	<td>The PostScript
428	interpreter version numbers as returned by the
429	<tt>version</tt> and <tt>revision</tt> operators. The
430	required format is "(version) revision". Multiple
431	<tt>PSVersion</tt> attributes may be specified to
432	support multiple interpreter version numbers. If not
433	specified, "(3010) 705" and "(3010) 707" are
434	assumed.</td>
435</tr>
436<tr>
437	<td><tt>TTRasterizer</tt></td>
438	<td>The type of TrueType
439	font rasterizer supported by the device, if any. The
440	supported values are <tt>None</tt>, <tt>Accept68k</tt>,
441	<tt>Type42</tt>, and <tt>TrueImage</tt>. If not
442	specified, <tt>None</tt> is assumed.</td>
443</tr>
444</table></div>
445
446<h3>Query Commands</h3>
447
448<p>Most PostScript printer PPD files include query commands (<tt>?PageSize</tt>, etc.) that allow applications to query the printer for its current settings and configuration. Query commands are included in driver information files as attributes. For example, the example in <a href='#LISTING_1'>Listing 1</a> uses the following definition for the <tt>PageSize</tt> query command:</p>
449
450<pre class='example'>
451<a href='ref-ppdcfile.html#Attribute'>Attribute</a> "?PageSize" "" "
452      save
453      currentpagedevice /PageSize get aload pop
454      2 copy gt {exch} if (Unknown)
455      23 dict
456              dup [612 792] (Letter) put
457              dup [612 1008] (Legal) put
458              dup [595 842] (A4) put
459              {exch aload pop 4 index sub abs 5 le exch
460               5 index sub abs 5 le and
461              {exch pop exit} {pop} ifelse
462      } bind forall = flush pop pop
463      restore"
464</pre>
465
466<p>Query commands can span multiple lines, however no single line may contain more than 255 characters.</p>
467
468<h3><a name='IMPORT'>Importing Existing PPD Files</a></h3>
469
470<P>CUPS includes a utility called <a href='man-ppdi.html'>ppdi(1)</a>
471which allows you to import existing PPD files into the driver information file
472format used by the PPD compiler <a href='man-ppdc.html'>ppdc(1)</a>. Once
473imported, you can modify, localize, and regenerate the PPD files easily. Type
474the following command to import the PPD file <VAR>mydevice.ppd</VAR> into the
475driver information file <VAR>mydevice.drv</VAR>:</P>
476
477<pre class='command'>
478ppdi -o mydevice.drv mydevice.ppd
479</pre>
480
481<P>If you have a whole directory of PPD files that you would like to import,
482you can list multiple filenames or use shell wildcards to import more than one
483PPD file on the command-line:</P>
484
485<pre class='command'>
486ppdi -o mydevice.drv mydevice1.ppd mydevice2.ppd
487ppdi -o mydevice.drv *.ppd
488</pre>
489
490<P>If the driver information file already exists, the new PPD
491file entries are appended to the end of the file. Each PPD file
492is placed in its own group of curly braces within the driver
493information file.</P>
494
495
496<h2 class='title'><a name='FILTERS'>Using Custom Filters</a></h2>
497
498<p>Normally a PostScript printer driver will not utilize any additional print filters. For drivers that provide additional filters such as a CUPS command file filter for doing printer maintenance, you must also list the following <tt>Filter</tt> directive to handle printing PostScript files:</p>
499
500<pre class='example'>
501<a href='ref-ppdcfile.html#Filter'>Filter</a> application/vnd.cups-postscript 0 -
502</pre>
503
504<h3>Custom Command Filters</h3>
505
506<p>The <tt>application/vnd.cups-command</tt> file type is used for CUPS command files. Use the following <tt>Filter</tt> directive to handle CUPS command files:</p>
507
508<pre class='example'>
509<a href='ref-ppdcfile.html#Filter'>Filter</a> application/vnd.cups-command 100 /path/to/command/filter
510</pre>
511
512<p>To use the standard PostScript command filter, specify <var>commandtops</var> as the path to the command filter.</p>
513
514<h3>Custom PDF Filters</h3>
515
516<p>The <tt>application/pdf</tt> file type is used for unfiltered PDF files while the <tt>application/vnd.cups-pdf</tt> file type is used for filtered PDF files. Use the following <tt>Filter</tt> directive to handle filtered PDF files:</p>
517
518<pre class='example'>
519<a href='ref-ppdcfile.html#Filter'>Filter</a> application/vnd.cups-pdf 100 /path/to/pdf/filter
520</pre>
521
522<p>For unfiltered PDF files, use:</p>
523
524<pre class='example'>
525<a href='ref-ppdcfile.html#Filter'>Filter</a> application/pdf 100 /path/to/pdf/filter
526</pre>
527
528<p>Custom PDF filters that accept filtered data do not need to perform number-up processing and other types of page imposition, while those that accept unfiltered data MUST do the number-up processing themselves.</p>
529
530<h3>Custom PostScript Filters</h3>
531
532<p>The <tt>application/vnd.cups-postscript</tt> file type is used for filtered PostScript files. Use the following <tt>Filter</tt> directive to handle PostScript files:</p>
533
534<pre class='example'>
535<a href='ref-ppdcfile.html#Filter'>Filter</a> application/vnd.cups-postscript 100 /path/to/postscript/filter
536</pre>
537
538
539<h2 class='title'><a name='COLOR'>Implementing Color Management</a></h2>
540
541<p>CUPS uses ICC color profiles to provide more accurate color reproduction. The <a href='spec-ppd.html#cupsICCProfile'><tt>cupsICCProfile</tt></a> attribute defines the color profiles that are available for a given printer, for example:</p>
542
543<pre class='example'>
544<a href='ref-ppdcfile.html#Attribute'>Attribute</a> cupsICCProfile "ColorModel.MediaType.Resolution/Description" /path/to/ICC/profile
545</pre>
546
547<p>where "ColorModel.MediaType.Resolution" defines a selector based on the corresponding option selections. A simple driver might only define profiles for the color models that are supported, for example a printer supporting Gray and RGB might use:</p>
548
549<pre class='example'>
550<a href='ref-ppdcfile.html#Attribute'>Attribute</a> cupsICCProfile "Gray../Grayscale Profile" /path/to/ICC/gray-profile
551<a href='ref-ppdcfile.html#Attribute'>Attribute</a> cupsICCProfile "RGB../Full Color Profile" /path/to/ICC/rgb-profile
552</pre>
553
554<p>The options used for profile selection can be customized using the <tt>cupsICCQualifier2</tt> and <tt>cupsICCQualifier3</tt> attributes.</p>
555
556
557<h2 class='title'><a name='MACOSX'>Adding macOS Features</a></h2>
558
559<p>macOS printer drivers can provide <a href='spec-ppd.html#MACOSX'>additional attributes</a> to specify additional option panes in the print dialog, an image of the printer, a help book, and option presets for the driver software:</p>
560
561<pre class='example'>
562<a href='ref-ppdcfile.html#Attribute'>Attribute</a> APDialogExtension "" /Library/Printers/Vendor/filename.plugin
563<a href='ref-ppdcfile.html#Attribute'>Attribute</a> APHelpBook "" /Library/Printers/Vendor/filename.bundle
564<a href='ref-ppdcfile.html#Attribute'>Attribute</a> APPrinterIconPath "" /Library/Printers/Vendor/filename.icns
565<a href='ref-ppdcfile.html#Attribute'>Attribute</a> APPrinterPreset "name/text" "*option choice ..."
566</pre>
567</div>
568</body>
569</html>
570