added bezier export in svg and postscript code

This commit is contained in:
stefan schippers 2024-03-01 17:23:49 +01:00
parent 7073b5b78c
commit e897aee1c4
3 changed files with 146 additions and 62 deletions

View File

@ -1717,12 +1717,6 @@ void drawbezier(Drawable w, GC gc, int c, double *x, double *y, int points, int
x2 = (x[b + 1] + x[b + 2]) / 2.0;
y2 = (y[b + 1] + y[b + 2]) / 2.0;
}
/*
* dbg(0, "\n-------- b=%d points=%d -----------\n", b, points);
* dbg(0, "x0=%g y0=%g\n", x0, y0);
* dbg(0, "x1=%g y1=%g\n", x1, y1);
* dbg(0, "x2=%g y2=%g\n", x2, 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;
@ -1740,26 +1734,6 @@ void drawbezier(Drawable w, GC gc, int c, double *x, double *y, int points, int
if(fill) {
XFillPolygon(display, w, xctx->gcstipple[c], p, i, Polygontype, CoordModeOrigin);
}
/* example of cubic bezier */
#if 0
if(points == 4) {
if(gc == xctx->gc[SELLAYER]) for(i = 0; i < points; i++) {
drawtemparc(gc, NOW, x[i], y[i], xctx->cadhalfdotsize, 0., 360.);
}
i = 0;
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);
p[i].y = (short)Y_TO_SCREEN(yp);
i++;
}
XDrawLines(display, w, gc, p, i, CoordModeOrigin);
if(fill) {
XFillPolygon(display, w, xctx->gcstipple[c], p, i, Polygontype, CoordModeOrigin);
}
}
#endif
}
/* Unused 'what' parameter used in spice data draw_graph()

View File

@ -422,14 +422,63 @@ static void ps_xfillrectange(int layer, double x1, double y1, double x2,
/*fprintf(fd,"stroke\n"); */
}
static void ps_drawbezier(double *x, double *y, int points)
{
const double bez_steps = 1.0/32.0; /* divide the t = [0,1] interval into 32 steps */
int b, i;
double t;
double xp, yp;
double x0, x1, x2, y0, y1, y2;
i = 0;
for(b = 0; b < points - 2; b++) {
if(points == 3) { /* 3 points: only one bezier */
x0 = x[0];
y0 = y[0];
x1 = x[1];
y1 = y[1];
x2 = x[2];
y2 = y[2];
} else if(b == points - 3) { /* last bezier */
x0 = (x[points - 3] + x[points - 2]) / 2.0;
y0 = (y[points - 3] + y[points - 2]) / 2.0;
x1 = x[points - 2];
y1 = y[points - 2];
x2 = x[points - 1];
y2 = y[points - 1];
} else if(b == 0) { /* first bezier */
x0 = x[0];
y0 = y[0];
x1 = x[1];
y1 = y[1];
x2 = (x[1] + x[2]) / 2.0;
y2 = (y[1] + y[2]) / 2.0;
} else { /* beziers in the middle */
x0 = (x[b] + x[b + 1]) / 2.0;
y0 = (y[b] + y[b + 1]) / 2.0;
x1 = x[b + 1];
y1 = y[b + 1];
x2 = (x[b + 1] + x[b + 2]) / 2.0;
y2 = (y[b + 1] + y[b + 2]) / 2.0;
}
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==0) fprintf(fd, "NP\n%g %g MT\n", X_TO_PS(xp), Y_TO_PS(yp));
else fprintf(fd, "%g %g LT\n", X_TO_PS(xp), Y_TO_PS(yp));
i++;
}
}
}
/* Convex Nonconvex Complex */
#define Polygontype Nonconvex
static void ps_drawpolygon(int c, int what, double *x, double *y, int points, int poly_fill, int dash)
static void ps_drawpolygon(int c, int what, double *x, double *y, int points, int poly_fill, int dash, int flags)
{
double x1,y1,x2,y2;
double xx, yy;
double psdash;
int i;
int i, bezier;
polygon_bbox(x, y, points, &x1,&y1,&x2,&y2);
x1=X_TO_PS(x1);
y1=Y_TO_PS(y1);
@ -438,24 +487,26 @@ static void ps_drawpolygon(int c, int what, double *x, double *y, int points, in
if( !rectclip(xctx->areax1,xctx->areay1,xctx->areax2,xctx->areay2,&x1,&y1,&x2,&y2) ) {
return;
}
psdash = dash / xctx->zoom;
if(dash) {
fprintf(fd, "[%g %g] 0 setdash\n", psdash, psdash);
}
for(i=0;i<points; ++i) {
xx = X_TO_PS(x[i]);
yy = Y_TO_PS(y[i]);
if(i==0) fprintf(fd, "NP\n%g %g MT\n", xx, yy);
else fprintf(fd, "%g %g LT\n", xx, yy);
bezier = flags && (points > 2);
if(bezier) {
ps_drawbezier(x, y, points);
} else {
for(i=0;i<points; ++i) {
xx = X_TO_PS(x[i]);
yy = Y_TO_PS(y[i]);
if(i==0) fprintf(fd, "NP\n%g %g MT\n", xx, yy);
else fprintf(fd, "%g %g LT\n", xx, yy);
}
}
if(xctx->fill_pattern && xctx->fill_type[c] && poly_fill) {
fprintf(fd, "GS C F GR S\n");
} else {
fprintf(fd, "S\n");
}
if(dash) {
fprintf(fd, "[] 0 setdash\n");
}
@ -782,7 +833,7 @@ static void ps_draw_symbol(int n,int layer, int what, short tmp_flip, short rot,
xRect rect;
xText text;
xArc arc;
xPoly polygon;
xPoly *polygon;
xSymbol *symptr;
char *textfont;
@ -847,17 +898,18 @@ static void ps_draw_symbol(int n,int layer, int what, short tmp_flip, short rot,
}
for(j=0;j< (xctx->inst[n].ptr+ xctx->sym)->polygons[layer]; ++j)
{
polygon = ((xctx->inst[n].ptr+ xctx->sym)->poly[layer])[j];
polygon = &((xctx->inst[n].ptr+ xctx->sym)->poly[layer])[j];
{ /* scope block so we declare some auxiliary arrays for coord transforms. 20171115 */
int k;
double *x = my_malloc(_ALLOC_ID_, sizeof(double) * polygon.points);
double *y = my_malloc(_ALLOC_ID_, sizeof(double) * polygon.points);
for(k=0;k<polygon.points; ++k) {
ROTATION(rot, flip, 0.0,0.0,polygon.x[k],polygon.y[k],x[k],y[k]);
int k, bezier;
double *x = my_malloc(_ALLOC_ID_, sizeof(double) * polygon->points);
double *y = my_malloc(_ALLOC_ID_, sizeof(double) * polygon->points);
for(k=0;k<polygon->points; ++k) {
ROTATION(rot, flip, 0.0,0.0,polygon->x[k],polygon->y[k],x[k],y[k]);
x[k]+= x0;
y[k] += y0;
}
ps_drawpolygon(layer, NOW, x, y, polygon.points, polygon.fill, polygon.dash);
bezier = !strboolcmp(get_tok_value(polygon->prop_ptr, "bezier", 0), "true");
ps_drawpolygon(layer, NOW, x, y, polygon->points, polygon->fill, polygon->dash, bezier);
my_free(_ALLOC_ID_, &x);
my_free(_ALLOC_ID_, &y);
}
@ -1269,8 +1321,9 @@ void create_ps(char **psfile, int what, int fullzoom, int eps)
xctx->arc[c][i].r, xctx->arc[c][i].a, xctx->arc[c][i].b, xctx->arc[c][i].dash);
}
for(i=0;i<xctx->polygons[c]; ++i) {
int bezier = !strboolcmp(get_tok_value(xctx->poly[c][i].prop_ptr, "bezier", 0), "true");
ps_drawpolygon(c, NOW, xctx->poly[c][i].x, xctx->poly[c][i].y, xctx->poly[c][i].points,
xctx->poly[c][i].fill, xctx->poly[c][i].dash);
xctx->poly[c][i].fill, xctx->poly[c][i].dash, bezier);
}
dbg(1, "create_ps(): starting drawing symbols on layer %d\n", c);
} /* for(c=0;c<cadlayers; ++c) */

View File

@ -66,11 +66,61 @@ static void svg_xfillrectangle(int layer, double x1, double y1, double x2, doubl
fprintf(fd,"d=\"M%g %gL%g %gL%g %gL%g %gL%g %gz\"/>\n", x1, y1, x2, y1, x2, y2, x1, y2, x1, y1);
}
static void svg_drawpolygon(int c, int what, double *x, double *y, int points, int fill, int dash)
static void svg_drawbezier(double *x, double *y, int points)
{
const double bez_steps = 1.0/32.0; /* divide the t = [0,1] interval into 32 steps */
int b, i;
double t;
double xp, yp;
double x0, x1, x2, y0, y1, y2;
i = 0;
fprintf(fd, "d=\"");
for(b = 0; b < points - 2; b++) {
if(points == 3) { /* 3 points: only one bezier */
x0 = x[0];
y0 = y[0];
x1 = x[1];
y1 = y[1];
x2 = x[2];
y2 = y[2];
} else if(b == points - 3) { /* last bezier */
x0 = (x[points - 3] + x[points - 2]) / 2.0;
y0 = (y[points - 3] + y[points - 2]) / 2.0;
x1 = x[points - 2];
y1 = y[points - 2];
x2 = x[points - 1];
y2 = y[points - 1];
} else if(b == 0) { /* first bezier */
x0 = x[0];
y0 = y[0];
x1 = x[1];
y1 = y[1];
x2 = (x[1] + x[2]) / 2.0;
y2 = (y[1] + y[2]) / 2.0;
} else { /* beziers in the middle */
x0 = (x[b] + x[b + 1]) / 2.0;
y0 = (y[b] + y[b + 1]) / 2.0;
x1 = x[b + 1];
y1 = y[b + 1];
x2 = (x[b + 1] + x[b + 2]) / 2.0;
y2 = (y[b + 1] + y[b + 2]) / 2.0;
}
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==0) fprintf(fd, "M%g %g", X_TO_SVG(xp), Y_TO_SVG(yp));
else fprintf(fd, "L%g %g", X_TO_SVG(xp), Y_TO_SVG(yp));
i++;
}
}
}
static void svg_drawpolygon(int c, int what, double *x, double *y, int points, int fill, int dash, int flags)
{
double x1,y1,x2,y2;
double xx, yy;
int i;
int bezier, i;
polygon_bbox(x, y, points, &x1,&y1,&x2,&y2);
x1=X_TO_SVG(x1);
y1=Y_TO_SVG(y1);
@ -84,12 +134,17 @@ static void svg_drawpolygon(int c, int what, double *x, double *y, int points, i
if(!fill) {
fprintf(fd,"style=\"fill:none;\" ");
}
fprintf(fd, "d=\"");
for(i=0;i<points; ++i) {
xx = X_TO_SVG(x[i]);
yy = Y_TO_SVG(y[i]);
if(i==0) fprintf(fd, "M%g %g", xx, yy);
else fprintf(fd, "L%g %g", xx, yy);
bezier = flags && (points > 2);
if(bezier) {
svg_drawbezier(x, y, points);
} else {
fprintf(fd, "d=\"");
for(i=0;i<points; ++i) {
xx = X_TO_SVG(x[i]);
yy = Y_TO_SVG(y[i]);
if(i==0) fprintf(fd, "M%g %g", xx, yy);
else fprintf(fd, "L%g %g", xx, yy);
}
}
/* fprintf(fd, "z\"/>\n"); */
fprintf(fd, "\"/>\n");
@ -443,7 +498,7 @@ static void svg_draw_symbol(int c, int n,int layer,short tmp_flip, short rot,
xRect *rect;
xText text;
xArc arc;
xPoly polygon;
xPoly *polygon;
xSymbol *symptr;
char *textfont;
@ -486,17 +541,18 @@ static void svg_draw_symbol(int c, int n,int layer,short tmp_flip, short rot,
svg_drawline(c, line.bus, x0+x1, y0+y1, x0+x2, y0+y2, line.dash);
}
for(j=0;j< symptr->polygons[layer]; ++j) {
polygon = (symptr->poly[layer])[j];
polygon =&(symptr->poly[layer])[j];
{ /* scope block so we declare some auxiliary arrays for coord transforms. 20171115 */
int k;
double *x = my_malloc(_ALLOC_ID_, sizeof(double) * polygon.points);
double *y = my_malloc(_ALLOC_ID_, sizeof(double) * polygon.points);
for(k=0;k<polygon.points; ++k) {
ROTATION(rot, flip, 0.0,0.0,polygon.x[k],polygon.y[k],x[k],y[k]);
int k, bezier;
double *x = my_malloc(_ALLOC_ID_, sizeof(double) * polygon->points);
double *y = my_malloc(_ALLOC_ID_, sizeof(double) * polygon->points);
for(k=0;k<polygon->points; ++k) {
ROTATION(rot, flip, 0.0,0.0,polygon->x[k],polygon->y[k],x[k],y[k]);
x[k]+= x0;
y[k] += y0;
}
svg_drawpolygon(c, NOW, x, y, polygon.points, polygon.fill, polygon.dash);
bezier = !strboolcmp(get_tok_value(polygon->prop_ptr, "bezier", 0), "true");
svg_drawpolygon(c, NOW, x, y, polygon->points, polygon->fill, polygon->dash, bezier);
my_free(_ALLOC_ID_, &x);
my_free(_ALLOC_ID_, &y);
}
@ -841,8 +897,9 @@ void svg_draw(void)
xctx->arc[c][i].a, xctx->arc[c][i].b, xctx->arc[c][i].dash);
}
for(i=0;i<xctx->polygons[c]; ++i) {
int bezier = !strboolcmp(get_tok_value(xctx->poly[c][i].prop_ptr, "bezier", 0), "true");
svg_drawpolygon(c, NOW, xctx->poly[c][i].x, xctx->poly[c][i].y, xctx->poly[c][i].points,
xctx->poly[c][i].fill, xctx->poly[c][i].dash);
xctx->poly[c][i].fill, xctx->poly[c][i].dash, bezier);
}
for(i=0;i<xctx->instances; ++i) {
color = c;