mirror of
				https://github.com/lleene/hugo-site.git
				synced 2025-10-31 03:09:03 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			134 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			134 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| ---
 | |
| 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.
 | |
| 
 |