---
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="<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.

``` awk
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.

``` xml
<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.

{{< 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.