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