66ee7c172964fe9665479973fa7c7536afe03fa2
kate
  Tue Apr 10 22:05:33 2018 -0700
Add Postscript for bezier curve.  Fix ellipse. refs #21109

diff --git src/lib/pscmGfx.c src/lib/pscmGfx.c
index 9d8c9ac..4405e2b 100644
--- src/lib/pscmGfx.c
+++ src/lib/pscmGfx.c
@@ -682,65 +682,95 @@
 }
 
 void pscmLine(struct pscmGfx *pscm, 
 	int x1, int y1, int x2, int y2, int color)
 /* Draw a line from one point to another. */
 {
 pscmSetColor(pscm, color);
 boolean fat = sameString(pscmGetHint(pscm,"fat"),"on");
 if (fat)
     pscmFatLine(pscm, x1, y1, x2, y2);
 else
     psDrawLine(pscm->ps, x1, y1, x2, y2);
 boxPscm = NULL;
 }
 
-void pscmEllipse(struct pscmGfx *pscm, 
-	int x1, int y1, int x2, int y2, int color, int mode, boolean isDashed)
+void pscmEllipse(struct pscmGfx *pscm, int x1, int y1, int x2, int y2, Color color, 
+                        int mode, boolean isDashed)
 /* Draw an ellipse specified as a rectangle. Args are left-most and top-most points.
  * Optionally draw half-ellipse (top or bottom) */
 {
 pscmSetColor(pscm, color);
 if (isDashed)
     psSetDash(pscm->ps, TRUE);
 else
     psSetDash(pscm->ps, FALSE);
 int startAngle = 0;
 int endAngle = 360;
 if (mode == ELLIPSE_TOP)
     endAngle = 180;
 else if (mode == ELLIPSE_BOTTOM)
     startAngle = 180;
-psDrawEllipse(pscm->ps, (double)x2, 0.0, (double)x2 - (double)x1, (double)y2, 
+int yrad = abs(y1 - y2)/2;
+int xrad = abs(x1 - x2)/2;
+x2 = x2 - xrad;
+y1 = y1 - yrad;
+psDrawEllipse(pscm->ps, (double)x2, (double)y1, (double)xrad, (double)yrad,
                 startAngle, endAngle);
-//warn("drawing ellipse: center: (%d,%d), xrad: %d, yrad=%d", x2, 0, x2-x1, y2);
+psSetDash(pscm->ps, FALSE);
+}
+
+static double bezierQuadraticToCubic(int a, int b)
+/* Derive cubic control points from quadratic control point. */
+{
+return (double)a + (2 * (b - a))/3.0;
+}
+
+void pscmCurve(struct pscmGfx *pscm, int x1, int y1, int x2, int y2, int x3, int y3, Color color,
+                        boolean isDashed)
+/* Draw Bezier curve specified by 3 points (quadratic Bezier).
+ * The points are: first (p1) and last (p3), and 1 control point (p2).
+ */ 
+{
+pscmSetColor(pscm, color);
+if (isDashed)
+    psSetDash(pscm->ps, TRUE);
+else
+    psSetDash(pscm->ps, FALSE);
+// PostScript bezier is cubic -- derive the two control points from the single quadratic control point
+double c1x = bezierQuadraticToCubic(x1, x2);
+double c1y = bezierQuadraticToCubic(y1, y2);
+double c2x = bezierQuadraticToCubic(x3, x2);
+double c2y = bezierQuadraticToCubic(y3, y2);
+psDrawCurve(pscm->ps, (double)x1, (double)y1, c1x, c1y, c2x, c2y, (double)x3, (double)y3);
 psSetDash(pscm->ps, FALSE);
 }
 
 struct vGfx *vgOpenPostScript(int width, int height, char *fileName)
 /* Open up something that will someday be a PostScript file. */
 {
 struct vGfx *vg = vgHalfInit(width, height);
 vg->data = pscmOpen(width, height, fileName);
 vg->close = (vg_close)pscmClose;
 vg->dot = (vg_dot)pscmDot;
 vg->box = (vg_box)pscmBox;
 vg->line = (vg_line)pscmLine;
 vg->text = (vg_text)pscmText;
 vg->textRight = (vg_textRight)pscmTextRight;
 vg->textCentered = (vg_textCentered)pscmTextCentered;
 vg->findColorIx = (vg_findColorIx)pscmFindColorIx;
 vg->colorIxToRgb = (vg_colorIxToRgb)pscmColorIxToRgb;
 vg->setClip = (vg_setClip)pscmSetClip;
 vg->unclip = (vg_unclip)pscmUnclip;
 vg->verticalSmear = (vg_verticalSmear)pscmVerticalSmear;
 vg->fillUnder = (vg_fillUnder)pscmFillUnder;
 vg->drawPoly = (vg_drawPoly)pscmDrawPoly;
 vg->ellipse = (vg_ellipse)pscmEllipse;
+vg->curve = (vg_curve)pscmCurve;
 vg->setHint = (vg_setHint)pscmSetHint;
 vg->getHint = (vg_getHint)pscmGetHint;
 vg->getFontPixelHeight = (vg_getFontPixelHeight)pscmGetFontPixelHeight;
 vg->getFontStringWidth = (vg_getFontStringWidth)pscmGetFontStringWidth;
 vg->setWriteMode = (vg_setWriteMode)pscmSetWriteMode;
 return vg;
 }