(hopefully) fix boundary parsing in TFM reader

This commit is contained in:
Marcel Krüger 2020-06-14 16:14:42 +02:00
parent 66e3482be4
commit 034a95569b

View File

@ -15,6 +15,27 @@ local function read_scaled(buf, i, count, factor)
end
return result, i + count * 4
end
local function parse_ligkern(buf, offset, r_boundary, kerns)
local kerns, ligatures, done = {}, {}, {}
repeat
local skip, next, op, rem
skip, next, op, rem, offset = string.unpack("BBBB", buf, offset)
if skip > 128 then break end
if next == r_boundary then next = "right_boundary" end
if not done[next] then
done[next] = true
if op >= 128 then
kerns[next] = kerns[(op - 128 << 8) + rem + 1]
else
ligatures[next] = {
type = op,
char = rem,
}
end
end
until skip == 128
return next(kerns) and kerns or nil, next(ligatures) and ligatures or nil
end
local function parse_tfm(buf, i, size)
local lf, lh, bc, ec, nw, nh, nd, ni, nl, nk, ne, np
lf, lh, bc, ec, nw, nh, nd, ni, nl, nk, ne, np, i =
@ -43,7 +64,7 @@ local function parse_tfm(buf, i, size)
italics, i = read_scaled(buf, i, ni, size)
for k,v in ipairs(italics) do if v == 0 then italics[k] = nil end end
ligatureoffset = i
if string.byte(buf, i, i) > 128 then
if nl ~= 0 and string.byte(buf, i, i) == 255 then
r_boundary = string.byte(buf, i+1, i+1)
end
i = i + nl * 4
@ -56,7 +77,7 @@ local function parse_tfm(buf, i, size)
end
extensibles[j] = ext
end
local slant = string.unpack(">i4", buf, i) >> 4
local slant = np ~= 0 and string.unpack(">i4", buf, i) >> 4 or nil
parameters = read_scaled(buf, i, np, size)
parameters[1] = slant
end
@ -76,30 +97,9 @@ local function parse_tfm(buf, i, size)
elseif tag == 1 then
local offset = (charinfo & 0xFF) * 4 + ligatureoffset
if string.byte(buf, offset, offset) > 128 then
offset = string.unpack(">H", buf, offset + 2)
offset = string.unpack(">H", buf, offset + 2) * 4 + ligatureoffset
end
char.kerns, char.ligatures = {}, {}
local done = {}
repeat
local skip, next, op, rem
skip, next, op, rem, offset = string.unpack("BBBB", buf, offset)
if skip > 128 then break end
if next == r_boundary then next = "right_boundary" end
if not done[next] then
done[next] = true
if op >= 128 then
char.kerns[next] = kerns[(op - 128 << 8) + rem + 1]
else
char.ligatures[next] = {
type = op,
char = rem,
}
end
end
offset = offset + 4*skip
until skip == 128
if not next(char.kerns) then char.kerns = nil end
if not next(char.ligatures) then char.ligatures = nil end
char.kerns, char.ligatures = parse_ligkern(buf, offset, r_boundary, kerns)
elseif tag == 2 then
char.next = charinfo & 0xFF
elseif tag == 3 then
@ -108,6 +108,12 @@ local function parse_tfm(buf, i, size)
characters[cc] = char
end
end
if nl ~= 0 and string.byte(buf, ligatureoffset + (nl-1) * 4) == 255 then
local char = {}
characters.left_boundary = char
local offset = string.unpack(">H", buf, ligatureoffset + nl * 4 - 2) * 4 + ligatureoffset
char.kerns, char.ligatures = parse_ligkern(buf, offset, r_boundary, kerns)
end
return {
checksum = checksum,
direction = 0,