home *** CD-ROM | disk | FTP | other *** search
/ Encyclopedia of Graphics File Formats Companion / GFF_CD.ISO / software / unix / saoimage / sao1_07.tar / csrshape.c < prev    next >
C/C++ Source or Header  |  1991-01-03  |  10KB  |  344 lines

  1. #ifndef lint
  2. static char SccsId[] = "%W%  %G%";
  3. #endif
  4.  
  5. /* Module:    csrshape.c (Cursor Shape)
  6.  * Purpose:    Make basic software cursors
  7.  * Subroutine:    make_cursor()            returns: void
  8.  * Subroutine:    change_circle_granularity()    returns: void
  9.  * Copyright:    1989 Smithsonian Astrophysical Observatory
  10.  *        You may do anything you like with this file except remove
  11.  *        this copyright.  The Smithsonian Astrophysical Observatory
  12.  *        makes no representations about the suitability of this
  13.  *        software for any purpose.  It is provided "as is" without
  14.  *        express or implied warranty.
  15.  * Modified:    {0} Michael VanHilst    initial version           9 May 1989
  16.  *        {1} MVH added arrow cursor               1 Jan 1991
  17.  *        {n} <who> -- <does what> -- <when>
  18.  */
  19.  
  20. #include <stdio.h>        /*  stderr, NULL, etc.  */
  21. #include <X11/Xlib.h>        /*  X window stuff  */
  22. #include <X11/Xutil.h>        /*  X window manager stuff  */
  23. #include "hfiles/color.h"    /*  Cursor colors needed by Cursor.h  */
  24. #include "hfiles/constant.h"    /*  Define codes  */
  25. #include "hfiles/cursor.h"    /*  Define cursor parameter structures  */
  26.  
  27. #include "defs/circle.def"    /*  Define Unit_circles  */
  28.  
  29.  
  30. #ifdef ANSIC
  31. /*  Exported declarations must be centralized before ANSI C can be used  */
  32.  
  33. void        make_cursor(    struct cursorRec *cursor);
  34. static int    make_arrow(    double xtip, double ytip, double xray,
  35.                 double rotsin, double rotcos, XPoint *points);
  36. static int    make_boxcur(    double xcen, double ycen,
  37.                 double xray, double yray,
  38.                 double rotsin, double rotcos, XPoint *points);
  39. static int    make_circur(    double xcen, double ycen, double radius,
  40.                 XPoint *points )
  41. static int    make_ellipse(    double xcen, double ycen,
  42.                 double xradius, double yradius,
  43.                 double rotsin, double rotcos, XPoint *points);
  44.  
  45. #else
  46.  
  47.   static int make_arrow(), make_boxcur(), make_circur(), make_ellipse();
  48.  
  49. #endif
  50.  
  51.  
  52. /*  Declare and initialize drawing tools  */
  53. double *UnitCircleX = Circle48X;
  54. double *UnitCircleY = Circle48Y;
  55. double *UnitEllipseX = Circle64X;
  56. double *UnitEllipseY = Circle64Y;
  57. int CircleCnt = 48;
  58. int EllipseCnt = 64;
  59. /*  Specify size and shape of arrow head (in pixels, regardless of zoom)  */
  60. int ArrowHeadLength = 8;
  61. int ArrowHeadWidth = 5;
  62.  
  63.  
  64. /*  Subroutine    make_cursor
  65.  *  Purpose:    Remake the current cursor polygon list
  66.  */
  67. #ifdef ANSIC
  68. void make_cursor ( struct cursorRec *cursor )
  69. #else
  70. void make_cursor ( cursor )
  71.      struct cursorRec *cursor;
  72. #endif
  73. {
  74.   switch( cursor->type ) {
  75.   case COP_Circle:
  76.     cursor->point_cnt =
  77.       make_circur(cursor->win.X, cursor->win.Y, cursor->win.rayX,
  78.           cursor->points);
  79.     break;
  80.   case COP_Ellipse:
  81.     cursor->point_cnt = make_ellipse(cursor->win.X, cursor->win.Y,
  82.                      cursor->win.rayX, cursor->win.rayY,
  83.                      cursor->rot.sin, cursor->rot.cos,
  84.                      cursor->points);
  85.     break;
  86.   case COP_Box:
  87.     cursor->point_cnt = make_boxcur(cursor->win.X, cursor->win.Y,
  88.                     cursor->win.rayX, cursor->win.rayY,
  89.                     cursor->rot.sin, cursor->rot.cos,
  90.                     cursor->points);
  91.     break;
  92.   case COP_Arrow:
  93.     cursor->point_cnt = make_arrow(cursor->win.X, cursor->win.Y,
  94.                    cursor->win.rayX, cursor->rot.sin,
  95.                    cursor->rot.cos, cursor->points);
  96.     break;
  97.   case COP_Point:
  98.     cursor->point_cnt = 0;
  99.   case COP_Polygon:
  100.   default:
  101.     break;
  102.   }
  103. }
  104.  
  105.  
  106. /*  Subroutine:    make_arrow
  107.  *  Purpose:    Given tip and tail, make line including arrow head
  108.  *  Returns:    Number of points needed to draw arrow
  109.  */
  110. #ifdef ANSIC
  111. static int make_arrow ( double xtip, double ytip, double xray,
  112.                 double rotsin, double rotcos, XPoint *points )
  113. #else
  114. static int make_arrow ( xtip, ytip, xray, rotsin, rotcos, points )
  115.      double xtip, ytip;        /*  Coords of tip  */
  116.      double xray;        /*  Length of shaft  */
  117.      double rotsin, rotcos;    /*  Trig values for angle  */
  118.      XPoint *points;
  119. #endif
  120. {
  121.   double head_xcos, head_ycos, head_xsin, head_ysin;
  122.  
  123.   /*  Compute offset_from_tip partials to draw arrow head  */
  124.   head_xcos = ArrowHeadWidth * rotcos;
  125.   head_ycos = ArrowHeadLength * rotcos;
  126.   head_xsin = ArrowHeadWidth * rotsin;
  127.   head_ysin = ArrowHeadLength * rotsin;
  128.   /*  Line drawn as 3 segments, all starting at tip  */
  129.   /*  Statements with like factors grouped to help compiler optimization */
  130.   points[5].x = xtip - (xray * rotsin);
  131.   points[5].y = ytip + (xray * rotcos);
  132.   points[1].x = xtip + (head_xcos - head_ysin);
  133.   points[1].y = ytip + (head_xsin + head_ycos);
  134.   points[3].x = xtip - (head_xcos + head_ysin);
  135.   points[3].y = ytip - (head_xsin - head_ycos);
  136.   points[0].x = xtip;
  137.   points[0].y = ytip;
  138.   points[2].x = xtip;
  139.   points[2].y = ytip;
  140.   points[4].x = xtip;
  141.   points[4].y = ytip;
  142.   return( -3 );
  143. }
  144.  
  145.  
  146. /*  Subroutine:    make_boxcur
  147.  *  Purpose:    Set the corner coordinates for the rotating box cursor
  148.  *  Returns:    Number of points needed to draw box
  149.  */
  150. #ifdef ANSIC
  151. static int make_boxcur ( double xcen, double ycen, double xray, double yray,
  152.              double rotsin, double rotcos, XPoint *points )
  153. #else
  154. static int make_boxcur ( xcen, ycen, xray, yray, rotsin, rotcos, points )
  155.      double xcen, ycen;
  156.      double xray, yray;
  157.      double rotsin, rotcos;
  158.      XPoint *points;
  159. #endif
  160. {
  161.   double x1, y1, x2, y2;
  162.  
  163.   /*  Calculate offset of two corners on the right  */
  164.   x1 = (xray * rotcos) - (yray * rotsin);
  165.   y1 = (xray * rotsin) + (yray * rotcos);
  166.   x2 = (xray * rotcos) + (yray * rotsin);
  167.   y2 = (xray * rotsin) - (yray * rotcos);
  168.   /*  Define box corners  */
  169.   points[0].x = xcen + x1;
  170.   points[0].y = ycen + y1;
  171.   points[1].x = xcen + x2;
  172.   points[1].y = ycen + y2;
  173.   points[2].x = xcen - x1;
  174.   points[2].y = ycen - y1;
  175.   points[3].x = xcen - x2;
  176.   points[3].y = ycen - y2;
  177.   points[4].x = xcen + x1;
  178.   points[4].y = ycen + y1;
  179.   return( 5 );
  180. }
  181.  
  182.  
  183. /*  Subroutine:    make_circur
  184.  *  Purpose:    Create a new circle cursor with given center and radius
  185.  *  Returns:    Number of points needed to draw circle
  186.  */
  187. #ifdef ANSIC
  188. static int make_circur ( double xcen, double ycen, double radius,
  189.              XPoint *points )
  190. #else
  191. static int make_circur ( xcen, ycen, radius, points )
  192.      double xcen, ycen, radius;
  193.      XPoint *points;
  194. #endif
  195. {
  196.   int loop;
  197.   register int i, xoff, yoff;
  198.   register int a1, a2, a3, b1, b2, b3, b4;
  199.  
  200.   /*  Set up array indexes for 8 fold symetry  */
  201.   /*  8 indexes radiating both ways from each of the four axes  */
  202.   a1 = CircleCnt / 4;        /*  (1 * cnt) / 4  */
  203.   a2 = a1 + a1;            /*  (2 * cnt) / 4  */
  204.   a3 = a2 + a1;            /*  (3 * cnt) / 4  */
  205.   b1 = a1 - 1;
  206.   b2 = a2 - 1;
  207.   b3 = a3 - 1;
  208.   b4 = a3 + a1 - 1;        /*  (4 * cnt) / 4 - 1  */
  209.   /*  Calculate points on circumference for 1/8th of circle  */
  210.   /*  Apply to each of 8 pairs  */
  211.   loop = CircleCnt / 8;
  212.   for( i=0; i <= loop; i++ ) {
  213.     xoff = UnitCircleX[i] * radius;
  214.     yoff = UnitCircleY[i] * radius;
  215.     points[i].x = xcen + xoff;
  216.     points[i].y = ycen + yoff;
  217.     points[a1+i].x = xcen + yoff;
  218.     points[a1+i].y = ycen - xoff;
  219.     points[a2+i].x = xcen - xoff;
  220.     points[a2+i].y = ycen - yoff;
  221.     points[a3+i].x = xcen - yoff;
  222.     points[a3+i].y = ycen + xoff;
  223.     points[b1-i].x = xcen + yoff;
  224.     points[b1-i].y = ycen + xoff;
  225.     points[b2-i].x = xcen + xoff;
  226.     points[b2-i].y = ycen - yoff;
  227.     points[b3-i].x = xcen - yoff;
  228.     points[b3-i].y = ycen - xoff;
  229.     points[b4-i].x = xcen - xoff;
  230.     points[b4-i].y = ycen + yoff;
  231.   }
  232.   /*  Close the circle (end point same as starting point)  */
  233.   points[CircleCnt].x = points[0].x;
  234.   points[CircleCnt].y = points[0].y;
  235.   return( CircleCnt + 1 );
  236. }
  237.  
  238.  
  239. /*  Subroutine:    make_ellipse
  240.  *  Purpose:    Create an ellipticle cursor with given center and radii
  241.  *  Returns:    Number of points needed to draw ellipse
  242.  */
  243. #ifdef ANSIC
  244. static int make_ellipse ( double xcen, double ycen,
  245.               double xradius, double yradius,
  246.               double rotsin, double rotcos, XPoint *points )
  247. #else
  248. static int make_ellipse ( xcen, ycen, xradius, yradius,
  249.               rotsin, rotcos, points )
  250.      double xcen, ycen;
  251.      double xradius, yradius;
  252.      double rotsin, rotcos;
  253.      XPoint *points;
  254. #endif
  255. {
  256.   int loop;
  257.   float xoff, yoff;
  258.   register int i;
  259.   register int x1, x2, y1, y2;
  260.   register int a2, b1, b3;
  261.  
  262.   /*  Set up array indexes for 8 fold symetry  */
  263.   /*  4 indexes radiating both ways from each of the two axis rays  */
  264.   a2 = EllipseCnt / 2;
  265.   b1 = a2 - 1;
  266.   b3 = EllipseCnt - 1;
  267.   /*  Recalculate points on circumference  */
  268.   /*  Apply to each of 4 pairs  */
  269.   loop = EllipseCnt / 4; 
  270.   for( i=0; i < loop; i++ ) {
  271.     /*  Calculate ray lengths for orthogonal case  */
  272.     xoff = UnitEllipseX[i] * xradius;
  273.     yoff = UnitEllipseY[i] * yradius;
  274.     /*  Calculate offset of two points on the right (rotate)  */
  275.     x2 = (xoff * rotcos) + (yoff * rotsin);
  276.     y2 = (xoff * rotsin) - (yoff * rotcos);
  277.     x1 = (xoff * rotcos) - (yoff * rotsin);
  278.     y1 = (xoff * rotsin) + (yoff * rotcos);
  279.     points[i].x = xcen + x1;
  280.     points[i].y = ycen + y1;
  281.     points[a2+i].x = xcen - x1;
  282.     points[a2+i].y = ycen - y1;
  283.     points[b1-i].x = xcen + x2;
  284.     points[b1-i].y = ycen + y2;
  285.     points[b3-i].x = xcen - x2;
  286.     points[b3-i].y = ycen - y2;
  287.   }
  288.   /*  Close the circle (end point same as starting point)  */
  289.   points[EllipseCnt].x = points[0].x;
  290.   points[EllipseCnt].y = points[0].y;
  291.   return( EllipseCnt + 1 );
  292. }
  293.  
  294.  
  295. #ifdef NOTNEEDED /* %% not yet needed */
  296. /*  Subroutine:    change_circle_granularity
  297.  *  Purpose:    Change number of points used to draw circles and ellipses
  298.  */
  299. void change_circle_granularity ( cursor, size, type )
  300.      struct cursorRec *cursor;
  301.      int size;            /* i: exact size (48, 64, or 80 */
  302.      int type;            /* i: code either COP_Circle or COP_Ellipse */
  303. {
  304.   double *X, *Y;
  305.   switch( size ) {
  306.   case 48:
  307.     X = Circle48X;
  308.     Y = Circle48Y;
  309.     break;
  310.   case 64:
  311.     X = Circle64X;
  312.     Y = Circle64Y;
  313.     break;
  314.   case 80:
  315.     X = Circle80X;
  316.     Y = Circle80Y;
  317.     break;
  318.   default:
  319.     (void)fprintf(stderr, "WARNING: Circle choices are 48, 64, or 80!\n");
  320.     return;
  321.   }
  322.   if( type == COP_Circle ) {
  323.     UnitCircleX = X;
  324.     UnitCircleY = Y;
  325.     CircleCnt = size;
  326.   } else if( type = COP_Ellipse ) {
  327.     UnitEllipseX = X;
  328.     UnitEllipseY = Y;
  329.     EllipseCnt = size;
  330.   } else
  331.     return;
  332.   if( cursor->type == type ) {
  333.     make_cursor (cursor);
  334.   }
  335. }
  336. #endif
  337.                          
  338.                                                                
  339.                                                                
  340.                                                                
  341.                                                                
  342.                                                                
  343.                          
  344.