1 #include "mupdf/fitz.h"
2 #include "mupdf/pdf.h"
3
4 static void
pdf_run_annot_with_usage(fz_context * ctx,pdf_document * doc,pdf_page * page,pdf_annot * annot,fz_device * dev,fz_matrix ctm,const char * usage,fz_cookie * cookie)5 pdf_run_annot_with_usage(fz_context *ctx, pdf_document *doc, pdf_page *page, pdf_annot *annot, fz_device *dev, fz_matrix ctm, const char *usage, fz_cookie *cookie)
6 {
7 fz_matrix page_ctm;
8 fz_rect mediabox;
9 pdf_processor *proc = NULL;
10 fz_default_colorspaces *default_cs = NULL;
11 int flags;
12
13 fz_var(proc);
14 fz_var(default_cs);
15
16 if (cookie && page->super.incomplete)
17 cookie->incomplete = 1;
18
19 /* Widgets only get displayed if they have both a T and a TF flag,
20 * apparently */
21 if (pdf_name_eq(ctx, pdf_dict_get(ctx, annot->obj, PDF_NAME(Subtype)), PDF_NAME(Widget)))
22 {
23 pdf_obj *ft = pdf_dict_get_inheritable(ctx, annot->obj, PDF_NAME(FT));
24 pdf_obj *t = pdf_dict_get_inheritable(ctx, annot->obj, PDF_NAME(T));
25
26 if (ft == NULL || t == NULL)
27 return;
28 }
29
30 fz_try(ctx)
31 {
32 default_cs = pdf_load_default_colorspaces(ctx, doc, page);
33 if (default_cs)
34 fz_set_default_colorspaces(ctx, dev, default_cs);
35
36 pdf_page_transform(ctx, page, &mediabox, &page_ctm);
37
38 flags = pdf_dict_get_int(ctx, annot->obj, PDF_NAME(F));
39 if (flags & PDF_ANNOT_IS_NO_ROTATE)
40 {
41 int rotate = pdf_to_int(ctx, pdf_dict_get_inheritable(ctx, page->obj, PDF_NAME(Rotate)));
42 fz_rect rect = pdf_dict_get_rect(ctx, annot->obj, PDF_NAME(Rect));
43 fz_point tp = fz_transform_point_xy(rect.x0, rect.y1, page_ctm);
44 page_ctm = fz_concat(page_ctm, fz_translate(-tp.x, -tp.y));
45 page_ctm = fz_concat(page_ctm, fz_rotate(-rotate));
46 page_ctm = fz_concat(page_ctm, fz_translate(tp.x, tp.y));
47 }
48
49 ctm = fz_concat(page_ctm, ctm);
50
51 proc = pdf_new_run_processor(ctx, dev, ctm, usage, NULL, default_cs, cookie);
52 pdf_process_annot(ctx, proc, doc, page, annot, cookie);
53 pdf_close_processor(ctx, proc);
54 }
55 fz_always(ctx)
56 {
57 pdf_drop_processor(ctx, proc);
58 fz_drop_default_colorspaces(ctx, default_cs);
59 }
60 fz_catch(ctx)
61 fz_rethrow(ctx);
62 }
63
64 static void
pdf_run_page_contents_with_usage(fz_context * ctx,pdf_document * doc,pdf_page * page,fz_device * dev,fz_matrix ctm,const char * usage,fz_cookie * cookie)65 pdf_run_page_contents_with_usage(fz_context *ctx, pdf_document *doc, pdf_page *page, fz_device *dev, fz_matrix ctm, const char *usage, fz_cookie *cookie)
66 {
67 fz_matrix page_ctm;
68 pdf_obj *resources;
69 pdf_obj *contents;
70 fz_rect mediabox;
71 pdf_processor *proc = NULL;
72 fz_default_colorspaces *default_cs = NULL;
73 fz_colorspace *colorspace = NULL;
74
75 fz_var(proc);
76 fz_var(colorspace);
77 fz_var(default_cs);
78
79 if (cookie && page->super.incomplete)
80 cookie->incomplete = 1;
81
82 fz_try(ctx)
83 {
84 default_cs = pdf_load_default_colorspaces(ctx, doc, page);
85 if (default_cs)
86 fz_set_default_colorspaces(ctx, dev, default_cs);
87
88 pdf_page_transform(ctx, page, &mediabox, &page_ctm);
89 ctm = fz_concat(page_ctm, ctm);
90 mediabox = fz_transform_rect(mediabox, ctm);
91
92 resources = pdf_page_resources(ctx, page);
93 contents = pdf_page_contents(ctx, page);
94
95 if (page->transparency)
96 {
97 pdf_obj *group = pdf_page_group(ctx, page);
98
99 if (group)
100 {
101 pdf_obj *cs = pdf_dict_get(ctx, group, PDF_NAME(CS));
102 if (cs)
103 {
104 fz_try(ctx)
105 colorspace = pdf_load_colorspace(ctx, cs);
106 fz_catch(ctx)
107 {
108 fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
109 fz_warn(ctx, "Ignoring Page blending colorspace.");
110 }
111 if (!fz_is_valid_blend_colorspace(ctx, colorspace))
112 {
113 fz_warn(ctx, "Ignoring invalid Page blending colorspace: %s.", colorspace->name);
114 fz_drop_colorspace(ctx, colorspace);
115 colorspace = NULL;
116 }
117 }
118 }
119 else
120 colorspace = fz_keep_colorspace(ctx, fz_default_output_intent(ctx, default_cs));
121
122 fz_begin_group(ctx, dev, mediabox, colorspace, 1, 0, 0, 1);
123 }
124
125 proc = pdf_new_run_processor(ctx, dev, ctm, usage, NULL, default_cs, cookie);
126 pdf_process_contents(ctx, proc, doc, resources, contents, cookie);
127 pdf_close_processor(ctx, proc);
128
129 if (page->transparency)
130 {
131 fz_end_group(ctx, dev);
132 }
133 }
134 fz_always(ctx)
135 {
136 pdf_drop_processor(ctx, proc);
137 fz_drop_colorspace(ctx, colorspace);
138 fz_drop_default_colorspaces(ctx, default_cs);
139 }
140 fz_catch(ctx)
141 {
142 fz_rethrow(ctx);
143 }
144 }
145
pdf_run_page_contents(fz_context * ctx,pdf_page * page,fz_device * dev,fz_matrix ctm,fz_cookie * cookie)146 void pdf_run_page_contents(fz_context *ctx, pdf_page *page, fz_device *dev, fz_matrix ctm, fz_cookie *cookie)
147 {
148 pdf_document *doc = page->doc;
149 int nocache;
150
151 nocache = !!(dev->hints & FZ_NO_CACHE);
152 if (nocache)
153 pdf_mark_xref(ctx, doc);
154
155 fz_try(ctx)
156 {
157 pdf_run_page_contents_with_usage(ctx, doc, page, dev, ctm, "View", cookie);
158 }
159 fz_always(ctx)
160 {
161 if (nocache)
162 pdf_clear_xref_to_mark(ctx, doc);
163 }
164 fz_catch(ctx)
165 {
166 fz_rethrow(ctx);
167 }
168 }
169
pdf_run_annot(fz_context * ctx,pdf_annot * annot,fz_device * dev,fz_matrix ctm,fz_cookie * cookie)170 void pdf_run_annot(fz_context *ctx, pdf_annot *annot, fz_device *dev, fz_matrix ctm, fz_cookie *cookie)
171 {
172 pdf_page *page = annot->page;
173 pdf_document *doc = page->doc;
174 int nocache;
175
176 nocache = !!(dev->hints & FZ_NO_CACHE);
177 if (nocache)
178 pdf_mark_xref(ctx, doc);
179 fz_try(ctx)
180 {
181 pdf_run_annot_with_usage(ctx, doc, page, annot, dev, ctm, "View", cookie);
182 }
183 fz_always(ctx)
184 {
185 if (nocache)
186 pdf_clear_xref_to_mark(ctx, doc);
187 }
188 fz_catch(ctx)
189 {
190 fz_rethrow(ctx);
191 }
192 }
193
194 static void
pdf_run_page_widgets_with_usage(fz_context * ctx,pdf_document * doc,pdf_page * page,fz_device * dev,fz_matrix ctm,const char * usage,fz_cookie * cookie)195 pdf_run_page_widgets_with_usage(fz_context *ctx, pdf_document *doc, pdf_page *page, fz_device *dev, fz_matrix ctm, const char *usage, fz_cookie *cookie)
196 {
197 pdf_widget *widget;
198
199 if (cookie && cookie->progress_max != (size_t)-1)
200 {
201 int count = 1;
202 for (widget = page->widgets; widget; widget = widget->next)
203 count++;
204 cookie->progress_max += count;
205 }
206
207 for (widget = page->widgets; widget; widget = widget->next)
208 {
209 /* Check the cookie for aborting */
210 if (cookie)
211 {
212 if (cookie->abort)
213 break;
214 cookie->progress++;
215 }
216
217 pdf_run_annot_with_usage(ctx, doc, page, widget, dev, ctm, usage, cookie);
218 }
219 }
220
221 static void
pdf_run_page_annots_with_usage(fz_context * ctx,pdf_document * doc,pdf_page * page,fz_device * dev,fz_matrix ctm,const char * usage,fz_cookie * cookie)222 pdf_run_page_annots_with_usage(fz_context *ctx, pdf_document *doc, pdf_page *page, fz_device *dev, fz_matrix ctm, const char *usage, fz_cookie *cookie)
223 {
224 pdf_annot *annot;
225
226 if (cookie && cookie->progress_max != (size_t)-1)
227 {
228 int count = 1;
229 for (annot = page->annots; annot; annot = annot->next)
230 count++;
231 cookie->progress_max += count;
232 }
233
234 for (annot = page->annots; annot; annot = annot->next)
235 {
236 /* Check the cookie for aborting */
237 if (cookie)
238 {
239 if (cookie->abort)
240 break;
241 cookie->progress++;
242 }
243
244 pdf_run_annot_with_usage(ctx, doc, page, annot, dev, ctm, usage, cookie);
245 }
246 }
247
pdf_run_page_annots(fz_context * ctx,pdf_page * page,fz_device * dev,fz_matrix ctm,fz_cookie * cookie)248 void pdf_run_page_annots(fz_context *ctx, pdf_page *page, fz_device *dev, fz_matrix ctm, fz_cookie *cookie)
249 {
250 pdf_document *doc = page->doc;
251 int nocache;
252
253 nocache = !!(dev->hints & FZ_NO_CACHE);
254 if (nocache)
255 pdf_mark_xref(ctx, doc);
256
257 fz_try(ctx)
258 {
259 pdf_run_page_annots_with_usage(ctx, doc, page, dev, ctm, "View", cookie);
260 }
261 fz_always(ctx)
262 {
263 if (nocache)
264 pdf_clear_xref_to_mark(ctx, doc);
265 }
266 fz_catch(ctx)
267 {
268 fz_rethrow(ctx);
269 }
270 }
271
pdf_run_page_widgets(fz_context * ctx,pdf_page * page,fz_device * dev,fz_matrix ctm,fz_cookie * cookie)272 void pdf_run_page_widgets(fz_context *ctx, pdf_page *page, fz_device *dev, fz_matrix ctm, fz_cookie *cookie)
273 {
274 pdf_document *doc = page->doc;
275 int nocache;
276
277 nocache = !!(dev->hints & FZ_NO_CACHE);
278 if (nocache)
279 pdf_mark_xref(ctx, doc);
280
281 fz_try(ctx)
282 {
283 pdf_run_page_widgets_with_usage(ctx, doc, page, dev, ctm, "View", cookie);
284 }
285 fz_always(ctx)
286 {
287 if (nocache)
288 pdf_clear_xref_to_mark(ctx, doc);
289 }
290 fz_catch(ctx)
291 {
292 fz_rethrow(ctx);
293 }
294 }
295
296 void
pdf_run_page_with_usage(fz_context * ctx,pdf_document * doc,pdf_page * page,fz_device * dev,fz_matrix ctm,const char * usage,fz_cookie * cookie)297 pdf_run_page_with_usage(fz_context *ctx, pdf_document *doc, pdf_page *page, fz_device *dev, fz_matrix ctm, const char *usage, fz_cookie *cookie)
298 {
299 int nocache = !!(dev->hints & FZ_NO_CACHE);
300
301 if (nocache)
302 pdf_mark_xref(ctx, doc);
303 fz_try(ctx)
304 {
305 pdf_run_page_contents_with_usage(ctx, doc, page, dev, ctm, usage, cookie);
306 pdf_run_page_annots_with_usage(ctx, doc, page, dev, ctm, usage, cookie);
307 pdf_run_page_widgets_with_usage(ctx, doc, page, dev, ctm, usage, cookie);
308 }
309 fz_always(ctx)
310 {
311 if (nocache)
312 pdf_clear_xref_to_mark(ctx, doc);
313 }
314 fz_catch(ctx)
315 {
316 fz_rethrow(ctx);
317 }
318 }
319
320 void
pdf_run_page(fz_context * ctx,pdf_page * page,fz_device * dev,fz_matrix ctm,fz_cookie * cookie)321 pdf_run_page(fz_context *ctx, pdf_page *page, fz_device *dev, fz_matrix ctm, fz_cookie *cookie)
322 {
323 pdf_document *doc = page->doc;
324 pdf_run_page_with_usage(ctx, doc, page, dev, ctm, "View", cookie);
325 }
326
327 void
pdf_run_glyph(fz_context * ctx,pdf_document * doc,pdf_obj * resources,fz_buffer * contents,fz_device * dev,fz_matrix ctm,void * gstate,fz_default_colorspaces * default_cs)328 pdf_run_glyph(fz_context *ctx, pdf_document *doc, pdf_obj *resources, fz_buffer *contents, fz_device *dev, fz_matrix ctm, void *gstate, fz_default_colorspaces *default_cs)
329 {
330 pdf_processor *proc;
331
332 proc = pdf_new_run_processor(ctx, dev, ctm, "View", gstate, default_cs, NULL);
333 fz_try(ctx)
334 {
335 pdf_process_glyph(ctx, proc, doc, resources, contents);
336 pdf_close_processor(ctx, proc);
337 }
338 fz_always(ctx)
339 pdf_drop_processor(ctx, proc);
340 fz_catch(ctx)
341 fz_rethrow(ctx);
342 }
343