The Plotutils Package - X Animations

Go to the first, previous, next, last section, table of contents.

### X Window System animations in C

You may use `libplot` to produce vector graphics animations on any Plotter that does real-time plotting (i.e., an X, X Drawable, 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 ()
    {
      int handle, i = 0, j;

      /* set Plotter parameters */
      pl_parampl ("BITMAPSIZE", "300x150");
      pl_parampl ("VANISH_ON_DELETE", "yes");
      pl_parampl ("USE_DOUBLE_BUFFERING", "yes");

      /* create an X Plotter with the specified parameters */
      if ((handle = pl_newpl ("X", stdin, stdout, stderr)) < 0)
        {
          fprintf (stderr, "Couldn't create Plotter\n");
          return 1;
        }
      pl_selectpl (handle);       /* select the Plotter for use */

      if (pl_openpl () < 0)       /* open Plotter */
        {
          fprintf (stderr, "Couldn't open Plotter\n");
          return 1;
        }
      pl_space (0, 0, 299, 149);  /* specify user coordinate system */
      pl_linewidth (8);           /* line thickness in user coordinates */
      pl_filltype (1);            /* objects will be filled */
      pl_bgcolorname ("saddle brown"); /* background color for the window*/
      for (j = 0; j < 300; j++)
        {
          pl_erase ();            /* erase window */
          pl_pencolorname ("red"); /* choose red pen, with cyan filling */
          pl_fillcolorname ("cyan");
          pl_ellipse (i, 75, 35, 50, i);  /* draw an ellipse */
          pl_colorname ("black"); /* choose black pen, with black filling */
          pl_circle (i, 75, 12);  /* draw a circle [the pupil] */
          i = (i + 2) % 300;      /* shift rightwards */
        }
      if (pl_closepl () < 0)         /* close Plotter */
        {
          fprintf (stderr, "Couldn't close Plotter\n");
          return 1;
        }

      pl_selectpl (0);            /* select default Plotter */
      if (pl_deletepl (handle) < 0) /* delete Plotter we used */
        {
          fprintf (stderr, "Couldn't delete Plotter\n");
          return 1;
        }
      return 0;
    }

As you can see, this application begins by calling `pl_parampl` several times to set device driver parameters, and then calls `pl_newpl` 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` 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` is called or the Plotter is closed. This is a bit counterintuitive, but is exactly what is needed for smooth animation.

After the Plotter is created, it is selected for use and opened. When `pl_openpl` is called, the window pops up, and the animation begins. In the body of the `for` loop there is a call to `pl_erase`, 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 locations of the objects that are plotted in the animation are expressed in terms of user coordinates, not pixel coordinates. But the call to `pl_space` defines user and pixel coordinates to be effectively the same. User coordinates are chosen so that the lower left corner is (0,0) and the upper right corner is (299,149). Since this agrees with the window size, individual pixels may be addressed in terms of integer user coordinates. For example, `pl_point(299,149)` would set the pixel in the upper right hand 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()
    {
      int handle, angle = 0;

      /* set Plotter parameters */
      pl_parampl ("BITMAPSIZE", "300x300");
      pl_parampl ("BG_COLOR", "blue"); /* background color for window */
      pl_parampl ("USE_DOUBLE_BUFFERING", "yes");

      /* create an X Plotter with the specified parameters */
      handle = pl_newpl ("X", stdin, stdout, stderr);
      pl_selectpl (handle);

      /* open X Plotter, initialize coordinates, pen, and font */
      pl_openpl ();
      pl_fspace (0.0, 0.0, 1.0, 1.0);  /* use normalized coordinates */
      pl_pencolorname ("white");
      pl_ffontsize (1.0);
      pl_fontname ("NewCenturySchlbk-Roman");

      pl_fmove (.50,.50);           /* move to center */
      while (1)                     /* loop endlessly */
        {
          pl_erase ();
          pl_textangle (angle++);      /* set new rotation angle */
          pl_alabel ('c', 'c', "A");   /* draw a centered `A' */
        }
      pl_closepl();                 /* close Plotter */

      pl_selectpl (0);              /* select default Plotter */
      pl_deletepl (handle);         /* delete Plotter we used */
      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 rasterize individual characters from a font without rasterizing the entire font. If your X display does not support the "NewCenturySchlbk-Roman" font, you may substitute any other scalable font, such as the widely available "utopia-medium-r-normal". For the format of font names, see section Available text fonts for the X Window System. If the X Plotter is unable to retrieve the font you specify, it will first attempt to use a default scalable font ("Helvetica"). 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. But if you use a scalable font such as "NewCenturySchlbk-Roman" or "utopia-medium-r-normal", you will notice that the rotation speeds up after the letter `A' has rotated through 360 degrees. That is because the `A' at angles past 360 degrees has already been rasterized.

Go to the first, previous, next, last section, table of contents.