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 | 
