diff --git a/src/actions.c b/src/actions.c index 529bd028..b0818b05 100644 --- a/src/actions.c +++ b/src/actions.c @@ -414,7 +414,7 @@ void ask_new_file(void) Tcl_VarEval(interp, "update_recent_file {", fullname, "}", NULL); my_strdup(1, &xctx->sch_path[xctx->currsch],"."); xctx->sch_inst_number[xctx->currsch] = 1; - zoom_full(1, 0); + zoom_full(1, 0, 1); } } @@ -1109,7 +1109,7 @@ void descend_schematic(int instnumber) if(enable_drill) drill_hilight(); } dbg(1, "descend_schematic(): before zoom(): prep_hash_inst=%d\n", xctx->prep_hash_inst); - zoom_full(1, 0); + zoom_full(1, 0, 1); } } @@ -1352,41 +1352,50 @@ void calc_drawing_bbox(xRect *boundbox, int selected) } -void zoom_full(int dr, int sel) +/* bit0: invoke change_linewidth(), bit1: centered zoom */ +void zoom_full(int dr, int sel, int flags) { xRect boundbox; - double yy1; + double yzoom; + double shrink = 0.98; /* shrink drawing to make room for margins */ + double bboxw, bboxh, schw, schh; - if(change_lw) { - xctx->lw = 1.; + if(flags & 1) { + if(change_lw) { + xctx->lw = 1.; + } + xctx->areax1 = -2*INT_WIDTH(xctx->lw); + xctx->areay1 = -2*INT_WIDTH(xctx->lw); + xctx->areax2 = xctx->xrect[0].width+2*INT_WIDTH(xctx->lw); + xctx->areay2 = xctx->xrect[0].height+2*INT_WIDTH(xctx->lw); + xctx->areaw = xctx->areax2-xctx->areax1; + xctx->areah = xctx->areay2 - xctx->areay1; } - xctx->areax1 = -2*INT_WIDTH(xctx->lw); - xctx->areay1 = -2*INT_WIDTH(xctx->lw); - xctx->areax2 = xctx->xrect[0].width+2*INT_WIDTH(xctx->lw); - xctx->areay2 = xctx->xrect[0].height+2*INT_WIDTH(xctx->lw); - xctx->areaw = xctx->areax2-xctx->areax1; - xctx->areah = xctx->areay2 - xctx->areay1; - calc_drawing_bbox(&boundbox, sel); - xctx->zoom=(boundbox.x2-boundbox.x1)/(xctx->areaw-4*INT_WIDTH(xctx->lw)); - yy1=(boundbox.y2-boundbox.y1)/(xctx->areah-4*INT_WIDTH(xctx->lw)); - if(yy1>xctx->zoom) xctx->zoom=yy1; - xctx->zoom*=1.05; - xctx->mooz=1/xctx->zoom; - xctx->xorigin=-boundbox.x1+(xctx->areaw-4*INT_WIDTH(xctx->lw))/40*xctx->zoom; - xctx->yorigin=(xctx->areah-4*INT_WIDTH(xctx->lw))*xctx->zoom-boundbox.y2 - - (xctx->areah-4*INT_WIDTH(xctx->lw))/40*xctx->zoom; - dbg(1, "zoom_full(): areaw=%d, areah=%d\n", xctx->areaw, xctx->areah); + schw = xctx->areaw-4*INT_WIDTH(xctx->lw); + schh = xctx->areah-4*INT_WIDTH(xctx->lw); + bboxw = boundbox.x2-boundbox.x1; + bboxh = boundbox.y2-boundbox.y1; + xctx->zoom = bboxw / schw; + yzoom = bboxh / schh; + if(yzoom > xctx->zoom) xctx->zoom = yzoom; + xctx->zoom /= shrink; + /* we do this here since change_linewidth may not be called if flags & 1 == 0*/ + cadhalfdotsize = CADHALFDOTSIZE + 0.04 * (cadsnap-10); - change_linewidth(-1.); - if(dr) - { - if(!has_x) return; - draw(); + xctx->mooz = 1 / xctx->zoom; + if(flags & 2) { + xctx->xorigin = -boundbox.x1 + (xctx->zoom * schw - bboxw) / 2; /* centered */ + xctx->yorigin = -boundbox.y1 + (xctx->zoom * schh - bboxh) / 2; /* centered */ + } else { + xctx->xorigin = -boundbox.x1 + (1 - shrink) / 2 * xctx->zoom * schw; + xctx->yorigin = -boundbox.y1 + xctx->zoom * schh - bboxh - (1 - shrink) / 2 * xctx->zoom * schh; } + dbg(1, "zoom_full(): areaw=%d, areah=%d\n", xctx->areaw, xctx->areah); + if(flags & 1) change_linewidth(-1.); + if(dr && has_x) draw(); } - void view_zoom(double z) { double factor; diff --git a/src/callback.c b/src/callback.c index 425fe933..d0e2c074 100644 --- a/src/callback.c +++ b/src/callback.c @@ -1002,7 +1002,7 @@ int callback(int event, int mx, int my, KeySym key, if(key=='*' && state==(Mod1Mask|ShiftMask) ) /* svg print , 20121108 */ { if(xctx->semaphore >= 2) break; - svg_draw(); + svg_draw(0, 0); break; } if(key=='*' && state==ShiftMask ) /* postscript print */ @@ -1014,7 +1014,7 @@ int callback(int event, int mx, int my, KeySym key, if(key=='*' && state==(ControlMask|ShiftMask) ) /* xpm print */ { if(xctx->semaphore >= 2) break; - print_image(); + print_image(0, 0); break; } if(key=='u' && state==Mod1Mask) /* align to grid */ @@ -1345,7 +1345,7 @@ int callback(int event, int mx, int my, KeySym key, xctx->prep_net_structs = 0; xctx->prep_hi_structs = 0; xctx->prep_hash_wires = 0; - zoom_full(1, 0); + zoom_full(1, 0, 1); break; } @@ -1357,7 +1357,7 @@ int callback(int event, int mx, int my, KeySym key, } if(key=='f' && state == 0 ) /* full zoom */ { - zoom_full(1, 0); + zoom_full(1, 0, 1); break; } if((key=='z' && state==ControlMask)) /* zoom out */ diff --git a/src/draw.c b/src/draw.c index 39da9821..1cc02f4b 100644 --- a/src/draw.c +++ b/src/draw.c @@ -47,7 +47,7 @@ int textclip(int x1,int y1,int x2,int y2, return 1; } -void print_image() +void print_image(int user_w, int user_h) { int w, h, tmp, ww, hh, save_draw_grid, changed_size; int modified_save; @@ -61,7 +61,10 @@ void print_image() changed_size = 0; w = ww = xctx->xschem_w; h = hh = xctx->xschem_h; - if(!plotfile[0]) { + if(user_w > 0 && user_h > 0 ) { + w = user_w; h = user_h; + if(w != xctx->xschem_w || h != xctx->xschem_h) changed_size = 1; + } else if(!plotfile[0]) { my_snprintf(cmd, S(cmd), "input_line {Enter image size} {} {%dx%d}", xctx->xschem_w, xctx->xschem_h); tcleval(cmd); if(sscanf(tclresult(), "%dx%d", &w, &h) != 2) { @@ -76,7 +79,6 @@ void print_image() if(r[0]) my_strncpy(plotfile, r, S(plotfile)); else return; } - modified_save=xctx->modified; /* 20161121 save state */ push_undo(); trim_wires(); /* 20161121 add connection boxes on wires but undo at end */ @@ -142,7 +144,7 @@ void print_image() save_draw_grid = draw_grid; draw_grid=0; draw_pixmap=1; - if(changed_size) zoom_full(0, 0); + if(changed_size) zoom_full(0, 0, 3); /* flags : 2 + 1 , center zoom & change_linewidth */ draw(); #ifdef __unix__ diff --git a/src/save.c b/src/save.c index cfc72db7..e1e2d68f 100644 --- a/src/save.c +++ b/src/save.c @@ -2251,7 +2251,7 @@ void descend_symbol(void) remove_symbols(); /* must follow save (if) embedded */ load_schematic(1, abs_sym_path(name, ""), 1); } - zoom_full(1, 0); + zoom_full(1, 0, 1); } /* 20111023 align selected object to current grid setting */ diff --git a/src/scheduler.c b/src/scheduler.c index f18a993f..3fdca4d3 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -888,6 +888,8 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg printf("sch[%d]=%s\n",i,xctx->sch[i]); } printf("modified=%d\n", xctx->modified); + printf("areaw=%d\n", xctx->areaw); + printf("areah=%d\n", xctx->areah); printf("color_ps=%d\n", color_ps); printf("hilight_nets=%d\n", xctx->hilight_nets); printf("need_reb_sel_arr=%d\n", xctx->need_reb_sel_arr); @@ -1365,7 +1367,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg Tcl_VarEval(interp, "update_recent_file {", abs_sym_path(argv[2], ""), "}", NULL); my_strdup(375, &xctx->sch_path[xctx->currsch],"."); xctx->sch_inst_number[xctx->currsch] = 1; - zoom_full(1, 0); + zoom_full(1, 0, 1); } } else if(argc==2) { @@ -1402,7 +1404,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg load_schematic(0, abs_sym_path(argv[2], ""), 1); my_strdup(374, &xctx->sch_path[xctx->currsch],"."); xctx->sch_inst_number[xctx->currsch] = 1; - zoom_full(1, 0); + zoom_full(1, 0, 1); } } @@ -1644,21 +1646,34 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg Tcl_ResetResult(interp); } + /* 0 1 2 3 4 5 + * xschem print png file.png 400 300 */ else if(!strcmp(argv[1],"print") ) { /* 20171022 added png, svg */ cmd_found = 1; - if(argc >= 4) { - my_strncpy(plotfile, argv[3], S(plotfile)); - } else { - plotfile[0] = '\0'; + if(argc < 3) { + Tcl_SetResult(interp, "xschem print needs at least 1 more arguments: plot_type", TCL_STATIC); + return TCL_ERROR; } - if(argc==2 || (argc>=3 && !strcmp(argv[2],"pdf")) ) { + if(argc >= 4) my_strncpy(plotfile, argv[3], S(plotfile)); + + if(!strcmp(argv[2],"pdf")) { ps_draw(); } - else if(argc>=3 && !strcmp(argv[2],"png") ) { - print_image(); + else if(!strcmp(argv[2],"png")) { + int w = 0, h = 0; + if(argc >= 6) { + w = atoi(argv[4]); + h = atoi(argv[5]); + } + print_image(w, h); } - else if(argc>=3 && !strcmp(argv[2],"svg") ) { - svg_draw(); + else if(!strcmp(argv[2],"svg")) { + int w = 0, h = 0; + if(argc >= 6) { + w = atoi(argv[4]); + h = atoi(argv[5]); + } + svg_draw(w, h); } Tcl_ResetResult(interp); } @@ -1745,7 +1760,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg remove_symbols(); load_schematic(1, xctx->sch[xctx->currsch], 1); if(argc >= 3 && !strcmp(argv[2], "zoom_full") ) { - zoom_full(1, 0); + zoom_full(1, 0, 1); } else { draw(); } @@ -2494,14 +2509,14 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg else if(!strcmp(argv[1],"zoom_full")) { cmd_found = 1; - zoom_full(1, 0); + zoom_full(1, 0, 1); Tcl_ResetResult(interp); } else if(!strcmp(argv[1],"zoom_hilighted")) { cmd_found = 1; - zoom_full(1, 2); + zoom_full(1, 2, 1); Tcl_ResetResult(interp); } @@ -2522,7 +2537,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg else if(!strcmp(argv[1],"zoom_selected")) { cmd_found = 1; - zoom_full(1, 1); + zoom_full(1, 1, 1); Tcl_ResetResult(interp); } } diff --git a/src/svgdraw.c b/src/svgdraw.c index aff7203b..ab6a221f 100644 --- a/src/svgdraw.c +++ b/src/svgdraw.c @@ -567,181 +567,224 @@ static void fill_svg_colors() } -void svg_draw(void) +void svg_draw(int w, int h) { - double dx, dy; - int c,i, textlayer; - int old_grid; - int modified_save; - char *tmpstring=NULL; - const char *r, *textfont; + double dx, dy; + int c,i, textlayer; + int old_grid; + int modified_save; + char *tmpstring=NULL; + const char *r, *textfont; + int savew, saveh; + double savexor, saveyor, savezoom, savelw; - if(!plotfile[0]) { - my_strdup(61, &tmpstring, "tk_getSaveFile -title {Select destination file} -initialdir [pwd]"); - tcleval(tmpstring); - r = tclresult(); - my_free(963, &tmpstring); - if(r[0]) my_strncpy(plotfile, r, S(plotfile)); - else return; - } + double xor, yor, zoom, lw; - svg_restore_lw(); - - svg_colors=my_calloc(419, cadlayers, sizeof(Svg_color)); - if(svg_colors==NULL){ - fprintf(errfp, "svg_draw(): calloc error\n");tcleval( "exit"); - } - - fill_svg_colors(); - - old_grid=draw_grid; - draw_grid=0; - - dx=xctx->areax2-xctx->areax1; - dy=xctx->areay2-xctx->areay1; - dbg(1, "svg_draw(): dx=%g dy=%g\n", dx, dy); - - - modified_save=xctx->modified; - push_undo(); - trim_wires(); /* 20161121 add connection boxes on wires but undo at end */ - - - if(plotfile[0]) fd=fopen(plotfile, "w"); - else fd=fopen("plot.svg", "w"); - my_strncpy(plotfile,"", S(plotfile)); - - - fprintf(fd, "\n", dx, dy); - - fprintf(fd, "\n"); - fclose(fd); - draw_grid=old_grid; - my_free(964, &svg_colors); - - pop_undo(0); - xctx->modified=modified_save; + if(w > 0 && h > 0 ) { + xctx->xrect[0].x = 0; + xctx->xrect[0].y = 0; + xctx->xschem_w = xctx->xrect[0].width = savew; + xctx->xschem_h = xctx->xrect[0].height = saveh; + xctx->areax2 = savew+2*INT_WIDTH(savelw); + xctx->areay2 = saveh+2*INT_WIDTH(savelw); + xctx->areax1 = -2*INT_WIDTH(savelw); + xctx->areay1 = -2*INT_WIDTH(savelw); + xctx->lw = savelw; + xctx->areaw = xctx->areax2-xctx->areax1; + xctx->areah = xctx->areay2-xctx->areay1; + xctx->xorigin = savexor; + xctx->yorigin = saveyor; + xctx->zoom = savezoom; + xctx->mooz = 1 / savezoom; + } + draw_grid=old_grid; + my_free(964, &svg_colors); + + pop_undo(0); + xctx->modified=modified_save; } diff --git a/src/xinit.c b/src/xinit.c index d0e89309..66d37f9b 100644 --- a/src/xinit.c +++ b/src/xinit.c @@ -426,6 +426,7 @@ void alloc_xschem_data() } xctx->window = xctx->save_pixmap = 0; xctx->xrect[0].width = xctx->xrect[0].height = xctx->xrect[0].x = xctx->xrect[0].y = 0; + xctx->xschem_w = xctx->xschem_h = 0; #if HAS_CAIRO==1 xctx->cairo_ctx = xctx->cairo_save_ctx = NULL; xctx->cairo_sfc = xctx->cairo_save_sfc = NULL; @@ -779,7 +780,7 @@ void preview_window(const char *what, const char *tk_win_path, const char *filen dbg(1, "preview_window() draw, load schematic\n"); load_schematic(1,filename, 0); } - zoom_full(1, 0); /* draw */ + zoom_full(1, 0, 1); /* draw */ xctx = save_xctx; } else if(!strcmp(what, "destroy")) { @@ -824,7 +825,7 @@ void new_schematic(const char *what, const char *tk_win_path, const char *filena xctx->window = new_window; resetwin(1, 0, 1); /* create preview pixmap. resetwin(create_pixmap, clear_pixmap, force) */ load_schematic(1,filename, 0); - zoom_full(1, 0); /* draw */ + zoom_full(1, 0, 1); /* draw */ } else if(!strcmp(what, "redraw")) { Xschem_ctx *save; save = xctx; @@ -1020,7 +1021,7 @@ void resetwin(int create_pixmap, int clear_pixmap, int force) } } if(pending_fullzoom) { - zoom_full(0, 0); + zoom_full(0, 0, 1); pending_fullzoom=0; } dbg(1, "resetwin(): Window reset\n"); @@ -1575,7 +1576,7 @@ int Tcl_AppInit(Tcl_Interp *inter) - zoom_full(0, 0); /* Necessary to tell xschem the + zoom_full(0, 0, 1); /* Necessary to tell xschem the * initial area to display */ pending_fullzoom=1; @@ -1618,17 +1619,17 @@ int Tcl_AppInit(Tcl_Interp *inter) xctx->areay1 = -2; xctx->areaw = xctx->areax2-xctx->areax1; xctx->areah = xctx->areay2-xctx->areay1; - zoom_full(0, 0); + zoom_full(0, 0, 2); ps_draw(); } else if(do_print == 2) { if(!has_x) { dbg(0, "xschem: can not do a png export if no X11 present / Xserver running (check if DISPLAY set).\n"); } else { tcleval("tkwait visibility .drw"); - print_image(); + print_image(0, 0); } } - else svg_draw(); + else svg_draw(0, 0); } if(do_simulation) { diff --git a/src/xschem.h b/src/xschem.h index db1f0401..0c11afc1 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -821,8 +821,8 @@ extern int search(const char *tok, const char *val, int sub, int sel, int what); extern int process_options(int argc, char **argv); extern void calc_drawing_bbox(xRect *boundbox, int selected); extern void ps_draw(void); -extern void svg_draw(void); -extern void print_image(); +extern void svg_draw(int w, int h); +extern void print_image(int user_w, int user_h); extern const char *skip_dir(const char *str); extern const char *get_cell(const char *str, int no_of_dir); extern const char *get_cell_w_ext(const char *str, int no_of_dir); @@ -831,13 +831,14 @@ extern const char *abs_sym_path(const char *s, const char *ext); extern const char *add_ext(const char *f, const char *ext); extern void make_symbol(void); extern const char *get_sym_template(char *s, char *extra); -extern void zoom_full(int draw, int sel); +extern void zoom_full(int draw, int sel, int flags); /* bit0: invoke change_linewidth(), bit1: centered zoom */ extern void updatebbox(int count,xRect *boundbox,xRect *tmp); extern void draw_selection(GC g, int interruptable); extern void delete(void); extern void delete_only_rect_line_arc_poly(void); extern void polygon_bbox(double *x, double *y, int points, double *bx1, double *by1, double *bx2, double *by2); -extern void arc_bbox(double x, double y, double r, double a, double b, double *bx1, double *by1, double *bx2, double *by2); +extern void arc_bbox(double x, double y, double r, double a, double b, + double *bx1, double *by1, double *bx2, double *by2); extern void bbox(int what,double x1,double y1, double x2, double y2); extern int set_text_custom_font(xText *txt); extern int text_bbox(const char * str,double xscale, double yscale,