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

📄 drivers.txt

📁 实现并行算法
💻 TXT
📖 第 1 页 / 共 4 页
字号:
   Copyright (C) 1989, 1996 Aladdin Enterprises.  All rights reserved.
  
  This file is part of Aladdin Ghostscript.
  
  Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  or distributor accepts any responsibility for the consequences of using it,
  or for whether it serves any particular purpose or works at all, unless he
  or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  License (the "License") for full details.
  
  Every copy of Aladdin Ghostscript must include a copy of the License,
  normally in a plain ASCII text file named PUBLIC.  The License grants you
  the right to copy, modify and redistribute Aladdin Ghostscript, but only
  under certain conditions described in the License.  Among other things, the
  License requires that the copyright notice and this notice be preserved on
  all copies.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

This file, drivers.txt, describes the interface between Ghostscript and
device drivers.

For an overview of Ghostscript and a list of the documentation files, see
README.

********
******** Adding a driver ********
********

To add a driver to Ghostscript, all you need to do is edit devs.mak in
two places.  The first is the list of devices, in the section headed

# -------------------------------- Catalog ------------------------------- #

Pick a name for your device, say smurf, and add smurf to the list.
(Device names must be 1 to 8 characters, consisting of only letters,
digits, and underscores, of which the first character must be a letter.
Case is significant: all current device names are lower case.)
The second is the section headed

# ---------------------------- Device drivers ---------------------------- #

Suppose the files containing the smurf driver are called joe and fred.
Then you should add the following lines:

# ------ The SMURF device ------ #

smurf_=joe.$(OBJ) fred.$(OBJ)
smurf.dev: $(smurf_)
	$(SETDEV) smurf $(smurf_)

joe.$(OBJ): joe.c ...and whatever it depends on

fred.$(OBJ): fred.c ...and whatever it depends on

If the smurf driver also needs special libraries, e.g., a library named
gorf, then the entry should look like this:

smurf.dev: $(smurf_)
	$(SETDEV) smurf $(smurf_)
	$(ADDMOD) smurf -lib gorf

If, as will usually be the case, your driver is a printer driver (as
discussed below), the device entry should look like this:

smurf.dev: $(smurf_) page.dev
	$(SETPDEV) smurf $(smurf_)

or

smurf.dev: $(smurf_) page.dev
	$(SETPDEV) smurf $(smurf_)
	$(ADDMOD) smurf -lib gorf

********
******** Keeping things simple
********

If you want to add a simple device (specifically, a black-and-white
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 BubbleJet
drivers (gdevepsn.c and gdevbj10.c) are good models for dot-matrix
printers, which require presenting the data for many scan lines at once;
the DeskJet/LaserJet drivers (gdevdjet.c) 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, gdevcdj.c and gdevstc.c, are
far too complex to read.)

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.

Duplication of code, and sheer code volume, 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 copying code.  gdevepsn.c and gdevdjet.c
are good examples of this approach.

********
******** Driver structure ********
********

A device is represented by a structure divided into three parts:

	- procedures that are shared by all instances of each device;

	- parameters that are present in all devices but may be different
	  for each device or instance; and

	- device-specific parameters that may be different for each instance.

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 const, but for backward
compatibility reasons are not.

The gx_device_common 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 gxdevice.h
or, if applicable, gdevprn.h.

	typedef struct smurf_device_s {
		gx_device_common;
		... device-specific parameters ...
	} smurf_device;
	smurf_device far_data gs_smurf_device = {
		... macro for generic parameter values ...,
		{ ... procedures ... },		/* std_procs */
		... device-specific parameter values if any ...
	};

The device structure instance *must* have the name gs_smurf_device, where
smurf is the device name used in devs.mak.

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 gx_device * as their first
argument, and must cast it to smurf_device * internally.  For example, in
the code for the "memory" device, the first argument to all routines is
called dev, but the routines actually use mdev to reference elements of the
full structure, by virtue of the definition

	#define mdev ((gx_device_memory *)dev)

(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.)

Structure definition
--------------------

You should consult the definition of struct gx_device_s in gxdevice.h for
the complete details of the generic device structure.  Some of the most
important members of this structure for ordinary drivers are:

	const char *dname;		/* the device name */
	bool is_open;			/* true if device has been opened */
	gx_device_color_info color_info;	/* color information */
	int width;			/* width in pixels */
	int height;			/* height in pixels */

The name in the structure (dname) should be the same as the name in
devs.mak.

gx_device_common is a macro consisting of just the element definitions.

For sophisticated developers only
---------------------------------

If for any reason you need to change the definition of the basic device
structure, or add procedures, you must change the following places:

	- This document and NEWS (if you want to keep the
	    documentation up to date).
	- The definition of gx_device_common and/or the procedures
	    in gxdevice.h.
	- Possibly, the default forwarding procedures declared in gxdevice.h
	    and implemented in gdevnfwd.c.
	- The device procedure record completion routines in gdevdflt.c.
	- Possibly, the default device implementation in gdevdflt.c and
	    gdevddrw.c.
	- If you are adding procedures that produce output, the bounding box
	    device in gdevbbox.c.
	- The following devices that must have complete (non-defaulted)
	    procedure vectors:
		- The null device in gdevnfwd.c.
		- The command list "device" in gxclist.c.  This is
		    not an actual device; it only defines procedures.
		- The "memory" devices in gdevmem.h and gdevm*.c.
		- The halftoning device in gdevht.c.
	- The clip list accumulation "device" in gxacpath.c.
	- The clipping "devices" in gxcpath.c and gxclip2.c.
	- The Pattern accumulation "device" in gxpcmap.c.
	- The generic printer device macros in gdevprn.h.
	- The generic printer device code in gdevprn.c.

You may also have to change the code for gx_default_get_params and/or
gx_default_put_params (in gsdparam.c).

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

********
******** Types and coordinates ********
********

Coordinate system
-----------------

Since each driver specifies the initial transformation from user to device
coordinates, the driver can use any coordinate system it wants, as long as a
device coordinate will fit in an int.  (This is only an issue on MS-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 X increasing to the right and Y 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.

Drivers must check (and, if necessary, clip) the coordinate parameters
given to them: they should not assume the coordinates will be in bounds.
The fit_fill and fit_copy macros in gxdevice.h are very helpful in doing
this.

Color definition
----------------

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
gx_color_index).  Drivers may provide a uniformly spaced gray ramp or
color cube for halftoning, or they may do their own color approximation,
or both.

The color_info member of the device structure defines the color and
gray-scale capabilities of the device.  Its type is defined as follows:

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;

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

#define dci_black_and_white ...
#define dci_color(depth,maxv,dither) ...

The idea is that a device has a certain number of gray levels (max_gray +1)
and a certain number of colors (max_rgb +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
num_components is 1, it converts all colors to gray levels.)  If so:

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

If the color is not a gray level:

	- If max_rgb is large (>= 31), Ghostscript asks the device to
approximate the color directly.  If the device returns a valid
gx_color_index, Ghostscript uses it.  Otherwise, Ghostscript assumes that
the device can represent dither_rgb * dither_rgb * dither_rgb distinct
colors, equally spaced throughout the color cube, and uses two of the
nearest ones to the desired color for halftoning.

Types
-----

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

gx_color_value (defined in gxdevice.h)

	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:
gx_color_value_bits is the number of bits actually used, and
gx_max_color_value is the maximum value (equal to 2^gx_max_color_value_bits
- 1).

gx_device (defined in gxdevice.h)

	This is the device structure, as explained above.

gs_matrix (defined in gsmatrix.h)

	This is a 2-D homogenous coordinate transformation matrix, used by
many Ghostscript operators.

gx_color_index (defined in gxdevice.h)

	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 gx_color_index values: it gets them from
map_rgb_color or map_cmyk_color and hands them back as arguments to
several other procedures.  The special value gx_no_color_index (defined as
(gx_color_index)(-1)) means "transparent" for some of the procedures.  The
type definition is simply:

	typedef unsigned long gx_color_index;

gs_param_list (defined in gsparam.h)

	This is a parameter list, which is used to read and set attributes
in a device.  See the comments in gsparam.h, and the description of the
get_params and put_params procedures below, for more detail.

gx_tile_bitmap (defined in gxbitmap.h)
gx_strip_bitmap (defined in gxbitmap.h)

	These structure types represent bitmaps to be used as a tile for
filling a region (rectangle).  gx_tile_bitmap is an older type lacking shift
and rep_shift; gx_strip_bitmap has superseded it, and it should not be used
in new code.  Here is a copy of the relevant part of the file:

/*
 * Structure for describing stored bitmaps.

⌨️ 快捷键说明

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