home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / server / ddx / mi / mizerarc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-21  |  19.1 KB  |  840 lines

  1. /************************************************************
  2. Copyright 1989 by The Massachusetts Institute of Technology
  3.  
  4. Permission to use, copy, modify, and distribute this
  5. software and its documentation for any purpose and without
  6. fee is hereby granted, provided that the above copyright
  7. notice appear in all copies and that both that copyright
  8. notice and this permission notice appear in supporting
  9. documentation, and that the name of MIT not be used in
  10. advertising or publicity pertaining to distribution of the
  11. software without specific prior written permission.
  12. M.I.T. makes no representation about the suitability of
  13. this software for any purpose. It is provided "as is"
  14. without any express or implied warranty.
  15.  
  16. Author:  Bob Scheifler, MIT X Consortium
  17.  
  18. ********************************************************/
  19.  
  20. /* $XConsortium: mizerarc.c,v 5.34 92/05/22 17:44:26 rws Exp $ */
  21.  
  22. /* Derived from:
  23.  * "Algorithm for drawing ellipses or hyperbolae with a digital plotter"
  24.  * by M. L. V. Pitteway
  25.  * The Computer Journal, November 1967, Volume 10, Number 3, pp. 282-289
  26.  */
  27.  
  28. #include <math.h>
  29. #include "X.h"
  30. #include "Xprotostr.h"
  31. #include "miscstruct.h"
  32. #include "gcstruct.h"
  33. #include "pixmapstr.h"
  34. #include "mi.h"
  35. #include "mizerarc.h"
  36.  
  37. #define FULLCIRCLE (360 * 64)
  38. #define OCTANT (45 * 64)
  39. #define QUADRANT (90 * 64)
  40. #define HALFCIRCLE (180 * 64)
  41. #define QUADRANT3 (270 * 64)
  42.  
  43. #ifndef M_PI
  44. #define M_PI    3.14159265358979323846
  45. #endif
  46.  
  47. #define Dsin(d)    ((d) == 0 ? 0.0 : ((d) == QUADRANT ? 1.0 : \
  48.          ((d) == HALFCIRCLE ? 0.0 : \
  49.          ((d) == QUADRANT3 ? -1.0 : sin((double)d*(M_PI/11520.0))))))
  50.  
  51. #define Dcos(d)    ((d) == 0 ? 1.0 : ((d) == QUADRANT ? 0.0 : \
  52.          ((d) == HALFCIRCLE ? -1.0 : \
  53.          ((d) == QUADRANT3 ? 0.0 : cos((double)d*(M_PI/11520.0))))))
  54.  
  55. #define EPSILON45 64
  56.  
  57. typedef struct {
  58.     int skipStart;
  59.     int haveStart;
  60.     DDXPointRec startPt;
  61.     int haveLast;
  62.     int skipLast;
  63.     DDXPointRec endPt;
  64.     int dashIndex;
  65.     int dashOffset;
  66.     int dashIndexInit;
  67.     int dashOffsetInit;
  68. } DashInfo;
  69.  
  70. static miZeroArcPtRec oob = {65536, 65536, 0};
  71.  
  72. /*
  73.  * (x - l)^2 / (W/2)^2  + (y + H/2)^2 / (H/2)^2 = 1
  74.  *
  75.  * where l is either 0 or .5
  76.  *
  77.  * alpha = 4(W^2)
  78.  * beta = 4(H^2)
  79.  * gamma = 0
  80.  * u = 2(W^2)H
  81.  * v = 4(H^2)l
  82.  * k = -4(H^2)(l^2)
  83.  *
  84.  */
  85.  
  86. Bool
  87. miZeroArcSetup(arc, info, ok360)
  88.     register xArc *arc;
  89.     register miZeroArcRec *info;
  90.     Bool ok360;
  91. {
  92.     int l;
  93.     int angle1, angle2;
  94.     int startseg, endseg;
  95.     int startAngle, endAngle;
  96.     int i, overlap;
  97.     miZeroArcPtRec start, end;
  98.  
  99.     l = arc->width & 1;
  100.     if (arc->width == arc->height)
  101.     {
  102.     info->alpha = 4;
  103.     info->beta = 4;
  104.     info->k1 = -8;
  105.     info->k3 = -16;
  106.     info->b = 12;
  107.     info->a = (arc->width << 2) - 12;
  108.     info->d = 17 - (arc->width << 1);
  109.     if (l)
  110.     {
  111.         info->b -= 4;
  112.         info->a += 4;
  113.         info->d -= 7;
  114.     }
  115.     }
  116.     else if (!arc->width || !arc->height)
  117.     {
  118.     info->alpha = 0;
  119.     info->beta = 0;
  120.     info->k1 = 0;
  121.     info->k3 = 0;
  122.     info->a = -(int)arc->height;
  123.     info->b = 0;
  124.     info->d = -1;
  125.     }
  126.     else
  127.     {
  128.     /* initial conditions */
  129.     info->alpha = (arc->width * arc->width) << 2;
  130.     info->beta = (arc->height * arc->height) << 2;
  131.     info->k1 = info->beta << 1;
  132.     info->k3 = info->k1 + (info->alpha << 1);
  133.     info->b = l ? 0 : -info->beta;
  134.     info->a = info->alpha * arc->height;
  135.     info->d = info->b - (info->a >> 1) - (info->alpha >> 2);
  136.     if (l)
  137.         info->d -= info->beta >> 2;
  138.     info->a -= info->b;
  139.     /* take first step, d < 0 always */
  140.     info->b -= info->k1;
  141.     info->a += info->k1;
  142.     info->d += info->b;
  143.     /* octant change, b < 0 always */
  144.     info->k1 = -info->k1;
  145.     info->k3 = -info->k3;
  146.     info->b = -info->b;
  147.     info->d = info->b - info->a - info->d;
  148.     info->a = info->a - (info->b << 1);
  149.     }
  150.     info->dx = 1;
  151.     info->dy = 0;
  152.     info->w = (arc->width + 1) >> 1;
  153.     info->h = arc->height >> 1;
  154.     info->xorg = arc->x + (arc->width >> 1);
  155.     info->yorg = arc->y;
  156.     info->xorgo = info->xorg + l;
  157.     info->yorgo = info->yorg + arc->height;
  158.     if (!arc->width)
  159.     {
  160.     if (!arc->height)
  161.     {
  162.         info->x = 0;
  163.         info->y = 0;
  164.         info->initialMask = 0;
  165.         info->startAngle = 0;
  166.         info->endAngle = 0;
  167.         info->start = oob;
  168.         info->end = oob;
  169.         return FALSE;
  170.     }
  171.     info->x = 0;
  172.     info->y = 1;
  173.     }
  174.     else
  175.     {
  176.     info->x = 1;
  177.     info->y = 0;
  178.     }
  179.     angle1 = arc->angle1;
  180.     angle2 = arc->angle2;
  181.     if ((angle1 == 0) && (angle2 >= FULLCIRCLE))
  182.     {
  183.     startAngle = 0;
  184.     endAngle = 0;
  185.     }
  186.     else
  187.     {
  188.     if (angle2 > FULLCIRCLE)
  189.         angle2 = FULLCIRCLE;
  190.     else if (angle2 < -FULLCIRCLE)
  191.         angle2 = -FULLCIRCLE;
  192.     if (angle2 < 0)
  193.     {
  194.         startAngle = angle1 + angle2;
  195.         endAngle = angle1;
  196.     }
  197.     else
  198.     {
  199.         startAngle = angle1;
  200.         endAngle = angle1 + angle2;
  201.     }
  202.     if (startAngle < 0)
  203.         startAngle = FULLCIRCLE - (-startAngle) % FULLCIRCLE;
  204.     if (startAngle >= FULLCIRCLE)
  205.         startAngle = startAngle % FULLCIRCLE;
  206.     if (endAngle < 0)
  207.         endAngle = FULLCIRCLE - (-endAngle) % FULLCIRCLE;
  208.     if (endAngle >= FULLCIRCLE)
  209.         endAngle = endAngle % FULLCIRCLE;
  210.     }
  211.     info->startAngle = startAngle;
  212.     info->endAngle = endAngle;
  213.     if (ok360 && (startAngle == endAngle) && arc->angle2 &&
  214.     arc->width && arc->height)
  215.     {
  216.     info->initialMask = 0xf;
  217.     info->start = oob;
  218.     info->end = oob;
  219.     return TRUE;
  220.     }
  221.     startseg = startAngle / OCTANT;
  222.     if (!arc->height || (((startseg + 1) & 2) && arc->width))
  223.     {
  224.     start.x = Dcos(startAngle) * ((arc->width + 1) / 2.0);
  225.     if (start.x < 0)
  226.         start.x = -start.x;
  227.     start.y = -1;
  228.     }
  229.     else
  230.     {
  231.     start.y = Dsin(startAngle) * (arc->height / 2.0);
  232.     if (start.y < 0)
  233.         start.y = -start.y;
  234.     start.y = info->h - start.y;
  235.     start.x = 65536;
  236.     }
  237.     endseg = endAngle / OCTANT;
  238.     if (!arc->height || (((endseg + 1) & 2) && arc->width))
  239.     {
  240.     end.x = Dcos(endAngle) * ((arc->width + 1) / 2.0);
  241.     if (end.x < 0)
  242.         end.x = -end.x;
  243.     end.y = -1;
  244.     }
  245.     else
  246.     {
  247.     end.y = Dsin(endAngle) * (arc->height / 2.0);
  248.     if (end.y < 0)
  249.         end.y = -end.y;
  250.     end.y = info->h - end.y;
  251.     end.x = 65536;
  252.     }
  253.     info->firstx = start.x;
  254.     info->firsty = start.y;
  255.     info->initialMask = 0;
  256.     overlap = arc->angle2 && (endAngle <= startAngle);
  257.     for (i = 0; i < 4; i++)
  258.     {
  259.     if (overlap ?
  260.         ((i * QUADRANT <= endAngle) || ((i + 1) * QUADRANT > startAngle)) :
  261.         ((i * QUADRANT <= endAngle) && ((i + 1) * QUADRANT > startAngle)))
  262.         info->initialMask |= (1 << i);
  263.     }
  264.     start.mask = info->initialMask;
  265.     end.mask = info->initialMask;
  266.     startseg >>= 1;
  267.     endseg >>= 1;
  268.     overlap = overlap && (endseg == startseg);
  269.     if (start.x != end.x || start.y != end.y || !overlap)
  270.     {
  271.     if (startseg & 1)
  272.     {
  273.         if (!overlap)
  274.         info->initialMask &= ~(1 << startseg);
  275.         if (start.x > end.x || start.y > end.y)
  276.         end.mask &= ~(1 << startseg);
  277.     }
  278.     else
  279.     {
  280.         start.mask &= ~(1 << startseg);
  281.         if (((start.x < end.x || start.y < end.y) ||
  282.          (start.x == end.x && start.y == end.y && (endseg & 1))) &&
  283.         !overlap)
  284.         end.mask &= ~(1 << startseg);
  285.     }
  286.     if (endseg & 1)
  287.     {
  288.         end.mask &= ~(1 << endseg);
  289.         if (((start.x > end.x || start.y > end.y) ||
  290.          (start.x == end.x && start.y == end.y && !(startseg & 1))) &&
  291.         !overlap)
  292.         start.mask &= ~(1 << endseg);
  293.     }
  294.     else
  295.     {
  296.         if (!overlap)
  297.         info->initialMask &= ~(1 << endseg);
  298.         if (start.x < end.x || start.y < end.y)
  299.         start.mask &= ~(1 << endseg);
  300.     }
  301.     }
  302.     /* take care of case when start and stop are both near 45 */
  303.     /* handle here rather than adding extra code to pixelization loops */
  304.     if (startAngle &&
  305.     ((start.y < 0 && end.y >= 0) || (start.y >= 0 && end.y < 0)))
  306.     {
  307.     i = (startAngle + OCTANT) % OCTANT;
  308.     if (i < EPSILON45 || i > OCTANT - EPSILON45)
  309.     {
  310.         i = (endAngle + OCTANT) % OCTANT;
  311.         if (i < EPSILON45 || i > OCTANT - EPSILON45)
  312.         {
  313.         if (start.y < 0)
  314.         {
  315.             i = Dsin(startAngle) * (arc->height / 2.0);
  316.             if (i < 0)
  317.             i = -i;
  318.             if (info->h - i == end.y)
  319.             start.mask = end.mask;
  320.         }
  321.         else
  322.         {
  323.             i = Dsin(endAngle) * (arc->height / 2.0);
  324.             if (i < 0)
  325.             i = -i;
  326.             if (info->h - i == start.y)
  327.             end.mask = start.mask;
  328.         }
  329.         }
  330.     }
  331.     }
  332.     if (startseg & 1)
  333.     {
  334.     info->start = start;
  335.     info->end = oob;
  336.     }
  337.     else
  338.     {
  339.     info->end = start;
  340.     info->start = oob;
  341.     }
  342.     if (endseg & 1)
  343.     {
  344.     info->altend = end;
  345.     if (info->altend.x < info->end.x || info->altend.y < info->end.y)
  346.     {
  347.         miZeroArcPtRec tmp;
  348.         tmp = info->altend;
  349.         info->altend = info->end;
  350.         info->end = tmp;
  351.     }
  352.     info->altstart = oob;
  353.     }
  354.     else
  355.     {
  356.     info->altstart = end;
  357.     if (info->altstart.x < info->start.x ||
  358.         info->altstart.y < info->start.y)
  359.     {
  360.         miZeroArcPtRec tmp;
  361.         tmp = info->altstart;
  362.         info->altstart = info->start;
  363.         info->start = tmp;
  364.     }
  365.     info->altend = oob;
  366.     }
  367.     if (!info->start.x || !info->start.y)
  368.     {
  369.     info->initialMask = info->start.mask;
  370.     info->start = info->altstart;
  371.     }
  372.     if (!arc->width && (arc->height == 1))
  373.     {
  374.     /* kludge! */
  375.     info->initialMask |= info->end.mask;
  376.     info->initialMask |= info->initialMask << 1;
  377.     info->end.x = 0;
  378.     info->end.mask = 0;
  379.     }
  380.     return FALSE;
  381. }
  382.  
  383. #define Pixelate(xval,yval) \
  384.     { \
  385.     pts->x = xval; \
  386.     pts->y = yval; \
  387.     pts++; \
  388.     }
  389.  
  390. #define DoPix(idx,xval,yval) if (mask & (1 << idx)) Pixelate(xval, yval);
  391.  
  392. DDXPointPtr
  393. miZeroArcPts(arc, pts)
  394.     xArc *arc;
  395.     register DDXPointPtr pts;
  396. {
  397.     miZeroArcRec info;
  398.     register int x, y, a, b, d, mask;
  399.     register int k1, k3, dx, dy;
  400.     Bool do360;
  401.  
  402.     do360 = miZeroArcSetup(arc, &info, TRUE);
  403.     MIARCSETUP();
  404.     mask = info.initialMask;
  405.     if (!(arc->width & 1))
  406.     {
  407.     DoPix(1, info.xorgo, info.yorg);
  408.     DoPix(3, info.xorgo, info.yorgo);
  409.     }
  410.     if (!info.end.x || !info.end.y)
  411.     {
  412.     mask = info.end.mask;
  413.     info.end = info.altend;
  414.     }
  415.     if (do360 && (arc->width == arc->height) && !(arc->width & 1))
  416.     {
  417.     int yorgh = info.yorg + info.h;
  418.     int xorghp = info.xorg + info.h;
  419.     int xorghn = info.xorg - info.h;
  420.  
  421.     while (1)
  422.     {
  423.         Pixelate(info.xorg + x, info.yorg + y);
  424.         Pixelate(info.xorg - x, info.yorg + y);
  425.         Pixelate(info.xorg - x, info.yorgo - y);
  426.         Pixelate(info.xorg + x, info.yorgo - y);
  427.         if (a < 0)
  428.         break;
  429.         Pixelate(xorghp - y, yorgh - x);
  430.         Pixelate(xorghn + y, yorgh - x);
  431.         Pixelate(xorghn + y, yorgh + x);
  432.         Pixelate(xorghp - y, yorgh + x);
  433.         MIARCCIRCLESTEP(;);
  434.     }
  435.     if (x > 1 && pts[-1].x == pts[-5].x && pts[-1].y == pts[-5].y)
  436.         pts -= 4;
  437.     x = info.w;
  438.     y = info.h;
  439.     }
  440.     else if (do360)
  441.     {
  442.     while (y < info.h || x < info.w)
  443.     {
  444.         MIARCOCTANTSHIFT(;);
  445.         Pixelate(info.xorg + x, info.yorg + y);
  446.         Pixelate(info.xorgo - x, info.yorg + y);
  447.         Pixelate(info.xorgo - x, info.yorgo - y);
  448.         Pixelate(info.xorg + x, info.yorgo - y);
  449.         MIARCSTEP(;,;);
  450.     }
  451.     }
  452.     else
  453.     {
  454.     while (y < info.h || x < info.w)
  455.     {
  456.         MIARCOCTANTSHIFT(;);
  457.         if ((x == info.start.x) || (y == info.start.y))
  458.         {
  459.         mask = info.start.mask;
  460.         info.start = info.altstart;
  461.         }
  462.         DoPix(0, info.xorg + x, info.yorg + y);
  463.         DoPix(1, info.xorgo - x, info.yorg + y);
  464.         DoPix(2, info.xorgo - x, info.yorgo - y);
  465.         DoPix(3, info.xorg + x, info.yorgo - y);
  466.         if ((x == info.end.x) || (y == info.end.y))
  467.         {
  468.         mask = info.end.mask;
  469.         info.end = info.altend;
  470.         }
  471.         MIARCSTEP(;,;);
  472.     }
  473.     }
  474.     if ((x == info.start.x) || (y == info.start.y))
  475.     mask = info.start.mask;
  476.     DoPix(0, info.xorg + x, info.yorg + y);
  477.     DoPix(2, info.xorgo - x, info.yorgo - y);
  478.     if (arc->height & 1)
  479.     {
  480.     DoPix(1, info.xorgo - x, info.yorg + y);
  481.     DoPix(3, info.xorg + x, info.yorgo - y);
  482.     }
  483.     return pts;
  484. }
  485.  
  486. #undef DoPix
  487. #define DoPix(idx,xval,yval) \
  488.     if (mask & (1 << idx)) \
  489.     { \
  490.     arcPts[idx]->x = xval; \
  491.     arcPts[idx]->y = yval; \
  492.     arcPts[idx]++; \
  493.     }
  494.  
  495. static void
  496. miZeroArcDashPts(pGC, arc, dinfo, points, maxPts, evenPts, oddPts)
  497.     GCPtr pGC;
  498.     xArc *arc;
  499.     DashInfo *dinfo;
  500.     int maxPts;
  501.     register DDXPointPtr points, *evenPts, *oddPts;
  502. {
  503.     miZeroArcRec info;
  504.     register int x, y, a, b, d, mask;
  505.     register int k1, k3, dx, dy;
  506.     int dashRemaining;
  507.     DDXPointPtr arcPts[4];
  508.     DDXPointPtr startPts[5], endPts[5];
  509.     int deltas[5];
  510.     DDXPointPtr startPt, pt, lastPt, pts;
  511.     int i, j, delta, ptsdelta, seg, startseg;
  512.  
  513.     for (i = 0; i < 4; i++)
  514.     arcPts[i] = points + (i * maxPts);
  515.     (void)miZeroArcSetup(arc, &info, FALSE);
  516.     MIARCSETUP();
  517.     mask = info.initialMask;
  518.     startseg = info.startAngle / QUADRANT;
  519.     startPt = arcPts[startseg];
  520.     if (!(arc->width & 1))
  521.     {
  522.     DoPix(1, info.xorgo, info.yorg);
  523.     DoPix(3, info.xorgo, info.yorgo);
  524.     }
  525.     if (!info.end.x || !info.end.y)
  526.     {
  527.     mask = info.end.mask;
  528.     info.end = info.altend;
  529.     }
  530.     while (y < info.h || x < info.w)
  531.     {
  532.     MIARCOCTANTSHIFT(;);
  533.     if ((x == info.firstx) || (y == info.firsty))
  534.         startPt = arcPts[startseg];
  535.     if ((x == info.start.x) || (y == info.start.y))
  536.     {
  537.         mask = info.start.mask;
  538.         info.start = info.altstart;
  539.     }
  540.     DoPix(0, info.xorg + x, info.yorg + y);
  541.     DoPix(1, info.xorgo - x, info.yorg + y);
  542.     DoPix(2, info.xorgo - x, info.yorgo - y);
  543.     DoPix(3, info.xorg + x, info.yorgo - y);
  544.     if ((x == info.end.x) || (y == info.end.y))
  545.     {
  546.         mask = info.end.mask;
  547.         info.end = info.altend;
  548.     }
  549.     MIARCSTEP(;,;);
  550.     }
  551.     if ((x == info.firstx) || (y == info.firsty))
  552.     startPt = arcPts[startseg];
  553.     if ((x == info.start.x) || (y == info.start.y))
  554.     mask = info.start.mask;
  555.     DoPix(0, info.xorg + x, info.yorg + y);
  556.     DoPix(2, info.xorgo - x, info.yorgo - y);
  557.     if (arc->height & 1)
  558.     {
  559.     DoPix(1, info.xorgo - x, info.yorg + y);
  560.     DoPix(3, info.xorg + x, info.yorgo - y);
  561.     }
  562.     for (i = 0; i < 4; i++)
  563.     {
  564.     seg = (startseg + i) & 3;
  565.     pt = points + (seg * maxPts);
  566.     if (seg & 1)
  567.     {
  568.         startPts[i] = pt;
  569.         endPts[i] = arcPts[seg];
  570.         deltas[i] = 1;
  571.     }
  572.     else
  573.     {
  574.         startPts[i] = arcPts[seg] - 1;
  575.         endPts[i] = pt - 1;
  576.         deltas[i] = -1;
  577.     }
  578.     }
  579.     startPts[4] = startPts[0];
  580.     endPts[4] = startPt;
  581.     startPts[0] = startPt;
  582.     if (startseg & 1)
  583.     {
  584.     if (startPts[4] != endPts[4])
  585.         endPts[4]--;
  586.     deltas[4] = 1;
  587.     }
  588.     else
  589.     {
  590.     if (startPts[0] > startPts[4])
  591.         startPts[0]--;
  592.     if (startPts[4] < endPts[4])
  593.         endPts[4]--;
  594.     deltas[4] = -1;
  595.     }
  596.     if (arc->angle2 < 0)
  597.     {
  598.     DDXPointPtr tmps, tmpe;
  599.     int tmpd;
  600.  
  601.     tmpd = deltas[0];
  602.     tmps = startPts[0] - tmpd;
  603.     tmpe = endPts[0] - tmpd;
  604.     startPts[0] = endPts[4] - deltas[4];
  605.     endPts[0] = startPts[4] - deltas[4];
  606.     deltas[0] = -deltas[4];
  607.     startPts[4] = tmpe;
  608.     endPts[4] = tmps;
  609.     deltas[4] = -tmpd;
  610.     tmpd = deltas[1];
  611.     tmps = startPts[1] - tmpd;
  612.     tmpe = endPts[1] - tmpd;
  613.     startPts[1] = endPts[3] - deltas[3];
  614.     endPts[1] = startPts[3] - deltas[3];
  615.     deltas[1] = -deltas[3];
  616.     startPts[3] = tmpe;
  617.     endPts[3] = tmps;
  618.     deltas[3] = -tmpd;
  619.     tmps = startPts[2] - deltas[2];
  620.     startPts[2] = endPts[2] - deltas[2];
  621.     endPts[2] = tmps;
  622.     deltas[2] = -deltas[2];
  623.     }
  624.     for (i = 0; i < 5 && startPts[i] == endPts[i]; i++)
  625.     ;
  626.     if (i == 5)
  627.     return;
  628.     pt = startPts[i];
  629.     for (j = 4; startPts[j] == endPts[j]; j--)
  630.     ;
  631.     lastPt = endPts[j] - deltas[j];
  632.     if (dinfo->haveLast &&
  633.     (pt->x == dinfo->endPt.x) && (pt->y == dinfo->endPt.y))
  634.     {
  635.     startPts[i] += deltas[i];
  636.     }
  637.     else
  638.     {
  639.     dinfo->dashIndex = dinfo->dashIndexInit;
  640.     dinfo->dashOffset = dinfo->dashOffsetInit;
  641.     }
  642.     if (!dinfo->skipStart && (info.startAngle != info.endAngle))
  643.     {
  644.     dinfo->startPt = *pt;
  645.     dinfo->haveStart = TRUE;
  646.     }
  647.     else if (!dinfo->skipLast && dinfo->haveStart &&
  648.          (lastPt->x == dinfo->startPt.x) &&
  649.          (lastPt->y == dinfo->startPt.y) &&
  650.          (lastPt != startPts[i]))
  651.     endPts[j] = lastPt;
  652.     if (info.startAngle != info.endAngle)
  653.     {
  654.     dinfo->haveLast = TRUE;
  655.     dinfo->endPt = *lastPt;
  656.     }
  657.     dashRemaining = pGC->dash[dinfo->dashIndex] - dinfo->dashOffset;
  658.     for (i = 0; i < 5; i++)
  659.     {
  660.     pt = startPts[i];
  661.     lastPt = endPts[i];
  662.     delta = deltas[i];
  663.     while (pt != lastPt)
  664.     {
  665.         if (dinfo->dashIndex & 1)
  666.         {
  667.         pts = *oddPts;
  668.         ptsdelta = -1;
  669.         }
  670.         else
  671.         {
  672.         pts = *evenPts;
  673.         ptsdelta = 1;
  674.         }
  675.         while ((pt != lastPt) && --dashRemaining >= 0)
  676.         {
  677.         *pts = *pt;
  678.         pts += ptsdelta;
  679.         pt += delta;
  680.         }
  681.         if (dinfo->dashIndex & 1)
  682.         *oddPts = pts;
  683.         else
  684.         *evenPts = pts;
  685.         if (dashRemaining <= 0)
  686.         {
  687.         if (++(dinfo->dashIndex) == pGC->numInDashList)
  688.             dinfo->dashIndex = 0;
  689.         dashRemaining = pGC->dash[dinfo->dashIndex];
  690.         }
  691.     }
  692.     }
  693.     dinfo->dashOffset = pGC->dash[dinfo->dashIndex] - dashRemaining;
  694. }
  695.  
  696. void
  697. miZeroPolyArc(pDraw, pGC, narcs, parcs)
  698.     DrawablePtr    pDraw;
  699.     GCPtr    pGC;
  700.     int        narcs;
  701.     xArc    *parcs;
  702. {
  703.     int maxPts = 0;
  704.     register int n, maxw;
  705.     register xArc *arc;
  706.     register int i;
  707.     DDXPointPtr points, pts, oddPts;
  708.     register DDXPointPtr pt;
  709.     int numPts;
  710.     Bool dospans;
  711.     int *widths;
  712.     unsigned long fgPixel = pGC->fgPixel;
  713.     DashInfo dinfo;
  714.  
  715.     for (arc = parcs, i = narcs; --i >= 0; arc++)
  716.     {
  717.     if (!miCanZeroArc(arc))
  718.         miPolyArc(pDraw, pGC, 1, arc);
  719.     else
  720.     {
  721.         if (arc->width > arc->height)
  722.         n = arc->width + (arc->height >> 1);
  723.         else
  724.         n = arc->height + (arc->width >> 1);
  725.         if (n > maxPts)
  726.         maxPts = n;
  727.     }
  728.     }
  729.     if (!maxPts)
  730.     return;
  731.     numPts = maxPts << 2;
  732.     dospans = (pGC->lineStyle != LineSolid) || (pGC->fillStyle != FillSolid);
  733.     if (dospans)
  734.     {
  735.     widths = (int *)ALLOCATE_LOCAL(sizeof(int) * numPts);
  736.     if (!widths)
  737.         return;
  738.     maxw = 0;
  739.     }
  740.     if (pGC->lineStyle != LineSolid)
  741.     {
  742.     numPts <<= 1;
  743.     dinfo.haveStart = FALSE;
  744.     dinfo.skipStart = FALSE;
  745.     dinfo.haveLast = FALSE;
  746.     dinfo.dashIndexInit = 0;
  747.     dinfo.dashOffsetInit = 0;
  748.     miStepDash((int)pGC->dashOffset, &dinfo.dashIndexInit,
  749.            (unsigned char *) pGC->dash, (int)pGC->numInDashList,
  750.            &dinfo.dashOffsetInit);
  751.     }
  752.     points = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * numPts);
  753.     if (!points)
  754.     {
  755.     if (dospans)
  756.     {
  757.         DEALLOCATE_LOCAL(widths);
  758.     }
  759.     return;
  760.     }
  761.     for (arc = parcs, i = narcs; --i >= 0; arc++)
  762.     {
  763.     if (miCanZeroArc(arc))
  764.     {
  765.         if (pGC->lineStyle == LineSolid)
  766.         pts = miZeroArcPts(arc, points);
  767.         else
  768.         {
  769.         pts = points;
  770.         oddPts = &points[(numPts >> 1) - 1];
  771.         dinfo.skipLast = i;
  772.         miZeroArcDashPts(pGC, arc, &dinfo,
  773.                  oddPts + 1, maxPts, &pts, &oddPts);
  774.         dinfo.skipStart = TRUE;
  775.         }
  776.         n = pts - points;
  777.         if (!dospans)
  778.         (*pGC->ops->PolyPoint)(pDraw, pGC, CoordModeOrigin, n, points);
  779.         else
  780.         {
  781.         if (n > maxw)
  782.         {
  783.             while (maxw < n)
  784.             widths[maxw++] = 1;
  785.         }
  786.         if (pGC->miTranslate)
  787.         {
  788.             for (pt = points; pt != pts; pt++)
  789.             {
  790.             pt->x += pDraw->x;
  791.             pt->y += pDraw->y;
  792.             }
  793.         }
  794.         (*pGC->ops->FillSpans)(pDraw, pGC, n, points, widths, FALSE);
  795.         }
  796.         if (pGC->lineStyle != LineDoubleDash)
  797.         continue;
  798.         if ((pGC->fillStyle == FillSolid) ||
  799.         (pGC->fillStyle == FillStippled))
  800.         {
  801.         DoChangeGC(pGC, GCForeground, (XID *)&pGC->bgPixel, 0);
  802.         ValidateGC(pDraw, pGC);
  803.         }
  804.         pts = &points[numPts >> 1];
  805.         oddPts++;
  806.         n = pts - oddPts;
  807.         if (!dospans)
  808.         (*pGC->ops->PolyPoint)(pDraw, pGC, CoordModeOrigin, n, oddPts);
  809.         else
  810.         {
  811.         if (n > maxw)
  812.         {
  813.             while (maxw < n)
  814.             widths[maxw++] = 1;
  815.         }
  816.         if (pGC->miTranslate)
  817.         {
  818.             for (pt = oddPts; pt != pts; pt++)
  819.             {
  820.             pt->x += pDraw->x;
  821.             pt->y += pDraw->y;
  822.             }
  823.         }
  824.         (*pGC->ops->FillSpans)(pDraw, pGC, n, oddPts, widths, FALSE);
  825.         }
  826.         if ((pGC->fillStyle == FillSolid) ||
  827.         (pGC->fillStyle == FillStippled))
  828.         {
  829.         DoChangeGC(pGC, GCForeground, (XID *)&fgPixel, 0);
  830.         ValidateGC(pDraw, pGC);
  831.         }
  832.     }
  833.     }
  834.     DEALLOCATE_LOCAL(points);
  835.     if (dospans)
  836.     {
  837.     DEALLOCATE_LOCAL(widths);
  838.     }
  839. }
  840.