diff --git a/luametalatex-callbacks.lua b/luametalatex-callbacks.lua index 58ed8c0..fefb603 100644 --- a/luametalatex-callbacks.lua +++ b/luametalatex-callbacks.lua @@ -87,3 +87,27 @@ callback_register('handle_error_hook', function() until false return 3 end) + +-- Now overwrite the callback functionality. Our system is based on the ssumption there there are +-- no unknown callback names, just callbacks very unlikely to ever be called. That doesn't lead to +-- good error checking, but we expect this to be overwritten by LaTeX anyway. + +local callback_find = callback.find +local rawset = rawset +local callbacks = setmetatable({}, { + __index = function(cbs, name) + return callback_find(name) + end, + __newindex = function(cbs, name, new) + return callback_register(name, new) or rawset(cbs, name, new) + end, +}) + +function callback.register(name, new) + callbacks[name] = new +end +function callback.find(name) + return callbacks[name] +end + +return callbacks diff --git a/luametalatex-font-enc.lua b/luametalatex-font-enc.lua index 3ff9ed4..b8d2a32 100644 --- a/luametalatex-font-enc.lua +++ b/luametalatex-font-enc.lua @@ -1,3 +1,5 @@ +local readfile = require'luametalatex-readfile' + local white = (lpeg.S'\0\9\10\12\13\32' + '%' * (1 - lpeg.S'\r\n')^0)^1 local regular = 1-lpeg.S'()<>[]{}/%\0\9\10\12\13\32' local name = lpeg.C(regular^1) @@ -5,8 +7,7 @@ local lname = '/' * name / 1 local namearray = lpeg.Ct('['*white^0*lpeg.Cg(lname*white^0, 0)^-1*(lname*white^0)^0*']') local encfile = white^0*lname*white^0*namearray*white^0*'def'*white^0*-1 return function(filename) - local file = io.open(filename, 'r') - local name, encoding = encfile:match(file:read'a') - file:close() + local file = readfile('enc', filename, nil, 'r') + local name, encoding = encfile:match(file()) return encoding, name end diff --git a/luametalatex-font-t1.lua b/luametalatex-font-t1.lua index 4a5baf0..b5ad593 100644 --- a/luametalatex-font-t1.lua +++ b/luametalatex-font-t1.lua @@ -140,11 +140,9 @@ local function parse_maintable(offset, str) return continue_maintable(offset, str, {}) end -return function(filename) - local file = io.open(filename, 'rb') - local preface, private = string.unpack(" = readfile('subset', filename, nil) + local buf = file() local i = 1 - file:close() local magic = buf:sub(1, 4) if magic == "ttcf" or magic == "OTTO" then -- assert(not encoding) -- nil or false @@ -598,4 +596,3 @@ return function(filename, fontid, encoding) return function(fontdir, usedcids) fontdir.bbox = bbox return content end end --- io.open(arg[3], 'w'):write(myfunc(buf, 1, 1, require'parseEnc'(arg[2]), {{string.byte'a'}, {string.byte'b'}, {string.byte'-'}})):close() diff --git a/luametalatex-pdf-font-map.lua b/luametalatex-pdf-font-map.lua index 4c27d38..d4016de 100644 --- a/luametalatex-pdf-font-map.lua +++ b/luametalatex-pdf-font-map.lua @@ -1,3 +1,5 @@ +local readfile = require'luametalatex-readfile' + local purenumber = lpeg.R'09'^1 local optoperator = lpeg.C(lpeg.S'+-='^-1)*lpeg.C(lpeg.P(1)^0) local commentchar = lpeg.S' %*;#'+-1 @@ -38,9 +40,8 @@ local function mapfile(filename, operator) if not operator then operator, filename = optoperator:match(filename) end - local file = io.open(kpse.find_file(filename, 'map'), 'r') + local file = readfile('map', filename, 'map', 'r') for line in file:lines() do mapline(line, operator) end - file:close() end local function reset() for k in next, fontmap do diff --git a/luametalatex-pdf-font-t1.lua b/luametalatex-pdf-font-t1.lua index 12a55d5..b65d106 100644 --- a/luametalatex-pdf-font-t1.lua +++ b/luametalatex-pdf-font-t1.lua @@ -1,11 +1,13 @@ +local readfile = require'luametalatex-readfile' + -- Some helpers: --- A kpse wrapper local serialize_cff = require'luametalatex-font-cff' local serializet2 = require'luametalatex-font-t2' local parseT1 = require'luametalatex-font-t1' local t1tot2 = require'luametalatex-font-t1tot2' return function(filename, reencode) - local parsed_t1 = parseT1(filename) + local file = readfile('subset', filename, nil) + local parsed_t1 = parseT1(file()) return function(f, usedcids) f.bbox = parsed_t1.FontBBox local fonttable = { diff --git a/luametalatex-pdf-font-ttf.lua b/luametalatex-pdf-font-ttf.lua index 2b03eee..8d6d086 100644 --- a/luametalatex-pdf-font-ttf.lua +++ b/luametalatex-pdf-font-ttf.lua @@ -1,3 +1,5 @@ +local readfile = require'luametalatex-readfile' + local sfnt = require'luametalatex-font-sfnt' local stdnames = require'luametalatex-font-ttf-data' local function round(x) @@ -15,7 +17,6 @@ local function addglyph(glyph, usedcids, cidtogid) while offset do local flags, component = string.unpack(">I2I2", glyph, offset) local gid = cidtogid[component] - print(glyph, component, gid) if not gid then gid = #usedcids usedcids[gid+1] = {component} @@ -68,11 +69,10 @@ local function readpostnames(buf, i, usedcids, encoding) return newusedcids end return function(filename, fontid, reencode) - local file = io.open(filename, 'rb') - local buf = file:read'a' - file:close() + local file = readfile('subset', filename, nil) + local buf = file() local magic, tables = sfnt.parse(buf, 1, fontid) - if magic ~= "\0\1\0\0" then error[[Invalid TTF font]] end + if magic ~= "\0\1\0\0" then error[[Invalid TTF font]] end -- TODO: Parse post table and add reencoding support -- if tables.post and string.unpack(">I4", buf, tables.post[1]) == 0x00020000 and reencode then -- local encoding = require'parseEnc'(reencode) diff --git a/luametalatex-pdf-image-png.lua b/luametalatex-pdf-image-png.lua index 500a557..36d1332 100644 --- a/luametalatex-pdf-image-png.lua +++ b/luametalatex-pdf-image-png.lua @@ -1,3 +1,4 @@ +local readfile = require'luametalatex-readfile' local strip_floats = require'luametalatex-pdf-utils'.strip_floats local function ignore() end @@ -204,12 +205,11 @@ end local png_functions = {} function png_functions.scan(img) - local file = io.open(img.filepath, 'rb') + local file = readfile('image', img.filepath, nil) if not file then error[[PDF image could not be opened.]] end - local buf = file:read'a' - file:close() + local buf = file() local t = run(buf, 1, #buf, 'IDAT') img.pages = 1 img.page = 1 @@ -228,9 +228,8 @@ local intents = {[0]= } local function srgb_lookup(pfile, intent) if not srgb_colorspace then - local f = io.open(kpse.find_file'sRGB.icc.zlib', 'rb') - local profile = f:read'a' - f:close() + local file = readfile('silent', 'sRGB.icc.zlib', 'other binary files') + local profile = file() local objnum = pfile:stream(nil, '/Filter/FlateDecode/N ' .. tostring(colortype & 2 == 2 and '3' or '1'), t.iCCP, nil, true) srgb_colorspace = string.format('[/ICCBased %i 0 R]', objnum) end @@ -259,12 +258,11 @@ local function rawimage(t, content) end function png_functions.write(pfile, img) - local file = io.open(img.filepath, 'rb') + local file = readfile('silent', img.filepath, nil) if not file then error[[PDF image could not be opened.]] end - local buf = file:read'a' - file:close() + local buf = file() local t = run(buf, 1, #buf, 'IEND') local colorspace local intent = '' diff --git a/luametalatex-pdf.lua b/luametalatex-pdf.lua index d157741..89b731d 100644 --- a/luametalatex-pdf.lua +++ b/luametalatex-pdf.lua @@ -1,3 +1,5 @@ +local readfile = require'luametalatex-readfile' + local format = string.format local byte = string.byte local pack = string.pack @@ -23,9 +25,8 @@ local function stream(pdf, num, dict, content, isfile, raw) end pdf[num] = {offset = pdf.file:seek()} if isfile then - local f = io.open(content, 'rb') - content = f:read'a' - f:close() + local file = readfile('pdf_stream', content, nil) + content = file() end local level = not raw and pdfvariable.compresslevel or 0 local filter = '' @@ -56,9 +57,8 @@ local function indirect(pdf, num, content, isfile, objstream) error[[Invalid object]] end if isfile then - local f = io.open(content, 'rb') - content = f:read'a' - f:close() + local file = readfile('pdf_dict', content, nil) + content = file() end if objstream ~= false and pdfvariable.objcompresslevel ~= 0 then objstream = objstream or true diff --git a/luametalatex-readfile.lua b/luametalatex-readfile.lua new file mode 100644 index 0000000..c1c113b --- /dev/null +++ b/luametalatex-readfile.lua @@ -0,0 +1,48 @@ +local io_open = io.open +local write = texio.write +local find_file = kpse.find_file + +local callbacks = require'luametalatex-callbacks' + +local categories = { data = 1, map = 2, image = 3, subset = 4, font = 5, enc = 6, pdf_stream = 7, pdf_stream = 8, silent = 9} +local start_categories = { [0] = '?', '(', '{', '<', '<', '<<' } +local stop_categories = { [0] = '?', ')', '}', '>', '>', '>>' } + +local function stop_file(t) + local cb = callbacks.stop_file + if cb then + cb(t.category) + else + write(stop_categories[t.category] or '') + end + t.file:close() +end + +local meta = { + __close = stop_file, + __call = function(t) return t.file:read'a' end, + close = stop_file, + lines = function(t, ...) return t.file:lines(...) end, +} +meta.__index = meta + +return function(category, name, kpse, mode) + category = tonumber(category) or categories[category] or 0 + if kpse then + name = find_file(name, kpse) + end + if not name then return name end + local f, msg = io_open(name, mode or 'rb') + if f then + local cb = callbacks.start_file + if cb then + cb(category, name) + else + local start_mark = start_categories[category] + if start_mark then + write(start_mark .. name) + end + end + end + return f and setmetatable({category = category, file = f}, meta), msg +end