From 8da982999af08312ef23c0c002582b5cee85c677 Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Fri, 28 Nov 2025 13:31:45 +0100 Subject: [PATCH] allow arbitrary widths (with ex. bus=3.5 attr) for arcs / circles --- src/actions.c | 2 +- src/draw.c | 45 ++++++++++++++++++++++++++++++++------------- src/editprop.c | 12 +++++++++--- src/hilight.c | 2 +- src/paste.c | 1 + src/psprint.c | 23 ++++++++++++++++++----- src/save.c | 2 ++ src/store.c | 2 +- src/svgdraw.c | 39 +++++++++++++++++++++++++++------------ src/xschem.h | 4 +++- 10 files changed, 95 insertions(+), 37 deletions(-) diff --git a/src/actions.c b/src/actions.c index 49a9a18d..3fc98697 100644 --- a/src/actions.c +++ b/src/actions.c @@ -3336,7 +3336,7 @@ void new_arc(int what, double sweep, double mousex_snap, double mousey_snap) if(xctx->nl_sweep_angle==360.) xctx->nl_b=360.; if(xctx->nl_r>0.) { xctx->push_undo(); - drawarc(xctx->rectcolor, NOW, xctx->nl_x, xctx->nl_y, xctx->nl_r, xctx->nl_a, xctx->nl_b, 0, 0); + drawarc(xctx->rectcolor, NOW, xctx->nl_x, xctx->nl_y, xctx->nl_r, xctx->nl_a, xctx->nl_b, 0, 0.0, 0); store_arc(-1, xctx->nl_x, xctx->nl_y, xctx->nl_r, xctx->nl_a, xctx->nl_b, xctx->rectcolor, 0, NULL); set_modify(1); } diff --git a/src/draw.c b/src/draw.c index 0470c195..5981d2da 100644 --- a/src/draw.c +++ b/src/draw.c @@ -770,7 +770,7 @@ void draw_symbol(int what,int c, int n,int layer,short tmp_flip, short rot, angle = fmod(angle, 360.); if(angle<0.) angle+=360.; ROTATION(rot, flip, 0.0, 0.0,arc->x,arc->y,x1,y1); - drawarc(c,what, x0+x1, y0+y1, arc->r, angle, arc->b, arc->fill, dash); + drawarc(c,what, x0+x1, y0+y1, arc->r, angle, arc->b, arc->fill, arc->bus, dash); } } /* if(!hide) */ @@ -1714,13 +1714,24 @@ void filledarc(int c, int what, double x, double y, double r, double a, double b } } -void drawarc(int c, int what, double x, double y, double r, double a, double b, int arc_fill, int dash) +void drawarc(int c, int what, double x, double y, double r, double a, double b, int arc_fill, double bus, int dash) { static int i=0; static XArc xarc[CADDRAWBUFFERSIZE]; double x1, y1, x2, y2; /* arc bbox */ double xx1, yy1, xx2, yy2; /* complete circle bbox in screen coords */ GC gc; + int width; + + if(bus == -1.0) { + what = NOW; + width = INT_BUS_WIDTH(xctx->lw); + } else if(bus > 0.0) { + what = NOW; + width = (int) (bus * xctx->mooz); + } else { + width = XLINEWIDTH(xctx->lw); + } if(arc_fill || dash) what = NOW; @@ -1769,12 +1780,19 @@ void drawarc(int c, int what, double x, double y, double r, double a, double b, y2=Y_TO_SCREEN(y2); if( rectclip(xctx->areax1,xctx->areay1,xctx->areax2,xctx->areay2,&x1,&y1,&x2,&y2) ) { - if(dash) { - char dash_arr[2]; - dash_arr[0] = dash_arr[1] = (char)dash; - XSetDashes(display, xctx->gc[c], 0, dash_arr, 1); - XSetLineAttributes (display, xctx->gc[c], XLINEWIDTH(xctx->lw), xDashType, xCap, xJoin); - } + + if(dash) { + char dash_arr[2]; + dash_arr[0] = dash_arr[1] = (char)dash; + XSetDashes(display, xctx->gc[c], 0, dash_arr, 1); + } + if(dash) { + XSetLineAttributes (display, xctx->gc[c], width, xDashType, xCap, xJoin); + } else if(bus > 0.0) { + XSetLineAttributes (display, xctx->gc[c], width, LineSolid, CapProjecting, JoinMiter); + } else if(bus == -1.0) { + XSetLineAttributes (display, xctx->gc[c], width, LineSolid, LINECAP, LINEJOIN); + } if(xctx->draw_window) { XDrawArc(display, xctx->window, xctx->gc[c], (int)xx1, (int)yy1, @@ -1798,9 +1816,10 @@ void drawarc(int c, int what, double x, double y, double r, double a, double b, (int)(xx2-xx1), (int)(yy2-yy1), (int)(a*64), (int)(b*64)); } } - if(dash) { - XSetLineAttributes (display, xctx->gc[c], XLINEWIDTH(xctx->lw) ,LineSolid, LINECAP , LINEJOIN); + if(dash || bus > 0.0) { + XSetLineAttributes (display, xctx->gc[c], XLINEWIDTH(xctx->lw), LineSolid, LINECAP, LINEJOIN); } + } } else if((what & END) && i) @@ -2100,7 +2119,7 @@ void drawpolygon(int c, int what, double *x, double *y, int points, int poly_fil XSetLineAttributes (display, xctx->gc[c], width, xDashType, xCap, xJoin); } else if(bus > 0.0) { XSetLineAttributes (display, xctx->gc[c], width, LineSolid, CapProjecting, JoinMiter); - } else { + } else if(bus == -1.0) { XSetLineAttributes (display, xctx->gc[c], width, LineSolid, LINECAP, LINEJOIN); } @@ -5174,7 +5193,7 @@ void draw(void) if(draw_layer && xctx->enable_layer[c]) for(i=0;iarcs[c]; ++i) { xArc **arc = xctx->arc; drawarc(cc, ADD, arc[c][i].x, arc[c][i].y, arc[c][i].r, arc[c][i].a, arc[c][i].b, - arc[c][i].fill, arc[c][i].dash); + arc[c][i].fill, arc[c][i].bus, arc[c][i].dash); } if(draw_layer && xctx->enable_layer[c]) for(i=0;ipolygons[c]; ++i) { int bezier; @@ -5213,7 +5232,7 @@ void draw(void) } } filledrect(cc, END, 0.0, 0.0, 0.0, 0.0, 2, -1, -1); /* fill parameter must be 2! */ - drawarc(cc, END, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0); + drawarc(cc, END, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0.0, 0); drawrect(cc, END, 0.0, 0.0, 0.0, 0.0, 0, -1, -1); drawline(cc, END, 0.0, 0.0, 0.0, 0.0, 0, NULL); } diff --git a/src/editprop.c b/src/editprop.c index 9b6c52bd..fa4322e6 100644 --- a/src/editprop.c +++ b/src/editprop.c @@ -1224,6 +1224,8 @@ static int edit_arc_property(void) char *oldprop = NULL; const char *dash, *fill_ptr; int preserve, modified = 0; + double bus = 0.0, oldbus = 0.0; + double width; my_strdup(_ALLOC_ID_, &oldprop, xctx->arc[xctx->sel_array[0].col][xctx->sel_array[0].n].prop_ptr); if(oldprop && oldprop[0]) { @@ -1243,7 +1245,7 @@ static int edit_arc_property(void) i = xctx->sel_array[ii].n; c = xctx->sel_array[ii].col; - + oldbus = xctx->arc[c][i].bus; if(oldprop && preserve == 1) { set_different_token(&xctx->arc[c][i].prop_ptr, (char *) tclgetvar("tctx::retval"), oldprop); @@ -1266,14 +1268,18 @@ static int edit_arc_property(void) } else xctx->arc[c][i].dash = 0; + bus = xctx->arc[c][i].bus = get_attr_val(get_tok_value(xctx->arc[c][i].prop_ptr,"bus",0)); + if(bus > 0.0) width = bus / 2.0; + else width = xctx->cadhalfdotsize; + if(oldbus / 2.0 > width) width = oldbus / 2.0; - if(old_fill != xctx->arc[c][i].fill || old_dash != xctx->arc[c][i].dash) { + if(oldbus != bus || old_fill != xctx->arc[c][i].fill || old_dash != xctx->arc[c][i].dash) { if(!drw) { bbox(START,0.0,0.0,0.0,0.0); drw = 1; } arc_bbox(xctx->arc[c][i].x, xctx->arc[c][i].y, xctx->arc[c][i].r, 0, 360, &x1,&y1,&x2,&y2); - bbox(ADD, x1, y1, x2, y2); + bbox(ADD, x1 - width, y1 - width, x2 + width, y2 + width); } } if(drw) { diff --git a/src/hilight.c b/src/hilight.c index 9dfcdddd..6cfed001 100644 --- a/src/hilight.c +++ b/src/hilight.c @@ -2268,7 +2268,7 @@ void draw_hilight_net(int on_window) if(c == cadlayers - 1) draw_symbol(ADD, col, i, c + 1, 0, 0, 0.0, 0.0); /* draw texts */ } filledrect(col, END, 0.0, 0.0, 0.0, 0.0, 2, -1, -1); /* last parameter must be 2! */ - drawarc(col, END, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0); + drawarc(col, END, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0.0, 0); drawrect(col, END, 0.0, 0.0, 0.0, 0.0, 0, -1, -1); drawline(col, END, 0.0, 0.0, 0.0, 0.0, 0, NULL); } diff --git a/src/paste.c b/src/paste.c index 8889f329..c3bbe732 100644 --- a/src/paste.c +++ b/src/paste.c @@ -171,6 +171,7 @@ static void merge_arc(FILE *fd) } else { ptr[i].dash = 0; } + ptr[i].bus = get_attr_val(get_tok_value(ptr[i].prop_ptr,"bus",0)); select_arc(c,i, SELECTED, 1, 1); xctx->arcs[c]++; diff --git a/src/psprint.c b/src/psprint.c index 0c2a5265..87e25f9a 100644 --- a/src/psprint.c +++ b/src/psprint.c @@ -612,11 +612,16 @@ static void ps_filledrect(int gc, double rectx1,double recty1,double rectx2,doub } } -static void ps_drawarc(int gc, int fillarc, double x,double y,double r,double a, double b, int dash) +static void ps_drawarc(int gc, int fillarc, double x,double y,double r,double a, double b, double bus, int dash) { double xx,yy,rr; double x1, y1, x2, y2; double psdash; + double width; + + if(bus == -1.0) width = BUS_WIDTH * xctx->lw; + else if(bus > 0.0) width = bus * xctx->mooz; + else width = -1.0; if(b < 0.0) { a = a + b; @@ -635,13 +640,21 @@ static void ps_drawarc(int gc, int fillarc, double x,double y,double r,double a, if( rectclip(xctx->areax1,xctx->areay1,xctx->areax2,xctx->areay2,&x1,&y1,&x2,&y2) ) { psdash = dash / xctx->zoom; + if(bus > 0.0) { + fprintf(fd, "0 setlinejoin 2 setlinecap\n"); + } if(dash) { fprintf(fd, "[%g %g] 0 setdash\n", psdash, psdash); } + if(width >= 0.0) set_lw(1.2 * width); ps_xdrawarc(gc, fillarc, xx, yy, rr, a, b); if(dash) { fprintf(fd, "[] 0 setdash\n"); } + if(width >= 0.0) set_lw(xctx->lw); + if(bus > 0.0) { + fprintf(fd, "1 setlinejoin 1 setlinecap\n"); + } } } @@ -1077,7 +1090,7 @@ static void ps_draw_symbol(int c, int n,int layer, int what, short tmp_flip, sho angle = fmod(angle, 360.); if(angle<0.) angle+=360.; ROTATION(rot, flip, 0.0,0.0,arc->x,arc->y,x1,y1); - ps_drawarc(c, arc->fill, x0+x1, y0+y1, arc->r, angle, arc->b, dash); + ps_drawarc(c, arc->fill, x0+x1, y0+y1, arc->r, angle, arc->b, arc->bus, dash); } } /* if(!hide) */ @@ -1487,7 +1500,7 @@ void create_ps(char **psfile, int what, int fullzoom, int eps) for(i=0;iarcs[c]; ++i) { ps_drawarc(c, xctx->arc[c][i].fill, xctx->arc[c][i].x, xctx->arc[c][i].y, - xctx->arc[c][i].r, xctx->arc[c][i].a, xctx->arc[c][i].b, xctx->arc[c][i].dash); + xctx->arc[c][i].r, xctx->arc[c][i].a, xctx->arc[c][i].b, xctx->arc[c][i].bus, xctx->arc[c][i].dash); } for(i=0;ipolygons[c]; ++i) { int bezier = !strboolcmp(get_tok_value(xctx->poly[c][i].prop_ptr, "bezier", 0), "true"); @@ -1537,10 +1550,10 @@ void create_ps(char **psfile, int what, int fullzoom, int eps) } i = wireptr->n; if( xctx->wire[i].end1 >1 ) { - ps_drawarc(WIRELAYER, 1, xctx->wire[i].x1, xctx->wire[i].y1, xctx->cadhalfdotsize, 0, 360, 0); + ps_drawarc(WIRELAYER, 1, xctx->wire[i].x1, xctx->wire[i].y1, xctx->cadhalfdotsize, 0, 360, 0.0, 0); } if( xctx->wire[i].end2 >1 ) { - ps_drawarc(WIRELAYER, 1, xctx->wire[i].x2, xctx->wire[i].y2, xctx->cadhalfdotsize, 0, 360, 0); + ps_drawarc(WIRELAYER, 1, xctx->wire[i].x2, xctx->wire[i].y2, xctx->cadhalfdotsize, 0, 360, 0.0, 0); } } } diff --git a/src/save.c b/src/save.c index ea25062c..70a1e94f 100644 --- a/src/save.c +++ b/src/save.c @@ -2968,6 +2968,7 @@ static void load_arc(FILE *fd) } else { ptr[i].dash = 0; } + ptr[i].bus = get_attr_val(get_tok_value(ptr[i].prop_ptr, "bus", 0)); xctx->arcs[c]++; } @@ -4584,6 +4585,7 @@ int load_sym_def(const char *name, FILE *embed_fd) aa[c][i].dash = (short)(d >= 0 ? d : 0); } else aa[c][i].dash = 0; + aa[c][i].bus = get_attr_val(get_tok_value(aa[c][i].prop_ptr,"bus", 0)); aa[c][i].sel = 0; dbg(2, "l_s_d(): loaded arc: ptr=%lx\n", (unsigned long)aa[c]); lasta[c]++; diff --git a/src/store.c b/src/store.c index 102020f4..ee20a33b 100644 --- a/src/store.c +++ b/src/store.c @@ -167,7 +167,7 @@ void store_arc(int pos, double x, double y, double r, double a, double b, xctx->arc[rectc][n].dash = (char) (d >= 0 ? d : 0); } else xctx->arc[rectc][n].dash = 0; - + xctx->arc[rectc][n].bus = get_attr_val(get_tok_value(xctx->arc[rectc][n].prop_ptr,"bus",0)); xctx->arcs[rectc]++; } diff --git a/src/svgdraw.c b/src/svgdraw.c index 3c9d694d..43d27b15 100644 --- a/src/svgdraw.c +++ b/src/svgdraw.c @@ -240,12 +240,17 @@ static void svg_drawcircle(int gc, int fillarc, double x,double y,double r,doubl } } -static void svg_drawarc(int gc, int fillarc, double x,double y,double r,double a, double b, int dash) +static void svg_drawarc(int gc, int fillarc, double x,double y,double r,double a, double b, double bus, int dash) { double xx,yy,rr; double x1, y1, x2, y2; double xx1, yy1, xx2, yy2; int fs, fa; + double width; + + if(bus == -1.0) width = BUS_WIDTH * svg_linew; + else if(bus > 0.0) width = bus * xctx->mooz; + else width = -1.0; if(b < 0.0) { a = a + b; @@ -278,16 +283,26 @@ static void svg_drawarc(int gc, int fillarc, double x,double y,double r,double a fs = b > 0 ? 0 : 1; fprintf(fd,"zoom, 0.8*dash/xctx->zoom); - if(fillarc == 0) { - fprintf(fd,"style=\"fill:none;\" "); - fprintf(fd, "d=\"M%g %g A%g %g 0 %d %d %g %g\"/>\n", xx1, yy1, rr, rr, fa, fs, xx2, yy2); - } else if(fillarc == 2) { - fprintf(fd, "style=\"fill-opacity:1.0;\" "); - fprintf(fd, "d=\"M%g %g A%g %g 0 %d %d %g %gL%g %gz\"/>\n", xx1, yy1, rr, rr, fa, fs, xx2, yy2, xx, yy); - } else { - fprintf(fd, "d=\"M%g %g A%g %g 0 %d %d %g %gL%g %gz\"/>\n", xx1, yy1, rr, rr, fa, fs, xx2, yy2, xx, yy); - } + if(width >= 0.0 || fillarc == 0 || fillarc == 2) { + if(width > 0) fprintf(fd, "style=\"stroke-width:%g; ", width); + else fprintf(fd, "style=\""); + if(bus > 0.0) { + fprintf(fd, " stroke-linecap:square;\n"); + fprintf(fd, " stroke-linejoin:miter;\n"); + } + if(fillarc == 0) { + fprintf(fd,"fill:none;\" "); + fprintf(fd, "d=\"M%g %g A%g %g 0 %d %d %g %g\"/>\n", xx1, yy1, rr, rr, fa, fs, xx2, yy2); + } else if(fillarc == 2) { + fprintf(fd, "fill-opacity:1.0;\" "); + fprintf(fd, "d=\"M%g %g A%g %g 0 %d %d %g %gL%g %gz\"/>\n", xx1, yy1, rr, rr, fa, fs, xx2, yy2, xx, yy); + } else { + fprintf(fd, "d=\"M%g %g A%g %g 0 %d %d %g %gL%g %gz\"/>\n", xx1, yy1, rr, rr, fa, fs, xx2, yy2, xx, yy); + } + } + } } } @@ -754,7 +769,7 @@ static void svg_draw_symbol(int c, int n,int layer,short tmp_flip, short rot, angle = fmod(angle, 360.); if(angle<0.) angle+=360.; ROTATION(rot, flip, 0.0,0.0,arc.x,arc.y,x1,y1); - svg_drawarc(c, arc.fill, x0+x1, y0+y1, arc.r, angle, arc.b, dash); + svg_drawarc(c, arc.fill, x0+x1, y0+y1, arc.r, angle, arc.b, arc.bus, dash); } } /* if(!hide) */ @@ -1080,7 +1095,7 @@ void svg_draw(void) for(i=0;iarcs[c]; ++i) { svg_drawarc(c, xctx->arc[c][i].fill, xctx->arc[c][i].x, xctx->arc[c][i].y, xctx->arc[c][i].r, - xctx->arc[c][i].a, xctx->arc[c][i].b, xctx->arc[c][i].dash); + xctx->arc[c][i].a, xctx->arc[c][i].b, xctx->arc[c][i].bus, xctx->arc[c][i].dash); } for(i=0;ipolygons[c]; ++i) { int bezier = !strboolcmp(get_tok_value(xctx->poly[c][i].prop_ptr, "bezier", 0), "true"); diff --git a/src/xschem.h b/src/xschem.h index 04c66878..b643b668 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -533,6 +533,7 @@ typedef struct char *prop_ptr; short fill; short dash; + double bus; } xArc; typedef struct @@ -1459,7 +1460,8 @@ extern void fix_restore_rect(double x1, double y1, double x2, double y2); extern void drawtemprect(GC gc, int what, double rectx1,double recty1, double rectx2,double recty2); extern void drawtemparc(GC gc, int what, double x, double y, double r, double a, double b); -extern void drawarc(int c, int what, double x, double y, double r, double a, double b, int arc_fill, int dash); +extern void drawarc(int c, int what, double x, double y, double r, double a, double b, + int arc_fill, double bus, int dash); extern void filledarc(int c, int what, double x, double y, double r, double a, double b); extern void drawtemppolygon(GC gc, int what, double *x, double *y, int points, int flags); extern void drawbezier(Drawable w, GC gc, int c, double *x, double *y, int points, int fill);