diff options
author | Karl Berry <karl@freefriends.org> | 2020-03-05 00:48:46 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2020-03-05 00:48:46 +0000 |
commit | f210bce174e1f2f05305ab03e88e120a1cbfc4da (patch) | |
tree | 5c4e2ad096b5c745e859516ac3196fa0864292d5 /Master/texmf-dist/tex/context/base/mkiv/font-tfm.lua | |
parent | 35fd641a3546acc0c62e0aa7f134888e36da30d4 (diff) |
context (from cont-tmf.zip of Feb 17 16:00, size 116339406)
git-svn-id: svn://tug.org/texlive/trunk@54086 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkiv/font-tfm.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/mkiv/font-tfm.lua | 504 |
1 files changed, 197 insertions, 307 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-tfm.lua b/Master/texmf-dist/tex/context/base/mkiv/font-tfm.lua index 6e4f8698052..e2f0d22f2a8 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-tfm.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-tfm.lua @@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['font-tfm'] = { license = "see context related readme files" } +if not context then return end -- use luatex-fonts-tfm.lua instead + local next, type = next, type local match, format = string.match, string.format local concat, sortedhash = table.concat, table.sortedhash @@ -118,266 +120,216 @@ local depth = { } -- table.setmetatableindex("number") -- -- So "czechdqcheat=yes" is then a valid feature. And yes, it's a cheat. -local read_from_tfm, check_tfm do - - local tfmreaders = context and tfm.readers - local loadtfmvf = tfmreaders and tfmreaders.loadtfmvf - local loadtfm = font.read_tfm - local loadvf = font.read_vf +local loadtfmvf = tfm.readers.loadtfmvf - directives.register("fonts.tfm.builtin",function(v) - loadtfmvf = tfmreaders and tfmreaders.loadtfmvf - if v and loadtfm then - loadtfmvf = false +local function read_from_tfm(specification) + local filename = specification.filename + local size = specification.size + depth[filename] = (depth[filename] or 0) + 1 + if trace_defining then + report_defining("loading tfm file %a at size %s",filename,size) + end + local tfmdata = loadtfmvf(filename,size) + if tfmdata then + + local features = specification.features and specification.features.normal or { } + local features = constructors.checkedfeatures("tfm",features) + specification.features.normal = features + + -- If reencode returns a new table, we assume that we're doing something + -- special. An 'auto' reencode picks up its vector from the pfb file. + + if lpdf and lpdf.getmapentry and not features.reencode then + -- This can happen multiple times but not that often so we don't + -- optimize this. + local encoding, pfbfile, encfile = lpdf.getmapentry(filename) + if encoding and pfbfile then + features.reencode = encfile + features.pfbfile = pfbfile + end end - end) - read_from_tfm = function(specification) - local filename = specification.filename - local size = specification.size - depth[filename] = (depth[filename] or 0) + 1 - if trace_defining then - report_defining("loading tfm file %a at size %s",filename,size) + local newtfmdata = (depth[filename] == 1) and tfm.reencode(tfmdata,specification) + if newtfmdata then + tfmdata = newtfmdata end - local tfmdata -- not cached, fast enough - if loadtfmvf then - tfmdata = loadtfmvf(filename,size) - else - tfmdata = loadtfm(filename,size) - end - if tfmdata then - - local features = specification.features and specification.features.normal or { } - local features = constructors.checkedfeatures("tfm",features) - specification.features.normal = features - -- If reencode returns a new table, we assume that we're doing something - -- special. An 'auto' reencode picks up its vector from the pfb file. - - local newtfmdata = (depth[filename] == 1) and tfm.reencode(tfmdata,specification) - if newtfmdata then - tfmdata = newtfmdata + local resources = tfmdata.resources or { } + local properties = tfmdata.properties or { } + local parameters = tfmdata.parameters or { } + local shared = tfmdata.shared or { } + -- + shared.features = features + shared.resources = resources + -- + properties.name = tfmdata.name -- todo: fallback + properties.fontname = tfmdata.fontname -- todo: fallback + properties.psname = tfmdata.psname -- todo: fallback + properties.fullname = tfmdata.fullname -- todo: fallback + properties.filename = specification.filename -- todo: fallback + properties.format = tfmdata.format or fonts.formats.tfm -- better than nothing + properties.usedbitmap = tfmdata.usedbitmap + -- +if lpdf and lpdf.getmapentry and newtfmdata then + properties.filename = features.pfbfile +end + -- + tfmdata.properties = properties + tfmdata.resources = resources + tfmdata.parameters = parameters + tfmdata.shared = shared + -- + shared.rawdata = { resources = resources } + shared.features = features + -- + -- The next branch is only entered when we have a proper encoded file i.e. + -- unicodes and such. It really nakes no sense to do feature juggling when + -- we have no names and unicodes. + -- + if newtfmdata then + -- + -- Some opentype processing assumes these to be present: + -- + if not resources.marks then + resources.marks = { } + end + if not resources.sequences then + resources.sequences = { } + end + if not resources.features then + resources.features = { + gsub = { }, + gpos = { }, + } + end + if not tfmdata.changed then + tfmdata.changed = { } + end + if not tfmdata.descriptions then + tfmdata.descriptions = tfmdata.characters end - - local resources = tfmdata.resources or { } - local properties = tfmdata.properties or { } - local parameters = tfmdata.parameters or { } - local shared = tfmdata.shared or { } -- - shared.features = features - shared.resources = resources + -- It might be handy to have this: -- - properties.name = tfmdata.name -- todo: fallback - properties.fontname = tfmdata.fontname -- todo: fallback - properties.psname = tfmdata.psname -- todo: fallback - properties.fullname = tfmdata.fullname -- todo: fallback - properties.filename = specification.filename -- todo: fallback - properties.format = tfmdata.format or fonts.formats.tfm -- better than nothing - properties.usedbitmap = tfmdata.usedbitmap + otf.readers.addunicodetable(tfmdata) -- - tfmdata.properties = properties - tfmdata.resources = resources - tfmdata.parameters = parameters - tfmdata.shared = shared + -- We make a pseudo opentype font, e.g. kerns and ligatures etc: -- - shared.rawdata = { resources = resources } - shared.features = features + tfmenhancers.apply(tfmdata,filename) -- - -- The next branch is only entered when we have a proper encoded file i.e. - -- unicodes and such. It really nakes no sense to do feature juggling when - -- we have no names and unicodes. + -- Now user stuff can kick in. -- - if newtfmdata then - -- - -- Some opentype processing assumes these to be present: - -- - if not resources.marks then - resources.marks = { } - end - if not resources.sequences then - resources.sequences = { } - end - if not resources.features then - resources.features = { - gsub = { }, - gpos = { }, - } - end - if not tfmdata.changed then - tfmdata.changed = { } - end - if not tfmdata.descriptions then - tfmdata.descriptions = tfmdata.characters - end - -- - -- It might be handy to have this: - -- - otf.readers.addunicodetable(tfmdata) - -- - -- We make a pseudo opentype font, e.g. kerns and ligatures etc: - -- - tfmenhancers.apply(tfmdata,filename) - -- - -- Now user stuff can kick in. - -- - constructors.applymanipulators("tfm",tfmdata,features,trace_features,report_tfm) - -- - -- As that can also mess with names and such, we are now ready for finalizing - -- the unicode information. This is a different order that for instance type one - -- (afm) files. First we try to deduce unicodes from already present information. - -- - otf.readers.unifymissing(tfmdata) - -- - -- Next we fill in the gaps, based on names from teh agl. Probably not much will - -- happen here. - -- - fonts.mappings.addtounicode(tfmdata,filename) - -- - -- The tounicode data is passed to the backend that constructs the vectors for us. - -- - tfmdata.tounicode = 1 - local tounicode = fonts.mappings.tounicode - for unicode, v in next, tfmdata.characters do - local u = v.unicode - if u then - v.tounicode = tounicode(u) - end - end - -- - -- However, when we use a bitmap font those vectors can't be constructed because - -- that information is not carried with those fonts (there is no name info, nor - -- proper index info, nor unicodes at that end). So, we provide it ourselves. - -- - if tfmdata.usedbitmap then - tfm.addtounicode(tfmdata) - end - end + constructors.applymanipulators("tfm",tfmdata,features,trace_features,report_tfm) -- - shared.processes = next(features) and tfm.setfeatures(tfmdata,features) or nil + -- As that can also mess with names and such, we are now ready for finalizing + -- the unicode information. This is a different order that for instance type one + -- (afm) files. First we try to deduce unicodes from already present information. -- - if size < 0 then - size = idiv(65536 * -size,100) - end - parameters.factor = 1 -- already scaled - parameters.units = 1000 -- just in case - parameters.size = size - parameters.slant = parameters.slant or parameters[1] or 0 - parameters.space = parameters.space or parameters[2] or 0 - parameters.space_stretch = parameters.space_stretch or parameters[3] or 0 - parameters.space_shrink = parameters.space_shrink or parameters[4] or 0 - parameters.x_height = parameters.x_height or parameters[5] or 0 - parameters.quad = parameters.quad or parameters[6] or 0 - parameters.extra_space = parameters.extra_space or parameters[7] or 0 + otf.readers.unifymissing(tfmdata) -- - constructors.enhanceparameters(parameters) -- official copies for us + -- Next we fill in the gaps, based on names from teh agl. Probably not much will + -- happen here. -- - properties.private = properties.private or tfmdata.private or privateoffset + fonts.mappings.addtounicode(tfmdata,filename) -- - if newtfmdata then - -- - -- We do nothing as we assume flat tfm files. It would become real messy - -- otherwise and I don't have something for testing on my system anyway. - -- - elseif loadtfmvf then - -- already loaded - local fonts = tfmdata.fonts - if fonts then - for i=1,#fonts do - local font = fonts[i] - local id = font.id - if not id then - local name = font.name - local size = font.size - if name and size then - local data, id = constructors.readanddefine(name,size) - if id then - font.id = id - font.name = nil - font.size = nil - end - end - end - end - end - elseif constructors.resolvevirtualtoo then - fonts.loggers.register(tfmdata,file.suffix(filename),specification) -- strange, why here - local vfname = findbinfile(specification.name, 'ovf') - if vfname and vfname ~= "" then - local vfdata = loadvf(vfname,size) - if vfdata then - local chars = tfmdata.characters - for k,v in next, vfdata.characters do - chars[k].commands = v.commands - end - properties.virtualized = true - tfmdata.fonts = vfdata.fonts - tfmdata.type = "virtual" -- else nested calls with cummulative scaling - local fontlist = vfdata.fonts - local name = file.nameonly(filename) - for i=1,#fontlist do - local n = fontlist[i].name - local s = fontlist[i].size - local d = depth[filename] - s = constructors.scaled(s,vfdata.designsize) - if d > tfm.maxnestingdepth then - report_defining("too deeply nested virtual font %a with size %a, max nesting depth %s",n,s,tfm.maxnestingdepth) - fontlist[i] = { id = 0 } - elseif (d > 1) and (s > tfm.maxnestingsize) then - report_defining("virtual font %a exceeds size %s",n,s) - fontlist[i] = { id = 0 } - else - local t, id = constructors.readanddefine(n,s) - fontlist[i] = { id = id } - end - end - end + -- The tounicode data is passed to the backend that constructs the vectors for us. + -- + tfmdata.tounicode = 1 + local tounicode = fonts.mappings.tounicode + for unicode, v in next, tfmdata.characters do + local u = v.unicode + if u then + v.tounicode = tounicode(u) end end -- - -- This is for old times sake (and context specific) so we comment it. It has - -- to do with encoding prefixes (a context naming that was later adopted by - -- the lm/gyre project) - -- - -- if not features.encoding then - -- local encoding, filename = match(properties.filename,"^(.-)%-(.*)$") - -- if filename and encoding and encodings.known and encodings.known[encoding] then - -- features.encoding = encoding - -- end - -- end - -- - -- Some afterthoughts: + -- However, when we use a bitmap font those vectors can't be constructed because + -- that information is not carried with those fonts (there is no name info, nor + -- proper index info, nor unicodes at that end). So, we provide it ourselves. -- - properties.haskerns = true - properties.hasligatures = true - properties.hasitalics = true - resources.unicodes = { } - resources.lookuptags = { } + if tfmdata.usedbitmap then + tfm.addtounicode(tfmdata) + end + end + -- + shared.processes = next(features) and tfm.setfeatures(tfmdata,features) or nil + -- + if size < 0 then + size = idiv(65536 * -size,100) + end + + parameters.factor = 1 -- already scaled + parameters.units = 1000 -- just in case + parameters.size = size + parameters.slant = parameters.slant or parameters[1] or 0 + parameters.space = parameters.space or parameters[2] or 0 + parameters.space_stretch = parameters.space_stretch or parameters[3] or 0 + parameters.space_shrink = parameters.space_shrink or parameters[4] or 0 + parameters.x_height = parameters.x_height or parameters[5] or 0 + parameters.quad = parameters.quad or parameters[6] or 0 + parameters.extra_space = parameters.extra_space or parameters[7] or 0 + -- + constructors.enhanceparameters(parameters) -- official copies for us + -- + properties.private = properties.private or tfmdata.private or privateoffset + -- + if newtfmdata then -- - depth[filename] = depth[filename] - 1 + -- We do nothing as we assume flat tfm files. It would become real messy + -- otherwise and I don't have something for testing on my system anyway. -- - return tfmdata else - depth[filename] = depth[filename] - 1 + -- already loaded + local fonts = tfmdata.fonts + if fonts then + for i=1,#fonts do + local font = fonts[i] + local id = font.id + if not id then + local name = font.name + local size = font.size + if name and size then + local data, id = constructors.readanddefine(name,size) + if id then + font.id = id + font.name = nil + font.size = nil + end + end + end + end + end end + -- + properties.haskerns = true + properties.hasligatures = true + properties.hasitalics = true + resources.unicodes = { } + resources.lookuptags = { } + -- + depth[filename] = depth[filename] - 1 + -- + return tfmdata + else + depth[filename] = depth[filename] - 1 end +end - check_tfm = function(specification,fullname) -- we could split up like afm/otf - local foundname = findbinfile(fullname, 'tfm') or "" - if foundname == "" then - foundname = findbinfile(fullname, 'ofm') or "" -- not needed in context - end - if foundname == "" then - foundname = fonts.names.getfilename(fullname,"tfm") or "" - end - if foundname ~= "" then - specification.filename = foundname - specification.format = "ofm" - return read_from_tfm(specification) - elseif trace_defining then - report_defining("loading tfm with name %a fails",specification.name) - end +local function check_tfm(specification,fullname) -- we could split up like afm/otf + local foundname = findbinfile(fullname, 'tfm') or "" + if foundname == "" then + foundname = findbinfile(fullname, 'ofm') or "" -- not needed in context + end + if foundname == "" then + foundname = fonts.names.getfilename(fullname,"tfm") or "" + end + if foundname ~= "" then + specification.filename = foundname + specification.format = "ofm" + return read_from_tfm(specification) + elseif trace_defining then + report_defining("loading tfm with name %a fails",specification.name) end - end readers.check_tfm = check_tfm @@ -437,7 +389,7 @@ do return end - local pfbfile = outfiles[tfmfile] + local pfbfile = pfbfile or outfiles[tfmfile] if pfbfile == nil then if bitmap then @@ -458,7 +410,6 @@ do local encoding = false local vector = false - if type(pfbfile) == "string" then local pfb = constructors.handlers.pfb if pfb and pfb.loadvector then @@ -490,17 +441,18 @@ do local indices = { } local parentfont = { "font", 1 } local private = tfmdata.privateoffset or constructors.privateoffset - local reported = encdone[tfmfile][encfile] - + local reported = encdone[tfmfile][encfile] -- bah, encdone for tfm or pfb ? -- create characters table + -- vector : pfbindex -> name + -- encoding : tfmindex -> name + local backmap = vector and table.swapped(vector) local done = { } -- prevent duplicate - - for index, name in sortedhash(encoding) do -- predictable order - local unicode = unicoding[name] - local original = originals[index] + for tfmindex, name in sortedhash(encoding) do -- predictable order + local original = originals[tfmindex] if original then + local unicode = unicoding[name] if unicode then original.unicode = unicode else @@ -511,17 +463,17 @@ do end end characters[unicode] = original - indices[index] = unicode + indices[tfmindex] = unicode original.name = name -- so one can lookup weird names if backmap then - original.index = backmap[name] + original.index = backmap[name] -- the pfb index else -- probably bitmap - original.commands = { parentfont, charcommand[index] } -- or "slot" - original.oindex = index + original.commands = { parentfont, charcommand[tfmindex] } -- or "slot" + original.oindex = tfmindex end done[name] = true elseif not done[name] then - report_tfm("bad index %a in font %a with name %a",index,tfmfile,name) + report_tfm("bad index %a in font %a with name %a",tfmindex,tfmfile,name) end end @@ -575,68 +527,6 @@ do end --- This code adds a ToUnicode vector for bitmap fonts. We don't bother about --- ranges because we have small fonts. it works ok with acrobat but fails with --- the other viewers (they get confused by the bitmaps I guess). - -do - - local template = [[ -/CIDInit /ProcSet findresource begin - 12 dict begin - begincmap - /CIDSystemInfo << /Registry (TeX) /Ordering (bitmap-%s) /Supplement 0 >> def - /CMapName /TeX-bitmap-%s def - /CMapType 2 def - 1 begincodespacerange - <00> <FF> - endcodespacerange - %s beginbfchar -%s - endbfchar - endcmap -CMapName currentdict /CMap defineresource pop end -end -end -]] - - local flushstreamobject = lpdf and lpdf.flushstreamobject -- context - local setfontattributes = lpdf and lpdf.setfontattributes -- context - - if not flushstreamobject then - flushstreamobject = function(data) - return pdf.obj { immediate = true, type = "stream", string = data } -- generic - end - end - - if not setfontattributes then - setfontattributes = function(id,data) - return pdf.setfontattributes(id,data) -- generic - end - end - - function tfm.addtounicode(tfmdata) - local id = tfmdata.usedbitmap - local map = { } - local char = { } -- no need for range, hardly used - for k, v in next, tfmdata.characters do - local index = v.oindex - local tounicode = v.tounicode - if index and tounicode then - map[index] = tounicode - end - end - for k, v in sortedhash(map) do - char[#char+1] = format("<%02X> <%s>",k,v) - end - char = concat(char,"\n") - local stream = format(template,id,id,#char,char) - local reference = flushstreamobject(stream,nil,true) - setfontattributes(id,format("/ToUnicode %i 0 R",reference)) - end - -end - -- Now we implement the regular features handlers. We need to convert the -- tfm specific structures to opentype structures. In basemode they are -- converted back so that is a bit of a waste but it's fast enough. |