diff options
Diffstat (limited to 'Master/xemtex/doc/ghostscript/Drivers.htm')
-rw-r--r-- | Master/xemtex/doc/ghostscript/Drivers.htm | 2538 |
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 *</tt></b> as +their first argument, and must cast it to +<b><tt>smurf_device *</tt></b> internally. For example, in the code +for the "memory" device, the first argument to all routines is called +<b><tt>dev</tt></b>, but the routines actually use <b><tt>mdev</tt></b> to +refer to elements of the full structure, 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> + <td>The device name +<tr valign=top> <td><b><tt>bool is_open;</tt></b> + <td> + <td>True if device has been opened +<tr valign=top> <td><b><tt>gx_device_color_info color_info;</tt></b> + <td> + <td>Color information +<tr valign=top> <td><b><tt>int width;</tt></b> + <td> + <td>Width in pixels +<tr valign=top> <td><b><tt>int height;</tt></b> + <td> + <td>Height in pixels +</table></blockquote> + +<p> +The name in the structure (<b><tt>dname</tt></b>) should be the same as the +name in <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. > 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. > 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 (>= 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 (>= 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> × <b><tt>dither_rgb</tt></b> × <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> ) 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 < 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 <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 *, +gx_color_value red, gx_color_value green, +gx_color_value 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> / 2, 0 otherwise. + +<p> +Ghostscript assumes that for devices that have color capability (that is, +<b><tt>color_info.num_components</tt></b> > 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 *, +gx_color_value cyan, gx_color_value magenta, +gx_color_value yellow, gx_color_value 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> > 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 *, +gx_color_index color, gx_color_value 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 *, +gx_color_value red, gx_color_value green, +gx_color_value blue, gx_color_value 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, r, g, b, gx_max_color_value)</tt></b> +returns the same value as +<b><tt>map_rgb_color(dev, r, g, b)</tt></b>. +</dl> + +<dl> +<dt><b><tt>int (*map_color_rgb_alpha)(P3(gx_device *, +gx_color_index color, gx_color_value 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 enum { go_text, +go_graphics } graphic_object_type; int +(*get_alpha_bits)(P4(gx_device *dev, +graphic_object_type 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 *, int x, +int y, int width, int height, +gx_color_index color))</tt></b> +<dd>Fill a rectangle with a color. The set of pixels filled is {(px,py) | +x <= px < x + width and y <= py < 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> <= 0 or +height <= 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 *, +const unsigned char *data, int data_x, int raster, +gx_bitmap_id id, int x, int y, int width, +int height, gx_color_index color0, +gx_color_index 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> = <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 *, +const gx_tile_bitmap *tile, int x, int y, +int width, int height, gx_color_index color0, +gx_color_index color1, int phase_x, int 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 != 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 *, +const gx_strip_bitmap *tile, int x, int y, +int width, int height, gx_color_index color0, +gx_color_index color1, int phase_x, int 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->width</tt></b><em>)</em> and +<em>[0..</em><b><tt>tile->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 *, +const unsigned char *data, int data_x, int raster, +gx_bitmap_id id, int x, int y, int width, +int 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 *dev, +const unsigned char *data, int data_x, int raster, +gx_bitmap_id id, int x, int y, int width, +int height, gx_color_index color, int 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 *dev, +gx_device_t **pcdev, const gs_composite_t *pcte, +const gs_imager_state *pis, gs_memory_t *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 *dev, +const byte *sdata, int sourcex, uint sraster, +gx_bitmap_id id, const gx_color_index *scolors, +const gx_tile_bitmap *texture, +const gx_color_index *tcolors, int x, int y, +int width, int height, int phase_x, int phase_y, +int 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 != 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 *dev, +const byte *sdata, int sourcex, uint sraster, +gx_bitmap_id id, const gx_color_index *scolors, +const gx_strip_bitmap *texture, +const gx_color_index *tcolors, int x, int y, +int width, int height, int phase_x, int phase_y, +int 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 = 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> + <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> + <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> + <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> + <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> + <td>part of <b>T</b> specification, <a href="#T_spec">see below</a> +<tr valign=top> <td><b><tt>command</tt></b> + <td> + <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> + <td> +<tr valign=top> <td>7-0 + <td> + <td>raster op +<tr valign=top> <td>8 + <td> + <td>0 if source opaque, 1 if source transparent +<tr valign=top> <td>9 + <td> + <td>0 if texture opaque, 1 if texture transparent +<tr valign=top> <td>?-10 + <td> + <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×2×2 input values as follows: + +<blockquote><table cellpadding=0 cellspacing=0> +<tr valign=bottom> + <th>Bit + <td> + <th>Texture + <td> + <th>Source + <td> + <th>Destination +<tr> <td colspan=7><hr> +<tr valign=top> <td align=center>7 + <td> + <td align=center>1 + <td> + <td align=center>1 + <td> + <td align=center>1 +<tr valign=top> <td align=center>6 + <td> + <td align=center>1 + <td> + <td align=center>1 + <td> + <td align=center>0 +<tr valign=top> <td align=center>5 + <td> + <td align=center>1 + <td> + <td align=center>0 + <td> + <td align=center>1 +<tr valign=top> <td align=center>4 + <td> + <td align=center>1 + <td> + <td align=center>0 + <td> + <td align=center>0 +<tr valign=top> <td align=center>3 + <td> + <td align=center>0 + <td> + <td align=center>1 + <td> + <td align=center>1 +<tr valign=top> <td align=center>2 + <td> + <td align=center>0 + <td> + <td align=center>1 + <td> + <td align=center>0 +<tr valign=top> <td align=center>1 + <td> + <td align=center>0 + <td> + <td align=center>0 + <td> + <td align=center>1 +<tr valign=top> <td align=center>0 + <td> + <td align=center>0 + <td> + <td align=center>0 + <td> + <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) ==> + + { 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) ==> + + (*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) ==> + + { 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) ==> + + (*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) ==> [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) ==> + + (*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 *dev, +const gs_fixed_edge *left, const gs_fixed_edge *right, +fixed ybot, fixed ytop, bool swap_axes, +const gx_drawing_color *pdcolor, +gs_logical_operation_t 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 *dev, +fixed px, fixed py, fixed ax, fixed ay, fixed bx, +fixed by, const gx_drawing_color *pdcolor, +gs_logical_operation_t 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 *dev, fixed px, +fixed py, fixed ax, fixed ay, fixed bx, fixed by, +const gx_drawing_color *pdcolor, +gs_logical_operation_t 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 *dev, +fixed fx0, fixed fy0, fixed fx1, fixed fy1, +const gx_drawing_color *pdcolor, +gs_logical_operation_t 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 *dev, int x0, int y0, +int x1, int y1, gx_color_index 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> + <th align=left>Defines +<tr valign=top> <td><a href="../src/gxpaint.h">gxpaint.h</a> + <td> + <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> + <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> + <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> + <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> + <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> + <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> + <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> + <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 *dev, +const gs_imager_state *pis, gx_path *ppath, +const gx_fill_params *params, +const gx_drawing_color *pdcolor, +const gx_clip_path *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 *dev, +const gs_imager_state *pis, gx_path *ppath, +const gx_stroke_params *params, +const gx_drawing_color *pdcolor, +const gx_clip_path *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 *dev, +const byte *data, int data_x, int raster, +gx_bitmap_id id, int x, int y, int width, +int height, const gx_drawing_color *pdcolor, int depth, +int command, const gx_clip_path *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> > 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 { + << gs_image_common_t >> + 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 { + << gs_data_image_t >> + 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 { + << gs_pixel_image_t >> + 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 *dev, +const gs_imager_state *pis, const gs_image_t *pim, +gs_image_format_t format, gs_int_rect *prect, +const gx_drawing_color *pdcolor, +const gx_clip_path *pcpath, gs_memory_t *memory, +gx_image_enum_common_t **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> + <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> + <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> + <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> + <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> + <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> + <td>if not <b><tt>NULL</tt></b>, defines an optional clipping path +<tr valign=top> <td><b><tt>memory</tt></b> + <td> + <td>defines the allocator to be used for allocating bookkeeping + information +<tr valign=top> <td><b><tt>pinfo</tt></b> + <td> + <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->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 *dev, +const gs_imager_state *pis, const gs_matrix *pmat, +const gs_image_common_t *pim, gs_int_rect *prect, +const gx_drawing_color *pdcolor, +const gx_clip_path *pcpath, gs_memory_t *memory, +gx_image_enum_common_t **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 *dev, +gx_image_enum_common_t *info, +const gx_image_plane_t *planes, int 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 × Width × 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 .. 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 .. 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 *dev, void *info, +bool 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 *dev, +gs_imager_state *pis, const gs_text_params_t *text, +gs_font *font, gx_path *path, +const gx_device_color *pdcolor, +const gx_clip_path *pcpath, gs_memory_t *memory, +gs_text_enum_t **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> + <td>The usual pointer to the device. +<tr valign=top> <td><b><tt>pis</tt></b> + <td> + <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> + <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> + <td>Defines the font for drawing. +<tr valign=top> <td><b><tt>path</tt></b> + <td> + <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> + <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> + <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> + <td>Defines the allocator to be used for allocating bookkeeping + information. +<tr valign=top> <td><b><tt>ppte</tt></b> + <td> + <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 *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 *pte, +client_name_t 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 *dev, +const gs_int_rect *prect, gs_get_bits_params_t *params, +gs_int_rect **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> + <td>the allowable formats for returning the data +<tr valign=top> <td><b><tt>data[32]</tt></b> + <td> + <td>pointers to the returned data +<tr valign=top> <td><b><tt>x_offset</tt></b> + <td> + <td>the X offset of the first returned pixel in data +<tr valign=top> <td><b><tt>raster</tt></b> + <td> + <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>-><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>->q.x - <b><tt>prect</tt></b>->p.x, h += <b><tt>prect</tt></b>->q.y - <b><tt>prect</tt></b>->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 < 0 || p.y < 0 || q.x > +<b><tt>dev</tt></b>->width || q.y > <b><tt>dev</tt></b>->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> × 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> × 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>->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 *dev, int y, +byte *data, byte **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->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>-><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 *dev, +gs_param_list *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 *dev, +gs_param_list *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 *dev, +gs_param_list *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> > 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 *(*get_xfont_procs)(P1(gx_device *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 *(*get_xfont_device)(P1(gx_device *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 *(*get_page_device)(P1(gx_device *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 *dev, int y, +int *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 *dev, +gs_fixed_rect *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 © 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> |