summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/font-afm.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/font-afm.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/font-afm.lua1296
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