summaryrefslogtreecommitdiff
path: root/tex/context/base/mkxl/lpdf-lmt.lmt
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkxl/lpdf-lmt.lmt')
-rw-r--r--tex/context/base/mkxl/lpdf-lmt.lmt481
1 files changed, 311 insertions, 170 deletions
diff --git a/tex/context/base/mkxl/lpdf-lmt.lmt b/tex/context/base/mkxl/lpdf-lmt.lmt
index 2bbf5ba61..32dfa574f 100644
--- a/tex/context/base/mkxl/lpdf-lmt.lmt
+++ b/tex/context/base/mkxl/lpdf-lmt.lmt
@@ -49,38 +49,56 @@ local zlibcompress = (xzip or zlib).compress
local nuts = nodes.nuts
local tonut = nodes.tonut
-local getdata = nuts.getdata
-local getsubtype = nuts.getsubtype
-local getwhd = nuts.getwhd
-local flushlist = nuts.flush_list
-
-local pdfincludeimage = lpdf.includeimage
-local pdfgetfontname = lpdf.getfontname
-local pdfgetfontobjnumber = lpdf.getfontobjnumber
-
-local pdfreserveobject = lpdf.reserveobject
-local pdfpagereference = lpdf.pagereference
-local pdfflushobject = lpdf.flushobject
-local pdfsharedobject = lpdf.shareobjectreference
local pdfreference = lpdf.reference
local pdfdictionary = lpdf.dictionary
local pdfarray = lpdf.array
local pdfconstant = lpdf.constant
-local pdfflushstreamobject = lpdf.flushstreamobject
local pdfliteral = lpdf.literal -- not to be confused with a whatsit!
-local pdf_pages = pdfconstant("Pages")
-local pdf_page = pdfconstant("Page")
-local pdf_xobject = pdfconstant("XObject")
-local pdf_form = pdfconstant("Form")
+local pdfreserveobject
+local pdfpagereference
+local pdfflushobject
+local pdfsharedobject
+local pdfflushstreamobject
+local pdfdeferredobject
+local pdfimmediateobject
-local fonthashes = fonts.hashes
-local characters = fonthashes.characters
-local descriptions = fonthashes.descriptions
-local parameters = fonthashes.parameters
-local properties = fonthashes.properties
+local pdfgetfontname
+local pdfgetfontobjectnumber
-local report = logs.reporter("backend")
+local pdfgetpagereference
+
+updaters.register("backend.update.lpdf",function()
+ pdfreserveobject = lpdf.reserveobject
+ pdfpagereference = lpdf.pagereference
+ pdfflushobject = lpdf.flushobject
+ pdfsharedobject = lpdf.shareobjectreference
+ pdfflushstreamobject = lpdf.flushstreamobject
+ pdfdeferredobject = lpdf.deferredobject
+ pdfimmediateobject = lpdf.immediateobject
+ --
+ pdfgetfontname = lpdf.getfontname
+ pdfgetfontobjectnumber = lpdf.getfontobjectnumber
+ --
+ pdfgetpagereference = lpdf.getpagereference
+end)
+
+local pdf_pages = pdfconstant("Pages")
+local pdf_page = pdfconstant("Page")
+local pdf_xobject = pdfconstant("XObject")
+local pdf_form = pdfconstant("Form")
+
+local fonthashes = fonts.hashes
+local characters = fonthashes.characters
+local descriptions = fonthashes.descriptions
+local parameters = fonthashes.parameters
+local properties = fonthashes.properties
+
+local report = logs.reporter("backend")
+local report_objects = logs.reporter("backend","objects")
+
+local trace_objects = false trackers.register("backend.objects", function(v) trace_objects = v end)
+local trace_details = false trackers.register("backend.details", function(v) trace_details = v end)
-- used variables
@@ -659,6 +677,8 @@ local flushliteral do
local textliteral_code = literalvalues.text
local fontliteral_code = literalvalues.font
+ local getdata = nuts.getdata
+
flushliteral = function(current,pos_h,pos_v,mode,str)
if mode then
if not str then
@@ -717,38 +737,36 @@ local flushliteral do
end
end
- updaters.register("backend.update.pdf",function()
- function pdf.print(mode,str)
- -- This only works inside objects, don't change this to flush
- -- in between. It's different from luatex but okay.
- if str then
- mode = literalvalues[mode]
+ function lpdf.print(mode,str)
+ -- This only works inside objects, don't change this to flush
+ -- in between. It's different from luatex but okay.
+ if str then
+ mode = literalvalues[mode]
+ else
+ mode, str = originliteral_code, mode
+ end
+ if str and str ~= "" then
+ if mode == originliteral_code then
+ pdf_goto_pagemode()
+ -- pdf_set_pos(pdf_h,pdf_v)
+ elseif mode == pageliteral_code then
+ pdf_goto_pagemode()
+ elseif mode == textliteral_code then
+ pdf_goto_textmode()
+ elseif mode == fontliteral_code then
+ pdf_goto_fontmode()
+ elseif mode == alwaysliteral_code then
+ pdf_end_string_nl()
+ need_tm = true
+ elseif mode == rawliteral_code then
+ pdf_end_string_nl()
else
- mode, str = originliteral_code, mode
- end
- if str and str ~= "" then
- if mode == originliteral_code then
- pdf_goto_pagemode()
- -- pdf_set_pos(pdf_h,pdf_v)
- elseif mode == pageliteral_code then
- pdf_goto_pagemode()
- elseif mode == textliteral_code then
- pdf_goto_textmode()
- elseif mode == fontliteral_code then
- pdf_goto_fontmode()
- elseif mode == alwaysliteral_code then
- pdf_end_string_nl()
- need_tm = true
- elseif mode == rawliteral_code then
- pdf_end_string_nl()
- else
- pdf_goto_pagemode()
- -- pdf_set_pos(pdf_h,pdf_v)
- end
- b = b + 1 ; buffer[b] = str
+ pdf_goto_pagemode()
+ -- pdf_set_pos(pdf_h,pdf_v)
end
+ b = b + 1 ; buffer[b] = str
end
- end)
+ end
end
@@ -763,6 +781,8 @@ local flushsave, flushrestore, flushsetmatrix do
local f_matrix = formatters["%s 0 0 cm"]
+ local getdata = nuts.getdata
+
flushsave = function(current,pos_h,pos_v)
nofpositions = nofpositions + 1
positions[nofpositions] = { pos_h, pos_v, nofmatrices }
@@ -831,11 +851,11 @@ local flushsave, flushrestore, flushsetmatrix do
do
- local function hasmatrix()
+ function lpdf.hasmatrix()
return nofmatrices > 0
end
- local function getmatrix()
+ function lpdf.getmatrix()
if nofmatrices > 0 then
return unpack(matrices[nofmatrices])
else
@@ -843,11 +863,6 @@ local flushsave, flushrestore, flushsetmatrix do
end
end
- updaters.register("backend.update.pdf",function()
- pdf.hasmatrix = hasmatrix
- pdf.getmatrix = getmatrix
- end)
-
end
pushorientation = function(orientation,pos_h,pos_v,pos_r)
@@ -899,6 +914,10 @@ local flushrule, flushsimplerule, flushspecialrule, flushimage, flushgroup do
local setprop = nuts.setprop
local getprop = nuts.getprop
+ local getwhd = nuts.getwhd
+ local flushlist = nuts.flush_list
+ local getdata = nuts.getdata
+
local normalrule_code = rulecodes.normal
local boxrule_code = rulecodes.box
local imagerule_code = rulecodes.image
@@ -942,9 +961,7 @@ local flushrule, flushsimplerule, flushspecialrule, flushimage, flushgroup do
end
end
- updaters.register("backend.update.pdf",function()
- pdf.getxformname = getxformname
- end)
+ lpdf.getxformname = getxformname
local function saveboxresource(box,attributes,resources,immediate,kind,margin)
n = n + 1
@@ -1012,7 +1029,8 @@ local flushrule, flushsimplerule, flushspecialrule, flushimage, flushgroup do
end
end
- updaters.register("backend.update.tex",function()
+-- updaters.register("backend.update.tex",function()
+ updaters.register("backend.update.lpdf",function()
tex.saveboxresource = saveboxresource
tex.useboxresource = useboxresource
tex.getboxresourcedimensions = getboxresourcedimensions
@@ -1069,7 +1087,7 @@ local flushrule, flushsimplerule, flushspecialrule, flushimage, flushgroup do
local imageresources, n = { }, 0
- getximagename = function(index)
+ getximagename = function(index) -- not used
local l = imageresources[index]
if l then
return l.name
@@ -1078,10 +1096,6 @@ local flushrule, flushsimplerule, flushspecialrule, flushimage, flushgroup do
end
end
- updaters.register("backend.update.pdf",function()
- pdf.getximagename = getximagename
- end)
-
-- Groups are flushed immediately but we can decide to make them into a
-- specific whatsit ... but not now. We could hash them if needed when
-- we use lot sof them in mp ... but not now.
@@ -1115,6 +1129,12 @@ local flushrule, flushsimplerule, flushspecialrule, flushimage, flushgroup do
-- end of experiment
+ local pdfincludeimage
+
+ updaters.register("backend.update.lpdf",function()
+ pdfincludeimage = lpdf.includeimage
+ end)
+
local function flushpdfximage(current,pos_h,pos_v,pos_r,size_h,size_v)
local width,
@@ -1626,7 +1646,7 @@ local finalize do
if next(usedfonts) then
fonts = pdfdictionary { }
for k, v in next, usedfonts do
- fonts[f_font(v)] = pdfreference(pdfgetfontobjnumber(k)) -- we can overload for testing
+ fonts[f_font(v)] = pdfreference(pdfgetfontobjectnumber(k)) -- we can overload for testing
end
end
@@ -1636,7 +1656,6 @@ local finalize do
if next(usedxforms) or next(usedximages) or next(usedxgroups) then
xforms = pdfdictionary { }
for k in sortedhash(usedxforms) do
- -- xforms[f_form(k)] = pdfreference(k)
xforms[f_form(getxformname(k))] = pdfreference(k)
end
for k, v in sortedhash(usedximages) do
@@ -1766,7 +1785,6 @@ local finalize do
wrapper.Resources = next(boxresources) and boxresources or nil
wrapper.ProcSet = lpdf.procset()
- -- pdfflushstreamobject(content,wrapper,false,objectnumber)
pdfflushstreamobject(content,wrapper,false,specification.objnum)
end
@@ -1793,15 +1811,6 @@ local finalize do
end
-updaters.register("backend.update.pdf",function()
- job.positions.registerhandlers {
- getpos = drivers.getpos,
- getrpos = drivers.getrpos,
- gethpos = drivers.gethpos,
- getvpos = drivers.getvpos,
- }
-end)
-
updaters.register("backend.update",function()
local saveboxresource = tex.boxresources.save
--
@@ -1859,45 +1868,51 @@ local s_stream_e = "\010endstream\010endobj\010"
do
- local function setinfo() end -- we get it
- local function setcatalog() end -- we get it
+ -- Versions can be set but normally are managed by the official standards. When possible
+ -- reading and writing should look at these values.
- local function settrailerid(v)
- trailerid = v or false
+ function lpdf.setversion(major,minor)
+ majorversion = tonumber(major) or majorversion
+ minorversion = tonumber(minor) or minorversion
end
- local function setmajorversion(v) majorversion = tonumber(v) or majorversion end
- local function setminorversion(v) minorversion = tonumber(v) or minorversion end
+ function lpdf.getversion(major,minor)
+ return majorversion, minorversion
+ end
- local function getmajorversion(v) return majorversion end
- local function getminorversion(v) return minorversion end
+ function lpdf.majorversion() return majorversion end
+ function lpdf.minorversion() return minorversion end
- local function setcompresslevel (v) compress = v and v ~= 0 and true or false end
- local function setobjcompresslevel(v) objectstream = v and v ~= 0 and true or false end
+ -- It makes no sense to support levels so we only enable and disable and stick to level 3
+ -- which is both fast and efficient.
- local function getcompresslevel (v) return compress and 3 or 0 end
- local function getobjcompresslevel(v) return objectstream and 1 or 0 end
+ local frozen = false
+ local clevel = 3
+ local olevel = 1
- local function setpageresources () end -- needs to be sorted out
- local function setpageattributes () end
- local function setpagesattributes() end
+ function lpdf.setcompression(level,objectlevel,freeze)
+ if not frozen then
+ compress = level and level ~= 0 and true or false
+ objectstream = objectlevel and objectlevel ~= 0 and true or false
+ frozen = freeze
+ end
+ end
- updaters.register("backend.update.pdf",function()
- pdf.setinfo = setinfo
- pdf.setcatalog = setcatalog
- pdf.settrailerid = settrailerid
- pdf.setmajorversion = setmajorversion
- pdf.setminorversion = setminorversion
- pdf.getmajorversion = getmajorversion
- pdf.getminorversion = getminorversion
- pdf.setcompresslevel = setcompresslevel
- pdf.setobjcompresslevel = setobjcompresslevel
- pdf.getcompresslevel = getcompresslevel
- pdf.getobjcompresslevel = getobjcompresslevel
- pdf.setpageresources = setpageresources
- pdf.setpageattributes = setpageattributes
- pdf.setpagesattributes = setpagesattributes
- end)
+ function lpdf.getcompression()
+ return compress and olevel or 0, objectstream and clevel or 0
+ end
+
+ function lpdf.compresslevel()
+ return compress and olevel or 0
+ end
+
+ function lpdf.objectcompresslevel()
+ return objectstream and clevel or 0
+ end
+
+ if environment.arguments.nocompression then
+ lpdf.setcompression(0,0,true)
+ end
end
@@ -1975,26 +1990,174 @@ local addtocache, flushcache, cache do
end
-local function pdfreserveobj()
- nofobjects = nofobjects + 1
- objects[nofobjects] = false
- return nofobjects
+do
+
+ local names = { }
+ local cache = { }
+ local nofpages = 0
+
+ local texgetcount = tex.getcount
+
+ function lpdf.reserveobject(name)
+ nofobjects = nofobjects + 1
+ objects[nofobjects] = false
+ if name then
+ names[name] = nofobjects
+ if trace_objects then
+ report_objects("reserving number %a under name %a",nofobjects,name)
+ end
+ elseif trace_objects then
+ report_objects("reserving number %a",nofobjects)
+ end
+ return nofobjects
+ end
+
+ function lpdf.pagereference(n,complete) -- true | false | nil | n [true,false]
+ if nofpages == 0 then
+ nofpages = structures.pages.nofpages
+ if nofpages == 0 then
+ nofpages = 1
+ end
+ end
+ if n == true or not n then
+ complete = n
+ n = texgetcount("realpageno")
+ end
+ local r = n > nofpages and pdfgetpagereference(nofpages) or pdfgetpagereference(n)
+ return complete and pdfreference(r) or r
+ end
+
+ function lpdf.nofpages()
+ return structures.pages.nofpages
+ end
+
+ function lpdf.object(...)
+ pdfdeferredobject(...)
+ end
+
+ function lpdf.delayedobject(data,n)
+ if n then
+ pdfdeferredobject(n,data)
+ else
+ n = pdfdeferredobject(data)
+ end
+-- pdfreferenceobject(n)
+ return n
+ end
+
+ function lpdf.flushobject(name,data)
+ if data then
+ local named = names[name]
+ if named then
+ if not trace_objects then
+ elseif trace_details then
+ report_objects("flushing data to reserved object with name %a, data: %S",name,data)
+ else
+ report_objects("flushing data to reserved object with name %a",name)
+ end
+ return pdfimmediateobject(named,tostring(data))
+ else
+ if not trace_objects then
+ elseif trace_details then
+ report_objects("flushing data to reserved object with number %s, data: %S",name,data)
+ else
+ report_objects("flushing data to reserved object with number %s",name)
+ end
+ return pdfimmediateobject(name,tostring(data))
+ end
+ else
+ if trace_objects and trace_details then
+ report_objects("flushing data: %S",name)
+ end
+ return pdfimmediateobject(tostring(name))
+ end
+ end
+
+ function lpdf.flushstreamobject(data,dict,compressed,objnum) -- default compressed
+ if trace_objects then
+ report_objects("flushing stream object of %s bytes",#data)
+ end
+ local dtype = type(dict)
+ local kind = compressed == "raw" and "raw" or "stream"
+ local nolength = nil
+ if compressed == "raw" then
+ compressed = nil
+ nolength = true
+ -- data = string.formatters["<< %s >>stream\n%s\nendstream"](attr,data)
+ end
+ return pdfdeferredobject {
+ objnum = objnum,
+ immediate = true,
+ nolength = nolength,
+ compresslevel = compressed == false and 0 or nil,
+ type = "stream",
+ string = data,
+ attr = (dtype == "string" and dict) or (dtype == "table" and dict()) or nil,
+ }
+ end
+
+ function lpdf.flushstreamfileobject(filename,dict,compressed,objnum) -- default compressed
+ if trace_objects then
+ report_objects("flushing stream file object %a",filename)
+ end
+ local dtype = type(dict)
+ return pdfdeferredobject {
+ objnum = objnum,
+ immediate = true,
+ compresslevel = compressed == false and 0 or nil,
+ type = "stream",
+ file = filename,
+ attr = (dtype == "string" and dict) or (dtype == "table" and dict()) or nil,
+ }
+ end
+
+ local shareobjectcache, shareobjectreferencecache = { }, { }
+
+ function lpdf.shareobject(content)
+ if content == nil then
+ -- invalid object not created
+ else
+ content = tostring(content)
+ local o = shareobjectcache[content]
+ if not o then
+ o = pdfimmediateobject(content)
+ shareobjectcache[content] = o
+ end
+ return o
+ end
+ end
+
+ function lpdf.shareobjectreference(content)
+ if content == nil then
+ -- invalid object not created
+ else
+ content = tostring(content)
+ local r = shareobjectreferencecache[content]
+ if not r then
+ local o = shareobjectcache[content]
+ if not o then
+ o = pdfimmediateobject(content)
+ shareobjectcache[content] = o
+ end
+ r = pdfreference(o)
+ shareobjectreferencecache[content] = r
+ end
+ return r
+ end
+ end
+
end
local pages = table.setmetatableindex(function(t,k)
- local v = pdfreserveobj()
+ local v = pdfreserveobject()
t[k] = v
return v
end)
-local function getpageref(n)
+function lpdf.getpagereference(n)
return pages[n]
end
-local function refobj()
- -- not needed, as we have auto-delay
-end
-
local function flushnormalobj(data,n)
if not n then
nofobjects = nofobjects + 1
@@ -2094,24 +2257,7 @@ flushdeferred = function() -- was forward defined
end
end
--- n = pdf.obj([n,] objtext)
--- n = pdf.obj([n,] "file", filename)
--- n = pdf.obj([n,] "stream", streamtext [, attrtext])
--- n = pdf.obj([n,] "streamfile", filename [, attrtext])
---
--- n = pdf.obj {
--- type = <string>, -- raw|stream
--- immediate = <boolean>,
--- objnum = <number>,
--- attr = <string>,
--- compresslevel = <number>,
--- objcompression = <boolean>,
--- file = <string>,
--- string = <string>,
--- nolength = <boolean>,
--- }
-
-local function obj(a,b,c,d)
+function lpdf.immediateobject(a,b,c,d)
local kind --, immediate
local objnum, data, attr, filename
local compresslevel, objcompression, nolength
@@ -2183,15 +2329,7 @@ local function obj(a,b,c,d)
return objnum
end
-updaters.register("backend.update.pdf",function()
- pdf.reserveobj = pdfreserveobj
- pdf.getpageref = getpageref
- pdf.refobj = refobj
- pdf.flushstreamobj = flushstreamobj
- pdf.flushnormalobj = flushnormalobj
- pdf.obj = obj
- pdf.immediateobj = obj
-end)
+lpdf.deferredobject = lpdf.immediateobject
-- In lua 5.4 the methods are now moved one metalevel deeper so we need to get them
-- from mt.__index instead. (I did get that at first.) It makes for a slightly (imo)
@@ -2483,7 +2621,7 @@ end
-- For the moment we overload it here, although back-fil.lua eventually will
-- be merged with back-pdf as it's pdf specific, or maybe back-imp-pdf or so.
-updaters.register("backend.update.pdf",function()
+do -- updaters.register("backend.update.pdf",function()
-- We overload img but at some point it will even go away, so we just
-- reimplement what we need in context. This will change completely i.e.
@@ -2603,7 +2741,7 @@ updaters.register("backend.update.pdf",function()
return n
end
- function pdf.includeimage(index)
+ function lpdf.includeimage(index)
local specification = indices[index]
if specification then
local bbox = specification.bbox
@@ -2612,7 +2750,7 @@ updaters.register("backend.update.pdf",function()
local xsize = bbox[3] - xorigin -- we need the original ones, not the 'rotated' ones
local ysize = bbox[4] - yorigin -- we need the original ones, not the 'rotated' ones
local transform = specification.transform or 0
- local objnum = specification.objnum or pdfreserveobj()
+ local objnum = specification.objnum or pdfreserveobject()
local groupref = nil
local kind = specification.kind or specification.type or img_none -- determines scaling type
return
@@ -2625,19 +2763,28 @@ updaters.register("backend.update.pdf",function()
end
end
-end)
+end -- )
-updaters.register("backend.update.lpdf",function()
+do -- updaters.register("backend.update.lpdf",function()
-- todo: an md5 or sha2 hash can save space
-- todo: make a type 3 font instead
-- todo: move to lpdf namespace
- local pdfimage = lpdf.epdf.image
- local newpdf = pdfimage.new
- local openpdf = pdfimage.open
- local closepdf = pdfimage.close
- local copypage = pdfimage.copy
+ local pdfimage
+ local newpdf
+ local openpdf
+ local closepdf
+ local copypage
+
+
+ updaters.register("backend.update.lpdf",function()
+ pdfimage = lpdf.epdf.image
+ newpdf = pdfimage.new
+ openpdf = pdfimage.open
+ closepdf = pdfimage.close
+ copypage = pdfimage.copy
+ end)
local embedimage = images.embed
@@ -2668,7 +2815,6 @@ updaters.register("backend.update.lpdf",function()
index = image.index
topdf[id] = index
end
- -- pdf.print or pdf.literal
flushimage(index,wd,ht,dp,pos_h,pos_v)
end
@@ -2721,7 +2867,7 @@ updaters.register("backend.update.lpdf",function()
lpdf.vfimage = pdfvfimage
-end)
+end -- )
-- The driver.
@@ -2743,19 +2889,14 @@ do
local function prepare(driver)
if not environment.initex then
-- install new functions in pdf namespace
- updaters.apply("backend.update.pdf")
+-- updaters.apply("backend.update.pdf")
-- install new functions in lpdf namespace
updaters.apply("backend.update.lpdf")
-- adapt existing shortcuts to lpdf namespace
- updaters.apply("backend.update.tex")
- -- adapt existing shortcuts to tex namespace
+-- updaters.apply("backend.update.tex")
+-- -- adapt existing shortcuts to tex namespace
updaters.apply("backend.update")
--
- -- if rawget(pdf,"setforcefile") then
- -- pdf.setforcefile(false) -- default anyway
- -- end
- --
- -- pdfname = file.addsuffix(tex.jobname,"pdf")
pdfname = tex.jobname .. ".pdf"
openfile(pdfname)
--
@@ -2776,7 +2917,7 @@ do
--
end
--
- environment.lmtxmode = CONTEXTLMTXMODE
+ environment.lmtxmode = true -- CONTEXTLMTXMODE
--
converter = drivers.converters.lmtx
useddriver = driver