From bcedaa6bc508e57727e4761795d6f7dc30c20808 Mon Sep 17 00:00:00 2001 From: Stefan Frederik Date: Sat, 19 Dec 2020 17:12:46 +0100 Subject: [PATCH] various drawing optimizations to speed up full zoom views --- src/actions.c | 3 +- src/draw.c | 130 +++++++++++++++++++++++--------------------------- src/move.c | 1 - 3 files changed, 63 insertions(+), 71 deletions(-) diff --git a/src/actions.c b/src/actions.c index ea05149b..42464348 100644 --- a/src/actions.c +++ b/src/actions.c @@ -2122,9 +2122,10 @@ int text_bbox(const char * str,double xscale, double yscale, double w, h; w=0;h=1; + cairo_lines = 1; if(str!=NULL) while( str[c] ) { - if((str)[c++]=='\n') {h++;length=0;} + if((str)[c++]=='\n') {cairo_lines++; h++; length=0;} else length++; if(length > w) w = length; diff --git a/src/draw.c b/src/draw.c index b6083d1a..e546fb6a 100644 --- a/src/draw.c +++ b/src/draw.c @@ -456,58 +456,77 @@ void draw_temp_string(GC gctext, int what, const char *str, short rot, short fli drawtemprect(gctext,what, textx1,texty1,textx2,texty2); } + +/* + * layer: the set of symbol objects on xschem layer 'layer' to draw + * c : the layer 'c' to draw those objects on (if != layer it is the hilight color) + */ void draw_symbol(int what,int c, int n,int layer,short tmp_flip, short rot, double xoffset, double yoffset) /* draws current layer only, should be called within */ { /* a "for(i=0;iinst[n].ptr == -1) return; if( (layer != PINLAYER && !enable_layer[layer]) ) return; if(!has_x) return; - if( - (hide_symbols==1 && (xctx->inst[n].ptr+ xctx->sym)->prop_ptr && - !strcmp( (xctx->inst[n].ptr+ xctx->sym)->type, "subcircuit") ) || (hide_symbols == 2) ) { + if( (hide_symbols==1 && (xctx->inst[n].ptr+ xctx->sym)->prop_ptr && + !strcmp( (xctx->inst[n].ptr+ xctx->sym)->type, "subcircuit") ) || (hide_symbols == 2) ) { hide = 1; } else { hide = 0; } - if(hide && layer == 0) { - drawrect(4, what, xctx->inst[n].xx1, xctx->inst[n].yy1, xctx->inst[n].xx2, xctx->inst[n].yy2, 2); - } + type = (xctx->inst[n].ptr+ xctx->sym)->type; if(layer==0) { x1=X_TO_SCREEN(xctx->inst[n].x1+xoffset); /* 20150729 added xoffset, yoffset */ x2=X_TO_SCREEN(xctx->inst[n].x2+xoffset); y1=Y_TO_SCREEN(xctx->inst[n].y1+yoffset); y2=Y_TO_SCREEN(xctx->inst[n].y2+yoffset); - if(!only_probes && (x2-x1)< 0.3 && (y2-y1)< 0.3) { - xctx->inst[n].flags|=1; - return; - } - else if(OUTSIDE(x1,y1,x2,y2,xctx->areax1,xctx->areay1,xctx->areax2,xctx->areay2)) + if(OUTSIDE(x1,y1,x2,y2,xctx->areax1,xctx->areay1,xctx->areax2,xctx->areay2)) { xctx->inst[n].flags|=1; return; } - else xctx->inst[n].flags&=~1; - + else if( + xctx->hilight_nets && /* if highlights... */ + c == 0 && /* we are not drawing highlighted inst */ + /* otherwise c > layer... */ + type && /* ... and type... */ + ( + ( /* ... and inst is hilighted ... */ + IS_LABEL_SH_OR_PIN(type) && xctx->inst[n].node && xctx->inst[n].node[0] && + bus_hilight_lookup(xctx->inst[n].node[0], 0, XLOOKUP ) + ) || ( !IS_LABEL_SH_OR_PIN(type) && (xctx->inst[n].color)) )) { + xctx->inst[n].flags|=1; /* ... then SKIP instance now and for following layers */ + return; + } + else if(!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(4, NOW, xctx->inst[n].xx1, xctx->inst[n].yy1, xctx->inst[n].xx2, xctx->inst[n].yy2, 0); + xctx->inst[n].flags|=1; + } + else { + xctx->inst[n].flags&=~1; + } + if(hide) drawrect(4, NOW, xctx->inst[n].xx1, xctx->inst[n].yy1, xctx->inst[n].xx2, xctx->inst[n].yy2, 2); } else if(xctx->inst[n].flags&1) { dbg(2, "draw_symbol(): skipping inst %d\n", n); return; } + flip = xctx->inst[n].flip; if(tmp_flip) flip = !flip; rot = (xctx->inst[n].rot + rot ) & 0x3; @@ -530,7 +549,7 @@ void draw_symbol(int what,int c, int n,int layer,short tmp_flip, short rot, for(j=0;j< symptr->polygons[layer];j++) { polygon = (symptr->poly[layer])[j]; - { /* scope block so we declare some auxiliary arrays for coord transforms. 20171115 */ + { /* scope block so we declare some auxiliary arrays for coord transforms. */ int k; double *x = my_malloc(34, sizeof(double) * polygon.points); double *y = my_malloc(35, sizeof(double) * polygon.points); @@ -539,14 +558,14 @@ void draw_symbol(int what,int c, int n,int layer,short tmp_flip, short rot, x[k]+= x0; y[k] += y0; } - drawpolygon(c, NOW, x, y, polygon.points, polygon.fill, polygon.dash); /* 20180914 added fill */ + drawpolygon(c, NOW, x, y, polygon.points, polygon.fill, polygon.dash); /* added fill */ my_free(718, &x); my_free(719, &y); } } for(j=0;j< symptr->arcs[layer];j++) { - + arc = (symptr->arc[layer])[j]; if(flip) { angle = 270.*rot+180.-arc.b-arc.a; @@ -854,7 +873,7 @@ void drawline(int c, int what, double linex1, double liney1, double linex2, doub y1=Y_TO_SCREEN(liney1); x2=X_TO_SCREEN(linex2); y2=Y_TO_SCREEN(liney2); - if(!only_probes && (x2-x1)< 0.3 && fabs(y2-y1) < 0.3) return; + /* if(!only_probes && (x2-x1)< 2.0 && fabs(y2-y1) < 2.0) return; */ if( clip(&x1,&y1,&x2,&y2) ) { rr[i].x1=(short)x1; @@ -870,7 +889,7 @@ void drawline(int c, int what, double linex1, double liney1, double linex2, doub y1=Y_TO_SCREEN(liney1); x2=X_TO_SCREEN(linex2); y2=Y_TO_SCREEN(liney2); - if(!only_probes && (x2-x1)< 0.3 && fabs(y2-y1)< 0.3) return; + /* if(!only_probes && (x2-x1)< 2.0 && fabs(y2-y1)< 2.0) return; */ if( clip(&x1,&y1,&x2,&y2) ) { if(dash) { @@ -893,7 +912,7 @@ void drawline(int c, int what, double linex1, double liney1, double linex2, doub y1=Y_TO_SCREEN(liney1); x2=X_TO_SCREEN(linex2); y2=Y_TO_SCREEN(liney2); - if(!only_probes && (x2-x1)< 0.3 && fabs(y2-y1)< 0.3) return; + /* if(!only_probes && (x2-x1)< 2.0 && fabs(y2-y1)< 2.0) return; */ if( clip(&x1,&y1,&x2,&y2) ) { if(dash) { @@ -1264,7 +1283,7 @@ void filledrect(int c, int what, double rectx1,double recty1,double rectx2,doubl y1=Y_TO_SCREEN(recty1); x2=X_TO_SCREEN(rectx2); y2=Y_TO_SCREEN(recty2); - if(!only_probes && (x2-x1)< 2 && (y2-y1)< 2) return; + if(!only_probes && (x2-x1)< 2.0 && (y2-y1)< 2.0) return; if( rectclip(xctx->areax1,xctx->areay1,xctx->areax2,xctx->areay2,&x1,&y1,&x2,&y2) ) { if(draw_window) XFillRectangle(display, xctx->window, gcstipple[c], (int)x1, (int)y1, @@ -1290,7 +1309,7 @@ void filledrect(int c, int what, double rectx1,double recty1,double rectx2,doubl y1=Y_TO_SCREEN(recty1); x2=X_TO_SCREEN(rectx2); y2=Y_TO_SCREEN(recty2); - if(!only_probes && (x2-x1)< 2 && (y2-y1)< 2) return; + if(!only_probes && (x2-x1)< 2.0 && (y2-y1)< 2.0) return; if( rectclip(xctx->areax1,xctx->areay1,xctx->areax2,xctx->areay2,&x1,&y1,&x2,&y2) ) { r[i].x=(short)x1; @@ -1394,7 +1413,7 @@ void drawpolygon(int c, int what, double *x, double *y, int points, int poly_fil if( !rectclip(xctx->areax1,xctx->areay1,xctx->areax2,xctx->areay2,&x1,&y1,&x2,&y2) ) { return; } - if( !only_probes && (x2-x1)<0.3 && (y2-y1)<0.3) return; + if( !only_probes && (x2-x1)<2.0 && (y2-y1)<2.0) return; p = my_malloc(38, sizeof(XPoint) * points); for(i=0;iareax1,xctx->areay1,xctx->areax2,xctx->areay2,&x1,&y1,&x2,&y2) ) { if(dash) { @@ -1500,7 +1519,7 @@ void drawrect(int c, int what, double rectx1,double recty1,double rectx2,double y1=Y_TO_SCREEN(recty1); x2=X_TO_SCREEN(rectx2); y2=Y_TO_SCREEN(recty2); - if(!only_probes && (x2-x1)< 0.3 && (y2-y1)< 0.3) return; + /* if(!only_probes && (x2-x1)< 2.0 && (y2-y1)< 2.0) return; */ if( rectclip(xctx->areax1,xctx->areay1,xctx->areax2,xctx->areay2,&x1,&y1,&x2,&y2) ) { r[i].x=(short)x1; @@ -1531,7 +1550,7 @@ void drawtemprect(GC gc, int what, double rectx1,double recty1,double rectx2,dou y1=Y_TO_SCREEN(recty1); x2=X_TO_SCREEN(rectx2); y2=Y_TO_SCREEN(recty2); - if( (x2-x1)< 0.3 && (y2-y1)< 0.3) return; + /* if( (x2-x1)< 2.0 && (y2-y1)< 2.0) return; */ if( rectclip(xctx->areax1,xctx->areay1,xctx->areax2,xctx->areay2,&x1,&y1,&x2,&y2) ) { XDrawRectangle(display, xctx->window, gc, (int)x1, (int)y1, @@ -1551,7 +1570,7 @@ void drawtemprect(GC gc, int what, double rectx1,double recty1,double rectx2,dou y1=Y_TO_SCREEN(recty1); x2=X_TO_SCREEN(rectx2); y2=Y_TO_SCREEN(recty2); - if( (x2-x1)< 0.3 && (y2-y1)< 0.3) return; + /* if( (x2-x1)< 2.0 && (y2-y1)< 2.0) return; */ if( rectclip(xctx->areax1,xctx->areay1,xctx->areax2,xctx->areay2,&x1,&y1,&x2,&y2) ) { r[i].x=(short)x1; @@ -1574,16 +1593,14 @@ void draw(void) double x1, y1, x2, y2; struct instentry *instanceptr; struct wireentry *wireptr; - char *type=NULL; int use_hash; register int c,i; register xSymbol *symptr; int textlayer; - #if HAS_CAIRO==1 - char *textfont; - #endif - + #if HAS_CAIRO==1 + char *textfont; + #endif if(no_draw) return; rebuild_selected_array(); if(has_x) { @@ -1598,32 +1615,26 @@ void draw(void) x2 = X_TO_XSCHEM(xctx->areax2); y2 = Y_TO_XSCHEM(xctx->areay2); use_hash = (xctx->wires> 2000 || xctx->instances > 2000 ) && (x2 - x1 < ITERATOR_THRESHOLD); - if(use_hash) { hash_instances(); hash_wires(); } if(!only_probes) { dbg(3, "draw(): check4\n"); - for(c=0;clines[c];i++) { xLine *l = &xctx->line[c][i]; - if(l->bus) - drawline(c, THICK, l->x1, l->y1, l->x2, l->y2, l->dash); - else - drawline(c, ADD, l->x1, l->y1, l->x2, l->y2, l->dash); + if(l->bus) drawline(c, THICK, l->x1, l->y1, l->x2, l->y2, l->dash); + else drawline(c, ADD, l->x1, l->y1, l->x2, l->y2, l->dash); } - if(enable_layer[c]) for(i=0;irects[c];i++) - { + if(enable_layer[c]) for(i=0;irects[c];i++) { xRect *r = &xctx->rect[c][i]; drawrect(c, ADD, r->x1, r->y1, r->x2, r->y2, r->dash); filledrect(c, ADD, r->x1, r->y1, r->x2, r->y2); } - if(enable_layer[c]) for(i=0;iarcs[c];i++) - { + if(enable_layer[c]) for(i=0;iarcs[c];i++) { xArc *a = &xctx->arc[c][i]; drawarc(c, ADD, a->x, a->y, a->r, a->a, a->b, a->fill, a->dash); } @@ -1631,7 +1642,6 @@ void draw(void) xPoly *p = &xctx->poly[c][i]; drawpolygon(c, NOW, p->x, p->y, p->points, p->fill, p->dash); } - if(use_hash) init_inst_iterator(x1, y1, x2, y2); else i = -1; while(1) { @@ -1645,41 +1655,24 @@ void draw(void) } if(xctx->inst[i].ptr == -1) continue; symptr = (xctx->inst[i].ptr+ xctx->sym); - if( c==0 || /*draw_symbol call is needed on layer 0 to avoid redundant work (outside check) */ + if( !(c > 0 && (xctx->inst[i].flags & 1)) && /* skip flag */ + ( c==0 || /*draw_symbol call is needed on layer 0 to avoid redundant work (outside check) */ symptr->lines[c] || symptr->arcs[c] || symptr->rects[c] || symptr->polygons[c] || - ((c==TEXTWIRELAYER || c==TEXTLAYER) && symptr->texts)) { + ((c==TEXTWIRELAYER || c==TEXTLAYER) && symptr->texts) ) ) + { - - type = (xctx->inst[i].ptr+ xctx->sym)->type; - if(!( - xctx->hilight_nets && /* if no highlights ... */ - type && /* ... or no type ... */ - ( - ( /* ... or inst is not hilighted ... */ - IS_LABEL_SH_OR_PIN(type) && xctx->inst[i].node && xctx->inst[i].node[0] && - bus_hilight_lookup(xctx->inst[i].node[0], 0, XLOOKUP ) - ) || - ( - !IS_LABEL_SH_OR_PIN(type) && (xctx->inst[i].color) - ) - ) - ) - ) { draw_symbol(ADD, c, i,c,0,0,0.0,0.0); /* ... then draw current layer */ - } } } - filledrect(c, END, 0.0, 0.0, 0.0, 0.0); drawarc(c, END, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0); drawrect(c, END, 0.0, 0.0, 0.0, 0.0, 0); drawline(c, END, 0.0, 0.0, 0.0, 0.0, 0); } if(draw_single_layer==-1 || draw_single_layer==WIRELAYER) { - if(use_hash) init_wire_iterator(x1, y1, x2, y2); else i = -1; while(1) { @@ -1727,7 +1720,6 @@ void draw(void) cairo_select_font_face (xctx->cairo_save_ctx, textfont, slant, weight); } #endif - draw_string(textlayer, ADD, xctx->text[i].txt_ptr, xctx->text[i].rot, xctx->text[i].flip, xctx->text[i].hcenter, xctx->text[i].vcenter, xctx->text[i].x0,xctx->text[i].y0, diff --git a/src/move.c b/src/move.c index 08aa0c7b..f49ae2fc 100644 --- a/src/move.c +++ b/src/move.c @@ -1473,7 +1473,6 @@ void move_objects(int what, int merge, double dx, double dy) find_inst_to_be_redrawn(wire[n].node); } } - /* draw_symbol(ADD,k, n,k, 0, 0, 0.0, 0.0); */ } if(show_pin_net_names) find_inst_hash_clear();