diff --git a/grafik/Readme.md b/grafik/Readme.md index 3e9fc4f5..b0e37e04 100644 --- a/grafik/Readme.md +++ b/grafik/Readme.md @@ -21,9 +21,7 @@ Um alle Bilder erzeugen können, benötigt man eine Vielzahl an Abhängigkeiten: - sed - ed - libxkbcommon (xkbcli) - - python mit jinja2, more-itertools, numpy, pandas, matplotlib und seaborn - - perl mit XML::Writer - - php + - python mit jinja2, numpy, pandas, matplotlib, seaborn und lxml - Linux Libertine - Gentium Plus Compact - DejaVu Sans Mono diff --git a/grafik/aufkleber/Makefile b/grafik/aufkleber/Makefile index 402bb79a..8a67cb0e 100644 --- a/grafik/aufkleber/Makefile +++ b/grafik/aufkleber/Makefile @@ -1,7 +1,7 @@ all: default %-grau-1234.svg: ../../A-REFERENZ-A/%.txt - ./alle-grau-1234.pl $< > $@ + ./alle-grau-1234.py $< > $@ EXTRASVG=\ neo20-grau-1234.svg \ diff --git a/grafik/aufkleber/alle-grau-1234.pl b/grafik/aufkleber/alle-grau-1234.pl deleted file mode 100755 index 4eec3281..00000000 --- a/grafik/aufkleber/alle-grau-1234.pl +++ /dev/null @@ -1,256 +0,0 @@ -#!/usr/bin/env -S perl -w - -use strict; -use warnings; - -use XML::Writer; - -use open ':encoding(utf8)'; -use utf8; - -sub start_svg; -sub end_svg; -sub create_defs; -sub create_key; -sub parse_ref; -sub in2px; -sub create_keys; -sub round; - -my $dpi = 90; -# a4 paper -my $height = in2px(8.268); -my $width = in2px(11.69); - -my $keywidth = in2px(0.75); -my $keyheight = in2px(0.75); -my $labelwidth = in2px(0.5); -my $labelheight = in2px(0.55); - -my $posx = 0; -my $posy = 0; - -my $row = 0; -my %kp_mapping = ( # mapping for keypad, level 4 - 'Hom' => '⇱', - 'KP↑' => '⇡', - 'PgU' => '⇞', - 'KP←' => '⇠', - 'Beg' => '•', - 'KP→' => '⇢', - 'End' => '⇲', - 'KP↓' => '⇣', - 'PgD' => '⇟', - 'Ins' => '⎀', - 'Del' => '⌦', - 'Ent' => '⏎', - 'vec' => ' ⃗' -); - -my $writer = new XML::Writer(ENCODING => 'utf-8', - DATA_MODE => 1, - DATA_INDENT => 2); - -start_svg; -create_defs; - -create_keys(parse_ref); - -end_svg; - -exit; - -# parse reference and return multi-array -sub parse_ref { - my @letters; - open REF, $ARGV[0] - or die 'Error opening reference: '.$!; - while () { - my @layer; - last if /^== Zeichenerläuterungen/; - - # layout blocks - if(/Miniatur ===$/) { - while() { - last if(/^$/); # empty line => end of current block - next if($_ !~ /^│/); # skip horizontal dividers - - push @layer, split /│/; - } - push @letters, [ @layer ]; # push ref - } - } - close REF; - - return @letters; -} - -sub create_keys { - my @letters = @_; - - for (0..$#{$letters[0]}) { # letters - create_key - $letters[0][$_], - $letters[0][$_], - $letters[1][$_], - $letters[2][$_], - $letters[3][$_]; - } - for (0..$#{$letters[7]}) { # numbers - create_key - $letters[7][$_], - $letters[7][$_], - $letters[8][$_], - $letters[9][$_], - $letters[10][$_]; - } -} - -sub in2px { - return ($_[0]||0) * $dpi; -} - -sub start_svg { - $writer->xmlDecl('UTF-8'); - $writer->doctype('svg', '-//W3C//DTD SVG 20001102//EN', - 'http://www.w3.org/TR/2000/CR-SVG-20001102/DTD/svg-20001102.dtd'); - - $writer->startTag('svg', height => $height, width => $width, - 'xmlns' => 'http://www.w3.org/2000/svg', - 'xmlns:xlink' => 'http://www.w3.org/1999/xlink'); -} -sub end_svg { - $writer->endTag('svg'); - $writer->end(); -} - -# create the key template -sub create_defs { - $writer->startTag('defs'); - - # style information - $writer->dataElement('style', ' - text.common { - font-family:Linux Biolinum O, Linux Biolinum; - font-style:normal; - font-variant:normal; - font-stretch:normal; - text-align:center; - text-anchor:middle; - stroke:none; - } - text.main { - /*font-weight:bold;*/ - font-size:19px; - fill:#eeeeee; - stroke-width:4; - } - text.special { - font-size:16px; - stroke-width:3; - } - text.outline { - stroke:#111111; - stroke-linejoin:round; - } - rect#boundary { - fill:none; - stroke:#eeeeee; - stroke-width:'.in2px(0.005).'; - } - rect#border { - fill:#333333; - stroke:#eeeeee; - stroke-width:'.in2px(0.025).'; - } - text.level1 { - } - text.level2 { - } - text.level3 { - fill:#99dd66; - } - text.level4 { - fill:#6699dd; - font-size:13px; - }', type => 'text/css'); - - # boundary of keys - $writer->emptyTag('rect', - id => 'boundary', - width => $keywidth, height => $keyheight, - rx => 5); - # border for keys, actual key stickers - $writer->emptyTag('rect', - id => 'border', - width => $labelwidth, height => $labelheight, - rx => 10); - - $writer->endTag('defs'); -} - -# create a specific key (cloned from template) -# first parameter (0) is first level, and is only used for line breaks in the graphic -# param 1..4 are actual layers -sub create_key { - my @keys = @_; - - $keys[0] = '' unless defined($keys[0]); - $keys[1] = '' unless defined($keys[1]); - s/\s//g for @keys; # remove any space - - # map words to symbols for numblock - foreach (keys %kp_mapping) { - $keys[3] =~ s/\Q$_/\Q$kp_mapping{$_}/; - $keys[4] =~ s/\Q$_/\Q$kp_mapping{$_}/; - } - - return if length($keys[0]) != 1; - - $writer->startTag('g', - transform => "translate($posx,$posy)", - id => 'key_'.(join '', @keys)); - $writer->emptyTag('use', 'xlink:href' => '#boundary'); - $writer->startTag('g', - transform => 'translate('.(($keywidth-$labelwidth)/2.5).', 2)'); - $writer->emptyTag('use', 'xlink:href' => '#border'); - - # add text+outlines to sticker - for(' outline', '') { - $writer->dataElement('text', $keys[1], - transform => 'translate(15,41)', - class => "level1 common main$_") - # do not show e1, if it's the same letter as e2 - # only use for latin letters - unless(#$keys[1] =~ /[a-züöäß]/ && - $keys[1] =~ /\Q$keys[2]/i); - $writer->dataElement('text', $keys[2]||'', - transform => 'translate(15,19)', - class => "level2 common main$_"); - $writer->dataElement('text', $keys[3]||'', - transform => 'translate(32,18)', - class => "level3 common special$_"); - $writer->dataElement('text', $keys[4]||'', - transform => 'translate(32,42)', - class => "level4 common special$_"); - # do not show e4 on keypad - #unless($row > 4 && $keys[0] =~ /\d/i); - } - $writer->endTag('g'); - $writer->endTag('g'); - - $posx += $keywidth; - if($row < 3) { - if($keys[0] =~ /[`´y]/) { # split keyboard rows, dirty way - $posx = ++$row*$keywidth/2; # not really accurate, but works - $posy += $keyheight; - } - } elsif($keys[0] =~ /[-93+j]/) { # keypad - $posx = ++$row*0; - $posy += $keyheight; - } -} - -sub round { - return int($_[0]+.5*($_[0]<=>0)); -} diff --git a/grafik/aufkleber/alle-grau-1234.py b/grafik/aufkleber/alle-grau-1234.py new file mode 100755 index 00000000..af254024 --- /dev/null +++ b/grafik/aufkleber/alle-grau-1234.py @@ -0,0 +1,221 @@ +#!/usr/bin/env python + +import sys +from lxml import etree as ET + + +def in2px(inch): + return round(inch * DPI, 2) + + +DPI = 90 + +# a4 paper +HEIGHT = in2px(8.268) +WIDTH = in2px(11.69) + +KEYWIDTH = in2px(0.75) +KEYHEIGHT = in2px(0.75) +LABELWIDTH = in2px(0.5) +LABELHEIGHT = in2px(0.55) + +KP_MAPPING = { # mapping for keypad, level 4 + 'Hom': '⇱', + 'KP↑': '⇡', + 'PgU': '⇞', + 'KP←': '⇠', + 'Beg': '•', + 'KP→': '⇢', + 'End': '⇲', + 'KP↓': '⇣', + 'PgD': '⇟', + 'Ins': '⎀', + 'Del': '⌦', + 'Ent': '⏎', + 'vec': ' ⃗' +} + +strokewidth = in2px(0.005) +STYLESHEET = ''' +text.common { + font-family:Linux Biolinum O, Linux Biolinum; + font-style:normal; + font-variant:normal; + font-stretch:normal; + text-align:center; + text-anchor:middle; + stroke:none; +} +text.main { + /*font-weight:bold;*/ + font-size:19px; + fill:#eeeeee; + stroke-width:4; +} +text.special { + font-size:16px; + stroke-width:3; +} +text.outline { + stroke:#111111; + stroke-linejoin:round; +} +rect#boundary { + fill:none; + stroke:#eeeeee; + stroke-width:''' + str(in2px(0.005)) + '''px; +} +rect#border { + fill:#333333; + stroke:#eeeeee; + stroke-width:''' + str(in2px(0.025)) + '''px; +} +text.level1 { +} +text.level2 { +} +text.level3 { + fill:#99dd66; +} +text.level4 { + fill:#6699dd; + font-size:13px; +}''' + +NSMAP = {None: 'http://www.w3.org/2000/svg', + 'xlink': 'http://www.w3.org/1999/xlink'} +XLINK = '{%s}' % NSMAP['xlink'] +DOCTYPE = ('') + + +def parse_ref(filename): + '''parse reference and return multi-array''' + with open(filename) as fh: + lines = fh.read().splitlines() + keymap = [] + state = 0 + for line in lines: + line = line.strip() + if state == 0: + if line.endswith("Miniatur ==="): + state = 1 + layer = [] + keymap.append(layer) + continue + elif not line: # empty line: end of current block/layer + state = 0 + layer = None + continue + elif not line.startswith("│"): # skip horizontal dividers + continue + else: + line = [k.strip() for k in line.split("│")] + layer.append(line[1:-1]) + return keymap + + +def create_defs(parent): + '''create the key template''' + node = ET.SubElement(parent, 'defs') + # style sheet + ET.SubElement(node, 'style', type='text/css').text = STYLESHEET + # boundary of keys + ET.SubElement(node, 'rect', id='boundary', + width=str(KEYWIDTH), height=str(KEYHEIGHT), rx="5") + # border for keys, actual key stickers + ET.SubElement(node, 'rect', id='border', + width=str(LABELWIDTH), height=str(LABELHEIGHT), rx="10") + + +def create_keys(parent, keymap): + posy = 0 + + # main keyboard + # TODO remove leading blank key + for row in range(len(keymap[0])): + posx = row / 2 * KEYWIDTH # not really accurate, but works + for key in range(len(keymap[0][row])): + key = create_key(parent, posx, posy, + keymap[0][row][key], + keymap[1][row][key], + keymap[2][row][key], + keymap[3][row][key]) + if key is not None: # advance only if sticker was output + posx += KEYWIDTH + posy += KEYHEIGHT + + # numpad + for row in range(len(keymap[7])): + posx = 0 + for key in range(len(keymap[7][row])): + key = create_key(parent, posx, posy, + keymap[7][row][key], + keymap[8][row][key], + keymap[9][row][key], + keymap[10][row][key]) + if key is not None: # advance only if sticker was output + posx += KEYWIDTH + posy += KEYHEIGHT + + +def create_key(parent, posx, posy, *keys): + '''create a specific key (cloned from template)''' + + if len(keys[0]) != 1: # skip keys like Tab at the left side + return + + def text(level, trans, type): + ET.SubElement( + g1, 'text', + {'transform': f'translate({trans})', + 'class': f"level{level} common {type}{outline}"} + ).text = keys[level-1] + + keys = list(keys) + + # map words to symbols for numblock + keys[2] = KP_MAPPING.get(keys[2], keys[2]) + keys[3] = KP_MAPPING.get(keys[3], keys[3]) + + g0 = ET.SubElement(parent, 'g', + transform=f"translate({posx},{posy})", + id='key_' + ''.join(keys)) + ET.SubElement(g0, 'use', {XLINK + 'href': '#boundary'}) + g1 = ET.SubElement(g0, 'g', + transform=f'translate({(KEYWIDTH-LABELWIDTH)/2.5}, 2)') + ET.SubElement(g1, 'use', {XLINK + 'href': '#border'}) + + # do not show e1, if it's the same letter as e2 + upper_eq_lower = (keys[1].lower() == keys[0]) + + # add text+outlines to sticker + for outline in (' outline', ''): + if not upper_eq_lower: + text(1, '15,41', 'main') + text(2, '15,19', 'main') + text(3, '32,18', 'special') + text(4, '32,42', 'special') + return g0 + + +def main(): + import argparse + parser = argparse.ArgumentParser() + parser.add_argument('filename') + args = parser.parse_args() + + keymap = parse_ref(args.filename) + + root = ET.Element('svg', + height=str(HEIGHT), width=str(WIDTH), + nsmap=NSMAP) + create_defs(root) + create_keys(root, keymap) + + doc = ET.tostring(root, encoding="UTF-8", xml_declaration=True, + doctype=DOCTYPE, pretty_print=True) + sys.stdout.buffer.write(doc) + + +main() diff --git a/grafik/bilder-uebersicht/Makefile b/grafik/bilder-uebersicht/Makefile index ad41df75..26cc588b 100644 --- a/grafik/bilder-uebersicht/Makefile +++ b/grafik/bilder-uebersicht/Makefile @@ -7,13 +7,13 @@ neo-bunt-123456.png: neo-bunt-123456.ods libreoffice --convert-to png $< neo20-grau-123456.svg: - ./all-grau-123456.php neo20 + ./all-grau-123456.py neo20 bone-grau-123456.svg: - ./all-grau-123456.php bone + ./all-grau-123456.py bone neoqwertz-grau-123456.svg: - ./all-grau-123456.php neoqwertz + ./all-grau-123456.py neoqwertz EXTRASVG=\ neo20-grau-123456.svg \ diff --git a/grafik/bilder-uebersicht/all-grau-123456.php b/grafik/bilder-uebersicht/all-grau-123456.php deleted file mode 100755 index 2a4c1f3c..00000000 --- a/grafik/bilder-uebersicht/all-grau-123456.php +++ /dev/null @@ -1,3476 +0,0 @@ -#!/usr/bin/env php - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - Strg - Umsch - Mod 3 - Mod 4 - Alt - Tab - Mod 4 - Strg - Umschalt - Mod 3 - Backspace - Return - {1_1} - {1_2} - {1_3} - {1_4} - {1_5} - {1_6} - - {2_1} - {2_2} - {2_3} - {2_4} - {2_5} - {2_6} - - {3_1} - {3_2} - {3_3} - {3_4} - {3_5} - {3_6} - - {4_1} - {4_2} - {4_3} - {4_4} - {4_5} - {4_6} - - {5_1} - {5_2} - {5_3} - {5_4} - {5_5} - {5_6} - - {6_1} - {6_2} - {6_3} - {6_4} - {6_5} - {6_6} - - {7_1} - {7_2} - {7_3} - {7_4} - {7_5} - {7_6} - - {8_1} - {8_2} - {8_3} - {8_4} - {8_5} - {8_6} - - {9_1} - {9_2} - {9_3} - {9_4} - {9_5} - {9_6} - - {10_1} - {10_2} - {10_3} - {10_4} - {10_5} - {10_6} - - {11_1} - {11_2} - {11_3} - {11_4} - {11_5} - {11_6} - - {12_1} - {12_2} - {12_3} - {12_4} - {12_5} - {12_6} - - {13_1} - {13_2} - {13_3} - {13_4} - {13_5} - {13_6} - - {14_1} - {14_2} - {14_3} - {14_4} - {14_5} - {14_6} - - {15_1} - {15_2} - {15_3} - {15_4} - {15_5} - {15_6} - - {16_1} - {16_2} - {16_3} - {16_4} - {16_5} - {16_6} - - {17_1} - {17_2} - {17_3} - {17_4} - {17_5} - {17_6} - - {18_1} - {18_2} - {18_3} - {18_4} - {18_5} - {18_6} - - {19_1} - {19_2} - {19_3} - {19_4} - {19_5} - {19_6} - - {20_1} - {20_2} - {20_3} - {20_4} - {20_5} - {20_6} - - {21_1} - {21_2} - {21_3} - {21_4} - {21_5} - {21_6} - - {22_1} - {22_2} - {22_3} - {22_4} - {22_5} - {22_6} - - {23_1} - {23_2} - {23_3} - {23_4} - {23_5} - {23_6} - - {24_1} - {24_2} - {24_3} - {24_4} - {24_5} - {24_6} - - {25_1} - {25_2} - {25_3} - {25_4} - {25_5} - {25_6} - - {26_1} - {26_2} - {26_3} - {26_4} - {26_5} - {26_6} - - {27_1} - {27_2} - {27_3} - {27_4} - {27_5} - {27_6} - - {28_1} - {28_2} - {28_3} - {28_4} - {28_5} - {28_6} - - {29_1} - {29_2} - {29_3} - {29_4} - {29_5} - {29_6} - - {30_1} - {30_2} - {30_3} - {30_4} - {30_5} - {30_6} - - {31_1} - {31_2} - {31_3} - {31_4} - {31_5} - {31_6} - - {32_1} - {32_2} - {32_3} - {32_4} - {32_5} - {32_6} - - {33_1} - {33_2} - {33_3} - {33_4} - {33_5} - {33_6} - - {34_1} - {34_2} - {34_3} - {34_4} - {34_5} - {34_6} - - {35_1} - {35_2} - {35_3} - {35_4} - {35_5} - {35_6} - - {36_1} - {36_2} - {36_3} - {36_4} - {36_5} - {36_6} - - {37_1} - {37_2} - {37_3} - {37_4} - {37_5} - {37_6} - - {38_1} - {38_2} - {38_3} - {38_4} - {38_5} - {38_6} - - {39_1} - {39_2} - {39_3} - {39_4} - {39_5} - {39_6} - - {40_1} - {40_2} - {40_3} - {40_4} - {40_5} - {40_6} - - {41_1} - {41_2} - {41_3} - {41_4} - {41_5} - {41_6} - - {42_1} - {42_2} - {42_3} - {42_4} - {42_5} - {42_6} - - {43_1} - {43_2} - {43_3} - {43_4} - {43_5} - {43_6} - - {44_1} - {44_2} - {44_3} - {44_4} - {44_5} - {44_6} - - {45_1} - {45_2} - {45_3} - {45_4} - {45_5} - {45_6} - - {46_1} - {46_2} - {46_3} - {46_4} - {46_5} - {46_6} - - -EOF; - - # Ersetze die Platzhalter mit den Zeichen aus dem Array - foreach ($key as $search => $replace) { - # Die Zeichen werden in HTML-NCRs (numeric character references) umgewandelt, damit sie nicht falsch interpretiert werden. - $svg = preg_replace('/{'.preg_quote($search).'}/', mb_encode_numericentity ($replace, array (0x0, 0xffff, 0, 0xffff), 'UTF-8'), $svg); - } - - # Speichern und Fertig - file_put_contents($layout . '-grau-123456.svg', $svg); -?> diff --git a/grafik/bilder-uebersicht/all-grau-123456.py b/grafik/bilder-uebersicht/all-grau-123456.py new file mode 100755 index 00000000..088f4d74 --- /dev/null +++ b/grafik/bilder-uebersicht/all-grau-123456.py @@ -0,0 +1,255 @@ +#!/usr/bin/env python + +import os +from lxml import etree as ET + +REFERENZ_DIR = '../../A-REFERENZ-A/' + +KEYWIDTH = KEYHEIGHT = 72 +LABELWIDTH = KEYWIDTH +LABELHEIGHT = KEYWIDTH + +KP_MAPPING = { # mapping for keypad, level 4 + 'Hom': '⇱', + 'KP↑': '⇡', + 'PgU': '⇞', + 'KP←': '⇠', + 'Beg': '•', + 'KP→': '⇢', + 'End': '⇲', + 'KP↓': '⇣', + 'PgD': '⇟', + 'Ins': '⎀', + 'Del': '⌦', + 'Ent': '⏎', + 'vec': ' ⃗' +} + +STYLESHEET = ''' +rect.grey { fill:#cccccc !important } +rect.key { fill:white; stroke:black; stroke-width: 1 } + +text { + /* font-family:Linux Biolinum O, Linux Biolinum;*/ + font-family:normal; + font-style:normal; + font-variant:normal; + font-stretch:normal; + stroke:none; + text-align:center; + text-anchor:middle; + dominant-baseline: middle; + fill: black; +} +text.main { font-weight:bold } +text.special { } +text.level1 { font-size:22px } +text.level2 { font-size:22px } +text.level3 { font-size:14px } +text.level4 { font-size:14px } +text.level5 { font-size:14px } +text.level6 { font-size:14px } +text.deadkey { fill: red } +text.modifier { font-size:20px } +''' + +NSMAP = {None: 'http://www.w3.org/2000/svg', + 'xlink': 'http://www.w3.org/1999/xlink'} +XLINK = '{%s}' % NSMAP['xlink'] +DOCTYPE = ('') + + +LAYOUT = ( + [1] * 13 + [2.0], + [1.5] + [1] * 12 + [0], + [1.75] + [1] * 11 + [1.0, 0], + [1.25, 1.0] + [1] * 10 + [2.75, 0], + ) + +SPECIAL_KEYS = ( + (0, 13, 2.0, "Backspace"), + (1, 0, 1.5, "Tab"), + (2, 0, 1.75, "Mod 3"), + (2, 12.75, 1, "Mod 3"), + (3, 0, 1.25, "Umsch"), + (3, 1.25, 1, "Mod 4"), + (3, 12.25, 2.75, "Umschalt"), + (4, 0, 1.5, "Strg"), + (4, 2.5, 1.5, "Alt"), + (4, 9.5, 1.5, "Mod4"), + (4, 13.5, 1.5, "Strg"), + ) + + +def parse_ref(layout): + '''parse reference and return multi-array''' + filename = os.path.join(REFERENZ_DIR, f'{layout}.txt') + with open(filename) as fh: + lines = fh.read().splitlines() + keymap = [] + state = 0 + for line in lines: + line = line.strip() + if state == 0: + if line.endswith("Miniatur ==="): + state = 1 + layer = [] + keymap.append(layer) + continue + elif not line: # empty line: end of current block/layer + state = 0 + layer = None + continue + elif not line.startswith("│"): # skip horizontal dividers + continue + else: + line = [k.strip() for k in line.split("│")] + layer.append(line[1:-1]) + return keymap + + +def create_defs(parent): + '''create the key template''' + node = ET.SubElement(parent, 'defs') + # style sheet + ET.SubElement(node, 'style', type='text/css').text = STYLESHEET + # boundary of keys + # ET.SubElement(node, 'rect', id='boundary', + # width=str(KEYWIDTH), height=str(KEYHEIGHT), rx="0") + # # border for keys, actual key stickers + # ET.SubElement(node, 'rect', id='border', + # width=str(LABELWIDTH), height=str(LABELHEIGHT), rx="0") + + +def draw_keys(parent): + # draw return key first to be overdrawn by others + w = sum(LAYOUT[0]) * KEYWIDTH + posx = sum(LAYOUT[1]) * KEYWIDTH + ET.SubElement(parent, 'rect', {'class': 'key grey'}, + x=str(posx), y=str(KEYHEIGHT + 1), + width=str(w - posx), height=str(2 * KEYHEIGHT)) + + def rect(x, y, kwidth, classes): + kwidth *= KEYWIDTH + ET.SubElement(parent, 'rect', {'class': classes}, + x=str(x), y=str(y), + width=str(kwidth), height=str(KEYHEIGHT)) + return kwidth + + # other keys + posy = 1 + for row in LAYOUT: + posx = 0 + for key in row: + if not key: + continue + elif isinstance(key, float): + kwidth = key * KEYWIDTH + else: + kwidth = rect(posx, posy, key, 'key') + posx += kwidth + posy += KEYHEIGHT + drawing_width = posx + 1 + + # special keys + for row, col_offset, kwidth, label in SPECIAL_KEYS: + rect(col_offset * KEYWIDTH, row * KEYHEIGHT + 1, kwidth, 'key grey') + rect(4 * KEYWIDTH, posy, 5.5, 'key') # Leertaste + + posy += KEYHEIGHT + return drawing_width, posy + + +def create_labels(parent, keymap): + posy = 1 + # main keyboard + for row in range(len(keymap[0])-1): + posx = 0 + for key in range(len(keymap[0][row])): + create_label(parent, posx, posy, + keymap[0][row][key], + keymap[1][row][key], + keymap[2][row][key], + keymap[3][row][key], + keymap[4][row][key], + keymap[5][row][key]) + posx += LAYOUT[row][key] * KEYWIDTH + posy += KEYHEIGHT + + def text(x, y, kwidth, label): + x = x * KEYWIDTH + kwidth * KEYWIDTH / 2 + 1 + y = y * KEYHEIGHT + KEYHEIGHT / 2 + 1 + ET.SubElement( + parent, 'text', + {'x': str(x), 'y': str(y), + 'class': 'modifier'} + ).text = label + + # special keys + for row, col_offset, kwidth, label in SPECIAL_KEYS: + text(col_offset, row, kwidth, label) + text(13.5, 1.25, 1.75, "Return") + + +def create_label(parent, posx, posy, *labels): + '''create a specific key (cloned from template)''' + + def text(level, trans, type): + ET.SubElement( + g, 'text', + {'transform': f'translate({trans})', + 'class': f"level{level} {type} {deadkey}"} + ).text = labels[level-1] + + labels = list(labels) + if len(labels[0]) > 1: + # special keys are labels special above + return + + # map words to symbols for numblock + labels[2] = KP_MAPPING.get(labels[2], labels[2]) + labels[3] = KP_MAPPING.get(labels[3], labels[3]) + + g = ET.SubElement(parent, 'g', + transform=f"translate({posx},{posy})", + id='key_' + ''.join(labels)) + upper_eq_lower = (labels[1].lower() == labels[0]) + deadkey = 'deadkey' if labels[0] in "ˆ`´" else 'live' + + if upper_eq_lower: + # do not show e1, if it's the same letter as e2 + text(2, '15,35', 'main') + else: + text(1, '15,55', 'main') + text(2, '15,20', '') + text(3, '42,50', 'special') + text(4, '42,20', 'special') + text(5, '59,50', 'special') + text(6, '59,20', 'special') + + +def main(): + import argparse + parser = argparse.ArgumentParser() + parser.add_argument('layout') + args = parser.parse_args() + + keymap = parse_ref(args.layout) + + root = ET.Element('svg', + nsmap=NSMAP) + create_defs(root) + width, height = draw_keys(root) + create_labels(root, keymap) + + root.set('width', str(width)) + root.set('height', str(height)) + + doc = ET.tostring(root, encoding="utf-8", xml_declaration=True, + doctype=DOCTYPE, pretty_print=True) + with open(f'{args.layout}-grau-123456.svg', 'wb') as fh: + fh.write(doc) + + +main() diff --git a/grafik/shell.nix b/grafik/shell.nix index aa475964..e7f45e57 100644 --- a/grafik/shell.nix +++ b/grafik/shell.nix @@ -14,9 +14,7 @@ pkgs.mkShell { python3Packages.seaborn python3Packages.more-itertools python3Packages.jinja2 - perl - perlPackages.XMLWriter - php + python3Packages.lxml ]; # You also need to install the fonts (libertine gentium dejavu ... )