diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/font-afm.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/font-afm.lua | 1296 |
1 files changed, 800 insertions, 496 deletions
diff --git a/Master/texmf-dist/tex/context/base/font-afm.lua b/Master/texmf-dist/tex/context/base/font-afm.lua index 87dec59c6e6..b719a9b3156 100644 --- a/Master/texmf-dist/tex/context/base/font-afm.lua +++ b/Master/texmf-dist/tex/context/base/font-afm.lua @@ -17,29 +17,56 @@ where we handles font encodings. Eventually font encoding goes away.</p> --ldx]]-- -local trace_features = false trackers.register("afm.features", function(v) trace_features = v end) -local trace_indexing = false trackers.register("afm.indexing", function(v) trace_indexing = v end) -local trace_loading = false trackers.register("afm.loading", function(v) trace_loading = v end) +local trace_features = false trackers.register("afm.features", function(v) trace_features = v end) +local trace_indexing = false trackers.register("afm.indexing", function(v) trace_indexing = v end) +local trace_loading = false trackers.register("afm.loading", function(v) trace_loading = v end) +local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end) -local format, match, gmatch, lower, gsub = string.format, string.match, string.gmatch, string.lower, string.gsub -local lpegmatch = lpeg.match +local report_afm = logs.reporter("fonts","afm loading") + +local next, type, tonumber = next, type, tonumber +local format, match, gmatch, lower, gsub, strip = string.format, string.match, string.gmatch, string.lower, string.gsub, string.strip local abs = math.abs +local P, S, C, R, lpegmatch, patterns = lpeg.P, lpeg.S, lpeg.C, lpeg.R, lpeg.match, lpeg.patterns + +local fonts = fonts +local afm = { } +local pfb = { } +fonts.handlers.afm = afm +fonts.handlers.pfb = pfb + +afm.version = 1.410 -- incrementing this number one up will force a re-cache +afm.cache = containers.define("fonts", "afm", afm.version, true) +afm.autoprefixed = true -- this will become false some day (catches texnansi-blabla.*) -fonts = fonts or { } -fonts.afm = fonts.afm or { } +afm.syncspace = true -- when true, nicer stretch values +afm.addligatures = true -- best leave this set to true +afm.addtexligatures = true -- best leave this set to true +afm.addkerns = true -- best leave this set to true -local afm = fonts.afm -local tfm = fonts.tfm +local definers = fonts.definers +local readers = fonts.readers +local constructors = fonts.constructors -afm.version = 1.402 -- incrementing this number one up will force a re-cache -afm.syncspace = true -- when true, nicer stretch values -afm.enhance_data = true -- best leave this set to true -afm.features = { } -afm.features.aux = { } -afm.features.data = { } -afm.features.list = { } -afm.features.default = { } -afm.cache = containers.define("fonts", "afm", afm.version, true) +local findbinfile = resolvers.findbinfile + +local afmfeatures = constructors.newfeatures("afm") +local registerafmfeature = afmfeatures.register + +local function setmode(tfmdata,value) + if value then + tfmdata.properties.mode = lower(value) + end +end + +registerafmfeature { + name = "mode", + description = "mode", + initializers = { + base = setmode, + node = setmode, + } +} --[[ldx-- <p>We start with the basic reader which we give a name similar to the @@ -62,43 +89,51 @@ built in <l n='tfm'/> and <l n='otf'/> reader.</p> --~ Comment DELIM 2390 1010 --~ Comment AXISHEIGHT 250 -local c = lpeg.P("Comment") -local s = lpeg.S(" \t") -local l = lpeg.S("\n\r") -local w = lpeg.C((1 - l)^1) -local n = lpeg.C((lpeg.R("09") + lpeg.S("."))^1) / tonumber * s^0 - -local fd = { } - -local pattern = ( c * s^1 * ( - ("CODINGSCHEME" * s^1 * w ) / function(a) end + - ("DESIGNSIZE" * s^1 * n * w ) / function(a) fd[ 1] = a end + - ("CHECKSUM" * s^1 * n * w ) / function(a) fd[ 2] = a end + - ("SPACE" * s^1 * n * "plus" * n * "minus" * n) / function(a,b,c) fd[ 3], fd[ 4], fd[ 5] = a, b, c end + - ("QUAD" * s^1 * n ) / function(a) fd[ 6] = a end + - ("EXTRASPACE" * s^1 * n ) / function(a) fd[ 7] = a end + - ("NUM" * s^1 * n * n * n ) / function(a,b,c) fd[ 8], fd[ 9], fd[10] = a, b, c end + - ("DENOM" * s^1 * n * n ) / function(a,b ) fd[11], fd[12] = a, b end + - ("SUP" * s^1 * n * n * n ) / function(a,b,c) fd[13], fd[14], fd[15] = a, b, c end + - ("SUB" * s^1 * n * n ) / function(a,b) fd[16], fd[17] = a, b end + - ("SUPDROP" * s^1 * n ) / function(a) fd[18] = a end + - ("SUBDROP" * s^1 * n ) / function(a) fd[19] = a end + - ("DELIM" * s^1 * n * n ) / function(a,b) fd[20], fd[21] = a, b end + - ("AXISHEIGHT" * s^1 * n ) / function(a) fd[22] = a end + - (1-l)^0 -) + (1-c)^1)^0 +local comment = P("Comment") +local spacing = patterns.spacer -- S(" \t")^1 +local lineend = patterns.newline -- S("\n\r") +local words = C((1 - lineend)^1) +local number = C((R("09") + S("."))^1) / tonumber * spacing^0 +local data = lpeg.Carg(1) + +local pattern = ( -- needs testing ... not used anyway as we no longer need math afm's + comment * spacing * + ( + data * ( + ("CODINGSCHEME" * spacing * words ) / function(fd,a) end + + ("DESIGNSIZE" * spacing * number * words ) / function(fd,a) fd[ 1] = a end + + ("CHECKSUM" * spacing * number * words ) / function(fd,a) fd[ 2] = a end + + ("SPACE" * spacing * number * "plus" * number * "minus" * number) / function(fd,a,b,c) fd[ 3], fd[ 4], fd[ 5] = a, b, c end + + ("QUAD" * spacing * number ) / function(fd,a) fd[ 6] = a end + + ("EXTRASPACE" * spacing * number ) / function(fd,a) fd[ 7] = a end + + ("NUM" * spacing * number * number * number ) / function(fd,a,b,c) fd[ 8], fd[ 9], fd[10] = a, b, c end + + ("DENOM" * spacing * number * number ) / function(fd,a,b ) fd[11], fd[12] = a, b end + + ("SUP" * spacing * number * number * number ) / function(fd,a,b,c) fd[13], fd[14], fd[15] = a, b, c end + + ("SUB" * spacing * number * number ) / function(fd,a,b) fd[16], fd[17] = a, b end + + ("SUPDROP" * spacing * number ) / function(fd,a) fd[18] = a end + + ("SUBDROP" * spacing * number ) / function(fd,a) fd[19] = a end + + ("DELIM" * spacing * number * number ) / function(fd,a,b) fd[20], fd[21] = a, b end + + ("AXISHEIGHT" * spacing * number ) / function(fd,a) fd[22] = a end + ) + + (1-lineend)^0 + ) + + (1-comment)^1 +)^0 local function scan_comment(str) - fd = { } - lpegmatch(pattern,str) + local fd = { } + lpegmatch(pattern,str,1,fd) return fd end --- On a rainy day I will rewrite this in lpeg ... +-- On a rainy day I will rewrite this in lpeg ... or we can use the (slower) fontloader +-- as in now supports afm/pfb loading but it's not too bad to have different methods +-- for testing approaches. local keys = { } -function keys.FontName (data,line) data.metadata.fullname = line:strip() end +function keys.FontName (data,line) data.metadata.fontname = strip (line) -- get rid of spaces + data.metadata.fullname = strip (line) end function keys.ItalicAngle (data,line) data.metadata.italicangle = tonumber (line) end function keys.IsFixedPitch(data,line) data.metadata.isfixedpitch = toboolean(line,true) end function keys.CharWidth (data,line) data.metadata.charwidth = tonumber (line) end @@ -115,35 +150,35 @@ end local function get_charmetrics(data,charmetrics,vector) local characters = data.characters - local chr, str, ind = { }, "", 0 + local chr, ind = { }, 0 for k,v in gmatch(charmetrics,"([%a]+) +(.-) *;") do if k == 'C' then - if str ~= "" then characters[str] = chr end - chr = { } - str = "" v = tonumber(v) if v < 0 then - ind = ind + 1 + ind = ind + 1 -- ? else ind = v end - chr.index = ind + chr = { + index = ind + } elseif k == 'WX' then - chr.width = v + chr.width = tonumber(v) elseif k == 'N' then - str = v + characters[v] = chr elseif k == 'B' then local llx, lly, urx, ury = match(v,"^ *(.-) +(.-) +(.-) +(.-)$") chr.boundingbox = { tonumber(llx), tonumber(lly), tonumber(urx), tonumber(ury) } elseif k == 'L' then local plus, becomes = match(v,"^(.-) +(.-)$") - if not chr.ligatures then chr.ligatures = { } end - chr.ligatures[plus] = becomes + local ligatures = chr.ligatures + if ligatures then + ligatures[plus] = becomes + else + chr.ligatures = { [plus] = becomes } + end end end - if str ~= "" then - characters[str] = chr - end end local function get_kernpairs(data,kernpairs) @@ -151,105 +186,112 @@ local function get_kernpairs(data,kernpairs) for one, two, value in gmatch(kernpairs,"KPX +(.-) +(.-) +(.-)\n") do local chr = characters[one] if chr then - if not chr.kerns then chr.kerns = { } end - chr.kerns[two] = tonumber(value) + local kerns = chr.kerns + if kerns then + kerns[two] = tonumber(value) + else + chr.kerns = { [two] = tonumber(value) } + end end end end local function get_variables(data,fontmetrics) for key, rest in gmatch(fontmetrics,"(%a+) *(.-)[\n\r]") do - if keys[key] then keys[key](data,rest) end + local keyhandler = keys[key] + if keyhandler then + keyhandler(data,rest) + end end end -local function get_indexes(data,filename) - local pfbfile = file.replacesuffix(filename,"pfb") - local pfbname = resolvers.find_file(pfbfile,"pfb") or "" - if pfbname == "" then - pfbname = resolvers.find_file(file.basename(pfbfile),"pfb") or "" - end - if pfbname ~= "" then - data.luatex.filename = pfbname - local pfbblob = fontloader.open(pfbname) - if pfbblob then - local characters = data.characters - local pfbdata = fontloader.to_table(pfbblob) - --~ print(table.serialize(pfbdata)) - if pfbdata then - local glyphs = pfbdata.glyphs - if glyphs then - if trace_loading then - logs.report("load afm","getting index data from %s",pfbname) - end - -- local offset = (glyphs[0] and glyphs[0] != .notdef) or 0 - for index, glyph in next, glyphs do - local name = glyph.name - if name then - local char = characters[name] - if char then - if trace_indexing then - logs.report("load afm","glyph %s has index %s",name,index) - end - char.index = index +local function get_indexes(data,pfbname) + data.resources.filename = resolvers.unresolve(pfbname) -- no shortcut + local pfbblob = fontloader.open(pfbname) + if pfbblob then + local characters = data.characters + local pfbdata = fontloader.to_table(pfbblob) + if pfbdata then + local glyphs = pfbdata.glyphs + if glyphs then + if trace_loading then + report_afm("getting index data from %s",pfbname) + end + for index, glyph in next, glyphs do + local name = glyph.name + if name then + local char = characters[name] + if char then + if trace_indexing then + report_afm("glyph %s has index %s",name,index) end + char.index = index end end - elseif trace_loading then - logs.report("load afm","no glyph data in pfb file %s",pfbname) end elseif trace_loading then - logs.report("load afm","no data in pfb file %s",pfbname) + report_afm("no glyph data in pfb file %s",pfbname) end - fontloader.close(pfbblob) elseif trace_loading then - logs.report("load afm","invalid pfb file %s",pfbname) + report_afm("no data in pfb file %s",pfbname) end + fontloader.close(pfbblob) elseif trace_loading then - logs.report("load afm","no pfb file for %s",filename) + report_afm("invalid pfb file %s",pfbname) end end -function afm.read_afm(filename) +local function readafm(filename) local ok, afmblob, size = resolvers.loadbinfile(filename) -- has logging --- local ok, afmblob = true, file.readdata(filename) if ok and afmblob then local data = { - characters = { }, - metadata = { - version = version or '0', -- hm + resources = { + filename = resolvers.unresolve(filename), + version = afm.version, + creator = "context mkiv", + }, + properties = { + italic_correction = false, + }, + goodies = { + }, + metadata = { filename = file.removesuffix(file.basename(filename)) - } + }, + characters = { + -- a temporary store + }, + descriptions = { + -- the final store + }, } afmblob = gsub(afmblob,"StartCharMetrics(.-)EndCharMetrics", function(charmetrics) if trace_loading then - logs.report("load afm","loading char metrics") + report_afm("loading char metrics") end get_charmetrics(data,charmetrics,vector) return "" end) afmblob = gsub(afmblob,"StartKernPairs(.-)EndKernPairs", function(kernpairs) if trace_loading then - logs.report("load afm","loading kern pairs") + report_afm("loading kern pairs") end get_kernpairs(data,kernpairs) return "" end) afmblob = gsub(afmblob,"StartFontMetrics%s+([%d%.]+)(.-)EndFontMetrics", function(version,fontmetrics) if trace_loading then - logs.report("load afm","loading variables") + report_afm("loading variables") end data.afmversion = version get_variables(data,fontmetrics) data.fontdimens = scan_comment(fontmetrics) -- todo: all lpeg, no time now return "" end) - data.luatex = { } - get_indexes(data,filename) return data else if trace_loading then - logs.report("load afm","no valid afm file %s",filename) + report_afm("no valid afm file %s",filename) end return nil end @@ -261,35 +303,61 @@ by adding ligatures and kern information to the afm derived data. That way we can set them faster when defining a font.</p> --ldx]]-- +local addkerns, addligatures, addtexligatures, unify, normalize -- we will implement these later + function afm.load(filename) -- hm, for some reasons not resolved yet - filename = resolvers.find_file(filename,'afm') or "" + filename = resolvers.findfile(filename,'afm') or "" if filename ~= "" then local name = file.removesuffix(file.basename(filename)) - local data = containers.read(afm.cache(),name) - local size = lfs.attributes(filename,"size") or 0 - if not data or data.verbose ~= fonts.verbose or data.size ~= size then - logs.report("load afm", "reading %s",filename) - data = afm.read_afm(filename) + local data = containers.read(afm.cache,name) + local attr = lfs.attributes(filename) + local size, time = attr.size or 0, attr.modification or 0 + -- + local pfbfile = file.replacesuffix(name,"pfb") + local pfbname = resolvers.findfile(pfbfile,"pfb") or "" + if pfbname == "" then + pfbname = resolvers.findfile(file.basename(pfbfile),"pfb") or "" + end + local pfbsize, pfbtime = 0, 0 + if pfbname ~= "" then + local attr = lfs.attributes(pfbname) + pfbsize = attr.size or 0 + pfbtime = attr.modification or 0 + end + if not data or data.size ~= size or data.time ~= time or data.pfbsize ~= pfbsize or data.pfbtime ~= pfbtime then + report_afm( "reading %s",filename) + data = readafm(filename) if data then - -- data.luatex = data.luatex or { } - logs.report("load afm", "unifying %s",filename) - afm.unify(data,filename) - if afm.enhance_data then - logs.report("load afm", "add ligatures") - afm.add_ligatures(data,'ligatures') -- easier this way - logs.report("load afm", "add tex-ligatures") - afm.add_ligatures(data,'texligatures') -- easier this way - logs.report("load afm", "add extra kerns") - afm.add_kerns(data) -- faster this way + if pfbname ~= "" then + get_indexes(data,pfbname) + elseif trace_loading then + report_afm("no pfb file for %s",filename) + end + report_afm( "unifying %s",filename) + unify(data,filename) + if afm.addligatures then + report_afm( "add ligatures") + addligatures(data) + end + if afm.addtexligatures then + report_afm( "add tex ligatures") + addtexligatures(data) end - logs.report("load afm", "add tounicode data") - fonts.map.add_to_unicode(data,filename) + if afm.addkerns then + report_afm( "add extra kerns") + addkerns(data) + end + normalize(data) + report_afm( "add tounicode data") + fonts.mappings.addtounicode(data,filename) data.size = size - data.verbose = fonts.verbose - logs.report("load afm","saving: %s in cache",name) - data = containers.write(afm.cache(), name, data) - data = containers.read(afm.cache(),name) + data.time = time + data.pfbsize = pfbsize + data.pfbtime = pfbtime + report_afm("saving: %s in cache",name) + data = containers.write(afm.cache, name, data) + data = containers.read(afm.cache,name) end end return data @@ -298,49 +366,61 @@ function afm.load(filename) end end -function afm.unify(data, filename) - local unicodevector = fonts.enc.load('unicode').hash - local glyphs, indices, unicodes, names = { }, { }, { }, { } - local verbose, private = fonts.verbose, fonts.private +local uparser = fonts.mappings.makenameparser() + +unify = function(data, filename) + local unicodevector = fonts.encodings.agl.unicodes -- loaded runtime in context + local unicodes, names = { }, { } + local private = constructors.privateoffset + local descriptions = data.descriptions for name, blob in next, data.characters do local code = unicodevector[name] -- or characters.name_to_unicode[name] if not code then - local u = match(name,"^uni(%x+)$") - code = u and tonumber(u,16) + code = lpegmatch(uparser,name) if not code then code = private private = private + 1 - logs.report("afm glyph", "assigning private slot U+%04X for unknown glyph name %s", code, name) + report_afm("assigning private slot U+%05X for unknown glyph name %s", code, name) end end local index = blob.index unicodes[name] = code - indices[code] = index - glyphs[index] = blob names[name] = index blob.name = name - if verbose then - local bu = blob.unicode - if not bu then - blob.unicode = code - elseif type(bu) == "table" then - bu[#bu+1] = code - else - blob.unicode = { bu, code } + descriptions[code] = { + boundingbox = blob.boundingbox, + width = blob.width, + kerns = blob.kerns, + index = index, + name = name, + } + end + for unicode, description in next, descriptions do + local kerns = description.kerns + if kerns then + local krn = { } + for name, kern in next, kerns do + local unicode = unicodes[name] + if unicode then + krn[unicode] = kern + else + print(unicode,name) + end end - else - blob.index = nil + description.kerns = krn end end - data.glyphs = glyphs data.characters = nil - local luatex = data.luatex - luatex.filename = luatex.filename or file.removesuffix(file.basename(filename)) - luatex.unicodes = unicodes -- name to unicode - luatex.indices = indices -- unicode to index - luatex.marks = { } -- todo - luatex.names = names -- name to index - luatex.private = private + local resources = data.resources + local filename = resources.filename or file.removesuffix(file.basename(filename)) + resources.filename = resolvers.unresolve(filename) -- no shortcut + resources.unicodes = unicodes -- name to unicode + resources.marks = { } -- todo + resources.names = names -- name to index + resources.private = private +end + +normalize = function(data) end --[[ldx-- @@ -348,22 +428,79 @@ end and extra kerns. This saves quite some lookups later.</p> --ldx]]-- -function afm.add_ligatures(afmdata,ligatures) - local glyphs, luatex = afmdata.glyphs, afmdata.luatex - local indices, unicodes, names = luatex.indices, luatex.unicodes, luatex.names - for k,v in next, characters[ligatures] do -- main characters table - local one = glyphs[names[k]] +--[[ldx-- +<p>Only characters with a code smaller than 128 make sense, +anything larger is encoding dependent. An interesting complication +is that a character can be in an encoding twice but is hashed +once.</p> +--ldx]]-- + +local ligatures = { -- okay, nowadays we could parse the name but type 1 fonts + ['f'] = { -- don't have that many ligatures anyway + { 'f', 'ff' }, + { 'i', 'fi' }, + { 'l', 'fl' }, + }, + ['ff'] = { + { 'i', 'ffi' } + }, + ['fi'] = { + { 'i', 'fii' } + }, + ['fl'] = { + { 'i', 'fli' } + }, + ['s'] = { + { 't', 'st' } + }, + ['i'] = { + { 'j', 'ij' } + }, +} + +local texligatures = { + -- ['space'] = { + -- { 'L', 'Lslash' }, + -- { 'l', 'lslash' } + -- }, + -- ['question'] = { + -- { 'quoteleft', 'questiondown' } + -- }, + -- ['exclam'] = { + -- { 'quoteleft', 'exclamdown' } + -- }, + ['quoteleft'] = { + { 'quoteleft', 'quotedblleft' } + }, + ['quoteright'] = { + { 'quoteright', 'quotedblright' } + }, + ['hyphen'] = { + { 'hyphen', 'endash' } + }, + ['endash'] = { + { 'hyphen', 'emdash' } + } +} + +local addthem = function(rawdata,ligatures) + local descriptions = rawdata.descriptions + local resources = rawdata.resources + local unicodes = resources.unicodes + local names = resources.names + for ligname, ligdata in next, ligatures do + local one = descriptions[unicodes[ligname]] if one then - for _, b in next, v do - two, three = b[1], b[2] - if two and three and names[two] and names[three] then - local ol = one[ligatures] + for _, pair in next, ligdata do + local two, three = unicodes[pair[1]], unicodes[pair[2]] + if two and three then + local ol = one.ligatures if ol then - if not ol[two] then -- was one.ligatures ... bug + if not ol[two] then ol[two] = three end else - one[ligatures] = { [two] = three } + one.ligatures = { [two] = three } end end end @@ -371,50 +508,223 @@ function afm.add_ligatures(afmdata,ligatures) end end +addligatures = function(rawdata) addthem(rawdata,ligatures ) end +addtexligatures = function(rawdata) addthem(rawdata,texligatures) end + --[[ldx-- <p>We keep the extra kerns in separate kerning tables so that we can use them selectively.</p> --ldx]]-- -function afm.add_kerns(afmdata) - local glyphs = afmdata.glyphs - local names = afmdata.luatex.names - local uncomposed = characters.uncomposed +-- This is rather old code (from the beginning when we had only tfm). If +-- we unify the afm data (now we have names all over the place) then +-- we can use shcodes but there will be many more looping then. But we +-- could get rid of the tables in char-cmp then. Als, in the generic version +-- we don't use the character database. (Ok, we can have a context specific +-- variant). + +-- we can make them numbers + +local left = { + AEligature = "A", aeligature = "a", + OEligature = "O", oeligature = "o", + IJligature = "I", ijligature = "i", + AE = "A", ae = "a", + OE = "O", oe = "o", + IJ = "I", ij = "i", + Ssharp = "S", ssharp = "s", +} + +local right = { + AEligature = "E", aeligature = "e", + OEligature = "E", oeligature = "e", + IJligature = "J", ijligature = "j", + AE = "E", ae = "e", + OE = "E", oe = "e", + IJ = "J", ij = "j", + Ssharp = "S", ssharp = "s", +} + +local both = { + Acircumflex = "A", acircumflex = "a", + Ccircumflex = "C", ccircumflex = "c", + Ecircumflex = "E", ecircumflex = "e", + Gcircumflex = "G", gcircumflex = "g", + Hcircumflex = "H", hcircumflex = "h", + Icircumflex = "I", icircumflex = "i", + Jcircumflex = "J", jcircumflex = "j", + Ocircumflex = "O", ocircumflex = "o", + Scircumflex = "S", scircumflex = "s", + Ucircumflex = "U", ucircumflex = "u", + Wcircumflex = "W", wcircumflex = "w", + Ycircumflex = "Y", ycircumflex = "y", + + Agrave = "A", agrave = "a", + Egrave = "E", egrave = "e", + Igrave = "I", igrave = "i", + Ograve = "O", ograve = "o", + Ugrave = "U", ugrave = "u", + Ygrave = "Y", ygrave = "y", + + Atilde = "A", atilde = "a", + Itilde = "I", itilde = "i", + Otilde = "O", otilde = "o", + Utilde = "U", utilde = "u", + Ntilde = "N", ntilde = "n", + + Adiaeresis = "A", adiaeresis = "a", Adieresis = "A", adieresis = "a", + Ediaeresis = "E", ediaeresis = "e", Edieresis = "E", edieresis = "e", + Idiaeresis = "I", idiaeresis = "i", Idieresis = "I", idieresis = "i", + Odiaeresis = "O", odiaeresis = "o", Odieresis = "O", odieresis = "o", + Udiaeresis = "U", udiaeresis = "u", Udieresis = "U", udieresis = "u", + Ydiaeresis = "Y", ydiaeresis = "y", Ydieresis = "Y", ydieresis = "y", + + Aacute = "A", aacute = "a", + Cacute = "C", cacute = "c", + Eacute = "E", eacute = "e", + Iacute = "I", iacute = "i", + Lacute = "L", lacute = "l", + Nacute = "N", nacute = "n", + Oacute = "O", oacute = "o", + Racute = "R", racute = "r", + Sacute = "S", sacute = "s", + Uacute = "U", uacute = "u", + Yacute = "Y", yacute = "y", + Zacute = "Z", zacute = "z", + + Dstroke = "D", dstroke = "d", + Hstroke = "H", hstroke = "h", + Tstroke = "T", tstroke = "t", + + Cdotaccent = "C", cdotaccent = "c", + Edotaccent = "E", edotaccent = "e", + Gdotaccent = "G", gdotaccent = "g", + Idotaccent = "I", idotaccent = "i", + Zdotaccent = "Z", zdotaccent = "z", + + Amacron = "A", amacron = "a", + Emacron = "E", emacron = "e", + Imacron = "I", imacron = "i", + Omacron = "O", omacron = "o", + Umacron = "U", umacron = "u", + + Ccedilla = "C", ccedilla = "c", + Kcedilla = "K", kcedilla = "k", + Lcedilla = "L", lcedilla = "l", + Ncedilla = "N", ncedilla = "n", + Rcedilla = "R", rcedilla = "r", + Scedilla = "S", scedilla = "s", + Tcedilla = "T", tcedilla = "t", + + Ohungarumlaut = "O", ohungarumlaut = "o", + Uhungarumlaut = "U", uhungarumlaut = "u", + + Aogonek = "A", aogonek = "a", + Eogonek = "E", eogonek = "e", + Iogonek = "I", iogonek = "i", + Uogonek = "U", uogonek = "u", + + Aring = "A", aring = "a", + Uring = "U", uring = "u", + + Abreve = "A", abreve = "a", + Ebreve = "E", ebreve = "e", + Gbreve = "G", gbreve = "g", + Ibreve = "I", ibreve = "i", + Obreve = "O", obreve = "o", + Ubreve = "U", ubreve = "u", + + Ccaron = "C", ccaron = "c", + Dcaron = "D", dcaron = "d", + Ecaron = "E", ecaron = "e", + Lcaron = "L", lcaron = "l", + Ncaron = "N", ncaron = "n", + Rcaron = "R", rcaron = "r", + Scaron = "S", scaron = "s", + Tcaron = "T", tcaron = "t", + Zcaron = "Z", zcaron = "z", + + dotlessI = "I", dotlessi = "i", + dotlessJ = "J", dotlessj = "j", + + AEligature = "AE", aeligature = "ae", AE = "AE", ae = "ae", + OEligature = "OE", oeligature = "oe", OE = "OE", oe = "oe", + IJligature = "IJ", ijligature = "ij", IJ = "IJ", ij = "ij", + + Lstroke = "L", lstroke = "l", Lslash = "L", lslash = "l", + Ostroke = "O", ostroke = "o", Oslash = "O", oslash = "o", + + Ssharp = "SS", ssharp = "ss", + + Aumlaut = "A", aumlaut = "a", + Eumlaut = "E", eumlaut = "e", + Iumlaut = "I", iumlaut = "i", + Oumlaut = "O", oumlaut = "o", + Uumlaut = "U", uumlaut = "u", + +} + +addkerns = function(rawdata) -- using shcodes is not robust here + local descriptions = rawdata.descriptions + local resources = rawdata.resources + local unicodes = resources.unicodes local function do_it_left(what) - for index, glyph in next, glyphs do - local kerns = glyph.kerns + for unicode, description in next, descriptions do + local kerns = description.kerns if kerns then - local extrakerns = glyph.extrakerns or { } - for complex, simple in next, uncomposed[what] do - if names[compex] then + local extrakerns + for complex, simple in next, what do + complex = unicodes[complex] + simple = unicodes[simple] + if complex and simple then local ks = kerns[simple] if ks and not kerns[complex] then - extrakerns[complex] = ks + if extrakerns then + extrakerns[complex] = ks + else + extrakerns = { [complex] = ks } + end end end end - if next(extrakerns) then - glyph.extrakerns = extrakerns + if extrakerns then + description.extrakerns = extrakerns end end end end local function do_it_copy(what) - for complex, simple in next, uncomposed[what] do - local c = glyphs[names[complex]] - if c then -- optional - local s = glyphs[names[simple]] - if s then - if not c.kerns then - c.extrakerns = s.kerns or { } - end - if s.extrakerns then - local extrakerns = c.extrakerns or { } - for k, v in next, s.extrakerns do - extrakerns[k] = v + for complex, simple in next, what do + complex = unicodes[complex] + simple = unicodes[simple] + if complex and simple then + local complexdescription = descriptions[complex] + if complexdescription then -- optional + local simpledescription = descriptions[complex] + if simpledescription then + local extrakerns + local kerns = simpledescription.kerns + if kerns then + for unicode, kern in next, kerns do + if extrakerns then + extrakerns[unicode] = kern + else + extrakerns = { [unicode] = kern } + end + end + end + local extrakerns = simpledescription.extrakerns + if extrakerns then + for unicode, kern in next, extrakerns do + if extrakerns then + extrakerns[unicode] = kern + else + extrakerns = { [unicode] = kern } + end + end end - if next(extrakerns) then - s.extrakerns = extrakerns + if extrakerns then + complexdescription.extrakerns = extrakerns end end end @@ -422,152 +732,157 @@ function afm.add_kerns(afmdata) end end -- add complex with values of simplified when present - do_it_left("left") - do_it_left("both") + do_it_left(left) + do_it_left(both) -- copy kerns from simple char to complex char unless set - do_it_copy("both") - do_it_copy("right") + do_it_copy(both) + do_it_copy(right) end --[[ldx-- <p>The copying routine looks messy (and is indeed a bit messy).</p> --ldx]]-- --- once we have otf sorted out (new format) we can try to make the afm --- cache similar to it (similar tables) - -function afm.add_dimensions(data) -- we need to normalize afm to otf i.e. indexed table instead of name +local function adddimensions(data) -- we need to normalize afm to otf i.e. indexed table instead of name if data then - for index, glyph in next, data.glyphs do - local bb = glyph.boundingbox + for unicode, description in next, data.descriptions do + local bb = description.boundingbox if bb then local ht, dp = bb[4], -bb[2] if ht == 0 or ht < 0 then -- no need to set it and no negative heights, nil == 0 else - glyph.height = ht + description.height = ht end if dp == 0 or dp < 0 then -- no negative depths and no negative depths, nil == 0 else - glyph.depth = dp + description.depth = dp end end end end end -fonts.formats.afm = "type1" -fonts.formats.pfb = "type1" - -function afm.copy_to_tfm(data) - if data then - local glyphs = data.glyphs - if glyphs then - local metadata, luatex = data.metadata, data.luatex - local unicodes, indices = luatex.unicodes, luatex.indices - local characters, parameters, descriptions = { }, { }, { } - -- todo : merge into tfm - for u, i in next, indices do - local d = glyphs[i] - characters[u] = { } - descriptions[u] = d +local function copytotfm(data) + if data and data.descriptions then + local metadata = data.metadata + local resources = data.resources + local properties = table.derive(data.properties) + local descriptions = table.derive(data.descriptions) + local goodies = table.derive(data.goodies) + local characters = { } + local parameters = { } + local unicodes = resources.unicodes + -- + for unicode, description in next, data.descriptions do -- use parent table + characters[unicode] = { } + end + -- + local filename = constructors.checkedfilename(resources) + local fontname = metadata.fontname or metadata.fullname + local fullname = metadata.fullname or metadata.fontname + local endash = unicodes['space'] + local emdash = unicodes['emdash'] + local spacer = "space" + local spaceunits = 500 + -- + local monospaced = metadata.isfixedpitch + local charwidth = metadata.charwidth + local italicangle = metadata.italicangle + local charxheight = metadata.xheight and metadata.xheight > 0 and metadata.xheight + properties.monospaced = monospaced + parameters.italicangle = italicangle + parameters.charwidth = charwidth + parameters.charxheight = charxheight + -- same as otf + if properties.monospaced then + if descriptions[endash] then + spaceunits, spacer = descriptions[endash].width, "space" end - local filename = fonts.tfm.checked_filename(luatex) -- was metadata.filename - local fontname = metadata.fontname or metadata.fullname - local fullname = metadata.fullname or metadata.fontname - local endash, emdash, space, spaceunits = unicodes['space'], unicodes['emdash'], "space", 500 - -- same as otf - if metadata.isfixedpitch then - if descriptions[endash] then - spaceunits, spacer = descriptions[endash].width, "space" - end - if not spaceunits and descriptions[emdash] then - spaceunits, spacer = descriptions[emdash].width, "emdash" - end - if not spaceunits and metadata.charwidth then - spaceunits, spacer = metadata.charwidth, "charwidth" - end - else - if descriptions[endash] then - spaceunits, spacer = descriptions[endash].width, "space" - end - if not spaceunits and metadata.charwidth then - spaceunits, spacer = metadata.charwidth, "charwidth" - end + if not spaceunits and descriptions[emdash] then + spaceunits, spacer = descriptions[emdash].width, "emdash" end - spaceunits = tonumber(spaceunits) - if spaceunits < 200 then - -- todo: warning + if not spaceunits and charwidth then + spaceunits, spacer = charwidth, "charwidth" end - -- - parameters.slant = 0 - parameters.space = spaceunits - parameters.space_stretch = 500 - parameters.space_shrink = 333 - parameters.x_height = 400 - parameters.quad = 1000 - local italicangle = data.metadata.italicangle - if italicangle then - parameters.slant = parameters.slant - math.round(math.tan(italicangle*math.pi/180)) + else + if descriptions[endash] then + spaceunits, spacer = descriptions[endash].width, "space" end - if metadata.isfixedpitch then - parameters.space_stretch = 0 - parameters.space_shrink = 0 - elseif afm.syncspace then - parameters.space_stretch = spaceunits/2 - parameters.space_shrink = spaceunits/3 + if not spaceunits and charwidth then + spaceunits, spacer = charwidth, "charwidth" end - parameters.extra_space = parameters.space_shrink - if metadata.xheight and metadata.xheight > 0 then - parameters.x_height = metadata.xheight - else - -- same as otf - local x = unicodes['x'] + end + spaceunits = tonumber(spaceunits) + if spaceunits < 200 then + -- todo: warning + end + -- + parameters.slant = 0 + parameters.space = spaceunits + parameters.space_stretch = 500 + parameters.space_shrink = 333 + parameters.x_height = 400 + parameters.quad = 1000 + -- + if italicangle then + parameters.italicangle = italicangle + parameters.italicfactor = math.cos(math.rad(90+italicangle)) + parameters.slant = - math.round(math.tan(italicangle*math.pi/180)) + end + if monospaced then + parameters.space_stretch = 0 + parameters.space_shrink = 0 + elseif afm.syncspace then + parameters.space_stretch = spaceunits/2 + parameters.space_shrink = spaceunits/3 + end + parameters.extra_space = parameters.space_shrink + if charxheight then + parameters.x_height = charxheight + else + -- same as otf + local x = unicodes['x'] + if x then + local x = descriptions[x] if x then - local x = descriptions[x] - if x then - parameters.x_height = x.height - end - end - -- - end - local fd = data.fontdimens - if fd and fd[8] and fd[9] and fd[10] then -- math - for k,v in next, fd do - parameters[k] = v + parameters.x_height = x.height end end -- - if next(characters) then - return { - characters = characters, - parameters = parameters, - descriptions = descriptions, - indices = indices, - unicodes = unicodes, - luatex = luatex, - encodingbytes = 2, - filename = filename, - fontname = fontname, - fullname = fullname, - psname = fullname, -- in otf: tfm.fontname or tfm.fullname - name = filename or fullname or fontname, - format = fonts.fontformat(filename,"type1"), - type = 'real', - units = 1000, - direction = 0, - boundarychar_label = 0, - boundarychar = 65536, - --~ false_boundarychar = 65536, -- produces invalid tfm in luatex - designsize = (metadata.designsize or 10)*65536, - spacer = spacer, - ascender = abs(metadata.ascender or 0), - descender = abs(metadata.descender or 0), - italicangle = italicangle, - } + end + local fd = data.fontdimens + if fd and fd[8] and fd[9] and fd[10] then -- math + for k,v in next, fd do + parameters[k] = v end end + -- + parameters.designsize = (metadata.designsize or 10)*65536 + parameters.ascender = abs(metadata.ascender or 0) + parameters.descender = abs(metadata.descender or 0) + parameters.units = 1000 + -- + properties.spacer = spacer + properties.encodingbytes = 2 + properties.format = fonts.formats[filename] or "type1" + properties.filename = filename + properties.fontname = fontname + properties.fullname = fullname + properties.psname = fullname + properties.name = filename or fullname or fontname + -- + if next(characters) then + return { + characters = characters, + descriptions = descriptions, + parameters = parameters, + resources = resources, + properties = properties, + goodies = goodies, + } + end end return nil end @@ -579,118 +894,61 @@ to treat this fontformat like any other and handle features in a more configurable way.</p> --ldx]]-- -function afm.features.register(name,default) - afm.features.list[#afm.features.list+1] = name - afm.features.default[name] = default -end - -function afm.set_features(tfmdata) - local shared = tfmdata.shared - local afmdata = shared.afmdata - local features = shared.features - if features and next(features) then - local mode = tfmdata.mode or fonts.mode - local initializers = fonts.initializers - local fi = initializers[mode] - local fiafm = fi and fi.afm - if fiafm then - local lists = { - fonts.triggers, - afm.features.list, - fonts.manipulators, - } - for l=1,3 do - local list = lists[l] - if list then - for i=1,#list do - local f = list[i] - local value = features[f] - if value and fiafm[f] then -- brr - if trace_features then - logs.report("define afm","initializing feature %s to %s for mode %s for font %s",f,tostring(value),mode or 'unknown',tfmdata.name or 'unknown') - end - fiafm[f](tfmdata,value) - mode = tfmdata.mode or fonts.mode - fiafm = initializers[mode].afm - end - end - end - end - end - local fm = fonts.methods[mode] - local fmafm = fm and fm.afm - if fmfm then - local lists = { - afm.features.list, - } - local sp = shared.processors - for l=1,1 do - local list = lists[l] - if list then - for i=1,#list do - local f = list[i] - if features[f] and fmafm[f] then -- brr - if not sp then - sp = { fmafm[f] } - shared.processors = sp - else - sp[#sp+1] = fmafm[f] - end - end - end - end - end - end +function afm.setfeatures(tfmdata,features) + local okay = constructors.initializefeatures("afm",tfmdata,features,trace_features,report_afm) + if okay then + return constructors.collectprocessors("afm",tfmdata,features,trace_features,report_afm) + else + return { } -- will become false end end -function afm.check_features(specification) - local features, done = fonts.define.check(specification.features.normal,afm.features.default) - if done then - specification.features.normal = features - tfm.hash_instance(specification,true) - end +local function checkfeatures(specification) end -function afm.afm_to_tfm(specification) +local function afmtotfm(specification) local afmname = specification.filename or specification.name if specification.forced == "afm" or specification.format == "afm" then -- move this one up if trace_loading then - logs.report("load afm","forcing afm format for %s",afmname) + report_afm("forcing afm format for %s",afmname) end else - local tfmname = resolvers.findbinfile(afmname,"ofm") or "" + local tfmname = findbinfile(afmname,"ofm") or "" if tfmname ~= "" then if trace_loading then - logs.report("load afm","fallback from afm to tfm for %s",afmname) + report_afm("fallback from afm to tfm for %s",afmname) end - afmname = "" + return -- just that end end - if afmname == "" then - return nil - else - afm.check_features(specification) - specification = fonts.define.resolve(specification) -- new, was forgotten - local features = specification.features.normal + if afmname ~= "" then + -- weird, isn't this already done then? + local features = constructors.checkedfeatures("afm",specification.features.normal) + specification.features.normal = features + constructors.hashinstance(specification,true) -- also weird here + -- + specification = definers.resolve(specification) -- new, was forgotten local cache_id = specification.hash - local tfmdata = containers.read(tfm.cache(), cache_id) -- cache with features applied + local tfmdata = containers.read(constructors.cache, cache_id) -- cache with features applied if not tfmdata then - local afmdata = afm.load(afmname) - if afmdata and next(afmdata) then - afm.add_dimensions(afmdata) - tfmdata = afm.copy_to_tfm(afmdata) + local rawdata = afm.load(afmname) + if rawdata and next(rawdata) then + adddimensions(rawdata) + tfmdata = copytotfm(rawdata) if tfmdata and next(tfmdata) then - tfmdata.shared = tfmdata.shared or { } - tfmdata.unique = tfmdata.unique or { } - tfmdata.shared.afmdata = afmdata - tfmdata.shared.features = features - afm.set_features(tfmdata) + local shared = tfmdata.shared + if not shared then + shared = { } + tfmdata.shared = shared + end + shared.rawdata = rawdata + shared.features = features + shared.processes = afm.setfeatures(tfmdata,features) end elseif trace_loading then - logs.report("load afm","no (valid) afm file found with name %s",afmname) + report_afm("no (valid) afm file found with name %s",afmname) end - tfmdata = containers.write(tfm.cache(),cache_id,tfmdata) + tfmdata = containers.write(constructors.cache,cache_id,tfmdata) end return tfmdata end @@ -704,37 +962,15 @@ those cases, but now that we can handle <l n='opentype'/> directly we no longer need this features.</p> --ldx]]-- -tfm.default_encoding = 'unicode' - -function tfm.set_normal_feature(specification,name,value) - if specification and name then - specification.features = specification.features or { } - specification.features.normal = specification.features.normal or { } - specification.features.normal[name] = value +local function read_from_afm(specification) + local tfmdata = afmtotfm(specification) + if tfmdata then + tfmdata.properties.name = specification.name + tfmdata = constructors.scale(tfmdata, specification) + constructors.applymanipulators("afm",tfmdata,specification.features.normal,trace_features,report_afm) + fonts.loggers.register(tfmdata,'afm',specification) end -end - -function tfm.read_from_afm(specification) - local tfmtable = afm.afm_to_tfm(specification) - if tfmtable then - tfmtable.name = specification.name - tfmtable = tfm.scale(tfmtable, specification.size, specification.relativeid) - local afmdata = tfmtable.shared.afmdata ---~ local filename = afmdata and afmdata.luatex and afmdata.luatex.filename ---~ if filename then ---~ tfmtable.encodingbytes = 2 ---~ tfmtable.filename = resolvers.findbinfile(filename,"") or filename ---~ tfmtable.fontname = afmdata.metadata.fontname or afmdata.metadata.fullname ---~ tfmtable.fullname = afmdata.metadata.fullname or afmdata.metadata.fontname ---~ tfmtable.format = 'type1' ---~ tfmtable.name = afmdata.luatex.filename or tfmtable.fullname ---~ end - if fonts.dontembed[filename] then - tfmtable.file = nil -- or filename ? - end - fonts.logger.save(tfmtable,'afm',specification) - end - return tfmtable + return tfmdata end --[[ldx-- @@ -742,40 +978,34 @@ end those that make sense for this format.</p> --ldx]]-- -function afm.features.prepare_ligatures(tfmdata,ligatures,value) +local function prepareligatures(tfmdata,ligatures,value) if value then - local afmdata = tfmdata.shared.afmdata - local luatex = afmdata.luatex - local unicodes = luatex.unicodes local descriptions = tfmdata.descriptions - for u, chr in next, tfmdata.characters do - local d = descriptions[u] - local l = d[ligatures] - if l then - local ligatures = chr.ligatures - if not ligatures then - ligatures = { } - chr.ligatures = ligatures + for unicode, character in next, tfmdata.characters do + local description = descriptions[unicode] + local dligatures = description.ligatures + if dligatures then + local cligatures = character.ligatures + if not cligatures then + cligatures = { } + character.ligatures = cligatures end - for k, v in next, l do - local uk, uv = unicodes[k], unicodes[v] - if uk and uv then - ligatures[uk] = { - char = uv, - type = 0 - } - end + for unicode, ligature in next, dligatures do + cligatures[unicode] = { + char = ligature, + type = 0 + } end end end end end -function afm.features.prepare_kerns(tfmdata,kerns,value) +local function preparekerns(tfmdata,kerns,value) if value then - local afmdata = tfmdata.shared.afmdata - local luatex = afmdata.luatex - local unicodes = luatex.unicodes + local rawdata = tfmdata.shared.rawdata + local resources = rawdata.resources + local unicodes = resources.unicodes local descriptions = tfmdata.descriptions for u, chr in next, tfmdata.characters do local d = descriptions[u] @@ -797,59 +1027,133 @@ function afm.features.prepare_kerns(tfmdata,kerns,value) end end --- hm, register? - -function fonts.initializers.base.afm.ligatures (tfmdata,value) afm.features.prepare_ligatures(tfmdata,'ligatures', value) end -function fonts.initializers.base.afm.texligatures(tfmdata,value) afm.features.prepare_ligatures(tfmdata,'texligatures',value) end -function fonts.initializers.base.afm.kerns (tfmdata,value) afm.features.prepare_kerns (tfmdata,'kerns', value) end -function fonts.initializers.base.afm.extrakerns (tfmdata,value) afm.features.prepare_kerns (tfmdata,'extrakerns', value) end - -afm.features.register('liga',true) -afm.features.register('kerns',true) -afm.features.register('extrakerns') -- needed? - -fonts.initializers.node.afm.ligatures = fonts.initializers.base.afm.ligatures -fonts.initializers.node.afm.texligatures = fonts.initializers.base.afm.texligatures -fonts.initializers.node.afm.kerns = fonts.initializers.base.afm.kerns -fonts.initializers.node.afm.extrakerns = fonts.initializers.base.afm.extrakerns - -fonts.initializers.base.afm.liga = fonts.initializers.base.afm.ligatures -fonts.initializers.node.afm.liga = fonts.initializers.base.afm.ligatures -fonts.initializers.base.afm.tlig = fonts.initializers.base.afm.texligatures -fonts.initializers.node.afm.tlig = fonts.initializers.base.afm.texligatures +local list = { + -- [0x0022] = 0x201D, + [0x0027] = 0x2019, + -- [0x0060] = 0x2018, +} -fonts.initializers.base.afm.trep = tfm.replacements -fonts.initializers.node.afm.trep = tfm.replacements +local function texreplacements(tfmdata,value) + local descriptions = tfmdata.descriptions + local characters = tfmdata.characters + for k, v in next, list do + characters [k] = characters [v] -- we forget about kerns + descriptions[k] = descriptions[v] -- we forget about kerns + end +end -afm.features.register('tlig',true) -- todo: also proper features for afm -afm.features.register('trep',true) -- todo: also proper features for afm +local function ligatures (tfmdata,value) prepareligatures(tfmdata,'ligatures', value) end +local function texligatures(tfmdata,value) prepareligatures(tfmdata,'texligatures',value) end +local function kerns (tfmdata,value) preparekerns (tfmdata,'kerns', value) end +local function extrakerns (tfmdata,value) preparekerns (tfmdata,'extrakerns', value) end --- tfm features +registerafmfeature { + name = "liga", + description = "traditional ligatures", + initializers = { + base = ligatures, + node = ligatures, + } +} -fonts.initializers.base.afm.equaldigits = fonts.initializers.common.equaldigits -fonts.initializers.node.afm.equaldigits = fonts.initializers.common.equaldigits -fonts.initializers.base.afm.lineheight = fonts.initializers.common.lineheight -fonts.initializers.node.afm.lineheight = fonts.initializers.common.lineheight +registerafmfeature { + name = "kern", + description = "intercharacter kerning", + initializers = { + base = kerns, + node = kerns, + } +} --- vf features +registerafmfeature { + name = "extrakerns", + description = "additional intercharacter kerning", + initializers = { + base = extrakerns, + node = extrakerns, + } +} -fonts.initializers.base.afm.compose = fonts.initializers.common.compose -fonts.initializers.node.afm.compose = fonts.initializers.common.compose +registerafmfeature { + name = 'tlig', + description = 'tex ligatures', + initializers = { + base = texligatures, + node = texligatures, + } +} --- afm specific, encodings ...kind of obsolete +registerafmfeature { + name = 'trep', + description = 'tex replacements', + initializers = { + base = texreplacements, + node = texreplacements, + } +} -afm.features.register('encoding') +-- readers -fonts.initializers.base.afm.encoding = fonts.initializers.common.encoding -fonts.initializers.node.afm.encoding = fonts.initializers.common.encoding +local check_tfm = readers.check_tfm --- todo: oldstyle smallcaps as features for afm files (use with care) +fonts.formats.afm = "type1" +fonts.formats.pfb = "type1" -fonts.initializers.base.afm.onum = fonts.initializers.common.oldstyle -fonts.initializers.base.afm.smcp = fonts.initializers.common.smallcaps -fonts.initializers.base.afm.fkcp = fonts.initializers.common.fakecaps +local function check_afm(specification,fullname) + local foundname = findbinfile(fullname, 'afm') or "" -- just to be sure + if foundname == "" then + foundname = fonts.names.getfilename(fullname,"afm") + end + if foundname == "" and afm.autoprefixed then + local encoding, shortname = match(fullname,"^(.-)%-(.*)$") -- context: encoding-name.* + if encoding and shortname and fonts.encodings.known[encoding] then + shortname = findbinfile(shortname,'afm') or "" -- just to be sure + if shortname ~= "" then + foundname = shortname + if trace_defining then + report_afm("stripping encoding prefix from filename %s",afmname) + end + end + end + end + if foundname ~= "" then + specification.filename = foundname + specification.format = "afm" + return read_from_afm(specification) + end +end -afm.features.register('onum',false) -afm.features.register('smcp',false) -afm.features.register('fkcp',false) +function readers.afm(specification,method) + local fullname, tfmdata = specification.filename or "", nil + if fullname == "" then + local forced = specification.forced or "" + if forced ~= "" then + tfmdata = check_afm(specification,specification.name .. "." .. forced) + end + if not tfmdata then + method = method or definers.method or "afm or tfm" + if method == "tfm" then + tfmdata = check_tfm(specification,specification.name) + elseif method == "afm" then + tfmdata = check_afm(specification,specification.name) + elseif method == "tfm or afm" then + tfmdata = check_tfm(specification,specification.name) or check_afm(specification,specification.name) + else -- method == "afm or tfm" or method == "" then + tfmdata = check_afm(specification,specification.name) or check_tfm(specification,specification.name) + end + end + else + tfmdata = check_afm(specification,fullname) + end + return tfmdata +end +function readers.pfb(specification,method) -- only called when forced + local original = specification.specification + if trace_defining then + report_afm("using afm reader for '%s'",original) + end + specification.specification = gsub(original,"%.pfb",".afm") + specification.forced = "afm" + return readers.afm(specification,method) +end |