if not modules then modules = { } end modules ['font-fbk'] = { version = 1.001, comment = "companion to font-ini.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" } local cos, tan, rad, format = math.cos, math.tan, math.rad, string.format local trace_combining = false trackers.register("fonts.combining", function(v) trace_combining = v end) --[[ldx--

This is very experimental code!

--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 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 vf.aux.combine.force_fallback = false 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 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 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 -- maybe store llx etc instead of bbox in tfm blob / more efficient vf.aux.combine.force_composed = false local push, pop = { "push" }, { "pop" } local cache = { } -- we could make these weak function vf.aux.compose_characters(g) -- todo: scaling depends on call location -- 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 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 } end local done = false for i,c in next, characters.data do if force or not chars[i] then local s = c.specials if s and s[1] == 'char' then local chr = s[2] local charschr = chars[chr] if charschr then local cc = c.category if cc == 'll' or cc == 'lu' or cc == 'lt' then local acc = s[3] local t = { } for k, v in next, charschr do if k ~= "commands" then 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] end if charsacc then local chr_t = cache[chr] if not cht_t then chr_t = {"slot", 1, chr} cache[chr] = chr_t 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 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 if a_ury < 0 then if trace_combining then 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 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, } else 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, } else t.commands = { {"push"}, {"right", dx+dd}, acc_t, {"pop"}, chr_t, } end end done = true end end chars[i] = t local d = { } for k, v in next, descs[chr] do d[k] = v end d.name = c.adobename or "unknown" -- d.unicode = i descs[i] = d end end end end end if done then g.virtualized = true end end end vf.aux.combine.commands["complete-composed-characters"] = function(g,v) vf.aux.compose_characters(g) 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'}, -- for documentation purposes we provide: fonts.define.methods.install("fallback", { -- todo: auto-fallback with loop over data.characters { "fake-character", 0x00A2, 'textcent' }, { "fake-character", 0x20AC, 'texteuro' } }) vf.aux.combine.commands["enable-force"] = function(g,v) vf.aux.combine.force_composed = true vf.aux.combine.force_fallback = true end vf.aux.combine.commands["disable-force"] = function(g,v) vf.aux.combine.force_composed = false vf.aux.combine.force_fallback = false end fonts.define.methods.install("demo-2", { { "enable-tracing" }, { "enable-force" }, { "initialize" }, { "include-method", "fallback" }, { "complete-composed-characters" }, { "disable-tracing" }, { "disable-force" }, }) fonts.define.methods.install("demo-3", { { "enable-tracing" }, { "initialize" }, { "complete-composed-characters" }, { "disable-tracing" }, })