Gsave/Grestore

The pair of functions gsave(); and grestore(); are useful for a variety of purposes. gsave(); stores the complete graphics state including the currently defined path while grestore(); restores the state to the last saved state. Each grestore(); must have a matching gsave(); preceding it.

The simplest use for this pair is to restore the initial state after translations and scaling. This often comes up in composite figures that are constructed from other existing picture. The composite is built by setting translations and scale factors for each component and then drawing the component. If a gsave(); was done at the beginning then a grestore(); can be done after drawing the components to restore the initial scale and translation. This can be useful for adding annotations to the final composite figure.

It is also possible to use gsave/grestore to repeatedly draw a given path since the currently defined path is also saved. In the following example a path is defined, saved (using gsave();), filled, restored (using grestore();) and then finally stroked. Filling and stroking the same path causes the filled region to have a border drawn in the current line colour and style.


#include <splot.h>
/* This is a region filling example */
int i;
main() 
   {     
   set(LINEWIDTH,0.1);
   set(FILLRULE,EVENODD);
   translate(10,15);
   for (i=0;i < 8;i++)
      {
      set(LINECOLOUR,i);
      leaf();
      rotate(45);
      }
   }

int leaf()
   {
   arc(3.1,3.38896,0.4,0,360);
   moveto(0,0);
   curveto(3.38924,0.598051,3.18987,3.85411,5.91456,6.11341);
   curveto(2.06013,5.44891,2.52532,1.5948,0,0);
   closepath();
   gsave();
   fill();
   grestore();
   set(LINECOLOUR,BLACK);
   stroke();
   }

The following example again illustrates the use of gsave/grestore to repeatedly draw the same path each time with a small translation to draw a stack of pages. It also illustrates the use of electronic white out (filling with colour white) to remove unwanted lines.


 
#include <splot.h>

int i;
double x,y,d,l;

main()
   {
   /* draw 3d stack of pages */
   x = 5;
   y = 15;
   l = 4;
   for (i = 0;i <= 10;i++;)
      {
      d = i * 0.2;
      box(x - d ,y - d, x - d + l, y - d + l);
      gsave();
      set(LINECOLOUR,WHITE);
      fill();
      grestore();
      stroke();
      }
   /* draw sample */
   arc(5.02,14.96,1.2,0,360);
   fill();
   white_box(3.95,13.51,6.134,13.904);
   white_box(3.862,13.689,3.752,15.443);
   /* draw axes */
   moveto(3.00,10.19);
   rarrowto(0.0,2);
   moveto(3.00,10.19);
   rarrowto(2,0);
   moveto(3.00,10.19);
   rarrowto(1.6,1.6);
   stroke();
   /* add labels */
   text(5.20,9.71,"X");
   text(2.31,11.82,"Y");
   text(5.01,11.64,"!l");
   }

int white_box(double x1,double y1,double x2,double y2)
   { 
   gsave();
   newpath();
   box(x1,y1,x2,y2);
   set(LINECOLOUR,WHITE);
   fill();
   grestore();
   }

Using the above technique to repeatedly draw the same element will not work with functions such as text(); which are implicitly stroked since there is no chance to do a gsave(); before the stroke. However, implicit stroking can be temporarily turned off with the newpath(); command. Without the newpath(); in the following example only the first "SPLOT" would have been printed. The first stroke(); after a newpath(); turns on implicit stroking again with these functions.

 
#include <splot.h>
main()
   {
   int i;
   newpath();
   translate(10,10);
   text(0,0,"      SPLOT");
   for (i=0;i < 360;i += 30)
      {
      gsave();
      rotate(i);
      stroke();
      grestore();
      }
   }