summaryrefslogtreecommitdiff
path: root/Master/xemtex/doc/ghostscript/Drivers.htm
diff options
context:
space:
mode:
Diffstat (limited to 'Master/xemtex/doc/ghostscript/Drivers.htm')
-rw-r--r--Master/xemtex/doc/ghostscript/Drivers.htm2538
1 files changed, 2538 insertions, 0 deletions
diff --git a/Master/xemtex/doc/ghostscript/Drivers.htm b/Master/xemtex/doc/ghostscript/Drivers.htm
new file mode 100644
index 00000000000..c97bfaeb642
--- /dev/null
+++ b/Master/xemtex/doc/ghostscript/Drivers.htm
@@ -0,0 +1,2538 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<title>The interface between Ghostscript and device drivers</title>
+<!-- $Id: Drivers.htm,v 1.21.2.11.2.5 2003/05/17 14:38:59 giles Exp $ -->
+<!-- Originally: drivers.txt -->
+<link rel="stylesheet" type="text/css" href="gs.css" title="Ghostscript Style">
+</head>
+
+<body>
+<!-- [1.0 begin visible header] ============================================ -->
+
+<!-- [1.1 begin headline] ================================================== -->
+
+<h1>The interface between Ghostscript and device drivers</h1>
+
+<!-- [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, copy</a>
+<li><a href="#Color_mapping">Color and alpha mapping</a>
+<li><a href="#Pixel_level_drawing">Pixel-level drawing</a>
+<ul>
+<li><a href="#Bitmap_imaging">Bitmap imaging</a>
+<li><a href="#Pixmap_imaging">Pixmap imaging</a>
+<li><a href="#Compositing">Compositing</a>
+ [<a href="#S_spec">S</a>, <a href="#T_spec">T</a>, <a href="#F_spec">f</a>,
+ <a href="#Compositing_notes">Notes</a>]
+</ul>
+<li><a href="#Polygon_level_drawing">Polygon-level drawing</a>
+<li><a href="#High_level_drawing">High-level drawing</a>
+<ul>
+<li><a href="#Paths">Paths</a>
+<li><a href="#Images">Images</a> [<a href="#Images_notes">Notes</a>]
+<li><a href="#Text">Text</a> [<a href="#Text_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] ================================================== -->
+
+<h2><a name="Adding_drivers"></a>Adding a driver</h2>
+
+<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_=$(GLOBJ)joe.$(OBJ) $(GLOBJ)fred.$(OBJ)
+$(DD)smurf.dev: $(smurf_)
+ $(SETDEV) $(DD)smurf $(smurf_)
+
+$(GLOBJ)joe.$(OBJ) : $(GLSRC)joe.c
+ $(GLCC) $(GLO_)joe.$(OBJ) $(C_) $(GLSRC)joe.c
+
+$(GLOBJ)fred.$(OBJ) : $(GLSRC)fred.c
+ $(GLCC) $(GLO_)fred.$(OBJ) $(C_) $(GLSRC)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>$(DD)smurf.dev : $(smurf_)
+ $(SETDEV) $(DD)smurf $(smurf_)
+ $(ADDMOD) $(DD)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>$(DD)smurf.dev : $(smurf_) $(GLD)page.dev
+ $(SETPDEV) $(DD)smurf $(smurf_)</pre>
+</blockquote>
+
+<p>
+or
+
+<blockquote>
+<pre>$(DD)smurf.dev : $(smurf_) $(GLD)page.dev
+ $(SETPDEV) $(DD)smurf $(smurf_)
+ $(ADDMOD) $(DD)smurf -lib gorf</pre>
+</blockquote>
+
+<p>
+Note that the space before the :, and the explicit compilation rules for the
+.c files, are required for portability,
+</ol>
+
+<hr>
+
+<h2><a name="KISS"></a>Keeping things simple</h2>
+
+<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 <a
+href="../src/gdevepsn.c">gdevepsn.c</a> and <a
+href="../src/gdevbj10.c">gdevbj10.c</a> are good models for dot-matrix
+printers, which require presenting the data for many scan lines at once; the
+DeskJet/LaserJet drivers in <a href="../src/gdevdjet.c">gdevdjet.c</a> 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, <a
+href="../src/gdevcdj.c">gdevcdj.c</a> and <a
+href="../src/gdevstc.c">gdevstc.c</a>, 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. <a href="../src/gdevepsn.c">gdevepsn.c</a> and <a
+href="../src/gdevdjet.c">gdevdjet.c</a> are good examples of this approach.
+
+<hr>
+
+<h2><a name="Structure"></a>Driver structure</h2>
+
+<p>
+A device is represented by a structure divided into three parts:
+
+<ul>
+<li>procedures that are (normally) 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 the latter is 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 <a href="../src/gxdevice.h">gxdevice.h</a> or, if applicable, <a
+href="../src/gdevprn.h">gdevprn.h</a>.
+
+<blockquote>
+<pre>typedef struct smurf_device_s {
+ gx_device_common;
+ <b><em>... device-specific parameters ...</em></b>
+} smurf_device;
+smurf_device 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&nbsp;*</tt></b> as
+their first argument, and must cast it to
+<b><tt>smurf_device&nbsp;*</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, using the following standard
+initialization statement at the beginning of each procedure:
+
+<blockquote>
+<pre>gx_memory_device *const 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.)
+
+<h3><a name="Structure_definition"></a>Structure definition</h3>
+
+<p>
+You should consult the definition of struct <b><tt>gx_device_s</tt></b> in
+<a href="../src/gxdevice.h">gxdevice.h</a> 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>&nbsp;&nbsp;&nbsp;&nbsp;
+ <td>The device name
+<tr valign=top> <td><b><tt>bool is_open;</tt></b>
+ <td>&nbsp;
+ <td>True if device has been opened
+<tr valign=top> <td><b><tt>gx_device_color_info color_info;</tt></b>
+ <td>&nbsp;
+ <td>Color information
+<tr valign=top> <td><b><tt>int width;</tt></b>
+ <td>&nbsp;
+ <td>Width in pixels
+<tr valign=top> <td><b><tt>int height;</tt></b>
+ <td>&nbsp;
+ <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 <a href="../src/contrib.mak">contrib.mak</a>.
+
+<h3><a name="Sophisticated"></a>For sophisticated developers only</h3>
+
+<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 <a href="../src/gxdevcli.h">gxdevcli.h</a>.
+<li>Possibly, the default forwarding procedures declared in
+ <a href="../src/gxdevice.h">gxdevice.h</a> and implemented in
+ <a href="../src/gdevnfwd.c">gdevnfwd.c</a>.
+<li>The device procedure record completion routines in
+ <a href="../src/gdevdflt.c">gdevdflt.c</a>.
+<li>Possibly, the default device implementation in
+ <a href="../src/gdevdflt.c">gdevdflt.c</a>,
+ <a href="../src/gdevddrw.c">gdevddrw.c</a>, and
+ <a href="../src/gxcmap.c">gxcmap.c</a>.
+<li>The bounding box device in <a href="../src/gdevbbox.c">gdevbbox.c</a>
+ (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 <a href="../src/gdevnfwd.c">gdevnfwd.c</a>.
+<li>The command list "device" in <a href="../src/gxclist.c">gxclist.c</a>.
+ This is not an actual device; it only defines procedures.
+<li>The "memory" devices in <a href="../src/gdevmem.h">gdevmem.h</a> and
+ <b><tt>gdevm*.c</tt></b>.
+<li>The halftoning device in <a href="../src/gdevht.c">gdevht.c</a>.
+</ul>
+<li>The clip list accumulation "device" in
+ <a href="../src/gxacpath.c">gxacpath.c</a>.
+<li>The clipping "devices" <a href="../src/gxclip.c">gxclip.c</a>,
+ <a href="../src/gxclip2.c">gxclip2.c</a>,
+ and <a href="../src/gxclipm.c">gxclipm.c</a>.
+<li>The pattern accumulation "device" in
+ <a href="../src/gxpcmap.c">gxpcmap.c</a>.
+<li>The hit detection "device" in <a href="../src/gdevhit.c">gdevhit.c</a>.
+<li>The generic printer device macros in
+ <a href="../src/gdevprn.h">gdevprn.h</a>.
+<li>The generic printer device code in
+ <a href="../src/gdevprn.c">gdevprn.c</a>.
+<li>The RasterOp source device in
+ <a href="../src/gdevrops.c">gdevrops.c</a>.
+</ul></blockquote>
+
+<p>
+You may also have to change the code for
+<b><tt>gx_default_get_params</tt></b> or
+<b><tt>gx_default_put_params</tt></b> in <a
+href="../src/gsdparam.c">gsdparam.c</a>.
+
+<p>
+You should not have to change any of the real devices in the standard
+Ghostscript distribution (listed in <a href="../src/devs.mak">devs.mak</a>
+and <a href="../src/contrib.mak">contrib.mak</a>) or any of your own
+devices, because all of them are supposed to use the macros in <a
+href="../src/gxdevice.h">gxdevice.h</a> or <a
+href="../src/gdevprn.h">gdevprn.h</a> to define and initialize their state.
+
+<hr>
+
+<h2><a name="coordinates_and_types"></a>Coordinates and types</h2>
+
+<h3><a name="Coordinate_system"></a>Coordinate system</h3>
+
+<p>
+Since each driver specifies the initial transformation from user
+coordinates to device coordinates, the driver can use any coordinate system
+it wants, as long as a device coordinate will fit in an
+<b><tt>int</tt></b>. (This is only an issue on DOS systems, where ints are
+only 16 bits. User coordinates are represented as floats.) Most current
+drivers use a coordinate system with (0,0) in the upper left corner, with
+<b><em>X</em></b> increasing to the right and <b><em>Y</em></b> increasing
+toward the bottom. However, there is supposed to be nothing in the rest of
+Ghostscript that assumes this, and indeed some drivers use a coordinate
+system with (0,0) in the lower left corner.
+
+<p>
+Drivers must check (and, if necessary, clip) the coordinate parameters given
+to them: they should not assume the coordinates will be in bounds. The
+<b><tt>fit_fill</tt></b> and <b><tt>fit_copy</tt></b> macros in <a
+href="../src/gxdevice.h">gxdevice.h</a> are very helpful in doing this.
+
+<h3><a name="Color_definition"></a>Color definition</h3>
+
+<p>
+Ghostscript represents colors internally as RGB or CMYK values. In
+communicating with devices, however, it assumes that each device has a
+palette of colors identified by integers (to be precise, elements of type
+<b><tt>gx_color_index</tt></b>). Drivers may provide a uniformly spaced
+gray ramp or color cube for halftoning, or they may do their own color
+approximation, or both.
+
+<p>
+The <b><tt>color_info</tt></b> member of the device structure defines the
+color and gray-scale capabilities of the device. Its type is defined as
+follows:
+
+<blockquote>
+<pre>typedef struct gx_device_color_info_s {
+ int num_components; /* 1 = gray only, 3 = RGB, */
+ /* 4 = CMYK */
+ int depth; /* # of bits per pixel */
+ gx_color_value max_gray; /* # of distinct gray levels -1 */
+ gx_color_value max_rgb; /* # of distinct color levels -1 */
+ /* (only relevant if num_comp. &gt; 1) */
+ gx_color_value dither_gray; /* size of gray ramp for halftoning */
+ gx_color_value dither_rgb; /* size of color cube ditto */
+ /* (only relevant if num_comp. &gt; 1) */
+} gx_device_color_info;</pre>
+</blockquote>
+
+<p>
+The following macros (in <a href="../src/gxdevice.h">gxdevice.h</a>) provide
+convenient shorthands for initializing this structure for ordinary
+black-and-white or color devices:
+
+<blockquote>
+<b><tt>#define dci_black_and_white</tt></b> ...<br>
+<b><tt>#define dci_color(depth,maxv,dither)</tt></b> ...
+</blockquote>
+
+<p>
+The idea is that a device has a certain number of gray levels
+(<b><tt>max_gray</tt></b>+1) and a certain number of colors
+(<b><tt>max_rgb</tt></b>+1) that it can produce directly. When Ghostscript
+wants to render a given RGB or CMYK color as a device color, it first tests
+whether the color is a gray level (if <b><tt>num_components</tt></b> is 1,
+it converts all colors to gray levels), and if so:
+
+<blockquote>
+If <b><tt>max_gray</tt></b> is large (&gt;= 31), Ghostscript asks the
+device to approximate the gray level directly. If the device returns a
+valid <b><tt>gx_color_index</tt></b>, Ghostscript uses it. Otherwise,
+Ghostscript assumes that the device can represent
+<b><tt>dither_gray</tt></b> distinct gray levels, equally spaced along the
+diagonal of the color cube, and uses the two nearest ones to the desired
+color for halftoning.
+</blockquote>
+
+<p>
+If the color is not a gray level:
+
+<blockquote>
+If <b><tt>max_rgb</tt></b> is large (&gt;= 31), Ghostscript asks the device
+to approximate the color directly. If the device returns a valid
+<b><tt>gx_color_index</tt></b>, Ghostscript uses it. Otherwise,
+Ghostscript assumes that the device can represent
+
+<blockquote>
+<b><tt>dither_rgb</tt></b> &times; <b><tt>dither_rgb</tt></b> &times; <b><tt>dither_rgb</tt></b>
+</blockquote>
+
+<p>
+distinct colors, equally spaced throughout the color cube, and uses two of
+the nearest ones to the desired color for halftoning.
+</blockquote>
+
+<h3><a name="Types"></a>Types</h3>
+
+<p>
+Here is a brief explanation of the various types that appear as parameters
+or results of the drivers.
+
+<dl>
+<dt><b><tt>gx_color_value</tt></b> (defined in <b><tt>gxdevice.h</tt></b>)
+<dd>This is the type used to represent RGB or CMYK color values. It is
+currently equivalent to unsigned short. However, Ghostscript may use less
+than the full range of the type to represent color values:
+<b><tt>gx_color_value_bits</tt></b> is the number of bits actually used,
+and <b><tt>gx_max_color_value</tt></b> is the maximum value, equal to
+(2^<small><sup><b><tt>gx_max_color_value_bits</tt></b></sup></small>)-1.
+</dl>
+
+<dl>
+<dt><b><tt>gx_device</tt></b> (defined in <b><tt>gxdevice.h</tt></b>)
+<dd>This is the device structure, as explained above.
+</dl>
+
+<dl>
+<dt><b><tt>gs_matrix</tt></b> (defined in <b><tt>gsmatrix.h</tt></b>)
+<dd>This is a 2-D homogeneous coordinate transformation matrix, used by
+many Ghostscript operators.
+</dl>
+
+<dl>
+<dt><b><tt>gx_color_index</tt></b> (defined in <b><tt>gxdevice.h</tt></b>)
+<dd>This is meant to be whatever the driver uses to represent a device
+color. For example, it might be an index in a color map, or it might be R,
+G, and B values packed into a single integer. Ghostscript doesn't ever do
+any computations with <b><tt>gx_color_index</tt></b> values: it gets them
+from <b><tt>map_rgb_color</tt></b> or <b><tt>map_cmyk_color</tt></b> and
+hands them back as arguments to several other procedures. The special
+value <b><tt>gx_no_color_index</tt></b> (defined as
+<b><tt>(gx_color_index)(-1)</tt></b>&nbsp;) means "transparent" for some of
+the procedures. The type definition is simply:
+
+<blockquote><b><tt>
+typedef unsigned long gx_color_index;
+</tt></b></blockquote>
+</dl>
+
+<dl>
+<dt><b><tt>gs_param_list</tt></b> (defined in <a
+href="../src/gsparam.h">gsparam.h</a>)
+<dd>This is a parameter list, which is used to read and set attributes in a
+device. See the comments in <a href="../src/gsparam.h">gsparam.h</a>, and
+the <a href="#Parameters">description of the <b><tt>get_params</tt></b> and
+<b><tt>put_params</tt></b> procedures</a> below, for more detail.
+</dl>
+
+<dl>
+<dt><b><tt>gx_tile_bitmap</tt></b> (defined in
+<a href="../src/gxbitmap.h">gxbitmap.h</a>)
+<br><b><tt>gx_strip_bitmap</tt></b> (defined in
+<a href="../src/gxbitmap.h">gxbitmap.h</a>)
+<dd>These structure types represent bitmaps to be used as a tile for
+filling a region (rectangle). <b><tt>gx_tile_bitmap</tt></b> is an older
+type lacking <b><tt>shift</tt></b> and <b><tt>rep_shift</tt></b>;
+<b><tt>gx_strip_bitmap</tt></b> has superseded it, and it should not be
+used in new code. Here is a copy of the relevant part of the file:
+
+<blockquote>
+<pre>/*
+ * Structure for describing stored bitmaps.
+ * Bitmaps are stored bit-big-endian (i.e., the 2^7 bit of the first
+ * byte corresponds to x=0), as a sequence of bytes (i.e., you can't
+ * do word-oriented operations on them if you're on a little-endian
+ * platform like the Intel 80x86 or VAX). Each scan line must start on
+ * a (32-bit) word boundary, and hence is padded to a word boundary,
+ * although this should rarely be of concern, since the raster and width
+ * are specified individually. The first scan line corresponds to y=0
+ * in whatever coordinate system is relevant.
+ *
+ * For bitmaps used as halftone tiles, we may replicate the tile in
+ * X and/or Y, but it is still valuable to know the true tile dimensions
+ * (i.e., the dimensions prior to replication). Requirements:
+ * width % rep_width = 0
+ * height % rep_height = 0
+ *
+ * For halftones at arbitrary angles, we provide for storing the halftone
+ * data as a strip that must be shifted in X for different values of Y.
+ * For an ordinary (non-shifted) halftone that has a repetition width of
+ * W and a repetition height of H, the pixel at coordinate (X,Y)
+ * corresponds to halftone pixel (X mod W, Y mod H), ignoring phase;
+ * for a shifted halftone with shift S, the pixel at (X,Y) corresponds
+ * to halftone pixel ((X + S * floor(Y/H)) mod W, Y mod H). Requirements:
+ * strip_shift &lt; rep_width
+ * strip_height % rep_height = 0
+ * shift = (strip_shift * (size.y / strip_height)) % rep_width
+ */
+typedef struct gx_strip_bitmap_s {
+ byte *data;
+ int raster; /* bytes per scan line */
+ gs_int_point size; /* width, height */
+ gx_bitmap_id id;
+ ushort rep_width, rep_height; /* true size of tile */
+ ushort strip_height;
+ ushort strip_shift;
+ ushort shift;
+} gx_strip_bitmap;</pre>
+</blockquote>
+</dl>
+
+<hr>
+
+<h2><a name="Coding_conventions"></a>Coding conventions</h2>
+
+<p>
+All the driver procedures defined below that return <b><tt>int</tt></b>
+results return 0 on success, or an appropriate negative error code in the
+case of error conditions. The error codes are defined in <a
+href="../src/gserrors.h">gserrors.h</a>; they correspond directly to the
+errors defined in the PostScript language reference manuals. The most
+common ones for drivers are:
+
+<blockquote><dl>
+<dt><b><tt>gs_error_invalidfileaccess</tt></b>
+<dd>An attempt to open a file failed.
+
+<dt><b><tt>gs_error_ioerror</tt></b>
+<dd>An error occurred in reading or writing a file.
+
+<dt><b><tt>gs_error_limitcheck</tt></b>
+<dd>An otherwise valid parameter value was too large for the
+implementation.
+
+<dt><b><tt>gs_error_rangecheck</tt></b>
+<dd>A parameter was outside the valid range.
+
+<dt><b><tt>gs_error_VMerror</tt></b>
+<dd>An attempt to allocate memory failed. (If this happens, the procedure
+should release all memory it allocated before it returns.)
+</dl></blockquote>
+
+<p>
+If a driver does return an error, rather than a simple return statement it
+should use the <b><tt>return_error</tt></b> macro defined in <a
+href="../src/gx.h">gx.h</a>, which is automatically included by <a
+href="../src/gdevprn.h">gdevprn.h</a> but not by <a
+href="../src/gserrors.h">gserrors.h</a>. For example
+
+<blockquote><b><tt>
+return_error(gs_error_VMerror);
+</tt></b></blockquote>
+
+<h3><a name="Allocating_storage"></a>Allocating storage</h3>
+
+<p>
+While most drivers (especially printer drivers) follow a very similar
+template, there is one important coding convention that is not obvious from
+reading the code for existing drivers: driver procedures must not use
+<b><tt>malloc</tt></b> to allocate any storage that stays around after the
+procedure returns. Instead, they must use <b><tt>gs_malloc</tt></b> and
+<b><tt>gs_free</tt></b>, which have slightly different calling conventions.
+(The prototypes for these are in <a href="../src/gsmemory.h">gsmemory.h</a>,
+which is included in <a href="../src/gx.h">gx.h</a>, which is included in <a
+href="../src/gdevprn.h">gdevprn.h</a>.) This is necessary so that
+Ghostscript can clean up all allocated memory before exiting, which is
+essential in environments that provide only single-address-space
+multi-tasking (some versions of Microsoft Windows).
+
+<blockquote>
+<pre>char *gs_malloc(uint num_elements, uint element_size,
+ const char *client_name);</pre>
+</blockquote>
+
+<p>
+Like <b><tt>calloc</tt></b>, but unlike <b><tt>malloc</tt></b>,
+<b><tt>gs_malloc</tt></b> takes an element count and an element size. For
+structures, <b><tt>num_elements</tt></b> is 1 and
+<b><tt>element_size</tt></b> is <b><tt>sizeof</tt></b> the structure; for
+byte arrays, <b><tt>num_elements</tt></b> is the number of bytes and
+<b><tt>element_size</tt></b> is 1. Unlike <b><tt>calloc</tt></b>,
+<b><tt>gs_malloc</tt></b> does <b>not</b> clear the block of storage.
+
+<p>
+The <b><tt>client_name</tt></b> is used for tracing and debugging. It must
+be a real string, not <b><tt>NULL</tt></b>. Normally it is the name of the
+procedure in which the call occurs.
+
+<blockquote>
+<pre>void gs_free(char *data, uint num_elements, uint element_size,
+ const char *client_name);</pre>
+</blockquote>
+
+<p>
+Unlike <b><tt>free</tt></b>, <b><tt>gs_free</tt></b> demands that
+<b><tt>num_elements</tt></b> and element_size be supplied. It also
+requires a client name, like <b><tt>gs_malloc</tt></b>.
+
+<h3><a name="Driver_instance_allocation"></a>Driver instance allocation</h3>
+
+<p>
+All driver instances allocated by Ghostscript's standard allocator must
+point to a "structure descriptor" that tells the garbage collector how to
+trace pointers in the structure. For drivers registered in the normal way
+(using the makefile approach described above), no special care is needed as
+long as instances are created only by calling the
+<b><tt>gs_copydevice</tt></b> procedure defined in <a
+href="../src/gsdevice.h">gsdevice.h</a>. If you have a need to define
+devices that are not registered in this way, you must fill in the stype
+member in any dynamically allocated instances with a pointer to the same
+structure descriptor used to allocate the instance. For more information
+about structure descriptors, see <a href="../src/gsmemory.h">gsmemory.h</a>
+and <a href="../src/gsstruct.h">gsstruct.h</a>.
+
+<hr>
+
+<h2><a name="Printer_drivers"></a>Printer drivers</h2>
+
+<p>
+Printer drivers (which include drivers that write some kind of raster file)
+are especially simple to implement. Of the driver procedures defined in the
+next section, they only need implement two: <b><tt>map_rgb_color</tt></b>
+(or <b><tt>map_cmyk_color</tt></b>) and <b><tt>map_color_rgb</tt></b>. In
+addition, they must implement a <b><tt>print_page</tt></b> or
+<b><tt>print_page_copies</tt></b> procedure. There are macros in <a
+href="../src/gdevprn.h">gdevprn.h</a> that generate the device structure for
+such devices, of which the simplest is <b><tt>prn_device</tt></b>; for an
+example, see <a href="../src/gdevbj10.c">gdevbj10.c</a>. If you are writing
+a printer driver, we suggest you start by reading <a
+href="../src/gdevprn.h">gdevprn.h</a> and the <a
+href="#Color_mapping">subsection on "Color mapping"</a> below; you may be
+able to ignore all the rest of the driver procedures.
+
+<p>
+The <b><tt>print_page</tt></b> procedures are defined as follows:
+
+<blockquote>
+<pre>int (*print_page)(P2(gx_device_printer *, FILE *))
+int (*print_page_copies)(P3(gx_device_printer *, FILE *, int))</pre>
+</blockquote>
+
+<p>
+This procedure must read out the rendered image from the device and write
+whatever is appropriate to the file. To read back one or more scan lines
+of the image, the <b><tt>print_page</tt></b> procedure must call one of the
+following procedures:
+
+<blockquote>
+<pre>int gdev_prn_copy_scan_lines(P4(gx_device_printer *pdev, int y, byte *str,
+ uint size)</pre>
+</blockquote>
+
+<p>
+For this procedure, <b><tt>str</tt></b> is where the data should be copied to, and <b><tt>size</tt></b> is
+the size of the buffer starting at <b><tt>str</tt></b>. This procedure returns the number
+of scan lines copied, or &lt;0 for an error. <b><tt>str</tt></b> need not be aligned.
+
+<blockquote>
+<pre>int gdev_prn_get_bits(gx_device_printer *pdev, int y, byte *str,
+ byte **actual_data)</pre>
+</blockquote>
+
+<p>
+This procedure reads out exactly one scan line. If the scan line is
+available in the correct format already, <b><tt>*actual_data</tt></b> is
+set to point to it; otherwise, the scan line is copied to the buffer
+starting at <b><tt>str</tt></b>, and <b><tt>*actual_data</tt></b> is set to
+<b><tt>str</tt></b>. This saves a copying step most of the time.
+<b><tt>str</tt></b> need not be aligned; however, if
+<b><tt>*actual_data</tt></b> is set to point to an existing scan line, it
+will be aligned. (See the description of the <b><tt>get_bits</tt></b>
+procedure below for more details.)
+
+<p>
+In either case, each row of the image is stored in the form described in
+the comment under <b><tt>gx_tile_bitmap</tt></b> above; each pixel takes
+the number of bits specified as <b><tt>color_info.depth</tt></b> in the
+device structure, and holds values returned by the device's
+<b><tt>map_</tt></b>{<b><tt>rgb</tt></b>,<b><tt>cmyk</tt></b>}<b><tt>_color</tt></b>
+procedure.
+
+<p>
+The <b><tt>print_page</tt></b> procedure can determine the number of bytes
+required to hold a scan line by calling:
+
+<blockquote>
+<pre>uint gdev_prn_raster(P1(gx_device_printer *))</pre>
+</blockquote>
+
+<p>
+For a very simple concrete example, we suggest reading the code in
+<b><tt>bit_print_page</tt></b> in <a href="../src/gdevbit.c">gdevbit.c</a>.
+
+<p>
+If the device provides <b><tt>print_page</tt></b>, Ghostscript will call
+<b><tt>print_page</tt></b> the requisite number of times to print the
+desired number of copies; if the device provides
+<b><tt>print_page_copies</tt></b>, Ghostscript will call
+<b><tt>print_page_copies</tt></b> once per page, passing it the desired
+number of copies.
+
+<hr>
+
+<h2><a name="Driver_procedures"></a>Driver procedures</h2>
+
+<p>
+Most of the procedures that a driver may implement are optional. If a
+device doesn't supply an optional procedure <b><tt>WXYZ</tt></b>, the entry
+in the procedure structure may be either <b><tt>gx_default_WXYZ</tt></b>,
+for instance <b><tt>gx_default_tile_rectangle</tt></b>, or
+<b><tt>NULL</tt></b> or 0. (The device procedure must also call the
+<b><tt>gx_default_</tt></b> procedure if it doesn't implement the function
+for particular values of the arguments.) Since C compilers supply 0 as the
+value for omitted structure elements, this convention means that statically
+initialized procedure structures continue to work even if new (optional)
+members are added.
+
+<h3><a name="Life_cycle"></a>Life cycle</h3>
+
+<p>
+A device instance begins life in a closed state. In this state, no output
+operations will occur. Only the following procedures may be called:
+
+<blockquote><b><tt>
+open_device<br>
+finish_copydevice<br>
+get_initial_matrix<br>
+get_params<br>
+put_params<br>
+get_hardware_params
+</tt></b></blockquote>
+
+<p>
+When <b><tt>setdevice</tt></b> installs a device instance in the graphics
+state, it checks whether the instance is closed or open. If the instance
+is closed, <b><tt>setdevice</tt></b> calls the open routine, and then sets
+the state to open. There is currently no user-accessible operation to
+close a device instance. Device instances are only closed when they are
+about to be freed, which occurs in three situations:
+
+<ul>
+<li>When a <b><tt>restore</tt></b> occurs, if the instance was created since
+the corresponding <b><tt>save</tt></b> and is in a VM being restored. I.e.,
+if the instance was created in local VM since a <b><tt>save</tt></b>, it
+will always be closed and freed by the corresponding
+<b><tt>restore</tt></b>; if it was created in global VM, it will only be
+closed by the outermost <b><tt>restore</tt></b>, regardless of the save
+level at the time the instance was created.
+
+<li>By the garbage collector, if the instance is no longer accessible.
+
+<li>When Ghostscript exits (terminates).
+</ul>
+
+<h3><a name="Open_close"></a>Open, close, sync, copy</h3>
+
+<dl>
+<dt><b><tt>int (*open_device)(P1(gx_device *))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>Open the device: do any initialization associated with making the device
+instance valid. This must be done before any output to the device. The
+default implementation does nothing. <b>NOTE</b>: Clients should never call
+a device's <b><tt>open_device</tt></b> procedure directly: they should
+always call <b><tt>gs_opendevice</tt></b> instead.
+</dl>
+
+<dl>
+<dt><b><tt>int (*finish_copydevice)(P2(gx_device *dev, const gx_device
+*from_dev))</tt></b> <b><em>[OPTIONAL]</em></b> <dd>Perform any cleanup
+required after <b><tt>copydevice</tt></b> has created a new device instance
+by copying <b><tt>from_dev</tt></b>. If the copy operation should not be
+allowed, this procedure should return an error; the copy will be freed. The
+default implementation allows copying the device prototype, but does not
+allow copying device instances, because instances may contain internal
+pointers that should not be shared between copies, and there is no way to
+determine this from outside the device. <b>NOTE</b>: Clients should never
+call a device's <b><tt>finish_copydevice</tt></b> procedure: this procedure
+is only intended for use by <b><tt>gs_copydevice[2]</tt></b>.
+</dl>
+
+<dl>
+<dt><b><tt>void (*get_initial_matrix)(P2(gx_device *, gs_matrix *))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>Construct the initial transformation matrix mapping user coordinates
+(nominally 1/72 inch per unit) to device coordinates. The default
+procedure computes this from width, height, and
+[<b><tt>xy</tt></b>]<b><tt>_pixels_per_inch</tt></b> on the assumption that
+the origin is in the upper left corner, that is
+<blockquote>
+<b><tt>xx</tt></b> = <b><tt>x_pixels_per_inch</tt></b>/72, <b><tt>xy</tt></b> = 0,<br>
+<b><tt>yx = 0, yy = -y_pixels_per_inch</tt></b>/72,<br>
+<b><tt>tx = 0, ty = height</tt></b>.
+</blockquote>
+</dl>
+
+<dl>
+<dt><b><tt>int (*sync_output)(P1(gx_device *))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>Synchronize the device. If any output to the device has been
+buffered, send or write it now. Note that this may be called several times
+in the process of constructing a page, so printer drivers should <b>not</b>
+implement this by printing the page. The default implementation does
+nothing.
+</dl>
+
+<dl>
+<dt><b><tt>int (*output_page)(P3(gx_device *, int num_copies, int flush))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>Output a fully composed page to the device. The
+<b><tt>num_copies</tt></b> argument is the number of copies that should be
+produced for a hardcopy device. (This may be ignored if the driver has
+some other way to specify the number of copies.) The <b><tt>flush</tt></b>
+argument is true for <b><tt>showpage</tt></b>, false for
+<b><tt>copypage</tt></b>. The default definition just calls
+<b><tt>sync_output</tt></b>. Printer drivers should implement this by
+printing and ejecting the page.
+</dl>
+
+<dl>
+<dt><b><tt>int (*close_device)(P1(gx_device *))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>Close the device: release any associated resources. After this, output
+to the device is no longer allowed. The default implementation does
+nothing. <b>NOTE</b>: Clients should never call a device's
+<b><tt>close_device</tt></b> procedure directly: they should always call
+<b><tt>gs_closedevice</tt></b> instead.
+</dl>
+
+<h3><a name="Color_mapping"></a>Color and alpha mapping</h3>
+
+<p>
+A given driver normally implements either <b><tt>map_rgb_color</tt></b> or
+<b><tt>map_cmyk_color</tt></b>, but not both. Black-and-white drivers need
+implement neither. Note that the <b><tt>map_xxx_color</tt></b> procedures
+must not return <b><tt>gx_no_color_index</tt></b> (all 1s).
+
+<p>
+Note that code in the Ghostscript library may cache the results of calling
+one or more of the color mapping procedures. If the result returned by any
+of these procedures would change (other than as a result of a change made by
+the driver's <b><tt>put_params</tt></b> procedure), the driver must call
+<b><tt>gx_device_decache_colors(dev)</tt></b>.
+
+<dl>
+<dt><b><tt>gx_color_index (*map_rgb_color)(P4(gx_device&nbsp;*,
+gx_color_value&nbsp;red, gx_color_value&nbsp;green,
+gx_color_value&nbsp;blue))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>Map a RGB color to a device color. The range of legal values of the
+RGB arguments is 0 to <b><tt>gx_max_color_value</tt></b>. The default
+algorithm uses the <b><tt>map_cmyk_color</tt></b> procedure if the driver
+supplies one, otherwise returns 1 if any of the values exceeds
+<b><tt>gx_max_color_value</tt></b>&nbsp;/&nbsp;2, 0 otherwise.
+
+<p>
+Ghostscript assumes that for devices that have color capability (that is,
+<b><tt>color_info.num_components</tt></b> &gt; 1),
+<b><tt>map_rgb_color</tt></b> returns a color index for a gray level (as
+opposed to a non-gray color) iff red = green = blue.
+</dl>
+
+<dl>
+<dt><b><tt>gx_color_index (*map_cmyk_color)(P5(gx_device&nbsp;*,
+gx_color_value&nbsp;cyan, gx_color_value&nbsp;magenta,
+gx_color_value&nbsp;yellow, gx_color_value&nbsp;black))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>Map a CMYK color to a device color. The range of legal values of the
+CMYK arguments is 0 to <b><tt>gx_max_color_value</tt></b>. The default
+algorithm calls the <b><tt>map_rgb_color</tt></b> procedure, with suitably
+transformed arguments.
+
+<p>
+Ghostscript assumes that for devices that have color capability (that is,
+<b><tt>color_info.num_components</tt></b> &gt; 1),
+<b><tt>map_cmyk_color</tt></b> returns a color index for a gray level (as
+opposed to a non-gray color) iff cyan = magenta = yellow.
+</dl>
+
+<dl>
+<dt><b><tt>int (*map_color_rgb)(P3(gx_device&nbsp;*,
+gx_color_index&nbsp;color, gx_color_value&nbsp;rgb[3]))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>Map a device color code to RGB values. The default algorithm returns
+(0 if <b><tt>color</tt></b>==0 else <b><tt>gx_max_color_value</tt></b>) for
+all three components.
+</dl>
+
+<dl>
+<dt><b><tt>gx_color_index (*map_rgb_alpha_color)(P5(gx_device&nbsp;*,
+gx_color_value&nbsp;red, gx_color_value&nbsp;green,
+gx_color_value&nbsp;blue, gx_color_value&nbsp;alpha))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>Map a RGB color and an opacity value to a device color. The range of
+legal values of the RGB and alpha arguments is 0 to
+<b><tt>gx_max_color_value</tt></b>; <b><tt>alpha</tt></b> = 0 means
+transparent, <b><tt>alpha</tt></b> = <b><tt>gx_max_color_value</tt></b>
+means fully opaque. The default is to use the
+<b><tt>map_rgb_color</tt></b> procedure and ignore alpha.
+
+<p>
+Note that if a driver implements <b><tt>map_rgb_alpha_color</tt></b>, it
+must also implement <b><tt>map_rgb_color</tt></b>, and must implement them
+in such a way that
+<b><tt>map_rgb_alpha_color(dev,&nbsp;r,&nbsp;g,&nbsp;b,&nbsp;gx_max_color_value)</tt></b>
+returns the same value as
+<b><tt>map_rgb_color(dev,&nbsp;r,&nbsp;g,&nbsp;b)</tt></b>.
+</dl>
+
+<dl>
+<dt><b><tt>int (*map_color_rgb_alpha)(P3(gx_device&nbsp;*,
+gx_color_index&nbsp;color, gx_color_value&nbsp;rgba[4]))</tt></b>
+<b><em>[OPTIONAL]</em></b>
+<dd>Map a device color code to RGB and alpha values. The default
+implementation calls <b><tt>map_color_rgb</tt></b> and fills in
+<b><tt>gx_max_color_value</tt></b> for alpha.
+
+<p>
+Note that if a driver implements <b><tt>map_color_rgb_alpha</tt></b>, it
+must also implement <b><tt>map_color_rgb</tt></b>, and must implement them
+in such a way that the first 3 values returned by
+<b><tt>map_color_rgb_alpha</tt></b> are the same as the values returned by
+<b><tt>map_color_rgb</tt></b>.
+
+<p>
+Note that CMYK devices currently do not support variable opacity; alpha is
+ignored on such devices.
+</dl>
+
+<dl>
+<dt><b><tt>typedef&nbsp;enum&nbsp;{&nbsp;go_text,
+go_graphics&nbsp;}&nbsp;graphic_object_type;&nbsp;int
+(*get_alpha_bits)(P4(gx_device&nbsp;*dev,
+graphic_object_type&nbsp;type))</tt></b> <b><em>[OPTIONAL] [OBSOLETE]</em></b>
+<dd>This procedure is no longer used: it is replaced by the
+color_info.anti_alias member of the driver structure. However, it still
+appears in the driver procedure vector for backward compatibility. It
+should never be called, and drivers should not implement it.
+</dl>
+
+<h3><a name="Pixel_level_drawing"></a>Pixel-level drawing</h3>
+
+<p>
+This group of drawing operations specifies data at the pixel level. All
+drawing operations use device coordinates and device color values.
+
+<dl>
+<dt><b><tt>int (*fill_rectangle)(P6(gx_device&nbsp;*, int&nbsp;x,
+int&nbsp;y, int&nbsp;width, int&nbsp;height,
+gx_color_index&nbsp;color))</tt></b>
+<dd>Fill a rectangle with a color. The set of pixels filled is {(px,py) |
+x &lt;= px &lt; x + width and y &lt;= py &lt; y + height}. In other words,
+the point <em>(x,y)</em> is included in the rectangle, as are
+<em>(x+w-1,y)</em>, <em>(x,y+h-1)</em>, and <em>(x+w-1,y+h-1)</em>, but
+<b><em>not</em></b> <em>(x+w,y)</em>, <em>(x,y+h)</em>, or
+<em>(x+w,y+h)</em>. If <b><tt>width</tt></b>&nbsp;&lt;=&nbsp;0 or
+height&nbsp;&lt;=&nbsp;0, <b><tt>fill_rectangle</tt></b> should return 0
+without drawing anything.
+
+<p>
+Note that <b><tt>fill_rectangle</tt></b> is the only non-optional procedure
+in the driver interface.
+</dl>
+
+<h4><a name="Bitmap_imaging"></a>Bitmap imaging</h4>
+
+<p>
+Bitmap (or pixmap) images are stored in memory in a nearly standard way.
+The first byte corresponds to <em>(0,0)</em> in the image coordinate
+system: bits (or polybit color values) are packed into it left to right.
+There may be padding at the end of each scan line: the distance from one
+scan line to the next is always passed as an explicit argument.
+
+<dl>
+<dt><b><tt>int (*copy_mono)(P11(gx_device&nbsp;*,
+const&nbsp;unsigned&nbsp;char&nbsp;*data, int&nbsp;data_x, int&nbsp;raster,
+gx_bitmap_id&nbsp;id, int&nbsp;x, int&nbsp;y, int&nbsp;width,
+int&nbsp;height, gx_color_index&nbsp;color0,
+gx_color_index&nbsp;color1))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>Copy a monochrome image (similar to the PostScript image operator).
+Each scan line is raster bytes wide. Copying begins at
+(<b><tt>data_x</tt></b>,0) and transfers a rectangle of the given width and
+height to the device at device coordinate <em>(x,y)</em>. (If the transfer
+should start at some non-zero y value in the data, the caller can adjust
+the data address by the appropriate multiple of the raster.) The copying
+operation writes device color <b><tt>color0</tt></b> at each 0-bit, and
+<b><tt>color1</tt></b> at each 1-bit: if <b><tt>color0</tt></b> or
+<b><tt>color1</tt></b> is <b><tt>gx_no_color_index</tt></b>, the device
+pixel is unaffected if the image bit is 0 or 1 respectively. If
+<b><tt>id</tt></b> is different from <b><tt>gx_no_bitmap_id</tt></b>, it
+identifies the bitmap contents unambiguously; a call with the same
+<b><tt>id</tt></b> will always have the same <b><tt>data</tt></b>,
+<b><tt>raster</tt></b>, and data contents.
+
+<p>
+This operation, with
+<b><tt>color0</tt></b>&nbsp;=&nbsp;<b><tt>gx_no_color_index</tt></b>, is
+the workhorse for text display in Ghostscript, so implementing it
+efficiently is very important.
+</dl>
+
+<dl>
+<dt><b><tt>int (*tile_rectangle)(P10(gx_device&nbsp;*,
+const&nbsp;gx_tile_bitmap&nbsp;*tile, int&nbsp;x, int&nbsp;y,
+int&nbsp;width, int&nbsp;height, gx_color_index&nbsp;color0,
+gx_color_index&nbsp;color1, int&nbsp;phase_x, int&nbsp;phase_y))</tt></b>
+<b><em>[OPTIONAL] [OBSOLETE]</em></b>
+<dd>This procedure is still supported, but has been superseded by
+<b><tt>strip_tile_rectangle</tt></b>. New drivers should implement
+<b><tt>strip_tile_rectangle</tt></b>; if they cannot cope with non-zero
+shift values, they should test for this explicitly and call the default
+implementation (<b><tt>gx_default_strip_tile_rectangle</tt></b>) if
+shift&nbsp;!=&nbsp;0. Clients should call
+<b><tt>strip_tile_rectangle</tt></b>, not <b><tt>tile_rectangle</tt></b>.
+</dl>
+
+<dl>
+<dt><b><tt>int (*strip_tile_rectangle)(P10(gx_device&nbsp;*,
+const&nbsp;gx_strip_bitmap&nbsp;*tile, int&nbsp;x, int&nbsp;y,
+int&nbsp;width, int&nbsp;height, gx_color_index&nbsp;color0,
+gx_color_index&nbsp;color1, int&nbsp;phase_x, int&nbsp;phase_y))</tt></b>
+<b><em>[OPTIONAL]</em></b>
+<dd>Tile a rectangle. Tiling consists of doing multiple
+<b><tt>copy_mono</tt></b> operations to fill the rectangle with copies of
+the tile. The tiles are aligned with the device coordinate system, to
+avoid "seams". Specifically, the (<b><tt>phase_x</tt></b>,
+<b><tt>phase_y</tt></b>) point of the tile is aligned with the origin of
+the device coordinate system. (Note that this is backwards from the
+PostScript definition of halftone phase.) <b><tt>phase_x</tt></b> and
+<b><tt>phase_y</tt></b> are guaranteed to be in the range
+<em>[0..</em><b><tt>tile-&gt;width</tt></b><em>)</em> and
+<em>[0..</em><b><tt>tile-&gt;height</tt></b><em>)</em> respectively.
+
+<p>
+If <b><tt>color0</tt></b> and <b><tt>color1</tt></b> are both
+<b><tt>gx_no_color_index</tt></b>, then the tile is a color pixmap, not a
+bitmap: see the next section.
+
+<p>
+This operation is the workhorse for halftone filling in Ghostscript, so
+implementing it efficiently for solid tiles (that is, where either
+<b><tt>color0</tt></b> and <b><tt>color1</tt></b> are both
+<b><tt>gx_no_color_index</tt></b>, for colored halftones, or neither one is
+<b><tt>gx_no_color_index</tt></b>, for monochrome halftones) is very
+important.
+</dl>
+
+<h4><a name="Pixmap_imaging"></a>Pixmap imaging</h4>
+
+<p>
+Pixmaps are just like bitmaps, except that each pixel occupies more than
+one bit. All the bits for each pixel are grouped together (this is
+sometimes called "chunky" or "Z" format). For <b><tt>copy_color</tt></b>,
+the number of bits per pixel is given by the
+<b><tt>color_info.depth</tt></b> parameter in the device structure: the
+legal values are 1, 2, 4, 8, 16, 24, or 32. The pixel values are device
+color codes (that is, whatever it is that <b><tt>map_rgb_color</tt></b>
+returns).
+
+<dl>
+<dt><b><tt>int (*copy_color)(P9(gx_device&nbsp;*,
+const&nbsp;unsigned&nbsp;char&nbsp;*data, int&nbsp;data_x, int&nbsp;raster,
+gx_bitmap_id&nbsp;id, int&nbsp;x, int&nbsp;y, int&nbsp;width,
+int&nbsp;height))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>Copy a color image with multiple bits per pixel. The raster is in
+bytes, but <b><tt>x</tt></b> and <b><tt>width</tt></b> are in pixels, not
+bits. If <b><tt>id</tt></b> is different from
+<b><tt>gx_no_bitmap_id</tt></b>, it identifies the bitmap contents
+unambiguously; a call with the same <b><tt>id</tt></b> will always have the
+same <b><tt>data</tt></b>, <b><tt>raster</tt></b>, and data contents.
+
+<p>
+We do not provide a separate procedure for tiling with a pixmap; instead,
+<b><tt>tile_rectangle</tt></b> can also take colored tiles. This is
+indicated by the <b><tt>color0</tt></b> and <b><tt>color1</tt></b>
+arguments' both being <b><tt>gx_no_color_index</tt></b>. In this case, as
+for <b><tt>copy_color</tt></b>, the <b><tt>raster</tt></b> and
+<b><tt>height</tt></b> in the "bitmap" are interpreted as for real bitmaps,
+but the <b><tt>x</tt></b> and <b><tt>width</tt></b> are in pixels, not
+bits.
+</dl>
+
+<h4><a name="Compositing"></a>Compositing</h4>
+
+<p>
+In addition to direct writing of opaque pixels, devices must also support
+compositing. Currently two kinds of compositing are defined
+(<b><tt>RasterOp</tt></b> and alpha-based), but more may be added in the
+future.
+
+<blockquote>
+<b><em>THIS AREA OF THE INTERFACE IS SOMEWHAT UNSTABLE: USE AT YOUR OWN
+RISK.</em></b>
+</blockquote>
+
+<dl>
+<dt><b><tt>int (*copy_alpha)(P11(gx_device&nbsp;*dev,
+const&nbsp;unsigned&nbsp;char&nbsp;*data, int&nbsp;data_x, int&nbsp;raster,
+gx_bitmap_id&nbsp;id, int&nbsp;x, int&nbsp;y, int&nbsp;width,
+int&nbsp;height, gx_color_index&nbsp;color, int&nbsp;depth))</tt></b>
+<b><em>[OPTIONAL]</em></b>
+<dd>This procedure is somewhat misnamed: it was added to the interface
+before we really understood alpha channel and compositing.
+
+<p>
+Fill a given region with a given color modified by an individual alpha
+value for each pixel. For each pixel, this is equivalent to
+alpha-compositing with a source pixel whose alpha value is obtained from
+the pixmap (<b><tt>data</tt></b>, <b><tt>data_x</tt></b>, and
+<b><tt>raster</tt></b>) and whose color is the given color (which has
+<b><em>not</em></b> been premultiplied by the alpha value), using the Sover
+rule. <b><tt>depth</tt></b>, the number of bits per alpha value, is either
+2 or 4, and in any case is always a value returned by a previous call on
+the <b><tt>get_alpha_bits</tt></b> procedure. Note that if
+<b><tt>get_alpha_bits</tt></b> always returns 1, this procedure will never
+be called.
+</dl>
+
+<dl>
+<dt><b><tt>int (*create_compositor)(P5(dev_t&nbsp;*dev,
+gx_device_t&nbsp;**pcdev, const&nbsp;gs_composite_t&nbsp;*pcte,
+const&nbsp;gs_imager_state&nbsp;*pis, gs_memory_t&nbsp;*memory))</tt></b>
+<b><em>[OPTIONAL]</em></b>
+<dd>Create a new device (called a "compositing device" or "compositor")
+that will composite data written to it with the device's existing data,
+according to the compositing function defined by <b><tt>*pcte</tt></b>.
+Devices will normally implement this in one of the following standard ways:
+
+<ul>
+<li>Devices that don't do any imaging and don't forward any imaging
+operations (for example, the null device, the hit detection device, and the
+clipping list accumulation device) simply return themselves, which
+effectively ignores the compositing function.
+
+<li>"Leaf" devices that do imaging and have no special optimizations for
+compositing (for example, some memory devices) ask the
+<b><tt>gs_composite_t</tt></b> to create a default compositor.
+
+<li>Leaf devices that can implement some kinds of compositing operation
+efficiently (for example, monobit memory devices and RasterOp) inspect the
+type and values of <b><tt>*pcte</tt></b> to determine whether it specifies
+such an operation: if so, they create a specialized compositor, and if not,
+they ask the <b><tt>gs_composite_t</tt></b> to create a default compositor.
+</ul>
+
+<p>
+Other kinds of forwarding devices, which don't fall into any of these
+categories, require special treatment. In principle, what they do is ask
+their target to create a compositor, and then create and return a copy of
+themselves with the target's new compositor as the target of the copy.
+There is a possible default implementation of this approach: if the
+original device was <b>D</b> with target <b>T</b>, and <b>T</b> creates a
+compositor <b>C</b>, then the default implementation creates a device
+<b>F</b> that for each operation temporarily changes <b>D</b>'s target to
+<b>C</b>, forwards the operation to <b>D</b>, and then changes <b>D</b>'s
+target back to <b>T</b>. However, the Ghostscript library currently only
+creates a compositor with an imaging forwarding device as target in a few
+specialized situations (banding, and bounding box computation), and these
+are handled as special cases.
+
+<p>
+Note that the compositor may have a different color space, color
+representation, or bit depth from the device to which it is compositing.
+For example, alpha-compositing devices use standard-format chunky color
+even if the underlying device doesn't.
+
+<p>
+Closing a compositor frees all of its storage, including the compositor
+itself. However, since the <b><tt>create_compositor</tt></b> call may
+return the same device, clients must check for this case, and only call the
+close procedure if a separate device was created.
+</dl>
+
+<p>
+<font size="+1">
+<b><em>[strip_]copy_rop WILL BE SUPERSEDED BY COMPOSITORS</em></b>
+</font>
+
+<dl>
+<dt><b><tt>int (*copy_rop)(P15(gx_device&nbsp;*dev,
+const&nbsp;byte&nbsp;*sdata, int&nbsp;sourcex, uint&nbsp;sraster,
+gx_bitmap_id&nbsp;id, const&nbsp;gx_color_index&nbsp;*scolors,
+const&nbsp;gx_tile_bitmap&nbsp;*texture,
+const&nbsp;gx_color_index&nbsp;*tcolors, int&nbsp;x, int&nbsp;y,
+int&nbsp;width, int&nbsp;height, int&nbsp;phase_x, int&nbsp;phase_y,
+int&nbsp;command))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>This procedure is still supported, but has been superseded by
+<b><tt>strip_copy_rop</tt></b>. New drivers should implement
+<b><tt>strip_copy_rop</tt></b>; if they cannot cope with non-zero shift
+values in the texture, they should test for this explicitly and call the
+default implementation (<b><tt>gx_default_strip_copy_rop</tt></b>) if
+shift&nbsp;!=&nbsp;0. Clients should call <b><tt>strip_copy_rop</tt></b>,
+not <b><tt>copy_rop</tt></b>.
+</dl>
+
+<dl>
+<dt><b><tt>int (*strip_copy_rop)(P15(gx_device&nbsp;*dev,
+const&nbsp;byte&nbsp;*sdata, int&nbsp;sourcex, uint&nbsp;sraster,
+gx_bitmap_id&nbsp;id, const&nbsp;gx_color_index&nbsp;*scolors,
+const&nbsp;gx_strip_bitmap&nbsp;*texture,
+const&nbsp;gx_color_index&nbsp;*tcolors, int&nbsp;x, int&nbsp;y,
+int&nbsp;width, int&nbsp;height, int&nbsp;phase_x, int&nbsp;phase_y,
+int&nbsp;command))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>Combine an optional source image <b>S</b> (as for
+<b><tt>copy_mono</tt></b> or <b><tt>copy_color</tt></b>) and an optional
+texture <b>T</b> (a tile, as for <b><tt>tile_rectangle</tt></b>) with the
+existing bitmap or pixmap <b>D</b> held by the driver, pixel by pixel,
+using any 3-input Boolean operation as modified by "transparency" flags:
+schematically, set <b>D&nbsp;=&nbsp;f(D,S,T)</b>, computing <b>f</b> in RGB
+space rather than using actual device pixel values. <b>S</b> and <b>T</b>
+may each (independently) be a solid color, a bitmap with "foreground" and
+"background" colors, or a pixmap. This is a complex (and currently rather
+slow) operation. The arguments are as follows:
+
+<blockquote><table cellpadding=0 cellspacing=0>
+<tr valign=top> <td><b><tt>dev</tt></b>
+ <td>&nbsp;
+ <td>the device, as for all driver procedures
+<tr valign=top> <td><b><tt>sdata</tt></b>, <b><tt>sourcex</tt></b>, <b><tt>sraster</tt></b>, <b><tt>id</tt></b>, <b><tt>scolors</tt></b>
+ <td>&nbsp;
+ <td>specify <b>S</b>, <a href="#S_spec">see below</a>
+<tr valign=top> <td><b><tt>texture</tt></b>, <b><tt>tcolors</tt></b>
+ <td>&nbsp;
+ <td>specify <b>T</b>, <a href="#T_spec">see below</a>
+<tr valign=top> <td><b><tt>x</tt></b>, <b><tt>y</tt></b>, <b><tt>width</tt></b>, <b><tt>height</tt></b>
+ <td>&nbsp;
+ <td>as for the other copy and fill procedures
+<tr valign=top> <td><b><tt>phase_x</tt></b>, <b><tt>phase_y</tt></b>
+ <td>&nbsp;
+ <td>part of <b>T</b> specification, <a href="#T_spec">see below</a>
+<tr valign=top> <td><b><tt>command</tt></b>
+ <td>&nbsp;
+ <td><a href="#F_spec">see below</a>
+</table></blockquote>
+</dl>
+
+<h5><a name="S_spec"></a>The source specification S</h5>
+
+<p>
+As noted above, the source <b>S</b> may be a solid color, a bitmap, or a
+pixmap. If <b>S</b> is a solid color:
+
+<ul>
+<li><b><tt>sdata</tt></b>, <b><tt>sourcex</tt></b>,
+<b><tt>sraster</tt></b>, and <b><tt>id</tt></b> are irrelevant.
+
+<li><b><tt>scolors</tt></b> points to two <b><tt>gx_color_index</tt></b>
+values; <b><tt>scolors[0]</tt></b> = <b><tt>scolors[1]</tt></b> = the
+color.
+</ul>
+
+<p>
+If <b>S</b> is a bitmap:
+
+<ul>
+<li><b><tt>sdata</tt></b>, <b><tt>sourcex</tt></b>,
+<b><tt>sraster</tt></b>, and <b><tt>id</tt></b> arguments are as for
+<b><tt>copy_mono</tt></b> or <b><tt>copy_color</tt></b>
+(<b><tt>data</tt></b>, <b><tt>data_x</tt></b>, <b><tt>raster</tt></b>,
+<b><tt>id</tt></b>), and specify a source bitmap.
+
+<li><b><tt>scolors</tt></b> points to two <b><tt>gx_color_index</tt></b>
+values; <b><tt>scolors[0]</tt></b> is the background color (the color
+corresponding to 0-bits in the bitmap), <b><tt>scolors[1]</tt></b> is the
+foreground color (the color corresponding to 1-bits in the bitmap).
+</ul>
+
+<p>
+If <b>S</b> is a pixmap:
+
+<ul>
+<li><b><tt>sdata</tt></b>, <b><tt>sourcex</tt></b>,
+<b><tt>sraster</tt></b>, and <b><tt>id</tt></b> arguments are as for
+<b><tt>copy_mono</tt></b> or <b><tt>copy_color</tt></b>
+(<b><tt>data</tt></b>, <b><tt>data_x</tt></b>, <b><tt>raster</tt></b>,
+<b><tt>id</tt></b>), and specify a source pixmap whose depth is the same as
+the depth of the destination.
+
+<li><b><tt>scolors</tt></b> is <b><tt>NULL</tt></b>.
+</ul>
+
+<p>
+Note that if the source is a bitmap with background=0 and foreground=1, and
+the destination is 1 bit deep, then the source can be treated as a pixmap
+(scolors=<b><tt>NULL</tt></b>).
+
+<h5><a name="T_spec"></a>The texture specification T</h5>
+
+<p>
+Similar to the source, the texture <b>T</b> may be a solid color, a bitmap,
+or a pixmap. If <b>T</b> is a solid color:
+
+<ul>
+<li>The texture pointer is irrelevant.
+
+<li><b><tt>tcolors</tt></b> points to two <b><tt>gx_color_index</tt></b>
+values; <b><tt>tcolors[0]</tt></b> = <b><tt>tcolors[1]</tt></b> = the
+color.
+</ul>
+
+<p>
+If <b>T</b> is a bitmap:
+
+<ul>
+<li>The texture argument points to a <b><tt>gx_tile_bitmap</tt></b>, as for
+the <b><tt>tile_rectangle</tt></b> procedure. Similarly,
+<b><tt>phase_x</tt></b> and <b><tt>phase_y</tt></b> specify the offset of
+the texture relative to the device coordinate system origin, again as for
+<b><tt>tile_rectangle</tt></b>. The tile is a bitmap (1 bit per pixel).
+
+<li><b><tt>tcolors</tt></b> points to two <b><tt>gx_color_index</tt></b>
+values; <b><tt>tcolors[0]</tt></b> is the background color (the color
+corresponding to 0-bits in the bitmap), <b><tt>tcolors[1]</tt></b> is the
+foreground color (the color corresponding to 1-bits in the bitmap).
+</ul>
+
+<p>
+If <b>T</b> is a pixmap:
+
+<ul>
+<li>The texture argument points to a <b><tt>gx_tile_bitmap</tt></b> whose
+depth is the same as the depth of the destination.
+
+<li>tcolors is <b><tt>NULL</tt></b>.
+</ul>
+
+<p>
+Again, if the texture is a bitmap with background=0 and foreground=1, and
+the destination depth is 1, the texture bitmap can be treated as a pixmap
+(tcolors=<b><tt>NULL</tt></b>).
+
+<p>
+Note that while a source bitmap or pixmap has the same width and height as
+the destination, a texture bitmap or pixmap has its own width and height
+specified in the <b><tt>gx_tile_bitmap</tt></b> structure, and is
+replicated or clipped as needed.
+
+<h5><a name="F_spec"></a>The function specification f</h5>
+
+<p>
+"Command" indicates the raster operation and transparency as follows:
+
+<blockquote><table cellpadding=0 cellspacing=0>
+<tr valign=bottom>
+ <th>Bits
+ <td>&nbsp;
+ <td>&nbsp;
+<tr valign=top> <td>7-0
+ <td>&nbsp;
+ <td>raster op
+<tr valign=top> <td>8
+ <td>&nbsp;
+ <td>0 if source opaque, 1 if source transparent
+<tr valign=top> <td>9
+ <td>&nbsp;
+ <td>0 if texture opaque, 1 if texture transparent
+<tr valign=top> <td>?-10
+ <td>&nbsp;
+ <td>unused, must be 0
+</table></blockquote>
+
+<p>
+The raster operation follows the Microsoft and H-P specification. It is an
+8-element truth table that specifies the output value for each of the
+possible 2&times;2&times;2 input values as follows:
+
+<blockquote><table cellpadding=0 cellspacing=0>
+<tr valign=bottom>
+ <th>Bit
+ <td>&nbsp;
+ <th>Texture
+ <td>&nbsp;
+ <th>Source
+ <td>&nbsp;
+ <th>Destination
+<tr> <td colspan=7><hr>
+<tr valign=top> <td align=center>7
+ <td>&nbsp;
+ <td align=center>1
+ <td>&nbsp;
+ <td align=center>1
+ <td>&nbsp;
+ <td align=center>1
+<tr valign=top> <td align=center>6
+ <td>&nbsp;
+ <td align=center>1
+ <td>&nbsp;
+ <td align=center>1
+ <td>&nbsp;
+ <td align=center>0
+<tr valign=top> <td align=center>5
+ <td>&nbsp;
+ <td align=center>1
+ <td>&nbsp;
+ <td align=center>0
+ <td>&nbsp;
+ <td align=center>1
+<tr valign=top> <td align=center>4
+ <td>&nbsp;
+ <td align=center>1
+ <td>&nbsp;
+ <td align=center>0
+ <td>&nbsp;
+ <td align=center>0
+<tr valign=top> <td align=center>3
+ <td>&nbsp;
+ <td align=center>0
+ <td>&nbsp;
+ <td align=center>1
+ <td>&nbsp;
+ <td align=center>1
+<tr valign=top> <td align=center>2
+ <td>&nbsp;
+ <td align=center>0
+ <td>&nbsp;
+ <td align=center>1
+ <td>&nbsp;
+ <td align=center>0
+<tr valign=top> <td align=center>1
+ <td>&nbsp;
+ <td align=center>0
+ <td>&nbsp;
+ <td align=center>0
+ <td>&nbsp;
+ <td align=center>1
+<tr valign=top> <td align=center>0
+ <td>&nbsp;
+ <td align=center>0
+ <td>&nbsp;
+ <td align=center>0
+ <td>&nbsp;
+ <td align=center>0
+</table></blockquote>
+
+<p>
+Transparency affects the output in the following way. A source or texture
+pixel is considered transparent if its value is all 1s (for instance, 1 for
+bitmaps, <tt>0xffffff</tt> for 24-bit RGB pixmaps) <b><em>and</em></b> the
+corresponding transparency bit is set in the command. For each pixel, the
+result of the Boolean operation is written into the destination iff neither
+the source nor the texture pixel is transparent. (Note that the H-P
+RasterOp specification, on which this is based, specifies that if the
+source and texture are both all 1s and the command specifies transparent
+source and opaque texture, the result <b><em>should</em></b> be written in
+the output. We think this is an error in the documentation.)
+
+<h5><a name="Compositing_notes"></a>Notes</h5>
+
+<p>
+<b><tt>copy_rop</tt></b> is defined to operate on pixels in RGB space,
+again following the H-P and Microsoft specification. For devices that
+don't use RGB (or gray-scale with black = 0, white = all 1s) as their
+native color representation, the implementation of <b><tt>copy_rop</tt></b>
+must convert to RGB or gray space, do the operation, and convert back (or
+do the equivalent of this). Here are the <b><tt>copy_rop</tt></b>
+equivalents of the most important previous imaging calls. We assume the
+declaration:
+
+<blockquote><b><tt>
+static const gx_color_index white2[2] = { 1, 1 };
+</tt></b></blockquote>
+
+<p>
+Note that <b><tt>rop3_S</tt></b> may be replaced by any other Boolean operation.
+For monobit devices, we assume that black = 1.
+
+<blockquote>
+<pre>/* For all devices: */
+(*fill_rectangle)(dev, x, y, w, h, color) ==&gt;
+
+ { gx_color_index colors[2];
+ colors[0] = colors[1] = color;
+ (*dev_proc(dev, copy_rop))(dev, NULL, 0, 0, gx_no_bitmap_id, colors,
+ NULL, colors /*irrelevant*/,
+ x, y, w, h, 0, 0, rop3_S);
+ }
+
+/* For black-and-white devices only: */
+(*copy_mono)(dev, base, sourcex, sraster, id,
+ x, y, w, h, (gx_color_index)0, (gx_color_index)1) ==&gt;
+
+ (*dev_proc(dev, copy_rop))(dev, base, sourcex, sraster, id, NULL,
+ NULL, white2 /*irrelevant*/,
+ x, y, w, h, 0, 0, rop3_S);
+
+/* For color devices, where neither color0 nor color1 is gx_no_color_index: */
+(*copy_mono)(dev, base, sourcex, sraster, id,
+ x, y, w, h, color0, color1) ==&gt;
+
+ { gx_color_index colors[2];
+ colors[0] = color0, colors[1] = color1;
+ (*dev_proc(dev, copy_rop))(dev, base, sourcex, sraster, id, colors,
+ NULL, white2 /*irrelevant*/,
+ x, y, w, h, 0, 0, rop3_S);
+ }
+
+/* For black-and-white devices only: */
+(*copy_mono)(dev, base, sourcex, sraster, id,
+ x, y, w, h, gx_no_color_index, (gx_color_index)1) ==&gt;
+
+ (*dev_proc(dev, copy_rop))(dev, base, sourcex, sraster, id, NULL,
+ NULL, white2 /*irrelevant*/,
+ x, y, w, h, 0, 0,
+ rop3_S | lop_S_transparent);
+
+/* For all devices: */
+(*copy_color)(dev, base, sourcex, sraster, id,
+ x, y, w, h) ==&gt; [same as first copy_mono above]
+
+/* For black-and-white devices only: */
+(*tile_rectangle)(dev, tile, x, y, w, h,
+ (gx_color_index)0, (gx_color_index)1, px, py) ==&gt;
+
+ (*dev_proc(dev, copy_rop))(dev, NULL, 0, 0, gx_no_bitmap_id,
+ white2 /*irrelevant*/,
+ tile, NULL,
+ x, y, w, h, px, py, rop3_T)
+</pre></blockquote>
+
+<h3><a name="Polygon_level_drawing"></a>Polygon-level drawing</h3>
+
+<p>
+In addition to the pixel-level drawing operations that take integer device
+coordinates and pure device colors, the driver interface includes
+higher-level operations that draw polygons using fixed-point coordinates,
+possibly halftoned colors, and possibly a non-default logical operation.
+
+<p>
+The <b><tt>fill_</tt></b>* drawing operations all use the center-of-pixel
+rule: a pixel is colored iff its center falls within the polygonal region
+being filled. If a pixel center <em>(X+0.5,Y+0.5)</em> falls exactly on
+the boundary, the pixel is filled iff the boundary is horizontal and the
+filled region is above it, or the boundary is not horizontal and the filled
+region is to the right of it.
+
+<dl>
+<dt><b><tt>int (*fill_trapezoid)(P10(gx_device&nbsp;*dev,
+const&nbsp;gs_fixed_edge&nbsp;*left, const&nbsp;gs_fixed_edge&nbsp;*right,
+fixed&nbsp;ybot, fixed&nbsp;ytop, bool&nbsp;swap_axes,
+const&nbsp;gx_drawing_color&nbsp;*pdcolor,
+gs_logical_operation_t&nbsp;lop))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>Fill a trapezoid. The bottom and top edges are parallel to the x
+axis, and are defined by <b><tt>ybot</tt></b> and <b><tt>ytop</tt></b>,
+respectively. The left and right edges are defined by <b><tt>left</tt></b>
+and <b><tt>right</tt></b>. Both of these respresent lines (<b><tt>gs_fixed_edge</tt></b>
+is defined in <a href="../src/gxdevcli.h">gxdevcli.h</a> and consists
+of <b><tt>gs_fixed_point</tt></b> <b><tt>start</tt></b> and <b><tt>end</tt></b> points).
+The y coordinates of these lines need not have any specific relation to
+<b><tt>ybot</tt></b> and <b><tt>ytop</tt></b>. The routine is defined this way so
+that the filling algorithm can subdivide edges and still guarantee
+that the exact same pixels will be filled. If
+<b><tt>swap_axes</tt></b> is set, the meanings of X and Y are
+interchanged.
+</dl>
+
+<dl>
+<dt><b><tt>int (*fill_parallelogram)(P9(gx_device&nbsp;*dev,
+fixed&nbsp;px, fixed&nbsp;py, fixed&nbsp;ax, fixed&nbsp;ay, fixed&nbsp;bx,
+fixed&nbsp;by, const&nbsp;gx_drawing_color&nbsp;*pdcolor,
+gs_logical_operation_t&nbsp;lop))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>Fill a parallelogram whose corners are <em>(px,py)</em>,
+<em>(px+ax,py+ay)</em>, <em>(px+bx,py+by)</em>, and
+<em>(px+ax+bx,py+ay+by)</em>. There are no constraints on the values of
+any of the parameters, so the parallelogram may have any orientation
+relative to the coordinate axes.
+</dl>
+
+<dl>
+<dt><b><tt>int (*fill_triangle)(P9(gx_device&nbsp;*dev, fixed&nbsp;px,
+fixed&nbsp;py, fixed&nbsp;ax, fixed&nbsp;ay, fixed&nbsp;bx, fixed&nbsp;by,
+const&nbsp;gx_drawing_color&nbsp;*pdcolor,
+gs_logical_operation_t&nbsp;lop))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>Fill a triangle whose corners are <em>(px,py)</em>,
+<em>(px+ax,py+ay)</em>, and <em>(px+bx,py+by)</em>.
+</dl>
+
+<dl>
+<dt><b><tt>int (*draw_thin_line)(P7(gx_device&nbsp;*dev,
+fixed&nbsp;fx0, fixed&nbsp;fy0, fixed&nbsp;fx1, fixed&nbsp;fy1,
+const&nbsp;gx_drawing_color&nbsp;*pdcolor,
+gs_logical_operation_t&nbsp;lop))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>Draw a one-pixel-wide line from <em>(fx0,fy0)</em> to
+<em>(fx1,fy1)</em>.
+</dl>
+
+<dl>
+<dt><b><tt>int (*draw_line)(P6(gx_device&nbsp;*dev, int&nbsp;x0, int&nbsp;y0,
+int&nbsp;x1, int&nbsp;y1, gx_color_index&nbsp;color))</tt></b>
+<b><em>[OPTIONAL] [OBSOLETE]</em></b>
+<dd>This procedure is no longer used: it is replaced by the draw_thin_line
+procedure. However, still appears in the driver procedure vector for
+backward compatibility. It should never be called, and drivers should not
+implement it.
+</dl>
+
+<h3><a name="High_level_drawing"></a>High-level drawing</h3>
+
+<p>
+In addition to the lower-level drawing operations described above, the
+driver interface provides a set of high-level operations. Normally these
+will have their default implementation, which converts the high-level
+operation to the low-level ones just described; however, drivers that
+generate high-level output formats such as CGM, or communicate with devices
+that have firmware for higher-level operations such as polygon fills, may
+implement these high-level operations directly. For more details, please
+consult the source code, specifically:
+
+<blockquote><table cellpadding=0 cellspacing=0>
+<tr valign=top> <th align=left>Header
+ <td>&nbsp;&nbsp;&nbsp;
+ <th align=left>Defines
+<tr valign=top> <td><a href="../src/gxpaint.h">gxpaint.h</a>
+ <td>&nbsp;
+ <td><b><tt>gx_fill_params</tt></b>, <b><tt>gx_stroke_params</tt></b>
+<tr valign=top> <td><a href="../src/gxfixed.h">gxfixed.h</a>
+ <td>&nbsp;
+ <td><b><tt>fixed</tt></b>, <b><tt>gs_fixed_point</tt></b> (used by
+ <b><tt>gx_*_params</tt></b>)
+<tr valign=top> <td><a href="../src/gxistate.h">gxistate.h</a>
+ <td>&nbsp;
+ <td><b><tt>gs_imager_state</tt></b> (used by <b><tt>gx_*_params</tt></b>)
+<tr valign=top> <td><a href="../src/gxline.h">gxline.h</a>
+ <td>&nbsp;
+ <td><b><tt>gx_line_params</tt></b> (used by <b><tt>gs_imager_state</tt></b>)
+<tr valign=top> <td><a href="../src/gslparam.h">gslparam.h</a>
+ <td>&nbsp;
+ <td>line cap/join values (used by <b><tt>gx_line_params</tt></b>)
+<tr valign=top> <td><a href="../src/gxmatrix.h">gxmatrix.h</a>
+ <td>&nbsp;
+ <td><b><tt>gs_matrix_fixed</tt></b> (used by <b><tt>gs_imager_state</tt></b>)
+<tr valign=top> <td><a href="../src/gspath.h">gspath.h</a>, <a href="../src/gxpath.h">gxpath.h</a>, <a href="../src/gzpath.h">gzpath.h</a>
+ <td>&nbsp;
+ <td><b><tt>gx_path</tt></b>
+<tr valign=top> <td><a href="../src/gxcpath.h">gxcpath.h</a>, <a href="../src/gzcpath.h">gzcpath.h</a>
+ <td>&nbsp;
+ <td><b><tt>gx_clip_path</tt></b>
+</table></blockquote>
+
+<p>
+For a minimal example of how to implement the high-level drawing operations,
+see <a href="../src/gdevtrac.c">gdevtrac.c</a>.
+
+<h4><a name="Paths"></a>Paths</h4>
+
+<dl>
+<dt><b><tt>int (*fill_path)(P6(gx_device&nbsp;*dev,
+const&nbsp;gs_imager_state&nbsp;*pis, gx_path&nbsp;*ppath,
+const&nbsp;gx_fill_params&nbsp;*params,
+const&nbsp;gx_drawing_color&nbsp;*pdcolor,
+const&nbsp;gx_clip_path&nbsp;*pcpath))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>Fill the given path, clipped by the given clip path, according to the
+given parameters, with the given color. The clip path pointer may be
+<b><tt>NULL</tt></b>, meaning do not clip.
+</dl>
+
+<dl>
+<dt><b><tt>int (*stroke_path)(P6(gx_device&nbsp;*dev,
+const&nbsp;gs_imager_state&nbsp;*pis, gx_path&nbsp;*ppath,
+const&nbsp;gx_stroke_params&nbsp;*params,
+const&nbsp;gx_drawing_color&nbsp;*pdcolor,
+const&nbsp;gx_clip_path&nbsp;*pcpath))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>Stroke the given path, clipped by the given clip path, according to the
+given parameters, with the given color. The clip path pointer may be
+<b><tt>NULL</tt></b>, meaning not to clip.
+</dl>
+
+<dl>
+<dt><b><tt>int (*fill_mask)(P13(gx_device&nbsp;*dev,
+const&nbsp;byte&nbsp;*data, int&nbsp;data_x, int&nbsp;raster,
+gx_bitmap_id&nbsp;id, int&nbsp;x, int&nbsp;y, int&nbsp;width,
+int&nbsp;height, const&nbsp;gx_drawing_color&nbsp;*pdcolor, int&nbsp;depth,
+int&nbsp;command, const&nbsp;gx_clip_path&nbsp;*pcpath))</tt></b>
+<b><em>[OPTIONAL]</em></b>
+<dd>Color the 1-bits in the given mask (or according to the alpha values,
+if <b><tt>depth</tt></b>&nbsp;&gt;&nbsp;1), clipped by the given clip path,
+with the given color and logical operation. The clip path pointer may be
+<b><tt>NULL</tt></b>, meaning do not clip. The parameters
+<b><tt>data</tt></b>, ..., <b><tt>height</tt></b> are as for
+<b><tt>copy_mono</tt></b>; depth is as for <b><tt>copy_alpha</tt></b>;
+command is as for <b><tt>copy_rop</tt></b>.
+</dl>
+
+<h4><a name="Images"></a>Images</h4>
+
+<p>
+Similar to the high-level interface for fill and stroke graphics, a high-level
+interface exists for bitmap images. The procedures in this part of the
+interface are optional.
+
+<p>
+Bitmap images come in a variety of types, corresponding closely (but not
+precisely) to the PostScript ImageTypes. The generic or common part of all
+bitmap images is defined by:
+
+<blockquote>
+<pre>typedef struct {
+ const gx_image_type_t *type;
+ gs_matrix ImageMatrix;
+} gs_image_common_t;</pre>
+</blockquote>
+
+<p>
+Bitmap images that supply data (all image types except
+<b><tt>image_type_from_device</tt></b> (2)) are defined by:
+
+<blockquote>
+<pre>#define gs_image_max_components 5
+typedef struct {
+ &lt;&lt; gs_image_common_t &gt;&gt;
+ int Width;
+ int Height;
+ int BitsPerComponent;
+ float Decode[gs_image_max_components * 2];
+ bool Interpolate;
+} gs_data_image_t;</pre>
+</blockquote>
+
+<p>
+Images that supply pixel (as opposed to mask) data are defined by:
+
+<blockquote>
+<pre>typedef enum {
+ /* Single plane, chunky pixels. */
+ gs_image_format_chunky = 0,
+ /* num_components planes, chunky components. */
+ gs_image_format_component_planar = 1,
+ /* BitsPerComponent * num_components planes, 1 bit per plane */
+ gs_image_format_bit_planar = 2
+} gs_image_format_t;
+typedef struct {
+ &lt;&lt; gs_data_image_t &gt;&gt;
+ const gs_color_space *ColorSpace;
+ bool CombineWithColor;
+} gs_pixel_image_t;</pre>
+</blockquote>
+
+<p>
+Ordinary PostScript Level 1 or Level 2 (<b><tt>ImageType</tt></b> 1) images
+are defined by:
+
+<blockquote>
+<pre>typedef enum {
+ /* No alpha. */
+ gs_image_alpha_none = 0,
+ /* Alpha precedes color components. */
+ gs_image_alpha_first,
+ /* Alpha follows color components. */
+ gs_image_alpha_last
+} gs_image_alpha_t;
+typedef struct {
+ &lt;&lt; gs_pixel_image_t &gt;&gt;
+ bool ImageMask;
+ bool adjust;
+ gs_image_alpha_t Alpha;
+} gs_image1_t;
+typedef gs_image1_t gs_image_t;</pre>
+</blockquote>
+
+<p>
+Of course, standard PostScript images don't have an alpha component. For
+more details, consult the source code in <a
+href="../src/gsiparam.h">gsiparam.h</a> and <b><tt>gsiparm*.h</tt></b>,
+which define parameters for an image.
+
+<p>
+The <b><tt>begin[_typed_]image</tt></b> driver procedures create image
+enumeration structures. The common part of these structures consists of:
+
+<blockquote>
+<pre>typedef struct gx_image_enum_common_s {
+ const gx_image_type_t *image_type;
+ const gx_image_enum_procs_t *procs;
+ gx_device *dev;
+ gs_id id;
+ int num_planes;
+ int plane_depths[gs_image_max_planes]; /* [num_planes] */
+ int plane_widths[gs_image_max_planes] /* [num_planes] */
+} gx_image_enum_common_t;</pre>
+</blockquote>
+
+<p>
+where <b><tt>procs</tt></b> consists of:
+
+<blockquote>
+<pre>typedef struct gx_image_enum_procs_s {
+
+ /*
+ * Pass the next batch of data for processing.
+ */
+#define image_enum_proc_plane_data(proc)\
+ int proc(P4(gx_device *dev,\
+ gx_image_enum_common_t *info, const gx_image_plane_t *planes,\
+ int height))
+
+ image_enum_proc_plane_data((*plane_data));
+
+ /*
+ * End processing an image, freeing the enumerator.
+ */
+#define image_enum_proc_end_image(proc)\
+ int proc(P3(gx_device *dev,\
+ gx_image_enum_common_t *info, bool draw_last))
+
+ image_enum_proc_end_image((*end_image));
+
+ /*
+ * Flush any intermediate buffers to the target device.
+ * We need this for situations where two images interact
+ * (currently, only the mask and the data of ImageType 3).
+ * This procedure is optional (may be 0).
+ */
+#define image_enum_proc_flush(proc)\
+ int proc(P1(gx_image_enum_common_t *info))
+
+ image_enum_proc_flush((*flush));
+
+} gx_image_enum_procs_t;</pre>
+</blockquote>
+
+<p> In other words, <b><tt>begin[_typed]_image</tt></b> sets up an
+enumeration structure that contains the procedures that will process the
+image data, together with all variables needed to maintain the state of the
+process. Since this is somewhat tricky to get right, if you plan to create
+one of your own you should probably read an existing implementation of
+<b><tt>begin[_typed]_image</tt></b>, such as the one in <a
+href="../src/gdevbbox.c">gdevbbox.c</a> or <a
+href="../src/gdevps.c">gdevps.c</a>.
+
+<p>
+The data passed at each call of <b><tt>image_plane_data</tt></b> consists of
+one or more planes, as appropriate for the type of image.
+<b><tt>begin[_typed]_image</tt></b> must initialize the
+<b><tt>plane_depths</tt></b> array in the enumeration structure with the
+depths (bits per element) of the planes. The array of
+<b><tt>gx_image_plane_t</tt></b> structures passed to each call of
+<b><tt>image_plane_data</tt></b> then defines where the data are stored, as
+follows:
+
+<blockquote>
+<pre>typedef struct gx_image_plane_s {
+ const byte *data;
+ int data_x;
+ uint raster;
+} gx_image_plane_t;</pre>
+</blockquote>
+
+<dl>
+<dt><b><tt>int (*begin_image)(P9(gx_device&nbsp;*dev,
+const&nbsp;gs_imager_state&nbsp;*pis, const&nbsp;gs_image_t&nbsp;*pim,
+gs_image_format_t&nbsp;format, gs_int_rect&nbsp;*prect,
+const&nbsp;gx_drawing_color&nbsp;*pdcolor,
+const&nbsp;gx_clip_path&nbsp;*pcpath, gs_memory_t&nbsp;*memory,
+gx_image_enum_common_t&nbsp;**pinfo))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>Begin the transmission of an image. Zero or more calls of
+<b><tt>image_plane_data</tt></b> will follow, and then a call of
+<b><tt>end_image</tt></b>. The parameters of <b><tt>begin_image</tt></b>
+are as follows:
+
+<blockquote><table cellpadding=0 cellspacing=0>
+<tr valign=top> <td><b><tt>pis</tt></b>
+ <td>&nbsp;&nbsp;&nbsp;
+ <td>pointer to an imager state. The only relevant elements of the
+ imager state are the CTM (coordinate transformation matrix),
+ the logical operation (<b><tt>RasterOp</tt></b> or
+ transparency), and the color rendering information.
+<tr valign=top> <td><b><tt>pim</tt></b>
+ <td>&nbsp;
+ <td>pointer to the <b><tt>gs_image_t</tt></b> structure that
+ defines the image parameters
+<tr valign=top> <td><b><tt>format</tt></b>
+ <td>&nbsp;
+ <td>defines how pixels are represented for
+ <b><tt>image_plane_data</tt></b>. See the description of
+ <b><tt>image_plane_data</tt></b> below
+<tr valign=top> <td><b><tt>prect</tt></b>
+ <td>&nbsp;
+ <td>if not <b><tt>NULL</tt></b>, defines a subrectangle of the
+ image; only the data for this subrectangle will be passed to
+ <b><tt>image_plane_data</tt></b>, and only this subrectangle should
+ be drawn
+<tr valign=top> <td><b><tt>pdcolor</tt></b>
+ <td>&nbsp;
+ <td>defines a drawing color, only needed for masks or if
+ <b><tt>CombineWithColor</tt></b> is true
+<tr valign=top> <td><b><tt>pcpath</tt></b>
+ <td>&nbsp;
+ <td>if not <b><tt>NULL</tt></b>, defines an optional clipping path
+<tr valign=top> <td><b><tt>memory</tt></b>
+ <td>&nbsp;
+ <td>defines the allocator to be used for allocating bookkeeping
+ information
+<tr valign=top> <td><b><tt>pinfo</tt></b>
+ <td>&nbsp;
+ <td>the implementation should return a pointer to its state
+ structure here
+</table></blockquote>
+
+<p>
+<b><tt>begin_image</tt></b> is expected to allocate a structure for its
+bookkeeping needs, using the allocator defined by the memory parameter, and
+return it in <b><tt>*pinfo</tt></b>. <b><tt>begin_image</tt></b> should not assume that
+the structures in <b><tt>*pim</tt></b>, <b><tt>*prect</tt></b>, or
+<b><tt>*pdcolor</tt></b> will survive the call on
+<b><tt>begin_image</tt></b> (except for the color space in
+<b><tt>*pim-&gt;ColorSpace</tt></b>): it should copy any necessary parts of
+them into its own bookkeeping structure. It may, however, assume that
+<b><tt>*pis</tt></b>, <b><tt>*pcpath</tt></b>, and of course
+<b><tt>*memory</tt></b> will live at least until <b><tt>end_image</tt></b>
+is called.
+
+<p>
+<b><tt>begin_image</tt></b> returns 0 normally, or 1 if the image does not
+need any data. In the latter case, <b><tt>begin_image</tt></b> does not
+allocate an enumeration structure.
+</dl>
+
+<dl>
+<dt><b><tt>int (*begin_typed_image)(P9(gx_device&nbsp;*dev,
+const&nbsp;gs_imager_state&nbsp;*pis, const&nbsp;gs_matrix&nbsp;*pmat,
+const&nbsp;gs_image_common_t&nbsp;*pim, gs_int_rect&nbsp;*prect,
+const&nbsp;gx_drawing_color&nbsp;*pdcolor,
+const&nbsp;gx_clip_path&nbsp;*pcpath, gs_memory_t&nbsp;*memory,
+gx_image_enum_common_t&nbsp;**pinfo))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>This has the same function as <b><tt>begin_image</tt></b>, except
+<ul>
+<li>The image may be of any <b><tt>ImageType</tt></b>, not only
+<b><tt>image_type_simple</tt></b> (1);
+
+<li>The image format is included in the image structure, not supplied as a
+separate argument;
+
+<li>The optional <b><tt>pmat</tt></b> argument provides a matrix that
+substitutes for the one in the imager state;
+
+<li>For mask images, if <b><tt>pmat</tt></b> is not <b><tt>NULL</tt></b>
+and the color is pure, <b><tt>pis</tt></b> may be <b><tt>NULL</tt></b>.
+</ul>
+</dl>
+
+<p>
+The actual transmission of data uses the procedures in the enumeration
+structure, not driver procedures, since the handling of the data usually
+depends on the image type and parameters rather than the device. These
+procedures are specified as follows.
+
+<dl>
+<dt><b><tt>int (*image_plane_data)(P4(gx_device&nbsp;*dev,
+gx_image_enum_common_t&nbsp;*info,
+const&nbsp;gx_image_plane_t&nbsp;*planes, int&nbsp;height))</tt></b>
+<dd>This call provides more of the image source data: specifically,
+<b><tt>height</tt></b> rows, with <b><tt>Width</tt></b> pixels supplied for
+each row.
+
+<p>
+The data for each row are packed big-endian within each byte, as for
+<b><tt>copy_color</tt></b>. The <b><tt>data_x</tt></b> (starting X position
+within the row) and <b><tt>raster</tt></b> (number of bytes per row) are
+specified separately for each plane, and may include some padding at the
+beginning or end of each row. Note that for non-mask images, the input data
+may be in any color space and may have any number of bits per component (1,
+2, 4, 8, 12); currently mask images always have 1 bit per component, but in
+the future, they might allow multiple bits of alpha. Note also that each
+call of <b><tt>image_plane_data</tt></b> passes complete pixels: for example, for
+a chunky image with 24 bits per pixel, each call of
+<b><tt>image_plane_data</tt></b> passes 3N bytes of data (specifically,
+3&nbsp;&times;&nbsp;Width&nbsp;&times;&nbsp;height).
+
+<p>
+The interpretation of planes depends on the <b><tt>format</tt></b> member of
+the <b><tt>gs_image[_common]_t</tt></b> structure:
+
+<ul>
+<li>If the format is <b><tt>gs_image_format_chunky</tt></b>,
+<b><tt>planes[0].data</tt></b> points to data in "chunky" format, in which
+the components follow each other (for instance, RGBRGBRGB....)
+
+<li>If the format is <b><tt>gs_image_format_component_planar</tt></b>,
+<b><tt>planes[0&nbsp;..&nbsp;N-1].data</tt></b> point to data for the
+<b><em>N</em></b> components (for example, <b><em>N</em></b>=3 for RGB
+data); each plane contains samples for a single component, for instance,
+RR..., GG..., BB.... Note that the planes are divided by component, not by
+bit: for example, for 24-bit RGB data, <b><em>N</em></b>=3, with 8-bit
+values in each plane of data.
+
+<li>If the format is <b><tt>gs_image_format_bit_planar</tt></b>,
+<b><tt>planes[0&nbsp;..&nbsp;N*B-1].data</tt></b> point to data for the
+<b><em>N</em></b> components of <b><em>B</em></b> bits each (for example,
+<b><em>N</em></b>=3 and <b><em>B</em></b>=4 for RGB data with 4 bits per
+component); each plane contains samples for a single bit, for instance, R0
+R1 R2 R3 G0 G1 G2 G3 B0 B1 B2 B3. Note that the most significant bit of
+each plane comes first.
+</ul>
+
+<p>
+If, as a result of this call, <b><tt>image_plane_data</tt></b> has been called with all
+the data for the (sub-)image, it returns 1; otherwise, it returns 0 or an
+error code as usual.
+
+<p>
+<b><tt>image_plane_data</tt></b>, unlike most other procedures that take bitmaps as
+arguments, does not require the data to be aligned in any way.
+
+<p>
+Note that for some image types, different planes may have different
+numbers of bits per pixel, as defined in the <b><tt>plane_depths</tt></b> array.
+</dl>
+
+<dl>
+<dt><b><tt>int (*end_image)(P3(gx_device&nbsp;*dev, void&nbsp;*info,
+bool&nbsp;draw_last))</tt></b>
+<dd>Finish processing an image, either because all data have been supplied
+or because the caller has decided to abandon this image.
+<b><tt>end_image</tt></b> may be called at any time after
+<b><tt>begin_image</tt></b>. It should free the info structure and any
+subsidiary structures. If <b><tt>draw_last</tt></b> is true, it should
+finish drawing any buffered lines of the image.
+</dl>
+
+<h5><a name="Images_notes"></a>Notes</h5>
+
+<p>
+While there will almost never be more than one image enumeration in
+progress -- that is, after a <b><tt>begin_image</tt></b>,
+<b><tt>end_image</tt></b> will almost always be called before the next
+<b><tt>begin_image</tt></b> -- driver code should not rely on this
+property; in particular, it should store all information regarding the
+image in the info structure, not in the driver structure.
+
+<p>
+Note that if <b><tt>begin_[typed_]image</tt></b> saves its parameters in
+the info structure, it can decide on each call whether to use its own
+algorithms or to use the default implementation. (It may need to call
+<b><tt>gx_default_begin</tt></b>/<b><tt>end_image</tt></b> partway
+through.) [A later revision of this document may include an example here.]
+
+<h4><a name="Text"></a>Text</h4>
+
+<p>
+The third high-level interface handles text. As for images, the interface
+is based on creating an enumerator which then may execute the operation in
+multiple steps. As for the other high-level interfaces, the procedures are
+optional.
+
+<dl>
+<dt><b><tt>int (*text_begin)(P9(gx_device&nbsp;*dev,
+gs_imager_state&nbsp;*pis, const&nbsp;gs_text_params_t&nbsp;*text,
+gs_font&nbsp;*font, gx_path&nbsp;*path,
+const&nbsp;gx_device_color&nbsp;*pdcolor,
+const&nbsp;gx_clip_path&nbsp;*pcpath, gs_memory_t&nbsp;*memory,
+gs_text_enum_t&nbsp;**ppte))</tt></b> <b><em>[OPTIONAL]</em></b>
+
+<dd>
+Begin processing text, by creating a state structure and storing it in
+<b><tt>*ppte</tt></b>. The parameters of <b><tt>text_begin</tt></b> are as
+follows:
+</dl>
+
+<blockquote><table cellpadding=0 cellspacing=0>
+<tr valign=top> <td><b><tt>dev</tt></b>
+ <td>&nbsp;&nbsp;&nbsp;
+ <td>The usual pointer to the device.
+<tr valign=top> <td><b><tt>pis</tt></b>
+ <td>&nbsp;&nbsp;&nbsp;
+ <td>A pointer to an imager state. All elements may be relevant,
+ depending on how the text is rendered.
+<tr valign=top> <td><b><tt>text</tt></b>
+ <td>&nbsp;
+ <td>A pointer to the structure that defines the text operation
+ and parameters. See <a href="../src/gstext.h">gstext.h</a> for details.
+<tr valign=top> <td><b><tt>font</tt></b>
+ <td>&nbsp;
+ <td>Defines the font for drawing.
+<tr valign=top> <td><b><tt>path</tt></b>
+ <td>&nbsp;
+ <td>Defines the path where the character outline will be appended
+ (if the text operation includes <b><tt>TEXT_DO_...PATH</tt></b>),
+ and whose current point indicates where drawing should occur
+ and will be updated by the string width (unless the text
+ operation includes <b><tt>TEXT_DO_NONE</tt></b>).
+<tr valign=top> <td><b><tt>pdcolor</tt></b>
+ <td>&nbsp;
+ <td>Defines the drawing color for the text. Only relevant if
+ the text operation includes <b><tt>TEXT_DO_DRAW</tt></b>.
+<tr valign=top> <td><b><tt>pcpath</tt></b>
+ <td>&nbsp;
+ <td>If not <b><tt>NULL</tt></b>, defines an optional clipping path.
+ Only relevant if the text operation includes
+ <b><tt>TEXT_DO_DRAW</tt></b>.
+<tr valign=top> <td><b><tt>memory</tt></b>
+ <td>&nbsp;
+ <td>Defines the allocator to be used for allocating bookkeeping
+ information.
+<tr valign=top> <td><b><tt>ppte</tt></b>
+ <td>&nbsp;
+ <td>The implementation should return a pointer to its state
+ structure here.
+</table></blockquote>
+
+<p>
+<b><tt>text_begin</tt></b> must allocate a structure for its bookkeeping
+needs, using the allocator defined by the <b><tt>memory</tt></b> parameter,
+and return it in <b><tt>*ppte</tt></b>. <b><tt>text_begin</tt></b> may
+assume that the structures passed as parameters will survive until text
+processing is complete.
+
+<p>
+Clients should not call the driver <b><tt>text_begin</tt></b> procedure
+directly. Instead, they should call <b><tt>gx_device_text_begin</tt></b>,
+which takes the same parameters and also initializes certain common elements
+of the text enumeration structure, or <b><tt>gs_text_begin</tt></b>, which
+takes many of the parameters from a graphics state structure. For details,
+see <a href="../src/gstext.h">gstext.h</a>.
+
+<p>
+The actual processing of text uses the procedures in the enumeration
+structure, not driver procedures, since the handling of the text may depend
+on the font and parameters rather than the device. Text processing may also
+require the client to take action between characters, either because the
+client requested it (<b><tt>TEXT_INTERVENE</tt></b> in the operation) or
+because rendering a character requires suspending text processing to call an
+external package such as the PostScript interpreter. (It is a deliberate
+design decision to handle this by returning to the client, rather than
+calling out of the text renderer, in order to avoid potentially unknown
+stack requirements.) Specifically, the client must call the following
+procedures, which in turn call the procedures in the text enumerator.
+
+<dl>
+<dt><b><tt>int gs_text_process(P1(gs_text_enum_t&nbsp;*pte))</tt></b>
+<dd>Continue processing text. This procedure may return 0 or a negative
+error code as usual, or one of the following values (see
+<a href="../src/gstext.h">gstext.h</a> for details).
+
+<blockquote><table cellpadding=0 cellspacing=0>
+<tr valign=top> <td><b><tt>TEXT_PROCESS_RENDER</tt></b>
+ <td>The client must cause the current character to be rendered.
+ This currently only is used for PostScript Type 0-4 fonts
+ and their CID-keyed relatives.
+<tr valign=top> <td><b><tt>TEXT_PROCESS_INTERVENE</tt></b>
+ <td>The client has asked to intervene between characters.
+ This is used for <b><tt>cshow</tt></b> and <b><tt>kshow</tt></b>.
+</table></blockquote>
+</dl>
+
+<dl>
+<dt><b><tt>int gs_text_release(P2(gs_text_enum_t&nbsp;*pte,
+client_name_t&nbsp;cname))</tt></b> <dd>Finish processing text and release
+all associated structures. Clients must call this procedure after
+<b><tt>gs_text_process</tt></b> returns 0 or an error, and may call it at
+any time.
+</dl>
+
+<p>
+There are numerous other procedures that clients may call during text
+processing. See <a href="../src/gstext.h">gstext.h</a> for details.
+
+<h5><a name="Text_notes"></a>Notes</h5>
+
+<p>
+Note that unlike many other optional procedures, the default implementation
+of <b><tt>text_begin</tt></b> cannot simply return: like the default
+implementation of <b><tt>begin[_typed]_image</tt></b>, it must create and
+return an enumerator. Furthermore, the implementation of the
+<b><tt>process</tt></b> procedure (in the enumerator structure, called by
+<b><tt>gs_text_process</tt></b>) cannot simply return without doing
+anything, even if it doesn't want to draw anything on the output. See the
+comments in <a href="../src/gxtext.h">gxtext.h</a> for details.
+
+<h3><a name="Reading_bits_back"></a>Reading bits back</h3>
+
+<dl>
+<dt><b><tt>int (*get_bits_rectangle)(P4(gx_device&nbsp;*dev,
+const&nbsp;gs_int_rect&nbsp;*prect, gs_get_bits_params_t&nbsp;*params,
+gs_int_rect&nbsp;**unread))</tt></b> <b><em>[OPTIONAL]</em></b>
+
+<dd>
+Read a rectangle of bits back from the device. The <b><tt>params</tt></b>
+structure consists of:
+
+<table cellpadding=0 cellspacing=0>
+<tr valign=top> <td><b><tt>options</tt></b>
+ <td>&nbsp;
+ <td>the allowable formats for returning the data
+<tr valign=top> <td><b><tt>data[32]</tt></b>
+ <td>&nbsp;
+ <td>pointers to the returned data
+<tr valign=top> <td><b><tt>x_offset</tt></b>
+ <td>&nbsp;
+ <td>the X offset of the first returned pixel in data
+<tr valign=top> <td><b><tt>raster</tt></b>
+ <td>&nbsp;
+ <td>the distance between scan lines in the returned data
+</table>
+
+<p>
+<b><tt>options</tt></b> is a bit mask specifying what formats the client is
+willing to accept. (If the client has more flexibility, the implementation
+may be able to return the data more efficiently, by avoiding representation
+conversions.) The options are divided into groups.
+
+<blockquote><dl>
+<dt><b><em>alignment</em></b>
+<dd>Specifies whether the returned data must be aligned in the normal
+manner for bitmaps, or whether unaligned data are acceptable.
+
+<dt><b><em>pointer or copy</em></b>
+<dd>Specifies whether the data may be copied into storage provided by the
+client and/or returned as pointers to existing storage. (Note that if
+copying is not allowed, it is much more likely that the implementation will
+return an error, since this requires that the client accept the data in the
+implementation's internal format.)
+
+<dt><b><em>X offset</em></b>
+<dd>Specifies whether the returned data must have a specific X offset
+(usually zero, but possibly other values to avoid skew at some later stage
+of processing) or whether it may have any X offset (which may avoid skew in
+the <b><tt>get_bits_rectangle</tt></b> operation itself).
+
+<dt><b><em>raster</em></b>
+<dd>Specifies whether the raster (distance between returned scan lines)
+must have its standard value, must have some other specific value, or may
+have any value. The standard value for the raster is the device width
+padded out to the alignment modulus when using pointers, or the minimum
+raster to accommodate the X offset + width when copying (padded out to the
+alignment modulus if standard alignment is required).
+
+<dt><b><em>format</em></b>
+<dd>Specifies whether the data are returned in chunky (all components of a
+single pixel together), component-planar (each component has its own scan
+lines), or bit-planar (each bit has its own scan lines) format.
+
+<dt><b><em>color space</em></b>
+<dd>Specifies whether the data are returned as native device pixels, or in
+a standard color space. Currently the only supported standard space is
+RGB.
+
+<dt><b><em>standard component depth</em></b>
+<dd>Specifies the number of bits per component if the data are returned in
+the standard color space. (Native device pixels use
+<b><tt>dev</tt></b>-&gt;<b><tt>color_info.depth</tt></b> bits per pixel.)
+
+<dt><b><em>alpha</em></b>
+<dd>Specifies whether alpha channel information should be returned as the
+first component, the last component, or not at all. Note that for devices
+that have no alpha capability, the returned alpha values will be all 1s.
+</dl></blockquote>
+
+<p>
+The client may set more than one option in each of the above groups; the
+implementation will choose one of the selected options in each group to
+determine the actual form of the returned data, and will update
+<b><tt>params[].options</tt></b> to indicate the form. The returned
+<b><tt>params[].options</tt></b> will normally have only one option set per
+group.
+
+<p>
+For further details on <b><tt>params</tt></b>, see <a
+href="../src/gxgetbit.h">gxgetbit.h</a>. For further details on
+<b><tt>options</tt></b>, see <a href="../src/gxbitfmt.h">gxbitfmt.h</a>.
+
+<p>
+Define w = <b><tt>prect</tt></b>-&gt;q.x - <b><tt>prect</tt></b>-&gt;p.x, h
+= <b><tt>prect</tt></b>-&gt;q.y - <b><tt>prect</tt></b>-&gt;p.y. If the
+bits cannot be read back (for example, from a printer), return
+<b><tt>gs_error_unknownerror</tt></b>; if raster bytes is not enough space
+to hold <b><tt>offset_x</tt></b> + w pixels, or if the source rectangle
+goes outside the device dimensions (p.x &lt; 0 || p.y &lt; 0 || q.x &gt;
+<b><tt>dev</tt></b>-&gt;width || q.y &gt; <b><tt>dev</tt></b>-&gt;height),
+return <b><tt>gs_error_rangecheck</tt></b>; if any regions could not be
+read, return <b><tt>gs_error_ioerror</tt></b> if unpainted is
+<b><tt>NULL</tt></b>, otherwise the number of rectangles (see below);
+otherwise return 0.
+
+<p>
+The caller supplies a buffer of <b><tt>raster</tt></b>&nbsp;&times;&nbsp;h
+bytes starting at <b><tt>data[0]</tt></b> for the returned data in chunky
+format, or <b><em>N</em></b> buffers of
+<b><tt>raster</tt></b>&nbsp;&times;&nbsp;h bytes starting at
+<b><tt>data[0]</tt></b> through
+<b><tt>data[</tt></b><b><em>N-1</em></b><b><tt>]</tt></b> in planar format
+where <b><em>N</em></b> is the number of components or bits. The contents
+of the bits beyond the last valid bit in each scan line (as defined by w)
+are unpredictable. data need not be aligned in any way. If
+<b><tt>x_offset</tt></b> is non-zero, the bits before the first valid bit
+in each scan line are undefined. If the implementation returns pointers to
+the data, it stores them into <b><tt>data[0]</tt></b> or
+<b><tt>data[</tt></b><b><em>0..N-1</em></b><b><tt>]</tt></b>.
+
+<p>
+If not all the source data are available (for example, because the source
+was a partially obscured window and backing store was not available or not
+used), or if the rectangle does not fall completely within the device's
+coordinate system, any unread bits are undefined, and the value returned
+depends on whether unread is <b><tt>NULL</tt></b>. If unread is
+<b><tt>NULL</tt></b>, return <b><tt>gs_error_ioerror</tt></b>; in this case,
+some bits may or may not have been read. If unread is not
+<b><tt>NULL</tt></b>, allocate (using <b><tt>dev</tt></b>-&gt;memory) and
+fill in a list of rectangles that could not be read, store the pointer to
+the list in <b><tt>*unread</tt></b>, and return the number of rectangles; in
+this case, all bits not listed in the rectangle list have been read back
+properly. The list is not sorted in any particular order, but the
+rectangles do not overlap. Note that the rectangle list may cover a
+superset of the region actually obscured: for example, a lazy implementation
+could return a single rectangle that was the bounding box of the region.
+</dl>
+
+<dl>
+<dt><b><tt>int (*get_bits)(P4(gx_device&nbsp;*dev, int&nbsp;y,
+byte&nbsp;*data, byte&nbsp;**actual_data))</tt></b>
+<b><em>[OPTIONAL]</em></b>
+<dd>Read scan line <b><tt>y</tt></b> of bits back from the device into the
+area starting at data. This call is functionally equivalent to
+
+<blockquote>
+<pre>(*get_bits_rectangle)
+ (dev, {0, y, dev-&gt;width, y+1},
+ {(GB_ALIGN_ANY | (GB_RETURN_COPY | GB_RETURN_POINTER) | GB_OFFSET_0 |
+ GB_RASTER_STANDARD | GB_FORMAT_CHUNKY | GB_COLORS_NATIVE |
+ GB_ALPHA_NONE),
+ {data}})</pre></blockquote>
+
+<p>
+with the returned value of
+<b><tt>params</tt></b>-&gt;<b><tt>data[0]</tt></b> stored in
+<b><tt>*actual_data</tt></b>, and will in fact be implemented this way if
+the device defines a <b><tt>get_bits_rectangle</tt></b> procedure and does
+not define one for <b><tt>get_bits</tt></b>. (If
+<b><tt>actual_data</tt></b> is <b><tt>NULL</tt></b>,
+<b><tt>GB_RETURN_POINTER</tt></b> is omitted from the options.)
+</dl>
+
+<h3><a name="Parameters"></a>Parameters</h3>
+
+<p>
+Devices may have an open-ended set of parameters, which are simply pairs
+consisting of a name and a value. The value may be of various types:
+integer (int or long), boolean, float, string, name, <b><tt>NULL</tt></b>,
+array of integer, array of float, or arrays or dictionaries of mixed types.
+For example, the <b><tt>Name</tt></b> of a device is a string; the
+<b><tt>Margins</tt></b> of a device is an array of two floats. See
+<a href="../src/gsparam.h">gsparam.h</a> for more details.
+
+<p>
+If a device has parameters other than the ones applicable to all devices
+(or, in the case of printer devices, all printer devices), it must provide
+<b><tt>get_params</tt></b> and <b><tt>put_params</tt></b> procedures. If
+your device has parameters beyond those of a straightforward display or
+printer, we strongly advise using the <b><tt>_get_params</tt></b> and
+<b><tt>_put_params</tt></b> procedures in an existing device (for example,
+<a href="../src/gdevcdj.c">gdevcdj.c</a> or <a
+href="../src/gdevbit.c">gdevbit.c</a>) as a model for your own code.
+
+<dl>
+<dt><b><tt>int (*get_params)(P2(gx_device&nbsp;*dev,
+gs_param_list&nbsp;*plist))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>Read the parameters of the device into the parameter list at
+<b><tt>plist</tt></b>, using the <b><tt>param_write_*</tt></b>
+macros or procedures defined in <a href="../src/gsparam.h">gsparam.h</a>.
+</dl>
+
+<dl>
+<dt><b><tt>int (*get_hardware_params)(P2(gx_device&nbsp;*dev,
+gs_param_list&nbsp;*plist))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>Read the hardware-related parameters of the device into the parameter
+list at plist. These are any parameters whose values are under control of
+external forces rather than the program -- for example, front panel
+switches, paper jam or tray empty sensors, etc. If a parameter involves
+significant delay or hardware action, the driver should only determine the
+value of the parameter if it is "requested" by the
+<b><tt>gs_param_list</tt></b> [<b><tt>param_requested</tt></b>(plist,
+<b><tt>key_name</tt></b>)]. This function may cause the asynchronous
+rendering pipeline (if enabled) to be drained, so it should be used
+sparingly.
+</dl>
+
+<dl>
+<dt><b><tt>int (*put_params)(P2(gx_device&nbsp;*dev,
+gs_param_list&nbsp;*plist))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>Set the parameters of the device from the parameter list at
+<b><tt>plist</tt></b>, using the <b><tt>param_read_</tt></b>*
+macros/procedures defined in <a href="../src/gsparam.h">gsparam.h</a>. All
+<b><tt>put_params</tt></b> procedures must use a "two-phase commit"
+algorithm; see <a href="../src/gsparam.h">gsparam.h</a> for details.
+</dl>
+
+<h4><a name="Default_CRD_parameters"></a>Default color rendering
+dictionary (CRD) parameters</h4>
+
+<p>
+Drivers that want to provide one or more default CIE color rendering
+dictionaries (CRDs) can do so through <b><tt>get_params</tt></b>. To do
+this, they create the CRD in the usual way (normally using the
+<b><tt>gs_cie_render1_build</tt></b> and <b><tt>_initialize</tt></b>
+procedures defined in <a href="../src/gscrd.h">gscrd.h</a>), and then write
+it as a parameter using <b><tt>param_write_cie_render1</tt></b> defined in
+<a href="../src/gscrdp.h">gscrdp.h</a>. However, the TransformPQR procedure
+requires special handling. If the CRD uses a TransformPQR procedure
+different from the default (identity), the driver must do the following:
+
+<ul>
+<li>The TransformPQR element of the CRD must include a
+<b><tt>proc_name</tt></b>, and optionally <b><tt>proc_data</tt></b>. The
+<b><tt>proc_name</tt></b> is an arbitrary name chosen by the driver to
+designate the particular TransformPQR function. It must not be the same as
+any device parameter name; we strongly suggest it include the device name,
+for instance, "<b><tt>bitTPQRDefault</tt></b>".
+
+<li>For each such named TransformPQR procedure, the driver's
+<b><tt>get_param</tt></b> procedure must provide a parameter of the same
+name. The parameter value must be a string whose bytes are the actual
+procedure address.
+</ul>
+
+<p>
+For a complete example, see the <b><tt>bit_get_params</tt></b> procedure in
+<a href="../src/gdevbit.c">gdevbit.c</a>. Note that it is essential that
+the driver return the CRD or the procedure address only if specifically
+requested (<b><tt>param_requested(...)</tt></b> &gt; 0); otherwise, errors
+will occur.
+
+<h3><a name="External_fonts"></a>External fonts</h3>
+
+<p>
+Drivers may include the ability to display text. More precisely, they may
+supply a set of procedures that in turn implement some font and text
+handling capabilities, described in <a href="Xfonts.htm">a separate
+document</a>. The link between the two is the driver procedure that
+supplies the font and text procedures:
+
+<dl>
+<dt><b><tt>xfont_procs&nbsp;*(*get_xfont_procs)(P1(gx_device&nbsp;*dev))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>Return a structure of procedures for handling external fonts and text
+display. A <b><tt>NULL</tt></b> value means that this driver doesn't
+provide this capability.
+</dl>
+
+<p>
+For technical reasons, a second procedure is also needed:
+
+<dl>
+<dt><b><tt>gx_device&nbsp;*(*get_xfont_device)(P1(gx_device&nbsp;*dev))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>Return the device that implements <b><tt>get_xfont_procs</tt></b> in a
+non-default way for this device, if any. Except for certain special
+internal devices, this is always the device argument.
+</dl>
+
+<h3><a name="Page_devices"></a>Page devices</h3>
+
+<dl>
+<dt><b><tt>gx_device&nbsp;*(*get_page_device)(P1(gx_device&nbsp;*dev))</tt></b>
+<b><em>[OPTIONAL]</em></b>
+<dd>According to the Adobe specifications, some devices are "page devices"
+and some are not. This procedure returns <b><tt>NULL</tt></b> if the
+device is not a page device, or the device itself if it is a page device.
+In the case of forwarding devices, <b><tt>get_page_device</tt></b> returns
+the underlying page device (or <b><tt>NULL</tt></b> if the underlying
+device is not a page device).
+</dl>
+
+<h3><a name="Miscellaneous"></a>Miscellaneous</h3>
+
+<dl>
+<dt><b><tt>int (*get_band)(P3(gx_device&nbsp;*dev, int&nbsp;y,
+int&nbsp;*band_start))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>If the device is a band device, this procedure stores in
+<b><tt>*band_start</tt></b> the scan line (device Y coordinate) of the band
+that includes the given Y coordinate, and returns the number of scan lines
+in the band. If the device is not a band device, this procedure returns 0.
+The latter is the default implementation.
+</dl>
+
+<dl>
+<dt><b><tt>void (*get_clipping_box)(P2(gx_device&nbsp;*dev,
+gs_fixed_rect&nbsp;*pbox))</tt></b> <b><em>[OPTIONAL]</em></b>
+<dd>Stores in <b><tt>*pbox</tt></b> a rectangle that defines the device's
+clipping region. For all but a few specialized devices, this is
+<em>((0,0),(width,height))</em>.
+</dl>
+
+<!-- [2.0 end contents] ==================================================== -->
+
+<!-- [3.0 begin visible trailer] =========================================== -->
+<hr>
+
+<p>
+<small>Copyright &copy; 1996, 2000 Aladdin Enterprises.
+All rights reserved.</small>
+
+<p>
+This software is provided AS-IS with no warranty, either express or
+implied.
+
+This software is distributed under license and may not be copied,
+modified or distributed except as expressly authorized under the terms
+of the license contained in the file LICENSE in this distribution.
+
+<p>
+<small>Ghostscript version 7.07, 17 May 2003
+
+<!-- [3.0 end visible trailer] ============================================= -->
+
+</body>
+</html>