From b506fd435754bf3644d65761177cb0d5cf78bd8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Fabian=20Kr=C3=BCger?= Date: Tue, 30 Jun 2020 15:14:24 +0200 Subject: [PATCH] pdfvariable handling --- luametalatex-back-pdf.lua | 15 ++++---- luametalatex-baseregisters.lua | 63 ++++++++++++++++++++++++++++++---- luametalatex-init.lua | 12 +++++-- 3 files changed, 74 insertions(+), 16 deletions(-) diff --git a/luametalatex-back-pdf.lua b/luametalatex-back-pdf.lua index e357f7c..c91b676 100644 --- a/luametalatex-back-pdf.lua +++ b/luametalatex-back-pdf.lua @@ -324,14 +324,15 @@ local function do_dest(prop, p, n, x, y) assert(cur_page, "Destinations can not appear outside of a page") local id = prop.dest_id local dest_type = prop.dest_type + local off = pdfvariable.linkmargin local data if dest_type == "xyz" then local x, y = projected(p.matrix, x, y) local zoom = prop.xyz_zoom if zoom then - data = string.format("[%i 0 R/XYZ %.5f %.5f %.3f]", cur_page, sp2bp(x), sp2bp(y), prop.zoom/1000) + data = string.format("[%i 0 R/XYZ %.5f %.5f %.3f]", cur_page, sp2bp(x-off), sp2bp(y+off), prop.zoom/1000) else - data = string.format("[%i 0 R/XYZ %.5f %.5f null]", cur_page, sp2bp(x), sp2bp(y)) + data = string.format("[%i 0 R/XYZ %.5f %.5f null]", cur_page, sp2bp(x-off), sp2bp(y+off)) end elseif dest_type == "fitr" then local m = p.matrix @@ -341,23 +342,23 @@ local function do_dest(prop, p, n, x, y) local urx, ury = projected(x+prop.width, x + prop.height) local left, lower, right, upper = math.min(llx, lrx, ulx, urx), math.min(lly, lry, uly, ury), math.max(llx, lrx, ulx, urx), math.max(lly, lry, uly, ury) - data = string.format("[%i 0 R/FitR %.5f %.5f %.5f %.5f]", cur_page, sp2bp(left), sp2bp(lower), sp2bp(right), sp2bp(upper)) + data = string.format("[%i 0 R/FitR %.5f %.5f %.5f %.5f]", cur_page, sp2bp(left-off), sp2bp(lower-off), sp2bp(right+off), sp2bp(upper+off)) elseif dest_type == "fit" then data = string.format("[%i 0 R/Fit]", cur_page) elseif dest_type == "fith" then local x, y = projected(p.matrix, x, y) - data = string.format("[%i 0 R/FitH %.5f]", cur_page, sp2bp(y)) + data = string.format("[%i 0 R/FitH %.5f]", cur_page, sp2bp(y+off)) elseif dest_type == "fitv" then local x, y = projected(p.matrix, x, y) - data = string.format("[%i 0 R/FitV %.5f]", cur_page, sp2bp(x)) + data = string.format("[%i 0 R/FitV %.5f]", cur_page, sp2bp(x-off)) elseif dest_type == "fitb" then data = string.format("[%i 0 R/FitB]", cur_page) elseif dest_type == "fitbh" then local x, y = projected(p.matrix, x, y) - data = string.format("[%i 0 R/FitBH %.5f]", cur_page, sp2bp(y)) + data = string.format("[%i 0 R/FitBH %.5f]", cur_page, sp2bp(y+off)) elseif dest_type == "fitbv" then local x, y = projected(p.matrix, x, y) - data = string.format("[%i 0 R/FitBV %.5f]", cur_page, sp2bp(x)) + data = string.format("[%i 0 R/FitBV %.5f]", cur_page, sp2bp(x-off)) end if pfile:written(dests[id]) then texio.write_nl(string.format("Duplicate destination %q", id)) diff --git a/luametalatex-baseregisters.lua b/luametalatex-baseregisters.lua index 7bbcc5b..7b041f1 100644 --- a/luametalatex-baseregisters.lua +++ b/luametalatex-baseregisters.lua @@ -11,7 +11,8 @@ local texmeta = getmetatable(tex) local texmetaoldindex = texmeta.__index local texmetaoldnewindex = texmeta.__newindex -local tex_variables = {} +local tex_variables = __luametalatex__preserved_tex_variables or {} +__luametalatex__preserved_tex_variables = nil function texmeta.__index(t, k) return tex_variables[k] or texmetaoldindex(t, k) @@ -33,10 +34,14 @@ local function tex_variable(value, scanner, name, default) return set_local(tex_variables, name, scanner(), scanning == 'global') end end, 'global', 'protected', 'value') - tex_variables[name] = default + if status.ini_version then + tex_variables[name] = default + end end -local real_pdf_variables, pdf_variable_names = {}, {} +local real_pdf_variables = __luametalatex__preserved_real_pdf_variables or {} +__luametalatex__preserved_real_pdf_variables = nil +local pdf_variable_names = {} local pdf_toks_map = {} local pdf_variables = setmetatable(pdf.variable, { __index = function(_, k) @@ -88,17 +93,26 @@ else end end -local function pdf_variable(value, scanner, name, default) +local function pdf_variable(value, scanner, name, default, force_default) pdf_variable_names[#pdf_variable_names+1] = name token.luacmd('pdfvariable ' .. name, function(_, scanning) if scanning == 'value' then return value, real_pdf_variables[name] + elseif force_default then + token.scan_keyword'=' + local new = scanner() + if new ~= default then + texio.write_nl('term and log', string.format("Unsupported PDF variable: \z + %q is not supported and fixed to %i, but you tried to set it to %i", name, default, new)) + end else token.scan_keyword'=' return set_local(real_pdf_variables, name, scanner(), scanning == 'global') end end, 'global', 'protected', 'value') - real_pdf_variables[name] = default + if status.ini_version then + real_pdf_variables[name] = default + end end tex_variable(count_code, token.scan_int, 'suppressfontnotfounderror', 0) @@ -113,10 +127,30 @@ tex_variable(count_code, token.scan_int, 'pagedirection', 0) pdf_variable(dimen_code, token.scan_dimen, 'horigin', tex.sp'1in') pdf_variable(dimen_code, token.scan_dimen, 'vorigin', tex.sp'1in') pdf_variable(dimen_code, token.scan_dimen, 'linkmargin', tex.sp'0pt') +pdf_variable(dimen_code, token.scan_dimen, 'destmargin', tex.sp'0pt') pdf_variable(count_code, token.scan_int, 'majorversion', 1) pdf_variable(count_code, token.scan_int, 'minorversion', 7) pdf_variable(count_code, token.scan_int, 'compresslevel', 0) -pdf_variable(count_code, token.scan_int, 'objcompresslevel', 0) -- 0 is actually the only supported value right now, so this is basically ignored + +pdf_variable(count_code, token.scan_int, 'objcompresslevel', 0, true) -- TODO ... not particularly urgent +pdf_variable(count_code, token.scan_int, 'decimaldigits', 4, true) -- Will probably stay fixed, but should be more consistent +pdf_variable(count_code, token.scan_int, 'gentounicode', 0, true) -- We expect the fontloader to generade tounicode tables. Might change at some point +-- These two are ignored, but that is consistent with pdfTeX as long as imageapplygamma is 0: +pdf_variable(count_code, token.scan_int, 'gamma', 1000) +pdf_variable(count_code, token.scan_int, 'imagegamma', 1000) +pdf_variable(count_code, token.scan_int, 'imageapplygamma', 0, true) +pdf_variable(count_code, token.scan_int, 'imagehicolor', 1, true) -- We don't consider ancient PDF versions, no no reason to strip images +pdf_variable(count_code, token.scan_int, 'imageaddfilename', 0, true) -- Could be added, but I never saw a reason for this anyway. +pdf_variable(count_code, token.scan_int, 'inclusionerrorlevel', -1, true) -- FIXME: At least a warning should be supported +pdf_variable(count_code, token.scan_int, 'inclusioncopyfonts', 0, true) -- Would be fragile and restrict our ability to use "creative" font constructs +pdf_variable(count_code, token.scan_int, 'uniqueresname', 0, true) -- I add this if you show me a usecase +pdf_variable(count_code, token.scan_int, 'pagebox', 2, true) -- TODO (1: media, 2: crop, 3: bleed, 4: trim, 5: art +pdf_variable(count_code, token.scan_int, 'forcepagebox', 0, true) -- Considered obsolete even in pdfTeX +pdf_variable(count_code, token.scan_int, 'imageresolution', 72, true) -- TODO Also 0 should be the same as 72 ?!?!?!? +-- The following two relate to pk fonts which we don't support, so they are ignored on a different level +pdf_variable(count_code, token.scan_int, 'pkresolution', 72) +-- pdf_variable(toks_code, token.scan_string, 'pkmode', '') + pdf_toks('pageresources', '') @@ -128,3 +162,20 @@ local dir_regs = require 'luametalatex-dir-registers' dir_regs 'textdir' dir_regs 'bodydir' dir_regs 'pagedir' + +if status.ini_version then + -- Run in pre_dump callback: + lua.prepared_code[#lua.prepared_code+1] = function() + local settings = " " + for k,v in next, {__luametalatex__preserved_tex_variables = tex_variables, + __luametalatex__preserved_real_pdf_variables = real_pdf_variables,} do + local entries = {} + for kk,vv in next, v do + -- entries[#entries+1] = string.format("[%q=%i],", kk, vv) -- If we ever get more compicated names here + entries[#entries+1] = string.format("%s=%i,", kk, vv) + end + settings = string.format("%s%s={%s}", settings, k, table.concat(entries)) + end + return settings + end +end diff --git a/luametalatex-init.lua b/luametalatex-init.lua index 2505538..6e140a8 100644 --- a/luametalatex-init.lua +++ b/luametalatex-init.lua @@ -119,7 +119,8 @@ callback_register('handle_error_hook', function() return 3 end) callback_register('pre_dump', function() - lua.prepared_code[1] = string.format("fixupluafunctions(%i)", fixupluafunctions()) + local prepared = lua.prepared_code + prepared[1] = string.format("fixupluafunctions(%i)", fixupluafunctions()) for i=0,0 do -- maybeFIXME: In practise only one language is preloaded in LuaTeX anyway -- for i=0,tex.count[19] do -- Sometimes catches reserved language ids which are not used yet -- for i=0,lang.new():id()-1 do -- lang.new():id() is always 0 in luametatex?!? @@ -148,9 +149,14 @@ callback_register('pre_dump', function() else str = str .. 'end' end - lua.prepared_code[#lua.prepared_code+1] = str + prepared[#prepared+1] = str end - lua.bytecode[1] = assert(load(table.concat(lua.prepared_code, ' '))) + for i=2,#prepared do + if type(prepared[i]) ~= 'string' then + prepared[i] = assert(prepared[i]()) + end + end + lua.bytecode[1] = assert(load(table.concat(prepared, ' '))) end) function texconfig.init() lua.bytecode[2]()