diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/font-fbk.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/font-fbk.lua | 402 |
1 files changed, 172 insertions, 230 deletions
diff --git a/Master/texmf-dist/tex/context/base/font-fbk.lua b/Master/texmf-dist/tex/context/base/font-fbk.lua index 1ad1cc781a8..6712fbe888e 100644 --- a/Master/texmf-dist/tex/context/base/font-fbk.lua +++ b/Master/texmf-dist/tex/context/base/font-fbk.lua @@ -7,146 +7,79 @@ if not modules then modules = { } end modules ['font-fbk'] = { } local cos, tan, rad, format = math.cos, math.tan, math.rad, string.format +local utfbyte, utfchar = utf.byte, utf.char -local trace_combining = false trackers.register("fonts.combining", function(v) trace_combining = v end) +local trace_combining = false trackers.register("fonts.combining", function(v) trace_combining = v end) +local trace_combining_all = false trackers.register("fonts.combining.all", function(v) trace_combining_all = v end) ---[[ldx-- -<p>This is very experimental code!</p> ---ldx]]-- - -fonts.fallbacks = fonts.fallbacks or { } - -local vf = fonts.vf -local tfm = fonts.tfm - -vf.aux.combine.commands["enable-tracing"] = function(g,v) - trace_combining = true -end - -vf.aux.combine.commands["disable-tracing"] = function(g,v) - trace_combining = false -end - -vf.aux.combine.commands["set-tracing"] = function(g,v) - if v[2] == nil then - trace_combining = true - else - trace_combining = v[2] - end -end +local force_combining = false -- just for demo purposes (see mk) -function vf.aux.combine.initialize_trace() - if trace_combining then - return "special", "pdf: .8 0 0 rg .8 0 0 RG", "pdf: 0 .8 0 rg 0 .8 0 RG", "pdf: 0 0 .8 rg 0 0 .8 RG", "pdf: 0 g 0 G" - else - return "comment", "", "", "", "" - end -end +trackers.register("fonts.composing", "fonts.combining") -vf.aux.combine.force_fallback = false +local report_combining = logs.reporter("fonts","combining") -vf.aux.combine.commands["fake-character"] = function(g,v) -- g, nr, fallback_id - local index, fallback = v[2], v[3] - if vf.aux.combine.force_fallback or not g.characters[index] then - if fonts.fallbacks[fallback] then - g.characters[index], g.descriptions[index] = fonts.fallbacks[fallback](g) - end - end -end +local allocate = utilities.storage.allocate -fonts.fallbacks['textcent'] = function (g) - local c = ("c"):byte() - local t = table.fastcopy(g.characters[c]) - local a = - tan(rad(g.italicangle or 0)) - local special, red, green, blue, black = vf.aux.combine.initialize_trace() - local quad = g.parameters.quad - if a == 0 then - t.commands = { - {"push"}, {"slot", 1, c}, {"pop"}, - {"right", .5*t.width}, - {"down", .2*t.height}, - {special, green}, - {"rule", 1.4*t.height, .02*quad}, - {special, black}, - } - else - t.commands = { - {"push"}, - {"right", .5*t.width-.025*quad}, - {"down", .2*t.height}, - {"special",format("pdf: q 1 0 %s 1 0 0 cm",a)}, - {special, green}, - {"rule", 1.4*t.height, .025*quad}, - {special, black}, - {"special","pdf: Q"}, - {"pop"}, - {"slot", 1, c} -- last else problems with cm - } - end - -- somehow the width is messed up now - -- todo: set height - t.height = 1.2*t.height - t.depth = 0.2*t.height - g.virtualized = true - local d = g.descriptions - return t, d and d[c] -end +--[[ldx-- +<p>This is very experimental code!</p> +--ldx]]-- -fonts.fallbacks['texteuro'] = function (g) - local c = ("C"):byte() - local t = table.fastcopy(g.characters[c]) - local d = cos(rad(90+(g.italicangle))) - local special, red, green, blue, black = vf.aux.combine.initialize_trace() - local quad = g.parameters.quad - t.width = 1.05*t.width - t.commands = { - {"right", .05*t.width}, - {"push"}, {"slot", 1, c}, {"pop"}, - {"right", .5*t.width*d}, - {"down", -.5*t.height}, - {special, green}, - {"rule", .05*quad, .4*quad}, - {special, black}, - } - g.virtualized = true - return t, g.descriptions[c] -end +local fonts = fonts +local handlers = fonts.handlers +local constructors = fonts.constructors +local vf = handlers.vf +local commands = vf.combiner.commands --- maybe store llx etc instead of bbox in tfm blob / more efficient +local otffeatures = constructors.newfeatures("otf") +local registerotffeature = otffeatures.register -vf.aux.combine.force_composed = false +local afmfeatures = constructors.newfeatures("afm") +local registerafmfeature = afmfeatures.register -local push, pop = { "push" }, { "pop" } +local unicodecharacters = characters.data +local unicodefallbacks = characters.fallbacks -local cache = { } -- we could make these weak +local push = vf.predefined.push +local pop = vf.predefined.pop +local force_composed = false +local cache = { } -- we could make these weak +local fraction = 0.15 -- 30 units for lucida -function vf.aux.compose_characters(g) -- todo: scaling depends on call location +local function composecharacters(tfmdata) -- this assumes that slot 1 is self, there will be a proper self some day - local chars, descs = g.characters, g.descriptions - local X = ("X"):byte() - local xchar = chars[X] - local xdesc = descs[X] - if xchar and xdesc then - local scale = g.factor or 1 - local cap_lly = scale*xdesc.boundingbox[4] - local ita_cor = cos(rad(90+(g.italicangle or 0))) - local force = vf.aux.combine.force_composed - local fallbacks = characters.fallbacks - local special, red, green, blue, black + local characters = tfmdata.characters + local descriptions = tfmdata.descriptions + local parameters = tfmdata.parameters + local properties = tfmdata.properties + local Xdesc = descriptions[utfbyte("X")] + local xdesc = descriptions[utfbyte("x")] + if Xdesc and xdesc then + local scale = parameters.factor or 1 + local deltaxheight = scale * (Xdesc.boundingbox[4] - xdesc.boundingbox[4]) + local extraxheight = fraction * deltaxheight -- maybe use compose value + local italicfactor = parameters.italicfactor or 0 + local vfspecials = backends.tables.vfspecials --brr + local red, green, blue, black if trace_combining then - special, red, green, blue, black = vf.aux.combine.initialize_trace() - red, green, blue, black = { special, red }, { special, green }, { special, blue }, { special, black } + red = vfspecials.red + green = vfspecials.green + blue = vfspecials.blue + black = vfspecials.black + end + local compose = fonts.goodies.getcompositions(tfmdata) + if compose and trace_combining then + report_combining("using compose information from goodies file") end local done = false - for i,c in next, characters.data do - if force or not chars[i] then + for i,c in next, unicodecharacters do -- loop over all characters ... not that efficient but a specials hash takes memory + if force_combining or not characters[i] then local s = c.specials if s and s[1] == 'char' then local chr = s[2] - local charschr = chars[chr] + local charschr = characters[chr] if charschr then local cc = c.category - if cc == 'll' or cc == 'lu' or cc == 'lt' then + if cc == 'll' or cc == 'lu' or cc == 'lt' then -- characters.is_letter[cc] local acc = s[3] local t = { } for k, v in next, charschr do @@ -154,163 +87,172 @@ function vf.aux.compose_characters(g) -- todo: scaling depends on call location t[k] = v end end - local charsacc = chars[acc] ---~ local ca = charsacc.category ---~ if ca == "mn" then ---~ -- mark nonspacing ---~ elseif ca == "ms" then ---~ -- mark spacing combining ---~ elseif ca == "me" then ---~ -- mark enclosing ---~ else - if not charsacc then - acc = fallbacks[acc] - charsacc = acc and chars[acc] + local charsacc = characters[acc] + --~ local ca = charsacc.category + --~ if ca == "mn" then + --~ -- mark nonspacing + --~ elseif ca == "ms" then + --~ -- mark spacing combining + --~ elseif ca == "me" then + --~ -- mark enclosing + --~ else + if not charsacc then -- fallback accents + acc = unicodefallbacks[acc] + charsacc = acc and characters[acc] + end + local chr_t = cache[chr] + if not chr_t then + chr_t = {"slot", 1, chr} + cache[chr] = chr_t end if charsacc then - local chr_t = cache[chr] - if not cht_t then - chr_t = {"slot", 1, chr} - cache[chr] = chr_t + if trace_combining_all then + report_combining("%s (U+%05X) = %s (U+%05X) + %s (U+%05X)",utfchar(i),i,utfchar(chr),chr,utfchar(acc),acc) end local acc_t = cache[acc] if not acc_t then acc_t = {"slot", 1, acc} cache[acc] = acc_t end - local cb = descs[chr].boundingbox - local ab = descs[acc].boundingbox + local cb = descriptions[chr].boundingbox + local ab = descriptions[acc].boundingbox + -- todo: adapt height if cb and ab then -- can be sped up for scale == 1 local c_llx, c_lly, c_urx, c_ury = scale*cb[1], scale*cb[2], scale*cb[3], scale*cb[4] local a_llx, a_lly, a_urx, a_ury = scale*ab[1], scale*ab[2], scale*ab[3], scale*ab[4] local dx = (c_urx - a_urx - a_llx + c_llx)/2 - local dd = (c_urx - c_llx)*ita_cor + local dd = (c_urx - c_llx)*italicfactor if a_ury < 0 then if trace_combining then - t.commands = { - push, - {"right", dx-dd}, - red, - acc_t, - black, - pop, - chr_t, - } + t.commands = { push, {"right", dx-dd}, red, acc_t, black, pop, chr_t } + else + t.commands = { push, {"right", dx-dd}, acc_t, pop, chr_t } + end + elseif c_ury > a_lly then -- messy test + local dy + if compose then + -- experimental: we could use sx but all that testing + -- takes time and code + dy = compose[i] + if dy then + dy = dy.DY + end + if not dy then + dy = compose[acc] + if dy then + dy = dy and dy.DY + end + end + if not dy then + dy = compose.DY + end + if not dy then + dy = - deltaxheight + extraxheight + elseif dy > -1.5 and dy < 1.5 then + -- we assume a fraction of (percentage) + dy = - dy * deltaxheight + else + -- we assume fontunits (value smaller than 2 make no sense) + dy = - dy * scale + end else - t.commands = { - push, - {"right", dx-dd}, - acc_t, - pop, - chr_t, - } + dy = - deltaxheight + extraxheight end - elseif c_ury > a_lly then - local dy = cap_lly-a_lly if trace_combining then - t.commands = { - push, - {"right", dx+dd}, - {"down", -dy}, - green, - acc_t, - black, - pop, - chr_t, - } + t.commands = { push, {"right", dx+dd}, {"down", dy}, green, acc_t, black, pop, chr_t } else - t.commands = { - push, - {"right", dx+dd}, - {"down", -dy}, - acc_t, - pop, - chr_t, - } + t.commands = { push, {"right", dx+dd}, {"down", dy}, acc_t, pop, chr_t } end else if trace_combining then - t.commands = { - {"push"}, - {"right", dx+dd}, - blue, - acc_t, - black, - {"pop"}, - chr_t, - } + t.commands = { push, {"right", dx+dd}, blue, acc_t, black, pop, chr_t } else - t.commands = { - {"push"}, - {"right", dx+dd}, - acc_t, - {"pop"}, - chr_t, - } + t.commands = { push, {"right", dx+dd}, acc_t, pop, chr_t } end end - done = true + else + t.commands = { chr_t } -- else index mess + end + else + if trace_combining_all then + report_combining("%s (U+%05X) = %s (U+%05X) (simplified)",utfchar(i),i,utfchar(chr),chr) end + t.commands = { chr_t } -- else index mess end - chars[i] = t + done = true + characters[i] = t local d = { } - for k, v in next, descs[chr] do + for k, v in next, descriptions[chr] do d[k] = v end - d.name = c.adobename or "unknown" - -- d.unicode = i - descs[i] = d + descriptions[i] = d end end end end end if done then - g.virtualized = true + properties.virtualized = true end end end -vf.aux.combine.commands["complete-composed-characters"] = function(g,v) - vf.aux.compose_characters(g) +registerotffeature { + name = "compose", + description = "additional composed characters", + manipulators = { + base = composecharacters, + node = composecharacters, + } +} + +registerafmfeature { + name = "compose", + description = "additional composed characters", + manipulators = { + base = composecharacters, + node = composecharacters, + } +} + +vf.helpers.composecharacters = composecharacters + +-- This installs the builder into the regular virtual font builder, +-- which only makes sense as demo. + +commands["compose.trace.enable"] = function() + trace_combining = true end ---~ {'special', 'pdf: q ' .. s .. ' 0 0 '.. s .. ' 0 0 cm'}, ---~ {'special', 'pdf: q 1 0 0 1 ' .. -w .. ' ' .. -h .. ' cm'}, ---~ -- {'special', 'pdf: /Fm\XX\space Do'}, ---~ {'special', 'pdf: Q'}, ---~ {'special', 'pdf: Q'}, +commands["compose.trace.disable"] = function() + trace_combining = false +end --- for documentation purposes we provide: +commands["compose.force.enable"] = function() + force_combining = true +end -fonts.define.methods.install("fallback", { -- todo: auto-fallback with loop over data.characters - { "fake-character", 0x00A2, 'textcent' }, - { "fake-character", 0x20AC, 'texteuro' } -}) +commands["compose.force.disable"] = function() + force_combining = false +end -vf.aux.combine.commands["enable-force"] = function(g,v) - vf.aux.combine.force_composed = true - vf.aux.combine.force_fallback = true +commands["compose.trace.set"] = function(g,v) + if v[2] == nil then + trace_combining = true + else + trace_combining = v[2] + end end -vf.aux.combine.commands["disable-force"] = function(g,v) - vf.aux.combine.force_composed = false - vf.aux.combine.force_fallback = false + +commands["compose.apply"] = function(g,v) + composecharacters(g) end -fonts.define.methods.install("demo-2", { - { "enable-tracing" }, - { "enable-force" }, - { "initialize" }, - { "include-method", "fallback" }, - { "complete-composed-characters" }, - { "disable-tracing" }, - { "disable-force" }, -}) +-- vf builder -fonts.define.methods.install("demo-3", { - { "enable-tracing" }, - { "initialize" }, - { "complete-composed-characters" }, - { "disable-tracing" }, -}) +-- {'special', 'pdf: q ' .. s .. ' 0 0 '.. s .. ' 0 0 cm'}, +-- {'special', 'pdf: q 1 0 0 1 ' .. -w .. ' ' .. -h .. ' cm'}, +-- {'special', 'pdf: /Fm\XX\space Do'}, +-- {'special', 'pdf: Q'}, +-- {'special', 'pdf: Q'}, |