char-brl.lmt /size: 11 Kb    last modification: 2024-01-16 10:22
1if not modules then modules = { } end modules ['char-bri'] = {
2    version   = 1.001,
3    comment   = "companion to char-ini.mkiv",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files"
7}
8
9-- We use a somewhat indirect approach because we generated the database and
10-- have to do that again probably. At some point we can move some to char-def
11-- so the interfaces here are kind of private and can change.
12--
13-- This is just an experiment. The data is taken from Wikipedia and the nemeth
14-- sequences come from a 2021 blog by Murray Sargent (from Microsoft):
15--
16-- https://devblogs.microsoft.com/math-in-office/unicode-math-braille-sequences/
17
18local next = next
19local gsub = string.gsub
20local utfbyte, utfsplit = utf.byte, string.utfvaluetable
21local sortedkeys = table.sortedkeys
22
23local braille      = { }
24characters.braille = braille
25
26local codepoints = {
27    digits = {
28        [48] = "",
29        [49] = "",
30        [50] = "",
31        [51] = "",
32        [52] = "",
33        [53] = "",
34        [54] = "",
35        [55] = "",
36        [56] = "",
37        [57] = "",
38    },
39    letters = {
40        [97] = "",
41        [98] = "",
42        [99] = "",
43       [100] = "",
44       [101] = "",
45       [102] = "",
46       [103] = "",
47       [104] = "",
48       [105] = "",
49       [106] = "",
50       [107] = "",
51       [108] = "",
52       [109] = "",
53       [110] = "",
54       [111] = "",
55       [112] = "",
56       [113] = "",
57       [114] = "",
58       [115] = "",
59       [116] = "",
60       [117] = "",
61       [118] = "",
62       [119] = "",
63       [120] = "",
64       [121] = "",
65       [122] = "",
66    },
67    punctuation = {
68        [33] = "",
69        [34] = "⠸⠡",
70        [40] = "⠐⠣",
71        [41] = "⠐⠜",
72        [44] = "",
73        [45] = "",
74        [46] = "",
75        [47] = "⠸⠌",
76        [58] = "",
77        [59] = "",
78        [63] = "",
79      [8211] = "⠠⠤",
80      [8212] = "⠐⠠⠤",
81      [8216] = "⠄⠦",
82      [8217] = "⠄⠴",
83      [8220] = "⠘⠦",
84      [8221] = "⠘⠴",
85    },
86    ueb = {
87        [33] = "",
88        [34] = "⠠⠶",
89        [35] = "⠸⠹",
90        [36] = "⠈⠎",
91        [37] = "⠨⠴",
92        [38] = "⠈⠯",
93        [39] = "",
94        [40] = "⠐⠣",
95        [41] = "⠐⠜",
96        [42] = "⠐⠔",
97        [43] = "⠐⠖",
98        [44] = "",
99        [45] = "",
100        [46] = "⠼⠲",
101        [47] = "⠸⠌",
102        [58] = "",
103        [59] = "",
104        [60] = "⠈⠣",
105        [61] = "⠐⠶",
106        [62] = "⠈⠜",
107        [63] = "",
108        [64] = "⠈⠁",
109        [91] = "⠨⠣",
110        [92] = "⠸⠡",
111        [93] = "⠨⠜",
112        [94] = "⠈⠢",
113        [95] = "⠨⠤",
114       [123] = "⠸⠣",
115       [124] = "⠸⠳",
116       [125] = "⠸⠜",
117       [126] = "⠈⠔",
118       [162] = "⠈⠉",
119       [163] = "⠈⠇",
120       [167] = "⠘⠎",
121       [169] = "⠘⠉",
122       [172] = "⠈⠹",
123       [174] = "⠘⠗",
124       [176] = "⠘⠚",
125       [177] = "⠸⠖",
126       [182] = "⠘⠏",
127       [215] = "⠐⠦",
128       [247] = "⠐⠌",
129       [913] = "⠠⠨⠁",
130       [914] = "⠠⠨⠃",
131       [915] = "⠠⠨⠛",
132       [916] = "⠠⠨⠙",
133       [917] = "⠠⠨⠑",
134       [918] = "⠠⠨⠵",
135       [919] = "⠠⠨⠱",
136       [920] = "⠠⠨⠹",
137       [921] = "⠠⠨⠊",
138       [922] = "⠠⠨⠅",
139       [923] = "⠠⠨⠇",
140       [924] = "⠠⠨⠍",
141       [925] = "⠠⠨⠝",
142       [926] = "⠠⠨⠭",
143       [927] = "⠠⠨⠕",
144       [928] = "⠠⠨⠏",
145       [929] = "⠠⠨⠗",
146       [931] = "⠠⠨⠎",
147       [932] = "⠠⠨⠞",
148       [933] = "⠠⠨⠥",
149       [934] = "⠠⠨⠋",
150       [935] = "⠠⠨⠯",
151       [936] = "⠠⠨⠽",
152       [937] = "⠠⠨⠺",
153       [945] = "⠨⠁",
154       [946] = "⠨⠃",
155       [947] = "⠨⠛",
156       [948] = "⠨⠙",
157       [949] = "⠨⠑",
158       [950] = "⠨⠵",
159       [951] = "⠨⠱",
160       [952] = "⠨⠹",
161       [953] = "⠨⠊",
162       [954] = "⠨⠅",
163       [955] = "⠨⠇",
164       [956] = "⠨⠍",
165       [957] = "⠨⠝",
166       [958] = "⠨⠭",
167       [959] = "⠨⠕",
168       [960] = "⠨⠏",
169       [961] = "⠨⠗",
170       [962] = "⠨⠎",
171       [963] = "⠨⠎",
172       [964] = "⠨⠞",
173       [965] = "⠨⠥",
174       [966] = "⠨⠋",
175       [967] = "⠨⠯",
176       [968] = "⠨⠽",
177       [969] = "⠨⠺",
178      [8212] = "⠠⠤",
179      [8213] = "⠐⠠⠤",
180      [8216] = "⠠⠦",
181      [8217] = "⠠⠴",
182      [8220] = "⠘⠦",
183      [8221] = "⠘⠴",
184      [8224] = "⠈⠠⠹",
185      [8225] = "⠈⠠⠻",
186      [8226] = "⠸⠲",
187      [8242] = "",
188      [8243] = "⠶⠶",
189      [8592] = "⠳⠪",
190      [8593] = "⠳⠬",
191      [8594] = "⠳⠕",
192      [8595] = "⠳⠩",
193      [8596] = "⠰⠳⠺⠗⠕",
194      [8598] = "⠳⠱",
195      [8599] = "⠳⠎",
196      [8600] = "⠳⠣",
197      [8601] = "⠳⠜",
198      [8656] = "⠰⠳⠶⠶⠪",
199      [8657] = "⠰⠳⠶⠶⠬",
200      [8658] = "⠰⠳⠶⠶⠕",
201      [8659] = "⠰⠳⠶⠶⠩",
202      [8704] = "⠘⠁",
203      [8706] = "⠈⠙",
204      [8707] = "⠘⠢",
205      [8709] = "⠈⠚",
206      [8711] = "⠘⠙",
207      [8712] = "⠘⠑",
208      [8715] = "⠈⠘⠑",
209      [8722] = "⠐⠤",
210      [8723] = "⠸⠤",
211      [8728] = "⠐⠴",
212      [8730] = "⠐⠩",
213      [8733] = "⠸⠐⠶",
214      [8734] = "⠼⠿",
215      [8736] = "⠸⠪",
216      [8737] = "⠨⠸⠪",
217      [8741] = "⠼⠇",
218      [8743] = "⠈⠦",
219      [8744] = "⠈⠖",
220      [8745] = "⠨⠦",
221      [8746] = "⠨⠖",
222      [8747] = "",
223      [8748] = "⠮⠮",
224      [8749] = "⠮⠮⠮",
225      [8750] = "⠈⠮",
226      [8756] = "⠠⠡",
227      [8757] = "⠈⠌",
228      [8758] = "",
229      [8759] = "⠒⠒",
230      [8771] = "⠸⠔",
231      [8773] = "⠐⠸⠔",
232      [8776] = "⠘⠔",
233      [8783] = "⠘⠐⠶",
234      [8785] = "⠨⠐⠶",
235      [8800] = "⠐⠶⠈⠱",
236      [8801] = "⠸⠿",
237      [8804] = "⠸⠈⠣",
238      [8805] = "⠸⠈⠜",
239      [8810] = "⠨⠈⠣",
240      [8811] = "⠨⠈⠜",
241      [8834] = "⠘⠣",
242      [8835] = "⠘⠜",
243      [8838] = "⠸⠘⠣",
244      [8839] = "⠸⠘⠜",
245      [8842] = "⠨⠘⠣",
246      [8843] = "⠨⠘⠜",
247      [8853] = "⠰⠫⠿⠪⠐⠖⠱",
248      [8867] = "⠈⠸⠒",
249      [8869] = "⠼⠤",
250      [8870] = "⠸⠒",
251      [8872] = "⠘⠸⠒",
252      [8882] = "⠈⠸⠣",
253      [8883] = "⠈⠸⠜",
254      [8884] = "⠸⠸⠣",
255      [8885] = "⠸⠸⠜",
256      [8894] = "⠼⠸⠪",
257      [8901] = "⠐⠲",
258      [9675] = "",
259     [10764] = "⠮⠮⠮⠮",
260    },
261    specials = {
262        uppercase = "",
263        space     = "",
264        number    = "",
265        rule      = "",
266    },
267    alphabets = {
268        ["lowercasenormal"]                    = "",
269        ["lowercasegreeknormal"]               = "",
270        ["lowercasegreekitalic"]               = "⠨⠨",
271        ["lowercaseitalic"]                    = "",
272        ["lowercasebold"]                      = "",
273        ["lowercasebolditalic"]                = "⠸⠨",
274        ["lowercasefraktur"]                   = "",
275        ["lowercaseboldfraktur"]               = "⠸⠸",
276        ["lowercasescript"]                    = "",
277        ["lowercaseboldscript"]                = "⠸⠈",
278        ["lowercasesansserifnormal"]           = "⠠⠨",
279        ["lowercasesansserifitalic"]           = "⠠⠨⠨",
280        ["lowercasesansserifbold"]             = "⠠⠨⠸",
281        ["lowercasesansserifbolditalic"]       = "⠠⠨⠸⠨",
282
283        ["uppercase"]                          = "",
284
285     -- ["russian"]                            = "⠈⠈",
286     -- ["hebrew"]                             = "⠠⠠",
287     -- ["altgreek"]                           = "⠨⠈",
288
289     -- ["lowercasedoublestruck"]              = ""
290     -- ["lowercasegreekbold"]                 = ""
291     -- ["lowercasegreekbolditalic"]           = ""
292     -- ["lowercasegreeksansserifbold"]        = ""
293     -- ["lowercasegreeksansserifbolditalic"]  = ""
294     -- ["lowercasemonospace"]                 = ""
295    },
296}
297
298braille.codepoints = codepoints
299
300local textunicodes, mathunicodes, textstrings, mathstrings, textlist, mathlist, specials
301
302local function prepare()
303
304    local charblocks  = characters.blocks
305    local uccodes     = characters.uccodes
306
307    local letters     = codepoints.letters
308    local cspecials   = codepoints.specials
309    local uppercase   = cspecials.uppercase
310    local number      = cspecials.number
311    local space       = cspecials.space
312    local rule        = cspecials.rule
313
314    -- filtered from the mentioned blog webpage:
315
316    local nemeth      = table.load(resolvers.find_file("math-brl.lmt")).nemeth
317    codepoints.nemeth = nemeth
318
319    -- we let the tex math engine do the spacing but it can become an option:
320
321    for k, v in next, nemeth do
322        nemeth[k] = gsub(v,space,"")
323    end
324
325    textstrings  = { }
326    mathstrings  = { }
327    textunicodes = { }
328    mathunicodes = { }
329
330    for k, v in next, codepoints.letters do
331        textstrings[k] = v
332        mathstrings[k] = v
333        local K = uccodes[k]
334        if K then
335            local V = uppercase .. v
336            textstrings[K] = V
337            mathstrings[K] = V
338        end
339    end
340
341    for k, v in next, codepoints.digits do
342        local d = number .. v
343        textstrings[k] = v
344        mathstrings[k] = v
345    end
346
347    for k, v in next, codepoints.punctuation do
348        textstrings[k] = v
349        mathstrings[k] = v
350    end
351    -- overlaps with the above
352
353    for k, v in next, codepoints.ueb do
354        textstrings[k] = v
355        mathstrings[k] = v
356    end
357
358    for k, v in next, codepoints.nemeth do
359        mathstrings[k] = v
360        if not textstrings[k] then
361            textstrings[k] = v
362        end
363    end
364
365    for k, v in next, codepoints.alphabets do
366        local block = charblocks[k]
367        if block then
368            local c = utfbyte('a')
369            for i=block.first,block.last do
370                mathstrings[i] = v..letters[c]
371                if not textstrings[i] then
372                    textstrings[i] = v .. letters[c]
373                end
374                c = c + 1
375            end
376        end
377    end
378
379    for k, v in next, textstrings do
380        textunicodes[k] = utfsplit(v)
381    end
382    for k, v in next, mathstrings do
383        mathunicodes[k] = utfsplit(v)
384    end
385
386    textlist = sortedkeys(textstrings)
387    mathlist = sortedkeys(mathstrings)
388
389    specials = {
390        uppercase = utfbyte(uppercase),
391        number    = utfbyte(number),
392        space     = utfbyte(space),
393        rule      = utfbyte(rule)
394    }
395end
396
397-- maybe an iterator
398
399function braille.textlist   ()  if not textlist     then prepare() end return textlist        end
400function braille.mathlist   ()  if not mathlist     then prepare() end return mathlist        end
401function braille.textunicode(n) if not textunicodes then prepare() end return textunicodes[n] end
402function braille.mathunicode(n) if not mathunicodes then prepare() end return mathunicodes[n] end
403function braille.textstring (n) if not textstrings  then prepare() end return textstrings [n] end
404function braille.mathstring (n) if not mathstrings  then prepare() end return mathstrings [n] end
405function braille.special    (n) if not specials     then prepare() end return specials    [n] end
406