summaryrefslogtreecommitdiff
path: root/tex/context/base/font-def.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/font-def.lua')
-rw-r--r--tex/context/base/font-def.lua336
1 files changed, 95 insertions, 241 deletions
diff --git a/tex/context/base/font-def.lua b/tex/context/base/font-def.lua
index 3a09b6664..ec9a059df 100644
--- a/tex/context/base/font-def.lua
+++ b/tex/context/base/font-def.lua
@@ -27,44 +27,32 @@ default loader that only handles <l n='tfm'/>.</p>
--ldx]]--
local fonts = fonts
-local tfm = fonts.tfm
-local vf = fonts.vf
-
-fonts.used = allocate()
-
-tfm.readers = tfm.readers or { }
-tfm.fonts = allocate()
-
-local readers = tfm.readers
-local sequence = allocate { 'otf', 'ttf', 'afm', 'tfm', 'lua' }
-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.*)
-
-fonts.definers = fonts.definers or { }
+local fontdata = fonts.hashes.identifiers
+local readers = fonts.readers
local definers = fonts.definers
+local specifiers = fonts.specifiers
+local constructors = fonts.constructors
-definers.specifiers = definers.specifiers or { }
-local specifiers = definers.specifiers
+readers.sequence = allocate { 'otf', 'ttf', 'afm', 'tfm', 'lua' } -- dfont ttc
-specifiers.variants = allocate()
-local variants = specifiers.variants
+local variants = allocate()
+specifiers.variants = variants
-definers.method = "afm or tfm" -- afm, tfm, afm or tfm, tfm or afm
definers.methods = definers.methods or { }
-local findbinfile = resolvers.findbinfile
+local internalized = allocate() -- internal tex numbers (private)
+
+
+local loadedfonts = constructors.loadedfonts
+local designsizes = constructors.designsizes
--[[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>
+<l n='tfm'/> table. But it can be handy for debugging, so we no
+longer carry this code along. Also, we now have quite some reference
+to other tables so we would end up with lots of catches.</p>
--ldx]]--
-fonts.version = 1.05
-fonts.cache = containers.define("fonts", "def", fonts.version, false)
-
--[[ldx--
<p>We can prefix a font specification by <type>name:</type> or
<type>file:</type>. The first case will result in a lookup in the
@@ -163,84 +151,6 @@ function definers.analyze(specification, size)
end
--[[ldx--
-<p>A unique hash value is generated by:</p>
---ldx]]--
-
-local sortedhashkeys = table.sortedhashkeys
-
-function tfm.hashfeatures(specification)
- local features = specification.features
- if features then
- local t, tn = { }, 0
- local normal = features.normal
- if normal and next(normal) then
- local f = sortedhashkeys(normal)
- for i=1,#f do
- local v = f[i]
- if v ~= "number" and v ~= "features" then -- i need to figure this out, features
- tn = tn + 1
- t[tn] = v .. '=' .. tostring(normal[v])
- end
- end
- end
- local vtf = features.vtf
- if vtf and next(vtf) then
- local f = sortedhashkeys(vtf)
- for i=1,#f do
- local v = f[i]
- tn = tn + 1
- t[tn] = v .. '=' .. tostring(vtf[v])
- end
- end
- -- if specification.mathsize then
- -- tn = tn + 1
- -- t[tn] = "mathsize=" .. specification.mathsize
- -- end
- if tn > 0 then
- return concat(t,"+")
- end
- end
- return "unknown"
-end
-
-fonts.designsizes = allocate()
-
---[[ldx--
-<p>In principle we can share tfm tables when we are in node for a font, but then
-we need to define a font switch as an id/attr switch which is no fun, so in that
-case users can best use dynamic features ... so, we will not use that speedup. Okay,
-when we get rid of base mode we can optimize even further by sharing, but then we
-loose our testcases for <l n='luatex'/>.</p>
---ldx]]--
-
-function tfm.hashinstance(specification,force)
- local hash, size, fallbacks = specification.hash, specification.size, specification.fallbacks
- if force or not hash then
- hash = tfm.hashfeatures(specification)
- specification.hash = hash
- end
- if size < 1000 and fonts.designsizes[hash] then
- size = math.round(tfm.scaled(size,fonts.designsizes[hash]))
- specification.size = 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]]--
@@ -310,7 +220,7 @@ function definers.resolve(specification)
end
end
--
- specification.hash = lower(specification.name .. ' @ ' .. tfm.hashfeatures(specification))
+ specification.hash = lower(specification.name .. ' @ ' .. constructors.hashfeatures(specification))
if specification.sub and specification.sub ~= "" then
specification.hash = specification.sub .. ' @ ' .. specification.hash
end
@@ -333,26 +243,48 @@ features (esp in virtual fonts) so let's not do that now.</p>
specification yet.</p>
--ldx]]--
-function tfm.read(specification)
- local hash = tfm.hashinstance(specification)
- local tfmtable = tfm.fonts[hash] -- hashes by size !
- if not tfmtable then
+-- not in context, at least not now:
+--
+-- function definers.applypostprocessors(tfmdata)
+-- local postprocessors = tfmdata.postprocessors
+-- if postprocessors then
+-- for i=1,#postprocessors do
+-- local extrahash = postprocessors[i](tfmdata) -- after scaling etc
+-- if type(extrahash) == "string" and extrahash ~= "" then
+-- -- e.g. a reencoding needs this
+-- extrahash = gsub(lower(extrahash),"[^a-z]","-")
+-- tfmdata.properties.fullname = format("%s-%s",tfmdata.properties.fullname,extrahash)
+-- end
+-- end
+-- end
+-- return tfmdata
+-- end
+
+function definers.applypostprocessors(tfmdata)
+ return tfmdata
+end
+
+function definers.loadfont(specification)
+ local hash = constructors.hashinstance(specification)
+ local tfmdata = loadedfonts[hash] -- hashes by size !
+ if not tfmdata then
local forced = specification.forced or ""
if forced ~= "" then
local reader = readers[lower(forced)]
- tfmtable = reader and reader(specification)
- if not tfmtable then
+ tfmdata = reader and reader(specification)
+ if not tfmdata then
report_defining("forced type %s of %s not found",forced,specification.name)
end
else
- for s=1,#sequence do -- reader sequence
+ local sequence = readers.sequence -- can be overloaded so only a shortcut here
+ for s=1,#sequence do
local reader = sequence[s]
- if readers[reader] then -- not really needed
+ if readers[reader] then -- we skip not loaded readers
if trace_defining then
report_defining("trying (reader sequence driven) type %s for %s with file %s",reader,specification.name,specification.filename or "unknown")
end
- tfmtable = readers[reader](specification)
- if tfmtable then
+ tfmdata = readers[reader](specification)
+ if tfmdata then
break
else
specification.filename = nil
@@ -360,82 +292,56 @@ function tfm.read(specification)
end
end
end
- if tfmtable then
+ if tfmdata then
+ local properties = tfmdata.properties
+ local embedding
if directive_embedall then
- tfmtable.embedding = "full"
- elseif tfmtable.filename and fonts.dontembed[tfmtable.filename] then
- tfmtable.embedding = "no"
+ embedding = "full"
+ elseif properties.filename and constructors.dontembed[properties.filename] then
+ embedding = "no"
else
- tfmtable.embedding = "subset"
+ embedding = "subset"
end
- -- fonts.goodies.postprocessors.apply(tfmdata) -- only here
- local postprocessors = tfmtable.postprocessors
- if postprocessors then
- for i=1,#postprocessors do
- local extrahash = postprocessors[i](tfmtable) -- after scaling etc
- if type(extrahash) == "string" and extrahash ~= "" then
- -- e.g. a reencoding needs this
- extrahash = gsub(lower(extrahash),"[^a-z]","-")
- tfmtable.fullname = format("%s-%s",tfmtable.fullname,extrahash)
- end
- end
+ if properties then
+ properties.embedding = embedding
+ else
+ tfmdata.properties = { embedding = embedding }
end
- --
- 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"
+ tfmdata = definers.applypostprocessors(tfmdata)
+ loadedfonts[hash] = tfmdata
+ designsizes[specification.hash] = tfmdata.parameters.designsize
end
end
- if not tfmtable then
+ if not tfmdata then
report_defining("font with asked name '%s' is not found using lookup '%s'",specification.name,specification.lookup)
end
- return tfmtable
+ return tfmdata
end
--[[ldx--
<p>For virtual fonts we need a slightly different approach:</p>
--ldx]]--
-function tfm.readanddefine(name,size) -- no id
+function constructors.readanddefine(name,size) -- no id -- maybe a dummy first
local specification = definers.analyze(name,size)
local method = specification.method
if method and variants[method] then
specification = variants[method](specification)
end
specification = definers.resolve(specification)
- local hash = tfm.hashinstance(specification)
+ local hash = constructors.hashinstance(specification)
local id = definers.registered(hash)
if not id then
- local tfmdata = tfm.read(specification)
+ local tfmdata = definers.loadfont(specification)
if tfmdata then
- tfmdata.hash = hash
+ tfmdata.properties.hash = hash
id = font.define(tfmdata)
definers.register(tfmdata,id)
- tfm.cleanuptable(tfmdata)
else
id = 0 -- signal
end
end
- return fonts.identifiers[id], id
-end
-
---[[ldx--
-<p>We need to check for default features. For this we provide
-a helper function.</p>
---ldx]]--
-
-function definers.check(features,defaults) -- nb adapts features !
- local done = false
- if features and next(features) then
- for k,v in next, defaults do
- if features[k] == nil then
- features[k], done = v, true
- end
- end
- else
- features, done = table.fastcopy(defaults), true
- end
- return features, done -- done signals a change
+ return fontdata[id], id
end
--[[ldx--
@@ -457,42 +363,24 @@ function definers.current() -- or maybe current
return lastdefined
end
-function definers.register(tfmdata,id) -- will be overloaded
+function definers.registered(hash)
+ local id = internalized[hash]
+ return id, id and fontdata[id]
+end
+
+function definers.register(tfmdata,id)
if tfmdata and id then
- local hash = tfmdata.hash
+ local hash = tfmdata.properties.hash
if not internalized[hash] then
+ internalized[hash] = id
if trace_defining then
report_defining("registering font, id: %s, hash: %s",id or "?",hash or "?")
end
- fonts.identifiers[id] = tfmdata
- internalized[hash] = id
+ fontdata[id] = tfmdata
end
end
end
-function definers.registered(hash) -- will be overloaded
- local id = internalized[hash]
- return id, id and fonts.identifiers[id]
-end
-
-local cache_them = false
-
-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 = definers.methods.variants[specification.features.vtf.preset]
- if fvm then
- return fvm(specification)
- else
- return nil
- end
-end
-
function definers.read(specification,size,id) -- id can be optional, name can already be table
statistics.starttiming(fonts)
if type(specification) == "string" then
@@ -503,26 +391,13 @@ function definers.read(specification,size,id) -- id can be optional, name can al
specification = variants[method](specification)
end
specification = definers.resolve(specification)
- local hash = tfm.hashinstance(specification)
- if cache_them then
- local tfmdata = containers.read(fonts.cache,hash) -- for tracing purposes
- end
+ local hash = constructors.hashinstance(specification)
local tfmdata = definers.registered(hash) -- id
if not tfmdata then
- if specification.features.vtf and specification.features.vtf.preset then
- tfmdata = tfm.make(specification)
- else
- tfmdata = tfm.read(specification)
- if tfmdata then
- tfm.checkvirtualid(tfmdata)
- end
- end
- if cache_them then
- tfmdata = containers.write(fonts.cache,hash,tfmdata) -- for tracing purposes
- end
+ tfmdata = definers.loadfont(specification) -- can be overloaded
if tfmdata then
- tfmdata.hash = hash
- tfmdata.cache = "no"
+--~ constructors.checkvirtualid(tfmdata) -- interferes
+ tfmdata.properties.hash = hash
if id then
definers.register(tfmdata,id)
end
@@ -532,46 +407,25 @@ function definers.read(specification,size,id) -- id can be optional, name can al
if not tfmdata then -- or id?
report_defining( "unknown font %s, loading aborted",specification.name)
elseif trace_defining and type(tfmdata) == "table" then
+ constructors.finalize(tfmdata)
+ -- local properties = tfmdata.properties or { }
+ -- local parameters = tfmdata.parameters or { }
report_defining("using %s font with id %s, name:%s size:%s bytes:%s encoding:%s fullname:%s filename:%s",
- tfmdata.type or "unknown",
- id or "?",
- tfmdata.name or "?",
- tfmdata.size or "default",
- tfmdata.encodingbytes or "?",
- tfmdata.encodingname or "unicode",
- tfmdata.fullname or "?",
- file.basename(tfmdata.filename or "?"))
+ properties.type or "unknown",
+ id or "?",
+ properties.name or "?",
+ parameters.size or "default",
+ properties.encodingbytes or "?",
+ properties.encodingname or "unicode",
+ properties.fullname or "?",
+ file.basename(properties.filename or "?"))
end
statistics.stoptiming(fonts)
return tfmdata
end
-function vf.find(name)
- name = file.removesuffix(file.basename(name))
- if tfm.resolvevirtualtoo then
- local format = fonts.logger.format(name)
- if format == 'tfm' or format == 'ofm' then
- if trace_defining then
- report_defining("locating vf for %s",name)
- end
- return findbinfile(name,"ovf")
- else
- if trace_defining then
- report_defining("vf for %s is already taken care of",name)
- end
- return nil -- ""
- end
- else
- if trace_defining then
- report_defining("locating vf for %s",name)
- end
- return findbinfile(name,"ovf")
- end
-end
-
--[[ldx--
-<p>We overload both the <l n='tfm'/> and <l n='vf'/> readers.</p>
+<p>We overload the <l n='tfm'/> reader.</p>
--ldx]]--
-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
+callbacks.register('define_font' , definers.read, "definition of fonts (tfmdata preparation)")