home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / Assembler / dse-src3.dms / in.adf / Source / Vectors / Ellipse.lha / ellipse.c
Encoding:
C/C++ Source or Header  |  1993-01-06  |  6.3 KB  |  219 lines

  1. /***********************************************/
  2. /* gred_ellipse.c - draw ellipses        *
  3. /* algorithm from IEEE CG&A Sept 1984 p.24     *
  4. /***********************************************/
  5. #include <stdio.h>
  6. #include <sunwindow/window_hs.h>
  7.  
  8. gred_ellipse (cx, cy, radius_x, radius_y, line_width, pw, pattern_pr)
  9. int               cx, cy;
  10. int               radius_x, radius_y;
  11. int            line_width;
  12. struct pixwin         *pw;
  13. struct pixrect         *pattern_pr;
  14. {
  15.     struct pixrect     *pr;
  16.     int            inner_radius_x;
  17.     int            inner_radius_y;
  18.     int            outer_radius_x;
  19.     int            outer_radius_y;
  20.  
  21. /*******************************************************************/
  22. /* Calculate the inner, outer radiuses of the ellipse              */
  23. /*******************************************************************/
  24.     /* if one pixel wide, radiuses are same */
  25.     if (line_width < 2)
  26.     {
  27.     inner_radius_x = outer_radius_x = radius_x;
  28.     inner_radius_y = outer_radius_y = radius_y;
  29.     }
  30.     else
  31.     {
  32.     outer_radius_x = radius_x + (line_width >> 1);
  33.     outer_radius_y = radius_y + (line_width >> 1);
  34.     inner_radius_x = outer_radius_x - line_width + 1;
  35.     inner_radius_y = outer_radius_y - line_width + 1;
  36.     }
  37.  
  38. /*******************************************************************/
  39. /* Create a pixrect to build the ellipse in.                       */
  40. /*******************************************************************/
  41.     pr = mem_create ((outer_radius_x << 1) + 1, (outer_radius_y << 1) + 1, 1);
  42.     /* now clear it */
  43.     pr_rop (pr,    0, 0, pr -> pr_size.x, pr -> pr_size.y,
  44.         PIX_CLR, (struct pixrect *) 0, 0, 0);
  45.  
  46. /*******************************************************************/
  47. /* If the inner_radius > 0 then outline the inner edge.            */
  48. /* Then if the outer radius of the ellipse is > than the inner     */
  49. /* radius, call the fill ellipse routine with the outer radius.    */
  50. /*******************************************************************/
  51.     if ((inner_radius_x > 0)
  52.             && (inner_radius_y > 0))
  53.         outline_ellipse (pr, outer_radius_x, outer_radius_y, 
  54.         inner_radius_x, inner_radius_y);
  55.  
  56.     if (line_width >=  2)
  57.     fill_ellipse(pr, outer_radius_x, outer_radius_y, 
  58.         outer_radius_x, outer_radius_y);
  59.     
  60. /*******************************************************************/
  61. /* Now write the ellipse out to the window.                        */
  62. /*******************************************************************/
  63.     inner_radius_x = inner_radius_y = 0;    /* normal source offset */
  64.     if ((cx -= outer_radius_x) < 0)    /* ellipse extends beyond left edge? */
  65.     {
  66.     inner_radius_x = -cx;
  67.     cx = 0;
  68.     }
  69.     if ((cy -= outer_radius_y) < 0)    /* above top edge? */
  70.     {
  71.         inner_radius_y = -cy;
  72.     cy = 0;
  73.     }
  74.  
  75.     if (pattern_pr == NULL)
  76.         pw_write (pw, cx, cy, pr->pr_size.x-inner_radius_x, pr->pr_size.y-inner_radius_y,
  77.         PIX_SRC ^ PIX_DST, pr, inner_radius_x, inner_radius_y);
  78.     else
  79.     pw_stencil (pw, cx, cy, pr -> pr_size.x, pr -> pr_size.y, 
  80.         PIX_SRC, pr, inner_radius_x, inner_radius_y, pattern_pr, 0, 0);
  81.  
  82.     pr_destroy (pr);
  83. }
  84.  
  85.  
  86. /* draw ellipse incrementally */
  87. static outline_ellipse (pr, center_x, center_y, rx, ry)
  88. struct pixrect *pr;
  89. int    center_x, center_y;
  90. int    rx, ry;
  91. {
  92.     /* intermediate terms to speed up loop */
  93.     long t1 = rx*rx, t2 = t1<<1, t3 = t2<<1;
  94.     long t4 = ry*ry, t5 = t4<<1, t6 = t5<<1;
  95.     long t7 = rx*t5, t8 = t7<<1, t9 = 0L;
  96.     long d1 = t2 - t7 + (t4>>1);    /* error terms */
  97.     long d2 = (t1>>1) - t8 + t5;
  98.  
  99.     register int x = rx, y = 0;    /* ellipse points */
  100.  
  101.     while (d2 < 0)            /* til slope = -1 */
  102.     {
  103.         /* draw 4 points using symmetry */
  104.             pr_put (pr, center_x + x, center_y + y, 1);
  105.             pr_put (pr, center_x + x, center_y - y, 1);
  106.             pr_put (pr, center_x - x, center_y + y, 1);
  107.             pr_put (pr, center_x - x, center_y - y, 1);
  108.  
  109.         y++;        /* always move up here */
  110.         t9 += t3;    
  111.         if (d1 < 0)    /* move straight up */
  112.         {
  113.             d1 += t9 + t2;
  114.             d2 += t9;
  115.         }
  116.         else        /* move up and left */
  117.         {
  118.             x--;
  119.             t8 -= t6;
  120.             d1 += t9 + t2 - t8;
  121.             d2 += t9 + t5 - t8;
  122.         }
  123.     }
  124.  
  125.     do                 /* rest of top right quadrant */
  126.     {
  127.         /* draw 4 points using symmetry */
  128.             pr_put (pr, center_x + x, center_y + y, 1);
  129.             pr_put (pr, center_x + x, center_y - y, 1);
  130.             pr_put (pr, center_x - x, center_y + y, 1);
  131.             pr_put (pr, center_x - x, center_y - y, 1);
  132.  
  133.         x--;        /* always move left here */
  134.         t8 -= t6;    
  135.         if (d2 < 0)    /* move up and left */
  136.         {
  137.             y++;
  138.             t9 += t3;
  139.             d2 += t9 + t5 - t8;
  140.         }
  141.         else        /* move straight left */
  142.             d2 += t5 - t8;
  143.     } while (x>=0);
  144. }
  145.  
  146.  
  147. static fill_ellipse (pr, center_x, center_y, rx, ry)
  148. struct pixrect *pr;
  149. int    center_x, center_y;
  150. int    rx, ry;
  151. {
  152.     long t1 = rx*rx, t2 = t1<<1, t3 = t2<<1;
  153.     long t4 = ry*ry, t5 = t4<<1, t6 = t5<<1;
  154.     long t7 = rx*t5, t8 = t7<<1, t9 = 0;
  155.     long d1 = t2 - t7 + (t4>>1);    /* error terms */
  156.     long d2 = (t1>>1) - t8 + t5;
  157.     register int x = rx, y = 0;    /* ellipse points */
  158.         register int t;            /* used in fill operation */
  159.     int wid;            /* width of fill */
  160.  
  161.     while (d2 < 0)            /* til slope = -1 */
  162.     {
  163.          /* fill in leftward to inner ellipse */
  164.             for (t=x; (!pr_get(pr, center_x+t, center_y+y)) && t; t--);
  165.         wid = x - t + 1;
  166.         pr_rop (pr, center_x+t, center_y+y, wid, 1,
  167.             PIX_SET | PIX_DONTCLIP, NULL, 0, 0);
  168.         pr_rop (pr, center_x-x, center_y+y, wid, 1,
  169.             PIX_SET | PIX_DONTCLIP, NULL, 0, 0);
  170.         pr_rop (pr, center_x+t, center_y-y, wid, 1,
  171.             PIX_SET | PIX_DONTCLIP, NULL, 0, 0);
  172.         pr_rop (pr, center_x-x, center_y-y, wid, 1,
  173.             PIX_SET | PIX_DONTCLIP, NULL, 0, 0);
  174.  
  175.         y++;        /* always move up here */
  176.         t9 += t3;    
  177.         if (d1 < 0)    /* move straight up */
  178.         {
  179.             d1 += t9 + t2;
  180.             d2 += t9;
  181.         }
  182.         else        /* move up and left */
  183.         {
  184.             x--;
  185.             t8 -= t6;
  186.             d1 += t9 + t2 - t8;
  187.             d2 += t9 + t5 - t8;
  188.         }
  189.     }
  190.  
  191.     do                 /* rest of top right quadrant */
  192.     {
  193.         /* fill in downward to inner ellipse */
  194.             for (t=y; (!pr_get(pr, center_x+x, center_y+t)) && t; t--);
  195.         wid = y - t + 1;
  196.         pr_rop (pr, center_x+x, center_y+t, 1, wid,
  197.             PIX_SET | PIX_DONTCLIP, NULL, 0, 0);
  198.         pr_rop (pr, center_x+x, center_y-y, 1, wid,
  199.             PIX_SET | PIX_DONTCLIP, NULL, 0, 0);
  200.         pr_rop (pr, center_x-x, center_y+t, 1, wid,
  201.             PIX_SET | PIX_DONTCLIP, NULL, 0, 0);
  202.         pr_rop (pr, center_x-x, center_y-y, 1, wid,
  203.             PIX_SET | PIX_DONTCLIP, NULL, 0, 0);
  204.  
  205.         x--;        /* always move left here */
  206.         t8 -= t6;    
  207.         if (d2 < 0)    /* move up and left */
  208.         {
  209.             y++;
  210.             t9 += t3;
  211.             d2 += t9 + t5 - t8;
  212.         }
  213.         else        /* move straight left */
  214.         {
  215.             d2 += t5 - t8;
  216.         }
  217.     } while (x>=0);
  218. }
  219.