# 3 - Developing Raster Printer Drivers

This chapter describes how to develop PPD files for the included DDK raster printer drivers.

## The DDK Drivers

The DDK includes two general-purpose raster printer drivers that support the HP-PCL and ESC/P languages. Driver information files based upon these drivers can use a driver-specific include file and the `DriverType` directive.

Both drivers offer color management and dithering capabilities which are described in detail in Chapter 6, Doing Raster Color Management.

## The HP-PCL Driver

The HP-PCL driver includes a printer command filter called `commandtopclx` and a raster printer driver filter called `rastertopclx`. The command filter supports head cleaning, printing a self-test page, and ink cartridge alignment.

Table 3-1, HP-PCL ModelNumber constants
Constant | Description
--- | ---
`PCL_PAPER_SIZE` | Use paper size command (`ESC & l # A`)
`PCL_INKJET` | Use inkjet commands
`PCL_RASTER_END_COLOR` | Use new end-raster command (`ESC * r C`)
`PCL_RASTER_CID` | Use configure-image-data command (`ESC * v # W`)
`PCL_RASTER_CRD` | Use configure-raster-data command (`ESC * g # W`)
`PCL_RASTER_SIMPLE` | Use simple-raster-color command (`ESC * r # U`)
`PCL_RASTER_RGB24` | Use 24-bit RGB mode
`PCL_PJL` | Use PJL commands
`PCL_PJL_PAPERWIDTH` | Use PJL PAPERWIDTH/LENGTH commands
`PCL_PJL_HPGL2` | Use PJL ENTER HPGL2 command
`PCL_PJL_PCL3GUI` | Use PJL ENTER PCL3GUI command
`PCL_PJL_RESOLUTION` | Use PJL SET RESOLUTION command

The raster printer driver filter accepts grayscale, RGB, and CMYK raster data for printing to laser and inkjet devices. It supports PJL commands for device-specific features and uses PCL 3/4/5 raster graphics commands for all laser and some older inkjet printers or the various PCL3GUI and HP-RTL variants that are used by most of the inkjet printers sold by HP. The driver does not support native text rendering due to the limitations of font support in most PCL implementations.

The HP-PCL driver also provides an include file, `<pcl.h>`. Driver information files that use the HP-PCL driver begin with the following:

        #include <font.defs>
        #include <media.defs>
        #include <raster.defs>
        #include <pcl.h>

        DriverType pcl

### ModelNumber Constants

Table 3-1 shows the constants that are defined in the `<pcl.h>` include file. These constants are used with the `ModelNumber` directive to control the behavior of the driver. For example, a typical PCL laser printer would use the following `ModelNumber` specification:

        ModelNumber ($PCL_PAPER_SIZE $PCL_PJL $PCL_PJL_RESOLUTION)

The parenthesis around the PCL constants tell the PPD compiler to compute the bitwise OR of each of the values. The HP-PCL driver will then use this information to tailor the output of the driver for the printer, in this case to use Printer Job Language ("PJL") commands to setup the job, including the PJL resolution command, and to use the PCL 3 paper size command. Table 3-2 shows the constants to use for several common types of HP printers.

### Writing a Basic HP LaserJet Driver

Now that we have covered the HP-PCL driver definitions, we will create a driver for the HP LaserJet 2100, 2200, and 2300 series printers which supports all of the features that are available via PCL 5. While these printers also support PostScript, the interpreters have several known problems with TrueType fonts which can only be bypassed by using the PCL 5 printing path.

All three models support printing at 300 and 600 DPI through PCL 5 graphics; the 1200 DPI resolution is only available through PostScript and PCL 6. Each printer has an optional high-capacity paper tray and the 2200 and 2300 series printers also offer an optional duplexing unit. Listing 3-1 shows the driver information file for a basic HP LaserJet driver which supports the three models.

The file starts with the usual `#include` directives and then sets the driver type and model number so that we use the HP-PCL driver with the output tailored to a HP LaserJet printer:

        // Specify that this driver uses the HP-PCL driver...
        DriverType pcl

        // Specify the driver options via the model number...
        ModelNumber ($PCL_PAPER_SIZE $PCL_PJL $PCL_PJL_RESOLUTION)

Table 3-2, ModelNumber values for common HP printers
Printer Model | ModelNumber Value
--- | ---
HP Color LaserJet Series | `($PCL_PAPER_SIZE $PCL_RASTER_END_COLOR $PCL_RASTER_CID $PCL_RASTER_SIMPLE $PCL_RASTER_RGB24 $PCL_PJL $PCL_PJL_RESOLUTION)`
HP DesignJet, Desktop | `($PCL_PAPER_SIZE $PCL_RASTER_END_COLOR $PCL_RASTER_CRD $PCL_PJL $PCL_PJL_PCL3GUI)`
HP DesignJet, High-End | `($PCL_PAPER_SIZE $PCL_RASTER_END_COLOR $PCL_RASTER_CID $PCL_RASTER_SIMPLE $PCL_RASTER_RGB24 $PCL_PJL $PCL_PJL_PAPERWIDTH $PCL_PJL_HPGL2 $PCL_PJL_RESOLUTION)`
HP DesignJet, Mid-Range | `($PCL_PAPER_SIZE $PCL_RASTER_END_COLOR $PCL_RASTER_CRD $PCL_RASTER_SIMPLE $PCL_RASTER_RGB24 $PCL_PJL $PCL_PJL_PAPERWIDTH $PCL_PJL_PCL3GUI $PCL_PJL_RESOLUTION)`
HP DeskJet Series | `($PCL_PAPER_SIZE $PCL_RASTER_END_COLOR $PCL_RASTER_CRD $PCL_PJL $PCL_PJL_PCL3GUI)`
HP LaserJet Series | `($PCL_PAPER_SIZE $PCL_PJL $PCL_PJL_RESOLUTION)`
HP OfficeJet Series | `($PCL_PAPER_SIZE $PCL_RASTER_END_COLOR $PCL_RASTER_CRD $PCL_PJL $PCL_PJL_PCL3GUI)`
HP Photosmart Series | `($PCL_PAPER_SIZE $PCL_RASTER_END_COLOR $PCL_RASTER_CRD $PCL_PJL $PCL_PJL_PCL3GUI)`

Then we list all of the media sizes that are supported by the printers along with the margins that should be used:

        HWMargins 18 12 18 12
        *MediaSize Letter
        MediaSize Legal
        MediaSize Executive
        MediaSize Monarch
        MediaSize Statement
        MediaSize FanFoldGermanLegal

        HWMargins 18 12.72 18 12.72
        MediaSize Env10

        HWMargins 9.72 12 9.72 12
        MediaSize A4
        MediaSize A5
        MediaSize B5
        MediaSize EnvC5
        MediaSize EnvDL
        MediaSize EnvISOB5
        MediaSize Postcard
        MediaSize DoublePostcard

Next we use the `ColorModel` directive to specify that our driver only prints grayscale output using the black colorspace and PCL mode 3 raster compression:

        ColorModel Gray k chunky 3

These printers support printing at 300 and 600 DPI through HP-PCL 5, so we list those resolutions using the `Resolution` directive. We use 1 bit per color for 300 DPI to provide fast printing and 8 bits per color for 600 DPI to provide the highest quality:

        Resolution - 1 0 0 0 "300dpi/300 DPI"
        *Resolution - 8 0 0 0 "600dpi/600 DPI"

All of the models provide two standard paper trays and one optional tray. The first tray is used as both the multi-purpose and manual feed tray and gets listed twice. We also provide an "auto" tray which tells the printer to grab media from the first available location:

        *InputSlot 7 "Auto/Automatic Selection"
        InputSlot 2 "Manual/Tray 1 - Manual Feed"
        InputSlot 4 "Upper/Tray 1"
        InputSlot 1 "Lower/Tray 2"
        InputSlot 5 "LargeCapacity/Tray 3"

Listing 3-1, "examples/laserjet-basic.drv"

    // Include standard font and media definitions
    #include <font.defs>
    #include <media.defs>

    // Include HP-PCL driver definitions
    #include <pcl.h>

    // Specify that this driver uses the HP-PCL driver...
    DriverType pcl

    // Specify the driver options via the model number...
    ModelNumber ($PCL_PAPER_SIZE $PCL_PJL $PCL_PJL_RESOLUTION)

    // List the fonts that are supported, in this case all
    // standard fonts...
    Font *

    // Manufacturer and driver version
    Manufacturer "HP"
    Version 1.0

    // Supported page sizes and their margins
    HWMargins 18 12 18 12
    *MediaSize Letter
    MediaSize Legal
    MediaSize Executive
    MediaSize Monarch
    MediaSize Statement
    MediaSize FanFoldGermanLegal

    HWMargins 18 12.72 18 12.72
    MediaSize Env10

    HWMargins 9.72 12 9.72 12
    MediaSize A4
    MediaSize A5
    MediaSize B5
    MediaSize EnvC5
    MediaSize EnvDL
    MediaSize EnvISOB5
    MediaSize Postcard
    MediaSize DoublePostcard

    // Only black-and-white output with mode 3 compression...
    ColorModel Gray k chunky 3

    // Supported input slots
    *InputSlot 7 "Auto/Automatic Selection"
    InputSlot 2 "Manual/Tray 1 - Manual Feed"
    InputSlot 4 "Upper/Tray 1"
    InputSlot 1 "Lower/Tray 2"
    InputSlot 5 "LargeCapacity/Tray 3"

Listing 3-1, "examples/laserjet-basic.drv", continued...

    // Supported resolutions
    Resolution - 1 0 0 0 "300dpi/300 DPI"
    *Resolution - 8 0 0 0 "600dpi/600 DPI"

    // Tray 3 is an option...
    Installable "OptionLargeCapacity/Tray 3 Installed"
    UIConstraints "*OptionLargeCapacity False
                   *InputSlot LargeCapacity"

    {
      // HP LaserJet 2100 Series
      Throughput 10
      ModelName "LaserJet 2100 Series"
      PCFileName "hpljt211.ppd"
    }

    {
      // LaserJet 2200 and 2300 series have duplexer option...
      Duplex normal
      Installable "OptionDuplex/Duplexer Installed"
      UIConstraints "*OptionDuplex False *Duplex"

      {
        // HP LaserJet 2200 Series
        Throughput 19
        ModelName "LaserJet 2200 Series"
        PCFileName "hpljt221.ppd"
      }

      {
        // HP LaserJet 2300 Series
        Throughput 25
        ModelName "LaserJet 2300 Series"
        PCFileName "hpljt231.ppd"
      }
    }

The numbers we used for the input slots are the PCL values associated with each tray; consult the HP-PCL Language Reference Manual for a complete list of possible values on all printers.

Since the third tray is an optional accessory, we list an installable option along with a constraint so that users may only select the third tray if it has been installed:

        Installable "OptionLargeCapacity/Tray 3 Installed"
        UIConstraints "*OptionLargeCapacity False *InputSlot LargeCapacity"

By convention, installable options usually begin with the prefix `Option`. Some vendors number the options, e.g. `Option1`, `Option2`, etc., however we have opted to use a more readable name, `OptionLargeCapacity`. Using a textual name also allows you to add additional installable options without renumbering existing options, and makes it easier to validate constraints.

The HP LaserJet 2200 and 2300 series printers also have an optional duplexer, which is listed using the `Duplex` directive along with another installable option and constraint:

        Duplex normal
        Installable "OptionDuplex/Duplexer Installed"
        UIConstraints "*OptionDuplex False *Duplex"

Again, we are using the more readable installable option name `OptionDuplex` instead of `Option2`.

We finish things up by using grouping to isolate the three printer models and provide unique values for the `Throughput`, `ModelName`, and `PCFileName` directives. Notice how we are able to group the duplex option and then share the definition with the 2200 and 2300 drivers:

        {
          // HP LaserJet 2100 Series
          Throughput 10
          ModelName "LaserJet 2100 Series"
          PCFileName "hpljt211.ppd"
        }

        {
          // LaserJet 2200 and 2300 series have duplexer option...
          Duplex normal
          Installable "OptionDuplex/Duplexer Installed"
          UIConstraints "*OptionDuplex False *Duplex"

          {
    	// HP LaserJet 2200 Series
    	Throughput 19
    	ModelName "LaserJet 2200 Series"
    	PCFileName "hpljt221.ppd"
          }

          {
    	// HP LaserJet 2300 Series
    	Throughput 25
    	ModelName "LaserJet 2300 Series"
    	PCFileName "hpljt231.ppd"
          }
        }

To test the new drivers, start by running the `ppdc` program to create the PPD files:

        ppdc laserjet-basic.drv ENTER

Then use the `lpadmin(8)` command to add the printer with the correct device URI. The following example adds a HP LaserJet 2100 which is connected via a JetDirect interface:

        lpadmin -p lj2100 -E -v socket://lj2100 -i ppd/hpljt211.ppd ENTER

Finally, print a test page to see it work:

        lp -d lj2100 /usr/share/cups/data/testprint.ps ENTER

### PJL Attributes

The HP-PCL driver also supports extensive Printer Job Language (PJL) commands through a combination of PPD attributes and options. Table 3-3 lists the PJL attributes that are supported along with the PPD options they map to. PJL attributes are specified using the `Attribute` directive using the `cupsPJL` keyword. For example, the following attribute provides the PJL commands to enable or disable the resolution enhancement features of the printer:

        Attribute cupsPJL cupsRET
                  "@PJL SET SMOOTHING=%?False:OFF;%?True:ON;%n"

The directive, `Attribute`, is followed by the attribute keyword, `cupsPJL`, the attribute name, `cupsRET`, and the attribute value, in this case a PJL command string. The command string consists of PJL command text and special substitution fields starting with the percent (`%`) character.

In the example above, the `%?` substitution conditionally inserts some text if the string matches the option value, typically the name of the choice. In this case, we have two conditional substitutions. The first inserts the text `OFF` if the `cupsRET` option is `False`, and the second inserts the text `ON` if the option is `True`. The syntax is as follows:

        %?look for:insert;

Multiple conditional substitutions can be listed up to about 230 characters - the PPD file format imposed a 255 character line length limit, and attribute values cannot span multiple lines.

Aside from conditional substitutions, the HP-PCL driver supports the following additional substitutions. Unknown substitutions are inserted verbatim:

- `%%` - inserts the percent character (`%`).
- `%b` - inserts the job-billing value for this job.
- `%h` - inserts the job-originating-hostname value for this job.
- `%j` - inserts the job-id value for this job.
- `%n` - inserts the carriage return (ASCII CR or `0D` hex) and linefeed (ASCII LF or `0A` hex) characters.
- `%q` - inserts the double quote character (`"`).
- `%s` - inserts the current option value or choice.
- `%t` - inserts the name/title of this job.
- `%u` - inserts the job-originating-username value for this job.

### Adding PJL Options to the Basic LaserJet Driver

All three HP LaserJet models support additional options via PJL commands. Listing 3-2 shows a modified version of the driver which adds support the resolution enhancement and toner saving features of the printers.

The new resolution enhancement option consists of a PPD attribute containing the `cupsRET` command followed by the `cupsRET` option. Since this option applies to the entire job, the option is placed in the `DocumentSetup` section:

        Attribute cupsPJL cupsRET
                  "@PJL SET SMOOTHING=%?False:OFF;%?True:ON;%n"

        Option "cupsRET/Smoothing" Boolean DocumentSetup 10
          Choice "False/Off" ""
          *Choice "True/On" ""

The toner saving option is added the same way using the `cupsTonerSave` attribute and option:

        Attribute cupsPJL cupsTonerSave
                  "@PJL SET ECONOMODE=%?False:OFF;%?True:ON;%n"

        Option "cupsTonerSave/Save Toner" Boolean DocumentSetup 10
          *Choice "False/No" ""
          Choice "True/Yes" ""

Since we didn't specify a group for these options, they will be put in the `General` option group.

Table 3-3, PJL attributes and options
Attribute | Option | Description
--- | --- | ---
`COLORSPACE. ColorModel` | Varies | Specifies the colorspace to set at the beginning of the job.
`cupsBooklet` | `cupsBooklet` | Specifies the PJL commands to send for setting the booklet printing mode.
`cupsPunch` | `cupsPunch` | Specifies the PJL commands to send for setting the punch mode.
`cupsRET` | `cupsRET` | Specifies the PJL commands to set the resolution enhancement mode.
`cupsStaple` | `cupsStaple` | Specifies the PJL commands to send for setting the stapler mode.
`cupsTonerSave` | `cupsTonerSave` | Specifies the PJL commands to set the toner saving mode.
`Duplex` | `Duplex` | Specifies the PJL commands to send for setting the duplex mode.
`EndJob` | N/A | Specifies the PJL commands to send at the end of a job.
`Jog` | Varies | Specifies the PJL commands to send for setting the output jogging.
`MediaClass` | Varies | Specifies the PJL commands to send for setting the media class.
`MediaColor` | Varies | Specifies the PJL commands to send for setting the media color.
`MediaType` | `MediaType` | Specifies the PJL commands to send for setting the media type.
`OutputType` | Varies | Specifies the PJL commands to send for setting the output type.
`RENDERINTENT. ColorModel` | Varies | Specifies the rendering intent to set at the beginning of the job.
`RENDERMODE. ColorModel` | Varies | Specifies the render mode to set at the beginning of the job.

Table 3-3, PJL attributes and options, continued...
Attribute | Option | Description
--- | --- | ---
`StartJob` | N/A | Specifies the PJL commands to send at the beginning of a job.
`Tumble` | `Duplex` | Specifies the PJL commands to send for setting the duplex tumble mode.

To test the new drivers, start by running the `ppdc` program to create the PPD files:

        ppdc laserjet-pjl.drv ENTER

Then use the `lpadmin(8)` command to add the printer with the correct device URI. The following example adds a HP LaserJet 2100 which is connected via a JetDirect interface:

        lpadmin -p lj2100 -E -v socket://lj2100 -i ppd/hpljt212.ppd ENTER

Finally, print a test page to see it work:

        lp -d lj2100 -o cupsTonerSave=True \
           /usr/share/cups/data/testprint.ps ENTER

Listing 3-2, "examples/laserjet-pjl.drv"

    // Include standard font and media definitions
    #include <font.defs>
    #include <media.defs>

    // Include HP-PCL driver definitions
    #include <pcl.h>

    // Specify that this driver uses the HP-PCL driver...
    DriverType pcl

    // Specify the driver options via the model number...
    ModelNumber ($PCL_PAPER_SIZE $PCL_PJL $PCL_PJL_RESOLUTION)

    // List the fonts that are supported, in this case all
    // standard fonts...
    Font *

    // Manufacturer and driver version
    Manufacturer "HP"
    Version 2.0

    // Supported page sizes and their margins
    HWMargins 18 12 18 12
    *MediaSize Letter
    MediaSize Legal
    MediaSize Executive
    MediaSize Monarch
    MediaSize Statement
    MediaSize FanFoldGermanLegal

    HWMargins 18 12.72 18 12.72
    MediaSize Env10

    HWMargins 9.72 12 9.72 12
    MediaSize A4
    MediaSize A5
    MediaSize B5
    MediaSize EnvC5
    MediaSize EnvDL
    MediaSize EnvISOB5
    MediaSize Postcard
    MediaSize DoublePostcard

    // Only black-and-white output with mode 3 compression...
    ColorModel Gray k chunky 3

    // Supported input slots
    *InputSlot 7 "Auto/Automatic Selection"
    InputSlot 2 "Manual/Tray 1 - Manual Feed"
    InputSlot 4 "Upper/Tray 1"
    InputSlot 1 "Lower/Tray 2"
    InputSlot 5 "LargeCapacity/Tray 3"

Listing 3-2, "examples/laserjet-pjl.drv", continued...

    // Supported resolutions
    Resolution - 1 0 0 0 "300dpi/300 DPI"
    *Resolution - 8 0 0 0 "600dpi/600 DPI"

    // Tray 3 is an option...
    Installable "OptionLargeCapacity/Tray 3 Installed"
    UIConstraints "*OptionLargeCapacity False
                   *InputSlot LargeCapacity"

    // PJL options
    Attribute cupsPJL cupsRET
              "@PJL SET SMOOTHING=%?False:OFF;%?True:ON;%n"

    Option "cupsRET/Smoothing" Boolean DocumentSetup 10
      Choice "False/Off" ""
      *Choice "True/On" ""

    Attribute cupsPJL cupsTonerSave
              "@PJL SET ECONOMODE=%?False:OFF;%?True:ON;%n"

    Option "cupsTonerSave/Save Toner" Boolean DocumentSetup 10
      *Choice "False/No" ""
      Choice "True/Yes" ""

    {
      // HP LaserJet 2100 Series
      Throughput 10
      ModelName "LaserJet 2100 Series PJL"
      PCFileName "hpljt212.ppd"
    }

    {
      // LaserJet 2200 and 2300 series have duplexer option...
      Duplex normal
      Installable "OptionDuplex/Duplexer Installed"
      UIConstraints "*OptionDuplex False *Duplex"

      {
        // HP LaserJet 2200 Series
        Throughput 19
        ModelName "LaserJet 2200 Series PJL"
        PCFileName "hpljt222.ppd"
      }

      {
        // HP LaserJet 2300 Series
        Throughput 25
        ModelName "LaserJet 2300 Series PJL"
        PCFileName "hpljt232.ppd"
      }
    }

## The ESC/P Driver

The ESC/P driver includes a printer command filter called `commandtoescpx` and a raster printer driver filter called `rastertoescpx`. The command filter supports head cleaning, printing a self-test page, and ink cartridge alignment.

The raster printer driver filter accepts grayscale, RGB, and CMYK raster data for printing to inkjet devices. It supports EJL commands for device-specific features and uses the appropriate ESC/P2 raster graphics commands for all inkjet printers sold by Epson. The driver does not support native text rendering due to the limitations of text support in most ESC/P implementations.

The ESC/P driver also provides an include file, `<escp.h>`. Driver information files that use the ESC/P driver begin with the following:

        #include <font.defs>
        #include <media.defs>
        #include <raster.defs>
        #include <escp.h>

        DriverType escp

### ModelNumber Constants

Table 3-4 shows the constants that are defined in the `<escp.h>` include file. These constants are used with the `ModelNumber` directive to control the behavior of the driver. For example, a typical Epson Stylus Color printer would use the following `ModelNumber` specification:

        ModelNumber ($ESCP_MICROWEAVE $ESCP_USB $ESCP_REMOTE)

The parenthesis around the ESCP constants tell the PPD compiler to compute the bitwise OR of each of the values. The ESC/P driver will then use this information to tailor the output of the driver for the printer, in this case to use the printer's built-in microweaving (a way of printing using multiple passes), send the USB packet mode escape sequence, and to use remote mode commands. Table 3-5 shows the constants to use for several common types of Epson printers.

### Writing a Basic Epson Stylus Photo R300 Driver

Now that we have covered the ESC/P driver definitions, we will create a driver for the popular Epson Stylus Photo R300 series printers. These printers offer 6-color, full-bleed printing at up to 5760x1440 DPI and can print on recordable CDs and DVDs as well as standard printer media.

Table 3-4, ESC/P ModelNumber constants
Constant | Description
--- | ---
`ESCP_MICROWEAVE` | Use microweave command?
`ESCP_STAGGER` | Are color jets staggered?
`ESCP_ESCK` | Use print mode command?
`ESCP_EXT_UNITS` | Use extended unit commands?
`ESCP_EXT_MARGINS` | Use extended margin command?
`ESCP_USB` | Send USB packet mode escape
`ESCP_PAGE_SIZE` | Use page size command
`ESCP_RASTER_ESCI` | Use `ESC i` graphics command
`ESCP_REMOTE` | Use remote mode commands

Table 3-5, ModelNumber values for common Epson printers
Printer Model | ModelNumber Value
--- | ---
Epson Stylus Color | `($ESCP_MICROWEAVE $ESCP_USB $ESCP_REMOTE)`
Epson Stylus C-Series | `($ESCP_STAGGER $ESCP_USB $ESCP_REMOTE)`
Epson Stylus Photo | `($ESCP_MICROWEAVE $ESCP_ESCK $ESCP_USB $ESCP_REMOTE)`
Epson Stylus Pro | `($ESCP_MICROWEAVE $ESCP_EXT_UNITS $ESCP_EXT_MARGINS $ESCP_PAGE_SIZE $ESCP_REMOTE)`

Our first cut of the driver will support printing at up to 1440 DPI. We'll add the full-bleed printing support in the next section. Listing 3-3 shows the driver information file for a basic Epson Stylus Photo R300 driver.

The file starts with the usual `#include` directives and then sets the driver type and model number so that we use the ESC/P driver with the output tailored to the R300:

        // Specify that this driver uses the ESC/P driver...
        DriverType escp

        // Specify the driver options via the model number...
        ModelNumber ($ESCP_ESCK $ESCP_EXT_UNITS $ESCP_EXT_MARGINS $ESCP_USB
            	 $ESCP_PAGE_SIZE $ESCP_RASTER_ESCI)

Then we list all of the media sizes that are supported by the printers along with the margins that should be used:

        HWMargins 8.4 0 8.4 0
        *MediaSize Letter
        MediaSize Legal
        MediaSize Executive
        MediaSize Statement
        MediaSize A4
        MediaSize A5
        MediaSize A6
        MediaSize B5
        MediaSize Env10
        MediaSize EnvC5
        MediaSize EnvDL
        MediaSize EnvISOB5
        MediaSize Postcard
        MediaSize DoublePostcard

The R300 supports custom page sizes up to 44 inches (1.1m) in length. We use the `VariablePaperSize` directive to instruct the PPD compiler to include the custom page size attributes, and the `MinSize` and `MaxSize` directives to specify the range of sizes that are supported:

        VariablePaperSize Yes
        MinSize 1in 4in
        MaxSize 8.5in 44in

The R300 driver also supports four color modes: Grayscale (colorspace = w), Black (colorspace = k), RGB (colorspace = rgb), and CMYK (colorspace = cmyk). The Grayscale and RGB modes provide color/gamma-corrected output while the Black and CMYK modes offer uncorrected color printing. The `ColorModel` directive tells the PPD compiler to include each of these modes:

        ColorModel Gray/Grayscale w chunky 1
        ColorModel Black k chunky 1
        *ColorModel RGB/Color rgb chunky 1
        ColorModel CMYK cmyk chunky 1

The driver provides printing at 360, 720, and 1440 DPI using the `Resolution` directives. Each resolution makes use of the bits per color, row count, and row step values:

        Resolution - 8 90 0 103 "360dpi/360 DPI"
        *Resolution - 8 90 0 206 "720dpi/720 DPI"
        Resolution - 8 90 0 412 "1440dpi/1440 DPI"

Listing 3-3, "examples/r300-basic.drv"

    // Include standard font and media definitions
    #include <font.defs>
    #include <media.defs>

    // Include ESC/P driver definitions
    #include <escp.h>

    // Specify that this driver uses the ESC/P driver...
    DriverType escp

    // Specify the driver options via the model number...
    ModelNumber ($ESCP_ESCK $ESCP_EXT_UNITS $ESCP_EXT_MARGINS
                 $ESCP_USB $ESCP_PAGE_SIZE $ESCP_RASTER_ESCI)

    // List the fonts that are supported, in this case all
    // standard fonts...
    Font *

    // Manufacturer and driver version
    Manufacturer "Epson"
    Version 1.0

    // Supported page sizes and their margins
    HWMargins 8.4 0 8.4 0
    *MediaSize Letter
    MediaSize Legal
    MediaSize Executive
    MediaSize Statement
    MediaSize A4
    MediaSize A5
    MediaSize A6
    MediaSize B5
    MediaSize Env10
    MediaSize EnvC5
    MediaSize EnvDL
    MediaSize EnvISOB5
    MediaSize Postcard
    MediaSize DoublePostcard

    VariablePaperSize Yes
    MinSize 1in 4in
    MaxSize 8.5in 44in

    // Four color modes are supported...
    ColorModel Gray/Grayscale w chunky 1
    ColorModel Black k chunky 1
    *ColorModel RGB/Color rgb chunky 1
    ColorModel CMYK cmyk chunky 1

    // Supported resolutions
    Resolution - 8 90 0 103 "360dpi/360 DPI"
    *Resolution - 8 90 0 206 "720dpi/720 DPI"
    Resolution - 8 90 0 412 "1440dpi/1440 DPI"

Listing 3-3, "examples/r300-basic.drv" continued...

    // Very basic dithering settings
    Attribute cupsInkChannels "" 6
    Attribute cupsInkLimit "" 2.0

    Attribute cupsCyanLtDk "" "0.5 1.0"
    Attribute cupsMagentaLtDk "" "0.5 1.0"

    Attribute cupsAllDither 360dpi "0.5 0.75 1.0"
    Attribute cupsAllDither 720dpi "0.6 0.9 1.2"
    Attribute cupsAllDither 1440dpi "0.9 1.35"

    Attribute cupsESCPDotSize 360dpi 16
    Attribute cupsESCPDotSize 720dpi 17
    Attribute cupsESCPDotSize 1440dpi 18

    {
      // EPSON Stylus Photo R300 Series
      Throughput 1
      ModelName "Epson Stylus Photo R300"
      PCFileName "epspr301.ppd"
    }

The R300 has 90 nozzles per color spaced at 120 DPI vertically; the head controller can print 360 DPI horizontally. The row count value is the same as the nozzle count, 90. The row step values require a small amount of calculation; each value is computed using the following formula:

        row-step = 100 * x-dpi / 360 + y-dpi / 120

For 360x360 DPI, the row step is therefore:

        row-step = 100 * x-dpi / 360 + y-dpi / 120
                 = 100 * 360 / 360 + 360 / 120
                 = 100 * 1 + 3
    	     = 100 + 3
    	     = 103

The 720 and 1440 DPI resolutions are computed similarly, and it is possible to support any multiple of the base resolution, 360x120 DPI, up to the physical limit of the printer controller, 5760x1440 DPI.

The R300 driver also needs some additional attributes defined to control the amount and kind of ink that is printed on the page. The first attribute we need to define is `cupsInkChannels` which tells the driver how many colors are used by the printer. In this case, the R300 is a 6-color printer:

        Attribute cupsInkChannels "" 6

Next we want to limit the amount of ink that is put on the page to 200%. The `cupsInkLimit` attribute specifies this value:

        Attribute cupsInkLimit "" 2.0

Since the R300 uses light versions of cyan and magenta, we need to tell the driver when to use the light ink and when to use the dark ink. The simplest attributes for this specify the transition range as two numbers from 0 to 1. We'll transition from 0.5 to 1.0 for both colors:

        Attribute cupsCyanLtDk "" "0.5 1.0"
        Attribute cupsMagentaLtDk "" "0.5 1.0"

Next, we want to specify the ink density for the dots that the R300 can produce for each resolution using the `cupsAllDither` attribute. Each number represents a percentage of ink, so a value of 1.0 means 100% coverage for each dot and a value of 2.0 means 200% coverage for each dot. The driver uses this information to reduce the amount of ink that is put on the page for each individual color. Since the R300 supports three different dot sizes, we include three numbers for the 360 and 720 DPI modes, however at 1440 DPI the largest dot size is not needed:

        Attribute cupsAllDither 360dpi "0.5 0.75 1.0"
        Attribute cupsAllDither 720dpi "0.6 0.9 1.2"
        Attribute cupsAllDither 1440dpi "0.9 1.35"

Finally, we tell the driver which dot sizes to use for each resolution using the `cupsESCPDotSize` attribute. These values are defined in the corresponding developer reference manual from Epson. For the R300, size 16 represents the largest variable size dots and size 18 the smallest:

        Attribute cupsESCPDotSize 360dpi 16
        Attribute cupsESCPDotSize 720dpi 17
        Attribute cupsESCPDotSize 1440dpi 18

To test the new drivers, start by running the `ppdc` program to create the PPD files:

        ppdc r300-basic.drv ENTER

Then use the `lpadmin(8)` command to add the printer with the correct device URI. The following example adds a R300 which is connected via a USB port:

        lpadmin -p r300 -E -v 'usb://EPSON/Stylus%20Photo%20R300' -i \
               ppd/epspr301.ppd ENTER

Finally, print a test page to see it work:

        lp -d r300 /usr/share/cups/data/testprint.ps ENTER

### Epson Remote Mode Attributes

Most Epson inkjet printers support a special "remote" mode which allows you to control things such as the paper cutter, media type, drying time, and so forth. Remote mode also allows you to query the current ink status from the printer, clean the print heads, etc., and that functionality is supported via the `commandtoescpx` filter.

Remote mode support is specified using the `ESCP_REMOTE` model number constant. If remote mode is enabled, the `rastertoescpx` driver will look for several attributes to determine which remote mode commands to send and with what values. Table 3-6 lists the remote mode attributes and their values.

Typically, each attribute maps from a single, integer value from the page device dictionary to a single integer value which is used for the corresponding remote mode command. The only exception to this rule is the `cupsESCPPP` attribute which maps the `MediaPosition` value to two integer values for the "PP" (paper path) remote mode command, for example:

        Attribute cupsESCPPP 0 "1 255"

The integer values used for all remote mode commands are documented in the corresponding Epson programming guide for your printer.

### Adding Remote Mode Commands to the R300 Driver

The R300 supports several remote mode commands that we can use. We will add support for full-bleed printing and specification of the media source. Listing 3-4 shows the updated driver information file. We'll start by adding the `ESCP_REMOTE` constant to the model number definition:

        ModelNumber ($ESCP_ESCK $ESCP_EXT_UNITS $ESCP_EXT_MARGINS $ESCP_USB
                     $ESCP_PAGE_SIZE $ESCP_RASTER_ESCI $ESCP_REMOTE)

Next we add the horizontal offset attribute, `cupsESCPFP`, that is used to offset the page for full-bleed printing:

        Attribute cupsESCPFP "" -80

Finally, we add `InputSlot` definitions for automatic and manual feed printing, and `cupsESCPPP` attributes for each `MediaPosition` value:

        *InputSlot 0 "Auto/Auto Select"
        InputSlot 1 "Manual/Manual Feed"

        Attribute cupsESCPPP 0 "1 255"
        Attribute cupsESCPPP 1 "2 1"

Table 3-6, Epson remote mode attributes
Attribute | Description
--- | ---
`cupsESCPAC` | Enables/disables the cutter based upon the `CutMedia` value
`cupsESCPCO` | Enables/disables the cutter based upon the `CutMedia` value
`cupsESCPEX` | Sets the media position based upon the `MediaPosition` value
`cupsESCPFP` | Sets the full-bleed horizontal position offset
`cupsESCPMS` | Sets the media size based upon the `MediaPosition` and `PageSize` values
`cupsESCPMT` | Sets the media type based upon the `cupsMediaType` value
`cupsESCPPC` | Sets paper checking based upon the `MediaPosition` value
`cupsESCPPH` | Sets the paper thickness based upon the `cupsMediaType` value
`cupsESCPPP` | Sets the paper path based upon the `MediaPosition` value
`cupsESCPSN0` | Sets the feed sequence based upon the `cupsMediaType` value
`cupsESCPSN1` | Sets the platten gap based upon the `cupsMediaType` value
`cupsESCPSN2` | Sets the paper feed/eject sequence based upon the `cupsMediaType` value
`cupsESCPSN6` | Sets the eject delay based upon the `cupsMediaType` value
`cupsESCPSN80` | Sets the cutting method based upon the `CutMedia` value
`cupsESCPSN81` | Sets the cutting pressure based upon the `CutMedia` value

To test the new drivers, start by running the `ppdc` program to create the PPD files:

        ppdc r300-remote.drv ENTER

Then use the `lpadmin(8)` command to add the printer with the correct device URI. The following example adds a R300 which is connected via a USB port:

        lpadmin -p r300 -E -v 'usb://EPSON/Stylus%20Photo%20R300' \
            -i ppd/epspr302.ppd ENTER

Finally, print a test page to see it work:

        lp -d r300 /usr/share/cups/data/testprint.ps ENTER

Listing 3-4, "examples/r300-remote.drv"

    // Include standard font and media definitions
    #include <font.defs>
    #include <media.defs>

    // Include ESC/P driver definitions
    #include <escp.h>

    // Specify that this driver uses the ESC/P driver...
    DriverType escp

    // Specify the driver options via the model number...
    ModelNumber ($ESCP_ESCK $ESCP_EXT_UNITS $ESCP_EXT_MARGINS
                 $ESCP_USB $ESCP_PAGE_SIZE $ESCP_RASTER_ESCI
                 $ESCP_REMOTE)

    // List the fonts that are supported, in this case all
    // standard fonts...
    Font *

    // Manufacturer and driver version
    Manufacturer "Epson"
    Version 2.0

    // Supported page sizes and their margins
    HWMargins 0 0 0 0
    *MediaSize Letter
    MediaSize Legal
    MediaSize Executive
    MediaSize Statement
    MediaSize A4
    MediaSize A5
    MediaSize A6
    MediaSize B5
    MediaSize Env10
    MediaSize EnvC5
    MediaSize EnvDL
    MediaSize EnvISOB5
    MediaSize Postcard
    MediaSize DoublePostcard

Listing 3-4, "examples/r300-remote.drv" continued...

    VariablePaperSize Yes
    MinSize 1in 4in
    MaxSize 8.5in 44in

    // Borderless printing offset...
    Attribute cupsESCPFP "" -80

    // Four color modes are supported...
    ColorModel Gray/Grayscale w chunky 1
    ColorModel Black k chunky 1
    *ColorModel RGB/Color rgb chunky 1
    ColorModel CMYK cmyk chunky 1

    // Supported resolutions
    Resolution - 8 90 0 103 "360dpi/360 DPI"
    *Resolution - 8 90 0 206 "720dpi/720 DPI"
    Resolution - 8 90 0 412 "1440dpi/1440 DPI"

    // Paper trays...
    *InputSlot 0 "Auto/Auto Select"
    InputSlot 1 "Manual/Manual Feed"

    Attribute cupsESCPPP 0 "1 255"
    Attribute cupsESCPPP 1 "2 1"

    // Very basic dithering settings
    Attribute cupsInkChannels "" 6
    Attribute cupsInkLimit "" 2.0

    Attribute cupsCyanLtDk "" "0.5 1.0"
    Attribute cupsMagentaLtDk "" "0.5 1.0"

    Attribute cupsAllDither 360dpi "0.5 0.75 1.0"
    Attribute cupsAllDither 720dpi "0.6 0.9 1.2"
    Attribute cupsAllDither 1440dpi "0.9 1.35"

    Attribute cupsESCPDotSize 360dpi 16
    Attribute cupsESCPDotSize 720dpi 17
    Attribute cupsESCPDotSize 1440dpi 18

    {
      // EPSON Stylus Photo R300 Series
      Throughput 1
      ModelName "Epson Stylus Photo R300"
      PCFileName "epspr302.ppd"
    }