home *** CD-ROM | disk | FTP | other *** search
/ gondwana.ecr.mu.oz.au/pub/ / Graphics.tar / Graphics / VOGLE.ZIP / VOGLE / DRIVERS / GIF.C < prev    next >
C/C++ Source or Header  |  2000-02-11  |  12KB  |  357 lines

  1. #include "gd.h"
  2. #include <stdio.h>
  3. #include <math.h>
  4. #include <stdlib.h>
  5. #include "vogle.h"
  6.  
  7. extern FILE     *_voutfile();
  8. static FILE     *fp;
  9.  
  10. static gdImagePtr    im;
  11.  
  12. static int x_size, y_size; /* size of graphics array */
  13.  
  14. byte *graphics_rgb; /* the graphics data */
  15.  
  16. static int color = 0;
  17.  
  18. static int drawn = 0;
  19.  
  20. static int GLOBAL_rasters = 1; /* line thickness */
  21.  
  22. static int lastx, lasty;     /* position of last draw */
  23.  
  24. int coltab[256];
  25.  
  26. static int 
  27. noop()
  28.     return(-1); /* do nothing but return-1 */
  29. }
  30.  
  31. static int
  32. GIF_color(col) /* change the current color */
  33.         int     col;
  34. {
  35.         color = coltab[col % 256];
  36.         return(0);
  37. }
  38. /******************************************************************************/
  39. static int 
  40. GIF_mapcolor(indx, r, g, b)
  41.         int     indx, r, g, b;
  42. {
  43.         if (indx < 256 && indx >= 0) {
  44.         coltab[indx] = gdImageColorAllocate(im, r, g, b);
  45.         }
  46.         return(0);
  47. }
  48. /******************************************************************************/
  49. static int 
  50. GIF_init()
  51. {
  52.         int prefx, prefy, prefxs, prefys;
  53.         int i;
  54.  
  55.         getprefposandsize(&prefx, &prefy, &prefxs, &prefys);
  56.         if (prefxs != -1 ) {
  57.                 if (prefys <= 0 ){
  58.                         fprintf(stderr,"*GIF_init* y size of %d set to 400\n",prefys);
  59.                         prefys = 400;
  60.                 }
  61.                 else{
  62.                         vdevice.sizeSy = prefys;
  63.                 }
  64.                 if (prefxs <= 0 ){
  65.                         fprintf(stderr,"*GIF_init* x size of %d set to 600\n",prefys);
  66.                         prefxs = 600;
  67.                 }
  68.                 else{
  69.                         vdevice.sizeSx = prefxs;
  70.                 }
  71.         } else {
  72.                 /* nice default value */
  73.                 prefx = 0;
  74.                 prefy = 0;
  75.                 vdevice.sizeSy = 400;
  76.                 vdevice.sizeSx = 600;
  77.         }
  78.         vdevice.sizeX = vdevice.sizeY = MIN(vdevice.sizeSy,vdevice.sizeSx);
  79.         x_size=vdevice.sizeSx;
  80.         y_size=vdevice.sizeSy;
  81.         vdevice.depth = 8;
  82.     im = gdImageCreate(x_size, y_size);
  83.  
  84.         fp = _voutfile();
  85.  
  86.         /* Cause scaling to be 0 to maxX maxY: prefx, vdevice.sizeSx+prefx, prefy, vdevice.sizeSy+prefy */
  87.  
  88.         lastx = -1111111;
  89.         lasty = -1111111;
  90.  
  91.         drawn = 0;
  92.  
  93.         GIF_mapcolor(0, 0, 0, 0);
  94.         GIF_mapcolor(1, 255, 0, 0);
  95.         GIF_mapcolor(2, 0, 255, 0);
  96.         GIF_mapcolor(3, 255, 255, 0);
  97.         GIF_mapcolor(4, 0, 0, 255);
  98.         GIF_mapcolor(5, 255, 0, 255);
  99.         GIF_mapcolor(6, 0, 255, 255);
  100.         GIF_mapcolor(7, 255, 255, 255);
  101.  
  102.         for(i=8; i<256; i++){
  103.            GIF_mapcolor(i, 255, 255, 255);
  104.         }
  105.  
  106.         return(1);
  107. }
  108.  
  109. /******************************************************************************/
  110. static 
  111. PPM_fill(n, x, y) /* "fill" a polygon */
  112. int     n, x[], y[];
  113. {
  114.         int     i;
  115.  
  116.         PROTOTYPE static void PPM_SOLID_FILL( int n, int x[], int y[]);
  117.  
  118.         /* update current position if needed */
  119.         GLOBAL_lastx=x[0];
  120.         GLOBAL_lasty=y[0];
  121.  
  122.         for (i = 1; i < n; i++){
  123.                 PPM_DRAW_LINE(x[i],y[i]); /* draw outline across graphics array */
  124.         }
  125.         if ( x[n-1] != x[0] || y[n-1] != y[0] ) /* close the polygon if it is not closed */
  126.                 PPM_DRAW_LINE(x[0],y[0]);
  127.  
  128.         PPM_SOLID_FILL(n, x, y);
  129.  
  130.         /* update current position */
  131.         GLOBAL_lastx = vdevice.cpVx = x[n - 1];
  132.         GLOBAL_lasty = vdevice.cpVy = y[n - 1];
  133.  
  134.         GLOBAL_drawn = DRAWN;
  135. }
  136. /******************************************************************************/
  137. static 
  138. GIF_draw(x, y)
  139.         int     x, y;
  140. {
  141.         int     holdx, holdy;
  142.         int    xwide[4], ywide[4];
  143.         float cosa, sina;
  144.         double angle;
  145.  
  146.         if (lastx != x || lasty != y) {
  147.         gdImageLine(im, lastx, lasty, x, y, color);
  148.         lastx = vdevice.cpVx
  149.         lasty = vdevice.cpVy
  150.         drawn = 1;
  151.     }
  152. }
  153. static 
  154. GIF_exit()
  155. {
  156.         gdImageGif(im, fp);
  157.         if (fp != stdout){
  158.                 fclose(fp);
  159.         }
  160. }
  161.  
  162. static 
  163. GIF_setlw(w) 
  164.         int     w;
  165. {
  166.         GLOBAL_rasters = MAX(1,w);
  167. }
  168. static 
  169. GIF_clear() 
  170. {
  171.         gdImageGif(im, fp);
  172.         memset(im->pixels, 0, x_size * y_size);
  173. }
  174. /******************************************************************************/
  175. static int GIF_font(font) /* load in large or small */
  176.         char    *font;
  177. {
  178.         if (strcmp(font, "small") == 0) {
  179.                 vdevice.hwidth = 97.01; /* Size in plotter resolution units */
  180.                 vdevice.hheight = vdevice.hwidth * 2.0;
  181.         } else if (strcmp(font, "large") == 0) {
  182.                 vdevice.hwidth = 145.5;
  183.                 vdevice.hheight = vdevice.hwidth * 2.0;
  184.         } else
  185.                 return(0);
  186.  
  187.         return(1);
  188. }
  189. /******************************************************************************/
  190. static PPM_string(s) /* output a string.  */
  191.         char    *s;
  192. {
  193.         int             dy, dx;
  194.  
  195.         if (GLOBAL_lastx != vdevice.cpVx || GLOBAL_lasty != vdevice.cpVy){
  196.                 GLOBAL_lastx=vdevice.cpVx;
  197.                 GLOBAL_lasty=vdevice.cpVy;
  198.         }
  199.  
  200.         fputs(s, fp);
  201.  
  202.         GLOBAL_lastx = GLOBAL_lasty = -1111111; /* undefine current position because used hardware text ?*/
  203.         GLOBAL_drawn = DRAWN;
  204. }
  205. /******************************************************************************/
  206. static PPM_char(c) /* output a character */
  207. char    c;
  208. {
  209.   char  s[2];
  210.   s[0] = c; s[1]='\0';
  211.   PPM_string(s);
  212. }
  213. /******************************************************************************/
  214. static DevEntry PPMdev = {
  215.                 "ppm",       /* name of device */
  216.                 "large",     /* name of large font */
  217.                 "small",     /* name of small font */
  218.                 noop,        /* Set drawing in back buffer */
  219.                 PPM_char,    /* Draw a hardware character */
  220.                 noop,        /* Check if a key was hit */
  221.                 PPM_clear,   /* Clear the screen to current color */
  222.                 PPM_color,   /* Set current color */
  223.                 PPM_draw,    /* Draw a line */
  224.                 PPM_exit,    /* Exit graphics */
  225.                 PPM_fill,    /* Fill a polygon */
  226.                 PPM_font,    /* Set hardware font */
  227.                 noop,        /* Set drawing in front buffer */
  228.                 noop,        /* Wait for and get the next key hit */
  229.                 PPM_init,    /* Initialize the device */
  230.                 noop,        /* Get mouse/cross hair position */
  231.                 PPM_mapcolor,/* Set color indices */
  232.                 PPM_setlw,   /* Set line width */
  233.                 PPM_string,  /* Draw a hardware string */
  234.                 noop,        /* Swap front and back buffers */
  235.                 noop         /* Syncronize the display */
  236. };
  237. /******************************************************************************/
  238. _P3_devcpy()
  239. {
  240.         vdevice.dev = PPMdev;
  241.         vdevice.dev.Vinit = PPM_init;
  242.         GLOBAL_driver = P3;
  243. }
  244. /******************************************************************************/
  245. _P6_devcpy()
  246. {
  247.         vdevice.dev = PPMdev;
  248.         vdevice.dev.Vinit = PPM_init;
  249.         GLOBAL_driver = P6;
  250. }
  251. /*******************************************************************************/
  252. static PPM_YINTERCEPT(yscan, x1, y1, x2, y2, xintercept,yprev)
  253. /*
  254. Determine if scan line intercepts the line segment. If it does, return the x intercept.
  255. */
  256. int     yscan, x1, y1, x2, y2, *xintercept, *yprev;
  257. {
  258.         int deltay, yprevious;
  259.         float   t;
  260.         yprevious = *yprev; /* the value we need to use in this pass */
  261.         *yprev = y1;        /* store the value for the next call to (probably) use */
  262.         deltay = y2 - y1;
  263.         if ( deltay == 0 ){
  264.                 /* horizontal lines do not contribute to scan line intercepts */
  265.                 *yprev=yprevious;
  266.                 return(0);
  267.         }
  268.         t = (float)(yscan - y1) / deltay;
  269.         if (t > 0.0 && t <= 1.0) {
  270.                 /* scan line and line segment intersect but not at leading vertex */
  271.                 *xintercept = x1 + t*(x2 - x1) + 0.5;
  272.                 return (1);
  273.         } else if ( t == 0.0 ){
  274.                 /* scan line and line segment intersect at leading vertex */
  275.                 *xintercept = x1 + t*(x2 - x1) + 0.5;
  276.                 if(yprevious <= y1 && y2 <= y1 ){
  277.                    /* local maximum */
  278.                    return (1);
  279.                 } else if(yprevious >= y1 && y2 >= y1 ){
  280.                    /* local minimum */
  281.                    return (1);
  282.                 } else{
  283.                    /* ignore duplicate at vertex that is not a local maximum or minimum */
  284.                    return (0);
  285.                 }
  286.         }
  287.         /* scan line and line segment did not intersect */
  288.         return (0);
  289. }
  290. /*******************************************************************************/
  291. static void PPM_SOLID_FILL(n, x, y) /* fill polygon of n points drawn by polyline <x,y>.  */
  292. int     n, x[], y[];
  293. {
  294.         int i, j, sorted, yhorizontal, xint, tmp, xmin, xmax, ymax, ymin, xi[MAXVERTS], yprev;
  295.  
  296.         if ( n > MAXVERTS) {
  297.            fprintf(stderr,"*PPM_SOLID_FILL* more than %d vertices in a polygon\n",MAXVERTS);
  298.            return;
  299.         }
  300.  
  301.         /* find clip range */
  302.         ymin = ymax = y[0];
  303.         xmin = xmax = y[0];
  304.         for (i = 0; i < n; i++) {
  305.                 ymax = MAX(ymax, y[i]);
  306.                 ymin = MIN(ymin, y[i]);
  307.                 xmax = MAX(xmax, x[i]);
  308.                 xmin = MIN(xmin, x[i]);
  309.         }
  310.         /* ensure scan lines are generated that do not cause out-of-bound problems in the y direction */
  311.         ymin=MAX(ymin,0);
  312.         ymax=MIN(ymax,Y_SIZE);
  313.  
  314.         /* For each y value, get a list of X intersections... */
  315.         yhorizontal = ymax ;
  316.         while (yhorizontal >= ymin) {
  317.                 j = 0;
  318.                 yprev = y[n-1];
  319.                 for (i = 0; i < n-1; i++)
  320.                         if (PPM_YINTERCEPT(yhorizontal, x[i], y[i], x[i+1], y[i+1], &xint, &yprev))
  321.                                         xi[j++] = xint;
  322.                 /* Last one. */
  323.                 if (PPM_YINTERCEPT(yhorizontal, x[n-1], y[n-1], x[0], y[0], &xint, &yprev))
  324.                                 xi[j++] = xint;
  325.  
  326.                 /* odd pairs means something went wrong in figuring out whether to count vertices or not */
  327.                 if( 2 * (j/2) != j){
  328.                    fprintf(stderr,"*PPM_SOLID_FILL* Internal error: odd number of intersection points (%d) \n",j);
  329.                 }
  330.  
  331.                 /* Sort the X intersections... */
  332.                 sorted = 0;
  333.                 while (!sorted) {
  334.                         sorted = 1;
  335.                         for (i = 0; i < j-1; i++)
  336.                                 if (xi[i] > xi[i+1]) {
  337.                                         tmp = xi[i];
  338.                                         xi[i] = xi[i+1];
  339.                                         xi[i+1] = tmp;
  340.                                         sorted = 0;
  341.                                 }
  342.                 }
  343.  
  344.                 /* Draw the horizontal lines */
  345.                 /* should make sure within X clipping range */
  346.                 for (i = 0; i < j-1; i += 2) {
  347.                         GLOBAL_lastx=MAX(0,MIN(xi[i],X_SIZE));
  348.                         GLOBAL_lasty=yhorizontal;
  349.                         PPM_DRAW_LINE(MAX(0,MIN(xi[i+1],X_SIZE)), yhorizontal);
  350.                 }
  351.                 yhorizontal -= 1;
  352.         }
  353. }
  354. /*******************************************************************************/
  355.  
  356.