summaryrefslogtreecommitdiff
path: root/tex/context/base/font-otf.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/font-otf.lua')
-rw-r--r--tex/context/base/font-otf.lua1293
1 files changed, 777 insertions, 516 deletions
diff --git a/tex/context/base/font-otf.lua b/tex/context/base/font-otf.lua
index 5c0db392d..196e155dc 100644
--- a/tex/context/base/font-otf.lua
+++ b/tex/context/base/font-otf.lua
@@ -1,4 +1,4 @@
- if not modules then modules = { } end modules ['font-otf'] = {
+if not modules then modules = { } end modules ['font-otf'] = {
version = 1.001,
comment = "companion to font-ini.tex",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -8,6 +8,16 @@
-- once we have all features working, i will redo this module .. caching lookups and such
+local format = string.format
+
+local space = lpeg.P(" ")
+local nospaces = (1-space)^1
+local optionalspace = space^0
+
+local split_at_space = lpeg.Ct((lpeg.C(nospaces) * optionalspace)^0)
+
+-- we can use more lpegs when lpeg is extended with function args and so
+
-- the flattening code is a prelude to a more compact table format (so, we're now
-- at the fourth version); maybe we will go unicode, although that will mean that we
-- miss some glyphs (unicode -1)
@@ -20,7 +30,7 @@
-- todo: pack ignoreflags
-- abvf abvs blwf blws dist falt half halt jalt lfbd ljmo
--- mset opbd palt pwid qwid rand rtbd rtla ruby size tjmo twid valt vatu vert
+-- mset opbd palt pwid qwid rand rtbd ruby size tjmo twid valt vatu vert
-- vhal vjmo vkna vkrn vpal vrt2
-- The specification of OpenType is vague, very vague. Apart from a lack of proper
@@ -88,42 +98,46 @@ number by one when there's a fix in the <l n='fontforge'/> library or
fonts = fonts or { }
fonts.otf = fonts.otf or { }
-fonts.otf.version = 2.09
-fonts.otf.pack = true
-fonts.otf.tables = fonts.otf.tables or { }
-fonts.otf.meanings = fonts.otf.meanings or { }
-fonts.otf.enhance_data = false
-fonts.otf.syncspace = true
-fonts.otf.features = { }
-fonts.otf.features.aux = { }
-fonts.otf.features.data = { }
-fonts.otf.features.list = { } -- not (yet) used, oft fonts have gpos/gsub lists
-fonts.otf.features.default = { }
-fonts.otf.trace_features = false
-fonts.otf.trace_set_features = false
-fonts.otf.trace_replacements = false
-fonts.otf.trace_contexts = false
-fonts.otf.trace_anchors = false
-fonts.otf.trace_ligatures = false
-fonts.otf.trace_kerns = false
-fonts.otf.trace_cursive = false
-fonts.otf.notdef = false
-fonts.otf.cache = containers.define("fonts", "otf", fonts.otf.version, true)
-
-function fonts.otf.trace_process()
- fonts.otf.trace_replacements = true
- fonts.otf.trace_contexts = true
- fonts.otf.trace_anchors = true
- fonts.otf.trace_ligatures = true
- fonts.otf.trace_kerns = true
- fonts.otf.trace_cursive = true
+
+local otf = fonts.otf
+local tfm = fonts.tfm
+
+otf.version = 2.10
+otf.pack = true
+otf.tables = otf.tables or { }
+otf.meanings = otf.meanings or { }
+otf.enhance_data = false
+otf.syncspace = true
+otf.features = { }
+otf.features.aux = { }
+otf.features.data = { }
+otf.features.list = { } -- not (yet) used, oft fonts have gpos/gsub lists
+otf.features.default = { }
+otf.trace_features = false
+otf.trace_set_features = false
+otf.trace_replacements = false
+otf.trace_contexts = false
+otf.trace_anchors = false
+otf.trace_ligatures = false
+otf.trace_kerns = false
+otf.trace_cursive = false
+otf.notdef = false
+otf.cache = containers.define("fonts", "otf", otf.version, true)
+
+function otf.trace_process()
+ otf.trace_replacements = true
+ otf.trace_contexts = true
+ otf.trace_anchors = true
+ otf.trace_ligatures = true
+ otf.trace_kerns = true
+ otf.trace_cursive = true
end
--[[ldx--
<p>We start with a lot of tables and related functions.</p>
--ldx]]--
-fonts.otf.tables.scripts = {
+otf.tables.scripts = {
['dflt'] = 'Default',
['arab'] = 'Arabic',
@@ -196,7 +210,7 @@ fonts.otf.tables.scripts = {
['yi' ] = 'Yi'
}
-fonts.otf.tables.languages = {
+otf.tables.languages = {
['dflt'] = 'Default',
['aba'] = 'Abaza',
@@ -590,7 +604,7 @@ fonts.otf.tables.languages = {
['zul'] = 'Zulu'
}
-fonts.otf.tables.features = {
+otf.tables.features = {
['aalt'] = 'Access All Alternates',
['abvf'] = 'Above-Base Forms',
['abvm'] = 'Above-Base Mark Positioning',
@@ -721,7 +735,7 @@ fonts.otf.tables.features = {
['zero'] = 'Slashed Zero'
}
-fonts.otf.tables.baselines = {
+otf.tables.baselines = {
['hang'] = 'Hanging baseline',
['icfb'] = 'Ideographic character face bottom edge baseline',
['icft'] = 'Ideographic character face tope edige baseline',
@@ -731,11 +745,11 @@ fonts.otf.tables.baselines = {
['romn'] = 'Roman baseline'
}
-function fonts.otf.tables.to_tag(id)
+function otf.tables.to_tag(id)
return stringformat("%4s",id:lower())
end
-function fonts.otf.meanings.resolve(tab,id)
+function otf.meanings.resolve(tab,id)
if tab and id then
id = id:lower()
return tab[id] or tab[id:gsub(" ","")] or tab['dflt'] or ''
@@ -744,34 +758,34 @@ function fonts.otf.meanings.resolve(tab,id)
end
end
-function fonts.otf.meanings.script(id)
- return fonts.otf.meanings.resolve(fonts.otf.tables.scripts,id)
+function otf.meanings.script(id)
+ return otf.meanings.resolve(otf.tables.scripts,id)
end
-function fonts.otf.meanings.language(id)
- return fonts.otf.meanings.resolve(fonts.otf.tables.languages,id)
+function otf.meanings.language(id)
+ return otf.meanings.resolve(otf.tables.languages,id)
end
-function fonts.otf.meanings.feature(id)
- return fonts.otf.meanings.resolve(fonts.otf.tables.features,id)
+function otf.meanings.feature(id)
+ return otf.meanings.resolve(otf.tables.features,id)
end
-function fonts.otf.meanings.baseline(id)
- return fonts.otf.meanings.resolve(fonts.otf.tables.baselines,id)
+function otf.meanings.baseline(id)
+ return otf.meanings.resolve(otf.tables.baselines,id)
end
-fonts.otf.tables.to_scripts = table.reverse_hash(fonts.otf.tables.scripts )
-fonts.otf.tables.to_languages = table.reverse_hash(fonts.otf.tables.languages)
-fonts.otf.tables.to_features = table.reverse_hash(fonts.otf.tables.features )
+otf.tables.to_scripts = table.reverse_hash(otf.tables.scripts )
+otf.tables.to_languages = table.reverse_hash(otf.tables.languages)
+otf.tables.to_features = table.reverse_hash(otf.tables.features )
do
- local scripts = fonts.otf.tables.scripts
- local languages = fonts.otf.tables.languages
- local features = fonts.otf.tables.features
+ local scripts = otf.tables.scripts
+ local languages = otf.tables.languages
+ local features = otf.tables.features
- local to_scripts = fonts.otf.tables.to_scripts
- local to_languages = fonts.otf.tables.to_languages
- local to_features = fonts.otf.tables.to_features
+ local to_scripts = otf.tables.to_scripts
+ local to_languages = otf.tables.to_languages
+ local to_features = otf.tables.to_features
- function fonts.otf.meanings.normalize(features)
+ function otf.meanings.normalize(features)
local h = { }
for k,v in pairs(features) do
k = k:lower() -- :gsub("[^a-z0-9%-%.]" -- not needed
@@ -811,14 +825,14 @@ end
<p>Here we go.</p>
--ldx]]--
-fonts.otf.enhance = fonts.otf.enhance or { }
-fonts.otf.enhance.add_kerns = true
+otf.enhance = otf.enhance or { }
+otf.enhance.add_kerns = true
-fonts.otf.featurefiles = {
+otf.featurefiles = {
--~ "texhistoric.fea"
}
-function fonts.otf.load(filename,format,sub,featurefile)
+function otf.load(filename,format,sub,featurefile)
local name = file.basename(file.removesuffix(filename))
if featurefile then
name = name .. "@" .. file.removesuffix(file.basename(featurefile))
@@ -830,13 +844,13 @@ function fonts.otf.load(filename,format,sub,featurefile)
hash = hash:lower()
hash = hash:gsub("[^%w%d]+","-")
end
- local data = containers.read(fonts.otf.cache(), hash)
+ local data = containers.read(otf.cache(), hash)
local size = lfs.attributes(filename,"size") or 0
if data and data.size ~= size then
data = nil
end
if not data then
- logs.report("load otf","loading: " .. filename)
+ logs.report("load otf","loading: %s",filename)
local ff, messages
if sub then
ff, messages = fontforge.open(filename,sub)
@@ -845,20 +859,20 @@ function fonts.otf.load(filename,format,sub,featurefile)
end
if messages and #messages > 0 then
for _, m in ipairs(messages) do
- logs.report("load otf","warning: " .. m)
+ logs.report("load otf","warning: %s",m)
end
end
if ff then
local function load_featurefile(featurefile)
if featurefile then
- featurefile = input.find_file(texmf.instance,file.addsuffix(featurefile,'fea')) -- "FONTFEATURES"
+ featurefile = input.find_file(file.addsuffix(featurefile,'fea')) -- "FONTFEATURES"
if featurefile and featurefile ~= "" then
- logs.report("load otf", "featurefile: " .. featurefile)
+ logs.report("load otf", "featurefile: %s", featurefile)
fontforge.apply_featurefile(ff, featurefile)
end
end
end
- -- for _, featurefile in pairs(fonts.otf.featurefiles) do
+ -- for _, featurefile in pairs(otf.featurefiles) do
-- load_featurefile(featurefile)
-- end
load_featurefile(featurefile)
@@ -866,41 +880,41 @@ function fonts.otf.load(filename,format,sub,featurefile)
fontforge.close(ff)
if data then
logs.report("load otf","enhance: before")
- fonts.otf.enhance.before(data,filename)
+ otf.enhance.before(data,filename)
logs.report("load otf","enhance: enrich")
- fonts.otf.enhance.enrich(data,filename)
+ otf.enhance.enrich(data,filename)
logs.report("load otf","enhance: flatten")
- fonts.otf.enhance.flatten(data,filename)
+ otf.enhance.flatten(data,filename)
logs.report("load otf","enhance: analyze")
- fonts.otf.enhance.analyze(data,filename)
+ otf.enhance.analyze(data,filename)
logs.report("load otf","enhance: after")
- fonts.otf.enhance.after(data,filename)
+ otf.enhance.after(data,filename)
logs.report("load otf","enhance: patch")
- fonts.otf.enhance.patch(data,filename)
+ otf.enhance.patch(data,filename)
logs.report("load otf","enhance: strip")
- fonts.otf.enhance.strip(data,filename)
- if fonts.otf.pack then
+ otf.enhance.strip(data,filename)
+ if otf.pack then
logs.report("load otf","enhance: pack")
- fonts.otf.enhance.pack(data)
+ otf.enhance.pack(data)
end
- logs.report("load otf","file size: " .. size)
+ logs.report("load otf","file size: %s", size)
data.size = size
logs.report("load otf","saving: in cache")
- data = containers.write(fonts.otf.cache(), hash, data)
+ data = containers.write(otf.cache(), hash, data)
else
- logs.error("load otf","loading failed (table conversion error)")
+ logs.report("load otf","loading failed (table conversion error)")
end
else
- logs.error("load otf","loading failed (file read error)")
+ logs.report("load otf","loading failed (file read error)")
end
end
- fonts.otf.enhance.unpack(data)
+ otf.enhance.unpack(data)
return data
end
-- memory saver ..
-function fonts.otf.enhance.pack(data)
+function otf.enhance.pack(data)
if data then
local h, t = { }, { }
local concat = table.concat
@@ -928,11 +942,26 @@ function fonts.otf.enhance.pack(data)
v.boundingbox = pack(v.boundingbox)
if v.lookups then
for k,v in pairs(v.lookups) do
- for kk, vv in ipairs(v) do
+ for kk, vv in ipairs(v) do -- for i=
v[kk] = pack(vv)
end
end
end
+ if v.anchors then
+ for k,v in pairs(v.anchors) do
+ if k == "baselig" then
+ for kk, vv in pairs(v) do
+ for kkk,vvv in ipairs(vv) do
+ vv[kkk] = pack(vvv)
+ end
+ end
+ else
+ for kk, vv in pairs(v) do
+ v[kk] = pack(vv)
+ end
+ end
+ end
+ end
end
if data.lookups then
for k, v in pairs(data.lookups) do
@@ -966,7 +995,7 @@ function fonts.otf.enhance.pack(data)
end
end
-function fonts.otf.enhance.unpack(data)
+function otf.enhance.unpack(data)
if data then
local t = data.tables
if t then
@@ -980,6 +1009,20 @@ function fonts.otf.enhance.unpack(data)
end
end
end
+ local a = v.anchors
+ if a then
+ for k,v in pairs(a) do
+ for kk, vv in pairs(v) do
+ if kk == "baselig" then
+ for kkk,vvv in ipairs(vv) do
+ vv[kkk] = t[vvv]
+ end
+ else
+ v[kk] = t[vv]
+ end
+ end
+ end
+ end
end
if data.lookups then
for k, v in pairs(data.lookups) do
@@ -1015,17 +1058,17 @@ end
-- todo: normalize, design_size => designsize
-function fonts.otf.enhance.analyze(data,filename)
+function otf.enhance.analyze(data,filename)
local t = {
filename = file.basename(filename),
- version = fonts.otf.version,
+ version = otf.version,
creator = "context mkiv",
- unicodes = fonts.otf.analyze_unicodes(data),
- gposfeatures = fonts.otf.analyze_features(data.gpos),
- gsubfeatures = fonts.otf.analyze_features(data.gsub),
- marks = fonts.otf.analyze_class(data,'mark'),
+ unicodes = otf.analyze_unicodes(data),
+ gposfeatures = otf.analyze_features(data.gpos),
+ gsubfeatures = otf.analyze_features(data.gsub),
+ marks = otf.analyze_class(data,'mark'),
}
- t.subtables, t.name_to_type, t.internals, t.always_valid, t.ignore_flags, t.ctx_always = fonts.otf.analyze_subtables(data)
+ t.subtables, t.name_to_type, t.internals, t.always_valid, t.ignore_flags, t.ctx_always = otf.analyze_subtables(data)
data.luatex = t
end
@@ -1070,7 +1113,7 @@ do
named = (number * spaces * name) / do_name
}
- function fonts.otf.load_cidmap(filename) -- lpeg
+ function otf.load_cidmap(filename) -- lpeg
local data = io.loaddata(filename)
if data then
unicodes, names = { }, { }
@@ -1091,25 +1134,25 @@ do
end
-fonts.otf.cidmaps = { }
-fonts.otf.cidmax = 10
+otf.cidmaps = { }
+otf.cidmax = 10
-function fonts.otf.cidmap(registry,ordering,supplement)
+function otf.cidmap(registry,ordering,supplement)
-- cf Arthur R. we can safely scan upwards since cids are downward compatible
local template = "%s-%s-%s.cidmap"
local supplement = tonumber(supplement)
- logs.report("load otf",string.format("needed cidmap, registry: %s, ordering: %s, supplement: %s",registry,ordering,supplement))
+ logs.report("load otf","needed cidmap, registry: %s, ordering: %s, supplement: %s",registry,ordering,supplement)
local function locate(registry,ordering,supplement)
- local filename = string.format(template,registry,ordering,supplement)
- local cidmap = fonts.otf.cidmaps[filename]
+ local filename = format(template,registry,ordering,supplement)
+ local cidmap = otf.cidmaps[filename]
if not cidmap then
- logs.report("load otf",string.format("checking cidmap, registry: %s, ordering: %s, supplement: %s, filename: %s",registry,ordering,supplement,filename))
- local fullname = input.find_file(texmf.instance,filename,'cid') or ""
+ logs.report("load otf","checking cidmap, registry: %s, ordering: %s, supplement: %s, filename: %s",registry,ordering,supplement,filename)
+ local fullname = input.find_file(filename,'cid') or ""
if fullname ~= "" then
- cidmap = fonts.otf.load_cidmap(fullname)
+ cidmap = otf.load_cidmap(fullname)
if cidmap then
- logs.report("load otf",string.format("using cidmap file %s",filename))
- fonts.otf.cidmaps[filename] = cidmap
+ logs.report("load otf","using cidmap file %s",filename)
+ otf.cidmaps[filename] = cidmap
return cidmap
end
end
@@ -1120,8 +1163,8 @@ function fonts.otf.cidmap(registry,ordering,supplement)
if not cidmap then
local cidnum = nil
-- next highest (alternatively we could start high)
- if supplement < fonts.otf.cidmax then
- for supplement=supplement+1,fonts.otf.cidmax do
+ if supplement < otf.cidmax then
+ for supplement=supplement+1,otf.cidmax do
local c = locate(registry,ordering,supplement)
if c then
cidmap, cidnum = c, supplement
@@ -1142,9 +1185,9 @@ function fonts.otf.cidmap(registry,ordering,supplement)
-- prevent further lookups
if cidmap and cidnum > 0 then
for s=0,cidnum-1 do
- filename = string.format(template,registry,ordering,s)
- if not fonts.otf.cidmaps[filename] then
- fonts.otf.cidmaps[filename] = cidmap -- copy of ref
+ filename = format(template,registry,ordering,s)
+ if not otf.cidmaps[filename] then
+ otf.cidmaps[filename] = cidmap -- copy of ref
end
end
end
@@ -1159,12 +1202,12 @@ end
--~ ["version"]=6,
--~ },
-function fonts.otf.enhance.before(data,filename)
+function otf.enhance.before(data,filename)
local private = fonts.private
if data.subfonts and table.is_empty(data.glyphs) then
local cidinfo = data.cidinfo
if cidinfo.registry then
- local cidmap = fonts.otf.cidmap(cidinfo.registry,cidinfo.ordering,cidinfo.supplement)
+ local cidmap = otf.cidmap(cidinfo.registry,cidinfo.ordering,cidinfo.supplement)
if cidmap then
local glyphs, uni_to_int, int_to_uni, nofnames, nofunicodes = { }, { }, { }, 0, 0
local unicodes, names = cidmap.unicodes, cidmap.names
@@ -1191,16 +1234,16 @@ function fonts.otf.enhance.before(data,filename)
end
subfont.glyphs = nil
end
- logs.report("load otf",string.format("cid font remapped, %s unicode points, %s symbolic names, %s glyphs",nofunicodes, nofnames, nofunicodes+nofnames))
+ logs.report("load otf","cid font remapped, %s unicode points, %s symbolic names, %s glyphs",nofunicodes, nofnames, nofunicodes+nofnames)
data.glyphs = glyphs
data.map = data.map or { }
data.map.map = uni_to_int
data.map.backmap = int_to_uni
else
- logs.report("load otf",string.format("unable to remap cid font, missing cid file for %s",filename))
+ logs.report("load otf","unable to remap cid font, missing cid file for %s",filename)
end
else
- logs.report("load otf",string.format("font %s has no glyphs",filename))
+ logs.report("load otf","font %s has no glyphs",filename)
end
end
if data.map then
@@ -1218,7 +1261,7 @@ function fonts.otf.enhance.before(data,filename)
int_to_uni[index] = private
glyph.unicode = private
if fonts.trace then
- logs.report("load otf",string.format("enhance: glyph %s at index %s is moved to private unicode slot %s",glyph.name,index,private))
+ logs.report("load otf","enhance: glyph %s at index %s is moved to private unicode slot %s",glyph.name,index,private)
end
else
glyph.unicode = unic -- safeguard for older version
@@ -1232,7 +1275,7 @@ function fonts.otf.enhance.before(data,filename)
end
end
if fonts.trace then
- logs.report("load otf",string.format("enhance: %s entries removed from map.backmap",n))
+ logs.report("load otf","enhance: %s entries removed from map.backmap",n)
end
local n = 0
for k,v in pairs(uni_to_int) do
@@ -1241,7 +1284,7 @@ function fonts.otf.enhance.before(data,filename)
end
end
if fonts.trace then
- logs.report("load otf",string.format("enhance: %s entries removed from map.mapmap",n))
+ logs.report("load otf","enhance: %s entries removed from map.mapmap",n)
end
else
data.map = { map = {}, backmap = {} }
@@ -1278,8 +1321,8 @@ function fonts.otf.enhance.before(data,filename)
--~ end
end
-function fonts.otf.enhance.after(data,filename) -- to be split
- if fonts.otf.enhance.add_kerns then
+function otf.enhance.after(data,filename) -- to be split
+ if otf.enhance.add_kerns then
local glyphs, mapmap, unicodes = data.glyphs, data.map.map, data.luatex.unicodes
local mkdone = false
for index, glyph in pairs(data.glyphs) do
@@ -1298,7 +1341,7 @@ function fonts.otf.enhance.after(data,filename) -- to be split
mkl[unicodes[vc]] = vo
end
else
- logs.report("load otf", string.format("problems with unicode %s of kern %s at glyph %s",vc,k,index))
+ logs.report("load otf","problems with unicode %s of kern %s at glyph %s",vc,k,index)
end
end
end
@@ -1319,7 +1362,7 @@ function fonts.otf.enhance.after(data,filename) -- to be split
for _, kcl in ipairs(kernclass) do
local firsts, seconds, offsets, lookup = kcl.firsts, kcl.seconds, kcl.offsets, kcl.lookup
local maxfirsts, maxseconds = table.getn(firsts), table.getn(seconds)
- logs.report("load otf", string.format("adding kernclass %s with %s times %s pairs)",lookup, maxfirsts, maxseconds))
+ logs.report("load otf", "adding kernclass %s with %s times %s pairs)",lookup, maxfirsts, maxseconds)
for fk, fv in pairs(firsts) do
for first in fv:gmatch("[^ ]+") do
local glyph = glyphs[mapmap[unicodes[first]]]
@@ -1351,7 +1394,7 @@ function fonts.otf.enhance.after(data,filename) -- to be split
end
end
-function fonts.otf.enhance.strip(data)
+function otf.enhance.strip(data)
for k, v in pairs(data.glyphs) do
local d = v.dependents
if d then v.dependents = nil end
@@ -1361,7 +1404,7 @@ function fonts.otf.enhance.strip(data)
data.luatex.comment = "Glyph tables have their original index. When present, mykern tables are indexed by unicode."
end
-function fonts.otf.enhance.flatten(data,filename) -- to be split
+function otf.enhance.flatten(data,filename) -- to be split
logs.report("load otf", "flattening 'specifications' tables")
for k, v in pairs(data.glyphs) do
if v.lookups then
@@ -1428,7 +1471,7 @@ function fonts.otf.enhance.flatten(data,filename) -- to be split
end
for _, tag in pairs({"gpos","gsub"}) do
if data[tag] then
- logs.report("load otf", "flattening '" .. tag.. "' tables")
+ logs.report("load otf", "flattening '%s' tables", tag)
for k, v in pairs(data[tag]) do
if v.features then
for kk, vv in ipairs(v.features) do
@@ -1444,11 +1487,11 @@ function fonts.otf.enhance.flatten(data,filename) -- to be split
end
end
-fonts.otf.enhance.patches = { }
+otf.enhance.patches = { }
-function fonts.otf.enhance.patch(data,filename)
+function otf.enhance.patch(data,filename)
local basename = file.basename(filename)
- for pattern, action in pairs(fonts.otf.enhance.patches) do
+ for pattern, action in pairs(otf.enhance.patches) do
if basename:find(pattern) then
action(data,filename)
end
@@ -1457,7 +1500,7 @@ end
-- tex features
-function fonts.otf.enhance.enrich(data,filename)
+function otf.enhance.enrich(data,filename)
-- later
end
@@ -1469,19 +1512,19 @@ do -- will move to a typescript
if data.design_size == 0 then
local ds = (file.basename(filename)):match("(%d+)")
if ds then
- logs.report("load otf",string.format("patching design size (%s)",ds))
+ logs.report("load otf","patching design size (%s)",ds)
data.design_size = tonumber(ds) * 10
end
end
end
- fonts.otf.enhance.patches["^lmroman"] = patch
- fonts.otf.enhance.patches["^lmsans"] = patch
- fonts.otf.enhance.patches["^lmtypewriter"] = patch
+ otf.enhance.patches["^lmroman"] = patch
+ otf.enhance.patches["^lmsans"] = patch
+ otf.enhance.patches["^lmtypewriter"] = patch
end
-function fonts.otf.analyze_class(data,class)
+function otf.analyze_class(data,class)
local classes = { }
for index, glyph in pairs(data.glyphs) do
if glyph.class == class then
@@ -1491,7 +1534,7 @@ function fonts.otf.analyze_class(data,class)
return classes
end
-function fonts.otf.analyze_subtables(data)
+function otf.analyze_subtables(data)
local subtables, name_to_type, internals, always_valid, ignore_flags, ctx_always = { }, { }, { }, { }, { }, { }
local function collect(g)
if g then
@@ -1566,7 +1609,7 @@ function fonts.otf.analyze_subtables(data)
return subtables, name_to_type, internals, always_valid, ignore_flags, ctx_always
end
-function fonts.otf.analyze_unicodes(data)
+function otf.analyze_unicodes(data)
local unicodes = { }
for _, blob in pairs(data.glyphs) do
if blob.name then
@@ -1577,7 +1620,7 @@ function fonts.otf.analyze_unicodes(data)
return unicodes
end
-function fonts.otf.analyze_features(g, features)
+function otf.analyze_features(g, features)
if g then
local t, done = { }, { }
for k=1,#g do
@@ -1600,7 +1643,7 @@ function fonts.otf.analyze_features(g, features)
return nil
end
-function fonts.otf.valid_subtable(otfdata,kind,script,language)
+function otf.valid_subtable(otfdata,kind,script,language)
local tk = otfdata.luatex.subtables[kind]
if tk then
local tks = tk[script] or tk.dflt
@@ -1614,17 +1657,17 @@ function fonts.otf.valid_subtable(otfdata,kind,script,language)
return false
end
-function fonts.otf.features.register(name,default)
- fonts.otf.features.list[#fonts.otf.features.list+1] = name
- fonts.otf.features.default[name] = default
+function otf.features.register(name,default)
+ otf.features.list[#otf.features.list+1] = name
+ otf.features.default[name] = default
end
-function fonts.otf.set_features(tfmdata) -- node and base, simple mapping
+function otf.set_features(tfmdata) -- node and base, simple mapping
local shared = tfmdata.shared
local otfdata = shared.otfdata
- shared.features = fonts.define.check(shared.features,fonts.otf.features.default)
+ shared.features = fonts.define.check(shared.features,otf.features.default)
local features = shared.features
- local trace = fonts.otf.trace_features or fonts.otf.trace_set_features
+ local trace = otf.trace_features or otf.trace_set_features
if not tfmdata.language then tfmdata.language = 'dflt' end
if not tfmdata.script then tfmdata.script = 'dflt' end
if not table.is_empty(features) then
@@ -1645,7 +1688,7 @@ function fonts.otf.set_features(tfmdata) -- node and base, simple mapping
if value and fiotf[f] then -- brr
if not done[f] then -- so, we can move some to triggers
if trace then
- logs.report("define otf",string.format("initializing feature %s to %s for mode %s for font %s",f,tostring(value),mode or 'unknown', tfmdata.fullname or 'unknown'))
+ logs.report("define otf","initializing feature %s to %s for mode %s for font %s",f,tostring(value),mode or 'unknown', tfmdata.fullname or 'unknown')
end
fiotf[f](tfmdata,value) -- can set mode (no need to pass otf)
mode = tfmdata.mode or fonts.mode -- keep this, mode can be set local !
@@ -1674,7 +1717,7 @@ function fonts.otf.set_features(tfmdata) -- node and base, simple mapping
local f = list[i]
if features[f] and fmotf[f] then -- brr
if trace then
- logs.report("define otf",string.format("installing feature handler %s for mode %s for font %s",f,mode or 'unknown', tfmdata.fullname or 'unknown'))
+ logs.report("define otf","installing feature handler %s for mode %s for font %s",f,mode or 'unknown', tfmdata.fullname or 'unknown')
end
sp[#sp+1] = fmotf[f]
end
@@ -1690,18 +1733,18 @@ function fonts.otf.set_features(tfmdata) -- node and base, simple mapping
end
end
-function fonts.otf.otf_to_tfm(specification)
+function otf.otf_to_tfm(specification)
local name = specification.name
local sub = specification.sub
local filename = specification.filename
local format = specification.format
local features = specification.features.normal
local cache_id = specification.hash
- local tfmdata = containers.read(fonts.tfm.cache(),cache_id)
+ local tfmdata = containers.read(tfm.cache(),cache_id)
if not tfmdata then
- local otfdata = fonts.otf.load(filename,format,sub,features and features.featurefile)
+ local otfdata = otf.load(filename,format,sub,features and features.featurefile)
if not table.is_empty(otfdata) then
- fonts.otf.add_dimensions(otfdata)
+ otf.add_dimensions(otfdata)
if true then
otfdata._shared_ = otfdata._shared_ or { -- aggressive sharing
processes = { },
@@ -1710,7 +1753,7 @@ function fonts.otf.otf_to_tfm(specification)
featurecache = { },
}
end
- tfmdata = fonts.otf.copy_to_tfm(otfdata)
+ tfmdata = otf.copy_to_tfm(otfdata)
if not table.is_empty(tfmdata) then
tfmdata.unique = tfmdata.unique or { }
tfmdata.shared = tfmdata.shared or { } -- combine
@@ -1729,20 +1772,20 @@ function fonts.otf.otf_to_tfm(specification)
shared.featuredata = otfdata._shared_.featuredata
shared.featurecache = otfdata._shared_.featurecache
end
- fonts.otf.set_features(tfmdata)
+ otf.set_features(tfmdata)
end
end
- containers.write(fonts.tfm.cache(),cache_id,tfmdata)
+ containers.write(tfm.cache(),cache_id,tfmdata)
end
return tfmdata
end
-function fonts.otf.features.prepare_base_kerns(tfmdata,kind,value) -- todo what kind of kerns, currently all
+function otf.features.prepare_base_kerns(tfmdata,kind,value) -- todo what kind of kerns, currently all
if value then
local otfdata = tfmdata.shared.otfdata
local charlist = otfdata.glyphs
local unicodes = otfdata.luatex.unicodes
- local somevalid = fonts.otf.some_valid_feature(otfdata,kind,tfmdata.script,tfmdata.language)
+ local somevalid = otf.some_valid_feature(otfdata,kind,tfmdata.script,tfmdata.language)
for _, chr in pairs(tfmdata.characters) do
local d = charlist[chr.description.index]
if d then
@@ -1783,9 +1826,9 @@ function fonts.otf.features.prepare_base_kerns(tfmdata,kind,value) -- todo what
end
end
-function fonts.otf.add_dimensions(data)
+function otf.add_dimensions(data)
if data then
- local force = fonts.otf.notdef
+ local force = otf.notdef
for k, d in pairs(data.glyphs) do
local bb, wd = d.boundingbox, d.width or 0
if force and not d.name then
@@ -1804,7 +1847,7 @@ function fonts.otf.add_dimensions(data)
end
end
-function fonts.otf.copy_to_tfm(data) -- we can save a copy when we reorder the tma to unicode
+function otf.copy_to_tfm(data) -- we can save a copy when we reorder the tma to unicode
if data then
local tfm = { characters = { }, parameters = { } }
local unicodes = data.luatex.unicodes
@@ -1823,7 +1866,7 @@ function fonts.otf.copy_to_tfm(data) -- we can save a copy when we reorder the t
local spaceunits = 500
tfm.units = data.units_per_em or 1000
-- we need a runtime lookup because of running from cdrom or zip, brrr
- tfm.filename = input.findbinfile(texmf.instance,data.luatex.filename,"") or data.luatex.filename
+ tfm.filename = input.findbinfile(data.luatex.filename,"") or data.luatex.filename
tfm.fullname = data.fontname or data.fullname
tfm.encodingbytes = 2
tfm.cidinfo = data.cidinfo
@@ -1883,7 +1926,7 @@ function fonts.otf.copy_to_tfm(data) -- we can save a copy when we reorder the t
if data.isfixedpitch then
parameters.space_stretch = 0
parameters.space_shrink = 0
- elseif fonts.otf.syncspace then --
+ elseif otf.syncspace then --
parameters.space_stretch = spaceunits/2
parameters.space_shrink = spaceunits/3
end
@@ -1902,12 +1945,12 @@ function fonts.otf.copy_to_tfm(data) -- we can save a copy when we reorder the t
end
end
-function fonts.tfm.read_from_open_type(specification)
- local tfmtable = fonts.otf.otf_to_tfm(specification)
+function tfm.read_from_open_type(specification)
+ local tfmtable = otf.otf_to_tfm(specification)
if tfmtable then
tfmtable.name = specification.name
tfmtable.sub = specification.sub
- tfmtable = fonts.tfm.scale(tfmtable, specification.size)
+ tfmtable = tfm.scale(tfmtable, specification.size)
-- here we resolve the name; file can be relocated, so this info is not in the cache
local otfdata = tfmtable.shared.otfdata
local filename = (otfdata and otfdata.luatex and otfdata.luatex.filename) or specification.filename
@@ -1916,7 +1959,7 @@ function fonts.tfm.read_from_open_type(specification)
end
if filename then
tfmtable.encodingbytes = 2
- tfmtable.filename = input.findbinfile(texmf.instance,filename,"") or filename
+ tfmtable.filename = input.findbinfile(filename,"") or filename
tfmtable.fullname = otfdata.fontname or otfdata.fullname
local order = otfdata and otfdata.order2
if order == 0 then
@@ -1933,8 +1976,8 @@ function fonts.tfm.read_from_open_type(specification)
return tfmtable
end
-function fonts.otf.analyze_only(otfdata)
- local analyze = fonts.otf.analyze_features
+function otf.analyze_only(otfdata)
+ local analyze = otf.analyze_features
return analyze(otfdata.gpos), analyze(otfdata.gsub)
end
@@ -1946,7 +1989,7 @@ do
local context_setups = fonts.define.specify.context_setups
local context_numbers = fonts.define.specify.context_numbers
- function fonts.otf.set_dynamics(tfmdata,attribute,features) --currently experimental and slow / hackery
+ function otf.set_dynamics(tfmdata,attribute,features) --currently experimental and slow / hackery
local shared = tfmdata.shared
if shared then
local dynamics = shared.dynamics
@@ -1975,8 +2018,8 @@ do
local otfdata = shared.otfdata
local methods = fonts.methods.node.otf
local initializers = fonts.initializers.node.otf
- local gposfeatures, gsubfeatures = fonts.otf.analyze_only(otfdata,features)
- local default = fonts.otf.features.default
+ local gposfeatures, gsubfeatures = otf.analyze_only(otfdata,features)
+ local default = otf.features.default
local function register(list)
if list then
for i=1,#list do
@@ -2010,15 +2053,15 @@ end
-- scripts
-fonts.otf.default_language = 'latn'
-fonts.otf.default_script = 'dflt'
+otf.default_language = 'latn'
+otf.default_script = 'dflt'
-function fonts.otf.valid_feature(otfdata,kind,script,language) -- return hash is faster
+function otf.valid_feature(otfdata,kind,script,language) -- return hash is faster
if otfdata.luatex.ctx_always[kind] then
script, language = 'dflt', 'dflt'
else
- script = script or fonts.otf.default_script
- language = language or fonts.otf.default_language
+ script = script or otf.default_script
+ language = language or otf.default_language
end
script, language = script:lower(), language:lower() -- will go away, we will lowercase values
local ft = otfdata.luatex.subtables[kind]
@@ -2027,12 +2070,12 @@ function fonts.otf.valid_feature(otfdata,kind,script,language) -- return hash is
return false, otfdata.luatex.always_valid, lt.valid
end
-function fonts.otf.some_valid_feature(otfdata,kind,script,language)
+function otf.some_valid_feature(otfdata,kind,script,language)
if otfdata.luatex.ctx_always[kind] then
script, language = 'dflt', 'dflt'
else
- script = script or fonts.otf.default_script
- language = language or fonts.otf.default_language
+ script = script or otf.default_script
+ language = language or otf.default_language
script, language = script:lower(), language:lower() -- will go away, we will lowercase values
end
local t = otfdata.luatex.subtables[kind]
@@ -2046,29 +2089,26 @@ function fonts.otf.some_valid_feature(otfdata,kind,script,language)
return { }
end
-function fonts.otf.features.aux.resolve_ligatures(tfmdata,ligatures,kind)
+function otf.features.aux.resolve_ligatures(tfmdata,ligatures,kind)
local otfdata = tfmdata.shared.otfdata
local unicodes = otfdata.luatex.unicodes
local chars = tfmdata.characters
local changed = tfmdata.changed or { }
local done = { }
kind = kind or "unknown"
- local trace = fonts.otf.trace_features
+ local trace = otf.trace_features
while true do
local ok = false
for k,v in pairs(ligatures) do
local lig = v[1]
if not done[lig] then
- local ligs = { }
- for s in lig:gmatch("[^ ]+") do
- ligs[#ligs+1] = s
- end
+ local ligs = split_at_space:match(lig)
if #ligs == 2 then
local c, f, s = chars[v[2]], ligs[1], ligs[2]
local uf, us = unicodes[f], unicodes[s]
if changed[uf] or changed[us] then
if trace then
- logs.report("define otf",string.format("%s: %s (%s) + %s (%s) ignored",kind,f,uf,s,us))
+ logs.report("define otf","%s: %s (%s) + %s (%s) ignored",kind,f,uf,s,us)
end
else
local first, second = chars[uf], us
@@ -2083,7 +2123,7 @@ function fonts.otf.features.aux.resolve_ligatures(tfmdata,ligatures,kind)
type = 0
}
if trace then
- logs.report("define otf",string.format("%s: %s (%s) + %s (%s) = %s (%s)",kind,f,uf,s,us,c.description.name,unicodes[c.description.name]))
+ logs.report("define otf","%s: %s (%s) + %s (%s) = %s (%s)",kind,f,uf,s,us,c.description.name,unicodes[c.description.name])
end
end
end
@@ -2106,14 +2146,14 @@ function fonts.otf.features.aux.resolve_ligatures(tfmdata,ligatures,kind)
end
end
-function fonts.otf.features.prepare_base_substitutions(tfmdata,kind,value) -- we can share some code with the node features
+function otf.features.prepare_base_substitutions(tfmdata,kind,value) -- we can share some code with the node features
if value then
local ligatures = { }
local otfdata = tfmdata.shared.otfdata
local unicodes = otfdata.luatex.unicodes
- local trace = fonts.otf.trace_features
+ local trace = otf.trace_features
local chars = tfmdata.characters
- local somevalid = fonts.otf.some_valid_feature(otfdata,kind,tfmdata.script,tfmdata.language)
+ local somevalid = otf.some_valid_feature(otfdata,kind,tfmdata.script,tfmdata.language)
if not table.is_empty(somevalid) then
tfmdata.changed = tfmdata.changed or { }
local changed = tfmdata.changed
@@ -2132,7 +2172,7 @@ function fonts.otf.features.prepare_base_substitutions(tfmdata,kind,value) -- we
local upv = unicodes[pv]
if upv and chars[upv] then
if trace then
- logs.report("define otf",string.format("%s: %s (%s) => %s (%s)",kind,chars[k].description.name,k,chars[upv].description.name,upv))
+ logs.report("define otf","%s: %s (%s) => %s (%s)",kind,chars[k].description.name,k,chars[upv].description.name,upv)
end
chars[k] = chars[upv]
changed[k] = true
@@ -2141,12 +2181,12 @@ function fonts.otf.features.prepare_base_substitutions(tfmdata,kind,value) -- we
elseif t == 'alternate' then
local pc = p[2] -- p.components
if pc then
- pc = pa.components:match("([^ ]+)")
+ pc = pa.components:match("([^ ]+)") -- todo: selector
if pc then
local upc = unicodes[pc]
if upc and chars[upc] then
if trace then
- logs.report("define otf",string.format("%s: %s (%s) => %s (%s)",kind,chars[k].description.name,k,chars[upc].description.name,upc))
+ logs.report("define otf","%s: %s (%s) => %s (%s)",kind,chars[k].description.name,k,chars[upc].description.name,upc)
end
chars[k] = chars[upc]
changed[k] = true
@@ -2157,7 +2197,7 @@ function fonts.otf.features.prepare_base_substitutions(tfmdata,kind,value) -- we
local pc = p[2]
if pc then
if trace then
- logs.report("define otf",string.format("%s: %s => %s (%s)",kind,pc,chars[k].description.name,k))
+ logs.report("define otf","%s: %s => %s (%s)",kind,pc,chars[k].description.name,k)
end
ligatures[#ligatures+1] = { pc, k }
end
@@ -2167,30 +2207,30 @@ function fonts.otf.features.prepare_base_substitutions(tfmdata,kind,value) -- we
end
end
end
- fonts.otf.features.aux.resolve_ligatures(tfmdata,ligatures,kind)
+ otf.features.aux.resolve_ligatures(tfmdata,ligatures,kind)
end
else
tfmdata.ligatures = tfmdata.ligatures or { }
end
end
-function fonts.initializers.base.otf.liga(tfm,value) fonts.otf.features.prepare_base_substitutions(tfm,'liga',value) end
-function fonts.initializers.base.otf.dlig(tfm,value) fonts.otf.features.prepare_base_substitutions(tfm,'dlig',value) end
-function fonts.initializers.base.otf.rlig(tfm,value) fonts.otf.features.prepare_base_substitutions(tfm,'rlig',value) end
-function fonts.initializers.base.otf.hlig(tfm,value) fonts.otf.features.prepare_base_substitutions(tfm,'hlig',value) end
-function fonts.initializers.base.otf.pnum(tfm,value) fonts.otf.features.prepare_base_substitutions(tfm,'pnum',value) end
-function fonts.initializers.base.otf.onum(tfm,value) fonts.otf.features.prepare_base_substitutions(tfm,'onum',value) end
-function fonts.initializers.base.otf.tnum(tfm,value) fonts.otf.features.prepare_base_substitutions(tfm,'tnum',value) end
-function fonts.initializers.base.otf.lnum(tfm,value) fonts.otf.features.prepare_base_substitutions(tfm,'lnum',value) end
-function fonts.initializers.base.otf.zero(tfm,value) fonts.otf.features.prepare_base_substitutions(tfm,'zero',value) end
-function fonts.initializers.base.otf.smcp(tfm,value) fonts.otf.features.prepare_base_substitutions(tfm,'smcp',value) end
-function fonts.initializers.base.otf.cpsp(tfm,value) fonts.otf.features.prepare_base_substitutions(tfm,'cpsp',value) end
-function fonts.initializers.base.otf.c2sc(tfm,value) fonts.otf.features.prepare_base_substitutions(tfm,'c2sc',value) end
-function fonts.initializers.base.otf.ornm(tfm,value) fonts.otf.features.prepare_base_substitutions(tfm,'ornm',value) end
-function fonts.initializers.base.otf.aalt(tfm,value) fonts.otf.features.prepare_base_substitutions(tfm,'aalt',value) end
-
-function fonts.initializers.base.otf.hwid(tfm,value) fonts.otf.features.prepare_base_substitutions(tfm,'hwid',value) end
-function fonts.initializers.base.otf.fwid(tfm,value) fonts.otf.features.prepare_base_substitutions(tfm,'fwid',value) end
+function fonts.initializers.base.otf.liga(tfm,value) otf.features.prepare_base_substitutions(tfm,'liga',value) end
+function fonts.initializers.base.otf.dlig(tfm,value) otf.features.prepare_base_substitutions(tfm,'dlig',value) end
+function fonts.initializers.base.otf.rlig(tfm,value) otf.features.prepare_base_substitutions(tfm,'rlig',value) end
+function fonts.initializers.base.otf.hlig(tfm,value) otf.features.prepare_base_substitutions(tfm,'hlig',value) end
+function fonts.initializers.base.otf.pnum(tfm,value) otf.features.prepare_base_substitutions(tfm,'pnum',value) end
+function fonts.initializers.base.otf.onum(tfm,value) otf.features.prepare_base_substitutions(tfm,'onum',value) end
+function fonts.initializers.base.otf.tnum(tfm,value) otf.features.prepare_base_substitutions(tfm,'tnum',value) end
+function fonts.initializers.base.otf.lnum(tfm,value) otf.features.prepare_base_substitutions(tfm,'lnum',value) end
+function fonts.initializers.base.otf.zero(tfm,value) otf.features.prepare_base_substitutions(tfm,'zero',value) end
+function fonts.initializers.base.otf.smcp(tfm,value) otf.features.prepare_base_substitutions(tfm,'smcp',value) end
+function fonts.initializers.base.otf.cpsp(tfm,value) otf.features.prepare_base_substitutions(tfm,'cpsp',value) end
+function fonts.initializers.base.otf.c2sc(tfm,value) otf.features.prepare_base_substitutions(tfm,'c2sc',value) end
+function fonts.initializers.base.otf.ornm(tfm,value) otf.features.prepare_base_substitutions(tfm,'ornm',value) end
+function fonts.initializers.base.otf.aalt(tfm,value) otf.features.prepare_base_substitutions(tfm,'aalt',value) end
+
+function fonts.initializers.base.otf.hwid(tfm,value) otf.features.prepare_base_substitutions(tfm,'hwid',value) end
+function fonts.initializers.base.otf.fwid(tfm,value) otf.features.prepare_base_substitutions(tfm,'fwid',value) end
-- Here comes the real thing ... node processing! The next session prepares
-- things. The main features (unchained by rules) have their own caches,
@@ -2198,16 +2238,16 @@ function fonts.initializers.base.otf.fwid(tfm,value) fonts.otf.features.prepare_
do
- fonts.otf.features.prepare = { }
+ otf.features.prepare = { }
local falsetable = { false, false, false }
- function fonts.otf.features.prepare.feature(tfmdata,kind,value)
+ function otf.features.prepare.feature(tfmdata,kind,value)
if value then
local language, script = tfmdata.language or "dflt", tfmdata.script or "dflt"
local shared = tfmdata.shared
local otfdata = shared.otfdata
- local lookuptable = fonts.otf.valid_subtable(otfdata,kind,script,language)
+ local lookuptable = otf.valid_subtable(otfdata,kind,script,language)
if lookuptable then
local fullkind = kind .. script .. language
if not shared.lookuptable [fullkind] then
@@ -2220,8 +2260,8 @@ do
shared.processes [fullkind] = processes
local types = otfdata.luatex.name_to_type
local flags = otfdata.luatex.ignore_flags
- local preparers = fonts.otf.features.prepare
- local process = fonts.otf.features.process
+ local preparers = otf.features.prepare
+ local process = otf.features.process
for i=1,#lookuptable do
local lookupname = lookuptable[i]
local lookuptype = types[lookupname]
@@ -2246,17 +2286,17 @@ do
local pairs = pairs
- function fonts.otf.features.collect_ligatures(tfmdata,kind) -- ligs are spread all over the place
+ function otf.features.collect_ligatures(tfmdata,kind) -- ligs are spread all over the place
local otfdata = tfmdata.shared.otfdata
local unicodes = tfmdata.shared.otfdata.luatex.unicodes -- actually the char index is ok too
- local trace = fonts.otf.trace_features
+ local trace = otf.trace_features
local ligatures = { }
local function collect(lookup,o,ps)
for i=1,#ps do
local p = ps[i]
if p[1] == 'ligature' then
if trace then
- logs.report("define otf",string.format("feature %s lookup %s ligature %s => %s",kind,lookup,p[2],o.name))
+ logs.report("define otf","feature %s lookup %s ligature %s => %s",kind,lookup,p[2],o.name)
end
local t = ligatures[lookup]
if not t then
@@ -2284,7 +2324,7 @@ do
end
end
end
- local forced, always, okay = fonts.otf.valid_feature(otfdata,kind,tfmdata.script,tfmdata.language)
+ local forced, always, okay = otf.valid_feature(otfdata,kind,tfmdata.script,tfmdata.language)
for _,o in pairs(otfdata.glyphs) do
local lookups = o.lookups
if lookups then
@@ -2312,7 +2352,7 @@ do
-- due to extensive calls to functions (easily hundreds of thousands per
-- document)
- function fonts.otf.features.prepare.gsub_single(tfmdata,kind,lookupname)
+ function otf.features.prepare.gsub_single(tfmdata,kind,lookupname)
local featuredata = tfmdata.shared.featuredata[kind]
local substitutions = featuredata[lookupname]
if not substitutions then
@@ -2320,7 +2360,7 @@ do
featuredata[lookupname] = substitutions
local otfdata = tfmdata.shared.otfdata
local unicodes = otfdata.luatex.unicodes
- local trace = fonts.otf.trace_features
+ local trace = otf.trace_features
for _, o in pairs(otfdata.glyphs) do
local lookups = o.lookups
if lookups then
@@ -2332,7 +2372,7 @@ do
local old, new = o.unicode, unicodes[p[2]]
substitutions[old] = new
if trace then
- logs.report("define otf",string.format("%s:%s substitution %s => %s",kind,lookupname,old,new))
+ logs.report("define otf","%s:%s substitution %s => %s",kind,lookupname,old,new)
end
end
end
@@ -2344,7 +2384,7 @@ do
return substitutions
end
- function fonts.otf.features.prepare.gsub_multiple(tfmdata,kind,lookupname)
+ function otf.features.prepare.gsub_multiple(tfmdata,kind,lookupname)
local featuredata = tfmdata.shared.featuredata[kind]
local substitutions = featuredata[lookupname]
if not substitutions then
@@ -2352,7 +2392,7 @@ do
featuredata[lookupname] = substitutions
local otfdata = tfmdata.shared.otfdata
local unicodes = otfdata.luatex.unicodes
- local trace = fonts.otf.trace_features
+ local trace = otf.trace_features
for _,o in pairs(otfdata.glyphs) do
local lookups = o.lookups
if lookups then
@@ -2367,7 +2407,7 @@ do
new[#new+1] = unicodes[pc]
end
if trace then
- logs.report("define otf",string.format("%s:%s multiple %s => %s",kind,lookupname,old,table.concat(new," ")))
+ logs.report("define otf","%s:%s multiple %s => %s",kind,lookupname,old,table.concat(new," "))
end
end
end
@@ -2379,7 +2419,7 @@ do
return substitutions
end
- function fonts.otf.features.prepare.gsub_alternate(tfmdata,kind,lookupname)
+ function otf.features.prepare.gsub_alternate(tfmdata,kind,lookupname)
-- todo: configurable preference list
local featuredata = tfmdata.shared.featuredata[kind]
local substitutions = featuredata[lookupname]
@@ -2388,7 +2428,7 @@ do
substitutions = featuredata[lookupname]
local otfdata = tfmdata.shared.otfdata
local unicodes = otfdata.luatex.unicodes
- local trace = fonts.otf.trace_features
+ local trace = otf.trace_features
for _,o in pairs(otfdata.glyphs) do
local lookups = o.lookups
if lookups then
@@ -2404,7 +2444,7 @@ do
end
substitutions[old] = t
if trace then
- logs.report("define otf",string.format("%s:%s alternate %s => %s",kind,lookupname,old,table.concat(substitutions,"|")))
+ logs.report("define otf","%s:%s alternate %s => %s",kind,lookupname,old,table.concat(substitutions,"|"))
end
end
end
@@ -2416,19 +2456,19 @@ do
return substitutions
end
- function fonts.otf.features.prepare.gsub_ligature(tfmdata,kind,lookupname)
+ function otf.features.prepare.gsub_ligature(tfmdata,kind,lookupname)
-- we collect them for all lookups, this saves loops, we only use the
-- lookupname for testing, we need to check if this leads to redundant
-- collections
local ligatures = tfmdata.shared.featuredata[kind]
if not ligatures[lookupname] then
- ligatures = fonts.otf.features.collect_ligatures(tfmdata,kind)
+ ligatures = otf.features.collect_ligatures(tfmdata,kind)
tfmdata.shared.featuredata[kind] = ligatures
end
return ligatures[lookupname]
end
- function fonts.otf.features.prepare.contextchain(tfmdata,kind,lookupname)
+ function otf.features.prepare.contextchain(tfmdata,kind,lookupname)
local featuredata = tfmdata.shared.featuredata[kind]
local contexts = featuredata[lookupname]
if not contexts then
@@ -2461,10 +2501,10 @@ do
end
local lookupdata = otfdata.lookups[lookupname]
if not lookupdata then
- logs.error("otf process", string.format("missing lookupdata table %s",lookupname))
+ logs.report("otf process","missing lookupdata table %s",lookupname)
elseif lookupdata.rules then
local rules = lookupdata.rules
- local center_match = fonts.otf.center_match
+ local center_match = otf.center_match
for nofrules=1,#rules do
local rule = rules[nofrules]
local coverage = rule.coverage
@@ -2508,9 +2548,9 @@ do
return contexts
end
- fonts.otf.features.prepare.gsub_context = fonts.otf.features.prepare.contextchain
- fonts.otf.features.prepare.gsub_contextchain = fonts.otf.features.prepare.contextchain
- fonts.otf.features.prepare.gsub_reversecontextchain = fonts.otf.features.prepare.contextchain
+ otf.features.prepare.gsub_context = otf.features.prepare.contextchain
+ otf.features.prepare.gsub_contextchain = otf.features.prepare.contextchain
+ otf.features.prepare.gsub_reversecontextchain = otf.features.prepare.contextchain
-- ruled->lookup=ks_latn_l_27_c_4 => internal[ls_l_84] => valid[ls_l_84_s]
@@ -2523,7 +2563,7 @@ do
-- gpos_context -> not done
-- gpos_reversecontextchain -> not done
- function fonts.otf.features.prepare.anchors(tfmdata,kind,lookupname) -- tracing
+ function otf.features.prepare.anchors(tfmdata,kind,lookupname) -- tracing
local featuredata = tfmdata.shared.featuredata[kind]
local anchors = featuredata[lookupname]
if not anchors then
@@ -2533,14 +2573,14 @@ do
local unicodes = otfdata.luatex.unicodes
local validanchors = { }
local glyphs = otfdata.glyphs
- local trace = fonts.otf.trace_features
+ local trace = otf.trace_features
if otfdata.anchor_classes then
local classes = otfdata.anchor_classes
for k=1,#classes do
local class = classes[k]
if class.lookup == lookupname then
if trace then
- logs.report("define otf",string.format("%s:%s anchor -> %s",kind,lookupname,class.name))
+ logs.report("define otf","%s:%s anchor -> %s",kind,lookupname,class.name)
end
validanchors[class.name] = true
end
@@ -2574,25 +2614,25 @@ do
return anchors
end
- fonts.otf.features.prepare.gpos_mark2base = fonts.otf.features.prepare.anchors
- fonts.otf.features.prepare.gpos_mark2ligature = fonts.otf.features.prepare.anchors
- fonts.otf.features.prepare.gpos_mark2mark = fonts.otf.features.prepare.anchors
- fonts.otf.features.prepare.gpos_cursive = fonts.otf.features.prepare.anchors
- fonts.otf.features.prepare.gpos_context = fonts.otf.features.prepare.contextchain
- fonts.otf.features.prepare.gpos_contextchain = fonts.otf.features.prepare.contextchain
+ otf.features.prepare.gpos_mark2base = otf.features.prepare.anchors
+ otf.features.prepare.gpos_mark2ligature = otf.features.prepare.anchors
+ otf.features.prepare.gpos_mark2mark = otf.features.prepare.anchors
+ otf.features.prepare.gpos_cursive = otf.features.prepare.anchors
+ otf.features.prepare.gpos_context = otf.features.prepare.contextchain
+ otf.features.prepare.gpos_contextchain = otf.features.prepare.contextchain
- function fonts.otf.features.prepare.gpos_single(tfmdata,kind,lookupname)
+ function otf.features.prepare.gpos_single(tfmdata,kind,lookupname)
logs.report("otf define","gpos_single not yet supported")
end
-- ["kerns"]={ { ["char"]="ytilde", ["lookup"]="pp_l_1_s", ["off"]=-83, ...
-- ["mykerns"] = { ["pp_l_1_s"] = { [67] = -28, ...
- function fonts.otf.features.prepare.gpos_pair(tfmdata,kind,lookupname)
+ function otf.features.prepare.gpos_pair(tfmdata,kind,lookupname)
local featuredata = tfmdata.shared.featuredata[kind]
local kerns = featuredata[lookupname]
if not kerns then
- local trace = fonts.otf.trace_features
+ local trace = otf.trace_features
featuredata[lookupname] = { }
kerns = featuredata[lookupname]
local otfdata = tfmdata.shared.otfdata
@@ -2614,7 +2654,7 @@ do
kerns[one] = { two = off }
end
if trace then
- logs.report("define otf",string.format("feature %s kern pair %s - %s",kind,one,two))
+ logs.report("define otf","feature %s kern pair %s - %s",kind,one,two)
end
end
end
@@ -2634,7 +2674,7 @@ do
kerns[one] = { two = k.off }
end
if trace then
- logs.report("define otf",string.format("feature %s kern pair %s - %s",kind,one,two))
+ logs.report("define otf","feature %s kern pair %s - %s",kind,one,two)
end
end
end
@@ -2656,7 +2696,7 @@ do
kerns[one] = { two = p }
end
if trace then
- logs.report("define otf",string.format("feature %s kern pair %s - %s",kind,one,two))
+ logs.report("define otf","feature %s kern pair %s - %s",kind,one,two)
end
end
end
@@ -2668,7 +2708,7 @@ do
return kerns
end
- fonts.otf.features.prepare.gpos_contextchain = fonts.otf.features.prepare.contextchain
+ otf.features.prepare.gpos_contextchain = otf.features.prepare.contextchain
end
@@ -2676,7 +2716,7 @@ end
do
- local prepare = fonts.otf.features.prepare.feature
+ local prepare = otf.features.prepare.feature
function fonts.initializers.node.otf.aalt(tfm,value) return prepare(tfm,'aalt',value) end
function fonts.initializers.node.otf.abvm(tfm,value) return prepare(tfm,'abvm',value) end
@@ -2734,6 +2774,7 @@ do
function fonts.initializers.node.otf.pstf(tfm,value) return prepare(tfm,'pstf',value) end
function fonts.initializers.node.otf.rlig(tfm,value) return prepare(tfm,'rlig',value) end
function fonts.initializers.node.otf.rphf(tfm,value) return prepare(tfm,'rphf',value) end
+ function fonts.initializers.node.otf.rtla(tfm,value) return prepare(tfm,'rtla',value) end
function fonts.initializers.node.otf.salt(tfm,value) return prepare(tfm,'salt',value) end
function fonts.initializers.node.otf.sinf(tfm,value) return prepare(tfm,'sinf',value) end
function fonts.initializers.node.otf.smcp(tfm,value) return prepare(tfm,'smcp',value) end
@@ -2767,17 +2808,17 @@ do
local glue = node.id('glue')
local kern = node.id('kern')
local disc = node.id('disc')
+ local whatsit = node.id('whatsit')
- local fontdata = fonts.tfm.id
+ local fontdata = tfm.id
local has_attribute = node.has_attribute
local set_attribute = node.set_attribute
local state = attributes.numbers['state'] or 100
local marknumber = attributes.numbers['mark'] or 200
- local format = string.format
local report = logs.report
local scale = tex.scale
- fonts.otf.features.process = { }
+ otf.features.process = { }
-- we share some vars here, after all, we have no nested lookups and
-- less code
@@ -2788,6 +2829,7 @@ do
local marks = false
local glyphs = false
local currentfont = false
+ local rlmode = 0
-- we cheat a bit and assume that a font,attr combination are kind of ranged
@@ -2798,9 +2840,9 @@ do
-- 2 loop over glyphs loop over lookups, continue at match
-- 3 loop over lookups loop over glyphs
- fonts.otf.strategy = 2
+ otf.strategy = 2
- function fonts.otf.features.process.feature(head,font,attr,kind,attribute)
+ function otf.features.process.feature(head,font,attr,kind,attribute)
tfmdata = fontdata[font]
local shared = tfmdata.shared
otfdata = shared.otfdata
@@ -2808,24 +2850,26 @@ do
marks = otfdata.luatex.marks
glyphs = otfdata.glyphs
currentfont = font
+ rlmode = 0
local script, language, strategy
if attr and attr > 0 then
local features = context_setups[context_numbers[attr]]
- language, script, strategy = features.language or "dflt", features.script or "dflt", features.strategy or fonts.otf.strategy
+ language, script, strategy = features.language or "dflt", features.script or "dflt", features.strategy or otf.strategy
else
- language, script, strategy = tfmdata.language or "dflt", tfmdata.script or "dflt", tfmdata.strategy or fonts.otf.strategy
+ language, script, strategy = tfmdata.language or "dflt", tfmdata.script or "dflt", tfmdata.strategy or otf.strategy
end
local fullkind = kind .. script .. language
local lookuptable = shared.lookuptable[fullkind]
if lookuptable then
- -- local strategy = fonts.otf.strategy
+ -- local strategy = otf.strategy
local types = otfdata.luatex.name_to_type
local start, done, ok = head, false, false
local processes = shared.processes[fullkind]
if #processes == 1 then
local p = processes[1]
while start do -- evt splitsen
- if start.id == glyph then
+ local id = start.id
+ if id == glyph then
if start.subtype<256 and start.font == font and
(not attr or has_attribute(start,0,attr)) and -- dynamic feature
(not attribute or has_attribute(start,state,attribute)) then
@@ -2842,9 +2886,9 @@ do
else
start = start.next
end
- elseif start.id == glue and p[5] then
+ elseif id == glue and p[5] then
local pp = p[3] -- all lookups
- local pc = pp[32] -- space
+ local pc = pp[32] -- space, todo: more generic spacing
if pc then
start, ok = p[1](start,kind,p[2],pc,pp,p[4])
done = done or ok
@@ -2852,6 +2896,28 @@ do
else
start = start.next
end
+ elseif id == whatsit then
+ local subtype = start.subtype
+ if subtype == 7 then
+ local dir = start.dir
+ if dir == "+TRT" then
+ rlmode = -1
+ elseif dir == "+TLT" then
+ rlmode = 1
+ else
+ rlmode = 0
+ end
+ elseif subtype == 6 then
+ local dir = start.dir
+ if dir == "TRT" then
+ rlmode = -1
+ elseif dir == "TLT" then
+ rlmode = 1
+ else
+ rlmode = 0
+ end
+ end
+ start = start.next
else
start = start.next
end
@@ -2861,7 +2927,8 @@ do
local pp = p[3]
start = head
while start do
- if start.id == glyph then
+ local id = start.id
+ if id == glyph then
if start.subtype<256 and start.font == font and
(not attr or has_attribute(start,0,attr)) and -- dynamic feature
(not attribute or has_attribute(start,state,attribute)) then
@@ -2878,7 +2945,7 @@ do
else
start = start.next
end
- elseif start.id == glue then
+ elseif id == glue then
if p[5] then -- chain
local pc = pp[32]
if pc then
@@ -2893,6 +2960,28 @@ do
else
start = start.next
end
+ elseif id == whatsit then
+ local subtype = start.subtype
+ if subtype == 7 then
+ local dir = start.dir
+ if dir == "+TRT" then
+ rlmode = -1
+ elseif dir == "+TLT" then
+ rlmode = 1
+ else
+ rlmode = 0
+ end
+ elseif subtype == 6 then
+ local dir = start.dir
+ if dir == "TRT" then
+ rlmode = -1
+ elseif dir == "TLT" then
+ rlmode = 1
+ else
+ rlmode = 0
+ end
+ end
+ start = start.next
else
start = start.next
end
@@ -2900,7 +2989,8 @@ do
end
else
while start do
- if start.id == glyph then
+ local id = start.id
+ if id == glyph then
if start.subtype<256 and start.font == font and
(not attr or has_attribute(start,0,attr)) and -- dynamic feature
(not attribute or has_attribute(start,state,attribute)) then
@@ -2923,29 +3013,51 @@ do
end
end
if start then start = start.next end
- elseif start.id == glue then
- for i=1,#processes do local p = processes[i]
- if p[5] then -- chain
- local pp = p[3]
- local pc = pp[32]
- if pc then
- start, ok = p[1](start,kind,p[2],pc,pp,p[4])
- if ok then
- done = true
- if strategy == 1 then
- break
- end
- end
- if not start then
+ else
+ start = start.next
+ end
+ elseif id == glue then
+ for i=1,#processes do local p = processes[i]
+ if p[5] then -- chain
+ local pp = p[3]
+ local pc = pp[32]
+ if pc then
+ start, ok = p[1](start,kind,p[2],pc,pp,p[4])
+ if ok then
+ done = true
+ if strategy == 1 then
break
end
end
+ if not start then
+ break
+ end
end
end
- if start then start = start.next end
- else
- start = start.next
end
+ if start then start = start.next end
+ elseif id == whatsit then
+ local subtype = start.subtype
+ if subtype == 7 then
+ local dir = start.dir
+ if dir == "+TRT" then
+ rlmode = -1
+ elseif dir == "+TLT" then
+ rlmode = 1
+ else
+ rlmode = 0
+ end
+ elseif subtype == 6 then
+ local dir = start.dir
+ if dir == "TRT" then
+ rlmode = -1
+ elseif dir == "TLT" then
+ rlmode = 1
+ else
+ rlmode = 0
+ end
+ end
+ start = start.next
else
start = start.next
end
@@ -2960,6 +3072,8 @@ do
-- we can assume that languages that use marks are not hyphenated
-- we can also assume that at most one discretionary is present
+ local copy_list, slide, free = node.copy_list, node.slide, node.free
+
local function toligature(start,stop,char,markflag,discfound) -- brr head
if start ~= stop then
if discfound then
@@ -2974,8 +3088,8 @@ do
end
else
local deletemarks = markflag ~= "mark"
- start.components = node.copy_list(start,stop)
- node.slide(start.components)
+ start.components = copy_list(start,stop)
+ slide(start.components)
-- todo: components
start.subtype = 2
start.char = char
@@ -3015,11 +3129,11 @@ do
end
if next == stop then
stop = crap.prev
- node.free(crap)
+ free(crap)
break
else
next = nn
- node.free(crap)
+ free(crap)
end
else
next = nn
@@ -3030,10 +3144,10 @@ do
return start
end
- function fonts.otf.features.process.gsub_single(start,kind,lookupname,replacements)
+ function otf.features.process.gsub_single(start,kind,lookupname,replacements)
if replacements then
- if fonts.otf.trace_replacements then
- report("otf process",format("%s:%s replacing 0x%04X by 0x%04X",kind,lookupname,start.char,replacements))
+ if otf.trace_replacements then
+ report("otf process","%s:%s replacing 0x%04X by 0x%04X",kind,lookupname,start.char,replacements)
end
start.char = replacements
return start, true
@@ -3042,10 +3156,10 @@ do
end
end
- function fonts.otf.features.process.gsub_alternate(start,kind,lookupname,alternatives)
+ function otf.features.process.gsub_alternate(start,kind,lookupname,alternatives)
if alternatives then
- if fonts.otf.trace_replacements then
- report("otf process",format("%s:%s alternative 0x%04X => %s",kind,lookupname,start.char,table.hexed(alternatives)))
+ if otf.trace_replacements then
+ report("otf process","%s:%s alternative 0x%04X => %s",kind,lookupname,start.char,table.hexed(alternatives))
end
start.char = alternatives[1] -- will be preference
return start, true
@@ -3054,10 +3168,10 @@ do
end
end
- function fonts.otf.features.process.gsub_multiple(start,kind,lookupname,multiples)
+ function otf.features.process.gsub_multiple(start,kind,lookupname,multiples)
if multiples then
- if fonts.otf.trace_replacements then
- report("otf process",format("%s:%s multiple 0x%04X => %s",kind,lookupname,start.char,table.hexed(multiples)))
+ if otf.trace_replacements then
+ report("otf process","%s:%s multiple 0x%04X => %s",kind,lookupname,start.char,table.hexed(multiples))
end
start.char = multiples[1]
if #multiples > 1 then
@@ -3080,7 +3194,7 @@ do
end
end
- function fonts.otf.features.process.gsub_ligature(start,kind,lookupname,ligatures,alldata,flags)
+ function otf.features.process.gsub_ligature(start,kind,lookupname,ligatures,alldata,flags)
local s, stop, discfound = start.next, nil, false
while s do
local id = s.id
@@ -3110,15 +3224,15 @@ do
end
if stop and ligatures[2] then
start = toligature(start,stop,ligatures[2],flags[1],discfound)
- if fonts.otf.trace_ligatures then
- report("otf process",format("%s: inserting ligature 0x%04X (%s)",kind,start.char,utf.char(start.char)))
+ if otf.trace_ligatures then
+ report("otf process","%s: inserting ligature 0x%04X (%s)",kind,start.char,utf.char(start.char))
end
return start, true
end
return start, false
end
- function fonts.otf.features.process.gpos_mark2base(start,kind,lookupname,m_anchors,b_anchors)
+ function otf.features.process.gpos_mark2base(start,kind,lookupname,m_anchors,b_anchors)
local markchar = start.char
if marks[markchar] then
local markanchors = m_anchors['mark']
@@ -3139,9 +3253,9 @@ do
local factor = tfmdata.factor
local dx, dy = scale(ba[1]-ma[1],factor), scale(ba[2]-ma[2],factor)
start.xoffset, start.yoffset = component.xoffset - dx, component.yoffset + dy
- if fonts.otf.trace_anchors then
- report("otf process",format("%s: anchoring mark 0x%04X to basechar 0x%04X => (%s,%s) => (%s,%s)",
- kind,markchar,basechar,dx,dy,start.xoffset,start.yoffset))
+ if otf.trace_anchors then
+ report("otf process","%s: anchoring mark 0x%04X to basechar 0x%04X => (%s,%s) => (%s,%s)",
+ kind,markchar,basechar,dx,dy,start.xoffset,start.yoffset)
end
return start, true
end
@@ -3156,7 +3270,7 @@ do
return start, false
end
- function fonts.otf.features.process.gpos_mark2ligature(start,kind,lookupname,m_anchors,b_anchors) -- maybe use copies
+ function otf.features.process.gpos_mark2ligature(start,kind,lookupname,m_anchors,b_anchors) -- maybe use copies
local markchar = start.char
if marks[markchar] then
local markanchors = m_anchors['mark']
@@ -3180,9 +3294,9 @@ do
local factor = tfmdata.factor
local dx, dy = scale(ba[1]-ma[1],factor), scale(ba[2]-ma[2],factor)
start.xoffset, start.yoffset = component.xoffset - dx, component.yoffset + dy
- if fonts.otf.trace_anchors then
- report("otf process",format("%s: anchoring mark 0x%04X to baseligature 0x%04X => (%s,%s) => (%s,%s)",
- kind,markchar,basechar,dx,dy,component.xoffset,component.yoffset))
+ if otf.trace_anchors then
+ report("otf process","%s: anchoring mark 0x%04X to baseligature 0x%04X => (%s,%s) => (%s,%s)",
+ kind,markchar,basechar,dx,dy,component.xoffset,component.yoffset)
end
return start, true
end
@@ -3199,7 +3313,7 @@ do
return start, false
end
- function fonts.otf.features.process.gpos_mark2mark(start,kind,lookupname,b_anchors,m_anchors)
+ function otf.features.process.gpos_mark2mark(start,kind,lookupname,b_anchors,m_anchors)
local basemarkchar = start.char
--~ print(lookupname)
if marks[basemarkchar] then
@@ -3232,9 +3346,9 @@ do
local factor = tfmdata.factor
local dx, dy = scale(ba[1]-ma[1],factor), scale(ba[2]-ma[2],factor)
component.xoffset, component.yoffset = start.xoffset - dx, start.yoffset + dy
- if fonts.otf.trace_anchors then
- report("otf process",format("%s:%s:%s anchoring mark 0x%04X to basemark 0x%04X => (%s,%s) => (%s,%s)",
- kind,anchor,markattr,markchar,basemarkchar,dx,dy,component.xoffset,component.yoffset))
+ if otf.trace_anchors then
+ report("otf process","%s:%s:%s anchoring mark 0x%04X to basemark 0x%04X => (%s,%s) => (%s,%s)",
+ kind,anchor,markattr,markchar,basemarkchar,dx,dy,component.xoffset,component.yoffset)
end
return start, true
end
@@ -3250,80 +3364,112 @@ do
return start, false
end
- -- the following can be optimized, also, we can share the table (no need to collect)
-
- function fonts.otf.features.process.gpos_cursive(start,kind,lookupname,exitanchors,anchors)
- local trace = fonts.otf.trace_anchors
- local next, done, x, y, total_x, total_y, tx, ty, first = start.next, false, 0, 0, 0, 0, { }, { }, nil
- local factor = tfmdata.factor
- local function finish()
- local i = 0
- while first and first.id == glyph do
- if marks[first.char] then
- first = first.next
+ function otf.features.process.gpos_cursive(start,kind,lookupname,exitanchors,anchors)
+ local trace = otf.trace_cursive
+ if rlmode >= 0 then
+ local prev, done = start.prev, false
+ while prev do
+ if prev.id == glyph and prev.subtype<256 and prev.font == currentfont then
+ local prevchar = prev.char
+ if marks[prevchar] then
+ -- what do do with marks, give them the offset of the previous glyph?
+ prev = prev.prev
+ else
+ local startchar = start.char
+ local entryanchors, exitanchors = anchors[startchar], anchors[prevchar]
+ if entryanchors and exitanchors then
+ local centry, cexit = entryanchors['centry'], exitanchors['cexit']
+ if centry and cexit then
+ for anchor, entry in pairs(centry) do
+ local exit = cexit[anchor]
+ if exit then
+ local factor = tfmdata.factor
+ local dx = -(tfmdata.characters[prevchar].description.width-exit[1]) - entry[1]
+ local dy = -(entry[2]-exit[2])
+ start.yoffset = prev.yoffset + scale(dy, factor)
+ -- start.xoffset = scale(tx[i], factor)
+ node.insert_before(prev,start,nodes.kern(scale(dx,factor)))
+ if trace then
+ report("otf process","%s:%s move 0x%04X cursive (%s,%s)",kind,lookupname,startchar,dx,dy)
+ end
+ done = true
+ end
+ end
+ end
+ end
+ break
+ end
else
- i = i + 1
- first.yoffset = scale(total_y, factor)
+ break
+ end
+ end
+ else
+ local trace, factor = fonts.otf.trace_anchors, tfmdata.factor
+ local next, done, total_x, total_y, tx, ty, stack = start.next, false, 0, 0, { }, { }, { }
+ local function finish()
+ done = true
+ for i=1,#stack do
+ local s = stack[i]
+ s.yoffset = scale(total_y, factor)
+ node.insert_before(s.prev,s,nodes.kern(scale(tx[i],factor)))
if fonts.otf.trace_cursive then
- report("otf process",format("%s:%s move 0x%04X cursive (%s,%s)",kind,lookupname,first.char,"?",total_y))
- end
- if first == next then
- break
- else
- total_y = total_y - (ty[i] or 0)
- first = first.next
+ report("otf process",format("%s:%s move 0x%04X cursive (%s,%s)",kind,lookupname,s.char,tx[i],total_y))
end
+ total_y = total_y - (ty[i] or 0)
end
+ total_x, total_y, tx, ty, stack = 0, 0, { }, { }, { }
end
- x, y, total_x, total_y, tx, ty, first = 0, 0, 0, 0, { }, { }, nil
- end
- while next do
- if next.id == glyph and next.subtype<256 and next.font == currentfont then
- local nextchar = next.char
- if marks[nextchar] then
- next = next.next
- else
- local entryanchors, exitanchors = anchors[nextchar], anchors[start.char]
- if entryanchors and exitanchors then
- local centry, cexit = entryanchors['centry'], exitanchors['cexit']
- if centry and cexit then
- for anchor, entry in pairs(centry) do
- local exit = cexit[anchor]
- if exit then
- if not first then first = start end
- local dx, dy = exit[1] + entry[1], -exit[2] + entry[2]
- tx[#tx+1], ty[#ty+1] = dx, dy
- total_x, total_y = total_x + dx, total_y + dy
- done = true
- break
+ while next do
+ if next.id == glyph and next.subtype<256 and next.font == currentfont then
+ local nextchar = next.char
+ if marks[nextchar] then
+ next = next.next
+ else
+ local entryanchors, exitanchors = anchors[nextchar], anchors[start.char]
+ if entryanchors and exitanchors then
+ local centry, cexit = entryanchors['centry'], exitanchors['cexit']
+ if centry and cexit then
+ for anchor, entry in pairs(centry) do
+ local exit = cexit[anchor]
+ if exit then
+ local dy = -exit[2] + entry[2]
+ local dx = -(tfmdata.characters[nextchar].description.width-entry[1]) - exit[1] -- often width == entry 1
+ tx[#tx+1], ty[#ty+1] = dx, dy
+ total_x, total_y = total_x + dx, total_y + dy
+ stack[#stack+1] = start
+ break
+ end
end
+ else
+ finish()
end
else
finish()
end
- else
- finish()
+ start = next
+ next = start.next
end
- start = next
- next = start.next
+ else
+ finish()
+ break
end
- else
- finish()
- break
end
+ return start, done
end
return start, done
end
- function fonts.otf.features.process.gpos_single(start,kind,lookupname,basekerns,kerns)
+ function otf.features.process.gpos_single(start,kind,lookupname,basekerns,kerns)
report("otf process","gpos_single not yet supported")
return start, false
end
- function fonts.otf.features.process.gpos_pair(start,kind,lookupname,basekerns,kerns)
+ function otf.features.process.gpos_pair(start,kind,lookupname,basekerns,kerns)
local next, prev, done = start.next, start, false
- -- to be optimized
- local trace = fonts.otf.trace_kerns
+ -- to be optimized, we can consider using basemode for fonts without lookups
+ -- todo: kerns in disc nodes: pre, post, replace -> loop over disc too
+ -- todo: kerns in components of ligatures
+ local trace = otf.trace_kerns
local factor = tfmdata.factor
while next and next.id == glyph and next.subtype<256 and next.font == currentfont do
local cn = characters[next.char]
@@ -3347,12 +3493,12 @@ do
end
end
if b and b ~= 0 then
- report("otf process","we need to do something with the second kern xoff " .. b)
+ report("otf process","we need to do something with the second kern xoff %s",b)
end
else
-- todo, just start, next = node.insert_before(head,next,nodes.kern(scale(kern,factor)))
- if fonts.otf.trace_kerns then
- report("otf process",format("%s: inserting kern %s between 0x%04X and 0x%04X",kind,krn,prev.char,next.char))
+ if otf.trace_kerns then
+ report("otf process","%s: inserting kern %s between 0x%04X and 0x%04X",kind,krn,prev.char,next.char)
end
local k = nodes.kern(scale(krn,factor))
k.next = next
@@ -3366,6 +3512,103 @@ do
return start, done
end
+-- -- -- temp here, needs to be tested first -- -- --
+
+--~ function do_gpos_pair(start,kind,lookupname,basekerns,kerns)
+--~ local trace = otf.trace_kerns
+--~ local factor = tfmdata.factor
+--~ local next, prev, middle = start.next, start, nil
+--~ -- to be optimized, we can consider using basemode for fonts without lookups
+--~ -- todo: kerns in disc nodes: pre, post, replace -> loop over disc too
+--~ -- todo: kerns in components of ligatures
+--~ --
+--~ -- find valid next
+--~ while next do
+--~ local id = next.id
+--~ if id == glyph and next.subtype<256 and next.font == currentfont then
+--~ local cn = characters[next.char]
+--~ if not cn or cn.description.class == 'mark' then
+--~ prev = next
+--~ next = next.next
+--~ else
+--~ break
+--~ end
+--~ elseif id == disc then -- assume same font
+--~ middle = next
+--~ else
+--~ return start, false
+--~ end
+--~ end
+--~ local function inject(head, prevkern, nextkern)
+--~ if head then
+--~ -- kern between prevchar and head
+--~ local tail = node.slide(head) -- tail
+--~ if head.id == glyph then
+--~ local c = head.char
+--~ local pc = prevkern[c]
+--~ if pc then
+--~ local k = nodes.kern(scale(pc,factor))
+--~ k.next = head
+--~ head = k
+--~ end
+--~ end
+--~ -- kern between prevchar and tail
+--~ if tail.id == glyph then
+--~ local c = tail.char
+--~ local nc = nextkern[c]
+--~ if nc then
+--~ tail.next = nodes.kern(scale(nc,factor))
+--~ end
+--~ end
+--~ -- kern between head .. tail
+--~ local c = head
+--~ while c do do_gpos_pair(c,kind,lookupname,basekerns,kerns) ; c = c.next end
+--~ end
+--~ return head
+--~ end
+--~ if middle then
+--~ -- prev middle next - assumes same lookup
+--~ local prevkern, nextkern = kerns[prev.char], kerns[next.char]
+--~ local m = middle.pre ; if m then middle.pre = inject(m, prevkern, nextkern) end
+--~ local m = middle.post ; if m then middle.post = inject(m, prevkern, nextkern) end
+--~ local m = middle.replace ; if m then middle.replace = inject(m, prevkern, nextkern) end
+--~ elseif next then
+--~ local prevchar, nextchar = prev.char, next.char
+--~ if prev.components then
+--~ local prevkern, nextkern = kerns[prev.char], kerns[next.char]
+--~ local p = prev.components ; if p then prev.components = inject(p, prevkern, nextkern) end
+--~ end
+--~ local krn = basekerns[nextchar]
+--~ if not krn then
+--~ return start, false
+--~ elseif type(krn) == "table" then
+--~ local a, b = krn[3], krn[7]
+--~ if a and a ~= 0 then
+--~ start, next = node.insert_before(start,next,nodes.kern(scale(a,factor)))
+--~ if trace then
+--~ report("otf process","%s: inserting kern %s between 0x%04X and 0x%04X",kind,a,prevchar,nextchar)
+--~ end
+--~ end
+--~ if b and b ~= 0 then
+--~ report("otf process","we need to do something with the second kern xoff %s",b)
+--~ end
+--~ return start, true -- could be next
+--~ else
+--~ if otf.trace_kerns then
+--~ report("otf process","%s: inserting kern %s between 0x%04X and 0x%04X",kind,krn,prevchar,nextchar)
+--~ end
+--~ start, next = node.insert_before(start,next,nodes.kern(scale(krn,factor)))
+--~ return start, true -- could be next
+--~ end
+--~ end
+--~ return start, false
+--~ end
+
+--~ otf.features.process.gpos_pair = do_gpos_pair
+
+-- -- -- temp here, needs to be tested -- -- --
+
+
local chainprocs = { } -- we can probably optimize this because they're all internal lookups
-- For the moment we save each looked up glyph in the sequence, which is ok because
@@ -3374,7 +3617,7 @@ do
-- in order to locate them.
function chainprocs.gsub_single(start,stop,kind,lookupname,sequence,f,l,lookups)
- local trace = fonts.otf.trace_replacements
+ local trace = otf.trace_replacements
local c, r = trace and { }, trace and { }
local lookup, index, current = 1, f, start
while current ~= nil do
@@ -3419,7 +3662,7 @@ do
end
end
if trace then
- report("otf chain",format("%s: single replacement %s by %s",kind,table.hexed(c),table.hexed(r)))
+ report("otf chain","%s: single replacement %s by %s",kind,table.hexed(c),table.hexed(r))
end
return start
end
@@ -3454,8 +3697,8 @@ do
cacheslot[char] = replacement
end
end
- if fonts.otf.trace_replacements then
- report("otf chain",format("%s: replacing character 0x%04X by multiple 0x%04X",kind,char,table.hexed(replacement)))
+ if otf.trace_replacements then
+ report("otf chain","%s: replacing character 0x%04X by multiple 0x%04X",kind,char,table.hexed(replacement))
end
start.char = replacement[1]
if #replacement > 1 then
@@ -3505,8 +3748,8 @@ do
cacheslot[char] = replacement
end
end
- if fonts.otf.trace_replacements then
- report("otf chain",format("%s: replacing character 0x%04X by alternate",kind,char))
+ if otf.trace_replacements then
+ report("otf chain","%s: replacing character 0x%04X by alternate",kind,char)
end
start.char = replacement[1]
return start
@@ -3516,11 +3759,11 @@ do
if lookups then
local featurecache = fontdata[currentfont].shared.featurecache
if not featurecache[kind] then
- featurecache[kind] = fonts.otf.features.collect_ligatures(tfmdata,kind) -- double cached ?
+ featurecache[kind] = otf.features.collect_ligatures(tfmdata,kind) -- double cached ?
end
local lookups = otfdata.luatex.internals[lookups[1]].lookups
local ligaturecache = featurecache[kind]
- local trace = fonts.otf.trace_ligatures
+ local trace = otf.trace_ligatures
for i=1,#lookups do
local ligatures = ligaturecache[lookups[i]]
if ligatures and ligatures[start.char] then
@@ -3550,9 +3793,9 @@ do
if ligatures[2] then
if trace then
if start == stop then
- report("otf chain",format("%s: replacing character 0x%04X by ligature 0x%04X",kind,start.char,ligatures[2]))
+ report("otf chain","%s: replacing character 0x%04X by ligature 0x%04X",kind,start.char,ligatures[2])
else
- report("otf chain",format("%s: replacing character 0x%04X upto 0x%04X by ligature 0x%04X",kind,start.char,stop.char,ligatures[2]))
+ report("otf chain","%s: replacing character 0x%04X upto 0x%04X by ligature 0x%04X",kind,start.char,stop.char,ligatures[2])
end
end
return toligature(start,stop,ligatures[2],flags[1],discfound)
@@ -3584,8 +3827,8 @@ do
break
end
end
- if not ok and fonts.otf.trace_anchors then
- report("otf chain",format("%s: no matching mark2base anchor class for 0x%04X, lookup %s",kind,markchar,lookups[1]))
+ if not ok and otf.trace_anchors then
+ report("otf chain","%s: no matching mark2base anchor class for 0x%04X, lookup %s",kind,markchar,lookups[1])
end
end
if anchortag ~= true then
@@ -3608,9 +3851,9 @@ do
local factor = tfmdata.factor
local dx, dy = scale(ba[1]-ma[1],factor), scale(ba[2]-ma[2],factor)
start.xoffset, start.yoffset = component.xoffset - dx, component.yoffset + dy
- if fonts.otf.trace_anchors then
- report("otf chain",format("%s: anchoring mark 0x%04X to basechar 0x%04X => (%s,%s) => (%s,%s)",
- kind,markchar,basechar,dx,dy,start.xoffset,start.yoffset))
+ if otf.trace_anchors then
+ report("otf chain","%s: anchoring mark 0x%04X to basechar 0x%04X => (%s,%s) => (%s,%s)",
+ kind,markchar,basechar,dx,dy,start.xoffset,start.yoffset)
end
return start, true
end
@@ -3643,8 +3886,8 @@ do
break
end
end
- if not ok and fonts.otf.trace_anchors then
- report("otf chain",format("%s: no matching mark2ligature anchor class for 0x%04X, lookup %s",kind,markchar,lookups[1]))
+ if not ok and otf.trace_anchors then
+ report("otf chain","%s: no matching mark2ligature anchor class for 0x%04X, lookup %s",kind,markchar,lookups[1])
end
end
if anchortag ~= true then
@@ -3670,9 +3913,9 @@ do
local factor = tfmdata.factor
local dx, dy = scale(ba[1]-ma[1],factor), scale(ba[2]-ma[2],factor)
start.xoffset, start.yoffset = component.xoffset - dx, component.yoffset + dy
- if fonts.otf.trace_anchors then
- report("otf chain",format("%s: anchoring mark 0x%04X to baseligature 0x%04X => (%s,%s) => (%s,%s)",
- kind,basechar,markchar,dx,dy,start.xoffset,start.yoffset))
+ if otf.trace_anchors then
+ report("otf chain","%s: anchoring mark 0x%04X to baseligature 0x%04X => (%s,%s) => (%s,%s)",
+ kind,basechar,markchar,dx,dy,start.xoffset,start.yoffset)
end
return start, true
end
@@ -3707,8 +3950,8 @@ do
break
end
end
- if not ok and fonts.otf.trace_anchors then
- report("otf chain",format("%s: no matching mark2mark anchor class for 0x%04X, lookup %s",kind,markchar,lookups[1]))
+ if not ok and otf.trace_anchors then
+ report("otf chain","%s: no matching mark2mark anchor class for 0x%04X, lookup %s",kind,markchar,lookups[1])
end
end
if anchortag ~= true then
@@ -3718,7 +3961,7 @@ do
if baseattr == markattr then
local glyph = glyphs[characters[markchar].description.index]
if glyph.anchors and glyph.anchors[anchortag] then
- local trace = fonts.otf.trace_anchors
+ local trace = otf.trace_anchors
local done = false
local baseanchors = glyph.anchors['basemark'][anchortag]
while true do
@@ -3732,9 +3975,9 @@ do
local factor = tfmdata.factor
local dx, dy = scale(ba[1]-ma[1],factor), scale(ba[2]-ma[2],factor)
start.xoffset, start.yoffset = component.xoffset - dx, component.yoffset + dy
- if fonts.otf.trace_anchors then
- report("otf chain",format("%s: anchoring mark 0x%04X to basemark 0x%04X => (%s,%s) => (%s,%s)",
- kind,markchar,basechar,dx,dy,component.xoffset,component.yoffset))
+ if otf.trace_anchors then
+ report("otf chain","%s: anchoring mark 0x%04X to basemark 0x%04X => (%s,%s) => (%s,%s)",
+ kind,markchar,basechar,dx,dy,component.xoffset,component.yoffset)
end
done = true
break
@@ -3782,7 +4025,7 @@ do
-- what pointer to return, spec says stop
- function fonts.otf.features.process.contextchain(start,kind,lookupname,contextdata)
+ function otf.features.process.contextchain(start,kind,lookupname,contextdata)
local contexts, flags, done = contextdata.lookups, contextdata.flags, false
local skipmark, skipligature, skipbase = unpack(flags) -- unpack slower than assignment
for k=1,#contexts do
@@ -3799,16 +4042,21 @@ do
local id = last.id
if id == glyph and last.subtype<256 and last.font == currentfont then
local char = last.char
- local class = characters[char].description.class
- if class == skipmark or class == skipligature or class == skipbase then
- -- skip 'm
- last = last.next
- elseif sequence[n][char] then
- if n < l then
+ local chardata = characters[char]
+ if chardata then
+ local class = chardata.description.class
+ if class == skipmark or class == skipligature or class == skipbase then
+ -- skip 'm
last = last.next
+ elseif sequence[n][char] then
+ if n < l then
+ last = last.next
+ end
+ n = n + 1
+ else
+ match = false break
end
- n = n + 1
- else
+ else -- play safe
match = false break
end
elseif id == disc then -- what to do with kerns?
@@ -3823,36 +4071,33 @@ do
if match and f > 1 then
local prev = start.prev
if prev then
- if f == 2 then
- match = prev.id == glyph and prev.subtype<256 and prev.font == currentfont and sequence[1][prev.char]
- else
- local n = f-1
- while n >= 1 do
- if prev then
- local id = prev.id
- if id == glyph and prev.subtype<256 and prev.font == currentfont then -- normal char
- local char = prev.char
- local class = characters[char].description.class
- if class == skipmark or class == skipligature or class == skipbase then
- -- skip 'm
- elseif sequence[n][char] then
- n = n -1
- else
- match = false break
- end
- elseif id == disc then
+ -- removed optimiziation for f == 2, we have to deal with marks anyway
+ local n = f-1
+ while n >= 1 do
+ if prev then
+ local id = prev.id
+ if id == glyph and prev.subtype<256 and prev.font == currentfont then -- normal char
+ local char = prev.char
+ local class = characters[char].description.class
+ if class == skipmark or class == skipligature or class == skipbase then
-- skip 'm
- elseif sequence[n][32] then
+ elseif sequence[n][char] then
n = n -1
else
match = false break
end
- prev = prev.prev
+ elseif id == disc then
+ -- skip 'm
elseif sequence[n][32] then
n = n -1
else
match = false break
end
+ prev = prev.prev
+ elseif sequence[n][32] then
+ n = n -1
+ else
+ match = false break
end
end
elseif f == 2 then
@@ -3868,36 +4113,33 @@ do
if match and s > l then
local next = last.next
if next then
- if s-l == 1 then
- match = next.id == glyph and next.subtype<256 and next.font == currentfont and sequence[s][next.char]
- else
- local n = l+ 1
- while n <= s do
- if next then
- local id = next.id
- if id == glyph and next.subtype<256 and next.font == currentfont then -- normal char
- local char = next.char
- local class = characters[char].description.class
- if class == skipmark or class == skipligature or class == skipbase then
- -- skip 'm
- elseif sequence[n][char] then
- n = n + 1
- else
- match = false break
- end
- elseif id == disc then
+ -- removed optimiziation for s-l == 1, we have to deal with marks anyway
+ local n = l+ 1
+ while n <= s do
+ if next then
+ local id = next.id
+ if id == glyph and next.subtype<256 and next.font == currentfont then -- normal char
+ local char = next.char
+ local class = characters[char].description.class
+ if class == skipmark or class == skipligature or class == skipbase then
-- skip 'm
- elseif sequence[n][32] then -- brrr
+ elseif sequence[n][char] then
n = n + 1
else
match = false break
end
- next = next.next
- elseif sequence[n][32] then
+ elseif id == disc then
+ -- skip 'm
+ elseif sequence[n][32] then -- brrr
n = n + 1
else
match = false break
end
+ next = next.next
+ elseif sequence[n][32] then
+ n = n + 1
+ else
+ match = false break
end
end
elseif s-l == 1 then
@@ -3912,20 +4154,20 @@ do
end
end
if match then
- local trace = fonts.otf.trace_contexts
+ local trace = otf.trace_contexts
if trace then
local char = start.char
- report("otf chain",format("%s: rule %s of %s matches at char 0x%04X (%s) for (%s,%s,%s) chars, lookuptype %s",kind,rule,lookupname,char,utf.char(char),f-1,l-f+1,s-l,lookuptype))
+ report("otf chain","%s: rule %s of %s matches at char 0x%04X (%s) for (%s,%s,%s) chars, lookuptype %s",kind,rule,lookupname,char,utf.char(char),f-1,l-f+1,s-l,lookuptype)
end
if lookups then
local cp = chainprocs[lookuptype]
if cp then
start = cp(start,last,kind,lookupname,sequence,f,l,lookups,flags)
else
- report("otf chain",format("%s: lookuptype %s not supported yet for %s",kind,lookuptype,lookupname))
+ report("otf chain","%s: lookuptype %s not supported yet for %s",kind,lookuptype,lookupname)
end
elseif trace then
- report("otf chain",format("%s: skipping match for %s",kind,lookupname))
+ report("otf chain","%s: skipping match for %s",kind,lookupname)
end
done = true
break
@@ -3936,11 +4178,11 @@ do
--~ if true then
--~ if n < f then
---~ texio.write_nl(string.format("%s before %s %04x %s %s %s",lookupname,n,char,class,skipmark or "?",tostring(sequence[n][char])))
+--~ texio.write_nl(format("%s before %s %04x %s %s %s",lookupname,n,char,class,skipmark or "?",tostring(sequence[n][char])))
--~ elseif n > l then
---~ texio.write_nl(string.format("%s after %s %04x %s %s %s",lookupname,n,char,class,skipmark or "?",tostring(sequence[n][char])))
+--~ texio.write_nl(format("%s after %s %04x %s %s %s",lookupname,n,char,class,skipmark or "?",tostring(sequence[n][char])))
--~ else
---~ texio.write_nl(string.format("%s current %s %04x %s %s %s",lookupname,n,char,class,skipmark or "?",tostring(sequence[n][char])))
+--~ texio.write_nl(format("%s current %s %04x %s %s %s",lookupname,n,char,class,skipmark or "?",tostring(sequence[n][char])))
--~ end
--~ end
@@ -3948,7 +4190,7 @@ do
-- this needs to be fixed ! ! ! ! ! ! ! !
- function fonts.otf.features.process.reversecontextchain(start,kind,lookupname,contextdata)
+ function otf.features.process.reversecontextchain(start,kind,lookupname,contextdata)
-- PROBABLY WRONG, WE NEED TO WALK BACK OVER THE LIST
local done = false
local contexts = contextdata.lookups
@@ -3994,10 +4236,10 @@ do
end
end
if match then
- local trace = fonts.otf.trace_contexts
+ local trace = otf.trace_contexts
if trace then
local char = first.char
- report("otf reverse chain",format("%s: rule %s of %s matches, replacing starts at char 0x%04X (%s) lookuptype %s",kind,rule,lookupname,char,utf.char(char),lookuptype))
+ report("otf reverse chain","%s: rule %s of %s matches, replacing starts at char 0x%04X (%s) lookuptype %s",kind,rule,lookupname,char,utf.char(char),lookuptype)
end
if lookups then
local cp = chainprocs[lookuptype]
@@ -4008,10 +4250,10 @@ do
first = cp(first,last,kind,lookupname,sequence,f,l,lookups,flags)
end
else
- report("otf reverse chain",format("%s: lookuptype %s not supported yet for %s",kind,lookuptype,lookupname))
+ report("otf reverse chain","%s: lookuptype %s not supported yet for %s",kind,lookuptype,lookupname)
end
elseif trace then
- report("otf reverse chain",format("%s: skipping match for %s",kind,lookupname))
+ report("otf reverse chain","%s: skipping match for %s",kind,lookupname)
end
done = true
break
@@ -4020,18 +4262,18 @@ do
return start, done
end
- fonts.otf.features.process.gsub_context = fonts.otf.features.process.contextchain
- fonts.otf.features.process.gsub_contextchain = fonts.otf.features.process.contextchain
- fonts.otf.features.process.gsub_reversecontextchain = fonts.otf.features.process.reversecontextchain
+ otf.features.process.gsub_context = otf.features.process.contextchain
+ otf.features.process.gsub_contextchain = otf.features.process.contextchain
+ otf.features.process.gsub_reversecontextchain = otf.features.process.reversecontextchain
- fonts.otf.features.process.gpos_contextchain = fonts.otf.features.process.contextchain
- fonts.otf.features.process.gpos_context = fonts.otf.features.process.contextchain
+ otf.features.process.gpos_contextchain = otf.features.process.contextchain
+ otf.features.process.gpos_context = otf.features.process.contextchain
end
do
- local process = fonts.otf.features.process.feature
+ local process = otf.features.process.feature
function fonts.methods.node.otf.aalt(head,font,attr) return process(head,font,attr,'aalt') end
function fonts.methods.node.otf.abvm(head,font,attr) return process(head,font,attr,'abvm') end
@@ -4089,6 +4331,7 @@ do
function fonts.methods.node.otf.pstf(head,font,attr) return process(head,font,attr,'pstf') end
function fonts.methods.node.otf.rlig(head,font,attr) return process(head,font,attr,'rlig') end
function fonts.methods.node.otf.rphf(head,font,attr) return process(head,font,attr,'rphf') end
+ function fonts.methods.node.otf.rtla(head,font,attr) return process(head,font,attr,'rtla') end
function fonts.methods.node.otf.salt(head,font,attr) return process(head,font,attr,'calt') end
function fonts.methods.node.otf.sinf(head,font,attr) return process(head,font,attr,'sinf') end
function fonts.methods.node.otf.smcp(head,font,attr) return process(head,font,attr,'smcp') end
@@ -4116,47 +4359,47 @@ end
-- common stuff
-function fonts.otf.features.language(tfmdata,value)
+function otf.features.language(tfmdata,value)
if value then
value = value:lower()
- if fonts.otf.tables.languages[value] then
+ if otf.tables.languages[value] then
tfmdata.language = value
end
end
end
-function fonts.otf.features.script(tfmdata,value)
+function otf.features.script(tfmdata,value)
if value then
value = value:lower()
- if fonts.otf.tables.scripts[value] then
+ if otf.tables.scripts[value] then
tfmdata.script = value
end
end
end
-function fonts.otf.features.mode(tfmdata,value)
+function otf.features.mode(tfmdata,value)
if value then
tfmdata.mode = value:lower()
end
end
-function fonts.otf.features.strategy(tfmdata,value)
+function otf.features.strategy(tfmdata,value)
if value then
- tfmdata.strategy = tonumber(value) or fonts.otf.strategy
+ tfmdata.strategy = tonumber(value) or otf.strategy
end
end
-fonts.initializers.base.otf.language = fonts.otf.features.language
-fonts.initializers.base.otf.script = fonts.otf.features.script
-fonts.initializers.base.otf.mode = fonts.otf.features.mode
-fonts.initializers.base.otf.method = fonts.otf.features.mode
-fonts.initializers.base.otf.strategy = fonts.otf.features.strategy -- not needed
+fonts.initializers.base.otf.language = otf.features.language
+fonts.initializers.base.otf.script = otf.features.script
+fonts.initializers.base.otf.mode = otf.features.mode
+fonts.initializers.base.otf.method = otf.features.mode
+fonts.initializers.base.otf.strategy = otf.features.strategy -- not needed
-fonts.initializers.node.otf.language = fonts.otf.features.language
-fonts.initializers.node.otf.script = fonts.otf.features.script
-fonts.initializers.node.otf.mode = fonts.otf.features.mode
-fonts.initializers.node.otf.method = fonts.otf.features.mode
-fonts.initializers.node.otf.strategy = fonts.otf.features.strategy
+fonts.initializers.node.otf.language = otf.features.language
+fonts.initializers.node.otf.script = otf.features.script
+fonts.initializers.node.otf.mode = otf.features.mode
+fonts.initializers.node.otf.method = otf.features.mode
+fonts.initializers.node.otf.strategy = otf.features.strategy
do
@@ -4192,7 +4435,7 @@ do
always = true
}
- function fonts.otf.enhance.enrich(data,filename)
+ function otf.enhance.enrich(data,filename)
for index, glyph in pairs(data.glyphs) do
local l = tlig_list[glyph.name]
if l then
@@ -4217,11 +4460,11 @@ do
table.insert(data.gsub,1,table.fastcopy(trep_feature))
end
- local prepare = fonts.otf.features.prepare.feature
- local process = fonts.otf.features.process.feature
+ local prepare = otf.features.prepare.feature
+ local process = otf.features.process.feature
- fonts.otf.tables.features['tlig'] = 'TeX Ligatures'
- fonts.otf.tables.features['trep'] = 'TeX Replacements'
+ otf.tables.features['tlig'] = 'TeX Ligatures'
+ otf.tables.features['trep'] = 'TeX Replacements'
function fonts.initializers.node.otf.tlig(tfm,value) return prepare(tfm,'tlig',value) end
function fonts.initializers.node.otf.trep(tfm,value) return prepare(tfm,'trep',value) end
@@ -4229,8 +4472,8 @@ do
function fonts.methods.node.otf.tlig(head,font,attr) return process(head,font,attr,'tlig') end
function fonts.methods.node.otf.trep(head,font,attr) return process(head,font,attr,'trep') end
- function fonts.initializers.base.otf.tlig(tfm,value) fonts.otf.features.prepare_base_substitutions(tfm,'tlig',value) end
- function fonts.initializers.base.otf.trep(tfm,value) fonts.otf.features.prepare_base_substitutions(tfm,'trep',value) end
+ function fonts.initializers.base.otf.tlig(tfm,value) otf.features.prepare_base_substitutions(tfm,'tlig',value) end
+ function fonts.initializers.base.otf.trep(tfm,value) otf.features.prepare_base_substitutions(tfm,'trep',value) end
end
@@ -4275,13 +4518,13 @@ fonts.initializers.node.otf.compose = fonts.initializers.common.compose
-- temp hack, may change
function fonts.initializers.base.otf.kern(tfmdata,value)
- fonts.otf.features.prepare_base_kerns(tfmdata,'kern',value)
+ otf.features.prepare_base_kerns(tfmdata,'kern',value)
end
-- bonus function
-function fonts.otf.name_to_slot(name) -- todo: afm en tfm
- local tfmdata = fonts.tfm.id[font.current()]
+function otf.name_to_slot(name) -- todo: afm en tfm
+ local tfmdata = tfm.id[font.current()]
if tfmdata and tfmdata.shared then
local otfdata = tfmdata.shared.otfdata
if otfdata and otfdata.luatex then
@@ -4291,18 +4534,18 @@ function fonts.otf.name_to_slot(name) -- todo: afm en tfm
return nil
end
-function fonts.otf.char(n) -- todo: afm en tfm
+function otf.char(n) -- todo: afm en tfm
if type(n) == "string" then
- n = fonts.otf.name_to_slot(n)
+ n = otf.name_to_slot(n)
end
if n then
- tex.sprint(tex.ctxcatcodes,string.format("\\char%s ",n))
+ tex.sprint(tex.ctxcatcodes,format("\\char%s ",n))
end
end
---~ function fonts.otf.name_to_table(name)
+--~ function otf.name_to_table(name)
--~ lcoal temp, result = { }
---~ local tfmdata = fonts.tfm.id[font.current()]
+--~ local tfmdata = tfm.id[font.current()]
--~ if tfmdata and tfmdata.shared then
--~ local otfdata = tfmdata.shared.otfdata
--~ if otfdata and otfdata.luatex then
@@ -4329,13 +4572,14 @@ do
local glue = node.id('glue')
local penalty = node.id('penalty')
- local fontdata = fonts.tfm.id
+ local fontdata = tfm.id
local set_attribute = node.set_attribute
local has_attribute = node.has_attribute
local state = attributes.numbers['state'] or 100
local fcs = fonts.color.set
local fcr = fonts.color.reset
+ local remove = node.remove
-- in the future we will use language/script attributes instead of the
-- font related value, but then we also need dynamic features which is
@@ -4387,8 +4631,8 @@ do
return head, false
end
- fonts.otf.features.register("analyze",true) -- we always analyze
- table.insert(fonts.triggers,"analyze") -- we need a proper function for doing this
+ otf.features.register("analyze",true) -- we always analyze
+ table.insert(fonts.triggers,"analyze") -- we need a proper function for doing this
-- latin
@@ -4424,7 +4668,7 @@ do
local function warning(current,what)
local char = current.char
if not arab_warned[char] then
- log.report("analyze",string.format("arab: character %s (0x%04X) has no %s class", char, char, what))
+ log.report("analyze","arab: character %s (0x%04X) has no %s class", char, char, what)
arab_warned[char] = true
end
end
@@ -4438,15 +4682,19 @@ do
return head, true
end
+ otf.remove_joiners = true -- for idris who want it as option
+
function fonts.analyzers.methods.arab(head,font,attr) -- maybe make a special version with no trace
local characters = fontdata[font].characters
local first, last, current, done = nil, nil, head, false
- local trace = fonts.color.trace
+ local trace, removejoiners = fonts.color.trace, otf.remove_joiners
--~ local laststate = 0
+ local joiners = { }
local function finish()
if last then
if first == last then
- if isol_fina_medi_init[first.char] or isol_fina[first.char] then
+ local fc = first.char
+ if isol_fina_medi_init[fc] or isol_fina[fc] then
set_attribute(first,state,4) -- isol
if trace then fcs(first,"font:isol") end
else
@@ -4455,7 +4703,8 @@ do
if trace then fcr(first) end
end
else
- if isol_fina_medi_init[last.char] or isol_fina[last.char] then -- why isol here ?
+ local lc = last.char
+ if isol_fina_medi_init[lc] or isol_fina[lc] then -- why isol here ?
-- if laststate == 1 or laststate == 2 or laststate == 4 then
set_attribute(last,state,3) -- fina
if trace then fcs(last,"font:fina") end
@@ -4468,7 +4717,8 @@ do
first, last = nil, nil
elseif first then
-- first and last are either both set so we never com here
- if isol_fina_medi_init[first.char] or isol_fina[first.char] then
+ local fc = first.char
+ if isol_fina_medi_init[fc] or isol_fina[fc] then
set_attribute(first,state,4) -- isol
if trace then fcs(first,"font:isol") end
else
@@ -4481,21 +4731,19 @@ do
--~ laststate = 0
end
while current do
- if current.id == glyph and current.subtype<256 and current.font == font then
+ if current.id == glyph and current.subtype<256 and current.font == font and not has_attribute(current,state) then
done = true
+ -- some day we will make a characters.marks hash
+ -- this is also more efficient since it's shared
local char = current.char
- local chardata = characters[char] -- some day we will make a characters.marks hash
- if not chardata then -- this is also more efficient since it's shared
- -- troubles
- -- elseif char == zwj then
- -- -- can probably be ignored, we could turn it into a kern or penalty
- -- elseif char == zwnj then
- -- -- acts like a space, we could turn it into a kern or penalty
- -- finish()
- elseif chardata.description.class == "mark" then
+ local chardata = characters[char]
+ if removejoiners and char == zwj or char == zwnj then
+ joiners[#joiners+1] = current
+ end
+ if chardata and chardata.description.class == "mark" then
set_attribute(current,state,5) -- mark
if trace then fcs(current,"font:mark") end
- elseif isol[char] then
+ elseif isol[char] then -- can be zwj or zwnj too
finish()
set_attribute(current,state,4) -- isol
if trace then fcs(current,"font:isol") end
@@ -4543,6 +4791,11 @@ do
current = current.next
end
finish()
+ if removejoiners then
+ for i=1,#joiners do
+ head = remove(head,joiners[i])
+ end
+ end
return head, done
end
@@ -4675,6 +4928,8 @@ do
(char>=0x2F800 and char<=0x2FA1F)
end
+ -- mayeb an entry in the character table: hanclass
+
--~ opening_parenthesis_hw / closing_parenthesis_hw
--~ opening_parenthesis_fw / closing_parenthesis_fw
--~ opening_punctuation_hw / closing_punctuation_hw
@@ -4721,7 +4976,8 @@ do
local interspecialshrink = stretch * hang_data.inter_char_half_shrink_factor
local internormalstretch = stretch * hang_data.inter_char_stretch_factor
local trace = fonts.color.trace
--- todo: check for first and last
+ -- todo: check for first and last
+-- maybe it's better to look back
while current do
if current.id == glyph and current.subtype<256 then
if current.font == font then
@@ -4730,9 +4986,9 @@ do
-- don't ask -)
elseif opening_punctuation_fw[char] or opening_parenthesis_fw[char] then
if trace then fcs(current,"font:init") end
-if head ~= current then
- head, _ = insert_before(head,current,nodes.glue(interspecialskip,0,interspecialshrink))
-end
+ if head ~= current then
+ head, _ = insert_before(head,current,nodes.glue(interspecialskip,0,interspecialshrink))
+ end
head, current = insert_after(head,current,nodes.penalty(10000))
head, current = insert_after(head,current,nodes.glue(0,internormalstretch,0))
prevclass, done = 1, true
@@ -4773,6 +5029,7 @@ end
head, current = insert_after(head,current,nodes.glue(0,internormalstretch,0))
prevclass, done = 6, true
elseif is_han_character(char) then
+ -- if trace then fcs(current,"font:isol") end
prevclass, done = 7, true
head, current = insert_after(head,current,nodes.penalty(0))
head, current = insert_after(head,current,nodes.glue(0,internormalstretch,0))
@@ -4781,7 +5038,11 @@ end
prevclass = 0
end
elseif prevclass > 0 and current.id == glue and current.spec and current.spec.width > 0 then
- head, current = delete(head,current)
+ -- hack, it might be better to look back and flush (we need to delete end-of-line spaces)
+ local next = current.next
+ if next.id == glyph and next.font == font then
+ head, current = delete(head,current)
+ end
end
if current then
current = current.next
@@ -4797,14 +5058,14 @@ end
-- experimental and will probably change
do
- local process = fonts.otf.features.process.feature
- local prepare = fonts.otf.features.prepare.feature
+ local process = otf.features.process.feature
+ local prepare = otf.features.prepare.feature
function fonts.install_feature(type,...)
if fonts[type] and fonts[type].install_feature then
fonts[type].install_feature(...)
end
end
- function fonts.otf.install_feature(tag)
+ function otf.install_feature(tag)
fonts.methods.node.otf [tag] = function(head,font,attr) return process(head,font,attr,tag) end
fonts.initializers.node.otf[tag] = function(tfm,value) return prepare(tfm,tag,value) end
end