⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 drivers.htm

📁 GhostScript的源代码
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<li>The clipping "devices" <b><tt>xclip.c</tt></b>,
	<b><tt>gxclip2.c</tt></b>, and <b><tt>gxclipm.c</tt></b>.
<li>The pattern accumulation "device" in <b><tt>gxpcmap.c</tt></b>.
<li>The hit detection "device" in <b><tt>gdevhit.c</tt></b>.
<li>The generic printer device macros in <b><tt>gdevprn.h</tt></b>.
<li>The generic printer device code in <b><tt>gdevprn.c</tt></b>.
<li>The RasterOp source device in <b><tt>gdevmrop.c</tt></b>.
</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 <b><tt>gsdparam.c</tt></b>.

<p>
You should not have to change any of the real devices in the standard
Ghostscript distribution (listed in <b><tt>devs.mak</tt></b> and
<b><tt>contrib.mak</tt></b>) or any of your own devices, because all of
them are supposed to use the macros in <b><tt>gxdevice.h</tt></b> or
<b><tt>gdevprn.h</tt></b> to define and initialize their state.

<hr>

<h1><a name="coordinates_and_types"></a>Coordinates and types</h1>

<h2><a name="Coordinate_system"></a>Coordinate system</h2>

<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
<b><tt>gxdevice.h</tt></b> are very helpful in doing this.

<h2><a name="Color_definition"></a>Color definition</h2>

<p>
Ghostscript represents colors internally as RGB or CMYK values.  In
communicating with devices, however, it assumes that each device has a
palette of colors identified by integers (to be precise, elements of type
<b><tt>gx_color_index</tt></b>).  Drivers may provide a uniformly spaced
gray ramp or color cube for halftoning, or they may do their own color
approximation, or both.

<p>
The <b><tt>color_info</tt></b> member of the device structure defines the
color and gray-scale capabilities of the device.  Its type is defined as
follows:

<blockquote>
<pre>typedef struct gx_device_color_info_s {
        int num_components;		/* 1 = gray only, 3 = RGB, */
        				/* 4 = CMYK */
        int depth;			/* # of bits per pixel */
        gx_color_value max_gray;	/* # of distinct gray levels -1 */
        gx_color_value max_rgb;		/* # of distinct color levels -1 */
        				/* (only relevant if num_comp. &gt; 1) */
        gx_color_value dither_gray;	/* size of gray ramp for halftoning */
        gx_color_value dither_rgb;	/* size of color cube ditto */
        				/* (only relevant if num_comp. &gt; 1) */
} gx_device_color_info;</pre>
</blockquote>

<p>
The following macros (in <b><tt>gxdevice.h</tt></b>) provide convenient shorthands for
initializing this structure for ordinary black-and-white or color devices:

<blockquote>
<b><tt>#define dci_black_and_white</tt></b> ...<br>
<b><tt>#define dci_color(depth,maxv,dither)</tt></b> ...
</blockquote>

<p>
The idea is that a device has a certain number of gray levels
(<b><tt>max_gray</tt></b>+1) and a certain number of colors
(<b><tt>max_rgb</tt></b>+1) that it can produce directly.  When Ghostscript
wants to render a given RGB or CMYK color as a device color, it first tests
whether the color is a gray level (if <b><tt>num_components</tt></b> is 1,
it converts all colors to gray levels), and if so:

<blockquote>
If <b><tt>max_gray</tt></b> is large (&gt;= 31), Ghostscript asks the
device to approximate the gray level directly.  If the device returns a
valid <b><tt>gx_color_index</tt></b>, Ghostscript uses it.  Otherwise,
Ghostscript assumes that the device can represent
<b><tt>dither_gray</tt></b> distinct gray levels, equally spaced along the
diagonal of the color cube, and uses the two nearest ones to the desired
color for halftoning.
</blockquote>

<p>
If the color is not a gray level:

<blockquote>
If <b><tt>max_rgb</tt></b> is large (&gt;= 31), Ghostscript asks the device
to approximate the color directly.  If the device returns a valid
<b><tt>gx_color_index</tt></b>, Ghostscript uses it.  Otherwise,
Ghostscript assumes that the device can represent

<blockquote>
<b><tt>dither_rgb</tt></b> &times; <b><tt>dither_rgb</tt></b> &times; <b><tt>dither_rgb</tt></b>
</blockquote>

<p>
distinct colors, equally spaced throughout the color cube, and uses two of
the nearest ones to the desired color for halftoning.
</blockquote>

<h2><a name="Types"></a>Types</h2>

<p>
Here is a brief explanation of the various types that appear as parameters
or results of the drivers.

<dl>
<dt><b><tt>gx_color_value</tt></b> (defined in <b><tt>gxdevice.h</tt></b>)
<dd>This is the type used to represent RGB or CMYK color values.  It is
currently equivalent to unsigned short.  However, Ghostscript may use less
than the full range of the type to represent color values:
<b><tt>gx_color_value_bits</tt></b> is the number of bits actually used,
and <b><tt>gx_max_color_value</tt></b> is the maximum value, equal to
(2^<small><sup><b><tt>gx_max_color_value_bits</tt></b></sup></small>)-1.
</dl>

<dl>
<dt><b><tt>gx_device</tt></b> (defined in <b><tt>gxdevice.h</tt></b>)
<dd>This is the device structure, as explained above.
</dl>

<dl>
<dt><b><tt>gs_matrix</tt></b> (defined in <b><tt>gsmatrix.h</tt></b>)
<dd>This is a 2-D homogeneous coordinate transformation matrix, used by
many Ghostscript operators.
</dl>

<dl>
<dt><b><tt>gx_color_index</tt></b> (defined in <b><tt>gxdevice.h</tt></b>)
<dd>This is meant to be whatever the driver uses to represent a device
color.  For example, it might be an index in a color map, or it might be R,
G, and B values packed into a single integer.  Ghostscript doesn't ever do
any computations with <b><tt>gx_color_index</tt></b> values: it gets them
from <b><tt>map_rgb_color</tt></b> or <b><tt>map_cmyk_color</tt></b> and
hands them back as arguments to several other procedures.  The special
value <b><tt>gx_no_color_index</tt></b> (defined as
<b><tt>(gx_color_index)(-1)</tt></b>&nbsp;) means "transparent" for some of
the procedures.  The type definition is simply:

<blockquote><b><tt>
typedef unsigned long gx_color_index;
</tt></b></blockquote>
</dl>

<dl>
<dt><b><tt>gs_param_list</tt></b> (defined in <b><tt>gsparam.h</tt></b>)
<dd>This is a parameter list, which is used to read and set attributes in a
device.  See the comments in <b><tt>gsparam.h</tt></b>, 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 <b><tt>gxbitmap.h</tt></b>)
<br><b><tt>gx_strip_bitmap</tt></b> (defined in <b><tt>gxbitmap.h</tt></b>)
<dd>These structure types represent bitmaps to be used as a tile for
filling a region (rectangle).  <b><tt>gx_tile_bitmap</tt></b> is an older
type lacking <b><tt>shift</tt></b> and <b><tt>rep_shift</tt></b>;
<b><tt>gx_strip_bitmap</tt></b> has superseded it, and it should not be
used in new code.  Here is a copy of the relevant part of the file:

<blockquote>
<pre>/*
 * Structure for describing stored bitmaps.
 * Bitmaps are stored bit-big-endian (i.e., the 2^7 bit of the first
 * byte corresponds to x=0), as a sequence of bytes (i.e., you can't
 * do word-oriented operations on them if you're on a little-endian
 * platform like the Intel 80x86 or VAX).  Each scan line must start on
 * a (32-bit) word boundary, and hence is padded to a word boundary,
 * although this should rarely be of concern, since the raster and width
 * are specified individually.  The first scan line corresponds to y=0
 * in whatever coordinate system is relevant.
 *
 * For bitmaps used as halftone tiles, we may replicate the tile in
 * X and/or Y, but it is still valuable to know the true tile dimensions
 * (i.e., the dimensions prior to replication).  Requirements:
 *      width % rep_width = 0
 *      height % rep_height = 0
 *
 * For halftones at arbitrary angles, we provide for storing the halftone
 * data as a strip that must be shifted in X for different values of Y.
 * For an ordinary (non-shifted) halftone that has a repetition width of
 * W and a repetition height of H, the pixel at coordinate (X,Y)
 * corresponds to halftone pixel (X mod W, Y mod H), ignoring phase;
 * for a shifted halftone with shift S, the pixel at (X,Y) corresponds
 * to halftone pixel ((X + S * floor(Y/H)) mod W, Y mod H).  Requirements:
 *      strip_shift &lt; rep_width
 *      strip_height % rep_height = 0
 *      shift = (strip_shift * (size.y / strip_height)) % rep_width
 */
typedef struct gx_strip_bitmap_s {
        byte *data;
        int raster;                     /* bytes per scan line */
        gs_int_point size;              /* width, height */
        gx_bitmap_id id;
        ushort rep_width, rep_height;   /* true size of tile */
        ushort strip_height;
        ushort strip_shift;
        ushort shift;
} gx_strip_bitmap;</pre>
</blockquote>
</dl>

<hr>

<h1><a name="Coding_conventions"></a>Coding conventions</h1>

<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
<b><tt>gserrors.h</tt></b>; 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
<b><tt>gx.h</tt></b>, which is automatically included by
<b><tt>gdevprn.h</tt></b> but not by <b><tt>gserrors.h</tt></b>.  For
example

<blockquote><b><tt>
return_error(gs_error_VMerror);
</tt></b></blockquote>

<h2><a name="Allocating_storage"></a>Allocating storage</h2>

<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 <b><tt>gsmemory.h</tt></b>, which is
included in <b><tt>gx.h</tt></b>, which is included in
<b><tt>gdevprn.h</tt></b>.)  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>.

<h2><a name="Driver_instance_allocation"></a>Driver instance allocation</h2>

<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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -