Appendix E. Writing a Device Handler
E.1 Introduction
PGPLOT can be configured for a particular installation by adding or
removing ``device handlers''. A device handler is a subroutine which
handles all the device-specific aspects of graphical output for a
particular device or class of devices.
To write a new device handler, it is simplest to start by modifying an
existing one. This Appendix explains what the device handler must do,
but it does not explain how to do it---which is, of course, very
hardware-dependent.
E.2 The device dispatch routine GREXEC
All graphical output and input is handled by a ``device dispatch
routine'' in PGPLOT, called GREXEC
. Routine
GREXEC
is called whenever PGPLOT needs to determine
device-specific information or perform graphical I/O. This routine in
turn calls on the appropriate device handler. Reconfiguring PGPLOT
involves modifying the GREXEC
routine to use a different
set of device handlers; no other changes to PGPLOT are needed.
Usually the Fortran code for GREXEC
is created
automatically from a list of selected device handlers during the
installation of PGPLOT.
Table E.1: Example Device Dispatch Routine
C*GREXEC -- PGPLOT device handler dispatch routine
C+
SUBROUTINE GREXEC(IDEV,IFUNC,RBUF,NBUF,CHR,LCHR)
INTEGER IDEV, IFUNC, NBUF, LCHR
REAL RBUF(*)
CHARACTER*(*) CHR
C---
INTEGER NDEV
PARAMETER (NDEV=6)
CHARACTER*10 MSG
C---
GOTO(1,2,3,4,5,6) IDEV
IF (IDEV.EQ.0) THEN
RBUF(1) = NDEV
NBUF = 1
ELSE
WRITE (MSG,'(I10)') IDEV
CALL GRWARN('Unknown device code in GREXEC: '//MSG)
END IF
RETURN
C---
1 CALL NUDRIV(IFUNC,RBUF,NBUF,CHR,LCHR)
RETURN
2 CALL PSDRIV(IFUNC,RBUF,NBUF,CHR,LCHR,1)
RETURN
3 CALL PSDRIV(IFUNC,RBUF,NBUF,CHR,LCHR,2)
RETURN
4 CALL TTDRIV(IFUNC,RBUF,NBUF,CHR,LCHR,1)
RETURN
5 CALL XWDRIV(IFUNC,RBUF,NBUF,CHR,LCHR,1)
RETURN
6 CALL XWDRIV(IFUNC,RBUF,NBUF,CHR,LCHR,2)
RETURN
C
END
Table E.1 gives an example. The first argument (IDEV
) is
an integer specifying the type of the currently selected
device. Routine GREXEC
calls the appropriate device
handler for this type, passing the remaining arguments to the device
handler. If IDEV
is zero, GREXEC
returns the
number of device types available. Some device handlers handle more
than one PGPLOT device type: e.g., in the above example
PSDRIV
handles both types PS and VPS. The last argument
passed to the device handler is an integer specifying which of the
supported types is required. This argument is omitted for handlers
that support only one type (NUDRIV
in the above example).
To reconfigure PGPLOT, GREXEC
must be modified as
follows: (a) set parameter NDEV
to the number of device
types; (b) make sure that the computed-goto statement has
NDEV
branches; (c) supply a target for each branch to
call the appropriate device handler.
E.3 Device handler interface
A device handler is a Fortran (or Fortran-callable) subroutine. The
name of the subroutine must be of the form xxDRIV, where
xx is a two-character code for the device type, usually the
first two letters of the type; this code must (of course) be different
for each different device handler.
SUBROUTINE xxDRIV (OPCODE, RBUF, NBUF, CHR, LCHR, MODE)
INTEGER OPCODE
REAL RBUF(*)
INTEGER NBUF
CHARACTER*(*) CHR
INTEGER LCHR
INTEGER MODE
The first argument (OPCODE
) is an integer ``operation
code'' which specifies what operation the device handler is to
perform; it is an input parameter to the subroutine (see Table
E.2). The MODE
argument is another input parameter that
distinguishes between multiple device types supported by the same
handler. The other arguments are used for both input and output, and
their meaning depends on the value of the operation code. Not all
arguments are used for every operation code. RBUF
is a
floating-point array used to pass numerical data to or from the device
handler, and NBUF
indicates how many elements of the
array are used. CHR
is a character variable used to pass
character data to or from the device handler, and LCHR
indicates how many characters are used. NBUF
or
LCHR
should be set to zero if no data of the
corresponding type are passed. If the function requested by the
operation code (OPCODE
) is not implemented in the device
handler, the subroutine should set NBUF = -1
before returning.
The device handler subroutine can communicate with PGPLOT only
through the arguments. It should not attempt to reference the PGPLOT
common blocks (this is because the internal structure of the PGPLOT
common blocks may change). Data stored internally by the handler
between calls should be placed in static storage (use the Fortran
SAVE
statement).
Table E.2: Device Handler Operation Codes
Opcode Function
1 Return device type
2 Return maximum dimensions of view surface,
and range of color index
3 Return device scale
4 Return device capabilities
5 Return default device/file name
6 Return default size of view surface
7 Return miscellaneous defaults
8 Select device
9 Open workstation
10 Close workstation
11 Begin picture
12 Draw line
13 Draw dot
14 End picture
15 Set color index
16 Flush buffer
17 Read cursor
18 Erase alpha screen
19 Set line style
20 Polygon fill
21 Set color representation
22 Set line width
23 Escape function
24 Rectangle fill
25 Set fill pattern
26 Line of pixels
27 Scaling information
28 Draw marker
29 Query color representation
E.4 Handler state
PGPLOT will send commands to the device handler in a set sequence.
Inquiry commands (opcodes 1--7 and 29) may be sent at any time,
whether or not a device has been selected for output. The open
workstation and close workstation commands are used to open
and close a device. The begin picture and end picture
commands are used to start and finish a ``frame'' (one page on a
hardcopy device). Graphical output commands (opcodes 12--13, 16--20,
and 22--28) are only used between begin picture and end
picture. The set-color-representation command (opcode 21) can be
used at any time that a device is open. Thus the sequence of commands
for a plot consisting of two frames will be:
(query commands)
open workstation
(query commands, set color rep)
begin picture
(graphical output commands)
end picture
(query commands, set color rep)
begin picture
(graphical output commands)
end picture
close workstation
Any violation of this sequence is due to a bug in PGPLOT.
Device handlers should attempt to trap all errors, including I/O
errors (e.g., insufficient disk space or insufficient memory), and
issue a warning message rather than terminating execution of the
program.
E.5 Summary of operations
OPCODE = 1, Return device type
This is an inquiry function; the handler returns the name by which the
the user will refer to the device type, e.g., `PRINTRONIX' for a
Printronix device handler. This name must be different for each mode
of each device handler installed in PGPLOT, and should preferably be
unique in the first two or three characters. An identifying character
string (displayed by routine PGLDEV
) can be included in
parentheses after the name.
Parameters returned by handler:
- CHR(:LCHR): the device type supported by the
handler in the specified mode.
OPCODE = 2, Return maximum dimensions of view surface, and
range of color index
This is an inquiry function; the handler returns the maximum
dimensions of the plot surface, and the range of color indices
available. These will usually be the same as the default dimensions,
but if it is possible to make a larger image, the maximum dimensions
may be larger. If there is no set upper limit to a dimension, the
corresponding maximum should be set to -1. All dimensions are
in device coordinates. All devices should support color indices 0 and
1; color and gray-scale devices will allow color indices >1 up
to a device-dependent maximum value (which should not exceed
255). Color index 0 is the background color and is used to erase; if
it is not possible to erase by overwriting in the background color,
then requests to write in color index 0 should be ignored.
Parameters returned by handler:
- RBUF(1): Minimum physical x value (set to zero).
- RBUF(2): Maximum physical x value
(a value of -1 indicates no effective maximum).
- RBUF(3): Minimum physical y value (set to zero).
- RBUF(4): Maximum physical y value
(a value of -1 indicates no effective maximum).
- RBUF(5): Minimum allowed color index (usually 0).
- RBUF(6): Maximum allowed color index (in range 1--255).
OPCODE = 3, Return device scale
This is an inquiry function; the handler returns the device scale in
device coordinate units per inch (1 inch = 25.4 mm). Usually, the
units of the device coordinates are pixels, so this also gives the
physical resolution in pixels per inch. For hardcopy devices, the
values should be as accurate as possible, to ensure that an image has
the correct scale. For video display terminals and other devices where
the scale is variable, nominal values should be returned.
Parameters returned by handler:
- RBUF(1): x scale in device coordinates per inch.
- RBUF(2): y scale in device coordinates per inch.
- RBUF(3): ``pen diameter'' in device coordinates
(i.e., the width of a hardware line); this value is used by PGPLOT
when emulating thick lines and polygon fill (usually 1).
OPCODE = 4, Return device capabilities
This is an inquiry function which is used to inform PGPLOT of the
device's capabilities. If the device lacks a capability in hardware,
PGPLOT will try to emulate it.
Parameters returned by handler:
- CHR(1:1) = `H' if the device is a hardcopy device, `I' if it is an
interactive device. On an interactive device, the image is visible as
it is being drawn, while on a hardcopy device it cannot be viewed until
the workstation is closed.
- CHR(2:2) = `C' if a cursor is available, `X' if a cursor is available
and opcode 27 is accepted by the handler, `N' if there is no cursor.
PGPLOT cannot emulate a cursor if none is available.
- CHR(3:3) = `D' if the hardware can draw dashed lines, `N' if it
cannot. PGPLOT emulates dashed lines by drawing line
segments. Software emulation is usually superior to hardware dashed
lines, and not much slower, so CHR(3:3) = `N' is recommended.
- CHR(4:4) = `A' if the hardware can fill arbitrary polygons with solid
color, `N' if it cannot. PGPLOT emulates polygon fill by drawing
horizontal or vertical lines spaced by the pen diameter (see OPCODE =
3).
- CHR(5:5) = `T' if the hardware can draw lines of variable width, `N'
if it cannot. PGPLOT emulates thick lines by drawing multiple
strokes. Note that thick lines are supposed to have rounded ends, as
if they had been drawn by a circular nib of the specified diameter.
- CHR(6:6) = `R' if the hardware can fill rectangles with solid color,
`N' if it cannot. If this feature is not available, PGPLOT will treat
the rectangle as an arbitrary polygon. In this context, a `rectangle'
is assumed to have its edges parallel to the device-coordinate axes.
- CHR(7:7) = `P' if the handler understands the pixel primitives, 'Q' if
it understands the image primitives (opcode 26), or `N' otherwise (see
the description of opcode 26).
- CHR(8:8) = `V' if PGPLOT should issue an extra prompt to the user
before closing the device (in
PGEND
), `N' otherwise. Use `V' for
devices where the PGPLOT window is deleted from the screen when the
device is closed.
- CHR(9:9) = `Y' if the handler accepts color representation queries
(opcode 29), `N' if it does not.
- CHR(10:10) = `M' if the device handler accepts opcode 28 to draw graph
markers; `N' otherwise.
OPCODE = 5, Return default device/file name
This is an inquiry routine. The device handler returns the device or
file name to be used if the PGPLOT device specification does not
include one. (On VMS, the default file name may also be used to fill
in missing fields of the supplied file name, e.g., disk, directory,
and file type.)
Parameters returned by handler:
- CHR(:LCHR): default device/file name.
OPCODE = 6, Return default size of view surface
This is an inquiry function; the handler returns the default
dimensions of the plot surface in device coordinates. At present,
PGPLOT assumes that the device coordinates of the bottom left corner
are (0,0). Note: on some devices the default size can change during
PGPLOT execution; e.g., on windowing workstations the window manager
may allow the user to change the size of the PGPLOT window. PGPLOT
uses this opcode to determine the current the default size before
starting each new page.
Parameters returned by handler:
- RBUF(1): default x-coordinate of bottom left
corner (must be zero).
- RBUF(2): default x-coordinate of top right
corner.
- RBUF(3): default y-coordinate of bottom left
corner (must be zero).
- RBUF(4): default y-coordinate of top right
corner.
OPCODE = 7, Return miscellaneous defaults
This is an inquiry routine. The handler returns a scale-factor to be
used for the ``obsolete character set'' used by old GRPCKG routines
but not by PGPLOT.
Parameters returned by handler:
- RBUF(1): character scale factor (integer, > 0).
OPCODE = 8, Select device
A PGPLOT device handler may handle more than one open device at once.
All graphical I/O operations apply to the ``active'' device. This
opcode is used to select a new active device; note that opcode 9 (open
workstation) also changes the active device.
Parameters passed to handler:
- RBUF(1): plot ID. This is not needed by the handler, and can be ignored.
- RBUF(2): identification number of selected device (as
returned by open workstation).
OPCODE = 9, Open workstation
Allocate an I/O channel to the requested device and open the device.
Any hardware resets that need to be done once for a plot session
(which could consist of several frames) should be done here. Allocate
buffer, if its size is fixed for the device. No visible I/O should be
performed on an interactive device: e.g., the screen should not be
cleared; this should be deferred until the begin picture call.
Parameters passed to handler:
- RBUF(3): if this is not 0.0, the device specification
included the /APPEND flag. If this flag is specified, the device
handler should suppress any initial screen erase so that the new image
is superimposed on any previously displayed image. The device handler
may ignore this if it is inappropriate (e.g., for a hardcopy device).
- CHR(:LCHR): the file/device to be opened. This may be
a physical device name or the name of a disk file.
Parameters returned by handler:
- RBUF(1): identification number for the opened device; PGPLOT will
use this number in subsequent select device calls for this
device (see OPCODE = 8).
- RBUF(2): error flag; 1.0 indicates that the
workstation was opened successfully; any other number indicates an
error.
OPCODE = 10, Close workstation
Close the device opened by the open workstation command, and
deallocate any resources allocated for the device (e.g., memory, I/O
channels).
OPCODE = 11, Begin picture
Prepare the workstation for plotting. This command has two arguments
which specify a size for the view surface overriding the default size;
if the device handler is unable to change the size of the view
surface, it may ignore these arguments. On interactive devices, erase
the screen. Note: this command has no way to return an error to the
user; if an error occurs (e.g., insufficient memory for a frame
buffer), the handler should issue an error message (with routine
GRWARN
) and ignore subsequent output commands, rather than
terminating execution of the program.
Parameters passed to handler:
- RBUF(1): maximum x coordinate.
- RBUF(2): maximum y coordinate.
OPCODE = 12, Draw line
Draw a straight line from device coordinates (x1,y1) to
(x2,y2) using the current line attributes (color index, line
style, and line width). The coordinates are floating point, and may
need to be rounded to the nearest integer before they are passed to
the hardware; they are in the range (0,0) to the maxima specified
with begin picture.
Parameters passed to handler:
- RBUF(1): x1.
- RBUF(2): y1.
- RBUF(3): x2.
- RBUF(4): y2.
OPCODE = 13, Draw dot
Draw a dot at device coordinates (x,y) using the current line
attributes (color index and line width). The result should be an
approximation to a filled circle of diameter equal to the line width,
or a dot of minimum size if line width is 0. The coordinates are
floating point, and may need to be rounded to the nearest integer
before they are passed to the hardware.
Parameters passed to handler:
OPCODE = 14, End picture
Terminate the current frame. On hardcopy devices always advance the
paper. On interactive devices, clear the screen only if requested.
Deallocate buffers that were created by begin picture (OPCODE
= 11).
Parameters passed to handler:
-
RBUF(1): if not 0.0, clear screen.
OPCODE = 15, Set color index
Set the color index for subsequent plotting. The default color index
is 1.
Parameters passed to handler:
- RBUF(1): color index; in range defined by OPCODE = 2.
OPCODE = 16, Flush buffer
If the handler is buffering output to an interactive device, it should
flush its buffers to ensure that the displayed image is up to date.
Hardcopy devices can ignore this opcode.
OPCODE = 17, Read cursor
This function is not used if OPCODE = 4 indicates that the device has
no cursor.
The handler should make the cursor visible at position (x,y), allow
the user to move the cursor, and wait for a key stroke. It should then
return the new cursor (x,y) position and the character (key stroke)
typed. (If it is not possible to make the cursor visible at a
particular position, the handler may ignore the requested (x,y)
coordinates.) On a device with a mouse or similar device, clicking
mouse-button 1 should return character `A', mouse-button 2 should
return `D', and mouse-button 3 should return `X'.
If the hardware permits, the handler should interpret the ``mode'' as
specified in the description of routine PGBAND
. The exact
appearance of the dynamic ``rubber band'' lines may be hardware
specific; if possible, they should be drawn with the current color
index, but they must not erase previously drawn graphics. Handlers
that cannot draw the ``rubber band'' lines should treat all modes as
mode = 0.
Parameters passed to handler:
- RBUF(1): initial x position of cursor.
- RBUF(2): initial y position of cursor.
- RBUF(3): x position of reference point.
- RBUF(4): y position of reference point.
- RBUF(5): mode = 0 (no feedback), 1 (rubber band), 2
(rubber rectangle), 3 (vertical range), 4 (horizontal range). 5
(horizontal line), 6 (vertical line), 7 (cross-hair).
Parameters returned by handler:
- RBUF(1): x position of cursor.
- RBUF(2): y position of cursor.
- CHR(1:1): character typed by user.
OPCODE = 18, Erase alpha screen
If the graphics device is a terminal that displays both graphics and
text on the same screen, clear the text screen, leaving graphics
unchanged. All other devices should ignore this opcode.
OPCODE = 19, Set line style
This opcode is not used if OPCODE = 4 indicates that the device does
not support hardware dashing; PGPLOT will use software-generated
dashed lines.
Parameters passed to handler:
- RBUF(1): requested line style (integer 1--5).
OPCODE = 20, Polygon fill
This function is not used if OPCODE = 4 indicates that the device does
not support hardware polygon fill. The polygon may be arbitrarily
complex (concave or re-entrant); if the hardware cannot cope with
this, the handler should set the OPCODE = 4 response to disable
hardware fill. If hardware fill is enabled, the handler should
respond to this function by filling the polygon with the current color
index. To draw an N-sided polygon, PGPLOT uses this opcode
N+1 times.
Parameters passed to handler on first call:
- RBUF(1): number of points N in polygon.
Parameters passed to handler on next N calls:
- RBUF(1): x value.
- RBUF(2): y value.
OPCODE = 21, Set color representation
Assign the specified (R,G,B) color, or the best available
approximation, to the specified color index. If colors cannot be
changed dynamically, ignore the request.
Parameters passed to handler:
- RBUF(1): color index (integer, in range defined by OPCODE = 2).
- RBUF(2): red component (0.0--1.0).
- RBUF(3): green component (0.0--1.0).
- RBUF(4): blue component (0.0--1.0).
OPCODE = 22, Set line width
This function is not used if OPCODE = 4 indicates that the device does
not support hardware thick lines. Subsequent lines and dots should be
drawn with the requested width, or the closest available
approximation. The units of line-width are 0.005 inches. A requested
line-width of zero should give the narrowest line available on the
device (``hair line'').
Parameters passed to handler:
- RBUF(1): requested line width, in units of 0.005 inch.
OPCODE = 23, Escape function
This function allows an arbitrary character string to be sent to the
device handler. The interpretation is up to the handler; usually, the
string will be sent directly to the device or ignored. Use of this
function should be avoided.
Parameters passed to handler:
- CHR(:LCHR): character string.
OPCODE = 24, Rectangle fill
This function is not used if OPCODE = 4 indicates that the device does
not support hardware rectangle fill.
Parameters passed to handler:
- RBUF(1), RBUF(2): x,y coordinates of lower left
corner of rectangle.
- RBUF(3), RBUF(4): x,y coordinates of upper right
corner of rectangle.
OPCODE = 25, Set fill pattern
This function is not yet implemented.
OPCODE = 26, Line of pixels or Image
This operation is used for gray-scale and color imaging (e.g., routine
PGGRAY). It is used in two different ways, depending whether OPCODE=4
reports CHR(7:7) = 'P' or 'Q'.
Case P
This function is used to write a horizontal line of pixels on
the device screen with specified color indices; it should be more
efficient to do this with one device handler call rather than separate
calls for each pixel. If the device handler implements this operation,
it is important that the device coordinates should be true pixel
numbers.
Parameters passed to handler:
- RBUF(1), RBUF(2): x,y coordinates of the first pixel
to be written. These should be integer pixel numbers in the device
coordinate system (passed as REAL numbers).
- RBUF(3),...RBUF(NBUF): color indices for n pixels
to be filled in, starting at (x,y) and ending at (x+n-1,y). The
values should be valid integer color indices for the device (passed as
REAL numbers). The number of pixels is specified by the argument NBUF:
n =
NBUF - 2
.
Case Q
This case is used for devices like PostScript where PGPLOT cannot
address individual device pixels; the handler, or the device, must map
the image array onto hardware pixels, taking care of clipping. In
this case, the first call specifies the parameters of the image, and
subsequent calls pass color indices of image pixels, and a final call
indicates the end of the image.
Parameters passed to handler on first call:
- RBUF(1): 0.0 (indicates start of image).
- RBUF(2,3): dimension of the image (image pixels in x
and y).
- RBUF(4),...RBUF(7): the current clipping rectangle, in
device coordinates.
- RBUF(8),...RBUF(13): a matrix used to transform image
coordinates to device coordinates.
Parameters passed to handler on first call:
- RBUF(1): number n of pixels in this call (> 0).
- RBUF(2),...RBUF(n+1): color indices for n pixels.
Parameters passed to handler on last call:
OPCODE = 27, Scaling information
This function is only used if OPCODE = 4 indicates a cursor of type X.
It is used to tell the device handler what the user's (world) coordinate
system is. The handler may ignore the information, or it may use it to
generate a read-out of the cursor position in the world coordinate
system.
Parameters passed to handler:
- RBUF(1)...RBUF(4): should be interpreted as follows:
(xd,yd) are device coordinates, as used by the handler, (xw,yw)
are user's world coordinates:
xw = [xd - RBUF(1)]/RBUF(2),
yw = [yd - RBUF(3)]/RBUF(4).
The device handler may (but is not required to) display the current
cursor location, in world coordinates. The display can be continuous or
only while the PGPLOT cursor is active (during execution of opcode 17).
Until opcode 27 is received, the handler should assume that
(xw,yw)=(xd,yd).
OPCODE = 28, Draw marker
This function is only used if OPCODE = 4 indicates that the device
handler can draw graph markers. If it is to be used, the device
handler (or hardware) must know how to draw each of the markers
numbered 0 to 31 (see Figure 4.1).
Parameters passed to handler:
- RBUF(1): the number of the marker symbol to be drawn
(integer, 0--31).
- RBUF(2), RBUF(3): the x,y coordinates of the center
of the marker (device coordinates).
- RBUF(4): scale factor (number of device units per
unit of ``marker coordinate space''). The shapes of the marker symbols
are defined in a coordinate system in which the radius of typical
symbols is 10 units or less; for more information, see the Hershey
definitions of the markers (Appendix B).
OPCODE = 29, Query color representation
This function ay be called at any time after open workstation (9) and
before close workstation (10). It will not be called if the handler
does not report itself as having this capability. The handler should
attempt to return the actual color representation in use on the
device, if it is possible that this is different from the values
requested. Otherwise it should return the values requested in the last
call with opcode 21 (set color representation) for this color index.
(Re-calling opcode 21 with the values returned by opcode 29 should not
change the actual color representation!) If the handler does not have
this capability, PGQCR
will return R=G=B=0.0 for color
index 0 and R=G=B=1.0 for all other color indices.
Parameters passed to handler:
- NBUF = 1
- RBUF(1) = color index to query (integer, passed as real),
in the device range reported by opcode 2.
Parameters returned by handler:
- NBUF = 4
- RBUF(1) = unchanged from input,
- RBUF(2) = red component [real, 0.0--1.0],
- RBUF(3) = green component [real, 0.0--1.0],
- RBUF(4) = blue component [real, 0.0--1.0].
Next: Appendix F
PGPLOT
Tim Pearson, California Institute of Technology,
tjp@astro.caltech.edu
Copyright © 1995-1996 California Institute of Technology