Fix bugs and add node fonts
This commit is contained in:
parent
2eefb9a14b
commit
1195e0f201
@ -5,6 +5,7 @@ local writer = require'luametalatex-nodewriter'
|
||||
local newpdf = require'luametalatex-pdf'
|
||||
local nametree = require'luametalatex-pdf-nametree'
|
||||
local build_fontdir = require'luametalatex-pdf-font'
|
||||
local prepare_node_font = require'luametalatex-pdf-font-node'.prepare
|
||||
local fontmap = require'luametalatex-pdf-font-map'
|
||||
|
||||
local utils = require'luametalatex-pdf-utils'
|
||||
@ -13,7 +14,17 @@ local to_bp = utils.to_bp
|
||||
|
||||
local pdfname, pfile
|
||||
local fontdirs = setmetatable({}, {__index=function(t, k)t[k] = pfile:getobj() return t[k] end})
|
||||
local usedglyphs = {}
|
||||
local nodefont_meta = {}
|
||||
local usedglyphs = setmetatable({}, {__index=function(t, fid)
|
||||
local v
|
||||
if font.fonts[fid].format == 'type3node' then
|
||||
v = setmetatable({generation = 0, next_generation = 0}, nodefont_meta)
|
||||
else
|
||||
v = {}
|
||||
end
|
||||
t[fid] = v
|
||||
return v
|
||||
end})
|
||||
local dests = {}
|
||||
local cur_page
|
||||
local declare_whatsit = require'luametalatex-whatsits'.new
|
||||
@ -69,7 +80,7 @@ token.luacmd("shipout", function()
|
||||
local out, resources, annots = writer(pfile, list, fontdirs, usedglyphs, colorstacks)
|
||||
cur_page = nil
|
||||
local content = pfile:stream(nil, '', out)
|
||||
pfile:indirect(page, string.format([[<</Type/Page/Parent %i 0 R/Contents %i 0 R/MediaBox[0 %i %i %i]/Resources<<%s%s>>%s%s>>]], parent, content, -math.ceil(to_bp(list.depth)), math.ceil(to_bp(list.width)), math.ceil(to_bp(list.height)), resources, pdfvariable.pageresources, annots, pdfvariable.pageattr))
|
||||
pfile:indirect(page, string.format([[<</Type/Page/Parent %i 0 R/Contents %i 0 R/MediaBox[0 %i %i %i]/Resources%s%s%s>>]], parent, content, -math.ceil(to_bp(list.depth)), math.ceil(to_bp(list.width)), math.ceil(to_bp(list.height)), resources(pdfvariable.pageresources), annots, pdfvariable.pageattr))
|
||||
node.flush_list(list)
|
||||
token.put_next(reset_deadcycles)
|
||||
token.scan_token()
|
||||
@ -104,14 +115,36 @@ local pdf_escape = require'luametalatex-pdf-escape'
|
||||
local pdf_bytestring = pdf_escape.escape_bytes
|
||||
local pdf_text = pdf_escape.escape_text
|
||||
|
||||
local function nodefont_newindex(t, k, v)
|
||||
t.generation = t.next_generation
|
||||
return rawset(t, k, v)
|
||||
end
|
||||
|
||||
callback.register("stop_run", function()
|
||||
if not pfile then
|
||||
return
|
||||
end
|
||||
do
|
||||
nodefont_meta.__newindex = nodefont_newindex -- Start recording generations
|
||||
local need_new_run = true
|
||||
while need_new_run do
|
||||
need_new_run = nil
|
||||
for fid, glyphs in pairs(usedglyphs) do
|
||||
local next_gen = glyphs.next_generation
|
||||
if next_gen and next_gen == glyphs.generation then
|
||||
glyphs.next_generation = next_gen+1
|
||||
need_new_run = true
|
||||
local f = font.getfont(fid) or font.fonts[fid]
|
||||
prepare_node_font(f, glyphs, pfile, fontdirs, usedglyphs) -- Might become fid, glyphs
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for fid, id in pairs(fontdirs) do
|
||||
local f = font.getfont(fid) or font.fonts[fid]
|
||||
local psname = f.psname or f.fullname
|
||||
local sorted = {}
|
||||
local used = usedglyphs[fid]
|
||||
used.generation, used.next_generation = nil, nil
|
||||
for k,v in pairs(usedglyphs[fid]) do
|
||||
sorted[#sorted+1] = v
|
||||
end
|
||||
@ -438,8 +471,8 @@ local refobj_whatsit = declare_whatsit('pdf_refobj', function(prop, p, n, x, y)
|
||||
end)
|
||||
local literal_whatsit = declare_whatsit('pdf_literal', function(prop, p, n, x, y)
|
||||
if not prop then
|
||||
tex.error('Invalid pdf_literal whatsit', {"A pdf_literal whatsit did not contain a literal to be inserted. \z
|
||||
Maybe your code hasn't been adapted to LuaMetaLaTeX yet?"})
|
||||
tex.error('Invalid pdf_literal whatsit', "A pdf_literal whatsit did not contain a literal to be inserted. \z
|
||||
Maybe your code hasn't been adapted to LuaMetaLaTeX yet?")
|
||||
return
|
||||
end
|
||||
pdf.write(prop.mode, prop.data, x, y, p)
|
||||
|
@ -55,7 +55,7 @@ function font.define(f)
|
||||
local format = f.format or "unknown"
|
||||
local encodingbytes = f.encodingbytes or (f.format:sub(5) == "type" and 2 or 1)
|
||||
f.encodingbytes = encodingbytes
|
||||
if encodingbytes == 1 and f.type ~= 'virtual' then
|
||||
if encodingbytes == 1 and f.type ~= 'virtual' and f.format ~= 'type3node' then
|
||||
-- map file lookup
|
||||
local entry = fontmap[f.name]
|
||||
if entry then
|
||||
@ -145,7 +145,7 @@ function font.addcharacters(fid, newdir)
|
||||
local existing = fontdir[cp]
|
||||
if existing ~= glyph then
|
||||
if existing then
|
||||
texio.write_nl'Overwriting existing character. Here be dragons'
|
||||
-- texio.write_nl'Overwriting existing character. Here be dragons'
|
||||
end
|
||||
end
|
||||
if glyph.commands then
|
||||
|
@ -35,6 +35,7 @@ local utils = require'luametalatex-pdf-utils'
|
||||
local strip_floats = utils.strip_floats
|
||||
local to_bp = utils.to_bp
|
||||
|
||||
local make_resources = require'luametalatex-pdf-resources'
|
||||
local pdf_font_map = require'luametalatex-pdf-font-deduplicate'
|
||||
local get_whatsit_handler = require'luametalatex-whatsits'.handler
|
||||
|
||||
@ -382,6 +383,8 @@ local function do_commands(p, c, f, fid, x, y, outer, ...)
|
||||
for _, cmd in ipairs(c.commands) do
|
||||
if cmd[1] == "node" then
|
||||
local cmd = cmd[2]
|
||||
assert(node.type(cmd))
|
||||
cmd = todirect(cmd)
|
||||
nodehandler[getid(cmd)](p, cmd, x, y, nil, ...)
|
||||
x = x + getwidth(cmd)
|
||||
elseif cmd[1] == "font" then
|
||||
@ -397,17 +400,17 @@ local function do_commands(p, c, f, fid, x, y, outer, ...)
|
||||
current_font = assert(fonts[cmd[2]], "invalid font requested")
|
||||
local n = direct.new'glyph'
|
||||
setsubtype(n, 256)
|
||||
setfont(n, current_font.id, cmd[2])
|
||||
setfont(n, current_font.id, cmd[3])
|
||||
nodehandler.glyph(p, n, x, y, outer, ...)
|
||||
direct.free(n)
|
||||
x = x + getwidth(n)
|
||||
direct.free(n)
|
||||
elseif cmd[1] == "rule" then
|
||||
local n = direct.new'rule'
|
||||
setheight(n, cmd[2])
|
||||
setwidth(n, cmd[3])
|
||||
nodehandler.rule(p, n, x, y, outer, ...)
|
||||
direct.free(n)
|
||||
x = x + getwidth(n)
|
||||
direct.free(n)
|
||||
elseif cmd[1] == "left" then
|
||||
x = x + cmd[2]
|
||||
elseif cmd[1] == "down" then
|
||||
@ -533,22 +536,9 @@ local ondemandmeta = {
|
||||
return t[k]
|
||||
end
|
||||
}
|
||||
local function writeresources(p)
|
||||
local resources = p.resources
|
||||
local result = {}
|
||||
for kind, t in pairs(resources) do if next(t) then
|
||||
result[#result+1] = format("/%s<<", kind)
|
||||
for name, value in pairs(t) do
|
||||
result[#result+1] = format("/%s %i 0 R", name, value)
|
||||
t[name] = nil
|
||||
end
|
||||
result[#result+1] = ">>"
|
||||
end end
|
||||
return concat(result)
|
||||
end
|
||||
local function nodewriter(file, n, fontdirs, usedglyphs, colorstacks)
|
||||
local function nodewriter(file, n, fontdirs, usedglyphs, colorstacks, resources)
|
||||
n = todirect(n)
|
||||
setmetatable(usedglyphs, ondemandmeta)
|
||||
resources = resources or make_resources()
|
||||
local p = {
|
||||
is_page = not not colorstacks,
|
||||
file = file,
|
||||
@ -560,7 +550,7 @@ local function nodewriter(file, n, fontdirs, usedglyphs, colorstacks)
|
||||
vfont = {},
|
||||
matrix = {1, 0, 0, 1, 0, 0},
|
||||
pending_matrix = {},
|
||||
resources = setmetatable({}, ondemandmeta),
|
||||
resources = resources,
|
||||
annots = {},
|
||||
linkcontext = file.linkcontext,
|
||||
fontdirs = fontdirs,
|
||||
@ -580,7 +570,7 @@ local function nodewriter(file, n, fontdirs, usedglyphs, colorstacks)
|
||||
nodehandler[getid(n)](p, n, 0, 0, n, nil, 0)
|
||||
-- nodehandler[getid(n)](p, n, 0, getdepth(n), n)
|
||||
topage(p)
|
||||
return concat(p.strings, '\n'), writeresources(p), (p.annots[1] and string.format("/Annots[%s]", table.concat(p.annots, ' ')) or "")
|
||||
return concat(p.strings, '\n'), resources, (p.annots[1] and string.format("/Annots[%s]", table.concat(p.annots, ' ')) or "")
|
||||
end
|
||||
require'luametalatex-pdf-savedbox':init_nodewriter(nodewriter)
|
||||
return nodewriter
|
||||
|
@ -17,7 +17,7 @@ local function build_sharekey(fontdir)
|
||||
local encodingbytes = assert(fontdir.encodingbytes)
|
||||
local key = string.format("%i:%s:", fontdir.encodingbytes, fontdir.format)
|
||||
if encodingbytes == 1 then
|
||||
if fontdir.format == "type3" then
|
||||
if fontdir.format:sub(1,5) == "type3" then
|
||||
return string.format("%s%i:%s", key, fontdir.size, fontdir.name)
|
||||
end
|
||||
key = string.format("%s%s:", key, fontdir.encoding or '')
|
||||
|
@ -250,27 +250,34 @@ local function buildfont0(pdf, fontdir, usedcids)
|
||||
cidfont)
|
||||
end
|
||||
local buildfontpk = require'luametalatex-pdf-font-pk'
|
||||
local buildfontnode = require'luametalatex-pdf-font-node'.buildfont
|
||||
local function buildfont3(pdf, fontdir, usedcids)
|
||||
local buildfont = fontdir.format == 'type3' and buildfontpk
|
||||
or fontdir.format == 'type3node' and buildfontnode
|
||||
or error[[Unsupported Type3 based font format]]
|
||||
usedcids = usedcids or allcids(fontdir)
|
||||
table.sort(usedcids, function(a,b) return a[1]<b[1] end)
|
||||
local enc = cidmap1byte(pdf)
|
||||
local bbox, matrix, widths, charprocs = buildfontpk(pdf, fontdir, usedcids) -- TOOD
|
||||
local bbox, matrix, widths, charprocs = buildfont(pdf, fontdir, usedcids)
|
||||
local touni = pdf:stream(nil, "", tounicode[1](fontdir, usedcids)) -- Done late to allow for defaults set from the font file
|
||||
return strip_floats(string.format(
|
||||
"<</Type/Font/Subtype/Type3/FontBBox[%f %f %f %f]/FontMatrix[%f %f %f %f %f %f]/CharProcs%s/Encoding%s/FirstChar %i/LastChar %i/Widths %i 0 R/ToUnicode %i 0 R>>",
|
||||
-- "<</Type/Font/Subtype/Type3/FontBBox[%f %f %f %f]/FontMatrix[%f %f %f %f %f %f]/CharProcs%s/Encoding%s/FirstChar %i/LastChar %i/Widths[%s]/ToUnicode %i 0 R/FontDescriptor %i 0 R>>",
|
||||
local matrices = strip_floats(string.format(
|
||||
"/FontBBox[%f %f %f %f]/FontMatrix[%f %f %f %f %f %f]",
|
||||
bbox[1], bbox[2], bbox[3], bbox[4],
|
||||
matrix[1], matrix[2], matrix[3], matrix[4], matrix[5], matrix[6],
|
||||
matrix[1], matrix[2], matrix[3], matrix[4], matrix[5], matrix[6]))
|
||||
return string.format(
|
||||
"<</Type/Font/Subtype/Type3%s/CharProcs%s/Encoding%s/FirstChar %i/LastChar %i/Widths %i 0 R/ToUnicode %i 0 R>>",
|
||||
-- "<</Type/Font/Subtype/Type3/CharProcs%s/Encoding%s/FirstChar %i/LastChar %i/Widths %i 0 R/ToUnicode %i 0 R/FontDescriptor %i 0 R>>",
|
||||
matrices,
|
||||
charprocs,
|
||||
encodingtype3(pdf),
|
||||
usedcids[1][1],
|
||||
usedcids[#usedcids][1],
|
||||
widths,
|
||||
touni
|
||||
)) -- , descriptor) -- TODO
|
||||
) -- , descriptor) -- TODO
|
||||
end
|
||||
return function(pdf, fontdir, usedcids)
|
||||
if fontdir.format == "type3" then
|
||||
if fontdir.format:sub(1,5) == "type3" then
|
||||
return buildfont3(pdf, fontdir, usedcids)
|
||||
else
|
||||
return buildfont0(pdf, fontdir, usedcids)
|
||||
|
@ -19,7 +19,7 @@ local function shipout(pfile, xform, fontdirs, usedglyphs)
|
||||
texio.write_nl('term and log', 'WARNING (savedboxresource shipout): Ignoring unsupported PDF variables xformattr and xformresources. Specify resources and attributes for specific XForms instead.')
|
||||
end
|
||||
local bbox = strip_floats(string.format('/BBox[%f %f %f %f]', -to_bp(margin), -to_bp(list.depth+margin), to_bp(list.width+margin), to_bp(list.height+margin)))
|
||||
local dict = string.format('/Subtype/Form%s/Resources<<%s%s>>%s', bbox, resources, xform.resources or '', xform.attributes or '')
|
||||
local dict = string.format('/Subtype/Form%s/Resources%s%s', bbox, resources(xform.resources), xform.attributes or '')
|
||||
node.flush_list(list)
|
||||
xform.list = nil
|
||||
local objnum = pfile:stream(xform.objnum, dict, out)
|
||||
|
Loading…
Reference in New Issue
Block a user