summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/font-onr.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkiv/font-onr.lua')
-rw-r--r--tex/context/base/mkiv/font-onr.lua216
1 files changed, 155 insertions, 61 deletions
diff --git a/tex/context/base/mkiv/font-onr.lua b/tex/context/base/mkiv/font-onr.lua
index a4969ad73..85d3604b7 100644
--- a/tex/context/base/mkiv/font-onr.lua
+++ b/tex/context/base/mkiv/font-onr.lua
@@ -21,23 +21,21 @@ add features.</p>
local fonts, logs, trackers, resolvers = fonts, logs, trackers, resolvers
-local next, type, tonumber, rawget = next, type, tonumber, rawget
+local next, type, tonumber, rawget, rawset = next, type, tonumber, rawget, rawset
local match, lower, gsub, strip, find = string.match, string.lower, string.gsub, string.strip, string.find
local char, byte, sub = string.char, string.byte, string.sub
local abs = math.abs
local bxor, rshift = bit32.bxor, bit32.rshift
-local P, S, R, Cmt, C, Ct, Cs, Carg = lpeg.P, lpeg.S, lpeg.R, lpeg.Cmt, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
+local P, S, R, Cmt, C, Ct, Cs, Carg, Cf, Cg = lpeg.P, lpeg.S, lpeg.R, lpeg.Cmt, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg, lpeg.Cf, lpeg.Cg
local lpegmatch, patterns = lpeg.match, lpeg.patterns
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 report_afm = logs.reporter("fonts","afm loading")
-local report_afm = logs.reporter("fonts","pfb loading")
+local report_pfb = logs.reporter("fonts","pfb loading")
-fonts = fonts or { }
-local handlers = fonts.handlers or { }
-fonts.handlers = handlers
+local handlers = fonts.handlers
local afm = handlers.afm or { }
handlers.afm = afm
local readers = afm.readers or { }
@@ -52,42 +50,10 @@ and <l n='otf'/> reader.</p>
and new vectors (we actually had one bad vector with the old loader).</p>
--ldx]]--
-local get_indexes
+local get_indexes, get_shapes
do
- 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
@@ -101,23 +67,107 @@ do
return char(plain)
end
- decrypt = function(binary)
- r, c1, c2, n = 55665, 52845, 22719, 4
+ decrypt = function(binary,initial,seed)
+ r, c1, c2, n = initial, 52845, 22719, seed
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
+ -- decrypt = function(binary,initial,seed)
+ -- r, c1, c2, n = initial, 52845, 22719, seed
-- binary = lpegmatch(pattern,binary)
-- return sub(binary,n+1)
-- end
end
- local function loadpfbvector(filename)
+ local charstrings = P("/CharStrings")
+ local subroutines = P("/Subrs")
+ local encoding = P("/Encoding")
+ local dup = P("dup")
+ local put = P("put")
+ local array = P("array")
+ local name = P("/") * C((R("az")+R("AZ")+R("09")+S("-_."))^1)
+ local digits = R("09")^1
+ local cardinal = digits / tonumber
+ local spaces = P(" ")^1
+ local spacing = patterns.whitespace^0
+
+ local routines, vector, chars, n, m
+
+ local initialize = function(str,position,size)
+ n = 0
+ m = size -- % tonumber(size)
+ return position + 1
+ end
+
+ local setroutine = function(str,position,index,size)
+ local forward = position + tonumber(size)
+ local stream = decrypt(sub(str,position+1,forward),4330,4)
+ routines[index] = { byte(stream,1,#stream) }
+ return forward
+ end
+
+ local setvector = function(str,position,name,size)
+ local forward = position + tonumber(size)
+ if n >= m then
+ return #str
+ elseif forward < #str then
+ vector[n] = name
+ n = n + 1 -- we compensate for notdef at the cff loader end
+ return forward
+ else
+ return #str
+ end
+ end
+
+ local setshapes = function(str,position,name,size)
+ local forward = position + tonumber(size)
+ local stream = sub(str,position+1,forward)
+ if n > m then
+ return #str
+ elseif forward < #str then
+ vector[n] = name
+ n = n + 1
+ chars [n] = decrypt(stream,4330,4)
+ return forward
+ else
+ return #str
+ end
+ end
+
+ local p_rd = spacing * (P("RD") + P("-|"))
+ local p_np = spacing * (P("NP") + P( "|"))
+ local p_nd = spacing * (P("ND") + P( "|"))
+
+ local p_filterroutines = -- dup <i> <n> RD or -| <n encrypted bytes> NP or |
+ (1-subroutines)^0 * subroutines * spaces * Cmt(cardinal,initialize)
+ * (Cmt(cardinal * spaces * cardinal * p_rd, setroutine) * p_np + P(1))^1
+
+ local p_filtershapes = -- /foo <n> RD <n encrypted bytes> ND
+ (1-charstrings)^0 * charstrings * spaces * Cmt(cardinal,initialize)
+ * (Cmt(name * spaces * cardinal * p_rd, setshapes) * p_nd + P(1))^1
+
+ local p_filternames = Ct (
+ (1-charstrings)^0 * charstrings * spaces * Cmt(cardinal,initialize)
+ * (Cmt(name * spaces * cardinal, setvector) + P(1))^1
+ )
+
+ -- /Encoding 256 array
+ -- 0 1 255 {1 index exch /.notdef put} for
+ -- dup 0 /Foo put
+
+ local p_filterencoding =
+ (1-encoding)^0 * encoding * spaces * digits * spaces * array * (1-dup)^0
+ * Cf(
+ Ct("") * Cg(spacing * dup * spaces * cardinal * spaces * name * spaces * put)^1
+ ,rawset)
+
+ -- if one of first 4 not 0-9A-F then binary else hex
+
+ local function loadpfbvector(filename,shapestoo)
-- for the moment limited to encoding only
local data = io.loaddata(resolvers.findfile(filename))
@@ -139,24 +189,43 @@ do
return
end
- binary = decrypt(binary,4)
-
- local vector = lpegmatch(p_filternames,binary)
-
- if vector[1] == ".notdef" then
- -- tricky
- vector[0] = table.remove(vector,1)
+ binary = decrypt(binary,55665,4)
+
+ local names = { }
+ local encoding = lpegmatch(p_filterencoding,ascii)
+ local glyphs = { }
+
+ routines, vector, chars = { }, { }, { }
+
+ if shapestoo then
+ lpegmatch(p_filterroutines,binary)
+ lpegmatch(p_filtershapes,binary)
+ local data = {
+ dictionaries = {
+ {
+ charstrings = chars,
+ charset = vector,
+ subroutines = routines,
+ }
+ },
+ }
+ fonts.handlers.otf.readers.parsecharstrings(false,data,glyphs,true,true)
+ else
+ lpegmatch(p_filternames,binary)
end
- if not vector then
- report_pfb("no vector in %a",filename)
- return
- end
+ names = vector
+
+ routines, vector, chars = nil, nil, nil
- return vector
+ return names, encoding, glyphs
end
+ local pfb = handlers.pfb or { }
+ handlers.pfb = pfb
+ pfb.loadvector = loadpfbvector
+
get_indexes = function(data,pfbname)
local vector = loadpfbvector(pfbname)
if vector then
@@ -177,6 +246,11 @@ do
end
end
+ get_shapes = function(pfbname)
+ local vector, encoding, glyphs = loadpfbvector(pfbname,true)
+ return glyphs
+ end
+
end
--[[ldx--
@@ -389,20 +463,40 @@ function readers.loadfont(afmname,pfbname)
local data = read(resolvers.findfile(afmname),fullparser)
if data then
if not pfbname or pfbname == "" then
- pfbname = file.replacesuffix(file.nameonly(afmname),"pfb")
- pfbname = resolvers.findfile(pfbname)
+ pfbname = resolvers.findfile(file.replacesuffix(file.nameonly(afmname),"pfb"))
end
if pfbname and pfbname ~= "" then
data.resources.filename = resolvers.unresolve(pfbname)
get_indexes(data,pfbname)
- elseif trace_loading then
+ return data
+ else -- if trace_loading then
report_afm("no pfb file for %a",afmname)
- -- data.resources.filename = "unset" -- better than loading the afm file
+ -- better than loading the afm file: data.resources.filename = rawname
+ -- but that will still crash the backend so we just return nothing now
end
- return data
end
end
+-- for now, todo: n and check with otf (no afm needed here)
+
+function readers.loadshapes(filename)
+ local fullname = resolvers.findfile(filename) or ""
+ if fullname == "" then
+ return {
+ filename = "not found: " .. filename,
+ glyphs = { }
+ }
+ else
+ return {
+ filename = fullname,
+ format = "opentype",
+ glyphs = get_shapes(fullname) or { },
+ units = 1000,
+ }
+ end
+end
+
+
function readers.getinfo(filename)
local data = read(resolvers.findfile(filename),infoparser)
if data then