31059016e90d9d6d65e11f55808869efacb8d4e2
kate
  Tue Apr 10 18:16:17 2018 -0700
Add postscript for ellipse drawing. refs #21109

diff --git src/hg/lib/hvGfx.c src/hg/lib/hvGfx.c
index 6ec4c60..97a40a7 100644
--- src/hg/lib/hvGfx.c
+++ src/hg/lib/hvGfx.c
@@ -388,30 +388,33 @@
          }
       } while (dy < dx);                  /* gradient negates -> close curves */
    }
    hvGfxLine(hvg, x0,y0, x2,y2, color);                  /* plot remaining needle to end */
    if (y0 > yMax)
        yMax = y0;
    return yMax;
 }
 
 int hvGfxCurve(struct hvGfx *hvg, int x0, int y0, int x1, int y1, int x2, int y2, 
                         Color color, boolean isDashed)
 /* Draw a segment of an anti-aliased curve within 3 points (quadratic Bezier)
  * Return max y value. Optionally alternate dots.
  * Adapted trivially from code posted at http://members.chello.at/~easyfilter/bresenham.html
  */
+/* TODO: allow specifying a third point on the line
+ *  P(t) = (1-t)^2 * p0 + 2 * (1-t) * t * p1 + t^2 * p2
+ */
 {
    int x = x0-x1, y = y0-y1;
    double t = x0-2*x1+x2, r;
    int yMax = 0, yMaxRet = 0;
    if ((long)x*(x2-x1) > 0) {                        /* horizontal cut at P4? */
       if ((long)y*(y2-y1) > 0)                     /* vertical cut at P6 too? */
          if (fabs((y0-2*y1+y2)/t*x) > abs(y)) {               /* which first? */
             x0 = x2; x2 = x+x1; y0 = y2; y2 = y+y1;            /* swap points */
          }                            /* now horizontal cut at P4 comes first */
       t = (x0-x1)/t;
       r = (1-t)*((1-t)*y0+2.0*t*y1)+t*t*y2;                       /* By(t=P4) */
       t = (x0*x2-x1*x1)*t/(x0-x1);                       /* gradient dP4/dx=0 */
       x = floor(t+0.5); y = floor(r+0.5);
       r = (y1-y0)*(t-x0)/(x1-x0)+y0;                  /* intersect P3 | P0 P1 */
       yMax = hvGfxCurveSegAA(hvg,x0,y0, x,floor(r+0.5), x,y, color, isDashed);
@@ -424,73 +427,15 @@
       t = (y0*y2-y1*y1)*t/(y0-y1);                       /* gradient dP6/dy=0 */
       x = floor(r+0.5); y = floor(t+0.5);
       r = (x1-x0)*(t-y0)/(y1-y0)+x0;                  /* intersect P6 | P0 P1 */
       yMaxRet = hvGfxCurveSegAA(hvg,x0,y0, floor(r+0.5),y, x,y, color, isDashed);
       if (yMaxRet > yMax)
         yMax = yMaxRet;
       r = (x1-x2)*(t-y2)/(y1-y2)+x2;                  /* intersect P7 | P1 P2 */
       x0 = x; x1 = floor(r+0.5); y0 = y1 = y;             /* P0 = P6, P1 = P7 */
    }
    yMaxRet = hvGfxCurveSegAA(hvg,x0,y0, x1,y1, x2,y2, color, isDashed); /* remaining part */
    if (yMaxRet > yMax)
      yMax = yMaxRet;
    return yMax;
 }
 
-void hvGfxEllipseDraw(struct hvGfx *hvg, int x0, int y0, int x1, int y1, Color color, 
-                        int mode, boolean isDashed)
-/* Draw an ellipse (or limit to top or bottom) specified by rectangle, using Bresenham algorithm.
- * Optionally, alternate dots.
- * Point 0 is left, point 1 is top of rectangle
- * Adapted trivially from code posted at http://members.chello.at/~easyfilter/bresenham.html
- */
-{
-   int a = abs(x1-x0), b = abs(y1-y0), b1 = b&1; /* values of diameter */
-   long dx = 4*(1-a)*b*b, dy = 4*(b1+1)*a*a; /* error increment */
-   long err = dx+dy+b1*a*a, e2; /* error of 1.step */
-
-   if (x0 > x1) { x0 = x1; x1 += a; } /* if called with swapped points */
-   if (y0 > y1) y0 = y1; /* .. exchange them */
-   y0 += (b+1)/2; y1 = y0-b1;   /* starting pixel */
-   a *= 8*a; b1 = 8*b*b;
-
-   int dots = 0;
-   do {
-       if (!isDashed || (++dots % 3))
-           {
-           if (mode == ELLIPSE_BOTTOM || mode == ELLIPSE_FULL) 
-               {
-               hvGfxDot(hvg, x1, y0, color); /*   I. Quadrant */
-               hvGfxDot(hvg, x0, y0, color); /*  II. Quadrant */
-               }
-           if (mode == ELLIPSE_TOP || mode == ELLIPSE_FULL) 
-               {
-               hvGfxDot(hvg, x0, y1, color); /* III. Quadrant */
-               hvGfxDot(hvg, x1, y1, color); /*  IV. Quadrant */
-               }
-           }
-       e2 = 2*err;
-       if (e2 <= dy) { y0++; y1--; err += dy += a; }  /* y step */
-       if (e2 >= dx || 2*err > dy) { x0++; x1--; err += dx += b1; } /* x step */
-   } while (x0 <= x1);
-
-   while (y0-y1 < b) {  /* too early stop of flat ellipses a=1 */
-       if (!isDashed && (++dots % 3))
-           {
-           hvGfxDot(hvg, x0-1, y0, color); /* -> finish tip of ellipse */
-           hvGfxDot(hvg, x1+1, y0++, color);
-           hvGfxDot(hvg, x0-1, y1, color);
-           hvGfxDot(hvg, x1+1, y1--, color);
-           }
-   }
-}
-
-void hvGfxEllipse(struct hvGfx *hvg, int x0, int y0, int x1, int y1, Color color)
-/* Draw a full ellipse specified by rectangle, using Bresenham algorithm.
- * Point 0 is left, point 1 is top of rectangle
- * Adapted trivially from code posted at http://members.chello.at/~easyfilter/bresenham.html
- */
-{
-hvGfxEllipseDraw(hvg, x0, y0, x1, y1, color, ELLIPSE_FULL, FALSE);
-}
-
-