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