diff options
Diffstat (limited to 'tex/context/base/font-def.lua')
-rw-r--r-- | tex/context/base/font-def.lua | 186 |
1 files changed, 101 insertions, 85 deletions
diff --git a/tex/context/base/font-def.lua b/tex/context/base/font-def.lua index af6f5f394..cc7c45a9e 100644 --- a/tex/context/base/font-def.lua +++ b/tex/context/base/font-def.lua @@ -19,8 +19,11 @@ fonts.tfm = fonts.tfm or { } fonts.vf = fonts.vf or { } fonts.used = fonts.used or { } -fonts.tfm.version = 1.01 -fonts.tfm.cache = containers.define("fonts", "tfm", fonts.tfm.version, false) -- better in font-tfm +local tfm = fonts.tfm +local vf = fonts.vf + +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 @@ -44,12 +47,12 @@ fonts.define.specify = fonts.define.specify or { } fonts.define.splitsymbols = "" fonts.define.methods = fonts.define.methods or { } -fonts.tfm.fonts = fonts.tfm.fonts or { } -fonts.tfm.readers = fonts.tfm.readers or { } -fonts.tfm.internalized = fonts.tfm.internalized or { } -- internal tex numbers -fonts.tfm.id = fonts.tfm.id or { } -- font data, maybe use just fonts.ids (faster lookup) +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) -fonts.tfm.readers.sequence = { 'otf', 'ttf', 'afm', 'tfm' } +tfm.readers.sequence = { 'otf', 'ttf', 'afm', 'tfm' } --[[ldx-- <p>We hardly gain anything when we cache the final (pre scaled) @@ -121,33 +124,39 @@ end <p>A unique hash value is generated by:</p> --ldx]]-- -function fonts.tfm.hash_features(specification) - if specification.features then +function tfm.hash_features(specification) + local features = specification.features + if features then local t = { } - local normal = specification.features.normal - if not table.is_empty(normal) then - for _, v in pairs(table.sortedkeys(normal)) do + local normal = features.normal + if normal and next(normal) then + local f = table.sortedkeys(normal) + for i=1,#f do + local v = f[i] if v ~= "number" then t[#t+1] = v .. '=' .. tostring(normal[v]) end end end - local vtf = specification.features.vtf - if not table.is_empty(vtf) then - for _, v in pairs(table.sortedkeys(vtf)) do + local vtf = features.vtf + if vtf and next(vtf) then + local f = table.sortedkeys(vtf) + for i=1,#f do + local v = f[i] t[#t+1] = v .. '=' .. tostring(vtf[v]) end end - if next(t) then + if #t > 0 then return table.concat(t,"+") end end return "unknown" end ---~ function fonts.tfm.hash_instance(specification) + +--~ function tfm.hash_instance(specification) --~ if not specification.hash then ---~ specification.hash = fonts.tfm.hash_features(specification) +--~ specification.hash = tfm.hash_features(specification) --~ end --~ return specification.hash .. ' @ ' .. tostring(specification.size) --~ end @@ -162,14 +171,14 @@ when we get rid of base mode we can optimize even further by sharing, but then w loose our testcases for <l n='luatex'/>.</p> --ldx]]-- -function fonts.tfm.hash_instance(specification,force) +function tfm.hash_instance(specification,force) local hash, size = specification.hash, specification.size if force or not hash then - hash = fonts.tfm.hash_features(specification) + hash = tfm.hash_features(specification) specification.hash = hash end if size < 1000 and fonts.designsizes[hash] then - size = fonts.tfm.scaled(size, fonts.designsizes[hash]) + size = tfm.scaled(size, fonts.designsizes[hash]) specification.size = size end return hash .. ' @ ' .. tostring(size) @@ -193,7 +202,7 @@ function fonts.define.resolve(specification) if specification.forced == "" then specification.forced = nil end - specification.hash = specification.name .. ' @ ' .. fonts.tfm.hash_features(specification) + specification.hash = specification.name .. ' @ ' .. tfm.hash_features(specification) if specification.sub and specification.sub ~= "" then specification.hash = specification.sub .. ' @ ' .. specification.hash end @@ -216,24 +225,24 @@ features (esp in virtual fonts) so let's not do that now.</p> specification yet.</p> --ldx]]-- -function fonts.tfm.read(specification) +function tfm.read(specification) garbagecollector.push() input.starttiming(fonts) - local hash = fonts.tfm.hash_instance(specification) - local tfmtable = fonts.tfm.fonts[hash] -- hashes by size ! + 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 = fonts.tfm.readers[specification.forced](specification) + tfmtable = tfm.readers[specification.forced](specification) if not tfmtable then - logs.error("define font",string.format("forced type %s of %s not found",specification.forced,specification.name)) + logs.report("define font","forced type %s of %s not found",specification.forced,specification.name) end else - for _, reader in ipairs(fonts.tfm.readers.sequence) do - if fonts.tfm.readers[reader] then -- not really needed + for _, reader in ipairs(tfm.readers.sequence) do + if tfm.readers[reader] then -- not really needed if fonts.trace then - logs.report("define font",string.format("trying type %s for %s with file %s",reader,specification.name,specification.filename or "unknown")) + logs.report("define font","trying type %s for %s with file %s",reader,specification.name,specification.filename or "unknown") end - tfmtable = fonts.tfm.readers[reader](specification) + tfmtable = tfm.readers[reader](specification) if tfmtable then break end end end @@ -244,7 +253,7 @@ function fonts.tfm.read(specification) else tfmtable.embedding = "subset" end - fonts.tfm.fonts[hash] = tfmtable + tfm.fonts[hash] = tfmtable fonts.designsizes[specification.hash] = tfmtable.designsize -- we only know this for sure after loading once --~ tfmtable.mode = specification.features.normal.mode or "base" end @@ -252,7 +261,7 @@ function fonts.tfm.read(specification) input.stoptiming(fonts) garbagecollector.pop() if not tfmtable then - logs.error("define font",string.format("font with name %s is not found",specification.name)) + logs.report("define font","font with name %s is not found",specification.name) end return tfmtable end @@ -261,32 +270,32 @@ end <p>For virtual fonts we need a slightly different approach:</p> --ldx]]-- -function fonts.tfm.read_and_define(name,size) -- no id +function tfm.read_and_define(name,size) -- no id local specification = fonts.define.analyze(name,size,nil) if specification.method and fonts.define.specify[specification.method] then specification = fonts.define.specify[specification.method](specification) end specification = fonts.define.resolve(specification) - local hash = fonts.tfm.hash_instance(specification) - local id = fonts.tfm.internalized[hash] + local hash = tfm.hash_instance(specification) + local id = tfm.internalized[hash] if not id then - local fontdata = fonts.tfm.read(specification) + local fontdata = tfm.read(specification) if fontdata then - if not fonts.tfm.internalized[hash] then + if not tfm.internalized[hash] then id = font.define(fontdata) - fonts.tfm.id[id] = fontdata - fonts.tfm.internalized[hash] = id + tfm.id[id] = fontdata + tfm.internalized[hash] = id if fonts.trace then - logs.report("define font", string.format("loading at 1 id %s, hash: %s",id,hash)) + logs.report("define font","loading at 1 id %s, hash: %s",id,hash) end else - id = fonts.tfm.internalized[hash] + id = tfm.internalized[hash] end else id = 0 -- signal end end - return fonts.tfm.id[id], id + return tfm.id[id], id end --[[ldx-- @@ -305,25 +314,25 @@ end) evolved. Each one has its own way of dealing with its format.</p> --ldx]]-- -function fonts.tfm.readers.opentype(specification,suffix,what) +function tfm.readers.opentype(specification,suffix,what) if fonts.define.auto_otf then local fullname, tfmtable = nil, nil - fullname = input.findbinfile(texmf.instance,specification.name,suffix) or "" + 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(texmf.instance,fb,suffix) or "" + 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(texmf.instance,fb,suffix) or "" + 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 = fonts.tfm.read_from_open_type(specification) -- we need to do it for all matches / todo + tfmtable = tfm.read_from_open_type(specification) -- we need to do it for all matches / todo end return tfmtable else @@ -331,34 +340,34 @@ function fonts.tfm.readers.opentype(specification,suffix,what) end end -function fonts.tfm.readers.otf(specification) return fonts.tfm.readers.opentype(specification,"otf","opentype") end -function fonts.tfm.readers.ttf(specification) return fonts.tfm.readers.opentype(specification,"ttf","truetype") end -function fonts.tfm.readers.ttc(specification) return fonts.tfm.readers.opentype(specification,"ttf","truetype") 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 fonts.tfm.readers.afm(specification,method) +function tfm.readers.afm(specification,method) local fullname, tfmtable = nil, nil method = method or fonts.define.method if method == 2 then - fullname = input.findbinfile(texmf.instance,specification.name,"ofm") or "" + fullname = input.findbinfile(specification.name,"ofm") or "" if fullname == "" then - tfmtable = fonts.tfm.read_from_afm(specification) + tfmtable = tfm.read_from_afm(specification) else -- redundant specification.filename = fullname - tfmtable = fonts.tfm.read_from_tfm(specification) + tfmtable = tfm.read_from_tfm(specification) end elseif method == 3 then -- maybe also findbinfile here if fonts.define.auto_afm then - tfmtable = fonts.tfm.read_from_afm(specification) + tfmtable = tfm.read_from_afm(specification) end elseif method == 4 then -- maybe also findbinfile here - tfmtable = fonts.tfm.read_from_afm(specification) + tfmtable = tfm.read_from_afm(specification) end return tfmtable end -function fonts.tfm.readers.tfm(specification) +function tfm.readers.tfm(specification) local fullname, tfmtable = nil, nil - tfmtable = fonts.tfm.read_from_tfm(specification) + tfmtable = tfm.read_from_tfm(specification) return tfmtable end @@ -378,8 +387,12 @@ name*context specification --ldx]]-- function fonts.define.specify.predefined(specification) - if specification.detail ~= "" and fonts.define.methods[specification.detail] then - specification.features.vtf = { preset = specification.detail } + 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 + end end return specification end @@ -391,7 +404,7 @@ function fonts.define.specify.colonized(specification) -- xetex mode if specification.detail and specification.detail ~= "" then local expanded_features = { } local function expand(features) - for _,v in pairs(features:split(";")) do + for _,v in pairs(features:split(";")) do --just gmatch expanded_features[#expanded_features+1] = v end end @@ -415,7 +428,7 @@ function fonts.define.specify.colonized(specification) -- xetex mode return specification end -function fonts.tfm.make(specification) +function tfm.make(specification) local fvm = fonts.define.methods[specification.features.vtf.preset] if fvm then return fvm(specification) @@ -594,43 +607,46 @@ 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 + function fonts.define.read(name,size,id) local specification = fonts.define.analyze(name,size,id) if specification.method and fonts.define.specify[specification.method] then specification = fonts.define.specify[specification.method](specification) end specification = fonts.define.resolve(specification) - local hash = fonts.tfm.hash_instance(specification) + local hash = tfm.hash_instance(specification) if true then --~ local fontdata = containers.read(fonts.cache(),hash) -- for tracing purposes end - local fontdata = fonts.tfm.internalized[hash] -- id + local fontdata = tfm.internalized[hash] -- id + fonts.define.last = fontdata or id if not fontdata then if specification.features.vtf and specification.features.vtf.preset then - fontdata = fonts.tfm.make(specification) + fontdata = tfm.make(specification) else - fontdata = fonts.tfm.read(specification) + fontdata = tfm.read(specification) if fontdata then - fonts.tfm.check_virtual_id(fontdata) + tfm.check_virtual_id(fontdata) end end if true then --~ fontdata = containers.write(fonts.cache(),hash,fontdata) -- for tracing purposes end - if not fonts.tfm.internalized[hash] then - fonts.tfm.id[id] = fontdata - fonts.tfm.internalized[hash] = id + if not tfm.internalized[hash] then + tfm.id[id] = fontdata + tfm.internalized[hash] = id if fonts.trace then - logs.report("define font", string.format("loading at 2 id %s, hash: %s",id,hash)) + logs.report("define font","loading at 2 id %s, hash: %s",id,hash) end else - fontdata = fonts.tfm.internalized[hash] + fontdata = tfm.internalized[hash] end end if not fontdata then - logs.error("define font", string.format("unknown font %s, loading aborted",specification.name)) + logs.report("define font", "unknown font %s, loading aborted",specification.name) elseif fonts.trace and type(fontdata) == "table" then - logs.report("define font",string.format("using %s font with id %s, n:%s s:%s b:%s e:%s p:%s f:%s", + 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 "?", fontdata.name or "?", @@ -638,16 +654,16 @@ function fonts.define.read(name,size,id) fontdata.encodingbytes or "?", fontdata.encodingname or "unicode", fontdata.fullname or "?", - file.basename(fontdata.filename or "?"))) + file.basename(fontdata.filename or "?")) end return fontdata end ---~ table.insert(fonts.tfm.readers.sequence,1,'vtf') +--~ table.insert(tfm.readers.sequence,1,'vtf') ---~ function fonts.tfm.readers.vtf(specification) +--~ function tfm.readers.vtf(specification) --~ if specification.features.vtf and specification.features.vtf.preset then ---~ return fonts.tfm.make(specification) +--~ return tfm.make(specification) --~ else --~ return nil --~ end @@ -655,24 +671,24 @@ end function fonts.vf.find(name) name = file.removesuffix(file.basename(name)) - if fonts.tfm.resolve_vf then + if tfm.resolve_vf then local format = fonts.logger.format(name) if format == 'tfm' or format == 'ofm' then if fonts.trace then - logs.report("define font",string.format("locating vf for %s",name)) + logs.report("define font","locating vf for %s",name) end - return input.findbinfile(texmf.instance,name,"ovf") + return input.findbinfile(name,"ovf") else if fonts.trace then - logs.report("define font",string.format("vf for %s is already taken care of",name)) + logs.report("define font","vf for %s is already taken care of",name) end return nil -- "" end else if fonts.trace then - logs.report("define font",string.format("locating vf for %s",name)) + logs.report("define font","locating vf for %s",name) end - return input.findbinfile(texmf.instance,name,"ovf") + return input.findbinfile(name,"ovf") end end |