1if not modules then modules = { } end modules ['lpdf-grp'] = {
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
9local type, tonumber = type, tonumber
10local formatters, gsub = string.formatters, string.gsub
11local concat = table.concat
12local round = math.round
13
14local colors = attributes.colors
15local basepoints = number.dimenfactors.bp
16
17local pdfbackend = backends.registered.pdf
18local nodeinjections = pdfbackend.nodeinjections
19local codeinjections = pdfbackend.codeinjections
20local registrations = pdfbackend.registrations
21
22local lpdf = lpdf
23local pdfdictionary = lpdf.dictionary
24local pdfarray = lpdf.array
25local pdfconstant = lpdf.constant
26local pdfboolean = lpdf.boolean
27local pdfreference = lpdf.reference
28local pdfflushobject = lpdf.flushobject
29
30local createimage = images.create
31local wrapimage = images.wrap
32local embedimage = images.embed
33
34
35
36
37
38
39
40local function shade(stype,name,domain,color_a,color_b,n,colorspace,coordinates,separation,steps,fractions)
41 local func = nil
42
43
44
45
46 domain = pdfarray(domain)
47 n = tonumber(n)
48
49 if steps then
50 local list = pdfarray()
51 local bounds = pdfarray()
52 local encode = pdfarray()
53 for i=1,steps do
54 if i < steps then
55 bounds[i] = fractions[i] or 1
56 end
57 encode[2*i-1] = 0
58 encode[2*i] = 1
59 list [i] = pdfdictionary {
60 FunctionType = 2,
61 Domain = domain,
62 C0 = pdfarray(color_a[i]),
63 C1 = pdfarray(color_b[i]),
64 N = n,
65 }
66 end
67 func = pdfdictionary {
68 FunctionType = 3,
69 Bounds = bounds,
70 Encode = encode,
71 Functions = list,
72 Domain = domain,
73 }
74 else
75 func = pdfdictionary {
76 FunctionType = 2,
77 Domain = domain,
78 C0 = pdfarray(color_a),
79 C1 = pdfarray(color_b),
80 N = n,
81 }
82 end
83 separation = separation and registrations.getspotcolorreference(separation)
84 local s = pdfdictionary {
85 ShadingType = stype,
86 ColorSpace = separation and pdfreference(separation) or pdfconstant(colorspace),
87 Domain = domain,
88 Function = pdfreference(pdfflushobject(func)),
89 Coords = pdfarray(coordinates),
90 Extend = pdfarray { true, true },
91 AntiAlias = pdfboolean(true),
92 }
93 lpdf.adddocumentshade(name,pdfreference(pdfflushobject(s)))
94end
95
96function lpdf.circularshade(name,domain,color_a,color_b,n,colorspace,coordinates,separation,steps,fractions)
97 shade(3,name,domain,color_a,color_b,n,colorspace,coordinates,separation,steps,fractions)
98end
99
100function lpdf.linearshade(name,domain,color_a,color_b,n,colorspace,coordinates,separation,steps,fractions)
101 shade(2,name,domain,color_a,color_b,n,colorspace,coordinates,separation,steps,fractions)
102end
103
104
105
106
107
108
109local template = "q BI %s ID %s > EI Q"
110local factor = 72/300
111
112function nodeinjections.injectbitmap(t)
113
114 local xresolution, yresolution = t.xresolution or 0, t.yresolution or 0
115 if xresolution == 0 or yresolution == 0 then
116 return
117 end
118 local colorspace = t.colorspace
119 if colorspace ~= "rgb" and colorspace ~= "cmyk" and colorspace ~= "gray" then
120
121 local d = gsub(t.data,"[^0-9a-f]","")
122 local b = math.round(#d / (xresolution * yresolution))
123 if b == 2 then
124 colorspace = "gray"
125 elseif b == 6 then
126 colorspace = "rgb"
127 elseif b == 8 then
128 colorspace = "cmyk"
129 end
130 end
131 colorspace = lpdf.colorspaceconstants[colorspace]
132 if not colorspace then
133 return
134 end
135 local d = pdfdictionary {
136 W = xresolution,
137 H = yresolution,
138 CS = colorspace,
139 BPC = 8,
140 F = pdfconstant("AHx"),
141
142
143
144 }
145
146 local urx, ury = 1/basepoints, 1/basepoints
147
148
149 local width, height = t.width or 0, t.height or 0
150 if width == 0 and height == 0 then
151 width = factor * xresolution / basepoints
152 height = factor * yresolution / basepoints
153 elseif width == 0 then
154 width = height * xresolution / yresolution
155 elseif height == 0 then
156 height = width * yresolution / xresolution
157 end
158 local a = pdfdictionary {
159 BBox = pdfarray { 0, 0, urx * basepoints, ury * basepoints }
160 }
161 local image = createimage {
162 stream = formatters[template](d(),t.data),
163 width = width,
164 height = height,
165 bbox = { 0, 0, urx, ury },
166 attr = a(),
167 nobbox = true,
168 }
169 return wrapimage(image)
170end
171
172
173
174function codeinjections.setfigurealternative(data,figure)
175 local request = data.request
176 local display = request.display
177 if display and display ~= "" then
178 local nested = figures.push {
179 name = display,
180 page = request.page,
181 size = request.size,
182 prefix = request.prefix,
183 cache = request.cache,
184 width = request.width,
185 height = request.height,
186 }
187 figures.identify()
188 local displayfigure = figures.check()
189 if displayfigure then
190
191 embedimage(figure)
192 local a = pdfarray {
193 pdfdictionary {
194 Image = pdfreference(figure.objnum),
195 DefaultForPrinting = true,
196 }
197 }
198 local d = pdfdictionary {
199 Alternates = pdfreference(pdfflushobject(a)),
200 }
201 displayfigure.attr = d()
202 figures.pop()
203 return displayfigure, nested
204 else
205 figures.pop()
206 end
207 end
208end
209
210function codeinjections.getpreviewfigure(request)
211 local figure = figures.initialize(request)
212 if not figure then
213 return
214 end
215 figure = figures.identify(figure)
216 if not (figure and figure.status and figure.status.fullname) then
217 return
218 end
219 figure = figures.check(figure)
220 if not (figure and figure.status and figure.status.fullname) then
221 return
222 end
223 local image = figure.status.private
224 if image then
225 embedimage(image)
226 end
227 return figure
228end
229
230function codeinjections.setfiguremask(data,figure)
231 local request = data.request
232 local mask = request.mask
233 if mask and mask ~= "" then
234 figures.push {
235 name = mask,
236 page = request.page,
237 size = request.size,
238 prefix = request.prefix,
239 cache = request.cache,
240 width = request.width,
241 height = request.height,
242 }
243 mask = figures.identify()
244 mask = figures.check(mask)
245 if mask then
246 local image = mask.status.private
247 if image then
248 figures.include(mask)
249 embedimage(image)
250 local d = pdfdictionary {
251 Interpolate = false,
252 SMask = pdfreference(mask.status.objectnumber),
253 }
254 figure.attr = d()
255 end
256 end
257 figures.pop()
258 end
259end
260
261
262
263local saveboxresource = tex.boxresources.save
264local nofpatterns = 0
265local f_pattern = formatters["q /Pattern cs /%s scn 0 0 %.6N %.6N re f Q"]
266
267function lpdf.registerpattern(specification)
268 nofpatterns = nofpatterns + 1
269 local d = pdfdictionary {
270 Type = pdfconstant("Pattern"),
271 PatternType = 1,
272 PaintType = 1,
273 TilingType = 2,
274 XStep = (specification.width or 10) * basepoints,
275 YStep = (specification.height or 10) * basepoints,
276 Matrix = {
277 1, 0, 0, 1,
278 (specification.hoffset or 0) * basepoints,
279 (specification.voffset or 0) * basepoints,
280 },
281 }
282
283
284 local resources = lpdf.collectedresources{ patterns = false, serialize = false }
285 local attributes = d
286 local onlybounds = 1
287 local patternobj = saveboxresource(specification.number,attributes,resources,true,onlybounds)
288 lpdf.adddocumentpattern("Pt" .. nofpatterns,lpdf.reference(patternobj ))
289 return nofpatterns
290end
291
292function lpdf.patternstream(n,width,height)
293 return f_pattern("Pt" .. n,width*basepoints,height*basepoints)
294end
295
296codeinjections.registerpattern = lpdf.registerpattern
297 |