From 87b59d22a5d78c10e474db6187e1f7fdd3aa09f1 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sat, 8 Aug 2020 22:59:52 +0200 Subject: [PATCH] add generation of svg graphics file based on patch no. 97 by Giles Atkinson --- examples/utf-8/стекло/있어요/ext-utf8-4.cir | 16 ++++++-- src/frontend/Makefile.am | 2 + src/frontend/com_hardcopy.c | 40 ++++++++++++++----- src/frontend/display.c | 11 +++++- src/frontend/plotting/grid.c | 43 ++++++++++++++++++++- visualc/vngspice.vcxproj | 2 + 6 files changed, 98 insertions(+), 16 deletions(-) diff --git a/examples/utf-8/стекло/있어요/ext-utf8-4.cir b/examples/utf-8/стекло/있어요/ext-utf8-4.cir index 5b0bdeef5..653068ff1 100644 --- a/examples/utf-8/стекло/있어요/ext-utf8-4.cir +++ b/examples/utf-8/стекло/있어요/ext-utf8-4.cir @@ -1,6 +1,6 @@ * test de titré それは私を傷つけません .control -set hcopydevtype = postscript +set hcopydevtype = svg set hcopypscolor=1 *set hcopyscale=0.5 set color2=rgb:FF/0/0 @@ -9,7 +9,7 @@ set color2=rgb:FF/0/0 if $oscompiled = 2 setcs hcopyfont='NimbusMono-Regular' end -set hcopyfontsize=14 +set hcopyfontsize=18 * for CYGWIN setcs xfont='Noto Sans CJK JP Medium' @@ -23,16 +23,24 @@ plot y vs x xlabel 'Labellisé X' ylabel 'Labellisé Y: ÜüÖöÄäÜÜÜÜÜÜ plot y vs x xlabel '我能吞下玻璃而不伤身体' ylabel 'Я могу есть стекло, оно мне не вредит' title 'Titré 22 أنا قادر على أكل الزجاج و هذا لا يؤلمني.' plot y vs x+0.001 xlabel 'Labellisé X' ylabel 'Labellisé Y' title 'Titré 23 私はガラスを食べられます。それは私を傷つけません' loglog plot y vs x+0.001 xlabel 'Titré 私はガラスを食べられます。それは私を傷つけません' ylabel 'Titré 24 나는 유리를 먹을 수 있어요. 그래도 아프지 않아요' title 'Titré 我能吞下玻璃而不伤身体。' loglog + +set xbrushwidth=6 +set xgridwidth=2 +setcs hcopyfont=Arial +setcs hcopyfontfamily=Arial +hardcopy plot_4.svg y vs x+0.001 xlabel 'Titré 私はガラスを食べられます。それは私を傷つけません' ylabel 'Titré 24 나는 유리를 먹을 수 있어요. 그래도 아프지 않아요' title 'Titré 我能吞下玻璃而不伤身体。' loglog + * for CYGWIN if $oscompiled = 2 setcs xfont='Times New Roman' end plot y vs x+0.001 xlabel 'Labellisé X' ylabel ' أنا قادر على أكل الزجاج و هذا لا يؤلمني.' title 'Titré 25' loglog -hardcopy plot_5.ps y vs x xlabel 'Labellisé X' ylabel 'Labellisé Y' title 'Titré Äü @µ€~' +hardcopy plot_5.svg y vs x xlabel 'Labellisé X' ylabel 'Labellisé Y' title 'Titré Äü @µ€~' * for MS Windows only if $oscompiled = 1 | $oscompiled = 8 - shell Start /B plot_5.ps + shell Start /B plot_4.svg + shell Start /B plot_5.svg * for CYGWIN else shell xterm -e gs plot_5.ps & diff --git a/src/frontend/Makefile.am b/src/frontend/Makefile.am index 2ebd79e19..4786522be 100644 --- a/src/frontend/Makefile.am +++ b/src/frontend/Makefile.am @@ -177,6 +177,8 @@ libfte_la_SOURCES = \ spiceif.h \ subckt.c \ subckt.h \ + svg.c \ + svg.h \ typesdef.c \ typesdef.h \ vectors.c \ diff --git a/src/frontend/com_hardcopy.c b/src/frontend/com_hardcopy.c index 9d62fcf10..7f00a6c90 100644 --- a/src/frontend/com_hardcopy.c +++ b/src/frontend/com_hardcopy.c @@ -77,17 +77,34 @@ void com_hardcopy(wordlist *wl) return; } - /* change .tmp to .ps */ - psfname = strchr(fname, '.'); - if (psfname) { - psfname[1] = 'p'; - psfname[2] = 's'; - psfname[3] = '\0'; + if (!strcmp(devtype, "svg")) { + /* change .tmp to .svg */ + psfname = strchr(fname, '.'); + if (psfname) { + psfname[1] = 's'; + psfname[2] = 'v'; + psfname[3] = 'g'; + psfname[4] = '\0'; + } + else { + fname = trealloc(fname, n_byte_fname + 4); + (void)memcpy(fname + n_byte_fname - 1, ".svg", 5); + n_byte_fname += 4; + } } else { - fname = trealloc(fname, n_byte_fname + 3); - (void) memcpy(fname + n_byte_fname - 1, ".ps", 4); - n_byte_fname += 3; + /* change .tmp to .ps */ + psfname = strchr(fname, '.'); + if (psfname) { + psfname[1] = 'p'; + psfname[2] = 's'; + psfname[3] = '\0'; + } + else { + fname = trealloc(fname, n_byte_fname + 3); + (void)memcpy(fname + n_byte_fname - 1, ".ps", 4); + n_byte_fname += 3; + } } tempgraph->devdep = fname; tempgraph->n_byte_devdep = n_byte_fname; @@ -225,6 +242,11 @@ void com_hardcopy(wordlist *wl) "\nThe file \"%s\" may be printed on a postscript printer.\n", fname); } + else if (!strcmp(devtype, "svg")) { + fprintf(cp_out, + "\nThe file \"%s\" has the Scalable Vector Graphics format.\n", + fname); + } else if (!strcmp(devtype, "MFB")) { fprintf(cp_out, "The file \"%s\" may be printed on a MFB device.\n", diff --git a/src/frontend/display.c b/src/frontend/display.c index 9ad29be0a..56f5589bc 100644 --- a/src/frontend/display.c +++ b/src/frontend/display.c @@ -36,7 +36,7 @@ static int nodev(void); #include "plotting/plot5.h" #include "postsc.h" #include "hpgl.h" - +#include "svg.h" DISPDEVICE device[] = { @@ -110,6 +110,15 @@ DISPDEVICE device[] = { (disp_fn_Track_t *) nodev, (disp_fn_MakeMenu_t *) nodev, (disp_fn_MakeDialog_t *) nodev, (disp_fn_Input_t *) nodev, gen_DatatoScreen, }, + { "svg", 0, 0, 1000, 1000, 0, 0, + SVG_Init, SVG_NewViewport, + SVG_Close, SVG_Clear, + SVG_DrawLine, SVG_Arc, SVG_Text, + (disp_fn_DefineColor_t*)nodev, (disp_fn_DefineLinestyle_t*)nodev, + SVG_SetLinestyle, SVG_SetColor, SVG_Update, + (disp_fn_Track_t*)nodev, (disp_fn_MakeMenu_t*)nodev, (disp_fn_MakeDialog_t*)nodev, (disp_fn_Input_t*)nodev, + gen_DatatoScreen, }, + { "hpgl", 0, 0, 1000, 1000, 0, 0, GL_Init, GL_NewViewport, GL_Close, GL_Clear, diff --git a/src/frontend/plotting/grid.c b/src/frontend/plotting/grid.c index 77476048b..adbc2fa57 100644 --- a/src/frontend/plotting/grid.c +++ b/src/frontend/plotting/grid.c @@ -141,7 +141,7 @@ gr_redrawgrid(GRAPH *graph) (int)(graph->absolute.width * 0.35), graph->fontheight, 0); #else - if (eq(dispdev->name, "postscript")) + if (eq(dispdev->name, "postscript") || eq(dispdev->name, "svg")) { DevDrawText(graph->grid.xlabel, (int)(graph->absolute.width * 0.35), @@ -232,6 +232,45 @@ gr_redrawgrid(GRAPH *graph) graph->grid.ylabel) * graph->fontwidth) / 2, 90); } +#if !defined(_MSC_VER ) && !defined(__MINGW32__) + /* svg for non-Windows */ + else if (eq(dispdev->name, "svg")) { + DevDrawText(graph->grid.ylabel, + graph->fontwidth, + /* vertical text, midpoint in y is aligned midpoint + * of utf-8 text string */ + graph->absolute.height - (int)(mbstowcs(NULL, graph->grid.ylabel, 0) * graph->fontwidth / 2), + 90); + } +#else + /* Windows and UTF-8: check for string length (in pixels), + place vertical text centered in y with respect to grid */ + else if (eq(dispdev->name, "svg")) { + /* utf-8: figure out the real length of the y label */ + const int n_byte_wide = 2 * (int)strlen(graph->grid.ylabel) + 1; + wchar_t* const wtext = TMALLOC(wchar_t, n_byte_wide); + int wlen = MultiByteToWideChar(CP_UTF8, 0, graph->grid.ylabel, -1, + wtext, n_byte_wide); + if (wlen == 0) { + fprintf(stderr, "UTF-8 to wide char conversion failed with 0x%x\n", GetLastError()); + fprintf(stderr, "%s could not be converted\n", graph->grid.ylabel); + } + else { + SIZE sz; + TEXTMETRICW tmw; + tpWindowData wd = graph->devdep; + GetTextMetricsW(wd->hDC, &tmw); + GetTextExtentPoint32W(wd->hDC, wtext, wlen, &sz); + // printf("length: %d, deviation: %d\n", sz.cx, sz.cx - graph->fontwidth*wlen); + DevDrawText(graph->grid.ylabel, + graph->fontwidth, + /*vertical text, midpoint in y is aligned midpoint of text string */ + (graph->absolute.height - (int)(1.2 * sz.cx + tmw.tmOverhang)) / 2, 90); + } + txfree(wtext); + } +#endif + #ifdef EXT_ASC else if (eq(dispdev->name, "Windows")) DevDrawText(graph->grid.ylabel, @@ -288,7 +327,7 @@ gr_redrawgrid(GRAPH *graph) } /* draw postscript title */ - if (graph->plotname && eq(dispdev->name, "postscript")) + if (graph->plotname && (eq(dispdev->name, "postscript") || eq(dispdev->name, "svg"))) DevDrawText(graph->plotname, graph->fontwidth, graph->absolute.height - graph->fontheight, 0); diff --git a/visualc/vngspice.vcxproj b/visualc/vngspice.vcxproj index cedc9b4d0..056d32512 100644 --- a/visualc/vngspice.vcxproj +++ b/visualc/vngspice.vcxproj @@ -927,6 +927,7 @@ + @@ -1538,6 +1539,7 @@ +