scripts/generate_shields.py

changeset 0
b0eb3af2f9ee
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/generate_shields.py	Mon Sep 14 22:55:45 2020 +0300
@@ -0,0 +1,122 @@
+#!/usr/bin/env python3
+
+# Generate highway shields as SVG files in symbols/shields.
+
+from __future__ import print_function
+import copy, lxml.etree, math, os
+
+
+def main():
+    namespace = 'http://www.w3.org/2000/svg'
+    svgns = '{' + namespace + '}'
+    svgnsmap = {None: namespace}
+
+    config = {}
+    config['base'] = {}
+
+    # font_height and font_width are determined by trial and error
+    config['base']['rounded_corners'] = 2
+    config['base']['font_height'] = 11
+    config['base']['font_width'] = 0.85
+    config['base']['padding_x'] = 8
+    config['base']['padding_y'] = 2
+    config['base']['stroke_width'] = 1
+
+    # Fall back colours used if no colours are defined in road-colours.yaml for a road type.
+    config['base']['fill'] = '#f1f1f1'
+    config['base']['stroke_fill'] = '#c6c6c6'
+
+    config['global'] = {}
+
+    config['global']['types'] = ['valtatie', 'kantatie', 'seututie', 'yhdystie', 'eurooppatie']
+    config['global']['max_width'] = 48
+    config['global']['output_dir'] = '../symbols/shields/' # specified relative to the script location
+    
+    config['valtatie'] = {'fill': '#ff163c', 'stroke_fill': 'white'}
+    config['kantatie'] = {'fill': '#ffd90f', 'stroke_fill': 'black', 'stroke_width': 0.5}
+    config['seututie'] = {'fill': 'white', 'stroke_fill': 'black', 'stroke_width': 0.5}
+    config['yhdystie'] = {'fill': '#005eb7', 'stroke_fill': 'white'}
+    config['eurooppatie'] = {'fill': '#00997c', 'stroke_fill': 'white'}
+
+    if not os.path.exists(os.path.dirname(config['global']['output_dir'])):
+        os.makedirs(os.path.dirname(config['global']['output_dir']))
+
+    height = 1
+    shield_size = 'base'
+
+    dirpath = os.path.join(os.path.dirname(__file__), config['global']['output_dir'])
+    try:
+        os.makedirs(dirpath)
+    except FileExistsError:
+        pass
+
+    for width in range(1, config['global']['max_width'] + 1):
+        for shield_type in config['global']['types']:
+
+            # merge base config and specific styles
+            vars = copy.deepcopy(config['base'])
+            if shield_type in config:
+                for option in config[shield_type]:
+                    vars[option] = config[shield_type][option]
+
+            shield_width = 2 * vars['padding_x'] + math.ceil(vars['font_width'] * width)
+            shield_height = 2 * vars['padding_y'] + math.ceil(vars['font_height'] * height)
+
+            svg = lxml.etree.Element('svg', nsmap=svgnsmap)
+            svg.set('width', '100%')
+            svg.set('height', '100%')
+            svg.set('viewBox', '0 0 ' + str(shield_width    + vars['stroke_width']) + ' ' + str(shield_height + vars['stroke_width']))
+
+            if vars['stroke_width'] > 0:
+                offset_x = vars['stroke_width'] / 2.0
+                offset_y = vars['stroke_width'] / 2.0
+            else:
+                offset_x = 0
+                offset_y = 0
+
+            background = lxml.etree.Element(svgns + 'rect')
+            background.set('x', str(offset_x))
+            background.set('y', str(offset_y))
+            background.set('width', str(shield_width))
+            background.set('height', str(shield_height))
+            background.set('id', 'shield-background')
+            background.set('style', 'fill:' + vars['fill'])
+            svg.append(background)
+
+            shield = lxml.etree.Element(svgns + 'rect')
+            shield.set('x', str(offset_x + 0.5))
+            shield.set('y', str(offset_y + 0.5))
+            shield.set('width', str(shield_width - 1))
+            shield.set('height', str(shield_height - 1))
+            if vars['rounded_corners'] > 0:
+                shield.set('rx', str(vars['rounded_corners']))
+                shield.set('ry', str(vars['rounded_corners']))
+            shield.set('id', 'shield')
+
+            stroke = ''
+            if vars['stroke_width'] > 0:
+                stroke = 'stroke:' + vars['stroke_fill'] + ';stroke-width:' + str(vars['stroke_width']) + ';'
+
+            shield.set('style', 'fill:' + vars['fill'] + ';' + stroke)
+
+            svg.append(shield)
+
+            filename = shield_type + '_' + str(width) + 'x' + str(height)
+            if shield_size != 'base':
+                filename = filename + '_' + shield_size
+
+            filename = filename + '.svg'
+
+            # save file
+            try:
+                shieldpath = os.path.join(os.path.dirname(__file__), config['global']['output_dir'] + filename)
+                print('Writing', os.path.realpath(shieldpath))
+                shieldfile = open(shieldpath, 'wb')
+                shieldfile.write(lxml.etree.tostring(svg, encoding='utf-8', xml_declaration=True, pretty_print=True))
+                shieldfile.close()
+            except IOError:
+                print('Could not save file ' + filename + '.')
+                continue
+
+if __name__ == "__main__":
+    main()

mercurial