EXPERIMENTAL: Implement file callbacks
This commit is contained in:
parent
7bea04d470
commit
063251b54f
@ -1,98 +1,9 @@
|
|||||||
-- Two callbacks are defined in other files: pre_dump in lateinit and find_fmt_file in init
|
|
||||||
|
|
||||||
local read_tfm = font.read_tfm
|
|
||||||
local font_define = font.define
|
|
||||||
local callback_register = callback.register
|
|
||||||
|
|
||||||
if status.ini_version then
|
|
||||||
callback_register('define_font', function(name, size)
|
|
||||||
local f = read_tfm(name, size)
|
|
||||||
if not f then return end
|
|
||||||
local id = font_define(f)
|
|
||||||
lua.prepared_code[#lua.prepared_code+1] = string.format("assert(%i == font.define(font.read_tfm(%q, %i)))", id, name, size)
|
|
||||||
return id
|
|
||||||
end)
|
|
||||||
else
|
|
||||||
callback_register('define_font', function(name, size)
|
|
||||||
local f = read_tfm(name, size)
|
|
||||||
if not f then
|
|
||||||
tex.error(string.format("Font %q not found", name), "The requested font could't be loaded.\n\z
|
|
||||||
Are you sure that you passed the right name and\n\z
|
|
||||||
that the font is actually installed?")
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
return font.define(f)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
callback_register('find_log_file', function(name) return name end)
|
|
||||||
do
|
|
||||||
local function normal_find_data_file(name)
|
|
||||||
return kpse.find_file(name, 'tex', true)
|
|
||||||
end
|
|
||||||
if status.ini_version then
|
|
||||||
function unhook_expl()
|
|
||||||
callback_register('find_data_file', normal_find_data_file)
|
|
||||||
end
|
|
||||||
callback_register('find_data_file', function(name)
|
|
||||||
if name == 'ltexpl.ltx' then
|
|
||||||
name = 'luametalatex-ltexpl-hook'
|
|
||||||
end
|
|
||||||
return normal_find_data_file(name)
|
|
||||||
end)
|
|
||||||
else
|
|
||||||
callback_register('find_data_file', normal_find_data_file)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- callback_register('read_data_file', function(name) error[[TODO]]return kpse.find_file(name, 'tex', true) end)
|
|
||||||
callback_register('open_data_file', function(name)
|
|
||||||
local f = io.open(name, 'r')
|
|
||||||
return setmetatable({
|
|
||||||
reader = function()
|
|
||||||
local line = f:read()
|
|
||||||
return line
|
|
||||||
end,
|
|
||||||
close = function()error[[1]] return f:close() end,
|
|
||||||
}, {
|
|
||||||
__gc = function()f:close()end,
|
|
||||||
})
|
|
||||||
end)
|
|
||||||
callback_register('handle_error_hook', function()
|
|
||||||
repeat
|
|
||||||
texio.write_nl'? '
|
|
||||||
local line = io.read()
|
|
||||||
if not line then
|
|
||||||
tex.fatalerror'End of line encountered on terminal'
|
|
||||||
end
|
|
||||||
if line == "" then return 3 end
|
|
||||||
local first = line:sub(1,1):upper()
|
|
||||||
if first == 'H' then
|
|
||||||
texio.write(tex.gethelptext() or "Sorry, I don't know how to help in this situation.\n\z
|
|
||||||
Maybe you should try asking a human?")
|
|
||||||
elseif first == 'I' then
|
|
||||||
line = line:sub(2)
|
|
||||||
tex.runtoks(function()
|
|
||||||
tex.sprint(token.scan_token(), line)
|
|
||||||
end)
|
|
||||||
return 3
|
|
||||||
elseif first == 'Q' then texio.write'OK, entering \\batchmode...\n' return 0
|
|
||||||
elseif first == 'R' then texio.write'OK, entering \\nonstopmode...\n' return 1
|
|
||||||
elseif first == 'S' then texio.write'OK, entering \\scrollmode...\n' return 2
|
|
||||||
elseif first == 'X' then return -1
|
|
||||||
else
|
|
||||||
texio.write'Type <return> to proceed, S to scroll future error messages,\
|
|
||||||
\z R to run without stopping, Q to run quietly,\
|
|
||||||
\z I to insert something,\
|
|
||||||
\z H for help, X to quit.'
|
|
||||||
end
|
|
||||||
until false
|
|
||||||
return 3
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- Now overwrite the callback functionality. Our system is based on the ssumption there there are
|
-- 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
|
-- 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.
|
-- good error checking, but we expect this to be overwritten by LaTeX anyway.
|
||||||
|
|
||||||
local callback_find = callback.find
|
local callback_find = callback.find
|
||||||
|
local callback_register = callback.register
|
||||||
local rawset = rawset
|
local rawset = rawset
|
||||||
local callbacks = setmetatable({}, {
|
local callbacks = setmetatable({}, {
|
||||||
__index = function(cbs, name)
|
__index = function(cbs, name)
|
||||||
|
@ -7,7 +7,7 @@ local lname = '/' * name / 1
|
|||||||
local namearray = lpeg.Ct('['*white^0*lpeg.Cg(lname*white^0, 0)^-1*(lname*white^0)^0*']')
|
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
|
local encfile = white^0*lname*white^0*namearray*white^0*'def'*white^0*-1
|
||||||
return function(filename)
|
return function(filename)
|
||||||
local file <close> = readfile('enc', filename, nil, 'r')
|
local file <close> = readfile('enc', filename)
|
||||||
local name, encoding = encfile:match(file())
|
local name, encoding = encfile:match(file())
|
||||||
return encoding, name
|
return encoding, name
|
||||||
end
|
end
|
||||||
|
@ -192,12 +192,9 @@ local function parse_commands(buf, off, t)
|
|||||||
until cmd == 245
|
until cmd == 245
|
||||||
return off
|
return off
|
||||||
end
|
end
|
||||||
return function(filename)
|
return function(data)
|
||||||
local f = assert(io.open(filename, 'rb'))
|
|
||||||
local pk = f:read'a'
|
|
||||||
f:close()
|
|
||||||
local res = {}
|
local res = {}
|
||||||
local off = parse_commands(pk, 1, res)
|
local off = parse_commands(data, 1, res)
|
||||||
-- assert(off == #pk+1) -- TODO: Check that only fillup bytes follow
|
-- assert(off == #pk+1) -- TODO: Check that only fillup bytes follow
|
||||||
return res
|
return res
|
||||||
end
|
end
|
||||||
|
@ -7,7 +7,7 @@ local callback_find = callback.find
|
|||||||
local old_font_define = font.define
|
local old_font_define = font.define
|
||||||
local old_addcharacters = font.addcharacters
|
local old_addcharacters = font.addcharacters
|
||||||
|
|
||||||
require'luametalatex-pdf-font-map'.mapfile(kpse.find_file('pdftex.map', 'map', true))
|
require'luametalatex-pdf-font-map'.mapfile'pdftex.map'
|
||||||
|
|
||||||
local all_fonts = {}
|
local all_fonts = {}
|
||||||
font.fonts = all_fonts
|
font.fonts = all_fonts
|
||||||
@ -16,9 +16,9 @@ function font.getfont(id)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local fontextensions = {
|
local fontextensions = {
|
||||||
ttf = {"truetype", "truetype fonts",},
|
ttf = "truetype",
|
||||||
otf = {"opentype", "opentype fonts",},
|
otf = "opentype",
|
||||||
pfb = {"type1", "type1 fonts",},
|
pfb = "type1",
|
||||||
}
|
}
|
||||||
fontextensions.cff = fontextensions.otf
|
fontextensions.cff = fontextensions.otf
|
||||||
local fontformats = {
|
local fontformats = {
|
||||||
@ -60,40 +60,15 @@ function font.define(f)
|
|||||||
local entry = fontmap[f.name]
|
local entry = fontmap[f.name]
|
||||||
if entry then
|
if entry then
|
||||||
local filename = entry[3]
|
local filename = entry[3]
|
||||||
local format = filename and filename:sub(-4, -4) == '.' and fontextensions[filename:sub(-3, -1)]
|
local format
|
||||||
if format then
|
if f.format == 'unknown' then
|
||||||
f.format = format[1]
|
f.format = filename and filename:sub(-4, -4) == '.' and fontextensions[filename:sub(-3, -1)] or 'type1'
|
||||||
f.filename = kpse.find_file(filename, format[2])
|
|
||||||
local encoding = entry[4]
|
|
||||||
if encoding then
|
|
||||||
f.encoding = kpse.find_file(encoding, 'enc files')
|
|
||||||
end
|
end
|
||||||
if entry[5] then
|
|
||||||
assert(special_parser:match(entry[5], 1, f))
|
|
||||||
end
|
|
||||||
else
|
|
||||||
local done = false
|
|
||||||
for _, format in ipairs(fontformats) do
|
|
||||||
local filename = kpse.find_file(filename, format[2])
|
|
||||||
if filename then
|
|
||||||
f.filename = filename
|
f.filename = filename
|
||||||
f.format = format[1]
|
f.encoding = entry[4]
|
||||||
local encoding = entry[4]
|
|
||||||
if encoding then
|
|
||||||
f.encoding = kpse.find_file(encoding, 'enc files')
|
|
||||||
end
|
|
||||||
if entry[5] then
|
if entry[5] then
|
||||||
assert(special_parser:match(entry[5], 1, f))
|
assert(special_parser:match(entry[5], 1, f))
|
||||||
end
|
end
|
||||||
done = true
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not done then
|
|
||||||
print('!', 'type3', require'inspect'(entry))
|
|
||||||
f.format = "type3"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
f.format = "type3"
|
f.format = "type3"
|
||||||
end
|
end
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
local readfile = require'luametalatex-readfile'
|
||||||
|
|
||||||
local upper_mask = (1<<20)-1<<44
|
local upper_mask = (1<<20)-1<<44
|
||||||
local shifted_sign = 1<<43
|
local shifted_sign = 1<<43
|
||||||
local function scale(factor1, factor2)
|
local function scale(factor1, factor2)
|
||||||
@ -141,13 +143,9 @@ local function parse_tfm(buf, i, size)
|
|||||||
end
|
end
|
||||||
local basename = ((1-lpeg.S'\\/')^0*lpeg.S'\\/')^0*lpeg.C((1-lpeg.P'.tfm'*-1)^0)
|
local basename = ((1-lpeg.S'\\/')^0*lpeg.S'\\/')^0*lpeg.C((1-lpeg.P'.tfm'*-1)^0)
|
||||||
return function(name, size)
|
return function(name, size)
|
||||||
local filename = kpse.find_file(name, 'tfm', true)
|
local file <close> = readfile('tfm', name)
|
||||||
if not filename then return end
|
if not file then return end
|
||||||
local f = io.open(filename, 'rb')
|
local result = parse_tfm(file(), 1, size)
|
||||||
if not f then return end
|
|
||||||
local buf = f:read'*a'
|
|
||||||
f:close()
|
|
||||||
local result = parse_tfm(buf, 1, size)
|
|
||||||
result.name = basename:match(name)
|
result.name = basename:match(name)
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
local readfile = require'luametalatex-readfile'
|
||||||
|
|
||||||
local fontcmds = {
|
local fontcmds = {
|
||||||
[243] = ">I1I4I4I4BB",
|
[243] = ">I1I4I4I4BB",
|
||||||
[244] = ">I2I4I4I4BB",
|
[244] = ">I2I4I4I4BB",
|
||||||
@ -166,13 +168,9 @@ local function parse_vf(buf, i, size)
|
|||||||
end
|
end
|
||||||
local basename = ((1-lpeg.S'\\/')^0*lpeg.S'\\/')^0*lpeg.C((1-lpeg.P'.tfm'*-1)^0)
|
local basename = ((1-lpeg.S'\\/')^0*lpeg.S'\\/')^0*lpeg.C((1-lpeg.P'.tfm'*-1)^0)
|
||||||
return function(name, size, must_exist)
|
return function(name, size, must_exist)
|
||||||
local filename = kpse.find_file(name, 'vf', must_exist)
|
local file <close> = readfile('vf', name)
|
||||||
if not filename then return end
|
if not file then return end
|
||||||
local f = io.open(filename, 'rb')
|
local result = parse_vf(file(), 1, size)
|
||||||
if not f then return end
|
|
||||||
local buf = f:read'*a'
|
|
||||||
f:close()
|
|
||||||
local result = parse_vf(buf, 1, size)
|
|
||||||
result.name = basename:match(name)
|
result.name = basename:match(name)
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
@ -13,7 +13,7 @@ pdf = {
|
|||||||
variable = {},
|
variable = {},
|
||||||
}
|
}
|
||||||
require'luametalatex-font-resolve' -- Replace font.define. Must be loaded before callbacks
|
require'luametalatex-font-resolve' -- Replace font.define. Must be loaded before callbacks
|
||||||
require'luametalatex-callbacks'
|
require'luametalatex-basecallbacks'
|
||||||
|
|
||||||
local functions = lua.getfunctionstable()
|
local functions = lua.getfunctionstable()
|
||||||
-- I am not sure why this is necessary, but otherwise LuaMetaTeX resets
|
-- I am not sure why this is necessary, but otherwise LuaMetaTeX resets
|
||||||
|
@ -451,11 +451,6 @@ function myfunc(buf, i0, fontid, usedcids, encoding, trust_widths)
|
|||||||
end
|
end
|
||||||
-- top.CharStrings = named_charstrings
|
-- top.CharStrings = named_charstrings
|
||||||
if not top.ROS then
|
if not top.ROS then
|
||||||
-- if encoding == true and top.Encoding < 3 then
|
|
||||||
-- if not reencode and parsed_t1.Encoding == "StandardEncoding" then
|
|
||||||
-- reencode = kpse.find_file("8a.enc", "enc files")
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
if encoding == true then -- Use the built-in encoding
|
if encoding == true then -- Use the built-in encoding
|
||||||
CharStrings = parse_encoding(buf, i0, top.Encoding, CharStrings)
|
CharStrings = parse_encoding(buf, i0, top.Encoding, CharStrings)
|
||||||
elseif encoding then
|
elseif encoding then
|
||||||
@ -580,7 +575,7 @@ function myfunc(buf, i0, fontid, usedcids, encoding, trust_widths)
|
|||||||
end
|
end
|
||||||
|
|
||||||
return function(filename, fontid, encoding) return function(fontdir, usedcids)
|
return function(filename, fontid, encoding) return function(fontdir, usedcids)
|
||||||
local file <close> = readfile('subset', filename, nil)
|
local file <close> = readfile('opentype', filename)
|
||||||
local buf = file()
|
local buf = file()
|
||||||
local i = 1
|
local i = 1
|
||||||
local magic = buf:sub(1, 4)
|
local magic = buf:sub(1, 4)
|
||||||
|
@ -40,7 +40,7 @@ local function mapfile(filename, operator)
|
|||||||
if not operator then
|
if not operator then
|
||||||
operator, filename = optoperator:match(filename)
|
operator, filename = optoperator:match(filename)
|
||||||
end
|
end
|
||||||
local file <close> = readfile('map', filename, 'map', 'r')
|
local file <close> = readfile('map', filename)
|
||||||
for line in file:lines() do mapline(line, operator) end
|
for line in file:lines() do mapline(line, operator) end
|
||||||
end
|
end
|
||||||
local function reset()
|
local function reset()
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
local pk_global_resolution, pk_resolution_is_fixed
|
local pk_global_resolution, pk_resolution_is_fixed
|
||||||
local pdfvariable = pdf.variable
|
local pdfvariable = pdf.variable
|
||||||
|
|
||||||
|
local readfile = require'luametalatex-readfile'
|
||||||
local read_pk = require'luametalatex-font-pk'
|
local read_pk = require'luametalatex-font-pk'
|
||||||
local strip_floats = require'luametalatex-pdf-utils'.strip_floats
|
local strip_floats = require'luametalatex-pdf-utils'.strip_floats
|
||||||
return function(pdf, fontdir, usedcids)
|
return function(pdf, fontdir, usedcids)
|
||||||
@ -13,7 +14,8 @@ return function(pdf, fontdir, usedcids)
|
|||||||
pk_resolution_is_fixed = pdfvariable.pkfixeddpi ~= 0
|
pk_resolution_is_fixed = pdfvariable.pkfixeddpi ~= 0
|
||||||
kpse.init_prog("LUATEX", pk_global_resolution, pkmode ~= '' and pkmode or nil, nil) -- ?
|
kpse.init_prog("LUATEX", pk_global_resolution, pkmode ~= '' and pkmode or nil, nil) -- ?
|
||||||
end
|
end
|
||||||
local pk = read_pk(kpse.find_file(fontdir.name, 'pk', pk_resolution_is_fixed and pk_global_resolution or (pk_global_resolution*fontdir.size/fontdir.designsize+.5)//1))
|
local f <close> = assert(readfile('pk', fontdir.name, pk_resolution_is_fixed and pk_global_resolution or (pk_global_resolution*fontdir.size/fontdir.designsize+.5)//1))
|
||||||
|
local pk = read_pk(f())
|
||||||
local designsize = pk.designsize/1044654.326 -- 1044654.326=2^20*72/72.27 -- designsize in bp
|
local designsize = pk.designsize/1044654.326 -- 1044654.326=2^20*72/72.27 -- designsize in bp
|
||||||
local hscale = 65536/pk.hppp / designsize -- 65291.158=2^16*72/72.27
|
local hscale = 65536/pk.hppp / designsize -- 65291.158=2^16*72/72.27
|
||||||
local vscale = 65536/pk.vppp / designsize -- 65291.158=2^16*72/72.27
|
local vscale = 65536/pk.vppp / designsize -- 65291.158=2^16*72/72.27
|
||||||
|
@ -6,7 +6,7 @@ local serializet2 = require'luametalatex-font-t2'
|
|||||||
local parseT1 = require'luametalatex-font-t1'
|
local parseT1 = require'luametalatex-font-t1'
|
||||||
local t1tot2 = require'luametalatex-font-t1tot2'
|
local t1tot2 = require'luametalatex-font-t1tot2'
|
||||||
return function(filename, reencode)
|
return function(filename, reencode)
|
||||||
local file <close> = readfile('subset', filename, nil)
|
local file <close> = readfile('type1', filename)
|
||||||
local parsed_t1 = parseT1(file())
|
local parsed_t1 = parseT1(file())
|
||||||
return function(f, usedcids)
|
return function(f, usedcids)
|
||||||
f.bbox = parsed_t1.FontBBox
|
f.bbox = parsed_t1.FontBBox
|
||||||
@ -40,7 +40,7 @@ return function(filename, reencode)
|
|||||||
-- LanguageGroup = parsed_t1.Private.LanguageGroup,
|
-- LanguageGroup = parsed_t1.Private.LanguageGroup,
|
||||||
}
|
}
|
||||||
if not reencode and parsed_t1.Encoding == "StandardEncoding" then
|
if not reencode and parsed_t1.Encoding == "StandardEncoding" then
|
||||||
reencode = kpse.find_file("8a.enc", "enc files")
|
reencode = '8a'
|
||||||
end
|
end
|
||||||
if reencode then
|
if reencode then
|
||||||
parsed_t1.Encoding = require'luametalatex-font-enc'(reencode)
|
parsed_t1.Encoding = require'luametalatex-font-enc'(reencode)
|
||||||
|
@ -69,7 +69,7 @@ local function readpostnames(buf, i, usedcids, encoding)
|
|||||||
return newusedcids
|
return newusedcids
|
||||||
end
|
end
|
||||||
return function(filename, fontid, reencode)
|
return function(filename, fontid, reencode)
|
||||||
local file <close> = readfile('subset', filename, nil)
|
local file <close> = readfile('truetype', filename)
|
||||||
local buf = file()
|
local buf = file()
|
||||||
local magic, tables = sfnt.parse(buf, 1, fontid)
|
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
|
||||||
|
@ -31,8 +31,16 @@ end
|
|||||||
|
|
||||||
local pdf_functions = {}
|
local pdf_functions = {}
|
||||||
|
|
||||||
local function open_pdfe(img)
|
local function open_pdfe(img, f)
|
||||||
local file = pdfe.open(img.filepath)
|
local file
|
||||||
|
if f and f.file then
|
||||||
|
file = pdfe.openfile(f.file)
|
||||||
|
f.file = nil
|
||||||
|
elseif img.filedata then
|
||||||
|
file = pdfe.new(img.filedata, #img.filedata)
|
||||||
|
elseif img.filepath then
|
||||||
|
file = pdfe.open(img.filepath)
|
||||||
|
end
|
||||||
do
|
do
|
||||||
local userpassword = img.userpassword
|
local userpassword = img.userpassword
|
||||||
local ownerpassword = img.ownerpassword
|
local ownerpassword = img.ownerpassword
|
||||||
@ -51,8 +59,8 @@ local function open_pdfe(img)
|
|||||||
assert(false)
|
assert(false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
function pdf_functions.scan(img)
|
function pdf_functions.scan(img, f)
|
||||||
local file = open_pdfe(img)
|
local file = open_pdfe(img, f)
|
||||||
img.pages = pdfe.getnofpages(file)
|
img.pages = pdfe.getnofpages(file)
|
||||||
img.page = img.page or 1
|
img.page = img.page or 1
|
||||||
if img.page > img.pages then
|
if img.page > img.pages then
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
local readfile = require'luametalatex-readfile'
|
|
||||||
local strip_floats = require'luametalatex-pdf-utils'.strip_floats
|
local strip_floats = require'luametalatex-pdf-utils'.strip_floats
|
||||||
|
|
||||||
local function ignore() end
|
local function ignore() end
|
||||||
@ -7,17 +6,18 @@ local parse = setmetatable({
|
|||||||
-- PLTE = below,
|
-- PLTE = below,
|
||||||
-- IDAT = below,
|
-- IDAT = below,
|
||||||
-- IEND = below,
|
-- IEND = below,
|
||||||
-- I'm not yet sure what to do about the following four color management chunks:
|
-- I originally thought about ignoring cHRM and gAMA (if you care about this stuff, you probably
|
||||||
-- These two will probably be ignored (if you care about this stuff, you probably
|
-- prefer an ICC profile anyway) but it was interesting to think about so it got implemented.
|
||||||
-- prefer an ICC profile anyway. Also especially cHRM requires some weird computations.)
|
-- But, gAMA is ONLY supported in combination with cHRM and not on it's own.
|
||||||
-- cHRM = TODO, -- ignore?
|
-- cHRM = below,
|
||||||
-- gAMA = TODO, -- ignore?
|
-- gAMA = below,
|
||||||
-- iCCP is implemented, but profiles are not cached, so it might include the
|
-- iCCP is implemented, but profiles are not cached, so it might include the
|
||||||
-- same profile many times
|
-- same profile many times
|
||||||
-- iCCP = below,
|
-- iCCP = below,
|
||||||
-- I would expect sRGB to be the most common, but it is a bit complicated because
|
-- I would expect sRGB to be the most common, but it is a bit complicated because
|
||||||
-- PDF seems to require us to ship an actual ICC profile to support sRGB. Maybe later.
|
-- PDF seems to require us to ship an actual ICC profile to support sRGB. Luckily,
|
||||||
-- sRGB = TODO,
|
-- such a profile is part of TeXLive anyway.
|
||||||
|
-- sRGB = below,
|
||||||
sBIT = ignore,
|
sBIT = ignore,
|
||||||
bKGD = ignore, -- Background color. Ignored since we support transparency
|
bKGD = ignore, -- Background color. Ignored since we support transparency
|
||||||
hIST = ignore, -- Color histogram
|
hIST = ignore, -- Color histogram
|
||||||
@ -204,12 +204,8 @@ end
|
|||||||
|
|
||||||
local png_functions = {}
|
local png_functions = {}
|
||||||
|
|
||||||
function png_functions.scan(img)
|
function png_functions.scan(img, f)
|
||||||
local file <close> = readfile('image', img.filepath, nil)
|
local buf = f()
|
||||||
if not file then
|
|
||||||
error[[PDF image could not be opened.]]
|
|
||||||
end
|
|
||||||
local buf = file()
|
|
||||||
local t = run(buf, 1, #buf, 'IDAT')
|
local t = run(buf, 1, #buf, 'IDAT')
|
||||||
img.pages = 1
|
img.pages = 1
|
||||||
img.page = 1
|
img.page = 1
|
||||||
@ -228,9 +224,9 @@ local intents = {[0]=
|
|||||||
}
|
}
|
||||||
local function srgb_lookup(pfile, intent)
|
local function srgb_lookup(pfile, intent)
|
||||||
if not srgb_colorspace then
|
if not srgb_colorspace then
|
||||||
local file <close> = readfile('silent', 'sRGB.icc.zlib', 'other binary files')
|
local file <close> = readfile('data', 'sRGB.icc')
|
||||||
local profile = file()
|
local profile = file()
|
||||||
local objnum = pfile:stream(nil, '/Filter/FlateDecode/N ' .. tostring(colortype & 2 == 2 and '3' or '1'), t.iCCP, nil, true)
|
local objnum = pfile:stream(nil, '/N 3', profile) -- FIXME: file stream
|
||||||
srgb_colorspace = string.format('[/ICCBased %i 0 R]', objnum)
|
srgb_colorspace = string.format('[/ICCBased %i 0 R]', objnum)
|
||||||
end
|
end
|
||||||
return objnum, intents[intent] or ''
|
return objnum, intents[intent] or ''
|
||||||
@ -258,11 +254,11 @@ local function rawimage(t, content)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function png_functions.write(pfile, img)
|
function png_functions.write(pfile, img)
|
||||||
local file <close> = readfile('silent', img.filepath, nil)
|
local buf = img.filedata
|
||||||
if not file then
|
if not buf then
|
||||||
error[[PDF image could not be opened.]]
|
local f <close> = assert(io.open(img.filepath, 'rb'))
|
||||||
|
buf = f:read'a'
|
||||||
end
|
end
|
||||||
local buf = file()
|
|
||||||
local t = run(buf, 1, #buf, 'IEND')
|
local t = run(buf, 1, #buf, 'IEND')
|
||||||
local colorspace
|
local colorspace
|
||||||
local intent = ''
|
local intent = ''
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
local readfile = require'luametalatex-readfile'
|
||||||
|
|
||||||
local rawset = rawset
|
local rawset = rawset
|
||||||
local setdata = node.direct.setdata
|
local setdata = node.direct.setdata
|
||||||
local nodenew = node.direct.new
|
local nodenew = node.direct.new
|
||||||
@ -61,14 +63,18 @@ local function scan(img)
|
|||||||
if m ~= meta then img = new(img) end
|
if m ~= meta then img = new(img) end
|
||||||
real = real_images[img]
|
real = real_images[img]
|
||||||
if real.stream then error[[stream images are not yet supported]] end
|
if real.stream then error[[stream images are not yet supported]] end
|
||||||
assert(real.filename)
|
|
||||||
-- TODO: At some point we should just take the lowercased extension
|
-- TODO: At some point we should just take the lowercased extension
|
||||||
local imagetype = real.filename:match'%.pdf$' and 'pdf'
|
local imagetype = real.filename:match'%.pdf$' and 'pdf'
|
||||||
or real.filename:match'%.png$' and 'png'
|
or real.filename:match'%.png$' and 'png'
|
||||||
or error'Unsupported image format'
|
or error'Unsupported image format'
|
||||||
real.filepath = assert(kpse.find_file(real.filename), "Image not found")
|
|
||||||
real.imagetype = imagetype
|
real.imagetype = imagetype
|
||||||
imagetypes[imagetype].scan(real)
|
local f <close>, path = assert(readfile('image', real.filename))
|
||||||
|
if f.file then
|
||||||
|
real.filepath = path
|
||||||
|
else
|
||||||
|
real.filedata = f.data
|
||||||
|
end
|
||||||
|
imagetypes[imagetype].scan(real, f)
|
||||||
setmetatable(img, restricted_meta)
|
setmetatable(img, restricted_meta)
|
||||||
end
|
end
|
||||||
img.transform = img.transform or 0
|
img.transform = img.transform or 0
|
||||||
|
@ -4,7 +4,22 @@ local find_file = kpse.find_file
|
|||||||
|
|
||||||
local callbacks = require'luametalatex-callbacks'
|
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 categories = { data = 1, map = 2, image = 3, subset = 4, font = 5 -- , enc = 6, pdf_stream = 7, pdf_stream = 8, silent = 9}
|
||||||
|
|
||||||
|
local our_callbacks = {
|
||||||
|
vf = {'vf', false, 'rb', 'find_vf_file_callback', 'read_vf_file_callback'},
|
||||||
|
tfm = {'tfm', false, 'rb', 'find_font_file_callback', 'read_font_file_callback'},
|
||||||
|
map = {'map', 2, 'rb', 'find_map_file_callback', 'read_map_file_callback'},
|
||||||
|
enc = {'enc', false, 'rb', 'find_enc_file_callback', 'read_enc_file_callback'},
|
||||||
|
type1 = {'type1 fonts', 4, 'rb', 'find_type1_file_callback', 'read_type1_file_callback'},
|
||||||
|
truetype = {'truetype fonts', 4, 'rb', 'find_truetype_file_callback', 'read_truetype_file_callback'},
|
||||||
|
opentype = {'opentype fonts', 4, 'rb', 'find_opentype_file_callback', 'read_opentype_file_callback'},
|
||||||
|
pk = {'pk', 4, 'rb', 'find_pk_file_callback', 'read_pk_file_callback'},
|
||||||
|
enc = {'enc files', false, 'rb', 'find_enc_file_callback', 'read_enc_file_callback'},
|
||||||
|
image = {'tex', 3, 'rb', 'find_image_file_callback', 'read_image_file_callback'},
|
||||||
|
data = {'tex', 1, 'rb', 'find_data_file_callback', 'read_data_file_callback'},
|
||||||
|
}
|
||||||
|
|
||||||
local start_categories = { [0] = '?', '(', '{', '<', '<', '<<' }
|
local start_categories = { [0] = '?', '(', '{', '<', '<', '<<' }
|
||||||
local stop_categories = { [0] = '?', ')', '}', '>', '>', '>>' }
|
local stop_categories = { [0] = '?', ')', '}', '>', '>', '>>' }
|
||||||
|
|
||||||
@ -15,34 +30,61 @@ local function stop_file(t)
|
|||||||
else
|
else
|
||||||
write(stop_categories[t.category] or '')
|
write(stop_categories[t.category] or '')
|
||||||
end
|
end
|
||||||
t.file:close()
|
if t.file then t.file:close() end
|
||||||
end
|
end
|
||||||
|
|
||||||
local meta = {
|
local meta_file = {
|
||||||
__close = stop_file,
|
__close = stop_file,
|
||||||
__call = function(t) return t.file:read'a' end,
|
__call = function(t) return t.file:read'a' end,
|
||||||
close = stop_file,
|
close = stop_file,
|
||||||
lines = function(t, ...) return t.file:lines(...) end,
|
lines = function(t, ...) return t.file:lines(...) end,
|
||||||
}
|
}
|
||||||
meta.__index = meta
|
meta_file.__index = meta_file
|
||||||
|
|
||||||
return function(category, name, kpse, mode)
|
local meta_data = {
|
||||||
category = tonumber(category) or categories[category] or 0
|
__close = stop_file,
|
||||||
if kpse then
|
__call = function(t) return t.data end,
|
||||||
name = find_file(name, kpse)
|
close = stop_file,
|
||||||
|
lines = function(t, ...) return t.data:gmatch('([^\n]*)\n') end,
|
||||||
|
}
|
||||||
|
meta_data.__index = meta_data
|
||||||
|
|
||||||
|
return function(kind, name, ...)
|
||||||
|
local handle
|
||||||
|
local kind_info = our_callbacks[kind]
|
||||||
|
local msg
|
||||||
|
if kind_info then
|
||||||
|
local find_callback = callbacks[kind_info[4]]
|
||||||
|
if find_callback then
|
||||||
|
name, msg = find_callback(name, ...)
|
||||||
|
else
|
||||||
|
name, msg = find_file(name, kind_info[1], ...)
|
||||||
end
|
end
|
||||||
if not name then return name end
|
if not name then return name, msg end
|
||||||
local f, msg = io_open(name, mode or 'rb')
|
handle = {category = kind_info[2]}
|
||||||
if f then
|
local read_callback = callbacks[kind_info[5]]
|
||||||
|
if read_callback then
|
||||||
|
local success, data, size = read_callback(name)
|
||||||
|
if not success then return success, data end
|
||||||
|
if size < #data then data = data:sub(1,size) end
|
||||||
|
handle.data = data, data
|
||||||
|
setmetatable(handle, meta_data)
|
||||||
|
else
|
||||||
|
local f f, msg = io_open(name, kind_info[3])
|
||||||
|
if not f then return f, msg end
|
||||||
|
handle.file = f
|
||||||
|
setmetatable(handle, meta_file)
|
||||||
|
end
|
||||||
|
if handle.category then
|
||||||
local cb = callbacks.start_file
|
local cb = callbacks.start_file
|
||||||
if cb then
|
if cb then
|
||||||
cb(category, name)
|
cb(handle.category, name)
|
||||||
else
|
else
|
||||||
local start_mark = start_categories[category]
|
write(start_categories[handle.category] .. name)
|
||||||
if start_mark then
|
|
||||||
write(start_mark .. name)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
error[[Unknown file]]
|
||||||
end
|
end
|
||||||
return f and setmetatable({category = category, file = f}, meta), msg
|
return handle, name
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user