/* galaxy.c
   The program galaxy.c uses the image-file logo-50.eps to create a new
   image-file galaxy.eps. */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
  {
    FILE *f;
/* The unit of length is 25.4/72 mm. */    
    double x0,y0; /* Coordinates of the lower-left corner of logo-50.eps */
    double x1,y1; /* Coordinates of the upper-right corner of logo-50.eps */
    double w,h;   /* Width and Heigth of logo-50.eps */
/* Coordinates of the lower-left corner of galaxy.eps */
    double x0f = 100.0;
    double y0f = 100.0;
/* Coordinates of the upper-right corner of galaxy.eps */
    double x1f = 400.0;
    double y1f = 400.0;
/* Coordinates of the lower-left corner of the first inclusion of
   logo-50.eps. */
    double x0a = 100.0;
    double y0a = 160.0;
/* Coordinates of the upper-right corner of the first inclusion of
   logo-50.eps. x1a will be computed from the aspect ratio of logo-50.eps. */
    double x1a;
    double y1a = 400.0;
/* Coordinates of the lower-left corner of the second inclusion of
   logo-50.eps. */
    double x0b = 150.0;
    double y0b = 100.0;
/* Coordinates of the upper-right corner of the second inclusion of
   logo-50.eps. */
    double x1b = 400.0;
    double y1b = 240.0;
/* Coordinates of the lower-left corner of the second inclusion of
   logo-50.eps inside of the original image. These are in relative to
   the original image. Thus, the lower-left corner of the original image
   would be (0.0,0.0) and the upper-right corner (1.0,1.0).*/
    double xc = 0.59;
    double yc = 0.39;
/* This is the scale factor of the second inclusion relative to the first
   inclusion. */
    double sf = 5.0;
/* This is the anti-clockwise rotation angle of the second inclusion. */
    double ra = -30.0;
/* The same in radian. */
    double rar = ra*atan(1)/45.0;
/* These are the coordinates of the corners of the magnified area. */
    double xm0,ym0,xm1,ym1,xm2,ym2,xm3,ym3;
/* At first, we need to know the coordinates of the lower-left und
   upper-right corner of the bounding box of logo-50.eps. */    
    system("grep %%BoundingBox logo-50.eps > logo-50.eps.BoundingBox");
    f = fopen("logo-50.eps.BoundingBox","r");
    fscanf(f,"%%%%BoundingBox:%lf%lf%lf%lf",&x0,&y0,&x1,&y1);
    fclose(f);
/* Now, we can compute the width and heigth of logo-50.eps. */
    w = x1-x0;
    h = y1-y0;
/* The x-coordinate of the upper-right corner of the first inclusion is
   determined. */
    x1a = x0a+(y1a-y0a)/h*w;
/* Now, we start to write the image. */
    f = fopen("galaxy.eps","w");
/* The first line indicates that its an eps-file. */
    fprintf(f,"%%!PS-Adobe-3.0 EPSF-3.0\n");
/* The bounding box of the new image is slightly larger then the nominal
   drawing area because of the linethickness of the frames. */    
    fprintf(f,"%%%%BoundingBox: %f %f %f %f\n",x0f-2,y0f-2,x1f+2,y1f+2);
/* We want to be able to just send galaxy.eps to a printer, so we save
   the current state of the virtual memory and redefine "showpage" to an
   empty procedure to disable any "showpage"-commands in the included
   eps-files. */
    fprintf(f,"save /showpage {} def\n");   
/* Now, we include logo-50.eps the first time. We save the state. */
    fprintf(f,"save\n");
/* The image is translated. */
    fprintf(f,"%f %f translate\n",x0a,y0a);
/* The image is scaled. */
    fprintf(f,"%f dup scale\n",(y1a-y0a)/(y1-y0));    
/* In case, the lower left corner of logo-50.eps in not at (0.0,0.0), it
   is now. */
    fprintf(f,"%f %f translate\n",-x0,-y0);
    fclose(f);
/* We mask the BoundingBox lines of the inserted image. */
    system(
    "sed -e's/BoundingBox/MaskedBoundingBox/' <logo-50.eps >logo-50.eps.temp");
    system("cat galaxy.eps logo-50.eps.temp > galaxy.eps.temp");
    system("mv galaxy.eps.temp galaxy.eps");
    f = fopen("galaxy.eps","a");
/* We restore the state. */    
    fprintf(f,"restore\n");

/* Now, we draw a frame with a line width of 2 points around the included
   image. */
/* The graphics state is saved. */
    fprintf(f,"gsave\n");
/* The linewidth is set to 2 points. */    
    fprintf(f,"2 setlinewidth\n");
/* We define the path of the frame. */
    fprintf(f,"newpath %f %f moveto\n",x0a,y0a);
    fprintf(f,"%f %f lineto\n",x1a,y0a);
    fprintf(f,"%f %f lineto\n",x1a,y1a);
    fprintf(f,"%f %f lineto closepath\n",x0a,y1a);
/* This draws the box. */
    fprintf(f,"stroke\n");
/* Finally, the graphics state is restored. */    
    fprintf(f,"grestore\n");    
    
/* Now, we draw a frame with a line width of 2 points around the area which
   is selected for magnification. */
/* The position of the corners are computed. */ 
    xm0 = xc*(x1a-x0a)+x0a;  
    ym0 = yc*(y1a-y0a)+y0a;
    xm1 = xm0+cos(rar)*(x1b-x0b)/sf;  
    ym1 = ym0-sin(rar)*(x1b-x0b)/sf;  
    xm3 = xm0+sin(rar)*(y1b-y0b)/sf;  
    ym3 = ym0+cos(rar)*(y1b-y0b)/sf;  
    xm2 = xm3-xm0+xm1;
    ym2 = ym3-ym0+ym1;
   
/* The graphics state is saved. */
    fprintf(f,"gsave\n");
/* The linewidth is set to 2 points. */
    fprintf(f,"2 setlinewidth\n");
/* We define the path of the frame in the coordinates of the final image. */
    fprintf(f,"newpath %f %f moveto\n",xm0,ym0);
    fprintf(f,"%f %f lineto\n",xm1,ym1);
    fprintf(f,"%f %f lineto\n",xm2,ym2);
    fprintf(f,"%f %f lineto closepath\n",xm3,ym3);
/* This draws the box. */
    fprintf(f,"stroke\n");
/* These means rounded linecaps. */
    fprintf(f,"2 setlinecap\n");    
/* Four additional lines are drawn to connect the related corners. */
    fprintf(f,"newpath %f %f moveto\n",x0b,y0b);
    fprintf(f,"%f %f lineto stroke\n",xm0,ym0);
    fprintf(f,"newpath %f %f moveto\n",x1b,y0b);
    fprintf(f,"%f %f lineto stroke\n",xm1,ym1);
    fprintf(f,"newpath %f %f moveto\n",x1b,y1b);
    fprintf(f,"%f %f lineto stroke\n",xm2,ym2);
    fprintf(f,"newpath %f %f moveto\n",x0b,y1b);
    fprintf(f,"%f %f lineto stroke\n",xm3,ym3);
/* Finally, the graphics state is restored. */    
    fprintf(f,"grestore\n");    

/* Now, we include logo-50.eps the second time. We save the state. */
    fprintf(f,"save\n");

/* Now, we draw a rectangle and reduce the drawing area to this rectangle. */
/* We define the path of the frame. */
    fprintf(f,"newpath %f %f moveto\n",x0b,y0b);
    fprintf(f,"%f %f lineto\n",x1b,y0b);
    fprintf(f,"%f %f lineto\n",x1b,y1b);
    fprintf(f,"%f %f lineto closepath\n",x0b,y1b);
/* This command reduces the drawing area to the area of the box. */
    fprintf(f,"clip\n");

/* The image is translated. */
    fprintf(f,"%f %f translate\n",x0b,y0b);

/* The image is rotated. */
    fprintf(f,"%f rotate\n",ra);    
/* The image is scaled. */
    fprintf(f,"%f dup scale\n",(y1a-y0a)/(y1-y0)*sf);    
/* The image is translated so that the lower-left point of the second
   inclusion gets into the origin. Thats necessary, because we want to rotate
   through this point. */
    fprintf(f,"%f %f translate\n",-xc*w,-yc*h);
/* In case, the lower left corner of logo-50.eps in not at (0.0,0.0), it
   is now. */
    fprintf(f,"%f %f translate\n",-x0,-y0);
    fclose(f);
    system("cat galaxy.eps logo-50.eps.temp > galaxy.eps.temp");
    system("mv galaxy.eps.temp galaxy.eps");
    f = fopen("galaxy.eps","a");
/* We restore the state. */    
    fprintf(f,"restore\n");
/* Now, we draw a frame with a line width of 2 points around the included
   image. */
/* The graphics state is saved. */
    fprintf(f,"gsave\n");
/* The linewidth is set to 2 points. */    
    fprintf(f,"2 setlinewidth\n");
/* We define the path of the frame. */
    fprintf(f,"newpath %f %f moveto\n",x0b,y0b);
    fprintf(f,"%f %f lineto\n",x1b,y0b);
    fprintf(f,"%f %f lineto\n",x1b,y1b);
    fprintf(f,"%f %f lineto closepath\n",x0b,y1b);
/* This draws the box. */
    fprintf(f,"stroke\n");
/* Finally, the graphics state is restored. */    
    fprintf(f,"grestore\n");    
/* We restore the state of the virtual memory. "showpage" does work again. */
    fprintf(f,"restore showpage\n");
    fclose(f);
    return 0; /* This is necessary to report success to "make"! */  
  }
