1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
|
if not modules then modules = { } end modules ['grph-inc'] = {
version = 1.001,
comment = "companion to grph-inc.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
}
local xpcall, pcall = xpcall, pcall
local bpfactor = number.dimenfactors.bp
local report = logs.reporter("graphics")
local report_inclusion = logs.reporter("graphics","inclusion")
local report_bitmap = logs.reporter("graphics","bitmap")
local report_pdf = logs.reporter("graphics","pdf")
local trace_pdf = false trackers.register("graphics.pdf", function(v) trace_pdf = v end)
local checkers = figures.checkers
local genericchecker = checkers.generic
local placeholder = graphics.bitmaps.placeholder
-- This is an experiment. The following method uses Lua to handle the embedding
-- using the epdf library. This feature will be used when we make the transition
-- from the pre 1.10 epdf library (using an unsuported low level poppler api) to a
-- new (lightweight, small and statically compiled) library. More on that later.
--
-- The method implemented below has the same performance as the hard coded inclusion
-- but opens up some possibilities (like merging fonts) that I will look into some
-- day.
function checkers.pdf(data)
local request = data.request
local used = data.used
if request and used and not request.scanimage then
local image = lpdf.epdf.image -- ok, this is a pdf specific main function
local openpdf = image.open
local closepdf = image.close
local querypdf = image.query
local copypage = image.copy
local pdfdoc = nil
local filename = nil
request.scanimage = function(t)
if pdfdoc then
if trace_pdf then
report_pdf("scan image %a",filename)
end
if not filename then
filename = pdfdoc.filename
end
else
filename = t.filename
if trace_pdf then
report_pdf("open and scan image %a",filename)
end
pdfdoc = openpdf(filename,request.userpassword,request.ownerpassword)
end
if pdfdoc then
--
local info = querypdf(pdfdoc,request.page,request.size)
if info then
local bbox = info and info.boundingbox or { 0, 0, 0, 0 }
local height = bbox[4] - bbox[2]
local width = bbox[3] - bbox[1]
local rotation = info.rotation or 0
if rotation == 90 then
rotation, height, width = 3, width, height
elseif rotation == 180 then
rotation = 2
elseif rotation == 270 then
rotation, height, width = 1, width, height
elseif rotation == 1 or rotation == 3 then
height, width = width, height
else
rotation = 0
end
return {
filename = filename,
-- page = 1,
pages = pdfdoc.nofpages,
width = width,
height = height,
depth = 0,
colordepth = 0,
xres = 0,
yres = 0,
xsize = width,
ysize = height,
rotation = rotation,
pdfdoc = pdfdoc,
}
end
end
end
request.copyimage = function(t)
if not pdfdoc then
pdfdoc = t.pdfdoc
end
if pdfdoc then
local page = request.page
local copied = pdfdoc.nofcopied or 0
if not pdfdoc.copied[page] then
pdfdoc.copied[page] = true
copied = copied + 1
end
pdfdoc.nofcopied = copied
if trace_pdf then
report_pdf("copy page %i from image %a, %i pages copied",page,filename,copied)
end
local result = copypage(pdfdoc,page,nil,request.compact,request.width,request.height,request.attr)
if pdfdoc.nofcopied >= pdfdoc.nofpages then
if trace_pdf then
report_pdf("closing image %a, %i pages copied",filename,copied)
end
closepdf(pdfdoc)
pdfdoc = nil
t.pdfdoc = nil
end
return result
else
-- message, should not happen as we always first scan so that reopens
end
end
end
return genericchecker(data)
end
local function wrappedidentify(identify,filename,filetype)
local wrapup = function() report_inclusion("fatal error reading %a",filename) end
local _, result = xpcall(identify,wrapup,filename,filetype)
if result then
local xsize = result.xsize or 0
local ysize = result.ysize or 0
local xres = result.xres or 0
local yres = result.yres or 0
if xres == 0 or yres == 0 then
xres = 300
yres = 300
end
result.xsize = xsize
result.ysize = ysize
result.xres = xres
result.yres = yres
result.width = result.width or ((72/xres) * xsize / bpfactor)
result.height = result.height or ((72/yres) * ysize / bpfactor)
result.depth = result.depth or 0
result.filename = filename
result.colordepth = result.colordepth or 0
result.colorspace = result.colorspace or 0
result.rotation = result.rotation or 0
result.orientation = result.orientation or 0
result.transform = result.transform or 0
return result
else
return { error = "fatal error" }
end
end
function checkers.jpg(data)
local request = data.request
local used = data.used
if request and used and not request.scanimage then
local identify = graphics.identify
local found = false
request.scanimage = function(t)
local result = wrappedidentify(identify,t.filename,"jpg")
found = not result.error
return {
filename = result.filename,
width = result.width,
height = result.height,
depth = result.depth,
colordepth = result.colordepth,
xres = result.xres,
yres = result.yres,
xsize = result.xsize,
ysize = result.ysize,
colorspace = result.colorspace,
rotation = result.rotation,
orientation = result.orientation,
transform = result.transform,
}
end
request.copyimage = function(t)
if found then
found = false
return backends.codeinjections.jpg(t)
end
end
end
return genericchecker(data)
end
function checkers.jp2(data) -- idem as jpg
local request = data.request
local used = data.used
if request and used and not request.scanimage then
local identify = graphics.identify
local found = false
request.scanimage = function(t)
local result = wrappedidentify(identify,t.filename,"jp2")
found = not result.error
return {
filename = result.filename,
width = result.width,
height = result.height,
depth = result.depth,
colordepth = result.colordepth,
xres = result.xres,
yres = result.yres,
xsize = result.xsize,
ysize = result.ysize,
rotation = result.rotation,
colorspace = result.colorspace,
orientation = result.orientation,
transform = result.transform,
}
end
request.copyimage = function(t)
if found then
found = false
return backends.codeinjections.jp2(t)
end
end
end
return genericchecker(data)
end
function checkers.png(data) -- same as jpg (for now)
local request = data.request
local used = data.used
if request and used and not request.scanimage then
local identify = graphics.identify
local found = false
request.scanimage = function(t)
local result = wrappedidentify(identify,t.filename,"png")
found = not result.error
return {
filename = result.filename,
width = result.width,
height = result.height,
depth = result.depth,
colordepth = result.colordepth,
xres = result.xres,
yres = result.yres,
xsize = result.xsize,
ysize = result.ysize,
rotation = result.rotation,
colorspace = result.colorspace,
tables = result.tables,
interlace = result.interlace,
filter = result.filter,
orientation = result.orientation,
transform = result.transform,
}
end
request.copyimage = function(t)
t.colorref = used.colorref -- this is a bit of a hack
if found then
found = false
local ok, result = pcall(backends.codeinjections.png,t)
if ok then
return result
else
report_inclusion("bad bitmap image")
return placeholder()
end
end
end
end
return genericchecker(data)
end
|