%D \module %D [ file=meta-imp-gamesymbols, %D version=2019.10.10, %D title=\METAPOST\ Graphics, %D subtitle=Game Symbols, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. %D The \METAFUN\ code here is not optimal and efficient but as it serves as an %D example I decided to keep it simple. Also, performance is not really an issue %D here anyway. Inspired by the classic \quote {Concrete Mathematics} by Don Knuth %D we define dice and dominos, which happen to be \UNICODE\ characters now. We %D use this opportunity to demonstrate slightly different approached. %D Each dice gets it's own macro at the \METAPOST\ end. Watch how we use the \type %D {simplefun} instance in combination with a calculation wrapper. This will just %D execute the code and leave no traces in the text flow. The code itself is not %D that spectacular: %D Todo: variant -2/-3 3D dice \startMPcalculation{simplefun} picture DiceDots[] ; pickup pencircle scaled 3/2 ; DiceDots[ 1] := image ( draw(4,4) ; ) ; DiceDots[ 2] := image ( draw(2,6) ; draw(6,2) ; ) ; DiceDots[-2] := image ( draw(6,6) ; draw(2,2) ; ) ; DiceDots[ 3] := image ( draw(2,6) ; draw(4,4) ; draw(6,2) ; ) ; DiceDots[-3] := image ( draw(6,6) ; draw(4,4) ; draw(2,2) ; ) ; DiceDots[ 4] := image ( draw(2,6) ; draw(6,6) ; draw(2,2) ; draw(6,2) ; ) ; DiceDots[ 5] := image ( draw(2,6) ; draw(6,6) ; draw(4,4) ; draw(2,2) ; draw(6,2) ; ) ; DiceDots[ 6] := image ( draw(2,6) ; draw(6,6) ; draw(2,4) ; draw(6,4) ; draw(2,2) ; draw(6,2) ; ) ; def DiceFrame = pickup pencircle scaled 1/2 ; draw unitsquare scaled 8 ; % pickup pencircle scaled 3/2 ; enddef ; vardef DiceOne = DiceFrame ; draw DiceDots[1] ; enddef ; vardef DiceTwo = DiceFrame ; draw DiceDots[if hasoption "mpsfont" "option" "reverse" : - fi 2] ; enddef ; vardef DiceThree = DiceFrame ; draw DiceDots[if hasoption "mpsfont" "option" "reverse" : - fi 3] ; enddef ; vardef DiceFour = DiceFrame ; draw DiceDots[4] ; enddef ; vardef DiceFive = DiceFrame ; draw DiceDots[5] ; enddef ; vardef DiceSix = DiceFrame ; draw DiceDots[6] ; enddef ; vardef DiceBad = DiceFrame ; draw (1,7) -- (7,1) ; draw (1,1) -- (7,7) ; enddef ; lmt_registerglyphs [ name = "dice", units = 12, width = 8, height = 8, depth = 0, usecolor = true, ] ; lmt_registerglyph [ category = "dice", unicode = "0x2680", code = "DiceOne;" ] ; lmt_registerglyph [ category = "dice", unicode = "0x2681", code = "DiceTwo;" ] ; lmt_registerglyph [ category = "dice", unicode = "0x2682", code = "DiceThree;" ] ; lmt_registerglyph [ category = "dice", unicode = "0x2683", code = "DiceFour;" ] ; lmt_registerglyph [ category = "dice", unicode = "0x2684", code = "DiceFive;" ] ; lmt_registerglyph [ category = "dice", unicode = "0x2685", code = "DiceSix;" ] ; lmt_registerglyph [ category = "dice", private = "invaliddice", code = "DiceBad;" ] ; %D The transformations come from DICE3D.MF by Thomas A. Heim (1998) transform t[]; numeric r ; r := sqrt(1/4) ; hide((0,0) transformed t1 = (0,0)) ; hide((1,0) transformed t1 = (r,r)) ; hide((0,1) transformed t1 = (0,1)) ; hide((0,0) transformed t2 = (0,0)) ; hide((1,0) transformed t2 = (1,0)) ; hide((0,1) transformed t2 = (r,r)) ; t3 := t1 shifted (8,0) ; % front to right side t4 := t2 shifted (0,8) ; % front to top vardef Diced(expr a, b, c) = draw image ( pickup pencircle scaled 1/2 ; draw image ( % unitsquare smoothed 1/10 nodraw unitsquare scaled 8 transformed t4 ; nodraw unitsquare scaled 8 transformed t3 ; nodraw unitsquare scaled 8 ; dodraw unitsquare scaled 8 ; ) ; draw DiceDots[a] ; draw DiceDots[b] transformed t3 ; draw DiceDots[c] transformed t4 ; ) ; enddef ; lmt_registerglyph [ category = "dice", unicode = "123", code = "Diced(1,2,3);", width = 12, height = 12 ] ; lmt_registerglyph [ category = "dice", unicode = "135", code = "Diced(1,3,5);", width = 12, height = 12 ] ; lmt_registerglyph [ category = "dice", unicode = "142", code = "Diced(1,4,2);", width = 12, height = 12 ] ; lmt_registerglyph [ category = "dice", unicode = "154", code = "Diced(1,5,4);", width = 12, height = 12 ] ; lmt_registerglyph [ category = "dice", unicode = "214", code = "Diced(2,1,4);", width = 12, height = 12 ] ; lmt_registerglyph [ category = "dice", unicode = "231", code = "Diced(2,3,1);", width = 12, height = 12 ] ; lmt_registerglyph [ category = "dice", unicode = "246", code = "Diced(2,4,6);", width = 12, height = 12 ] ; lmt_registerglyph [ category = "dice", unicode = "263", code = "Diced(2,6,3);", width = 12, height = 12 ] ; lmt_registerglyph [ category = "dice", unicode = "312", code = "Diced(3,1,2);", width = 12, height = 12 ] ; lmt_registerglyph [ category = "dice", unicode = "326", code = "Diced(3,2,6);", width = 12, height = 12 ] ; lmt_registerglyph [ category = "dice", unicode = "351", code = "Diced(3,5,1);", width = 12, height = 12 ] ; lmt_registerglyph [ category = "dice", unicode = "365", code = "Diced(3,6,5);", width = 12, height = 12 ] ; lmt_registerglyph [ category = "dice", unicode = "415", code = "Diced(4,1,5);", width = 12, height = 12 ] ; lmt_registerglyph [ category = "dice", unicode = "421", code = "Diced(4,2,1);", width = 12, height = 12 ] ; lmt_registerglyph [ category = "dice", unicode = "456", code = "Diced(4,5,6);", width = 12, height = 12 ] ; lmt_registerglyph [ category = "dice", unicode = "462", code = "Diced(4,6,2);", width = 12, height = 12 ] ; lmt_registerglyph [ category = "dice", unicode = "513", code = "Diced(5,1,3);", width = 12, height = 12 ] ; lmt_registerglyph [ category = "dice", unicode = "536", code = "Diced(5,3,6);", width = 12, height = 12 ] ; lmt_registerglyph [ category = "dice", unicode = "541", code = "Diced(5,4,1);", width = 12, height = 12 ] ; lmt_registerglyph [ category = "dice", unicode = "564", code = "Diced(5,6,4);", width = 12, height = 12 ] ; lmt_registerglyph [ category = "dice", unicode = "624", code = "Diced(6,2,4);", width = 12, height = 12 ] ; lmt_registerglyph [ category = "dice", unicode = "632", code = "Diced(6,3,2);", width = 12, height = 12 ] ; lmt_registerglyph [ category = "dice", unicode = "645", code = "Diced(6,4,5);", width = 12, height = 12 ] ; lmt_registerglyph [ category = "dice", unicode = "653", code = "Diced(6,5,3);", width = 12, height = 12 ] ; \stopMPcalculation %D At the \TEX\ end we define four features. The reverse is just there for fun. The %D digits features will map digits onto dice. \definefontfeature [dice:normal] [default] [metapost={category=dice}] \definefontfeature [dice:reverse] [default] [metapost={category=dice,option=reverse}] \definefontfeature [dice:digits] [dice:digits=yes] \definefontfeature [dice:three] [dice:three=yes] %D The mapping to dice happens here: \startluacode -- before the digits feature fonts.handlers.otf.addfeature("dice:three", { type = "ligature", order = { "dice:three" }, nocheck = true, data = { [123] = { 0x31, 0x32, 0x33 }, [135] = { 0x31, 0x33, 0x35 }, [142] = { 0x31, 0x34, 0x32 }, [154] = { 0x31, 0x35, 0x34 }, [214] = { 0x32, 0x31, 0x34 }, [231] = { 0x32, 0x33, 0x31 }, [246] = { 0x32, 0x34, 0x36 }, [263] = { 0x32, 0x36, 0x33 }, [312] = { 0x33, 0x31, 0x32 }, [326] = { 0x33, 0x32, 0x36 }, [351] = { 0x33, 0x35, 0x31 }, [365] = { 0x33, 0x36, 0x35 }, [415] = { 0x34, 0x31, 0x35 }, [421] = { 0x34, 0x32, 0x31 }, [456] = { 0x34, 0x35, 0x36 }, [462] = { 0x34, 0x36, 0x32 }, [513] = { 0x35, 0x31, 0x33 }, [536] = { 0x35, 0x33, 0x36 }, [541] = { 0x35, 0x34, 0x31 }, [564] = { 0x35, 0x36, 0x34 }, [624] = { 0x36, 0x32, 0x34 }, [632] = { 0x36, 0x33, 0x32 }, [645] = { 0x36, 0x34, 0x35 }, [653] = { 0x36, 0x35, 0x33 }, } } ) -- local invalid = fonts.helpers.privateslot("invaliddice") fonts.handlers.otf.addfeature("dice:digits", { type = "substitution", order = { "dice:digits" }, nocheck = true, data = { [0x30] = "invaliddice", [0x31] = 0x2680, [0x32] = 0x2681, [0x33] = 0x2682, [0x34] = 0x2683, [0x35] = 0x2684, [0x36] = 0x2685, [0x37] = "invaliddice", [0x38] = "invaliddice", [0x39] = "invaliddice", }, } ) \stopluacode %D An example is given at the the end of this file so we now move forward with %D the dominos. \startMPcalculation{simplefun} %D Because there are so many dominos we predefine the shapes and then register %D the lot in a loop. picture Dominos[] ; Dominos[0] := image() ; Dominos[1] := image(draw(4,4);) ; Dominos[2] := image(draw(2,6);draw(6,2);); Dominos[3] := image(draw(2,6);draw(4,4);draw(6,2);); Dominos[4] := image(draw(2,6);draw(6,6);draw(2,2);draw(6,2);); Dominos[5] := image(draw(2,6);draw(6,6);draw(4,4);draw(2,2);draw(6,2);); Dominos[6] := image(draw(2,6);draw(4,6);draw(6,6);draw(2,2);draw(4,2);draw(6,2);); % Dominos[7] := Dominos[0] ; % Dominos[8] := Dominos[0] ; % Dominos[9] := Dominos[0] ; %D Defining the font properties is straightforward: lmt_registerglyphs [ name = "dominos", units = 12, width = 16, height = 8, depth = 0, usecolor = true, ] ; %D We have horizontal dominos: def DrawDominoH(expr a, b) = draw image ( pickup pencircle scaled 1/2 ; if (getparameterdefault "mpsfont" "color" "") = "black" : fillup unitsquare xyscaled (16,8) ; draw (8,.5) -- (8,7.5) withcolor white ; pickup pencircle scaled 3/2 ; draw Dominos[a] withpen currentpen withcolor white ; draw Dominos[b] shifted (8,0) withpen currentpen withcolor white ; else : draw unitsquare xyscaled (16,8) ; draw (8,0) -- (8,8) ; pickup pencircle scaled 3/2 ; draw Dominos[a] withpen currentpen ; draw Dominos[b] shifted (8,0) withpen currentpen ; fi ; ) ; enddef ; %D and vertical ones. We could use the above macro and rotate and shift and reflect %D but why bother with it: def DrawDominoV(expr a, b) = % is H rotated and shifted draw image ( pickup pencircle scaled 1/2 ; if (getparameterdefault "mpsfont" "color" "") = "black" : fillup unitsquare xyscaled (8,16) ; draw (.5,8) -- (7.5,8) withcolor white ; pickup pencircle scaled 3/2 ; draw Dominos[a] rotatedaround(center Dominos[a],90) withpen currentpen withcolor white ; draw Dominos[b] rotatedaround(center Dominos[b],90) shifted (0,8) withpen currentpen withcolor white ; else : draw unitsquare xyscaled (8,16) ; draw (0,8) -- (8,8) ; pickup pencircle scaled 3/2 ; draw Dominos[a] rotatedaround(center Dominos[a],90) withpen currentpen ; draw Dominos[b] rotatedaround(center Dominos[b],90) shifted (0,8) withpen currentpen ; fi ; ) ; enddef ; %D We have two simple loops that define the horizontal range: save unicode ; numeric unicode ; unicode := 127025 ; % 1F031 for i=0 upto 6 : for j=0 upto 6 : lmt_registerglyph [ category = "dominos", unicode = unicode, code = "DrawDominoH(" & decimal i & "," & decimal j & ");", width = 16, height = 8, ] ; unicode := unicode + 1 ; endfor ; endfor ; %D and the vertical range: save unicode ; numeric unicode ; unicode := 127075 ; for i=0 upto 6 : for j=0 upto 6 : lmt_registerglyph [ category = "dominos", unicode = unicode, code = "DrawDominoV(" & decimal i & "," & decimal j & ");", width = 8, height = 16, ] ; unicode := unicode + 1 ; endfor ; endfor ; %D Now we're done at the \METAFUN\ end. \stopMPcalculation %D We predefine two features: \definefontfeature [dominos:white] [default] [metapost={category=dominos}] \definefontfeature [dominos:black] [default] [metapost={category=dominos,color=black}] \definefontfeature [dominos:digits] [dominos:digits=yes] %D This last feature is yet to be defined. We could deal with the invalid %D dominos with some substitution trickery but let's keep it simple. \startluacode local ligatures = { } local unicode = 127025 for i=0x30,0x36 do for j=0x30,0x36 do ligatures[unicode] = { i, j } unicode = unicode + 1 ; end end fonts.handlers.otf.addfeature("dominos:digits", { type = "ligature", order = { "dominos:digits" }, nocheck = true, data = ligatures, } ) \stopluacode \continueifinputfile{meta-imp-gamesymbols.mkxl} \starttext \definefont[DominoW][Serif*dominos:white] \definefont[DominoB][Serif*dominos:black] \definefont[DominoD][Serif*dominos:white,dominos:digits] \startTEXpage[offset=3pt] \DominoW \char"1F043\quad 🀱\quad \char"1F052\quad 🀲\quad \char"1F038\quad 🀳\quad \darkgreen\char"1F049\quad \char"1F07B\quad \DominoB \char"1F087\quad \char"1F088\quad \char"1F089\quad \DominoD \darkred 12\quad56\quad64% \stopTEXpage \definefont[DiceN][Serif*dice:normal] \definefont[DiceR][Serif*dice:reverse] \definefont[DiceD][Serif*dice:normal,dice:digits] \definefont[DiceT][Serif*dice:normal,dice:three,dice:digits] \startTEXpage[offset=3pt] \DiceN \dostepwiserecurse{"2680}{"2685}{1}{\char#1\quad}% \DiceR \dostepwiserecurse{"2680}{"2685}{1}{\char#1\quad}% \DiceD \darkblue 2\quad5\quad3\quad0 \stopTEXpage \startTEXpage[offset=3pt] \showglyphs \DiceT 1 2 3 4 5 6 \showglyphs \DiceT 653 421 \stopTEXpage \stoptext