back-pdp.lua /size: 9034 b    last modification: 2023-12-21 09:44
1if not modules then modules = { } end modules ['back-pdp'] = {
2    version   = 1.001,
3    comment   = "companion to lpdf-ini.mkiv",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files"
7}
8
9-- This is temporary ... awaiting a better test .. basically we can
10-- always use this: pdf primitives.
11
12local context           = context
13local lpdf              = lpdf
14
15local lpdfreserveobject = lpdf.reserveobject
16local lpdfcompresslevel = lpdf.compresslevel
17local lpdfobj           = lpdf.obj
18local lpdfpagereference = lpdf.pagereference
19local lpdfxformname     = lpdf.xformname
20
21local tokenscanners     = tokens.scanners
22local scanword          = tokenscanners.word
23local scankeyword       = tokenscanners.keyword
24local scanstring        = tokenscanners.string
25local scantoks          = tokenscanners.toks
26local scaninteger       = tokenscanners.integer
27local scanwhd           = tokenscanners.whd
28
29local trace             = false  trackers.register("backend", function(v) trace = v end)
30local report            = logs.reporter("backend")
31
32local nodepool          = nodes.pool
33local newliteral        = nodepool.literal
34local newlateliteral    = nodepool.lateliteral
35local newsave           = nodepool.save
36local newrestore        = nodepool.restore
37local newsetmatrix      = nodepool.setmatrix
38
39local implement         = interfaces.implement
40local constants         = interfaces.constants
41local variables         = interfaces.variables
42
43-- literals
44
45-- local function pdfliteral()
46--     context(newliteral(scanword() or "origin",scanstring()))
47-- end
48
49-- Who knows what will end up in e.g. tikz .. so we now do:
50
51local function pdfliteral()
52    local word = scanword()
53    local node
54    if word == "shipout" then
55        context(newlateliteral(scanword() or "origin",scantoks()))
56    else
57        context(newliteral(word or "origin",scanstring()))
58    end
59end
60
61local function pdflateliteral()
62    context(newlateliteral(scanword() or "origin",scantoks()))
63end
64
65-- objects
66
67local lastobjnum = 0
68
69local function pdfobj()
70    if scankeyword("reserveobjnum") then
71        lastobjnum = lpdfreserveobject()
72        if trace then
73            report("\\pdfobj reserveobjnum: object %i",lastobjnum)
74        end
75    else
76        local immediate    = true
77        local objnum       = scankeyword("useobjnum") and scaninteger() or lpdfreserveobject()
78        local uncompress   = scankeyword("uncompressed") or lpdfcompresslevel() == 0
79        local streamobject = scankeyword("stream")
80        local attributes   = scankeyword("attr") and scanstring() or nil
81        local fileobject   = scankeyword("file")
82        local content      = scanstring()
83        local object = streamobject and {
84            type          = "stream",
85            objnum        = objnum,
86            immediate     = immediate,
87            attr          = attributes,
88            compresslevel = uncompress and 0 or nil,
89        } or {
90            type          = "raw",
91            objnum        = objnum,
92            immediate     = immediate,
93        }
94        if fileobject then
95            object.file = content
96         -- object.filename = content
97        else
98            object.string = content
99        end
100        lpdfobj(object)
101        lastobjnum = objnum
102        if trace then
103            report("\\pdfobj: object %i",lastobjnum)
104        end
105    end
106end
107
108local function pdflastobj()
109    context("%i",lastobjnum)
110    if trace then
111        report("\\lastobj: object %i",lastobjnum)
112    end
113end
114
115local function pdfrefobj()
116    local objnum = scaninteger()
117    if trace then
118        report("\\refobj: object %i (todo)",objnum)
119    end
120end
121
122-- annotations
123
124local lastobjnum = 0
125
126local function pdfannot()
127    if scankeyword("reserveobjnum") then
128        lastobjnum = lpdfreserveobject()
129        if trace then
130            report("\\pdfannot reserveobjnum: object %i",lastobjnum)
131        end
132    else
133        local width  = false
134        local height = false
135        local depth  = false
136        local data   = false
137        local object = false
138        local attr   = false
139        --
140        if scankeyword("useobjnum") then
141            object = scancount()
142            report("\\pdfannot useobjectnum is not (yet) supported")
143        end
144        local width, height, depth = scanwhd()
145        if scankeyword("attr") then
146            attr = scanstring()
147        end
148        data = scanstring()
149        context(backends.nodeinjections.annotation(width or 0,height or 0,depth or 0,data or ""))
150    end
151end
152
153local function pdfdest()
154    local name   = false
155    local zoom   = false
156    local view   = false
157    local width  = false
158    local height = false
159    local depth  = false
160    if scankeyword("num") then
161        report("\\pdfdest num is not (yet) supported")
162    elseif scankeyword("name") then
163        name = scanstring()
164    end
165    if scankeyword("xyz") then
166        view = "xyz"
167        if scankeyword("zoom") then
168            report("\\pdfdest zoom is ignored")
169            zoom = scancount() -- will be divided by 1000 in the backend
170        end
171    elseif scankeyword("fitbh") then
172        view = "fitbh"
173    elseif scankeyword("fitbv") then
174        view = "fitbv"
175    elseif scankeyword("fitb") then
176        view = "fitb"
177    elseif scankeyword("fith") then
178        view = "fith"
179    elseif scankeyword("fitv") then
180        view = "fitv"
181    elseif scankeyword("fitr") then
182        view = "fitr"
183        width, height, depth = scanwhd()
184    elseif scankeyword("fit") then
185        view = "fit"
186    end
187    context(backends.nodeinjections.destination(width or 0,height or 0,depth or 0,{ name or "" },view or "fit"))
188end
189
190-- management
191
192local function pdfsave()
193    context(newsave())
194end
195
196local function pdfrestore()
197    context(newrestore())
198end
199
200local function pdfsetmatrix()
201    context(newsetmatrix(scanstring()))
202end
203
204-- extras
205
206local function pdfpageref()
207    context(lpdfpagereference())
208end
209
210local function pdfxformname()
211    context(lpdfxformname())
212end
213
214-- extensions: literal dest annot save restore setmatrix obj refobj colorstack
215-- startlink endlink startthread endthread thread outline glyphtounicode fontattr
216-- mapfile mapline includechars catalog info names trailer
217
218local extensions = {
219    literal     = pdfliteral,
220    lateliteral = pdflateliteral,
221    obj         = pdfobj,
222    refobj      = pdfrefobj,
223    dest        = pdfdest,
224    annot       = pdfannot,
225    save        = pdfsave,
226    restore     = pdfrestore,
227    setmatrix   = pdfsetmatrix,
228}
229
230local function pdfextension()
231    local w = scanword()
232    if w then
233        local e = extensions[w]
234        if e then
235            e()
236        else
237            report("\\pdfextension: unsupported %a",w)
238        end
239    end
240end
241
242-- feedbacks: colorstackinit creationdate fontname fontobjnum fontsize lastannot
243-- lastlink lastobj pageref retval revision version xformname
244
245local feedbacks = {
246    lastobj    = pdflastobj,
247    pageref    = pdfpageref,
248    xformname  = pdfxformname,
249}
250
251local function pdffeedback()
252    local w = scanword()
253    if w then
254        local f = feedbacks[w]
255        if f then
256            f()
257        else
258            report("\\pdffeedback: unsupported %a",w)
259        end
260    end
261end
262
263-- variables: (integers:) compresslevel decimaldigits gamma gentounicode
264-- ignoreunknownimages imageaddfilename imageapplygamma imagegamma imagehicolor
265-- imageresolution inclusioncopyfonts inclusionerrorlevel majorversion minorversion
266-- objcompresslevel omitcharset omitcidset pagebox pkfixeddpi pkresolution
267-- recompress suppressoptionalinfo uniqueresname (dimensions:) destmargin horigin
268-- linkmargin threadmargin vorigin xformmargin (tokenlists:) pageattr pageresources
269-- pagesattr pkmode trailerid xformattr xformresources
270
271local variables = {
272    minorversion = function() context(lpdf.minorversion()) end,
273    majorversion = function() context(lpdf.majorversion()) end,
274}
275
276local function pdfvariable()
277    local w = scanword()
278    if w then
279        local f = variables[w]
280        if f then
281            f()
282        else
283            report("\\pdfvariable: unsupported %a",w)
284        end
285    else
286        print("missing variable")
287    end
288end
289
290-- kept:
291
292implement { name = "pdfextension", actions = pdfextension }
293implement { name = "pdffeedback",  actions = pdffeedback }
294implement { name = "pdfvariable",  actions = pdfvariable }
295
296-- for the moment (tikz)
297
298implement { name = "pdfliteral",     actions = pdfliteral }
299implement { name = "pdflateliteral", actions = pdflateliteral }
300implement { name = "pdfobj",         actions = pdfobj }
301implement { name = "pdflastobj",     actions = pdflastobj }
302implement { name = "pdfrefobj",      actions = pdfrefobj }
303--------- { name = "pdfannot",       actions = pdfannot }
304--------- { name = "pdfdest",        actions = pdfdest }
305--------- { name = "pdfsave",        actions = pdfsave }
306--------- { name = "pdfrestore",     actions = pdfrestore }
307--------- { name = "pdfsetmatrix",   actions = pdfsetmatrix }
308