📄 drivers.htm
字号:
<html>
<head>
<title>The interface between Ghostscript and device drivers</title>
<!-- $Id: Drivers.htm $ -->
<!-- Originally: drivers.txt -->
</head>
<body>
<!-- [1.0 begin visible header] -------------------------------------------- -->
<!-- [1.1 begin headline] -------------------------------------------------- -->
<p><table width="100%" border="0">
<tr><th align="center" bgcolor="#CCCC00"><font size=6>
The interface between Ghostscript and device drivers
</font>
</table>
<!-- [1.1 end headline] ---------------------------------------------------- -->
<!-- [1.2 begin table of contents] ----------------------------------------- -->
<h2>Table of contents</h2>
<blockquote><ul>
<li><a href="#Adding_drivers">Adding a driver</a>
<li><a href="#KISS">Keeping things simple</a>
<li><a href="#Structure">Driver structure</a>
<ul>
<li><a href="#Structure_definition">Structure definition</a>
<li><a href="#Sophisticated">For sophisticated developers only</a>
</ul>
<li><a href="#coordinates_and_types">Coordinates and types</a>
<ul>
<li><a href="#Coordinate_system">Coordinate system</a>
<li><a href="#Color_definition">Color definition</a>
<li><a href="#Types">Types</a>
</ul>
<li><a href="#Coding_conventions">Coding conventions</a>
<ul>
<li><a href="#Allocating_storage">Allocating storage</a>
<li><a href="#Driver_instance_allocation">Driver instance allocation</a>
</ul>
<li><a href="#Printer_drivers">Printer drivers</a>
<li><a href="#Driver_procedures">Driver procedures</a>
<ul>
<li><a href="#Life_cycle">Life cycle</a>
<li><a href="#Open_close">Open, close, sync</a>
<li><a href="#Color_mapping">Color and alpha mapping</a>
<li><a href="#Drawing">Drawing</a>
<li><a href="#Bitmap_imaging">Bitmap imaging</a>
<li><a href="#Pixmap_imaging">Pixmap imaging</a>
<li><a href="#Compositing">Compositing</a>
<ul>
<li><a href="#S_spec">The source specification S</a>
<li><a href="#T_spec">The texture specification T</a>
<li><a href="#F_spec">The function specification f</a>
<li><a href="#Notes">Notes</a>
</ul>
<li><a href="#Polygons">Polygons</a>
<li><a href="#High_level_drawing">High-level drawing</a>
<li><a href="#High_level_bitmap_imaging">High-level bitmap imaging</a>
<ul>
<li><a href="#HLBMI_notes">Notes</a>
</ul>
<li><a href="#Reading_bits_back">Reading bits back</a>
<li><a href="#Parameters">Parameters</a>
<ul>
<li><a href="#Default_CRD_parameters">Default color rendering dictionary (CRD) parameters</a>
</ul>
<li><a href="#External_fonts">External fonts</a>
<li><a href="#Page_devices">Page devices</a>
<li><a href="#Miscellaneous">Miscellaneous</a>
</ul>
</ul></blockquote>
<!-- [1.2 end table of contents] ------------------------------------------- -->
<!-- [1.3 begin hint] ------------------------------------------------------ -->
<p>For other information, see the <a href="Readme.htm">Ghostscript
overview</a> and the documentation on <a href="Make.htm">how to build
Ghostscript</a>.
<!-- [1.3 end hint] -------------------------------------------------------- -->
<hr>
<!-- [1.0 end visible header] ---------------------------------------------- -->
<!-- [2.0 begin contents] -------------------------------------------------- -->
<h1><a name="Adding_drivers"></a>Adding a driver</h1>
<p>
To add a driver to Ghostscript, first pick a name for your device, say
"<b><tt>smurf</tt></b>". (Device names must be 1 to 8 characters, begin
with a letter, and consist only of letters, digits, and underscores. Case
is significant: all current device names are lower case.) Then all you
need do is edit <b><tt>contrib.mak</tt></b> in two places.
<ol>
<li>The list of devices, in the section headed "Catalog". Add
<b><tt>smurf</tt></b> to the list.
<li>The section headed "Device drivers".
<p>
Suppose the files containing the smurf driver are called
"<b><tt>joe</tt></b>" and "<b><tt>fred</tt></b>". Then you should add the
following lines:
<blockquote>
<pre># ------ The SMURF device ------ #
smurf_=joe.$(OBJ) fred.$(OBJ)
smurf.dev: $(smurf_)
$(SETDEV) smurf $(smurf_)
joe.$(OBJ): joe.c
fred.$(OBJ): fred.c</pre>
</blockquote>
<p>
and whatever <b><tt>joe.c</tt></b> and <b><tt>fred.c</tt></b> depend on.
If the smurf driver also needs special libraries, for instance a library
named "<b><tt>gorf</tt></b>", then the entry should look like this:
<blockquote>
<pre>smurf.dev: $(smurf_)
$(SETDEV) smurf $(smurf_)
$(ADDMOD) smurf -lib gorf</pre>
</blockquote>
<p>
If, as will usually be the case, your driver is a printer driver (as
<a href="#Printer_drivers">discussed below</a>), the device entry should
look like this:
<blockquote>
<pre>smurf.dev: $(smurf_) page.dev
$(SETPDEV) smurf $(smurf_)</pre>
</blockquote>
<p>
or
<blockquote>
<pre>smurf.dev: $(smurf_) page.dev
$(SETPDEV) smurf $(smurf_)
$(ADDMOD) smurf -lib gorf</pre>
</blockquote>
</ol>
<hr>
<h1><a name="KISS"></a>Keeping things simple</h1>
<p>
If you want to add a simple device (specifically, a monochrome printer),
you probably don't need to read the rest of this document; just use the
code in an existing driver as a guide. The Epson and Canon BubbleJet
drivers <b><tt>gdevepsn.c</tt></b> and <b><tt>gdevbj10.c</tt></b> are good
models for dot-matrix printers, which require presenting the data for many
scan lines at once; the DeskJet/LaserJet drivers in
<b><tt>gdevdjet.c</tt></b> are good models for laser printers, which take a
single scan line at a time but support data compression. For color
printers, there are unfortunately no good models: the two major color
inkjet printer drivers, <b><tt>gdevcdj.c</tt></b> and
<b><tt>gdevstc.c</tt></b>, are far too complex to read.
<p>
On the other hand, if you're writing a driver for some more esoteric
device, you probably do need at least some of the information in the rest
of this document. It might be a good idea for you to read it in
conjunction with one of the existing drivers.
<p>
Duplication of code, and sheer volume of code, is a serious maintenance and
distribution problem for Ghostscript. If your device is similar to an
existing one, try to implement your driver by adding some parameterization
to an existing driver rather than by copying code to create an entirely new
source module. <b><tt>gdevepsn.c</tt></b> and <b><tt>gdevdjet.c</tt></b>
are good examples of this approach.
<hr>
<h1><a name="Structure"></a>Driver structure</h1>
<p>
A device is represented by a structure divided into three parts:
<ul>
<li>procedures that are shared by all instances of each device;
<li>parameters that are present in all devices but may be different for
each device or instance; and
<li>device-specific parameters that may be different for each instance.
</ul>
<p>
Normally the procedure structure is defined and initialized at compile
time. A prototype of the parameter structure (including both generic and
device-specific parameters) is defined and initialized at compile time, but
is copied and filled in when an instance of the device is created. Both of
these structures should be declared as <b><tt>const</tt></b>, but for backward
compatibility reasons are not.
<p>
The <b><tt>gx_device_common</tt></b> macro defines the common structure
elements, with the intent that devices define and export a structure along
the following lines. Do not fill in the individual generic parameter
values in the usual way for C structures: use the macros defined for this
purpose in <b><tt>gxdevice.h</tt></b> or, if applicable,
<b><tt>gdevprn.h</tt></b>.
<blockquote>
<pre>typedef struct smurf_device_s {
gx_device_common;
<b><em>... device-specific parameters ...</em></b>
} smurf_device;
smurf_device far_data gs_smurf_device = {
<b><em>... macro for generic parameter values ...,</em></b>
{ <b><em>... procedures ...</em></b> }, /* std_procs */
<b><em>... device-specific parameter values if any ...</em></b>
};</pre>
</blockquote>
<p>
The device structure instance <b>must</b> have the name
<b><tt>gs_smurf_device</tt></b>, where <b><tt>smurf</tt></b> is the device
name used in <b><tt>contrib.mak</tt></b>. <b><tt>gx_device_common</tt></b>
is a macro consisting only of the element definitions.
<p>
All the device procedures are called with the device as the first argument.
Since each device type is actually a different structure type, the device
procedures must be declared as taking a <b><tt>gx_device *</tt></b> as
their first argument, and must cast it to
<b><tt>smurf_device *</tt></b> internally. For example, in the code
for the "memory" device, the first argument to all routines is called
<b><tt>dev</tt></b>, but the routines actually use <b><tt>mdev</tt></b> to
refer to elements of the full structure, by virtue of the definition
<blockquote>
<pre>#define mdev ((gx_device_memory *)dev)</pre>
</blockquote>
<p>
(This is a cheap version of "object-oriented" programming: in C++, for
example, the cast would be unnecessary, and in fact the procedure table
would be constructed by the compiler.)
<h2><a name="Structure_definition"></a>Structure definition</h2>
<p>
You should consult the definition of struct <b><tt>gx_device_s</tt></b> in
<b><tt>gxdevice.h</tt></b> for the complete details of the generic device
structure. Some of the most important members of this structure for
ordinary drivers are:
<blockquote><table cellpadding=0 cellspacing=0>
<tr valign=top> <td><b><tt>const char *dname;</tt></b>
<td>
<td>The device name
<tr valign=top> <td><b><tt>bool is_open;</tt></b>
<td>
<td>True if device has been opened
<tr valign=top> <td><b><tt>gx_device_color_info color_info;</tt></b>
<td>
<td>Color information
<tr valign=top> <td><b><tt>int width;</tt></b>
<td>
<td>Width in pixels
<tr valign=top> <td><b><tt>int height;</tt></b>
<td>
<td>Height in pixels
</table></blockquote>
<p>
The name in the structure (<b><tt>dname</tt></b>) should be the same as the
name in <b><tt>contrib.mak</tt></b>.
<h2><a name="Sophisticated"></a>For sophisticated developers only</h2>
<p>
If for any reason you need to change the definition of the basic device
structure, or to add procedures, you must change the following places:
<blockquote><ul>
<li>This document and the <a href="News.htm">news document</a> (if you want
to keep the documentation up to date).
<li>The definition of <b><tt>gx_device_common</tt></b> and the procedures
in <b><tt>gxdevcli.h</tt></b>.
<li>Possibly, the default forwarding procedures declared in
<b><tt>gxdevice.h</tt></b> and implemented in
<b><tt>gdevnfwd.c</tt></b>.
<li>The device procedure record completion routines in
<b><tt>gdevdflt.c</tt></b>.
<li>Possibly, the default device implementation in
<b><tt>gdevdflt.c</tt></b>, <b><tt>gdevddrw.c</tt></b>, and
<b><tt>gxcmap.c</tt></b>.
<li>The bounding box device in <b><tt>gdevbbox.c</tt></b> (probably just
adding <b><tt>NULL</tt></b> procedure entries if the new procedures
don't produce output).
<li>These devices that must have complete (non-defaulted) procedure vectors:
<ul>
<li>The null device in <b><tt>gdevnfwd.c</tt></b>.
<li>The command list "device" in <b><tt>gxclist.c</tt></b>. This is not an
actual device; it only defines procedures.
<li>The "memory" devices in <b><tt>gdevmem.h</tt></b> and
<b><tt>gdevm*.c</tt></b>.
<li>The halftoning device in <b><tt>gdevht.c</tt></b>.
</ul>
<li>The clip list accumulation "device" in <b><tt>gxacpath.c</tt></b>.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -