IBM Omni Driver


IBM Omni driver
Copyright (c) © International Business Machines Corp., 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.

Table of Contents

Part 1: Introducing the Omni driver

The Omni driver for Linux printers uses the Ghostscript framework and can support over 500 raster, inkjet, and impact devices, including: Canon, Brother, Epson, HP, IBM, Lexmark, Okidata, Olivetti, Panasonic, Seiko, Star, and Xerox. Current support includes over 200 devices, primarily from Epson and Brother. For specifics, see IBM Linux Technology Center : OMNI Printer Driver Model for Linux.

The Omni base supports legacy devices still used by customers:

  • Contains accurate information on device features -- printable area, color corrections, resolutions, forms, trays
  • Provides information to the community -- printer languages, commands, device capabilities

The Omni print driver uses an easily extensible device support model characterized by:

  • Subclassable features
  • XML device description files
  • Job property interface
  • Dynamically loadable drivers

Subclassable Features

Using a schema for building devices based on previous device features allows for exploitation of new features without the duplication of common code. This provides the ability to install code for unique options and test separate components, reducing time to create drivers. Subclassable features also results in smaller drivers.

Below is a diagram of the Epson Stylus 760 schema.

Device-Epson Stylus 760
Epson High Res ESCP2 Commands Epson Stylus Color 660 Resolutions Epson DLQ-3000+ PrintModes Epson Stylus 200 Trays
Epson Stylus 660 Forms Epson Stylus 200 Medias Epson Stylus 660 Connections Epson Stylus 760 Gammas
Epson High Res Instance Epson High ESCP2 Blitter

XML Device Descriptions

XML-tagged device descriptions are easily edited. This facilitates creating and modifying descriptions, as well as reuse of existing descriptions. Device data is separate from the driver code.

XML Device Description

Dynamically Loadable Drivers

Omni is the first Ghostscript driver to enable dynamic loading. Once the initial patch is applied to Ghostscript, printer drivers install easily without recompiling Ghostscript.

The completely data-driven (postscript PPD) model does not work for all devices.

Ghostscript parameters used to load the device driver are:

-sDEVICE=OMNI -sDeviceName=Epson_Stylus_Color_760

Dynamic loading

Job Properties

Linux has multiple drivers, driver types, and rendering engines with no single defined interface for querying and setting job options. OMNI uses a Job Properties interface to query job options that can be set on a per-job basis. This simplifies configuration by providing an interface which can be queried by a setup program or presented to a user with print time dialogs.

Omni job properties interface

Part 2: Understanding the Interface

The following sections explain how the Omni driver loads and how devices are dynamically created using the Ghostscript interface.

Invoking Ghostscript With No Properties

When invoking Ghostscript, you can accept the default options for the device selected by not entering properties on the command line. A typical command line will look similar to:

./gs -sDEVICE=omni -sDeviceName=Epson_Stylus_Color_760-sOutputFile=temp.out input.ps

The above command line will invoke the driver with its default job properties in the device.xml file described in Part 4: Steps To Create A Device.

Invoking Ghostscript With Specified Properties

When invoking Ghostscript you can also provide properties that are not defaults for the device. This is done by providing a properties command line option, formatted as follows:

-sproperties"...options..."

This will force the driver to configure to the specified properties, provided they are valid for the printer.

For example:

-sproperties="media=MEDIA_SPECIAL_360 resolution=RESOLUTION_1440_X_720"

This will force the printer into a mode to use a special paper type along with switching the driver and Ghostscript into creating 1440 X 720 dpi output.

Other options are available for each of the devices. Please refer to the "Omni.readme.1st" document for how to acquire the available properties for each.

Setting Internal Ghostscript Attributes

Since Ghostscript allows for the retrieval and setting of attributes for a job, Omni properties are passed in the SetupDevice routine inside gomni.c. This enables loading the core Omni libraries and setting up hook pointers to the specific Omni routines for handling specific functions.

After loading the core Omni library, properties are retrieved and set within Ghostscript. Retrieval occurs before creating the specific printer device by calling CreateDevice and before setting up Ghostscript for page/resolution information.

Creating the Device

When creating the device, the user defined options that were set on the command line (if any) are passed into the CreateDevice function. The driver function, in this example Epson_Stylus_Color_760, accepts the input parameters and creates a device based on those options.

Once the driver has been created, you can now call back to the loaded library and get the specific values needed to have Ghostscript properly render your output page. This is done by asking the driver for the current resolution (GetResolutionInfo), page area, and page margins (GetMarginInfo). Lastly the call to GetMarginInfo allows you to know the number of lines that are needed to make a complete pass for the head on your printer. This value is set up in fScanDots, which is what Omni bases its banding information on.

Printer Specific Data -- Color Output

Once the job interface starts receiving data from Ghostscript, the job interface calls the Omni driver with bands of data to assemble the page. The optimal band size is found based on memory constraints and the number of lines that comprise a head pass, previously stated as the fScanDots.

The page data (rgb lines) inside the Omni driver are then mapped to either CMY (three colors), CMYK (four colors), or CcMmYK (six colors). These lines are dithered/diffused to provide the requested quality of output requested by the user. There are multiple routines inside the core Omni code to do different dithers.

When the lines of data have been converted and diffused to the proper values, the data is either sent to file or sent to the output device.

Printer Specific Data -- Mono Output

In the case of mono output, the path is very similar to that for color output, although the output is generated inside of the mono dither code. Once the mono output has been created, the job interface then sends the finished lines to the Omni driver to be either modified slightly for the specific device or passed through to the printer.

Part 3: Plugging Into Omni Architecture

There are several ways that the Omni driver architecture can be used to provide enhanced or specific functions based on user preferences.

Creating a standard device

A standard device that needs little modification can be created as described in Part 4: Steps To Create A Device. The current device.xml file can be duplicated and modified to change the name and include files that will define the device function. Typically this function will be limited to creating slight variations of the original device.

For a new gamma file: The xxx Gammas.xml can be copied and the new file altered to include the various changes to modify the output of the added device. The color gamma values can be raised or lowered to decrease or increase, respectively, the amount of ink flow to the page.

For new form sizes: The xxx Forms.xml file can be added to correctly position the actual printable area. A test program provided will print using your new margins, to validate correct values are set. If values are not correct, you can modify the margins to correctly fit that printer with some trial and error. Also, any additional form sizes for the newly created device need to be added to this file along with their associated margins.

Replacing the Instance Information

The instance file, such as Epson High Res ESCP2 Instance.cpp, holds the initialization code for the printer. Whatever the setup and page configuration is for the printer, it should be specified here and the correct commands sent to the printer.

Replacing the Core Blitter

The blitter that actually formats data and sends it down to the printer can be replaced.

In the blitter are the routines that work with the RGB scan line values that have been provided by Ghostscript and are to be sent to the dither routines in GplDitherInstance.cpp for RGB to CMY conversion.

With the conversion to CMY(K) completed, the output to the device can be managed by the blitter. Due to the nature of the output device, some printers will need a fair amount of management. In these cases the original banding algorithms will have to be modified to send the data to the device in the order that is needed.

Adding to the dithering code

Since the current core of the Omni code is similar to textbook algorithms, many people have been able to come up with modifications to or variations of different algorithms that can yield very high quality output. At this point in time, IBM recommends that you do not replace the GplDitherInstance.cpp code. Instead, add in the correct IDs and code to setup and provide your custom dither support. It would be cumbersome to debug any setup or configuration for any of the dithering routines contained in Omni.

Part 4: Steps to Create a Device

The following sections are steps required to create a device for use with the Omni Interface. The steps are as follows:

Step 1: Determine and edit the build layout

Drivers have separate subdirectories. The list of devices for a driver is contained in a file called "Device List". The naming convention used is the name that the driver reports as its driver name followed by the device name. Spaces are used for the real files. These are converted to underscores in the generated files.

$ ls -l "Epson/Epson LQ-2550"
-rw-rw-r--   1 nobody nobody     1160 Jul 13 13:35 Epson/Epson LQ-2550

Step 2: Create an XML file defining the device capabilities

The format for the device capabilities file is as follows.

 1: <?xml version="1.0" encoding="UTF-8" ?>
 2: <!DOCTYPE Device SYSTEM "../OmniDevice.dtd">
 3: <Device name="Epson LQ-2550">
 4:    <DriverName>Epson</DriverName>
 5:    <Capability type="COLOR"/>
 6:    <Capability type="MONOCHROME"/>
 7:    <Capability type="MIRROR"/>
 8:    <RasterCapabilities type="TOP_TO_BOTTOM"/>
 9:    <PDL level="PDL_Epson" sublevel="LEVEL_ESC" major="1" minor="0"/>
10:    <Uses>Brother HJ-100i Commands.xml</Uses>
11:    <Has>Citizen PN60 Resolutions.xml</Has>
12:    <Has>Brother M-1824L Color PrintModes.xml</Has>
13:    <Has>Brother HJ-100i Trays.xml</Has>
14:    <Has>Epson LQ-2550 Forms.xml</Has>
15:    <Has>Brother HJ-100i Medias.xml</Has>
16:    <Has>Brother HJ-100i Connections.xml</Has>
17:    <Has>Epson LQ-2550 Gammas.xml</Has>
18:    <Instance>Epson ESC Instance.hpp</Instance>
19:    <Instance>Epson ESC Instance.cpp</Instance>
20:    <Blitter>Epson ESC Blitter.hpp</Blitter>
21:    <Blitter>Epson ESC Blitter.cpp</Blitter>
22:    <DefaultJobProperties>
23:       <orientation>ORIENTATION_PORTRAIT</orientation>
24:       <form>FORM_LETTER</form>
25:       <tray>TRAY_REAR_CONTINUOUS</tray>
26:       <media>MEDIA_PLAIN</media>
27:       <resolution>RESOLUTION_180_X_180</resolution>
28:       <dither>DITHER_STUCKI_DIFFUSION</dither>
29:       <printmode>PRINT_MODE_24_BLACK_COLOR</printmode>
30:    </DefaultJobProperties>
31: </Device>

Where:

Line 3 -- specifies the root type of the data in this file. Valid choices are:

  • Device
  • DeviceCommands
  • DeviceConnections
  • DeviceForms
  • DeviceGammaTable
  • DeviceMedias
  • DeviceOptions
  • DevicePrintModes
  • DeviceResolutions
  • DeviceTrays
The required attribute name is the device name.

Line 4 -- specifies the name of the driver named in line 1.

Line 5 -- specifies capabilities for the device. They are used in C++ code by including Capability.hpp.

For example:

if (hasCapability (Capability::MIRROR))
{
}

You can use these in the device blitter and instance code. However, these capabilities are intended for application inquiries.

For example:

if (pDevice->hasCapability (Capability::MIRROR))
{
}

Line 8 -- specifies the raster capabilities for the device.

Line 9 -- specifies the Page Description Language for the specific printer. The required attributes are as follows:

  • Level -- General category of the device
  • Sublevel -- Subcategory of the device
  • Major -- Major revision code
  • Minor -- Minor revision code

Line 10 -- specifies the command set contained in the printer.
Note: You can use either the Uses or Has keyword.

Line 11 -- specifies the resolutions that the printer supports.

Line 12 -- specifies the print modes that the printer supports.

Line 13 -- specifies the trays that the printer supports.

Line 14 -- specifies the forms that the printer supports.

Line 15 -- specifies the medias that the printer supports.

Line 16 -- specifies the connections that the printer supports.

Line 17 -- specifies the gamma corrections for a printer.

Lines 18 and 19 -- point to the instance code for this device. These are pure C++ files and are copied verbatim and then compiled.
Note: In the future, this will be a script language instead of C++.

Lines 20 and 21 -- point to the blitter code for this device. These are pure C++ files and are copied verbatim and then compiled.
Note: In the future, this will be a script language instead of C++.

Line 22 -- starts a structure that describes the default job properties for a device. There are two ways to create the device in C++. One is to pass in the job properties as arguments. The other is using the properties specified on lines 23 through 29.

Line 23 -- specifies orientation.
Note: all of the following ids must be defined in the previous tables.

Line 24 -- specifies form id.

Line 25 -- specifies tray id.

Line 26 -- specifies media id.

Line 27 -- specifies resolution id.

Line 28 -- specifies dithering id.

Line 29 -- specifies print mode id.

Line 30 -- specifies end of the structure.

Line 31 -- specifies end of the device definition.

Step 3: Create a text file for command definitions

Create a new text file or reuse an existing one, formatted as follows:

1: <deviceCommands>
2:   <command name="cmdSetColor">_ESC_ "r%c"</command>
3:   ...
4: </deviceCommands>

Where:

Line 1 -- specifies the root type of the data in this file. In this case, deviceCommands.

Line 2 -- specifies elements in the structure, each formatted as follows: name of the tag (command) followed by an attribute (name) which contains the name of the command. The command data is between the start and end command tags. The command data can be composed of one or more of the following:

  • _ESC_ hexadecimal 0x1b
  • _FF_ hexadecimal 0x0c
  • _LF_ hexadecimal 0x0a
  • _CR_ hexadecimal 0x0d
  • _EM_ hexadecimal 0x19
  • _FS_ hexadecimal 0x1c
  • _CAN_ hexadecimal 0x18
  • _NUL_ hexadecimal 0x00
  • HEX (xx) any hexadecimal value 2 hexdigits long
  • ASCII (c) any ASCII character c
  • "String" an ASCII string

The command structure comes from the device's getCurrentCommand method. Individual commands are then accessed by calling the device command's GetCommandData method. You can then send the command by itself via the device's sendBinaryDataToDevice method, or you can use a printf style call with the Device's sendPrintfToDevice method.

Valid printf arguments are:

  • %d -- little endian 32-bit value
  • %D -- big endian 32-bit value
  • %w -- little endian 16-bit value
  • %W -- big endian 16-bit value
  • %c -- 8-bit value
  • %% -- % character

Usage:

DeviceCommand *pCommands = pDevice_d->getCurrentCommand ();
BinaryData *pCmd = 0;
 
pCmd = pCommands->getCommandData ("cmdSetColor");
pDevice_d->sendPrintfToDevice (pCmd, 4);

Step 4: Create a text file for resolution definitions

Create a new text file or reuse an existing one, formatted as follows:

 1: <deviceResolutions>
 2:   <deviceResolution>
 3:     <name>RESOLUTION_60_X_180</name>
 4:     <xRes>60</xRes>
 5:     <yRes>180</yRes>
 6:     <command>_ESC_ "* %w"</command>
 7:     <resolutionCapability>0</resolutionCapability>
 8:     <resolutionDestinationBitsPerPel>1</resolutionDestinationBitsPerPel>
 9:     <resolutionScanlineMultiple>24</resolutionScanlineMultiple>
10:   </deviceResolution>
11:   ...
12: </deviceResolutions>

Where:

Line 1 -- specifies the root type of the data in this file. In this case, deviceResolutions.

Line 3 -- specifies the id of the structure.
Note: The ids are global and are defined in DeviceResolution.hpp.

Line 4 -- specifies the x resolution in dots per inch.

Line 5 -- specifies the y resolution in dots per inch.

Line 6 -- specifies the command for the resolution. See above for a description of the command format.

Line 7 -- specifies the capabilities of the resolution. This is for future use.

Line 8 -- specifies the bits per pel of the destination bitmap on the printer. (This is for future use.)

Line 9 -- specifies the number of scanlines that the blitter codes wants at a time. The actual number of scanlines will be a multiple of this number. For example, for 10, it could be 10, 20, 30, etc.

Usage:

DeviceResolution *pDR = pDevice->getCurrentResolution ();
( 360 == pDR->getXRes ()
&& 360 == pDR->getYRes ()
)
{
...
}
if

Step 5: Create a text file for print mode definitions

A print mode is the combination of the physical bits per pel (bpp), the logical bpp, and the number of planes in the logical bitmap. The logical bitmap is the intermediate format that the printer driver converts to the final format (physical bitmap).

Currently, you will receive the bitmap in the logical depth and the physical depth is only informational.

Create a new text file or reuse an existing one, formatted as follows:

  1: <devicePrintModes>
  2:   <devicePrintMode>
  3:     <name>PRINT_MODE_MONOCHROME</name>
  4:     <printModePhysicalCount>1</printModePhysicalCount>
  5:     <printModeLogicalCount>1</printModeLogicalCount>
  6:     <printModePlanes>1</printModePlanes>
  7:   </devicePrintMode>
  8:   ...
  9: </devicePrintModes>

Where:

Line 1 -- specifies the root type of the data in this file. In this case, devicePrintModes.

Line 3 -- specifies the id of the structure.
Note: The ids are global and are defined in DevicePrintMode.hpp.

Line 4 -- specifies the physical bit count of the output bitmap.

Line 5 -- specifies the logical bit count of the input bitmap.

Line 6 -- specifies the logical number of color planes of the input bitmap.

Usage:

DevicePrintMode *pDPM = pDevice->getCurrentPrintMode ();
 
if (1 == pDPM->getLogicalCount ())
{
   // Printer wants a monochrome surface.
}

Step 6: Create a text file for tray definitions

Create a new text file or reuse an existing one, formatted as follows:

  1: <deviceTrays>
  2:   <deviceTray>
  3:     <name>TRAY_REAR_CONTINUOUS</name>
  4:     <trayType>TRAY_TYPE_AUTO</trayType>
  5:     <command>_ESC_ HEX (19) "B"</command>
  6:   </deviceTray>
  7:   ...
  8: </deviceTrays>

Where:

Line 1 -- specifies the root type of the data in this file. In this case, deviceTrays.

Line 3 -- specifies the id of the structure.
Note: The ids are global and are defined in DeviceTray.hpp.

Line 4 -- is unique within the deviceTrays file. To use it:

#include "Brother_HJ_100i_Trays.hpp"
if (Brother_HJ_100i_Trays::TRAY_TYPE_AUTO == pTray->getType ())
{
}
Note: This is reserved for future use and will be probably be consolidated into DeviceTray.hpp.

Line 5 -- specifies the command for the tray. See above for a description of the command format.

Usage:

DeviceTray *pTray = pDevice->getCurrentTray ();
 
if (pTray->isID (DeviceTray::TRAY_REAR_CONTINUOUS))
{
}

Step 7: Create a text file for form definitions

Create a new text file or reuse an existing one, formatted as follows:

 1: <deviceForms>
 2:   <deviceForm>
 3:     <name>FORM_LETTER</name>
 4:     <formCapabilities>NO_CAPABILITIES</formCapabilities>
 5:     <command>_NUL_</command>
 6:     <hardCopyCap>
 7:       <hardCopyCapLeft>0</hardCopyCapLeft>
 8:       <hardCopyCapTop>900</hardCopyCapTop>
 9:       <hardCopyCapRight>0</hardCopyCapRight>
10:       <hardCopyCapBottom>400</hardCopyCapBottom>
11:     </hardCopyCap>
12:   </deviceForm>
13:   ...
14: </deviceForms>

Where:

Line 1 -- specifies the root type of the data in this file. In this case, deviceForms.

Line 3 -- specifies the id of the structure.
Note: The ids are global and are defined in DeviceForm.hpp.

Line 4 -- is unique within the deviceForms file.
Note: This is reserved for future use and will be probably be consolidated into DeviceTray.hpp.

Line 5 -- specifies the command for the form. See above for a description of the command format.

Line 6 -- specifies the start of the form's unprintable areas. These are called Hard Copy Caps (short for Capabilities). The units are in hundredths of a millimeter (hmm). One inch would be 2540 hmms.

Line 7 -- specifies the form's left unprintable area.

Line 8 -- specifies the form's top unprintable area.

Line 9 -- specifies the form's right unprintable area.

Line 10 -- specifies the form's bottom unprintable area.

Usage:

DeviceForm *pDF = pDevice->getCurrentForm ();
HardCopyCap *pHCC = pDF->getHardCopyCap ();
 
if (pDF->isID (DeviceForm::FORM_LETTER))
{
}

Step 8: Create a text file for media definitions

Create a new text file or reuse an existing one, formatted as follows:

  1: <deviceMedias>
  2:   <deviceMedia>
  3:     <name>MEDIA_PLAIN</name>
  4:     <command>_NUL_</command>
  5:     <mediaColorAdjustRequired>0</mediaColorAdjustRequired>
  6:     <mediaAbsorption>MEDIA_HEAVY_ABSORPTION</mediaAbsorption>
  7:   </deviceMedia>
  8:   ...
  9: </deviceMedias>

Where:

Line 1 -- specifies the root type of the data in this file. In this case, deviceMedias.

Line 3 -- specifies the id of the structure.
Note: The ids are global and are defined in DeviceMedia.hpp.

Line 4 -- specifies the command for the media. See above for a description of the command format.

Line 5 -- specifies the color adjustment that is required for this media.
Note: This is reserved for future use.

Line 6 -- specifies the absorption for this media.
Note: This is reserved for future use.

Usage:

DeviceMedia *pDM = pDevice->getCurrentMedia ();
 
if (pDM->isID (DeviceMedia::MEDIA_PLAIN))
{
}

Step 9: Create a text file for connection definitions

A connection is defined to be a grouping of a form, a tray, and a media. It is reserved for future use such as dialogs that show what is allowable for a device.

Create a new text file or reuse an existing one, formatted as follows:

  1: <deviceConnections>
  2:   <deviceConnection>
  3:     <name>EPSON_CONN_ID_1</name>
  4:     <connectionForm>FORM_LETTER</connectionForm>
  5:     <connectionTray>TRAY_REAR_CONTINUOUS</connectionTray>
  6:     <connectionMedia>MEDIA_PLAIN</connectionMedia>
  7:   </deviceConnection>
  8:   ...
  9: </deviceConnections>

Where:

Line 1 -- specifies the root type of the data in this file. In this case, deviceConnections.

Line 3 -- specifies the id of the structure.
Note: The ids are local for this file.

Line 4 -- specifies the form id.

Line 5 -- specifies the tray id.

Line 6 -- specifies the media id.

Step 10: Create a text file for gamma definitions

A gamma table entry consists of gamma values for the cyan, magenta, yellow, and black planes. The gamma values are in tenths (ex: 1.0 is 10). It also has a minimum level of value for each of the CMYK planes. This is passed as input to the dithering algorithm in the instance code. Gamma corrections are based on a resolution, media, print mode, and dither Category.

Create a new text file or reuse an existing one, formatted as follows:

 1: <deviceGammaTable>
 2:   <deviceGammaTable>
 3:    <gammaTableResolution>RESOLUTION_60_X_180</gammaTableResolution>
 4:    <gammaTableMedia>MEDIA_PLAIN</gammaTableMedia>
 5:    <gammaTablePrintMode>PRINT_MODE_MONOCHROME</gammaTablePrintMode>
 6:    <gammaTableDitherCategory>DITHER_CATEGORY_MATRIX</gammaTableDitherCategory>
 7:    <gammaTableCGamma>10</gammaTableCGamma>
 8:    <gammaTableMGamma>10</gammaTableMGamma>
 9:    <gammaTableYGamma>10</gammaTableYGamma>
10:    <gammaTableKGamma>10</gammaTableKGamma>
11:    <gammaTableCBias>0</gammaTableCBias>
12:    <gammaTableMBias>0</gammaTableMBias>
13:    <gammaTableYBias>0</gammaTableYBias>
14:    <gammaTableKBias>0</gammaTableKBias>
15:   </deviceGammaTable>
16:   ...
17: </deviceGammaTable>

Where:

Line 1 -- specifies the root type of the data in this file. In this case, deviceGammaTable.

Line 3 -- specifies the resolution id.

Line 4 -- specifies the media id.

Line 5 -- specifies the print mode id.

Line 6 -- specifies the dither category. Currently valid categories are:

  • DITHER_CATAGORY_MATRIX
  • DITHER_CATAGORY_DIFFUSION
  • DITHER_CATAGORY_HSV_DIFFUSION
  • DITHER_CATAGORY_CMYK_DIFFUSION
  • DITHER_CATAGORY_VOID_CLUSTER
  • DITHER_CATAGORY_NEW_DIFFUSION
  • DITHER_CATAGORY_NEW_MATRIX

Line 7 -- specifies the cyan gamma.

Line 8 -- specifies the magenta gamma.

Line 9 -- specifies the yellow gamma.

Line 10 -- specifies the black gamma.

Line 11 -- specifies the cyan bias.

Line 12 -- specifies the magenta bias.

Line 13 -- specifies the yellow bias.

Line 14 -- specifies the black bias.

Usage:

DeviceGamma *pDG = pDevice->getCurrentGamma ();

Step 11: Create a device data table

A device data table consists of values that you want to be different on a per device basis. It consists of a key followed by an equals sign followed by a value (either a string, a boolean value (true or false), or an integer). Multiple data entries are separated by commas. If you have a class of devices, then each device can have the same key name but have different Values.

Create a new text file or reuse an existing one, formatted as follows:

  1: <deviceDatas>
  2:   <deviceData name="dataTestString" type="string">Hello world!</deviceData>
  3:   <deviceData name="dataTestBool" type="boolean">true</deviceData>
  4:   <deviceData name="dataTestInt" type="integer">42</deviceData>
  5: </deviceDatas>

Where:

Line 1 -- specifies the root type of the data in this file. In this case, deviceDatas.

Line 2 -- specifies a string value set to "Hello world!".

Line 3 -- specifies a boolean value set to true.

Line 4 -- specifies an integer value set to 42.

Usage:

DeviceData *pData             = getDeviceData ();
char       *pszDataTestString = 0;
bool        fDataTestBool     = false;
int         iDataTestInt      = 0;
bool        fRc;
 
if (pData)
{
   fRc = pData->getStringData ("dataTestString", &pszDataTestString);
   fRc = pData->getBooleanData ("dataTestBool", &fDataTestBool);
   fRc = pData->getIntData ("dataTestInt", &iDataTestInt);
}

Glossary

Blitter
The portion of the code that actually calls the dither routine with the data to do RGB to CMY conversion, formats the data, and sends the data to the output device

Connection
Grouping of a form, a tray, and a media; reserved for future use such as dialogs that show what is allowable for a given device

Device Data Table
Contains values that will be different on a per device basis

Job Properties
Printing options that are defined on a job by job basis

Printable Area
Area on the page which is the full page size minus the top, left, bottom, and right margins.

Printer Properties
Current hardware (printer) configuration such as trays available, duplexing support installed, etc.

Print Mode
Combination of physical bits per pel (bpp), logical bpp, and the number of planes in the logical bitmap (intermediate format that the printer driver converts to the physical bitmap).