diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/math-vfu.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/math-vfu.lua | 485 |
1 files changed, 316 insertions, 169 deletions
diff --git a/Master/texmf-dist/tex/context/base/math-vfu.lua b/Master/texmf-dist/tex/context/base/math-vfu.lua index 2f7c0507ba9..6d9a9f903bc 100644 --- a/Master/texmf-dist/tex/context/base/math-vfu.lua +++ b/Master/texmf-dist/tex/context/base/math-vfu.lua @@ -26,6 +26,7 @@ local type, next = type, next local max = math.max local format = string.format local utfchar = utf.char +local fastcopy = table.copy local fonts, nodes, mathematics = fonts, nodes, mathematics @@ -38,6 +39,7 @@ local report_virtual = logs.reporter("fonts","virtual math") local allocate = utilities.storage.allocate local setmetatableindex = table.setmetatableindex +local formatters = string.formatters local mathencodings = allocate() fonts.encodings.math = mathencodings -- better is then: fonts.encodings.vectors @@ -199,21 +201,44 @@ end -- { "node", nodeinjections.transform(.7,0,0,.7) }, -- commands[#commands+1] = { "node", nodeinjections.restore() } -local done = { } +-- local done = { } +-- +-- local function raise(main,characters,id,size,unicode,private,n,id_of_smaller) -- this is a real fake mess +-- local raised = characters[private] +-- if raised then +-- if not done[unicode] then +-- report_virtual("temporary too large %U 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 raise(main,characters,id,size,unicode,private,n) -- this is a real fake mess - local raised = characters[private] +local function raise(main,characters,id,size,unicode,private,n,id_of_smaller) -- this is a real fake mess + local raised = fonts.hashes.characters[main.fonts[id_of_smaller].id][private] -- characters[private] if raised then - if not done[unicode] then - report_virtual("temporary too large %U 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 slot = { "slot", id_of_smaller, private } local commands = { push, { "down", - up }, - -- { "scale", .7, 0, 0, .7 }, slot, } for i=2,n do @@ -221,9 +246,10 @@ local function raise(main,characters,id,size,unicode,private,n) -- this is a rea end commands[#commands+1] = pop characters[unicode] = { - width = .7 * n * raised.width, - height = .7 * (raised.height + up), - depth = .7 * (raised.depth - up), + width = n * raised.width, + height = (raised.height or 0) + up, + depth = (raised.depth or 0) - up, + italic = raised.italic, commands = commands, } end @@ -406,7 +432,25 @@ local function repeated(main,characters,id,size,unicode,u,n,private,fraction) -- end end +-- we use the fact that context defines the smallest sizes first .. a real dirty and ugly hack + +local data_of_smaller = nil +local size_of_smaller = 0 + function vfmath.addmissing(main,id,size) + + local id_of_smaller = nil + + if size < size_of_smaller or size_of_smaller == 0 then + data_of_smaller = main.fonts[id] + id_of_smaller = id + else + id_of_smaller = #main.fonts + 1 + main.fonts[id_of_smaller] = data_of_smaller + end + + -- here id is the index in fonts (normally 14 or so) and that slot points to self + local characters = main.characters local shared = main.shared local variables = main.goodies.mathematics and main.goodies.mathematics.variables or { } @@ -504,9 +548,11 @@ function vfmath.addmissing(main,id,size) repeated(main,characters,id,size,0x222C,0x222B,2,0xFF800,1/3) repeated(main,characters,id,size,0x222D,0x222B,3,0xFF810,1/3) - -- 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 + characters[0xFE325] = fastcopy(characters[0x2032]) + + raise (main,characters,id,size,0x02032,0xFE325,1,id_of_smaller) -- prime + raise (main,characters,id,size,0x02033,0xFE325,2,id_of_smaller) -- double prime + raise (main,characters,id,size,0x02034,0xFE325,3,id_of_smaller) -- triple prime -- there are more (needs discussion first): @@ -515,6 +561,9 @@ function vfmath.addmissing(main,id,size) characters[0x02B9] = characters[0x2032] -- we're nice + data_of_smaller = main.fonts[id] + size_of_smaller = size + end local unique = 0 -- testcase: \startTEXpage \math{!\text{-}\text{-}\text{-}} \stopTEXpage @@ -534,6 +583,82 @@ setmetatableindex(reverse, function(t,name) return r end) +local function copy_glyph(main,target,original,unicode,slot) + local addprivate = fonts.helpers.addprivate + local olddata = original[unicode] + if olddata then + local newdata = { + width = olddata.width, + height = olddata.height, + depth = olddata.depth, + italic = olddata.italic, + kerns = olddata.kerns, + commands = { { "slot", slot, unicode } }, + } + local glyphdata = newdata + local nextglyph = olddata.next + while nextglyph do + local oldnextdata = original[nextglyph] + local newnextdata = { + commands = { { "slot", slot, nextglyph } }, + width = oldnextdata.width, + height = oldnextdata.height, + depth = oldnextdata.depth, + } + local newnextglyph = addprivate(main,formatters["M-N-%H"](nextglyph),newnextdata) + newdata.next = newnextglyph +-- report_virtual("copied next: %X",newdata.next) + local nextnextglyph = oldnextdata.next + if nextnextglyph == nextglyph then + break + else + olddata = oldnextdata + newdata = newnextdata + nextglyph = nextnextglyph + 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 = original[oldglyph] + local newdata = { + commands = { { "slot", slot, oldglyph } }, + width = olddata.width, + height = olddata.height, + depth = olddata.depth, + } + hvi.glyph = addprivate(main,formatters["M-H-%H"](oldglyph),newdata) +-- report_virtual("copied h variant: %X at index %i",hvi.glyph,i) + end + end + local vv = olddata.vert_variants + if vv then + vv = fastcopy(vv) + newdata.vert_variants = vv + for i=1,#vv do + local vvi = vv[i] + local oldglyph = vvi.glyph + local olddata = original[oldglyph] + local newdata = { + commands = { { "slot", slot, oldglyph } }, + width = olddata.width, + height = olddata.height, + depth = olddata.depth, + } + vvi.glyph = addprivate(main,formatters["M-V-%H"](oldglyph),newdata) +-- report_virtual("copied v variant: %X at index %i",vvi.glyph,i) + end + end + return newdata + end +end + +vfmath.copy_glyph = copy_glyph + function vfmath.define(specification,set,goodies) local name = specification.name -- symbolic name local size = specification.size -- given size @@ -576,7 +701,7 @@ function vfmath.define(specification,set,goodies) shared[n] = { } end if trace_virtual then - report_virtual("loading font %a subfont %s with name %a at %p as id %s using encoding %p",name,s,ssname,size,id,ss.vector) + report_virtual("loading font %a subfont %s with name %a at %p as id %s using encoding %a",name,s,ssname,size,id,ss.vector) end if not ss.checked then ss.checked = true @@ -677,6 +802,7 @@ function vfmath.define(specification,set,goodies) parameters.x_height = parameters.x_height or 0 -- local already_reported = false + local parameters_done = false for s=1,n do local ss, fs = okset[s], loaded[s] if not fs then @@ -685,7 +811,13 @@ function vfmath.define(specification,set,goodies) -- skip, redundant else local newparameters = fs.parameters - if not newparameters then + local newmathparameters = fs.mathparameters + if newmathparameters then + if not parameters_done or ss.parameters then + mathparameters = newmathparameters + parameters_done = true + end + elseif not newparameters then report_virtual("no parameters set in font %a",name) elseif ss.extension then mathparameters.math_x_height = newparameters.x_height or 0 -- math_x_height : height of x @@ -716,187 +848,202 @@ function vfmath.define(specification,set,goodies) mathparameters.axis_height = newparameters[22] or 0 -- axis_height : height of fraction lines above the baseline -- report_virtual("loading and virtualizing font %a at size %p, 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 slot %U has no index %H in vector %a for font %a",unicode,index,vectorname,fontname) - elseif not already_reported then - report_virtual("the mapping is incomplete for %a at %p",name,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 italic > 0 then - -- int_a^b - if isextension then - width = width + italic -- for obscure reasons the integral as a width + italic correction - end - 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 + if ss.overlay then + local fc = fs.characters + local first = ss.first + if first then + local last = ss.last or first + for unicode = first, last do + characters[unicode] = copy_glyph(main,characters,fc,unicode,s) + end + else + for unicode, data in next, fc do + characters[unicode] = copy_glyph(main,characters,fc,unicode,s) + end + end + else + 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 slot %U has no index %H in vector %a for font %a",unicode,index,vectorname,fontname) + elseif not already_reported then + report_virtual("the mapping is incomplete for %a at %p",name,size) + already_reported = true end + rv[unicode] = true end - characters[unicode] = t else - characters[unicode] = { - width = width, - height = fci.height, - depth = fci.depth, - italic = italic, - commands = ref, - } - end - 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 kerns = fci.kerns + local width = fci.width local italic = fci.italic - local t = { - width = fci.width, - 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 + if italic and italic > 0 then + -- int_a^b + if isextension then + width = width + italic -- for obscure reasons the integral as a width + italic correction 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 + 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 - 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 + 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 - t.horiz_variants = hv end + characters[unicode] = t + else + characters[unicode] = { + width = width, + height = fci.height, + depth = fci.depth, + italic = italic, + commands = ref, + } 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 + 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 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 + local italic = fci.italic + local t = { + width = fci.width, + 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 - 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, - } + 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 %a, problematic vector %a",name,vectorname) end - else - report_virtual("error in loading %a, problematic vector %a",name,vectorname) end end mathematics.extras.copy(main) --not needed here (yet) |