From fb6d73723ebda8f9ef31507a20b95f0496800d07 Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Thu, 29 Feb 2024 11:11:33 +0100 Subject: [PATCH] display control point circles when polygon or bezier selected, simplify bezier drawing (no use pow(), no use precomputed cached power values) --- src/draw.c | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/src/draw.c b/src/draw.c index f826b170..f92a229d 100644 --- a/src/draw.c +++ b/src/draw.c @@ -1664,30 +1664,19 @@ void arc_bbox(double x, double y, double r, double a, double b, void drawbezier(Drawable w, GC gc, int c, double *x, double *y, int points, int fill) { - enum { bez_points = 32 }; /* number of points a single bezier is approximated with */ - static int psize = 512; - static double power[bez_points + 1]; /* cached values for t^2 values */ + const double bez_steps = 1.0/32.0; /* divide the t = [0,1] interval into 32 steps */ + static int psize = 1024; static XPoint *p = NULL; - int b, i, j; + int b, i; double t; double xp, yp; double x0, x1, x2, y0, y1, y2; if(points == 0 && x == NULL && y == NULL) { /* cleanup */ - if(p) my_free(_ALLOC_ID_, &p); - } - if(!p) { - p = my_malloc(_ALLOC_ID_, psize * sizeof(XPoint)); - /* cache t^2 values for speed */ - for(j = 0; j <= bez_points; j++) { - t = 1.0 / bez_points * j; - power[j] = pow(t, 2); - } - } - if(gc == xctx->gc[SELLAYER]) for(i = 0; i < points; i++) { - drawtemparc(gc, NOW, x[i], y[i], cadhalfdotsize, 0., 360.); + my_free(_ALLOC_ID_, &p); } + if(!p) p = my_malloc(_ALLOC_ID_, psize * sizeof(XPoint)); i = 0; for(b = 0; b < points - 2; b++) { if(points == 3) { /* 3 points: only one bezier */ @@ -1725,10 +1714,9 @@ void drawbezier(Drawable w, GC gc, int c, double *x, double *y, int points, int * dbg(0, "x1=%g y1=%g\n", x1, y1); * dbg(0, "x2=%g y2=%g\n", x2, y2); */ - for(j = 0; j <= bez_points; j++) { - t = 1.0 / bez_points * j; - xp = power[bez_points - j] * x0 + 2 * (1-t) * t * x1 + power[j] * x2; - yp = power[bez_points - j] * y0 + 2 * (1-t) * t * y1 + power[j] * y2; + for(t = 0; t <= 1.0; t += bez_steps) { + xp = (1 - t) * (1 - t) * x0 + 2 * (1 - t) * t * x1 + t * t * x2; + yp = (1 - t) * (1 - t) * y0 + 2 * (1 - t) * t * y1 + t * t * y2; if(i >= psize) { psize *= 2; my_realloc(_ALLOC_ID_, &p, psize * sizeof(XPoint)); @@ -1750,7 +1738,7 @@ void drawbezier(Drawable w, GC gc, int c, double *x, double *y, int points, int drawtemparc(gc, NOW, x[i], y[i], cadhalfdotsize, 0., 360.); } i = 0; - for(t = 0; t <= 1.0; t += 0.0078125/* 1/128 */) { + for(t = 0; t <= 1.0; t += bez_steps) { xp = pow(1-t, 3) * x[0] + 3 * pow(1-t, 2) * t * x[1] + 3 * (1-t) * pow(t, 2) * x[2] + pow(t, 3) * x[3]; yp = pow(1-t, 3) * y[0] + 3 * pow(1-t, 2) * t * y[1] + 3 * (1-t) * pow(t, 2) * y[2] + pow(t, 3) * y[3]; p[i].x = (short)X_TO_SCREEN(xp); @@ -1855,6 +1843,12 @@ void drawtemppolygon(GC gc, int what, double *x, double *y, int points, int flag x2 + cadhalfdotsize, y2 + cadhalfdotsize, x1 - cadhalfdotsize, y1 - cadhalfdotsize, xctx->lw); } else { + if(gc == xctx->gc[SELLAYER]) for(i = 0; i < points; i++) { + if( POINTINSIDE(X_TO_SCREEN(x[i]), Y_TO_SCREEN(y[i]), xctx->areax1, xctx->areay1, + xctx->areax2, xctx->areay2)) { + drawtemparc(gc, NOW, x[i], y[i], cadhalfdotsize, 0., 360.); + } + } if(bezier) { drawbezier(xctx->window, gc, 0, x, y, points, 0); } else {