diff options
author | Karl Berry <karl@freefriends.org> | 2016-04-22 22:14:39 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2016-04-22 22:14:39 +0000 |
commit | fc4466b32ed330a956ac603b00fd145524cff49a (patch) | |
tree | 2c50e2b8de13aa9233b2c76dffe201558f169e86 /Master/texmf-dist/tex/context/base/mkiv/math-fbk.lua | |
parent | 50e2368597d5f6fe2057195d0ae6a9f2044923e4 (diff) |
context (22apr16)
git-svn-id: svn://tug.org/texlive/trunk@40691 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkiv/math-fbk.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/mkiv/math-fbk.lua | 614 |
1 files changed, 614 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-fbk.lua b/Master/texmf-dist/tex/context/base/mkiv/math-fbk.lua new file mode 100644 index 00000000000..564ece8d7ca --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/math-fbk.lua @@ -0,0 +1,614 @@ +if not modules then modules = { } end modules ['math-fbk'] = { + 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" +} + +local trace_fallbacks = false trackers.register("math.fallbacks", function(v) trace_fallbacks = v end) + +local report_fallbacks = logs.reporter("math","fallbacks") + +local formatters = string.formatters +local fastcopy = table.fastcopy +local byte = string.byte + +local fallbacks = { } +mathematics.fallbacks = fallbacks + +local virtualcharacters = { } + +local identifiers = fonts.hashes.identifiers +local lastmathids = fonts.hashes.lastmathids + +-- we need a trick (todo): if we define scriptscript, script and text in +-- that order we could use their id's .. i.e. we could always add a font +-- table with those id's .. in fact, we could also add a whole lot more +-- as it doesn't hurt +-- +-- todo: use index 'true when luatex provides that feature (on the agenda) + +-- to be considered: +-- +-- in luatex provide reserve_id (and pass id as field of tfmdata) +-- in context define three sizes but pass them later i.e. do virtualize afterwards + +function fallbacks.apply(target,original) + local mathparameters = target.mathparameters -- why not hasmath + if mathparameters then + local characters = target.characters + local parameters = target.parameters + local mathsize = parameters.mathsize + local size = parameters.size + local usedfonts = target.fonts + if not usedfonts then + usedfonts = { } + target.fonts = usedfonts + end + -- This is not okay yet ... we have no proper way to refer to 'self' + -- otherwise I will make my own id allocator). + local self = #usedfonts == 0 and font.nextid() or nil -- will be true + local textid, scriptid, scriptscriptid + local textindex, scriptindex, scriptscriptindex + local textdata, scriptdata, scriptscriptdata + if mathsize == 3 then + -- scriptscriptsize + -- textid = nil -- self + -- scriptid = nil -- no smaller + -- scriptscriptid = nil -- no smaller + textid = self + scriptid = self + scriptscriptid = self + elseif mathsize == 2 then + -- scriptsize + -- textid = nil -- self + textid = self + scriptid = lastmathids[3] + scriptscriptid = lastmathids[3] + else + -- textsize + -- textid = nil -- self + textid = self + scriptid = lastmathids[2] + scriptscriptid = lastmathids[3] + end + if textid then + textindex = #usedfonts + 1 + usedfonts[textindex] = { id = textid } +-- textdata = identifiers[textid] or target + textdata = target + else + textdata = target + end + if scriptid then + scriptindex = #usedfonts + 1 + usedfonts[scriptindex] = { id = scriptid } + scriptdata = identifiers[scriptid] + else + scriptindex = textindex + scriptdata = textdata + end + if scriptscriptid then + scriptscriptindex = #usedfonts + 1 + usedfonts[scriptscriptindex] = { id = scriptscriptid } + scriptscriptdata = identifiers[scriptscriptid] + else + scriptscriptindex = scriptindex + scriptscriptdata = scriptdata + end + -- report_fallbacks("used textid: %S, used script id: %S, used scriptscript id: %S",textid,scriptid,scriptscriptid) + local data = { + textdata = textdata, + scriptdata = scriptdata, + scriptscriptdata = scriptscriptdata, + textindex = textindex, + scriptindex = scriptindex, + scriptscriptindex = scriptscriptindex, + textid = textid, + scriptid = scriptid, + scriptscriptid = scriptscriptid, + characters = characters, + unicode = k, + target = target, + original = original, + size = size, + mathsize = mathsize, + } + target.mathrelation = data + -- inspect(usedfonts) + for k, v in next, virtualcharacters do + if not characters[k] then + local tv = type(v) + local cd = nil + if tv == "table" then + cd = v + elseif tv == "number" then + cd = characters[v] + elseif tv == "function" then + cd = v(data) + end + if cd then + characters[k] = cd + else + -- something else + end + if trace_fallbacks and characters[k] then + report_fallbacks("extending math font %a with %U",target.properties.fullname,k) + end + end + end + data.unicode = nil + end +end + +utilities.sequencers.appendaction("aftercopyingcharacters","system","mathematics.fallbacks.apply") + +function fallbacks.install(unicode,value) + virtualcharacters[unicode] = value +end + +-- a few examples: + +local function reference(index,char) + if index then + return { "slot", index, char } + else + return { "char", char } + end +end + +local function raised(data,down) + local replacement = data.replacement + local character = data.scriptdata.characters[replacement] + if character then + return { + width = character.width, + height = character.height, + depth = character.depth, + commands = { + { "down", down and data.size/4 or -data.size/2 }, -- maybe exheight + reference(data.scriptindex,replacement) + } + } + end +end + +-- virtualcharacters[0x207A] = 0x2212 +-- virtualcharacters[0x207B] = 0x002B +-- virtualcharacters[0x208A] = 0x2212 +-- virtualcharacters[0x208B] = 0x002B + +virtualcharacters[0x207A] = function(data) + data.replacement = 0x002B + return raised(data) +end + +virtualcharacters[0x207B] = function(data) + data.replacement = 0x2212 + return raised(data) +end + +virtualcharacters[0x208A] = function(data) + data.replacement = 0x002B + return raised(data,true) +end + +virtualcharacters[0x208B] = function(data) + data.replacement = 0x2212 + return raised(data,true) +end + +-- local function repeated(data,char,n,fraction) +-- local character = data.characters[char] +-- if character then +-- local width = character.width +-- local delta = width - character.italic -- width * fraction +-- local c = { "char", char } +-- local r = { "right", right } +-- local commands = { } +-- for i=1,n-1 do +-- width = width + delta +-- commands[#commands+1] = c +-- commands[#commands+1] = -delta +-- end +-- commands[#commands+1] = c +-- return { +-- width = width, +-- height = character.height, +-- depth = character.depth, +-- commands = commands, +-- } +-- end +-- end + +-- virtualcharacters[0x222C] = function(data) +-- return repeated(data,0x222B,2,1/8) +-- end + +-- virtualcharacters[0x222D] = function(data) +-- return repeated(data,0x222B,3,1/8) +-- end + +local addextra = mathematics.extras.add + +addextra(0xFE350, { + category="sm", + description="MATHEMATICAL DOUBLE ARROW LEFT END", + mathclass="relation", + mathname="ctxdoublearrowfillleftend", + unicodeslot=0xFE350, +} ) + +addextra(0xFE351, { + category="sm", + description="MATHEMATICAL DOUBLE ARROW MIDDLE PART", + mathclass="relation", + mathname="ctxdoublearrowfillmiddlepart", + unicodeslot=0xFE351, +} ) + +addextra(0xFE352, { + category="sm", + description="MATHEMATICAL DOUBLE ARROW RIGHT END", + mathclass="relation", + mathname="ctxdoublearrowfillrightend", + unicodeslot=0xFE352, +} ) + +local push = { "push" } +local pop = { "pop" } +local leftarrow = { "char", 0x2190 } +local relbar = { "char", 0x2212 } +local rightarrow = { "char", 0x2192 } + +virtualcharacters[0xFE350] = function(data) + -- return combined(data,0x2190,0x2212) -- leftarrow relbar + local charone = data.characters[0x2190] + local chartwo = data.characters[0x2212] + if charone and chartwo then + local size = data.size/2 + return { + width = chartwo.width, + height = size, + depth = size, + commands = { + push, + { "down", size/2 }, + leftarrow, + pop, + { "down", -size/2 }, + relbar, + } + } + end +end + +virtualcharacters[0xFE351] = function(data) + -- return combined(data,0x2212,0x2212) -- relbar, relbar (isn't that just equal) + local char = data.characters[0x2212] + if char then + local size = data.size/2 + return { + width = char.width, + height = size, + depth = size, + commands = { + push, + { "down", size/2 }, + relbar, + pop, + { "down", -size/2 }, + relbar, + } + } + end +end + +virtualcharacters[0xFE352] = function(data) + -- return combined(data,0x2192,0x2212) -- rightarrow relbar + local charone = data.characters[0x2192] + local chartwo = data.characters[0x2212] + if charone and chartwo then + local size = data.size/2 + return { + width = chartwo.width, + height = size, + depth = size, + commands = { + push, + { "down", size/2 }, + relbar, + pop, + { "right", chartwo.width - charone.width }, + { "down", -size/2 }, + rightarrow, + } + } + end +end + +-- we could move the defs from math-act here + +local function accent_to_extensible(target,newchr,original,oldchr,height,depth,swap,offset,unicode) + local characters = target.characters + local olddata = characters[oldchr] + -- brrr ... pagella has only next + if olddata and not olddata.commands and olddata.width > 0 then + local addprivate = fonts.helpers.addprivate + if swap then + swap = characters[swap] + height = swap.depth or 0 + depth = 0 + else + height = height or 0 + depth = depth or 0 + end + local correction = swap and { "down", (olddata.height or 0) - height } or { "down", olddata.height + (offset or 0)} + local newdata = { + commands = { correction, { "slot", 1, oldchr } }, + width = olddata.width, + height = height, + depth = depth, + unicode = unicode, + } + local glyphdata = newdata + local nextglyph = olddata.next + while nextglyph do + local oldnextdata = characters[nextglyph] + if oldnextdata then + local newnextdata = { + commands = { correction, { "slot", 1, nextglyph } }, + width = oldnextdata.width, + height = height, + depth = depth, + } + local newnextglyph = addprivate(target,formatters["M-N-%H"](nextglyph),newnextdata) + newdata.next = newnextglyph + local nextnextglyph = oldnextdata.next + if nextnextglyph == nextglyph then + break + else + olddata = oldnextdata + newdata = newnextdata + nextglyph = nextnextglyph + end + else + report_fallbacks("error in fallback: no valid next, slot %X",nextglyph) + break + end + end + local hv = olddata.horiz_variants + if hv then + hv = fastcopy(hv) + newdata.horiz_variants = hv + for i=1,#hv do + local hvi = hv[i] + local oldglyph = hvi.glyph + local olddata = characters[oldglyph] + if olddata then + local newdata = { + commands = { correction, { "slot", 1, oldglyph } }, + width = olddata.width, + height = height, + depth = depth, + } + hvi.glyph = addprivate(target,formatters["M-H-%H"](oldglyph),newdata) + else + report_fallbacks("error in fallback: no valid horiz_variants, slot %X, index %i",oldglyph,i) + end + end + end + return glyphdata, true + else + return olddata, false + end +end + +virtualcharacters[0x203E] = function(data) -- could be FE33E instead + local target = data.target + local height, depth = 0, 0 + local mathparameters = target.mathparameters + if mathparameters then + height = mathparameters.OverbarVerticalGap + depth = mathparameters.UnderbarVerticalGap + else + height = target.parameters.xheight/4 + depth = height + end + return accent_to_extensible(target,0x203E,data.original,0x0305,height,depth,nil,nil,0x203E) +end + +virtualcharacters[0xFE33E] = virtualcharacters[0x203E] -- convenient +virtualcharacters[0xFE33F] = virtualcharacters[0x203E] -- convenient + +-- spacing + +local c_zero = byte('0') +local c_period = byte('.') + +local function spacefraction(data,fraction) + local width = fraction * data.target.parameters.space + return { + width = width, + commands = { right = width } + } +end + +local function charfraction(data,char) + local width = data.target.characters[char].width + return { + width = width, + commands = { right = width } + } +end + +local function quadfraction(data,fraction) + local width = fraction * data.target.parameters.quad + return { + width = width, + commands = { right = width } + } +end + +virtualcharacters[0x00A0] = function(data) return spacefraction(data,1) end -- nbsp +virtualcharacters[0x2000] = function(data) return quadfraction (data,1/2) end -- enquad +virtualcharacters[0x2001] = function(data) return quadfraction (data,1) end -- emquad +virtualcharacters[0x2002] = function(data) return quadfraction (data,1/2) end -- enspace +virtualcharacters[0x2003] = function(data) return quadfraction (data,1) end -- emspace +virtualcharacters[0x2004] = function(data) return quadfraction (data,1/3) end -- threeperemspace +virtualcharacters[0x2005] = function(data) return quadfraction (data,1/4) end -- fourperemspace +virtualcharacters[0x2006] = function(data) return quadfraction (data,1/6) end -- sixperemspace +virtualcharacters[0x2007] = function(data) return charfraction (data,c_zero) end -- figurespace +virtualcharacters[0x2008] = function(data) return charfraction (data,c_period) end -- punctuationspace +virtualcharacters[0x2009] = function(data) return quadfraction (data,1/8) end -- breakablethinspace +virtualcharacters[0x200A] = function(data) return quadfraction (data,1/8) end -- hairspace +virtualcharacters[0x200B] = function(data) return quadfraction (data,0) end -- zerowidthspace +virtualcharacters[0x202F] = function(data) return quadfraction (data,1/8) end -- narrownobreakspace +virtualcharacters[0x205F] = function(data) return spacefraction(data,1/2) end -- math thinspace + +-- + +local function smashed(data,unicode,swap,private) + local target = data.target + local original = data.original + local chardata = target.characters[unicode] + if chardata and chardata.height > target.parameters.xheight then + return accent_to_extensible(target,private,original,unicode,0,0,swap,nil,unicode) + else + return original.characters[unicode] + end +end + +addextra(0xFE3DE, { description="EXTENSIBLE OF 0x03DE", unicodeslot=0xFE3DE, mathextensible = "r", mathstretch = "h", mathclass = "topaccent" } ) +addextra(0xFE3DC, { description="EXTENSIBLE OF 0x03DC", unicodeslot=0xFE3DC, mathextensible = "r", mathstretch = "h", mathclass = "topaccent" } ) +addextra(0xFE3B4, { description="EXTENSIBLE OF 0x03B4", unicodeslot=0xFE3B4, mathextensible = "r", mathstretch = "h", mathclass = "topaccent" } ) + +virtualcharacters[0xFE3DE] = function(data) return smashed(data,0x23DE,0x23DF,0xFE3DE) end +virtualcharacters[0xFE3DC] = function(data) return smashed(data,0x23DC,0x23DD,0xFE3DC) end +virtualcharacters[0xFE3B4] = function(data) return smashed(data,0x23B4,0x23B5,0xFE3B4) end + +addextra(0xFE3DF, { description="EXTENSIBLE OF 0x03DF", unicodeslot=0xFE3DF, mathextensible = "r", mathstretch = "h", mathclass = "botaccent" } ) +addextra(0xFE3DD, { description="EXTENSIBLE OF 0x03DD", unicodeslot=0xFE3DD, mathextensible = "r", mathstretch = "h", mathclass = "botaccent" } ) +addextra(0xFE3B5, { description="EXTENSIBLE OF 0x03B5", unicodeslot=0xFE3B5, mathextensible = "r", mathstretch = "h", mathclass = "botaccent" } ) + +virtualcharacters[0xFE3DF] = function(data) local c = data.target.characters[0x23DF] if c then c.unicode = 0x23DF return c end end +virtualcharacters[0xFE3DD] = function(data) local c = data.target.characters[0x23DD] if c then c.unicode = 0x23DD return c end end +virtualcharacters[0xFE3B5] = function(data) local c = data.target.characters[0x23B5] if c then c.unicode = 0x23B5 return c end end + +-- todo: add some more .. numbers might change + +addextra(0xFE302, { description="EXTENSIBLE OF 0x0302", unicodeslot=0xFE302, mathstretch = "h", mathclass = "topaccent" } ) +addextra(0xFE303, { description="EXTENSIBLE OF 0x0303", unicodeslot=0xFE303, mathstretch = "h", mathclass = "topaccent" } ) + +local function smashed(data,unicode,private) + local target = data.target + local height = target.parameters.xheight / 2 + local c, done = accent_to_extensible(target,private,data.original,unicode,height,0,nil,-height,unicode) + if done then + c.top_accent = nil -- or maybe also all the others + end + return c +end + +virtualcharacters[0xFE302] = function(data) return smashed(data,0x0302,0xFE302) end +virtualcharacters[0xFE303] = function(data) return smashed(data,0x0303,0xFE303) end + +-- another crazy hack .. doesn't work as we define scrscr first .. we now have smaller +-- primes so we have smaller primes for the moment, big ones will become an option .. +-- these primes in fonts are a real mess .. kind of a dead end, so don't wonder about +-- the values below + +-- todo: check tounicodes + +local function smashed(data,unicode,optional) + local oldchar = data.characters[unicode] + if oldchar then + local xheight = data.target.parameters.xheight + local height = 1.2 * xheight + local shift = oldchar.height - height + local newchar = { + commands = { + { "down", shift }, + { "char", unicode }, + }, + height = height, + width = oldchar.width, + } + return newchar + elseif not optional then + report_fallbacks("missing %U prime in font %a",unicode,data.target.properties.fullname) + end +end + +-- -- relocate all but less flexible so not used .. instead some noad hackery plus +-- -- the above +-- +-- local function smashed(data,unicode,optional) +-- local oldchar = data.characters[unicode] +-- if oldchar then +-- local xheight = data.target.parameters.xheight +-- local height = oldchar.height +-- local shift = oldchar.height < 1.5*xheight and -(1.8*xheight-height) or 0 +-- local newchar = { +-- commands = { +-- { "down", shift }, +-- { "char", unicode }, +-- }, +-- unicode = unicode, +-- height = height, +-- width = oldchar.width, +-- } +-- return newchar +-- elseif not optional then +-- report_fallbacks("missing %U prime in font %a",unicode,data.target.properties.fullname) +-- end +-- end + +addextra(0xFE932, { description="SMASHED PRIME 0x02032", unicodeslot=0xFE932 } ) +addextra(0xFE933, { description="SMASHED PRIME 0x02033", unicodeslot=0xFE933 } ) +addextra(0xFE934, { description="SMASHED PRIME 0x02034", unicodeslot=0xFE934 } ) +addextra(0xFE957, { description="SMASHED PRIME 0x02057", unicodeslot=0xFE957 } ) + +addextra(0xFE935, { description="SMASHED BACKWARD PRIME 0x02035", unicodeslot=0xFE935 } ) +addextra(0xFE936, { description="SMASHED BACKWARD PRIME 0x02036", unicodeslot=0xFE936 } ) +addextra(0xFE937, { description="SMASHED BACKWARD PRIME 0x02037", unicodeslot=0xFE937 } ) + +virtualcharacters[0xFE932] = function(data) return smashed(data,0x02032) end +virtualcharacters[0xFE933] = function(data) return smashed(data,0x02033) end +virtualcharacters[0xFE934] = function(data) return smashed(data,0x02034) end +virtualcharacters[0xFE957] = function(data) return smashed(data,0x02057) end + +virtualcharacters[0xFE935] = function(data) return smashed(data,0x02035,true) end +virtualcharacters[0xFE936] = function(data) return smashed(data,0x02036,true) end +virtualcharacters[0xFE937] = function(data) return smashed(data,0x02037,true) end + +-- actuarian (beware: xits has an ugly one) + +addextra(0xFE940, { category = "mn", description="SMALL ANNUITY SYMBOL", unicodeslot=0xFE940, mathclass="topaccent", mathname="smallactuarial" }) + +local function actuarian(data) + local characters = data.target.characters + local parameters = data.target.parameters + local basechar = characters[0x0078] -- x (0x0058 X) or 0x1D431 + local linewidth = parameters.xheight / 10 + local basewidth = basechar.width + local baseheight = basechar.height + return { + -- todo: add alttext + -- compromise: lm has large hooks e.g. \actuarial{a} + width = basewidth + 4 * linewidth, + unicode = 0x20E7, + commands = { + { "right", 2 * linewidth }, + { "down", - baseheight - 3 * linewidth }, + { "rule", linewidth, basewidth + 4 * linewidth }, + { "right", -linewidth }, + { "down", baseheight + 4 * linewidth }, + { "rule", baseheight + 5 * linewidth, linewidth }, + }, + } +end + +virtualcharacters[0x020E7] = actuarian -- checked +virtualcharacters[0xFE940] = actuarian -- unchecked |