graphs are now rendered (as detailed png bitmaps) in svg exports
This commit is contained in:
parent
87937a5add
commit
f644ce58a6
121
src/draw.c
121
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, "<image x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" %s "
|
||||
"xlink:href=\"data:image/png;base64,%s\"/>\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;i<xctx->rects[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)
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;c<cadlayers;c++)
|
||||
{
|
||||
for(i=0;i<xctx->rects[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;c<cadlayers;c++)
|
||||
{
|
||||
for(i=0;i<xctx->lines[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;i<xctx->rects[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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
10
src/xschem.h
10
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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue