summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/luatex/minim/minim-pdfresources.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/luatex/minim/minim-pdfresources.lua')
-rw-r--r--Master/texmf-dist/tex/luatex/minim/minim-pdfresources.lua154
1 files changed, 154 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/luatex/minim/minim-pdfresources.lua b/Master/texmf-dist/tex/luatex/minim/minim-pdfresources.lua
new file mode 100644
index 00000000000..bc09aeaf401
--- /dev/null
+++ b/Master/texmf-dist/tex/luatex/minim/minim-pdfresources.lua
@@ -0,0 +1,154 @@
+
+local M = { }
+
+local alloc = require 'minim-alloc'
+local cb = require 'minim-callbacks'
+
+-- the standard table design
+local function init_resources()
+ return {
+ ExtGState = { },
+ ColorSpace = { },
+ Pattern = { },
+ Shading = { },
+ }
+end
+
+-- the module will use optex’s functions if present
+M.self_destruct = pdf.add_page_resource or false
+
+-- resource_data is a table that can contain any data. only the following keys
+-- are used by this module:
+--
+-- _entry_ internal value; do not use
+-- value value in the resource dictionary
+-- write() called for writing the resource to the pdf; returns value
+--
+-- of the last two, only one needs be present; if the value is missing it will
+-- be set at first use to the result of write().
+--
+local resource_data = init_resources() -- name ↦ { [write = ... | value = ...], ... }
+--
+function M.add_resource(kind, name, resource)
+ resource_data[kind][name] = resource
+end
+function M.get_resource(kind, name)
+ return resource_data[kind][name]
+end
+function M.use_resource(kind, name)
+ local res = resource_data[kind][name]
+ if not res then
+ return alloc.err('Unknown %s resource: %s', kind, name)
+ end
+ res.value = res.value or res:write()
+ if not res._entry_ then -- first-use
+ res._entry_ = string.format('%s %s', alloc.pdf_name(name), res.value)
+ if M.self_destruct then
+ M.self_destruct(kind, name, res.value)
+ end
+ end
+ return res._entry_
+end
+
+-- global resources are mainly for pgf compatibility: contains adds entries to
+-- the resource dictionaries that will be added for every page.
+--
+local global_resources = init_resources() -- name ↦ '/Key <value>'
+--
+function M.add_global_resource(kind, name, value)
+ local r = global_resources[kind]
+ if M.self_destruct then
+ M.self_destruct(kind, name, value)
+ elseif name == nil then -- used for pgf compatibility
+ if value ~= '' then
+ r[''] = r[''] and string.format('%s %s', global_resources[kind][''], value) or value
+ end
+ else
+ r[name] = string.format('%s %s', alloc.pdf_name(name), value)
+ end
+end
+
+-- we can now provide optex’s interface
+if not M.self_destruct then
+ pdf.add_page_resource = M.add_global_resource
+end
+
+-- for nonglobal resources, every use must be markes with a late_lua node. from
+-- those, the M.use_resouce() function will be called automatically.
+--
+local page_resources = init_resources() -- name ↦ '/Key <value>'
+--
+function _with_pdf_resource_(kind, name) -- global, for use in latelua
+ page_resources[kind][name] = M.use_resource(kind, name)
+end
+function M.use_resource_node(kind, name)
+ local n = node.new('whatsit', 'late_lua')
+ n.data = string.format('_with_pdf_resource_("%s", "%s")', kind, name)
+ return n
+end
+
+-- construction and caching of resource dictionaries.
+--
+local previous_dicts = init_resources() -- pdf dict ↦ objnum
+--
+local function make_resource_entry(kind)
+ local arr = { }
+ for _, entry in pairs(page_resources[kind]) do table.insert(arr, entry) end
+ for _, entry in pairs(global_resources[kind]) do table.insert(arr, entry) end
+ if #arr == 0 then return false end
+ table.sort(arr)
+ arr[0] = '<<'; table.insert(arr, '>>')
+ local dict = table.concat(arr, ' ', 0)
+ local objnum = previous_dicts[kind][dict]
+ if not objnum then
+ objnum = pdf.obj(dict)
+ pdf.refobj(objnum)
+ previous_dicts[kind][dict] = objnum
+ end
+ return string.format('/%s %d 0 R', kind, objnum)
+end
+
+local removal_regex = {
+ ExtGState = ' */ExtGState *%d+ +0 *R',
+ ColorSpace = ' */ColorSpace *%d+ +0 *R',
+ Pattern = ' */Pattern *%d+ +0 *R',
+ Shading = ' */Shading *%d+ +0 *R' }
+
+local function update_page_resources(shippingout)
+ if M.self_destruct then return end
+ local resources = shippingout and pdf.getpageresources() or pdf.getxformresources() or ''
+ for kind, used in pairs(page_resources) do
+ resources = string.gsub(resources, removal_regex[kind], '')
+ local entry = make_resource_entry(kind)
+ if entry then
+ resources = resources == '' and entry or string.format('%s %s', resources, entry)
+ end
+ end
+ -- update page resources
+ if shippingout then
+ pdf.setpageresources(resources)
+ else
+ pdf.setxformresources(resources)
+ end
+ page_resources = init_resources()
+end
+
+cb.register('finish_pdfpage', update_page_resources)
+
+-- for pgf compatibility, reroute the pgf resource registration functions to
+-- our global resource pool.
+--
+alloc.luadef('minim:pgf:fix:luaside', function()
+ alloc.luadef('pgf@sys@addpdfresource@extgs@plain', function()
+ M.add_global_resource('ExtGState', nil, token.scan_string())
+ end)
+ alloc.luadef('pgf@sys@addpdfresource@patterns@plain', function()
+ M.add_global_resource('Pattern', nil, token.scan_string())
+ end)
+ alloc.luadef('pgf@sys@addpdfresource@colorspaces@plain', function()
+ M.add_global_resource('ColorSpace', nil, token.scan_string())
+ end)
+end)
+
+return M
+