summaryrefslogtreecommitdiff
path: root/tex/context/base/font-fbk.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/font-fbk.lua')
-rw-r--r--tex/context/base/font-fbk.lua316
1 files changed, 316 insertions, 0 deletions
diff --git a/tex/context/base/font-fbk.lua b/tex/context/base/font-fbk.lua
new file mode 100644
index 000000000..1ad1cc781
--- /dev/null
+++ b/tex/context/base/font-fbk.lua
@@ -0,0 +1,316 @@
+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--
+<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
+
+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" },
+})