lpdf-grp.lmt /size: 9914 b    last modification: 2021-10-28 13:51
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
colors
=
attributes
.
colors
15
local
basepoints
=
number
.
dimenfactors
.
bp
16 17
local
pdfbackend
=
backends
.
registered
.
pdf
18
local
nodeinjections
=
pdfbackend
.
nodeinjections
19
local
codeinjections
=
pdfbackend
.
codeinjections
20
local
registrations
=
pdfbackend
.
registrations
21 22
local
lpdf
=
lpdf
23
local
pdfdictionary
=
lpdf
.
dictionary
24
local
pdfarray
=
lpdf
.
array
25
local
pdfconstant
=
lpdf
.
constant
26
local
pdfboolean
=
lpdf
.
boolean
27
local
pdfreference
=
lpdf
.
reference
28
local
pdfflushobject
=
lpdf
.
flushobject
29 30
local
createimage
=
images
.
create
31
local
wrapimage
=
images
.
wrap
32
local
embedimage
=
images
.
embed
33 34
-- can also be done indirectly:
35
--
36
-- 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 >>
37
-- 22 : << /Bounds [ ] /Domain [ 0.0 1.0 ] /Encode [ 0.0 1.0 ] /FunctionType 3 /Functions [ 31 0 R ] >>
38
-- 31 : << /C0 [ 1.0 0.0 ] /C1 [ 0.0 1.0 ] /Domain [ 0.0 1.0 ] /FunctionType 2 /N 1.0 >>
39 40
local
function
shade
(
stype
,
name
,
domain
,
color_a
,
color_b
,
n
,
colorspace
,
coordinates
,
separation
,
steps
,
fractions
)
41
local
func
=
nil
42
--
43
-- domain has to be consistently added in all dictionaries here otherwise
44
-- acrobat fails with a drawing error
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
)
)
)
94
end
95 96
function
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
)
98
end
99 100
function
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
)
102
end
103 104
-- inline bitmaps but xform'd
105
--
106
-- we could derive the colorspace if we strip the data
107
-- and divide by x*y
108 109
local
template
=
"
q BI %s ID %s > EI Q
"
110
local
factor
=
72
/
300
111 112
function
nodeinjections
.
injectbitmap
(
t
)
113
-- encoding is ascii hex, no checking here
114
local
xresolution
,
yresolution
=
t
.
xresolution
or
0
,
t
.
yresolution
or
0
115
if
xresolution
=
=
0
or
yresolution
=
=
0
then
116
return
-- fatal error
117
end
118
local
colorspace
=
t
.
colorspace
119
if
colorspace
~
=
"
rgb
"
and
colorspace
~
=
"
cmyk
"
and
colorspace
~
=
"
gray
"
then
120
-- not that efficient but ok
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
-- fatal error
134
end
135
local
d
=
pdfdictionary
{
136
W
=
xresolution
,
137
H
=
yresolution
,
138
CS
=
colorspace
,
139
BPC
=
8
,
140
F
=
pdfconstant
(
"
AHx
"
)
,
141
-- CS = nil,
142
-- BPC = 1,
143
-- IM = true,
144
}
145
-- for some reasons it only works well if we take a 1bp boundingbox
146
local
urx
,
ury
=
1
/
basepoints
,
1
/
basepoints
147
-- urx = (xresolution/300)/basepoints
148
-- ury = (yresolution/300)/basepoints
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
)
170
end
171 172
-- general graphic helpers
173 174
function
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
-- figure.aform = true
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
208
end
209 210
function
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
228
end
229 230
function
codeinjections
.
setfiguremask
(
data
,
figure
)
-- mark
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
259
end
260 261
-- experimental (q Q is not really needed)
262 263
local
saveboxresource
=
tex
.
boxresources
.
save
264
local
nofpatterns
=
0
265
local
f_pattern
=
formatters
[
"
q /Pattern cs /%s scn 0 0 %.6N %.6N re f Q
"
]
266 267
function
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
-- local resources = lpdf.collectedresources{ patterns = false } -- we don't want duplicates, so no serialize here:
284
local
resources
=
lpdf
.
collectedresources
{
patterns
=
false
,
serialize
=
false
}
285
local
attributes
=
d
-- () -- we need to check for patterns
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
290
end
291 292
function
lpdf
.
patternstream
(
n
,
width
,
height
)
293
return
f_pattern
(
"
Pt
"
.
.
n
,
width
*
basepoints
,
height
*
basepoints
)
294
end
295 296
codeinjections
.
registerpattern
=
lpdf
.
registerpattern
297