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; }