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