44fc0d6ce526810b3229cd1437277b7ff0453e45
[sheet.git] / writing-latn.inc.pl
1 use 5.014;
2 use utf8;
3 use warnings;
4 use List::Util qw( pairs pairmap sum );
5
6 my %C = (
7         red    => '#EC1C24',
8         blue   => '#3953A3',
9         yellow => '#F9EC31',
10         black  => '#231F20',
11 );
12 my $U = 0;  # optional unicode alternatives
13
14 my @wrapstyle = (
15         'td { white-space: normal; word-spacing: 10em }', # force line break between words
16         '.sample { word-spacing: 0 }',
17         '.sample span { margin-right: 1ex; white-space: nowrap; display: inline-block }', # larger space between letters
18 );
19 my $spacestyle = '.sample span { margin-right: 0.5ex }';  # separate multiple letters
20 my @tapstyle = (
21         @wrapstyle,
22         '{ line-height: 1ex }',
23         '.sample { font-size: 80% }',
24 );
25
26 my @hueorder = (
27         2,11,20,19,18,21,24,15,6,7,8,5,13, # red .. magenta, grey
28         1,10,9,12,3,4,0, 14,23,22,25,16,17,26, # dark, light hues
29 );
30
31 sub disptap {
32         my $code = shift;
33         my ($prefix, @dots) = $code =~ m/\A(-?)(\d)(\d)/ or return $code;
34         if ($U) {
35                 # unicode glyph alternative as DOMINO TILE HORIZONTAL-0a-0b
36                 return $prefix . chr(0x1F031 + ($dots[0] * 7) + $dots[1]);
37         }
38         return $prefix . join(' ', map { '·' x $_ } @dots);
39 }
40
41 sub dispbar {
42         my $code = shift or return '';
43
44         return join '', pairmap {
45                 ($a =~ tr/123/❘❙❚/r) . ($b =~ tr/321/  /dr)
46         } split //, $code if $U;
47
48         my @cols = split //, $code;  # bar and space widths
49         my $width = sum(@cols);
50         return sprintf(
51                 '<svg width="%d" height="%d" viewBox="-.5 0 %d %d"><path d="%s"/></svg>',
52                 $width * 2, 14, $width, 7, join(' ',
53                         'M0,0',
54                         map {
55                                 join('m1,-7', ('v7') x $_->[0]),  # line per bar width
56                                 (map { sprintf 'm%d,-7', $_ + 1 } $_->[1] || ()),  # space forward
57                         }
58                         pairs @cols
59                 )
60         );
61 }
62
63 sub disphues {
64         my ($index, $hues, $opaque) = @_;
65         my @lum = ($index % 3, $index / 3 % 3, $index / 9);  # hue opacities (0..2)x3
66         my @lumf = $opaque ? ('hsl(%s,100%%,50%%)', 'hsl(%s,100%%,25%%)') :
67                 ('hsl(%s,100%%,50%%)', 'hsla(%s,100%%,50%%,.5)');
68         return sprintf(
69                 '<svg width="16" height="16" viewBox="0 0 22 22">%s</svg>',
70                 join '', map {
71                         my $colf = $lumf[ $lum[$_] ];
72                         !$colf ? () : sprintf('<circle cx="%d" cy="%d" r="%d" fill="%s"/>',
73                                 10 + $_, $_ == 1 ? 12 : 10, 10, sprintf($colf, $hues->[$_])
74                         );
75                 } 0 .. 2
76         );
77 }
78
79 (
80 uppercase => {
81         list => [qw{ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z }],
82 },
83 lowercase => {
84         list => [qw{ a b c d e f g h i j k l m n o p q r s t u v w x y z }],
85 },
86 suetterlin => {
87         title => 'Sütterlin',
88         style => [
89                 '@font-face {
90                         font-family: Suetterlin; /* R. G. Arens */
91                         src: url("/suetterlin.ttf");
92                 }',
93                 'td { font-family: Suetterlin }',
94         ],
95         list => [qw{ a b c d e f g h i j k l m n o p q r ſ s t u v w x y z }],
96 },
97 roman => {
98         title => 'Old Roman Cursive',
99         style => [
100                 'svg path { stroke-linecap: round; stroke-linejoin: round }',
101                 '.sample span { margin-right: -10px }',
102         ],
103         list => [
104                 map {
105                         !m/^(-?)(\w.+)/ ? $_ :
106                         $1.'<svg width="20" height="20" viewBox="0 0 12 20"><path d="'.$2.'"/></svg>'
107                 }
108                 "m2,4 c1,2 8,9 8,9 M2,15 6,9",
109                 "m2,4 c0,0 3,-2 4,1 1,2 0,9 3,9 1,-0 2,-1 2,-1 m-6,-2 c-5,4 -0,6 1,3",
110                 "m4,7 4,-2 m-4,4 c0,0 -2,7 3,6",
111                 "m3,2 c0,0 7,10 7,12 m-2,-4 c-5,2 -4,9 1,3",
112                 "m3,10 4,0 m2,-7 c0,0 -7,1 -5,16",
113                 "m4,11 5,-2 m-3,-4 7,-4 M0,18 c0,0 4,3 5,-3 2,-6 2,-10 2,-10",
114                 "m3,6 7,-2 m-7,4 c-2,5 4,9 6,6 l1,3",
115                 "m7,9 4,-0 m-8,0 c4,0 6,-1 5,6 M1,3 c2,-0 2,12 2,12",
116                 '>', # i = j
117                 "m6,8 -0,7",
118                 "-m9,5 -5,4 4,4 m-4,-10 -1,13",
119                 "m3,2 c0,0 -1,9 1,10 5,2 6,2 6,2",
120                 "m0,16 3,-10 4,6 2,-5 5,4",
121                 "m2,16 1,-9 5,8 2,-9",
122                 "m5,8 c-2,0 -2,6 1,5 4,-2 1,-5 1,-5",
123                 "m5,8 c0,0 -1,8 2,6 m-3,-7 5,3",
124                 "m3,6 9,12 m-9,-11 c-4,1 -3,4 -3,4 0,0 2,2 6,-1",
125                 "m0,6 c3,-1 3,-1 6,0 2,1 3,3 6,1 m-7,-1 -2,11",
126                 "m13,3 c0,0 -5,2 -8,4 -2,3 -1,5 -2,9 -1,1 -4,2 -4,2",
127                 "m2,7 8,0 m-4,1 c0,0 -1,8 3,5",
128                 '>', # u = v
129                 "m2,5 c0,0 3,5 6,3 3,-2 2,-3 2,-3",
130                 '-',
131                 "m3,19 c-1,-6 6,-17 6,-17 M1,8 c0,0 10,1 10,1",
132                 "-m0,7 c2,-3 5,-2 5,1 l0,11 c0,0 -0,-4 -0,-10 -0,-4 4,-4 6,-3",
133                 "-m3,6 c4,-1 3,3 3,3 -1,3 -2,5 -1,5 1,1 3,0 3,0",
134         ],
135 },
136 sutton => {
137         title => 'Sutton <abbr title="American Sign Lanugage">ASL</abbr>',
138         style => $spacestyle,
139         list => [
140                 # American manual alphabet in Sutton (U+1D800+) notation
141                 map { !!$_ && pack 'W*', map { hex "1D$_" } unpack '(A3)*', $_ } qw{
142                 8F7a9c    847a9c    86Da9c    801a9c    84Aa9c
143                 8CEa9c    8F0       815aa2    892a9c    892a9c9A2aac
144                 840a9c    8DCa9c    88Da9c
145                 819a9c    876a9c    840a9caA1 8F0a9caA1 81Aa9c
146                 903a9c    8FBa9c    815a9c    80Ea9c    887a9c
147                 806a9c    89Aa9c    800a9c945aaa
148                 0         965aa6
149         }],
150 },
151 unistrokes => {
152         title => 'Unistrokes',
153         url   => 'https://www.google.com/patents/US5596656', # by Xerox
154         style => 'svg path { stroke-linecap: round; stroke-linejoin: round }',
155         list => [
156                 map { '<svg width="14" height="16" viewBox="-1 -1 8 10">'.$_.'</svg>' }
157                 map {
158                         sprintf('<circle cx="%s" cy="%s" r="1"/>', m/\AM(\d+),(\d+)(.?)/) . # start point
159                         (!!$3 && qq(<path d="$_"/>))
160                 }
161                 'M3,8 V0',
162                 'M0,0 6,4 0,8',
163                 'M6,0 0,4 6,8',
164                 'M6,0 0,4 6,8',
165                 'M6,4 H0',
166                 'M6,0 0,0 0,8',
167                 'M0,8 6,8 6,0',
168                 'M0,0 6,0 6,8',
169                 'M3,0 V8',
170                 'M6,0 6,8 0,8',
171                 'M0,8 6,0',
172                 'M0,0 0,8 6,8',
173                 'M6,8 3,0 0,8',
174                 'M0,8 3,0 6,8',
175                 'M6,0 Q0,6 3,8 6,6 0,0',
176                 'M0,0 Q4,8 6,4 4,0 0,8',
177                 'M6,0 Q2,8 0,4 2,0 6,8',
178                 'M0,0 6,8',
179                 'M6,0 0,0 6,8 0,8',
180                 'M0,4 H6',
181                 'M6,0 3,8 0,0',
182                 'M0,0 3,8 6,0',
183                 'M0,0 0,8 6,0 6,8',
184                 'M0,0 Q6,6 3,8 0,6 6,0',
185                 'M6,0 0,8',
186                 'M0,0 6,0 0,8 6,8',
187                 'M3,4',
188         ],
189 },
190 edgewrite => {
191         title => 'EdgeWrite',
192         url   => 'http://depts.washington.edu/ewrite/', # patented US7729542
193         style => 'svg path { stroke-linecap: round; stroke-linejoin: round }',
194         list => [
195                 map { '<svg width="14" height="14" viewBox="-1 -1 10 10">'.$_.'</svg>' }
196                 map {
197                         my @route = split //;
198                         my @coords = map { $_ % 2 << 3, $_ >> 1 << 3 } @route; # x,y,
199                         sprintf('<circle cx="%s" cy="%s" r="1"/>', @coords[0, 1]) . # start point
200                         sprintf('<path d="M%s"/>', join ' ', map {
201                                 my $pos = join(',', @coords[$_*2, $_*2 + 1]);
202                                 $_ > 1 && $route[$_] == $route[$_ - 2] ? 'Q4,4 '.$pos.'L' : # curve back
203                                 $pos
204                         } 0 .. $#route)
205                 }
206                 # corners (0..3) clockwise from top-left in order
207                 qw(
208                         213 0232 1023 1323 103 102 10132 0213 02 132 02123 023 20313 2031
209                         10231 0102 10131 201 1032 013 0231 021 02131 0312 0313 0123  01
210                 )
211         ],
212 },
213 #graffiti => {
214 #       title => 'Palm Graffiti',
215 #},
216 ita2 => {
217         title => '<abbr title="International Telegraph Alphabet">ITA</abbr>2',
218         style => [@wrapstyle, 'td { font-size: 50% }'],
219         list => [map { tr/01/○●/r =~ s/..\K/ /r } qw(
220                 11000 10011 01110 10010 10000 10110 01011 00101 01100 11010 11110 01001 00111
221                 00110 00011 01101 11101 01010 10100 00001 11100 01111 11001 10111 10101 10001
222                 00100
223         )],
224 },
225 braille => {
226         list => [qw{ ⠁ ⠃ ⠉ ⠙ ⠑ ⠋ ⠛ ⠓ ⠊ ⠚ ⠅ ⠇ ⠍ ⠝ ⠕ ⠏ ⠟ ⠗ ⠎ ⠞ ⠥ ⠧ ⠺ ⠭ ⠽ ⠵ }],
227 },
228 tactile => {
229         title => '5-point Tactile',
230         list => [
231                 map { '<svg width="9" height="12" viewBox="0 0 18 24">'.$_.'</svg>' }
232                 map {
233                         join '', map { sprintf '<circle cx="%d" cy="%d" r="4"/>',
234                                 !$_ ?  9 : $_ & 1 ? 4 : 14,
235                                 !$_ ? 12 : $_ < 3 ? 4 : 20,
236                         } split //
237                 }
238                 qw{
239                         4 234 012 14 0 014 023 12
240                         02 024 0134 23 013 03 01 123
241                         0124 13 04 1 34 0123 134 0234
242                         034 124
243                 }
244         ],
245 },
246 morse => {
247         style => $spacestyle,
248         list => [map {tr/.-/‧‑/r} qw{
249                 .- -... -.-. -.. . ..-. --. .... .. .--- -.- .-.. --
250                 -. --- .--. --.- .-. ... - ..- ...- .-- -..- -.-- --..
251         }],
252 },
253 tap => {
254         title => 'Tap code',
255         style => \@tapstyle,
256         list => [map { disptap($_) } qw{
257                 11 12 13 14 15 21 22 23  > 24 25 31 32
258                 33 34 35 41 42 43 44 45 51 52 53 54 55
259         }],
260 },
261 shorttap => {
262         title => 'Short Tap',
263         style => \@tapstyle,
264         list => [map { disptap($_) } qw{
265                 11 12 13 14 21 22 23 20 > 31 -13 32 33
266                 30 41 42 -13 43 40 10 51 52 53 50 -31 -40
267         }],
268 },
269 cards => {
270         style => 'td { font-family: Symbola, "DejaVu Sans", serif, sans }',
271         list => [(
272                 map { chr(0x1F0A0 + $_), sprintf('<b>%s</b>', chr(0x1F0B0 + $_)) }  # spades, hearts
273                 1 .. 11, 13, 14  # A 2-10 J Q K
274         ), '', chr(0x1F0CF), chr(0x1F0DF) ],
275 },
276 maritime => {
277         title => 'Maritime flags',
278         style => $spacestyle,
279         list => [
280                 # International Code of Signals, SVG fills
281                 map { !!$_ && '<svg width="20" height="20" viewBox="0 0 30 30">'.s/\n?\t+//gr.'</svg>' }
282                 split /\n\n/, qq{
283                         <path fill="$C{blue}" d="M0,0 h30 l-7.5,15 7.5,15 h-30 z"/>
284                         <path fill="white" d="M0,0 h15 v30 h-15"/>
285
286                         <path fill="$C{red}" d="M0,0 h30 l-7.5,15 7.5,15 h-30 z"/>
287
288                         <path fill="$C{blue}" d="M0,0 h30v30 h-30z"/>
289                         <path fill="white" d="M0,6  h30 v18 h-30" />
290                         <path fill="$C{red}" d="M0,12 h30 v6  h-30" />
291
292                         <path fill="$C{yellow}" d="M0,0 h30v30 h-30z"/>
293                         <path fill="$C{blue}" d="M0,6 h30 v18 h-30"/>
294
295                         <path fill="$C{red}" d="M0,0 h30v30 h-30z"/>
296                         <path fill="$C{blue}" d="M0,0 h30 v15 h-30"/>
297
298                         <path fill="white" d="M0,0 h30v30 h-30z"/>
299                         <path fill="$C{red}" d="M15,0 l15,15 -15,15 -15,-15"/>
300
301                         <path fill="$C{blue}" d="M0,0 h30v30 h-30z"/>
302                         <path fill="$C{yellow}" d="M 0,0 h5 v30 h-5"/>
303                         <path fill="$C{yellow}" d="M10,0 h5 v30 h-5"/>
304                         <path fill="$C{yellow}" d="M20,0 h5 v30 h-5"/>
305
306                         <path fill="$C{red}" d="M0,0 h30v30 h-30z"/>
307                         <path fill="white" d="M0,0 h15 v30 h-15"/>
308
309                         <path fill="$C{yellow}" d="M0,0 h30v30 h-30z"/>
310                         <circle fill="$C{black}" r="7.5" cx="15" cy="15"/>
311
312                         <path fill="$C{blue}" d="M0,0 h30v30 h-30z"/>
313                         <path fill="white" d="M0,10 h30 v10 h-30"/>
314
315                         <path fill="$C{blue}" d="M0,0 h30v30 h-30z"/>
316                         <path fill="$C{yellow}" d="M0,0 h15 v30 h-15"/>
317
318                         <path fill="$C{black}" d="M0,0 h30v30 h-30z"/>
319                         <path fill="$C{yellow}" d="M0,0 h15 v15 h-15 M15,15 h15 v15 h-15"/>
320
321                         <path fill="white" d="M0,0 h30v30 h-30z"/>
322                         <path fill="$C{blue}" d="M4,0h22l-11,11 M4,30h22l-11,-11 M0,4v22l11,-11 M30,4v22l-11,-11"/>
323
324                         <path fill="white" d="M0,0 h30v30 h-30z"/>
325                         <path fill="$C{blue}" d="
326                                 M0,0     h7.5v7.5h-7.5 m0,7.5h7.5v7.5h-7.5
327                                 m7.5,-15 h7.5v7.5h-7.5 m0,7.5h7.5v7.5h-7.5
328                                 m7.5,-30 h7.5v7.5h-7.5 m0,7.5h7.5v7.5h-7.5
329                                 m7.5,-15 h7.5v7.5h-7.5 m0,7.5h7.5v7.5h-7.5
330                         "/>
331
332                         <path fill="$C{yellow}" d="M0,0 h30v30 h-30z"/>
333                         <path fill="$C{red}" d="M0,0 h30 v30"/>
334
335                         <path fill="$C{blue}" d="M0,0 h30v30 h-30z"/>
336                         <path fill="white" d="M10,10 h10 v10 h-10"/>
337
338                         <path fill="$C{yellow}" d="M0,0 h30v30 h-30z"/>
339
340                         <path fill="$C{red}" d="M0,0 h30v30 h-30z"/>
341                         <path fill="$C{yellow}" d="M12.5,0 v30 h5 v-30"/>
342                         <path fill="$C{yellow}" d="M0,12.5 h30 v5 h-30"/>
343
344                         <path fill="white" d="M0,0 h30v30 h-30z"/>
345                         <path fill="$C{blue}" d="M10,10 h10 v10 h-10"/>
346
347                         <path fill="white" d="M0,0 h30v30 h-30z"/>
348                         <path fill="$C{red}" d="M0,0 h10 v30 h-10"/>
349                         <path fill="$C{blue}" d="M20,0 h10 v30 h-10"/>
350
351                         <path fill="white" d="M0,0 h30v30 h-30z"/>
352                         <path fill="$C{red}" d="M0,0 h15 v15 h-15 M15,15 h15 v15 h-15"/>
353
354                         <path fill="$C{red}" d="M0,0 h30v30 h-30z"/>
355                         <path fill="white" d="M4,0h22l-11,11 M4,30h22l-11,-11 M0,4v22l11,-11 M30,4v22l-11,-11"/>
356
357                         <path fill="$C{blue}" d="M0,0 h30v30 h-30z"/>
358                         <path fill="white" d="M5,5 h20 v20 h-20"/>
359                         <path fill="$C{red}" d="M10,10 h10 v10 h-10"/>
360
361                         <path fill="white" d="M0,0 h30v30 h-30z"/>
362                         <path fill="$C{blue}" d="M12.5,0 v30 h5 v-30"/>
363                         <path fill="$C{blue}" d="M0,12.5 h30 v5 h-30"/>
364
365                         <path fill="$C{red}" d="M0,0 h30v30 h-30z"/>
366                         <path fill="$C{yellow}" d="M0,0h6l-6,6 M12,0h6l-18,18v-6 M24,0h6l-30,30v-6
367                                 M30,6v6l-18,18h-6 M30,18v6l-6,6h-6"/>
368
369                         <path fill="$C{black}" d="M0,0 h30v30 h-30z"/>
370                         <path fill="$C{blue}" d="M30,0 v31 l-15,-15"/>
371                         <path fill="$C{yellow}" d="M0,0  h31 l-15,15"/>
372                         <path fill="$C{red}" d="M0,30 h31 l-15,-15"/>
373
374
375
376                         <path fill="$C{blue}" d="M0,5 30,15 0,25"/>
377                         <path fill="$C{yellow}" d="M0,9 20,15 0,21"/>
378
379                         <path fill="$C{blue}" d="M0,5 30,15 0,25"/>
380                         <path fill="white" d="M15,10 30,15 15,20"/>
381                 },
382         ],
383 },
384 flag => {
385         title => 'Flag semaphore',
386         list => [
387                 map {
388                         local $_ = $_;
389                         s/[1-4]\K(?=[4-9])/ /; # prevent unwanted vertical crossing
390                         tr/1-9/↙←↖↑↗→↘↓/;
391                         s{(\S)(?=.)}{<span style="position:absolute">$1</span>};
392                         $_
393                 }
394                 qw(
395                         1 2 3 4 5  6 7 21 31 46  14 51 16 17 23
396                         24 25 26 27 34  35 47 56 57 36  67
397                 )
398         ],
399 },
400 chappe => {
401         title => 'Chappe semaphore',
402         list => [
403                 map {
404                         my ($r, $pr, $pl) = split //, $_;
405                         /^\D$/ ? $_ : sprintf(
406                                 join('',
407                                         '<svg width="16" height="20" viewBox="0 0 10 15">',
408                                         '<path d="M5,6 v7"/>',
409                                         '<path d="M0,%s h10 %s" transform="rotate(%d 5 6)"/>',
410                                         '</svg>',
411                                 ),
412                                 ['6', '3v3', '9v-3']->[$pl],
413                                 [ '',  'v3',  'v-3']->[$pr],
414                                 $r * 45,
415                         );
416                 }
417                 # 360° rotation (0-7) and position state (0-2) of left and right bars
418                 qw(
419                   021 121 221 321 421 521 621 721
420                   > 022 122 222 322 011 111 211 311
421                   001 101 201 301 401 501 601 701 020
422                 )
423         ],
424 },
425 prussian => {
426         title => 'Prussian semaphore',
427         list => [
428                 map { /^\D+$/ ? $_ : sprintf
429                         join('',
430                                 '<svg width="10" height="20" viewBox="0 0 8 18">',
431                                 '<path d="M4,1 v18"/>',
432                                 (map {(
433                                         qq(<path d="M0 $_ h4" transform="rotate(%d 4 $_)"/>),
434                                         qq(<path d="M4 $_ h4" transform="rotate(-%d 4 $_)"/>),
435                                 )} 3, 7, 14),
436                                 '</svg>',
437                         ),
438                         map { ($_ - 2) * 45 % 360 } split //, $_
439                 }
440                 # rotation state (0-3) for left and right bar of 3 rows
441                 qw(
442                         003000 000200 203300 000030 033030 000130 000330 032330 > 031330
443                         022020 130120 001320 233010 030210 022310 203001 233001
444                         131001 231301 000202 023302 230003 032003 201003 101003
445                 )
446         ],
447 },
448 code39 => {
449         title => 'Code 39',
450         list => [map { dispbar($_) } qw(
451                 2111121121 1121121121 2121121111 1111221121 2111221111 1121221111
452                 1111122121 2111122111 1121122111 1111222111 2111111221 1121111221
453                 2121111211 1111211221 2111211211 1121211211 1111112221 2111112211
454                 1121112211 1111212211 2211111121 1221111121 2221111111 1211211121
455                 2211211111 1221211111            1221112111 0 1211212111
456         )], # ISO/IEC 16388
457 },
458 code93 => {
459         title => 'Code 93',
460         list => [map { dispbar($_) } qw(
461                 211113 211212 211311 221112 221211 231111 112113 112212 112311 122112
462                 132111 111123 111222 111321 121122 131121 212112 212211 211122 211221
463                 221121 222111 112122 112221 122121 123111        311211 0 111141
464         )],
465 },
466 code128 => {
467         title => 'Code 128',
468         list => [map { dispbar($_) } qw(
469                 111323 131123 131321 112313 132113 132311 211313 231113 231311 112133
470                 112331 132131 113123 113321 133121 313121 211331 231131 213113 213311
471                 213131 311123 311321 331121 312113 312311        212222 0 211412 23311120
472         )],
473 },
474 rm4scc => {
475         title => '<abbr title="Royal Mail 4-State Customer Code">RM4SCC</abbr>',
476         list => [
477                 map {
478                         my $len = length $_;
479                         !$len ? '' : sprintf(
480                                 '<svg width="%d" height="20" viewBox="0 0 %d 6">'
481                                 . '<path d="M1%s"/></svg>',
482                                 $len * 5, $len * 2,
483                                 join ' m2',
484                                 map { sprintf ',%dv%dm0,-%d',
485                                         ($_ & 1 ? 0 : 2),  2 + ($_ & 2) + ($_ & 1) * 2,
486                                         ($_ & 1 ? 0 : 2) + 2 + ($_ & 2) + ($_ & 1) * 2,
487                                 }
488                                 split //
489                         );
490                 }
491                 qw(
492                                                                 2121 2301
493                         0132 0312 0330 2112 2130 2310
494                         1023 1203 1221 3003 3021 3201
495                         1032 1212 1230 3012 3030 3210
496                         1122 1302 1320 3102 3120 3300
497                         0033
498                 ), # 0 for space
499                 '', 1, 3  # start/end
500         ],
501 },
502 rgbmap => {
503         title => 'RGBmap',
504         style => [
505                 'svg { isolation: isolate }',
506                 'svg circle { mix-blend-mode: screen }',
507                 '.sample { background: black }',
508         ],
509         list => [
510                 map { disphues($_, [0, 240, 120], 1) } # Red, Blue, Green
511                 @hueorder[23..25,20..22, 12, 6..11,0..5, 16..18, 13..15, 19, 26],
512         ],
513 },
514 cmymap => {
515         title => 'CMYmap',
516         style => [
517                 'svg { isolation: isolate }',  # mix on white
518                 'svg circle { mix-blend-mode: multiply }',
519                 '.sample { background: white }',
520         ],
521         list => [
522                 map { disphues($_, [180, 60, 300]) } # Cyan, Yellow, Magenta
523                 @hueorder[13..18, 19, 0..11, 20..25, 12, 26],
524         ],
525 },
526 dni => {
527         title => "D'ni",
528         list => [
529                 map {
530                         state $window = 'M-.5,-.5H8.5V8.5H-.5Z';
531                         state $v = [
532                                 '',
533                                 'M0,4 8,4',
534                                 'M0,8 Q4,4 8,8',
535                                 'M0,4 4,8 8,4',
536                                 'M2,0 2,4 8,4',
537                                 'M0,0 8,8 M0,8 8,0', # cross
538                                 'M3.5,4 h1', # dot
539                         ];
540                         state $h = [
541                                 '',
542                                 'M4,0 4,8',
543                                 'M0,0 Q4,4 0,8',
544                                 'M4,-.5 0,4 4,8.5',
545                                 'M4,8 4,2 8,2',
546                         ];
547                         sprintf '<svg width="16" height="16" viewBox="-.5 -.5 9 9"><path d="%s"/></svg>',
548                                 $window . ($h->[$_ % 5] . $v->[$_ / 5] || $v->[6]);
549                 } 0 .. 5*5
550         ],
551 },
552 pigpen => {
553         style => [
554                 'svg path { stroke-linecap: square }',
555                 '.sample svg { margin-right: 0.1em }',
556         ],
557         list => [
558                 map {
559                         qq(<svg width="12" height="12" viewBox="-.5 -.5 7 7">$_</svg>)
560                 }
561                 map {
562                         local $_ = $_;
563                         s/^H/mX,0/ or s/^V/m0,X/ or s/^/m0,0/;
564                         s/[hv]\K|X/6/g;
565                         s/(?:v|,[^0]).*?v\K/-/;
566                         s/(?:h|m[^0]).*?h\K/-/;
567                         m/h/ or s/v/l3,/g;
568                         m/v/ or s/h([^h]*)/l$1,3/g;
569                         my $dot = s/\.// && qq(<circle cx="3" cy="3" r="1"/>);
570                         qq(<path d="$_"/>$dot)
571                 }
572                 qw(
573                         Hvh  vhv  vh  hvh  vhvh  Hhvh  hv  Vvhv  Hhv
574                         Hvh. vhv. vh. hvh. vhvh. Hhvh. hv. Vvhv. Hhv.
575                         vv  hh  Hhh  Vvv
576                         vv. hh. Hhh. Vvv.
577                 ),
578         ],
579 },
580 nyctographs => {
581         style => [
582                 'svg path { stroke-linecap: round; stroke-linejoin: round }',
583                 '.sample svg {
584                         background: rgba(0,0,0, .1);
585                         padding: 0.1em;
586                         margin-right: 0.2em;
587                 }',
588         ],
589         list => [
590                 map { s/M[\d,\hM]+(?=[M"])//gr }  # clean up superfluous moves
591                 map { sprintf
592                         '<svg width="14" height="14" viewBox="-.5 -.5 5 5">'
593                         . '<path d="M0,0%s %s4,0 %s4,4 %s0,4 %s0,0"/></svg>',
594                         'h.5v.5h-.5v-.5',  # start anchor
595                         map { ['M', 'h0M', 'L']->[$_] }
596                         split //
597                 }
598                 # draw style (0=empty, 1=dot, 2=line connect) to right, down, left, up
599                 qw(
600                         0010 0112 2022 2220 2000 2012 0122 0202 0020 0220 0012 0022 2202
601                         0222 2222 0102 0200 2201 2002 2200 0100 0110 0120 2001 2010 2020 0000
602                 ),
603         ],
604 },
605 chromacons => {
606 #       style => '.sample { word-break: break-all }',
607         list => [
608                 # Colour Alphabet by Paul Green-Armytage (2010)
609                 map {
610                         sprintf('<span%s>%s</span>',
611                                 !!$_ && sprintf(' style="background:#%s" title="%s"', split /:/),
612                                 chr(8195) . (!$_ && chr(8203)) # em space (plus zwsp for spaces)
613                         );
614                 }
615                 qw{
616                         F0A3FF:Amethyst 0075DC:Blue      993F00:Caramel  4C005C:Damson   191919:Ebony
617                         005C31:Forest   2BCE48:Green     FFCC99:Honeydew 808080:Iron     94FFB5:Jade
618                         8F7C00:Khaki    9DCC00:Lime      C20088:Mallow
619                         003380:Navy     FFA405:Orpiment  FFA8BB:Pink     426600:Quagmire FF0010:Red
620                         5EF1F2:Sky      00998F:Turquoise E0FF66:Uranium  740AFF:Violet   990000:Wine
621                         FFFF80:Xanthin  FFFF00:Yellow    FF5005:Zinnia   0
622                 }
623         ],
624 },
625 );