5.0 KiB
title | date | draft | toc | tags | ||||
---|---|---|---|---|---|---|---|---|
Building With SVG 🖼 | 2021-08-28T11:53:54+02:00 | false | true |
|
SVG is generally my image format of choice having used it for illustrations, chip diagrams, device specifications, and visual outputs generated by code. SVG is plain text-baesd xml that is structured with some top level object/properties followed by standardized objects that draw lines and shapes.
On a few occasions, I have scripted the generation of some SVG illustration where some parameters are extracted from a database that are then visualized. These scripts are generally quite simple since you just define some pre-formatted shapes and place them inside the drawing region. Besides this I think it useful to highlight some of the automated tools and libraries that are useful with similar functionality.
KGT: Kate's Grammar Tool
KGT is a pretty neat starting point to experiment with this kind of function. It is relatively self contained and produces compact SVG objects from simple statements.
Build Instructions
Building libfms
and kgt
from source was not too much of a hassle although
the build / dependency documentation could be better. This was build with my
WLS-Ubuntu environment.
apt install clang pmake
git clone --recursive "https://$libfsm_REPO/libfsm"
pushd libfsm; CC=clang PREFIX=$HOME pmake -r install; popd
git clone --recursive "https://$KGT_REPO/kgt"
pushd kgt/src; CC=clang PREFIX=$HOME pmake -r install; popd
The main issue is noticed
is the SVG being generated uses path {rouded}
in its style definition which
the svg rasterizer from librsvg2 2.40.20
complained about. Getting the latest
build however is quite involved requiring the latest cairo and proppler
libraries as well. Ideally generating pngs or rasterizing won't be needed.
Example
Just to show a typical use case for making an illustration using the KGT tool, below I generate the svg for one of the examples included by it's repository.
KGT_DEF="<personal-part> ::= <first-name> | <initial> \".\" "
echo "$KGT_DEF" | kgt -l bnf -e svg | awk -vf1="$(<style.svg)" -f replace_style.awk > example_kgt.svg
The style is automatically introduced in the xml header section which is mostly
plain black. This has some legibility issues for dark themes so a short awk
script is used to replace the style with one that we define for this theme.
BEGIN{style_flag=0}
/<style>/{style_flag=1}
{if(style_flag == 0) print $0}
/<\/style>/{style_flag=0;print f1}
For completeness we include the style definition below but this could be added directly to KGT as a feature in future releases.
<style>
rect, line, path { stroke-width: 1.5px; stroke: white; fill: transparent; }
rect, line, path { stroke-linecap: square; stroke-linejoin: rounded; }
path { fill: transparent; }
text { fill: white; font-family:'Trebuchet MS'; }
text.literal { }
line.ellipsis { stroke-dasharray: 1 3.5; }
tspan.hex { font-family: monospace; font-size: 90%; }
path.arrow { fill: white; }
</style>
The final result is shown below.
Tabatkins Railroad Diagrams
On the topic of rail-road diagrams there is also a repository from tabatkins which is a python based code-base for generating similar SVG diagrams as KGT but without having to deal with building or running binaries. I prefer monochrome diagrams with plan formatting so again we are overriding the default style.
style = ( ''
+'\tsvg.railroad-diagram {\n\t\tbackground-color:none;\n\t}\n'
+'\tsvg.railroad-diagram path {\n\t\tstroke-width:1.5;\n\t\tstroke:white;\n\t\tfill:rgba(0,0,0,0);\n\t}\n'
+'\tsvg.railroad-diagram text {\n\t\tfont:bold 14px monospace;\n\t\tfill: white;\n\t\ttext-anchor:middle;\n\t}\n'
+'\tsvg.railroad-diagram text.label{\n\t\ttext-anchor:start;\n\t}\n'
+'\tsvg.railroad-diagram text.comment{\n\t\tfont:italic 12px monospace;\n\t}\n'
+'\tsvg.railroad-diagram rect{\n\t\tstroke-width:1.5;\n\t\tstroke:white;\n\t\tfill:none;\n\t}\n'
+'\tsvg.railroad-diagram rect.group-box {\n\t\tstroke: gray;\n\t\tstroke-dasharray: 10 5;\n\t\tfill: none;\n\t}\n'
)
Styling is best done on a case to case basis with various color-schemes such as using white text/lines for dark themes. Since this is all handeled in python the overall interface. Possibly including some kind of command-line utility here would be quite good but it depends on the final flow for figure generation. Using the style definition shown above, generating a similar example as before would look like this:
import railroad
with open("./test.svg","w+") as file:
obj = railroad.Diagram("foo", railroad.Choice(0, "bar", "baz"), css=style)
obj.writeSvg(file.write)
The final result is shown below.
Note that this figure is quite a bit more compact but adding additional labels or customizations outside the scope of the library will probably require quite a bit of manual work. This could be a fun side project though.