summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/luaotfload-main.tex2
-rw-r--r--src/fontloader/misc/fontloader-font-afm.lua231
-rw-r--r--src/fontloader/misc/fontloader-font-con.lua11
-rw-r--r--src/fontloader/misc/fontloader-font-dsp.lua2
-rw-r--r--src/fontloader/misc/fontloader-font-map.lua4
-rw-r--r--src/fontloader/misc/fontloader-font-otj.lua6
-rw-r--r--src/fontloader/misc/fontloader-font-otl.lua2
-rw-r--r--src/fontloader/misc/fontloader-font-otr.lua80
-rw-r--r--src/fontloader/misc/fontloader-font-ots.lua50
-rw-r--r--src/fontloader/misc/fontloader-font-oup.lua28
-rw-r--r--src/fontloader/misc/fontloader-font-tfm.lua2
-rw-r--r--src/fontloader/runtime/fontloader-basics-gen.lua6
-rw-r--r--src/fontloader/runtime/fontloader-reference.lua327
-rw-r--r--src/luaotfload-auxiliary.lua265
-rw-r--r--src/luaotfload-configuration.lua2
-rw-r--r--src/luaotfload-database.lua201
-rw-r--r--src/luaotfload-loaders.lua14
-rw-r--r--src/luaotfload-main.lua26
-rw-r--r--src/luaotfload-parsers.lua4
-rw-r--r--src/luaotfload-resolvers.lua12
20 files changed, 932 insertions, 343 deletions
diff --git a/doc/luaotfload-main.tex b/doc/luaotfload-main.tex
index c243f03..90738de 100644
--- a/doc/luaotfload-main.tex
+++ b/doc/luaotfload-main.tex
@@ -855,7 +855,7 @@ Sans}:
\font \onetwothree = "combo: 1 -> \fontid\one;
2 -> \fontid\two, 0x30-0x39;
- 3 -> \fontid\three, 0x21*0x3f;
+ 3 -> \fontid\three, 0x21*0x3f; "
{\onetwothree \TeX—0123456789—?!}
\bye
diff --git a/src/fontloader/misc/fontloader-font-afm.lua b/src/fontloader/misc/fontloader-font-afm.lua
index 329639b..99b8577 100644
--- a/src/fontloader/misc/fontloader-font-afm.lua
+++ b/src/fontloader/misc/fontloader-font-afm.lua
@@ -28,9 +28,11 @@ don't have this issue.</p>
local fonts, logs, trackers, containers, resolvers = fonts, logs, trackers, containers, resolvers
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 match, gmatch, lower, gsub, strip, find = string.match, string.gmatch, string.lower, string.gsub, string.strip, string.find
+local char, byte, sub = string.char, string.byte, string.sub
local abs = math.abs
-local P, S, C, R, lpegmatch, patterns = lpeg.P, lpeg.S, lpeg.C, lpeg.R, lpeg.match, lpeg.patterns
+local bxor, rshift = bit32.bxor, bit32.rshift
+local P, S, R, Cmt, C, Ct, Cs, lpegmatch, patterns = lpeg.P, lpeg.S, lpeg.R, lpeg.Cmt, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.match, lpeg.patterns
local derivetable = table.derive
local trace_features = false trackers.register("afm.features", function(v) trace_features = v end)
@@ -48,18 +50,13 @@ local definers = fonts.definers
local readers = fonts.readers
local constructors = fonts.constructors
-local fontloader = fontloader
-local font_to_table = fontloader.to_table
-local open_font = fontloader.open
-local close_font = fontloader.close
-
local afm = constructors.newhandler("afm")
local pfb = constructors.newhandler("pfb")
local afmfeatures = constructors.newfeatures("afm")
local registerafmfeature = afmfeatures.register
-afm.version = 1.500 -- incrementing this number one up will force a re-cache
+afm.version = 1.501 -- 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.*)
@@ -171,7 +168,7 @@ end
local function get_charmetrics(data,charmetrics,vector)
local characters = data.characters
local chr, ind = { }, 0
- for k,v in gmatch(charmetrics,"([%a]+) +(.-) *;") do
+ for k, v in gmatch(charmetrics,"([%a]+) +(.-) *;") do
if k == 'C' then
v = tonumber(v)
if v < 0 then
@@ -225,41 +222,193 @@ local function get_variables(data,fontmetrics)
end
end
-local function get_indexes(data,pfbname)
- data.resources.filename = resolvers.unresolve(pfbname) -- no shortcut
- local pfbblob = open_font(pfbname)
- if pfbblob then
- local characters = data.characters
- local pfbdata = font_to_table(pfbblob)
- if pfbdata then
- local glyphs = pfbdata.glyphs
- if glyphs then
- if trace_loading then
- report_afm("getting index data from %a",pfbname)
- end
- for index, glyph in next, glyphs do
- -- for index, glyph in table.sortedhash(glyphs) do
- local name = glyph.name
- if name then
- local char = characters[name]
- if char then
- if trace_indexing then
- report_afm("glyph %a has index %a",name,index)
+local get_indexes
+
+do
+
+ -- old font loader
+
+ local fontloader = fontloader
+
+ if fontloader then
+
+ local font_to_table = fontloader.to_table
+ local open_font = fontloader.open
+ local close_font = fontloader.close
+
+ local function get_indexes_old(data,pfbname)
+ local pfbblob = open_font(pfbname)
+ if pfbblob then
+ local characters = data.characters
+ local pfbdata = font_to_table(pfbblob)
+ if pfbdata then
+ local glyphs = pfbdata.glyphs
+ if glyphs then
+ if trace_loading then
+ report_afm("getting index data from %a",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 %a has index %a",name,index)
+ end
+ char.index = index
+ end
end
- char.index = index
end
+ elseif trace_loading then
+ report_afm("no glyph data in pfb file %a",pfbname)
end
+ elseif trace_loading then
+ report_afm("no data in pfb file %a",pfbname)
end
+ close_font(pfbblob)
elseif trace_loading then
- report_afm("no glyph data in pfb file %a",pfbname)
+ report_afm("invalid pfb file %a",pfbname)
end
- elseif trace_loading then
- report_afm("no data in pfb file %a",pfbname)
end
- close_font(pfbblob)
- elseif trace_loading then
- report_afm("invalid pfb file %a",pfbname)
+
end
+
+ -- new (unfinished) font loader but i see no differences between
+ -- old and new (one bad vector with old)
+
+ local n, m
+
+ local progress = function(str,position,name,size)
+ local forward = position + tonumber(size) + 3 + 2
+ n = n + 1
+ if n >= m then
+ return #str, name
+ elseif forward < #str then
+ return forward, name
+ else
+ return #str, name
+ end
+ end
+
+ local initialize = function(str,position,size)
+ n = 0
+ m = tonumber(size)
+ return position + 1
+ end
+
+ local charstrings = P("/CharStrings")
+ local name = P("/") * C((R("az")+R("AZ")+R("09")+S("-_."))^1)
+ local size = C(R("09")^1)
+ local spaces = P(" ")^1
+
+ local p_filternames = Ct (
+ (1-charstrings)^0 * charstrings * spaces * Cmt(size,initialize)
+ * (Cmt(name * P(" ")^1 * C(R("09")^1), progress) + P(1))^1
+ )
+
+ -- if one of first 4 not 0-9A-F then binary else hex
+
+ local decrypt
+
+ do
+
+ local r, c1, c2, n = 0, 0, 0, 0
+
+ local function step(c)
+ local cipher = byte(c)
+ local plain = bxor(cipher,rshift(r,8))
+ r = ((cipher + r) * c1 + c2) % 65536
+ return char(plain)
+ end
+
+ decrypt = function(binary)
+ r, c1, c2, n = 55665, 52845, 22719, 4
+ binary = gsub(binary,".",step)
+ return sub(binary,n+1)
+ end
+
+ -- local pattern = Cs((P(1) / step)^1)
+ --
+ -- decrypt = function(binary)
+ -- r, c1, c2, n = 55665, 52845, 22719, 4
+ -- binary = lpegmatch(pattern,binary)
+ -- return sub(binary,n+1)
+ -- end
+
+ end
+
+ local function loadpfbvector(filename)
+ -- for the moment limited to encoding only
+
+ local data = io.loaddata(resolvers.findfile(filename))
+
+ if not find(data,"!PS%-AdobeFont%-") then
+ print("no font",filename)
+ return
+ end
+
+ if not data then
+ print("no data",filename)
+ return
+ end
+
+ local ascii, binary = match(data,"(.*)eexec%s+......(.*)")
+
+ if not binary then
+ print("no binary",filename)
+ return
+ end
+
+ binary = decrypt(binary,4)
+
+ local vector = lpegmatch(p_filternames,binary)
+
+ vector[0] = table.remove(vector,1)
+
+ if not vector then
+ print("no vector",filename)
+ return
+ end
+
+ return vector
+
+ end
+
+ get_indexes = function(data,pfbname)
+ local vector = loadpfbvector(pfbname)
+ if vector then
+ local characters = data.characters
+ if trace_loading then
+ report_afm("getting index data from %a",pfbname)
+ end
+ for index=1,#vector do
+ local name = vector[index]
+ local char = characters[name]
+ if char then
+ if trace_indexing then
+ report_afm("glyph %a has index %a",name,index)
+ end
+ char.index = index
+ end
+ end
+ end
+ end
+
+ if fontloader then
+
+ afm.use_new_indexer = true
+ get_indexes_new = get_indexes
+
+ get_indexes = function(data,pfbname)
+ if afm.use_new_indexer then
+ return get_indexes_new(data,pfbname)
+ else
+ return get_indexes_old(data,pfbname)
+ end
+ end
+
+ end
+
end
local function readafm(filename)
@@ -351,8 +500,9 @@ function afm.load(filename)
data = readafm(filename)
if data then
if pfbname ~= "" then
+ data.resources.filename = resolvers.unresolve(pfbname)
get_indexes(data,pfbname)
- elseif trace_loading then
+ elseif trace_loading then
report_afm("no pfb file for %a",filename)
-- data.resources.filename = "unset" -- better than loading the afm file
end
@@ -397,9 +547,10 @@ 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
+ local unicodes = { }
+ local 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
diff --git a/src/fontloader/misc/fontloader-font-con.lua b/src/fontloader/misc/fontloader-font-con.lua
index f36f750..b118535 100644
--- a/src/fontloader/misc/fontloader-font-con.lua
+++ b/src/fontloader/misc/fontloader-font-con.lua
@@ -776,9 +776,14 @@ function constructors.scale(tfmdata,specification)
elseif autoitalicamount then -- itlc feature
local vi = description.italic
if not vi then
- local vi = description.boundingbox[3] - description.width + autoitalicamount
- if vi > 0 then -- < 0 indicates no overshoot or a very small auto italic
- chr.italic = vi*hdelta
+ local bb = description.boundingbox
+ if bb then
+ local vi = bb[3] - description.width + autoitalicamount
+ if vi > 0 then -- < 0 indicates no overshoot or a very small auto italic
+ chr.italic = vi*hdelta
+ end
+ else
+ -- report_defining("no boundingbox for character %C in font %a, fullname %a, filename %a",unicode,name,fullname,filename)
end
elseif vi ~= 0 then
chr.italic = vi*hdelta
diff --git a/src/fontloader/misc/fontloader-font-dsp.lua b/src/fontloader/misc/fontloader-font-dsp.lua
index 14e816d..85a80bd 100644
--- a/src/fontloader/misc/fontloader-font-dsp.lua
+++ b/src/fontloader/misc/fontloader-font-dsp.lua
@@ -525,7 +525,7 @@ local function chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nof
end
end
local noflookups = readushort(f)
- local lookups = { }
+ local lookups = { }
for i=1,noflookups do
lookups[readushort(f)+1] = readushort(f) + 1
end
diff --git a/src/fontloader/misc/fontloader-font-map.lua b/src/fontloader/misc/fontloader-font-map.lua
index db501f0..509e751 100644
--- a/src/fontloader/misc/fontloader-font-map.lua
+++ b/src/fontloader/misc/fontloader-font-map.lua
@@ -19,6 +19,8 @@ local trace_mapping = false trackers.register("fonts.mapping", function(v) trac
local report_fonts = logs.reporter("fonts","loading") -- not otf only
+local force_ligatures = false directives.register("fonts.mapping.forceligatures",function(v) force_ligatures = v end)
+
local fonts = fonts or { }
local mappings = fonts.mappings or { }
fonts.mappings = mappings
@@ -443,7 +445,7 @@ function mappings.addtounicode(data,filename,checklookups)
local collected = false
local unicoded = 0
for unicode, glyph in next, descriptions do
- if not glyph.unicode and glyph.class == "ligature" then
+ if glyph.class == "ligature" and (force_ligatures or not glyph.unicode) then
if not collected then
collected = fonts.handlers.otf.readers.getcomponents(data)
if not collected then
diff --git a/src/fontloader/misc/fontloader-font-otj.lua b/src/fontloader/misc/fontloader-font-otj.lua
index aae70d1..ebda723 100644
--- a/src/fontloader/misc/fontloader-font-otj.lua
+++ b/src/fontloader/misc/fontloader-font-otj.lua
@@ -49,8 +49,8 @@ local attributes, nodes, node = attributes, nodes, node
fonts = fonts
local hashes = fonts.hashes
local fontdata = hashes.identifiers
-local parameters = fonts.hashes.parameters
-local resources = fonts.hashes.resources
+----- parameters = fonts.hashes.parameters -- not in generic
+----- resources = fonts.hashes.resources -- not in generic
nodes.injections = nodes.injections or { }
local injections = nodes.injections
@@ -1444,7 +1444,7 @@ local function injectspaces(head)
-- end
leftkerns = trig.left
rightkerns = trig.right
- local par = parameters[font]
+ local par = fontdata[font].parameters -- fallback for generic
factor = par.factor
threshold = par.spacing.width - 1 -- get rid of rounding errors
lastfont = font
diff --git a/src/fontloader/misc/fontloader-font-otl.lua b/src/fontloader/misc/fontloader-font-otl.lua
index 210abfe..bcea275 100644
--- a/src/fontloader/misc/fontloader-font-otl.lua
+++ b/src/fontloader/misc/fontloader-font-otl.lua
@@ -53,7 +53,7 @@ local report_otf = logs.reporter("fonts","otf loading")
local fonts = fonts
local otf = fonts.handlers.otf
-otf.version = 3.017 -- beware: also sync font-mis.lua and in mtx-fonts
+otf.version = 3.018 -- beware: also sync font-mis.lua and in mtx-fonts
otf.cache = containers.define("fonts", "otl", otf.version, true)
local otfreaders = otf.readers
diff --git a/src/fontloader/misc/fontloader-font-otr.lua b/src/fontloader/misc/fontloader-font-otr.lua
index 3542d18..24f6854 100644
--- a/src/fontloader/misc/fontloader-font-otr.lua
+++ b/src/fontloader/misc/fontloader-font-otr.lua
@@ -60,16 +60,16 @@ if not modules then modules = { } end modules ['font-otr'] = {
-- faster but it might not be the real bottleneck as we still need to juggle data. It
-- is probably more memory efficient as no intermediate strings are involved.
-if not characters then
- require("char-def")
- require("char-ini")
-end
+-- if not characters then
+-- require("char-def")
+-- require("char-ini")
+-- end
local next, type, unpack = next, type, unpack
local byte, lower, char, strip, gsub = string.byte, string.lower, string.char, string.strip, string.gsub
local bittest = bit32.btest
-local concat, remove, unpack = table.concat, table.remov, table.unpack
-local floor, mod, abs, sqrt, round = math.floor, math.mod, math.abs, math.sqrt, math.round
+local concat, remove, unpack, fastcopy = table.concat, table.remov, table.unpack, table.fastcopy
+local floor, abs, sqrt, round = math.floor, math.abs, math.sqrt, math.round
local P, R, S, C, Cs, Cc, Ct, Carg, Cmt = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Ct, lpeg.Carg, lpeg.Cmt
local lpegmatch = lpeg.match
@@ -1066,14 +1066,13 @@ readers.hmtx = function(f,fontdata,specification)
local nofmetrics = fontdata.horizontalheader.nofhmetrics
local glyphs = fontdata.glyphs
local nofglyphs = fontdata.nofglyphs
- local nofrepeated = nofglyphs - nofmetrics
local width = 0 -- advance
local leftsidebearing = 0
for i=0,nofmetrics-1 do
local glyph = glyphs[i]
width = readshort(f)
leftsidebearing = readshort(f)
- if advance ~= 0 then
+ if width ~= 0 then
glyph.width = width
end
-- if leftsidebearing ~= 0 then
@@ -1082,8 +1081,8 @@ readers.hmtx = function(f,fontdata,specification)
end
-- The next can happen in for instance a monospace font or in a cjk font
-- with fixed widths.
- for i=nofmetrics,nofrepeated do
- local glyph = glyphs[i]
+ for i=nofmetrics,nofglyphs-1 do
+ local glyph = glyphs[i]
if width ~= 0 then
glyph.width = width
end
@@ -1187,6 +1186,8 @@ local sequence = {
{ 3, 0, 6 },
-- variants
{ 0, 5, 14 },
+ -- last resort ranges
+ { 3, 10, 13 },
}
-- local sequence = {
@@ -1269,10 +1270,10 @@ formatreaders[4] = function(f,fontdata,offset)
-- bad encoding
elseif offset == 0 then
if trace_cmap then
- report("format 4.%i segment %2i from %C upto %C at index %H",1,segment,startchar,endchar,mod(startchar + delta,65536))
+ report("format 4.%i segment %2i from %C upto %C at index %H",1,segment,startchar,endchar,(startchar + delta) % 65536)
end
for unicode=startchar,endchar do
- local index = mod(unicode + delta,65536)
+ local index = (unicode + delta) % 65536
if index and index > 0 then
local glyph = glyphs[index]
if glyph then
@@ -1302,13 +1303,13 @@ formatreaders[4] = function(f,fontdata,offset)
else
local shift = (segment-nofsegments+offset/2) - startchar
if trace_cmap then
- report("format 4.%i segment %2i from %C upto %C at index %H",0,segment,startchar,endchar,mod(startchar + delta,65536))
+ report("format 4.%i segment %2i from %C upto %C at index %H",0,segment,startchar,endchar,(startchar + delta) % 65536)
end
for unicode=startchar,endchar do
local slot = shift + unicode
local index = indices[slot]
if index and index > 0 then
- index = mod(index + delta,65536)
+ index = (index + delta) % 65536
local glyph = glyphs[index]
if glyph then
local gu = glyph.unicode
@@ -1389,7 +1390,7 @@ formatreaders[12] = function(f,fontdata,offset)
local last = readulong(f)
local index = readulong(f)
if trace_cmap then
- report("format 12 from %C to %C",first,last)
+ report("format 12 from %C to %C starts at index %i",first,last,index)
end
for unicode=first,last do
local glyph = glyphs[index]
@@ -1417,6 +1418,53 @@ formatreaders[12] = function(f,fontdata,offset)
return nofdone
end
+formatreaders[13] = function(f,fontdata,offset)
+ --
+ -- this fector is only used for simple fallback fonts
+ --
+ setposition(f,offset+2+2+4+4) -- skip format reserved length language
+ local mapping = fontdata.mapping
+ local glyphs = fontdata.glyphs
+ local duplicates = fontdata.duplicates
+ local nofgroups = readulong(f)
+ local nofdone = 0
+ for i=1,nofgroups do
+ local first = readulong(f)
+ local last = readulong(f)
+ local index = readulong(f)
+ if first < privateoffset then
+ if trace_cmap then
+ report("format 13 from %C to %C get index %i",first,last,index)
+ end
+ local glyph = glyphs[index]
+ local unicode = glyph.unicode
+ if not unicode then
+ unicode = first
+ glyph.unicode = unicode
+ first = first + 1
+ end
+ local list = duplicates[unicode]
+ mapping[index] = unicode
+ if not list then
+ list = { }
+ duplicates[unicode] = list
+ end
+ if last >= privateoffset then
+ local limit = privateoffset - 1
+ report("format 13 from %C to %C pruned to %C",first,last,limit)
+ last = limit
+ end
+ for unicode=first,last do
+ list[unicode] = true
+ end
+ nofdone = nofdone + last - first + 1
+ else
+ report("format 13 from %C to %C ignored",first,last)
+ end
+ end
+ return nofdone
+end
+
formatreaders[14] = function(f,fontdata,offset)
if offset and offset ~= 0 then
setposition(f,offset)
@@ -2226,7 +2274,7 @@ function readers.extend(fontdata)
end
end
---
+-- for now .. this will move to a context specific file
if fonts.hashes then
diff --git a/src/fontloader/misc/fontloader-font-ots.lua b/src/fontloader/misc/fontloader-font-ots.lua
index 6911872..90fcde2 100644
--- a/src/fontloader/misc/fontloader-font-ots.lua
+++ b/src/fontloader/misc/fontloader-font-ots.lua
@@ -9,6 +9,9 @@ if not modules then modules = { } end modules ['font-ots'] = { -- sequences
-- to be checked: discrun doesn't seem to do something useful now (except run the
-- check again) so if we need it again we'll do a zwnjrun or so
+-- components will go away and be replaced by a property table which simplifies
+-- code (also more efficient)
+
-- beware, on my development machine we test a slightly a more optimized version
-- assumptions:
@@ -566,7 +569,22 @@ local function toligature(head,start,stop,char,dataset,sequence,markflag,discfou
local pre, post, replace, pretail, posttail, replacetail = getdisc(discfound,true)
if not replace then -- todo: signal simple hyphen
local prev = getprev(base)
- local copied = copy_node_list(comp)
+-- local copied = copy_node_list(comp)
+local current = comp
+local previous = nil
+local copied = nil
+while current do
+ if getid(current) == glyph_code then
+ local n = copy_node(current)
+ if copied then
+ setlink(previous,n)
+ else
+ copied = n
+ end
+ previous = n
+ end
+ current = getnext(current)
+end
setprev(discnext,nil) -- also blocks funny assignments
setnext(discprev,nil) -- also blocks funny assignments
if pre then
@@ -2126,7 +2144,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
else
local discfound = nil
local n = f + 1
- last = getnext(last)
+ last = getnext(last) -- the second in current (first already matched)
while n <= l do
if not last and (sweeptype == "post" or sweeptype == "replace") then
last = getnext(sweepnode)
@@ -2167,7 +2185,6 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
break
end
- last = getnext(last)
elseif char == false then
if discfound then
notmatchreplace[discfound] = true
@@ -2220,6 +2237,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
match = not notmatchpre[last]
end
+ -- maybe only if match
last = getnext(last)
else
match = false
@@ -2255,8 +2273,12 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
if trace_skips then
show_skip(dataset,sequence,char,ck,class)
end
+ prev = getprev(prev) -- moved here
elseif seq[n][char] then
- n = n -1
+ if n > 1 then -- new test
+ prev = getprev(prev) -- moved here
+ end
+ n = n - 1
else
if discfound then
notmatchreplace[discfound] = true
@@ -2275,7 +2297,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
break
end
- prev = getprev(prev)
+ -- prev = getprev(prev) -- moved up
elseif char == false then
if discfound then
notmatchreplace[discfound] = true
@@ -2339,21 +2361,20 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
if not match then
break
end
- else
- -- skip 'm
end
- else
- -- skip 'm
end
+ -- maybe only if match
+ prev = getprev(prev)
elseif seq[n][32] then
n = n - 1
+ prev = getprev(prev)
else
match = false
break
end
- prev = getprev(prev)
elseif seq[n][32] then -- somewhat special, as zapfino can have many preceding spaces
n = n - 1
+ prev = getprev(prev) -- was absent
else
match = false
break
@@ -2391,7 +2412,11 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
if trace_skips then
show_skip(dataset,sequence,char,ck,class)
end
+ current = getnext(current) -- was absent
elseif seq[n][char] then
+ if n < s then -- new test
+ current = getnext(current) -- was absent
+ end
n = n + 1
else
if discfound then
@@ -2467,16 +2492,17 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
else
-- skip 'm
end
+ -- maybe only if match
+ current = getnext(current)
elseif seq[n][32] then -- brrr
n = n + 1
else
match = false
break
end
- current = getnext(current)
elseif seq[n][32] then
n = n + 1
-current = getnext(current)
+ current = getnext(current)
else
match = false
break
diff --git a/src/fontloader/misc/fontloader-font-oup.lua b/src/fontloader/misc/fontloader-font-oup.lua
index 7edaaf6..3b6d8ea 100644
--- a/src/fontloader/misc/fontloader-font-oup.lua
+++ b/src/fontloader/misc/fontloader-font-oup.lua
@@ -367,18 +367,29 @@ local function copyduplicates(fontdata)
for u, d in next, duplicates do
local du = descriptions[u]
if du then
- local t = { f_character_y(u), "@", f_index(du.index), "->" }
+ local t = { f_character_y(u), "@", f_index(du.index), "->" }
+ local n = 0
+ local m = 25
for u in next, d do
if descriptions[u] then
- t[#t+1] = f_character_n(u)
+ if n < m then
+ t[n+4] = f_character_n(u)
+ end
else
local c = copy(du)
- -- c.unicode = u -- maybe
+ c.unicode = u -- better this way
descriptions[u] = c
- t[#t+1] = f_character_y(u)
+ if n < m then
+ t[n+4] = f_character_y(u)
+ end
end
+ n = n + 1
+ end
+ if n <= m then
+ report("duplicates: %i : % t",n,t)
+ else
+ report("duplicates: %i : % t ...",n,t)
end
- report("duplicates: % t",t)
else
-- what a mess
end
@@ -577,13 +588,12 @@ local function checklookups(fontdata,missing,nofmissing)
if r then
local name = descriptions[i].name or f_index(i)
if not ignore[name] then
- done[#done+1] = name
+ done[name] = true
end
end
end
- if #done > 0 then
- table.sort(done)
- report("not unicoded: % t",done)
+ if next(done) then
+ report("not unicoded: % t",table.sortedkeys(done))
end
end
end
diff --git a/src/fontloader/misc/fontloader-font-tfm.lua b/src/fontloader/misc/fontloader-font-tfm.lua
index 83ac2f0..8e92c48 100644
--- a/src/fontloader/misc/fontloader-font-tfm.lua
+++ b/src/fontloader/misc/fontloader-font-tfm.lua
@@ -155,7 +155,7 @@ local function read_from_tfm(specification)
end
-- let's play safe:
properties.haskerns = true
- properties.haslogatures = true
+ properties.hasligatures = true
resources.unicodes = { }
resources.lookuptags = { }
--
diff --git a/src/fontloader/runtime/fontloader-basics-gen.lua b/src/fontloader/runtime/fontloader-basics-gen.lua
index c298f6d..2a68b1c 100644
--- a/src/fontloader/runtime/fontloader-basics-gen.lua
+++ b/src/fontloader/runtime/fontloader-basics-gen.lua
@@ -92,12 +92,10 @@ local remapper = {
otf = "opentype fonts",
ttf = "truetype fonts",
ttc = "truetype fonts",
- dfont = "truetype fonts", -- "truetype dictionary",
cid = "cid maps",
cidmap = "cid maps",
- fea = "font feature files",
- pfa = "type1 fonts", -- this is for Khaled, in ConTeXt we don't use this!
- pfb = "type1 fonts", -- this is for Khaled, in ConTeXt we don't use this!
+ -- fea = "font feature files", -- no longer supported
+ pfb = "type1 fonts", -- needed for vector loading
afm = "afm",
}
diff --git a/src/fontloader/runtime/fontloader-reference.lua b/src/fontloader/runtime/fontloader-reference.lua
index e784738..5be6493 100644
--- a/src/fontloader/runtime/fontloader-reference.lua
+++ b/src/fontloader/runtime/fontloader-reference.lua
@@ -1,6 +1,6 @@
-- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua
-- parent file : c:/data/develop/context/sources/luatex-fonts.lua
--- merge date : 04/18/16 22:12:36
+-- merge date : 04/27/16 10:18:10
do -- begin closure to overcome local limits and interference
@@ -3693,11 +3693,8 @@ local remapper={
otf="opentype fonts",
ttf="truetype fonts",
ttc="truetype fonts",
- dfont="truetype fonts",
cid="cid maps",
cidmap="cid maps",
- fea="font feature files",
- pfa="type1 fonts",
pfb="type1 fonts",
afm="afm",
}
@@ -5656,9 +5653,13 @@ function constructors.scale(tfmdata,specification)
elseif autoitalicamount then
local vi=description.italic
if not vi then
- local vi=description.boundingbox[3]-description.width+autoitalicamount
- if vi>0 then
- chr.italic=vi*hdelta
+ local bb=description.boundingbox
+ if bb then
+ local vi=bb[3]-description.width+autoitalicamount
+ if vi>0 then
+ chr.italic=vi*hdelta
+ end
+ else
end
elseif vi~=0 then
chr.italic=vi*hdelta
@@ -6408,6 +6409,7 @@ local formatters=string.formatters
local trace_loading=false trackers.register("fonts.loading",function(v) trace_loading=v end)
local trace_mapping=false trackers.register("fonts.mapping",function(v) trace_unimapping=v end)
local report_fonts=logs.reporter("fonts","loading")
+local force_ligatures=false directives.register("fonts.mapping.forceligatures",function(v) force_ligatures=v end)
local fonts=fonts or {}
local mappings=fonts.mappings or {}
fonts.mappings=mappings
@@ -6676,7 +6678,7 @@ function mappings.addtounicode(data,filename,checklookups)
local collected=false
local unicoded=0
for unicode,glyph in next,descriptions do
- if not glyph.unicode and glyph.class=="ligature" then
+ if glyph.class=="ligature" and (force_ligatures or not glyph.unicode) then
if not collected then
collected=fonts.handlers.otf.readers.getcomponents(data)
if not collected then
@@ -6927,7 +6929,7 @@ local function read_from_tfm(specification)
end
end
properties.haskerns=true
- properties.haslogatures=true
+ properties.hasligatures=true
resources.unicodes={}
resources.lookuptags={}
depth[filename]=depth[filename]-1
@@ -6980,9 +6982,11 @@ if not modules then modules={} end modules ['font-afm']={
}
local fonts,logs,trackers,containers,resolvers=fonts,logs,trackers,containers,resolvers
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 match,gmatch,lower,gsub,strip,find=string.match,string.gmatch,string.lower,string.gsub,string.strip,string.find
+local char,byte,sub=string.char,string.byte,string.sub
local abs=math.abs
-local P,S,C,R,lpegmatch,patterns=lpeg.P,lpeg.S,lpeg.C,lpeg.R,lpeg.match,lpeg.patterns
+local bxor,rshift=bit32.bxor,bit32.rshift
+local P,S,R,Cmt,C,Ct,Cs,lpegmatch,patterns=lpeg.P,lpeg.S,lpeg.R,lpeg.Cmt,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.match,lpeg.patterns
local derivetable=table.derive
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)
@@ -6994,15 +6998,11 @@ local findbinfile=resolvers.findbinfile
local definers=fonts.definers
local readers=fonts.readers
local constructors=fonts.constructors
-local fontloader=fontloader
-local font_to_table=fontloader.to_table
-local open_font=fontloader.open
-local close_font=fontloader.close
local afm=constructors.newhandler("afm")
local pfb=constructors.newhandler("pfb")
local afmfeatures=constructors.newfeatures("afm")
local registerafmfeature=afmfeatures.register
-afm.version=1.500
+afm.version=1.501
afm.cache=containers.define("fonts","afm",afm.version,true)
afm.autoprefixed=true
afm.helpdata={}
@@ -7111,39 +7111,140 @@ local function get_variables(data,fontmetrics)
end
end
end
-local function get_indexes(data,pfbname)
- data.resources.filename=resolvers.unresolve(pfbname)
- local pfbblob=open_font(pfbname)
- if pfbblob then
- local characters=data.characters
- local pfbdata=font_to_table(pfbblob)
- if pfbdata then
- local glyphs=pfbdata.glyphs
- if glyphs then
- if trace_loading then
- report_afm("getting index data from %a",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 %a has index %a",name,index)
+local get_indexes
+do
+ local fontloader=fontloader
+ if fontloader then
+ local font_to_table=fontloader.to_table
+ local open_font=fontloader.open
+ local close_font=fontloader.close
+ local function get_indexes_old(data,pfbname)
+ local pfbblob=open_font(pfbname)
+ if pfbblob then
+ local characters=data.characters
+ local pfbdata=font_to_table(pfbblob)
+ if pfbdata then
+ local glyphs=pfbdata.glyphs
+ if glyphs then
+ if trace_loading then
+ report_afm("getting index data from %a",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 %a has index %a",name,index)
+ end
+ char.index=index
+ end
end
- char.index=index
end
+ elseif trace_loading then
+ report_afm("no glyph data in pfb file %a",pfbname)
end
+ elseif trace_loading then
+ report_afm("no data in pfb file %a",pfbname)
end
+ close_font(pfbblob)
elseif trace_loading then
- report_afm("no glyph data in pfb file %a",pfbname)
+ report_afm("invalid pfb file %a",pfbname)
+ end
+ end
+ end
+ local n,m
+ local progress=function(str,position,name,size)
+ local forward=position+tonumber(size)+3+2
+ n=n+1
+ if n>=m then
+ return #str,name
+ elseif forward<#str then
+ return forward,name
+ else
+ return #str,name
+ end
+ end
+ local initialize=function(str,position,size)
+ n=0
+ m=tonumber(size)
+ return position+1
+ end
+ local charstrings=P("/CharStrings")
+ local name=P("/")*C((R("az")+R("AZ")+R("09")+S("-_."))^1)
+ local size=C(R("09")^1)
+ local spaces=P(" ")^1
+ local p_filternames=Ct (
+ (1-charstrings)^0*charstrings*spaces*Cmt(size,initialize)*(Cmt(name*P(" ")^1*C(R("09")^1),progress)+P(1))^1
+ )
+ local decrypt
+ do
+ local r,c1,c2,n=0,0,0,0
+ local function step(c)
+ local cipher=byte(c)
+ local plain=bxor(cipher,rshift(r,8))
+ r=((cipher+r)*c1+c2)%65536
+ return char(plain)
+ end
+ decrypt=function(binary)
+ r,c1,c2,n=55665,52845,22719,4
+ binary=gsub(binary,".",step)
+ return sub(binary,n+1)
+ end
+ end
+ local function loadpfbvector(filename)
+ local data=io.loaddata(resolvers.findfile(filename))
+ if not find(data,"!PS%-AdobeFont%-") then
+ print("no font",filename)
+ return
+ end
+ if not data then
+ print("no data",filename)
+ return
+ end
+ local ascii,binary=match(data,"(.*)eexec%s+......(.*)")
+ if not binary then
+ print("no binary",filename)
+ return
+ end
+ binary=decrypt(binary,4)
+ local vector=lpegmatch(p_filternames,binary)
+ vector[0]=table.remove(vector,1)
+ if not vector then
+ print("no vector",filename)
+ return
+ end
+ return vector
+ end
+ get_indexes=function(data,pfbname)
+ local vector=loadpfbvector(pfbname)
+ if vector then
+ local characters=data.characters
+ if trace_loading then
+ report_afm("getting index data from %a",pfbname)
+ end
+ for index=1,#vector do
+ local name=vector[index]
+ local char=characters[name]
+ if char then
+ if trace_indexing then
+ report_afm("glyph %a has index %a",name,index)
+ end
+ char.index=index
+ end
+ end
+ end
+ end
+ if fontloader then
+ afm.use_new_indexer=true
+ get_indexes_new=get_indexes
+ get_indexes=function(data,pfbname)
+ if afm.use_new_indexer then
+ return get_indexes_new(data,pfbname)
+ else
+ return get_indexes_old(data,pfbname)
end
- elseif trace_loading then
- report_afm("no data in pfb file %a",pfbname)
end
- close_font(pfbblob)
- elseif trace_loading then
- report_afm("invalid pfb file %a",pfbname)
end
end
local function readafm(filename)
@@ -7222,6 +7323,7 @@ function afm.load(filename)
data=readafm(filename)
if data then
if pfbname~="" then
+ data.resources.filename=resolvers.unresolve(pfbname)
get_indexes(data,pfbname)
elseif trace_loading then
report_afm("no pfb file for %a",filename)
@@ -7265,7 +7367,8 @@ end
local uparser=fonts.mappings.makenameparser()
unify=function(data,filename)
local unicodevector=fonts.encodings.agl.unicodes
- local unicodes,names={},{}
+ local unicodes={}
+ local names={}
local private=constructors.privateoffset
local descriptions=data.descriptions
for name,blob in next,data.characters do
@@ -8142,15 +8245,11 @@ if not modules then modules={} end modules ['font-otr']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
-if not characters then
- require("char-def")
- require("char-ini")
-end
local next,type,unpack=next,type,unpack
local byte,lower,char,strip,gsub=string.byte,string.lower,string.char,string.strip,string.gsub
local bittest=bit32.btest
-local concat,remove,unpack=table.concat,table.remov,table.unpack
-local floor,mod,abs,sqrt,round=math.floor,math.mod,math.abs,math.sqrt,math.round
+local concat,remove,unpack,fastcopy=table.concat,table.remov,table.unpack,table.fastcopy
+local floor,abs,sqrt,round=math.floor,math.abs,math.sqrt,math.round
local P,R,S,C,Cs,Cc,Ct,Carg,Cmt=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Ct,lpeg.Carg,lpeg.Cmt
local lpegmatch=lpeg.match
local setmetatableindex=table.setmetatableindex
@@ -8701,18 +8800,17 @@ readers.hmtx=function(f,fontdata,specification)
local nofmetrics=fontdata.horizontalheader.nofhmetrics
local glyphs=fontdata.glyphs
local nofglyphs=fontdata.nofglyphs
- local nofrepeated=nofglyphs-nofmetrics
local width=0
local leftsidebearing=0
for i=0,nofmetrics-1 do
local glyph=glyphs[i]
width=readshort(f)
leftsidebearing=readshort(f)
- if advance~=0 then
+ if width~=0 then
glyph.width=width
end
end
- for i=nofmetrics,nofrepeated do
+ for i=nofmetrics,nofglyphs-1 do
local glyph=glyphs[i]
if width~=0 then
glyph.width=width
@@ -8795,6 +8893,7 @@ local sequence={
{ 0,0,6 },
{ 3,0,6 },
{ 0,5,14 },
+ { 3,10,13 },
}
local supported={}
for i=1,#sequence do
@@ -8853,10 +8952,10 @@ formatreaders[4]=function(f,fontdata,offset)
elseif offset==0xFFFF then
elseif offset==0 then
if trace_cmap then
- report("format 4.%i segment %2i from %C upto %C at index %H",1,segment,startchar,endchar,mod(startchar+delta,65536))
+ report("format 4.%i segment %2i from %C upto %C at index %H",1,segment,startchar,endchar,(startchar+delta)%65536)
end
for unicode=startchar,endchar do
- local index=mod(unicode+delta,65536)
+ local index=(unicode+delta)%65536
if index and index>0 then
local glyph=glyphs[index]
if glyph then
@@ -8885,13 +8984,13 @@ formatreaders[4]=function(f,fontdata,offset)
else
local shift=(segment-nofsegments+offset/2)-startchar
if trace_cmap then
- report("format 4.%i segment %2i from %C upto %C at index %H",0,segment,startchar,endchar,mod(startchar+delta,65536))
+ report("format 4.%i segment %2i from %C upto %C at index %H",0,segment,startchar,endchar,(startchar+delta)%65536)
end
for unicode=startchar,endchar do
local slot=shift+unicode
local index=indices[slot]
if index and index>0 then
- index=mod(index+delta,65536)
+ index=(index+delta)%65536
local glyph=glyphs[index]
if glyph then
local gu=glyph.unicode
@@ -8966,7 +9065,7 @@ formatreaders[12]=function(f,fontdata,offset)
local last=readulong(f)
local index=readulong(f)
if trace_cmap then
- report("format 12 from %C to %C",first,last)
+ report("format 12 from %C to %C starts at index %i",first,last,index)
end
for unicode=first,last do
local glyph=glyphs[index]
@@ -8992,6 +9091,49 @@ formatreaders[12]=function(f,fontdata,offset)
end
return nofdone
end
+formatreaders[13]=function(f,fontdata,offset)
+ setposition(f,offset+2+2+4+4)
+ local mapping=fontdata.mapping
+ local glyphs=fontdata.glyphs
+ local duplicates=fontdata.duplicates
+ local nofgroups=readulong(f)
+ local nofdone=0
+ for i=1,nofgroups do
+ local first=readulong(f)
+ local last=readulong(f)
+ local index=readulong(f)
+ if first<privateoffset then
+ if trace_cmap then
+ report("format 13 from %C to %C get index %i",first,last,index)
+ end
+ local glyph=glyphs[index]
+ local unicode=glyph.unicode
+ if not unicode then
+ unicode=first
+ glyph.unicode=unicode
+ first=first+1
+ end
+ local list=duplicates[unicode]
+ mapping[index]=unicode
+ if not list then
+ list={}
+ duplicates[unicode]=list
+ end
+ if last>=privateoffset then
+ local limit=privateoffset-1
+ report("format 13 from %C to %C pruned to %C",first,last,limit)
+ last=limit
+ end
+ for unicode=first,last do
+ list[unicode]=true
+ end
+ nofdone=nofdone+last-first+1
+ else
+ report("format 13 from %C to %C ignored",first,last)
+ end
+ end
+ return nofdone
+end
formatreaders[14]=function(f,fontdata,offset)
if offset and offset~=0 then
setposition(f,offset)
@@ -13831,16 +13973,28 @@ local function copyduplicates(fontdata)
local du=descriptions[u]
if du then
local t={ f_character_y(u),"@",f_index(du.index),"->" }
+ local n=0
+ local m=25
for u in next,d do
if descriptions[u] then
- t[#t+1]=f_character_n(u)
+ if n<m then
+ t[n+4]=f_character_n(u)
+ end
else
local c=copy(du)
+ c.unicode=u
descriptions[u]=c
- t[#t+1]=f_character_y(u)
+ if n<m then
+ t[n+4]=f_character_y(u)
+ end
end
+ n=n+1
+ end
+ if n<=m then
+ report("duplicates: %i : % t",n,t)
+ else
+ report("duplicates: %i : % t ...",n,t)
end
- report("duplicates: % t",t)
else
end
end
@@ -14025,13 +14179,12 @@ local function checklookups(fontdata,missing,nofmissing)
if r then
local name=descriptions[i].name or f_index(i)
if not ignore[name] then
- done[#done+1]=name
+ done[name]=true
end
end
end
- if #done>0 then
- table.sort(done)
- report("not unicoded: % t",done)
+ if next(done) then
+ report("not unicoded: % t",table.sortedkeys(done))
end
end
end
@@ -15486,7 +15639,7 @@ local trace_defining=false registertracker("fonts.defining",function(v) trace_de
local report_otf=logs.reporter("fonts","otf loading")
local fonts=fonts
local otf=fonts.handlers.otf
-otf.version=3.017
+otf.version=3.018
otf.cache=containers.define("fonts","otl",otf.version,true)
local otfreaders=otf.readers
local hashes=fonts.hashes
@@ -16527,8 +16680,6 @@ local attributes,nodes,node=attributes,nodes,node
fonts=fonts
local hashes=fonts.hashes
local fontdata=hashes.identifiers
-local parameters=fonts.hashes.parameters
-local resources=fonts.hashes.resources
nodes.injections=nodes.injections or {}
local injections=nodes.injections
local tracers=nodes.tracers
@@ -17718,7 +17869,7 @@ local function injectspaces(head)
local function updatefont(font,trig)
leftkerns=trig.left
rightkerns=trig.right
- local par=parameters[font]
+ local par=fontdata[font].parameters
factor=par.factor
threshold=par.spacing.width-1
lastfont=font
@@ -18566,7 +18717,21 @@ local function toligature(head,start,stop,char,dataset,sequence,markflag,discfou
local pre,post,replace,pretail,posttail,replacetail=getdisc(discfound,true)
if not replace then
local prev=getprev(base)
- local copied=copy_node_list(comp)
+local current=comp
+local previous=nil
+local copied=nil
+while current do
+ if getid(current)==glyph_code then
+ local n=copy_node(current)
+ if copied then
+ setlink(previous,n)
+ else
+ copied=n
+ end
+ previous=n
+ end
+ current=getnext(current)
+end
setprev(discnext,nil)
setnext(discprev,nil)
if pre then
@@ -19871,7 +20036,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
else
local discfound=nil
local n=f+1
- last=getnext(last)
+ last=getnext(last)
while n<=l do
if not last and (sweeptype=="post" or sweeptype=="replace") then
last=getnext(sweepnode)
@@ -19912,7 +20077,6 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
break
end
- last=getnext(last)
elseif char==false then
if discfound then
notmatchreplace[discfound]=true
@@ -19997,8 +20161,12 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
if trace_skips then
show_skip(dataset,sequence,char,ck,class)
end
+ prev=getprev(prev)
elseif seq[n][char] then
- n=n -1
+ if n>1 then
+ prev=getprev(prev)
+ end
+ n=n-1
else
if discfound then
notmatchreplace[discfound]=true
@@ -20017,7 +20185,6 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
break
end
- prev=getprev(prev)
elseif char==false then
if discfound then
notmatchreplace[discfound]=true
@@ -20079,19 +20246,19 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
if not match then
break
end
- else
end
- else
end
+ prev=getprev(prev)
elseif seq[n][32] then
n=n-1
+ prev=getprev(prev)
else
match=false
break
end
- prev=getprev(prev)
elseif seq[n][32] then
n=n-1
+ prev=getprev(prev)
else
match=false
break
@@ -20126,7 +20293,11 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
if trace_skips then
show_skip(dataset,sequence,char,ck,class)
end
+ current=getnext(current)
elseif seq[n][char] then
+ if n<s then
+ current=getnext(current)
+ end
n=n+1
else
if discfound then
@@ -20200,16 +20371,16 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
else
end
+ current=getnext(current)
elseif seq[n][32] then
n=n+1
else
match=false
break
end
- current=getnext(current)
elseif seq[n][32] then
n=n+1
-current=getnext(current)
+ current=getnext(current)
else
match=false
break
diff --git a/src/luaotfload-auxiliary.lua b/src/luaotfload-auxiliary.lua
index 3d300e7..e544dd7 100644
--- a/src/luaotfload-auxiliary.lua
+++ b/src/luaotfload-auxiliary.lua
@@ -88,13 +88,12 @@ package.
--doc]]--
local set_sscale_dimens = function (fontdata)
- local mathconstants = fontdata.MathConstants
- local parameters = fontdata.parameters
- if mathconstants then
- parameters[10] = mathconstants.ScriptPercentScaleDown or 70
- parameters[11] = mathconstants.ScriptScriptPercentScaleDown or 50
- end
- return fontdata
+ local resources = fontdata.resources if not resources then return end
+ local mathconstants = resources.MathConstants if not mathconstants then return end
+ local parameters = fontdata.parameters if not parameters then return end
+ --- the default values below are complete crap
+ parameters [10] = mathconstants.ScriptPercentScaleDown or 70
+ parameters [11] = mathconstants.ScriptScriptPercentScaleDown or 50
end
luaotfload_callbacks [#luaotfload_callbacks + 1] = {
@@ -104,8 +103,8 @@ luaotfload_callbacks [#luaotfload_callbacks + 1] = {
--- fontobj -> int
local lookup_units = function (fontdata)
local metadata = fontdata.shared and fontdata.shared.rawdata.metadata
- if metadata and metadata.units_per_em then
- return metadata.units_per_em
+ if metadata and metadata.units then
+ return metadata.units
elseif fontdata.parameters and fontdata.parameters.units then
return fontdata.parameters.units
elseif fontdata.units then --- v1.x
@@ -122,9 +121,9 @@ local patch_cambria_domh = function (fontdata)
local mathconstants = fontdata.MathConstants
if mathconstants and fontdata.psname == "CambriaMath" then
--- my test Cambria has 2048
- local units_per_em = fontdata.units_per_em or lookup_units(fontdata)
- local sz = fontdata.parameters.size or fontdata.size
- local mh = 2800 / units_per_em * sz
+ local units = fontdata.units or lookup_units(fontdata)
+ local sz = fontdata.parameters.size or fontdata.size
+ local mh = 2800 / units * sz
if mathconstants.DisplayOperatorMinHeight < mh then
mathconstants.DisplayOperatorMinHeight = mh
end
@@ -177,40 +176,95 @@ Comment from fontspec:
--doc]]--
+local capheight_reference_chars = { "X", "M", "Ж", "ξ", }
+local capheight_reference_codepoints do
+ local utfbyte = unicode.utf8.byte
+ capheight_reference_codepoints = { }
+ for i = 1, #capheight_reference_chars do
+ local chr = capheight_reference_chars [i]
+ capheight_reference_codepoints [i] = utfbyte (chr)
+ end
+end
+
+local determine_capheight = function (fontdata)
+ local parameters = fontdata.parameters if not parameters then return false end
+ local characters = fontdata.characters if not characters then return false end
+ --- Pretty simplistic but it does return *some* value for most fonts;
+ --- we could also refine the approach to return some kind of average
+ --- of all capital letters or a user-provided subset.
+ for i = 1, #capheight_reference_codepoints do
+ local refcp = capheight_reference_codepoints [i]
+ local refchar = characters [refcp]
+ if refchar then
+ logreport ("both", 4, "aux",
+ "picked height of character ‘%s’ (U+%d) as \\fontdimen8 \z
+ candidate",
+ capheight_reference_chars [i], refcp)
+ return refchar.height
+ end
+ end
+ return false
+end
+
+local query_ascender = function (fontdata)
+ local parameters = fontdata.parameters if not parameters then return false end
+ local shared = fontdata.shared if not shared then return false end
+ local rawdata = shared.rawdata if not rawdata then return false end
+ local metadata = rawdata.metadata if not metadata then return false end
+ local ascender = parameters.ascender
+ or metadata.ascender if not ascender then return false end
+ local units = metadata.units if units == 0 then return false end
+ local size = parameters.size if not size then return false end
+ return ascender * size / units
+end
+
+local query_capheight = function (fontdata)
+ local parameters = fontdata.parameters if not parameters then return false end
+ local shared = fontdata.shared if not shared then return false end
+ local rawdata = shared.rawdata if not rawdata then return false end
+ local metadata = rawdata.metadata if not metadata then return false end
+ local capheight = metadata.capheight if not capheight then return false end
+ local units = metadata.units if units == 0 then return false end
+ local size = parameters.size if not size then return false end
+ return capheight * size / units
+end
+
+local query_fontdimen8 = function (fontdata)
+ local parameters = fontdata.parameters if not parameters then return false end
+ local fontdimen8 = parameters [8]
+ if fontdimen8 then return fontdimen8 end
+ return false
+end
+
+local caphtfmt = function (ref, ht)
+ if not ht then return "<none>" end
+ if not ref then return tostring (ht) end
+ return stringformat ("%s(δ=%s)", ht, ht - ref)
+end
+
local set_capheight = function (fontdata)
- local shared = fontdata.shared
- local parameters = fontdata.parameters
- local capheight
- if shared
- and shared.rawdata.metadata
- and shared.rawdata.metadata.pfminfo
- then
- local units_per_em = parameters.units
- local size = parameters.size
- local os2_capheight = shared.rawdata.metadata.pfminfo.os2_capheight
-
- if capheight and os2_capheight > 0 then
- capheight = os2_capheight / units_per_em * size
- else
- local X8_str = stringbyte"X"
- local X8_chr = fontdata.characters[X8_str]
- if X8_chr then
- capheight = X8_chr.height
- else
- capheight = parameters.ascender / units_per_em * size
- end
- end
- else
- local X8_str = stringbyte "X"
- local X8_chr = fontdata.characters[X8_str]
- if X8_chr then
- capheight = X8_chr.height
- end
+ if not fontdata then
+ logreport ("both", 0, "aux",
+ "error: set_capheight() received garbage")
+ return
+ end
+ local capheight_dimen8 = query_fontdimen8 (fontdata)
+ local capheight_alleged = query_capheight (fontdata)
+ local capheight_ascender = query_ascender (fontdata)
+ local capheight_measured = determine_capheight (fontdata)
+ logreport ("term", 4, "aux",
+ "capht: param[8]=%s advertised=%s ascender=%s measured=%s",
+ tostring (capheight_dimen8),
+ caphtfmt (capheight_dimen8, capheight_alleged),
+ caphtfmt (capheight_dimen8, capheight_ascender),
+ caphtfmt (capheight_dimen8, capheight_measured))
+ if capheight_dimen8 then --- nothing to do
+ return
end
+
+ local capheight = capheight_alleged or capheight_ascender or capheight_measured
if capheight then
- --- is this legit? afaics there’s nothing else on the
- --- array part of that table
- fontdata.parameters[8] = capheight
+ fontdata.parameters [8] = capheight
end
end
@@ -263,20 +317,27 @@ end
--- int -> string -> bool -> (int | false)
local slot_of_name = function (font_id, glyphname, unsafe)
- local fontdata = identifiers[font_id]
- if fontdata then
- local unicode = fontdata.resources.unicodes[glyphname]
- if unicode then
- if type(unicode) == "number" then
- return unicode
- else
- return unicode[1] --- for multiple components
- end
--- else
--- --- missing
+ if not font_id or type (font_id) ~= "number"
+ or not glyphname or type (glyphname) ~= "string"
+ then
+ logreport ("both", 0, "aux",
+ "invalid parameters to slot_of_name (%s, %s)",
+ tostring (font_id), tostring (glyphname))
+ return false
+ end
+
+ local tfmdata = identifiers [font_id]
+ if not tfmdata then return raw_slot_of_name (font_id, glyphname) end
+ local resources = tfmdata.resources if not resources then return false end
+ local unicodes = resources.unicodes if not unicodes then return false end
+
+ local unicode = unicodes [glyphname]
+ if unicode then
+ if type (unicode) == "number" then
+ return unicode
+ else
+ return unicode [1] --- for multiple components
end
- elseif unsafe == true then -- for Robert
- return raw_slot_of_name(font_id, glyphname)
end
return false
end
@@ -298,11 +359,23 @@ local indices
--- int -> (string | false)
local name_of_slot = function (codepoint)
+ if not codepoint or type (codepoint) ~= "number" then
+ logreport ("both", 0, "aux",
+ "invalid parameters to name_of_slot (%s)",
+ tostring (codepoint))
+ return false
+ end
+
if not indices then --- this will load the glyph list
local unicodes = encodings.agl.unicodes
- indices = table.swapped(unicodes)
+ if not unicodes or not next (unicodes)then
+ logreport ("both", 0, "aux",
+ "name_of_slot: failed to load the AGL.")
+ end
+ indices = table.swapped (unicodes)
end
- local glyphname = indices[codepoint]
+
+ local glyphname = indices [codepoint]
if glyphname then
return glyphname
end
@@ -317,6 +390,12 @@ aux.name_of_slot = name_of_slot
-----------------------------------------------------------------------
--- lots of arrowcode ahead
+local get_features = function (tfmdata)
+ local resources = tfmdata.resources if not resources then return false end
+ local features = resources.features if not features then return false end
+ return features
+end
+
--[[doc--
This function, modeled after “check_script()” from fontspec, returns
true if in the given font, the script “asked_script” is accounted for in at
@@ -325,13 +404,23 @@ least one feature.
--- int -> string -> bool
local provides_script = function (font_id, asked_script)
+ if not font_id or type (font_id) ~= "number"
+ or not asked_script or type (asked_script) ~= "string"
+ then
+ logreport ("both", 0, "aux",
+ "invalid parameters to provides_script(%s, %s)",
+ tostring (font_id), tostring (asked_script))
+ return false
+ end
asked_script = stringlower(asked_script)
if font_id and font_id > 0 then
- local tfmdata = identifiers[font_id] if not tfmdata then return false end
- local shared = tfmdata.shared if not shared then return false end
- local fontdata = shared.rawdata if not fontdata then return false end
- local fontname = fontdata.metadata.fontname
- local features = fontdata.resources.features
+ local tfmdata = identifiers[font_id]
+ if not tfmdata then return false end
+ local features = get_features (tfmdata)
+ if features == false then
+ logreport ("log", 1, "aux", "font no %d lacks a features table", font_id)
+ return false
+ end
for method, featuredata in next, features do
--- where method: "gpos" | "gsub"
for feature, data in next, featuredata do
@@ -362,14 +451,27 @@ feature.
--- int -> string -> string -> bool
local provides_language = function (font_id, asked_script, asked_language)
- asked_script = stringlower(asked_script)
- asked_language = stringlower(asked_language)
+ if not font_id or type (font_id) ~= "number"
+ or not asked_script or type (asked_script) ~= "string"
+ or not asked_language or type (asked_language) ~= "string"
+ then
+ logreport ("both", 0, "aux",
+ "invalid parameters to provides_language(%s, %s, %s)",
+ tostring (font_id),
+ tostring (asked_script),
+ tostring (asked_language))
+ return false
+ end
+ asked_script = stringlower(asked_script)
+ asked_language = stringlower(asked_language)
if font_id and font_id > 0 then
- local tfmdata = identifiers[font_id] if not tfmdata then return false end
- local shared = tfmdata.shared if not shared then return false end
- local fontdata = shared.rawdata if not fontdata then return false end
- local fontname = fontdata.metadata.fontname
- local features = fontdata.resources.features
+ local tfmdata = identifiers[font_id]
+ if not tfmdata then return false end
+ local features = get_features (tfmdata)
+ if features == false then
+ logreport ("log", 1, "aux", "font no %d lacks a features table", font_id)
+ return false
+ end
for method, featuredata in next, features do
--- where method: "gpos" | "gsub"
for feature, data in next, featuredata do
@@ -432,16 +534,29 @@ accounted for in the script with tag “asked_script” in feature
--- int -> string -> string -> string -> bool
local provides_feature = function (font_id, asked_script,
asked_language, asked_feature)
+ if not font_id or type (font_id) ~= "number"
+ or not asked_script or type (asked_script) ~= "string"
+ or not asked_language or type (asked_language) ~= "string"
+ or not asked_feature or type (asked_feature) ~= "string"
+ then
+ logreport ("both", 0, "aux",
+ "invalid parameters to provides_feature(%s, %s, %s, %s)",
+ tostring (font_id), tostring (asked_script),
+ tostring (asked_language), tostring (asked_feature))
+ return false
+ end
asked_script = stringlower(asked_script)
asked_language = stringlower(asked_language)
asked_feature = lpegmatch(strip_garbage, asked_feature)
if font_id and font_id > 0 then
- local tfmdata = identifiers[font_id] if not tfmdata then return false end
- local shared = tfmdata.shared if not shared then return false end
- local fontdata = shared.rawdata if not fontdata then return false end
- local features = fontdata.resources.features
- local fontname = fontdata.metadata.fontname
+ local tfmdata = identifiers[font_id]
+ if not tfmdata then return false end
+ local features = get_features (tfmdata)
+ if features == false then
+ logreport ("log", 1, "aux", "font no %d lacks a features table", font_id)
+ return false
+ end
for method, featuredata in next, features do
--- where method: "gpos" | "gsub"
local feature = featuredata[asked_feature]
diff --git a/src/luaotfload-configuration.lua b/src/luaotfload-configuration.lua
index 8faf3d1..92de432 100644
--- a/src/luaotfload-configuration.lua
+++ b/src/luaotfload-configuration.lua
@@ -89,7 +89,7 @@ local config_paths = {
}
local valid_formats = tabletohash {
- "otf", "ttc", "ttf", "afm", --"pfb", "pfa",
+ "otf", "ttc", "ttf", "afm", "pfb"
}
local feature_presets = {
diff --git a/src/luaotfload-database.lua b/src/luaotfload-database.lua
index 135ab0e..437091f 100644
--- a/src/luaotfload-database.lua
+++ b/src/luaotfload-database.lua
@@ -208,7 +208,7 @@ end
local format_precedence = {
"otf", "ttc", "ttf", "afm",
- --- "pfb", "pfa",
+ -- "pfb" --- may come back before Luatex 1.0
}
local location_precedence = {
@@ -359,7 +359,7 @@ This is a sketch of the luaotfload db:
conflicts : { barename : int; basename : int }; // filename conflict with font at index; happens with subfonts
familyname : string; // sanitized name of the font family the font belongs to, usually from the names table
fontname : string; // sanitized name of the font
- format : string; // "otf" | "ttf" | "afm"
+ format : string; // "otf" | "ttf" | "afm" (* | "pfb" *)
fullname : string; // sanitized full name of the font including style modifiers
fullpath : string; // path to font in filesystem
index : int; // index in the mappings table
@@ -478,7 +478,6 @@ end
--- define locals in scope
local access_font_index
-local collect_families
local find_closest
local flush_lookup_cache
local generate_filedata
@@ -495,6 +494,7 @@ local lookup_fullpath
local save_lookups
local save_names
local set_font_filter
+local t1_fullinfo
local update_names
--- state of the database
@@ -595,11 +595,11 @@ load_lookups = function ( )
end
local regular_synonym = {
- book = "r",
- normal = "r",
- plain = "r",
- regular = "r",
- roman = "r",
+ book = true,
+ normal = true,
+ plain = true,
+ regular = true,
+ roman = true,
}
local italic_synonym = {
@@ -1034,7 +1034,7 @@ local lookup_fontname = function (specification, name, style)
lastresort = face
end
elseif face.metafamily == name
- and (regular_synonym [prefmodifiers]
+ and ( regular_synonym [prefmodifiers]
or regular_synonym [subfamily])
then
lastresort = face
@@ -1409,7 +1409,6 @@ local map_english_names = function (metadata)
certain.
--]]--
if platformnames then
- --inspect(metadata)
--namesource = platformnames.macintosh or platformnames.windows
namesource = platformnames.windows or platformnames.macintosh
end
@@ -1448,7 +1447,6 @@ local get_raw_info = function (metadata, basename)
return {
familyname = metadata.familyname,
fontname = fontname,
- fontstyle_name = metadata.fontstyle_name,
fullname = fullname,
italicangle = metadata.italicangle,
names = metadata.names,
@@ -1519,21 +1517,6 @@ local organize_namedata = function (rawinfo,
},
}
- -- see http://www.microsoft.com/typography/OTSPEC/features_pt.htm#size
- if rawinfo.fontstyle_name then
- --- not present in all fonts, often differs from the preferred
- --- subfamily as well as subfamily fields, e.g. with
- --- LMSans10-BoldOblique:
- --- subfamily: “Bold Italic”
- --- prefmodifiers: “10 Bold Oblique”
- --- fontstyle_name: “Bold Oblique”
- for _, name in next, rawinfo.fontstyle_name do
- if name.lang == 1033 then --- I hate magic numbers
- fontnames.fontstyle_name = name.name
- end
- end
- end
-
return {
sanitized = sanitize_fontnames (fontnames),
fontname = rawinfo.fontname,
@@ -1617,13 +1600,71 @@ ot_fullinfo = function (filename,
return res
end
+--[[doc--
+
+ Type1 font inspector. In comparison with OTF, PFB’s contain a good
+ deal less name fields which makes it tricky in some parts to find a
+ meaningful representation for the database.
+
+ Good read: http://www.adobe.com/devnet/font/pdfs/5004.AFM_Spec.pdf
+
+--doc]]--
+
+--- string -> int -> bool -> string -> fontentry
+
+t1_fullinfo = function (filename, _subfont, location, basename, format)
+ local sanitized
+ local metadata = load_font_file (filename)
+ local fontname = metadata.fontname
+ local fullname = metadata.fullname
+ local familyname = metadata.familyname
+ local italicangle = metadata.italicangle
+ local style = ""
+ local weight
+
+ sanitized = sanitize_fontnames ({
+ fontname = fontname,
+ psname = fullname,
+ metafamily = familyname,
+ familyname = familyname,
+ weight = metadata.weight, --- string identifier
+ prefmodifiers = style,
+ })
+
+ weight = sanitized.weight
+
+ if weight == "bold" then
+ style = weight
+ end
+
+ if italicangle ~= 0 then
+ style = style .. "italic"
+ end
+
+ return {
+ basename = basename,
+ fullpath = filename,
+ subfont = false,
+ location = location or "system",
+ format = format,
+ fullname = sanitized.fullname,
+ fontname = sanitized.fontname,
+ familyname = sanitized.familyname,
+ plainname = fullname,
+ psname = sanitized.fontname,
+ version = metadata.version,
+ size = false,
+ prefmodifiers = style ~= "" and style or weight,
+ weight = metadata.pfminfo and pfminfo.weight or 400,
+ italicangle = italicangle,
+ }
+end
+
local loaders = {
otf = ot_fullinfo,
ttc = ot_fullinfo,
ttf = ot_fullinfo,
-
-----pfb = t1_fullinfo, --> may come back one day, so
-----pfa = t1_fullinfo, --> we keep the indirection
+--- pfb = t1_fullinfo,
}
--- not side-effect free!
@@ -2525,6 +2566,9 @@ generate_filedata = function (mappings)
return files
end
+local bold_spectrum_low = 501 --- 500 is medium, 900 heavy/black
+local bold_weight = 700
+
local pick_style
local pick_fallback_style
local check_regular
@@ -2552,31 +2596,33 @@ do
return false
end
- pick_style = function (fontstyle_name,
- prefmodifiers,
+ pick_style = function (prefmodifiers,
subfamily)
local style
- if fontstyle_name --[[ff only]] then
- style = choose_exact (fontstyle_name)
- end
- if not style then
- if prefmodifiers then
- style = choose_exact (prefmodifiers)
- elseif subfamily then
- style = choose_exact (subfamily)
- end
+ if prefmodifiers then
+ style = choose_exact (prefmodifiers)
+ elseif subfamily then
+ style = choose_exact (subfamily)
end
return style
end
pick_fallback_style = function (italicangle, weight, pfmweight)
- --- more aggressive, but only to determine bold faces
- if pfmweight > 500 or bold_synonym [weight] then --- bold spectrum matches
+ --[[--
+ More aggressive, but only to determine bold faces.
+ Note: Before you make this test more inclusive, ensure
+ no fonts are matched in the bold synonym spectrum over
+ a literally “bold[italic]” one. In the past, heuristics
+ been tried but ultimately caused unwanted modifiers
+ polluting the lookup table. What doesn’t work is, e. g.
+ treating weights > 500 as bold or allowing synonyms like
+ “heavy”, “black”.
+ --]]--
+ if pfmweight == bold_weight then --- bold spectrum matches
if italicangle == 0 then
- return tostring (weight)
- else
- return tostring (weight) .. "i"
+ return "b"
end
+ return "bi"
end
return false
end
@@ -2584,13 +2630,12 @@ do
--- we use only exact matches here since there are constructs
--- like “regularitalic” (Cabin, Bodoni Old Fashion)
- check_regular = function (fontstyle_name,
- prefmodifiers,
+ check_regular = function (prefmodifiers,
subfamily,
italicangle,
weight,
pfmweight)
- local plausible_weight
+ local plausible_weight = false
--[[--
This filters out undesirable candidates that specify their
prefmodifiers or subfamily as “regular” but are actually of
@@ -2605,9 +2650,11 @@ do
end
if plausible_weight then
- return fontstyle_name and regular_synonym [fontstyle_name]
- or prefmodifiers and regular_synonym [prefmodifiers]
- or subfamily and regular_synonym [subfamily]
+ if prefmodifiers and regular_synonym [prefmodifiers]
+ or subfamily and regular_synonym [subfamily]
+ then
+ return "r"
+ end
end
return false
end
@@ -2634,7 +2681,6 @@ local pull_values = function (entry)
entry.fullname = english.fullname or info.fullname
entry.prefmodifiers = english.prefmodifiers
entry.familyname = metadata.familyname or english.preffamily or english.family
- entry.fontstyle_name = sanitized.fontstyle_name
entry.plainname = names.fullname
entry.subfamily = english.subfamily
@@ -2678,7 +2724,7 @@ local get_subtable = function (families, entry)
return subtable
end
-collect_families = function (mappings)
+local collect_families = function (mappings)
logreport ("info", 2, "db", "Analyzing families.")
@@ -2699,7 +2745,6 @@ collect_families = function (mappings)
local subtable = get_subtable (families, entry)
local familyname = entry.familyname
- local fontstyle_name = entry.fontstyle_name
local prefmodifiers = entry.prefmodifiers
local subfamily = entry.subfamily
@@ -2707,34 +2752,22 @@ collect_families = function (mappings)
local pfmweight = entry.pfmweight
local italicangle = entry.italicangle
- local modifier = pick_style (fontstyle_name,
- prefmodifiers,
- subfamily)
+ local modifier = pick_style (prefmodifiers, subfamily)
if not modifier then --- regular, exact only
- modifier = check_regular (fontstyle_name,
- prefmodifiers,
+ modifier = check_regular (prefmodifiers,
subfamily,
italicangle,
weight,
pfmweight)
end
- --if familyname == "garamondpremierpro" then
- --print(entry.fullname, "reg?",modifier, "->",fontstyle_name,
- --prefmodifiers,
- --subfamily,
- --italicangle,
- --pfmweight,
- --weight)
- --end
+
+ if not modifier then
+ modifier = pick_fallback_style (italicangle, weight, pfmweight)
+ end
if modifier then
add_family (familyname, subtable, modifier, entry)
- elseif pfmweight > 500 then -- in bold spectrum
- modifier = pick_fallback_style (italicangle, weight, pfmweight)
- if modifier then
- add_family (familyname, subtable, modifier, entry)
- end
end
end
@@ -2753,8 +2786,6 @@ end
--doc]]--
-local bold_spectrum_low = 501 --- 500 is medium, 900 heavy/black
-local bold_weight = 700
local style_categories = { "r", "b", "i", "bi" }
local bold_categories = { "b", "bi" }
@@ -2963,7 +2994,7 @@ local collect_statistics = function (mappings)
local sum_dsnsize, n_dsnsize = 0, 0
local fullname, family, families = { }, { }, { }
- local subfamily, prefmodifiers, fontstyle_name = { }, { }, { }
+ local subfamily, prefmodifiers = { }, { }
local addtohash = function (hash, item)
if item then
@@ -3023,7 +3054,6 @@ local collect_statistics = function (mappings)
addtohash (family, englishnames.family)
addtohash (subfamily, englishnames.subfamily)
addtohash (prefmodifiers, englishnames.prefmodifiers)
- addtohash (fontstyle_name, names.fontstyle_name)
addtoset (families, englishnames.family, englishnames.fullname)
@@ -3098,10 +3128,6 @@ local collect_statistics = function (mappings)
setsize (prefmodifiers))
pprint_top (prefmodifiers, 4)
- logreport ("both", 0, "db",
- " · %d different “fontstyle_name” kinds.",
- setsize (fontstyle_name))
- pprint_top (fontstyle_name, 4)
end
local mean_dsnsize = 0
@@ -3118,7 +3144,6 @@ local collect_statistics = function (mappings)
-- style = {
-- subfamily = subfamily,
-- prefmodifiers = prefmodifiers,
--- fontstyle_name = fontstyle_name,
-- },
}
end
@@ -3483,8 +3508,16 @@ local use_fontforge = function (val)
close_font_file = fontloader.close
get_english_names = get_english_names_from_ff
else
- read_font_file = otfhandler.readers.getinfo
- read_font_info = read_font_file
+ local wrapper = function (filename, subfont)
+ return otfhandler.readers.getinfo (filename,
+ { subfont = subfont
+ , details = false
+ , platformnames = true
+ , rawfamilynames = true
+ })
+ end
+ read_font_file = wrapper
+ read_font_info = wrapper
close_font_file = function () end
get_english_names = map_english_names
end
@@ -3537,7 +3570,7 @@ return {
fonts.definers = fonts.definers or { resolvers = { } }
names.blacklist = blacklist
- names.version = 2.6
+ names.version = 2.7
names.data = nil --- contains the loaded database
names.lookups = nil --- contains the lookup cache
diff --git a/src/luaotfload-loaders.lua b/src/luaotfload-loaders.lua
index f0c1913..f6cb272 100644
--- a/src/luaotfload-loaders.lua
+++ b/src/luaotfload-loaders.lua
@@ -43,12 +43,20 @@ end
local unsupported_reader = function (format)
return function (specification)
- logreport ("both", 0, "loaders",
+ logreport ("both", 4, "loaders",
"font format “%s” unsupported; cannot load %s.",
format, tostring (specification.name))
end
end
+local afm_compat_message = function (specification, method)
+ logreport ("both", 4, "loaders",
+ "PFB format only supported with matching \z
+ AFM; redirecting (“%s”, “%s”).",
+ tostring (specification.name), tostring (method))
+ return fonts.readers.afm (specification, method)
+end
+
local install_formats = function ()
local fonts = fonts
if not fonts then return false end
@@ -70,7 +78,7 @@ local install_formats = function ()
readers [which] = reader
handlers [which] = { }
if not seqset [which] then
- logreport ("both", 0, "loaders",
+ logreport ("both", 3, "loaders",
"Extending reader sequence for “%s”.", which)
sequence [#sequence + 1] = which
seqset [which] = true
@@ -81,7 +89,7 @@ local install_formats = function ()
return aux ("evl", eval_reader)
and aux ("lua", lua_reader)
and aux ("pfa", unsupported_reader "pfa")
- and aux ("pfb", unsupported_reader "pfb")
+ and aux ("pfb", afm_compat_message) --- pfb loader is incomplete
and aux ("ofm", readers.tfm)
and aux ("dfont", unsupported_reader "dfont")
end
diff --git a/src/luaotfload-main.lua b/src/luaotfload-main.lua
index 51a0657..9e8d088 100644
--- a/src/luaotfload-main.lua
+++ b/src/luaotfload-main.lua
@@ -111,9 +111,33 @@ local make_loader = function (prefix)
return function (name)
local t_0 = osgettimeofday ()
local modname = make_loader_name (prefix, name)
- local data = require (modname)
+ --- We don’t want the stack info from inside, so just pcall().
+ local ok, data = pcall (require, modname)
local t_end = osgettimeofday ()
timing_info.t_load [name] = t_end - t_0
+ if not ok then
+ io.write "\n"
+ local msg = luaotfload.log and luaotfload.log.report or print
+ msg ("both", 0, "load", "FATAL ERROR")
+ msg ("both", 0, "load", " × Failed to load module %q.",
+ tostring (modname))
+ local lines = string.split (data, "\n\t")
+ if not lines then
+ msg ("both", 0, "load", " × Error message: %q", data)
+ else
+ msg ("both", 0, "load", " × Error message:")
+ for i = 1, #lines do
+ msg ("both", 0, "load", " × %q.", lines [i])
+ end
+ end
+ io.write "\n\n"
+ local debug = debug
+ if debug then
+ io.write (debug.traceback())
+ io.write "\n\n"
+ end
+ os.exit(-1)
+ end
return data
end
end
diff --git a/src/luaotfload-parsers.lua b/src/luaotfload-parsers.lua
index 83e2a54..307c35c 100644
--- a/src/luaotfload-parsers.lua
+++ b/src/luaotfload-parsers.lua
@@ -722,10 +722,10 @@ local blank_line = ws * eol
local skip_line = comment_line + blank_line
local ini_id_char = alpha + (dash / "_")
local ini_id = Cs(alpha * ini_id_char^0) / stringlower
-local ini_value_char = (valid_escapes + (1 - newline - backslash - comment_char))
+local ini_value_char = (valid_escapes + (1 - linebreak - backslash - comment_char))
local ini_value = (Cs (ini_value_char^0) / string.strip)
* (comment_char * (1 - eol)^0)^-1
-local ini_string_char = (valid_escapes + (1 - newline - dquote - backslash))
+local ini_string_char = (valid_escapes + (1 - linebreak - dquote - backslash))
local ini_string = dquote
* Cs (ini_string_char^0)
* dquote
diff --git a/src/luaotfload-resolvers.lua b/src/luaotfload-resolvers.lua
index 05a0656..ee3b597 100644
--- a/src/luaotfload-resolvers.lua
+++ b/src/luaotfload-resolvers.lua
@@ -205,20 +205,18 @@ local resolve_sequence = function (seq, specification)
for i = 1, #seq do
local id = seq [i]
local mth = resolve_methods [id]
- logreport ("both", 0, "resolve", "step %d: apply method %q (%s)", i, id, mth)
+ logreport ("both", 3, "resolve", "step %d: apply method %q (%s)", i, id, mth)
if mth (specification) == true then
- logreport ("both", 0, "resolve",
- "%d: method %q indicated lookup success", i, id)
- logreport ("both", 0, "resolve",
- "method %q resolved %q -> %s (%s)",
- id, specification.specification,
+ logreport ("both", 3, "resolve",
+ "%d: method %q resolved %q -> %s (%s).",
+ i, id, specification.specification,
specification.name,
specification.forcedname)
return true
end
end
logreport ("both", 0, "resolve",
- "sequence of %d lookups yielded nothing appropriate", #seq)
+ "sequence of %d lookups yielded nothing appropriate.", #seq)
return false
end