|
1 #!/usr/bin/env python3 |
|
2 |
|
3 # Generate highway shields as SVG files in symbols/shields. |
|
4 |
|
5 from __future__ import print_function |
|
6 import copy, lxml.etree, math, os |
|
7 |
|
8 |
|
9 def main(): |
|
10 namespace = 'http://www.w3.org/2000/svg' |
|
11 svgns = '{' + namespace + '}' |
|
12 svgnsmap = {None: namespace} |
|
13 |
|
14 config = {} |
|
15 config['base'] = {} |
|
16 |
|
17 # font_height and font_width are determined by trial and error |
|
18 config['base']['rounded_corners'] = 2 |
|
19 config['base']['font_height'] = 11 |
|
20 config['base']['font_width'] = 0.85 |
|
21 config['base']['padding_x'] = 8 |
|
22 config['base']['padding_y'] = 2 |
|
23 config['base']['stroke_width'] = 1 |
|
24 |
|
25 # Fall back colours used if no colours are defined in road-colours.yaml for a road type. |
|
26 config['base']['fill'] = '#f1f1f1' |
|
27 config['base']['stroke_fill'] = '#c6c6c6' |
|
28 |
|
29 config['global'] = {} |
|
30 |
|
31 config['global']['types'] = ['valtatie', 'kantatie', 'seututie', 'yhdystie', 'eurooppatie'] |
|
32 config['global']['max_width'] = 48 |
|
33 config['global']['output_dir'] = '../symbols/shields/' # specified relative to the script location |
|
34 |
|
35 config['valtatie'] = {'fill': '#ff163c', 'stroke_fill': 'white'} |
|
36 config['kantatie'] = {'fill': '#ffd90f', 'stroke_fill': 'black', 'stroke_width': 0.5} |
|
37 config['seututie'] = {'fill': 'white', 'stroke_fill': 'black', 'stroke_width': 0.5} |
|
38 config['yhdystie'] = {'fill': '#005eb7', 'stroke_fill': 'white'} |
|
39 config['eurooppatie'] = {'fill': '#00997c', 'stroke_fill': 'white'} |
|
40 |
|
41 if not os.path.exists(os.path.dirname(config['global']['output_dir'])): |
|
42 os.makedirs(os.path.dirname(config['global']['output_dir'])) |
|
43 |
|
44 height = 1 |
|
45 shield_size = 'base' |
|
46 |
|
47 dirpath = os.path.join(os.path.dirname(__file__), config['global']['output_dir']) |
|
48 try: |
|
49 os.makedirs(dirpath) |
|
50 except FileExistsError: |
|
51 pass |
|
52 |
|
53 for width in range(1, config['global']['max_width'] + 1): |
|
54 for shield_type in config['global']['types']: |
|
55 |
|
56 # merge base config and specific styles |
|
57 vars = copy.deepcopy(config['base']) |
|
58 if shield_type in config: |
|
59 for option in config[shield_type]: |
|
60 vars[option] = config[shield_type][option] |
|
61 |
|
62 shield_width = 2 * vars['padding_x'] + math.ceil(vars['font_width'] * width) |
|
63 shield_height = 2 * vars['padding_y'] + math.ceil(vars['font_height'] * height) |
|
64 |
|
65 svg = lxml.etree.Element('svg', nsmap=svgnsmap) |
|
66 svg.set('width', '100%') |
|
67 svg.set('height', '100%') |
|
68 svg.set('viewBox', '0 0 ' + str(shield_width + vars['stroke_width']) + ' ' + str(shield_height + vars['stroke_width'])) |
|
69 |
|
70 if vars['stroke_width'] > 0: |
|
71 offset_x = vars['stroke_width'] / 2.0 |
|
72 offset_y = vars['stroke_width'] / 2.0 |
|
73 else: |
|
74 offset_x = 0 |
|
75 offset_y = 0 |
|
76 |
|
77 background = lxml.etree.Element(svgns + 'rect') |
|
78 background.set('x', str(offset_x)) |
|
79 background.set('y', str(offset_y)) |
|
80 background.set('width', str(shield_width)) |
|
81 background.set('height', str(shield_height)) |
|
82 background.set('id', 'shield-background') |
|
83 background.set('style', 'fill:' + vars['fill']) |
|
84 svg.append(background) |
|
85 |
|
86 shield = lxml.etree.Element(svgns + 'rect') |
|
87 shield.set('x', str(offset_x + 0.5)) |
|
88 shield.set('y', str(offset_y + 0.5)) |
|
89 shield.set('width', str(shield_width - 1)) |
|
90 shield.set('height', str(shield_height - 1)) |
|
91 if vars['rounded_corners'] > 0: |
|
92 shield.set('rx', str(vars['rounded_corners'])) |
|
93 shield.set('ry', str(vars['rounded_corners'])) |
|
94 shield.set('id', 'shield') |
|
95 |
|
96 stroke = '' |
|
97 if vars['stroke_width'] > 0: |
|
98 stroke = 'stroke:' + vars['stroke_fill'] + ';stroke-width:' + str(vars['stroke_width']) + ';' |
|
99 |
|
100 shield.set('style', 'fill:' + vars['fill'] + ';' + stroke) |
|
101 |
|
102 svg.append(shield) |
|
103 |
|
104 filename = shield_type + '_' + str(width) + 'x' + str(height) |
|
105 if shield_size != 'base': |
|
106 filename = filename + '_' + shield_size |
|
107 |
|
108 filename = filename + '.svg' |
|
109 |
|
110 # save file |
|
111 try: |
|
112 shieldpath = os.path.join(os.path.dirname(__file__), config['global']['output_dir'] + filename) |
|
113 print('Writing', os.path.realpath(shieldpath)) |
|
114 shieldfile = open(shieldpath, 'wb') |
|
115 shieldfile.write(lxml.etree.tostring(svg, encoding='utf-8', xml_declaration=True, pretty_print=True)) |
|
116 shieldfile.close() |
|
117 except IOError: |
|
118 print('Could not save file ' + filename + '.') |
|
119 continue |
|
120 |
|
121 if __name__ == "__main__": |
|
122 main() |