diff --git a/src/actions.c b/src/actions.c index b0818b05..df4faef7 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, 1); + zoom_full(1, 0, 1, 0.97); } } @@ -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, 1); + zoom_full(1, 0, 1, 0.97); } } @@ -1352,12 +1352,11 @@ void calc_drawing_bbox(xRect *boundbox, int selected) } -/* bit0: invoke change_linewidth(), bit1: centered zoom */ -void zoom_full(int dr, int sel, int flags) +/* flags: bit0: invoke change_linewidth()/XSetLineAttributes, bit1: centered zoom */ +void zoom_full(int dr, int sel, int flags, double shrink) { xRect boundbox; double yzoom; - double shrink = 0.98; /* shrink drawing to make room for margins */ double bboxw, bboxh, schw, schh; if(flags & 1) { @@ -1431,7 +1430,68 @@ void view_unzoom(double z) draw(); } -void zoom_box(int what) +void set_viewport_size(int w, int h, double lw) +{ + xctx->xrect[0].x = 0; + xctx->xrect[0].y = 0; + xctx->xschem_w = xctx->xrect[0].width = w; + xctx->xschem_h = xctx->xrect[0].height = h; + xctx->areax2 = w+2*INT_WIDTH(lw); + xctx->areay2 = h+2*INT_WIDTH(lw); + xctx->areax1 = -2*INT_WIDTH(lw); + xctx->areay1 = -2*INT_WIDTH(lw); + xctx->lw = lw; + xctx->areaw = xctx->areax2-xctx->areax1; + xctx->areah = xctx->areay2-xctx->areay1; +} + +void save_restore_zoom(int save) +{ + static int savew, saveh; + static double savexor, saveyor, savezoom, savelw; + + if(save) { + savew = xctx->xschem_w; + saveh = xctx->xschem_h; + savelw = xctx->lw; + savexor = xctx->xorigin; + saveyor = xctx->yorigin; + savezoom = xctx->zoom; + } else { + 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; + } +} + +void zoom_box(double x1, double y1, double x2, double y2, double factor) +{ + double yy1; + if(factor == 0.) factor = 1.; + RECTORDER(x1,y1,x2,y2); + xctx->xorigin=-x1;xctx->yorigin=-y1; + xctx->zoom=(x2-x1)/(xctx->areaw-4*INT_WIDTH(xctx->lw)); + yy1=(y2-y1)/(xctx->areah-4*INT_WIDTH(xctx->lw)); + if(yy1>xctx->zoom) xctx->zoom=yy1; + xctx->zoom*= factor; + xctx->mooz=1/xctx->zoom; + xctx->xorigin=xctx->xorigin+xctx->areaw*xctx->zoom*(1-1/factor)/2; + xctx->yorigin=xctx->yorigin+xctx->areah*xctx->zoom*(1-1/factor)/2; +} + +void zoom_rectangle(int what) { if( (what & START) ) { @@ -1450,7 +1510,7 @@ void zoom_box(int what) xctx->mooz=1/xctx->zoom; change_linewidth(-1.); draw(); - dbg(1, "zoom_box(): coord: %.16g %.16g %.16g %.16g zoom=%.16g\n", + dbg(1, "zoom_rectangle(): coord: %.16g %.16g %.16g %.16g zoom=%.16g\n", xctx->nl_x1,xctx->nl_y1,xctx->mousex_snap, xctx->mousey_snap,xctx->zoom); } if(what & RUBBER) diff --git a/src/callback.c b/src/callback.c index d0e2c074..87636d21 100644 --- a/src/callback.c +++ b/src/callback.c @@ -181,7 +181,7 @@ int callback(int event, int mx, int my, KeySym key, dbg(1, "callback(): Expose\n"); break; case ConfigureNotify: - resetwin(1, 1, 0); + resetwin(1, 1, 0, 0, 0); draw(); break; @@ -212,7 +212,7 @@ int callback(int event, int mx, int my, KeySym key, statusmsg(str,1); } if(xctx->ui_state & STARTPAN) pan(RUBBER); - if(xctx->ui_state & STARTZOOM) zoom_box(RUBBER); + if(xctx->ui_state & STARTZOOM) zoom_rectangle(RUBBER); if(xctx->ui_state & STARTSELECT && !(xctx->ui_state & PLACE_SYMBOL) && !(xctx->ui_state & STARTPAN2)) { if( (state & Button1Mask) && (state & Mod1Mask)) { /* 20171026 added unselect by area */ select_rect(RUBBER,0); @@ -578,8 +578,8 @@ int callback(int event, int mx, int my, KeySym key, } if(key=='z' && state == 0) /* zoom box */ { - dbg(1, "callback(): zoom_box call\n"); - zoom_box(START);break; + dbg(1, "callback(): zoom_rectangle call\n"); + zoom_rectangle(START);break; } if(key=='Z' && state == ShiftMask) /* zoom in */ { @@ -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(0, 0); + svg_draw(); 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(0, 0); + print_image(); 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, 1); + zoom_full(1, 0, 1, 0.97); 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, 1); + zoom_full(1, 0, 1, 0.97); break; } if((key=='z' && state==ControlMask)) /* zoom out */ @@ -1526,7 +1526,7 @@ int callback(int event, int mx, int my, KeySym key, break; } if(xctx->ui_state & MENUSTARTZOOM) { - zoom_box(START); + zoom_rectangle(START); xctx->ui_state &=~MENUSTARTZOOM; break; } @@ -1535,7 +1535,7 @@ int callback(int event, int mx, int my, KeySym key, break; } if(xctx->ui_state & STARTZOOM) { - zoom_box(END); + zoom_rectangle(END); break; } if(xctx->ui_state & STARTWIRE) { diff --git a/src/draw.c b/src/draw.c index 1cc02f4b..d8551121 100644 --- a/src/draw.c +++ b/src/draw.c @@ -47,31 +47,15 @@ int textclip(int x1,int y1,int x2,int y2, return 1; } -void print_image(int user_w, int user_h) +void print_image() { - int w, h, tmp, ww, hh, save_draw_grid, changed_size; - int modified_save; + int modified_save, save_draw_grid; char cmd[PATH_MAX+100]; const char *r; char *tmpstring=NULL; - double saveorx, saveory, savezoom; if(!has_x) return ; - - changed_size = 0; - w = ww = xctx->xschem_w; - h = hh = xctx->xschem_h; - 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) { - w = xctx->xschem_w; h = xctx->xschem_h; - } else { - if(w != xctx->xschem_w || h != xctx->xschem_h) changed_size = 1; - } + if(!plotfile[0]) { my_strdup(60, &tmpstring, "tk_getSaveFile -title {Select destination file} -initialdir [pwd]"); tcleval(tmpstring); r = tclresult(); @@ -82,76 +66,21 @@ void print_image(int user_w, int user_h) modified_save=xctx->modified; /* 20161121 save state */ push_undo(); trim_wires(); /* 20161121 add connection boxes on wires but undo at end */ - - XUnmapWindow(display, xctx->window); - - xctx->xrect[0].x = 0; - xctx->xrect[0].y = 0; - xctx->xschem_w = xctx->xrect[0].width = w; - xctx->xschem_h = xctx->xrect[0].height = h; - xctx->areax2 = w+2*INT_WIDTH(xctx->lw); - xctx->areay2 = h+2*INT_WIDTH(xctx->lw); - xctx->areax1 = -2*INT_WIDTH(xctx->lw); - xctx->areay1 = -2*INT_WIDTH(xctx->lw); - xctx->areaw = xctx->areax2-xctx->areax1; - xctx->areah = xctx->areay2-xctx->areay1; - saveorx = xctx->xorigin; - saveory = xctx->yorigin; - savezoom = xctx->zoom; -#ifdef __unix__ - XFreePixmap(display,xctx->save_pixmap); - /* xctx->save_pixmap = XCreatePixmap(display,xctx->window,xctx->areaw,xctx->areah,depth); */ - xctx->save_pixmap = XCreatePixmap(display,xctx->window,w,h,depth); /* 20161119 pixmap should be exact size of */ - /* cliprectangle to avoid random borders */ -#else - Tk_FreePixmap(display, xctx->save_pixmap); - xctx->save_pixmap = Tk_GetPixmap(display, xctx->window, w, h, depth); -#endif - XSetTile(display, xctx->gctiled, xctx->save_pixmap); - - #if HAS_CAIRO==1 - cairo_destroy(xctx->cairo_save_ctx); - cairo_surface_destroy(xctx->cairo_save_sfc); - - #if HAS_XRENDER==1 - #if HAS_XCB==1 - xctx->cairo_save_sfc = cairo_xcb_surface_create_with_xrender_format(xcbconn, screen_xcb, xctx->save_pixmap, &format_rgb, w, h); - #else - xctx->cairo_save_sfc = cairo_xlib_surface_create_with_xrender_format(display, - xctx->save_pixmap, DefaultScreenOfDisplay(display), render_format, w, h); - #endif /*HAS_XCB */ - #else - xctx->cairo_save_sfc = cairo_xlib_surface_create(display, xctx->save_pixmap, visual, w, h); - #endif /*HAS_XRENDER */ - if(cairo_surface_status(xctx->cairo_save_sfc)!=CAIRO_STATUS_SUCCESS) { - fprintf(errfp, "ERROR: invalid cairo xcb surface\n"); - exit(-1); - } - xctx->cairo_save_ctx = cairo_create(xctx->cairo_save_sfc); - cairo_set_line_width(xctx->cairo_save_ctx, 1); - cairo_set_line_join(xctx->cairo_save_ctx, CAIRO_LINE_JOIN_ROUND); - cairo_set_line_cap(xctx->cairo_save_ctx, CAIRO_LINE_CAP_ROUND); - cairo_select_font_face (xctx->cairo_save_ctx, cairo_font_name, - CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); - cairo_set_font_size (xctx->cairo_save_ctx, 20); - #endif /*HAS_CAIRO */ - for(tmp=0;tmpxrect, 1, Unsorted); XSetClipRectangles(display, gcstipple[tmp], 0,0, xctx->xrect, 1, Unsorted); } XSetClipRectangles(display, xctx->gctiled, 0,0, xctx->xrect, 1, Unsorted); + #endif save_draw_grid = draw_grid; draw_grid=0; draw_pixmap=1; - if(changed_size) zoom_full(0, 0, 3); /* flags : 2 + 1 , center zoom & change_linewidth */ - draw(); -#ifdef __unix__ + #ifdef __unix__ XpmWriteFileFromPixmap(display, "plot.xpm", xctx->save_pixmap,0, NULL ); /* .gz ???? */ -#endif + #endif dbg(1, "print_image(): Window image saved\n"); - if(plotfile[0]) { my_snprintf(cmd, S(cmd), "convert_to_png plot.xpm %s", plotfile); tcleval(cmd); @@ -159,72 +88,10 @@ void print_image(int user_w, int user_h) my_strncpy(plotfile,"", S(plotfile)); pop_undo(0); /* 20161121 restore state */ xctx->modified=modified_save; - - w=ww;h=hh; - xctx->xrect[0].x = 0; - xctx->xrect[0].y = 0; - xctx->xschem_w = xctx->xrect[0].width = w; - xctx->xschem_h = xctx->xrect[0].height = h; - xctx->areax2 = w+2*INT_WIDTH(xctx->lw); - xctx->areay2 = h+2*INT_WIDTH(xctx->lw); - xctx->areax1 = -2*INT_WIDTH(xctx->lw); - xctx->areay1 = -2*INT_WIDTH(xctx->lw); - xctx->areaw = xctx->areax2-xctx->areax1; - xctx->areah = xctx->areay2-xctx->areay1; - xctx->zoom = savezoom; - xctx->mooz = 1/xctx->zoom; - xctx->xorigin = saveorx; - xctx->yorigin = saveory; -#ifdef __unix__ - XFreePixmap(display,xctx->save_pixmap); - xctx->save_pixmap = XCreatePixmap(display,xctx->window,xctx->areaw,xctx->areah,depth); -#else - Tk_FreePixmap(display, xctx->save_pixmap); - xctx->save_pixmap = Tk_GetPixmap(display, xctx->window, xctx->areaw, xctx->areah, depth); -#endif - XSetTile(display, xctx->gctiled, xctx->save_pixmap); - - -#if HAS_CAIRO==1 - cairo_destroy(xctx->cairo_save_ctx); - cairo_surface_destroy(xctx->cairo_save_sfc); - - #if HAS_XRENDER==1 - #if HAS_XCB==1 - xctx->cairo_save_sfc = cairo_xcb_surface_create_with_xrender_format(xcbconn, screen_xcb, xctx->save_pixmap, &format_rgb, w, h); - #else - xctx->cairo_save_sfc = cairo_xlib_surface_create_with_xrender_format (display, - xctx->save_pixmap, DefaultScreenOfDisplay(display), render_format, w, h); - #endif /*HAS_XCB */ - #else - xctx->cairo_save_sfc = cairo_xlib_surface_create(display, xctx->save_pixmap, visual, w, h); - #endif /*HAS_XRENDER */ - if(cairo_surface_status(xctx->cairo_save_sfc)!=CAIRO_STATUS_SUCCESS) { - fprintf(errfp, "ERROR: invalid cairo xcb surface\n"); - exit(-1); - } - xctx->cairo_save_ctx = cairo_create(xctx->cairo_save_sfc); - cairo_set_line_width(xctx->cairo_save_ctx, 1); - cairo_set_line_join(xctx->cairo_save_ctx, CAIRO_LINE_JOIN_ROUND); - cairo_set_line_cap(xctx->cairo_save_ctx, CAIRO_LINE_CAP_ROUND); - cairo_select_font_face (xctx->cairo_save_ctx, cairo_font_name, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); - cairo_set_font_size (xctx->cairo_save_ctx, 20); - #endif /*HAS_CAIRO */ - - for(tmp=0;tmpgctiled, None); - - XMapWindow(display, xctx->window); draw_grid=save_draw_grid; draw_pixmap=1; - draw(); } - #if HAS_CAIRO==1 void set_cairo_color(int layer) { diff --git a/src/globals.c b/src/globals.c index ddee6a41..7e176a5e 100644 --- a/src/globals.c +++ b/src/globals.c @@ -98,6 +98,7 @@ unsigned char pixdata_init[22][32]={ /* fill patterns... indexed by laynumb. GC *gcstipple,*gc; Pixmap *pixmap = NULL; Display *display; +int screen_number; Pixmap cad_icon_pixmap=0, cad_icon_mask=0; XColor xcolor_array[256]; Visual *visual; diff --git a/src/psprint.c b/src/psprint.c index e7fae6c3..26feee27 100644 --- a/src/psprint.c +++ b/src/psprint.c @@ -573,6 +573,8 @@ void ps_draw(void) double dx, dy, scale, scaley; int landscape=1; double margin=0; /* in postscript points, (1/72)". No need to add margin as xschem zoom full already has margins.*/ + + /* Legal: 612 792 */ double pagex=842;/* a4, in postscript points, (1/72)" */ double pagey=595;/* a4, in postscript points, (1/72)" */ xRect boundbox; @@ -632,8 +634,9 @@ void ps_draw(void) dbg(1, "ps_draw(): bbox: x1=%g y1=%g x2=%g y2=%g\n", boundbox.x1, boundbox.y1, boundbox.x2, boundbox.y2); fprintf(fd, "%%!PS-Adobe-3.0\n"); - fprintf(fd, "%%%%DocumentMedia: %s %g %g 80 () ()\n", landscape ? "a4land" : "a4", pagex, pagey); - fprintf(fd, "%%%%Orientation: Portrait\n"); + /* fprintf(fd, "%%%%DocumentMedia: %s %g %g 80 () ()\n", landscape ? "a4land" : "a4", pagex, pagey); */ + fprintf(fd, "%%%%DocumentMedia: %s %g %g 80 () ()\n", "a4", pagex, pagey); + fprintf(fd, "%%%%PageOrientation: %s\n", landscape ? "Landscape" : "Portrait"); fprintf(fd, "%%%%Title: xschem plot\n"); fprintf(fd, "%%%%Creator: xschem\n"); fprintf(fd, "%%%%Pages: 1\n"); diff --git a/src/save.c b/src/save.c index e1e2d68f..8a239c59 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, 1); + zoom_full(1, 0, 1, 0.97); } /* 20111023 align selected object to current grid setting */ diff --git a/src/scheduler.c b/src/scheduler.c index 3fdca4d3..39aef97c 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -624,6 +624,12 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg else Tcl_SetResult(interp, "0",TCL_STATIC); } + else if(!strcmp(argv[2],"no_draw")) { + if( no_draw != 0 ) + Tcl_SetResult(interp, "1",TCL_STATIC); + else + Tcl_SetResult(interp, "0",TCL_STATIC); + } else if(!strcmp(argv[2],"only_probes")) { if( only_probes != 0 ) Tcl_SetResult(interp, "1",TCL_STATIC); @@ -892,6 +898,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg printf("areah=%d\n", xctx->areah); printf("color_ps=%d\n", color_ps); printf("hilight_nets=%d\n", xctx->hilight_nets); + printf("semaphore=%d\n", xctx->semaphore); printf("need_reb_sel_arr=%d\n", xctx->need_reb_sel_arr); printf("******* end global variables:*******\n"); } @@ -1367,7 +1374,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, 1); + zoom_full(1, 0, 1, 0.97); } } else if(argc==2) { @@ -1404,7 +1411,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, 1); + zoom_full(1, 0, 1, 0.97); } } @@ -1646,35 +1653,109 @@ 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 */ + /* img x y size xschem area to export + * 0 1 2 3 4 5 6 7 8 9 + * xschem print png file.png 400 300 [ -300 -200 300 200 ] + * xschem print svg file.svg 400 300 [ -300 -200 300 200 ] + * xschem print ps file.ps + * xschem print pdf file.pdf + */ + else if(!strcmp(argv[1],"print") ) { + int save_nodraw, save_draw_window, save_draw_pixmap; cmd_found = 1; + save_nodraw = no_draw; + save_draw_window = draw_window; + save_draw_pixmap = draw_pixmap; + no_draw = 1; + draw_window = 0; + draw_pixmap = 0; if(argc < 3) { Tcl_SetResult(interp, "xschem print needs at least 1 more arguments: plot_type", TCL_STATIC); return TCL_ERROR; } if(argc >= 4) my_strncpy(plotfile, argv[3], S(plotfile)); - if(!strcmp(argv[2],"pdf")) { + if(!strcmp(argv[2],"pdf") || !strcmp(argv[2],"ps")) { ps_draw(); } else if(!strcmp(argv[2],"png")) { int w = 0, h = 0; - if(argc >= 6) { + double x1, y1, x2, y2; + if(argc == 6) { w = atoi(argv[4]); h = atoi(argv[5]); + save_restore_zoom(1); + set_viewport_size(w, h, 0.8); + zoom_full(0, 0, 2, 0.97); + resetwin(1, 1, 1, w, h); + no_draw = 0; + draw_pixmap = 1; + print_image(); + draw_pixmap = 0; + no_draw = 1; + save_restore_zoom(0); + resetwin(1, 1, 1, 0, 0); + change_linewidth(-1.); + draw(); + } else if( argc == 10) { + w = atoi(argv[4]); + h = atoi(argv[5]); + x1 = atof(argv[6]); + y1 = atof(argv[7]); + x2 = atof(argv[8]); + y2 = atof(argv[9]); + save_restore_zoom(1); + set_viewport_size(w, h, 0.8); + zoom_box(x1, y1, x2, y2, 1.0); + resetwin(1, 1, 1, w, h); + no_draw = 0; + draw_pixmap = 1; + print_image(); + draw_pixmap = 0; + no_draw = 1; + save_restore_zoom(0); + resetwin(1, 1, 1, 0, 0); + change_linewidth(-1.); + draw(); + } else { + no_draw = 0; + draw_pixmap = 1; + print_image(); + draw_pixmap = 0; + no_draw = 1; } - print_image(w, h); } else if(!strcmp(argv[2],"svg")) { int w = 0, h = 0; - if(argc >= 6) { + double x1, y1, x2, y2; + if(argc == 6) { w = atoi(argv[4]); h = atoi(argv[5]); + save_restore_zoom(1); + set_viewport_size(w, h, 0.8); + zoom_full(0, 0, 2, 0.97); + svg_draw(); + save_restore_zoom(0); + } else if( argc == 10) { + w = atoi(argv[4]); + h = atoi(argv[5]); + x1 = atof(argv[6]); + y1 = atof(argv[7]); + x2 = atof(argv[8]); + y2 = atof(argv[9]); + save_restore_zoom(1); + set_viewport_size(w, h, 0.8); + zoom_box(x1, y1, x2, y2, 1.0); + svg_draw(); + save_restore_zoom(0); + } else { + svg_draw(); } - svg_draw(w, h); } + no_draw = save_nodraw; + draw_window = save_draw_window; + draw_pixmap = save_draw_pixmap; + draw(); Tcl_ResetResult(interp); } @@ -1760,7 +1841,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, 1); + zoom_full(1, 0, 1, 0.97); } else { draw(); } @@ -2476,7 +2557,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg else if(argv[1][0] == 'z') { if(!strcmp(argv[1],"zoom_box")) { - double x1, y1, x2, y2, yy1, factor; + double x1, y1, x2, y2, factor; cmd_found = 1; dbg(1, "scheduler(): xschem zoom_box: argc=%d, argv[2]=%s\n", argc, argv[2]); if(argc==6 || argc == 7) { @@ -2487,16 +2568,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg if(argc == 7) factor = atof(argv[6]); else factor = 1.; if(factor == 0.) factor = 1.; - RECTORDER(x1,y1,x2,y2); - xctx->xorigin=-x1;xctx->yorigin=-y1; - xctx->zoom=(x2-x1)/(xctx->areaw-4*INT_WIDTH(xctx->lw)); - yy1=(y2-y1)/(xctx->areah-4*INT_WIDTH(xctx->lw)); - if(yy1>xctx->zoom) xctx->zoom=yy1; - xctx->mooz=1/xctx->zoom; - xctx->xorigin=xctx->xorigin+xctx->areaw*xctx->zoom*(1-1/factor)/2; - xctx->yorigin=xctx->yorigin+xctx->areah*xctx->zoom*(1-1/factor)/2; - xctx->zoom*= factor; - xctx->mooz=1/xctx->zoom; + zoom_box(x1, y1, x2, y2, factor); change_linewidth(-1.); draw(); } @@ -2506,17 +2578,32 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg Tcl_ResetResult(interp); } + /* xschem zoom_full [center | nodraw | nolinewidth] */ else if(!strcmp(argv[1],"zoom_full")) { + int i, flags = 1; + int draw = 1; + double shrink = 0.97; + char * endptr; + cmd_found = 1; - zoom_full(1, 0, 1); + for(i = 2; i < argc; i++) { + if(!strcmp(argv[i], "center")) flags |= 2; + else if(!strcmp(argv[i], "nodraw")) draw = 0; + else if(!strcmp(argv[i], "nolinewidth")) flags &= ~1; + else { + shrink = strtod(argv[i], &endptr); + if(endptr == argv[i]) shrink = 1.0; + } + } + zoom_full(draw, 0, flags, shrink); Tcl_ResetResult(interp); } else if(!strcmp(argv[1],"zoom_hilighted")) { cmd_found = 1; - zoom_full(1, 2, 1); + zoom_full(1, 2, 1, 0.97); Tcl_ResetResult(interp); } @@ -2537,7 +2624,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, 1); + zoom_full(1, 1, 1, 0.97); Tcl_ResetResult(interp); } } diff --git a/src/select.c b/src/select.c index 6264275e..724aea86 100644 --- a/src/select.c +++ b/src/select.c @@ -400,7 +400,7 @@ void bbox(int what,double x1,double y1, double x2, double y2) fprintf(errfp, "ERROR: rentrant bbox() call\n"); tcleval("alert_ {ERROR: reentrant bbox() call} {}"); } - bbx1 = 300000000; + bbx1 = 300000000; /* screen coordinates */ bbx2 = 0; bby1 = 300000000; bby2 = 0; @@ -451,6 +451,7 @@ void bbox(int what,double x1,double y1, double x2, double y2) XSetClipMask(display, gc[i], None); /* 20171110 optimization, clipping already done in software */ XSetClipMask(display, gcstipple[i], None); /* 20171110 optimization, clipping already done in software */ } + #if HAS_CAIRO==1 cairo_reset_clip(xctx->cairo_ctx); cairo_reset_clip(xctx->cairo_save_ctx); diff --git a/src/svgdraw.c b/src/svgdraw.c index ab6a221f..7c8bf43a 100644 --- a/src/svgdraw.c +++ b/src/svgdraw.c @@ -567,7 +567,7 @@ static void fill_svg_colors() } -void svg_draw(int w, int h) +void svg_draw(void) { double dx, dy; int c,i, textlayer; @@ -576,43 +576,6 @@ void svg_draw(int w, int h) char *tmpstring=NULL; const char *r, *textfont; - int savew, saveh; - double savexor, saveyor, savezoom, savelw; - - double xor, yor, zoom, lw; - - - if( w > 0 && h > 0 ) { - savew = xctx->xschem_w; - saveh = xctx->xschem_h; - savelw = xctx->lw; - savexor = xctx->xorigin; - saveyor = xctx->yorigin; - savezoom = xctx->zoom; - - lw = 0.8; - xor = 0.0; - yor = 0.0; - zoom = 1.0; - - /* give: w, h, xor, yor, zoom, lw */ - xctx->xrect[0].x = 0; - xctx->xrect[0].y = 0; - xctx->xschem_w = xctx->xrect[0].width = w; - xctx->xschem_h = xctx->xrect[0].height = h; - xctx->areax2 = w+2*INT_WIDTH(lw); - xctx->areay2 = h+2*INT_WIDTH(lw); - xctx->areax1 = -2*INT_WIDTH(lw); - xctx->areay1 = -2*INT_WIDTH(lw); - xctx->lw = lw; - xctx->areaw = xctx->areax2-xctx->areax1; - xctx->areah = xctx->areay2-xctx->areay1; - xctx->xorigin = xor; - xctx->yorigin = yor; - xctx->zoom = zoom; - xctx->mooz = 1 / zoom; - zoom_full(0, 0, 2); /* draw, sel, center|change_linew */ - } if(!plotfile[0]) { my_strdup(61, &tmpstring, "tk_getSaveFile -title {Select destination file} -initialdir [pwd]"); tcleval(tmpstring); @@ -629,21 +592,18 @@ void svg_draw(int w, int h) fill_svg_colors(); old_grid=draw_grid; draw_grid=0; - dx=xctx->areax2-xctx->areax1; - dy=xctx->areay2-xctx->areay1; + dx=xctx->xschem_w; + dy=xctx->xschem_h; 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); - 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); diff --git a/src/xinit.c b/src/xinit.c index 66d37f9b..a7c6b4b6 100644 --- a/src/xinit.c +++ b/src/xinit.c @@ -27,7 +27,6 @@ static int init_done=0; /* 20150409 to avoid double call by Xwindows close and TclExitHandler */ static XSetWindowAttributes winattr; -static int screen_number; static Tk_Window tkwindow, mainwindow; static XWMHints *hints_ptr; static Window topwindow; @@ -545,7 +544,7 @@ void xwin_exit(void) delete_hilight_net(); get_unnamed_node(0, 0, 0); if(has_x) { - resetwin(0, 1, 1); /* create_pixmap, clear_pixmap, force */ + resetwin(0, 1, 1, 0, 0); /* create_pixmap, clear_pixmap, force */ dbg(1, "xwin_exit(): Releasing pixmaps and cairo data structures\n"); for(i=0;iwindow = pre_window; - resetwin(1, 0, 1); /* create preview pixmap. resetwin(create_pixmap, clear_pixmap, force) */ + resetwin(1, 0, 1, 0, 0); /* create preview pixmap. resetwin(create_pixmap, clear_pixmap, force) */ dbg(1, "preview_window() draw, load schematic\n"); load_schematic(1,filename, 0); } - zoom_full(1, 0, 1); /* draw */ + zoom_full(1, 0, 1, 0.97); /* draw */ xctx = save_xctx; } else if(!strcmp(what, "destroy")) { @@ -823,9 +822,9 @@ void new_schematic(const char *what, const char *tk_win_path, const char *filena save_xctx[cnt] = xctx; dbg(1, "new_schematic() draw, load schematic\n"); xctx->window = new_window; - resetwin(1, 0, 1); /* create preview pixmap. resetwin(create_pixmap, clear_pixmap, force) */ + resetwin(1, 0, 1, 0, 0); /* create preview pixmap. resetwin(create_pixmap, clear_pixmap, force) */ load_schematic(1,filename, 0); - zoom_full(1, 0, 1); /* draw */ + zoom_full(1, 0, 1, 0.97); /* draw */ } else if(!strcmp(what, "redraw")) { Xschem_ctx *save; save = xctx; @@ -964,22 +963,38 @@ void resetcairo(int create, int clear, int force_or_resize) #endif /* HAS_CAIRO */ } -void resetwin(int create_pixmap, int clear_pixmap, int force) +/* w and h (if > 0 ) parameters force reset pixmap to w x h, regardless of window size */ +void resetwin(int create_pixmap, int clear_pixmap, int force, int w, int h) { unsigned int width, height; XWindowAttributes wattr; + int status; + #ifndef __unix__ + HWND hwnd = Tk_GetHWND(xctx->window); + RECT rct; + #endif + if(has_x) { -#ifdef __unix__ - if( XGetWindowAttributes(display, xctx->window, &wattr) ) { - width = wattr.width; - height = wattr.height; -#else - HWND hwnd = Tk_GetHWND(xctx->window); - RECT rct; - if (GetWindowRect(hwnd, &rct)) { - width = rct.right - rct.left; - height = rct.bottom - rct.top; -#endif + if(w && h) { + width = w; + height = h; + status = 1; + } else { + #ifdef __unix__ + status = XGetWindowAttributes(display, xctx->window, &wattr); + if(status) { + width = wattr.width; + height = wattr.height; + } + #else + status = GetWindowRect(hwnd, &rct); + if(status) { + width = rct.right - rct.left; + height = rct.bottom - rct.top; + } + #endif + } + if(status) { /* if(wattr.map_state==IsUnmapped) return; */ xctx->xschem_w=width; xctx->xschem_h=height; @@ -1021,7 +1036,7 @@ void resetwin(int create_pixmap, int clear_pixmap, int force) } } if(pending_fullzoom) { - zoom_full(0, 0, 1); + zoom_full(0, 0, 1, 0.97); pending_fullzoom=0; } dbg(1, "resetwin(): Window reset\n"); @@ -1466,7 +1481,7 @@ int Tcl_AppInit(Tcl_Interp *inter) #if HAS_XRENDER==1 render_format = XRenderFindStandardFormat(display, PictStandardRGB24); #endif - resetwin(1, 0, 1); + resetwin(1, 0, 1, 0, 0); #if HAS_CAIRO==1 /* load font from tcl 20171112 */ tcleval("xschem set svg_font_name $svg_font_name"); @@ -1563,7 +1578,7 @@ int Tcl_AppInit(Tcl_Interp *inter) to tcl is_xschem_file that could change netlist_type to symbol */ load_schematic(1, f, !do_netlist); Tcl_VarEval(interp, "update_recent_file {", f, "}", NULL); - } else { + } else if(!tcl_script[0]) { char * tmp; char filename[PATH_MAX]; tmp = (char *) tclgetvar("XSCHEM_START_WINDOW"); @@ -1576,7 +1591,7 @@ int Tcl_AppInit(Tcl_Interp *inter) - zoom_full(0, 0, 1); /* Necessary to tell xschem the + zoom_full(0, 0, 1, 0.97); /* Necessary to tell xschem the * initial area to display */ pending_fullzoom=1; @@ -1619,17 +1634,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, 2); + zoom_full(0, 0, 2, 0.97); 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(0, 0); + print_image(); } } - else svg_draw(0, 0); + else svg_draw(); } if(do_simulation) { @@ -1649,7 +1664,8 @@ int Tcl_AppInit(Tcl_Interp *inter) } if(tcl_script[0]) { - Tcl_VarEval(interp, "source ", tcl_script, NULL); + + Tcl_VarEval(interp, "update; source ", tcl_script, NULL); } if(quit) { diff --git a/src/xschem.h b/src/xschem.h index 0c11afc1..87161ac8 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -776,6 +776,7 @@ extern unsigned char **pixdata; extern unsigned char pixdata_init[22][32]; extern GC *gc, *gcstipple, gctiled; extern Display *display; +extern int screen_number; extern XRectangle *rectangle; extern Pixmap cad_icon_pixmap, cad_icon_mask, *pixmap; extern XColor xcolor_array[]; @@ -821,8 +822,9 @@ 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(int w, int h); -extern void print_image(int user_w, int user_h); +extern void svg_draw(void); +extern void set_viewport_size(int w, int h, double lw); +extern void print_image(); 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,7 +833,8 @@ 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, int flags); /* bit0: invoke change_linewidth(), bit1: centered zoom */ +/* bit0: invoke change_linewidth(), bit1: centered zoom */ +extern void zoom_full(int draw, int sel, int flags, double shrink); extern void updatebbox(int count,xRect *boundbox,xRect *tmp); extern void draw_selection(GC g, int interruptable); extern void delete(void); @@ -871,7 +874,7 @@ extern int Tcl_AppInit(Tcl_Interp *interp); extern int source_tcl_file(char *s); extern int callback(int event, int mx, int my, KeySym key, int button, int aux, int state); -extern void resetwin(int create_pixmap, int clear_pixmap, int force); +extern void resetwin(int create_pixmap, int clear_pixmap, int force, int w, int h); extern void find_closest_net(double mx,double my); extern void find_closest_box(double mx,double my); extern void find_closest_arc(double mx,double my); @@ -991,7 +994,9 @@ extern void find_inst_to_be_redrawn(const char *node); extern void find_inst_hash_clear(void); extern void pan(int what); extern void pan2(int what, int mx, int my); -extern void zoom_box(int what); +extern void zoom_rectangle(int what); +extern void zoom_box(double x1, double y1, double x2, double y2, double factor); +extern void save_restore_zoom(int save); extern void select_rect(int what, int select); extern void new_rect(int what); extern void new_polygon(int what); diff --git a/src/xschem.tcl b/src/xschem.tcl index 27fb2d4f..d7a0489a 100644 --- a/src/xschem.tcl +++ b/src/xschem.tcl @@ -3190,7 +3190,9 @@ global env has_x bind $window_path {xschem callback -3 %x %y 0 %b 0 %s} bind $window_path {xschem callback %T %x %y 0 %w %h %s} bind $window_path {xschem windowid; xschem callback %T %x %y 0 %w %h 0} - bind $window_path {xschem callback %T %x %y 0 %b 0 %s} + bind $window_path { + xschem callback %T %x %y 0 %b 0 %s + } if {$::OS == "Windows"} { bind $window_path { if {%D<0} { @@ -3207,7 +3209,9 @@ global env has_x bind $window_path {xschem callback %T %x %y %N 0 0 [expr {$ControlMask + $Mod1Mask}]} bind $window_path {xschem callback %T %x %y %N 0 0 [expr {$ShiftMask + $Mod1Mask}]} } - bind $window_path {xschem callback %T %x %y %N 0 0 %s} + bind $window_path { + xschem callback %T %x %y %N 0 0 %s + } bind $window_path {xschem callback %T %x %y %N 0 0 %s} ;# 20161118 bind $window_path {xschem callback %T %x %y 0 0 0 %s} bind $window_path {xschem callback %T %x %y 0 0 0 0 }