diff options
Diffstat (limited to 'tex/context/base/font-def.lua')
-rw-r--r-- | tex/context/base/font-def.lua | 201 |
1 files changed, 113 insertions, 88 deletions
diff --git a/tex/context/base/font-def.lua b/tex/context/base/font-def.lua index a466ca655..3f585b908 100644 --- a/tex/context/base/font-def.lua +++ b/tex/context/base/font-def.lua @@ -10,6 +10,8 @@ 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) @@ -24,33 +26,38 @@ local report_afm = logs.new("load afm") default loader that only handles <l n='tfm'/>.</p> --ldx]]-- -local fonts = fonts -local tfm = fonts.tfm -local vf = fonts.vf -local fontids = fonts.ids +local fonts = fonts +local tfm = fonts.tfm +local vf = fonts.vf +local fontids = fonts.ids + +fonts.used = allocate() -fonts.used = fonts.used or { } +tfm.readers = tfm.readers or { } +tfm.fonts = allocate() +tfm.internalized = allocate() -- internal tex numbers -tfm.readers = tfm.readers or { } -tfm.fonts = tfm.fonts or { } -tfm.internalized = tfm.internalized or { } -- internal tex numbers +local readers = tfm.readers +local sequence = allocate { 'otf', 'ttf', 'afm', 'tfm' } +readers.sequence = sequence -local readers = tfm.readers -local sequence = { 'otf', 'ttf', 'afm', 'tfm' } -readers.sequence = sequence +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.version = 1.01 -tfm.cache = containers.define("fonts", "tfm", tfm.version, false) -- better in font-tfm -tfm.auto_afm = true +fonts.definers = fonts.definers or { } +local definers = fonts.definers -fonts.define = fonts.define or { } -local define = fonts.define +definers.specifiers = definers.specifiers or { } +local specifiers = definers.specifiers -define.method = "afm or tfm" -- afm, tfm, afm or tfm, tfm or afm -define.specify = define.specify or { } -define.methods = define.methods or { } +specifiers.variants = allocate() +local variants = specifiers.variants -local findbinfile = resolvers.findbinfile +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) @@ -79,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 @@ -88,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) @@ -102,24 +109,28 @@ 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 report_define("%s -> lookup: %s, name: %s, sub: %s, method: %s, detail: %s", @@ -127,7 +138,7 @@ function define.makespecification(specification, lookup, name, sub, method, deta (sub ~= "" and sub) or "-", (method ~= "" and method) or "-", (detail ~= "" and detail) or "-") end if not lookup or lookup == "" then - lookup = define.defaultlookup + lookup = definers.defaultlookup end local t = { lookup = lookup, -- forced type @@ -144,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-- @@ -156,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 = { } @@ -188,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 @@ -198,10 +209,10 @@ 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 @@ -229,8 +240,8 @@ end <p>We can resolve the filename using the next function:</p> --ldx]]-- -define.resolvers = define.resolvers or { } -local resolvers = define.resolvers +definers.resolvers = definers.resolvers or { } +local resolvers = definers.resolvers -- todo: reporter @@ -274,7 +285,7 @@ function resolvers.spec(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 = resolvers[specification.lookup] if r then @@ -295,7 +306,7 @@ function define.resolve(specification) end end -- - specification.hash = lower(specification.name .. ' @ ' .. tfm.hash_features(specification)) + specification.hash = lower(specification.name .. ' @ ' .. tfm.hashfeatures(specification)) if specification.sub and specification.sub ~= "" then specification.hash = specification.sub .. ' @ ' .. specification.hash end @@ -319,7 +330,7 @@ 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 "" @@ -367,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 @@ -402,6 +413,9 @@ local function check_tfm(specification,fullname) if foundname == "" then foundname = findbinfile(fullname, 'ofm') or "" -- bonus for usage outside context end + if foundname == "" then + foundname = fonts.names.getfilename(fullname,"tfm") + end if foundname ~= "" then specification.filename, specification.format = foundname, "ofm" return tfm.read_from_tfm(specification) @@ -410,13 +424,15 @@ end local function check_afm(specification,fullname) local foundname = findbinfile(fullname, 'afm') or "" -- just to be sure - if foundname == "" and tfm.auto_afm then + 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 = 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 report_afm("stripping encoding prefix from filename %s",afmname) end @@ -453,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 @@ -478,21 +494,26 @@ local function check_otf(forced,specification,suffix,what) name = file.addsuffix(name,suffix,true) 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.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 + 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 @@ -518,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 @@ -533,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> @@ -544,9 +565,13 @@ 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 definers.current() -- or maybe current + return lastdefined +end -function define.register(fontdata,id) +function definers.register(fontdata,id) if fontdata and id then local hash = fontdata.hash if not tfm.internalized[hash] then @@ -562,7 +587,7 @@ function define.register(fontdata,id) end end -function define.registered(hash) +function definers.registered(hash) local id = tfm.internalized[hash] return id, id and fonts.ids[id] end @@ -577,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 @@ -585,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 @@ -616,11 +641,11 @@ 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 ! ! ! ! ! + lastdefined = fontdata or id -- todo ! ! ! ! ! if not fontdata then report_define( "unknown font %s, loading aborted",specification.name) elseif trace_defining and type(fontdata) == "table" then @@ -640,7 +665,7 @@ 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 @@ -665,5 +690,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 |