Next: X Programming, Previous: Animated GIFs, Up: C Programming
You may use GNU libplot
to produce vector graphics animations on
any Plotter that does real-time plotting (i.e., an X, X Drawable, ReGIS, Tektronix, or Metafile Plotter). By definition, the
`frames' in any page of graphics are separated by invocations of
erase
. So the graphics display will be cleared after each
frame. If successive frames differ only slightly, a smooth
animation will result.
The following is a sample application, written in C, that produces an animation for the X Window System. It displays a `drifting eye'. As the eye drifts across a popped-up window from left to right, it slowly rotates. After the eye has drifted across twice, the window will vanish.
#include <stdio.h> #include <plot.h> int main () { plPlotter *plotter; plPlotterParams *plotter_params; int i = 0, j; /* set Plotter parameters */ plotter_params = pl_newplparams (); pl_setplparam (plotter_params, "BITMAPSIZE", "300x150"); pl_setplparam (plotter_params, "VANISH_ON_DELETE", "yes"); pl_setplparam (plotter_params, "USE_DOUBLE_BUFFERING", "yes"); /* create an X Plotter with the specified parameters */ if ((plotter = pl_newpl_r ("X", stdin, stdout, stderr, plotter_params)) == NULL) { fprintf (stderr, "Couldn't create Plotter\n"); return 1; } if (pl_openpl_r (plotter) < 0) /* open Plotter */ { fprintf (stderr, "Couldn't open Plotter\n"); return 1; } pl_fspace_r (plotter, -0.5, -0.5, 299.5, 149.5); /* set user coor system */ pl_linewidth_r (plotter, 8); /* set line thickness */ pl_filltype_r (plotter, 1); /* objects will be filled */ pl_bgcolorname_r (plotter, "saddle brown"); /* set background color */ for (j = 0; j < 300; j++) { pl_erase_r (plotter); /* erase window */ pl_pencolorname_r (plotter, "red"); /* use red pen */ pl_fillcolorname_r (plotter, "cyan"); /* use cyan filling */ pl_ellipse_r (plotter, i, 75, 35, 50, i); /* draw an ellipse */ pl_colorname_r (plotter, "black"); /* use black pen and filling */ pl_circle_r (plotter, i, 75, 12); /* draw a circle [the pupil] */ i = (i + 2) % 300; /* shift rightwards */ } if (pl_closepl_r (plotter) < 0) /* close Plotter */ { fprintf (stderr, "Couldn't close Plotter\n"); return 1; } if (pl_deletepl_r (plotter) < 0) /* delete Plotter */ { fprintf (stderr, "Couldn't delete Plotter\n"); return 1; } return 0; }
As you can see, this application begins by calling pl_setplparam
several times to set Plotter parameters, and then calls
pl_newpl_r
to create an X Plotter. The X Plotter window
will have size 300x150 pixels. This window will vanish when the Plotter
is deleted. If the VANISH_ON_DELETE
parameter were not set
to "yes", the window would remain on the screen until removed by the
user (by typing ‘q’ in it, or by clicking with a mouse).
Setting the parameter USE_DOUBLE_BUFFERING
to "yes" requests
that double buffering be used. This is very important if you wish to
produce a smooth animation, with no jerkiness. Normally, an X Plotter draws graphics into a window in real time, and erases the
window when pl_erase_r
is called. But if double buffering is
used, each frame of graphics is written into an off-screen buffer, and
is copied into the window, pixel by pixel, when pl_erase_r
is
called or the Plotter is closed. This is exactly what is needed for
smooth animation.
After the Plotter is created, it is selected for use and opened. When
pl_openpl_r
is called, the window pops up, and the animation
begins. In the body of the for loop there is a call to
pl_erase_r
, and also a sequence of libplot
operations that
draws the eye. The pen color and fill color are changed twice with each
passage through the loop. You may wish to experiment with the animation
parameters to produce the best effects on your video hardware.
The positions of the objects that are plotted in the animation are
expressed in terms of user coordinates, not pixel coordinates. But the
call to pl_fspace_r
defines user and pixel coordinates to be
effectively the same. User coordinates are chosen so that the lower
left corner of the rectangle mapped to the X window is
(−0.5,−0.5) and the upper right corner is (299.5,149.5).
Since this agrees with the window size, individual pixels may be
addressed in terms of integer user coordinates. For example,
pl_point_r(plotter,299,149)
would set the pixel in the upper
right corner of the window to the current pen color.
The following is another sample animation, this time of a rotating letter `A'.
#include <stdio.h> #include <plot.h> int main() { plPlotter *plotter; plPlotterParams *plotter_params; int angle = 0; /* set Plotter parameters */ plotter_params = pl_newplparams (); pl_setplparam (plotter_params, "BITMAPSIZE", "300x300"); pl_setplparam (plotter_params, "USE_DOUBLE_BUFFERING", "yes"); pl_setplparam (plotter_params, "BG_COLOR", "blue"); /* create an X Plotter with the specified parameters */ plotter = pl_newpl_r ("X", stdin, stdout, stderr, plotter_params); /* open X Plotter, initialize coordinates, pen, and font */ pl_openpl_r (plotter); pl_fspace_r (plotter, 0.0, 0.0, 1.0, 1.0); /* use normalized coors */ pl_pencolorname_r (plotter, "white"); pl_ffontsize_r (plotter, 1.0); pl_fontname_r (plotter, "NewCenturySchlbk-Roman"); pl_fmove_r (plotter, 0.5, 0.5); /* move to center */ while (1) /* loop endlessly */ { pl_erase_r (plotter); pl_textangle_r (plotter, angle++); /* set new rotation angle */ pl_alabel_r (plotter, 'c', 'c', "A"); /* draw a centered `A' */ } pl_closepl_r (plotter); /* close Plotter */ pl_deletepl_r (plotter); /* delete Plotter */ return 0; }
This animation serves as a good test of the capabilities of an X Window System display. On a modern X11R6 display, animation will be smooth and fast. That is because X11R6 displays can retrieve individual characters from a font without retrieving the entire font. If your X display does not support the "NewCenturySchlbk-Roman" font, you may substitute most core X fonts, such as the widely available scalable font "charter-medium-r-normal", or the traditional screen font "fixed". For the format of font names, see Text Fonts in X. If the X Plotter is unable to retrieve the font you specify, it will first attempt to use a default scalable font ("Helvetica", interpreted in the context of the X Window System as "helvetica-medium-r-normal"). If that too fails, it will use a default Hershey vector font ("HersheySerif") instead.
Animations that use Hershey fonts are normally faster than ones that use Postscript fonts or other X Window System fonts, since the Hershey fonts are constructed from line segments. Rasterizing line segments can be done rapidly.
If you are writing an application that performs a lengthy sequence of
drawing operations on an X Plotter, you may find it useful to set
the Plotter parameter X_AUTO_FLUSH
to "no". By default, an
X Plotter flushes all graphics to its X Window System display
after each drawing operation. This flushing ensures that graphics are
visible to the user immediately after they are drawn. However, it
sometimes slows down the rendering process. For additional details on
Plotter parameters, see Plotter Parameters.