home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 5
/
FreshFish_July-August1994.bin
/
bbs
/
gnu
/
gs-2.6.1.4-src.lha
/
src
/
amiga
/
gs-2.6.1.4
/
drivers.doc
< prev
next >
Wrap
Text File
|
1994-01-27
|
28KB
|
679 lines
Copyright (C) 1989, 1990, 1991, 1992, 1993 Aladdin Enterprises.
All rights reserved.
This file is part of Ghostscript.
Ghostscript is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
to anyone for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing. Refer
to the Ghostscript General Public License for full details.
Everyone is granted permission to copy, modify and redistribute
Ghostscript, but only under the conditions described in the Ghostscript
General Public License. A copy of this license is supposed to have been
given to you along with Ghostscript so you can know your rights and
responsibilities. It should be in a file named COPYING. Among other
things, the copyright notice and this notice must be preserved on all
copies.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
This file, drivers.doc, 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_)
$(SHP)gssetdev 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 gssetdev line should look like
$(SHP)gssetdev smurf $(smurf_)
$(SHP)gsaddmod 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, the DeskJet 500 C driver (gdevcdj.c) is
a good place to start.
On the other hand, if you're writing a driver for some more esoteric
device, or want to do something like add new settable attributes (besides
page size and resolution), 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.
********
******** 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.
The gx_device_common macro defines the common structure elements, with the
intent that devices define and export a structure along the following
lines:
typedef struct smurf_device_s {
gx_device_common;
... device-specific parameters ...
} smurf_device;
smurf_device gs_smurf_device = {
sizeof(smurf_device), * params_size
{ ... procedures ... }, * procs
... generic parameter values ...
... device-specific parameter values ...
};
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 md to reference
elements of the full structure, by virtue of the definition
#define md ((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
--------------------
This essentially duplicates the structure definition in gxdevice.h.
typedef struct gx_device_s {
int params_size; /* size of this structure */
gx_device_procs *procs; /* pointer to procedure structure */
char *name; /* the device name */
int width; /* width in pixels */
int height; /* height in pixels */
float x_pixels_per_inch; /* x density */
float y_pixels_per_inch; /* y density */
gs_rect margin_inches; /* margins around imageable area, */
/* in inches */
gx_device_color_info color_info; /* color information */
int is_open; /* true if device has been opened */
} gx_device;
The name in the structure 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.
- The null device in gsdevice.c. (Note that this device does
not allow procedure defaulting.)
- The tracing "device" in gstdev.c. (Ditto.)
- The command list "device" in gxclist.c. (Ditto.)
- The clip list accumulation and clipping "devices" in gxcpath.c.
(Ditto.)
- The "memory" devices in gdevmem.h and gdevmem*.c. (Ditto.)
- The generic printer device macros in gdevprn.h.
- The generic printer device code in gdevprn.c.
- All the real devices in the standard Ghostscript distribution,
as listed in devs.mak. (Most of the printer devices are
created with the macros in gdevprn.h, so you may not have to
edit the source code for them.)
- Any other drivers you have that aren't part of the standard
Ghostscript distribution.
You may also have to change the code for gx_default_get_props and/or
gx_default_put_props (in gsdevice.c). Note that if all you are doing
is adding optional procedures, you do NOT have to modify any device
drivers other than the ones specifically listed above; Ghostscript
will substitute the default procedures properly.
********
******** Coding conventions ********
********
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
malloc to allocate any storage that stays around after the procedure
returns. Instead, they must use gs_malloc and gs_free, which have
slightly different calling conventions. (The prototypes for these are in
gs.h, which is included in gx.h, which is included in gdevprn.h.) This is
necessary so that Ghostscript can clean up all allocated memory before
exiting, which is essential in environments that provide only
single-addr