Implement counterhinting in Type1 to Type2 code
Gives better hinted output for asian fonts
This commit is contained in:
parent
3ec7bc1c1e
commit
4d356676b1
@ -40,7 +40,7 @@ local function parse_charstring(cs, subrs, result)
|
|||||||
elseif cmd == 1 then -- Flex initialization
|
elseif cmd == 1 then -- Flex initialization
|
||||||
elseif cmd == 2 then -- Flex parameter
|
elseif cmd == 2 then -- Flex parameter
|
||||||
if result[#result-1].flex then
|
if result[#result-1].flex then
|
||||||
result[#result] = nil -- TODO: Warn if there were values.
|
result[#result] = nil -- TODO: Warn if there were additional values in lastresult.
|
||||||
lastresult = result[#result] -- We keep collecting arguments
|
lastresult = result[#result] -- We keep collecting arguments
|
||||||
end
|
end
|
||||||
lastresult.flex = true
|
lastresult.flex = true
|
||||||
@ -64,14 +64,51 @@ local function parse_charstring(cs, subrs, result)
|
|||||||
pending[i] = lastresult[results-numargs+i]
|
pending[i] = lastresult[results-numargs+i]
|
||||||
lastresult[results-numargs+i] = nil
|
lastresult[results-numargs+i] = nil
|
||||||
end
|
end
|
||||||
for i = 1,#lastresult.pendingargs do
|
if lastresult.pendingargs then
|
||||||
pending[numargs+i] = lastresult.pendingargs[i]
|
for i = 1,#lastresult.pendingargs do
|
||||||
|
pending[numargs+i] = lastresult.pendingargs[i]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
if cmd == 12 then
|
if cmd == 12 then
|
||||||
lastresult.pendingargs = pending
|
lastresult.pendingargs = pending
|
||||||
else
|
else
|
||||||
lastresult.pendingargs = nil
|
lastresult.pendingargs = nil
|
||||||
-- TODO Translate pending to counter mask
|
local n = pending[1]
|
||||||
|
local i = 2
|
||||||
|
local groups = {}
|
||||||
|
for group = 1, n do
|
||||||
|
local current = {20}
|
||||||
|
local last = 0
|
||||||
|
while pending[i+1] > 0 do
|
||||||
|
last = last + pending[i]
|
||||||
|
current[#current+1] = {1, last, pending[i+1]}
|
||||||
|
last = last + pending[i+1]
|
||||||
|
i = i+2
|
||||||
|
end
|
||||||
|
last = last + pending[i]
|
||||||
|
current[#current+1] = {1, last + pending[i+1], -pending[i+1]}
|
||||||
|
groups[group] = current
|
||||||
|
i = i+2
|
||||||
|
end
|
||||||
|
n = pending[i]
|
||||||
|
i = i+1
|
||||||
|
for group = 1, n do
|
||||||
|
local current = groups[group] or {20}
|
||||||
|
local last = 0
|
||||||
|
while pending[i+1] > 0 do
|
||||||
|
last = last + pending[i]
|
||||||
|
current[#current+1] = {3, last, pending[i+1]}
|
||||||
|
last = last + pending[i+1]
|
||||||
|
i = i+2
|
||||||
|
end
|
||||||
|
last = last + pending[i]
|
||||||
|
current[#current+1] = {3, last + pending[i+1], -pending[i+1]}
|
||||||
|
groups[group] = current
|
||||||
|
i = i+2
|
||||||
|
end
|
||||||
|
assert(i == #pending+1)
|
||||||
|
table.move(groups, 1, #groups, #result, result) -- This overwrites lastresult
|
||||||
|
result[#result+1] = lastresult -- And restore lastresult
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
error[[UNSUPPORTED Othersubr]]
|
error[[UNSUPPORTED Othersubr]]
|
||||||
@ -132,12 +169,12 @@ local function adjust_charstring(cs) -- Here we get a not yet optimized but pars
|
|||||||
cs[1][1] = nil
|
cs[1][1] = nil
|
||||||
-- That's it for the width, now we need some hinting stuff. This would be easy, if hint replacement
|
-- That's it for the width, now we need some hinting stuff. This would be easy, if hint replacement
|
||||||
-- wouldn't require hint masks in Type2. And because we really enjoy this BS, we get counter
|
-- wouldn't require hint masks in Type2. And because we really enjoy this BS, we get counter
|
||||||
-- hinting as an additional treat... Oh, if you actually you counter hinting: Please test this
|
-- hinting as an additional treat... Oh, if you actually use counter hinting: Please test this
|
||||||
-- and report back if it works, because this is pretty much untested.
|
-- and report back if it works, because this is pretty much untested.
|
||||||
-- TODO: Even more than that, counters are not implemented at all right now, except for [hv]stem3
|
|
||||||
local stems = {}
|
local stems = {}
|
||||||
local stem3 = {}
|
local stem3 = {20}
|
||||||
-- First iterate over the charstring, recording all hints and collecting them in stems/stem3
|
local cntrs = {}
|
||||||
|
-- First iterate over the charstring, recording all hints and collecting them in stems/stem3/cntrs
|
||||||
for i, cmd in ipairs(cs) do
|
for i, cmd in ipairs(cs) do
|
||||||
if cmd[1] == 1 or cmd[1] == 3 then
|
if cmd[1] == 1 or cmd[1] == 3 then
|
||||||
stems[#stems + 1] = cmd
|
stems[#stems + 1] = cmd
|
||||||
@ -148,6 +185,9 @@ local function adjust_charstring(cs) -- Here we get a not yet optimized but pars
|
|||||||
stems[#stems + 1] = {c, cmd[6], cmd[7]}
|
stems[#stems + 1] = {c, cmd[6], cmd[7]}
|
||||||
table.move(stems, #stems-2, #stems, #stem3+1, stem3)
|
table.move(stems, #stems-2, #stems, #stem3+1, stem3)
|
||||||
cs[i] = false
|
cs[i] = false
|
||||||
|
elseif cmd[1] == 20 then
|
||||||
|
cntrs[#cntrs+1] = cmd
|
||||||
|
table.move(cmd, 2, #cmd, #stems+1, stems)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
table.sort(stems, function(first, second)
|
table.sort(stems, function(first, second)
|
||||||
@ -168,18 +208,25 @@ local function adjust_charstring(cs) -- Here we get a not yet optimized but pars
|
|||||||
stems[i].idx = j
|
stems[i].idx = j
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- Now the indices are known, so the cntrmask can be written, if stem3 occured.
|
-- Now the indices are known, so the cntrmask can be written, if counters or stem3 occured.
|
||||||
-- This is done before writing the stem list to make the thable.insert parameters easier.
|
-- This is done before writing the stem list to make the thable.insert parameters easier.
|
||||||
|
-- First translate stem3 into a counter group
|
||||||
|
if stem3[2] then
|
||||||
|
cntrs[#cntrs+1] = stem3
|
||||||
|
table.insert(cs, 2, stem3)
|
||||||
|
end
|
||||||
local bytes = {}
|
local bytes = {}
|
||||||
if stem3[1] then
|
for i=1, #cntrs do
|
||||||
for l = 1, math.floor((j + 7)/8) do
|
local cntr = cntrs[i]
|
||||||
bytes[l] = 0
|
for l = 1, math.floor((j + 7)/8) do
|
||||||
end
|
bytes[l] = 0
|
||||||
for l = 1, #stem3 do
|
|
||||||
local idx = stem3[l].idx-1
|
|
||||||
bytes[math.floor(idx/8) + 1] = bytes[math.floor(idx/8) + 1] | (1<<(7-idx%8))
|
|
||||||
end
|
end
|
||||||
table.insert(cs, 2, {20, string.char(table.unpack(bytes))})
|
for l = 2, #cntr do
|
||||||
|
local idx = cntr[l].idx-1
|
||||||
|
bytes[math.floor(idx/8) + 1] = bytes[math.floor(idx/8) + 1] | (1<<(7-idx%8))
|
||||||
|
cntr[l] = nil
|
||||||
|
end
|
||||||
|
cntr[2] = string.char(table.unpack(bytes))
|
||||||
end
|
end
|
||||||
local current = 1
|
local current = 1
|
||||||
-- Then list the collected stems at the beginning of the charstring
|
-- Then list the collected stems at the beginning of the charstring
|
||||||
@ -220,7 +267,7 @@ local function adjust_charstring(cs) -- Here we get a not yet optimized but pars
|
|||||||
cs[i] = false
|
cs[i] = false
|
||||||
i = i+1
|
i = i+1
|
||||||
end
|
end
|
||||||
for l = 1, #stem3 do
|
for l = 2, #stem3 do
|
||||||
local idx = stem3[l].idx-1
|
local idx = stem3[l].idx-1
|
||||||
bytes[math.floor(idx/8) + 1] = bytes[math.floor(idx/8) + 1] | (1<<(7-idx%8))
|
bytes[math.floor(idx/8) + 1] = bytes[math.floor(idx/8) + 1] | (1<<(7-idx%8))
|
||||||
end
|
end
|
||||||
|
@ -10,7 +10,7 @@ local our_callbacks = {
|
|||||||
vf = {'vf', false, 'rb', 'find_vf_file', 'read_vf_file'},
|
vf = {'vf', false, 'rb', 'find_vf_file', 'read_vf_file'},
|
||||||
tfm = {'tfm', false, 'rb', 'find_font_file', 'read_font_file'},
|
tfm = {'tfm', false, 'rb', 'find_font_file', 'read_font_file'},
|
||||||
map = {'map', 2, 'r', 'find_map_file', 'read_map_file'},
|
map = {'map', 2, 'r', 'find_map_file', 'read_map_file'},
|
||||||
enc = {'enc', false, 'r', 'find_enc_file', 'read_enc_file'},
|
enc = {'enc files', false, 'r', 'find_enc_file', 'read_enc_file'},
|
||||||
type1 = {'type1 fonts', 4, 'rb', 'find_type1_file', 'read_type1_file'},
|
type1 = {'type1 fonts', 4, 'rb', 'find_type1_file', 'read_type1_file'},
|
||||||
truetype = {'truetype fonts', 4, 'rb', 'find_truetype_file', 'read_truetype_file'},
|
truetype = {'truetype fonts', 4, 'rb', 'find_truetype_file', 'read_truetype_file'},
|
||||||
opentype = {'opentype fonts', 4, 'rb', 'find_opentype_file', 'read_opentype_file'},
|
opentype = {'opentype fonts', 4, 'rb', 'find_opentype_file', 'read_opentype_file'},
|
||||||
|
Loading…
Reference in New Issue
Block a user