back-pdp.lmt /size: 9122 b    last modification: 2021-10-28 13:50
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 pdfreserveobject = lpdf.reserveobject
16local pdfcompresslevel = lpdf.compresslevel
17local pdfobject        = lpdf.object
18local pdfpagereference = lpdf.pagereference
19local pdfgetxformname  = lpdf.getxformname
20local pdfminorversion  = lpdf.minorversion
21local pdfmajorversion  = lpdf.majorversion
22
23local tokenscanners    = tokens.scanners
24local scanword         = tokenscanners.word
25local scankeyword      = tokenscanners.keyword
26local scanstring       = tokenscanners.string
27local scaninteger      = tokenscanners.integer
28local scanwhd          = tokenscanners.whd
29
30local values           = tokens.values
31local dimension_value  = values.dimension
32local cardinal_value   = values.cardinal
33
34local immediate_code   = tex.flagcodes.immediate
35
36local trace            = false  trackers.register("backend", function(v) trace = v end)
37local report           = logs.reporter("backend")
38
39local nodepool         = nodes.pool
40local newliteral       = nodepool.literal
41local newsave          = nodepool.save
42local newrestore       = nodepool.restore
43local newsetmatrix     = nodepool.setmatrix
44
45local implement        = interfaces.implement
46local constants        = interfaces.constants
47local variables        = interfaces.variables
48
49-- literals
50
51local function pdf_literal()
52    context(newliteral(scanword() or "origin",scanstring()))
53end
54
55-- objects
56
57local lastobjnum = 0
58
59local function pdf_obj(prefix)
60    if scankeyword("reserveobjnum") then
61        lastobjnum = pdfreserveobject()
62        if trace then
63            report("\\pdfobj reserveobjnum: object %i",lastobjnum)
64        end
65    else
66        local immediate    = prefix and (prefix & immediate_code) ~= 0 -- was just "true"
67        local objnum       = scankeyword("useobjnum") and scaninteger() or pdfreserveobject()
68        local uncompress   = scankeyword("uncompressed") or pdfcompresslevel() == 0
69        local streamobject = scankeyword("stream")
70        local attributes   = scankeyword("attr") and scanstring() or nil
71        local fileobject   = scankeyword("file")
72        local content      = scanstring()
73        local object = streamobject and {
74            type          = "stream",
75            objnum        = objnum,
76            immediate     = immediate,
77            attr          = attributes,
78            compresslevel = uncompress and 0 or nil,
79        } or {
80            type          = "raw",
81            objnum        = objnum,
82            immediate     = immediate,
83        }
84        if fileobject then
85            object.file = content
86         -- object.filename = content
87        else
88            object.string = content
89        end
90        pdfobject(object)
91        lastobjnum = objnum
92        if trace then
93            report("\\pdfobj: object %i",lastobjnum)
94        end
95    end
96end
97
98local function pdf_lastobj()
99    if trace then
100        report("\\lastobj: object %i",lastobjnum)
101    end
102    return cardinal_value, lastobjnum
103end
104
105local function pdf_pagereference()
106    return cardinal_value, pdfpagereference()
107end
108
109local function pdf_refobj()
110    local objnum = scaninteger()
111    if trace then
112        report("\\refobj: object %i (todo)",objnum)
113    end
114end
115
116-- annotations
117
118local lastobjnum = 0
119
120local function pdf_annot()
121    if scankeyword("reserveobjnum") then
122        lastobjnum = pdfreserveobject()
123        if trace then
124            report("\\pdfannot reserveobjnum: object %i",lastobjnum)
125        end
126    else
127        local width  = false
128        local height = false
129        local depth  = false
130        local data   = false
131        local object = false
132        local attr   = false
133        --
134        if scankeyword("useobjnum") then
135            object = scancount()
136            report("\\pdfannot useobjectnum is not (yet) supported")
137        end
138        local width, height, depth = scanwhd()
139        if scankeyword("attr") then
140            attr = scanstring()
141        end
142        data = scanstring()
143        context(backends.nodeinjections.annotation(width or 0,height or 0,depth or 0,data or ""))
144    end
145end
146
147local function pdf_dest()
148    local name   = false
149    local zoom   = false
150    local view   = false
151    local width  = false
152    local height = false
153    local depth  = false
154    if scankeyword("num") then
155        report("\\pdfdest num is not (yet) supported")
156    elseif scankeyword("name") then
157        name = scanstring()
158    end
159    if scankeyword("xyz") then
160        view = "xyz"
161        if scankeyword("zoom") then
162            report("\\pdfdest zoom is ignored")
163            zoom = scancount() -- will be divided by 1000 in the backend
164        end
165    elseif scankeyword("fitbh") then
166        view = "fitbh"
167    elseif scankeyword("fitbv") then
168        view = "fitbv"
169    elseif scankeyword("fitb") then
170        view = "fitb"
171    elseif scankeyword("fith") then
172        view = "fith"
173    elseif scankeyword("fitv") then
174        view = "fitv"
175    elseif scankeyword("fitr") then
176        view = "fitr"
177        width, height, depth = scanwhd()
178    elseif scankeyword("fit") then
179        view = "fit"
180    end
181    context(backends.nodeinjections.destination(width or 0,height or 0,depth or 0,{ name or "" },view or "fit"))
182end
183
184-- management
185
186local function pdf_save()
187    context(newsave())
188end
189
190local function pdf_restore()
191    context(newrestore())
192end
193
194local function pdf_setmatrix()
195    context(newsetmatrix(scanstring()))
196end
197
198-- extras
199
200-- extensions: literal dest annot save restore setmatrix obj refobj colorstack
201-- startlink endlink startthread endthread thread outline glyphtounicode fontattr
202-- mapfile mapline includechars catalog info names trailer
203
204local extensions = {
205    literal   = pdf_literal,
206    obj       = pdf_obj,
207    refobj    = pdf_refobj,
208    dest      = pdf_dest,
209    annot     = pdf_annot,
210    save      = pdf_save,
211    restore   = pdf_restore,
212    setmatrix = pdf_setmatrix,
213}
214
215local function pdf_extension()
216    local w = scanword()
217    if w then
218        local e = extensions[w]
219        if e then
220            e()
221        else
222            report("\\pdfextension: unsupported %a",w)
223        end
224    end
225end
226
227-- feedbacks: colorstackinit creationdate fontname fontobjnum fontsize lastannot
228-- lastlink lastobj pageref retval revision version xformname
229
230local feedbacks = {
231    lastobj   = pdf_lastobj,
232    pageref   = pdf_pagereference,
233    xformname = function() context(pdfgetxformname ()) end,
234}
235
236local function pdf_feedback()
237    local w = scanword()
238    if w then
239        local f = feedbacks[w]
240        if f then
241            f()
242        else
243            report("\\pdffeedback: unsupported %a",w)
244        end
245    end
246end
247
248-- variables: (integers:) compresslevel decimaldigits gamma gentounicode
249-- ignoreunknownimages imageaddfilename imageapplygamma imagegamma imagehicolor
250-- imageresolution inclusioncopyfonts inclusionerrorlevel majorversion minorversion
251-- objcompresslevel omitcharset omitcidset pagebox pkfixeddpi pkresolution
252-- recompress suppressoptionalinfo uniqueresname (dimensions:) destmargin horigin
253-- linkmargin threadmargin vorigin xformmargin (tokenlists:) pageattr pageresources
254-- pagesattr pkmode trailerid xformattr xformresources
255
256local variables = {
257    minorversion = function() context(pdfminorversion()) end,
258    majorversion = function() context(pdfmajorversion()) end,
259}
260
261local function pdf_variable()
262    local w = scanword()
263    if w then
264        local f = variables[w]
265        if f then
266            f()
267        else
268            report("\\pdfvariable: unsupported %a",w)
269        end
270    else
271        print("missing variable")
272    end
273end
274
275-- kept (also because tikz needs including the pdftex primitives):
276
277implement { name = "pdfextension", actions = pdf_extension, public = true, untraced = true, protected = true }
278implement { name = "pdffeedback",  actions = pdf_feedback,  public = true, untraced = true } -- expandable / todo : value
279implement { name = "pdfvariable",  actions = pdf_variable,  public = true, untraced = true } -- expandable / todo : value
280implement { name = "pdfliteral",   actions = pdf_literal,   public = true, untraced = true, protected = true }
281implement { name = "pdfobj",       actions = pdf_obj,       public = true, usage = "value", protected = true }
282implement { name = "pdflastobj",   actions = pdf_lastobj,   public = true, usage = "value", protected = true }
283implement { name = "pdfrefobj",    actions = pdf_refobj,    public = true, untraced = true, protected = true }
284
285--------- { name = "pdfannot",     actions = pdf_annot }
286--------- { name = "pdfdest",      actions = pdf_dest }
287--------- { name = "pdfsave",      actions = pdf_save }
288--------- { name = "pdfrestore",   actions = pdf_restore }
289--------- { name = "pdfsetmatrix", actions = pdf_setmatrix }
290