diff options
Diffstat (limited to 'tex/context/base/font-def.lua')
-rw-r--r-- | tex/context/base/font-def.lua | 624 |
1 files changed, 187 insertions, 437 deletions
diff --git a/tex/context/base/font-def.lua b/tex/context/base/font-def.lua index 474cde41d..8c367e148 100644 --- a/tex/context/base/font-def.lua +++ b/tex/context/base/font-def.lua @@ -6,9 +6,13 @@ if not modules then modules = { } end modules ['font-def'] = { license = "see context related readme files" } --- check reuse of lmroman1o-regular vs lmr10 +local format, concat, gmatch, match, find, lower = string.format, table.concat, string.gmatch, string.match, string.find, string.lower +local tostring, next = tostring, next -local texsprint, count, dimen, format, concat = tex.sprint, tex.count, tex.dimen, string.format, table.concat +local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end) + +trackers.register("fonts.loading", "fonts.defining", "otf.loading", "afm.loading", "tfm.loading") +trackers.register("fonts.all", "fonts.*", "otf.*", "afm.*", "tfm.*") --[[ldx-- <p>Here we deal with defining fonts. We do so by intercepting the @@ -18,43 +22,30 @@ default loader that only handles <l n='tfm'/>.</p> fonts = fonts or { } fonts.define = fonts.define or { } fonts.tfm = fonts.tfm or { } +fonts.ids = fonts.ids or { } fonts.vf = fonts.vf or { } fonts.used = fonts.used or { } -local tfm = fonts.tfm -local vf = fonts.vf +local tfm = fonts.tfm +local vf = fonts.vf +local define = fonts.define tfm.version = 1.01 tfm.cache = containers.define("fonts", "tfm", tfm.version, false) -- better in font-tfm ---[[ldx-- -<p>Choosing a font by name and specififying its size is only part of the -game. In order to prevent complex commands, <l n='xetex'/> introduced -a method to pass feature information as part of the font name. At the -risk of introducing nasty parsing and compatinility problems, this -syntax was expanded over time.</p> - -<p>For the sake of users who have defined fonts using that syntax, we -will support it, but we will provide additional methods as well. -Normally users will not use this direct way, but use a more abstract -interface.</p> - --ldx]]-- - ---~ name, kind, features = fonts.features.split_xetex("blabla / B : + lnum ; foo = bar ; - whatever ; whow ; + hans ; test = yes") - -fonts.define.method = 3 -- 1: tfm 2: tfm and if not then afm 3: afm and if not then tfm -fonts.define.auto_afm = true -fonts.define.auto_otf = true -fonts.define.specify = fonts.define.specify or { } -fonts.define.methods = fonts.define.methods or { } +define.method = "afm or tfm" -- afm, tfm, afm or tfm, tfm or afm +define.specify = fonts.define.specify or { } +define.methods = fonts.define.methods or { } tfm.fonts = tfm.fonts or { } tfm.readers = tfm.readers or { } tfm.internalized = tfm.internalized or { } -- internal tex numbers -tfm.id = tfm.id or { } -- font data, maybe use just fonts.ids (faster lookup) tfm.readers.sequence = { 'otf', 'ttf', 'afm', 'tfm' } +local readers = tfm.readers +local sequence = readers.sequence + --[[ldx-- <p>We hardly gain anything when we cache the final (pre scaled) <l n='tfm'/> table. But it can be handy for debugging.</p> @@ -84,7 +75,7 @@ and prepares a table that will move along as we proceed.</p> local splitter, specifiers = nil, "" -function fonts.define.add_specifier(symbol) +function define.add_specifier(symbol) specifiers = specifiers .. symbol local left = lpeg.P("(") local right = lpeg.P(")") @@ -92,27 +83,32 @@ function fonts.define.add_specifier(symbol) local method = lpeg.S(specifiers) local lookup = lpeg.C(lpeg.P("file")+lpeg.P("name")) * colon -- hard test, else problems with : method local sub = left * lpeg.C(lpeg.P(1-left-right-method)^1) * right - local specification = lpeg.C(method) * lpeg.C(lpeg.P(1-method)^1) +--~ local specification = lpeg.C(method) * lpeg.C(lpeg.P(1-method)^1) + local specification = lpeg.C(method) * lpeg.C(lpeg.P(1)^1) local name = lpeg.C((1-sub-specification)^1) splitter = lpeg.P((lookup + lpeg.Cc("")) * name * (sub + lpeg.Cc("")) * (specification + lpeg.Cc(""))) end -function fonts.define.get_specification(str) +function define.get_specification(str) return splitter:match(str) end -function fonts.define.register_split(symbol,action) - fonts.define.add_specifier(symbol) - fonts.define.specify[symbol] = action +function define.register_split(symbol,action) + define.add_specifier(symbol) + define.specify[symbol] = action end -function fonts.define.makespecification(specification, lookup, name, sub, method, detail, size) +function define.makespecification(specification, lookup, name, sub, method, detail, size) size = size or 655360 - if fonts.trace then + if trace_defining then logs.report("define font","%s -> lookup: %s, name: %s, sub: %s, method: %s, detail: %s", specification, (lookup ~= "" and lookup) or "[file]", (name ~= "" and name) or "-", (sub ~= "" and sub) or "-", (method ~= "" and method) or "-", (detail ~= "" and detail) or "-") end +--~ if specification.lookup then +--~ lookup = specification.lookup -- can come from xetex [] syntax +--~ specification.lookup = nil +--~ end if lookup ~= 'name' then -- for the moment only two lookups, maybe some day also system: lookup = 'file' end @@ -131,37 +127,43 @@ function fonts.define.makespecification(specification, lookup, name, sub, method return t end -function fonts.define.analyze(specification, size) - local lookup, name, sub, method, detail = fonts.define.get_specification(specification or "") - return fonts.define.makespecification(specification,lookup, name, sub, method, detail, size) +function define.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) end --[[ldx-- <p>A unique hash value is generated by:</p> --ldx]]-- +local sortedhashkeys = table.sortedhashkeys + function tfm.hash_features(specification) local features = specification.features if features then local t = { } local normal = features.normal if normal and next(normal) then - local f = table.sortedhashkeys(normal) + local f = sortedhashkeys(normal) for i=1,#f do local v = f[i] - if v ~= "number" then + if v ~= "number" and v ~= "features" then -- i need to figure this out, features t[#t+1] = v .. '=' .. tostring(normal[v]) end end end local vtf = features.vtf if vtf and next(vtf) then - local f = table.sortedhashkeys(vtf) + local f = sortedhashkeys(vtf) for i=1,#f do local v = f[i] t[#t+1] = v .. '=' .. tostring(vtf[v]) end end +--~ if specification.mathsize then +--~ t[#t] = "mathsize=" .. specification.mathsize +--~ end if #t > 0 then return concat(t,"+") end @@ -189,18 +191,28 @@ function tfm.hash_instance(specification,force) size = math.round(tfm.scaled(size, fonts.designsizes[hash])) specification.size = size end - if fallbacks then - return hash .. ' @ ' .. tostring(size) .. ' @ ' .. fallbacks - else - return hash .. ' @ ' .. tostring(size) - end +--~ local mathsize = specification.mathsize or 0 +--~ if mathsize > 0 then +--~ local textsize = specification.textsize +--~ if fallbacks then +--~ return hash .. ' @ ' .. tostring(size) .. ' [ ' .. tostring(mathsize) .. ' : ' .. tostring(textsize) .. ' ] @ ' .. fallbacks +--~ else +--~ return hash .. ' @ ' .. tostring(size) .. ' [ ' .. tostring(mathsize) .. ' : ' .. tostring(textsize) .. ' ]' +--~ end +--~ else + if fallbacks then + return hash .. ' @ ' .. tostring(size) .. ' @ ' .. fallbacks + else + return hash .. ' @ ' .. tostring(size) + end +--~ end end --[[ldx-- <p>We can resolve the filename using the next function:</p> --ldx]]-- -function fonts.define.resolve(specification) +function define.resolve(specification) if not specification.resolved or specification.resolved == "" then -- resolved itself not per se in mapping hash if specification.lookup == 'name' then specification.resolved, specification.sub = fonts.names.resolve(specification.name,specification.sub) @@ -218,7 +230,8 @@ function fonts.define.resolve(specification) else specification.forced = specification.forced end - specification.hash = specification.name .. ' @ ' .. tfm.hash_features(specification) +--~ specification.hash = specification.name .. ' @ ' .. tfm.hash_features(specification) + specification.hash = lower(specification.name .. ' @ ' .. tfm.hash_features(specification)) if specification.sub and specification.sub ~= "" then specification.hash = specification.sub .. ' @ ' .. specification.hash end @@ -242,22 +255,23 @@ specification yet.</p> --ldx]]-- function tfm.read(specification) ---~ input.starttiming(fonts) local hash = tfm.hash_instance(specification) local tfmtable = tfm.fonts[hash] -- hashes by size ! if not tfmtable then - if specification.forced and specification.forced ~= "" then - tfmtable = tfm.readers[specification.forced:lower()](specification) + local forced = specification.forced or "" + if forced ~= "" then + tfmtable = readers[lower(forced)](specification) if not tfmtable then - logs.report("define font","forced type %s of %s not found",specification.forced,specification.name) + logs.report("define font","forced type %s of %s not found",forced,specification.name) end else - for _, reader in ipairs(tfm.readers.sequence) do - if tfm.readers[reader] then -- not really needed - if fonts.trace then + for s=1,#sequence do -- reader sequence + local reader = sequence[s] + if readers[reader] then -- not really needed + if trace_defining then logs.report("define font","trying type %s for %s with file %s",reader,specification.name,specification.filename or "unknown") end - tfmtable = tfm.readers[reader](specification) + tfmtable = readers[reader](specification) if tfmtable then break end end end @@ -273,7 +287,6 @@ function tfm.read(specification) --~ tfmtable.mode = specification.features.normal.mode or "base" end end ---~ input.stoptiming(fonts) if not tfmtable then logs.report("define font","font with name %s is not found",specification.name) end @@ -285,26 +298,26 @@ end --ldx]]-- function tfm.read_and_define(name,size) -- no id - local specification = fonts.define.analyze(name,size) + local specification = define.analyze(name,size) local method = specification.method - if method and fonts.define.specify[method] then - specification = fonts.define.specify[method](specification) + if method and define.specify[method] then + specification = define.specify[method](specification) end - specification = fonts.define.resolve(specification) + specification = define.resolve(specification) local hash = tfm.hash_instance(specification) - local id = fonts.define.registered(hash) + local id = define.registered(hash) if not id then local fontdata = tfm.read(specification) if fontdata then fontdata.hash = hash id = font.define(fontdata) - fonts.define.register(fontdata,id) -tfm.cleanup_table(fontdata) + define.register(fontdata,id) + tfm.cleanup_table(fontdata) else id = 0 -- signal end end - return tfm.id[id], id + return fonts.ids[id], id end --[[ldx-- @@ -312,275 +325,113 @@ end evolved. Each one has its own way of dealing with its format.</p> --ldx]]-- -function tfm.readers.opentype(specification,suffix,what) - if fonts.define.auto_otf then - local fullname, tfmtable = nil, nil - fullname = input.findbinfile(specification.name,suffix) or "" - if fullname == "" then - local fb = fonts.names.old_to_new[specification.name] - if fb then - fullname = input.findbinfile(fb,suffix) or "" - end - end - if fullname == "" then - local fb = fonts.names.new_to_old[specification.name] - if fb then - fullname = input.findbinfile(fb,suffix) or "" - end - 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 - end - return tfmtable - else - return nil +local function check_tfm(specification,fullname) + -- ofm directive blocks local path search unless set + fullname = resolvers.findbinfile(fullname, 'tfm') or "" -- just to be sure + if fullname ~= "" then + specification.filename, specification.format = fullname, "ofm" + return tfm.read_from_tfm(specification) end end -function tfm.readers.otf(specification) return tfm.readers.opentype(specification,"otf","opentype") end -function tfm.readers.ttf(specification) return tfm.readers.opentype(specification,"ttf","truetype") end -function tfm.readers.ttc(specification) return tfm.readers.opentype(specification,"ttf","truetype") end -- !! - -function tfm.readers.afm(specification,method) - local fullname, tfmtable = nil, nil - method = method or fonts.define.method - if method == 2 then - fullname = input.findbinfile(specification.name,"ofm") or "" - if fullname == "" then - tfmtable = tfm.read_from_afm(specification) - else -- redundant - specification.filename = fullname - tfmtable = tfm.read_from_tfm(specification) - end - elseif method == 3 then -- maybe also findbinfile here - if fonts.define.auto_afm then - tfmtable = tfm.read_from_afm(specification) - end - elseif method == 4 then -- maybe also findbinfile here - tfmtable = tfm.read_from_afm(specification) +local function check_afm(specification,fullname) + fullname = resolvers.findbinfile(fullname, 'afm') or "" -- just to be sure + if fullname ~= "" then + specification.filename, specification.format = fullname, "afm" + return tfm.read_from_afm(specification) end - return tfmtable end -function tfm.readers.tfm(specification) - local fullname, tfmtable = nil, nil - tfmtable = tfm.read_from_tfm(specification) - return tfmtable -end - ---[[ldx-- -<p>So far we haven't really dealt with features (or whatever we want -to pass along with the font definition. We distinguish the following -situations:</p> -situations:</p> - -<code> -name:xetex like specs -name@virtual font spec -name*context specification -</code> - -<p>Of course one can always define more.</p> ---ldx]]-- - -function fonts.define.specify.predefined(specification) - local detail = specification.detail - if detail ~= "" then - -- detail = detail:gsub("["..fonts.define.splitsymbols.."].*$","") -- get rid of *whatever specs and such - if fonts.define.methods[detail] then -- since these may be appended at the - specification.features.vtf = { preset = detail } -- tex end by default +function readers.tfm(specification) + local fullname, tfmtable = specification.filename or "", nil + if fullname == "" then + local forced = specification.forced or "" + if forced ~= "" then + tfmtable = check_tfm(specification,specification.name .. "." .. forced) end - end - return specification -end - -fonts.define.register_split("@", fonts.define.specify.predefined) - -function fonts.define.specify.colonized(specification) -- xetex mode - local list = { } - if specification.detail and specification.detail ~= "" then - local expanded_features = { } - local function expand(features) - for _,v in pairs(features:split(";")) do --just gmatch - expanded_features[#expanded_features+1] = v - end - end - expand(specification.detail) - for _,v in pairs(expanded_features) do - local a, b = v:match("^%s*(%S+)%s*=%s*(%S+)%s*$") - if a and b then - list[a] = b:is_boolean() - if type(list[a]) == "nil" then - list[a] = b - end - else - local a, b = v:match("^%s*([%+%-]?)%s*(%S+)%s*$") - if a and b then - list[b] = a ~= "-" - end - end + if not tfmtable then + tfmtable = check_tfm(specification,specification.name) end - end - specification.features.normal = list - return specification -end - -function tfm.make(specification) - -- currently fonts are scaled while constructing the font, so we - -- have to do scaling of commands in the vf at that point using - -- e.g. "local scale = g.factor or 1" after all, we need to work - -- with copies anyway and scaling needs to be done at some point; - -- 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 = fonts.define.methods[specification.features.vtf.preset] - if fvm then - return fvm(specification) else - return nil + tfmtable = check_tfm(specification,fullname) end + return tfmtable end -fonts.define.register_split(":", fonts.define.specify.colonized) - -fonts.define.specify.context_setups = fonts.define.specify.context_setups or { } -fonts.define.specify.context_numbers = fonts.define.specify.context_numbers or { } -fonts.define.specify.synonyms = fonts.define.specify.synonyms or { } - -input.storage.register(false,"fonts/setups" , fonts.define.specify.context_setups , "fonts.define.specify.context_setups" ) -input.storage.register(false,"fonts/numbers", fonts.define.specify.context_numbers, "fonts.define.specify.context_numbers") - -fonts.triggers = fonts.triggers or { } - -function fonts.define.specify.preset_context(name,parent,features) - if features == "" then - if parent:find("=") then - features = parent - parent = "" +function readers.afm(specification,method) + local fullname, tfmtable = specification.filename or "", nil + if fullname == "" then + local forced = specification.forced or "" + if forced ~= "" then + tfmtable = check_afm(specification,specification.name .. "." .. forced) end - end - local fds = fonts.define.specify - local setups, numbers, synonyms = fds.context_setups, fds.context_numbers, fds.synonyms - local number = (setups[name] and setups[name].number) or 0 - local t = (features == "" and { }) or fonts.otf.meanings.normalize(aux.settings_to_hash(features)) - -- todo: synonyms, and not otf bound - if parent ~= "" then - for p in parent:gmatch("[^, ]+") do - local s = setups[p] - if s then - for k,v in pairs(s) do - if t[k] == nil then - t[k] = v - end - end + if not tfmtable then + method = method or define.method or "afm or tfm" + if method == "tfm" then + tfmtable = check_tfm(specification,specification.name) + elseif method == "afm" then + tfmtable = check_afm(specification,specification.name) + elseif method == "tfm or afm" then + tfmtable = check_tfm(specification,specification.name) or check_afm(specification,specification.name) + else -- method == "afm or tfm" or method == "" then + tfmtable = check_afm(specification,specification.name) or check_tfm(specification,specification.name) end end - end - -- these are auto set so in order to prevent redundant definitions - -- we need to preset them (we hash the features and adding a default - -- setting during initialization may result in a different hash) - local default = fonts.otf.features.default - for k,v in pairs(fonts.triggers) do - if type(t[v]) == "nil" then - local vv = default[v] - if vv then t[v] = vv end - end - end - -- sparse 'm so that we get a better hash and less test (experimental - -- optimization) - local tt = { } - for k,v in pairs(t) do - if v then tt[k] = v end - end - -- needed for dynamic features - if number == 0 then - numbers[#numbers+1] = name - tt.number = #numbers else - tt.number = number + tfmtable = check_afm(specification,fullname) end - setups[name] = tt + return tfmtable end -do - - -- here we clone features according to languages - - local default = 0 - local setups = fonts.define.specify.context_setups - local numbers = fonts.define.specify.context_numbers - - function fonts.define.specify.context_number(name) - local t = setups[name] - if not t then - return default - elseif t.auto then - local lng = tonumber(tex.language) - local tag = name .. ":" .. lng - local s = setups[tag] - if s then - return s.number or default - else - local script, language = languages.association(lng) - if t.script ~= script or t.language ~= language then - local s = table.fastcopy(t) - local n = #numbers + 1 - setups[tag] = s - numbers[n] = tag - s.number = n - s.script = script - s.language = language - return n - else - setups[tag] = t - return t.number or default - end - end - else - return t.number or default +local function check_otf(specification,suffix,what) + local fullname, tfmtable = resolvers.findbinfile(specification.name,suffix) or "", nil + if fullname == "" then + local fb = fonts.names.old_to_new[specification.name] + if fb then + fullname = resolvers.findbinfile(fb,suffix) or "" end end - -end - -function fonts.define.specify.context_tostring(name,kind,separator,yes,no,strict,omit) -- not used - return aux.hash_to_string(table.merged(fonts[kind].features.default or {},fonts.define.specify.context_setups[name] or {}),separator,yes,no,strict,omit) -end - -function fonts.define.specify.split_context(features) - if fonts.define.specify.context_setups[features] then - return fonts.define.specify.context_setups[features] - else -- ? ? ? - return fonts.define.specify.preset_context("***",features) + if fullname == "" then + local fb = fonts.names.new_to_old[specification.name] + if fb then + fullname = resolvers.findbinfile(fb,suffix) or "" + end + 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 end + return tfmtable end -local splitter = lpeg.splitat(",") - -function fonts.define.specify.starred(features) -- no longer fallbacks here - local detail = features.detail - if detail and detail ~= "" then - features.features.normal = fonts.define.specify.split_context(detail) +function readers.opentype(specification,suffix,what) + local forced = specification.forced or "" + if forced == "otf" then + return check_otf(specification,forced,"opentype") + elseif forced == "ttf" then + return check_otf(specification,forced,"truetype") + elseif forced == "ttf" then + return check_otf(specification,forced,"truetype") else - features.features.normal = { } + return check_otf(specification,suffix,what) end - return features end -fonts.define.register_split('*',fonts.define.specify.starred) +function readers.otf(specification) return readers.opentype(specification,"otf","opentype") end +function readers.ttf(specification) return readers.opentype(specification,"ttf","truetype") end +function readers.ttc(specification) return readers.opentype(specification,"ttf","truetype") end -- !! --[[ldx-- <p>We need to check for default features. For this we provide a helper function.</p> --ldx]]-- -function fonts.define.check(features,defaults) -- nb adapts features ! +function define.check(features,defaults) -- nb adapts features ! local done = false if table.is_empty(features) then features, done = table.fastcopy(defaults), true else - for k,v in pairs(defaults) do + for k,v in next, defaults do if features[k] == nil then features[k], done = v, true end @@ -601,43 +452,59 @@ not gain much. By the way, passing id's back to in the callback was introduced later in the development.</p> --ldx]]-- -fonts.define.last = nil +define.last = nil -function fonts.define.register(fontdata,id) +function define.register(fontdata,id) if fontdata and id then local hash = fontdata.hash if not tfm.internalized[hash] then - if fonts.trace then + if trace_defining then logs.report("define font","loading at 2 id %s, hash: %s",id or "?",hash or "?") end - tfm.id[id] = fontdata + fonts.ids[id] = fontdata tfm.internalized[hash] = id end end end -function fonts.define.registered(hash) +function define.registered(hash) local id = tfm.internalized[hash] - return id, id and tfm.id[id] + return id, id and fonts.ids[id] end local cache_them = false -function fonts.define.read(specification,size,id) -- id can be optional, name can already be table - input.starttiming(fonts) +function tfm.make(specification) + -- currently fonts are scaled while constructing the font, so we + -- have to do scaling of commands in the vf at that point using + -- e.g. "local scale = g.factor or 1" after all, we need to work + -- with copies anyway and scaling needs to be done at some point; + -- 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] + if fvm then + return fvm(specification) + else + return nil + end +end + +function define.read(specification,size,id) -- id can be optional, name can already be table + statistics.starttiming(fonts) if type(specification) == "string" then - specification = fonts.define.analyze(specification,size) + specification = define.analyze(specification,size) end local method = specification.method - if method and fonts.define.specify[method] then - specification = fonts.define.specify[method](specification) + if method and define.specify[method] then + specification = define.specify[method](specification) end - specification = fonts.define.resolve(specification) + specification = define.resolve(specification) local hash = tfm.hash_instance(specification) if cache_them then local fontdata = containers.read(fonts.cache(),hash) -- for tracing purposes end - local fontdata = fonts.define.registered(hash) -- id + local fontdata = define.registered(hash) -- id if not fontdata then if specification.features.vtf and specification.features.vtf.preset then fontdata = tfm.make(specification) @@ -652,15 +519,16 @@ function fonts.define.read(specification,size,id) -- id can be optional, name ca end if fontdata then fontdata.hash = hash + fontdata.cache = "no" if id then - fonts.define.register(fontdata,id) + define.register(fontdata,id) end end end - fonts.define.last = fontdata or id -- todo ! ! ! ! ! + define.last = fontdata or id -- todo ! ! ! ! ! if not fontdata then logs.report("define font", "unknown font %s, loading aborted",specification.name) - elseif fonts.trace and type(fontdata) == "table" then + elseif trace_defining and type(fontdata) == "table" then logs.report("define font","using %s font with id %s, n:%s s:%s b:%s e:%s p:%s f:%s", fontdata.type or "unknown", id or "?", @@ -671,148 +539,30 @@ function fonts.define.read(specification,size,id) -- id can be optional, name ca fontdata.fullname or "?", file.basename(fontdata.filename or "?")) end - input.stoptiming(fonts) + statistics.stoptiming(fonts) return fontdata end --- define (two steps) - -local P, C, Cc = lpeg.P, lpeg.C, lpeg.Cc - -local space = P(" ") -local spaces = space^0 -local value = C((1-space)^1) -local rest = C(P(1)^0) -local scale_none = Cc(0) -local scale_at = P("at") * Cc(1) * spaces * value -local scale_sa = P("sa") * Cc(2) * spaces * value -local scale_mo = P("mo") * Cc(3) * spaces * value -local scale_scaled = P("scaled") * Cc(4) * spaces * value - -local sizepattern = spaces * (scale_at + scale_sa + scale_mo + scale_scaled + scale_none) -local splitpattern = spaces * value * spaces * rest - -local specification -- - -function fonts.define.command_1(str) - input.starttiming(fonts) - local fullname, size = splitpattern:match(str) - local lookup, name, sub, method, detail = fonts.define.get_specification(fullname) - if not name then - logs.report("define font","strange definition '%s'",str) - texsprint(tex.ctxcatcodes,"\\glet\\somefontname\\defaultfontfile") - elseif name == "unknown" then - texsprint(tex.ctxcatcodes,"\\glet\\somefontname\\defaultfontfile") - else - texsprint(tex.ctxcatcodes,format("\\xdef\\somefontname{%s}",name)) - end - -- we can also use a count for the size - if size and size ~= "" then - local mode, size = sizepattern:match(size) - if size and mode then - count.scaledfontmode = mode - texsprint(tex.ctxcatcodes,format("\\def\\somefontsize{%s}",size)) - else - count.scaledfontmode = 0 - texsprint(tex.ctxcatcodes,format("\\let\\somefontsize\\empty",size)) - end - else - count.scaledfontmode = 0 - texsprint(tex.ctxcatcodes,format("\\let\\somefontsize\\empty",size)) - end - specification = fonts.define.makespecification(str,lookup,name,sub,method,detail,size) -end - -function fonts.define.command_2(global,cs,name,size,classfeatures,fontfeatures,classfallbacks,fontfallbacks) - local trace = fonts.trace - -- name is now resolved and size is scaled cf sa/mo - local lookup, name, sub, method, detail = fonts.define.get_specification(name or "") - -- asome settings can be overloaded - if lookup and lookup ~= "" then specification.lookup = lookup end - specification.name = name - specification.size = size - specification.sub = sub - if detail and detail ~= "" then - specification.method, specification.detail = method or "*", detail - elseif specification.detail and specification.detail ~= "" then - -- already set - elseif fontfeatures and fontfeatures ~= "" then - specification.method, specification.detail = "*", fontfeatures - elseif classfeatures and classfeatures ~= "" then - specification.method, specification.detail = "*", classfeatures - end - if trace then - logs.report("define font","memory usage before: %s",ctx.memused()) - end -if fontfallbacks and fontfallbacks ~= "" then - specification.fallbacks = fontfallbacks -elseif classfallbacks and classfallbacks ~= "" then - specification.fallbacks = classfallbacks -end - local tfmdata = fonts.define.read(specification,size) -- id not yet known - if not tfmdata then - logs.report("define font","unable to define %s as \\%s",name,cs) - elseif type(tfmdata) == "number" then - if trace then - logs.report("define font","reusing %s with id %s as \\%s (features: %s/%s, fallbacks: %s/%s)",name,tfmdata,cs,classfeatures,fontfeatures,classfallbacks,fontfallbacks) - end - tex.definefont(global,cs,tfmdata) - -- resolved (when designsize is used): - texsprint(tex.ctxcatcodes,format("\\def\\somefontsize{%isp}",tfm.id[tfmdata].size)) - else - -- local t = os.clock(t) - local id = font.define(tfmdata) - -- print(name,os.clock()-t) - tfmdata.id = id - fonts.define.register(tfmdata,id) - tex.definefont(global,cs,id) - tfm.cleanup_table(tfmdata) - if fonts.trace then - logs.report("define font","defining %s with id %s as \\%s (features: %s/%s, fallbacks: %s/%s)",name,id,cs,classfeatures,fontfeatures,classfallbacks,fontfallbacks) - end - -- resolved (when designsize is used): - texsprint(tex.ctxcatcodes,format("\\def\\somefontsize{%isp}",tfmdata.size)) - --~ if specification.fallbacks then - --~ fonts.collections.prepare(specification.fallbacks) - --~ end - end - if trace then - logs.report("define font","memory usage after: %s",ctx.memused()) - end - input.stoptiming(fonts) -end - - ---~ table.insert(tfm.readers.sequence,1,'vtf') - ---~ function tfm.readers.vtf(specification) ---~ if specification.features.vtf and specification.features.vtf.preset then ---~ return tfm.make(specification) ---~ else ---~ return nil ---~ end ---~ end - -function fonts.vf.find(name) +function vf.find(name) name = file.removesuffix(file.basename(name)) if tfm.resolve_vf then local format = fonts.logger.format(name) if format == 'tfm' or format == 'ofm' then - if fonts.trace then + if trace_defining then logs.report("define font","locating vf for %s",name) end - return input.findbinfile(name,"ovf") + return resolvers.findbinfile(name,"ovf") else - if fonts.trace then + if trace_defining then logs.report("define font","vf for %s is already taken care of",name) end return nil -- "" end else - if fonts.trace then + if trace_defining then logs.report("define font","locating vf for %s",name) end - return input.findbinfile(name,"ovf") + return resolvers.findbinfile(name,"ovf") end end @@ -820,5 +570,5 @@ end <p>We overload both the <l n='tfm'/> and <l n='vf'/> readers.</p> --ldx]]-- -callback.register('define_font' , fonts.define.read) -callback.register('find_vf_file', fonts.vf.find ) -- not that relevant any more +callback.register('define_font' , define.read) +callback.register('find_vf_file', vf.find ) -- not that relevant any more |