diff --git a/src/draw.c b/src/draw.c
index 14e67fa1..4674ec34 100644
--- a/src/draw.c
+++ b/src/draw.c
@@ -81,7 +81,7 @@ void print_image()
#if HAS_CAIRO == 0
char cmd[PATH_MAX+100];
#endif
- int save_draw_grid;
+ int save_draw_grid, save_draw_window;
static char lastdir[PATH_MAX] = "";
const char *r;
@@ -107,7 +107,10 @@ void print_image()
#endif
save_draw_grid = tclgetboolvar("draw_grid");
tclsetvar("draw_grid", "0");
+ save_draw_window = xctx->draw_window;
+ xctx->draw_window=0;
xctx->draw_pixmap=1;
+ xctx->do_copy_area=0;
draw();
@@ -115,29 +118,31 @@ void print_image()
* XPM and handles Xrender extensions for transparent embedded images */
{
cairo_surface_t *png_sfc;
-#ifdef __unix__
+ #ifdef __unix__
png_sfc = cairo_xlib_surface_create(display, xctx->save_pixmap, visual,
xctx->xrect[0].width, xctx->xrect[0].height);
-#else
+ #else
HWND hwnd = Tk_GetHWND(xctx->window);
HDC dc = GetDC(hwnd);
png_sfc = cairo_win32_surface_create(dc);
-#endif
+ #endif
if(xctx->plotfile[0])
cairo_surface_write_to_png(png_sfc, xctx->plotfile);
else
cairo_surface_write_to_png(png_sfc, "plot.png");
+
+ cairo_surface_destroy(png_sfc);
}
#else /* no cairo */
-#ifdef __unix__
+ #ifdef __unix__
XpmWriteFileFromPixmap(display, "plot.xpm", xctx->save_pixmap,0, NULL ); /* .gz ???? */
dbg(1, "print_image(): Window image saved\n");
if(xctx->plotfile[0]) {
my_snprintf(cmd, S(cmd), "convert_to_png plot.xpm {%s}", xctx->plotfile);
tcleval(cmd);
} else tcleval( "convert_to_png plot.xpm plot.png");
-#else
+ #else
char *psfile = NULL;
create_ps(&psfile, 7);
if (xctx->plotfile[0]) {
@@ -145,11 +150,13 @@ void print_image()
tcleval(cmd);
}
else tcleval("convert_to_png {%s} plot.png", psfile);
-#endif
+ #endif
#endif
my_strncpy(xctx->plotfile,"", S(xctx->plotfile));
tclsetboolvar("draw_grid", save_draw_grid);
xctx->draw_pixmap=1;
+ xctx->draw_window=save_draw_window;
+ xctx->do_copy_area=1;
}
#if HAS_CAIRO==1
@@ -2943,10 +2950,10 @@ static cairo_status_t png_writer(void *in_closure, const unsigned char *in_data,
/* rot and flip for rotated / flipped symbols
- * draw: 1 draw image
+ * dr: 1 draw image
* 0 only load image and build base64
*/
-void draw_image(int draw, xRect *r, double *x1, double *y1, double *x2, double *y2, int rot, int flip)
+void draw_image(int dr, xRect *r, double *x1, double *y1, double *x2, double *y2, int rot, int flip)
{
#if HAS_CAIRO == 1
const char *ptr;
@@ -2973,7 +2980,7 @@ void draw_image(int draw, xRect *r, double *x1, double *y1, double *x2, double *
xctx->areax1,xctx->areay1,xctx->areax2,xctx->areay2)) return;
set_rect_extraptr(1, r); /* create r->extraptr pointing to a xEmb_image struct */
emb_ptr = r->extraptr;
- if(draw) {
+ if(dr) {
cairo_save(xctx->cairo_ctx);
cairo_save(xctx->cairo_save_ctx);
}
@@ -3074,7 +3081,7 @@ void draw_image(int draw, xRect *r, double *x1, double *y1, double *x2, double *
scalex = rw/w * xctx->mooz;
scaley = rh/h * xctx->mooz;
}
- if(draw && xctx->draw_pixmap) {
+ if(dr && xctx->draw_pixmap) {
cairo_translate(xctx->cairo_save_ctx, x, y);
if(flip && (rot == 0 || rot == 2)) cairo_scale(xctx->cairo_save_ctx, -scalex, scaley);
else if(flip && (rot == 1 || rot == 3)) cairo_scale(xctx->cairo_save_ctx, scalex, -scaley);
@@ -3087,7 +3094,7 @@ void draw_image(int draw, xRect *r, double *x1, double *y1, double *x2, double *
cairo_clip(xctx->cairo_save_ctx);
cairo_paint_with_alpha(xctx->cairo_save_ctx, alpha);
}
- if(draw && xctx->draw_window) {
+ if(dr && xctx->draw_window) {
cairo_translate(xctx->cairo_ctx, x, y);
if(flip && (rot == 0 || rot == 2)) cairo_scale(xctx->cairo_ctx, -scalex, scaley);
else if(flip && (rot == 1 || rot == 3)) cairo_scale(xctx->cairo_ctx, scalex, -scaley);
@@ -3100,7 +3107,7 @@ void draw_image(int draw, xRect *r, double *x1, double *y1, double *x2, double *
cairo_clip(xctx->cairo_ctx);
cairo_paint_with_alpha(xctx->cairo_ctx, alpha);
}
- if(draw) {
+ if(dr) {
cairo_restore(xctx->cairo_ctx);
cairo_restore(xctx->cairo_save_ctx);
}
@@ -3122,6 +3129,64 @@ static void draw_images_all(void)
#endif
}
+void svg_embedded_graph(FILE *fd, xRect *r, double rx1, double ry1, double rx2, double ry2)
+{
+ char *ptr = NULL;
+ double x1, y1, x2, y2, w, h;
+ int rw, rh;
+ char transform[150];
+ png_to_byte_closure_t closure;
+ cairo_surface_t *png_sfc;
+ int save_draw_window, save_draw_grid;
+ size_t olength;
+
+ rw = (int) fabs(rx2 -rx1);
+ rh = (int) fabs(ry2 - ry1);
+ save_restore_zoom(1);
+ set_viewport_size(rw, rh, 0.8);
+ zoom_box(rx1, ry1, rx2, ry2, 1.0);
+ resetwin(1, 1, 1, rw, rh);
+ save_draw_grid = tclgetboolvar("draw_grid");
+ tclsetvar("draw_grid", "0");
+ save_draw_window = xctx->draw_window;
+ xctx->draw_window=0;
+ xctx->draw_pixmap=1;
+ xctx->do_copy_area=0;
+ draw();
+ png_sfc = cairo_xlib_surface_create(display, xctx->save_pixmap, visual,
+ xctx->xrect[0].width, xctx->xrect[0].height);
+ closure.buffer = NULL;
+ closure.size = 0;
+ closure.pos = 0;
+ cairo_surface_write_to_png_stream(png_sfc, png_writer, &closure);
+ ptr = base64_encode(closure.buffer, closure.pos, &olength, 1);
+ my_free(1547, &closure.buffer);
+ cairo_surface_destroy(png_sfc);
+ xctx->draw_pixmap=1;
+ xctx->draw_window=save_draw_window;
+ xctx->do_copy_area=1;
+ tclsetboolvar("draw_grid", save_draw_grid);
+ save_restore_zoom(0);
+ resetwin(1, 1, 1, 0, 0);
+ change_linewidth(-1.);
+
+ x1=X_TO_SVG(rx1);
+ y1=Y_TO_SVG(ry1);
+ x2=X_TO_SVG(rx2);
+ y2=Y_TO_SVG(ry2);
+ h = fabs(y2 - y1);
+ w = fabs(x2 - x1);
+
+ my_snprintf(transform, S(transform), "transform=\"translate(%g,%g)\"", x1, y1);
+ if(ptr[0]) {
+ fprintf(fd, "\n",
+ 0.0, 0.0, w, h, transform, ptr);
+ }
+ my_free(1546, &ptr);
+}
+
+
void draw(void)
{
/* inst_ptr and wire hash iterator 20171224 */
@@ -3133,15 +3198,15 @@ void draw(void)
xSymbol *symptr;
int textlayer;
int show_hidden_texts = tclgetboolvar("show_hidden_texts");
-
+
#if HAS_CAIRO==1
const char *textfont;
-#ifndef __unix__
+ #ifndef __unix__
clear_cairo_surface(xctx->cairo_save_ctx,
xctx->xrect[0].x, xctx->xrect[0].y, xctx->xrect[0].width, xctx->xrect[0].height);
clear_cairo_surface(xctx->cairo_ctx,
xctx->xrect[0].x, xctx->xrect[0].y, xctx->xrect[0].width, xctx->xrect[0].height);
-#endif
+ #endif
#endif
if(xctx->no_draw) return;
rebuild_selected_array();
@@ -3179,10 +3244,11 @@ void draw(void)
if(xctx->enable_layer[c]) for(i=0;irects[c];i++) {
xRect *r = &xctx->rect[c][i];
#if HAS_CAIRO==1
- if(c != GRIDLAYER || !(r->flags & (1 + 1024)) ) {
+ if(c != GRIDLAYER || !(r->flags & (1 + 1024)))
#else
- if(c != GRIDLAYER || !(r->flags & 1) ) {
+ if(c != GRIDLAYER || !(r->flags & 1) )
#endif
+ {
drawrect(c, ADD, r->x1, r->y1, r->x2, r->y2, r->dash);
filledrect(c, ADD, r->x1, r->y1, r->x2, r->y2);
}
@@ -3294,14 +3360,16 @@ void draw(void)
}
} /* !xctx->only_probes, 20110112 */
draw_hilight_net(xctx->draw_window);
- if(!xctx->draw_window) {
- MyXCopyArea(display, xctx->save_pixmap, xctx->window, xctx->gctiled, xctx->xrect[0].x, xctx->xrect[0].y,
- xctx->xrect[0].width, xctx->xrect[0].height, xctx->xrect[0].x, xctx->xrect[0].y);
+ if(xctx->do_copy_area) { /* this is zero only when doing png hardcopy to avoid video flickering */
+ if(!xctx->draw_window) {
+ MyXCopyArea(display, xctx->save_pixmap, xctx->window, xctx->gctiled, xctx->xrect[0].x, xctx->xrect[0].y,
+ xctx->xrect[0].width, xctx->xrect[0].height, xctx->xrect[0].x, xctx->xrect[0].y);
+ }
+ #if !defined(__unix__) && defined(HAS_CAIRO)
+ else
+ my_cairo_fill(xctx->cairo_sfc, xctx->xrect[0].x, xctx->xrect[0].y, xctx->xrect[0].width, xctx->xrect[0].height);
+ #endif
}
-#if !defined(__unix__) && defined(HAS_CAIRO)
- else
- my_cairo_fill(xctx->cairo_sfc, xctx->xrect[0].x, xctx->xrect[0].y, xctx->xrect[0].width, xctx->xrect[0].height);
-#endif
draw_selection(xctx->gc[SELLAYER], 0); /* 20181009 moved outside of cadlayers loop */
} /* if(has_x) */
}
@@ -3319,7 +3387,8 @@ int XSetTile(Display* display, GC gc, Pixmap s_pixmap)
}
#endif
-void MyXCopyArea(Display* display, Drawable src, Drawable dest, GC gc, int src_x, int src_y, unsigned int width, unsigned int height, int dest_x, int dest_y)
+void MyXCopyArea(Display* display, Drawable src, Drawable dest, GC gc, int src_x, int src_y,
+ unsigned int width, unsigned int height, int dest_x, int dest_y)
{
XCopyArea(display, src, dest, gc, src_x, src_y, width, height, dest_x, dest_y);
#if !defined(__unix__) && defined(HAS_CAIRO)
diff --git a/src/save.c b/src/save.c
index b735bb5f..c2e17948 100644
--- a/src/save.c
+++ b/src/save.c
@@ -115,6 +115,7 @@ int filter_data(const char* din, const size_t ilen,
#endif
/* Caller should free returned buffer */
+/* set brk to 1 if you want newlines added */
char *base64_encode(const unsigned char *data, const size_t input_length, size_t *output_length, int brk) {
static const char b64_enc[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
diff --git a/src/scheduler.c b/src/scheduler.c
index 3078e224..dc964b6d 100644
--- a/src/scheduler.c
+++ b/src/scheduler.c
@@ -1998,7 +1998,6 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
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]);
@@ -2007,14 +2006,13 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
x2 = atof(argv[8]);
y2 = atof(argv[9]);
save_restore_zoom(1);
- set_viewport_size(w, h, 0.8);
+ set_viewport_size(w, h, 0.8);
zoom_box(x1, y1, x2, y2, 1.0);
resetwin(1, 1, 1, w, h);
print_image();
save_restore_zoom(0);
resetwin(1, 1, 1, 0, 0);
change_linewidth(-1.);
- draw();
} else {
print_image();
}
diff --git a/src/svgdraw.c b/src/svgdraw.c
index 3a313671..11e3d991 100644
--- a/src/svgdraw.c
+++ b/src/svgdraw.c
@@ -21,8 +21,6 @@
*/
#include "xschem.h"
-#define X_TO_SVG(x) ( (x+xctx->xorigin)* xctx->mooz )
-#define Y_TO_SVG(y) ( (y+xctx->yorigin)* xctx->mooz )
static FILE *fd;
@@ -391,7 +389,6 @@ static void svg_drawgrid()
}
}
-
static void svg_embedded_image(xRect *r, double rx1, double ry1, double rx2, double ry2, int rot, int flip)
{
const char *ptr;
@@ -431,7 +428,6 @@ static void svg_embedded_image(xRect *r, double rx1, double ry1, double rx2, dou
}
}
-
static void svg_draw_symbol(int c, int n,int layer,short tmp_flip, short rot,
double xoffset, double yoffset)
/* draws current layer only, should be called within */
@@ -467,10 +463,11 @@ static void svg_draw_symbol(int c, int n,int layer,short tmp_flip, short rot,
xctx->inst[n].flags|=1;
return;
}
- else xctx->inst[n].flags&=~1;
+ else {
+ xctx->inst[n].flags&=~1;
+ }
}
else if(xctx->inst[n].flags&1) {
- dbg(1, "draw_symbol(): skipping inst %d\n", n);
return;
}
flip = xctx->inst[n].flip;
@@ -521,7 +518,6 @@ static void svg_draw_symbol(int c, int n,int layer,short tmp_flip, short rot,
ROTATION(rot, flip, 0.0,0.0,rect->x1,rect->y1,x1,y1);
ROTATION(rot, flip, 0.0,0.0,rect->x2,rect->y2,x2,y2);
-
if(layer == GRIDLAYER && rect->flags & 1024) {
double xx1 = x0 + x1;
double yy1 = y0 + y1;
@@ -795,6 +791,19 @@ void svg_draw(void)
xctx->text[i].x0,xctx->text[i].y0,
xctx->text[i].xscale, xctx->text[i].yscale);
}
+
+
+ /* do first graphs as these require draw() which clobbers xctx->inst[n].flags bit 0 */
+ for(c=0;crects[c];i++)
+ {
+ if(c == GRIDLAYER && (xctx->rect[c][i].flags & 1) ) { /* graph */
+ xRect *r = &xctx->rect[c][i];
+ svg_embedded_graph(fd, r, r->x1, r->y1, r->x2, r->y2);
+ }
+ }
+ }
for(c=0;clines[c];i++)
@@ -802,10 +811,12 @@ void svg_draw(void)
xctx->line[c][i].x2, xctx->line[c][i].y2, xctx->line[c][i].dash);
for(i=0;irects[c];i++)
{
- if(c == GRIDLAYER && (xctx->rect[c][i].flags & 1024) ) {
+ if(c == GRIDLAYER && (xctx->rect[c][i].flags & 1) ) { /* graph */
+ /* do nothing, done above */
+ } else if(c == GRIDLAYER && (xctx->rect[c][i].flags & 1024) ) { /* image */
xRect *r = &xctx->rect[c][i];
svg_embedded_image(r, r->x1, r->y1, r->x2, r->y2, 0, 0);
- } else if(c != GRIDLAYER || !(xctx->rect[c][i].flags & 1) ) {
+ } 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);
}
diff --git a/src/xinit.c b/src/xinit.c
index f7b1ff57..37bb976f 100644
--- a/src/xinit.c
+++ b/src/xinit.c
@@ -633,6 +633,7 @@ static void alloc_xschem_data(const char *top_path, const char *win_path)
xctx->x_strcmp = strcmp;
xctx->fill_pattern = 1;
xctx->draw_window = 0;
+ xctx->do_copy_area = 1;
xctx->time_last_modify = 0;
}
diff --git a/src/xschem.h b/src/xschem.h
index df7445a4..6a630f8f 100644
--- a/src/xschem.h
+++ b/src/xschem.h
@@ -327,6 +327,10 @@ extern char win_temp_dir[PATH_MAX];
#define X_TO_XSCHEM(x) ( (x) * xctx->zoom - xctx->xorigin )
#define Y_TO_XSCHEM(y) ( (y) * xctx->zoom - xctx->yorigin )
+#define X_TO_SVG(x) ( (x+xctx->xorigin)* xctx->mooz )
+#define Y_TO_SVG(y) ( (y+xctx->yorigin)* xctx->mooz )
+
+
/* coordinate transformations graph to xschem */
#define W_X(x) (gr->cx * (x) + gr->dx)
#define W_Y(y) (gr->cy * (y) + gr->dy)
@@ -924,7 +928,6 @@ typedef struct {
int menu_removed; /* fullscreen previous setting */
double save_lw; /* used to save linewidth when selecting 'only_probes' view */
int no_draw;
- int draw_pixmap; /* pixmap used as 2nd buffer */
int netlist_count; /* netlist counter incremented at any cell being netlisted */
int hide_symbols;
int netlist_type;
@@ -941,7 +944,9 @@ typedef struct {
char *current_win_path; /* .drw or .x1.drw, .... ; always .drw in tabbed interface */
int *fill_type; /* for every layer: 0: no fill, 1, solid fill, 2: stipple fill */
int fill_pattern;
+ int draw_pixmap; /* pixmap used as 2nd buffer */
int draw_window;
+ int do_copy_area;
time_t time_last_modify;
int undo_type; /* 0: on disk, 1: in memory */
void (*push_undo)(void);
@@ -1021,7 +1026,7 @@ extern int cli_opt_load_initfile;
extern Xschem_ctx *xctx;
/* FUNCTIONS */
-extern void draw_image(int draw, xRect *r, double *x1, double *y1, double *x2, double *y2, int rot, int flip);
+extern void draw_image(int dr, xRect *r, double *x1, double *y1, double *x2, double *y2, int rot, int flip);
extern int filter_data(const char *din, const size_t ilen,
char **dout, size_t *olen, const char *cmd);
extern int embed_rawfile(const char *rawfile);
@@ -1073,6 +1078,7 @@ extern int process_options(int argc, char **argv);
extern void calc_drawing_bbox(xRect *boundbox, int selected);
extern int ps_draw(int what);
extern void svg_draw(void);
+extern void svg_embedded_graph(FILE *fd, xRect *r, double rx1, double ry1, double rx2, double ry2);
extern void set_viewport_size(int w, int h, double lw);
extern void print_image();
extern const char *get_trailing_path(const char *str, int no_of_dir, int skip_ext);