math-map.lmt /size: 31 Kb    last modification: 2021-10-28 13:51
1if not modules then modules = { } end modules ['math-map'] = {
2    version   = 1.001,
3    optimize  = true,
4    comment   = "companion to math-ini.mkiv",
5    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
6    copyright = "PRAGMA ADE / ConTeXt Development Team",
7    license   = "see context related readme files"
8}
9
10-- todo: make sparse .. if self
11
12--[[ldx--
13<p>Remapping mathematics alphabets.</p>
14--ldx]]--
15
16-- oldstyle: not really mathematics but happened to be part of
17-- the mathematics fonts in cmr
18--
19-- persian: we will also provide mappers for other
20-- scripts
21
22-- todo: alphabets namespace
23-- maybe: script/scriptscript dynamic,
24
25-- superscripped primes get unscripted !
26
27-- to be looked into once the fonts are ready (will become font
28-- goodie):
29--
30-- (U+2202,U+1D715) : upright
31-- (U+2202,U+1D715) : italic
32-- (U+2202,U+1D715) : upright
33--
34-- plus add them to the regular vectors below so that they honor \it etc
35
36local type, next = type, next
37local merged, sortedhash = table.merged, table.sortedhash
38
39local allocate            = utilities.storage.allocate
40
41local otffeatures         = fonts.constructors.features.otf
42local registerotffeature  = otffeatures.register
43
44local setmetatableindex   = table.setmetatableindex
45
46local texgetattribute     = tex.getattribute
47local texsetattribute     = tex.setattribute
48
49local texgetmode          = tex.getmode
50local mathmode_code       = tex.modelevels.math
51
52local trace_greek         = false  trackers.register("math.greek",  function(v) trace_greek = v end)
53local report_remapping    = logs.reporter("mathematics","remapping")
54
55mathematics               = mathematics or { }
56local mathematics         = mathematics
57
58local implement           = interfaces.implement
59
60-- Unfortunately some alphabets have gaps (thereby troubling all applications that
61-- need to deal with math). Somewhat strange considering all those weird symbols that
62-- were added afterwards. The following trickery (and data) is only to be used for
63-- diagnostics and quick and dirty alphabet tracing (s-mat-10.mkiv) as we deal with
64-- it otherwise.
65
66-- todo: allocate
67
68mathematics.styles       = allocate { "regular", "sansserif", "monospaced", "fraktur", "script", "blackboard" }
69mathematics.alternatives = allocate { "normal", "bold", "italic", "bolditalic" }
70mathematics.sets         = allocate { "ucletters", "lcletters", "digits", "ucgreek", "lcgreek", "symbols" }
71
72mathematics.charactersets = allocate {
73    ucletters = {
74        0x00041, 0x00042, 0x00043, 0x00044, 0x00045,
75        0x00046, 0x00047, 0x00048, 0x00049, 0x0004A,
76        0x0004B, 0x0004C, 0x0004D, 0x0004E, 0x0004F,
77        0x00050, 0x00051, 0x00052, 0x00053, 0x00054,
78        0x00055, 0x00056, 0x00057, 0x00058, 0x00059,
79        0x0005A,
80    },
81    lcletters = {
82        0x00061, 0x00062, 0x00063, 0x00064, 0x00065,
83        0x00066, 0x00067, 0x00068, 0x00069, 0x0006A,
84        0x0006B, 0x0006C, 0x0006D, 0x0006E, 0x0006F,
85        0x00070, 0x00071, 0x00072, 0x00073, 0x00074,
86        0x00075, 0x00076, 0x00077, 0x00078, 0x00079,
87        0x0007A,
88    },
89    digits = {
90        0x00030, 0x00031, 0x00032, 0x00033, 0x00034,
91        0x00035, 0x00036, 0x00037, 0x00038, 0x00039,
92    },
93    ucgreek = {
94        0x0391, 0x0392, 0x0393, 0x0394, 0x0395,
95        0x0396, 0x0397, 0x0398, 0x0399, 0x039A,
96        0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
97        0x03A0, 0x03A1, 0x03A3, 0x03A4, 0x03A5,
98        0x03A6, 0x03A7, 0x03A8, 0x03A9
99    },
100    lcgreek = {
101        0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5,
102        0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA,
103        0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
104        0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4,
105        0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9,
106        0x03D1, 0x03D5, 0x03D6, 0x03F0, 0x03F1,
107        0x03F4, 0x03F5
108    },
109}
110
111mathematics.gaps = allocate {
112    [0x1D455] = 0x0210E, -- ℎ h
113    [0x1D49D] = 0x0212C, -- ℬ script B
114    [0x1D4A0] = 0x02130, -- ℰ script E
115    [0x1D4A1] = 0x02131, -- ℱ script F
116    [0x1D4A3] = 0x0210B, -- ℋ script H
117    [0x1D4A4] = 0x02110, -- ℐ script I
118    [0x1D4A7] = 0x02112, -- ℒ script L
119    [0x1D4A8] = 0x02133, -- ℳ script M
120    [0x1D4AD] = 0x0211B, -- ℛ script R
121    [0x1D4BA] = 0x0212F, -- ℯ script e
122    [0x1D4BC] = 0x0210A, -- ℊ script g
123 -- [0x1D4C1] = 0x02113, -- exception: liter
124    [0x1D4C4] = 0x02134, -- ℴ script o
125    [0x1D506] = 0x0212D, -- ℭ fraktur C
126    [0x1D50B] = 0x0210C, -- ℌ fraktur H
127    [0x1D50C] = 0x02111, -- ℑ fraktur I
128    [0x1D515] = 0x0211C, -- ℜ fraktur R
129    [0x1D51D] = 0x02128, -- ℨ fraktur Z
130    [0x1D53A] = 0x02102, -- ℂ bb C
131    [0x1D53F] = 0x0210D, -- ℍ bb H
132    [0x1D545] = 0x02115, -- ℕ bb N
133    [0x1D547] = 0x02119, -- ℙ bb P
134    [0x1D548] = 0x0211A, -- ℚ bb Q
135    [0x1D549] = 0x0211D, -- ℝ bb R
136    [0x1D551] = 0x02124, -- ℤ bb Z
137}
138
139local function fillinmathgaps(tfmdata,key,value)
140    local mathgaps     = mathematics.gaps
141    local characters   = tfmdata.characters
142    local descriptions = tfmdata.descriptions
143    for gap, original in next, mathgaps do
144        if characters[original] and not characters[gap] then
145            characters  [gap] = characters  [original]
146            descriptions[gap] = descriptions[original]
147        end
148    end
149end
150
151registerotffeature {
152    name         = "mathgaps",
153    description  = "plug gaps in math alphabets",
154    comment      = "regular document sources should not depend on this",
155    manipulators = {
156        base = fillinmathgaps,
157        node = fillinmathgaps,
158    }
159}
160
161-- we could use one level less and have tf etc be tables directly but the
162-- following approach permits easier remapping of a-a, A-Z and 0-9 to
163-- fallbacks; symbols is currently mostly greek
164
165local function todigit (n) local t = { } for i=0, 9 do t[0x00030+i] = n+i end return t end
166local function toupper (n) local t = { } for i=0,25 do t[0x00041+i] = n+i end return t end
167local function tolower (n) local t = { } for i=0,25 do t[0x00061+i] = n+i end return t end
168local function tovector(t)                                                    return t end
169
170-- how about 0x2A (ast)    cq. 0x2217
171--           0x2D (hyphen) cq. 0x2212
172--           0x3A (colon)  cq. 0x2236
173
174local regular_tf = {
175    digits    = todigit(0x00030),
176    ucletters = toupper(0x00041),
177    lcletters = tolower(0x00061),
178    ucgreek   = {
179        [0x0391]=0x0391, [0x0392]=0x0392, [0x0393]=0x0393, [0x0394]=0x0394, [0x0395]=0x0395,
180        [0x0396]=0x0396, [0x0397]=0x0397, [0x0398]=0x0398, [0x0399]=0x0399, [0x039A]=0x039A,
181        [0x039B]=0x039B, [0x039C]=0x039C, [0x039D]=0x039D, [0x039E]=0x039E, [0x039F]=0x039F,
182        [0x03A0]=0x03A0, [0x03A1]=0x03A1, [0x03A3]=0x03A3, [0x03A4]=0x03A4, [0x03A5]=0x03A5,
183        [0x03A6]=0x03A6, [0x03A7]=0x03A7, [0x03A8]=0x03A8, [0x03A9]=0x03A9,
184        },
185    lcgreek   = {
186        [0x03B1]=0x03B1, [0x03B2]=0x03B2, [0x03B3]=0x03B3, [0x03B4]=0x03B4, [0x03B5]=0x03B5,
187        [0x03B6]=0x03B6, [0x03B7]=0x03B7, [0x03B8]=0x03B8, [0x03B9]=0x03B9, [0x03BA]=0x03BA,
188        [0x03BB]=0x03BB, [0x03BC]=0x03BC, [0x03BD]=0x03BD, [0x03BE]=0x03BE, [0x03BF]=0x03BF,
189        [0x03C0]=0x03C0, [0x03C1]=0x03C1, [0x03C2]=0x03C2, [0x03C3]=0x03C3, [0x03C4]=0x03C4,
190        [0x03C5]=0x03C5, [0x03C6]=0x03C6, [0x03C7]=0x03C7, [0x03C8]=0x03C8, [0x03C9]=0x03C9,
191        [0x03D1]=0x03D1, [0x03D5]=0x03D5, [0x03D6]=0x03D6, [0x03F0]=0x03F0, [0x03F1]=0x03F1,
192        [0x03F4]=0x03F4, [0x03F5]=0x03F5,
193    },
194    symbols   = {
195        [0x2202]=0x2202, [0x2207]=0x2207,
196        [0x0027]=0x2032, -- prime
197    },
198}
199
200local regular_it = {
201    digits    = tovector(regular_tf.digits),
202    ucletters = toupper(0x1D434),
203    lcletters = { -- H
204        [0x00061]=0x1D44E, [0x00062]=0x1D44F, [0x00063]=0x1D450, [0x00064]=0x1D451, [0x00065]=0x1D452,
205        [0x00066]=0x1D453, [0x00067]=0x1D454, [0x00068]=0x0210E, [0x00069]=0x1D456, [0x0006A]=0x1D457,
206        [0x0006B]=0x1D458, [0x0006C]=0x1D459, [0x0006D]=0x1D45A, [0x0006E]=0x1D45B, [0x0006F]=0x1D45C,
207        [0x00070]=0x1D45D, [0x00071]=0x1D45E, [0x00072]=0x1D45F, [0x00073]=0x1D460, [0x00074]=0x1D461,
208        [0x00075]=0x1D462, [0x00076]=0x1D463, [0x00077]=0x1D464, [0x00078]=0x1D465, [0x00079]=0x1D466,
209        [0x0007A]=0x1D467,
210        -- arabic
211        [0x00627] = 0x1EE00, [0x00628] = 0x1EE21, [0x0062A] = 0x1EE15, [0x0062B] = 0x1EE16,
212        [0x0062C] = 0x1EE22, [0x0062D] = 0x1EE07, [0x0062E] = 0x1EE17, [0x0062F] = 0x1EE03,
213        [0x00630] = 0x1EE18, [0x00631] = 0x1EE13, [0x00632] = 0x1EE06, [0x00633] = 0x1EE0E,
214        [0x00634] = 0x1EE14, [0x00635] = 0x1EE11, [0x00636] = 0x1EE19, [0x00637] = 0x1EE08,
215        [0x00638] = 0x1EE1A, [0x00639] = 0x1EE0F, [0x0063A] = 0x1EE1B, [0x00641] = 0x1EE10,
216        [0x00642] = 0x1EE12, [0x00643] = 0x1EE0A, [0x00644] = 0x1EE0B, [0x00645] = 0x1EE0C,
217        [0x00646] = 0x1EE0D, [0x00647] = 0x1EE24, [0x00648] = 0x1EE05, [0x0064A] = 0x1EE09,
218        [0x0066E] = 0x1EE1C, [0x0066F] = 0x1EE1F, [0x006A1] = 0x1EE1E, [0x006BA] = 0x1EE1D,
219    },
220    ucgreek   = {
221        [0x0391]=0x1D6E2, [0x0392]=0x1D6E3, [0x0393]=0x1D6E4, [0x0394]=0x1D6E5, [0x0395]=0x1D6E6,
222        [0x0396]=0x1D6E7, [0x0397]=0x1D6E8, [0x0398]=0x1D6E9, [0x0399]=0x1D6EA, [0x039A]=0x1D6EB,
223        [0x039B]=0x1D6EC, [0x039C]=0x1D6ED, [0x039D]=0x1D6EE, [0x039E]=0x1D6EF, [0x039F]=0x1D6F0,
224        [0x03A0]=0x1D6F1, [0x03A1]=0x1D6F2, [0x03A3]=0x1D6F4, [0x03A4]=0x1D6F5, [0x03A5]=0x1D6F6,
225        [0x03A6]=0x1D6F7, [0x03A7]=0x1D6F8, [0x03A8]=0x1D6F9, [0x03A9]=0x1D6FA,
226        },
227    lcgreek   = {
228        [0x03B1]=0x1D6FC, [0x03B2]=0x1D6FD, [0x03B3]=0x1D6FE, [0x03B4]=0x1D6FF, [0x03B5]=0x1D700,
229        [0x03B6]=0x1D701, [0x03B7]=0x1D702, [0x03B8]=0x1D703, [0x03B9]=0x1D704, [0x03BA]=0x1D705,
230        [0x03BB]=0x1D706, [0x03BC]=0x1D707, [0x03BD]=0x1D708, [0x03BE]=0x1D709, [0x03BF]=0x1D70A,
231        [0x03C0]=0x1D70B, [0x03C1]=0x1D70C, [0x03C2]=0x1D70D, [0x03C3]=0x1D70E, [0x03C4]=0x1D70F,
232        [0x03C5]=0x1D710, [0x03C6]=0x1D711, [0x03C7]=0x1D712, [0x03C8]=0x1D713, [0x03C9]=0x1D714,
233        [0x03D1]=0x1D717, [0x03D5]=0x1D719, [0x03D6]=0x1D71B, [0x03F0]=0x1D718, [0x03F1]=0x1D71A,
234        [0x03F4]=0x1D6F3, [0x03F5]=0x1D716,
235    },
236    symbols   = {
237        [0x2202]=0x1D715, [0x2207]=0x1D6FB,
238        [0x0027]=0x2032, -- prime
239    },
240}
241
242local regular_bf= {
243    digits    = todigit(0x1D7CE),
244    ucletters = toupper(0x1D400),
245    lcletters = tolower(0x1D41A),
246    ucgreek   = {
247        [0x0391]=0x1D6A8, [0x0392]=0x1D6A9, [0x0393]=0x1D6AA, [0x0394]=0x1D6AB, [0x0395]=0x1D6AC,
248        [0x0396]=0x1D6AD, [0x0397]=0x1D6AE, [0x0398]=0x1D6AF, [0x0399]=0x1D6B0, [0x039A]=0x1D6B1,
249        [0x039B]=0x1D6B2, [0x039C]=0x1D6B3, [0x039D]=0x1D6B4, [0x039E]=0x1D6B5, [0x039F]=0x1D6B6,
250        [0x03A0]=0x1D6B7, [0x03A1]=0x1D6B8, [0x03A3]=0x1D6BA, [0x03A4]=0x1D6BB, [0x03A5]=0x1D6BC,
251        [0x03A6]=0x1D6BD, [0x03A7]=0x1D6BE, [0x03A8]=0x1D6BF, [0x03A9]=0x1D6C0,
252        },
253    lcgreek   = {
254        [0x03B1]=0x1D6C2, [0x03B2]=0x1D6C3, [0x03B3]=0x1D6C4, [0x03B4]=0x1D6C5, [0x03B5]=0x1D6C6,
255        [0x03B6]=0x1D6C7, [0x03B7]=0x1D6C8, [0x03B8]=0x1D6C9, [0x03B9]=0x1D6CA, [0x03BA]=0x1D6CB,
256        [0x03BB]=0x1D6CC, [0x03BC]=0x1D6CD, [0x03BD]=0x1D6CE, [0x03BE]=0x1D6CF, [0x03BF]=0x1D6D0,
257        [0x03C0]=0x1D6D1, [0x03C1]=0x1D6D2, [0x03C2]=0x1D6D3, [0x03C3]=0x1D6D4, [0x03C4]=0x1D6D5,
258        [0x03C5]=0x1D6D6, [0x03C6]=0x1D6D7, [0x03C7]=0x1D6D8, [0x03C8]=0x1D6D9, [0x03C9]=0x1D6DA,
259        [0x03D1]=0x1D6DD, [0x03D5]=0x1D6DF, [0x03D6]=0x1D6E1, [0x03F0]=0x1D6DE, [0x03F1]=0x1D6E0,
260        [0x03F4]=0x1D6B9, [0x03F5]=0x1D6DC,
261    },
262    symbols   = {
263        [0x2202]=0x1D6DB, [0x2207]=0x1D6C1,
264        [0x0027]=0x2032, -- prime
265    },
266}
267
268local regular_bi = {
269    digits    = tovector(regular_bf.digits),
270    ucletters = toupper(0x1D468),
271    lcletters = tolower(0x1D482),
272    ucgreek   = {
273        [0x0391]=0x1D71C, [0x0392]=0x1D71D, [0x0393]=0x1D71E, [0x0394]=0x1D71F, [0x0395]=0x1D720,
274        [0x0396]=0x1D721, [0x0397]=0x1D722, [0x0398]=0x1D723, [0x0399]=0x1D724, [0x039A]=0x1D725,
275        [0x039B]=0x1D726, [0x039C]=0x1D727, [0x039D]=0x1D728, [0x039E]=0x1D729, [0x039F]=0x1D72A,
276        [0x03A0]=0x1D72B, [0x03A1]=0x1D72C, [0x03A3]=0x1D72E, [0x03A4]=0x1D72F, [0x03A5]=0x1D730,
277        [0x03A6]=0x1D731, [0x03A7]=0x1D732, [0x03A8]=0x1D733, [0x03A9]=0x1D734,
278        },
279    lcgreek   = {
280        [0x03B1]=0x1D736, [0x03B2]=0x1D737, [0x03B3]=0x1D738, [0x03B4]=0x1D739, [0x03B5]=0x1D73A,
281        [0x03B6]=0x1D73B, [0x03B7]=0x1D73C, [0x03B8]=0x1D73D, [0x03B9]=0x1D73E, [0x03BA]=0x1D73F,
282        [0x03BB]=0x1D740, [0x03BC]=0x1D741, [0x03BD]=0x1D742, [0x03BE]=0x1D743, [0x03BF]=0x1D744,
283        [0x03C0]=0x1D745, [0x03C1]=0x1D746, [0x03C2]=0x1D747, [0x03C3]=0x1D748, [0x03C4]=0x1D749,
284        [0x03C5]=0x1D74A, [0x03C6]=0x1D74B, [0x03C7]=0x1D74C, [0x03C8]=0x1D74D, [0x03C9]=0x1D74E,
285        [0x03D1]=0x1D751, [0x03D5]=0x1D753, [0x03D6]=0x1D755, [0x03F0]=0x1D752, [0x03F1]=0x1D754,
286        [0x03F4]=0x1D72D, [0x03F5]=0x1D750,
287    },
288    symbols   = {
289        [0x2202]=0x1D74F, [0x2207]=0x1D735,
290        [0x0027]=0x2032, -- prime
291    },
292}
293
294local regular = {
295    tf = regular_tf,
296    it = regular_it,
297    bf = regular_bf,
298    bi = regular_bi,
299}
300
301local sansserif_tf = {
302    digits    = todigit(0x1D7E2),
303    ucletters = toupper(0x1D5A0),
304    lcletters = tolower(0x1D5BA),
305    lcgreek   = tovector(regular_tf.lcgreek),
306    ucgreek   = tovector(regular_tf.ucgreek),
307    symbols   = tovector(regular_tf.symbols),
308}
309
310local sansserif_it = {
311    digits    = tovector(regular_tf.digits),
312    ucletters = toupper(0x1D608),
313    lcletters = tolower(0x1D622),
314    lcgreek   = tovector(regular_tf.lcgreek),
315    ucgreek   = tovector(regular_tf.ucgreek),
316    symbols   = tovector(regular_tf.symbols),
317}
318
319local sansserif_bf = {
320    digits    = todigit(0x1D7EC),
321    ucletters = toupper(0x1D5D4),
322    lcletters = tolower(0x1D5EE),
323    ucgreek   = {
324        [0x0391]=0x1D756, [0x0392]=0x1D757, [0x0393]=0x1D758, [0x0394]=0x1D759, [0x0395]=0x1D75A,
325        [0x0396]=0x1D75B, [0x0397]=0x1D75C, [0x0398]=0x1D75D, [0x0399]=0x1D75E, [0x039A]=0x1D75F,
326        [0x039B]=0x1D760, [0x039C]=0x1D761, [0x039D]=0x1D762, [0x039E]=0x1D763, [0x039F]=0x1D764,
327        [0x03A0]=0x1D765, [0x03A1]=0x1D766, [0x03A3]=0x1D768, [0x03A4]=0x1D769, [0x03A5]=0x1D76A,
328        [0x03A6]=0x1D76B, [0x03A7]=0x1D76C, [0x03A8]=0x1D76D, [0x03A9]=0x1D76E,
329        },
330    lcgreek   = {
331        [0x03B1]=0x1D770, [0x03B2]=0x1D771, [0x03B3]=0x1D772, [0x03B4]=0x1D773, [0x03B5]=0x1D774,
332        [0x03B6]=0x1D775, [0x03B7]=0x1D776, [0x03B8]=0x1D777, [0x03B9]=0x1D778, [0x03BA]=0x1D779,
333        [0x03BB]=0x1D77A, [0x03BC]=0x1D77B, [0x03BD]=0x1D77C, [0x03BE]=0x1D77D, [0x03BF]=0x1D77E,
334        [0x03C0]=0x1D77F, [0x03C1]=0x1D780, [0x03C2]=0x1D781, [0x03C3]=0x1D782, [0x03C4]=0x1D783,
335        [0x03C5]=0x1D784, [0x03C6]=0x1D785, [0x03C7]=0x1D786, [0x03C8]=0x1D787, [0x03C9]=0x1D788,
336        [0x03D1]=0x1D78B, [0x03D5]=0x1D78D, [0x03D6]=0x1D78F, [0x03F0]=0x1D78C, [0x03F1]=0x1D78E,
337        [0x03F4]=0x1D767, [0x03F5]=0x1D78A,
338    },
339    symbols   = {
340        [0x2202]=0x1D789, [0x2207]=0x1D76F,
341        [0x0027]=0x2032, -- prime
342    },
343}
344
345local sansserif_bi = {
346    digits    = tovector(sansserif_bf.digits),
347    ucletters = toupper(0x1D63C),
348    lcletters = tolower(0x1D656),
349    ucgreek   = {
350        [0x0391]=0x1D790, [0x0392]=0x1D791, [0x0393]=0x1D792, [0x0394]=0x1D793, [0x0395]=0x1D794,
351        [0x0396]=0x1D795, [0x0397]=0x1D796, [0x0398]=0x1D797, [0x0399]=0x1D798, [0x039A]=0x1D799,
352        [0x039B]=0x1D79A, [0x039C]=0x1D79B, [0x039D]=0x1D79C, [0x039E]=0x1D79D, [0x039F]=0x1D79E,
353        [0x03A0]=0x1D79F, [0x03A1]=0x1D7A0, [0x03A3]=0x1D7A2, [0x03A4]=0x1D7A3, [0x03A5]=0x1D7A4,
354        [0x03A6]=0x1D7A5, [0x03A7]=0x1D7A6, [0x03A8]=0x1D7A7, [0x03A9]=0x1D7A8,
355        },
356    lcgreek   = {
357        [0x03B1]=0x1D7AA, [0x03B2]=0x1D7AB, [0x03B3]=0x1D7AC, [0x03B4]=0x1D7AD, [0x03B5]=0x1D7AE,
358        [0x03B6]=0x1D7AF, [0x03B7]=0x1D7B0, [0x03B8]=0x1D7B1, [0x03B9]=0x1D7B2, [0x03BA]=0x1D7B3,
359        [0x03BB]=0x1D7B4, [0x03BC]=0x1D7B5, [0x03BD]=0x1D7B6, [0x03BE]=0x1D7B7, [0x03BF]=0x1D7B8,
360        [0x03C0]=0x1D7B9, [0x03C1]=0x1D7BA, [0x03C2]=0x1D7BB, [0x03C3]=0x1D7BC, [0x03C4]=0x1D7BD,
361        [0x03C5]=0x1D7BE, [0x03C6]=0x1D7BF, [0x03C7]=0x1D7C0, [0x03C8]=0x1D7C1, [0x03C9]=0x1D7C2,
362        [0x03D1]=0x1D7C5, [0x03D5]=0x1D7C7, [0x03D6]=0x1D7C9, [0x03F0]=0x1D7C6, [0x03F1]=0x1D7C8,
363        [0x03F4]=0x1D7A1, [0x03F5]=0x1D7C4,
364    },
365    symbols   = {
366        [0x2202]=0x1D7C3, [0x2207]=0x1D7A9,
367        [0x0027]=0x2032, -- prime
368    },
369}
370
371local sansserif = {
372    tf = sansserif_tf,
373    it = sansserif_it,
374    bf = sansserif_bf,
375    bi = sansserif_bi,
376}
377
378local monospaced_tf = {
379    digits    = todigit(0x1D7F6),
380    ucletters = toupper(0x1D670),
381    lcletters = tolower(0x1D68A),
382    lcgreek   = tovector(sansserif_tf.lcgreek),
383    ucgreek   = tovector(sansserif_tf.ucgreek),
384    symbols   = tovector(sansserif_tf.symbols),
385}
386
387local monospaced_it = tovector(sansserif_it)
388local monospaced_bf = tovector(sansserif_bf)
389local monospaced_bi = tovector(sansserif_bi)
390
391local monospaced = {
392    tf = monospaced_tf,
393    it = monospaced_tf,
394    bf = monospaced_tf,
395    bi = monospaced_bf,
396}
397
398local blackboard_tf = {
399    digits    = todigit(0x1D7D8),
400    ucletters = { -- C H N P Q R Z
401        [0x00041]=0x1D538, [0x00042]=0x1D539, [0x00043]=0x02102, [0x00044]=0x1D53B, [0x00045]=0x1D53C,
402        [0x00046]=0x1D53D, [0x00047]=0x1D53E, [0x00048]=0x0210D, [0x00049]=0x1D540, [0x0004A]=0x1D541,
403        [0x0004B]=0x1D542, [0x0004C]=0x1D543, [0x0004D]=0x1D544, [0x0004E]=0x02115, [0x0004F]=0x1D546,
404        [0x00050]=0x02119, [0x00051]=0x0211A, [0x00052]=0x0211D, [0x00053]=0x1D54A, [0x00054]=0x1D54B,
405        [0x00055]=0x1D54C, [0x00056]=0x1D54D, [0x00057]=0x1D54E, [0x00058]=0x1D54F, [0x00059]=0x1D550,
406        [0x0005A]=0x02124,
407    },
408    lcletters = {
409        -- tolower(0x1D552) :
410        [0x00061] = 0x1D552, [0x00062] = 0x1D553, [0x00063] = 0x1D554, [0x00064] = 0x1D555,
411        [0x00065] = 0x1D556, [0x00066] = 0x1D557, [0x00067] = 0x1D558, [0x00068] = 0x1D559,
412        [0x00069] = 0x1D55A, [0x0006A] = 0x1D55B, [0x0006B] = 0x1D55C, [0x0006C] = 0x1D55D,
413        [0x0006D] = 0x1D55E, [0x0006E] = 0x1D55F, [0x0006F] = 0x1D560, [0x00070] = 0x1D561,
414        [0x00071] = 0x1D562, [0x00072] = 0x1D563, [0x00073] = 0x1D564, [0x00074] = 0x1D565,
415        [0x00075] = 0x1D566, [0x00076] = 0x1D567, [0x00077] = 0x1D568, [0x00078] = 0x1D569,
416        [0x00079] = 0x1D56A, [0x0007A] = 0x1D56B,
417        -- arabic
418        [0x00628] = 0x1EEA1, [0x0062A] = 0x1EEB5, [0x0062B] = 0x1EEB6, [0x0062C] = 0x1EEA2,
419        [0x0062D] = 0x1EEA7, [0x0062E] = 0x1EEB7, [0x0062F] = 0x1EEA3, [0x00630] = 0x1EEB8,
420        [0x00631] = 0x1EEB3, [0x00632] = 0x1EEA6, [0x00633] = 0x1EEAE, [0x00634] = 0x1EEB4,
421        [0x00635] = 0x1EEB1, [0x00636] = 0x1EEB9, [0x00637] = 0x1EEA8, [0x00638] = 0x1EEBA,
422        [0x00639] = 0x1EEAF, [0x0063A] = 0x1EEBB, [0x00641] = 0x1EEB0, [0x00642] = 0x1EEB2,
423        [0x00644] = 0x1EEAB, [0x00645] = 0x1EEAC, [0x00646] = 0x1EEAD, [0x00648] = 0x1EEA5,
424        [0x0064A] = 0x1EEA9,
425    },
426    lcgreek   = { -- gamma pi
427        [0x03B3]=0x0213C, [0x03C0]=0x0213D,
428    },
429    ucgreek   = { -- Gamma pi
430        [0x0393]=0x0213E, [0x03A0]=0x0213F,
431    },
432    symbols   = { -- sum
433        [0x2211]=0x02140,
434        [0x0027]=0x2032, -- prime
435    },
436}
437
438blackboard_tf.lcgreek = merged(regular_tf.lcgreek, blackboard_tf.lcgreek)
439blackboard_tf.ucgreek = merged(regular_tf.ucgreek, blackboard_tf.ucgreek)
440blackboard_tf.symbols = merged(regular_tf.symbols, blackboard_tf.symbols)
441
442local blackboard = {
443    tf = blackboard_tf,
444    it = blackboard_tf,
445    bf = blackboard_tf,
446    bi = blackboard_tf,
447}
448
449local fraktur_tf= {
450    digits    = tovector(regular_tf.digits),
451    ucletters = { -- C H I R Z
452        [0x00041]=0x1D504, [0x00042]=0x1D505, [0x00043]=0x0212D, [0x00044]=0x1D507, [0x00045]=0x1D508,
453        [0x00046]=0x1D509, [0x00047]=0x1D50A, [0x00048]=0x0210C, [0x00049]=0x02111, [0x0004A]=0x1D50D,
454        [0x0004B]=0x1D50E, [0x0004C]=0x1D50F, [0x0004D]=0x1D510, [0x0004E]=0x1D511, [0x0004F]=0x1D512,
455        [0x00050]=0x1D513, [0x00051]=0x1D514, [0x00052]=0x0211C, [0x00053]=0x1D516, [0x00054]=0x1D517,
456        [0x00055]=0x1D518, [0x00056]=0x1D519, [0x00057]=0x1D51A, [0x00058]=0x1D51B, [0x00059]=0x1D51C,
457        [0x0005A]=0x02128,
458    },
459    lcletters = tolower(0x1D51E),
460    lcgreek   = tovector(regular_tf.lcgreek),
461    ucgreek   = tovector(regular_tf.ucgreek),
462    symbols   = tovector(regular_tf.symbols),
463}
464
465local fraktur_bf = {
466    digits    = tovector(regular_bf.digits),
467    ucletters = toupper(0x1D56C),
468    lcletters = tolower(0x1D586),
469    lcgreek   = tovector(regular_bf.lcgreek),
470    ucgreek   = tovector(regular_bf.ucgreek),
471    symbols   = tovector(regular_bf.symbols),
472}
473
474local fraktur = { -- ok
475    tf = fraktur_tf,
476    bf = fraktur_bf,
477    it = fraktur_tf,
478    bi = fraktur_bf,
479}
480
481local script_tf = {
482    digits    = tovector(regular_tf.digits),
483    ucletters = { -- B E F H I L M R -- P 2118
484        [0x00041]=0x1D49C, [0x00042]=0x0212C, [0x00043]=0x1D49E, [0x00044]=0x1D49F, [0x00045]=0x02130,
485        [0x00046]=0x02131, [0x00047]=0x1D4A2, [0x00048]=0x0210B, [0x00049]=0x02110, [0x0004A]=0x1D4A5,
486        [0x0004B]=0x1D4A6, [0x0004C]=0x02112, [0x0004D]=0x02133, [0x0004E]=0x1D4A9, [0x0004F]=0x1D4AA,
487        [0x00050]=0x1D4AB, [0x00051]=0x1D4AC, [0x00052]=0x0211B, [0x00053]=0x1D4AE, [0x00054]=0x1D4AF,
488        [0x00055]=0x1D4B0, [0x00056]=0x1D4B1, [0x00057]=0x1D4B2, [0x00058]=0x1D4B3, [0x00059]=0x1D4B4,
489        [0x0005A]=0x1D4B5,
490    },
491    lcletters = { -- E G O -- L 2113
492        [0x00061]=0x1D4B6, [0x00062]=0x1D4B7, [0x00063]=0x1D4B8, [0x00064]=0x1D4B9, [0x00065]=0x0212F,
493        [0x00066]=0x1D4BB, [0x00067]=0x0210A, [0x00068]=0x1D4BD, [0x00069]=0x1D4BE, [0x0006A]=0x1D4BF,
494        [0x0006B]=0x1D4C0, [0x0006C]=0x1D4C1, [0x0006D]=0x1D4C2, [0x0006E]=0x1D4C3, [0x0006F]=0x02134,
495        [0x00070]=0x1D4C5, [0x00071]=0x1D4C6, [0x00072]=0x1D4C7, [0x00073]=0x1D4C8, [0x00074]=0x1D4C9,
496        [0x00075]=0x1D4CA, [0x00076]=0x1D4CB, [0x00077]=0x1D4CC, [0x00078]=0x1D4CD, [0x00079]=0x1D4CE,
497        [0x0007A]=0x1D4CF,
498    },
499    lcgreek = tovector(regular_tf.lcgreek),
500    ucgreek = tovector(regular_tf.ucgreek),
501    symbols = tovector(regular_tf.symbols),
502}
503
504local script_bf = {
505    digits    = tovector(regular_bf.digits),
506    ucletters = toupper(0x1D4D0),
507    lcletters = tolower(0x1D4EA),
508    lcgreek   = tovector(regular_bf.lcgreek),
509    ucgreek   = tovector(regular_bf.ucgreek),
510    symbols   = tovector(regular_bf.symbols),
511}
512
513local script = {
514    tf = script_tf,
515    bf = script_bf,
516    it = script_tf,
517    bi = script_bf,
518}
519
520local alphabets = allocate {
521    regular    = regular,
522    sansserif  = sansserif,
523    monospaced = monospaced,
524    blackboard = blackboard,
525    fraktur    = fraktur,
526    script     = script,
527}
528
529alphabets.tt          = tovector(monospaced)
530alphabets.ss          = tovector(sansserif)
531alphabets.rm          = tovector(regular)
532alphabets.bb          = tovector(blackboard)
533alphabets.fr          = tovector(fraktur)
534alphabets.sr          = tovector(script)
535
536monospaced.normal     = tovector(monospaced_tf)
537monospaced.italic     = tovector(monospaced_it)
538monospaced.bold       = tovector(monospaced_bf)
539monospaced.bolditalic = tovector(monospaced_bi)
540
541sansserif.normal      = tovector(sansserif_tf)
542sansserif.italic      = tovector(sansserif_it)
543sansserif.bold        = tovector(sansserif_bf)
544sansserif.bolditalic  = tovector(sansserif_bi)
545
546regular.normal        = tovector(regular_tf)
547regular.italic        = tovector(regular_it)
548regular.bold          = tovector(regular_bf)
549regular.bolditalic    = tovector(regular_bi)
550
551alphabets.serif       = tovector(regular)
552alphabets.type        = tovector(monospaced)
553alphabets.teletype    = tovector(monospaced)
554
555mathematics.alphabets = alphabets
556
557local mathremap       = allocate { }
558mathematics.mapremap  = mathremap
559
560local boldmap         = allocate { }
561mathematics.boldmap   = boldmap
562
563-- all math (a bit of redundancy here) (sorted for tracing)
564
565for alphabet, styles in sortedhash(alphabets) do -- per 9/6/2011 we also have attr for missing
566    for style, data in sortedhash(styles) do
567     -- let's keep the long names (for tracing)
568        local n = #mathremap + 1
569        local d = {
570            attribute = n,
571            alphabet  = alphabet,
572            style     = style,
573        }
574        styles[style] = d
575        setmetatableindex(d,data) -- we could use a alphadata table
576        mathremap[n] = d
577    end
578end
579
580-- bold math
581
582local function remapbold(tf,bf)
583    local styles = mathematics.styles
584    local sets   = mathematics.sets
585    for i=1,#styles do
586        for j=1,#sets do
587            local one = styles[i]
588            local two = sets[j]
589            local a  = alphabets[one]
590            local tf = a[tf][two]
591            local bf = a[bf][two]
592            if tf and bf then
593                for k, v in next, tf do
594                    boldmap[v] = bf[k]
595                end
596            end
597        end
598    end
599end
600
601remapbold("tf","bf")
602remapbold("it","bi")
603
604-- table.save("e:/tmp/a.lua",alphabets)
605-- table.save("e:/tmp/b.lua",boldmap)
606
607function mathematics.tostyle(attribute)
608    local r = mathremap[attribute]
609    return r and r.style or "tf"
610end
611
612function mathematics.toname(attribute)
613    local r = mathremap[attribute]
614    return r and r.alphabet or "regular"
615end
616
617-- of course we could do some div/mod trickery instead
618
619local mathalphabet = attributes.private("mathalphabet")
620
621function mathematics.getboth(alphabet,style)
622    local data = alphabet and alphabets[alphabet] or regular
623    data = data[style or "tf"] or data.tf
624    return data and data.attribute
625end
626
627function mathematics.getstyle(style)
628    local r = mathremap[texgetattribute(mathalphabet)]
629    local alphabet = r and r.alphabet or "regular"
630    local data = alphabets[alphabet][style]
631    return data and data.attribute
632end
633
634function mathematics.syncboth(alphabet,style)
635    local data = alphabet and alphabets[alphabet] or regular
636    data = style and data[style] or data.tf
637    texsetattribute(mathalphabet,data and data.attribute or texattribute[mathalphabet])
638end
639
640function mathematics.syncstyle(style)
641    local r = mathremap[texgetattribute(mathalphabet)]
642    local alphabet = r and r.alphabet or "regular"
643    local data = alphabets[alphabet][style]
644    texsetattribute(mathalphabet,data and data.attribute or texattribute[mathalphabet])
645end
646
647function mathematics.syncname(alphabet)
648 -- local r = mathremap[mathalphabet]
649    local r = mathremap[texgetattribute(mathalphabet)]
650    local style = r and r.style or "tf"
651    local data = alphabets[alphabet][style]
652    texsetattribute(mathalphabet,data and data.attribute or texattribute[mathalphabet])
653end
654
655implement {
656    name      = "setmathattribute",
657    arguments = "2 arguments",
658    public    = true,
659    protected = true,
660    actions   = function(alphabet,style)
661        if texgetmode() == mathmode_code then
662            local data = alphabets[alphabet] or regular
663            data = data[style] or data.tf
664            texsetattribute(mathalphabet,data and data.attribute or texattribute[mathalphabet])
665        end
666    end
667}
668
669implement {
670    name      = "setmathfontstyle",
671    arguments = "argument",
672    public    = true,
673    protected = true,
674    actions   = function(style)
675        if texgetmode() == mathmode_code then
676            local r = mathremap[texgetattribute(mathalphabet)]
677            local alphabet = r and r.alphabet or "regular"
678            local data = alphabets[alphabet][style]
679            texsetattribute(mathalphabet,data and data.attribute or texattribute[mathalphabet])
680        end
681    end
682}
683
684implement {
685    name      = "setmathalphabet",
686    arguments = "argument",
687    public    = true,
688    protected = true,
689    actions   = function(alphabet)
690        if texgetmode() == mathmode_code then
691         -- local r = mathremap[mathalphabet]
692            local r = mathremap[texgetattribute(mathalphabet)]
693            local style = r and r.style or "tf"
694            local data = alphabets[alphabet][style]
695            texsetattribute(mathalphabet,data and data.attribute or texattribute[mathalphabet])
696        end
697    end
698}
699
700local islcgreek = regular_tf.lcgreek
701local isucgreek = regular_tf.ucgreek
702local issygreek = regular_tf.symbols
703local isgreek   = merged(islcgreek,isucgreek,issygreek)
704
705local greekremapping = {
706    { what = "unchanged" }, -- upright
707    { what = "upright", it = "tf", bi = "bf" }, -- upright
708    { what = "italic",  tf = "it", bf = "bi" }, -- italic
709}
710
711local usedremap = { }
712
713local function resolver(map)
714    return function (t,k)
715        local v =
716            map.digits   [k] or
717            map.lcletters[k] or map.ucletters[k] or
718            map.lcgreek  [k] or map.ucgreek  [k] or
719            map.symbols  [k] or k
720        t[k] = v
721        return v
722    end
723end
724
725for k, v in next, mathremap do
726    local t = { }
727    setmetatableindex(t,resolver(v))
728    usedremap[k] = t
729end
730
731local function remapgreek(mathalphabet,how,detail,char)
732    local r = mathremap[mathalphabet] -- what if 0
733    local alphabet = r and r.alphabet or "regular"
734    local style = r and r.style or "tf"
735    local remapping = greekremapping[how]
736    if trace_greek then
737        report_remapping("greek %s, %s char %C, alphabet %a %a, method %a","before",detail,char,alphabet,style,remapping.what)
738    end
739    local newstyle = remapping[style]
740    if newstyle then
741        local data = alphabets[alphabet][newstyle] -- always something
742        mathalphabet = data and data.attribute or mathalphabet
743        style        = newstyle
744    end
745    if trace_greek then
746        report_remapping("greek %s, %s char %C, alphabet %a %a, method %a","after",detail,char,alphabet,style,remapping.what)
747    end
748    return mathalphabet, style
749end
750
751function mathematics.remapalphabets(char,mathalphabet,mathgreek)
752    if not mathalphabet then
753        return
754    end
755    if mathgreek and mathgreek > 0 then
756        if not isgreek[char] then
757            -- nothing needed
758        elseif islcgreek[char] then
759            local lc = (mathgreek >> 4) & 0x0F
760            if lc > 1 then
761                mathalphabet = remapgreek(mathalphabet,lc,"lowercase",char)
762            end
763        elseif isucgreek[char] then
764            local uc = (mathgreek >> 0) & 0x0F
765            if uc > 1 then
766                mathalphabet = remapgreek(mathalphabet,uc,"uppercase",char)
767            end
768        elseif issygreek[char] then
769            local sy = (mathgreek >> 8) & 0x0F
770            if sy > 1 then
771                mathalphabet = remapgreek(mathalphabet,sy,"symbol",char)
772            end
773        end
774    end
775    if mathalphabet > 0 then
776        local remap = usedremap[mathalphabet] -- redundant check
777        if remap then
778            local newchar = remap[char]
779            return newchar ~= char and newchar
780        end
781    end
782 -- return nil
783end
784
785-- begin of experiment
786
787local fallback = {
788    tf = "bf",
789    it = "bi",
790    bf = "tf",
791    bi = "it",
792}
793
794function mathematics.fallbackstyleattr(attribute)
795    local r = mathremap[attribute]
796    local alphabet = r.alphabet or "regular"
797    local style = r.style or "tf"
798    local fback = fallback[style]
799    if fback then
800        local data = alphabets[alphabet][fback]
801        if data then
802            local attr = data.attribute
803            return attribute ~= attr and attr
804        end
805    end
806end
807
808-- end of experiment
809
810local function checkedcopy(characters,child,parent)
811    for k, v in next, child do
812        if not characters[v] then
813            characters[v] = characters[parent[k]]
814        end
815    end
816end
817
818function mathematics.addfallbacks(main)
819    local characters = main.characters
820    checkedcopy(characters,regular.bf.ucgreek,regular.tf.ucgreek)
821    checkedcopy(characters,regular.bf.lcgreek,regular.tf.lcgreek)
822    checkedcopy(characters,regular.bi.ucgreek,regular.it.ucgreek)
823    checkedcopy(characters,regular.bi.lcgreek,regular.it.lcgreek)
824end
825