diff options
author | Philipp Gesang <phg@phi-gamma.net> | 2016-07-30 12:26:59 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-07-30 12:26:59 +0200 |
commit | 9e2db3ead715ceecf2afc879aefc020f84ea4f09 (patch) | |
tree | 89960031e5cf796661e7a6f10bdf9d32f36c01dd /src/fontloader/misc | |
parent | 2fcdccf7edfa1cfb0f03fe8f2163c7c5d8281984 (diff) | |
parent | c0597dba961fb9f99c2bd5d2d7f442dc37382dc2 (diff) | |
download | luaotfload-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.lua | 358 | ||||
-rw-r--r-- | src/fontloader/misc/fontloader-font-one.lua | 110 | ||||
-rw-r--r-- | src/fontloader/misc/fontloader-font-otl.lua | 180 | ||||
-rw-r--r-- | src/fontloader/misc/fontloader-font-ots.lua | 158 | ||||
-rw-r--r-- | src/fontloader/misc/fontloader-font-tfm.lua | 44 |
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: |