summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/mkiv/font-cff.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkiv/font-cff.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-cff.lua340
1 files changed, 231 insertions, 109 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-cff.lua b/Master/texmf-dist/tex/context/base/mkiv/font-cff.lua
index 46deedb5f93..72b0a038f17 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/font-cff.lua
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-cff.lua
@@ -27,7 +27,7 @@ if not modules then modules = { } end modules ['font-cff'] = {
-- the other hand, we can now feed back cff2 stuff.
local next, type, tonumber, rawget = next, type, tonumber, rawget
-local byte, char, gmatch = string.byte, string.char, string.gmatch
+local byte, char, gmatch, sub = string.byte, string.char, string.gmatch, string.sub
local concat, remove, unpack = table.concat, table.remove, table.unpack
local floor, abs, round, ceil, min, max = math.floor, math.abs, math.round, math.ceil, math.min, math.max
local P, C, R, S, C, Cs, Ct = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Ct
@@ -145,6 +145,38 @@ local defaultstrings = { [0] = -- taken from ff
"Black", "Bold", "Book", "Light", "Medium", "Regular", "Roman", "Semibold",
}
+local standardnames = { [0] = -- needed for seac
+ false, false, false, false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false, false, false,
+ "space", "exclam", "quotedbl", "numbersign", "dollar", "percent",
+ "ampersand", "quoteright", "parenleft", "parenright", "asterisk", "plus",
+ "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four",
+ "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less",
+ "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H",
+ "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W",
+ "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum",
+ "underscore", "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
+ "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y",
+ "z", "braceleft", "bar", "braceright", "asciitilde", false, false, false,
+ false, false, false, false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false, false, "exclamdown",
+ "cent", "sterling", "fraction", "yen", "florin", "section", "currency",
+ "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft",
+ "guilsinglright", "fi", "fl", false, "endash", "dagger", "daggerdbl",
+ "periodcentered", false, "paragraph", "bullet", "quotesinglbase",
+ "quotedblbase", "quotedblright", "guillemotright", "ellipsis", "perthousand",
+ false, "questiondown", false, "grave", "acute", "circumflex", "tilde",
+ "macron", "breve", "dotaccent", "dieresis", false, "ring", "cedilla", false,
+ "hungarumlaut", "ogonek", "caron", "emdash", false, false, false, false,
+ false, false, false, false, false, false, false, false, false, false, false,
+ false, "AE", false, "ordfeminine", false, false, false, false, "Lslash",
+ "Oslash", "OE", "ordmasculine", false, false, false, false, false, "ae",
+ false, false, false, "dotlessi", false, false, "lslash", "oslash", "oe",
+ "germandbls", false, false, false, false
+}
+
local cffreaders = {
readbyte,
readushort,
@@ -152,6 +184,15 @@ local cffreaders = {
readulong,
}
+directives.register("fonts.streamreader",function()
+ cffreaders = {
+ readbyte,
+ readushort,
+ readuint,
+ readulong,
+ }
+end)
+
-- The header contains information about its own size.
local function readheader(f)
@@ -655,6 +696,7 @@ do
local x = 0
local y = 0
local width = false
+ local lsb = 0
local r = 0
local stems = 0
local globalbias = 0
@@ -678,6 +720,9 @@ do
local factors = false
local axis = false
local vsindex = 0
+ local justpass = false
+ local seacs = { }
+ local procidx = nil
local function showstate(where)
report("%w%-10s : [%s] n=%i",depth*2,where,concat(stack," ",1,top),top)
@@ -1012,43 +1057,6 @@ do
top = 0
end
--- local function xxcurveto(swap)
--- local last = top % 4 ~= 0 and stack[top]
--- if last then
--- top = top - 1
--- end
--- for i=1,top,4 do
--- local ax, ay, bx, by
--- if swap then
--- ax = x + stack[i]
--- ay = y
--- bx = ax + stack[i+1]
--- by = ay + stack[i+2]
--- y = by + stack[i+3]
--- if last and i+3 == top then
--- x = bx + last
--- else
--- x = bx
--- end
--- swap = false
--- else
--- ax = x
--- ay = y + stack[i]
--- bx = ax + stack[i+1]
--- by = ay + stack[i+2]
--- x = bx + stack[i+3]
--- if last and i+3 == top then
--- y = by + last
--- else
--- y = by
--- end
--- swap = true
--- end
--- xycurveto(ax,ay,bx,by,x,y)
--- end
--- top = 0
--- end
-
local function xxcurveto(swap)
local last = top % 4 ~= 0 and stack[top]
if last then
@@ -1086,7 +1094,6 @@ do
top = 0
end
-
local function hvcurveto()
if trace_charstrings then
showstate("hvcurveto")
@@ -1302,7 +1309,7 @@ do
end
local function divide()
- if version == 1 then
+ if version == "cff" then
local d = stack[top]
top = top - 1
stack[top] = stack[top] / d
@@ -1310,7 +1317,7 @@ do
end
local function closepath()
- if version == 1 then
+ if version == "cff" then
if trace_charstrings then
showstate("closepath")
end
@@ -1319,65 +1326,90 @@ do
end
local function hsbw()
- if version == 1 then
+ if version == "cff" then
if trace_charstrings then
showstate("hsbw")
end
- -- lsb = stack[top-1]
+ lsb = stack[top-1] or 0
width = stack[top]
end
top = 0
end
- local function seac()
- if version == 1 then
+ local function sbw()
+ if version == "cff" then
if trace_charstrings then
- showstate("seac")
+ showstate("sbw")
end
+ lsb = stack[top-3]
+ width = stack[top-1]
end
top = 0
end
- local function sbw()
- if version == 1 then
+ -- asb adx ady bchar achar seac (accented characters)
+
+ local function seac()
+ if version == "cff" then
if trace_charstrings then
- showstate("sbw")
+ showstate("seac")
end
- width = stack[top-1]
end
top = 0
end
- -- these are probably used for special cases i.e. call out to postscript
+ -- These are probably used for special cases i.e. call out to the
+ -- postscript interpreter (p 61 of the spec as well as chapter 8).
+ --
+ -- This needs checking (I have to ask Taco next time we meet.)
+
+ local popped = 3
+ local hints = 3
+
+ -- arg1 ... argn n othersubr# <callothersubr> (on postscript stack)
local function callothersubr()
- if version == 1 then
- -- we don't support this (ok, we could mimick these othersubs)
+ if version == "cff" then
if trace_charstrings then
- showstate("callothersubr (unsupported)")
+ showstate("callothersubr")
+ end
+ if stack[top] == hints then
+ popped = stack[top-2]
+ else
+ popped = 3
+ end
+ local t = stack[top-1]
+ if t then
+ top = top - (t + 2)
+ if top < 0 then
+ top = 0
+ end
+ else
+ top = 0
end
+ else
+ top = 0
end
- top = 0
end
+ -- <pop> number (from postscript stack)
+
local function pop()
- if version == 1 then
- -- we don't support this
+ if version == "cff" then
if trace_charstrings then
- showstate("pop (unsupported)")
+ showstate("pop")
end
top = top + 1
- stack[top] = 0 -- a dummy
+ stack[top] = popped
else
top = 0
end
end
local function setcurrentpoint()
- if version == 1 then
- -- we don't support this
+ if version == "cff" then
if trace_charstrings then
- showstate("pop (unsupported)")
+ showstate("setcurrentpoint (unsupported)")
end
x = x + stack[top-1]
y = y + stack[top]
@@ -1527,6 +1559,41 @@ do
hvcurveto, -- 31
}
+ local reverse = { [0] =
+ "unsupported",
+ "getstem",
+ "unsupported",
+ "getstem",
+ "vmoveto",
+ "rlineto",
+ "hlineto",
+ "vlineto",
+ "rrcurveto",
+ "unsupported",
+ "unsupported",
+ "unsupported",
+ "unsupported",
+ "hsbw",
+ "unsupported",
+ "setvsindex",
+ "blend",
+ "unsupported",
+ "getstem",
+ "getmask",
+ "getmask",
+ "rmoveto",
+ "hmoveto",
+ "getstem",
+ "rcurveline",
+ "rlinecurve",
+ "vvcurveto",
+ "hhcurveto",
+ "unsupported",
+ "unsupported",
+ "vhcurveto",
+ "hvcurveto",
+ }
+
local subactions = {
-- cff 1
[000] = dotsection,
@@ -1578,6 +1645,7 @@ do
for i=1132,2048 do
t[i] = char(28,band(rshift(i,8),0xFF),band(i,0xFF))
end
+ -- we could inline some ...
setmetatableindex(encode,function(t,k)
-- 16.16-bit signed fixed value
local r = round(k)
@@ -1663,7 +1731,7 @@ do
local function call(scope,list,bias) -- ,process)
depth = depth + 1
if top == 0 then
- showstate(formatters["unknown %s call"](scope))
+ showstate(formatters["unknown %s call %s, case %s"](scope,"?",1))
top = 0
else
local index = stack[top] + bias
@@ -1675,7 +1743,7 @@ do
if tab then
process(tab)
else
- showstate(formatters["unknown %s call %i"](scope,index))
+ showstate(formatters["unknown %s call %s, case %s"](scope,index,2))
top = 0
end
end
@@ -1684,8 +1752,6 @@ do
-- precompiling and reuse is much slower than redoing the calls
- local justpass = false
-
-- local function decode(str)
-- local a, b, c, d, e = byte(str,1,5)
-- if a == 28 then
@@ -1796,13 +1862,24 @@ do
i = i + 1
local t = tab[i]
if justpass then
- if t >= 34 or t <= 37 then -- flexes
+ if t >= 34 and t <= 37 then -- flexes
for i=1,top do
r = r + 1 ; result[r] = encode[stack[i]]
end
r = r + 1 ; result[r] = chars[12]
r = r + 1 ; result[r] = chars[t]
top = 0
+ elseif t == 6 then
+ seacs[procidx] = {
+ asb = stack[1],
+ adx = stack[2],
+ ady = stack[3],
+ base = stack[4],
+ accent = stack[5],
+ width = width,
+ lsb = lsb,
+ }
+ top = 0
else
local a = subactions[t]
if a then
@@ -1834,46 +1911,56 @@ do
-- cff 1: (when cff2 strip them)
elseif t == 1 or t == 3 or t == 18 or operation == 23 then
p_getstem() -- at the start
-if true then
- if top > 0 then
- for i=1,top do
- r = r + 1 ; result[r] = encode[stack[i]]
+ if true then
+ if top > 0 then
+ for i=1,top do
+ r = r + 1 ; result[r] = encode[stack[i]]
+ end
+ top = 0
end
+ r = r + 1 ; result[r] = chars[t]
+ else
top = 0
end
- r = r + 1 ; result[r] = chars[t]
-else
- top = 0
-end
i = i + 1
-- cff 1: (when cff2 strip them)
elseif t == 19 or t == 20 then
local s = p_getmask() or 0 -- after the stems
-if true then
- if top > 0 then
- for i=1,top do
- r = r + 1 ; result[r] = encode[stack[i]]
+ if true then
+ if top > 0 then
+ for i=1,top do
+ r = r + 1 ; result[r] = encode[stack[i]]
+ end
+ top = 0
end
+ r = r + 1 ; result[r] = chars[t]
+ for j=1,s do
+ i = i + 1
+ r = r + 1 ; result[r] = chars[tab[i]]
+ end
+ else
+ i = i + s
top = 0
end
- r = r + 1 ; result[r] = chars[t]
- for j=1,s do
- i = i + 1
- r = r + 1 ; result[r] = chars[tab[i]]
- end
-else
- i = i + s
- top = 0
-end
i = i + 1
-- cff 1: closepath
elseif t == 9 then
top = 0
i = i + 1
elseif t == 13 then
- local s = hsbw() or 0
- i = i + s + 1
+ hsbw()
+ if version == "cff" then
+ -- we do a moveto over lsb
+ r = r + 1 ; result[r] = encode[lsb]
+ r = r + 1 ; result[r] = chars[22]
+ else
+ -- lsb is supposed to be zero
+ end
+ i = i + 1
else
+ if trace_charstrings then
+ showstate(reverse[t] or "<action>")
+ end
if top > 0 then
for i=1,top do
r = r + 1 ; result[r] = encode[stack[i]]
@@ -1894,7 +1981,7 @@ end
end
else
if trace_charstrings then
- showvalue("<action>",t)
+ showstate(reverse[t] or "<action>")
end
top = 0
i = i + 1
@@ -1941,24 +2028,19 @@ end
-- end
-- end
- local function setbias(globals,locals)
--- if version == 1 then -- charstring version, not cff
--- return
--- 0,
--- 0
--- return
--- 1,
--- 1
--- else
+ local function setbias(globals,locals,nobias)
+ if nobias then
+ return 0, 0
+ else
local g = #globals
local l = #locals
return
((g < 1240 and 107) or (g < 33900 and 1131) or 32768) + 1,
((l < 1240 and 107) or (l < 33900 and 1131) or 32768) + 1
--- end
+ end
end
- local function processshape(tab,index)
+ local function processshape(tab,index,hack)
if not tab then
glyphs[index] = {
@@ -1974,10 +2056,13 @@ end
x = 0
y = 0
width = false
+ lsb = 0
r = 0
top = 0
stems = 0
result = { } -- we could reuse it when only boundingbox calculations are needed
+ popped = 3
+ procidx = index
xmin = 0
xmax = 0
@@ -1995,6 +2080,10 @@ end
process(tab)
+ if hack then
+ return x, y
+ end
+
local boundingbox = {
round(xmin),
round(ymin),
@@ -2059,6 +2148,8 @@ end
axis = false
regions = data.regions
justpass = streams == true
+ popped = 3
+ seacs = { }
if regions then
regions = { regions } -- needs checking
axis = data.factors or false
@@ -2073,6 +2164,8 @@ end
locals = false
globals = false
strings = false
+ popped = 3
+ seacs = { }
end
local function setwidths(private)
@@ -2086,7 +2179,7 @@ end
return privatedata.nominalwidthx or 0, privatedata.defaultwidthx or 0
end
- parsecharstrings = function(fontdata,data,glphs,doshapes,tversion,streams)
+ parsecharstrings = function(fontdata,data,glphs,doshapes,tversion,streams,nobias)
local dictionary = data.dictionaries[1]
local charstrings = dictionary.charstrings
@@ -2100,14 +2193,42 @@ end
vsindex = dictionary.vsindex or 0
glyphs = glphs or { }
- globalbias, localbias = setbias(globals,locals)
+ globalbias, localbias = setbias(globals,locals,nobias)
nominalwidth, defaultwidth = setwidths(dictionary.private)
if charstrings then
startparsing(fontdata,data,streams)
for index=1,#charstrings do
processshape(charstrings[index],index-1)
--- charstrings[index] = nil -- free memory (what if used more often?)
+ end
+ if justpass and next(seacs) then
+ -- old type 1 stuff ... seacs
+ local charset = data.dictionaries[1].charset
+ if charset then
+ local lookup = table.swapped(charset)
+ for index, v in next, seacs do
+ local bindex = lookup[standardnames[v.base]]
+ local aindex = lookup[standardnames[v.accent]]
+ local bglyph = bindex and glyphs[bindex]
+ local aglyph = aindex and glyphs[aindex]
+ if bglyph and aglyph then
+ -- this is a real ugly hack but we seldom enter this branch (e.g. old lbr)
+ local jp = justpass
+ justpass = false
+ local x, y = processshape(charstrings[bindex+1],bindex,true)
+ justpass = jp
+ --
+ local base = bglyph.stream
+ local accent = aglyph.stream
+ local moveto = encode[-x-v.asb+v.adx] .. chars[22]
+ .. encode[-y +v.ady] .. chars[ 4]
+ -- prune an endchar
+ base = sub(base,1,#base-1)
+ -- combine them
+ glyphs[index].stream = base .. moveto .. accent
+ end
+ end
+ end
end
stopparsing(fontdata,data)
else
@@ -2127,9 +2248,10 @@ end
vsindex = dictionary.vsindex or 0
glyphs = glphs or { }
- justpass = streams == true
+ justpass = streams == true
+ seacs = { }
- globalbias, localbias = setbias(globals,locals)
+ globalbias, localbias = setbias(globals,locals,nobias)
nominalwidth, defaultwidth = setwidths(dictionary.private)
processshape(tab,index-1)
@@ -2428,8 +2550,8 @@ function readers.cff(f,fontdata,specification)
if private then
local data = private.data
if type(data) == "table" then
- cffinfo.defaultwidth = data.defaultwidth or cffinfo.defaultwidth
- cffinfo.nominalwidth = data.nominalwidth or cffinfo.nominalwidth
+ cffinfo.defaultwidth = data.defaultwidthx or cffinfo.defaultwidth
+ cffinfo.nominalwidth = data.nominalwidthx or cffinfo.nominalwidth
cffinfo.bluevalues = data.bluevalues
cffinfo.otherblues = data.otherblues
cffinfo.familyblues = data.familyblues