summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKhaled Hosny <khaledhosny@eglug.org>2010-10-28 19:38:16 +0200
committerKhaled Hosny <khaledhosny@eglug.org>2010-10-28 21:01:07 +0200
commit808e70bd7ccff7c25c4e1979bf9eec204ed8cb3c (patch)
treea05c80b7ee54f0c2e5829f6b88daa9bb49de3c50
parente730ef56664f9394270348cad7176f72cc411e48 (diff)
downloadluaotfload-808e70bd7ccff7c25c4e1979bf9eec204ed8cb3c.tar.gz
Sync with context 2010.10.22
This is a big sync and things might be seriously broken.
-rw-r--r--otfl-data-con.lua13
-rw-r--r--otfl-font-cid.lua48
-rw-r--r--otfl-font-def.lua276
-rw-r--r--otfl-font-dum.lua121
-rw-r--r--otfl-font-ini.lua47
-rw-r--r--otfl-font-map.lua69
-rw-r--r--otfl-font-ota.lua62
-rw-r--r--otfl-font-otb.lua59
-rw-r--r--otfl-font-otc.lua173
-rw-r--r--otfl-font-otd.lua42
-rw-r--r--otfl-font-otf.lua1789
-rw-r--r--otfl-font-oti.lua37
-rw-r--r--otfl-font-otn.lua288
-rw-r--r--otfl-font-ott.lua155
-rw-r--r--otfl-font-tfm.lua206
-rw-r--r--otfl-font-xtx.lua75
-rw-r--r--otfl-luat-dum.lua24
-rw-r--r--otfl-node-dum.lua30
-rw-r--r--otfl-node-inj.lua76
19 files changed, 1938 insertions, 1652 deletions
diff --git a/otfl-data-con.lua b/otfl-data-con.lua
index e7bb8af..5d9650f 100644
--- a/otfl-data-con.lua
+++ b/otfl-data-con.lua
@@ -25,13 +25,15 @@ table structures without bothering about the disk cache.</p>
<p>Examples of usage can be found in the font related code.</p>
--ldx]]--
-containers = containers or { }
-
+containers = containers or { }
+local containers = containers
containers.usecache = true
+local report_cache = logs.new("cache")
+
local function report(container,tag,name)
if trace_cache or trace_containers then
- logs.report(format("%s cache",container.subcategory),"%s: %s",tag,name or 'invalid')
+ report_cache("container: %s, tag: %s, name: %s",container.subcategory,tag,name or 'invalid')
end
end
@@ -48,7 +50,8 @@ local mt = {
t.readables = readables
return readables
end
- end
+ end,
+ __storage__ = true
}
function containers.define(category, subcategory, version, enabled)
@@ -78,7 +81,7 @@ function containers.define(category, subcategory, version, enabled)
end
function containers.is_usable(container, name)
- return container.enabled and caches and caches.iswritable(container.writable, name)
+ return container.enabled and caches and caches.is_writable(container.writable, name)
end
function containers.is_valid(container, name)
diff --git a/otfl-font-cid.lua b/otfl-font-cid.lua
index d1c727a..1d03bca 100644
--- a/otfl-font-cid.lua
+++ b/otfl-font-cid.lua
@@ -12,11 +12,14 @@ local lpegmatch = lpeg.match
local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
-fonts = fonts or { }
-fonts.cid = fonts.cid or { }
-fonts.cid.map = fonts.cid.map or { }
-fonts.cid.max = fonts.cid.max or 10
+local report_otf = logs.new("load otf")
+local fonts = fonts
+
+fonts.cid = fonts.cid or { }
+local cid = fonts.cid
+cid.map = cid.map or { }
+cid.max = cid.max or 10
-- original string parser: 0.109, lpeg parser: 0.036 seconds for Adobe-CNS1-4.cidmap
--
@@ -25,12 +28,14 @@ fonts.cid.max = fonts.cid.max or 10
-- 1..95 0020
-- 99 3000
-local number = lpeg.C(lpeg.R("09","af","AF")^1)
-local space = lpeg.S(" \n\r\t")
+local P, S, R, C = lpeg.P, lpeg.S, lpeg.R, lpeg.C
+
+local number = C(R("09","af","AF")^1)
+local space = S(" \n\r\t")
local spaces = space^0
-local period = lpeg.P(".")
+local period = P(".")
local periods = period * period
-local name = lpeg.P("/") * lpeg.C((1-space)^1)
+local name = P("/") * C((1-space)^1)
local unicodes, names = { }, { }
@@ -58,7 +63,7 @@ local grammar = lpeg.P { "start",
named = (number * spaces * name) / do_name
}
-function fonts.cid.load(filename)
+function cid.load(filename)
local data = io.loaddata(filename)
if data then
unicodes, names = { }, { }
@@ -79,23 +84,22 @@ end
local template = "%s-%s-%s.cidmap"
-
local function locate(registry,ordering,supplement)
local filename = format(template,registry,ordering,supplement)
local hashname = lower(filename)
- local cidmap = fonts.cid.map[hashname]
+ local cidmap = cid.map[hashname]
if not cidmap then
if trace_loading then
- logs.report("load otf","checking cidmap, registry: %s, ordering: %s, supplement: %s, filename: %s",registry,ordering,supplement,filename)
+ report_otf("checking cidmap, registry: %s, ordering: %s, supplement: %s, filename: %s",registry,ordering,supplement,filename)
end
- local fullname = resolvers.find_file(filename,'cid') or ""
+ local fullname = resolvers.findfile(filename,'cid') or ""
if fullname ~= "" then
- cidmap = fonts.cid.load(fullname)
+ cidmap = cid.load(fullname)
if cidmap then
if trace_loading then
- logs.report("load otf","using cidmap file %s",filename)
+ report_otf("using cidmap file %s",filename)
end
- fonts.cid.map[hashname] = cidmap
+ cid.map[hashname] = cidmap
cidmap.usedname = file.basename(filename)
return cidmap
end
@@ -104,18 +108,18 @@ local function locate(registry,ordering,supplement)
return cidmap
end
-function fonts.cid.getmap(registry,ordering,supplement)
+function cid.getmap(registry,ordering,supplement)
-- cf Arthur R. we can safely scan upwards since cids are downward compatible
local supplement = tonumber(supplement)
if trace_loading then
- logs.report("load otf","needed cidmap, registry: %s, ordering: %s, supplement: %s",registry,ordering,supplement)
+ report_otf("needed cidmap, registry: %s, ordering: %s, supplement: %s",registry,ordering,supplement)
end
local cidmap = locate(registry,ordering,supplement)
if not cidmap then
local cidnum = nil
-- next highest (alternatively we could start high)
- if supplement < fonts.cid.max then
- for supplement=supplement+1,fonts.cid.max do
+ if supplement < cid.max then
+ for supplement=supplement+1,cid.max do
local c = locate(registry,ordering,supplement)
if c then
cidmap, cidnum = c, supplement
@@ -137,8 +141,8 @@ function fonts.cid.getmap(registry,ordering,supplement)
if cidmap and cidnum > 0 then
for s=0,cidnum-1 do
filename = format(template,registry,ordering,s)
- if not fonts.cid.map[filename] then
- fonts.cid.map[filename] = cidmap -- copy of ref
+ if not cid.map[filename] then
+ cid.map[filename] = cidmap -- copy of ref
end
end
end
diff --git a/otfl-font-def.lua b/otfl-font-def.lua
index 8e64872..aac69ed 100644
--- a/otfl-font-def.lua
+++ b/otfl-font-def.lua
@@ -10,45 +10,54 @@ local format, concat, gmatch, match, find, lower = string.format, table.concat,
local tostring, next = tostring, next
local lpegmatch = lpeg.match
+local allocate = utilities.storage.allocate
+
local trace_defining = false trackers .register("fonts.defining", function(v) trace_defining = v end)
local directive_embedall = false directives.register("fonts.embedall", function(v) directive_embedall = v end)
trackers.register("fonts.loading", "fonts.defining", "otf.loading", "afm.loading", "tfm.loading")
trackers.register("fonts.all", "fonts.*", "otf.*", "afm.*", "tfm.*")
+local report_define = logs.new("define fonts")
+local report_afm = logs.new("load afm")
+
--[[ldx--
<p>Here we deal with defining fonts. We do so by intercepting the
default loader that only handles <l n='tfm'/>.</p>
--ldx]]--
-fonts = fonts or { }
-fonts.define = fonts.define or { }
-fonts.tfm = fonts.tfm or { }
-fonts.ids = fonts.ids or { }
-fonts.vf = fonts.vf or { }
-fonts.used = fonts.used or { }
+local fonts = fonts
+local tfm = fonts.tfm
+local vf = fonts.vf
+local fontcsnames = fonts.csnames
+
+fonts.used = allocate()
-local tfm = fonts.tfm
-local vf = fonts.vf
-local define = fonts.define
+tfm.readers = tfm.readers or { }
+tfm.fonts = allocate()
+tfm.internalized = allocate() -- internal tex numbers
-tfm.version = 1.01
-tfm.cache = containers.define("fonts", "tfm", tfm.version, false) -- better in font-tfm
+local readers = tfm.readers
+local sequence = allocate { 'otf', 'ttf', 'afm', 'tfm' }
+readers.sequence = sequence
-define.method = "afm or tfm" -- afm, tfm, afm or tfm, tfm or afm
-define.specify = fonts.define.specify or { }
-define.methods = fonts.define.methods or { }
+tfm.version = 1.01
+tfm.cache = containers.define("fonts", "tfm", tfm.version, false) -- better in font-tfm
+tfm.autoprefixedafm = true -- this will become false some day (catches texnansi-blabla.*)
-tfm.fonts = tfm.fonts or { }
-tfm.readers = tfm.readers or { }
-tfm.internalized = tfm.internalized or { } -- internal tex numbers
+fonts.definers = fonts.definers or { }
+local definers = fonts.definers
-tfm.readers.sequence = { 'otf', 'ttf', 'afm', 'tfm' }
+definers.specifiers = definers.specifiers or { }
+local specifiers = definers.specifiers
-tfm.auto_afm = true
+specifiers.variants = allocate()
+local variants = specifiers.variants
-local readers = tfm.readers
-local sequence = readers.sequence
+definers.method = "afm or tfm" -- afm, tfm, afm or tfm, tfm or afm
+definers.methods = definers.methods or { }
+
+local findbinfile = resolvers.findbinfile
--[[ldx--
<p>We hardly gain anything when we cache the final (pre scaled)
@@ -77,7 +86,7 @@ and prepares a table that will move along as we proceed.</p>
-- name name(sub) name(sub)*spec name*spec
-- name@spec*oeps
-local splitter, specifiers = nil, ""
+local splitter, splitspecifiers = nil, ""
local P, C, S, Cc = lpeg.P, lpeg.C, lpeg.S, lpeg.Cc
@@ -86,13 +95,13 @@ local right = P(")")
local colon = P(":")
local space = P(" ")
-define.defaultlookup = "file"
+definers.defaultlookup = "file"
local prefixpattern = P(false)
-function define.add_specifier(symbol)
- specifiers = specifiers .. symbol
- local method = S(specifiers)
+local function addspecifier(symbol)
+ splitspecifiers = splitspecifiers .. symbol
+ local method = S(splitspecifiers)
local lookup = C(prefixpattern) * colon
local sub = left * C(P(1-left-right-method)^1) * right
local specification = C(method) * C(P(1)^1)
@@ -100,36 +109,36 @@ function define.add_specifier(symbol)
splitter = P((lookup + Cc("")) * name * (sub + Cc("")) * (specification + Cc("")))
end
-function define.add_lookup(str,default)
+local function addlookup(str,default)
prefixpattern = prefixpattern + P(str)
end
-define.add_lookup("file")
-define.add_lookup("name")
-define.add_lookup("spec")
+definers.addlookup = addlookup
+
+addlookup("file")
+addlookup("name")
+addlookup("spec")
-function define.get_specification(str)
+local function getspecification(str)
return lpegmatch(splitter,str)
end
-function define.register_split(symbol,action)
- define.add_specifier(symbol)
- define.specify[symbol] = action
+definers.getspecification = getspecification
+
+function definers.registersplit(symbol,action)
+ addspecifier(symbol)
+ variants[symbol] = action
end
-function define.makespecification(specification, lookup, name, sub, method, detail, size)
+function definers.makespecification(specification, lookup, name, sub, method, detail, size)
size = size or 655360
if trace_defining then
- logs.report("define font","%s -> lookup: %s, name: %s, sub: %s, method: %s, detail: %s",
+ report_define("%s -> lookup: %s, name: %s, sub: %s, method: %s, detail: %s",
specification, (lookup ~= "" and lookup) or "[file]", (name ~= "" and name) or "-",
(sub ~= "" and sub) or "-", (method ~= "" and method) or "-", (detail ~= "" and detail) or "-")
end
---~ if specification.lookup then
---~ lookup = specification.lookup -- can come from xetex [] syntax
---~ specification.lookup = nil
---~ end
if not lookup or lookup == "" then
- lookup = define.defaultlookup
+ lookup = definers.defaultlookup
end
local t = {
lookup = lookup, -- forced type
@@ -146,10 +155,10 @@ function define.makespecification(specification, lookup, name, sub, method, deta
return t
end
-function define.analyze(specification, size)
+function definers.analyze(specification, size)
-- can be optimized with locals
- local lookup, name, sub, method, detail = define.get_specification(specification or "")
- return define.makespecification(specification, lookup, name, sub, method, detail, size)
+ local lookup, name, sub, method, detail = getspecification(specification or "")
+ return definers.makespecification(specification, lookup, name, sub, method, detail, size)
end
--[[ldx--
@@ -158,7 +167,7 @@ end
local sortedhashkeys = table.sortedhashkeys
-function tfm.hash_features(specification)
+function tfm.hashfeatures(specification)
local features = specification.features
if features then
local t = { }
@@ -190,7 +199,7 @@ function tfm.hash_features(specification)
return "unknown"
end
-fonts.designsizes = { }
+fonts.designsizes = allocate()
--[[ldx--
<p>In principle we can share tfm tables when we are in node for a font, but then
@@ -200,14 +209,14 @@ when we get rid of base mode we can optimize even further by sharing, but then w
loose our testcases for <l n='luatex'/>.</p>
--ldx]]--
-function tfm.hash_instance(specification,force)
+function tfm.hashinstance(specification,force)
local hash, size, fallbacks = specification.hash, specification.size, specification.fallbacks
if force or not hash then
- hash = tfm.hash_features(specification)
+ hash = tfm.hashfeatures(specification)
specification.hash = hash
end
if size < 1000 and fonts.designsizes[hash] then
- size = math.round(tfm.scaled(size, fonts.designsizes[hash]))
+ size = math.round(tfm.scaled(size,fonts.designsizes[hash]))
specification.size = size
end
--~ local mathsize = specification.mathsize or 0
@@ -231,11 +240,12 @@ end
<p>We can resolve the filename using the next function:</p>
--ldx]]--
-define.resolvers = resolvers
+definers.resolvers = definers.resolvers or { }
+local resolvers = definers.resolvers
-- todo: reporter
-function define.resolvers.file(specification)
+function resolvers.file(specification)
local suffix = file.suffix(specification.name)
if fonts.formats[suffix] then
specification.forced = suffix
@@ -243,7 +253,7 @@ function define.resolvers.file(specification)
end
end
-function define.resolvers.name(specification)
+function resolvers.name(specification)
local resolve = fonts.names.resolve
if resolve then
local resolved, sub = fonts.names.resolve(specification)
@@ -258,11 +268,11 @@ function define.resolvers.name(specification)
end
end
else
- define.resolvers.file(specification)
+ resolvers.file(specification)
end
end
-function define.resolvers.spec(specification)
+function resolvers.spec(specification)
local resolvespec = fonts.names.resolvespec
if resolvespec then
specification.resolved, specification.sub = fonts.names.resolvespec(specification)
@@ -271,13 +281,13 @@ function define.resolvers.spec(specification)
specification.name = file.removesuffix(specification.resolved)
end
else
- define.resolvers.name(specification)
+ resolvers.name(specification)
end
end
-function define.resolve(specification)
+function definers.resolve(specification)
if not specification.resolved or specification.resolved == "" then -- resolved itself not per se in mapping hash
- local r = define.resolvers[specification.lookup]
+ local r = resolvers[specification.lookup]
if r then
r(specification)
end
@@ -287,7 +297,16 @@ function define.resolve(specification)
else
specification.forced = specification.forced
end
- specification.hash = lower(specification.name .. ' @ ' .. tfm.hash_features(specification))
+ -- for the moment here (goodies set outside features)
+ local goodies = specification.goodies
+ if goodies and goodies ~= "" then
+ local normalgoodies = specification.features.normal.goodies
+ if not normalgoodies or normalgoodies == "" then
+ specification.features.normal.goodies = goodies
+ end
+ end
+ --
+ specification.hash = lower(specification.name .. ' @ ' .. tfm.hashfeatures(specification))
if specification.sub and specification.sub ~= "" then
specification.hash = specification.sub .. ' @ ' .. specification.hash
end
@@ -311,21 +330,21 @@ specification yet.</p>
--ldx]]--
function tfm.read(specification)
- local hash = tfm.hash_instance(specification)
+ local hash = tfm.hashinstance(specification)
local tfmtable = tfm.fonts[hash] -- hashes by size !
if not tfmtable then
local forced = specification.forced or ""
if forced ~= "" then
tfmtable = readers[lower(forced)](specification)
if not tfmtable then
- logs.report("define font","forced type %s of %s not found",forced,specification.name)
+ report_define("forced type %s of %s not found",forced,specification.name)
end
else
for s=1,#sequence do -- reader sequence
local reader = sequence[s]
if readers[reader] then -- not really needed
if trace_defining then
- logs.report("define font","trying (reader sequence driven) type %s for %s with file %s",reader,specification.name,specification.filename or "unknown")
+ report_define("trying (reader sequence driven) type %s for %s with file %s",reader,specification.name,specification.filename or "unknown")
end
tfmtable = readers[reader](specification)
if tfmtable then
@@ -350,7 +369,7 @@ function tfm.read(specification)
end
end
if not tfmtable then
- logs.report("define font","font with name %s is not found",specification.name)
+ report_define("font with name %s is not found",specification.name)
end
return tfmtable
end
@@ -359,22 +378,22 @@ end
<p>For virtual fonts we need a slightly different approach:</p>
--ldx]]--
-function tfm.read_and_define(name,size) -- no id
- local specification = define.analyze(name,size)
+function tfm.readanddefine(name,size) -- no id
+ local specification = definers.analyze(name,size)
local method = specification.method
- if method and define.specify[method] then
- specification = define.specify[method](specification)
+ if method and variants[method] then
+ specification = variants[method](specification)
end
- specification = define.resolve(specification)
- local hash = tfm.hash_instance(specification)
- local id = define.registered(hash)
+ specification = definers.resolve(specification)
+ local hash = tfm.hashinstance(specification)
+ local id = definers.registered(hash)
if not id then
local fontdata = tfm.read(specification)
if fontdata then
fontdata.hash = hash
id = font.define(fontdata)
- define.register(fontdata,id)
- tfm.cleanup_table(fontdata)
+ definers.register(fontdata,id)
+ tfm.cleanuptable(fontdata)
else
id = 0 -- signal
end
@@ -390,9 +409,12 @@ evolved. Each one has its own way of dealing with its format.</p>
local function check_tfm(specification,fullname)
-- ofm directive blocks local path search unless set; btw, in context we
-- don't support ofm files anyway as this format is obsolete
- local foundname = resolvers.findbinfile(fullname, 'tfm') or "" -- just to be sure
+ local foundname = findbinfile(fullname, 'tfm') or "" -- just to be sure
+ if foundname == "" then
+ foundname = findbinfile(fullname, 'ofm') or "" -- bonus for usage outside context
+ end
if foundname == "" then
- foundname = resolvers.findbinfile(fullname, 'ofm') or "" -- bonus for usage outside context
+ foundname = fonts.names.getfilename(fullname,"tfm")
end
if foundname ~= "" then
specification.filename, specification.format = foundname, "ofm"
@@ -401,16 +423,18 @@ local function check_tfm(specification,fullname)
end
local function check_afm(specification,fullname)
- local foundname = resolvers.findbinfile(fullname, 'afm') or "" -- just to be sure
- if foundname == "" and tfm.auto_afm then
+ local foundname = findbinfile(fullname, 'afm') or "" -- just to be sure
+ if foundname == "" then
+ foundname = fonts.names.getfilename(fullname,"afm")
+ end
+ if foundname == "" and tfm.autoprefixedafm then
local encoding, shortname = match(fullname,"^(.-)%-(.*)$") -- context: encoding-name.*
if encoding and shortname and fonts.enc.known[encoding] then
- shortname = resolvers.findbinfile(shortname,'afm') or "" -- just to be sure
+ shortname = findbinfile(shortname,'afm') or "" -- just to be sure
if shortname ~= "" then
foundname = shortname
- -- tfm.set_normal_feature(specification,'encoding',encoding) -- will go away
if trace_loading then
- logs.report("load afm","stripping encoding prefix from filename %s",afmname)
+ report_afm("stripping encoding prefix from filename %s",afmname)
end
end
end
@@ -445,7 +469,7 @@ function readers.afm(specification,method)
tfmtable = check_afm(specification,specification.name .. "." .. forced)
end
if not tfmtable then
- method = method or define.method or "afm or tfm"
+ method = method or definers.method or "afm or tfm"
if method == "tfm" then
tfmtable = check_tfm(specification,specification.name)
elseif method == "afm" then
@@ -469,22 +493,27 @@ local function check_otf(forced,specification,suffix,what)
if forced then
name = file.addsuffix(name,suffix,true)
end
- local fullname, tfmtable = resolvers.findbinfile(name,suffix) or "", nil -- one shot
- if fullname == "" then
- local fb = fonts.names.old_to_new[name]
- if fb then
- fullname = resolvers.findbinfile(fb,suffix) or ""
- end
- end
+ local fullname, tfmtable = findbinfile(name,suffix) or "", nil -- one shot
+ -- if false then -- can be enabled again when needed
+ -- if fullname == "" then
+ -- local fb = fonts.names.old_to_new[name]
+ -- if fb then
+ -- fullname = findbinfile(fb,suffix) or ""
+ -- end
+ -- end
+ -- if fullname == "" then
+ -- local fb = fonts.names.new_to_old[name]
+ -- if fb then
+ -- fullname = findbinfile(fb,suffix) or ""
+ -- end
+ -- end
+ -- end
if fullname == "" then
- local fb = fonts.names.new_to_old[name]
- if fb then
- fullname = resolvers.findbinfile(fb,suffix) or ""
- end
+ fullname = fonts.names.getfilename(name,suffix)
end
if fullname ~= "" then
specification.filename, specification.format = fullname, what -- hm, so we do set the filename, then
- tfmtable = tfm.read_from_open_type(specification) -- we need to do it for all matches / todo
+ tfmtable = tfm.read_from_otf(specification) -- we need to do it for all matches / todo
end
return tfmtable
end
@@ -510,7 +539,7 @@ function readers.dfont(specification) return readers.opentype(specification,"ttf
a helper function.</p>
--ldx]]--
-function define.check(features,defaults) -- nb adapts features !
+function definers.check(features,defaults) -- nb adapts features !
local done = false
if features and next(features) then
for k,v in next, defaults do
@@ -525,7 +554,7 @@ function define.check(features,defaults) -- nb adapts features !
end
--[[ldx--
-<p>So far the specifyers. Now comes the real definer. Here we cache
+<p>So far the specifiers. Now comes the real definer. Here we cache
based on id's. Here we also intercept the virtual font handler. Since
it evolved stepwise I may rewrite this bit (combine code).</p>
@@ -536,25 +565,29 @@ not gain much. By the way, passing id's back to in the callback was
introduced later in the development.</p>
--ldx]]--
-define.last = nil
+local lastdefined = nil -- we don't want this one to end up in s-tra-02
-function define.register(fontdata,id)
+function definers.current() -- or maybe current
+ return lastdefined
+end
+
+function definers.register(fontdata,id)
if fontdata and id then
local hash = fontdata.hash
if not tfm.internalized[hash] then
if trace_defining then
- logs.report("define font","loading at 2 id %s, hash: %s",id or "?",hash or "?")
+ report_define("loading at 2 id %s, hash: %s",id or "?",hash or "?")
end
fonts.identifiers[id] = fontdata
fonts.characters [id] = fontdata.characters
- fonts.quads [id] = fontdata.parameters.quad
+ fonts.quads [id] = fontdata.parameters and fontdata.parameters.quad
-- todo: extra functions, e.g. setdigitwidth etc in list
tfm.internalized[hash] = id
end
end
end
-function define.registered(hash)
+function definers.registered(hash)
local id = tfm.internalized[hash]
return id, id and fonts.ids[id]
end
@@ -569,7 +602,7 @@ function tfm.make(specification)
-- however, when virtual tricks are used as feature (makes more
-- sense) we scale the commands in fonts.tfm.scale (and set the
-- factor there)
- local fvm = define.methods[specification.features.vtf.preset]
+ local fvm = definers.methods.variants[specification.features.vtf.preset]
if fvm then
return fvm(specification)
else
@@ -577,28 +610,28 @@ function tfm.make(specification)
end
end
-function define.read(specification,size,id) -- id can be optional, name can already be table
+function definers.read(specification,size,id) -- id can be optional, name can already be table
statistics.starttiming(fonts)
if type(specification) == "string" then
- specification = define.analyze(specification,size)
+ specification = definers.analyze(specification,size)
end
local method = specification.method
- if method and define.specify[method] then
- specification = define.specify[method](specification)
+ if method and variants[method] then
+ specification = variants[method](specification)
end
- specification = define.resolve(specification)
- local hash = tfm.hash_instance(specification)
+ specification = definers.resolve(specification)
+ local hash = tfm.hashinstance(specification)
if cache_them then
local fontdata = containers.read(fonts.cache,hash) -- for tracing purposes
end
- local fontdata = define.registered(hash) -- id
+ local fontdata = definers.registered(hash) -- id
if not fontdata then
if specification.features.vtf and specification.features.vtf.preset then
fontdata = tfm.make(specification)
else
fontdata = tfm.read(specification)
if fontdata then
- tfm.check_virtual_id(fontdata)
+ tfm.checkvirtualid(fontdata)
end
end
if cache_them then
@@ -608,15 +641,15 @@ function define.read(specification,size,id) -- id can be optional, name can alre
fontdata.hash = hash
fontdata.cache = "no"
if id then
- define.register(fontdata,id)
+ definers.register(fontdata,id)
end
end
end
- define.last = fontdata or id -- todo ! ! ! ! !
- if not fontdata then
- logs.report("define font", "unknown font %s, loading aborted",specification.name)
+ lastdefined = fontdata or id -- todo ! ! ! ! !
+ if not fontdata then -- or id?
+ report_define( "unknown font %s, loading aborted",specification.name)
elseif trace_defining and type(fontdata) == "table" then
- logs.report("define font","using %s font with id %s, name:%s size:%s bytes:%s encoding:%s fullname:%s filename:%s",
+ report_define("using %s font with id %s, name:%s size:%s bytes:%s encoding:%s fullname:%s filename:%s",
fontdata.type or "unknown",
id or "?",
fontdata.name or "?",
@@ -625,7 +658,10 @@ function define.read(specification,size,id) -- id can be optional, name can alre
fontdata.encodingname or "unicode",
fontdata.fullname or "?",
file.basename(fontdata.filename or "?"))
-
+ end
+ local cs = specification.cs
+ if cs then
+ fontcsnames[cs] = fontdata -- new (beware: locals can be forgotten)
end
statistics.stoptiming(fonts)
return fontdata
@@ -633,24 +669,24 @@ end
function vf.find(name)
name = file.removesuffix(file.basename(name))
- if tfm.resolve_vf then
+ if tfm.resolvevirtualtoo then
local format = fonts.logger.format(name)
if format == 'tfm' or format == 'ofm' then
if trace_defining then
- logs.report("define font","locating vf for %s",name)
+ report_define("locating vf for %s",name)
end
- return resolvers.findbinfile(name,"ovf")
+ return findbinfile(name,"ovf")
else
if trace_defining then
- logs.report("define font","vf for %s is already taken care of",name)
+ report_define("vf for %s is already taken care of",name)
end
return nil -- ""
end
else
if trace_defining then
- logs.report("define font","locating vf for %s",name)
+ report_define("locating vf for %s",name)
end
- return resolvers.findbinfile(name,"ovf")
+ return findbinfile(name,"ovf")
end
end
@@ -658,5 +694,5 @@ end
<p>We overload both the <l n='tfm'/> and <l n='vf'/> readers.</p>
--ldx]]--
-callbacks.register('define_font' , define.read, "definition of fonts (tfmtable preparation)")
+callbacks.register('define_font' , definers.read, "definition of fonts (tfmtable preparation)")
callbacks.register('find_vf_file', vf.find , "locating virtual fonts, insofar needed") -- not that relevant any more
diff --git a/otfl-font-dum.lua b/otfl-font-dum.lua
index c9ffb63..e8237cc 100644
--- a/otfl-font-dum.lua
+++ b/otfl-font-dum.lua
@@ -10,9 +10,9 @@ fonts = fonts or { }
-- general
-fonts.otf.pack = false
-fonts.tfm.resolve_vf = false -- no sure about this
-fonts.tfm.fontname_mode = "specification" -- somehow latex needs this
+fonts.otf.pack = false -- only makes sense in context
+fonts.tfm.resolvevirtualtoo = false -- context specific (du eto resolver)
+fonts.tfm.fontnamemode = "specification" -- somehow latex needs this (changed name!)
-- readers
@@ -22,16 +22,17 @@ fonts.tfm.readers.afm = nil
-- define
-fonts.define = fonts.define or { }
+fonts.definers = fonts.definers or { }
+fonts.definers.specifiers = fonts.definers.specifiers or { }
---~ fonts.define.method = "tfm"
+fonts.definers.specifiers.colonizedpreference = "name" -- is "file" in context
-fonts.define.specify.colonized_default_lookup = "name"
-
-function fonts.define.get_specification(str)
+function fonts.definers.getspecification(str)
return "", str, "", ":", str
end
+fonts.definers.registersplit("",fonts.definers.specifiers.variants[":"]) -- we add another one for catching lone [names]
+
-- logger
fonts.logger = fonts.logger or { }
@@ -63,7 +64,7 @@ function fonts.names.resolve(name,sub)
if basename and basename ~= "" then
for i=1,#fileformats do
local format = fileformats[i]
- local foundname = resolvers.find_file(basename,format) or ""
+ local foundname = resolvers.findfile(basename,format) or ""
if foundname ~= "" then
data = dofile(foundname)
break
@@ -90,6 +91,10 @@ end
fonts.names.resolvespec = fonts.names.resolve -- only supported in mkiv
+function fonts.names.getfilename(askedname,suffix) -- only supported in mkiv
+ return ""
+end
+
-- For the moment we put this (adapted) pseudo feature here.
table.insert(fonts.triggers,"itlc")
@@ -183,36 +188,40 @@ local setups = fonts.protrusions.setups
--
-- \definefontfeature[whocares][default][mode=node,protrusion=2,opbd=yes,script=latn,featurefile=texgyrepagella-regularxx.fea]
+classes['double'] = { -- for testing opbd
+ factor = 2, left = 1, right = 1,
+}
+
local function map_opbd_onto_protrusion(tfmdata,value,opbd)
local characters, descriptions = tfmdata.characters, tfmdata.descriptions
local otfdata = tfmdata.shared.otfdata
local singles = otfdata.shared.featuredata.gpos_single
local script, language = tfmdata.script, tfmdata.language
local done, factor, left, right = false, 1, 1, 1
- local setup = setups[value]
- if setup then
- factor = setup.factor or 1
- left = setup.left or 1
- right = setup.right or 1
+ local class = classes[value]
+ if class then
+ factor = class.factor or 1
+ left = class.left or 1
+ right = class.right or 1
else
factor = tonumber(value) or 1
end
if opbd ~= "right" then
- local validlookups, lookuplist = fonts.otf.collect_lookups(otfdata,"lfbd",script,language)
+ local validlookups, lookuplist = otf.collectlookups(otfdata,"lfbd",script,language)
if validlookups then
for i=1,#lookuplist do
local lookup = lookuplist[i]
local data = singles[lookup]
if data then
if trace_protrusion then
- logs.report("fonts","set left protrusion using lfbd lookup '%s'",lookup)
+ report_fonts("set left protrusion using lfbd lookup '%s'",lookup)
end
for k, v in next, data do
-- local p = - v[3] / descriptions[k].width-- or 1 ~= 0 too but the same
local p = - (v[1] / 1000) * factor * left
characters[k].left_protruding = p
if trace_protrusion then
- logs.report("opbd","lfbd -> %s -> 0x%05X (%s) -> %0.03f (%s)",lookup,k,utfchar(k),p,concat(v," "))
+ report_protrusions("lfbd -> %s -> 0x%05X (%s) -> %0.03f (%s)",lookup,k,utfchar(k),p,concat(v," "))
end
end
done = true
@@ -221,21 +230,21 @@ local function map_opbd_onto_protrusion(tfmdata,value,opbd)
end
end
if opbd ~= "left" then
- local validlookups, lookuplist = fonts.otf.collect_lookups(otfdata,"rtbd",script,language)
+ local validlookups, lookuplist = otf.collectlookups(otfdata,"rtbd",script,language)
if validlookups then
for i=1,#lookuplist do
local lookup = lookuplist[i]
local data = singles[lookup]
if data then
if trace_protrusion then
- logs.report("fonts","set right protrusion using rtbd lookup '%s'",lookup)
+ report_fonts("set right protrusion using rtbd lookup '%s'",lookup)
end
for k, v in next, data do
-- local p = v[3] / descriptions[k].width -- or 3
local p = (v[1] / 1000) * factor * right
characters[k].right_protruding = p
if trace_protrusion then
- logs.report("opbd","rtbd -> %s -> 0x%05X (%s) -> %0.03f (%s)",lookup,k,utfchar(k),p,concat(v," "))
+ report_protrusions("rtbd -> %s -> 0x%05X (%s) -> %0.03f (%s)",lookup,k,utfchar(k),p,concat(v," "))
end
end
end
@@ -251,26 +260,60 @@ end
-- only has some kerns for digits. So, consider this feature not
-- supported till we have a proper test font.
-function fonts.initializers.common.protrusion(tfmdata,value)
+function initializers.common.protrusion(tfmdata,value)
if value then
local opbd = tfmdata.shared.features.opbd
if opbd then
-- possible values: left right both yes no (experimental)
map_opbd_onto_protrusion(tfmdata,value,opbd)
- elseif value then
- local setup = setups[value]
- if setup then
- local factor, left, right = setup.factor or 1, setup.left or 1, setup.right or 1
- local emwidth = tfmdata.parameters.quad
- tfmdata.auto_protrude = true
- for i, chr in next, tfmdata.characters do
- local v, pl, pr = setup[i], nil, nil
- if v then
- pl, pr = v[1], v[2]
+ else
+ local class, vector = get_class_and_vector(tfmdata,value,"protrusions")
+ if class then
+ if vector then
+ local factor = class.factor or 1
+ local left = class.left or 1
+ local right = class.right or 1
+ if trace_protrusion then
+ report_fonts("set protrusion class %s, vector: %s, factor: %s, left: %s, right: %s",
+ value,class.vector,factor,left,right)
end
- if pl and pl ~= 0 then chr.left_protruding = left *pl*factor end
- if pr and pr ~= 0 then chr.right_protruding = right*pr*factor end
+ local data = characters.data
+ local emwidth = tfmdata.parameters.quad
+ tfmdata.auto_protrude = true
+ for i, chr in next, tfmdata.characters do
+ local v, pl, pr = vector[i], nil, nil
+ if v then
+ pl, pr = v[1], v[2]
+ else
+ local d = data[i]
+ if d then
+ local s = d.shcode
+ if not s then
+ -- sorry
+ elseif type(s) == "table" then
+ local vl, vr = vector[s[1]], vector[s[#s]]
+ if vl then pl = vl[1] end
+ if vr then pr = vr[2] end
+ else
+ v = vector[s]
+ if v then
+ pl, pr = v[1], v[2]
+ end
+ end
+ end
+ end
+ if pl and pl ~= 0 then
+ chr.left_protruding = left *pl*factor
+ end
+ if pr and pr ~= 0 then
+ chr.right_protruding = right*pr*factor
+ end
+ end
+ elseif trace_protrusion then
+ report_fonts("unknown protrusion vector '%s' in class '%s",class.vector,value)
end
+ elseif trace_protrusion then
+ report_fonts("unknown protrusion class '%s'",value)
end
end
end
@@ -309,7 +352,7 @@ fonts.initializers.node.otf.expansion = fonts.initializers.common.expansion
-- left over
-function fonts.register_message()
+function fonts.registermessage()
end
-- example vectors
@@ -360,9 +403,15 @@ fonts.otf.meanings.normalize = fonts.otf.meanings.normalize or function(t)
end
end
+-- needed (different in context)
+
+function fonts.otf.scriptandlanguage(tfmdata)
+ return tfmdata.script, tfmdata.language
+end
+
-- bonus
-function fonts.otf.name_to_slot(name)
+function fonts.otf.nametoslot(name)
local tfmdata = fonts.ids[font.current()]
if tfmdata and tfmdata.shared then
local otfdata = tfmdata.shared.otfdata
@@ -373,7 +422,7 @@ end
function fonts.otf.char(n)
if type(n) == "string" then
- n = fonts.otf.name_to_slot(n)
+ n = fonts.otf.nametoslot(n)
end
if type(n) == "number" then
tex.sprint("\\char" .. n)
diff --git a/otfl-font-ini.lua b/otfl-font-ini.lua
index c695ec4..6082c1d 100644
--- a/otfl-font-ini.lua
+++ b/otfl-font-ini.lua
@@ -14,24 +14,33 @@ local utf = unicode.utf8
local format, serialize = string.format, table.serialize
local write_nl = texio.write_nl
local lower = string.lower
+local allocate, mark = utilities.storage.allocate, utilities.storage.mark
-if not fontloader then fontloader = fontforge end
+local report_define = logs.new("define fonts")
fontloader.totable = fontloader.to_table
-- vtf comes first
-- fix comes last
-fonts = fonts or { }
+fonts = fonts or { }
-fonts.ids = fonts.ids or { } fonts.identifiers = fonts.ids -- aka fontdata
-fonts.chr = fonts.chr or { } fonts.characters = fonts.chr -- aka chardata
-fonts.qua = fonts.qua or { } fonts.quads = fonts.qua -- aka quaddata
+-- we will also have des and fam hashes
+
+-- beware, soem alreadyu defined
+
+fonts.ids = mark(fonts.ids or { }) fonts.identifiers = fonts.ids -- aka fontdata
+fonts.chr = mark(fonts.chr or { }) fonts.characters = fonts.chr -- aka chardata
+fonts.qua = mark(fonts.qua or { }) fonts.quads = fonts.qua -- aka quaddata
+fonts.css = mark(fonts.css or { }) fonts.csnames = fonts.css -- aka namedata
fonts.tfm = fonts.tfm or { }
+fonts.vf = fonts.vf or { }
+fonts.afm = fonts.afm or { }
+fonts.pfb = fonts.pfb or { }
+fonts.otf = fonts.otf or { }
-fonts.mode = 'base'
-fonts.private = 0xF0000 -- 0x10FFFF
+fonts.privateoffset = 0xF0000 -- 0x10FFFF
fonts.verbose = false -- more verbose cache tables
fonts.ids[0] = { -- nullfont
@@ -62,18 +71,28 @@ fonts.triggers = fonts.triggers or {
fonts.processors = fonts.processors or {
}
+fonts.analyzers = fonts.analyzers or {
+ useunicodemarks = false,
+}
+
fonts.manipulators = fonts.manipulators or {
}
-fonts.define = fonts.define or { }
-fonts.define.specify = fonts.define.specify or { }
-fonts.define.specify.synonyms = fonts.define.specify.synonyms or { }
+fonts.tracers = fonts.tracers or {
+}
+
+fonts.typefaces = fonts.typefaces or {
+}
+
+fonts.definers = fonts.definers or { }
+fonts.definers.specifiers = fonts.definers.specifiers or { }
+fonts.definers.specifiers.synonyms = fonts.definers.specifiers.synonyms or { }
-- tracing
-if not fonts.color then
+if not fonts.colors then
- fonts.color = {
+ fonts.colors = allocate {
set = function() end,
reset = function() end,
}
@@ -82,7 +101,7 @@ end
-- format identification
-fonts.formats = { }
+fonts.formats = allocate()
function fonts.fontformat(filename,default)
local extname = lower(file.extname(filename))
@@ -90,7 +109,7 @@ function fonts.fontformat(filename,default)
if format then
return format
else
- logs.report("fonts define","unable to determine font format for '%s'",filename)
+ report_define("unable to determine font format for '%s'",filename)
return default
end
end
diff --git a/otfl-font-map.lua b/otfl-font-map.lua
index 2995087..46e84ad 100644
--- a/otfl-font-map.lua
+++ b/otfl-font-map.lua
@@ -14,7 +14,7 @@ local utfbyte = utf.byte
local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
local trace_unimapping = false trackers.register("otf.unimapping", function(v) trace_unimapping = v end)
-local ctxcatcodes = tex and tex.ctxcatcodes
+local report_otf = logs.new("load otf")
--[[ldx--
<p>Eventually this code will disappear because map files are kind
@@ -22,50 +22,51 @@ of obsolete. Some code may move to runtime or auxiliary modules.</p>
<p>The name to unciode related code will stay of course.</p>
--ldx]]--
-fonts = fonts or { }
-fonts.map = fonts.map or { }
+local fonts = fonts
+fonts.map = fonts.map or { }
-local function load_lum_table(filename) -- will move to font goodies
+local function loadlumtable(filename) -- will move to font goodies
local lumname = file.replacesuffix(file.basename(filename),"lum")
- local lumfile = resolvers.find_file(lumname,"map") or ""
+ local lumfile = resolvers.findfile(lumname,"map") or ""
if lumfile ~= "" and lfs.isfile(lumfile) then
if trace_loading or trace_unimapping then
- logs.report("load otf","enhance: loading %s ",lumfile)
+ report_otf("enhance: loading %s ",lumfile)
end
lumunic = dofile(lumfile)
return lumunic, lumfile
end
end
-local hex = lpeg.R("AF","09")
+local P, R, S, C, Ct, Cc = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cc
+
+local hex = R("AF","09")
local hexfour = (hex*hex*hex*hex) / function(s) return tonumber(s,16) end
local hexsix = (hex^1) / function(s) return tonumber(s,16) end
-local dec = (lpeg.R("09")^1) / tonumber
-local period = lpeg.P(".")
-
-local unicode = lpeg.P("uni") * (hexfour * (period + lpeg.P(-1)) * lpeg.Cc(false) + lpeg.Ct(hexfour^1) * lpeg.Cc(true))
-local ucode = lpeg.P("u") * (hexsix * (period + lpeg.P(-1)) * lpeg.Cc(false) + lpeg.Ct(hexsix ^1) * lpeg.Cc(true))
-local index = lpeg.P("index") * dec * lpeg.Cc(false)
+local dec = (R("09")^1) / tonumber
+local period = P(".")
+local unicode = P("uni") * (hexfour * (period + P(-1)) * Cc(false) + Ct(hexfour^1) * Cc(true))
+local ucode = P("u") * (hexsix * (period + P(-1)) * Cc(false) + Ct(hexsix ^1) * Cc(true))
+local index = P("index") * dec * Cc(false)
local parser = unicode + ucode + index
local parsers = { }
-local function make_name_parser(str)
+local function makenameparser(str)
if not str or str == "" then
return parser
else
local p = parsers[str]
if not p then
- p = lpeg.P(str) * period * dec * lpeg.Cc(false)
+ p = P(str) * period * dec * Cc(false)
parsers[str] = p
end
return p
end
end
---~ local parser = fonts.map.make_name_parser("Japan1")
---~ local parser = fonts.map.make_name_parser()
+--~ local parser = fonts.map.makenameparser("Japan1")
+--~ local parser = fonts.map.makenameparser()
--~ local function test(str)
--~ local b, a = lpegmatch(parser,str)
--~ print((a and table.serialize(b)) or b)
@@ -119,14 +120,14 @@ end
--~ return s
--~ end
-fonts.map.load_lum_table = load_lum_table
-fonts.map.make_name_parser = make_name_parser
+fonts.map.loadlumtable = loadlumtable
+fonts.map.makenameparser = makenameparser
fonts.map.tounicode16 = tounicode16
fonts.map.tounicode16sequence = tounicode16sequence
-local separator = lpeg.S("_.")
-local other = lpeg.C((1 - separator)^1)
-local ligsplitter = lpeg.Ct(other * (separator * other)^0)
+local separator = S("_.")
+local other = C((1 - separator)^1)
+local ligsplitter = Ct(other * (separator * other)^0)
--~ print(table.serialize(lpegmatch(ligsplitter,"this")))
--~ print(table.serialize(lpegmatch(ligsplitter,"this.that")))
@@ -134,7 +135,7 @@ local ligsplitter = lpeg.Ct(other * (separator * other)^0)
--~ print(table.serialize(lpegmatch(ligsplitter,"such_so_more")))
--~ print(table.serialize(lpegmatch(ligsplitter,"such_so_more.that")))
-fonts.map.add_to_unicode = function(data,filename)
+fonts.map.addtounicode = function(data,filename)
local unicodes = data.luatex and data.luatex.unicodes
if not unicodes then
return
@@ -145,11 +146,11 @@ fonts.map.add_to_unicode = function(data,filename)
unicodes['zwj'] = unicodes['zwj'] or 0x200D
unicodes['zwnj'] = unicodes['zwnj'] or 0x200C
-- the tounicode mapping is sparse and only needed for alternatives
- local tounicode, originals, ns, nl, private, unknown = { }, { }, 0, 0, fonts.private, format("%04X",utfbyte("?"))
+ local tounicode, originals, ns, nl, private, unknown = { }, { }, 0, 0, fonts.privateoffset, format("%04X",utfbyte("?"))
data.luatex.tounicode, data.luatex.originals = tounicode, originals
local lumunic, uparser, oparser
if false then -- will become an option
- lumunic = load_lum_table(filename)
+ lumunic = loadlumtable(filename)
lumunic = lumunic and lumunic.tounicode
end
local cidinfo, cidnames, cidcodes = data.cidinfo
@@ -157,12 +158,12 @@ fonts.map.add_to_unicode = function(data,filename)
usedmap = usedmap and lower(usedmap)
usedmap = usedmap and fonts.cid.map[usedmap]
if usedmap then
- oparser = usedmap and make_name_parser(cidinfo.ordering)
+ oparser = usedmap and makenameparser(cidinfo.ordering)
cidnames = usedmap.names
cidcodes = usedmap.unicodes
end
- uparser = make_name_parser()
- local aglmap = fonts.map and fonts.map.agl_to_unicode
+ uparser = makenameparser()
+ local aglmap = fonts.enc and fonts.enc.agl -- to name
for index, glyph in next, data.glyphs do
local name, unic = glyph.name, glyph.unicode or -1 -- play safe
if unic == -1 or unic >= private or (unic >= 0xE000 and unic <= 0xF8FF) or unic == 0xFFFE or unic == 0xFFFF then
@@ -230,7 +231,11 @@ fonts.map.add_to_unicode = function(data,filename)
t[#t+1] = u
end
end
- if #t > 0 then -- done then
+ if #t == 0 then -- done then
+ -- nothing
+ elseif #t == 1 then
+ originals[index], tounicode[index], nl, unicode = t[1], tounicode16(t[1]), nl + 1, true
+ else
originals[index], tounicode[index], nl, unicode = t, tounicode16sequence(t), nl + 1, true
end
end
@@ -255,14 +260,14 @@ fonts.map.add_to_unicode = function(data,filename)
for index, glyph in table.sortedhash(data.glyphs) do
local toun, name, unic = tounicode[index], glyph.name, glyph.unicode or -1 -- play safe
if toun then
- logs.report("load otf","internal: 0x%05X, name: %s, unicode: 0x%05X, tounicode: %s",index,name,unic,toun)
+ report_otf("internal: 0x%05X, name: %s, unicode: 0x%05X, tounicode: %s",index,name,unic,toun)
else
- logs.report("load otf","internal: 0x%05X, name: %s, unicode: 0x%05X",index,name,unic)
+ report_otf("internal: 0x%05X, name: %s, unicode: 0x%05X",index,name,unic)
end
end
end
if trace_loading and (ns > 0 or nl > 0) then
- logs.report("load otf","enhance: %s tounicode entries added (%s ligatures)",nl+ns, ns)
+ report_otf("enhance: %s tounicode entries added (%s ligatures)",nl+ns, ns)
end
end
diff --git a/otfl-font-ota.lua b/otfl-font-ota.lua
index 0e5b555..18b0bf2 100644
--- a/otfl-font-ota.lua
+++ b/otfl-font-ota.lua
@@ -17,46 +17,46 @@ local trace_cjk = false trackers.register("cjk.injections", function(v) t
trackers.register("cjk.analyzing","otf.analyzing")
-fonts = fonts or { }
-fonts.analyzers = fonts.analyzers or { }
-fonts.analyzers.initializers = fonts.analyzers.initializers or { node = { otf = { } } }
-fonts.analyzers.methods = fonts.analyzers.methods or { node = { otf = { } } }
+local fonts, nodes = fonts, nodes
+local node = node
local otf = fonts.otf
local tfm = fonts.tfm
-local initializers = fonts.analyzers.initializers
-local methods = fonts.analyzers.methods
+fonts.analyzers = fonts.analyzers or { }
+local analyzers = fonts.analyzers
-local glyph = node.id('glyph')
-local glue = node.id('glue')
-local penalty = node.id('penalty')
+analyzers.initializers = analyzers.initializers or { node = { otf = { } } }
+analyzers.methods = analyzers.methods or { node = { otf = { } } }
+
+local initializers = analyzers.initializers
+local methods = analyzers.methods
+
+local nodecodes = nodes.nodecodes
+local glyph_code = nodecodes.glyph
local set_attribute = node.set_attribute
local has_attribute = node.has_attribute
local traverse_id = node.traverse_id
local traverse_node_list = node.traverse
-local fontdata = fonts.ids
-local state = attributes.private('state')
+local fontdata = fonts.ids
+local state = attributes.private('state')
+local categories = characters and characters.categories or { } -- sorry, only in context
-local fcs = (fonts.color and fonts.color.set) or function() end
-local fcr = (fonts.color and fonts.color.reset) or function() end
+local fontscolors = fonts.colors
+local fcs = (fontscolors and fontscolors.set) or function() end
+local fcr = (fontscolors and fontscolors.reset) or function() end
-local a_to_script = otf.a_to_script
-local a_to_language = otf.a_to_language
-- in the future we will use language/script attributes instead of the
-- font related value, but then we also need dynamic features which is
-- somewhat slower; and .. we need a chain of them
+local scriptandlanguage = otf.scriptandlanguage
+
function fonts.initializers.node.otf.analyze(tfmdata,value,attr)
- local script, language
- if attr and attr > 0 then
- script, language = a_to_script[attr], a_to_language[attr]
- else
- script, language = tfmdata.script, tfmdata.language
- end
+ local script, language = otf.scriptandlanguage(tfmdata,attr)
local action = initializers[script]
if action then
if type(action) == "function" then
@@ -73,12 +73,7 @@ end
function fonts.methods.node.otf.analyze(head,font,attr)
local tfmdata = fontdata[font]
- local script, language
- if attr and attr > 0 then
- script, language = a_to_script[attr], a_to_language[attr]
- else
- script, language = tfmdata.script, tfmdata.language
- end
+ local script, language = otf.scriptandlanguage(tfmdata,attr)
local action = methods[script]
if action then
if type(action) == "function" then
@@ -98,7 +93,7 @@ table.insert(fonts.triggers,"analyze") -- we need a proper function for doing t
-- latin
-fonts.analyzers.methods.latn = fonts.analyzers.aux.setstate
+analyzers.methods.latn = analyzers.aux.setstate
-- this info eventually will go into char-def
@@ -180,8 +175,8 @@ local function warning(current,what)
end
end
-function fonts.analyzers.methods.nocolor(head,font,attr)
- for n in traverse_node_list(head,glyph) do
+function analyzers.methods.nocolor(head,font,attr)
+ for n in traverse_id(glyph_code,head) do
if not font or n.font == font then
fcr(n)
end
@@ -230,15 +225,16 @@ local function finish(first,last)
return first, last
end
-function fonts.analyzers.methods.arab(head,font,attr) -- maybe make a special version with no trace
+function analyzers.methods.arab(head,font,attr) -- maybe make a special version with no trace
+ local useunicodemarks = analyzers.useunicodemarks
local tfmdata = fontdata[font]
local marks = tfmdata.marks
local first, last, current, done = nil, nil, head, false
while current do
- if current.id == glyph and current.subtype<256 and current.font == font and not has_attribute(current,state) then
+ if current.id == glyph_code and current.subtype<256 and current.font == font and not has_attribute(current,state) then
done = true
local char = current.char
- if marks[char] then
+ if marks[char] or (useunicodemarks and categories[char] == "mn") then
set_attribute(current,state,5) -- mark
if trace_analyzing then fcs(current,"font:mark") end
elseif isol[char] then -- can be zwj or zwnj too
diff --git a/otfl-font-otb.lua b/otfl-font-otb.lua
index e0528a4..241845f 100644
--- a/otfl-font-otb.lua
+++ b/otfl-font-otb.lua
@@ -11,8 +11,9 @@ local format, gmatch, gsub, find, match, lower, strip = string.format, string.gm
local type, next, tonumber, tostring = type, next, tonumber, tostring
local lpegmatch = lpeg.match
-local otf = fonts.otf
-local tfm = fonts.tfm
+local fonts = fonts
+local otf = fonts.otf
+local tfm = fonts.tfm
local trace_baseinit = false trackers.register("otf.baseinit", function(v) trace_baseinit = v end)
local trace_singles = false trackers.register("otf.singles", function(v) trace_singles = v end)
@@ -22,6 +23,8 @@ local trace_ligatures = false trackers.register("otf.ligatures", function
local trace_kerns = false trackers.register("otf.kerns", function(v) trace_kerns = v end)
local trace_preparing = false trackers.register("otf.preparing", function(v) trace_preparing = v end)
+local report_prepare = logs.new("otf prepare")
+
local wildcard = "*"
local default = "dflt"
@@ -41,8 +44,20 @@ local function gref(descriptions,n)
local num, nam = { }, { }
for i=1,#n do
local ni = n[i]
- num[i] = format("U+%04X",ni)
- nam[i] = descriptions[ni].name or "?"
+ -- ! ! ! could be a helper ! ! !
+ if type(ni) == "table" then
+ local nnum, nnam = { }, { }
+ for j=1,#ni do
+ local nj = ni[j]
+ nnum[j] = format("U+%04X",nj)
+ nnam[j] = descriptions[nj].name or "?"
+ end
+ num[i] = concat(nnum,"|")
+ nam[i] = concat(nnam,"|")
+ else
+ num[i] = format("U+%04X",ni)
+ nam[i] = descriptions[ni].name or "?"
+ end
end
return format("%s (%s)",concat(num," "), concat(nam," "))
else
@@ -76,7 +91,7 @@ local function resolve_ligatures(tfmdata,ligatures,kind)
local c, f, s = characters[uc], ligs[1], ligs[2]
local uft, ust = unicodes[f] or 0, unicodes[s] or 0
if not uft or not ust then
- logs.report("define otf","%s: unicode problem with base ligature %s = %s + %s",cref(kind),gref(descriptions,uc),gref(descriptions,uft),gref(descriptions,ust))
+ report_prepare("%s: unicode problem with base ligature %s = %s + %s",cref(kind),gref(descriptions,uc),gref(descriptions,uft),gref(descriptions,ust))
-- some kind of error
else
if type(uft) == "number" then uft = { uft } end
@@ -87,7 +102,7 @@ local function resolve_ligatures(tfmdata,ligatures,kind)
local us = ust[usi]
if changed[uf] or changed[us] then
if trace_baseinit and trace_ligatures then
- logs.report("define otf","%s: base ligature %s + %s ignored",cref(kind),gref(descriptions,uf),gref(descriptions,us))
+ report_prepare("%s: base ligature %s + %s ignored",cref(kind),gref(descriptions,uf),gref(descriptions,us))
end
else
local first, second = characters[uf], us
@@ -103,7 +118,7 @@ local function resolve_ligatures(tfmdata,ligatures,kind)
t[second] = { type = 0, char = uc[1] } -- can this still happen?
end
if trace_baseinit and trace_ligatures then
- logs.report("define otf","%s: base ligature %s + %s => %s",cref(kind),gref(descriptions,uf),gref(descriptions,us),gref(descriptions,uc))
+ report_prepare("%s: base ligature %s + %s => %s",cref(kind),gref(descriptions,uf),gref(descriptions,us),gref(descriptions,uc))
end
end
end
@@ -139,7 +154,7 @@ local splitter = lpeg.splitat(" ")
local function prepare_base_substitutions(tfmdata,kind,value) -- we can share some code with the node features
if value then
local otfdata = tfmdata.shared.otfdata
- local validlookups, lookuplist = otf.collect_lookups(otfdata,kind,tfmdata.script,tfmdata.language)
+ local validlookups, lookuplist = otf.collectlookups(otfdata,kind,tfmdata.script,tfmdata.language)
if validlookups then
local ligatures = { }
local unicodes = tfmdata.unicodes -- names to unicodes
@@ -154,12 +169,12 @@ local function prepare_base_substitutions(tfmdata,kind,value) -- we can share so
if pv then
local upv = unicodes[pv]
if upv then
- if type(upv) == "table" then
+ if type(upv) == "table" then -- zero change that table
upv = upv[1]
end
if characters[upv] then
if trace_baseinit and trace_singles then
- logs.report("define otf","%s: base substitution %s => %s",cref(kind,lookup),gref(descriptions,k),gref(descriptions,upv))
+ report_prepare("%s: base substitution %s => %s",cref(kind,lookup),gref(descriptions,k),gref(descriptions,upv))
end
changed[k] = upv
end
@@ -182,12 +197,12 @@ local function prepare_base_substitutions(tfmdata,kind,value) -- we can share so
if pc then
local upc = unicodes[pc]
if upc then
- if type(upc) == "table" then
+ if type(upc) == "table" then -- zero change that table
upc = upc[1]
end
if characters[upc] then
if trace_baseinit and trace_alternatives then
- logs.report("define otf","%s: base alternate %s %s => %s",cref(kind,lookup),tostring(value),gref(descriptions,k),gref(descriptions,upc))
+ report_prepare("%s: base alternate %s %s => %s",cref(kind,lookup),tostring(value),gref(descriptions,k),gref(descriptions,upc))
end
changed[k] = upc
end
@@ -202,7 +217,7 @@ local function prepare_base_substitutions(tfmdata,kind,value) -- we can share so
local upc = { lpegmatch(splitter,pc) }
for i=1,#upc do upc[i] = unicodes[upc[i]] end
-- we assume that it's no table
- logs.report("define otf","%s: base ligature %s => %s",cref(kind,lookup),gref(descriptions,upc),gref(descriptions,k))
+ report_prepare("%s: base ligature %s => %s",cref(kind,lookup),gref(descriptions,upc),gref(descriptions,k))
end
ligatures[#ligatures+1] = { pc, k }
end
@@ -248,10 +263,10 @@ local function prepare_base_substitutions(tfmdata,kind,value) -- we can share so
end
end
-local function prepare_base_kerns(tfmdata,kind,value) -- todo what kind of kerns, currently all
+local function preparebasekerns(tfmdata,kind,value) -- todo what kind of kerns, currently all
if value then
local otfdata = tfmdata.shared.otfdata
- local validlookups, lookuplist = otf.collect_lookups(otfdata,kind,tfmdata.script,tfmdata.language)
+ local validlookups, lookuplist = otf.collectlookups(otfdata,kind,tfmdata.script,tfmdata.language)
if validlookups then
local unicodes = tfmdata.unicodes -- names to unicodes
local indices = tfmdata.indices
@@ -261,7 +276,7 @@ local function prepare_base_kerns(tfmdata,kind,value) -- todo what kind of kerns
for u, chr in next, characters do
local d = descriptions[u]
if d then
- local dk = d.mykerns -- shared
+ local dk = d.kerns -- shared
if dk then
local s = sharedkerns[dk]
if s == false then
@@ -278,7 +293,7 @@ local function prepare_base_kerns(tfmdata,kind,value) -- todo what kind of kerns
if v ~= 0 and not t[k] then -- maybe no 0 test here
t[k], done = v, true
if trace_baseinit and trace_kerns then
- logs.report("define otf","%s: base kern %s + %s => %s",cref(kind,lookup),gref(descriptions,u),gref(descriptions,k),v)
+ report_prepare("%s: base kern %s + %s => %s",cref(kind,lookup),gref(descriptions,u),gref(descriptions,k),v)
end
end
end
@@ -318,10 +333,10 @@ local supported_gpos = {
'kern'
}
-function otf.features.register_base_substitution(tag)
+function otf.features.registerbasesubstitution(tag)
supported_gsub[#supported_gsub+1] = tag
end
-function otf.features.register_base_kern(tag)
+function otf.features.registerbasekern(tag)
supported_gsub[#supported_gpos+1] = tag
end
@@ -345,7 +360,7 @@ function fonts.initializers.base.otf.features(tfmdata,value)
for f=1,#supported_gpos do
local feature = supported_gpos[f]
local value = features[feature]
- prepare_base_kerns(tfmdata,feature,features[feature])
+ preparebasekerns(tfmdata,feature,features[feature])
if value then
h[#h+1] = feature .. "=" .. tostring(value)
end
@@ -364,10 +379,10 @@ function fonts.initializers.base.otf.features(tfmdata,value)
-- verbose name as long as we don't use <()<>[]{}/%> and the length
-- is < 128.
tfmdata.fullname = tfmdata.fullname .. "-" .. base -- tfmdata.psname is the original
- --~ logs.report("otf define","fullname base hash: '%s', featureset '%s'",tfmdata.fullname,hash)
+ --~ report_prepare("fullname base hash: '%s', featureset '%s'",tfmdata.fullname,hash)
end
if trace_preparing then
- logs.report("otf define","preparation time is %0.3f seconds for %s",os.clock()-t,tfmdata.fullname or "?")
+ report_prepare("preparation time is %0.3f seconds for %s",os.clock()-t,tfmdata.fullname or "?")
end
end
end
diff --git a/otfl-font-otc.lua b/otfl-font-otc.lua
index 35555ed..cc7f0ab 100644
--- a/otfl-font-otc.lua
+++ b/otfl-font-otc.lua
@@ -13,8 +13,10 @@ local type, next = type, next
local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
-local otf = fonts.otf
-local tfm = fonts.tfm
+local fonts = fonts
+local otf = fonts.otf
+
+local report_otf = logs.new("load otf")
-- instead of "script = "DFLT", langs = { 'dflt' }" we now use wildcards (we used to
-- have always); some day we can write a "force always when true" trick for other
@@ -22,6 +24,12 @@ local tfm = fonts.tfm
--
-- we could have a tnum variant as well
+-- In the userdata interface we can not longer tweak the loaded font as
+-- conveniently as before. For instance, instead of pushing extra data in
+-- in the table using the original structure, we now have to operate on
+-- the mkiv representation. And as the fontloader interface is modelled
+-- after fontforge we cannot change that one too much either.
+
local extra_lists = {
tlig = {
{
@@ -76,142 +84,157 @@ local extra_lists = {
local extra_features = { -- maybe just 1..n so that we prescribe order
tlig = {
{
- features = { { scripts = { { script = "*", langs = { "*" }, } }, tag = "tlig", comment = "added bij mkiv" }, },
+ features = { ["*"] = { ["*"] = true } },
name = "ctx_tlig_1",
- subtables = { { name = "ctx_tlig_1_s" } },
+ subtables = { "ctx_tlig_1_s" },
type = "gsub_ligature",
flags = { },
},
},
trep = {
{
- features = { { scripts = { { script = "*", langs = { "*" }, } }, tag = "trep", comment = "added bij mkiv" }, },
+ features = { ["*"] = { ["*"] = true } },
name = "ctx_trep_1",
- subtables = { { name = "ctx_trep_1_s" } },
+ subtables = { "ctx_trep_1_s" },
type = "gsub_single",
flags = { },
},
},
anum = {
{
- features = { { scripts = { { script = "arab", langs = { "dflt", "ARA" }, } }, tag = "anum", comment = "added bij mkiv" }, },
+ features = { arab = { FAR = true, dflt = true } },
name = "ctx_anum_1",
- subtables = { { name = "ctx_anum_1_s" } },
+ subtables = { "ctx_anum_1_s" },
type = "gsub_single",
flags = { },
},
{
- features = { { scripts = { { script = "arab", langs = { "FAR" }, } }, tag = "anum", comment = "added bij mkiv" }, },
+ features = { arab = { FAR = true } },
name = "ctx_anum_2",
- subtables = { { name = "ctx_anum_2_s" } },
+ subtables = { "ctx_anum_2_s" },
type = "gsub_single",
flags = { },
},
},
}
-fonts.otf.enhancers["add some missing characters"] = function(data,filename)
- -- todo
-end
-
-fonts.otf.enhancers["enrich with features"] = function(data,filename)
- -- could be done elsewhere (true can be #)
- local used = { }
- for i=1,#otf.glists do
- local g = data[otf.glists[i]]
- if g then
- for i=1,#g do
- local f = g[i].features
- if f then
- for i=1,#f do
- local t = f[i].tag
- if t then used[t] = true end
- end
- end
- end
- end
- end
- --
+local function enhancedata(data,filename,raw)
+ local luatex = data.luatex
+ local lookups = luatex.lookups
+ local sequences = luatex.sequences
local glyphs = data.glyphs
- local indices = data.map.map
- data.gsub = data.gsub or { }
+ local indices = luatex.indices
+ local gsubfeatures = luatex.features.gsub
for kind, specifications in next, extra_features do
- if not used[kind] then
+ if gsub and gsub[kind] then
+ -- already present
+ else
local done = 0
for s=1,#specifications do
local added = false
local specification = specifications[s]
+ local features, subtables = specification.features, specification.subtables
+ local name, type, flags = specification.name, specification.type, specification.flags
+ local full = subtables[1]
local list = extra_lists[kind][s]
- local name = specification.name .. "_s"
- if specification.type == "gsub_ligature" then
+ if type == "gsub_ligature" then
+ -- inefficient loop
for unicode, index in next, indices do
local glyph = glyphs[index]
local ligature = list[glyph.name]
if ligature then
- local o = glyph.lookups or { }
- -- o[name] = { "ligature", ligature, glyph.name }
- o[name] = {
- {
- ["type"] = "ligature",
- ["specification"] = {
- char = glyph.name,
- components = ligature,
- }
- }
- }
- glyph.lookups, done, added = o, done+1, true
+ if glyph.slookups then
+ glyph.slookups [full] = { "ligature", ligature, glyph.name }
+ else
+ glyph.slookups = { [full] = { "ligature", ligature, glyph.name } }
+ end
+ done, added = done+1, true
end
end
- elseif specification.type == "gsub_single" then
+ elseif type == "gsub_single" then
+ -- inefficient loop
for unicode, index in next, indices do
local glyph = glyphs[index]
local r = list[unicode]
if r then
local replacement = indices[r]
if replacement and glyphs[replacement] then
- local o = glyph.lookups or { }
- -- o[name] = { { "substitution", glyphs[replacement].name } }
- o[name] = {
- {
- ["type"] = "substitution",
- ["specification"] = {
- variant = glyphs[replacement].name,
- }
- }
- }
- glyph.lookups, done, added = o, done+1, true
+ if glyph.slookups then
+ glyph.slookups [full] = { "substitution", glyphs[replacement].name }
+ else
+ glyph.slookups = { [full] = { "substitution", glyphs[replacement].name } }
+ end
+ done, added = done+1, true
end
end
end
end
if added then
- insert(data.gsub,s,table.fastcopy(specification)) -- right order
+ sequences[#sequences+1] = {
+ chain = 0,
+ features = { [kind] = features },
+ flags = flags,
+ name = name,
+ subtables = subtables,
+ type = type,
+ }
+ -- register in metadata (merge as there can be a few)
+ if not gsubfeatures then
+ gsubfeatures = { }
+ luatex.features.gsub = gsubfeatures
+ end
+ local k = gsubfeatures[kind]
+ if not k then
+ k = { }
+ gsubfeatures[kind] = k
+ end
+ for script, languages in next, features do
+ local kk = k[script]
+ if not kk then
+ kk = { }
+ k[script] = kk
+ end
+ for language, value in next, languages do
+ kk[language] = value
+ end
+ end
end
end
if done > 0 then
if trace_loading then
- logs.report("load otf","enhance: registering %s feature (%s glyphs affected)",kind,done)
+ report_otf("enhance: registering %s feature (%s glyphs affected)",kind,done)
end
end
end
end
end
-otf.tables.features['tlig'] = 'TeX Ligatures'
-otf.tables.features['trep'] = 'TeX Replacements'
-otf.tables.features['anum'] = 'Arabic Digits'
+otf.enhancers.register("check extra features",enhancedata)
-otf.features.register_base_substitution('tlig')
-otf.features.register_base_substitution('trep')
-otf.features.register_base_substitution('anum')
+local features = otf.tables.features
+
+features['tlig'] = 'TeX Ligatures'
+features['trep'] = 'TeX Replacements'
+features['anum'] = 'Arabic Digits'
+
+local registerbasesubstitution = otf.features.registerbasesubstitution
+
+registerbasesubstitution('tlig')
+registerbasesubstitution('trep')
+registerbasesubstitution('anum')
-- the functionality is defined elsewhere
-fonts.initializers.base.otf.equaldigits = fonts.initializers.common.equaldigits
-fonts.initializers.node.otf.equaldigits = fonts.initializers.common.equaldigits
+local initializers = fonts.initializers
+local common_initializers = initializers.common
+local base_initializers = initializers.base.otf
+local node_initializers = initializers.node.otf
+
+base_initializers.equaldigits = common_initializers.equaldigits
+node_initializers.equaldigits = common_initializers.equaldigits
-fonts.initializers.base.otf.lineheight = fonts.initializers.common.lineheight
-fonts.initializers.node.otf.lineheight = fonts.initializers.common.lineheight
+base_initializers.lineheight = common_initializers.lineheight
+node_initializers.lineheight = common_initializers.lineheight
-fonts.initializers.base.otf.compose = fonts.initializers.common.compose
-fonts.initializers.node.otf.compose = fonts.initializers.common.compose
+base_initializers.compose = common_initializers.compose
+node_initializers.compose = common_initializers.compose
diff --git a/otfl-font-otd.lua b/otfl-font-otd.lua
index 46899fd..910725a 100644
--- a/otfl-font-otd.lua
+++ b/otfl-font-otd.lua
@@ -6,25 +6,28 @@ if not modules then modules = { } end modules ['font-otd'] = {
license = "see context related readme files"
}
-local trace_dynamics = false trackers.register("otf.dynamics", function(v) trace_dynamics = v end)
+local trace_dynamics = false trackers.register("otf.dynamics", function(v) trace_dynamics = v end)
-fonts = fonts or { }
-fonts.otf = fonts.otf or { }
+local report_otf = logs.new("load otf")
-local otf = fonts.otf
-local fontdata = fonts.ids
+local fonts = fonts
+local otf = fonts.otf
+local fontdata = fonts.ids
otf.features = otf.features or { }
otf.features.default = otf.features.default or { }
-local context_setups = fonts.define.specify.context_setups
-local context_numbers = fonts.define.specify.context_numbers
+local definers = fonts.definers
+local contextsetups = definers.specifiers.contextsetups
+local contextnumbers = definers.specifiers.contextnumbers
-local a_to_script = { } otf.a_to_script = a_to_script
-local a_to_language = { } otf.a_to_language = a_to_language
+-- todo: dynamics namespace
-function otf.set_dynamics(font,dynamics,attribute)
- local features = context_setups[context_numbers[attribute]] -- can be moved to caller
+local a_to_script = { }
+local a_to_language = { }
+
+function otf.setdynamics(font,dynamics,attribute)
+ local features = contextsetups[contextnumbers[attribute]] -- can be moved to caller
if features then
local script = features.script or 'dflt'
local language = features.language or 'dflt'
@@ -41,7 +44,7 @@ function otf.set_dynamics(font,dynamics,attribute)
local dsla = dsl[attribute]
if dsla then
-- if trace_dynamics then
- -- logs.report("otf define","using dynamics %s: attribute %s, script %s, language %s",context_numbers[attribute],attribute,script,language)
+ -- report_otf("using dynamics %s: attribute %s, script %s, language %s",contextnumbers[attribute],attribute,script,language)
-- end
return dsla
else
@@ -56,14 +59,15 @@ function otf.set_dynamics(font,dynamics,attribute)
features = tfmdata.shared.features
}
tfmdata.mode = "node"
+ tfmdata.dynamics = true -- handy for tracing
tfmdata.language = language
tfmdata.script = script
tfmdata.shared.features = { }
-- end of save
- local set = fonts.define.check(features,otf.features.default)
- dsla = otf.set_features(tfmdata,set)
+ local set = definers.check(features,otf.features.default)
+ dsla = otf.setfeatures(tfmdata,set)
if trace_dynamics then
- logs.report("otf define","setting dynamics %s: attribute %s, script %s, language %s, set: %s",context_numbers[attribute],attribute,script,language,table.sequenced(set))
+ report_otf("setting dynamics %s: attribute %s, script %s, language %s, set: %s",contextnumbers[attribute],attribute,script,language,table.sequenced(set))
end
-- we need to restore some values
tfmdata.script = saved.script
@@ -77,3 +81,11 @@ function otf.set_dynamics(font,dynamics,attribute)
end
return nil -- { }
end
+
+function otf.scriptandlanguage(tfmdata,attr)
+ if attr and attr > 0 then
+ return a_to_script[attr] or tfmdata.script, a_to_language[attr] or tfmdata.language
+ else
+ return tfmdata.script, tfmdata.language
+ end
+end
diff --git a/otfl-font-otf.lua b/otfl-font-otf.lua
index d1ad3d0..085950d 100644
--- a/otfl-font-otf.lua
+++ b/otfl-font-otf.lua
@@ -6,6 +6,11 @@ if not modules then modules = { } end modules ['font-otf'] = {
license = "see context related readme files"
}
+-- langs -> languages enz
+-- anchor_classes vs kernclasses
+-- modification/creationtime in subfont is runtime dus zinloos
+-- to_table -> totable
+
local utf = unicode.utf8
local concat, utfbyte = table.concat, utf.byte
@@ -14,89 +19,140 @@ local type, next, tonumber, tostring = type, next, tonumber, tostring
local abs = math.abs
local getn = table.getn
local lpegmatch = lpeg.match
+local reverse = table.reverse
+local ioflush = io.flush
-local trace_private = false trackers.register("otf.private", function(v) trace_private = v end)
-local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
-local trace_features = false trackers.register("otf.features", function(v) trace_features = v end)
-local trace_dynamics = false trackers.register("otf.dynamics", function(v) trace_dynamics = v end)
-local trace_sequences = false trackers.register("otf.sequences", function(v) trace_sequences = v end)
-local trace_math = false trackers.register("otf.math", function(v) trace_math = v end)
-local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
+local allocate = utilities.storage.allocate
---~ trackers.enable("otf.loading")
+local trace_private = false trackers.register("otf.private", function(v) trace_private = v end)
+local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
+local trace_features = false trackers.register("otf.features", function(v) trace_features = v end)
+local trace_dynamics = false trackers.register("otf.dynamics", function(v) trace_dynamics = v end)
+local trace_sequences = false trackers.register("otf.sequences", function(v) trace_sequences = v end)
+local trace_math = false trackers.register("otf.math", function(v) trace_math = v end)
+local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
---[[ldx--
-<p>The fontforge table has organized lookups in a certain way. A first implementation
-of this code was organized featurewise: information related to features was
-collected and processing boiled down to a run over the features. The current
-implementation honors the order in the main feature table. Since we can reorder this
-table as we want, we can eventually support several models of processing. We kept
-the static as well as dynamic feature processing, because it had proved to be
-rather useful. The formerly three loop variants have beem discarded but will
-reapear at some time.</p>
-
-<itemize>
-<item>we loop over all lookups</item>
-<item>for each lookup we do a run over the list of glyphs</item>
-<item>but we only process them for features that are enabled</item>
-<item>if we're dealing with a contextual lookup, we loop over all contexts</item>
-<item>in that loop we quit at a match and then process the list of sublookups</item>
-<item>we always continue after the match</item>
-</itemize>
-
-<p>In <l n='context'/> we do this for each font that is used in a list, so in
-practice we have quite some nested loops.</p>
-
-<p>We process the whole list and then consult the glyph nodes. An alternative approach
-is to collect strings of characters using the same font including spaces (because some
-lookups involve spaces). However, we then need to reconstruct the list which is no fun.
-Also, we need to carry quite some information, like attributes, so eventually we don't
-gain much (if we gain something at all).</p>
-
-<p>Another consideration has been to operate on sublists (subhead, subtail) but again
-this would complicate matters as we then neext to keep track of a changing subhead
-and subtail. On the other hand, this might save some runtime. The number of changes
-involved is not that large. This only makes sense when we have many fonts in a list
-and don't change to frequently.</p>
---ldx]]--
+local report_otf = logs.new("load otf")
-fonts = fonts or { }
-fonts.otf = fonts.otf or { }
-fonts.tfm = fonts.tfm or { }
+local starttiming, stoptiming, elapsedtime = statistics.starttiming, statistics.stoptiming, statistics.elapsedtime
+
+local fonts = fonts
+fonts.otf = fonts.otf or { }
local otf = fonts.otf
local tfm = fonts.tfm
local fontdata = fonts.ids
-
-otf.tables = otf.tables or { } -- defined in font-ott.lua
-otf.meanings = otf.meanings or { } -- defined in font-ott.lua
-otf.tables.features = otf.tables.features or { } -- defined in font-ott.lua
-otf.tables.languages = otf.tables.languages or { } -- defined in font-ott.lua
-otf.tables.scripts = otf.tables.scripts or { } -- defined in font-ott.lua
+local chardata = characters.data
otf.features = otf.features or { }
otf.features.list = otf.features.list or { }
otf.features.default = otf.features.default or { }
-otf.enhancers = otf.enhancers or { }
+otf.enhancers = allocate()
+local enhancers = otf.enhancers
+enhancers.patches = { }
+
+local definers = fonts.definers
+
otf.glists = { "gsub", "gpos" }
-otf.version = 2.653 -- beware: also sync font-mis.lua
-otf.pack = true -- beware: also sync font-mis.lua
-otf.syncspace = true
-otf.notdef = false
+otf.version = 2.705 -- beware: also sync font-mis.lua
otf.cache = containers.define("fonts", "otf", otf.version, true)
-otf.cleanup_aat = false -- only context
-local wildcard = "*"
-local default = "dflt"
+local loadmethod = "table" -- table, mixed, sparse
+local forceload = false
+local cleanup = 0
+local usemetatables = false -- .4 slower on mk but 30 M less mem so we might change the default -- will be directive
+local packdata = true
+local syncspace = true
+local forcenotdef = false
+
+local wildcard = "*"
+local default = "dflt"
+
+local fontloaderfields = fontloader.fields
+local mainfields = nil
+local glyphfields = nil -- not used yet
+
+directives.register("fonts.otf.loader.method", function(v)
+ if v == "sparse" and fontloaderfields then
+ loadmethod = "sparse"
+ elseif v == "mixed" then
+ loadmethod = "mixed"
+ elseif v == "table" then
+ loadmethod = "table"
+ else
+ loadmethod = "table"
+ report_otf("no loader method '%s', using '%s' instead",v,loadmethod)
+ end
+end)
+
+directives.register("fonts.otf.loader.cleanup",function(v)
+ cleanup = tonumber(v) or (v and 1) or 0
+end)
+
+directives.register("fonts.otf.loader.force", function(v) forceload = v end)
+directives.register("fonts.otf.loader.usemetatables", function(v) usemetatables = v end)
+directives.register("fonts.otf.loader.pack", function(v) packdata = v end)
+directives.register("fonts.otf.loader.syncspace", function(v) syncspace = v end)
+directives.register("fonts.otf.loader.forcenotdef", function(v) forcenotdef = v end)
+
+local function load_featurefile(raw,featurefile)
+ if featurefile and featurefile ~= "" then
+ if trace_loading then
+ report_otf("featurefile: %s", featurefile)
+ end
+ fontloader.apply_featurefile(raw, featurefile)
+ end
+end
+
+local function showfeatureorder(otfdata,filename)
+ local sequences = otfdata.luatex.sequences
+ if sequences and #sequences > 0 then
+ if trace_loading then
+ report_otf("font %s has %s sequences",filename,#sequences)
+ report_otf(" ")
+ end
+ for nos=1,#sequences do
+ local sequence = sequences[nos]
+ local typ = sequence.type or "no-type"
+ local name = sequence.name or "no-name"
+ local subtables = sequence.subtables or { "no-subtables" }
+ local features = sequence.features
+ if trace_loading then
+ report_otf("%3i %-15s %-20s [%s]",nos,name,typ,concat(subtables,","))
+ end
+ if features then
+ for feature, scripts in next, features do
+ local tt = { }
+ for script, languages in next, scripts do
+ local ttt = { }
+ for language, _ in next, languages do
+ ttt[#ttt+1] = language
+ end
+ tt[#tt+1] = format("[%s: %s]",script,concat(ttt," "))
+ end
+ if trace_loading then
+ report_otf(" %s: %s",feature,concat(tt," "))
+ end
+ end
+ end
+ end
+ if trace_loading then
+ report_otf("\n")
+ end
+ elseif trace_loading then
+ report_otf("font %s has no sequences",filename)
+ end
+end
--[[ldx--
<p>We start with a lot of tables and related functions.</p>
--ldx]]--
-otf.tables.global_fields = table.tohash {
+local global_fields = table.tohash {
+ "metadata",
"lookups",
"glyphs",
"subfonts",
@@ -107,20 +163,20 @@ otf.tables.global_fields = table.tohash {
"names",
"unicodes",
"names",
---~ "math",
+ -- "math",
"anchor_classes",
"kern_classes",
"gpos",
"gsub"
}
-otf.tables.valid_fields = {
- "anchor_classes",
+local valid_fields = table.tohash {
+ -- "anchor_classes",
"ascent",
- "cache_version",
+ -- "cache_version",
"cidinfo",
"copyright",
- "creationtime",
+ -- "creationtime",
"descent",
"design_range_bottom",
"design_range_top",
@@ -132,23 +188,23 @@ otf.tables.valid_fields = {
"fontstyle_id",
"fontstyle_name",
"fullname",
- "glyphs",
+ -- "glyphs",
"hasvmetrics",
"head_optimized_for_cleartype",
"horiz_base",
"issans",
"isserif",
"italicangle",
- "kerns",
- "lookups",
+ -- "kerns",
+ -- "lookups",
-- "luatex",
"macstyle",
- "modificationtime",
+ -- "modificationtime",
"onlybitmaps",
"origname",
"os2_version",
- "pfminfo",
- "private",
+ -- "pfminfo",
+ -- "private",
"serifcheck",
"sfd_version",
-- "size",
@@ -165,65 +221,116 @@ otf.tables.valid_fields = {
"upos",
"use_typo_metrics",
"uwidth",
- "validation_state",
+ -- "validation_state",
"verbose",
"version",
"vert_base",
"weight",
"weight_width_slope_only",
- "xuid",
+ -- "xuid",
+}
+
+local ordered_enhancers = {
+ "prepare tables",
+ "prepare glyphs",
+ "prepare unicodes",
+ "prepare lookups",
+
+ "analyze glyphs",
+ "analyze math",
+
+ "prepare tounicode", -- maybe merge with prepare
+
+ "reorganize lookups",
+ "reorganize mark classes",
+ "reorganize anchor classes",
+
+ "reorganize glyph kerns",
+ "reorganize glyph lookups",
+ "reorganize glyph anchors",
+
+ "reorganize features",
+ "reorganize subtables",
+
+ "check glyphs",
+ "check metadata",
+ "check math parameters",
+ "check extra features", -- after metadata
}
--[[ldx--
<p>Here we go.</p>
--ldx]]--
-local function load_featurefile(ff,featurefile)
- if featurefile then
- featurefile = resolvers.find_file(file.addsuffix(featurefile,'fea'),'fea')
- if featurefile and featurefile ~= "" then
- if trace_loading then
- logs.report("load otf", "featurefile: %s", featurefile)
- end
- fontloader.apply_featurefile(ff, featurefile)
+local actions = { }
+
+enhancers.patches.before = allocate()
+enhancers.patches.after = allocate()
+
+local before = enhancers.patches.before
+local after = enhancers.patches.after
+
+local function enhance(name,data,filename,raw,verbose)
+ local enhancer = actions[name]
+ if enhancer then
+ if verbose then
+ report_otf("enhance: %s (%s)",name,filename)
+ ioflush()
end
+ enhancer(data,filename,raw)
+ else
+ report_otf("enhance: %s is undefined",name)
end
end
-function otf.enhance(name,data,filename,verbose)
- local enhancer = otf.enhancers[name]
- if enhancer then
- if (verbose ~= nil and verbose) or trace_loading then
- logs.report("load otf","enhance: %s (%s)",name,filename)
+function enhancers.apply(data,filename,raw,verbose)
+ local basename = file.basename(lower(filename))
+ report_otf("start enhancing: %s",filename)
+ ioflush() -- we want instant messages
+ for e=1,#ordered_enhancers do
+ local enhancer = ordered_enhancers[e]
+ local b = before[enhancer]
+ if b then
+ for pattern, action in next, b do
+ if find(basename,pattern) then
+ action(data,filename,raw)
+ end
+ end
+ end
+ enhance(enhancer,data,filename,raw,verbose)
+ local a = after[enhancer]
+ if a then
+ for pattern, action in next, a do
+ if find(basename,pattern) then
+ action(data,filename,raw)
+ end
+ end
end
- enhancer(data,filename)
+ ioflush() -- we want instant messages
end
+ report_otf("stop enhancing")
+ ioflush() -- we want instant messages
end
-local enhancers = {
- -- pack and unpack are handled separately; they might even be moved
- -- away from the enhancers namespace
- "patch bugs",
- "merge cid fonts", "prepare unicode", "cleanup ttf tables", "compact glyphs", "reverse coverage",
- "cleanup aat", "enrich with features", "add some missing characters",
- "reorganize mark classes",
- "reorganize kerns", -- moved here
- "flatten glyph lookups", "flatten anchor tables", "flatten feature tables",
- "simplify glyph lookups", -- some saving
- "prepare luatex tables",
- "analyse features", "rehash features",
- "analyse anchors", "analyse marks", "analyse unicodes", "analyse subtables",
- "check italic correction","check math",
- "share widths",
- "strip not needed data",
- "migrate metadata",
- "check math parameters",
-}
+-- enhancers.patches.register("before","migrate metadata","cambria",function() end)
+
+function enhancers.patches.register(what,where,pattern,action)
+ local ww = what[where]
+ if ww then
+ ww[pattern] = action
+ else
+ ww = { [pattern] = action}
+ end
+end
+
+function enhancers.register(what,action) -- only already registered can be overloaded
+ actions[what] = action
+end
function otf.load(filename,format,sub,featurefile)
local name = file.basename(file.removesuffix(filename))
local attr = lfs.attributes(filename)
- local size, time = attr.size or 0, attr.modification or 0
+ local size, time = attr and attr.size or 0, attr and attr.modification or 0
if featurefile then
name = name .. "@" .. file.removesuffix(file.basename(featurefile))
end
@@ -233,151 +340,467 @@ function otf.load(filename,format,sub,featurefile)
hash = hash .. "-" .. sub
end
hash = containers.cleanname(hash)
+ local featurefiles
+ if featurefile then
+ featurefiles = { }
+ for s in gmatch(featurefile,"[^,]+") do
+ local name = resolvers.findfile(file.addsuffix(s,'fea'),'fea') or ""
+ if name == "" then
+ report_otf("loading: no featurefile '%s'",s)
+ else
+ local attr = lfs.attributes(name)
+ featurefiles[#featurefiles+1] = {
+ name = name,
+ size = attr.size or 0,
+ time = attr.modification or 0,
+ }
+ end
+ end
+ if #featurefiles == 0 then
+ featurefiles = nil
+ end
+ end
local data = containers.read(otf.cache,hash)
- if not data or data.verbose ~= fonts.verbose or data.size ~= size or data.time ~= time then
- logs.report("load otf","loading: %s (hash: %s)",filename,hash)
- local ff, messages
+ local reload = not data or data.verbose ~= fonts.verbose or data.size ~= size or data.time ~= time
+ if forceload then
+ report_otf("loading: forced reload due to hard coded flag")
+ reload = true
+ end
+ if not reload then
+ local featuredata = data.featuredata
+ if featurefiles then
+ if not featuredata or #featuredata ~= #featurefiles then
+ reload = true
+ else
+ for i=1,#featurefiles do
+ local fi, fd = featurefiles[i], featuredata[i]
+ if fi.name ~= fd.name or fi.size ~= fd.size or fi.time ~= fd.time then
+ reload = true
+ break
+ end
+ end
+ end
+ elseif featuredata then
+ reload = true
+ end
+ if reload then
+ report_otf("loading: forced reload due to changed featurefile specification: %s",featurefile or "--")
+ end
+ end
+ if reload then
+ report_otf("loading: %s (hash: %s)",filename,hash)
+ local fontdata, messages, rawdata
if sub then
- ff, messages = fontloader.open(filename,sub)
+ fontdata, messages = fontloader.open(filename,sub)
else
- ff, messages = fontloader.open(filename)
+ fontdata, messages = fontloader.open(filename)
+ end
+ if fontdata then
+ mainfields = mainfields or (fontloaderfields and fontloaderfields(fontdata))
end
if trace_loading and messages and #messages > 0 then
if type(messages) == "string" then
- logs.report("load otf","warning: %s",messages)
+ report_otf("warning: %s",messages)
else
for m=1,#messages do
- logs.report("load otf","warning: %s",tostring(messages[m]))
+ report_otf("warning: %s",tostring(messages[m]))
end
end
else
- logs.report("load otf","font loaded okay")
+ report_otf("font loaded okay")
end
- if ff then
- load_featurefile(ff,featurefile)
- data = fontloader.to_table(ff)
- fontloader.close(ff)
- if data then
- logs.report("load otf","file size: %s", size)
- logs.report("load otf","enhancing ...")
- for e=1,#enhancers do
- otf.enhance(enhancers[e],data,filename)
- io.flush() -- we want instant messages
+ if fontdata then
+ if featurefiles then
+ for i=1,#featurefiles do
+ load_featurefile(fontdata,featurefiles[i].name)
end
- if otf.pack and not fonts.verbose then
- otf.enhance("pack",data,filename)
+ end
+ report_otf("loading method: %s",loadmethod)
+ if loadmethod == "sparse" then
+ rawdata = fontdata
+ else
+ rawdata = fontloader.to_table(fontdata)
+ fontloader.close(fontdata)
+ end
+ if rawdata then
+ data = { }
+ starttiming(data)
+ local verboseindeed = verbose ~= nil and verbose or trace_loading
+ report_otf("file size: %s", size)
+ enhancers.apply(data,filename,rawdata,verboseindeed)
+ if packdata and not fonts.verbose then
+ enhance("pack",data,filename,nil,verboseindeed)
end
data.size = size
data.time = time
+ if featurefiles then
+ data.featuredata = featurefiles
+ end
data.verbose = fonts.verbose
- logs.report("load otf","saving in cache: %s",filename)
+ report_otf("saving in cache: %s",filename)
data = containers.write(otf.cache, hash, data)
- collectgarbage("collect")
+ if cleanup > 0 then
+ collectgarbage("collect")
+ end
+ stoptiming(data)
+ if elapsedtime then -- not in generic
+ report_otf("preprocessing and caching took %s seconds",elapsedtime(data))
+ end
data = containers.read(otf.cache, hash) -- this frees the old table and load the sparse one
- collectgarbage("collect")
+ if cleanup > 1 then
+ collectgarbage("collect")
+ end
else
- logs.report("load otf","loading failed (table conversion error)")
+ data = nil
+ report_otf("loading failed (table conversion error)")
+ end
+ if loadmethod == "sparse" then
+ fontloader.close(fontdata)
+ if cleanup > 2 then
+ -- collectgarbage("collect")
+ end
end
else
- logs.report("load otf","loading failed (file read error)")
+ data = nil
+ report_otf("loading failed (file read error)")
end
end
if data then
if trace_defining then
- logs.report("define font","loading from cache: %s",hash)
+ report_otf("loading from cache: %s",hash)
end
- otf.enhance("unpack",data,filename,false) -- no message here
- otf.add_dimensions(data)
+ enhance("unpack",data,filename,nil,false)
+ enhance("add dimensions",data,filename,nil,false)
if trace_sequences then
- otf.show_feature_order(data,filename)
+ showfeatureorder(data,filename)
end
end
return data
end
-function otf.add_dimensions(data)
+local mt = {
+ __index = function(t,k) -- maybe set it
+ if k == "height" then
+ local ht = t.boundingbox[4]
+ return ht < 0 and 0 or ht
+ elseif k == "depth" then
+ local dp = -t.boundingbox[2]
+ return dp < 0 and 0 or dp
+ elseif k == "width" then
+ return 0
+ elseif k == "name" then -- or maybe uni*
+ return forcenotdef and ".notdef"
+ end
+ end
+}
+
+actions["add dimensions"] = function(data,filename)
-- todo: forget about the width if it's the defaultwidth (saves mem)
-- we could also build the marks hash here (instead of storing it)
if data then
- local force = otf.notdef
local luatex = data.luatex
local defaultwidth = luatex.defaultwidth or 0
local defaultheight = luatex.defaultheight or 0
local defaultdepth = luatex.defaultdepth or 0
- for _, d in next, data.glyphs do
- local bb, wd = d.boundingbox, d.width
- if not wd then
- d.width = defaultwidth
- elseif wd ~= 0 and d.class == "mark" then
- d.width = -wd
+ if usemetatables then
+ for _, d in next, data.glyphs do
+ local wd = d.width
+ if not wd then
+ d.width = defaultwidth
+ elseif wd ~= 0 and d.class == "mark" then
+ d.width = -wd
+ end
+ setmetatable(d,mt)
end
- if force and not d.name then
- d.name = ".notdef"
+ else
+ for _, d in next, data.glyphs do
+ local bb, wd = d.boundingbox, d.width
+ if not wd then
+ d.width = defaultwidth
+ elseif wd ~= 0 and d.class == "mark" then
+ d.width = -wd
+ end
+ if forcenotdef and not d.name then
+ d.name = ".notdef"
+ end
+ if bb then
+ local ht, dp = bb[4], -bb[2]
+ if ht == 0 or ht < 0 then
+ -- not set
+ else
+ d.height = ht
+ end
+ if dp == 0 or dp < 0 then
+ -- not set
+ else
+ d.depth = dp
+ end
+ end
end
- if bb then
- local ht, dp = bb[4], -bb[2]
- if ht == 0 or ht < 0 then
- -- no need to set it and no negative heights, nil == 0
+ end
+ end
+end
+
+actions["prepare tables"] = function(data,filename,raw)
+ local luatex = {
+ filename = filename,
+ version = otf.version,
+ creator = "context mkiv",
+ }
+ data.luatex = luatex
+ data.metadata = { }
+end
+
+local function somecopy(old) -- fast one
+ if old then
+ local new = { }
+ if type(old) == "table" then
+ for k, v in next, old do
+ if k == "glyphs" then
+ -- skip
+ elseif type(v) == "table" then
+ new[k] = somecopy(v)
else
- d.height = ht
+ new[k] = v
end
- if dp == 0 or dp < 0 then
- -- no negative depths and no negative depths, nil == 0
+ end
+ else
+ for i=1,#mainfields do
+ local k = mainfields[i]
+ local v = old[k]
+ if k == "glyphs" then
+ -- skip
+ elseif type(v) == "table" then
+ new[k] = somecopy(v)
else
- d.depth = dp
+ new[k] = v
end
end
end
+ return new
+ else
+ return { }
end
end
-function otf.show_feature_order(otfdata,filename)
- local sequences = otfdata.luatex.sequences
- if sequences and #sequences > 0 then
- if trace_loading then
- logs.report("otf check","font %s has %s sequences",filename,#sequences)
- logs.report("otf check"," ")
+-- not setting italic_correction and class (when nil) during
+-- table cronstruction can save some mem
+
+actions["prepare glyphs"] = function(data,filename,raw)
+ -- we can also move the names to data.luatex.names which might
+ -- save us some more memory (at the cost of harder tracing)
+ local rawglyphs = raw.glyphs
+ local glyphs, udglyphs
+ if loadmethod == "sparse" then
+ glyphs, udglyphs = { }, { }
+ elseif loadmethod == "mixed" then
+ glyphs, udglyphs = { }, rawglyphs
+ else
+ glyphs, udglyphs = rawglyphs, rawglyphs
+ end
+ data.glyphs, data.udglyphs = glyphs, udglyphs
+ local subfonts = raw.subfonts
+ if subfonts then
+ if data.glyphs and next(data.glyphs) then
+ report_otf("replacing existing glyph table due to subfonts")
end
- for nos=1,#sequences do
- local sequence = sequences[nos]
- local typ = sequence.type or "no-type"
- local name = sequence.name or "no-name"
- local subtables = sequence.subtables or { "no-subtables" }
- local features = sequence.features
- if trace_loading then
- logs.report("otf check","%3i %-15s %-20s [%s]",nos,name,typ,concat(subtables,","))
- end
- if features then
- for feature, scripts in next, features do
- local tt = { }
- for script, languages in next, scripts do
- local ttt = { }
- for language, _ in next, languages do
- ttt[#ttt+1] = language
+ local cidinfo = raw.cidinfo
+ if cidinfo.registry then
+ local cidmap, cidname = fonts.cid.getmap(cidinfo.registry,cidinfo.ordering,cidinfo.supplement)
+ if cidmap then
+ cidinfo.usedname = cidmap.usedname
+ local uni_to_int, int_to_uni, nofnames, nofunicodes = { }, { }, 0, 0
+ local unicodes, names = cidmap.unicodes, cidmap.names
+ for cidindex=1,#subfonts do
+ local subfont = subfonts[cidindex]
+ if loadmethod == "sparse" then
+ local rawglyphs = subfont.glyphs
+ for index=0,subfont.glyphmax - 1 do
+ local g = rawglyphs[index]
+ if g then
+ local unicode, name = unicodes[index], names[index]
+ if unicode then
+ uni_to_int[unicode] = index
+ int_to_uni[index] = unicode
+ nofunicodes = nofunicodes + 1
+ elseif name then
+ nofnames = nofnames + 1
+ end
+ udglyphs[index] = g
+ glyphs[index] = {
+ width = g.width,
+ italic = g.italic_correction,
+ boundingbox = g.boundingbox,
+ class = g.class,
+ name = g.name or name or "unknown", -- uniXXXX
+ cidindex = cidindex,
+ unicode = unicode,
+ }
+ end
end
- tt[#tt+1] = format("[%s: %s]",script,concat(ttt," "))
- end
- if trace_loading then
- logs.report("otf check"," %s: %s",feature,concat(tt," "))
+ -- If we had more userdata, we would need more of this
+ -- and it would start working against us in terms of
+ -- convenience and speed.
+ subfont = somecopy(subfont)
+ subfont.glyphs = nil
+ subfont[cidindex] = subfont
+ elseif loadmethod == "mixed" then
+ for index, g in next, subfont.glyphs do
+ local unicode, name = unicodes[index], names[index]
+ if unicode then
+ uni_to_int[unicode] = index
+ int_to_uni[index] = unicode
+ nofunicodes = nofunicodes + 1
+ elseif name then
+ nofnames = nofnames + 1
+ end
+ udglyphs[index] = g
+ glyphs[index] = {
+ width = g.width,
+ italic = g.italic_correction,
+ boundingbox = g.boundingbox,
+ class = g.class,
+ name = g.name or name or "unknown", -- uniXXXX
+ cidindex = cidindex,
+ unicode = unicode,
+ }
+ end
+ subfont.glyphs = nil
+ else
+ for index, g in next, subfont.glyphs do
+ local unicode, name = unicodes[index], names[index]
+ if unicode then
+ uni_to_int[unicode] = index
+ int_to_uni[index] = unicode
+ nofunicodes = nofunicodes + 1
+ g.unicode = unicode
+ elseif name then
+ nofnames = nofnames + 1
+ end
+ g.cidindex = cidindex
+ glyphs[index] = g
+ end
+ subfont.glyphs = nil
end
end
+ if trace_loading then
+ report_otf("cid font remapped, %s unicode points, %s symbolic names, %s glyphs",nofunicodes, nofnames, nofunicodes+nofnames)
+ end
+ data.map = data.map or { }
+ data.map.map = uni_to_int
+ data.map.backmap = int_to_uni
+ elseif trace_loading then
+ report_otf("unable to remap cid font, missing cid file for %s",filename)
+ end
+ data.subfonts = subfonts
+ elseif trace_loading then
+ report_otf("font %s has no glyphs",filename)
+ end
+ else
+ if loadmethod == "sparse" then
+ -- we get fields from the userdata glyph table and create
+ -- a minimal entry first
+ for index=0,raw.glyphmax - 1 do
+ local g = rawglyphs[index]
+ if g then
+ udglyphs[index] = g
+ glyphs[index] = {
+ width = g.width,
+ italic = g.italic_correction,
+ boundingbox = g.boundingbox,
+ class = g.class,
+ name = g.name,
+ unicode = g.unicode,
+ }
+ end
+ end
+ elseif loadmethod == "mixed" then
+ -- we get fields from the totable glyph table and copy to the
+ -- final glyph table so first we create a minimal entry
+ for index, g in next, rawglyphs do
+ udglyphs[index] = g
+ glyphs[index] = {
+ width = g.width,
+ italic = g.italic_correction,
+ boundingbox = g.boundingbox,
+ class = g.class,
+ name = g.name,
+ unicode = g.unicode,
+ }
end
+ else
+ -- we use the totable glyph table directly and manipulate the
+ -- entries in this (also final) table
end
+ data.map = raw.map
+ end
+ data.cidinfo = raw.cidinfo -- hack
+end
+
+-- watch copy of cidinfo: we can best make some more copies to data
+
+actions["analyze glyphs"] = function(data,filename,raw) -- maybe integrate this in the previous
+ local glyphs = data.glyphs
+ -- collect info
+ local has_italic, widths, marks = false, { }, { }
+ for index, glyph in next, glyphs do
+ local italic = glyph.italic_correction
+ if not italic then
+ -- skip
+ elseif italic == 0 then
+ glyph.italic_correction = nil
+ glyph.italic = nil
+ else
+ glyph.italic_correction = nil
+ glyph.italic = italic
+ has_italic = true
+ end
+ local width = glyph.width
+ widths[width] = (widths[width] or 0) + 1
+ local class = glyph.class
+ local unicode = glyph.unicode
+ if class == "mark" then
+ marks[unicode] = true
+ -- elseif chardata[unicode].category == "mn" then
+ -- marks[unicode] = true
+ -- glyph.class = "mark"
+ end
+ local a = glyph.altuni if a then glyph.altuni = nil end
+ local d = glyph.dependents if d then glyph.dependents = nil end
+ local v = glyph.vwidth if v then glyph.vwidth = nil end
+ end
+ -- flag italic
+ data.metadata.has_italic = has_italic
+ -- flag marks
+ data.luatex.marks = marks
+ -- share most common width for cjk fonts
+ local wd, most = 0, 1
+ for k,v in next, widths do
+ if v > most then
+ wd, most = k, v
+ end
+ end
+ if most > 1000 then -- maybe 500
if trace_loading then
- logs.report("otf check","\n")
+ report_otf("most common width: %s (%s times), sharing (cjk font)",wd,most)
end
- elseif trace_loading then
- logs.report("otf check","font %s has no sequences",filename)
+ for index, glyph in next, glyphs do
+ if glyph.width == wd then
+ glyph.width = nil
+ end
+ end
+ data.luatex.defaultwidth = wd
end
end
--- todo: normalize, design_size => designsize
-
-otf.enhancers["reorganize mark classes"] = function(data,filename)
- if data.mark_classes then
- local unicodes = data.luatex.unicodes
+actions["reorganize mark classes"] = function(data,filename,raw)
+ local mark_classes = raw.mark_classes
+ if mark_classes then
+ local luatex = data.luatex
+ local unicodes = luatex.unicodes
local reverse = { }
- for name, class in next, data.mark_classes do
+ luatex.markclasses = reverse
+ for name, class in next, mark_classes do
local t = { }
for s in gmatch(class,"[^ ]+") do
local us = unicodes[s]
@@ -391,58 +814,15 @@ otf.enhancers["reorganize mark classes"] = function(data,filename)
end
reverse[name] = t
end
- data.luatex.markclasses = reverse
- data.mark_classes = nil
- end
-end
-
-otf.enhancers["prepare luatex tables"] = function(data,filename)
- data.luatex = data.luatex or { }
- local luatex = data.luatex
- luatex.filename = filename
- luatex.version = otf.version
- luatex.creator = "context mkiv"
-end
-
-otf.enhancers["cleanup aat"] = function(data,filename)
- if otf.cleanup_aat then
- end
-end
-
-local function analyze_features(g, features)
- if g then
- local t, done = { }, { }
- for k=1,#g do
- local f = features or g[k].features
- if f then
- for k=1,#f do
- -- scripts and tag
- local tag = f[k].tag
- if not done[tag] then
- t[#t+1] = tag
- done[tag] = true
- end
- end
- end
- end
- if #t > 0 then
- return t
- end
+ data.mark_classes = nil -- when using table
end
- return nil
-end
-
-otf.enhancers["analyse features"] = function(data,filename)
- -- local luatex = data.luatex
- -- luatex.gposfeatures = analyze_features(data.gpos)
- -- luatex.gsubfeatures = analyze_features(data.gsub)
end
-otf.enhancers["rehash features"] = function(data,filename)
+actions["reorganize features"] = function(data,filename,raw) -- combine with other
local features = { }
data.luatex.features = features
for k, what in next, otf.glists do
- local dw = data[what]
+ local dw = raw[what]
if dw then
local f = { }
features[what] = f
@@ -455,8 +835,10 @@ otf.enhancers["rehash features"] = function(data,filename)
local tag = strip(lower(df.tag))
local ft = f[tag] if not ft then ft = {} f[tag] = ft end
local dscripts = df.scripts
- for script, languages in next, dscripts do
- script = strip(lower(script))
+ for i=1,#dscripts do
+ local d = dscripts[i]
+ local languages = d.langs
+ local script = strip(lower(d.script))
local fts = ft[script] if not fts then fts = {} ft[script] = fts end
for i=1,#languages do
fts[strip(lower(languages[i]))] = true
@@ -469,8 +851,8 @@ otf.enhancers["rehash features"] = function(data,filename)
end
end
-otf.enhancers["analyse anchors"] = function(data,filename)
- local classes = data.anchor_classes
+actions["reorganize anchor classes"] = function(data,filename,raw)
+ local classes = raw.anchor_classes -- anchor classes not in final table
local luatex = data.luatex
local anchor_to_lookup, lookup_to_anchor = { }, { }
luatex.anchor_to_lookup, luatex.lookup_to_anchor = anchor_to_lookup, lookup_to_anchor
@@ -495,179 +877,131 @@ otf.enhancers["analyse anchors"] = function(data,filename)
end
end
-otf.enhancers["analyse marks"] = function(data,filename)
- local glyphs = data.glyphs
- local marks = { }
- data.luatex.marks = marks
- for unicode, index in next, data.luatex.indices do
- local glyph = glyphs[index]
- if glyph.class == "mark" then
- marks[unicode] = true
- end
- end
+actions["prepare tounicode"] = function(data,filename,raw)
+ fonts.map.addtounicode(data,filename)
end
-otf.enhancers["analyse unicodes"] = fonts.map.add_to_unicode
-
-otf.enhancers["analyse subtables"] = function(data,filename)
- data.luatex = data.luatex or { }
+actions["reorganize subtables"] = function(data,filename,raw)
local luatex = data.luatex
- local sequences = { }
- local lookups = { }
- luatex.sequences = sequences
- luatex.lookups = lookups
- for _, g in next, { data.gsub, data.gpos } do
- for k=1,#g do
- local gk = g[k]
- local typ = gk.type
- if typ == "gsub_contextchain" or typ == "gpos_contextchain" then
- gk.chain = 1
- elseif typ == "gsub_reversecontextchain" or typ == "gpos_reversecontextchain" then
- gk.chain = -1
- else
- gk.chain = 0
- end
- local features = gk.features
- if features then
- sequences[#sequences+1] = gk
- -- scripts, tag, ismac
- local t = { }
- for f=1,#features do
- local feature = features[f]
- local hash = { }
- -- only script and langs matter
- for s, languages in next, feature.scripts do
- s = lower(s)
- local h = hash[s]
- if not h then h = { } hash[s] = h end
- for l=1,#languages do
- h[strip(lower(languages[l]))] = true
- end
+ local sequences, lookups = { }, { }
+ luatex.sequences, luatex.lookups = sequences, lookups
+ for _, what in next, otf.glists do
+ local dw = raw[what]
+ if dw then
+ for k=1,#dw do
+ local gk = dw[k]
+ local typ = gk.type
+ local chain =
+ (typ == "gsub_contextchain" or typ == "gpos_contextchain") and 1 or
+ (typ == "gsub_reversecontextchain" or typ == "gpos_reversecontextchain") and -1 or 0
+ --
+ local subtables = gk.subtables
+ if subtables then
+ local t = { }
+ for s=1,#subtables do
+ local subtable = subtables[s]
+ local name = subtable.name
+ t[#t+1] = name
end
- t[feature.tag] = hash
+ subtables = t
end
- gk.features = t
- else
- lookups[gk.name] = gk
- gk.name = nil
- end
- local subtables = gk.subtables
- if subtables then
- local t = { }
- for s=1,#subtables do
- local subtable = subtables[s]
- local name = subtable.name
- t[#t+1] = name
- end
- gk.subtables = t
- end
- local flags = gk.flags
- if flags then
- gk.flags = { -- forcing false packs nicer
- (flags.ignorecombiningmarks and "mark") or false,
- (flags.ignoreligatures and "ligature") or false,
- (flags.ignorebaseglyphs and "base") or false,
- flags.r2l or false,
- }
- if flags.mark_class then
- gk.markclass = luatex.markclasses[flags.mark_class]
+ local flags, markclass = gk.flags, nil
+ if flags then
+ local t = { -- forcing false packs nicer
+ (flags.ignorecombiningmarks and "mark") or false,
+ (flags.ignoreligatures and "ligature") or false,
+ (flags.ignorebaseglyphs and "base") or false,
+ flags.r2l or false,
+ }
+ markclass = flags.mark_class
+ if markclass then
+ markclass = luatex.markclasses[markclass]
+ end
+ flags = t
end
- end
- end
- end
-end
-
-otf.enhancers["merge cid fonts"] = function(data,filename)
- -- we can also move the names to data.luatex.names which might
- -- save us some more memory (at the cost of harder tracing)
- if data.subfonts then
- if data.glyphs and next(data.glyphs) then
- logs.report("load otf","replacing existing glyph table due to subfonts")
- end
- local cidinfo = data.cidinfo
- local verbose = fonts.verbose
- if cidinfo.registry then
- local cidmap, cidname = fonts.cid.getmap(cidinfo.registry,cidinfo.ordering,cidinfo.supplement)
- if cidmap then
- cidinfo.usedname = cidmap.usedname
- local glyphs, uni_to_int, int_to_uni, nofnames, nofunicodes = { }, { }, { }, 0, 0
- local unicodes, names = cidmap.unicodes, cidmap.names
- for n, subfont in next, data.subfonts do
- for index, g in next, subfont.glyphs do
- if not next(g) then
- -- dummy entry
- else
- local unicode, name = unicodes[index], names[index]
- g.cidindex = n
- g.boundingbox = g.boundingbox -- or zerobox
- g.name = g.name or name or "unknown"
- if unicode then
- uni_to_int[unicode] = index
- int_to_uni[index] = unicode
- nofunicodes = nofunicodes + 1
- g.unicode = unicode
- elseif name then
- nofnames = nofnames + 1
- g.unicode = -1
+ --
+ local name = gk.name
+ --
+ local features = gk.features
+ if features then
+ -- scripts, tag, ismac
+ local f = { }
+ for i=1,#features do
+ local df = features[i]
+ local tag = strip(lower(df.tag))
+ local ft = f[tag] if not ft then ft = {} f[tag] = ft end
+ local dscripts = df.scripts
+ for i=1,#dscripts do
+ local d = dscripts[i]
+ local languages = d.langs
+ local script = strip(lower(d.script))
+ local fts = ft[script] if not fts then fts = {} ft[script] = fts end
+ for i=1,#languages do
+ fts[strip(lower(languages[i]))] = true
end
- glyphs[index] = g
end
end
- subfont.glyphs = nil
- end
- if trace_loading then
- logs.report("load otf","cid font remapped, %s unicode points, %s symbolic names, %s glyphs",nofunicodes, nofnames, nofunicodes+nofnames)
+ sequences[#sequences+1] = {
+ type = typ,
+ chain = chain,
+ flags = flags,
+ name = name,
+ subtables = subtables,
+ markclass = markclass,
+ features = f,
+ }
+ else
+ lookups[name] = {
+ type = typ,
+ chain = chain,
+ flags = flags,
+ subtables = subtables,
+ markclass = markclass,
+ }
end
- data.glyphs = glyphs
- data.map = data.map or { }
- data.map.map = uni_to_int
- data.map.backmap = int_to_uni
- elseif trace_loading then
- logs.report("load otf","unable to remap cid font, missing cid file for %s",filename)
end
- elseif trace_loading then
- logs.report("load otf","font %s has no glyphs",filename)
end
end
end
-otf.enhancers["prepare unicode"] = function(data,filename)
+actions["prepare unicodes"] = function(data,filename,raw)
local luatex = data.luatex
- if not luatex then luatex = { } data.luatex = luatex end
local indices, unicodes, multiples, internals = { }, { }, { }, { }
- local glyphs = data.glyphs
- local mapmap = data.map
+ local mapmap = data.map or raw.map
if not mapmap then
- logs.report("load otf","no map in %s",filename)
+ report_otf("no map in %s",filename)
mapmap = { }
data.map = { map = mapmap }
elseif not mapmap.map then
- logs.report("load otf","no unicode map in %s",filename)
+ report_otf("no unicode map in %s",filename)
mapmap = { }
data.map.map = mapmap
else
mapmap = mapmap.map
end
- local criterium = fonts.private
- local private = fonts.private
+ local criterium = fonts.privateoffset
+ local private = criterium
+ local glyphs = data.glyphs
for index, glyph in next, glyphs do
if index > 0 then
- local name = glyph.name
+ local name = glyph.name -- really needed ?
if name then
local unicode = glyph.unicode
- if unicode == -1 or unicode >= criterium then
+ if not unicode or unicode == -1 or unicode >= criterium then
glyph.unicode = private
indices[private] = index
unicodes[name] = private
internals[index] = true
if trace_private then
- logs.report("load otf","enhance: glyph %s at index U+%04X is moved to private unicode slot U+%04X",name,index,private)
+ report_otf("enhance: glyph %s at index U+%04X is moved to private unicode slot U+%04X",name,index,private)
end
private = private + 1
else
indices[unicode] = index
unicodes[name] = unicode
end
+ else
+ -- message that something is wrong
end
end
end
@@ -679,7 +1013,7 @@ otf.enhancers["prepare unicode"] = function(data,filename)
local un = unicodes[name]
if not un then
unicodes[name] = unicode -- or 0
- elseif type(un) == "number" then
+ elseif type(un) == "number" then -- tonumber(un)
if un ~= unicode then
multiples[#multiples+1] = name
unicodes[name] = { un, unicode }
@@ -704,9 +1038,9 @@ otf.enhancers["prepare unicode"] = function(data,filename)
end
if trace_loading then
if #multiples > 0 then
- logs.report("load otf","%s glyph are reused: %s",#multiples, concat(multiples," "))
+ report_otf("%s glyphs are reused: %s",#multiples, concat(multiples," "))
else
- logs.report("load otf","no glyph are reused")
+ report_otf("no glyphs are reused")
end
end
luatex.indices = indices
@@ -714,26 +1048,14 @@ otf.enhancers["prepare unicode"] = function(data,filename)
luatex.private = private
end
-otf.enhancers["cleanup ttf tables"] = function(data,filename)
- local ttf_tables = data.ttf_tables
- if ttf_tables then
- for k=1,#ttf_tables do
- if ttf_tables[k].data then ttf_tables[k].data = "deleted" end
- end
- end
- data.ttf_tab_saved = nil
-end
-
-otf.enhancers["compact glyphs"] = function(data,filename)
- table.compact(data.glyphs) -- needed?
- if data.subfonts then
- for _, subfont in next, data.subfonts do
- table.compact(subfont.glyphs) -- needed?
- end
+actions["prepare lookups"] = function(data,filename,raw)
+ local lookups = raw.lookups
+ if lookups then
+ data.lookups = lookups
end
end
-otf.enhancers["reverse coverage"] = function(data,filename)
+actions["reorganize lookups"] = function(data,filename,raw)
-- we prefer the before lookups in a normal order
if data.lookups then
for _, v in next, data.lookups do
@@ -741,7 +1063,7 @@ otf.enhancers["reverse coverage"] = function(data,filename)
for _, vv in next, v.rules do
local c = vv.coverage
if c and c.before then
- c.before = table.reverse(c.before)
+ c.before = reverse(c.before)
end
end
end
@@ -749,35 +1071,19 @@ otf.enhancers["reverse coverage"] = function(data,filename)
end
end
-otf.enhancers["check italic correction"] = function(data,filename)
- local glyphs = data.glyphs
- local ok = false
- for index, glyph in next, glyphs do
- local ic = glyph.italic_correction
- if ic then
- if ic ~= 0 then
- glyph.italic = ic
- end
- glyph.italic_correction = nil
- ok = true
- end
- end
- -- we can use this to avoid calculations
- otf.tables.valid_fields[#otf.tables.valid_fields+1] = "has_italic"
- data.has_italic = true
-end
-
-otf.enhancers["check math"] = function(data,filename)
- if data.math then
+actions["analyze math"] = function(data,filename,raw)
+ if raw.math then
+data.metadata.math = raw.math
-- we move the math stuff into a math subtable because we then can
-- test faster in the tfm copy
- local glyphs = data.glyphs
+ local glyphs, udglyphs = data.glyphs, data.udglyphs
local unicodes = data.luatex.unicodes
- for index, glyph in next, glyphs do
- local mk = glyph.mathkern
- local hv = glyph.horiz_variants
- local vv = glyph.vert_variants
+ for index, udglyph in next, udglyphs do
+ local mk = udglyph.mathkern
+ local hv = udglyph.horiz_variants
+ local vv = udglyph.vert_variants
if mk or hv or vv then
+ local glyph = glyphs[index]
local math = { }
glyph.math = math
if mk then
@@ -787,7 +1093,6 @@ otf.enhancers["check math"] = function(data,filename)
end
end
math.kerns = mk
- glyph.mathkern = nil
end
if hv then
math.horiz_variants = hv.variants
@@ -803,7 +1108,6 @@ otf.enhancers["check math"] = function(data,filename)
if ic and ic ~= 0 then
math.horiz_italic_correction = ic
end
- glyph.horiz_variants = nil
end
if vv then
local uc = unicodes[index]
@@ -820,227 +1124,54 @@ otf.enhancers["check math"] = function(data,filename)
if ic and ic ~= 0 then
math.vert_italic_correction = ic
end
- glyph.vert_variants = nil
end
local ic = glyph.italic_correction
if ic then
if ic ~= 0 then
math.italic_correction = ic
end
- glyph.italic_correction = nil
end
end
end
end
end
-otf.enhancers["share widths"] = function(data,filename)
- local glyphs = data.glyphs
- local widths = { }
- for index, glyph in next, glyphs do
- local width = glyph.width
- widths[width] = (widths[width] or 0) + 1
- end
- -- share width for cjk fonts
- local wd, most = 0, 1
- for k,v in next, widths do
- if v > most then
- wd, most = k, v
- end
- end
- if most > 1000 then
- if trace_loading then
- logs.report("load otf", "most common width: %s (%s times), sharing (cjk font)",wd,most)
- end
- for k, v in next, glyphs do
- if v.width == wd then
- v.width = nil
- end
- end
- data.luatex.defaultwidth = wd
- end
-end
-
--- kern: ttf has a table with kerns
-
--- Weird, as maxfirst and maxseconds can have holes, first seems to be indexed, but
--- seconds can start at 2 .. this need to be fixed as getn as well as # are sort of
--- unpredictable alternatively we could force an [1] if not set (maybe I will do that
--- anyway).
-
---~ otf.enhancers["reorganize kerns"] = function(data,filename)
---~ local glyphs, mapmap, unicodes = data.glyphs, data.luatex.indices, data.luatex.unicodes
---~ local mkdone = false
---~ for index, glyph in next, glyphs do
---~ if glyph.kerns then
---~ local mykerns = { }
---~ for k,v in next, glyph.kerns do
---~ local vc, vo, vl = v.char, v.off, v.lookup
---~ if vc and vo and vl then -- brrr, wrong! we miss the non unicode ones
---~ local uvc = unicodes[vc]
---~ if not uvc then
---~ if trace_loading then
---~ logs.report("load otf","problems with unicode %s of kern %s at glyph %s",vc,k,index)
---~ end
---~ else
---~ if type(vl) ~= "table" then
---~ vl = { vl }
---~ end
---~ for l=1,#vl do
---~ local vll = vl[l]
---~ local mkl = mykerns[vll]
---~ if not mkl then
---~ mkl = { }
---~ mykerns[vll] = mkl
---~ end
---~ if type(uvc) == "table" then
---~ for u=1,#uvc do
---~ mkl[uvc[u]] = vo
---~ end
---~ else
---~ mkl[uvc] = vo
---~ end
---~ end
---~ end
---~ end
---~ end
---~ glyph.mykerns = mykerns
---~ glyph.kerns = nil -- saves space and time
---~ mkdone = true
---~ end
---~ end
---~ if trace_loading and mkdone then
---~ logs.report("load otf", "replacing 'kerns' tables by 'mykerns' tables")
---~ end
---~ if data.kerns then
---~ if trace_loading then
---~ logs.report("load otf", "removing global 'kern' table")
---~ end
---~ data.kerns = nil
---~ end
---~ local dgpos = data.gpos
---~ if dgpos then
---~ local separator = lpeg.P(" ")
---~ local other = ((1 - separator)^0) / unicodes
---~ local splitter = lpeg.Ct(other * (separator * other)^0)
---~ for gp=1,#dgpos do
---~ local gpos = dgpos[gp]
---~ local subtables = gpos.subtables
---~ if subtables then
---~ for s=1,#subtables do
---~ local subtable = subtables[s]
---~ local kernclass = subtable.kernclass -- name is inconsistent with anchor_classes
---~ if kernclass then -- the next one is quite slow
---~ local split = { } -- saves time
---~ for k=1,#kernclass do
---~ local kcl = kernclass[k]
---~ local firsts, seconds, offsets, lookups = kcl.firsts, kcl.seconds, kcl.offsets, kcl.lookup -- singular
---~ if type(lookups) ~= "table" then
---~ lookups = { lookups }
---~ end
---~ local maxfirsts, maxseconds = getn(firsts), getn(seconds)
---~ for _, s in next, firsts do
---~ split[s] = split[s] or lpegmatch(splitter,s)
---~ end
---~ for _, s in next, seconds do
---~ split[s] = split[s] or lpegmatch(splitter,s)
---~ end
---~ for l=1,#lookups do
---~ local lookup = lookups[l]
---~ local function do_it(fk,first_unicode)
---~ local glyph = glyphs[mapmap[first_unicode]]
---~ if glyph then
---~ local mykerns = glyph.mykerns
---~ if not mykerns then
---~ mykerns = { } -- unicode indexed !
---~ glyph.mykerns = mykerns
---~ end
---~ local lookupkerns = mykerns[lookup]
---~ if not lookupkerns then
---~ lookupkerns = { }
---~ mykerns[lookup] = lookupkerns
---~ end
---~ local baseoffset = (fk-1) * maxseconds
---~ for sk=2,maxseconds do -- we can avoid this loop with a table
---~ local sv = seconds[sk]
---~ local splt = split[sv]
---~ if splt then
---~ local offset = offsets[baseoffset + sk]
---~ --~ local offset = offsets[sk] -- (fk-1) * maxseconds + sk]
---~ if offset then
---~ for i=1,#splt do
---~ local second_unicode = splt[i]
---~ if tonumber(second_unicode) then
---~ lookupkerns[second_unicode] = offset
---~ else for s=1,#second_unicode do
---~ lookupkerns[second_unicode[s]] = offset
---~ end end
---~ end
---~ end
---~ end
---~ end
---~ elseif trace_loading then
---~ logs.report("load otf", "no glyph data for U+%04X", first_unicode)
---~ end
---~ end
---~ for fk=1,#firsts do
---~ local fv = firsts[fk]
---~ local splt = split[fv]
---~ if splt then
---~ for i=1,#splt do
---~ local first_unicode = splt[i]
---~ if tonumber(first_unicode) then
---~ do_it(fk,first_unicode)
---~ else for f=1,#first_unicode do
---~ do_it(fk,first_unicode[f])
---~ end end
---~ end
---~ end
---~ end
---~ end
---~ end
---~ subtable.comment = "The kernclass table is merged into mykerns in the indexed glyph tables."
---~ subtable.kernclass = { }
---~ end
---~ end
---~ end
---~ end
---~ end
---~ end
-
-otf.enhancers["reorganize kerns"] = function(data,filename)
- local glyphs, mapmap, unicodes = data.glyphs, data.luatex.indices, data.luatex.unicodes
+actions["reorganize glyph kerns"] = function(data,filename,raw)
+ local luatex = data.luatex
+ local udglyphs, glyphs, mapmap, unicodes = data.udglyphs, data.glyphs, luatex.indices, luatex.unicodes
local mkdone = false
- local function do_it(lookup,first_unicode,kerns)
+ local function do_it(lookup,first_unicode,extrakerns) -- can be moved inline but seldom used
local glyph = glyphs[mapmap[first_unicode]]
if glyph then
- local mykerns = glyph.mykerns
- if not mykerns then
- mykerns = { } -- unicode indexed !
- glyph.mykerns = mykerns
+ local kerns = glyph.kerns
+ if not kerns then
+ kerns = { } -- unicode indexed !
+ glyph.kerns = kerns
end
- local lookupkerns = mykerns[lookup]
+ local lookupkerns = kerns[lookup]
if not lookupkerns then
lookupkerns = { }
- mykerns[lookup] = lookupkerns
+ kerns[lookup] = lookupkerns
end
- for second_unicode, kern in next, kerns do
+ for second_unicode, kern in next, extrakerns do
lookupkerns[second_unicode] = kern
end
elseif trace_loading then
- logs.report("load otf", "no glyph data for U+%04X", first_unicode)
+ report_otf("no glyph data for U+%04X", first_unicode)
end
end
- for index, glyph in next, glyphs do
- if glyph.kerns then
- local mykerns = { }
- for k,v in next, glyph.kerns do
+ for index, udglyph in next, data.udglyphs do
+ local kerns = udglyph.kerns
+ if kerns then
+ local glyph = glyphs[index]
+ local newkerns = { }
+ for k,v in next, kerns do
local vc, vo, vl = v.char, v.off, v.lookup
if vc and vo and vl then -- brrr, wrong! we miss the non unicode ones
local uvc = unicodes[vc]
if not uvc then
if trace_loading then
- logs.report("load otf","problems with unicode %s of kern %s at glyph %s",vc,k,index)
+ report_otf("problems with unicode %s of kern %s at glyph %s",vc,k,index)
end
else
if type(vl) ~= "table" then
@@ -1048,10 +1179,10 @@ otf.enhancers["reorganize kerns"] = function(data,filename)
end
for l=1,#vl do
local vll = vl[l]
- local mkl = mykerns[vll]
+ local mkl = newkerns[vll]
if not mkl then
mkl = { }
- mykerns[vll] = mkl
+ newkerns[vll] = mkl
end
if type(uvc) == "table" then
for u=1,#uvc do
@@ -1064,21 +1195,14 @@ otf.enhancers["reorganize kerns"] = function(data,filename)
end
end
end
- glyph.mykerns = mykerns
- glyph.kerns = nil -- saves space and time
+ glyph.kerns = newkerns -- udglyph.kerns = nil when in mixed mode
mkdone = true
end
end
if trace_loading and mkdone then
- logs.report("load otf", "replacing 'kerns' tables by 'mykerns' tables")
+ report_otf("replacing 'kerns' tables by a new 'kerns' tables")
end
- if data.kerns then
- if trace_loading then
- logs.report("load otf", "removing global 'kern' table")
- end
- data.kerns = nil
- end
- local dgpos = data.gpos
+ local dgpos = raw.gpos
if dgpos then
local separator = lpeg.P(" ")
local other = ((1 - separator)^0) / unicodes
@@ -1143,7 +1267,7 @@ otf.enhancers["reorganize kerns"] = function(data,filename)
end
end
end
- subtable.comment = "The kernclass table is merged into mykerns in the indexed glyph tables."
+ subtable.comment = "The kernclass table is merged into kerns in the indexed glyph tables."
subtable.kernclass = { }
end
end
@@ -1152,22 +1276,10 @@ otf.enhancers["reorganize kerns"] = function(data,filename)
end
end
-
-
-
-
-
-
-
-
-otf.enhancers["strip not needed data"] = function(data,filename)
+actions["check glyphs"] = function(data,filename,raw)
local verbose = fonts.verbose
local int_to_uni = data.luatex.unicodes
for k, v in next, data.glyphs do
- local d = v.dependents
- if d then v.dependents = nil end
- local a = v.altuni
- if a then v.altuni = nil end
if verbose then
local code = int_to_uni[k]
-- looks like this is done twice ... bug?
@@ -1189,33 +1301,65 @@ otf.enhancers["strip not needed data"] = function(data,filename)
v.unicode = nil
v.index = nil
end
+ -- only needed on non sparse/mixed mode
+ if v.math then
+ if v.mathkern then v.mathkern = nil end
+ if v.horiz_variant then v.horiz_variant = nil end
+ if v.vert_variants then v.vert_variants = nil end
+ end
+ --
end
- data.luatex.comment = "Glyph tables have their original index. When present, mykern tables are indexed by unicode."
- data.map = nil
- data.names = nil -- funny names for editors
- data.glyphcnt = nil
- data.glyphmax = nil
- if true then
- data.gpos = nil
- data.gsub = nil
- data.anchor_classes = nil
- end
+ data.luatex.comment = "Glyph tables have their original index. When present, kern tables are indexed by unicode."
end
-otf.enhancers["migrate metadata"] = function(data,filename)
- local global_fields = otf.tables.global_fields
- local metadata = { }
- for k,v in next, data do
- if not global_fields[k] then
- metadata[k] = v
- data[k] = nil
+actions["check metadata"] = function(data,filename,raw)
+ local metadata = data.metadata
+ metadata.method = loadmethod
+ if loadmethod == "sparse" then
+ for _, k in next, mainfields do
+ if valid_fields[k] then
+ local v = raw[k]
+ if global_fields[k] then
+ if not data[k] then
+ data[k] = v
+ end
+ else
+ if not metadata[k] then
+ metadata[k] = v
+ end
+ end
+ end
+ end
+ else
+ for k, v in next, raw do
+ if valid_fields[k] then
+ if global_fields[k] then
+ if not data[k] then
+ data[v] = v
+ end
+ else
+ if not metadata[k] then
+ metadata[k] = v
+ end
+ end
+ end
+ end
+ end
+ local pfminfo = raw.pfminfo
+ if pfminfo then
+ data.pfminfo = pfminfo
+ metadata.isfixedpitch = metadata.isfixedpitch or (pfminfo.panose and pfminfo.panose.proportion == "Monospaced")
+ metadata.charwidth = pfminfo and pfminfo.avgwidth
+ end
+ local ttftables = metadata.ttf_tables
+ if ttftables then
+ for i=1,#ttftables do
+ ttftables[i].data = "deleted"
end
end
- data.metadata = metadata
- -- goodies
- local pfminfo = data.pfminfo
- metadata.isfixedpitch = metadata.isfixedpitch or (pfminfo.panose and pfminfo.panose["proportion"] == "Monospaced")
- metadata.charwidth = pfminfo and pfminfo.avgwidth
+ metadata.xuid = nil
+ data.udglyphs = nil
+ data.map = nil
end
local private_math_parameters = {
@@ -1223,14 +1367,14 @@ local private_math_parameters = {
"FractionDelimiterDisplayStyleSize",
}
-otf.enhancers["check math parameters"] = function(data,filename)
+actions["check math parameters"] = function(data,filename,raw)
local mathdata = data.metadata.math
if mathdata then
for m=1,#private_math_parameters do
local pmp = private_math_parameters[m]
if not mathdata[pmp] then
if trace_loading then
- logs.report("load otf", "setting math parameter '%s' to 0", pmp)
+ report_otf("setting math parameter '%s' to 0", pmp)
end
mathdata[pmp] = 0
end
@@ -1238,123 +1382,101 @@ otf.enhancers["check math parameters"] = function(data,filename)
end
end
-otf.enhancers["flatten glyph lookups"] = function(data,filename)
- for k, v in next, data.glyphs do
- local lookups = v.lookups
+
+-- kern: ttf has a table with kerns
+--
+-- Weird, as maxfirst and maxseconds can have holes, first seems to be indexed, but
+-- seconds can start at 2 .. this need to be fixed as getn as well as # are sort of
+-- unpredictable alternatively we could force an [1] if not set (maybe I will do that
+-- anyway).
+
+actions["reorganize glyph lookups"] = function(data,filename,raw)
+ local glyphs = data.glyphs
+ for index, udglyph in next, data.udglyphs do
+ local lookups = udglyph.lookups
if lookups then
+ local glyph = glyphs[index]
+ local l = { }
for kk, vv in next, lookups do
+ local aa = { }
+ l[kk] = aa
for kkk=1,#vv do
local vvv = vv[kkk]
local s = vvv.specification
- if s then
- local t = vvv.type
- if t == "ligature" then
- vv[kkk] = { "ligature", s.components, s.char }
- elseif t == "alternate" then
- vv[kkk] = { "alternate", s.components }
- elseif t == "substitution" then
- vv[kkk] = { "substitution", s.variant }
- elseif t == "multiple" then
- vv[kkk] = { "multiple", s.components }
- elseif t == "position" then
- vv[kkk] = { "position", { s.x or 0, s.y or 0, s.h or 0, s.v or 0 } }
- elseif t == "pair" then
- local one, two, paired = s.offsets[1], s.offsets[2], s.paired or ""
- if one then
- if two then
- vv[kkk] = { "pair", paired, { one.x or 0, one.y or 0, one.h or 0, one.v or 0 }, { two.x or 0, two.y or 0, two.h or 0, two.v or 0 } }
- else
- vv[kkk] = { "pair", paired, { one.x or 0, one.y or 0, one.h or 0, one.v or 0 } }
- end
+ local t = vvv.type
+ -- #aa+1
+ if t == "ligature" then
+ aa[kkk] = { "ligature", s.components, s.char }
+ elseif t == "alternate" then
+ aa[kkk] = { "alternate", s.components }
+ elseif t == "substitution" then
+ aa[kkk] = { "substitution", s.variant }
+ elseif t == "multiple" then
+ aa[kkk] = { "multiple", s.components }
+ elseif t == "position" then
+ aa[kkk] = { "position", { s.x or 0, s.y or 0, s.h or 0, s.v or 0 } }
+ elseif t == "pair" then
+ -- maybe flatten this one
+ local one, two, paired = s.offsets[1], s.offsets[2], s.paired or ""
+ if one then
+ if two then
+ aa[kkk] = { "pair", paired, { one.x or 0, one.y or 0, one.h or 0, one.v or 0 }, { two.x or 0, two.y or 0, two.h or 0, two.v or 0 } }
else
- if two then
- vv[kkk] = { "pair", paired, { }, { two.x or 0, two.y or 0, two.h or 0, two.v or 0} } -- maybe nil instead of { }
- else
- vv[kkk] = { "pair", paired }
- end
+ aa[kkk] = { "pair", paired, { one.x or 0, one.y or 0, one.h or 0, one.v or 0 } }
end
else
- if trace_loading then
- logs.report("load otf", "flattening needed, report to context list")
- end
- for a, b in next, s do
- if trace_loading and vvv[a] then
- logs.report("load otf", "flattening conflict, report to context list")
- end
- vvv[a] = b
+ if two then
+ aa[kkk] = { "pair", paired, { }, { two.x or 0, two.y or 0, two.h or 0, two.v or 0} } -- maybe nil instead of { }
+ else
+ aa[kkk] = { "pair", paired }
end
- vvv.specification = nil
end
end
end
end
- end
- end
-end
-
-otf.enhancers["simplify glyph lookups"] = function(data,filename)
- for k, v in next, data.glyphs do
- local lookups = v.lookups
- if lookups then
+ -- we could combine this
local slookups, mlookups
- for kk, vv in next, lookups do
+ for kk, vv in next, l do
if #vv == 1 then
if not slookups then
slookups = { }
- v.slookups = slookups
+ glyph.slookups = slookups
end
slookups[kk] = vv[1]
else
if not mlookups then
mlookups = { }
- v.mlookups = mlookups
+ glyph.mlookups = mlookups
end
mlookups[kk] = vv
end
end
- v.lookups = nil
+ glyph.lookups = nil -- when using table
end
end
end
-otf.enhancers["flatten anchor tables"] = function(data,filename)
- for k, v in next, data.glyphs do
- if v.anchors then
- for kk, vv in next, v.anchors do
+actions["reorganize glyph anchors"] = function(data,filename,raw)
+ local glyphs = data.glyphs
+ for index, udglyph in next, data.udglyphs do
+ local anchors = udglyph.anchors
+ if anchors then
+ local glyph = glyphs[index]
+ local a = { }
+ glyph.anchors = a
+ for kk, vv in next, anchors do
+ local aa = { }
+ a[kk] = aa
for kkk, vvv in next, vv do
if vvv.x or vvv.y then
- vv[kkk] = { vvv.x or 0, vvv.y or 0 }
+ aa[kkk] = { vvv.x , vvv.y }
else
+ local aaa = { }
+ aa[kkk] = aaa
for kkkk=1,#vvv do
local vvvv = vvv[kkkk]
- vvv[kkkk] = { vvvv.x or 0, vvvv.y or 0 }
- end
- end
- end
- end
- end
- end
-end
-
-otf.enhancers["flatten feature tables"] = function(data,filename)
- -- is this needed? do we still use them at all?
- for _, tag in next, otf.glists do
- if data[tag] then
- if trace_loading then
- logs.report("load otf", "flattening %s table", tag)
- end
- for k, v in next, data[tag] do
- local features = v.features
- if features then
- for kk=1,#features do
- local vv = features[kk]
- local t = { }
- local scripts = vv.scripts
- for kkk=1,#scripts do
- local vvv = scripts[kkk]
- t[vvv.script] = vvv.langs
+ aaa[kkkk] = { vvvv.x, vvvv.y }
end
- vv.scripts = t
end
end
end
@@ -1362,22 +1484,12 @@ otf.enhancers["flatten feature tables"] = function(data,filename)
end
end
-otf.enhancers.patches = otf.enhancers.patches or { }
-
-otf.enhancers["patch bugs"] = function(data,filename)
- local basename = file.basename(lower(filename))
- for pattern, action in next, otf.enhancers.patches do
- if find(basename,pattern) then
- action(data,filename)
- end
- end
-end
-
--- tex features
+--~ actions["check extra features"] = function(data,filename,raw)
+--~ -- later, ctx only
+--~ end
-fonts.otf.enhancers["enrich with features"] = function(data,filename)
- -- later, ctx only
-end
+-- -- -- -- -- --
+-- -- -- -- -- --
function otf.features.register(name,default)
otf.features.list[#otf.features.list+1] = name
@@ -1386,22 +1498,23 @@ end
-- for context this will become a task handler
-function otf.set_features(tfmdata,features)
+local lists = { -- why local
+ fonts.triggers,
+ fonts.processors,
+ fonts.manipulators,
+}
+
+function otf.setfeatures(tfmdata,features)
local processes = { }
if features and next(features) then
- local lists = { -- why local
- fonts.triggers,
- fonts.processors,
- fonts.manipulators,
- }
- local mode = tfmdata.mode or fonts.mode -- or features.mode
+ local mode = tfmdata.mode or features.mode or "base"
local initializers = fonts.initializers
local fi = initializers[mode]
if fi then
local fiotf = fi.otf
if fiotf then
local done = { }
- for l=1,4 do
+ for l=1,#lists do
local list = lists[l]
if list then
for i=1,#list do
@@ -1410,10 +1523,10 @@ function otf.set_features(tfmdata,features)
if value and fiotf[f] then -- brr
if not done[f] then -- so, we can move some to triggers
if trace_features then
- 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')
+ report_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 !
+ mode = tfmdata.mode or features.mode or "base"
local im = initializers[mode]
if im then
fiotf = initializers[mode].otf
@@ -1426,18 +1539,19 @@ function otf.set_features(tfmdata,features)
end
end
end
+tfmdata.mode = mode
local fm = fonts.methods[mode] -- todo: zonder node/mode otf/...
if fm then
local fmotf = fm.otf
if fmotf then
- for l=1,4 do
+ for l=1,#lists do
local list = lists[l]
if list then
for i=1,#list do
local f = list[i]
if fmotf[f] then -- brr
if trace_features then
- logs.report("define otf","installing feature handler %s for mode %s for font %s",f,mode or 'unknown', tfmdata.fullname or 'unknown')
+ report_otf("installing feature handler %s for mode %s for font %s",f,mode or 'unknown', tfmdata.fullname or 'unknown')
end
processes[#processes+1] = fmotf[f]
end
@@ -1452,71 +1566,6 @@ function otf.set_features(tfmdata,features)
return processes, features
end
-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(tfm.cache,cache_id)
---~ print(cache_id)
- if not tfmdata then
- local otfdata = otf.load(filename,format,sub,features and features.featurefile)
- if otfdata and next(otfdata) then
- otfdata.shared = otfdata.shared or {
- featuredata = { },
- anchorhash = { },
- initialized = false,
- }
- tfmdata = otf.copy_to_tfm(otfdata,cache_id)
- if tfmdata and next(tfmdata) then
- tfmdata.unique = tfmdata.unique or { }
- tfmdata.shared = tfmdata.shared or { } -- combine
- local shared = tfmdata.shared
- shared.otfdata = otfdata
- shared.features = features -- default
- shared.dynamics = { }
- shared.processes = { }
- shared.set_dynamics = otf.set_dynamics -- fast access and makes other modules independent
- -- this will be done later anyway, but it's convenient to have
- -- them already for fast access
- tfmdata.luatex = otfdata.luatex
- tfmdata.indices = otfdata.luatex.indices
- tfmdata.unicodes = otfdata.luatex.unicodes
- tfmdata.marks = otfdata.luatex.marks
- tfmdata.originals = otfdata.luatex.originals
- tfmdata.changed = { }
- tfmdata.has_italic = otfdata.metadata.has_italic
- if not tfmdata.language then tfmdata.language = 'dflt' end
- if not tfmdata.script then tfmdata.script = 'dflt' end
- shared.processes, shared.features = otf.set_features(tfmdata,fonts.define.check(features,otf.features.default))
- end
- end
- containers.write(tfm.cache,cache_id,tfmdata)
- end
- return tfmdata
-end
-
---~ {
---~ ['boundingbox']={ 95, -458, 733, 1449 },
---~ ['class']="base",
---~ ['name']="braceleft",
---~ ['unicode']=123,
---~ ['vert_variants']={
---~ ['italic_correction']=0,
---~ ['parts']={
---~ { ['component']="uni23A9", ['endConnectorLength']=1000, ['fullAdvance']=2546, ['is_extender']=0, ['startConnectorLength']=0, }, -- bot
---~ { ['component']="uni23AA", ['endConnectorLength']=2500, ['fullAdvance']=2501, ['is_extender']=1, ['startConnectorLength']=2500, }, -- rep
---~ { ['component']="uni23A8", ['endConnectorLength']=1000, ['fullAdvance']=4688, ['is_extender']=0, ['startConnectorLength']=1000, }, -- mid
---~ { ['component']="uni23AA", ['endConnectorLength']=2500, ['fullAdvance']=2501, ['is_extender']=1, ['startConnectorLength']=2500, }, -- rep
---~ { ['component']="uni23A7", ['endConnectorLength']=0, ['fullAdvance']=2546, ['is_extender']=0, ['startConnectorLength']=1000, }, -- top
---~ },
---~ ['variants']="braceleft braceleft.vsize1 braceleft.vsize2 braceleft.vsize3 braceleft.vsize4 braceleft.vsize5 braceleft.vsize6 braceleft.vsize7",
---~ },
---~ ['width']=793,
---~ },
-
-- the first version made a top/mid/not extensible table, now we just pass on the variants data
-- and deal with it in the tfm scaler (there is no longer an extensible table anyway)
@@ -1528,12 +1577,13 @@ fonts.formats.ttc = "truetype"
fonts.formats.ttf = "truetype"
fonts.formats.otf = "opentype"
-function otf.copy_to_tfm(data,cache_id) -- we can save a copy when we reorder the tma to unicode (nasty due to one->many)
+local function copytotfm(data,cache_id) -- we can save a copy when we reorder the tma to unicode (nasty due to one->many)
if data then
local glyphs, pfminfo, metadata = data.glyphs or { }, data.pfminfo or { }, data.metadata or { }
local luatex = data.luatex
local unicodes = luatex.unicodes -- names to unicodes
- local indices = luatex.indices
+ local indices = luatex.indices local mode = data.mode or "base"
+
local characters, parameters, math_parameters, descriptions = { }, { }, { }, { }
local designsize = metadata.designsize or metadata.design_size or 100
if designsize == 0 then
@@ -1620,10 +1670,10 @@ function otf.copy_to_tfm(data,cache_id) -- we can save a copy when we reorder th
end
spaceunits = tonumber(spaceunits) or tfm.units/2 -- 500 -- brrr
-- we need a runtime lookup because of running from cdrom or zip, brrr (shouldn't we use the basename then?)
- local filename = fonts.tfm.checked_filename(luatex)
+ local filename = fonts.tfm.checkedfilename(luatex)
local fontname = metadata.fontname
local fullname = metadata.fullname or fontname
- local cidinfo = data.cidinfo
+ local cidinfo = data.cidinfo -- or { }
local units = metadata.units_per_em or 1000
--
cidinfo.registry = cidinfo and cidinfo.registry or "" -- weird here, fix upstream
@@ -1644,7 +1694,7 @@ function otf.copy_to_tfm(data,cache_id) -- we can save a copy when we reorder th
if metadata.isfixedpitch then
parameters.space_stretch = 0
parameters.space_shrink = 0
- elseif otf.syncspace then --
+ elseif syncspace then --
parameters.space_stretch = spaceunits/2
parameters.space_shrink = spaceunits/3
end
@@ -1675,6 +1725,7 @@ function otf.copy_to_tfm(data,cache_id) -- we can save a copy when we reorder th
designsize = (designsize/10)*65536,
spacer = "500 units",
encodingbytes = 2,
+ mode = mode,
filename = filename,
fontname = fontname,
fullname = fullname,
@@ -1693,10 +1744,56 @@ function otf.copy_to_tfm(data,cache_id) -- we can save a copy when we reorder th
end
end
+local function otftotfm(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(tfm.cache,cache_id)
+--~ print(cache_id)
+ if not tfmdata then
+ local otfdata = otf.load(filename,format,sub,features and features.featurefile)
+ if otfdata and next(otfdata) then
+ otfdata.shared = otfdata.shared or {
+ featuredata = { },
+ anchorhash = { },
+ initialized = false,
+ }
+ tfmdata = copytotfm(otfdata,cache_id)
+ if tfmdata and next(tfmdata) then
+ tfmdata.unique = tfmdata.unique or { }
+ tfmdata.shared = tfmdata.shared or { } -- combine
+ local shared = tfmdata.shared
+ shared.otfdata = otfdata
+ shared.features = features -- default
+ shared.dynamics = { }
+ shared.processes = { }
+ shared.setdynamics = otf.setdynamics -- fast access and makes other modules independent
+ -- this will be done later anyway, but it's convenient to have
+ -- them already for fast access
+ tfmdata.luatex = otfdata.luatex
+ tfmdata.indices = otfdata.luatex.indices
+ tfmdata.unicodes = otfdata.luatex.unicodes
+ tfmdata.marks = otfdata.luatex.marks
+ tfmdata.originals = otfdata.luatex.originals
+ tfmdata.changed = { }
+ tfmdata.has_italic = otfdata.metadata.has_italic
+ if not tfmdata.language then tfmdata.language = 'dflt' end
+ if not tfmdata.script then tfmdata.script = 'dflt' end
+ shared.processes, shared.features = otf.setfeatures(tfmdata,definers.check(features,otf.features.default))
+ end
+ end
+ containers.write(tfm.cache,cache_id,tfmdata)
+ end
+ return tfmdata
+end
+
otf.features.register('mathsize')
-function tfm.read_from_open_type(specification)
- local tfmtable = otf.otf_to_tfm(specification)
+function tfm.read_from_otf(specification) -- wrong namespace
+ local tfmtable = otftotfm(specification)
if tfmtable then
local otfdata = tfmtable.shared.otfdata
tfmtable.name = specification.name
@@ -1715,7 +1812,7 @@ function tfm.read_from_open_type(specification)
if p then
local ps = p * specification.textsize / 100
if trace_math then
- logs.report("define font","asked script size: %s, used: %s (%2.2f %%)",s,ps,(ps/s)*100)
+ report_otf("asked script size: %s, used: %s (%2.2f %%)",s,ps,(ps/s)*100)
end
s = ps
end
@@ -1724,7 +1821,7 @@ function tfm.read_from_open_type(specification)
if p then
local ps = p * specification.textsize / 100
if trace_math then
- logs.report("define font","asked scriptscript size: %s, used: %s (%2.2f %%)",s,ps,(ps/s)*100)
+ report_otf("asked scriptscript size: %s, used: %s (%2.2f %%)",s,ps,(ps/s)*100)
end
s = ps
end
@@ -1733,13 +1830,13 @@ function tfm.read_from_open_type(specification)
end
end
tfmtable = tfm.scale(tfmtable,s,specification.relativeid)
- if tfm.fontname_mode == "specification" then
+ if tfm.fontnamemode == "specification" then
-- not to be used in context !
local specname = specification.specification
if specname then
tfmtable.name = specname
if trace_defining then
- logs.report("define font","overloaded fontname: '%s'",specname)
+ report_otf("overloaded fontname: '%s'",specname)
end
end
end
@@ -1751,7 +1848,7 @@ end
-- helpers
-function otf.collect_lookups(otfdata,kind,script,language)
+function otf.collectlookups(otfdata,kind,script,language)
-- maybe store this in the font
local sequences = otfdata.luatex.sequences
if sequences then
diff --git a/otfl-font-oti.lua b/otfl-font-oti.lua
index 4cb2706..e531ba8 100644
--- a/otfl-font-oti.lua
+++ b/otfl-font-oti.lua
@@ -6,19 +6,17 @@ if not modules then modules = { } end modules ['font-oti'] = {
license = "see context related readme files"
}
--- i need to check features=yes|no also in relation to hashing
-
local lower = string.lower
-local otf = fonts.otf
+local fonts = fonts
-otf.default_language = 'latn'
-otf.default_script = 'dflt'
+local otf = fonts.otf
+local initializers = fonts.initializers
-local languages = otf.tables.languages
-local scripts = otf.tables.scripts
+local languages = otf.tables.languages
+local scripts = otf.tables.scripts
-function otf.features.language(tfmdata,value)
+local function set_language(tfmdata,value)
if value then
value = lower(value)
if languages[value] then
@@ -27,7 +25,7 @@ function otf.features.language(tfmdata,value)
end
end
-function otf.features.script(tfmdata,value)
+local function set_script(tfmdata,value)
if value then
value = lower(value)
if scripts[value] then
@@ -36,21 +34,24 @@ function otf.features.script(tfmdata,value)
end
end
-function otf.features.mode(tfmdata,value)
+local function set_mode(tfmdata,value)
if value then
tfmdata.mode = lower(value)
end
end
-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
+local base_initializers = initializers.base.otf
+local node_initializers = initializers.node.otf
+
+base_initializers.language = set_language
+base_initializers.script = set_script
+base_initializers.mode = set_mode
+base_initializers.method = set_mode
-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
+node_initializers.language = set_language
+node_initializers.script = set_script
+node_initializers.mode = set_mode
+node_initializers.method = set_mode
otf.features.register("features",true) -- we always do features
table.insert(fonts.processors,"features") -- we need a proper function for doing this
diff --git a/otfl-font-otn.lua b/otfl-font-otn.lua
index 6a6a046..2bccc3c 100644
--- a/otfl-font-otn.lua
+++ b/otfl-font-otn.lua
@@ -124,6 +124,9 @@ local concat, insert, remove = table.concat, table.insert, table.remove
local format, gmatch, gsub, find, match, lower, strip = string.format, string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip
local type, next, tonumber, tostring = type, next, tonumber, tostring
local lpegmatch = lpeg.match
+local random = math.random
+
+local logs, trackers, fonts, nodes, attributes = logs, trackers, fonts, nodes, attributes
local otf = fonts.otf
local tfm = fonts.tfm
@@ -145,6 +148,12 @@ local trace_steps = false trackers.register("otf.steps", function
local trace_skips = false trackers.register("otf.skips", function(v) trace_skips = v end)
local trace_directions = false trackers.register("otf.directions", function(v) trace_directions = v end)
+local report_direct = logs.new("otf direct")
+local report_subchain = logs.new("otf subchain")
+local report_chain = logs.new("otf chain")
+local report_process = logs.new("otf process")
+local report_prepare = logs.new("otf prepare")
+
trackers.register("otf.verbose_chain", function(v) otf.setcontextchain(v and "verbose") end)
trackers.register("otf.normal_chain", function(v) otf.setcontextchain(v and "normal") end)
@@ -169,11 +178,19 @@ local default = "dflt"
local split_at_space = lpeg.splitters[" "] or lpeg.Ct(lpeg.splitat(" ")) -- no trailing or multiple spaces anyway
-local glyph = node.id('glyph')
-local glue = node.id('glue')
-local kern = node.id('kern')
-local disc = node.id('disc')
-local whatsit = node.id('whatsit')
+local nodecodes = nodes.nodecodes
+local whatcodes = nodes.whatcodes
+local glyphcodes = nodes.glyphcodes
+
+local glyph_code = nodecodes.glyph
+local glue_code = nodecodes.glue
+local disc_code = nodecodes.disc
+local whatsit_code = nodecodes.whatsit
+
+local dir_code = whatcodes.dir
+local localpar_code = whatcodes.localpar
+
+local ligature_code = glyphcodes.ligature
local state = attributes.private('state')
local markbase = attributes.private('markbase')
@@ -184,10 +201,11 @@ local curscurs = attributes.private('curscurs')
local cursdone = attributes.private('cursdone')
local kernpair = attributes.private('kernpair')
-local set_mark = nodes.set_mark
-local set_cursive = nodes.set_cursive
-local set_kern = nodes.set_kern
-local set_pair = nodes.set_pair
+local injections = nodes.injections
+local setmark = injections.setmark
+local setcursive = injections.setcursive
+local setkern = injections.setkern
+local setpair = injections.setpair
local markonce = true
local cursonce = true
@@ -216,9 +234,10 @@ local featurevalue = false
-- we cheat a bit and assume that a font,attr combination are kind of ranged
-local context_setups = fonts.define.specify.context_setups
-local context_numbers = fonts.define.specify.context_numbers
-local context_merged = fonts.define.specify.context_merged
+local specifiers = fonts.definers.specifiers
+local contextsetups = specifiers.contextsetups
+local contextnumbers = specifiers.contextnumbers
+local contextmerged = specifiers.contextmerged
-- we cannot optimize with "start = first_character(head)" because then we don't
-- know which rlmode we're in which messes up cursive handling later on
@@ -242,10 +261,10 @@ local function logprocess(...)
if trace_steps then
registermessage(...)
end
- logs.report("otf direct",...)
+ report_direct(...)
end
local function logwarning(...)
- logs.report("otf direct",...)
+ report_direct(...)
end
local function gref(n)
@@ -303,7 +322,7 @@ local function markstoligature(kind,lookupname,start,stop,char)
snext.prev = current
end
start.prev, stop.next = nil, nil
- current.char, current.subtype, current.components = char, 2, start
+ current.char, current.subtype, current.components = char, ligature_code, start
return keep
end
@@ -313,16 +332,16 @@ local function toligature(kind,lookupname,start,stop,char,markflag,discfound) --
--~ local lignode = copy_node(start)
--~ lignode.font = start.font
--~ lignode.char = char
---~ lignode.subtype = 2
+--~ lignode.subtype = ligature_code
--~ start = node.do_ligature_n(start, stop, lignode)
---~ if start.id == disc then
+--~ if start.id == disc_code then
--~ local prev = start.prev
--~ start = start.next
--~ end
if discfound then
-- print("start->stop",nodes.tosequence(start,stop))
local lignode = copy_node(start)
- lignode.font, lignode.char, lignode.subtype = start.font, char, 2
+ lignode.font, lignode.char, lignode.subtype = start.font, char, ligature_code
local next, prev = stop.next, start.prev
stop.next = nil
lignode = node.do_ligature_n(start, stop, lignode)
@@ -344,7 +363,7 @@ local function toligature(kind,lookupname,start,stop,char,markflag,discfound) --
snext.prev = current
end
start.prev, stop.next = nil, nil
- current.char, current.subtype, current.components = char, 2, start
+ current.char, current.subtype, current.components = char, ligature_code, start
local head = current
if deletemarks then
if trace_marks then
@@ -370,7 +389,7 @@ local function toligature(kind,lookupname,start,stop,char,markflag,discfound) --
start = start.next
end
start = current.next
- while start and start.id == glyph do
+ while start and start.id == glyph_code do
if marks[start.char] then
set_attribute(start,markdone,i)
if trace_marks then
@@ -401,7 +420,7 @@ end
local function alternative_glyph(start,alternatives,kind,chainname,chainlookupname,lookupname) -- chainname and chainlookupname optional
local value, choice, n = featurevalue or tfmdata.shared.features[kind], nil, #alternatives -- global value, brrr
if value == "random" then
- local r = math.random(1,n)
+ local r = random(1,n)
value, choice = format("random, choice %s",r), alternatives[r]
elseif value == "first" then
value, choice = format("first, choice %s",1), alternatives[1]
@@ -465,7 +484,7 @@ function handlers.gsub_ligature(start,kind,lookupname,ligature,sequence) --or ma
if marks[startchar] then
while s do
local id = s.id
- if id == glyph and s.subtype<256 then
+ if id == glyph_code and s.subtype<256 then
if s.font == currentfont then
local char = s.char
local lg = ligature[1][char]
@@ -497,7 +516,7 @@ function handlers.gsub_ligature(start,kind,lookupname,ligature,sequence) --or ma
local skipmark = sequence.flags[1]
while s do
local id = s.id
- if id == glyph and s.subtype<256 then
+ if id == glyph_code and s.subtype<256 then
if s.font == currentfont then
local char = s.char
if skipmark and marks[char] then
@@ -515,7 +534,7 @@ function handlers.gsub_ligature(start,kind,lookupname,ligature,sequence) --or ma
else
break
end
- elseif id == disc then
+ elseif id == disc_code then
discfound = true
s = s.next
else
@@ -545,12 +564,12 @@ function handlers.gpos_mark2base(start,kind,lookupname,markanchors,sequence)
local markchar = start.char
if marks[markchar] then
local base = start.prev -- [glyph] [start=mark]
- if base and base.id == glyph and base.subtype<256 and base.font == currentfont then
+ if base and base.id == glyph_code and base.subtype<256 and base.font == currentfont then
local basechar = base.char
if marks[basechar] then
while true do
base = base.prev
- if base and base.id == glyph and base.subtype<256 and base.font == currentfont then
+ if base and base.id == glyph_code and base.subtype<256 and base.font == currentfont then
basechar = base.char
if not marks[basechar] then
break
@@ -575,7 +594,7 @@ function handlers.gpos_mark2base(start,kind,lookupname,markanchors,sequence)
if al[anchor] then
local ma = markanchors[anchor]
if ma then
- local dx, dy, bound = set_mark(start,base,tfmdata.factor,rlmode,ba,ma)
+ local dx, dy, bound = setmark(start,base,tfmdata.factor,rlmode,ba,ma)
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%s,%s)",
pref(kind,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
@@ -590,7 +609,7 @@ function handlers.gpos_mark2base(start,kind,lookupname,markanchors,sequence)
end
else -- if trace_bugs then
-- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(basechar))
- fonts.register_message(currentfont,basechar,"no base anchors")
+ fonts.registermessage(currentfont,basechar,"no base anchors")
end
elseif trace_bugs then
logwarning("%s: prev node is no char",pref(kind,lookupname))
@@ -607,13 +626,13 @@ function handlers.gpos_mark2ligature(start,kind,lookupname,markanchors,sequence)
if marks[markchar] then
local base = start.prev -- [glyph] [optional marks] [start=mark]
local index = 1
- if base and base.id == glyph and base.subtype<256 and base.font == currentfont then
+ if base and base.id == glyph_code and base.subtype<256 and base.font == currentfont then
local basechar = base.char
if marks[basechar] then
index = index + 1
while true do
base = base.prev
- if base and base.id == glyph and base.subtype<256 and base.font == currentfont then
+ if base and base.id == glyph_code and base.subtype<256 and base.font == currentfont then
basechar = base.char
if marks[basechar] then
index = index + 1
@@ -643,7 +662,7 @@ function handlers.gpos_mark2ligature(start,kind,lookupname,markanchors,sequence)
if ma then
ba = ba[index]
if ba then
- local dx, dy, bound = set_mark(start,base,tfmdata.factor,rlmode,ba,ma,index)
+ local dx, dy, bound = setmark(start,base,tfmdata.factor,rlmode,ba,ma,index)
if trace_marks then
logprocess("%s, anchor %s, index %s, bound %s: anchoring mark %s to baselig %s at index %s => (%s,%s)",
pref(kind,lookupname),anchor,index,bound,gref(markchar),gref(basechar),index,dx,dy)
@@ -660,7 +679,7 @@ function handlers.gpos_mark2ligature(start,kind,lookupname,markanchors,sequence)
end
else -- if trace_bugs then
-- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(basechar))
- fonts.register_message(currentfont,basechar,"no base anchors")
+ fonts.registermessage(currentfont,basechar,"no base anchors")
end
elseif trace_bugs then
logwarning("%s: prev node is no char",pref(kind,lookupname))
@@ -677,7 +696,7 @@ function handlers.gpos_mark2mark(start,kind,lookupname,markanchors,sequence)
--~ local alreadydone = markonce and has_attribute(start,markmark)
--~ if not alreadydone then
local base = start.prev -- [glyph] [basemark] [start=mark]
- if base and base.id == glyph and base.subtype<256 and base.font == currentfont then -- subtype test can go
+ if base and base.id == glyph_code and base.subtype<256 and base.font == currentfont then -- subtype test can go
local basechar = base.char
local baseanchors = descriptions[basechar]
if baseanchors then
@@ -690,7 +709,7 @@ function handlers.gpos_mark2mark(start,kind,lookupname,markanchors,sequence)
if al[anchor] then
local ma = markanchors[anchor]
if ma then
- local dx, dy, bound = set_mark(start,base,tfmdata.factor,rlmode,ba,ma)
+ local dx, dy, bound = setmark(start,base,tfmdata.factor,rlmode,ba,ma)
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%s,%s)",
pref(kind,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
@@ -706,7 +725,7 @@ function handlers.gpos_mark2mark(start,kind,lookupname,markanchors,sequence)
end
else -- if trace_bugs then
-- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(basechar))
- fonts.register_message(currentfont,basechar,"no base anchors")
+ fonts.registermessage(currentfont,basechar,"no base anchors")
end
elseif trace_bugs then
logwarning("%s: prev node is no mark",pref(kind,lookupname))
@@ -731,7 +750,7 @@ function handlers.gpos_cursive(start,kind,lookupname,exitanchors,sequence) -- to
end
else
local nxt = start.next
- while not done and nxt and nxt.id == glyph and nxt.subtype<256 and nxt.font == currentfont do
+ while not done and nxt and nxt.id == glyph_code and nxt.subtype<256 and nxt.font == currentfont do
local nextchar = nxt.char
if marks[nextchar] then
-- should not happen (maybe warning)
@@ -748,7 +767,7 @@ function handlers.gpos_cursive(start,kind,lookupname,exitanchors,sequence) -- to
if al[anchor] then
local exit = exitanchors[anchor]
if exit then
- local dx, dy, bound = set_cursive(start,nxt,tfmdata.factor,rlmode,exit,entry,characters[startchar],characters[nextchar])
+ local dx, dy, bound = setcursive(start,nxt,tfmdata.factor,rlmode,exit,entry,characters[startchar],characters[nextchar])
if trace_cursive then
logprocess("%s: moving %s to %s cursive (%s,%s) using anchor %s and bound %s in rlmode %s",pref(kind,lookupname),gref(startchar),gref(nextchar),dx,dy,anchor,bound,rlmode)
end
@@ -761,7 +780,7 @@ function handlers.gpos_cursive(start,kind,lookupname,exitanchors,sequence) -- to
end
else -- if trace_bugs then
-- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(startchar))
- fonts.register_message(currentfont,startchar,"no entry anchors")
+ fonts.registermessage(currentfont,startchar,"no entry anchors")
end
break
end
@@ -778,7 +797,7 @@ end
function handlers.gpos_single(start,kind,lookupname,kerns,sequence)
local startchar = start.char
- local dx, dy, w, h = set_pair(start,tfmdata.factor,rlmode,sequence.flags[4],kerns,characters[startchar])
+ local dx, dy, w, h = setpair(start,tfmdata.factor,rlmode,sequence.flags[4],kerns,characters[startchar])
if trace_kerns then
logprocess("%s: shifting single %s by (%s,%s) and correction (%s,%s)",pref(kind,lookupname),gref(startchar),dx,dy,w,h)
end
@@ -794,9 +813,9 @@ function handlers.gpos_pair(start,kind,lookupname,kerns,sequence)
else
local prev, done = start, false
local factor = tfmdata.factor
- while snext and snext.id == glyph and snext.subtype<256 and snext.font == currentfont do
+ while snext and snext.id == glyph_code and snext.subtype<256 and snext.font == currentfont do
local nextchar = snext.char
-local krn = kerns[nextchar]
+ local krn = kerns[nextchar]
if not krn and marks[nextchar] then
prev = snext
snext = snext.next
@@ -809,23 +828,23 @@ local krn = kerns[nextchar]
local a, b = krn[3], krn[4]
if a and #a > 0 then
local startchar = start.char
- local x, y, w, h = set_pair(start,factor,rlmode,sequence.flags[4],a,characters[startchar])
+ local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,characters[startchar])
if trace_kerns then
logprocess("%s: shifting first of pair %s and %s by (%s,%s) and correction (%s,%s)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
end
end
if b and #b > 0 then
local startchar = start.char
- local x, y, w, h = set_pair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar])
+ local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar])
if trace_kerns then
logprocess("%s: shifting second of pair %s and %s by (%s,%s) and correction (%s,%s)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
end
end
else
- logs.report("%s: check this out (old kern stuff)",pref(kind,lookupname))
+ report_process("%s: check this out (old kern stuff)",pref(kind,lookupname))
local a, b = krn[3], krn[7]
if a and a ~= 0 then
- local k = set_kern(snext,factor,rlmode,a)
+ local k = setkern(snext,factor,rlmode,a)
if trace_kerns then
logprocess("%s: inserting first kern %s between %s and %s",pref(kind,lookupname),k,gref(prev.char),gref(nextchar))
end
@@ -836,7 +855,7 @@ local krn = kerns[nextchar]
end
done = true
elseif krn ~= 0 then
- local k = set_kern(snext,factor,rlmode,krn)
+ local k = setkern(snext,factor,rlmode,krn)
if trace_kerns then
logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(prev.char),gref(nextchar))
end
@@ -861,12 +880,11 @@ local function logprocess(...)
if trace_steps then
registermessage(...)
end
- logs.report("otf subchain",...)
-end
-local function logwarning(...)
- logs.report("otf subchain",...)
+ report_subchain(...)
end
+local logwarning = report_subchain
+
-- ['coverage']={
-- ['after']={ "r" },
-- ['before']={ "q" },
@@ -904,12 +922,11 @@ local function logprocess(...)
if trace_steps then
registermessage(...)
end
- logs.report("otf chain",...)
-end
-local function logwarning(...)
- logs.report("otf chain",...)
+ report_chain(...)
end
+local logwarning = report_chain
+
-- We could share functions but that would lead to extra function calls with many
-- arguments, redundant tests and confusing messages.
@@ -976,7 +993,7 @@ function chainprocs.gsub_single(start,stop,kind,chainname,currentcontext,cache,c
local current = start
local subtables = currentlookup.subtables
while current do
- if current.id == glyph then
+ if current.id == glyph_code then
local currentchar = current.char
local lookupname = subtables[1]
local replacement = cache.gsub_single[lookupname]
@@ -1064,7 +1081,7 @@ function chainprocs.gsub_alternate(start,stop,kind,chainname,currentcontext,cach
local current = start
local subtables = currentlookup.subtables
while current do
- if current.id == glyph then
+ if current.id == glyph_code then
local currentchar = current.char
local lookupname = subtables[1]
local alternatives = cache.gsub_alternate[lookupname]
@@ -1121,7 +1138,7 @@ function chainprocs.gsub_ligature(start,stop,kind,chainname,currentcontext,cache
local s, discfound, last, nofreplacements = start.next, false, stop, 0
while s do
local id = s.id
- if id == disc then
+ if id == disc_code then
s = s.next
discfound = true
else
@@ -1182,12 +1199,12 @@ function chainprocs.gpos_mark2base(start,stop,kind,chainname,currentcontext,cach
end
if markanchors then
local base = start.prev -- [glyph] [start=mark]
- if base and base.id == glyph and base.subtype<256 and base.font == currentfont then
+ if base and base.id == glyph_code and base.subtype<256 and base.font == currentfont then
local basechar = base.char
if marks[basechar] then
while true do
base = base.prev
- if base and base.id == glyph and base.subtype<256 and base.font == currentfont then
+ if base and base.id == glyph_code and base.subtype<256 and base.font == currentfont then
basechar = base.char
if not marks[basechar] then
break
@@ -1209,7 +1226,7 @@ function chainprocs.gpos_mark2base(start,stop,kind,chainname,currentcontext,cach
if al[anchor] then
local ma = markanchors[anchor]
if ma then
- local dx, dy, bound = set_mark(start,base,tfmdata.factor,rlmode,ba,ma)
+ local dx, dy, bound = setmark(start,base,tfmdata.factor,rlmode,ba,ma)
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%s,%s)",
cref(kind,chainname,chainlookupname,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
@@ -1247,13 +1264,13 @@ function chainprocs.gpos_mark2ligature(start,stop,kind,chainname,currentcontext,
if markanchors then
local base = start.prev -- [glyph] [optional marks] [start=mark]
local index = 1
- if base and base.id == glyph and base.subtype<256 and base.font == currentfont then
+ if base and base.id == glyph_code and base.subtype<256 and base.font == currentfont then
local basechar = base.char
if marks[basechar] then
index = index + 1
while true do
base = base.prev
- if base and base.id == glyph and base.subtype<256 and base.font == currentfont then
+ if base and base.id == glyph_code and base.subtype<256 and base.font == currentfont then
basechar = base.char
if marks[basechar] then
index = index + 1
@@ -1282,7 +1299,7 @@ function chainprocs.gpos_mark2ligature(start,stop,kind,chainname,currentcontext,
if ma then
ba = ba[index]
if ba then
- local dx, dy, bound = set_mark(start,base,tfmdata.factor,rlmode,ba,ma,index)
+ local dx, dy, bound = setmark(start,base,tfmdata.factor,rlmode,ba,ma,index)
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to baselig %s at index %s => (%s,%s)",
cref(kind,chainname,chainlookupname,lookupname),anchor,a or bound,gref(markchar),gref(basechar),index,dx,dy)
@@ -1323,7 +1340,7 @@ function chainprocs.gpos_mark2mark(start,stop,kind,chainname,currentcontext,cach
end
if markanchors then
local base = start.prev -- [glyph] [basemark] [start=mark]
- if base and base.id == glyph and base.subtype<256 and base.font == currentfont then -- subtype test can go
+ if base and base.id == glyph_code and base.subtype<256 and base.font == currentfont then -- subtype test can go
local basechar = base.char
local baseanchors = descriptions[basechar].anchors
if baseanchors then
@@ -1334,7 +1351,7 @@ function chainprocs.gpos_mark2mark(start,stop,kind,chainname,currentcontext,cach
if al[anchor] then
local ma = markanchors[anchor]
if ma then
- local dx, dy, bound = set_mark(start,base,tfmdata.factor,rlmode,ba,ma)
+ local dx, dy, bound = setmark(start,base,tfmdata.factor,rlmode,ba,ma)
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%s,%s)",
cref(kind,chainname,chainlookupname,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
@@ -1383,7 +1400,7 @@ function chainprocs.gpos_cursive(start,stop,kind,chainname,currentcontext,cache,
end
else
local nxt = start.next
- while not done and nxt and nxt.id == glyph and nxt.subtype<256 and nxt.font == currentfont do
+ while not done and nxt and nxt.id == glyph_code and nxt.subtype<256 and nxt.font == currentfont do
local nextchar = nxt.char
if marks[nextchar] then
-- should not happen (maybe warning)
@@ -1400,7 +1417,7 @@ function chainprocs.gpos_cursive(start,stop,kind,chainname,currentcontext,cache,
if al[anchor] then
local exit = exitanchors[anchor]
if exit then
- local dx, dy, bound = set_cursive(start,nxt,tfmdata.factor,rlmode,exit,entry,characters[startchar],characters[nextchar])
+ local dx, dy, bound = setcursive(start,nxt,tfmdata.factor,rlmode,exit,entry,characters[startchar],characters[nextchar])
if trace_cursive then
logprocess("%s: moving %s to %s cursive (%s,%s) using anchor %s and bound %s in rlmode %s",pref(kind,lookupname),gref(startchar),gref(nextchar),dx,dy,anchor,bound,rlmode)
end
@@ -1413,7 +1430,7 @@ function chainprocs.gpos_cursive(start,stop,kind,chainname,currentcontext,cache,
end
else -- if trace_bugs then
-- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(startchar))
- fonts.register_message(currentfont,startchar,"no entry anchors")
+ fonts.registermessage(currentfont,startchar,"no entry anchors")
end
break
end
@@ -1439,7 +1456,7 @@ function chainprocs.gpos_single(start,stop,kind,chainname,currentcontext,cache,c
if kerns then
kerns = kerns[startchar]
if kerns then
- local dx, dy, w, h = set_pair(start,tfmdata.factor,rlmode,sequence.flags[4],kerns,characters[startchar])
+ local dx, dy, w, h = setpair(start,tfmdata.factor,rlmode,sequence.flags[4],kerns,characters[startchar])
if trace_kerns then
logprocess("%s: shifting single %s by (%s,%s) and correction (%s,%s)",cref(kind,chainname,chainlookupname),gref(startchar),dx,dy,w,h)
end
@@ -1463,7 +1480,7 @@ function chainprocs.gpos_pair(start,stop,kind,chainname,currentcontext,cache,cur
if kerns then
local prev, done = start, false
local factor = tfmdata.factor
- while snext and snext.id == glyph and snext.subtype<256 and snext.font == currentfont do
+ while snext and snext.id == glyph_code and snext.subtype<256 and snext.font == currentfont do
local nextchar = snext.char
local krn = kerns[nextchar]
if not krn and marks[nextchar] then
@@ -1477,23 +1494,23 @@ function chainprocs.gpos_pair(start,stop,kind,chainname,currentcontext,cache,cur
local a, b = krn[3], krn[4]
if a and #a > 0 then
local startchar = start.char
- local x, y, w, h = set_pair(start,factor,rlmode,sequence.flags[4],a,characters[startchar])
+ local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,characters[startchar])
if trace_kerns then
logprocess("%s: shifting first of pair %s and %s by (%s,%s) and correction (%s,%s)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
end
end
if b and #b > 0 then
local startchar = start.char
- local x, y, w, h = set_pair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar])
+ local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar])
if trace_kerns then
logprocess("%s: shifting second of pair %s and %s by (%s,%s) and correction (%s,%s)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
end
end
else
- logs.report("%s: check this out (old kern stuff)",cref(kind,chainname,chainlookupname))
+ report_process("%s: check this out (old kern stuff)",cref(kind,chainname,chainlookupname))
local a, b = krn[3], krn[7]
if a and a ~= 0 then
- local k = set_kern(snext,factor,rlmode,a)
+ local k = setkern(snext,factor,rlmode,a)
if trace_kerns then
logprocess("%s: inserting first kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(prev.char),gref(nextchar))
end
@@ -1504,7 +1521,7 @@ function chainprocs.gpos_pair(start,stop,kind,chainname,currentcontext,cache,cur
end
done = true
elseif krn ~= 0 then
- local k = set_kern(snext,factor,rlmode,krn)
+ local k = setkern(snext,factor,rlmode,krn)
if trace_kerns then
logprocess("%s: inserting kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(prev.char),gref(nextchar))
end
@@ -1551,7 +1568,7 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence
-- f..l = mid string
if s == 1 then
-- never happens
- match = current.id == glyph and current.subtype<256 and current.font == currentfont and seq[1][current.char]
+ match = current.id == glyph_code and current.subtype<256 and current.font == currentfont and seq[1][current.char]
else
-- todo: better space check (maybe check for glue)
local f, l = ck[4], ck[5]
@@ -1565,12 +1582,12 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence
-- we cannot optimize for n=2 because there can be disc nodes
-- if not someskip and n == l then
-- -- n=2 and no skips then faster loop
- -- match = last and last.id == glyph and last.subtype<256 and last.font == currentfont and seq[n][last.char]
+ -- match = last and last.id == glyph_code and last.subtype<256 and last.font == currentfont and seq[n][last.char]
-- else
while n <= l do
if last then
local id = last.id
- if id == glyph then
+ if id == glyph_code then
if last.subtype<256 and last.font == currentfont then
local char = last.char
local ccd = descriptions[char]
@@ -1596,7 +1613,7 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence
else
match = false break
end
- elseif id == disc then -- what to do with kerns?
+ elseif id == disc_code then -- what to do with kerns?
last = last.next
else
match = false break
@@ -1615,7 +1632,7 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence
while n >= 1 do
if prev then
local id = prev.id
- if id == glyph then
+ if id == glyph_code then
if prev.subtype<256 and prev.font == currentfont then -- normal char
local char = prev.char
local ccd = descriptions[char]
@@ -1637,7 +1654,7 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence
else
match = false break
end
- elseif id == disc then
+ elseif id == disc_code then
-- skip 'm
elseif seq[n][32] then
n = n -1
@@ -1670,7 +1687,7 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence
while n <= s do
if current then
local id = current.id
- if id == glyph then
+ if id == glyph_code then
if current.subtype<256 and current.font == currentfont then -- normal char
local char = current.char
local ccd = descriptions[char]
@@ -1692,7 +1709,7 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence
else
match = false break
end
- elseif id == disc then
+ elseif id == disc_code then
-- skip 'm
elseif seq[n][32] then -- brrr
n = n + 1
@@ -1768,22 +1785,22 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence
local i = 1
repeat
-if skipped then
- while true do
- local char = start.char
- local ccd = descriptions[char]
- if ccd then
- local class = ccd.class
- if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
- start = start.next
- else
- break
- end
- else
- break
- end
- end
-end
+ if skipped then
+ while true do
+ local char = start.char
+ local ccd = descriptions[char]
+ if ccd then
+ local class = ccd.class
+ if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
+ start = start.next
+ else
+ break
+ end
+ else
+ break
+ end
+ end
+ end
local chainlookupname = chainlookups[i]
local chainlookup = lookuptable[chainlookupname]
local cp = chainmores[chainlookup.type]
@@ -1864,12 +1881,11 @@ local function logprocess(...)
if trace_steps then
registermessage(...)
end
- logs.report("otf process",...)
-end
-local function logwarning(...)
- logs.report("otf process",...)
+ report_process(...)
end
+local logwarning = report_process
+
local function report_missing_cache(typ,lookup)
local f = missing[currentfont] if not f then f = { } missing[currentfont] = f end
local t = f[typ] if not t then t = { } f[typ] = t end
@@ -1909,8 +1925,8 @@ function fonts.methods.node.otf.features(head,font,attr)
local script, language, s_enabled, a_enabled, dyn
local attribute_driven = attr and attr ~= 0
if attribute_driven then
- local features = context_setups[context_numbers[attr]] -- could be a direct list
- dyn = context_merged[attr] or 0
+ local features = contextsetups[contextnumbers[attr]] -- could be a direct list
+ dyn = contextmerged[attr] or 0
language, script = features.language or "dflt", features.script or "dflt"
a_enabled = features -- shared.features -- can be made local to the resolver
if dyn == 2 or dyn == -2 then
@@ -1967,7 +1983,7 @@ function fonts.methods.node.otf.features(head,font,attr)
end
if trace_applied then
local typ, action = match(sequence.type,"(.*)_(.*)")
- logs.report("otf node mode",
+ report_process(
"%s font: %03i, dynamic: %03i, kind: %s, lookup: %3i, script: %-4s, language: %-4s (%-4s), type: %s, action: %s, name: %s",
(valid and "+") or "-",font,attr or 0,kind,s,script,language,what,typ,action,sequence.name)
end
@@ -1995,7 +2011,7 @@ function fonts.methods.node.otf.features(head,font,attr)
local start = find_node_tail(head) -- slow (we can store tail because there's always a skip at the end): todo
while start do
local id = start.id
- if id == glyph then
+ if id == glyph_code then
if start.subtype<256 and start.font == font then
local a = has_attribute(start,0)
if a then
@@ -2044,7 +2060,7 @@ function fonts.methods.node.otf.features(head,font,attr)
else
while start do
local id = start.id
- if id == glyph then
+ if id == glyph_code then
if start.subtype<256 and start.font == font then
local a = has_attribute(start,0)
if a then
@@ -2069,7 +2085,7 @@ function fonts.methods.node.otf.features(head,font,attr)
else
start = start.next
end
- -- elseif id == glue then
+ -- elseif id == glue_code then
-- if p[5] then -- chain
-- local pc = pp[32]
-- if pc then
@@ -2084,9 +2100,9 @@ function fonts.methods.node.otf.features(head,font,attr)
-- else
-- start = start.next
-- end
- elseif id == whatsit then
+ elseif id == whatsit_code then
local subtype = start.subtype
- if subtype == 7 then
+ if subtype == dir_code then
local dir = start.dir
if dir == "+TRT" or dir == "+TLT" then
insert(txtdir,dir)
@@ -2102,9 +2118,9 @@ function fonts.methods.node.otf.features(head,font,attr)
rlmode = pardir
end
if trace_directions then
- logs.report("fonts","directions after textdir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode)
+ report_process("directions after textdir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode)
end
- elseif subtype == 6 then
+ elseif subtype == localpar_code then
local dir = start.dir
if dir == "TRT" then
pardir = -1
@@ -2116,7 +2132,7 @@ function fonts.methods.node.otf.features(head,font,attr)
rlmode = pardir
--~ txtdir = { }
if trace_directions then
- logs.report("fonts","directions after pardir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode)
+ report_process("directions after pardir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode)
end
end
start = start.next
@@ -2128,7 +2144,7 @@ function fonts.methods.node.otf.features(head,font,attr)
else
while start do
local id = start.id
- if id == glyph then
+ if id == glyph_code then
if start.subtype<256 and start.font == font then
local a = has_attribute(start,0)
if a then
@@ -2162,7 +2178,7 @@ function fonts.methods.node.otf.features(head,font,attr)
else
start = start.next
end
- -- elseif id == glue then
+ -- elseif id == glue_code then
-- if p[5] then -- chain
-- local pc = pp[32]
-- if pc then
@@ -2177,9 +2193,9 @@ function fonts.methods.node.otf.features(head,font,attr)
-- else
-- start = start.next
-- end
- elseif id == whatsit then
+ elseif id == whatsit_code then
local subtype = start.subtype
- if subtype == 7 then
+ if subtype == dir_code then
local dir = start.dir
if dir == "+TRT" or dir == "+TLT" then
insert(txtdir,dir)
@@ -2195,9 +2211,9 @@ function fonts.methods.node.otf.features(head,font,attr)
rlmode = pardir
end
if trace_directions then
- logs.report("fonts","directions after textdir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode)
+ report_process("directions after textdir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode)
end
- elseif subtype == 6 then
+ elseif subtype == localpar_code then
local dir = start.dir
if dir == "TRT" then
pardir = -1
@@ -2209,7 +2225,7 @@ function fonts.methods.node.otf.features(head,font,attr)
rlmode = pardir
--~ txtdir = { }
if trace_directions then
- logs.report("fonts","directions after pardir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode)
+ report_process("directions after pardir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode)
end
end
start = start.next
@@ -2317,7 +2333,7 @@ local function prepare_lookups(tfmdata)
if not s then s = { } single[lookup] = s end
s[old] = new
--~ if trace_lookups then
- --~ logs.report("define otf","lookup %s: substitution %s => %s",lookup,old,new)
+ --~ report_prepare("lookup %s: substitution %s => %s",lookup,old,new)
--~ end
end,
multiple = function (p,lookup,glyph,unicode)
@@ -2334,7 +2350,7 @@ local function prepare_lookups(tfmdata)
end
end
--~ if trace_lookups then
- --~ logs.report("define otf","lookup %s: multiple %s => %s",lookup,old,concat(new," "))
+ --~ report_prepare("lookup %s: multiple %s => %s",lookup,old,concat(new," "))
--~ end
end,
alternate = function(p,lookup,glyph,unicode)
@@ -2351,12 +2367,12 @@ local function prepare_lookups(tfmdata)
end
end
--~ if trace_lookups then
- --~ logs.report("define otf","lookup %s: alternate %s => %s",lookup,old,concat(new,"|"))
+ --~ report_prepare("lookup %s: alternate %s => %s",lookup,old,concat(new,"|"))
--~ end
end,
ligature = function (p,lookup,glyph,unicode)
--~ if trace_lookups then
- --~ logs.report("define otf","lookup %s: ligature %s => %s",lookup,p[2],glyph.name)
+ --~ report_prepare("lookup %s: ligature %s => %s",lookup,p[2],glyph.name)
--~ end
local first = true
local t = ligature[lookup]
@@ -2365,7 +2381,7 @@ local function prepare_lookups(tfmdata)
if first then
local u = unicodes[s]
if not u then
- logs.report("define otf","lookup %s: ligature %s => %s ignored due to invalid unicode",lookup,p[2],glyph.name)
+ report_prepare("lookup %s: ligature %s => %s ignored due to invalid unicode",lookup,p[2],glyph.name)
break
elseif type(u) == "number" then
if not t[u] then
@@ -2435,7 +2451,7 @@ local function prepare_lookups(tfmdata)
end
end
--~ if trace_lookups then
- --~ logs.report("define otf","lookup %s: pair for U+%04X",lookup,unicode)
+ --~ report_prepare("lookup %s: pair for U+%04X",lookup,unicode)
--~ end
end,
}
@@ -2456,14 +2472,14 @@ local function prepare_lookups(tfmdata)
end
end
end
- local list = glyph.mykerns
+ local list = glyph.kerns
if list then
for lookup, krn in next, list do
local k = kerns[lookup]
if not k then k = { } kerns[lookup] = k end
k[unicode] = krn -- ref to glyph, saves lookup
--~ if trace_lookups then
- --~ logs.report("define otf","lookup %s: kern for U+%04X",lookup,unicode)
+ --~ report_prepare("lookup %s: kern for U+%04X",lookup,unicode)
--~ end
end
end
@@ -2479,7 +2495,7 @@ local function prepare_lookups(tfmdata)
if not f then f = { } mark[lookup] = f end
f[unicode] = anchors -- ref to glyph, saves lookup
--~ if trace_lookups then
- --~ logs.report("define otf","lookup %s: mark anchor %s for U+%04X",lookup,name,unicode)
+ --~ report_prepare("lookup %s: mark anchor %s for U+%04X",lookup,name,unicode)
--~ end
end
end
@@ -2493,7 +2509,7 @@ local function prepare_lookups(tfmdata)
if not f then f = { } cursive[lookup] = f end
f[unicode] = anchors -- ref to glyph, saves lookup
--~ if trace_lookups then
- --~ logs.report("define otf","lookup %s: exit anchor %s for U+%04X",lookup,name,unicode)
+ --~ report_prepare("lookup %s: exit anchor %s for U+%04X",lookup,name,unicode)
--~ end
end
end
@@ -2526,7 +2542,7 @@ local function prepare_contextchains(tfmdata)
for lookupname, lookupdata in next, otfdata.lookups do
local lookuptype = lookupdata.type
if not lookuptype then
- logs.report("otf process","missing lookuptype for %s",lookupname)
+ report_prepare("missing lookuptype for %s",lookupname)
else
local rules = lookupdata.rules
if rules then
@@ -2534,7 +2550,7 @@ local function prepare_contextchains(tfmdata)
-- contextchain[lookupname][unicode]
if fmt == "coverage" then
if lookuptype ~= "chainsub" and lookuptype ~= "chainpos" then
- logs.report("otf process","unsupported coverage %s for %s",lookuptype,lookupname)
+ report_prepare("unsupported coverage %s for %s",lookuptype,lookupname)
else
local contexts = contextchain[lookupname]
if not contexts then
@@ -2570,7 +2586,7 @@ local function prepare_contextchains(tfmdata)
end
elseif fmt == "reversecoverage" then
if lookuptype ~= "reversesub" then
- logs.report("otf process","unsupported reverse coverage %s for %s",lookuptype,lookupname)
+ report_prepare("unsupported reverse coverage %s for %s",lookuptype,lookupname)
else
local contexts = reversecontextchain[lookupname]
if not contexts then
@@ -2610,7 +2626,7 @@ local function prepare_contextchains(tfmdata)
end
elseif fmt == "glyphs" then
if lookuptype ~= "chainsub" and lookuptype ~= "chainpos" then
- logs.report("otf process","unsupported coverage %s for %s",lookuptype,lookupname)
+ report_prepare("unsupported coverage %s for %s",lookuptype,lookupname)
else
local contexts = contextchain[lookupname]
if not contexts then
@@ -2681,7 +2697,7 @@ function fonts.initializers.node.otf.features(tfmdata,value)
prepare_lookups(tfmdata)
otfdata.shared.initialized = true
if trace_preparing then
- logs.report("otf process","preparation time is %0.3f seconds for %s",os.clock()-t,tfmdata.fullname or "?")
+ report_prepare("preparation time is %0.3f seconds for %s",os.clock()-t,tfmdata.fullname or "?")
end
end
end
diff --git a/otfl-font-ott.lua b/otfl-font-ott.lua
index c56e984..a5a0df3 100644
--- a/otfl-font-ott.lua
+++ b/otfl-font-ott.lua
@@ -7,17 +7,23 @@ if not modules then modules = { } end modules ['font-otf'] = {
}
local type, next, tonumber, tostring = type, next, tonumber, tostring
-local gsub, lower = string.gsub, string.lower
+local gsub, lower, format = string.gsub, string.lower, string.format
+local is_boolean = string.is_boolean
-fonts = fonts or { }
-fonts.otf = fonts.otf or { }
+local allocate = utilities.storage.allocate
-local otf = fonts.otf
+fonts = fonts or { } -- needed for font server
+local fonts = fonts
+fonts.otf = fonts.otf or { }
+local otf = fonts.otf
-otf.tables = otf.tables or { }
-otf.meanings = otf.meanings or { }
+otf.tables = otf.tables or { }
+local tables = otf.tables
-otf.tables.scripts = {
+otf.meanings = otf.meanings or { }
+local meanings = otf.meanings
+
+local scripts = allocate {
['dflt'] = 'Default',
['arab'] = 'Arabic',
@@ -90,7 +96,7 @@ otf.tables.scripts = {
['yi' ] = 'Yi',
}
-otf.tables.languages = {
+local languages = allocate {
['dflt'] = 'Default',
['aba'] = 'Abaza',
@@ -484,7 +490,7 @@ otf.tables.languages = {
['zul'] = 'Zulu'
}
-otf.tables.features = {
+local features = allocate {
['aalt'] = 'Access All Alternates',
['abvf'] = 'Above-Base Forms',
['abvm'] = 'Above-Base Mark Positioning',
@@ -622,7 +628,7 @@ otf.tables.features = {
['tlig'] = 'Traditional TeX Ligatures',
}
-otf.tables.baselines = {
+local baselines = allocate {
['hang'] = 'Hanging baseline',
['icfb'] = 'Ideographic character face bottom edge baseline',
['icft'] = 'Ideographic character face tope edige baseline',
@@ -632,10 +638,33 @@ otf.tables.baselines = {
['romn'] = 'Roman baseline'
}
+local verbosescripts = allocate(table.swaphash(scripts ))
+local verboselanguages = allocate(table.swaphash(languages))
+local verbosefeatures = allocate(table.swaphash(features ))
+
+tables.scripts = scripts
+tables.languages = languages
+tables.features = features
+tables.baselines = baselines
+
+tables.verbosescripts = verbosescripts
+tables.verboselanguages = verboselanguages
+tables.verbosefeatures = verbosefeatures
+
+for k, v in next, verbosefeatures do
+ local stripped = gsub(k,"%-"," ")
+ verbosefeatures[stripped] = v
+ local stripped = gsub(k,"[^a-zA-Z0-9]","")
+ verbosefeatures[stripped] = v
+end
+for k, v in next, verbosefeatures do
+ verbosefeatures[lower(k)] = v
+end
+
-- can be sped up by local tables
-function otf.tables.to_tag(id)
- return stringformat("%4s",lower(id))
+function tables.totag(id) -- not used
+ return format("%4s",lower(id))
end
local function resolve(tab,id)
@@ -647,87 +676,59 @@ local function resolve(tab,id)
end
end
-function otf.meanings.script(id)
- return resolve(otf.tables.scripts,id)
-end
-function otf.meanings.language(id)
- return resolve(otf.tables.languages,id)
-end
-function otf.meanings.feature(id)
- return resolve(otf.tables.features,id)
-end
-function otf.meanings.baseline(id)
- return resolve(otf.tables.baselines,id)
-end
-
-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 )
-
-local scripts = otf.tables.scripts
-local languages = otf.tables.languages
-local features = otf.tables.features
+function meanings.script (id) return resolve(scripts, id) end
+function meanings.language(id) return resolve(languages,id) end
+function meanings.feature (id) return resolve(features, id) end
+function meanings.baseline(id) return resolve(baselines,id) end
-local to_scripts = otf.tables.to_scripts
-local to_languages = otf.tables.to_languages
-local to_features = otf.tables.to_features
-
-for k, v in next, to_features do
- local stripped = gsub(k,"%-"," ")
- to_features[stripped] = v
- local stripped = gsub(k,"[^a-zA-Z0-9]","")
- to_features[stripped] = v
-end
-for k, v in next, to_features do
- to_features[lower(k)] = v
-end
-
-otf.meanings.checkers = {
+local checkers = {
rand = function(v)
return v and "random"
end
}
-local checkers = otf.meanings.checkers
+meanings.checkers = checkers
-function otf.meanings.normalize(features)
- local h = { }
- for k,v in next, features do
- k = lower(k)
- if k == "language" or k == "lang" then
- v = gsub(lower(v),"[^a-z0-9%-]","")
- if not languages[v] then
- h.language = to_languages[v] or "dflt"
- else
- h.language = v
- end
- elseif k == "script" then
- v = gsub(lower(v),"[^a-z0-9%-]","")
- if not scripts[v] then
- h.script = to_scripts[v] or "dflt"
- else
- h.script = v
- end
- else
- if type(v) == "string" then
- local b = v:is_boolean()
- if type(b) == "nil" then
- v = tonumber(v) or lower(v)
+function meanings.normalize(features)
+ if features then
+ local h = { }
+ for k,v in next, features do
+ k = lower(k)
+ if k == "language" or k == "lang" then
+ v = gsub(lower(v),"[^a-z0-9%-]","")
+ if not languages[v] then
+ h.language = verboselanguages[v] or "dflt"
else
- v = b
+ h.language = v
+ end
+ elseif k == "script" then
+ v = gsub(lower(v),"[^a-z0-9%-]","")
+ if not scripts[v] then
+ h.script = verbosescripts[v] or "dflt"
+ else
+ h.script = v
+ end
+ else
+ if type(v) == "string" then
+ local b = is_boolean(v)
+ if type(b) == "nil" then
+ v = tonumber(v) or lower(v)
+ else
+ v = b
+ end
end
+ k = verbosefeatures[k] or k
+ local c = checkers[k]
+ h[k] = c and c(v) or v
end
- k = to_features[k] or k
- local c = checkers[k]
- h[k] = c and c(v) or v
end
+ return h
end
- return h
end
-- When I feel the need ...
---~ otf.tables.aat = {
+--~ tables.aat = {
--~ [ 0] = {
--~ name = "allTypographicFeaturesType",
--~ [ 0] = "allTypeFeaturesOnSelector",
diff --git a/otfl-font-tfm.lua b/otfl-font-tfm.lua
index 560ba1c..4d80f07 100644
--- a/otfl-font-tfm.lua
+++ b/otfl-font-tfm.lua
@@ -11,9 +11,13 @@ local utf = unicode.utf8
local next, format, match, lower, gsub = next, string.format, string.match, string.lower, string.gsub
local concat, sortedkeys, utfbyte, serialize = table.concat, table.sortedkeys, utf.byte, table.serialize
+local allocate = utilities.storage.allocate
+
local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
local trace_scaling = false trackers.register("fonts.scaling" , function(v) trace_scaling = v end)
+local report_define = logs.new("define fonts")
+
-- tfmdata has also fast access to indices and unicodes
-- to be checked: otf -> tfm -> tfmscaled
--
@@ -23,32 +27,32 @@ local trace_scaling = false trackers.register("fonts.scaling" , function(v) tr
<p>Here we only implement a few helper functions.</p>
--ldx]]--
-fonts = fonts or { }
-fonts.tfm = fonts.tfm or { }
-fonts.ids = fonts.ids or { }
-
-local tfm = fonts.tfm
+local fonts = fonts
+local tfm = fonts.tfm
-fonts.loaded = fonts.loaded or { }
-fonts.dontembed = fonts.dontembed or { }
-fonts.triggers = fonts.triggers or { } -- brrr
-fonts.initializers = fonts.initializers or { }
+fonts.loaded = allocate()
+fonts.dontembed = allocate()
+fonts.triggers = fonts.triggers or { } -- brrr
+fonts.initializers = fonts.initializers or { }
fonts.initializers.common = fonts.initializers.common or { }
-local fontdata = fonts.ids
-local disc = node.id('disc')
-local glyph = node.id('glyph')
local set_attribute = node.set_attribute
+local fontdata = fonts.ids
+local nodecodes = nodes.nodecodes
+
+local disc_code = nodecodes.disc
+local glyph_code = nodecodes.glyph
+
--[[ldx--
<p>The next function encapsulates the standard <l n='tfm'/> loader as
supplied by <l n='luatex'/>.</p>
--ldx]]--
-tfm.resolve_vf = true -- false
-tfm.share_base_kerns = false -- true (.5 sec slower on mk but brings down mem from 410M to 310M, beware: then script/lang share too)
-tfm.mathactions = { }
-tfm.fontname_mode = "fullpath"
+tfm.resolvevirtualtoo = true -- false
+tfm.sharebasekerns = false -- true (.5 sec slower on mk but brings down mem from 410M to 310M, beware: then script/lang share too)
+tfm.mathactions = { }
+tfm.fontnamemode = "fullpath"
tfm.enhance = tfm.enhance or function() end
@@ -58,12 +62,12 @@ function tfm.read_from_tfm(specification)
local fname, tfmdata = specification.filename or "", nil
if fname ~= "" then
if trace_defining then
- logs.report("define font","loading tfm file %s at size %s",fname,specification.size)
+ report_define("loading tfm file %s at size %s",fname,specification.size)
end
tfmdata = font.read_tfm(fname,specification.size) -- not cached, fast enough
if tfmdata then
tfmdata.descriptions = tfmdata.descriptions or { }
- if tfm.resolve_vf then
+ if tfm.resolvevirtualtoo then
fonts.logger.save(tfmdata,file.extname(fname),specification) -- strange, why here
fname = resolvers.findbinfile(specification.name, 'ovf')
if fname and fname ~= "" then
@@ -81,7 +85,7 @@ function tfm.read_from_tfm(specification)
tfm.enhance(tfmdata,specification)
end
elseif trace_defining then
- logs.report("define font","loading tfm with name %s fails",specification.name)
+ report_define("loading tfm with name %s fails",specification.name)
end
return tfmdata
end
@@ -124,7 +128,7 @@ end
to scale virtual characters.</p>
--ldx]]--
-function tfm.get_virtual_id(tfmdata)
+function tfm.getvirtualid(tfmdata)
-- since we don't know the id yet, we use 0 as signal
if not tfmdata.fonts then
tfmdata.type = "virtual"
@@ -136,7 +140,7 @@ function tfm.get_virtual_id(tfmdata)
end
end
-function tfm.check_virtual_id(tfmdata, id)
+function tfm.checkvirtualid(tfmdata, id)
if tfmdata and tfmdata.type == "virtual" then
if not tfmdata.fonts or #tfmdata.fonts == 0 then
tfmdata.type, tfmdata.fonts = "real", nil
@@ -166,7 +170,7 @@ fonts.trace_scaling = false
-- sharedkerns are unscaled and are be hashed by concatenated indexes
--~ function tfm.check_base_kerns(tfmdata)
---~ if tfm.share_base_kerns then
+--~ if tfm.sharebasekerns then
--~ local sharedkerns = tfmdata.sharedkerns
--~ if sharedkerns then
--~ local basekerns = { }
@@ -178,7 +182,7 @@ fonts.trace_scaling = false
--~ end
--~ function tfm.prepare_base_kerns(tfmdata)
---~ if tfm.share_base_kerns and not tfmdata.sharedkerns then
+--~ if tfm.sharebasekerns and not tfmdata.sharedkerns then
--~ local sharedkerns = { }
--~ tfmdata.sharedkerns = sharedkerns
--~ for u, chr in next, tfmdata.characters do
@@ -207,7 +211,47 @@ local charactercache = { }
-- a virtual font has italic correction make sure to set the
-- has_italic flag. Some more flags will be added in the future.
-function tfm.calculate_scale(tfmtable, scaledpoints, relativeid)
+--[[ldx--
+<p>The reason why the scaler was originally split, is that for a while we experimented
+with a helper function. However, in practice the <l n='api'/> calls are too slow to
+make this profitable and the <l n='lua'/> based variant was just faster. A days
+wasted day but an experience richer.</p>
+--ldx]]--
+
+tfm.autocleanup = true
+
+local lastfont = nil
+
+-- we can get rid of the tfm instance when we have fast access to the
+-- scaled character dimensions at the tex end, e.g. a fontobject.width
+--
+-- flushing the kern and ligature tables from memory saves a lot (only
+-- base mode) but it complicates vf building where the new characters
+-- demand this data .. solution: functions that access them
+
+-- we don't need the glyph data as we can use the description .. but we will
+-- have to wait till we can access the internal tfm table efficiently in which
+-- case characters will become a metatable afterwards
+
+function tfm.cleanuptable(tfmdata) -- we need a cleanup callback, now we miss the last one
+ if tfm.autocleanup then -- ok, we can hook this into everyshipout or so ... todo
+ if tfmdata.type == 'virtual' or tfmdata.virtualized then
+ for k, v in next, tfmdata.characters do
+ if v.commands then v.commands = nil end
+ -- if v.kerns then v.kerns = nil end
+ end
+ else
+ -- for k, v in next, tfmdata.characters do
+ -- if v.kerns then v.kerns = nil end
+ -- end
+ end
+ end
+end
+
+function tfm.cleanup(tfmdata) -- we need a cleanup callback, now we miss the last one
+end
+
+function tfm.calculatescale(tfmtable, scaledpoints)
if scaledpoints < 0 then
scaledpoints = (- scaledpoints/1000) * tfmtable.designsize -- already in sp
end
@@ -216,10 +260,10 @@ function tfm.calculate_scale(tfmtable, scaledpoints, relativeid)
return scaledpoints, delta, units
end
-function tfm.do_scale(tfmtable, scaledpoints, relativeid)
+function tfm.scale(tfmtable, scaledpoints, relativeid)
-- tfm.prepare_base_kerns(tfmtable) -- optimalization
local t = { } -- the new table
- local scaledpoints, delta, units = tfm.calculate_scale(tfmtable, scaledpoints, relativeid)
+ local scaledpoints, delta, units = tfm.calculatescale(tfmtable, scaledpoints, relativeid)
t.units_per_em = units or 1000
local hdelta, vdelta = delta, delta
-- unicoded unique descriptions shared cidinfo characters changed parameters indices
@@ -249,18 +293,23 @@ function tfm.do_scale(tfmtable, scaledpoints, relativeid)
local nodemode = tfmtable.mode == "node"
local hasquality = tfmtable.auto_expand or tfmtable.auto_protrude
local hasitalic = tfmtable.has_italic
+ local descriptions = tfmtable.descriptions or { }
+ --
+ if hasmath then
+ t.has_math = true -- this will move to elsewhere
+ end
--
t.parameters = { }
t.characters = { }
t.MathConstants = { }
-- fast access
- local descriptions = tfmtable.descriptions or { }
+ t.unscaled = tfmtable -- the original unscaled one (temp)
t.unicodes = tfmtable.unicodes
t.indices = tfmtable.indices
t.marks = tfmtable.marks
-t.goodies = tfmtable.goodies
-t.colorscheme = tfmtable.colorscheme
---~ t.embedding = tfmtable.embedding
+ t.goodies = tfmtable.goodies
+ t.colorscheme = tfmtable.colorscheme
+ -- t.embedding = tfmtable.embedding
t.descriptions = descriptions
if tfmtable.fonts then
t.fonts = table.fastcopy(tfmtable.fonts) -- hm also at the end
@@ -296,7 +345,7 @@ t.colorscheme = tfmtable.colorscheme
local scaledheight = defaultheight * vdelta
local scaleddepth = defaultdepth * vdelta
local stackmath = tfmtable.ignore_stack_math ~= true
- local private = fonts.private
+ local private = fonts.privateoffset
local sharedkerns = { }
for k,v in next, characters do
local chr, description, index
@@ -357,7 +406,7 @@ t.colorscheme = tfmtable.colorscheme
end
end
-- if trace_scaling then
- -- logs.report("define font","t=%s, u=%s, i=%s, n=%s c=%s",k,chr.tounicode or k,description.index,description.name or '-',description.class or '-')
+ -- report_define("t=%s, u=%s, i=%s, n=%s c=%s",k,chr.tounicode or k,description.index,description.name or '-',description.class or '-')
-- end
if tounicode then
local tu = tounicode[index] -- nb: index!
@@ -394,7 +443,7 @@ t.colorscheme = tfmtable.colorscheme
if vn then
chr.next = vn
--~ if v.vert_variants or v.horiz_variants then
- --~ logs.report("glyph 0x%05X has combination of next, vert_variants and horiz_variants",index)
+ --~ report_define("glyph 0x%05X has combination of next, vert_variants and horiz_variants",index)
--~ end
else
local vv = v.vert_variants
@@ -565,11 +614,11 @@ t.colorscheme = tfmtable.colorscheme
-- can have multiple subfonts
if hasmath then
if trace_defining then
- logs.report("define font","math enabled for: name '%s', fullname: '%s', filename: '%s'",t.name or "noname",t.fullname or "nofullname",t.filename or "nofilename")
+ report_define("math enabled for: name '%s', fullname: '%s', filename: '%s'",t.name or "noname",t.fullname or "nofullname",t.filename or "nofilename")
end
else
if trace_defining then
- logs.report("define font","math disabled for: name '%s', fullname: '%s', filename: '%s'",t.name or "noname",t.fullname or "nofullname",t.filename or "nofilename")
+ report_define("math disabled for: name '%s', fullname: '%s', filename: '%s'",t.name or "noname",t.fullname or "nofullname",t.filename or "nofilename")
end
t.nomath, t.MathConstants = true, nil
end
@@ -578,58 +627,17 @@ t.colorscheme = tfmtable.colorscheme
t.psname = t.fontname or (t.fullname and fonts.names.cleanname(t.fullname))
end
if trace_defining then
- logs.report("define font","used for accesing subfont: '%s'",t.psname or "nopsname")
- logs.report("define font","used for subsetting: '%s'",t.fontname or "nofontname")
- end
---~ print(t.fontname,table.serialize(t.MathConstants))
- return t, delta
-end
-
---[[ldx--
-<p>The reason why the scaler is split, is that for a while we experimented
-with a helper function. However, in practice the <l n='api'/> calls are too slow to
-make this profitable and the <l n='lua'/> based variant was just faster. A days
-wasted day but an experience richer.</p>
---ldx]]--
-
-tfm.auto_cleanup = true
-
-local lastfont = nil
-
--- we can get rid of the tfm instance when we have fast access to the
--- scaled character dimensions at the tex end, e.g. a fontobject.width
---
--- flushing the kern and ligature tables from memory saves a lot (only
--- base mode) but it complicates vf building where the new characters
--- demand this data .. solution: functions that access them
-
-function tfm.cleanup_table(tfmdata) -- we need a cleanup callback, now we miss the last one
- if tfm.auto_cleanup then -- ok, we can hook this into everyshipout or so ... todo
- if tfmdata.type == 'virtual' or tfmdata.virtualized then
- for k, v in next, tfmdata.characters do
- if v.commands then v.commands = nil end
- -- if v.kerns then v.kerns = nil end
- end
- else
- -- for k, v in next, tfmdata.characters do
- -- if v.kerns then v.kerns = nil end
- -- end
- end
+ report_define("used for accessing (sub)font: '%s'",t.psname or "nopsname")
+ report_define("used for subsetting: '%s'",t.fontname or "nofontname")
end
-end
-
-function tfm.cleanup(tfmdata) -- we need a cleanup callback, now we miss the last one
-end
-
-function tfm.scale(tfmtable, scaledpoints, relativeid)
- local t, factor = tfm.do_scale(tfmtable, scaledpoints, relativeid)
- t.factor = factor
- t.ascender = factor*(tfmtable.ascender or 0)
- t.descender = factor*(tfmtable.descender or 0)
+ -- this will move up (side effect of merging split call)
+ t.factor = delta
+ t.ascender = delta*(tfmtable.ascender or 0)
+ t.descender = delta*(tfmtable.descender or 0)
t.shared = tfmtable.shared or { }
t.unique = table.fastcopy(tfmtable.unique or {})
---~ print("scaling", t.name, t.factor) -- , tfm.hash_features(tfmtable.specification))
tfm.cleanup(t)
+ -- print(t.fontname,table.serialize(t.MathConstants))
return t
end
@@ -638,10 +646,12 @@ end
process features right.</p>
--ldx]]--
-fonts.analyzers = fonts.analyzers or { }
-fonts.analyzers.aux = fonts.analyzers.aux or { }
-fonts.analyzers.methods = fonts.analyzers.methods or { }
-fonts.analyzers.initializers = fonts.analyzers.initializers or { }
+fonts.analyzers = fonts.analyzers or { }
+local analyzers = fonts.analyzers
+
+analyzers.aux = analyzers.aux or { }
+analyzers.methods = analyzers.methods or { }
+analyzers.initializers = analyzers.initializers or { }
-- todo: analyzers per script/lang, cross font, so we need an font id hash -> script
-- e.g. latin -> hyphenate, arab -> 1/2/3 analyze
@@ -650,17 +660,19 @@ fonts.analyzers.initializers = fonts.analyzers.initializers or { }
local state = attributes.private('state')
-function fonts.analyzers.aux.setstate(head,font)
+function analyzers.aux.setstate(head,font)
+ local useunicodemarks = analyzers.useunicodemarks
local tfmdata = fontdata[font]
local characters = tfmdata.characters
local descriptions = tfmdata.descriptions
local first, last, current, n, done = nil, nil, head, 0, false -- maybe make n boolean
while current do
local id = current.id
- if id == glyph and current.font == font then
- local d = descriptions[current.char]
+ if id == glyph_code and current.font == font then
+ local char = current.char
+ local d = descriptions[char]
if d then
- if d.class == "mark" then
+ if d.class == "mark" or (useunicodemarks and categories[char] == "mn") then
done = true
set_attribute(current,state,5) -- mark
elseif n == 0 then
@@ -678,7 +690,7 @@ function fonts.analyzers.aux.setstate(head,font)
end
first, last, n = nil, nil, 0
end
- elseif id == disc then
+ elseif id == disc_code then
-- always in the middle
set_attribute(current,state,2) -- midi
last = current
@@ -711,25 +723,25 @@ end
-- checking
-function tfm.checked_filename(metadata,whatever)
+function tfm.checkedfilename(metadata,whatever)
local foundfilename = metadata.foundfilename
if not foundfilename then
local askedfilename = metadata.filename or ""
if askedfilename ~= "" then
foundfilename = resolvers.findbinfile(askedfilename,"") or ""
if foundfilename == "" then
- logs.report("fonts","source file '%s' is not found",askedfilename)
+ report_define("source file '%s' is not found",askedfilename)
foundfilename = resolvers.findbinfile(file.basename(askedfilename),"") or ""
if foundfilename ~= "" then
- logs.report("fonts","using source file '%s' (cache mismatch)",foundfilename)
+ report_define("using source file '%s' (cache mismatch)",foundfilename)
end
end
elseif whatever then
- logs.report("fonts","no source file for '%s'",whatever)
+ report_define("no source file for '%s'",whatever)
foundfilename = ""
end
metadata.foundfilename = foundfilename
- -- logs.report("fonts","using source file '%s'",foundfilename)
+ -- report_define("using source file '%s'",foundfilename)
end
return foundfilename
end
diff --git a/otfl-font-xtx.lua b/otfl-font-xtx.lua
index 8237851..dc3c6b9 100644
--- a/otfl-font-xtx.lua
+++ b/otfl-font-xtx.lua
@@ -31,32 +31,10 @@ well and that does not work too well with the general design
of the specifier.</p>
--ldx]]--
---~ function fonts.define.specify.colonized(specification) -- xetex mode
---~ local list = { }
---~ if specification.detail and specification.detail ~= "" then
---~ for v in gmatch(specification.detail,"%s*([^;]+)%s*") do
---~ local a, b = match(v,"^(%S*)%s*=%s*(%S*)$")
---~ if a and b then
---~ list[a] = b:is_boolean()
---~ if type(list[a]) == "nil" then
---~ list[a] = b
---~ end
---~ else
---~ local a, b = match(v,"^([%+%-]?)%s*(%S+)$")
---~ if a and b then
---~ list[b] = a ~= "-"
---~ end
---~ end
---~ end
---~ end
---~ specification.features.normal = list
---~ return specification
---~ end
-
---~ check("oeps/BI:+a;-b;c=d")
---~ check("[oeps]/BI:+a;-b;c=d")
---~ check("file:oeps/BI:+a;-b;c=d")
---~ check("name:oeps/BI:+a;-b;c=d")
+local fonts = fonts
+local definers = fonts.definers
+local specifiers = definers.specifiers
+local normalize_meanings = fonts.otf.meanings.normalize
local list = { }
@@ -157,11 +135,15 @@ local function parse_script(script)
end
end
-local function issome () list.lookup = fonts.define.specify.colonized_default_lookup end
+specifiers.colonizedpreference = "file"
+
+local function issome () list.lookup = specifiers.colonizedpreference end
local function isfile () list.lookup = 'file' end
local function isname () list.lookup = 'name' end
local function thename(s) list.name = s end
local function issub (v) list.sub = v end
+local function istrue (s) list[s] = true end
+local function isfalse(s) list[s] = false end
local function iskey (k,v)
if k == "script" then
parse_script(v)
@@ -169,28 +151,25 @@ local function iskey (k,v)
list[k] = v
end
-local function istrue (s) list[s] = true end
-local function isfalse(s) list[s] = false end
-
-local spaces = lpeg.P(" ")^0
-local namespec = (1-lpeg.S("/:("))^0 -- was: (1-lpeg.S("/: ("))^0
-local filespec = (lpeg.R("az", "AZ") * lpeg.P(":"))^-1 * (1-lpeg.S(":("))^1
-local crapspec = spaces * lpeg.P("/") * (((1-lpeg.P(":"))^0)/isstyle) * spaces
-local filename = (lpeg.P("file:")/isfile * (filespec/thename)) + (lpeg.P("[") * lpeg.P(true)/isfile * (((1-lpeg.P("]"))^0)/thename) * lpeg.P("]"))
-local fontname = (lpeg.P("name:")/isname * (namespec/thename)) + lpeg.P(true)/issome * (namespec/thename)
-local sometext = (lpeg.R("az","AZ","09") + lpeg.S("+-."))^1
-local truevalue = lpeg.P("+") * spaces * (sometext/istrue)
-local falsevalue = lpeg.P("-") * spaces * (sometext/isfalse)
-local keyvalue = lpeg.P("+") + (lpeg.C(sometext) * spaces * lpeg.P("=") * spaces * lpeg.C(sometext))/iskey
+local P, S, R, C = lpeg.P, lpeg.S, lpeg.R, lpeg.C
+
+local spaces = P(" ")^0
+local namespec = (1-S("/:("))^0 -- was: (1-S("/: ("))^0
+local filespec = (R("az", "AZ") * P(":"))^-1 * (1-S(":("))^1
+local stylespec = spaces * P("/") * (((1-P(":"))^0)/isstyle) * spaces
+local filename = (P("file:")/isfile * (filespec/thename)) + (P("[") * P(true)/isname * (((1-P("]"))^0)/thename) * P("]"))
+local fontname = (P("name:")/isname * (namespec/thename)) + P(true)/issome * (namespec/thename)
+local sometext = (R("az","AZ","09") + S("+-."))^1
+local truevalue = P("+") * spaces * (sometext/istrue)
+local falsevalue = P("-") * spaces * (sometext/isfalse)
+local keyvalue = P("+") + (C(sometext) * spaces * P("=") * spaces * C(sometext))/iskey
local somevalue = sometext/istrue
-local subvalue = lpeg.P("(") * (lpeg.C(lpeg.P(1-lpeg.S("()"))^1)/issub) * lpeg.P(")") -- for Kim
+local subvalue = P("(") * (C(P(1-S("()"))^1)/issub) * P(")") -- for Kim
local option = spaces * (keyvalue + falsevalue + truevalue + somevalue) * spaces
-local options = lpeg.P(":") * spaces * (lpeg.P(";")^0 * option)^0
-local pattern = (filename + fontname) * subvalue^0 * crapspec^0 * options^0
-
-local normalize_meanings = fonts.otf.meanings.normalize
+local options = P(":") * spaces * (P(";")^0 * option)^0
+local pattern = (filename + fontname) * subvalue^0 * stylespec^0 * options^0
-function fonts.define.specify.colonized(specification) -- xetex mode
+local function colonized(specification) -- xetex mode
list = { }
lpegmatch(pattern,specification.specification)
if list.style then
@@ -221,9 +200,9 @@ function fonts.define.specify.colonized(specification) -- xetex mode
specification.sub = list.sub
list.sub = nil
end
--- specification.features.normal = list
+ -- specification.features.normal = list
specification.features.normal = normalize_meanings(list)
return specification
end
-fonts.define.register_split(":", fonts.define.specify.colonized)
+definers.registersplit(":",colonized)
diff --git a/otfl-luat-dum.lua b/otfl-luat-dum.lua
index 9607697..675d2da 100644
--- a/otfl-luat-dum.lua
+++ b/otfl-luat-dum.lua
@@ -12,6 +12,7 @@ statistics = {
register = dummyfunction,
starttiming = dummyfunction,
stoptiming = dummyfunction,
+ elapsedtime = nil,
}
directives = {
register = dummyfunction,
@@ -28,23 +29,24 @@ experiments = {
enable = dummyfunction,
disable = dummyfunction,
}
-storage = {
+storage = { -- probably no longer needed
register = dummyfunction,
shared = { },
}
logs = {
+ new = function() return dummyfunction end,
report = dummyfunction,
simple = dummyfunction,
}
-tasks = {
- new = dummyfunction,
- actions = dummyfunction,
- appendaction = dummyfunction,
- prependaction = dummyfunction,
-}
callbacks = {
register = function(n,f) return callback.register(n,f) end,
}
+utilities = {
+ storage = {
+ allocate = function(t) return t or { } end,
+ mark = function(t) return t or { } end,
+ },
+}
-- we need to cheat a bit here
@@ -61,7 +63,7 @@ local remapper = {
fea = "font feature files",
}
-function resolvers.find_file(name,kind)
+function resolvers.findfile(name,kind)
name = string.gsub(name,"\\","\/")
kind = string.lower(kind)
return kpse.find_file(name,(kind and kind ~= "" and (remapper[kind] or kind)) or file.extname(name,"tex"))
@@ -71,7 +73,7 @@ function resolvers.findbinfile(name,kind)
if not kind or kind == "" then
kind = file.extname(name) -- string.match(name,"%.([^%.]-)$")
end
- return resolvers.find_file(name,(kind and remapper[kind]) or kind)
+ return resolvers.findfile(name,(kind and remapper[kind]) or kind)
end
-- Caches ... I will make a real stupid version some day when I'm in the
@@ -160,9 +162,9 @@ local function makefullname(path,name)
end
end
-function caches.iswritable(path,name)
+function caches.is_writable(path,name)
local fullname = makefullname(path,name)
- return fullname and file.iswritable(fullname)
+ return fullname and file.is_writable(fullname)
end
function caches.loaddata(paths,name)
diff --git a/otfl-node-dum.lua b/otfl-node-dum.lua
index 9483e51..b042047 100644
--- a/otfl-node-dum.lua
+++ b/otfl-node-dum.lua
@@ -10,12 +10,24 @@ nodes = nodes or { }
fonts = fonts or { }
attributes = attributes or { }
+nodes.pool = nodes.pool or { }
+nodes.handlers = nodes.handlers or { }
+
+local nodecodes = { } for k,v in next, node.types () do nodecodes[string.gsub(v,"_","")] = k end
+local whatcodes = { } for k,v in next, node.whatsits() do whatcodes[string.gsub(v,"_","")] = k end
+local glyphcodes = { [0] = "character", "glyph", "ligature", "ghost", "left", "right" }
+
+nodes.nodecodes = nodecodes
+nodes.whatcodes = whatcodes
+nodes.whatsitcodes = whatcodes
+nodes.glyphcodes = glyphcodes
+
local traverse_id = node.traverse_id
local free_node = node.free
local remove_node = node.remove
local new_node = node.new
-local glyph = node.id('glyph')
+local glyph_code = nodecodes.glyph
-- fonts
@@ -23,9 +35,9 @@ local fontdata = fonts.ids or { }
function nodes.simple_font_handler(head)
-- lang.hyphenate(head)
- head = nodes.process_characters(head)
- nodes.inject_kerns(head)
- nodes.protect_glyphs(head)
+ head = nodes.handlers.characters(head)
+ nodes.injections.handler(head)
+ nodes.handlers.protectglyphs(head)
head = node.ligaturing(head)
head = node.kerning(head)
return head
@@ -43,12 +55,12 @@ if tex.attribute[0] ~= 0 then
end
-nodes.protect_glyphs = node.protect_glyphs
-nodes.unprotect_glyphs = node.unprotect_glyphs
+nodes.handlers.protectglyphs = node.protect_glyphs
+nodes.handlers.unprotectglyphs = node.unprotect_glyphs
-function nodes.process_characters(head)
+function nodes.handlers.characters(head)
local usedfonts, done, prevfont = { }, false, nil
- for n in traverse_id(glyph,head) do
+ for n in traverse_id(glyph_code,head) do
local font = n.font
if font ~= prevfont then
prevfont = font
@@ -81,7 +93,7 @@ end
-- helper
-function nodes.kern(k)
+function nodes.pool.kern(k)
local n = new_node("kern",1)
n.kern = k
return n
diff --git a/otfl-node-inj.lua b/otfl-node-inj.lua
index fdea7f1..f576c7e 100644
--- a/otfl-node-inj.lua
+++ b/otfl-node-inj.lua
@@ -17,14 +17,22 @@ local next = next
local trace_injections = false trackers.register("nodes.injections", function(v) trace_injections = v end)
+local report_injections = logs.new("injections")
+
+local attributes, nodes, node = attributes, nodes, node
+
fonts = fonts or { }
fonts.tfm = fonts.tfm or { }
fonts.ids = fonts.ids or { }
-local fontdata = fonts.ids
+nodes.injections = nodes.injections or { }
+local injections = nodes.injections
-local glyph = node.id('glyph')
-local kern = node.id('kern')
+local fontdata = fonts.ids
+local nodecodes = nodes.nodecodes
+local glyph_code = nodecodes.glyph
+local nodepool = nodes.pool
+local newkern = nodepool.kern
local traverse_id = node.traverse_id
local unset_attribute = node.unset_attribute
@@ -33,8 +41,6 @@ local set_attribute = node.set_attribute
local insert_node_before = node.insert_before
local insert_node_after = node.insert_after
-local newkern = nodes.kern
-
local markbase = attributes.private('markbase')
local markmark = attributes.private('markmark')
local markdone = attributes.private('markdone')
@@ -54,7 +60,7 @@ local kerns = { }
-- for the moment we pass the r2l key ... volt/arabtype tests
-function nodes.set_cursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmnext)
+function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmnext)
local dx, dy = factor*(exit[1]-entry[1]), factor*(exit[2]-entry[2])
local ws, wn = tfmstart.width, tfmnext.width
local bound = #cursives + 1
@@ -64,7 +70,7 @@ function nodes.set_cursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmnext)
return dx, dy, bound
end
-function nodes.set_pair(current,factor,rlmode,r2lflag,spec,tfmchr)
+function injections.setpair(current,factor,rlmode,r2lflag,spec,tfmchr)
local x, y, w, h = factor*spec[1], factor*spec[2], factor*spec[3], factor*spec[4]
-- dy = y - h
if x ~= 0 or w ~= 0 or y ~= 0 or h ~= 0 then
@@ -83,7 +89,7 @@ function nodes.set_pair(current,factor,rlmode,r2lflag,spec,tfmchr)
return x, y, w, h -- no bound
end
-function nodes.set_kern(current,factor,rlmode,x,tfmchr)
+function injections.setkern(current,factor,rlmode,x,tfmchr)
local dx = factor*x
if dx ~= 0 then
local bound = #kerns + 1
@@ -95,7 +101,7 @@ function nodes.set_kern(current,factor,rlmode,x,tfmchr)
end
end
-function nodes.set_mark(start,base,factor,rlmode,ba,ma,index) --ba=baseanchor, ma=markanchor
+function injections.setmark(start,base,factor,rlmode,ba,ma,index) --ba=baseanchor, ma=markanchor
local dx, dy = factor*(ba[1]-ma[1]), factor*(ba[2]-ma[2])
local bound = has_attribute(base,markbase)
if bound then
@@ -107,7 +113,7 @@ function nodes.set_mark(start,base,factor,rlmode,ba,ma,index) --ba=baseanchor, m
set_attribute(start,markdone,index)
return dx, dy, bound
else
- logs.report("nodes mark", "possible problem, U+%04X is base without data (id: %s)",base.char,bound)
+ report_injections("possible problem, U+%04X is base mark without data (id: %s)",base.char,bound)
end
end
index = index or 1
@@ -119,15 +125,13 @@ function nodes.set_mark(start,base,factor,rlmode,ba,ma,index) --ba=baseanchor, m
return dx, dy, bound
end
-function nodes.trace_injection(head)
- local function dir(n)
- return (n and n<0 and "r-to-l") or (n and n>0 and "l-to-r") or ("unset")
- end
- local function report(...)
- logs.report("nodes finisher",...)
- end
- report("begin run")
- for n in traverse_id(glyph,head) do
+local function dir(n)
+ return (n and n<0 and "r-to-l") or (n and n>0 and "l-to-r") or "unset"
+end
+
+local function trace(head)
+ report_injections("begin run")
+ for n in traverse_id(glyph_code,head) do
if n.subtype < 256 then
local kp = has_attribute(n,kernpair)
local mb = has_attribute(n,markbase)
@@ -135,59 +139,59 @@ function nodes.trace_injection(head)
local md = has_attribute(n,markdone)
local cb = has_attribute(n,cursbase)
local cc = has_attribute(n,curscurs)
- report("char U+%05X, font=%s",n.char,n.font)
+ report_injections("char U+%05X, font=%s",n.char,n.font)
if kp then
local k = kerns[kp]
if k[3] then
- report(" pairkern: dir=%s, x=%s, y=%s, w=%s, h=%s",dir(k[1]),k[2] or "?",k[3] or "?",k[4] or "?",k[5] or "?")
+ report_injections(" pairkern: dir=%s, x=%s, y=%s, w=%s, h=%s",dir(k[1]),k[2] or "?",k[3] or "?",k[4] or "?",k[5] or "?")
else
- report(" kern: dir=%s, dx=%s",dir(k[1]),k[2] or "?")
+ report_injections(" kern: dir=%s, dx=%s",dir(k[1]),k[2] or "?")
end
end
if mb then
- report(" markbase: bound=%s",mb)
+ report_injections(" markbase: bound=%s",mb)
end
if mm then
local m = marks[mm]
if mb then
local m = m[mb]
if m then
- report(" markmark: bound=%s, index=%s, dx=%s, dy=%s",mm,md or "?",m[1] or "?",m[2] or "?")
+ report_injections(" markmark: bound=%s, index=%s, dx=%s, dy=%s",mm,md or "?",m[1] or "?",m[2] or "?")
else
- report(" markmark: bound=%s, missing index",mm)
+ report_injections(" markmark: bound=%s, missing index",mm)
end
else
m = m[1]
- report(" markmark: bound=%s, dx=%s, dy=%s",mm,m[1] or "?",m[2] or "?")
+ report_injections(" markmark: bound=%s, dx=%s, dy=%s",mm,m[1] or "?",m[2] or "?")
end
end
if cb then
- report(" cursbase: bound=%s",cb)
+ report_injections(" cursbase: bound=%s",cb)
end
if cc then
local c = cursives[cc]
- report(" curscurs: bound=%s, dir=%s, dx=%s, dy=%s",cc,dir(c[1]),c[2] or "?",c[3] or "?")
+ report_injections(" curscurs: bound=%s, dir=%s, dx=%s, dy=%s",cc,dir(c[1]),c[2] or "?",c[3] or "?")
end
end
end
- report("end run")
+ report_injections("end run")
end
-- todo: reuse tables (i.e. no collection), but will be extra fields anyway
-- todo: check for attribute
-function nodes.inject_kerns(head,where,keep)
+function injections.handler(head,where,keep)
local has_marks, has_cursives, has_kerns = next(marks), next(cursives), next(kerns)
if has_marks or has_cursives then
--~ if has_marks or has_cursives or has_kerns then
if trace_injections then
- nodes.trace_injection(head)
+ trace(head)
end
-- in the future variant we will not copy items but refs to tables
local done, ky, rl, valid, cx, wx, mk = false, { }, { }, { }, { }, { }, { }
if has_kerns then -- move outside loop
local nf, tm = nil, nil
- for n in traverse_id(glyph,head) do
+ for n in traverse_id(glyph_code,head) do
if n.subtype < 256 then
valid[#valid+1] = n
if n.font ~= nf then
@@ -215,7 +219,7 @@ function nodes.inject_kerns(head,where,keep)
end
else
local nf, tm = nil, nil
- for n in traverse_id(glyph,head) do
+ for n in traverse_id(glyph_code,head) do
if n.subtype < 256 then
valid[#valid+1] = n
if n.font ~= nf then
@@ -308,7 +312,7 @@ function nodes.inject_kerns(head,where,keep)
local p_markbase = has_attribute(p,markbase)
if p_markbase then
local mrks = marks[p_markbase]
- for n in traverse_id(glyph,p.next) do
+ for n in traverse_id(glyph_code,p.next) do
local n_markmark = has_attribute(n,markmark)
if p_markbase == n_markmark then
local index = has_attribute(n,markdone) or 1
@@ -391,9 +395,9 @@ function nodes.inject_kerns(head,where,keep)
end
elseif has_kerns then
if trace_injections then
- nodes.trace_injection(head)
+ trace(head)
end
- for n in traverse_id(glyph,head) do
+ for n in traverse_id(glyph_code,head) do
if n.subtype < 256 then
local k = has_attribute(n,kernpair)
if k then