📄 drivers.txt
字号:
* 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;
********
******** Coding conventions ********
********
All the driver procedures defined below that return int results return 0 on
success, or an appropriate negative error code in the case of error
conditions. The error codes are defined in gserrors.h; they correspond
directly to the errors defined in the PostScript language reference
manuals. The most common ones for drivers are:
gs_error_invalidfileaccess
An attempt to open a file failed.
gs_error_ioerror
An error occurred in reading or writing a file.
gs_error_limitcheck
An otherwise valid parameter value was too large for
the implementation.
gs_error_rangecheck
A parameter was outside the valid range.
gs_error_VMerror
An attempt to allocate memory failed. (If this
happens, the procedure should release all memory it
allocated before it returns.)
If a driver does return an error, it should use the return_error
macro rather than a simple return statement, e.g.,
return_error(gs_error_VMerror);
This macro is defined in gx.h, which is automatically included by
gdevprn.h but not by gserrors.h.
Allocating storage
------------------
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
gsmemory.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-address-space multi-tasking (some versions of Microsoft Windows).
char *gs_malloc(uint num_elements, uint element_size,
const char *client_name);
Like calloc, but unlike malloc, gs_malloc takes an element count
and an element size. For structures, num_elements is 1 and element_size is
sizeof the structure; for byte arrays, num_elements is the number of bytes
and element_size is 1. Unlike calloc, gs_malloc does NOT clear the block
of storage.
The client_name is used for tracing and debugging. It must be a
real string, not NULL. Normally it is the name of the procedure in which
the call occurs.
void gs_free(char *data, uint num_elements, uint element_size,
const char *client_name);
Unlike free, gs_free demands that num_elements and element_size be
supplied. It also requires a client name, like gs_malloc.
Driver instance allocation
--------------------------
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 that are registered in the
normal way (using the makefile approach described above), no special care
is needed as long as instances are only created by calling the
gs_copydevice procedure defined in gsdevice.h. 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 gsmemory.h and gsstruct.h.
********
******** Printer drivers ********
********
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: map_rgb_color (or
map_cmyk_color) and map_color_rgb. In addition, they must implement a
print_page or print_page_copies procedure. There are a set of macros in
gdevprn.h that generate the device structure for such devices, of which the
simplest is prn_device; for an example, see gdevbj10.c. If you are writing
a printer driver, we suggest you start by reading gdevprn.h and the
subsection on "Color mapping" below; you may be able to ignore all the rest
of the driver procedures.
The print_page procedures are defined as follows:
int (*print_page)(P2(gx_device_printer *, FILE *))
int (*print_page_copies)(P3(gx_device_printer *, FILE *, int))
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 print_page procedure must call one of the following
procedures:
int gdev_prn_copy_scan_lines(P4(gx_device_printer *pdev, int y, byte *str,
uint size)
For this procedure, str is where the data should be copied to, and size is
the size of the buffer starting at str. This procedure returns the number
of scan lines copied, or <0 for an error. str need not be aligned.
int gdev_prn_get_bits(gx_device_printer *pdev, int y, byte *str,
byte **actual_data)
This procedure reads out exactly one scan line. If the scan line is
available in the correct format already, *actual_data is set to point to it;
otherwise, the scan line is copied to the buffer starting at str, and
*actual_data is set to str. This saves a copying step most of the time.
str need not be aligned; however, if *actual_data is set to point to an
existing scan line, it will be aligned. (See the description of the
get_bits procedure below for more details.)
In either case, each row of the image is stored in the form described
in the comment under gx_tile_bitmap above; each pixel takes the
number of bits specified as color_info.depth in the device structure,
and holds values returned by the device's map_{rgb,cmyk}_color
procedure.
The print_page procedure can determine the number of bytes required to hold
a scan line by calling:
uint gdev_prn_raster(P1(gx_device_printer *))
For a very simple concrete example, we suggest reading the code in
bit_print_page in gdevbit.c.
If the device provides print_page, Ghostscript will call print_page the
requisite number of times to print the desired number of copies; if the
device provides print_page_copies, Ghostscript will call print_page_copies
once per page, passing it the desired number of copies.
********
******** Driver procedures ********
********
Most of the procedures that a driver may implement are optional. If a
device doesn't supply an optional procedure <proc>, the entry in the
procedure structure may be either gx_default_<proc>, e.g.
gx_default_tile_rectangle, or NULL or 0. (The device procedure must also
call the gx_default_ 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 will continue to work even if
new (optional) members are added.
Life cycle
----------
A device instance start out life in a closed state. In this state, no
output operations will occur. Only the following procedures may be called:
open_device
get_initial_matrix
get_params
put_params
When setdevice installs a device instance in the graphics state, it checks
whether the instance is closed or open. If the instance is closed,
setdevice 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:
- When a 'restore' occurs, if the instance was created since the
corresponding 'save';
- By the garbage collector, if the instance is no longer accessible;
- When Ghostscript exits (terminates).
Open/close/sync
---------------
int (*open_device)(P1(gx_device *)) [OPTIONAL]
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.
void (*get_initial_matrix)(P2(gx_device *, gs_matrix *)) [OPTIONAL]
Construct the initial transformation matrix mapping user
coordinates (nominally 1/72" per unit) to device coordinates. The default
procedure computes this from width, height, and x/y_pixels_per_inch on the
assumption that the origin is in the upper left corner, i.e.
xx = x_pixels_per_inch/72, xy = 0,
yx = 0, yy = -y_pixels_per_inch/72,
tx = 0, ty = height.
int (*sync_output)(P1(gx_device *)) [OPTIONAL]
Synchronize the device. If any output to the device has been
buffered, send / write it now. Note that this may be called several times
in the process of constructing a page, so printer drivers should NOT
implement this by printing the page. The default implementation does
nothing.
int (*output_page)(P3(gx_device *, int num_copies, int flush)) [OPTIONAL]
Output a fully composed page to the device. The num_copies
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 flush argument is true for showpage, false for
copypage. The default definition just calls sync_output. Printer drivers
should implement this by printing and ejecting the page.
int (*close_device)(P1(gx_device *)) [OPTIONAL]
Close the device: release any associated resources. After this,
output to the device is no longer allowed. The default implementation
does nothing.
Color/alpha mapping
-------------------
A given driver normally will implement either map_rgb_color or
map_cmyk_color, but not both. Black-and-white drivers do not need to
implement either one. Note that the map_xxx_color procedures must not
return gx_no_color_index (all 1's).
gx_color_index (*map_rgb_color)(P4(gx_device *, gx_color_value red,
gx_color_value green, gx_color_value blue)) [OPTIONAL]
Map a RGB color to a device color. The range of legal values of
the RGB arguments is 0 to gx_max_color_value. The default algorithm uses
the map_cmyk_color procedure if the driver supplies one, otherwise returns
1 if any of the values exceeds gx_max_color_value/2, 0 otherwise.
Ghostscript assumes that for devices that have color capability
(i.e., color_info.num_components > 1), map_rgb_color returns a color index
for a gray level (as opposed to a non-gray color) iff red = green = blue.
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))
[OPTIONAL]
Map a CMYK color to a device color. The range of legal values of
the CMYK arguments is 0 to gx_max_color_value. The default algorithm
calls the map_rgb_color procedure, with suitably transformed arguments.
Ghostscript assumes that for devices that have color capability
(i.e., color_info.num_components > 1), map_cmyk_color returns a color
index for a gray level (as opposed to a non-gray color) iff cyan = magenta
= yellow.
int (*map_color_rgb)(P3(gx_device *, gx_color_index color,
gx_color_value rgb[3])) [OPTIONAL]
Map a device color code to RGB values. The default algorithm
returns (0 if color==0 else gx_max_color_value) for all three components.
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)) [OPTIONAL]
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 gx_max_color_value;
alpha = 0 means transparent, alpha = gx_max_color_value means fully
opaque. The default is to use the map_rgb_color procedure and ignore
alpha.
Note that if a driver implements map_rgb_alpha_color, it must also
implement map_rgb_color, and must implement them in such a way that
map_rgb_alpha_color(dev, r, g, b, gx_max_color_value) returns the same
value as map_rgb_color(dev, r, g, b).
Note that there is no map_cmyk_alpha_color procedure. CMYK
devices currently do not support variable opacity; alpha is ignored on
such devices.
typedef enum { go_text, go_graphics } graphic_object_type;
int (*get_alpha_bits)(P4(gx_device *dev, graphic_object_type type)) [OPTIONAL]
Return the number of alpha (opacity) bits that should be used in
rendering an object of the given type. The default value is 1; the only
values allowed are 1, 2, and 4.
Drawing
-------
All drawing operations use device coordinates and device color values.
int (*fill_rectangle)(P6(gx_device *, int x, int y,
int width, int height, gx_color_index color))
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,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -