libplot: An overview
libplot 4.4 is a free function library for drawing
two-dimensional vector graphics. It can produce smooth,
double-buffered animations for the X Window System, and can export
graphics files in many file formats. It is `device-independent'
in the sense that its API (application programming interface) is to a
large extent independent of the output format. The API is
thread-safe, so it may be used in multithreaded programs.
There are bindings for C, C++, and other languages. The C binding,
which is the most frequently used, is also called
the C++ binding, when it needs to be distinguished, is called
libplotter. In this section we use
libplot to refer
to the library itself, irrespective of binding.
The graphical objects that
libplot can draw include paths,
`adjusted labels' (i.e., justified text strings), marker symbols, and
points (i.e., pixels). Paths may be simple or compound. A simple
path is a contiguous sequence of line segments, circular arcs, elliptic
arcs, quadratic Bezier curves, and/or cubic Bezier curves. A simple
path may also be a circle, an ellipse, or a rectangle. A compound
path consists of one or more nested simple paths. User-specified
filling of paths, both simple and compound, is supported (fill color and
fill rule, as well as pen color, may be specified).
There is support for maintaining a Postscript-style stack of graphics contexts, i.e., a stack of drawing attribute sets. Path-related attributes include pen color, line thickness, line type, cap type, join type, miter limit, fill color, fill rule, and transformation matrix, and text-related attributes include font name, font size, text angle, and transformation matrix.
The fundamental abstraction provided by
libplot is that of a
Plotter. A Plotter is an object with an interface for the
drawing of vector graphics which is similar to the interface provided by
a traditional pen plotter. There are many types of Plotter, which
differ in the output format they produce. Any number of Plotters, of
the same or different types, may exist simultaneously in an application.
The drawing operations supported by Plotters of different types are
identical, in agreement with the principle of device independence.
So a graphics application that is linked with
easily be written so as to produce output in any or all of the
supported output formats.
The following are the currently supported types of Plotter.
display, which is part of the free
display. The creation of animated pseudo-GIFs is supported.
idrawdrawing editor. See idraw.
xfigdrawing editor. The
xfigeditor can export drawings in various other formats for inclusion in documents. See xfig.
dxterm, the DECwindows terminal emulation program.
xterm, the X Window System terminal emulation program. The MS-DOS version of
kermitalso includes such an emulator.
plot. (See plot.)
A distinction among these types of Plotter is that all except X and X Drawable Plotters write graphics to a file or other output stream. An X Plotter pops up its own windows, and an X Drawable Plotter draws graphics in one or two X drawables.
Another distinction is that the first five types of Plotter (X, X Drawable, PNG, PNM, and GIF) produce bitmap output, while the remaining types produce output in a vector graphics format. In bitmap output the structure of the graphical objects is lost, but in a vector format it is retained.
An additional distinction is that X, X Drawable, ReGIS, Tektronix and Metafile Plotters are real-time. This means that they draw graphics or write to an output stream as the drawing operations are invoked on them. The remaining types of Plotter are not real-time, since their output streams can only be emitted after all functions have been called. For PNM and GIF Plotters, this is because the bitmap must be constructed before it is written out. For Illustrator and Postscript Plotters, it is because a `bounding box' line must be placed at the head of the output file. For a Fig Plotter, it is because color definitions must be placed at the head of the output file.
The most important operations supported by any Plotter are
closepl, which open and close it. Graphics may be drawn,
and drawing attributes set, only within an
closepl pair. The graphics produced within
closepl pair constitute a `page'. In
principle, any Plotter may be opened and closed arbitrarily many times.
An X Plotter displays each page in a separate X window, and
Postscript, PCL, and HP-GL Plotters render each page as a separate
physical page. X Drawable, ReGIS and Tektronix Plotters manipulate
a single drawable or display, on which pages are displayed in
succession. Plotters that do not draw in real time (PNG, PNM, GIF,
Illustrator, Postscript, CGM, Fig, PCL, and HP-GL Plotters) may wait
until their existence comes to an end (i.e., until they are deleted)
before outputting their pages of graphics.
In the current release of
libplot, Postscript and CGM Plotters
delay outputting graphics in this way, but PCL and HP-GL Plotters output
each page of graphics individually, i.e., when
invoked. PNG, PNM, GIF, SVG, Illustrator and Fig Plotters are similar,
but output only the first page. That is because PNG, PNM, GIF, SVG,
Illustrator and Fig formats support only a single page of graphics.
The graphics display, or `viewport', that is drawn in by a Plotter is normally a square or rectangular region on its output device. But when using any Plotter to draw graphics, a user will specify the coordinates of graphical objects in device-independent `user' coordinates, not in device coordinates. A Plotter transforms user coordinates to device coordinates by performing an affine transformation.
openpl to open a Plotter, an application would
space specifies a rectangular
`window' in the user coordinate system that will be mapped affinely to
the viewport on the output device. (The default window is a square,
with opposite corners (0,0) and (1,1).) The transformation from
user coordinates to device coordinates may be updated at any later time
space, or by invoking
fconcat operation will concatenate (i.e., compose) the current
affine transformation with any specified affine transformation. This
sort of concatenation is a capability familiar from, e.g., Postscript.
Each Plotter maintains a Postscript-style stack of graphics contexts. This makes possible the rapid, efficient drawing of complicated pages of graphics. A graphics context includes the current affine transformation from user coordinates to device coordinates. It also includes such modal drawing attributes as graphics cursor position, pen color, line type, line thickness, fill color, and the font used for drawing text. The state of any uncompleted path (if any) is included as well, since paths may be drawn incrementally, one portion (line segment, arc, or Bezier curve) at a time.
Warning: Much as in Postscript, the current graphics context
may be pushed onto the stack by calling
savestate, and popped off by calling
Postscript's drawing models are significantly different. In
libplot, the new graphics context created by
contains no path. So a new path may be constructed in it from
scratch, and drawn. Afterwards, the path in the former graphics context
will be returned to when
restorestate is called, at which
time it may be extended further. Another difference from Postscript is
libplot, there is no need to start a new path by calling
newpath' function. Instead, you just start drawing. At least in theory, you do need to end a path explicitly, by calling
endpath to request that it be drawn on the graphics display. But
the call to
endpath can usually be omitted. For example, calling
restorestate automatically invokes
endpath to end the path
(if any) contained in the current graphics context.
To permit vector graphics animation, any page of graphics may be split
into `frames'. A frame is ended, and a new frame is begun, by
erase operation. This first terminates the path
under construction, if any. What then happens depends on whether
the Plotter does real-time plotting. If it does (i.e., if the
Plotter is an X, X Drawable, ReGIS, Tektronix, or Metafile
erase removes all plotted objects from the graphics
display, allowing a new frame to be drawn. Displaying a sequence of
frames in succession creates the illusion of smooth animation.
On most Plotters that do not do real-time plotting (i.e., PNG, PNM,
SVG, Illustrator, Postscript, CGM, Fig, PCL, or HP-GL Plotters),
erase deletes all plotted objects from an internal
buffer. For this reason, most Plotters that do not do real-time
plotting will display only the final frame of any multiframe page.
GIF Plotters are in a class by themselves. Even though they do not do
real time plotting, a GIF Plotter can produce multi-image output,
i.e., an animated pseudo-GIF file, from a multiframe page. As noted
above, the pseudo-GIF file produced by a GIF Plotter will contain only
the first page of graphics. But if this page consists of multiple
frames, then each invocation of
erase after the first will be
treated, by default, as a separator between successive images.