--- title: "Building With SVG 🖼" date: 2021-08-28T11:53:54+02:00 draft: false toc: true tags: - svg - xml - python - code --- 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. ``` bash 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. ``` bash KGT_DEF=" ::= | \".\" " echo "$KGT_DEF" | kgt -l bnf -e svg | awk -vf1="$( 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. ``` awk BEGIN{style_flag=0} / ``` The final result is shown below. {{< figure src="/images/posts/example_kgt.svg" title="example_kgt.svg" >}} ## Tabatkins Railroad Diagrams On the topic of rail-road diagrams there is also a repository from [tabatkins](https://github.com/tabatkins/railroad-diagrams) 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. ``` python 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: ``` python import railroad with open("./posts/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. {{< figure src="/images/posts/example_trd.svg" title="example_trd.svg" >}} 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. # Using Hugo Short Codes ``` go {< python-svg dest="/images/posts/test.svg" title="This is a pyuthon-svg exmaple." >} railroad.Diagram("foo", railroad.Choice(0, "bar", "baz"), css=style) {< /python-svg >} ``` {{< python-svg dest="/images/posts/test.svg" title="This is a python-svg exmaple." >}} railroad.Diagram("foo", railroad.Choice(0, "bar", "baz"), css=style) {{< /python-svg >}}