if not modules then modules = { } end modules ['math-vfu'] = { version = 1.001, comment = "companion to math-ini.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" } -- All these math vectors .. thanks to Aditya and Mojca they become -- better and better. If you have problems with math fonts or miss -- characters report it to the ConTeXt mailing list. Also thanks to -- Boguslaw for finding a couple of errors. -- 20D6 -> 2190 -- 20D7 -> 2192 local type, next = type, next local max = math.max local format = string.format local fonts, nodes, mathematics = fonts, nodes, mathematics local trace_virtual = false trackers.register("math.virtual", function(v) trace_virtual = v end) local trace_timings = false trackers.register("math.timings", function(v) trace_timings = v end) local add_optional = false directives.register("math.virtual.optional",function(v) add_optional = v end) local report_virtual = logs.reporter("fonts","virtual math") local allocate = utilities.storage.allocate local setmetatableindex = table.setmetatableindex local mathencodings = allocate() fonts.encodings.math = mathencodings -- better is then: fonts.encodings.vectors local vfmath = allocate() fonts.handlers.vf.math = vfmath local shared = { } --~ local push, pop, back = { "push" }, { "pop" }, { "slot", 1, 0x2215 } --~ local function negate(main,characters,id,size,unicode,basecode) --~ if not characters[unicode] then --~ local basechar = characters[basecode] --~ if basechar then --~ local ht, wd = basechar.height, basechar.width --~ characters[unicode] = { --~ width = wd, --~ height = ht, --~ depth = basechar.depth, --~ italic = basechar.italic, --~ kerns = basechar.kerns, --~ commands = { --~ { "slot", 1, basecode }, --~ push, --~ { "down", ht/5}, --~ { "right", - wd/2}, --~ back, --~ push, --~ } --~ } --~ end --~ end --~ end --~ \Umathchardef\braceld="0 "1 "FF07A --~ \Umathchardef\bracerd="0 "1 "FF07B --~ \Umathchardef\bracelu="0 "1 "FF07C --~ \Umathchardef\braceru="0 "1 "FF07D local function brace(main,characters,id,size,unicode,first,rule,left,right,rule,last) if not characters[unicode] then characters[unicode] = { horiz_variants = { { extender = 0, glyph = first }, { extender = 1, glyph = rule }, { extender = 0, glyph = left }, { extender = 0, glyph = right }, { extender = 1, glyph = rule }, { extender = 0, glyph = last }, } } end end local function arrow(main,characters,id,size,unicode,arrow,minus,isleft) local chr = characters[unicode] if not chr then -- skip elseif isleft then chr.horiz_variants = { { extender = 0, glyph = arrow }, { extender = 1, glyph = minus }, } else chr.horiz_variants = { { extender = 1, glyph = minus }, { extender = 0, glyph = arrow }, } end end local function parent(main,characters,id,size,unicode,first,rule,last) if not characters[unicode] then characters[unicode] = { horiz_variants = { { extender = 0, glyph = first }, { extender = 1, glyph = rule }, { extender = 0, glyph = last }, } } end end local push, pop, step = { "push" }, { "pop" }, 0.2 -- 0.1 is nicer but gives larger files local function make(main,characters,id,size,n,m) local old = 0xFF000+n local c = characters[old] if c then local upslot, dnslot, uprule, dnrule = 0xFF100+n, 0xFF200+n, 0xFF300+m, 0xFF400+m local xu = main.parameters.x_height + 0.3*size local xd = 0.3*size local w, h, d = c.width, c.height, c.depth local thickness = h - d local rulewidth = step*size -- we could use an overlap local slot = { "slot", id, old } local rule = { "rule", thickness, rulewidth } local up = { "down", -xu } local dn = { "down", xd } local ht, dp = xu + 3*thickness, 0 if not characters[uprule] then characters[uprule] = { width = rulewidth, height = ht, depth = dp, commands = { push, up, rule, pop } } end characters[upslot] = { width = w, height = ht, depth = dp, commands = { push, up, slot, pop } } local ht, dp = 0, xd + 3*thickness if not characters[dnrule] then characters[dnrule] = { width = rulewidth, height = ht, depth = dp, commands = { push, dn, rule, pop } } end characters[dnslot] = { width = w, height = ht, depth = dp, commands = { push, dn, slot, pop } } end end local function minus(main,characters,id,size,unicode) -- push/pop needed? local minus = characters[0x002D] if minus then local mu = size/18 local width = minus.width - 5*mu characters[unicode] = { width = width, height = minus.height, depth = minus.depth, commands = { push, { "right", -3*mu }, { "slot", id, 0x002D }, pop } } end end -- fails: pdf:page: pdf:direct: ... some funny displacement -- this does not yet work ... { "scale", 2, 0, 0, 3 } .. commented code -- -- this does not work ... no interpretation going on here -- -- local nodeinjections = backends.nodeinjections -- { "node", nodeinjections.save() }, -- { "node", nodeinjections.transform(.7,0,0,.7) }, -- commands[#commands+1] = { "node", nodeinjections.restore() } local done = { } local function raise(main,characters,id,size,unicode,private,n) -- this is a real fake mess local raised = characters[private] if raised then if not done[unicode] then report_virtual("temporary too large U+%05X due to issues in luatex backend",unicode) done[unicode] = true end local up = 0.85 * main.parameters.x_height local slot = { "slot", id, private } local commands = { push, { "down", - up }, -- { "scale", .7, 0, 0, .7 }, slot, } for i=2,n do commands[#commands+1] = slot end commands[#commands+1] = pop characters[unicode] = { width = .7 * n * raised.width, height = .7 * (raised.height + up), depth = .7 * (raised.depth - up), commands = commands, } end end local function dots(main,characters,id,size,unicode) local c = characters[0x002E] if c then local w, h, d = c.width, c.height, c.depth local mu = size/18 local right3mu = { "right", 3*mu } local right1mu = { "right", 1*mu } local up1size = { "down", -.1*size } local up4size = { "down", -.4*size } local up7size = { "down", -.7*size } local right2muw = { "right", 2*mu + w } local slot = { "slot", id, 0x002E } if unicode == 0x22EF then local c = characters[0x022C5] if c then local w, h, d = c.width, c.height, c.depth local slot = { "slot", id, 0x022C5 } characters[unicode] = { width = 3*w + 2*3*mu, height = h, depth = d, commands = { push, slot, right3mu, slot, right3mu, slot, pop } } end elseif unicode == 0x22EE then -- weird height ! characters[unicode] = { width = w, height = h+(1.4)*size, depth = 0, commands = { push, push, slot, pop, up4size, push, slot, pop, up4size, slot, pop } } elseif unicode == 0x22F1 then characters[unicode] = { width = 3*w + 6*size/18, height = 1.5*size, depth = 0, commands = { push, right1mu, push, up7size, slot, pop, right2muw, push, up4size, slot, pop, right2muw, push, up1size, slot, pop, right1mu, pop } } elseif unicode == 0x22F0 then characters[unicode] = { width = 3*w + 6*size/18, height = 1.5*size, depth = 0, commands = { push, right1mu, push, up1size, slot, pop, right2muw, push, up4size, slot, pop, right2muw, push, up7size, slot, pop, right1mu, pop } } else characters[unicode] = { width = 3*w + 2*3*mu, height = h, depth = d, commands = { push, slot, right3mu, slot, right3mu, slot, pop } } end end end local function vertbar(main,characters,id,size,parent,scale,unicode) local cp = characters[parent] if cp then local sc = scale * size local pc = { "slot", id, parent } characters[unicode] = { width = cp.width, height = cp.height + sc, depth = cp.depth + sc, commands = { push, { "down", -sc }, pc, pop, push, { "down", sc }, pc, pop, pc, }, next = cp.next -- can be extensible } cp.next = unicode end end local function jointwo(main,characters,id,size,unicode,u1,d12,u2) local c1, c2 = characters[u1], characters[u2] if c1 and c2 then local w1, w2 = c1.width, c2.width local mu = size/18 characters[unicode] = { width = w1 + w2 - d12*mu, height = max(c1.height or 0, c2.height or 0), depth = max(c1.depth or 0, c2.depth or 0), commands = { { "slot", id, u1 }, { "right", -d12*mu } , { "slot", id, u2 }, } } end end local function jointhree(main,characters,id,size,unicode,u1,d12,u2,d23,u3) local c1, c2, c3 = characters[u1], characters[u2], characters[u3] if c1 and c2 and c3 then local w1, w2, w3 = c1.width, c2.width, c3.width local mu = size/18 characters[unicode] = { width = w1 + w2 + w3 - d12*mu - d23*mu, height = max(c1.height or 0, c2.height or 0, c3.height or 0), depth = max(c1.depth or 0, c2.depth or 0, c3.depth or 0), commands = { { "slot", id, u1 }, { "right", - d12*mu } , { "slot", id, u2 }, { "right", - d23*mu }, { "slot", id, u3 }, } } end end local function stack(main,characters,id,size,unicode,u1,d12,u2) local c1, c2 = characters[u1], characters[u2] if c1 and c2 then local w1, w2 = c1.width, c2.width local h1, h2 = c1.height, c2.height local d1, d2 = c1.depth, c2.depth local mu = size/18 characters[unicode] = { width = w1, height = h1 + h2 + d12, depth = d1, commands = { { "slot", id, u1 }, { "right", - w1/2 - w2/2 } , { "down", -h1 + d2 -d12*mu } , { "slot", id, u2 }, } } end end function vfmath.addmissing(main,id,size) local characters = main.characters local shared = main.shared local variables = main.goodies.mathematics and main.goodies.mathematics.variables or { } local joinrelfactor = variables.joinrelfactor or 3 for i=0x7A,0x7D do make(main,characters,id,size,i,1) end brace (main,characters,id,size,0x23DE,0xFF17A,0xFF301,0xFF17D,0xFF17C,0xFF301,0xFF17B) brace (main,characters,id,size,0x23DF,0xFF27C,0xFF401,0xFF27B,0xFF27A,0xFF401,0xFF27D) parent (main,characters,id,size,0x23DC,0xFF17A,0xFF301,0xFF17B) parent (main,characters,id,size,0x23DD,0xFF27C,0xFF401,0xFF27D) -- negate (main,characters,id,size,0x2260,0x003D) dots (main,characters,id,size,0x2026) -- ldots dots (main,characters,id,size,0x22EE) -- vdots dots (main,characters,id,size,0x22EF) -- cdots dots (main,characters,id,size,0x22F1) -- ddots dots (main,characters,id,size,0x22F0) -- udots minus (main,characters,id,size,0xFF501) arrow (main,characters,id,size,0x2190,0x2190,0xFF501,true) -- left arrow (main,characters,id,size,0x2192,0x2192,0xFF501,false) -- right vertbar (main,characters,id,size,0x0007C,0.10,0xFF601) -- big : 0.85 bodyfontsize vertbar (main,characters,id,size,0xFF601,0.30,0xFF602) -- Big : 1.15 bodyfontsize vertbar (main,characters,id,size,0xFF602,0.30,0xFF603) -- bigg : 1.45 bodyfontsize vertbar (main,characters,id,size,0xFF603,0.30,0xFF604) -- Bigg : 1.75 bodyfontsize vertbar (main,characters,id,size,0x02016,0.10,0xFF605) vertbar (main,characters,id,size,0xFF605,0.30,0xFF606) vertbar (main,characters,id,size,0xFF606,0.30,0xFF607) vertbar (main,characters,id,size,0xFF607,0.30,0xFF608) jointwo (main,characters,id,size,0x21A6,0xFE321,0,0x02192) -- \mapstochar\rightarrow jointwo (main,characters,id,size,0x21A9,0x02190,joinrelfactor,0xFE323) -- \leftarrow\joinrel\rhook jointwo (main,characters,id,size,0x21AA,0xFE322,joinrelfactor,0x02192) -- \lhook\joinrel\rightarrow stack (main,characters,id,size,0x2259,0x0003D,3,0x02227) -- \buildrel\wedge\over= jointwo (main,characters,id,size,0x22C8,0x022B3,joinrelfactor,0x022B2) -- \mathrel\triangleright\joinrel\mathrel\triangleleft (4 looks better than 3) jointwo (main,characters,id,size,0x2260,0x00338,0,0x0003D) -- \not\equal jointwo (main,characters,id,size,0x2284,0x00338,0,0x02282) -- \not\subset jointwo (main,characters,id,size,0x2285,0x00338,0,0x02283) -- \not\supset jointwo (main,characters,id,size,0x22A7,0x0007C,joinrelfactor,0x0003D) -- \mathrel|\joinrel= jointwo (main,characters,id,size,0x27F5,0x02190,joinrelfactor,0x0002D) -- \leftarrow\joinrel\relbar jointwo (main,characters,id,size,0x27F6,0x0002D,joinrelfactor,0x02192) -- \relbar\joinrel\rightarrow jointwo (main,characters,id,size,0x27F7,0x02190,joinrelfactor,0x02192) -- \leftarrow\joinrel\rightarrow jointwo (main,characters,id,size,0x27F8,0x021D0,joinrelfactor,0x0003D) -- \Leftarrow\joinrel\Relbar jointwo (main,characters,id,size,0x27F9,0x0003D,joinrelfactor,0x021D2) -- \Relbar\joinrel\Rightarrow jointwo (main,characters,id,size,0x27FA,0x021D0,joinrelfactor,0x021D2) -- \Leftarrow\joinrel\Rightarrow jointhree(main,characters,id,size,0x27FB,0x02190,joinrelfactor,0x0002D,0,0xFE324) -- \leftarrow\joinrel\relbar\mapsfromchar jointhree(main,characters,id,size,0x27FC,0xFE321,0,0x0002D,joinrelfactor,0x02192) -- \mapstochar\relbar\joinrel\rightarrow jointwo (main,characters,id,size,0x2254,0x03A,0,0x03D) -- := (≔) -- raise (main,characters,id,size,0x02032,0xFE325,1) -- prime -- raise (main,characters,id,size,0x02033,0xFE325,2) -- double prime -- raise (main,characters,id,size,0x02034,0xFE325,3) -- triple prime -- there are more (needs discussion first): -- characters[0x20D6] = characters[0x2190] -- characters[0x20D7] = characters[0x2192] characters[0x02B9] = characters[0x2032] -- we're nice end local unique = 0 -- testcase: \startTEXpage \math{!\text{-}\text{-}\text{-}} \stopTEXpage local reported = { } local reverse = { } -- index -> unicode setmetatableindex(reverse, function(t,name) if trace_virtual then report_virtual("initializing math vector '%s'",name) end local m, r = mathencodings[name], { } for u, i in next, m do r[i] = u end reverse[name] = r return r end) function vfmath.define(specification,set,goodies) local name = specification.name -- symbolic name local size = specification.size -- given size local loaded, fontlist, names, main = { }, { }, { }, nil local start = (trace_virtual or trace_timings) and os.clock() local okset, n = { }, 0 for s=1,#set do local ss = set[s] local ssname = ss.name if add_optional and ss.optional then if trace_virtual then report_virtual("loading font %s subfont %s with name %s at %s is skipped",name,s,ssname,size) end else if ss.features then ssname = ssname .. "*" .. ss.features end if ss.main then main = s end local alreadyloaded = names[ssname] -- for px we load one twice (saves .04 sec) local f, id if alreadyloaded then f, id = alreadyloaded.f, alreadyloaded.id if trace_virtual then report_virtual("loading font %s subfont %s with name %s is reused",name,s,ssname) end else f, id = fonts.constructors.readanddefine(ssname,size) names[ssname] = { f = f, id = id } end if not f or id == 0 then report_virtual("loading font %s subfont %s with name %s at %s is skipped, not found",name,s,ssname,size) else n = n + 1 okset[n] = ss loaded[n] = f fontlist[n] = { id = id, size = size } if not shared[s] then shared[n] = { } end if trace_virtual then report_virtual("loading font %s subfont %s with name %s at %s as id %s using encoding %s",name,s,ssname,size,id,ss.vector or "none") end if not ss.checked then ss.checked = true local vector = mathencodings[ss.vector] if vector then -- we resolve named glyphs only once as we can assume that vectors -- are unique to a font set (when we read an afm we get those names -- mapped onto the private area) for unicode, index in next, vector do if not tonumber(index) then local u = f.unicodes u = u and u[index] if u then if trace_virtual then report_virtual("resolving name %s to %s",index,u) end else report_virtual("unable to resolve name %s",index) end vector[unicode] = u end end end end end end end -- beware, loaded[1] is already passed to tex (we need to make a simple copy then .. todo) local parent = loaded[1] -- a text font local characters = { } local parameters = { } local mathparameters = { } local descriptions = { } local metadata = { } local properties = { } local goodies = { } local main = { metadata = metadata, properties = properties, characters = characters, descriptions = descriptions, parameters = parameters, mathparameters = mathparameters, fonts = fontlist, goodies = goodies, } -- -- for key, value in next, parent do if type(value) ~= "table" then main[key] = value end end -- if parent.characters then for unicode, character in next, parent.characters do characters[unicode] = character end else report_virtual("font %s has no characters",name) end -- if parent.parameters then for key, value in next, parent.parameters do parameters[key] = value end else report_virtual("font %s has no parameters",name) end -- local description = { name = "" } setmetatableindex(descriptions,function() return description end) -- if parent.properties then setmetatableindex(properties,parent.properties) end -- if parent.goodies then setmetatableindex(goodies,parent.goodies) end -- properties.virtualized = true properties.hasitalics = true properties.hasmath = true -- local fullname = properties.fullname -- parent via mt if fullname then unique = unique + 1 properties.fullname = fullname .. "-" .. unique end -- -- we need to set some values in main as well (still?) -- main.fullname = properties.fullname main.type = "virtual" main.nomath = false -- parameters.x_height = parameters.x_height or 0 -- local already_reported = false for s=1,n do local ss, fs = okset[s], loaded[s] if not fs then -- skip, error elseif add_optional and ss.optional then -- skip, redundant else local newparameters = fs.parameters if not newparameters then report_virtual("font %s, no parameters set",name) elseif ss.extension then mathparameters.math_x_height = newparameters.x_height or 0 -- math_x_height : height of x mathparameters.default_rule_thickness = newparameters[ 8] or 0 -- default_rule_thickness : thickness of \over bars mathparameters.big_op_spacing1 = newparameters[ 9] or 0 -- big_op_spacing1 : minimum clearance above a displayed op mathparameters.big_op_spacing2 = newparameters[10] or 0 -- big_op_spacing2 : minimum clearance below a displayed op mathparameters.big_op_spacing3 = newparameters[11] or 0 -- big_op_spacing3 : minimum baselineskip above displayed op mathparameters.big_op_spacing4 = newparameters[12] or 0 -- big_op_spacing4 : minimum baselineskip below displayed op mathparameters.big_op_spacing5 = newparameters[13] or 0 -- big_op_spacing5 : padding above and below displayed limits -- report_virtual("loading and virtualizing font %s at size %s, setting ex parameters",name,size) elseif ss.parameters then mathparameters.x_height = newparameters.x_height or mathparameters.x_height mathparameters.x_height = mathparameters.x_height or fp.x_height or 0 -- x_height : height of x mathparameters.num1 = newparameters[ 8] or 0 -- num1 : numerator shift-up in display styles mathparameters.num2 = newparameters[ 9] or 0 -- num2 : numerator shift-up in non-display, non-\atop mathparameters.num3 = newparameters[10] or 0 -- num3 : numerator shift-up in non-display \atop mathparameters.denom1 = newparameters[11] or 0 -- denom1 : denominator shift-down in display styles mathparameters.denom2 = newparameters[12] or 0 -- denom2 : denominator shift-down in non-display styles mathparameters.sup1 = newparameters[13] or 0 -- sup1 : superscript shift-up in uncramped display style mathparameters.sup2 = newparameters[14] or 0 -- sup2 : superscript shift-up in uncramped non-display mathparameters.sup3 = newparameters[15] or 0 -- sup3 : superscript shift-up in cramped styles mathparameters.sub1 = newparameters[16] or 0 -- sub1 : subscript shift-down if superscript is absent mathparameters.sub2 = newparameters[17] or 0 -- sub2 : subscript shift-down if superscript is present mathparameters.sup_drop = newparameters[18] or 0 -- sup_drop : superscript baseline below top of large box mathparameters.sub_drop = newparameters[19] or 0 -- sub_drop : subscript baseline below bottom of large box mathparameters.delim1 = newparameters[20] or 0 -- delim1 : size of \atopwithdelims delimiters in display styles mathparameters.delim2 = newparameters[21] or 0 -- delim2 : size of \atopwithdelims delimiters in non-displays mathparameters.axis_height = newparameters[22] or 0 -- axis_height : height of fraction lines above the baseline -- report_virtual("loading and virtualizing font %s at size %s, setting sy parameters",name,size) end local vectorname = ss.vector if vectorname then local offset = 0xFF000 local vector = mathencodings[vectorname] local rotcev = reverse[vectorname] local isextension = ss.extension if vector and rotcev then local fc, fd, si = fs.characters, fs.descriptions, shared[s] local skewchar = ss.skewchar for unicode, index in next, vector do local fci = fc[index] if not fci then local fontname = fs.properties.name or "unknown" local rf = reported[fontname] if not rf then rf = { } reported[fontname] = rf end local rv = rf[vectorname] if not rv then rv = { } rf[vectorname] = rv end local ru = rv[unicode] if not ru then if trace_virtual then report_virtual( "unicode point U+%05X has no index %04X in vector %s for font %s",unicode,index,vectorname,fontname) elseif not already_reported then report_virtual( "the mapping is incomplete for '%s' at %s",name,number.topoints(size)) already_reported = true end rv[unicode] = true end else local ref = si[index] if not ref then ref = { { 'slot', s, index } } si[index] = ref end local kerns = fci.kerns local width = fci.width local italic = fci.italic if italic and isextension then -- int_a^b width = width + italic end if kerns then local krn = { } for k, v in next, kerns do -- kerns is sparse local rk = rotcev[k] if rk then krn[rk] = v -- kerns[k] end end if not next(krn) then krn = nil end local t = { width = width, height = fci.height, depth = fci.depth, italic = italic, kerns = krn, commands = ref, } if skewchar then local k = kerns[skewchar] if k then t.top_accent = width/2 + k end end characters[unicode] = t else characters[unicode] = { width = width, height = fci.height, depth = fci.depth, italic = italic, commands = ref, } end --~ report_virtual("%05X %s %s",unicode,fci.height or "NO HEIGHT",fci.depth or "NO DEPTH") end end if isextension then -- todo: if multiple ex, then 256 offsets per instance local extension = mathencodings["large-to-small"] local variants_done = fs.variants_done for index, fci in next, fc do -- the raw ex file if type(index) == "number" then local ref = si[index] if not ref then ref = { { 'slot', s, index } } si[index] = ref end local italic = fci.italic local t = { width = fci.width + italic, -- watch this ! height = fci.height, depth = fci.depth, italic = italic, commands = ref, } local n = fci.next if n then t.next = offset + n elseif variants_done then local vv = fci.vert_variants if vv then t.vert_variants = vv end local hv = fci.horiz_variants if hv then t.horiz_variants = hv end else local vv = fci.vert_variants if vv then for i=1,#vv do local vvi = vv[i] vvi.glyph = vvi.glyph + offset end t.vert_variants = vv end local hv = fci.horiz_variants if hv then for i=1,#hv do local hvi = hv[i] hvi.glyph = hvi.glyph + offset end t.horiz_variants = hv end end characters[offset + index] = t end end fs.variants_done = true for unicode, index in next, extension do local cu = characters[unicode] if cu then cu.next = offset + index else local fci = fc[index] if not fci then -- do nothing else -- probably never entered local ref = si[index] if not ref then ref = { { 'slot', s, index } } si[index] = ref end local kerns = fci.kerns if kerns then local krn = { } --~ for k=1,#kerns do --~ krn[offset + k] = kerns[k] --~ end for k, v in next, kerns do -- is kerns sparse? krn[offset + k] = v end characters[unicode] = { width = fci.width, height = fci.height, depth = fci.depth, italic = fci.italic, commands = ref, kerns = krn, next = offset + index, } else characters[unicode] = { width = fci.width, height = fci.height, depth = fci.depth, italic = fci.italic, commands = ref, next = offset + index, } end end end end end else report_virtual("error in loading %s: problematic vector %s",name,vectorname) end end mathematics.extras.copy(main) --not needed here (yet) end end -- fontlist[#fontlist+1] = { id = font.nextid(), size = size, } -- main.mathparameters = mathparameters -- still traditional ones vfmath.addmissing(main,#fontlist,size) mathematics.addfallbacks(main) -- main.properties.math_is_scaled = true -- signal fonts.constructors.assignmathparameters(main,main) -- main.MathConstants = main.mathparameters -- we directly pass it to TeX (bypasses the scaler) so this is needed -- inspect(main.MathConstants) -- if trace_virtual or trace_timings then report_virtual("loading and virtualizing font %s at size %s took %0.3f seconds",name,size,os.clock()-start) end -- return main end function mathematics.makefont(name,set,goodies) fonts.definers.methods.variants[name] = function(specification) return vfmath.define(specification,set,goodies) end end -- helpers function vfmath.setletters(font_encoding, name, uppercase, lowercase) local enc = font_encoding[name] for i = 0,25 do enc[uppercase+i] = i + 0x41 enc[lowercase+i] = i + 0x61 end end function vfmath.setdigits(font_encoding, name, digits) local enc = font_encoding[name] for i = 0,9 do enc[digits+i] = i + 0x30 end end