meta-imp-gamesymbols.mkxl /size: 15 Kb    last modification: 2023-12-21 09:44
1%D \module
2%D   [       file=meta-imp-gamesymbols,
3%D        version=2019.10.10,
4%D          title=\METAPOST\ Graphics,
5%D       subtitle=Game Symbols,
6%D         author=Hans Hagen,
7%D           date=\currentdate,
8%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
9%C
10%C This module is part of the \CONTEXT\ macro||package and is
11%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
12%C details.
13
14%D The \METAFUN\ code here is not optimal and efficient but as it serves as an
15%D example I decided to keep it simple. Also, performance is not really an issue
16%D here anyway. Inspired by the classic \quote {Concrete Mathematics} by Don Knuth
17%D we define dice and dominos, which happen to be \UNICODE\ characters now. We
18%D use this opportunity to demonstrate slightly different approached.
19
20%D Each dice gets it's own macro at the \METAPOST\ end. Watch how we use the \type
21%D {simplefun} instance in combination with a calculation wrapper. This will just
22%D execute the code and leave no traces in the text flow. The code itself is not
23%D that spectacular:
24
25%D Todo: variant -2/-3 3D dice
26
27\startMPcalculation{simplefun}
28
29    picture DiceDots[] ; pickup pencircle scaled 3/2 ;
30
31    DiceDots[ 1] := image ( draw(4,4) ; ) ;
32    DiceDots[ 2] := image ( draw(2,6) ; draw(6,2) ; ) ;
33    DiceDots[-2] := image ( draw(6,6) ; draw(2,2) ; ) ;
34    DiceDots[ 3] := image ( draw(2,6) ; draw(4,4) ; draw(6,2) ; ) ;
35    DiceDots[-3] := image ( draw(6,6) ; draw(4,4) ; draw(2,2) ; ) ;
36    DiceDots[ 4] := image ( draw(2,6) ; draw(6,6) ; draw(2,2) ; draw(6,2) ; ) ;
37    DiceDots[ 5] := image ( draw(2,6) ; draw(6,6) ; draw(4,4) ; draw(2,2) ; draw(6,2) ; ) ;
38    DiceDots[ 6] := image ( draw(2,6) ; draw(6,6) ; draw(2,4) ; draw(6,4) ; draw(2,2) ; draw(6,2) ; ) ;
39
40    def DiceFrame =
41        pickup pencircle scaled 1/2 ;
42        draw unitsquare scaled 8 ;
43      % pickup pencircle scaled 3/2 ;
44    enddef ;
45
46    vardef DiceOne =
47        DiceFrame ;
48        draw DiceDots[1] ;
49    enddef ;
50    vardef DiceTwo =
51        DiceFrame ;
52        draw DiceDots[if hasoption "mpsfont" "option" "reverse" : - fi 2] ;
53    enddef ;
54    vardef DiceThree =
55        DiceFrame ;
56        draw DiceDots[if hasoption "mpsfont" "option" "reverse" : - fi 3] ;
57    enddef ;
58    vardef DiceFour =
59        DiceFrame ;
60        draw DiceDots[4] ;
61    enddef ;
62    vardef DiceFive =
63        DiceFrame ;
64        draw DiceDots[5] ;
65    enddef ;
66    vardef DiceSix =
67        DiceFrame ;
68        draw DiceDots[6] ;
69    enddef ;
70
71    vardef DiceBad =
72        DiceFrame ;
73        draw (1,7) -- (7,1) ; draw (1,1) -- (7,7) ;
74    enddef ;
75
76    lmt_registerglyphs [
77        name     = "dice",
78        units    = 12,
79        width    = 8,
80        height   = 8,
81        depth    = 0,
82        usecolor = true,
83    ] ;
84
85    lmt_registerglyph [ category = "dice", unicode = "0x2680", code = "DiceOne;" ] ;
86    lmt_registerglyph [ category = "dice", unicode = "0x2681", code = "DiceTwo;" ] ;
87    lmt_registerglyph [ category = "dice", unicode = "0x2682", code = "DiceThree;" ] ;
88    lmt_registerglyph [ category = "dice", unicode = "0x2683", code = "DiceFour;" ] ;
89    lmt_registerglyph [ category = "dice", unicode = "0x2684", code = "DiceFive;" ] ;
90    lmt_registerglyph [ category = "dice", unicode = "0x2685", code = "DiceSix;" ] ;
91
92    lmt_registerglyph [ category = "dice", private = "invaliddice", code = "DiceBad;" ] ;
93
94    %D The transformations come from DICE3D.MF by Thomas A. Heim (1998)
95
96    transform t[];
97
98    numeric r ; r := sqrt(1/4) ;
99
100    hide((0,0) transformed t1 = (0,0)) ;
101    hide((1,0) transformed t1 = (r,r)) ;
102    hide((0,1) transformed t1 = (0,1)) ;
103
104    hide((0,0) transformed t2 = (0,0)) ;
105    hide((1,0) transformed t2 = (1,0)) ;
106    hide((0,1) transformed t2 = (r,r)) ;
107
108    t3 := t1 shifted (8,0) ; % front to right side
109    t4 := t2 shifted (0,8) ; % front to top
110
111    vardef Diced(expr a, b, c) =
112        draw image (
113            pickup pencircle scaled 1/2 ;
114            draw image (
115                % unitsquare smoothed 1/10
116                nodraw unitsquare scaled 8 transformed t4  ;
117                nodraw unitsquare scaled 8 transformed t3  ;
118                nodraw unitsquare scaled 8 ;
119                dodraw unitsquare scaled 8 ;
120            ) ;
121            draw DiceDots[a]                ;
122            draw DiceDots[b] transformed t3 ;
123            draw DiceDots[c] transformed t4 ;
124        ) ;
125    enddef ;
126
127    lmt_registerglyph [ category = "dice", unicode = "123", code = "Diced(1,2,3);", width = 12, height = 12 ] ;
128    lmt_registerglyph [ category = "dice", unicode = "135", code = "Diced(1,3,5);", width = 12, height = 12 ] ;
129    lmt_registerglyph [ category = "dice", unicode = "142", code = "Diced(1,4,2);", width = 12, height = 12 ] ;
130    lmt_registerglyph [ category = "dice", unicode = "154", code = "Diced(1,5,4);", width = 12, height = 12 ] ;
131    lmt_registerglyph [ category = "dice", unicode = "214", code = "Diced(2,1,4);", width = 12, height = 12 ] ;
132    lmt_registerglyph [ category = "dice", unicode = "231", code = "Diced(2,3,1);", width = 12, height = 12 ] ;
133    lmt_registerglyph [ category = "dice", unicode = "246", code = "Diced(2,4,6);", width = 12, height = 12 ] ;
134    lmt_registerglyph [ category = "dice", unicode = "263", code = "Diced(2,6,3);", width = 12, height = 12 ] ;
135    lmt_registerglyph [ category = "dice", unicode = "312", code = "Diced(3,1,2);", width = 12, height = 12 ] ;
136    lmt_registerglyph [ category = "dice", unicode = "326", code = "Diced(3,2,6);", width = 12, height = 12 ] ;
137    lmt_registerglyph [ category = "dice", unicode = "351", code = "Diced(3,5,1);", width = 12, height = 12 ] ;
138    lmt_registerglyph [ category = "dice", unicode = "365", code = "Diced(3,6,5);", width = 12, height = 12 ] ;
139    lmt_registerglyph [ category = "dice", unicode = "415", code = "Diced(4,1,5);", width = 12, height = 12 ] ;
140    lmt_registerglyph [ category = "dice", unicode = "421", code = "Diced(4,2,1);", width = 12, height = 12 ] ;
141    lmt_registerglyph [ category = "dice", unicode = "456", code = "Diced(4,5,6);", width = 12, height = 12 ] ;
142    lmt_registerglyph [ category = "dice", unicode = "462", code = "Diced(4,6,2);", width = 12, height = 12 ] ;
143    lmt_registerglyph [ category = "dice", unicode = "513", code = "Diced(5,1,3);", width = 12, height = 12 ] ;
144    lmt_registerglyph [ category = "dice", unicode = "536", code = "Diced(5,3,6);", width = 12, height = 12 ] ;
145    lmt_registerglyph [ category = "dice", unicode = "541", code = "Diced(5,4,1);", width = 12, height = 12 ] ;
146    lmt_registerglyph [ category = "dice", unicode = "564", code = "Diced(5,6,4);", width = 12, height = 12 ] ;
147    lmt_registerglyph [ category = "dice", unicode = "624", code = "Diced(6,2,4);", width = 12, height = 12 ] ;
148    lmt_registerglyph [ category = "dice", unicode = "632", code = "Diced(6,3,2);", width = 12, height = 12 ] ;
149    lmt_registerglyph [ category = "dice", unicode = "645", code = "Diced(6,4,5);", width = 12, height = 12 ] ;
150    lmt_registerglyph [ category = "dice", unicode = "653", code = "Diced(6,5,3);", width = 12, height = 12 ] ;
151
152\stopMPcalculation
153
154%D At the \TEX\ end we define four features. The reverse is just there for fun. The
155%D digits features will map digits onto dice.
156
157\definefontfeature
158  [dice:normal]
159  [default]
160  [metapost={category=dice}]
161
162\definefontfeature
163  [dice:reverse]
164  [default]
165  [metapost={category=dice,option=reverse}]
166
167\definefontfeature
168  [dice:digits]
169  [dice:digits=yes]
170
171\definefontfeature
172  [dice:three]
173  [dice:three=yes]
174
175%D The mapping to dice happens here:
176
177\startluacode
178
179    -- before the digits feature
180
181    fonts.handlers.otf.addfeature("dice:three", {
182        type      = "ligature",
183        order     = { "dice:three" },
184        nocheck   = true,
185        data      = {
186            [123] = { 0x31, 0x32, 0x33 },
187            [135] = { 0x31, 0x33, 0x35 },
188            [142] = { 0x31, 0x34, 0x32 },
189            [154] = { 0x31, 0x35, 0x34 },
190            [214] = { 0x32, 0x31, 0x34 },
191            [231] = { 0x32, 0x33, 0x31 },
192            [246] = { 0x32, 0x34, 0x36 },
193            [263] = { 0x32, 0x36, 0x33 },
194            [312] = { 0x33, 0x31, 0x32 },
195            [326] = { 0x33, 0x32, 0x36 },
196            [351] = { 0x33, 0x35, 0x31 },
197            [365] = { 0x33, 0x36, 0x35 },
198            [415] = { 0x34, 0x31, 0x35 },
199            [421] = { 0x34, 0x32, 0x31 },
200            [456] = { 0x34, 0x35, 0x36 },
201            [462] = { 0x34, 0x36, 0x32 },
202            [513] = { 0x35, 0x31, 0x33 },
203            [536] = { 0x35, 0x33, 0x36 },
204            [541] = { 0x35, 0x34, 0x31 },
205            [564] = { 0x35, 0x36, 0x34 },
206            [624] = { 0x36, 0x32, 0x34 },
207            [632] = { 0x36, 0x33, 0x32 },
208            [645] = { 0x36, 0x34, 0x35 },
209            [653] = { 0x36, 0x35, 0x33 },
210        }
211    } )
212
213    -- local invalid = fonts.helpers.privateslot("invaliddice")
214
215    fonts.handlers.otf.addfeature("dice:digits", {
216        type      = "substitution",
217        order     = { "dice:digits" },
218        nocheck   = true,
219        data      = {
220            [0x30] = "invaliddice",
221            [0x31] = 0x2680,
222            [0x32] = 0x2681,
223            [0x33] = 0x2682,
224            [0x34] = 0x2683,
225            [0x35] = 0x2684,
226            [0x36] = 0x2685,
227            [0x37] = "invaliddice",
228            [0x38] = "invaliddice",
229            [0x39] = "invaliddice",
230        },
231    } )
232
233\stopluacode
234
235%D An example is given at the the end of this file so we now move forward with
236%D the dominos.
237
238\startMPcalculation{simplefun}
239
240    %D Because there are so many dominos we predefine the shapes and then register
241    %D the lot in a loop.
242
243    picture Dominos[] ;
244
245    Dominos[0] := image() ;
246    Dominos[1] := image(draw(4,4);) ;
247    Dominos[2] := image(draw(2,6);draw(6,2););
248    Dominos[3] := image(draw(2,6);draw(4,4);draw(6,2););
249    Dominos[4] := image(draw(2,6);draw(6,6);draw(2,2);draw(6,2););
250    Dominos[5] := image(draw(2,6);draw(6,6);draw(4,4);draw(2,2);draw(6,2););
251    Dominos[6] := image(draw(2,6);draw(4,6);draw(6,6);draw(2,2);draw(4,2);draw(6,2););
252  % Dominos[7] := Dominos[0] ;
253  % Dominos[8] := Dominos[0] ;
254  % Dominos[9] := Dominos[0] ;
255
256    %D Defining the font properties is straightforward:
257
258    lmt_registerglyphs [
259        name     = "dominos",
260        units    = 12,
261        width    = 16,
262        height   = 8,
263        depth    = 0,
264        usecolor = true,
265    ] ;
266
267    %D We have horizontal dominos:
268
269    def DrawDominoH(expr a, b) =
270        draw image (
271            pickup pencircle scaled 1/2 ;
272            if (getparameterdefault "mpsfont" "color" "") = "black" :
273                fillup unitsquare xyscaled (16,8) ;
274                draw (8,.5) -- (8,7.5) withcolor white ;
275                pickup pencircle scaled 3/2 ;
276                draw Dominos[a]
277                    withpen currentpen
278                    withcolor white ;
279                draw Dominos[b] shifted (8,0)
280                    withpen currentpen
281                    withcolor white ;
282            else :
283                draw unitsquare xyscaled (16,8) ;
284                draw (8,0) -- (8,8) ;
285                pickup pencircle scaled 3/2 ;
286                draw Dominos[a]
287                    withpen currentpen ;
288                draw Dominos[b] shifted (8,0)
289                    withpen currentpen ;
290            fi ;
291        ) ;
292    enddef ;
293
294    %D and vertical ones. We could use the above macro and rotate and shift and reflect
295    %D but why bother with it:
296
297    def DrawDominoV(expr a, b) = % is H rotated and shifted
298        draw image (
299            pickup pencircle scaled 1/2 ;
300            if (getparameterdefault "mpsfont" "color" "") = "black" :
301                fillup unitsquare xyscaled (8,16) ;
302                draw (.5,8) -- (7.5,8) withcolor white ;
303                pickup pencircle scaled 3/2 ;
304                draw Dominos[a] rotatedaround(center Dominos[a],90)
305                    withpen currentpen
306                    withcolor white  ;
307                draw Dominos[b] rotatedaround(center Dominos[b],90) shifted (0,8)
308                    withpen currentpen
309                    withcolor white  ;
310            else :
311                draw unitsquare xyscaled (8,16) ;
312                draw (0,8) -- (8,8) ;
313                pickup pencircle scaled 3/2 ;
314                draw Dominos[a] rotatedaround(center Dominos[a],90)
315                    withpen currentpen ;
316                draw Dominos[b] rotatedaround(center Dominos[b],90) shifted (0,8)
317                    withpen currentpen ;
318            fi ;
319        ) ;
320    enddef ;
321
322    %D We have two simple loops that define the horizontal range:
323
324    save unicode ; numeric unicode ; unicode := 127025 ; % 1F031
325
326    for i=0 upto 6 :
327        for j=0 upto 6 :
328            lmt_registerglyph [
329                category = "dominos",
330                unicode  = unicode,
331                code     = "DrawDominoH(" & decimal i & "," & decimal j & ");",
332                width    = 16,
333                height   = 8,
334            ] ;
335            unicode := unicode + 1 ;
336        endfor ;
337    endfor ;
338
339    %D and the vertical range:
340
341    save unicode ; numeric unicode ; unicode := 127075 ;
342
343    for i=0 upto 6 :
344        for j=0 upto 6 :
345            lmt_registerglyph [
346                category = "dominos",
347                unicode  = unicode,
348                code     = "DrawDominoV(" & decimal i & "," & decimal j & ");",
349                width    = 8,
350                height   = 16,
351            ] ;
352            unicode := unicode + 1 ;
353        endfor ;
354    endfor ;
355
356    %D Now we're done at the \METAFUN\ end.
357
358\stopMPcalculation
359
360%D We predefine two features:
361
362\definefontfeature
363  [dominos:white]
364  [default]
365  [metapost={category=dominos}]
366
367\definefontfeature
368  [dominos:black]
369  [default]
370  [metapost={category=dominos,color=black}]
371
372\definefontfeature
373  [dominos:digits]
374  [dominos:digits=yes]
375
376%D This last feature is yet to be defined. We could deal with the invalid
377%D dominos with some substitution trickery but let's keep it simple.
378
379\startluacode
380
381    local ligatures = { }
382    local unicode   = 127025
383
384    for i=0x30,0x36 do
385        for j=0x30,0x36 do
386            ligatures[unicode] = { i, j }
387            unicode = unicode + 1 ;
388        end
389    end
390
391    fonts.handlers.otf.addfeature("dominos:digits", {
392        type      = "ligature",
393        order     = { "dominos:digits" },
394        nocheck   = true,
395        data      = ligatures,
396    } )
397
398\stopluacode
399
400\continueifinputfile{meta-imp-gamesymbols.mkxl}
401
402\starttext
403
404    \definefont[DominoW][Serif*dominos:white]
405    \definefont[DominoB][Serif*dominos:black]
406    \definefont[DominoD][Serif*dominos:white,dominos:digits]
407
408    \startTEXpage[offset=3pt]
409        \DominoW
410            \char"1F043\quad 🀱\quad
411            \char"1F052\quad 🀲\quad
412            \char"1F038\quad 🀳\quad
413            \darkgreen\char"1F049\quad \char"1F07B\quad
414        \DominoB
415            \char"1F087\quad
416            \char"1F088\quad
417            \char"1F089\quad
418        \DominoD
419            \darkred 12\quad56\quad64%
420    \stopTEXpage
421
422    \definefont[DiceN][Serif*dice:normal]
423    \definefont[DiceR][Serif*dice:reverse]
424    \definefont[DiceD][Serif*dice:normal,dice:digits]
425    \definefont[DiceT][Serif*dice:normal,dice:three,dice:digits]
426
427    \startTEXpage[offset=3pt]
428        \DiceN
429            \dostepwiserecurse{"2680}{"2685}{1}{\char#1\quad}%
430        \DiceR
431            \dostepwiserecurse{"2680}{"2685}{1}{\char#1\quad}%
432        \DiceD
433            \darkblue 2\quad5\quad3\quad0
434    \stopTEXpage
435
436    \startTEXpage[offset=3pt]
437        \showglyphs \DiceT 1 2 3 4 5 6
438        \showglyphs \DiceT 653 421
439    \stopTEXpage
440
441\stoptext
442