summaryrefslogtreecommitdiff
path: root/src/fontloader/misc
diff options
context:
space:
mode:
authorPhilipp Gesang <phg@phi-gamma.net>2016-07-30 12:26:59 +0200
committerGitHub <noreply@github.com>2016-07-30 12:26:59 +0200
commit9e2db3ead715ceecf2afc879aefc020f84ea4f09 (patch)
tree89960031e5cf796661e7a6f10bdf9d32f36c01dd /src/fontloader/misc
parent2fcdccf7edfa1cfb0f03fe8f2163c7c5d8281984 (diff)
parentc0597dba961fb9f99c2bd5d2d7f442dc37382dc2 (diff)
downloadluaotfload-9e2db3ead715ceecf2afc879aefc020f84ea4f09.tar.gz
Merge pull request #374 from phi-gamma/master
lastest feature code
Diffstat (limited to 'src/fontloader/misc')
-rw-r--r--src/fontloader/misc/fontloader-font-con.lua358
-rw-r--r--src/fontloader/misc/fontloader-font-one.lua110
-rw-r--r--src/fontloader/misc/fontloader-font-otl.lua180
-rw-r--r--src/fontloader/misc/fontloader-font-ots.lua158
-rw-r--r--src/fontloader/misc/fontloader-font-tfm.lua44
5 files changed, 455 insertions, 395 deletions
diff --git a/src/fontloader/misc/fontloader-font-con.lua b/src/fontloader/misc/fontloader-font-con.lua
index 9a6f3f8..931e4e7 100644
--- a/src/fontloader/misc/fontloader-font-con.lua
+++ b/src/fontloader/misc/fontloader-font-con.lua
@@ -12,9 +12,10 @@ local next, tostring, rawget = next, tostring, rawget
local format, match, lower, gsub, find = string.format, string.match, string.lower, string.gsub, string.find
local sort, insert, concat, sortedkeys, serialize, fastcopy = table.sort, table.insert, table.concat, table.sortedkeys, table.serialize, table.fastcopy
local derivetable = table.derive
+local ioflush = io.flush
-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 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_defining = logs.reporter("fonts","defining")
@@ -1086,146 +1087,269 @@ setmetatableindex(formats, function(t,k)
return rawget(t,file.suffix(l))
end)
-local locations = { }
+do
-local function setindeed(mode,target,group,name,action,position)
- local t = target[mode]
- if not t then
- report_defining("fatal error in setting feature %a, group %a, mode %a",name,group,mode)
- os.exit()
- elseif position then
- -- todo: remove existing
- insert(t, position, { name = name, action = action })
- else
- for i=1,#t do
- local ti = t[i]
- if ti.name == name then
- ti.action = action
- return
+ local function setindeed(mode,target,group,name,action,position)
+ local t = target[mode]
+ if not t then
+ report_defining("fatal error in setting feature %a, group %a, mode %a",name,group,mode)
+ os.exit()
+ elseif position then
+ -- todo: remove existing
+ insert(t, position, { name = name, action = action })
+ else
+ for i=1,#t do
+ local ti = t[i]
+ if ti.name == name then
+ ti.action = action
+ return
+ end
end
+ insert(t, { name = name, action = action })
end
- insert(t, { name = name, action = action })
- end
-end
-
-local function set(group,name,target,source)
- target = target[group]
- if not target then
- report_defining("fatal target error in setting feature %a, group %a",name,group)
- os.exit()
- end
- local source = source[group]
- if not source then
- report_defining("fatal source error in setting feature %a, group %a",name,group)
- os.exit()
- end
- local node = source.node
- local base = source.base
- local position = source.position
- if node then
- setindeed("node",target,group,name,node,position)
end
- if base then
- setindeed("base",target,group,name,base,position)
- end
-end
-local function register(where,specification)
- local name = specification.name
- if name and name ~= "" then
- local default = specification.default
- local description = specification.description
- local initializers = specification.initializers
- local processors = specification.processors
- local manipulators = specification.manipulators
- local modechecker = specification.modechecker
- if default then
- where.defaults[name] = default
+ local function set(group,name,target,source)
+ target = target[group]
+ if not target then
+ report_defining("fatal target error in setting feature %a, group %a",name,group)
+ os.exit()
end
- if description and description ~= "" then
- where.descriptions[name] = description
+ local source = source[group]
+ if not source then
+ report_defining("fatal source error in setting feature %a, group %a",name,group)
+ os.exit()
end
- if initializers then
- set('initializers',name,where,specification)
+ local node = source.node
+ local base = source.base
+ local position = source.position
+ if node then
+ setindeed("node",target,group,name,node,position)
end
- if processors then
- set('processors', name,where,specification)
- end
- if manipulators then
- set('manipulators',name,where,specification)
+ if base then
+ setindeed("base",target,group,name,base,position)
end
- if modechecker then
- where.modechecker = modechecker
+ end
+
+ local function register(where,specification)
+ local name = specification.name
+ if name and name ~= "" then
+ local default = specification.default
+ local description = specification.description
+ local initializers = specification.initializers
+ local processors = specification.processors
+ local manipulators = specification.manipulators
+ local modechecker = specification.modechecker
+ if default then
+ where.defaults[name] = default
+ end
+ if description and description ~= "" then
+ where.descriptions[name] = description
+ end
+ if initializers then
+ set('initializers',name,where,specification)
+ end
+ if processors then
+ set('processors', name,where,specification)
+ end
+ if manipulators then
+ set('manipulators',name,where,specification)
+ end
+ if modechecker then
+ where.modechecker = modechecker
+ end
end
end
-end
-constructors.registerfeature = register
-
-function constructors.getfeatureaction(what,where,mode,name)
- what = handlers[what].features
- if what then
- where = what[where]
- if where then
- mode = where[mode]
- if mode then
- for i=1,#mode do
- local m = mode[i]
- if m.name == name then
- return m.action
+ constructors.registerfeature = register
+
+ function constructors.getfeatureaction(what,where,mode,name)
+ what = handlers[what].features
+ if what then
+ where = what[where]
+ if where then
+ mode = where[mode]
+ if mode then
+ for i=1,#mode do
+ local m = mode[i]
+ if m.name == name then
+ return m.action
+ end
end
end
end
end
end
+
+ local newfeatures = { }
+ constructors.newfeatures = newfeatures -- downward compatible
+ constructors.features = newfeatures
+
+ local function setnewfeatures(what)
+ local handler = handlers[what]
+ local features = handler.features
+ if not features then
+ local tables = handler.tables -- can be preloaded
+ local statistics = handler.statistics -- can be preloaded
+ features = allocate {
+ defaults = { },
+ descriptions = tables and tables.features or { },
+ used = statistics and statistics.usedfeatures or { },
+ initializers = { base = { }, node = { } },
+ processors = { base = { }, node = { } },
+ manipulators = { base = { }, node = { } },
+ }
+ features.register = function(specification) return register(features,specification) end
+ handler.features = features -- will also become hidden
+ end
+ return features
+ end
+
+ setmetatable(newfeatures, {
+ __call = function(t,k) local v = t[k] return v end,
+ __index = function(t,k) local v = setnewfeatures(k) t[k] = v return v end,
+ })
+
end
-local newhandler = { }
-constructors.handlers = newhandler -- downward compatible
-constructors.newhandler = newhandler
+do
-local function setnewhandler(what) -- could be a metatable newindex
- local handler = handlers[what]
- if not handler then
- handler = { }
- handlers[what] = handler
+ local newhandler = { }
+ constructors.handlers = newhandler -- downward compatible
+ constructors.newhandler = newhandler
+
+ local function setnewhandler(what) -- could be a metatable newindex
+ local handler = handlers[what]
+ if not handler then
+ handler = { }
+ handlers[what] = handler
+ end
+ return handler
end
- return handler
+
+ setmetatable(newhandler, {
+ __call = function(t,k) local v = t[k] return v end,
+ __index = function(t,k) local v = setnewhandler(k) t[k] = v return v end,
+ })
+
end
-setmetatable(newhandler, {
- __call = function(t,k) local v = t[k] return v end,
- __index = function(t,k) local v = setnewhandler(k) t[k] = v return v end,
-})
-
-local newfeatures = { }
-constructors.newfeatures = newfeatures -- downward compatible
-constructors.features = newfeatures
-
-local function setnewfeatures(what)
- local handler = handlers[what]
- local features = handler.features
- if not features then
- local tables = handler.tables -- can be preloaded
- local statistics = handler.statistics -- can be preloaded
- features = allocate {
- defaults = { },
- descriptions = tables and tables.features or { },
- used = statistics and statistics.usedfeatures or { },
- initializers = { base = { }, node = { } },
- processors = { base = { }, node = { } },
- manipulators = { base = { }, node = { } },
- }
- features.register = function(specification) return register(features,specification) end
- handler.features = features -- will also become hidden
+do
+ -- a pitty that we need to be generic as we have nicer mechanisms for this ...
+
+ local newenhancer = { }
+ constructors.enhancers = newenhancer
+ constructors.newenhancer = newenhancer
+
+ local function setnewenhancer(format)
+
+ local handler = handlers[format]
+ local enhancers = handler.enhancers
+
+ if not enhancers then
+
+ local actions = allocate()
+ local before = allocate()
+ local after = allocate()
+ local order = allocate()
+ local patches = { before = before, after = after }
+
+ local trace = false
+ local report = logs.reporter("fonts",format .. " enhancing")
+
+ trackers.register(format .. ".loading", function(v) trace = v end)
+
+ local function enhance(name,data,filename,raw)
+ local enhancer = actions[name]
+ if enhancer then
+ if trace then
+ report("apply enhancement %a to file %a",name,filename)
+ ioflush()
+ end
+ enhancer(data,filename,raw)
+ else
+ -- no message as we can have private ones
+ end
+ end
+
+ local function apply(data,filename,raw)
+ local basename = file.basename(lower(filename))
+ if trace then
+ report("%s enhancing file %a","start",filename)
+ end
+ ioflush() -- we want instant messages
+ for e=1,#order do
+ local enhancer = order[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)
+ 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
+ ioflush() -- we want instant messages
+ end
+ if trace then
+ report("%s enhancing file %a","stop",filename)
+ end
+ ioflush() -- we want instant messages
+ end
+
+ local function register(what,action)
+ if action then
+ if actions[what] then
+ -- overloading, e.g."check extra features"
+ else
+ order[#order+1] = what
+ end
+ actions[what] = action
+ else
+ report("bad enhancer %a",what)
+ end
+ end
+
+ -- fonts.constructors.otf.enhancers.patch("before","migrate metadata","cambria",function() end)
+
+ local function patch(what,where,pattern,action)
+ local pw = patches[what]
+ if pw then
+ local ww = pw[where]
+ if ww then
+ ww[pattern] = action
+ else
+ pw[where] = { [pattern] = action}
+ end
+ end
+ end
+
+ enhancers = {
+ register = register,
+ apply = apply,
+ patch = patch,
+ patches = { register = patch }, -- for old times sake
+ }
+
+ handler.enhancers = enhancers
+ end
+ return enhancers
end
- return features
-end
-setmetatable(newfeatures, {
- __call = function(t,k) local v = t[k] return v end,
- __index = function(t,k) local v = setnewfeatures(k) t[k] = v return v end,
-})
+ setmetatable(newenhancer, {
+ __call = function(t,k) local v = t[k] return v end,
+ __index = function(t,k) local v = setnewenhancer(k) t[k] = v return v end,
+ })
+
+end
--[[ldx--
<p>We need to check for default features. For this we provide
diff --git a/src/fontloader/misc/fontloader-font-one.lua b/src/fontloader/misc/fontloader-font-one.lua
index 8629850..d9b9c65 100644
--- a/src/fontloader/misc/fontloader-font-one.lua
+++ b/src/fontloader/misc/fontloader-font-one.lua
@@ -29,42 +29,45 @@ local bxor, rshift = bit32.bxor, bit32.rshift
local P, S, R, Cmt, C, Ct, Cs, Carg = lpeg.P, lpeg.S, lpeg.R, lpeg.Cmt, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local lpegmatch, patterns = lpeg.match, lpeg.patterns
-local trace_features = false trackers.register("afm.features", function(v) trace_features = v end)
-local trace_indexing = false trackers.register("afm.indexing", function(v) trace_indexing = v end)
-local trace_loading = false trackers.register("afm.loading", function(v) trace_loading = v end)
-local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
+local trace_features = false trackers.register("afm.features", function(v) trace_features = v end)
+local trace_indexing = false trackers.register("afm.indexing", function(v) trace_indexing = v end)
+local trace_loading = false trackers.register("afm.loading", function(v) trace_loading = v end)
+local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
-local report_afm = logs.reporter("fonts","afm loading")
+local report_afm = logs.reporter("fonts","afm loading")
-local setmetatableindex = table.setmetatableindex
-local derivetable = table.derive
+local setmetatableindex = table.setmetatableindex
+local derivetable = table.derive
-local findbinfile = resolvers.findbinfile
+local findbinfile = resolvers.findbinfile
-local definers = fonts.definers
-local readers = fonts.readers
-local constructors = fonts.constructors
+local definers = fonts.definers
+local readers = fonts.readers
+local constructors = fonts.constructors
-local afm = constructors.handlers.afm
-local pfb = constructors.handlers.pfb
-local otf = fonts.handlers.otf
+local afm = constructors.handlers.afm
+local pfb = constructors.handlers.pfb
+local otf = fonts.handlers.otf
-local otfreaders = otf.readers
-local otfenhancers = otf.enhancers
+local otfreaders = otf.readers
+local otfenhancers = otf.enhancers
-local afmfeatures = constructors.features.afm
-local registerafmfeature = afmfeatures.register
+local afmfeatures = constructors.features.afm
+local registerafmfeature = afmfeatures.register
-afm.version = 1.512 -- incrementing this number one up will force a re-cache
-afm.cache = containers.define("fonts", "afm", afm.version, true)
-afm.autoprefixed = true -- this will become false some day (catches texnansi-blabla.*)
+local afmenhancers = constructors.enhancers.afm
+local registerafmenhancer = afmenhancers.register
-afm.helpdata = { } -- set later on so no local for this
-afm.syncspace = true -- when true, nicer stretch values
+afm.version = 1.512 -- incrementing this number one up will force a re-cache
+afm.cache = containers.define("fonts", "one", afm.version, true)
+afm.autoprefixed = true -- this will become false some day (catches texnansi-blabla.*)
-local overloads = fonts.mappings.overloads
+afm.helpdata = { } -- set later on so no local for this
+afm.syncspace = true -- when true, nicer stretch values
-local applyruntimefixes = fonts.treatments and fonts.treatments.applyfixes
+local overloads = fonts.mappings.overloads
+
+local applyruntimefixes = fonts.treatments and fonts.treatments.applyfixes
--[[ldx--
<p>We cache files. Caching is taken care of in the loader. We cheat a bit by adding
@@ -76,36 +79,6 @@ fashion and later we transform it to sequences. Then we apply some methods also
used in opentype fonts (like <t>tlig</t>).</p>
--ldx]]--
-local enhancers = {
- -- It's cleaner to implement them after we've seen what we are
- -- dealing with.
-}
-
-local steps = {
- "unify names",
- "add ligatures",
- "add extra kerns",
- "normalize features",
- "check extra features",
- "fix names", -- what a hack ...
--- "add tounicode data",
-}
-
-local function applyenhancers(data,filename)
- for i=1,#steps do
- local step = steps[i]
- local enhancer = enhancers[step]
- if enhancer then
- if trace_loading then
- report_afm("applying enhancer %a",step)
- end
- enhancer(data,filename)
- else
- report_afm("invalid enhancer %a",step)
- end
- end
-end
-
function afm.load(filename)
filename = resolvers.findfile(filename,'afm') or ""
if filename ~= "" and not fonts.names.ignoredfile(filename) then
@@ -129,7 +102,7 @@ function afm.load(filename)
report_afm("reading %a",filename)
data = afm.readers.loadfont(filename,pfbname)
if data then
- applyenhancers(data,filename)
+ afmenhancers.apply(data,filename)
-- otfreaders.addunicodetable(data) -- only when not done yet
fonts.mappings.addtounicode(data,filename)
-- otfreaders.extend(data)
@@ -162,7 +135,7 @@ end
local uparser = fonts.mappings.makenameparser() -- each time
-enhancers["unify names"] = function(data, filename)
+local function enhance_unify_names(data, filename)
local unicodevector = fonts.encodings.agl.unicodes -- loaded runtime in context
local unicodes = { }
local names = { }
@@ -218,7 +191,7 @@ end
local everywhere = { ["*"] = { ["*"] = true } } -- or: { ["*"] = { "*" } }
local noflags = { false, false, false, false }
-enhancers["normalize features"] = function(data)
+local function enhance_normalize_features(data)
local ligatures = setmetatableindex("table")
local kerns = setmetatableindex("table")
local extrakerns = setmetatableindex("table")
@@ -319,9 +292,7 @@ enhancers["normalize features"] = function(data)
data.resources.sequences = sequences
end
-enhancers["check extra features"] = otf.enhancers.enhance
-
-enhancers["fix names"] = function(data)
+local function enhance_fix_names(data)
for k, v in next, data.descriptions do
local n = v.name
local r = overloads[n]
@@ -368,14 +339,10 @@ local addthem = function(rawdata,ligatures)
end
end
-enhancers["add ligatures"] = function(rawdata)
+local function enhance_add_ligatures(rawdata)
addthem(rawdata,afm.helpdata.ligatures)
end
--- enhancers["add tex ligatures"] = function(rawdata)
--- addthem(rawdata,afm.helpdata.texligatures)
--- end
-
--[[ldx--
<p>We keep the extra kerns in separate kerning tables so that we can use
them selectively.</p>
@@ -388,7 +355,7 @@ them selectively.</p>
-- we don't use the character database. (Ok, we can have a context specific
-- variant).
-enhancers["add extra kerns"] = function(rawdata) -- using shcodes is not robust here
+local function enhance_add_extra_kerns(rawdata) -- using shcodes is not robust here
local descriptions = rawdata.descriptions
local resources = rawdata.resources
local unicodes = resources.unicodes
@@ -851,3 +818,12 @@ function readers.pfb(specification,method) -- only called when forced
swap("specification")
return readers.afm(specification,method)
end
+
+-- now we register them
+
+registerafmenhancer("unify names", enhance_unify_names)
+registerafmenhancer("add ligatures", enhance_add_ligatures)
+registerafmenhancer("add extra kerns", enhance_add_extra_kerns)
+registerafmenhancer("normalize features", enhance_normalize_features)
+registerafmenhancer("check extra features", otfenhancers.enhance)
+registerafmenhancer("fix names", enhance_fix_names)
diff --git a/src/fontloader/misc/fontloader-font-otl.lua b/src/fontloader/misc/fontloader-font-otl.lua
index bdce80d..94f6a45 100644
--- a/src/fontloader/misc/fontloader-font-otl.lua
+++ b/src/fontloader/misc/fontloader-font-otl.lua
@@ -26,70 +26,67 @@ if not modules then modules = { } end modules ['font-otl'] = {
local gmatch, find, match, lower, strip = string.gmatch, string.find, string.match, string.lower, string.strip
local type, next, tonumber, tostring, unpack = type, next, tonumber, tostring, unpack
local abs = math.abs
-local ioflush = io.flush
local derivetable = table.derive
local formatters = string.formatters
-local setmetatableindex = table.setmetatableindex
-local allocate = utilities.storage.allocate
-local registertracker = trackers.register
-local registerdirective = directives.register
-local starttiming = statistics.starttiming
-local stoptiming = statistics.stoptiming
-local elapsedtime = statistics.elapsedtime
-local findbinfile = resolvers.findbinfile
+local setmetatableindex = table.setmetatableindex
+local allocate = utilities.storage.allocate
+local registertracker = trackers.register
+local registerdirective = directives.register
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+local elapsedtime = statistics.elapsedtime
+local findbinfile = resolvers.findbinfile
------ trace_private = false registertracker("otf.private", function(v) trace_private = v end)
------ trace_subfonts = false registertracker("otf.subfonts", function(v) trace_subfonts = v end)
-local trace_loading = false registertracker("otf.loading", function(v) trace_loading = v end)
-local trace_features = false registertracker("otf.features", function(v) trace_features = v end)
------ trace_dynamics = false registertracker("otf.dynamics", function(v) trace_dynamics = v end)
------ trace_sequences = false registertracker("otf.sequences", function(v) trace_sequences = v end)
------ trace_markwidth = false registertracker("otf.markwidth", function(v) trace_markwidth = v end)
-local trace_defining = false registertracker("fonts.defining", function(v) trace_defining = v end)
+----- trace_private = false registertracker("otf.private", function(v) trace_private = v end)
+----- trace_subfonts = false registertracker("otf.subfonts", function(v) trace_subfonts = v end)
+local trace_loading = false registertracker("otf.loading", function(v) trace_loading = v end)
+local trace_features = false registertracker("otf.features", function(v) trace_features = v end)
+----- trace_dynamics = false registertracker("otf.dynamics", function(v) trace_dynamics = v end)
+----- trace_sequences = false registertracker("otf.sequences", function(v) trace_sequences = v end)
+----- trace_markwidth = false registertracker("otf.markwidth", function(v) trace_markwidth = v end)
+local trace_defining = false registertracker("fonts.defining", function(v) trace_defining = v end)
-local report_otf = logs.reporter("fonts","otf loading")
+local report_otf = logs.reporter("fonts","otf loading")
-local fonts = fonts
-local otf = fonts.handlers.otf
+local fonts = fonts
+local otf = fonts.handlers.otf
-otf.version = 3.025 -- beware: also sync font-mis.lua and in mtx-fonts
-otf.cache = containers.define("fonts", "otl", otf.version, true)
-otf.svgcache = containers.define("fonts", "svg", otf.version, true)
-otf.pdfcache = containers.define("fonts", "pdf", otf.version, true)
+otf.version = 3.025 -- beware: also sync font-mis.lua and in mtx-fonts
+otf.cache = containers.define("fonts", "otl", otf.version, true)
+otf.svgcache = containers.define("fonts", "svg", otf.version, true)
+otf.pdfcache = containers.define("fonts", "pdf", otf.version, true)
-otf.svgenabled = false
+otf.svgenabled = false
-local otfreaders = otf.readers
+local otfreaders = otf.readers
-local hashes = fonts.hashes
-local definers = fonts.definers
-local readers = fonts.readers
-local constructors = fonts.constructors
+local hashes = fonts.hashes
+local definers = fonts.definers
+local readers = fonts.readers
+local constructors = fonts.constructors
-local otffeatures = constructors.features.otf
-local registerotffeature = otffeatures.register
+local otffeatures = constructors.features.otf
+local registerotffeature = otffeatures.register
-local enhancers = allocate()
-otf.enhancers = enhancers
-local patches = { }
-enhancers.patches = patches
+local otfenhancers = constructors.enhancers.otf
+local registerotfenhancer = otfenhancers.register
-local forceload = false
-local cleanup = 0 -- mk: 0=885M 1=765M 2=735M (regular run 730M)
-local syncspace = true
-local forcenotdef = false
+local forceload = false
+local cleanup = 0 -- mk: 0=885M 1=765M 2=735M (regular run 730M)
+local syncspace = true
+local forcenotdef = false
-local applyruntimefixes = fonts.treatments and fonts.treatments.applyfixes
+local applyruntimefixes = fonts.treatments and fonts.treatments.applyfixes
-local wildcard = "*"
-local default = "dflt"
+local wildcard = "*"
+local default = "dflt"
-local formats = fonts.formats
+local formats = fonts.formats
-formats.otf = "opentype"
-formats.ttf = "truetype"
-formats.ttc = "truetype"
+formats.otf = "opentype"
+formats.ttf = "truetype"
+formats.ttc = "truetype"
registerdirective("fonts.otf.loader.cleanup", function(v) cleanup = tonumber(v) or (v and 1) or 0 end)
registerdirective("fonts.otf.loader.force", function(v) forceload = v end)
@@ -105,92 +102,9 @@ registerdirective("fonts.otf.loader.forcenotdef", function(v) forcenotdef =
-- end
-- end
--- Enhancers are used to apply fixes and extensions to fonts. For instance, we use them
--- to implement tlig and trep features. They are not neccessarily bound to opentype
--- fonts but can also apply to type one fonts, given that they obey the structure of an
--- opentype font. They are not to be confused with format specific features but maybe
--- some are so generic that they might eventually move to this mechanism.
+-- otfenhancers.patch("before","migrate metadata","cambria",function() end)
-local ordered_enhancers = {
- "check extra features",
-}
-
-local actions = allocate()
-local before = allocate()
-local after = allocate()
-
-patches.before = before
-patches.after = after
-
-local function enhance(name,data,filename,raw)
- local enhancer = actions[name]
- if enhancer then
- if trace_loading then
- report_otf("apply enhancement %a to file %a",name,filename)
- ioflush()
- end
- enhancer(data,filename,raw)
- else
- -- no message as we can have private ones
- end
-end
-
-function enhancers.apply(data,filename,raw)
- local basename = file.basename(lower(filename))
- if trace_loading then
- report_otf("%s enhancing file %a","start",filename)
- end
- 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)
- 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
- ioflush() -- we want instant messages
- end
- if trace_loading then
- report_otf("%s enhancing file %a","stop",filename)
- end
- ioflush() -- we want instant messages
-end
-
--- patches.register("before","migrate metadata","cambria",function() end)
-
-function patches.register(what,where,pattern,action)
- local pw = patches[what]
- if pw then
- local ww = pw[where]
- if ww then
- ww[pattern] = action
- else
- pw[where] = { [pattern] = action}
- end
- end
-end
-
-function patches.report(fmt,...)
- if trace_loading then
- report_otf("patching: %s",formatters[fmt](...))
- end
-end
-
-function enhancers.register(what,action) -- only already registered can be overloaded
- actions[what] = action
-end
+registerotfenhancer("check extra features", function() end) -- placeholder
function otf.load(filename,sub,featurefile) -- second argument (format) is gone !
--
@@ -329,7 +243,7 @@ function otf.load(filename,sub,featurefile) -- second argument (format) is gone
otfreaders.expand(data) -- inline tables
otfreaders.addunicodetable(data) -- only when not done yet
--
- enhancers.apply(data,filename,data)
+ otfenhancers.apply(data,filename,data)
--
-- constructors.addcoreunicodes(data.resources.unicodes) -- still needed ?
--
diff --git a/src/fontloader/misc/fontloader-font-ots.lua b/src/fontloader/misc/fontloader-font-ots.lua
index 10f0518..d371156 100644
--- a/src/fontloader/misc/fontloader-font-ots.lua
+++ b/src/fontloader/misc/fontloader-font-ots.lua
@@ -275,6 +275,13 @@ local checkstep = (nodes and nodes.tracers and nodes.tracers.steppers.chec
local registerstep = (nodes and nodes.tracers and nodes.tracers.steppers.register) or function() end
local registermessage = (nodes and nodes.tracers and nodes.tracers.steppers.message) or function() end
+local function checkdisccontent(d)
+ local pre, post, replace = getdisc(d)
+ if pre then for n in traverse_id(glue_code,pre) do print("pre",nodes.idstostring(pre)) break end end
+ if post then for n in traverse_id(glue_code,post) do print("pos",nodes.idstostring(post)) break end end
+ if replace then for n in traverse_id(glue_code,replace) do print("rep",nodes.idstostring(replace)) break end end
+end
+
local function logprocess(...)
if trace_steps then
registermessage(...)
@@ -351,7 +358,7 @@ end
local function copy_glyph(g) -- next and prev are untouched !
local components = getfield(g,"components")
if components then
- setfield(g,"components",nil)
+ setfield(g,"components")
local n = copy_node(g)
copyinjection(n,g) -- we need to preserve the lig indices
setfield(g,"components",components)
@@ -364,11 +371,18 @@ local function copy_glyph(g) -- next and prev are untouched !
end
local function flattendisk(head,disc)
- local _, _, replace, _, _, replacetail = getdisc(disc,true)
- setfield(disc,"replace",nil)
+ local pre, post, replace, pretail, posttail, replacetail = getdisc(disc,true)
+ local prev, next = getboth(disc)
+ local ishead = head == disc
+ setdisc(disc)
flush_node(disc)
- if head == disc then
- local next = getnext(disc)
+ if pre then
+ flush_node_list(pre)
+ end
+ if post then
+ flush_node_list(post)
+ end
+ if ishead then
if replace then
if next then
setlink(replacetail,next)
@@ -380,7 +394,6 @@ local function flattendisk(head,disc)
return -- maybe warning
end
else
- local prev, next = getboth(disc)
if replace then
if next then
setlink(replacetail,next)
@@ -419,8 +432,8 @@ local function markstoligature(head,start,stop,char)
else
local prev = getprev(start)
local next = getnext(stop)
- setprev(start,nil)
- setnext(stop,nil)
+ setprev(start)
+ setnext(stop)
local base = copy_glyph(start)
if head == start then
head = base
@@ -482,8 +495,8 @@ local function toligature(head,start,stop,char,dataset,sequence,markflag,discfou
local prev = getprev(start)
local next = getnext(stop)
local comp = start
- setprev(start,nil)
- setnext(stop,nil)
+ setprev(start)
+ setnext(stop)
local base = copy_glyph(start)
if start == head then
head = base
@@ -553,38 +566,37 @@ local function toligature(head,start,stop,char,dataset,sequence,markflag,discfou
-- anyway
local pre, post, replace, pretail, posttail, replacetail = getdisc(discfound,true)
if not replace then -- todo: signal simple hyphen
- local prev = getprev(base)
--- local copied = copy_node_list(comp)
-local current = comp
-local previous = nil
-local copied = nil
-while current do
- if getid(current) == glyph_code then
- local n = copy_node(current)
- if copied then
- setlink(previous,n)
- else
- copied = n
- end
- previous = n
- end
- current = getnext(current)
-end
- setprev(discnext,nil) -- also blocks funny assignments
- setnext(discprev,nil) -- also blocks funny assignments
+ local prev = getprev(base)
+ local current = comp
+ local previous = nil
+ local copied = nil
+ while current do
+ if getid(current) == glyph_code then
+ local n = copy_node(current)
+ if copied then
+ setlink(previous,n)
+ else
+ copied = n
+ end
+ previous = n
+ end
+ current = getnext(current)
+ end
+ setprev(discnext) -- also blocks funny assignments
+ setnext(discprev) -- also blocks funny assignments
if pre then
setlink(discprev,pre)
end
pre = comp
if post then
setlink(posttail,discnext)
- setprev(post,nil)
+ setprev(post)
else
post = discnext
end
setlink(prev,discfound)
setlink(discfound,next)
- setboth(base,nil,nil)
+ setboth(base)
setfield(base,"components",copied)
setdisc(discfound,pre,post,base,discretionary_code)
base = prev -- restart
@@ -1751,6 +1763,42 @@ end
-- order to handle that we need more complex code which also slows down even more. The main
-- loop variant could deal with that: test, collapse, backtrack.
+local new_kern = nuts.pool.kern
+
+local function checked(head)
+ local current = head
+ while current do
+ if getid(current) == glue_code then
+ local kern = new_kern(getfield(current,"width"))
+ if head == current then
+ local next = getnext(current)
+ if next then
+ setlink(kern,next)
+ end
+ flush_node(current)
+ head = kern
+ current = next
+ else
+ local prev, next = getboth(current)
+ setlink(prev,kern)
+ setlink(kern,next)
+ flush_node(current)
+ current = next
+ end
+ else
+ current = getnext(current)
+ end
+ end
+ return head
+end
+
+local function setdiscchecked(d,pre,post,replace)
+ if pre then pre = checked(pre) end
+ if post then post = checked(post) end
+ if replace then replace = checked(replace) end
+ setdisc(d,pre,post,replace)
+end
+
local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,ck,chainproc)
if not start then
@@ -1773,8 +1821,10 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
local current = start
local last = start
local prev = getprev(start)
+ local hasglue = false
-- fishy: so we can overflow and then go on in the sweep?
+ -- todo : id can also be glue_code as we checked spaces
local i = f
while i <= l do
@@ -1783,6 +1833,11 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
i = i + 1
last = current
current = getnext(current)
+ elseif id == glue_code then
+ i = i + 1
+ last = current
+ current = getnext(current)
+ hasglue = true
elseif id == disc_code then
if keepdisc then
keepdisc = false
@@ -1835,8 +1890,8 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
tail = find_node_tail(head)
end
setnext(sweepnode,current)
- setprev(head,nil)
- setnext(tail,nil)
+ setprev(head)
+ setnext(tail)
appenddisc(sweepnode,head)
end
end
@@ -1849,6 +1904,10 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
if id == glyph_code then
i = i + 1
current = getnext(current)
+ elseif id == glue_code then
+ i = i + 1
+ current = getnext(current)
+ hasglue = true
elseif id == disc_code then
if keepdisc then
keepdisc = false
@@ -1891,6 +1950,9 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
local id = getid(current)
if id == glyph_code then
i = i - 1
+ elseif id == glue_code then
+ i = i - 1
+ hasglue = true
elseif id == disc_code then
if keepdisc then
keepdisc = false
@@ -1939,8 +2001,8 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
if cprev then
setnext(cprev,lookaheaddisc)
end
- setprev(cf,nil)
- setnext(cl,nil)
+ setprev(cf)
+ setnext(cl)
if startishead then
head = lookaheaddisc
end
@@ -1967,7 +2029,11 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
local tail = find_node_tail(new)
setlink(tail,replace)
end
- setdisc(lookaheaddisc,cf,post,new)
+ if hasglue then
+ setdiscchecked(lookaheaddisc,cf,post,new)
+ else
+ setdisc(lookaheaddisc,cf,post,new)
+ end
start = getprev(lookaheaddisc)
sweephead[cf] = getnext(clast)
sweephead[new] = getnext(last)
@@ -1993,8 +2059,8 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
setprev(cnext,backtrackdisc)
end
setnext(backtrackdisc,cnext)
- setprev(cf,nil)
- setnext(cl,nil)
+ setprev(cf)
+ setnext(cl)
local pre, post, replace, pretail, posttail, replacetail = getdisc(backtrackdisc,true)
local new = copy_node_list(cf)
local cnew = find_node_tail(new)
@@ -2021,7 +2087,11 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
else
replace = new
end
- setdisc(backtrackdisc,pre,post,replace)
+ if hasglue then
+ setdiscchecked(backtrackdisc,pre,post,replace)
+ else
+ setdisc(backtrackdisc,pre,post,replace)
+ end
start = getprev(backtrackdisc)
sweephead[post] = getnext(clast)
sweephead[replace] = getnext(last)
@@ -2744,7 +2814,7 @@ local function kernrun(disc,k_run,font,attr,...)
done = true
end
setprev(pre,nest)
--- setprev(pre,nil)
+-- setprev(pre)
setnext(prev,disc)
end
end
@@ -2758,7 +2828,7 @@ local function kernrun(disc,k_run,font,attr,...)
if k_run(posttail,"postinjections",next,font,attr,...) then
done = true
end
- setnext(posttail,nil)
+ setnext(posttail)
setprev(next,disc)
end
end
@@ -2774,7 +2844,7 @@ local function kernrun(disc,k_run,font,attr,...)
done = true
end
setprev(replace,nest)
--- setprev(replace,nil)
+-- setprev(replace)
setnext(prev,disc)
end
if next then
@@ -2782,7 +2852,7 @@ local function kernrun(disc,k_run,font,attr,...)
if k_run(replacetail,"replaceinjections",next,font,attr,...) then
done = true
end
- setnext(replacetail,nil)
+ setnext(replacetail)
setprev(next,disc)
end
elseif prev and next then
@@ -2862,7 +2932,7 @@ local function testrun(disc,t_run,c_run,...)
local ok, overflow = t_run(replace,next,...)
if ok and overflow then
-- so, we can have crossed the boundary
- setfield(disc,"replace",nil)
+ setfield(disc,"replace")
setlink(prev,replace)
-- setlink(replacetail,next)
setboth(disc)
diff --git a/src/fontloader/misc/fontloader-font-tfm.lua b/src/fontloader/misc/fontloader-font-tfm.lua
index 6565a0e..6584190 100644
--- a/src/fontloader/misc/fontloader-font-tfm.lua
+++ b/src/fontloader/misc/fontloader-font-tfm.lua
@@ -31,10 +31,14 @@ tfm.maxnestingdepth = 5
tfm.maxnestingsize = 65536*1024
local otf = fonts.handlers.otf
+local otfenhancers = otf.enhancers
local tfmfeatures = constructors.features.tfm
local registertfmfeature = tfmfeatures.register
+local tfmenhancers = constructors.enhancers.tfm
+local registertfmenhancer = tfmenhancers.register
+
constructors.resolvevirtualtoo = false -- wil be set in font-ctx.lua
fonts.formats.tfm = "type1" -- we need to have at least a value here
@@ -73,38 +77,7 @@ function tfm.setfeatures(tfmdata,features)
end
end
-local depth = { } -- table.setmetatableindex("number")
-local enhancers = { }
-
-local steps = {
- "normalize features",
- "check extra features"
-}
-
--- otf.enhancers.register("check extra features",enhance)
-
-enhancers["check extra features"] = otf.enhancers.enhance
-
---[[ PHG: begin hack for Luaotfload ]]--
-luaotfload_tfm_enhancers_reregister = function ()
- enhancers["check extra features"]=otf.enhancers.enhance
-end
---[[ PHG: end hack for Luaotfload ]]--
-
-local function applyenhancers(data,filename)
- for i=1,#steps do
- local step = steps[i]
- local enhancer = enhancers[step]
- if enhancer then
- if trace_loading then
- report_tfm("applying enhancer %a",step)
- end
- enhancer(data,filename)
- else
- report_tfm("invalid enhancer %a",step)
- end
- end
-end
+local depth = { } -- table.setmetatableindex("number")
-- Normally we just load the tfm data and go on. However there was some demand for
-- loading good old tfm /pfb files where afm files were lacking and even enc files
@@ -220,7 +193,7 @@ local function read_from_tfm(specification)
--
-- We make a pseudo opentype font, e.g. kerns and ligatures etc:
--
- applyenhancers(tfmdata,filename)
+ tfmenhancers.apply(tfmdata,filename)
--
-- Now user stuff can kick in.
--
@@ -622,7 +595,7 @@ do
local everywhere = { ["*"] = { ["*"] = true } } -- or: { ["*"] = { "*" } }
local noflags = { false, false, false, false }
- enhancers["normalize features"] = function(data)
+ local function enhance_normalize_features(data)
local ligatures = setmetatableindex("table")
local kerns = setmetatableindex("table")
local characters = data.characters
@@ -708,6 +681,9 @@ do
data.shared.resources = data.shared.resources or resources
end
+ registertfmenhancer("normalize features", enhance_normalize_features)
+ registertfmenhancer("check extra features", otfenhancers.enhance)
+
end
-- As with type one (afm) loading, we just use the opentype ones: