/src/mupdf/source/pdf/pdf-op-buffer.c
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (C) 2004-2024 Artifex Software, Inc. |
2 | | // |
3 | | // This file is part of MuPDF. |
4 | | // |
5 | | // MuPDF is free software: you can redistribute it and/or modify it under the |
6 | | // terms of the GNU Affero General Public License as published by the Free |
7 | | // Software Foundation, either version 3 of the License, or (at your option) |
8 | | // any later version. |
9 | | // |
10 | | // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY |
11 | | // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
12 | | // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more |
13 | | // details. |
14 | | // |
15 | | // You should have received a copy of the GNU Affero General Public License |
16 | | // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html> |
17 | | // |
18 | | // Alternative licensing terms are available from the licensor. |
19 | | // For commercial licensing, see <https://www.artifex.com/> or contact |
20 | | // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, |
21 | | // CA 94129, USA, for further information. |
22 | | |
23 | | #include "mupdf/fitz.h" |
24 | | #include "mupdf/pdf.h" |
25 | | |
26 | | typedef struct resources_stack |
27 | | { |
28 | | struct resources_stack *next; |
29 | | pdf_obj *res; |
30 | | } resources_stack; |
31 | | |
32 | | typedef struct |
33 | | { |
34 | | pdf_processor super; |
35 | | fz_output *out; |
36 | | int ahxencode; |
37 | | int extgstate; |
38 | | int newlines; |
39 | | int balance; |
40 | | pdf_obj *res; |
41 | | pdf_obj *last_res; |
42 | | resources_stack *rstack; |
43 | | int sep; |
44 | | } pdf_output_processor; |
45 | | |
46 | | /* general graphics state */ |
47 | | |
48 | | static void |
49 | | post_op(fz_context *ctx, pdf_output_processor *proc) |
50 | 0 | { |
51 | 0 | if (proc->newlines) |
52 | 0 | { |
53 | 0 | fz_write_byte(ctx, proc->out, '\n'); |
54 | 0 | proc->sep = 0; |
55 | 0 | } |
56 | 0 | else |
57 | 0 | proc->sep = 1; |
58 | 0 | } |
59 | | |
60 | | static void |
61 | | pdf_out_w(fz_context *ctx, pdf_processor *proc_, float linewidth) |
62 | 0 | { |
63 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
64 | |
|
65 | 0 | if (proc->extgstate != 0) |
66 | 0 | return; |
67 | | |
68 | 0 | if (proc->sep) |
69 | 0 | fz_write_byte(ctx, proc->out, ' '); |
70 | 0 | fz_write_printf(ctx, proc->out, "%g w", linewidth); |
71 | 0 | post_op(ctx, proc); |
72 | 0 | } |
73 | | |
74 | | static void |
75 | | pdf_out_j(fz_context *ctx, pdf_processor *proc_, int linejoin) |
76 | 0 | { |
77 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
78 | |
|
79 | 0 | if (proc->extgstate != 0) |
80 | 0 | return; |
81 | | |
82 | 0 | if (proc->sep) |
83 | 0 | fz_write_byte(ctx, proc->out, ' '); |
84 | 0 | fz_write_printf(ctx, proc->out, "%d j", linejoin); |
85 | 0 | post_op(ctx, proc); |
86 | 0 | } |
87 | | |
88 | | static void |
89 | | pdf_out_J(fz_context *ctx, pdf_processor *proc_, int linecap) |
90 | 0 | { |
91 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
92 | |
|
93 | 0 | if (proc->extgstate != 0) |
94 | 0 | return; |
95 | | |
96 | 0 | if (proc->sep) |
97 | 0 | fz_write_byte(ctx, proc->out, ' '); |
98 | 0 | fz_write_printf(ctx, proc->out, "%d J", linecap); |
99 | 0 | post_op(ctx, proc); |
100 | 0 | } |
101 | | |
102 | | static void |
103 | | pdf_out_M(fz_context *ctx, pdf_processor *proc_, float a) |
104 | 0 | { |
105 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
106 | |
|
107 | 0 | if (proc->extgstate != 0) |
108 | 0 | return; |
109 | | |
110 | 0 | if (proc->sep) |
111 | 0 | fz_write_byte(ctx, proc->out, ' '); |
112 | 0 | fz_write_printf(ctx, proc->out, "%g M", a); |
113 | 0 | post_op(ctx, proc); |
114 | 0 | } |
115 | | |
116 | | static void |
117 | | pdf_out_d(fz_context *ctx, pdf_processor *proc_, pdf_obj *array, float phase) |
118 | 0 | { |
119 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
120 | 0 | int ahx = proc->ahxencode; |
121 | |
|
122 | 0 | if (proc->extgstate != 0) |
123 | 0 | return; |
124 | | |
125 | 0 | pdf_print_encrypted_obj(ctx, proc->out, array, 1, ahx, NULL, 0, 0, &proc->sep); |
126 | 0 | if (proc->sep) |
127 | 0 | fz_write_byte(ctx, proc->out, ' '); |
128 | 0 | fz_write_printf(ctx, proc->out, "%g d", phase); |
129 | 0 | post_op(ctx, proc); |
130 | 0 | } |
131 | | |
132 | | static void |
133 | | pdf_out_ri(fz_context *ctx, pdf_processor *proc_, const char *intent) |
134 | 0 | { |
135 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
136 | |
|
137 | 0 | if (proc->extgstate != 0) |
138 | 0 | return; |
139 | | |
140 | 0 | if (proc->sep) |
141 | 0 | fz_write_byte(ctx, proc->out, ' '); |
142 | 0 | fz_write_printf(ctx, proc->out, "%n ri", intent); |
143 | 0 | post_op(ctx, proc); |
144 | 0 | } |
145 | | |
146 | | static void |
147 | | pdf_out_i(fz_context *ctx, pdf_processor *proc_, float flatness) |
148 | 0 | { |
149 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
150 | |
|
151 | 0 | if (proc->extgstate != 0) |
152 | 0 | return; |
153 | | |
154 | 0 | if (proc->sep) |
155 | 0 | fz_write_byte(ctx, proc->out, ' '); |
156 | 0 | fz_write_printf(ctx, proc->out, "%g i", flatness); |
157 | 0 | post_op(ctx, proc); |
158 | 0 | } |
159 | | |
160 | | static void |
161 | | pdf_out_gs_begin(fz_context *ctx, pdf_processor *proc_, const char *name, pdf_obj *extgstate) |
162 | 0 | { |
163 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
164 | |
|
165 | 0 | proc->extgstate = 1; |
166 | |
|
167 | 0 | fz_write_printf(ctx, proc->out, "%n gs", name); |
168 | 0 | post_op(ctx, proc); |
169 | 0 | } |
170 | | |
171 | | static void |
172 | | pdf_out_gs_end(fz_context *ctx, pdf_processor *proc) |
173 | 0 | { |
174 | 0 | ((pdf_output_processor*)proc)->extgstate = 0; |
175 | 0 | } |
176 | | |
177 | | /* special graphics state */ |
178 | | |
179 | | static void |
180 | | pdf_out_q(fz_context *ctx, pdf_processor *proc_) |
181 | 0 | { |
182 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
183 | |
|
184 | 0 | proc->balance++; |
185 | |
|
186 | 0 | if (proc->sep) |
187 | 0 | fz_write_byte(ctx, proc->out, ' '); |
188 | 0 | fz_write_string(ctx, proc->out, "q"); |
189 | 0 | post_op(ctx, proc); |
190 | 0 | } |
191 | | |
192 | | static void |
193 | | pdf_out_Q(fz_context *ctx, pdf_processor *proc_) |
194 | 0 | { |
195 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
196 | |
|
197 | 0 | proc->balance--; |
198 | 0 | if (proc->balance < 0) |
199 | 0 | fz_warn(ctx, "gstate underflow (too many Q operators)"); |
200 | |
|
201 | 0 | if (proc->sep) |
202 | 0 | fz_write_byte(ctx, proc->out, ' '); |
203 | 0 | fz_write_string(ctx, proc->out, "Q"); |
204 | 0 | post_op(ctx, proc); |
205 | 0 | } |
206 | | |
207 | | static void |
208 | | pdf_out_cm(fz_context *ctx, pdf_processor *proc_, float a, float b, float c, float d, float e, float f) |
209 | 0 | { |
210 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
211 | |
|
212 | 0 | if (proc->sep) |
213 | 0 | fz_write_byte(ctx, proc->out, ' '); |
214 | 0 | fz_write_printf(ctx, proc->out, "%g %g %g %g %g %g cm", a, b, c, d, e, f); |
215 | 0 | post_op(ctx, proc); |
216 | 0 | } |
217 | | |
218 | | /* path construction */ |
219 | | |
220 | | static void |
221 | | pdf_out_m(fz_context *ctx, pdf_processor *proc_, float x, float y) |
222 | 0 | { |
223 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
224 | |
|
225 | 0 | if (proc->sep) |
226 | 0 | fz_write_byte(ctx, proc->out, ' '); |
227 | 0 | fz_write_printf(ctx, proc->out, "%g %g m", x, y); |
228 | 0 | post_op(ctx, proc); |
229 | 0 | } |
230 | | |
231 | | static void |
232 | | pdf_out_l(fz_context *ctx, pdf_processor *proc_, float x, float y) |
233 | 0 | { |
234 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
235 | |
|
236 | 0 | if (proc->sep) |
237 | 0 | fz_write_byte(ctx, proc->out, ' '); |
238 | 0 | fz_write_printf(ctx, proc->out, "%g %g l", x, y); |
239 | 0 | post_op(ctx, proc); |
240 | 0 | } |
241 | | |
242 | | static void |
243 | | pdf_out_c(fz_context *ctx, pdf_processor *proc_, float x1, float y1, float x2, float y2, float x3, float y3) |
244 | 0 | { |
245 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
246 | |
|
247 | 0 | if (proc->sep) |
248 | 0 | fz_write_byte(ctx, proc->out, ' '); |
249 | 0 | fz_write_printf(ctx, proc->out, "%g %g %g %g %g %g c", x1, y1, x2, y2, x3, y3); |
250 | 0 | post_op(ctx, proc); |
251 | 0 | } |
252 | | |
253 | | static void |
254 | | pdf_out_v(fz_context *ctx, pdf_processor *proc_, float x2, float y2, float x3, float y3) |
255 | 0 | { |
256 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
257 | |
|
258 | 0 | if (proc->sep) |
259 | 0 | fz_write_byte(ctx, proc->out, ' '); |
260 | 0 | fz_write_printf(ctx, proc->out, "%g %g %g %g v", x2, y2, x3, y3); |
261 | 0 | post_op(ctx, proc); |
262 | 0 | } |
263 | | |
264 | | static void |
265 | | pdf_out_y(fz_context *ctx, pdf_processor *proc_, float x1, float y1, float x3, float y3) |
266 | 0 | { |
267 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
268 | |
|
269 | 0 | if (proc->sep) |
270 | 0 | fz_write_byte(ctx, proc->out, ' '); |
271 | 0 | fz_write_printf(ctx, proc->out, "%g %g %g %g y", x1, y1, x3, y3); |
272 | 0 | post_op(ctx, proc); |
273 | 0 | } |
274 | | |
275 | | static void |
276 | | pdf_out_h(fz_context *ctx, pdf_processor *proc_) |
277 | 0 | { |
278 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
279 | |
|
280 | 0 | if (proc->sep) |
281 | 0 | fz_write_byte(ctx, proc->out, ' '); |
282 | 0 | fz_write_string(ctx, proc->out, "h"); |
283 | 0 | post_op(ctx, proc); |
284 | 0 | } |
285 | | |
286 | | static void |
287 | | pdf_out_re(fz_context *ctx, pdf_processor *proc_, float x, float y, float w, float h) |
288 | 0 | { |
289 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
290 | |
|
291 | 0 | if (proc->sep) |
292 | 0 | fz_write_byte(ctx, proc->out, ' '); |
293 | 0 | fz_write_printf(ctx, proc->out, "%g %g %g %g re", x, y, w, h); |
294 | 0 | post_op(ctx, proc); |
295 | 0 | } |
296 | | |
297 | | /* path painting */ |
298 | | |
299 | | static void |
300 | | pdf_out_S(fz_context *ctx, pdf_processor *proc_) |
301 | 0 | { |
302 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
303 | |
|
304 | 0 | if (proc->sep) |
305 | 0 | fz_write_byte(ctx, proc->out, ' '); |
306 | 0 | fz_write_string(ctx, proc->out, "S"); |
307 | 0 | post_op(ctx, proc); |
308 | 0 | } |
309 | | |
310 | | static void |
311 | | pdf_out_s(fz_context *ctx, pdf_processor *proc_) |
312 | 0 | { |
313 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
314 | |
|
315 | 0 | if (proc->sep) |
316 | 0 | fz_write_byte(ctx, proc->out, ' '); |
317 | 0 | fz_write_string(ctx, proc->out, "s"); |
318 | 0 | post_op(ctx, proc); |
319 | 0 | } |
320 | | |
321 | | static void |
322 | | pdf_out_F(fz_context *ctx, pdf_processor *proc_) |
323 | 0 | { |
324 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
325 | |
|
326 | 0 | if (proc->sep) |
327 | 0 | fz_write_byte(ctx, proc->out, ' '); |
328 | 0 | fz_write_string(ctx, proc->out, "F"); |
329 | 0 | post_op(ctx, proc); |
330 | 0 | } |
331 | | |
332 | | static void |
333 | | pdf_out_f(fz_context *ctx, pdf_processor *proc_) |
334 | 0 | { |
335 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
336 | |
|
337 | 0 | if (proc->sep) |
338 | 0 | fz_write_byte(ctx, proc->out, ' '); |
339 | 0 | fz_write_string(ctx, proc->out, "f"); |
340 | 0 | post_op(ctx, proc); |
341 | 0 | } |
342 | | |
343 | | static void |
344 | | pdf_out_fstar(fz_context *ctx, pdf_processor *proc_) |
345 | 0 | { |
346 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
347 | |
|
348 | 0 | if (proc->sep) |
349 | 0 | fz_write_byte(ctx, proc->out, ' '); |
350 | 0 | fz_write_string(ctx, proc->out, "f*"); |
351 | 0 | post_op(ctx, proc); |
352 | 0 | } |
353 | | |
354 | | static void |
355 | | pdf_out_B(fz_context *ctx, pdf_processor *proc_) |
356 | 0 | { |
357 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
358 | |
|
359 | 0 | if (proc->sep) |
360 | 0 | fz_write_byte(ctx, proc->out, ' '); |
361 | 0 | fz_write_string(ctx, proc->out, "B"); |
362 | 0 | post_op(ctx, proc); |
363 | 0 | } |
364 | | |
365 | | static void |
366 | | pdf_out_Bstar(fz_context *ctx, pdf_processor *proc_) |
367 | 0 | { |
368 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
369 | |
|
370 | 0 | if (proc->sep) |
371 | 0 | fz_write_byte(ctx, proc->out, ' '); |
372 | 0 | fz_write_string(ctx, proc->out, "B*"); |
373 | 0 | post_op(ctx, proc); |
374 | 0 | } |
375 | | |
376 | | static void |
377 | | pdf_out_b(fz_context *ctx, pdf_processor *proc_) |
378 | 0 | { |
379 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
380 | |
|
381 | 0 | if (proc->sep) |
382 | 0 | fz_write_byte(ctx, proc->out, ' '); |
383 | 0 | fz_write_string(ctx, proc->out, "b"); |
384 | 0 | post_op(ctx, proc); |
385 | 0 | } |
386 | | |
387 | | static void |
388 | | pdf_out_bstar(fz_context *ctx, pdf_processor *proc_) |
389 | 0 | { |
390 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
391 | |
|
392 | 0 | if (proc->sep) |
393 | 0 | fz_write_byte(ctx, proc->out, ' '); |
394 | 0 | fz_write_string(ctx, proc->out, "b*"); |
395 | 0 | post_op(ctx, proc); |
396 | 0 | } |
397 | | |
398 | | static void |
399 | | pdf_out_n(fz_context *ctx, pdf_processor *proc_) |
400 | 0 | { |
401 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
402 | |
|
403 | 0 | if (proc->sep) |
404 | 0 | fz_write_byte(ctx, proc->out, ' '); |
405 | 0 | fz_write_string(ctx, proc->out, "n"); |
406 | 0 | post_op(ctx, proc); |
407 | 0 | } |
408 | | |
409 | | /* clipping paths */ |
410 | | |
411 | | static void |
412 | | pdf_out_W(fz_context *ctx, pdf_processor *proc_) |
413 | 0 | { |
414 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
415 | |
|
416 | 0 | if (proc->sep) |
417 | 0 | fz_write_byte(ctx, proc->out, ' '); |
418 | 0 | fz_write_string(ctx, proc->out, "W"); |
419 | 0 | post_op(ctx, proc); |
420 | 0 | } |
421 | | |
422 | | static void |
423 | | pdf_out_Wstar(fz_context *ctx, pdf_processor *proc_) |
424 | 0 | { |
425 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
426 | |
|
427 | 0 | if (proc->sep) |
428 | 0 | fz_write_byte(ctx, proc->out, ' '); |
429 | 0 | fz_write_string(ctx, proc->out, "W*"); |
430 | 0 | post_op(ctx, proc); |
431 | 0 | } |
432 | | |
433 | | /* text objects */ |
434 | | |
435 | | static void |
436 | | pdf_out_BT(fz_context *ctx, pdf_processor *proc_) |
437 | 0 | { |
438 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
439 | |
|
440 | 0 | if (proc->sep) |
441 | 0 | fz_write_byte(ctx, proc->out, ' '); |
442 | 0 | fz_write_string(ctx, proc->out, "BT"); |
443 | 0 | post_op(ctx, proc); |
444 | 0 | } |
445 | | |
446 | | static void |
447 | | pdf_out_ET(fz_context *ctx, pdf_processor *proc_) |
448 | 0 | { |
449 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
450 | |
|
451 | 0 | if (proc->sep) |
452 | 0 | fz_write_byte(ctx, proc->out, ' '); |
453 | 0 | fz_write_string(ctx, proc->out, "ET"); |
454 | 0 | post_op(ctx, proc); |
455 | 0 | } |
456 | | |
457 | | /* text state */ |
458 | | |
459 | | static void |
460 | | pdf_out_Tc(fz_context *ctx, pdf_processor *proc_, float charspace) |
461 | 0 | { |
462 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
463 | |
|
464 | 0 | if (proc->sep) |
465 | 0 | fz_write_byte(ctx, proc->out, ' '); |
466 | 0 | fz_write_printf(ctx, proc->out, "%g Tc", charspace); |
467 | 0 | post_op(ctx, proc); |
468 | 0 | } |
469 | | |
470 | | static void |
471 | | pdf_out_Tw(fz_context *ctx, pdf_processor *proc_, float wordspace) |
472 | 0 | { |
473 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
474 | |
|
475 | 0 | if (proc->sep) |
476 | 0 | fz_write_byte(ctx, proc->out, ' '); |
477 | 0 | fz_write_printf(ctx, proc->out, "%g Tw", wordspace); |
478 | 0 | post_op(ctx, proc); |
479 | 0 | } |
480 | | |
481 | | static void |
482 | | pdf_out_Tz(fz_context *ctx, pdf_processor *proc_, float scale) |
483 | 0 | { |
484 | | /* scale is exactly as read from the file. */ |
485 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
486 | |
|
487 | 0 | if (proc->sep) |
488 | 0 | fz_write_byte(ctx, proc->out, ' '); |
489 | 0 | fz_write_printf(ctx, proc->out, "%g Tz", scale); |
490 | 0 | post_op(ctx, proc); |
491 | 0 | } |
492 | | |
493 | | static void |
494 | | pdf_out_TL(fz_context *ctx, pdf_processor *proc_, float leading) |
495 | 0 | { |
496 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
497 | |
|
498 | 0 | if (proc->sep) |
499 | 0 | fz_write_byte(ctx, proc->out, ' '); |
500 | 0 | fz_write_printf(ctx, proc->out, "%g TL", leading); |
501 | 0 | post_op(ctx, proc); |
502 | 0 | } |
503 | | |
504 | | static void |
505 | | pdf_out_Tf(fz_context *ctx, pdf_processor *proc_, const char *name, pdf_font_desc *font, float size) |
506 | 0 | { |
507 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
508 | |
|
509 | 0 | if (proc->extgstate != 0) |
510 | 0 | return; |
511 | | |
512 | 0 | fz_write_printf(ctx, proc->out, "%n %g Tf", name, size); |
513 | 0 | post_op(ctx, proc); |
514 | 0 | } |
515 | | |
516 | | static void |
517 | | pdf_out_Tr(fz_context *ctx, pdf_processor *proc_, int render) |
518 | 0 | { |
519 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
520 | |
|
521 | 0 | if (proc->sep) |
522 | 0 | fz_write_byte(ctx, proc->out, ' '); |
523 | 0 | fz_write_printf(ctx, proc->out, "%d Tr", render); |
524 | 0 | post_op(ctx, proc); |
525 | 0 | } |
526 | | |
527 | | static void |
528 | | pdf_out_Ts(fz_context *ctx, pdf_processor *proc_, float rise) |
529 | 0 | { |
530 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
531 | |
|
532 | 0 | if (proc->sep) |
533 | 0 | fz_write_byte(ctx, proc->out, ' '); |
534 | 0 | fz_write_printf(ctx, proc->out, "%g Ts", rise); |
535 | 0 | post_op(ctx, proc); |
536 | 0 | } |
537 | | |
538 | | /* text positioning */ |
539 | | |
540 | | static void |
541 | | pdf_out_Td(fz_context *ctx, pdf_processor *proc_, float tx, float ty) |
542 | 0 | { |
543 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
544 | |
|
545 | 0 | if (proc->sep) |
546 | 0 | fz_write_byte(ctx, proc->out, ' '); |
547 | 0 | fz_write_printf(ctx, proc->out, "%g %g Td", tx, ty); |
548 | 0 | post_op(ctx, proc); |
549 | 0 | } |
550 | | |
551 | | static void |
552 | | pdf_out_TD(fz_context *ctx, pdf_processor *proc_, float tx, float ty) |
553 | 0 | { |
554 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
555 | |
|
556 | 0 | if (proc->sep) |
557 | 0 | fz_write_byte(ctx, proc->out, ' '); |
558 | 0 | fz_write_printf(ctx, proc->out, "%g %g TD", tx, ty); |
559 | 0 | post_op(ctx, proc); |
560 | 0 | } |
561 | | |
562 | | static void |
563 | | pdf_out_Tm(fz_context *ctx, pdf_processor *proc_, float a, float b, float c, float d, float e, float f) |
564 | 0 | { |
565 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
566 | |
|
567 | 0 | if (proc->sep) |
568 | 0 | fz_write_byte(ctx, proc->out, ' '); |
569 | 0 | fz_write_printf(ctx, proc->out, "%g %g %g %g %g %g Tm", a, b, c, d, e, f); |
570 | 0 | post_op(ctx, proc); |
571 | 0 | } |
572 | | |
573 | | static void |
574 | | pdf_out_Tstar(fz_context *ctx, pdf_processor *proc_) |
575 | 0 | { |
576 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
577 | |
|
578 | 0 | if (proc->sep) |
579 | 0 | fz_write_byte(ctx, proc->out, ' '); |
580 | 0 | fz_write_string(ctx, proc->out, "T*"); |
581 | 0 | post_op(ctx, proc); |
582 | 0 | } |
583 | | |
584 | | /* text showing */ |
585 | | |
586 | | static void |
587 | | fz_write_pdf_string(fz_context *ctx, fz_output *out, const unsigned char *str, size_t len) |
588 | 0 | { |
589 | 0 | size_t i; |
590 | |
|
591 | 0 | for (i = 0; i < len; ++i) |
592 | 0 | if (str[i] < 32 || str[i] >= 127) |
593 | 0 | break; |
594 | |
|
595 | 0 | if (i < len) |
596 | 0 | { |
597 | 0 | fz_write_byte(ctx, out, '<'); |
598 | 0 | for (i = 0; i < len; ++i) |
599 | 0 | { |
600 | 0 | unsigned char c = str[i]; |
601 | 0 | fz_write_byte(ctx, out, "0123456789abcdef"[(c>>4)&15]); |
602 | 0 | fz_write_byte(ctx, out, "0123456789abcdef"[(c)&15]); |
603 | 0 | } |
604 | 0 | fz_write_byte(ctx, out, '>'); |
605 | 0 | } |
606 | 0 | else |
607 | 0 | { |
608 | 0 | fz_write_byte(ctx, out, '('); |
609 | 0 | for (i = 0; i < len; ++i) |
610 | 0 | { |
611 | 0 | unsigned char c = str[i]; |
612 | 0 | if (c == '(' || c == ')' || c == '\\') |
613 | 0 | fz_write_byte(ctx, out, '\\'); |
614 | 0 | fz_write_byte(ctx, out, c); |
615 | 0 | } |
616 | 0 | fz_write_byte(ctx, out, ')'); |
617 | 0 | } |
618 | 0 | } |
619 | | |
620 | | static void |
621 | | pdf_out_TJ(fz_context *ctx, pdf_processor *proc_, pdf_obj *array) |
622 | 0 | { |
623 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
624 | 0 | int ahx = proc->ahxencode; |
625 | |
|
626 | 0 | pdf_print_encrypted_obj(ctx, proc->out, array, 1, ahx, NULL, 0, 0, &proc->sep); |
627 | 0 | if (proc->sep) |
628 | 0 | fz_write_byte(ctx, proc->out, ' '); |
629 | 0 | fz_write_string(ctx, proc->out, "TJ"); |
630 | 0 | post_op(ctx, proc); |
631 | 0 | } |
632 | | |
633 | | static void |
634 | | pdf_out_Tj(fz_context *ctx, pdf_processor *proc_, char *str, size_t len) |
635 | 0 | { |
636 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
637 | |
|
638 | 0 | fz_write_pdf_string(ctx, proc->out, (const unsigned char *)str, len); |
639 | 0 | fz_write_string(ctx, proc->out, "Tj"); |
640 | 0 | post_op(ctx, proc); |
641 | 0 | } |
642 | | |
643 | | static void |
644 | | pdf_out_squote(fz_context *ctx, pdf_processor *proc_, char *str, size_t len) |
645 | 0 | { |
646 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
647 | |
|
648 | 0 | fz_write_pdf_string(ctx, proc->out, (const unsigned char *)str, len); |
649 | 0 | fz_write_string(ctx, proc->out, "'"); |
650 | 0 | post_op(ctx, proc); |
651 | 0 | } |
652 | | |
653 | | static void |
654 | | pdf_out_dquote(fz_context *ctx, pdf_processor *proc_, float aw, float ac, char *str, size_t len) |
655 | 0 | { |
656 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
657 | |
|
658 | 0 | if (proc->sep) |
659 | 0 | fz_write_byte(ctx, proc->out, ' '); |
660 | 0 | fz_write_printf(ctx, proc->out, "%g %g ", aw, ac); |
661 | 0 | fz_write_pdf_string(ctx, proc->out, (const unsigned char *)str, len); |
662 | 0 | fz_write_string(ctx, proc->out, "\""); |
663 | 0 | post_op(ctx, proc); |
664 | 0 | } |
665 | | |
666 | | /* type 3 fonts */ |
667 | | |
668 | | static void |
669 | | pdf_out_d0(fz_context *ctx, pdf_processor *proc_, float wx, float wy) |
670 | 0 | { |
671 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
672 | |
|
673 | 0 | if (proc->sep) |
674 | 0 | fz_write_byte(ctx, proc->out, ' '); |
675 | 0 | fz_write_printf(ctx, proc->out, "%g %g d0", wx, wy); |
676 | 0 | post_op(ctx, proc); |
677 | 0 | } |
678 | | |
679 | | static void |
680 | | pdf_out_d1(fz_context *ctx, pdf_processor *proc_, float wx, float wy, float llx, float lly, float urx, float ury) |
681 | 0 | { |
682 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
683 | |
|
684 | 0 | if (proc->sep) |
685 | 0 | fz_write_byte(ctx, proc->out, ' '); |
686 | 0 | fz_write_printf(ctx, proc->out, "%g %g %g %g %g %g d1", wx, wy, llx, lly, urx, ury); |
687 | 0 | post_op(ctx, proc); |
688 | 0 | } |
689 | | |
690 | | /* color */ |
691 | | |
692 | | static void |
693 | | pdf_out_CS(fz_context *ctx, pdf_processor *proc_, const char *name, fz_colorspace *cs) |
694 | 0 | { |
695 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
696 | |
|
697 | 0 | fz_write_printf(ctx, proc->out, "%n CS", name); |
698 | 0 | post_op(ctx, proc); |
699 | 0 | } |
700 | | |
701 | | static void |
702 | | pdf_out_cs(fz_context *ctx, pdf_processor *proc_, const char *name, fz_colorspace *cs) |
703 | 0 | { |
704 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
705 | |
|
706 | 0 | fz_write_printf(ctx, proc->out, "%n cs", name); |
707 | 0 | post_op(ctx, proc); |
708 | 0 | } |
709 | | |
710 | | static void |
711 | | pdf_out_SC_pattern(fz_context *ctx, pdf_processor *proc_, const char *name, pdf_pattern *pat, int n, float *color) |
712 | 0 | { |
713 | 0 | int i; |
714 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
715 | |
|
716 | 0 | if (proc->sep) |
717 | 0 | fz_write_byte(ctx, proc->out, ' '); |
718 | 0 | for (i = 0; i < n; ++i) |
719 | 0 | fz_write_printf(ctx, proc->out, "%g ", color[i]); |
720 | 0 | fz_write_printf(ctx, proc->out, "%n SCN", name); |
721 | 0 | post_op(ctx, proc); |
722 | 0 | } |
723 | | |
724 | | static void |
725 | | pdf_out_sc_pattern(fz_context *ctx, pdf_processor *proc_, const char *name, pdf_pattern *pat, int n, float *color) |
726 | 0 | { |
727 | 0 | int i; |
728 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
729 | |
|
730 | 0 | if (proc->sep) |
731 | 0 | fz_write_byte(ctx, proc->out, ' '); |
732 | 0 | for (i = 0; i < n; ++i) |
733 | 0 | fz_write_printf(ctx, proc->out, "%g ", color[i]); |
734 | 0 | fz_write_printf(ctx, proc->out, "%n scn", name); |
735 | 0 | post_op(ctx, proc); |
736 | 0 | } |
737 | | |
738 | | static void |
739 | | pdf_out_SC_shade(fz_context *ctx, pdf_processor *proc_, const char *name, fz_shade *shade) |
740 | 0 | { |
741 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
742 | |
|
743 | 0 | fz_write_printf(ctx, proc->out, "%n SCN", name); |
744 | 0 | post_op(ctx, proc); |
745 | 0 | } |
746 | | |
747 | | static void |
748 | | pdf_out_sc_shade(fz_context *ctx, pdf_processor *proc_, const char *name, fz_shade *shade) |
749 | 0 | { |
750 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
751 | |
|
752 | 0 | fz_write_printf(ctx, proc->out, "%n scn", name); |
753 | 0 | post_op(ctx, proc); |
754 | 0 | } |
755 | | |
756 | | static void |
757 | | pdf_out_SC_color(fz_context *ctx, pdf_processor *proc_, int n, float *color) |
758 | 0 | { |
759 | 0 | int i; |
760 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
761 | |
|
762 | 0 | if (proc->sep) |
763 | 0 | fz_write_byte(ctx, proc->out, ' '); |
764 | 0 | for (i = 0; i < n; ++i) |
765 | 0 | fz_write_printf(ctx, proc->out, "%g ", color[i]); |
766 | 0 | fz_write_string(ctx, proc->out, "SCN"); |
767 | 0 | post_op(ctx, proc); |
768 | 0 | } |
769 | | |
770 | | static void |
771 | | pdf_out_sc_color(fz_context *ctx, pdf_processor *proc_, int n, float *color) |
772 | 0 | { |
773 | 0 | int i; |
774 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
775 | |
|
776 | 0 | if (proc->sep) |
777 | 0 | fz_write_byte(ctx, proc->out, ' '); |
778 | 0 | for (i = 0; i < n; ++i) |
779 | 0 | fz_write_printf(ctx, proc->out, "%g ", color[i]); |
780 | 0 | fz_write_string(ctx, proc->out, "scn"); |
781 | 0 | post_op(ctx, proc); |
782 | 0 | } |
783 | | |
784 | | static void |
785 | | pdf_out_G(fz_context *ctx, pdf_processor *proc_, float g) |
786 | 0 | { |
787 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
788 | |
|
789 | 0 | if (proc->sep) |
790 | 0 | fz_write_byte(ctx, proc->out, ' '); |
791 | 0 | fz_write_printf(ctx, proc->out, "%g G", g); |
792 | 0 | post_op(ctx, proc); |
793 | 0 | } |
794 | | |
795 | | static void |
796 | | pdf_out_g(fz_context *ctx, pdf_processor *proc_, float g) |
797 | 0 | { |
798 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
799 | |
|
800 | 0 | if (proc->sep) |
801 | 0 | fz_write_byte(ctx, proc->out, ' '); |
802 | 0 | fz_write_printf(ctx, proc->out, "%g g", g); |
803 | 0 | post_op(ctx, proc); |
804 | 0 | } |
805 | | |
806 | | static void |
807 | | pdf_out_RG(fz_context *ctx, pdf_processor *proc_, float r, float g, float b) |
808 | 0 | { |
809 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
810 | |
|
811 | 0 | if (proc->sep) |
812 | 0 | fz_write_byte(ctx, proc->out, ' '); |
813 | 0 | fz_write_printf(ctx, proc->out, "%g %g %g RG", r, g, b); |
814 | 0 | post_op(ctx, proc); |
815 | 0 | } |
816 | | |
817 | | static void |
818 | | pdf_out_rg(fz_context *ctx, pdf_processor *proc_, float r, float g, float b) |
819 | 0 | { |
820 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
821 | |
|
822 | 0 | if (proc->sep) |
823 | 0 | fz_write_byte(ctx, proc->out, ' '); |
824 | 0 | fz_write_printf(ctx, proc->out, "%g %g %g rg", r, g, b); |
825 | 0 | post_op(ctx, proc); |
826 | 0 | } |
827 | | |
828 | | static void |
829 | | pdf_out_K(fz_context *ctx, pdf_processor *proc_, float c, float m, float y, float k) |
830 | 0 | { |
831 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
832 | |
|
833 | 0 | if (proc->sep) |
834 | 0 | fz_write_byte(ctx, proc->out, ' '); |
835 | 0 | fz_write_printf(ctx, proc->out, "%g %g %g %g K", c, m, y, k); |
836 | 0 | post_op(ctx, proc); |
837 | 0 | } |
838 | | |
839 | | static void |
840 | | pdf_out_k(fz_context *ctx, pdf_processor *proc_, float c, float m, float y, float k) |
841 | 0 | { |
842 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
843 | |
|
844 | 0 | if (proc->sep) |
845 | 0 | fz_write_byte(ctx, proc->out, ' '); |
846 | 0 | fz_write_printf(ctx, proc->out, "%g %g %g %g k", c, m, y, k); |
847 | 0 | post_op(ctx, proc); |
848 | 0 | } |
849 | | |
850 | | /* shadings, images, xobjects */ |
851 | | |
852 | | static void |
853 | | pdf_out_BI(fz_context *ctx, pdf_processor *proc_, fz_image *img, const char *colorspace) |
854 | 0 | { |
855 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
856 | 0 | fz_output *out = proc->out; |
857 | 0 | int ahx = proc->ahxencode; |
858 | 0 | fz_compressed_buffer *cbuf; |
859 | 0 | fz_buffer *buf = NULL; |
860 | 0 | int i, w, h, bpc; |
861 | 0 | unsigned char *data; |
862 | 0 | size_t len; |
863 | 0 | fz_pixmap *pix = NULL; |
864 | 0 | fz_colorspace *cs; |
865 | 0 | int type; |
866 | |
|
867 | 0 | if (img == NULL) |
868 | 0 | return; |
869 | 0 | cbuf = fz_compressed_image_buffer(ctx, img); |
870 | 0 | if (cbuf == NULL) |
871 | 0 | { |
872 | 0 | pix = fz_get_pixmap_from_image(ctx, img, NULL, NULL, &w, &h); |
873 | 0 | bpc = 8; |
874 | 0 | cs = pix->colorspace; |
875 | 0 | type = FZ_IMAGE_RAW; |
876 | 0 | } |
877 | 0 | else |
878 | 0 | { |
879 | 0 | buf = cbuf->buffer; |
880 | 0 | if (buf == NULL) |
881 | 0 | return; |
882 | 0 | w = img->w; |
883 | 0 | h = img->h; |
884 | 0 | bpc = img->bpc; |
885 | 0 | cs = img->colorspace; |
886 | 0 | type = cbuf->params.type; |
887 | 0 | } |
888 | | |
889 | 0 | fz_try(ctx) |
890 | 0 | { |
891 | 0 | if (proc->sep) |
892 | 0 | fz_write_byte(ctx, out, ' '); |
893 | 0 | fz_write_string(ctx, out, "BI "); |
894 | 0 | fz_write_printf(ctx, out, "/W %d", w); |
895 | 0 | fz_write_printf(ctx, out, "/H %d", h); |
896 | 0 | fz_write_printf(ctx, out, "/BPC %d", bpc); |
897 | 0 | if (img->imagemask) |
898 | 0 | fz_write_string(ctx, out, "/IM true"); |
899 | 0 | else if (cs == fz_device_gray(ctx)) |
900 | 0 | fz_write_string(ctx, out, "/CS/G"); |
901 | 0 | else if (cs == fz_device_rgb(ctx)) |
902 | 0 | fz_write_string(ctx, out, "/CS/RGB"); |
903 | 0 | else if (cs == fz_device_cmyk(ctx)) |
904 | 0 | fz_write_string(ctx, out, "/CS/CMYK"); |
905 | 0 | else if (cs) |
906 | 0 | fz_write_printf(ctx, out, "/CS%n", colorspace); |
907 | 0 | else |
908 | 0 | fz_throw(ctx, FZ_ERROR_ARGUMENT, "BI operator can only show ImageMask, Gray, RGB, or CMYK images"); |
909 | 0 | if (img->interpolate) |
910 | 0 | fz_write_string(ctx, out, "/I true"); |
911 | 0 | fz_write_string(ctx, out, "/D["); |
912 | 0 | for (i = 0; i < img->n * 2; ++i) |
913 | 0 | { |
914 | 0 | if (i > 0) |
915 | 0 | fz_write_byte(ctx, out, ' '); |
916 | 0 | fz_write_printf(ctx, out, "%g", img->decode[i]); |
917 | 0 | } |
918 | 0 | fz_write_string(ctx, out, "]"); |
919 | 0 | proc->sep = 0; |
920 | |
|
921 | 0 | switch (type) |
922 | 0 | { |
923 | 0 | default: |
924 | 0 | fz_throw(ctx, FZ_ERROR_ARGUMENT, "unknown compressed buffer type"); |
925 | 0 | break; |
926 | | |
927 | 0 | case FZ_IMAGE_JPEG: |
928 | 0 | fz_write_string(ctx, out, ahx ? "/F[/AHx/DCT]" : "/F/DCT"); |
929 | 0 | proc->sep = !ahx; |
930 | 0 | if (cbuf->params.u.jpeg.color_transform >= 0) |
931 | 0 | { |
932 | 0 | fz_write_printf(ctx, out, "/DP<</ColorTransform %d>>", cbuf->params.u.jpeg.color_transform); |
933 | 0 | proc->sep = 0; |
934 | 0 | } |
935 | 0 | if (cbuf->params.u.jpeg.invert_cmyk && img->n == 4) |
936 | 0 | { |
937 | 0 | fz_write_string(ctx, out, "/D[1 0 1 0 1 0 1 0]"); |
938 | 0 | proc->sep = 0; |
939 | 0 | } |
940 | 0 | break; |
941 | | |
942 | 0 | case FZ_IMAGE_FAX: |
943 | 0 | fz_write_string(ctx, out, ahx ? "/F[/AHx/CCF]/DP[null<<" : "/F/CCF/DP<<"); |
944 | 0 | fz_write_printf(ctx, out, "/K %d", cbuf->params.u.fax.k); |
945 | 0 | if (cbuf->params.u.fax.columns != 1728) |
946 | 0 | fz_write_printf(ctx, out, "/Columns %d", cbuf->params.u.fax.columns); |
947 | 0 | if (cbuf->params.u.fax.rows > 0) |
948 | 0 | fz_write_printf(ctx, out, "/Rows %d", cbuf->params.u.fax.rows); |
949 | 0 | if (cbuf->params.u.fax.end_of_line) |
950 | 0 | fz_write_string(ctx, out, "/EndOfLine true"); |
951 | 0 | if (cbuf->params.u.fax.encoded_byte_align) |
952 | 0 | fz_write_string(ctx, out, "/EncodedByteAlign true"); |
953 | 0 | if (!cbuf->params.u.fax.end_of_block) |
954 | 0 | fz_write_string(ctx, out, "/EndOfBlock false"); |
955 | 0 | if (cbuf->params.u.fax.black_is_1) |
956 | 0 | fz_write_string(ctx, out, "/BlackIs1 true"); |
957 | 0 | if (cbuf->params.u.fax.damaged_rows_before_error > 0) |
958 | 0 | fz_write_printf(ctx, out, "/DamagedRowsBeforeError %d", |
959 | 0 | cbuf->params.u.fax.damaged_rows_before_error); |
960 | 0 | fz_write_string(ctx, out, ahx ? ">>]" : ">>"); |
961 | 0 | proc->sep = 0; |
962 | 0 | break; |
963 | | |
964 | 0 | case FZ_IMAGE_RAW: |
965 | 0 | if (ahx) |
966 | 0 | { |
967 | 0 | fz_write_string(ctx, out, "/F/AHx"); |
968 | 0 | proc->sep = 1; |
969 | 0 | } |
970 | 0 | break; |
971 | | |
972 | 0 | case FZ_IMAGE_RLD: |
973 | 0 | fz_write_string(ctx, out, ahx ? "/F[/AHx/RL]" : "/F/RL"); |
974 | 0 | proc->sep = !ahx; |
975 | 0 | break; |
976 | | |
977 | 0 | case FZ_IMAGE_FLATE: |
978 | 0 | fz_write_string(ctx, out, ahx ? "/F[/AHx/Fl]" : "/F/Fl"); |
979 | 0 | proc->sep = !ahx; |
980 | 0 | if (cbuf->params.u.flate.predictor > 1) |
981 | 0 | { |
982 | 0 | fz_write_string(ctx, out, ahx ? "/DP[null<<" : "/DP<<"); |
983 | 0 | fz_write_printf(ctx, out, "/Predictor %d", cbuf->params.u.flate.predictor); |
984 | 0 | if (cbuf->params.u.flate.columns != 1) |
985 | 0 | fz_write_printf(ctx, out, "/Columns %d", cbuf->params.u.flate.columns); |
986 | 0 | if (cbuf->params.u.flate.colors != 1) |
987 | 0 | fz_write_printf(ctx, out, "/Colors %d", cbuf->params.u.flate.colors); |
988 | 0 | if (cbuf->params.u.flate.bpc != 8) |
989 | 0 | fz_write_printf(ctx, out, "/BitsPerComponent %d", cbuf->params.u.flate.bpc); |
990 | 0 | fz_write_string(ctx, out, ahx ? ">>]" : ">>"); |
991 | 0 | proc->sep = 0; |
992 | 0 | } |
993 | 0 | break; |
994 | | |
995 | 0 | case FZ_IMAGE_LZW: |
996 | 0 | fz_write_string(ctx, out, ahx ? "/F[/AHx/LZW]" : "/F/LZW"); |
997 | 0 | proc->sep = !ahx; |
998 | 0 | if (cbuf->params.u.lzw.predictor > 1) |
999 | 0 | { |
1000 | 0 | fz_write_string(ctx, out, ahx ? "/DP[<<null" : "/DP<<"); |
1001 | 0 | fz_write_printf(ctx, out, "/Predictor %d", cbuf->params.u.lzw.predictor); |
1002 | 0 | if (cbuf->params.u.lzw.columns != 1) |
1003 | 0 | fz_write_printf(ctx, out, "/Columns %d", cbuf->params.u.lzw.columns); |
1004 | 0 | if (cbuf->params.u.lzw.colors != 1) |
1005 | 0 | fz_write_printf(ctx, out, "/Colors %d", cbuf->params.u.lzw.colors); |
1006 | 0 | if (cbuf->params.u.lzw.bpc != 8) |
1007 | 0 | fz_write_printf(ctx, out, "/BitsPerComponent %d", cbuf->params.u.lzw.bpc); |
1008 | 0 | if (cbuf->params.u.lzw.early_change != 1) |
1009 | 0 | fz_write_printf(ctx, out, "/EarlyChange %d", cbuf->params.u.lzw.early_change); |
1010 | 0 | fz_write_string(ctx, out, ahx ? ">>]" : ">>"); |
1011 | 0 | proc->sep = 0; |
1012 | 0 | } |
1013 | 0 | break; |
1014 | 0 | } |
1015 | | |
1016 | 0 | if (proc->sep) |
1017 | 0 | fz_write_byte(ctx, out, ' '); |
1018 | 0 | fz_write_string(ctx, out, "ID "); |
1019 | 0 | if (buf) |
1020 | 0 | len = fz_buffer_storage(ctx, buf, &data); |
1021 | 0 | else |
1022 | 0 | { |
1023 | 0 | data = pix->samples; |
1024 | 0 | len = ((size_t)w) * h * pix->n; |
1025 | 0 | } |
1026 | 0 | if (ahx) |
1027 | 0 | { |
1028 | 0 | size_t z; |
1029 | 0 | for (z = 0; z < len; ++z) |
1030 | 0 | { |
1031 | 0 | int c = data[z]; |
1032 | 0 | fz_write_byte(ctx, out, "0123456789abcdef"[(c >> 4) & 0xf]); |
1033 | 0 | fz_write_byte(ctx, out, "0123456789abcdef"[c & 0xf]); |
1034 | 0 | if ((z & 31) == 31) |
1035 | 0 | fz_write_byte(ctx, out, '\n'); |
1036 | 0 | } |
1037 | 0 | fz_write_byte(ctx, out, '>'); |
1038 | 0 | } |
1039 | 0 | else |
1040 | 0 | { |
1041 | 0 | fz_write_data(ctx, out, data, len); |
1042 | 0 | } |
1043 | 0 | fz_write_string(ctx, out, " EI"); |
1044 | 0 | proc->sep = 1; |
1045 | 0 | } |
1046 | 0 | fz_always(ctx) |
1047 | 0 | fz_drop_pixmap(ctx, pix); |
1048 | 0 | fz_catch(ctx) |
1049 | 0 | fz_rethrow(ctx); |
1050 | 0 | } |
1051 | | |
1052 | | static void |
1053 | | pdf_out_sh(fz_context *ctx, pdf_processor *proc_, const char *name, fz_shade *shade) |
1054 | 0 | { |
1055 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
1056 | |
|
1057 | 0 | fz_write_printf(ctx, proc->out, "%n sh", name); |
1058 | 0 | post_op(ctx, proc); |
1059 | 0 | } |
1060 | | |
1061 | | static void |
1062 | | pdf_out_Do_image(fz_context *ctx, pdf_processor *proc_, const char *name, fz_image *image) |
1063 | 0 | { |
1064 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
1065 | |
|
1066 | 0 | fz_write_printf(ctx, proc->out, "%n Do", name); |
1067 | 0 | post_op(ctx, proc); |
1068 | 0 | } |
1069 | | |
1070 | | static void |
1071 | | pdf_out_Do_form(fz_context *ctx, pdf_processor *proc_, const char *name, pdf_obj *xobj) |
1072 | 0 | { |
1073 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
1074 | |
|
1075 | 0 | fz_write_printf(ctx, proc->out, "%n Do", name); |
1076 | 0 | post_op(ctx, proc); |
1077 | 0 | } |
1078 | | |
1079 | | /* marked content */ |
1080 | | |
1081 | | static void |
1082 | | pdf_out_MP(fz_context *ctx, pdf_processor *proc_, const char *tag) |
1083 | 0 | { |
1084 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
1085 | |
|
1086 | 0 | fz_write_printf(ctx, proc->out, "%n MP", tag); |
1087 | 0 | post_op(ctx, proc); |
1088 | 0 | } |
1089 | | |
1090 | | static void |
1091 | | pdf_out_DP(fz_context *ctx, pdf_processor *proc_, const char *tag, pdf_obj *raw, pdf_obj *cooked) |
1092 | 0 | { |
1093 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
1094 | 0 | int ahx = proc->ahxencode; |
1095 | |
|
1096 | 0 | fz_write_printf(ctx, proc->out, "%n", tag); |
1097 | 0 | proc->sep = 1; |
1098 | 0 | pdf_print_encrypted_obj(ctx, proc->out, raw, 1, ahx, NULL, 0, 0, &proc->sep); |
1099 | 0 | if (proc->sep) |
1100 | 0 | fz_write_byte(ctx, proc->out, ' '); |
1101 | 0 | fz_write_string(ctx, proc->out, "DP"); |
1102 | 0 | post_op(ctx, proc); |
1103 | 0 | } |
1104 | | |
1105 | | static void |
1106 | | pdf_out_BMC(fz_context *ctx, pdf_processor *proc_, const char *tag) |
1107 | 0 | { |
1108 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
1109 | |
|
1110 | 0 | fz_write_printf(ctx, proc->out, "%n BMC", tag); |
1111 | 0 | post_op(ctx, proc); |
1112 | 0 | } |
1113 | | |
1114 | | static void |
1115 | | pdf_out_BDC(fz_context *ctx, pdf_processor *proc_, const char *tag, pdf_obj *raw, pdf_obj *cooked) |
1116 | 0 | { |
1117 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
1118 | 0 | int ahx = proc->ahxencode; |
1119 | |
|
1120 | 0 | fz_write_printf(ctx, proc->out, "%n", tag); |
1121 | 0 | proc->sep = 1; |
1122 | 0 | pdf_print_encrypted_obj(ctx, proc->out, raw, 1, ahx, NULL, 0, 0, &proc->sep); |
1123 | 0 | if (proc->sep) |
1124 | 0 | fz_write_byte(ctx, proc->out, ' '); |
1125 | 0 | fz_write_string(ctx, proc->out, "BDC"); |
1126 | 0 | post_op(ctx, proc); |
1127 | 0 | } |
1128 | | |
1129 | | static void |
1130 | | pdf_out_EMC(fz_context *ctx, pdf_processor *proc_) |
1131 | 0 | { |
1132 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
1133 | |
|
1134 | 0 | if (proc->sep) |
1135 | 0 | fz_write_byte(ctx, proc->out, ' '); |
1136 | 0 | fz_write_string(ctx, proc->out, "EMC"); |
1137 | 0 | post_op(ctx, proc); |
1138 | 0 | } |
1139 | | |
1140 | | /* compatibility */ |
1141 | | |
1142 | | static void |
1143 | | pdf_out_BX(fz_context *ctx, pdf_processor *proc_) |
1144 | 0 | { |
1145 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
1146 | |
|
1147 | 0 | if (proc->sep) |
1148 | 0 | fz_write_byte(ctx, proc->out, ' '); |
1149 | 0 | fz_write_string(ctx, proc->out, "BX"); |
1150 | 0 | post_op(ctx, proc); |
1151 | 0 | } |
1152 | | |
1153 | | static void |
1154 | | pdf_out_EX(fz_context *ctx, pdf_processor *proc_) |
1155 | 0 | { |
1156 | 0 | pdf_output_processor *proc = (pdf_output_processor *)proc_; |
1157 | |
|
1158 | 0 | if (proc->sep) |
1159 | 0 | fz_write_byte(ctx, proc->out, ' '); |
1160 | 0 | fz_write_string(ctx, proc->out, "EX"); |
1161 | 0 | post_op(ctx, proc); |
1162 | 0 | } |
1163 | | |
1164 | | static void |
1165 | | pdf_close_output_processor(fz_context *ctx, pdf_processor *proc_) |
1166 | 0 | { |
1167 | 0 | pdf_output_processor *proc = (pdf_output_processor*)proc_; |
1168 | 0 | fz_output *out = proc->out; |
1169 | | |
1170 | | /* Add missing 'Q' operators to get back to zero. */ |
1171 | | /* We can't prepend missing 'q' operators to guarantee we don't underflow. */ |
1172 | 0 | while (proc->balance > 0) |
1173 | 0 | { |
1174 | 0 | proc->balance--; |
1175 | 0 | if (proc->sep) |
1176 | 0 | fz_write_byte(ctx, proc->out, ' '); |
1177 | 0 | fz_write_byte(ctx, out, 'Q'); |
1178 | 0 | post_op(ctx, proc); |
1179 | 0 | } |
1180 | |
|
1181 | 0 | fz_close_output(ctx, out); |
1182 | 0 | } |
1183 | | |
1184 | | static void |
1185 | | pdf_drop_output_processor(fz_context *ctx, pdf_processor *proc) |
1186 | 0 | { |
1187 | 0 | pdf_output_processor *p = (pdf_output_processor *)proc; |
1188 | |
|
1189 | 0 | fz_drop_output(ctx, p->out); |
1190 | 0 | } |
1191 | | |
1192 | | static void |
1193 | | pdf_reset_output_processor(fz_context *ctx, pdf_processor *proc) |
1194 | 0 | { |
1195 | 0 | pdf_output_processor *p = (pdf_output_processor *)proc; |
1196 | |
|
1197 | 0 | fz_reset_output(ctx, p->out); |
1198 | 0 | } |
1199 | | |
1200 | | static void |
1201 | | pdf_out_push_resources(fz_context *ctx, pdf_processor *proc, pdf_obj *res) |
1202 | 0 | { |
1203 | 0 | pdf_output_processor *p = (pdf_output_processor *)proc; |
1204 | 0 | resources_stack *stk = fz_malloc_struct(ctx, resources_stack); |
1205 | |
|
1206 | 0 | stk->next = p->rstack; |
1207 | 0 | p->rstack = stk; |
1208 | 0 | stk->res = pdf_keep_obj(ctx, res); |
1209 | 0 | } |
1210 | | |
1211 | | static pdf_obj * |
1212 | | pdf_out_pop_resources(fz_context *ctx, pdf_processor *proc) |
1213 | 0 | { |
1214 | 0 | pdf_output_processor *p = (pdf_output_processor *)proc; |
1215 | 0 | resources_stack *stk = p->rstack; |
1216 | 0 | pdf_obj *res = stk->res; |
1217 | |
|
1218 | 0 | p->rstack = stk->next; |
1219 | 0 | fz_free(ctx, stk); |
1220 | |
|
1221 | 0 | return res; |
1222 | 0 | } |
1223 | | |
1224 | | pdf_processor * |
1225 | | pdf_new_output_processor(fz_context *ctx, fz_output *out, int ahxencode, int newlines) |
1226 | 0 | { |
1227 | 0 | pdf_output_processor *proc = pdf_new_processor(ctx, sizeof *proc); |
1228 | |
|
1229 | 0 | proc->super.close_processor = pdf_close_output_processor; |
1230 | 0 | proc->super.drop_processor = pdf_drop_output_processor; |
1231 | 0 | proc->super.reset_processor = pdf_reset_output_processor; |
1232 | |
|
1233 | 0 | proc->super.push_resources = pdf_out_push_resources; |
1234 | 0 | proc->super.pop_resources = pdf_out_pop_resources; |
1235 | | |
1236 | | /* general graphics state */ |
1237 | 0 | proc->super.op_w = pdf_out_w; |
1238 | 0 | proc->super.op_j = pdf_out_j; |
1239 | 0 | proc->super.op_J = pdf_out_J; |
1240 | 0 | proc->super.op_M = pdf_out_M; |
1241 | 0 | proc->super.op_d = pdf_out_d; |
1242 | 0 | proc->super.op_ri = pdf_out_ri; |
1243 | 0 | proc->super.op_i = pdf_out_i; |
1244 | 0 | proc->super.op_gs_begin = pdf_out_gs_begin; |
1245 | 0 | proc->super.op_gs_end = pdf_out_gs_end; |
1246 | | |
1247 | | /* transparency graphics state */ |
1248 | 0 | proc->super.op_gs_BM = NULL; |
1249 | 0 | proc->super.op_gs_CA = NULL; |
1250 | 0 | proc->super.op_gs_ca = NULL; |
1251 | 0 | proc->super.op_gs_SMask = NULL; |
1252 | | |
1253 | | /* special graphics state */ |
1254 | 0 | proc->super.op_q = pdf_out_q; |
1255 | 0 | proc->super.op_Q = pdf_out_Q; |
1256 | 0 | proc->super.op_cm = pdf_out_cm; |
1257 | | |
1258 | | /* path construction */ |
1259 | 0 | proc->super.op_m = pdf_out_m; |
1260 | 0 | proc->super.op_l = pdf_out_l; |
1261 | 0 | proc->super.op_c = pdf_out_c; |
1262 | 0 | proc->super.op_v = pdf_out_v; |
1263 | 0 | proc->super.op_y = pdf_out_y; |
1264 | 0 | proc->super.op_h = pdf_out_h; |
1265 | 0 | proc->super.op_re = pdf_out_re; |
1266 | | |
1267 | | /* path painting */ |
1268 | 0 | proc->super.op_S = pdf_out_S; |
1269 | 0 | proc->super.op_s = pdf_out_s; |
1270 | 0 | proc->super.op_F = pdf_out_F; |
1271 | 0 | proc->super.op_f = pdf_out_f; |
1272 | 0 | proc->super.op_fstar = pdf_out_fstar; |
1273 | 0 | proc->super.op_B = pdf_out_B; |
1274 | 0 | proc->super.op_Bstar = pdf_out_Bstar; |
1275 | 0 | proc->super.op_b = pdf_out_b; |
1276 | 0 | proc->super.op_bstar = pdf_out_bstar; |
1277 | 0 | proc->super.op_n = pdf_out_n; |
1278 | | |
1279 | | /* clipping paths */ |
1280 | 0 | proc->super.op_W = pdf_out_W; |
1281 | 0 | proc->super.op_Wstar = pdf_out_Wstar; |
1282 | | |
1283 | | /* text objects */ |
1284 | 0 | proc->super.op_BT = pdf_out_BT; |
1285 | 0 | proc->super.op_ET = pdf_out_ET; |
1286 | | |
1287 | | /* text state */ |
1288 | 0 | proc->super.op_Tc = pdf_out_Tc; |
1289 | 0 | proc->super.op_Tw = pdf_out_Tw; |
1290 | 0 | proc->super.op_Tz = pdf_out_Tz; |
1291 | 0 | proc->super.op_TL = pdf_out_TL; |
1292 | 0 | proc->super.op_Tf = pdf_out_Tf; |
1293 | 0 | proc->super.op_Tr = pdf_out_Tr; |
1294 | 0 | proc->super.op_Ts = pdf_out_Ts; |
1295 | | |
1296 | | /* text positioning */ |
1297 | 0 | proc->super.op_Td = pdf_out_Td; |
1298 | 0 | proc->super.op_TD = pdf_out_TD; |
1299 | 0 | proc->super.op_Tm = pdf_out_Tm; |
1300 | 0 | proc->super.op_Tstar = pdf_out_Tstar; |
1301 | | |
1302 | | /* text showing */ |
1303 | 0 | proc->super.op_TJ = pdf_out_TJ; |
1304 | 0 | proc->super.op_Tj = pdf_out_Tj; |
1305 | 0 | proc->super.op_squote = pdf_out_squote; |
1306 | 0 | proc->super.op_dquote = pdf_out_dquote; |
1307 | | |
1308 | | /* type 3 fonts */ |
1309 | 0 | proc->super.op_d0 = pdf_out_d0; |
1310 | 0 | proc->super.op_d1 = pdf_out_d1; |
1311 | | |
1312 | | /* color */ |
1313 | 0 | proc->super.op_CS = pdf_out_CS; |
1314 | 0 | proc->super.op_cs = pdf_out_cs; |
1315 | 0 | proc->super.op_SC_color = pdf_out_SC_color; |
1316 | 0 | proc->super.op_sc_color = pdf_out_sc_color; |
1317 | 0 | proc->super.op_SC_pattern = pdf_out_SC_pattern; |
1318 | 0 | proc->super.op_sc_pattern = pdf_out_sc_pattern; |
1319 | 0 | proc->super.op_SC_shade = pdf_out_SC_shade; |
1320 | 0 | proc->super.op_sc_shade = pdf_out_sc_shade; |
1321 | |
|
1322 | 0 | proc->super.op_G = pdf_out_G; |
1323 | 0 | proc->super.op_g = pdf_out_g; |
1324 | 0 | proc->super.op_RG = pdf_out_RG; |
1325 | 0 | proc->super.op_rg = pdf_out_rg; |
1326 | 0 | proc->super.op_K = pdf_out_K; |
1327 | 0 | proc->super.op_k = pdf_out_k; |
1328 | | |
1329 | | /* shadings, images, xobjects */ |
1330 | 0 | proc->super.op_BI = pdf_out_BI; |
1331 | 0 | proc->super.op_sh = pdf_out_sh; |
1332 | 0 | proc->super.op_Do_image = pdf_out_Do_image; |
1333 | 0 | proc->super.op_Do_form = pdf_out_Do_form; |
1334 | | |
1335 | | /* marked content */ |
1336 | 0 | proc->super.op_MP = pdf_out_MP; |
1337 | 0 | proc->super.op_DP = pdf_out_DP; |
1338 | 0 | proc->super.op_BMC = pdf_out_BMC; |
1339 | 0 | proc->super.op_BDC = pdf_out_BDC; |
1340 | 0 | proc->super.op_EMC = pdf_out_EMC; |
1341 | | |
1342 | | /* compatibility */ |
1343 | 0 | proc->super.op_BX = pdf_out_BX; |
1344 | 0 | proc->super.op_EX = pdf_out_EX; |
1345 | | |
1346 | | /* extgstate */ |
1347 | 0 | proc->super.op_gs_OP = NULL; |
1348 | 0 | proc->super.op_gs_op = NULL; |
1349 | 0 | proc->super.op_gs_OPM = NULL; |
1350 | 0 | proc->super.op_gs_UseBlackPtComp = NULL; |
1351 | |
|
1352 | 0 | proc->out = out; |
1353 | 0 | proc->ahxencode = ahxencode; |
1354 | 0 | proc->newlines = newlines; |
1355 | |
|
1356 | 0 | proc->super.requirements = PDF_PROCESSOR_REQUIRES_DECODED_IMAGES; |
1357 | |
|
1358 | 0 | proc->balance = 0; |
1359 | |
|
1360 | 0 | return (pdf_processor*)proc; |
1361 | 0 | } |
1362 | | |
1363 | | pdf_processor * |
1364 | | pdf_new_buffer_processor(fz_context *ctx, fz_buffer *buffer, int ahxencode, int newlines) |
1365 | 0 | { |
1366 | 0 | pdf_processor *proc = NULL; |
1367 | 0 | fz_output *out = fz_new_output_with_buffer(ctx, buffer); |
1368 | 0 | fz_try(ctx) |
1369 | 0 | { |
1370 | 0 | proc = pdf_new_output_processor(ctx, out, ahxencode, newlines); |
1371 | 0 | } |
1372 | 0 | fz_catch(ctx) |
1373 | 0 | { |
1374 | 0 | fz_drop_output(ctx, out); |
1375 | 0 | fz_rethrow(ctx); |
1376 | 0 | } |
1377 | 0 | return proc; |
1378 | 0 | } |
1379 | | |
1380 | | /* Simplified processor that only counts matching q/Q pairs. */ |
1381 | | |
1382 | | typedef struct |
1383 | | { |
1384 | | pdf_processor super; |
1385 | | int *balance; |
1386 | | int *min_q; |
1387 | | int *min_op_q; |
1388 | | int first; |
1389 | | } pdf_balance_processor; |
1390 | | |
1391 | | static void |
1392 | | pdf_balance_q(fz_context *ctx, pdf_processor *proc_) |
1393 | 0 | { |
1394 | 0 | pdf_balance_processor *proc = (pdf_balance_processor*)proc_; |
1395 | 0 | (*proc->balance)++; |
1396 | 0 | } |
1397 | | |
1398 | | static void |
1399 | | pdf_balance_Q(fz_context *ctx, pdf_processor *proc_) |
1400 | 0 | { |
1401 | 0 | pdf_balance_processor *proc = (pdf_balance_processor*)proc_; |
1402 | 0 | (*proc->balance)--; |
1403 | 0 | if (*proc->balance < *proc->min_q) |
1404 | 0 | *proc->min_q = *proc->balance; |
1405 | 0 | } |
1406 | | |
1407 | | static void |
1408 | | pdf_balance_void(fz_context *ctx, pdf_processor *proc_) |
1409 | 0 | { |
1410 | 0 | pdf_balance_processor *proc = (pdf_balance_processor*)proc_; |
1411 | 0 | if (*proc->balance < *proc->min_op_q) |
1412 | 0 | *proc->min_op_q = *proc->balance; |
1413 | 0 | } |
1414 | | |
1415 | 0 | #define BALANCE { pdf_balance_void(ctx, p); }Unexecuted instantiation: pdf-op-buffer.c:pdf_balance_float Unexecuted instantiation: pdf-op-buffer.c:pdf_balance_int Unexecuted instantiation: pdf-op-buffer.c:pdf_balance_d Unexecuted instantiation: pdf-op-buffer.c:pdf_balance_string Unexecuted instantiation: pdf-op-buffer.c:pdf_balance_gs_begin Unexecuted instantiation: pdf-op-buffer.c:pdf_balance_float6 Unexecuted instantiation: pdf-op-buffer.c:pdf_balance_float2 Unexecuted instantiation: pdf-op-buffer.c:pdf_balance_float4 Unexecuted instantiation: pdf-op-buffer.c:pdf_balance_Tf Unexecuted instantiation: pdf-op-buffer.c:pdf_balance_TJ Unexecuted instantiation: pdf-op-buffer.c:pdf_balance_Tj Unexecuted instantiation: pdf-op-buffer.c:pdf_balance_squote Unexecuted instantiation: pdf-op-buffer.c:pdf_balance_dquote Unexecuted instantiation: pdf-op-buffer.c:pdf_balance_cs Unexecuted instantiation: pdf-op-buffer.c:pdf_balance_sc_color Unexecuted instantiation: pdf-op-buffer.c:pdf_balance_sc_pattern Unexecuted instantiation: pdf-op-buffer.c:pdf_balance_sc_shade Unexecuted instantiation: pdf-op-buffer.c:pdf_balance_float3 Unexecuted instantiation: pdf-op-buffer.c:pdf_balance_BI Unexecuted instantiation: pdf-op-buffer.c:pdf_balance_sh Unexecuted instantiation: pdf-op-buffer.c:pdf_balance_Do_image Unexecuted instantiation: pdf-op-buffer.c:pdf_balance_Do_form Unexecuted instantiation: pdf-op-buffer.c:pdf_balance_BDC |
1416 | | |
1417 | | static void pdf_balance_string(fz_context *ctx, pdf_processor *p, const char *x) BALANCE |
1418 | | static void pdf_balance_int(fz_context *ctx, pdf_processor *p, int x) BALANCE |
1419 | | static void pdf_balance_float(fz_context *ctx, pdf_processor *p, float x) BALANCE |
1420 | | static void pdf_balance_float2(fz_context *ctx, pdf_processor *p, float x, float y) BALANCE |
1421 | | static void pdf_balance_float3(fz_context *ctx, pdf_processor *p, float x, float y, float z) BALANCE |
1422 | | static void pdf_balance_float4(fz_context *ctx, pdf_processor *p, float x, float y, float z, float w) BALANCE |
1423 | | static void pdf_balance_float6(fz_context *ctx, pdf_processor *p, float a, float b, float c, float d, float e, float f) BALANCE |
1424 | | |
1425 | | static void pdf_balance_d(fz_context *ctx, pdf_processor *p, pdf_obj *array, float phase) BALANCE |
1426 | | static void pdf_balance_gs_begin(fz_context *ctx, pdf_processor *p, const char *name, pdf_obj *extgstate) BALANCE |
1427 | | static void pdf_balance_Tf(fz_context *ctx, pdf_processor *p, const char *name, pdf_font_desc *font, float size) BALANCE |
1428 | | static void pdf_balance_TJ(fz_context *ctx, pdf_processor *p, pdf_obj *array) BALANCE |
1429 | | static void pdf_balance_Tj(fz_context *ctx, pdf_processor *p, char *str, size_t len) BALANCE |
1430 | | static void pdf_balance_squote(fz_context *ctx, pdf_processor *p, char *str, size_t len) BALANCE |
1431 | | static void pdf_balance_dquote(fz_context *ctx, pdf_processor *p, float aw, float ac, char *str, size_t len) BALANCE |
1432 | | static void pdf_balance_cs(fz_context *ctx, pdf_processor *p, const char *name, fz_colorspace *cs) BALANCE |
1433 | | static void pdf_balance_sc_pattern(fz_context *ctx, pdf_processor *p, const char *name, pdf_pattern *pat, int n, float *color) BALANCE |
1434 | | static void pdf_balance_sc_shade(fz_context *ctx, pdf_processor *p, const char *name, fz_shade *shade) BALANCE |
1435 | | static void pdf_balance_sc_color(fz_context *ctx, pdf_processor *p, int n, float *color) BALANCE |
1436 | | static void pdf_balance_BDC(fz_context *ctx, pdf_processor *p, const char *tag, pdf_obj *raw, pdf_obj *cooked) BALANCE |
1437 | | static void pdf_balance_BI(fz_context *ctx, pdf_processor *p, fz_image *img, const char *colorspace) BALANCE |
1438 | | static void pdf_balance_sh(fz_context *ctx, pdf_processor *p, const char *name, fz_shade *shade) BALANCE |
1439 | | static void pdf_balance_Do_image(fz_context *ctx, pdf_processor *p, const char *name, fz_image *image) BALANCE |
1440 | | static void pdf_balance_Do_form(fz_context *ctx, pdf_processor *p, const char *name, pdf_obj *xobj) BALANCE |
1441 | | |
1442 | | static pdf_processor * |
1443 | | pdf_new_balance_processor(fz_context *ctx, int *balance, int *min_q, int *min_op_q) |
1444 | 0 | { |
1445 | 0 | pdf_balance_processor *proc = pdf_new_processor(ctx, sizeof *proc); |
1446 | |
|
1447 | 0 | proc->super.op_q = pdf_balance_q; |
1448 | 0 | proc->super.op_Q = pdf_balance_Q; |
1449 | | |
1450 | | /* general graphics state */ |
1451 | 0 | proc->super.op_w = pdf_balance_float; |
1452 | 0 | proc->super.op_j = pdf_balance_int; |
1453 | 0 | proc->super.op_J = pdf_balance_int; |
1454 | 0 | proc->super.op_M = pdf_balance_float; |
1455 | 0 | proc->super.op_d = pdf_balance_d; |
1456 | 0 | proc->super.op_ri = pdf_balance_string; |
1457 | 0 | proc->super.op_i = pdf_balance_float; |
1458 | 0 | proc->super.op_gs_begin = pdf_balance_gs_begin; |
1459 | | |
1460 | | /* special graphics state */ |
1461 | 0 | proc->super.op_cm = pdf_balance_float6; |
1462 | | |
1463 | | /* path construction */ |
1464 | 0 | proc->super.op_m = pdf_balance_float2; |
1465 | 0 | proc->super.op_l = pdf_balance_float2; |
1466 | 0 | proc->super.op_c = pdf_balance_float6; |
1467 | 0 | proc->super.op_v = pdf_balance_float4; |
1468 | 0 | proc->super.op_y = pdf_balance_float4; |
1469 | 0 | proc->super.op_h = pdf_balance_void; |
1470 | 0 | proc->super.op_re = pdf_balance_float4; |
1471 | | |
1472 | | /* path painting */ |
1473 | 0 | proc->super.op_S = pdf_balance_void; |
1474 | 0 | proc->super.op_s = pdf_balance_void; |
1475 | 0 | proc->super.op_F = pdf_balance_void; |
1476 | 0 | proc->super.op_f = pdf_balance_void; |
1477 | 0 | proc->super.op_fstar = pdf_balance_void; |
1478 | 0 | proc->super.op_B = pdf_balance_void; |
1479 | 0 | proc->super.op_Bstar = pdf_balance_void; |
1480 | 0 | proc->super.op_b = pdf_balance_void; |
1481 | 0 | proc->super.op_bstar = pdf_balance_void; |
1482 | 0 | proc->super.op_n = pdf_balance_void; |
1483 | | |
1484 | | /* clipping paths */ |
1485 | 0 | proc->super.op_W = pdf_balance_void; |
1486 | 0 | proc->super.op_Wstar = pdf_balance_void; |
1487 | | |
1488 | | /* text objects */ |
1489 | 0 | proc->super.op_BT = pdf_balance_void; |
1490 | 0 | proc->super.op_ET = pdf_balance_void; |
1491 | | |
1492 | | /* text state */ |
1493 | 0 | proc->super.op_Tc = pdf_balance_float; |
1494 | 0 | proc->super.op_Tw = pdf_balance_float; |
1495 | 0 | proc->super.op_Tz = pdf_balance_float; |
1496 | 0 | proc->super.op_TL = pdf_balance_float; |
1497 | 0 | proc->super.op_Tf = pdf_balance_Tf; |
1498 | 0 | proc->super.op_Tr = pdf_balance_int; |
1499 | 0 | proc->super.op_Ts = pdf_balance_float; |
1500 | | |
1501 | | /* text positioning */ |
1502 | 0 | proc->super.op_Td = pdf_balance_float2; |
1503 | 0 | proc->super.op_TD = pdf_balance_float2; |
1504 | 0 | proc->super.op_Tm = pdf_balance_float6; |
1505 | 0 | proc->super.op_Tstar = pdf_balance_void; |
1506 | | |
1507 | | /* text showing */ |
1508 | 0 | proc->super.op_TJ = pdf_balance_TJ; |
1509 | 0 | proc->super.op_Tj = pdf_balance_Tj; |
1510 | 0 | proc->super.op_squote = pdf_balance_squote; |
1511 | 0 | proc->super.op_dquote = pdf_balance_dquote; |
1512 | | |
1513 | | /* type 3 fonts */ |
1514 | 0 | proc->super.op_d0 = pdf_balance_float2; |
1515 | 0 | proc->super.op_d1 = pdf_balance_float6; |
1516 | | |
1517 | | /* color */ |
1518 | 0 | proc->super.op_CS = pdf_balance_cs; |
1519 | 0 | proc->super.op_cs = pdf_balance_cs; |
1520 | 0 | proc->super.op_SC_color = pdf_balance_sc_color; |
1521 | 0 | proc->super.op_sc_color = pdf_balance_sc_color; |
1522 | 0 | proc->super.op_SC_pattern = pdf_balance_sc_pattern; |
1523 | 0 | proc->super.op_sc_pattern = pdf_balance_sc_pattern; |
1524 | 0 | proc->super.op_SC_shade = pdf_balance_sc_shade; |
1525 | 0 | proc->super.op_sc_shade = pdf_balance_sc_shade; |
1526 | |
|
1527 | 0 | proc->super.op_G = pdf_balance_float; |
1528 | 0 | proc->super.op_g = pdf_balance_float; |
1529 | 0 | proc->super.op_RG = pdf_balance_float3; |
1530 | 0 | proc->super.op_rg = pdf_balance_float3; |
1531 | 0 | proc->super.op_K = pdf_balance_float4; |
1532 | 0 | proc->super.op_k = pdf_balance_float4; |
1533 | | |
1534 | | /* shadings, images, xobjects */ |
1535 | 0 | proc->super.op_BI = pdf_balance_BI; |
1536 | 0 | proc->super.op_sh = pdf_balance_sh; |
1537 | 0 | proc->super.op_Do_image = pdf_balance_Do_image; |
1538 | 0 | proc->super.op_Do_form = pdf_balance_Do_form; |
1539 | | |
1540 | | /* marked content */ |
1541 | 0 | proc->super.op_MP = pdf_balance_string; |
1542 | 0 | proc->super.op_DP = pdf_balance_BDC; |
1543 | 0 | proc->super.op_BMC = pdf_balance_string; |
1544 | 0 | proc->super.op_BDC = pdf_balance_BDC; |
1545 | 0 | proc->super.op_EMC = pdf_balance_void; |
1546 | | |
1547 | | /* compatibility */ |
1548 | 0 | proc->super.op_BX = pdf_balance_void; |
1549 | 0 | proc->super.op_EX = pdf_balance_void; |
1550 | |
|
1551 | 0 | proc->balance = balance; |
1552 | 0 | proc->min_q = min_q; |
1553 | 0 | proc->min_op_q = min_op_q; |
1554 | |
|
1555 | 0 | return (pdf_processor*)proc; |
1556 | 0 | } |
1557 | | |
1558 | | void |
1559 | | pdf_count_q_balance(fz_context *ctx, pdf_document *doc, pdf_obj *res, pdf_obj *stm, int *prepend, int *append) |
1560 | 0 | { |
1561 | 0 | pdf_processor *proc; |
1562 | |
|
1563 | 0 | int end_q = 0; |
1564 | 0 | int min_q = 0; |
1565 | 0 | int min_op_q = 1; |
1566 | |
|
1567 | 0 | proc = pdf_new_balance_processor(ctx, &end_q, &min_q, &min_op_q); |
1568 | 0 | fz_try(ctx) |
1569 | 0 | { |
1570 | 0 | pdf_process_raw_contents(ctx, proc, doc, res, stm, NULL); |
1571 | 0 | pdf_close_processor(ctx, proc); |
1572 | 0 | } |
1573 | 0 | fz_always(ctx) |
1574 | 0 | pdf_drop_processor(ctx, proc); |
1575 | 0 | fz_catch(ctx) |
1576 | 0 | fz_rethrow(ctx); |
1577 | | |
1578 | | /* normally zero, but in bad files there could be more Q than q */ |
1579 | 0 | *prepend = -min_q; |
1580 | | |
1581 | | /* how many Q are missing at the end */ |
1582 | 0 | *append = end_q - min_q; |
1583 | | |
1584 | | /* if there are unguarded operators we must add one level of q/Q around everything */ |
1585 | 0 | if (min_op_q == min_q) |
1586 | 0 | { |
1587 | 0 | *prepend += 1; |
1588 | 0 | *append += 1; |
1589 | 0 | } |
1590 | 0 | } |