From b628d66e8fb1f5545c5b56ae54727f9da3cd0dc7 Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Sat, 29 Nov 2025 14:36:15 +0100 Subject: [PATCH] arbitrary box widths (and some fixes on wire widths) --- src/actions.c | 2 +- src/draw.c | 71 +++++++++++++++++++----------------- src/editprop.c | 11 +++++- src/hilight.c | 2 +- src/paste.c | 10 ++--- src/psprint.c | 57 +++++++++++++++++++++++------ src/save.c | 2 + src/scheduler.c | 4 +- src/store.c | 5 ++- src/svgdraw.c | 97 +++++++++++++++++++++++++++++++++++++------------ src/xschem.h | 3 +- 11 files changed, 182 insertions(+), 82 deletions(-) diff --git a/src/actions.c b/src/actions.c index 4d86011f..8bc16de6 100644 --- a/src/actions.c +++ b/src/actions.c @@ -3455,7 +3455,7 @@ void new_rect(int what, double mousex_snap, double mousey_snap) int save_draw; RECTORDER(xctx->nl_x1,xctx->nl_y1,xctx->nl_x2,xctx->nl_y2); xctx->push_undo(); - drawrect(xctx->rectcolor, NOW, xctx->nl_x1,xctx->nl_y1,xctx->nl_x2,xctx->nl_y2, 0, -1, -1); + drawrect(xctx->rectcolor, NOW, xctx->nl_x1,xctx->nl_y1,xctx->nl_x2,xctx->nl_y2, 0.0, 0, -1, -1); save_draw = xctx->draw_window; xctx->draw_window = 1; /* draw fill pattern even in xcopyarea mode */ diff --git a/src/draw.c b/src/draw.c index ca3d000f..2aed8cc7 100644 --- a/src/draw.c +++ b/src/draw.c @@ -698,7 +698,8 @@ void draw_symbol(int what,int c, int n,int layer,short tmp_flip, short rot, } else if(!xctx->only_probes && (xctx->inst[n].x2 - xctx->inst[n].x1) * xctx->mooz < 3 && (xctx->inst[n].y2 - xctx->inst[n].y1) * xctx->mooz < 3) { - drawrect(SYMLAYER, NOW, xctx->inst[n].xx1, xctx->inst[n].yy1, xctx->inst[n].xx2, xctx->inst[n].yy2, 0, -1, -1); + drawrect(SYMLAYER, NOW, xctx->inst[n].xx1, xctx->inst[n].yy1, xctx->inst[n].xx2, xctx->inst[n].yy2, + 0.0, 0, -1, -1); xctx->inst[n].flags|=1; return; } @@ -707,7 +708,8 @@ void draw_symbol(int what,int c, int n,int layer,short tmp_flip, short rot, } if(hide) { int color = (disabled==1) ? GRIDLAYER : (disabled == 2) ? PINLAYER : SYMLAYER; - drawrect(color, NOW, xctx->inst[n].xx1, xctx->inst[n].yy1, xctx->inst[n].xx2, xctx->inst[n].yy2, 2, -1, -1); + drawrect(color, NOW, xctx->inst[n].xx1, xctx->inst[n].yy1, xctx->inst[n].xx2, xctx->inst[n].yy2, + 0.0, 2, -1, -1); } } else if(xctx->inst[n].flags&1) { dbg(2, "draw_symbol(): skipping inst %d\n", n); @@ -812,7 +814,7 @@ void draw_symbol(int what,int c, int n,int layer,short tmp_flip, short rot, } } RECTORDER(x1,y1,x2,y2); - drawrect(c,what, x0+x1, y0+y1, x0+x2, y0+y2, dash, ellipse_a, ellipse_b); + drawrect(c,what, x0+x1, y0+y1, x0+x2, y0+y2, rect->bus, dash, ellipse_a, ellipse_b); if(rect->fill) filledrect(c,what, x0+x1, y0+y1, x0+x2, y0+y2, rect->fill, ellipse_a, ellipse_b); } @@ -886,7 +888,7 @@ void draw_symbol(int what,int c, int n,int layer,short tmp_flip, short rot, x0+x1, y0+y1, xscale, yscale); my_free(_ALLOC_ID_, &txtptr); #if HAS_CAIRO!=1 - drawrect(textlayer, END, 0.0, 0.0, 0.0, 0.0, 0, -1, -1); + drawrect(textlayer, END, 0.0, 0.0, 0.0, 0.0, 0.0, 0, -1, -1); drawline(textlayer, END, 0.0, 0.0, 0.0, 0.0, 0.0, 0, NULL); #endif #if HAS_CAIRO==1 @@ -1393,25 +1395,15 @@ void drawline(int c, int what, double linex1, double liney1, double linex2, doub if( clip(&x1,&y1,&x2,&y2) ) { if(dash) { - dash_arr[0] = dash_arr[1] = (char) dash; + 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); + 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(dash) { - dash_arr[0] = dash_arr[1] = (char)dash; - XSetDashes(display, xctx->gc[c], 0, dash_arr, 1); - 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) XDrawLine(display, xctx->window, xctx->gc[c], (int)x1, (int)y1, (int)x2, (int)y2); if(xctx->draw_pixmap) XDrawLine(display, xctx->save_pixmap, xctx->gc[c], (int)x1, (int)y1, (int)x2, (int)y2); @@ -1813,8 +1805,6 @@ void drawarc(int c, int what, double x, double y, double r, double a, double b, 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); @@ -2142,8 +2132,6 @@ void drawpolygon(int c, int what, double *x, double *y, int points, int poly_fil 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); @@ -2227,7 +2215,7 @@ void drawtemppolygon(GC gc, int what, double *x, double *y, int points, int flag } } -void drawrect(int c, int what, double rectx1,double recty1,double rectx2,double recty2, int dash, +void drawrect(int c, int what, double rectx1,double recty1,double rectx2,double recty2, double bus, int dash, int e_a, int e_b) { static int i=0; @@ -2235,9 +2223,21 @@ void drawrect(int c, int what, double rectx1,double recty1,double rectx2,double double x1,y1,x2,y2; double xx1,yy1,xx2,yy2; char dash_arr[2]; + int width; if(!has_x) return; + + 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(dash) what = NOW; + if(e_a != -1) what = NOW; /* ellipse */ if(what & NOW) { @@ -2250,8 +2250,13 @@ void drawrect(int c, int what, double rectx1,double recty1,double rectx2,double if(dash) { 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); - } + 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) { if(e_a != -1) { XDrawArc(display, xctx->window, xctx->gc[c], (int)xx1, (int)yy1, @@ -2276,8 +2281,8 @@ void drawrect(int c, int what, double rectx1,double recty1,double rectx2,double (unsigned int)y2 - (unsigned int)y1); } } - 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); } } } @@ -3100,7 +3105,7 @@ static void draw_graph_grid(Graph_ctx *gr, void *ct) /* background */ filledrect(0, NOW, gr->rx1, gr->ry1, gr->rx2, gr->ry2, 2, -1, -1); /* graph bounding box */ - drawrect(GRIDLAYER, NOW, gr->rx1, gr->ry1, gr->rx2, gr->ry2, 2, -1, -1); + drawrect(GRIDLAYER, NOW, gr->rx1, gr->ry1, gr->rx2, gr->ry2, 0.0, 2, -1, -1); bbox(START, 0.0, 0.0, 0.0, 0.0); bbox(ADD, gr->rx1, gr->ry1, gr->rx2, gr->ry2); @@ -5214,7 +5219,7 @@ void draw(void) if(c != GRIDLAYER || !(r->flags & 1) ) #endif { - drawrect(cc, ADD, r->x1, r->y1, r->x2, r->y2, r->dash, r->ellipse_a, r->ellipse_b); + drawrect(cc, ADD, r->x1, r->y1, r->x2, r->y2, r->bus, r->dash, r->ellipse_a, r->ellipse_b); if(r->fill) filledrect(cc, ADD, r->x1, r->y1, r->x2, r->y2, r->fill, r->ellipse_a, r->ellipse_b); } } @@ -5261,7 +5266,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.0, 0); - drawrect(cc, END, 0.0, 0.0, 0.0, 0.0, 0, -1, -1); + drawrect(cc, END, 0.0, 0.0, 0.0, 0.0, 0.0, 0, -1, -1); drawline(cc, END, 0.0, 0.0, 0.0, 0.0, 0.0, 0, NULL); } cc = WIRELAYER; if(xctx->only_probes) cc = GRIDLAYER; @@ -5334,7 +5339,7 @@ void draw(void) } #endif #if HAS_CAIRO!=1 - drawrect(textlayer, END, 0.0, 0.0, 0.0, 0.0, 0, -1, -1); + drawrect(textlayer, END, 0.0, 0.0, 0.0, 0.0, 0.0, 0, -1, -1); drawline(textlayer, END, 0.0, 0.0, 0.0, 0.0, 0.0, 0, NULL); #endif } /* for(i=0;itexts; ++i) */ diff --git a/src/editprop.c b/src/editprop.c index c2a7bc86..9c357b54 100644 --- a/src/editprop.c +++ b/src/editprop.c @@ -1013,7 +1013,8 @@ static int edit_rect_property(int x) const char *attr; int preserve, modified = 0; char *oldprop=NULL; - + double bus = 0.0, oldbus = 0.0; + double width; if(x < 0 || x > 2) { fprintf(errfp, "edit_rect_property() : unknown parameter x=%d\n",x); return 0; @@ -1039,12 +1040,17 @@ static int edit_rect_property(int x) if(xctx->sel_array[i].type != xRECT) continue; c = xctx->sel_array[i].col; n = xctx->sel_array[i].n; + oldbus = xctx->rect[c][n].bus; if(oldprop && preserve == 1) { set_different_token(&xctx->rect[c][n].prop_ptr, (char *) tclgetvar("tctx::retval"), oldprop); } else { my_strdup(_ALLOC_ID_, &xctx->rect[c][n].prop_ptr, (char *) tclgetvar("tctx::retval")); } + bus = xctx->rect[c][n].bus = get_attr_val(get_tok_value(xctx->rect[c][n].prop_ptr,"bus",0)); + if(bus > 0.0) width = bus / 2.0; + else width = INT_BUS_WIDTH(xctx->lw) / 2.0; + if(oldbus / 2.0 > width) width = oldbus / 2.0; set_rect_flags(&xctx->rect[c][n]); /* set cached .flags bitmask from attributes */ set_rect_extraptr(0, &xctx->rect[c][n]); @@ -1087,7 +1093,8 @@ static int edit_rect_property(int x) draw_image(0, &xctx->rect[c][n], &xctx->rect[c][n].x1, &xctx->rect[c][n].y1, &xctx->rect[c][n].x2, &xctx->rect[c][n].y2, 0, 0); } - bbox(ADD, xctx->rect[c][n].x1, xctx->rect[c][n].y1, xctx->rect[c][n].x2, xctx->rect[c][n].y2); + bbox(ADD, xctx->rect[c][n].x1 - width, xctx->rect[c][n].y1 - width, + xctx->rect[c][n].x2 + width, xctx->rect[c][n].y2 + width); } } if(drw) { diff --git a/src/hilight.c b/src/hilight.c index 044fea60..0cde77bc 100644 --- a/src/hilight.c +++ b/src/hilight.c @@ -2269,7 +2269,7 @@ void draw_hilight_net(int on_window) } 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.0, 0); - drawrect(col, END, 0.0, 0.0, 0.0, 0.0, 0, -1, -1); + drawrect(col, END, 0.0, 0.0, 0.0, 0.0, 0.0, 0, -1, -1); drawline(col, END, 0.0, 0.0, 0.0, 0.0, 0.0, 0, NULL); } } diff --git a/src/paste.c b/src/paste.c index c3bbe732..be1a13f5 100644 --- a/src/paste.c +++ b/src/paste.c @@ -95,6 +95,7 @@ static void merge_box(FILE *fd) RECTORDER(ptr[i].x1, ptr[i].y1, ptr[i].x2, ptr[i].y2); ptr[i].sel=0; load_ascii_string( &ptr[i].prop_ptr, fd); + ptr[i].bus = get_attr_val(get_tok_value(ptr[i].prop_ptr, "bus", 0)); attr = get_tok_value(ptr[i].prop_ptr,"dash",0); if(strcmp(attr, "")) { int d = atoi(attr); @@ -155,8 +156,7 @@ static void merge_arc(FILE *fd) ptr[i].prop_ptr=NULL; ptr[i].sel=0; load_ascii_string(&ptr[i].prop_ptr, fd); - - + ptr[i].bus = get_attr_val(get_tok_value(ptr[i].prop_ptr,"bus",0)); fill_ptr = get_tok_value(ptr[i].prop_ptr,"fill",0); if( !strcmp(fill_ptr, "full") ) ptr[i].fill = 2; /* bit 1: solid fill (not stippled) */ @@ -171,8 +171,6 @@ 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]++; } @@ -218,6 +216,7 @@ static void merge_polygon(FILE *fd) } } load_ascii_string( &ptr[i].prop_ptr, fd); + ptr[i].bus = get_attr_val(get_tok_value(ptr[i].prop_ptr, "bus", 0)); fill_ptr = get_tok_value(ptr[i].prop_ptr,"fill",0); if( !strcmp(fill_ptr, "full") ) ptr[i].fill = 2; /* bit 1: solid fill (not stippled) */ @@ -232,7 +231,6 @@ static void merge_polygon(FILE *fd) } else { ptr[i].dash = 0; } - ptr[i].bus = get_attr_val(get_tok_value(ptr[i].prop_ptr, "bus", 0)); select_polygon(c,i, SELECTED, 1, 1); xctx->polygons[c]++; } @@ -261,6 +259,7 @@ static void merge_line(FILE *fd) ptr[i].prop_ptr=NULL; ptr[i].sel=0; load_ascii_string( &ptr[i].prop_ptr, fd); + ptr[i].bus = get_attr_val(get_tok_value(ptr[i].prop_ptr, "bus", 0)); dash = get_tok_value(ptr[i].prop_ptr,"dash",0); if(strcmp(dash, "")) { int d = atoi(dash); @@ -268,7 +267,6 @@ static void merge_line(FILE *fd) } else { ptr[i].dash = 0; } - ptr[i].bus = get_attr_val(get_tok_value(ptr[i].prop_ptr, "bus", 0)); select_line(c,i, SELECTED, 1, 1); xctx->lines[c]++; } diff --git a/src/psprint.c b/src/psprint.c index 87e25f9a..75e395d0 100644 --- a/src/psprint.c +++ b/src/psprint.c @@ -576,10 +576,15 @@ static void ps_drawpolygon(int c, int what, double *x, double *y, int points, static void ps_filledrect(int gc, double rectx1,double recty1,double rectx2,double recty2, - int dash, int fill, int e_a, int e_b) + double bus, int dash, int fill, int e_a, int e_b) { 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; x1=X_TO_PS(rectx1); y1=Y_TO_PS(recty1); @@ -588,9 +593,15 @@ static void ps_filledrect(int gc, double rectx1,double recty1,double rectx2,doub if(rectclip(xctx->areax1,xctx->areay1,xctx->areax2,xctx->areay2,&x1,&y1,&x2,&y2)) { psdash = dash / xctx->zoom; - if(dash) { - fprintf(fd, "[%g %g] 0 setdash\n", psdash, psdash); + + 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); + if(e_a != -1) { double rx = (x2 - x1) / 2.0; double ry = (y2 - y1) / 2.0; @@ -608,7 +619,11 @@ static void ps_filledrect(int gc, double rectx1,double recty1,double rectx2,doub } 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"); + } } } @@ -663,6 +678,12 @@ static void ps_drawline(int gc, double linex1,double liney1,double linex2,double { 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; + x1=X_TO_PS(linex1); y1=Y_TO_PS(liney1); @@ -671,11 +692,21 @@ static void ps_drawline(int gc, double linex1,double liney1,double linex2,double if( clip(&x1,&y1,&x2,&y2) ) { psdash = dash / xctx->zoom; - if(dash) fprintf(fd, "[%g %g] 0 setdash\n", psdash, psdash); - if(bus == -1.0) set_lw(xctx->lw * BUS_WIDTH); + 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_xdrawline(gc, x1, y1, x2, y2); - if(dash) fprintf(fd, "[] 0 setdash\n"); - if(bus == -1.0) set_lw(xctx->lw); + 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"); + } } } @@ -995,7 +1026,8 @@ static void ps_draw_symbol(int c, int n,int layer, int what, short tmp_flip, sho else if((xctx->inst[n].x2 - xctx->inst[n].x1) * xctx->mooz < 3 && (xctx->inst[n].y2 - xctx->inst[n].y1) * xctx->mooz < 3) { set_ps_colors(SYMLAYER); - ps_filledrect(SYMLAYER, xctx->inst[n].xx1, xctx->inst[n].yy1, xctx->inst[n].xx2, xctx->inst[n].yy2, 0, 0, -1, -1); + ps_filledrect(SYMLAYER, xctx->inst[n].xx1, xctx->inst[n].yy1, xctx->inst[n].xx2, xctx->inst[n].yy2, + 0.0, 0, 0, -1, -1); xctx->inst[n].flags|=1; return; } @@ -1005,7 +1037,8 @@ static void ps_draw_symbol(int c, int n,int layer, int what, short tmp_flip, sho if(hide) { int color = (disabled==1) ? GRIDLAYER : (disabled == 2) ? PINLAYER : SYMLAYER; set_ps_colors(color); - ps_filledrect(color, xctx->inst[n].xx1, xctx->inst[n].yy1, xctx->inst[n].xx2, xctx->inst[n].yy2, 2, 0, -1, -1); + ps_filledrect(color, xctx->inst[n].xx1, xctx->inst[n].yy1, xctx->inst[n].xx2, xctx->inst[n].yy2, + 0.0, 2, 0, -1, -1); } /* pdfmarks, only if doing hierarchy print and if symbol has a subcircuit */ if(what != 7) { @@ -1131,7 +1164,7 @@ static void ps_draw_symbol(int c, int n,int layer, int what, short tmp_flip, sho ellipse_a %= 360; } } - ps_filledrect(c, x0+x1, y0+y1, x0+x2, y0+y2, dash, rect->fill, ellipse_a, ellipse_b); + ps_filledrect(c, x0+x1, y0+y1, x0+x2, y0+y2, rect->bus, dash, rect->fill, ellipse_a, ellipse_b); } } } /* if( (!hide && xctx->enable_layer[layer]) || ... */ @@ -1492,7 +1525,7 @@ void create_ps(char **psfile, int what, int fullzoom, int eps) if(c != GRIDLAYER || !(xctx->rect[c][i].flags & 1) ) { ps_filledrect(c, xctx->rect[c][i].x1, xctx->rect[c][i].y1, xctx->rect[c][i].x2, xctx->rect[c][i].y2, - xctx->rect[c][i].dash, xctx->rect[c][i].fill, + xctx->rect[c][i].bus, xctx->rect[c][i].dash, xctx->rect[c][i].fill, xctx->rect[c][i].ellipse_a, xctx->rect[c][i].ellipse_b); } } diff --git a/src/save.c b/src/save.c index 70a1e94f..d5a7fb53 100644 --- a/src/save.c +++ b/src/save.c @@ -2999,6 +2999,7 @@ static void load_box(FILE *fd) ptr[i].prop_ptr=NULL; ptr[i].sel=0; load_ascii_string( &ptr[i].prop_ptr, fd); + ptr[i].bus = get_attr_val(get_tok_value(ptr[i].prop_ptr, "bus", 0)); fill_ptr = get_tok_value(ptr[i].prop_ptr,"fill",0); if( !strcmp(fill_ptr, "full") ) ptr[i].fill = 2; @@ -4649,6 +4650,7 @@ int load_sym_def(const char *name, FILE *embed_fd) bb[c][i].dash = (short)(d >= 0 ? d : 0); } else bb[c][i].dash = 0; + bb[c][i].bus = get_attr_val(get_tok_value(bb[c][i].prop_ptr,"bus", 0)); attr = get_tok_value(bb[c][i].prop_ptr,"ellipse", 0); if( strcmp(attr, "") ) { int a; diff --git a/src/scheduler.c b/src/scheduler.c index 40a40df0..aee402a9 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -212,7 +212,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg if(draw) { save = xctx->draw_window; xctx->draw_window = 1; - drawrect(PINLAYER, NOW, x - 2.5, y - 2.5, x + 2.5, y + 2.5, 0, -1, -1); + drawrect(PINLAYER, NOW, x - 2.5, y - 2.5, x + 2.5, y + 2.5, 0.0, 0, -1, -1); filledrect(PINLAYER,NOW, x - 2.5, y - 2.5, x + 2.5, y + 2.5, 1, -1, -1); if(flip) { drawline(linecol, NOW, x -20, y, x, y, 0.0, 0, NULL); @@ -4678,7 +4678,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg int e_a = xctx->rect[c][n].ellipse_a; int e_b = xctx->rect[c][n].ellipse_b; save = xctx->draw_window; xctx->draw_window = 1; - drawrect(xctx->rectcolor,NOW, x1,y1,x2,y2, 0, e_a, e_b); + drawrect(xctx->rectcolor,NOW, x1,y1,x2,y2, 0.0, 0, e_a, e_b); filledrect(xctx->rectcolor, NOW, x1, y1, x2, y2, 1, -1, -1); xctx->draw_window = save; } diff --git a/src/store.c b/src/store.c index ee20a33b..858cf3f7 100644 --- a/src/store.c +++ b/src/store.c @@ -285,7 +285,10 @@ int storeobject(int pos, double x1,double y1,double x2,double y2, my_strdup(_ALLOC_ID_, &xctx->rect[rectc][n].prop_ptr, prop_ptr); xctx->rect[rectc][n].sel=sel; if(sel == SELECTED) set_first_sel(xRECT, n, rectc); - + xctx->rect[rectc][n].bus = 0.0; + if(prop_ptr) { + xctx->rect[rectc][n].bus = get_attr_val(get_tok_value(prop_ptr, "bus", 0)); + } if(prop_ptr && (attr = get_tok_value(prop_ptr,"dash",0))[0]) { int d = atoi(attr); xctx->rect[rectc][n].dash = (char) (d >= 0 ? d : 0); diff --git a/src/svgdraw.c b/src/svgdraw.c index 43d27b15..ea58d762 100644 --- a/src/svgdraw.c +++ b/src/svgdraw.c @@ -44,9 +44,23 @@ static void svg_restore_lw(void) static void svg_xdrawline(int layer, double bus, double x1, double y1, double x2, double y2, int dash) { + double width; + + if(bus == -1.0) width = BUS_WIDTH * svg_linew; + else if(bus > 0.0) width = bus * xctx->mooz; + else width = -1.0; + fprintf(fd,"zoom, 0.8*dash/xctx->zoom); - if(bus == -1.0) fprintf(fd, "style=\"stroke-width:%g;\" ", BUS_WIDTH * svg_linew); + if(width >= 0.0) { + 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"); + } + fprintf(fd, "\" "); + } fprintf(fd,"d=\"M%g %gL%g %g\"/>\n", x1, y1, x2, y2); } @@ -56,15 +70,34 @@ static void svg_xdrawpoint(int layer, double x1, double y1) fprintf(fd,"M%g %gL%g %gL%g%gL%g %gL%g %gz\"/>\n", x1, y1, x1+1.0, y1, x1+1.0, y1+1.0, x1, y1+1.0, x1, y1); } -static void svg_xfillrectangle(int layer, double x1, double y1, double x2, double y2, int dash, int fill) +static void svg_xfillrectangle(int layer, double x1, double y1, double x2, double y2, + double bus, int dash, int fill) { + double width; + + if(bus == -1.0) width = BUS_WIDTH * svg_linew; + else if(bus > 0.0) width = bus * xctx->mooz; + else width = -1.0; + fprintf(fd,"zoom, 0.8*dash/xctx->zoom); - if(fill == 0) { - fprintf(fd,"style=\"fill:none;\" "); - } else if(fill == 2) { - fprintf(fd, "style=\"fill-opacity:1.0;\" "); - } + + + if(width >= 0.0 || fill == 0 || fill == 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(fill == 0) { + fprintf(fd,"fill:none;\" "); + } else if(fill == 2) { + fprintf(fd, "fill-opacity:1.0;\" "); + } else { + fprintf(fd, "\" "); + } + } 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); } @@ -172,9 +205,14 @@ static void svg_drawpolygon(int c, int what, double *x, double *y, int points, } static void svg_filledrect(int gc, double rectx1,double recty1,double rectx2,double recty2, - int dash, int fill, int e_a, int e_b) + double bus, int dash, int fill, int e_a, int e_b) { - double x1,y1,x2,y2; + double x1,y1,x2,y2; + double width; + + if(bus == -1.0) width = BUS_WIDTH * svg_linew; + else if(bus > 0.0) width = bus * xctx->mooz; + else width = -1.0; x1=X_TO_SCREEN(rectx1); y1=Y_TO_SCREEN(recty1); @@ -204,18 +242,29 @@ static void svg_filledrect(int gc, double rectx1,double recty1,double rectx2,dou fprintf(fd,"zoom, 0.8*dash/xctx->zoom); - if(fill == 0) { - fprintf(fd,"style=\"fill:none;\" "); - fprintf(fd, "d=\"M%g %g A%g %g 0 %d %d %g %g\"/>\n", xx1, yy1, rx, ry, fa, fs, xx2, yy2); - } else if(fill == 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, rx, ry, fa, fs, xx2, yy2, cx, cy); - } else { - fprintf(fd, "d=\"M%g %g A%g %g 0 %d %d %g %gL%g %gz\"/>\n", xx1, yy1, rx, ry, fa, fs, xx2, yy2, cx, cy); - } + + + if(width >= 0.0 || fill == 0 || fill == 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(fill == 0) { + fprintf(fd,"fill:none;\" "); + fprintf(fd, "d=\"M%g %g A%g %g 0 %d %d %g %g\"/>\n", xx1, yy1, rx, ry, fa, fs, xx2, yy2); + } else if(fill == 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, rx, ry, fa, fs, xx2, yy2, cx, cy); + } else { + fprintf(fd, "\" "); + fprintf(fd, "d=\"M%g %g A%g %g 0 %d %d %g %gL%g %gz\"/>\n", xx1, yy1, rx, ry, fa, fs, xx2, yy2, cx, cy); + } + } } } else { - svg_xfillrectangle(gc, x1,y1,x2,y2, dash, fill); + svg_xfillrectangle(gc, x1,y1,x2,y2, bus, dash, fill); } } } @@ -700,7 +749,8 @@ static void svg_draw_symbol(int c, int n,int layer,short tmp_flip, short rot, } else if((xctx->inst[n].x2 - xctx->inst[n].x1) * xctx->mooz < 3 && (xctx->inst[n].y2 - xctx->inst[n].y1) * xctx->mooz < 3) { - svg_filledrect(SYMLAYER, xctx->inst[n].xx1, xctx->inst[n].yy1, xctx->inst[n].xx2, xctx->inst[n].yy2, 0, 0, -1, -1); + svg_filledrect(SYMLAYER, xctx->inst[n].xx1, xctx->inst[n].yy1, xctx->inst[n].xx2, xctx->inst[n].yy2, + 0.0, 0, 0, -1, -1); xctx->inst[n].flags|=1; return; } @@ -709,7 +759,8 @@ static void svg_draw_symbol(int c, int n,int layer,short tmp_flip, short rot, } if(hide) { int color = (disabled==1) ? GRIDLAYER : (disabled == 2) ? PINLAYER : SYMLAYER; - svg_filledrect(color, xctx->inst[n].xx1, xctx->inst[n].yy1, xctx->inst[n].xx2, xctx->inst[n].yy2, 2, 0, -1, -1); + svg_filledrect(color, xctx->inst[n].xx1, xctx->inst[n].yy1, xctx->inst[n].xx2, xctx->inst[n].yy2, + 0.0, 2, 0, -1, -1); } } else if(xctx->inst[n].flags&1) { @@ -809,7 +860,7 @@ static void svg_draw_symbol(int c, int n,int layer,short tmp_flip, short rot, ellipse_a %= 360; } } - svg_filledrect(c, x0+x1, y0+y1, x0+x2, y0+y2, dash, rect->fill, ellipse_a, ellipse_b); + svg_filledrect(c, x0+x1, y0+y1, x0+x2, y0+y2, rect->bus, dash, rect->fill, ellipse_a, ellipse_b); } } } @@ -1088,7 +1139,7 @@ void svg_draw(void) } else { svg_filledrect(c, xctx->rect[c][i].x1, xctx->rect[c][i].y1, xctx->rect[c][i].x2, xctx->rect[c][i].y2, - xctx->rect[c][i].dash, xctx->rect[c][i].fill, + xctx->rect[c][i].bus, xctx->rect[c][i].dash, xctx->rect[c][i].fill, xctx->rect[c][i].ellipse_a, xctx->rect[c][i].ellipse_b); } } diff --git a/src/xschem.h b/src/xschem.h index c2edf111..65bcd4b9 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -500,6 +500,7 @@ typedef struct void *extraptr; /* generic data pointer (images) */ short fill; /* 0: no fill, 1: stippled fill, 2: solid fill */ short dash; + double bus; int ellipse_a, ellipse_b; /* bit0=1 for graph function, bit1=1 for unlocked x axis * bit10: image embedding (png) @@ -1444,7 +1445,7 @@ extern void get_sym_text_layer(int inst, int text_n, int *layer); extern void draw_symbol(int what,int c, int n,int layer, short tmp_flip, short tmp_rot, double xoffset, double yoffset); extern void drawrect(int c, int what, double rectx1,double recty1, - double rectx2,double recty2, int dash, int e_a, int e_b); + double rectx2,double recty2, double bus, int dash, int e_a, int e_b); extern void filledrect(int c, int what, double rectx1,double recty1, double rectx2,double recty2, int fill, int e_a, int e_b);