1 | #include "mupdf/fitz.h" |
2 | #include "mupdf/pdf.h" |
3 | |
4 | typedef struct pdf_output_processor_s pdf_output_processor; |
5 | |
6 | struct pdf_output_processor_s |
7 | { |
8 | pdf_processor super; |
9 | fz_output *out; |
10 | int ahxencode; |
11 | int extgstate; |
12 | }; |
13 | |
14 | /* general graphics state */ |
15 | |
16 | static void |
17 | pdf_out_w(fz_context *ctx, pdf_processor *proc, float linewidth) |
18 | { |
19 | fz_output *out = ((pdf_output_processor*)proc)->out; |
20 | if (!((pdf_output_processor*)proc)->extgstate) |
21 | fz_write_printf(ctx, out, "%g w\n" , linewidth); |
22 | } |
23 | |
24 | static void |
25 | pdf_out_j(fz_context *ctx, pdf_processor *proc, int linejoin) |
26 | { |
27 | fz_output *out = ((pdf_output_processor*)proc)->out; |
28 | if (!((pdf_output_processor*)proc)->extgstate) |
29 | fz_write_printf(ctx, out, "%d j\n" , linejoin); |
30 | } |
31 | |
32 | static void |
33 | pdf_out_J(fz_context *ctx, pdf_processor *proc, int linecap) |
34 | { |
35 | fz_output *out = ((pdf_output_processor*)proc)->out; |
36 | if (!((pdf_output_processor*)proc)->extgstate) |
37 | fz_write_printf(ctx, out, "%d J\n" , linecap); |
38 | } |
39 | |
40 | static void |
41 | pdf_out_M(fz_context *ctx, pdf_processor *proc, float a) |
42 | { |
43 | fz_output *out = ((pdf_output_processor*)proc)->out; |
44 | if (!((pdf_output_processor*)proc)->extgstate) |
45 | fz_write_printf(ctx, out, "%g M\n" , a); |
46 | } |
47 | |
48 | static void |
49 | pdf_out_d(fz_context *ctx, pdf_processor *proc, pdf_obj *array, float phase) |
50 | { |
51 | fz_output *out = ((pdf_output_processor*)proc)->out; |
52 | int ahx = ((pdf_output_processor*)proc)->ahxencode; |
53 | if (!((pdf_output_processor*)proc)->extgstate) |
54 | { |
55 | pdf_print_obj(ctx, out, array, 1, ahx); |
56 | fz_write_printf(ctx, out, " %g d\n" , phase); |
57 | } |
58 | } |
59 | |
60 | static void |
61 | pdf_out_ri(fz_context *ctx, pdf_processor *proc, const char *intent) |
62 | { |
63 | fz_output *out = ((pdf_output_processor*)proc)->out; |
64 | if (!((pdf_output_processor*)proc)->extgstate) |
65 | fz_write_printf(ctx, out, "%n ri\n" , intent); |
66 | } |
67 | |
68 | static void |
69 | pdf_out_gs_OP(fz_context *ctx, pdf_processor *proc, int b) |
70 | { |
71 | } |
72 | |
73 | static void |
74 | pdf_out_gs_op(fz_context *ctx, pdf_processor *proc, int b) |
75 | { |
76 | } |
77 | |
78 | static void |
79 | pdf_out_gs_OPM(fz_context *ctx, pdf_processor *proc, int i) |
80 | { |
81 | } |
82 | |
83 | static void |
84 | pdf_out_gs_UseBlackPtComp(fz_context *ctx, pdf_processor *proc, pdf_obj *name) |
85 | { |
86 | } |
87 | |
88 | static void |
89 | pdf_out_i(fz_context *ctx, pdf_processor *proc, float flatness) |
90 | { |
91 | fz_output *out = ((pdf_output_processor*)proc)->out; |
92 | if (!((pdf_output_processor*)proc)->extgstate) |
93 | fz_write_printf(ctx, out, "%g i\n" , flatness); |
94 | } |
95 | |
96 | static void |
97 | pdf_out_gs_begin(fz_context *ctx, pdf_processor *proc, const char *name, pdf_obj *extgstate) |
98 | { |
99 | fz_output *out = ((pdf_output_processor*)proc)->out; |
100 | ((pdf_output_processor*)proc)->extgstate = 1; |
101 | fz_write_printf(ctx, out, "%n gs\n" , name); |
102 | } |
103 | |
104 | static void |
105 | pdf_out_gs_end(fz_context *ctx, pdf_processor *proc) |
106 | { |
107 | ((pdf_output_processor*)proc)->extgstate = 0; |
108 | } |
109 | |
110 | /* special graphics state */ |
111 | |
112 | static void |
113 | pdf_out_q(fz_context *ctx, pdf_processor *proc) |
114 | { |
115 | fz_output *out = ((pdf_output_processor*)proc)->out; |
116 | fz_write_string(ctx, out, "q\n" ); |
117 | } |
118 | |
119 | static void |
120 | pdf_out_Q(fz_context *ctx, pdf_processor *proc) |
121 | { |
122 | fz_output *out = ((pdf_output_processor*)proc)->out; |
123 | fz_write_string(ctx, out, "Q\n" ); |
124 | } |
125 | |
126 | static void |
127 | pdf_out_cm(fz_context *ctx, pdf_processor *proc, float a, float b, float c, float d, float e, float f) |
128 | { |
129 | fz_output *out = ((pdf_output_processor*)proc)->out; |
130 | fz_write_printf(ctx, out, "%g %g %g %g %g %g cm\n" , a, b, c, d, e, f); |
131 | } |
132 | |
133 | /* path construction */ |
134 | |
135 | static void |
136 | pdf_out_m(fz_context *ctx, pdf_processor *proc, float x, float y) |
137 | { |
138 | fz_output *out = ((pdf_output_processor*)proc)->out; |
139 | fz_write_printf(ctx, out, "%g %g m\n" , x, y); |
140 | } |
141 | |
142 | static void |
143 | pdf_out_l(fz_context *ctx, pdf_processor *proc, float x, float y) |
144 | { |
145 | fz_output *out = ((pdf_output_processor*)proc)->out; |
146 | fz_write_printf(ctx, out, "%g %g l\n" , x, y); |
147 | } |
148 | |
149 | static void |
150 | pdf_out_c(fz_context *ctx, pdf_processor *proc, float x1, float y1, float x2, float y2, float x3, float y3) |
151 | { |
152 | fz_output *out = ((pdf_output_processor*)proc)->out; |
153 | fz_write_printf(ctx, out, "%g %g %g %g %g %g c\n" , x1, y1, x2, y2, x3, y3); |
154 | } |
155 | |
156 | static void |
157 | pdf_out_v(fz_context *ctx, pdf_processor *proc, float x2, float y2, float x3, float y3) |
158 | { |
159 | fz_output *out = ((pdf_output_processor*)proc)->out; |
160 | fz_write_printf(ctx, out, "%g %g %g %g v\n" , x2, y2, x3, y3); |
161 | } |
162 | |
163 | static void |
164 | pdf_out_y(fz_context *ctx, pdf_processor *proc, float x1, float y1, float x3, float y3) |
165 | { |
166 | fz_output *out = ((pdf_output_processor*)proc)->out; |
167 | fz_write_printf(ctx, out, "%g %g %g %g y\n" , x1, y1, x3, y3); |
168 | } |
169 | |
170 | static void |
171 | pdf_out_h(fz_context *ctx, pdf_processor *proc) |
172 | { |
173 | fz_output *out = ((pdf_output_processor*)proc)->out; |
174 | fz_write_string(ctx, out, "h\n" ); |
175 | } |
176 | |
177 | static void |
178 | pdf_out_re(fz_context *ctx, pdf_processor *proc, float x, float y, float w, float h) |
179 | { |
180 | fz_output *out = ((pdf_output_processor*)proc)->out; |
181 | fz_write_printf(ctx, out, "%g %g %g %g re\n" , x, y, w, h); |
182 | } |
183 | |
184 | /* path painting */ |
185 | |
186 | static void |
187 | pdf_out_S(fz_context *ctx, pdf_processor *proc) |
188 | { |
189 | fz_output *out = ((pdf_output_processor*)proc)->out; |
190 | fz_write_string(ctx, out, "S\n" ); |
191 | } |
192 | |
193 | static void |
194 | pdf_out_s(fz_context *ctx, pdf_processor *proc) |
195 | { |
196 | fz_output *out = ((pdf_output_processor*)proc)->out; |
197 | fz_write_string(ctx, out, "s\n" ); |
198 | } |
199 | |
200 | static void |
201 | pdf_out_F(fz_context *ctx, pdf_processor *proc) |
202 | { |
203 | fz_output *out = ((pdf_output_processor*)proc)->out; |
204 | fz_write_string(ctx, out, "F\n" ); |
205 | } |
206 | |
207 | static void |
208 | pdf_out_f(fz_context *ctx, pdf_processor *proc) |
209 | { |
210 | fz_output *out = ((pdf_output_processor*)proc)->out; |
211 | fz_write_string(ctx, out, "f\n" ); |
212 | } |
213 | |
214 | static void |
215 | pdf_out_fstar(fz_context *ctx, pdf_processor *proc) |
216 | { |
217 | fz_output *out = ((pdf_output_processor*)proc)->out; |
218 | fz_write_string(ctx, out, "f*\n" ); |
219 | } |
220 | |
221 | static void |
222 | pdf_out_B(fz_context *ctx, pdf_processor *proc) |
223 | { |
224 | fz_output *out = ((pdf_output_processor*)proc)->out; |
225 | fz_write_string(ctx, out, "B\n" ); |
226 | } |
227 | |
228 | static void |
229 | pdf_out_Bstar(fz_context *ctx, pdf_processor *proc) |
230 | { |
231 | fz_output *out = ((pdf_output_processor*)proc)->out; |
232 | fz_write_string(ctx, out, "B*\n" ); |
233 | } |
234 | |
235 | static void |
236 | pdf_out_b(fz_context *ctx, pdf_processor *proc) |
237 | { |
238 | fz_output *out = ((pdf_output_processor*)proc)->out; |
239 | fz_write_string(ctx, out, "b\n" ); |
240 | } |
241 | |
242 | static void |
243 | pdf_out_bstar(fz_context *ctx, pdf_processor *proc) |
244 | { |
245 | fz_output *out = ((pdf_output_processor*)proc)->out; |
246 | fz_write_string(ctx, out, "b*\n" ); |
247 | } |
248 | |
249 | static void |
250 | pdf_out_n(fz_context *ctx, pdf_processor *proc) |
251 | { |
252 | fz_output *out = ((pdf_output_processor*)proc)->out; |
253 | fz_write_string(ctx, out, "n\n" ); |
254 | } |
255 | |
256 | /* clipping paths */ |
257 | |
258 | static void |
259 | pdf_out_W(fz_context *ctx, pdf_processor *proc) |
260 | { |
261 | fz_output *out = ((pdf_output_processor*)proc)->out; |
262 | fz_write_string(ctx, out, "W\n" ); |
263 | } |
264 | |
265 | static void |
266 | pdf_out_Wstar(fz_context *ctx, pdf_processor *proc) |
267 | { |
268 | fz_output *out = ((pdf_output_processor*)proc)->out; |
269 | fz_write_string(ctx, out, "W*\n" ); |
270 | } |
271 | |
272 | /* text objects */ |
273 | |
274 | static void |
275 | pdf_out_BT(fz_context *ctx, pdf_processor *proc) |
276 | { |
277 | fz_output *out = ((pdf_output_processor*)proc)->out; |
278 | fz_write_string(ctx, out, "BT\n" ); |
279 | } |
280 | |
281 | static void |
282 | pdf_out_ET(fz_context *ctx, pdf_processor *proc) |
283 | { |
284 | fz_output *out = ((pdf_output_processor*)proc)->out; |
285 | fz_write_string(ctx, out, "ET\n" ); |
286 | } |
287 | |
288 | /* text state */ |
289 | |
290 | static void |
291 | pdf_out_Tc(fz_context *ctx, pdf_processor *proc, float charspace) |
292 | { |
293 | fz_output *out = ((pdf_output_processor*)proc)->out; |
294 | fz_write_printf(ctx, out, "%g Tc\n" , charspace); |
295 | } |
296 | |
297 | static void |
298 | pdf_out_Tw(fz_context *ctx, pdf_processor *proc, float wordspace) |
299 | { |
300 | fz_output *out = ((pdf_output_processor*)proc)->out; |
301 | fz_write_printf(ctx, out, "%g Tw\n" , wordspace); |
302 | } |
303 | |
304 | static void |
305 | pdf_out_Tz(fz_context *ctx, pdf_processor *proc, float scale) |
306 | { |
307 | /* scale is exactly as read from the file. */ |
308 | fz_output *out = ((pdf_output_processor*)proc)->out; |
309 | fz_write_printf(ctx, out, "%g Tz\n" , scale); |
310 | } |
311 | |
312 | static void |
313 | pdf_out_TL(fz_context *ctx, pdf_processor *proc, float leading) |
314 | { |
315 | fz_output *out = ((pdf_output_processor*)proc)->out; |
316 | fz_write_printf(ctx, out, "%g TL\n" , leading); |
317 | } |
318 | |
319 | static void |
320 | pdf_out_Tf(fz_context *ctx, pdf_processor *proc, const char *name, pdf_font_desc *font, float size) |
321 | { |
322 | fz_output *out = ((pdf_output_processor*)proc)->out; |
323 | if (!((pdf_output_processor*)proc)->extgstate) |
324 | { |
325 | fz_write_printf(ctx, out, "%n %g Tf\n" , name, size); |
326 | } |
327 | } |
328 | |
329 | static void |
330 | pdf_out_Tr(fz_context *ctx, pdf_processor *proc, int render) |
331 | { |
332 | fz_output *out = ((pdf_output_processor*)proc)->out; |
333 | fz_write_printf(ctx, out, "%d Tr\n" , render); |
334 | } |
335 | |
336 | static void |
337 | pdf_out_Ts(fz_context *ctx, pdf_processor *proc, float rise) |
338 | { |
339 | fz_output *out = ((pdf_output_processor*)proc)->out; |
340 | fz_write_printf(ctx, out, "%g Ts\n" , rise); |
341 | } |
342 | |
343 | /* text positioning */ |
344 | |
345 | static void |
346 | pdf_out_Td(fz_context *ctx, pdf_processor *proc, float tx, float ty) |
347 | { |
348 | fz_output *out = ((pdf_output_processor*)proc)->out; |
349 | fz_write_printf(ctx, out, "%g %g Td\n" , tx, ty); |
350 | } |
351 | |
352 | static void |
353 | pdf_out_TD(fz_context *ctx, pdf_processor *proc, float tx, float ty) |
354 | { |
355 | fz_output *out = ((pdf_output_processor*)proc)->out; |
356 | fz_write_printf(ctx, out, "%g %g TD\n" , tx, ty); |
357 | } |
358 | |
359 | static void |
360 | pdf_out_Tm(fz_context *ctx, pdf_processor *proc, float a, float b, float c, float d, float e, float f) |
361 | { |
362 | fz_output *out = ((pdf_output_processor*)proc)->out; |
363 | fz_write_printf(ctx, out, "%g %g %g %g %g %g Tm\n" , a, b, c, d, e, f); |
364 | } |
365 | |
366 | static void |
367 | pdf_out_Tstar(fz_context *ctx, pdf_processor *proc) |
368 | { |
369 | fz_output *out = ((pdf_output_processor*)proc)->out; |
370 | fz_write_string(ctx, out, "T*\n" ); |
371 | } |
372 | |
373 | /* text showing */ |
374 | |
375 | static void |
376 | fz_write_pdf_string(fz_context *ctx, fz_output *out, const unsigned char *str, int len) |
377 | { |
378 | int i; |
379 | |
380 | for (i = 0; i < len; ++i) |
381 | if (str[i] < 32 || str[i] >= 127) |
382 | break; |
383 | |
384 | if (i < len) |
385 | { |
386 | fz_write_byte(ctx, out, '<'); |
387 | for (i = 0; i < len; ++i) |
388 | { |
389 | unsigned char c = str[i]; |
390 | fz_write_byte(ctx, out, "0123456789abcdef" [(c>>4)&15]); |
391 | fz_write_byte(ctx, out, "0123456789abcdef" [(c)&15]); |
392 | } |
393 | fz_write_byte(ctx, out, '>'); |
394 | } |
395 | else |
396 | { |
397 | fz_write_byte(ctx, out, '('); |
398 | for (i = 0; i < len; ++i) |
399 | { |
400 | unsigned char c = str[i]; |
401 | if (c == '(' || c == ')' || c == '\\') |
402 | fz_write_byte(ctx, out, '\\'); |
403 | fz_write_byte(ctx, out, c); |
404 | } |
405 | fz_write_byte(ctx, out, ')'); |
406 | } |
407 | } |
408 | |
409 | static void |
410 | pdf_out_TJ(fz_context *ctx, pdf_processor *proc, pdf_obj *array) |
411 | { |
412 | fz_output *out = ((pdf_output_processor*)proc)->out; |
413 | int ahx = ((pdf_output_processor*)proc)->ahxencode; |
414 | pdf_print_obj(ctx, out, array, 1, ahx); |
415 | fz_write_string(ctx, out, " TJ\n" ); |
416 | } |
417 | |
418 | static void |
419 | pdf_out_Tj(fz_context *ctx, pdf_processor *proc, char *str, int len) |
420 | { |
421 | fz_output *out = ((pdf_output_processor*)proc)->out; |
422 | fz_write_pdf_string(ctx, out, (const unsigned char *)str, len); |
423 | fz_write_string(ctx, out, " Tj\n" ); |
424 | } |
425 | |
426 | static void |
427 | pdf_out_squote(fz_context *ctx, pdf_processor *proc, char *str, int len) |
428 | { |
429 | fz_output *out = ((pdf_output_processor*)proc)->out; |
430 | fz_write_pdf_string(ctx, out, (const unsigned char *)str, len); |
431 | fz_write_string(ctx, out, " '\n" ); |
432 | } |
433 | |
434 | static void |
435 | pdf_out_dquote(fz_context *ctx, pdf_processor *proc, float aw, float ac, char *str, int len) |
436 | { |
437 | fz_output *out = ((pdf_output_processor*)proc)->out; |
438 | fz_write_printf(ctx, out, "%g %g " , aw, ac); |
439 | fz_write_pdf_string(ctx, out, (const unsigned char *)str, len); |
440 | fz_write_string(ctx, out, " \"\n" ); |
441 | } |
442 | |
443 | /* type 3 fonts */ |
444 | |
445 | static void |
446 | pdf_out_d0(fz_context *ctx, pdf_processor *proc, float wx, float wy) |
447 | { |
448 | fz_output *out = ((pdf_output_processor*)proc)->out; |
449 | fz_write_printf(ctx, out, "%g %g d0\n" , wx, wy); |
450 | } |
451 | |
452 | static void |
453 | pdf_out_d1(fz_context *ctx, pdf_processor *proc, float wx, float wy, float llx, float lly, float urx, float ury) |
454 | { |
455 | fz_output *out = ((pdf_output_processor*)proc)->out; |
456 | fz_write_printf(ctx, out, "%g %g %g %g %g %g d1\n" , wx, wy, llx, lly, urx, ury); |
457 | } |
458 | |
459 | /* color */ |
460 | |
461 | static void |
462 | pdf_out_CS(fz_context *ctx, pdf_processor *proc, const char *name, fz_colorspace *cs) |
463 | { |
464 | fz_output *out = ((pdf_output_processor*)proc)->out; |
465 | fz_write_printf(ctx, out, "%n CS\n" , name); |
466 | } |
467 | |
468 | static void |
469 | pdf_out_cs(fz_context *ctx, pdf_processor *proc, const char *name, fz_colorspace *cs) |
470 | { |
471 | fz_output *out = ((pdf_output_processor*)proc)->out; |
472 | fz_write_printf(ctx, out, "%n cs\n" , name); |
473 | } |
474 | |
475 | static void |
476 | pdf_out_SC_pattern(fz_context *ctx, pdf_processor *proc, const char *name, pdf_pattern *pat, int n, float *color) |
477 | { |
478 | fz_output *out = ((pdf_output_processor*)proc)->out; |
479 | int i; |
480 | for (i = 0; i < n; ++i) |
481 | fz_write_printf(ctx, out, "%g " , color[i]); |
482 | fz_write_printf(ctx, out, "%n SCN\n" , name); |
483 | } |
484 | |
485 | static void |
486 | pdf_out_sc_pattern(fz_context *ctx, pdf_processor *proc, const char *name, pdf_pattern *pat, int n, float *color) |
487 | { |
488 | fz_output *out = ((pdf_output_processor*)proc)->out; |
489 | int i; |
490 | for (i = 0; i < n; ++i) |
491 | fz_write_printf(ctx, out, "%g " , color[i]); |
492 | fz_write_printf(ctx, out, "%n scn\n" , name); |
493 | } |
494 | |
495 | static void |
496 | pdf_out_SC_shade(fz_context *ctx, pdf_processor *proc, const char *name, fz_shade *shade) |
497 | { |
498 | fz_output *out = ((pdf_output_processor*)proc)->out; |
499 | fz_write_printf(ctx, out, "%n SCN\n" , name); |
500 | } |
501 | |
502 | static void |
503 | pdf_out_sc_shade(fz_context *ctx, pdf_processor *proc, const char *name, fz_shade *shade) |
504 | { |
505 | fz_output *out = ((pdf_output_processor*)proc)->out; |
506 | fz_write_printf(ctx, out, "%n scn\n" , name); |
507 | } |
508 | |
509 | static void |
510 | pdf_out_SC_color(fz_context *ctx, pdf_processor *proc, int n, float *color) |
511 | { |
512 | fz_output *out = ((pdf_output_processor*)proc)->out; |
513 | int i; |
514 | for (i = 0; i < n; ++i) |
515 | fz_write_printf(ctx, out, "%g " , color[i]); |
516 | fz_write_string(ctx, out, "SCN\n" ); |
517 | } |
518 | |
519 | static void |
520 | pdf_out_sc_color(fz_context *ctx, pdf_processor *proc, int n, float *color) |
521 | { |
522 | fz_output *out = ((pdf_output_processor*)proc)->out; |
523 | int i; |
524 | for (i = 0; i < n; ++i) |
525 | fz_write_printf(ctx, out, "%g " , color[i]); |
526 | fz_write_string(ctx, out, "scn\n" ); |
527 | } |
528 | |
529 | static void |
530 | pdf_out_G(fz_context *ctx, pdf_processor *proc, float g) |
531 | { |
532 | fz_output *out = ((pdf_output_processor*)proc)->out; |
533 | fz_write_printf(ctx, out, "%g G\n" , g); |
534 | } |
535 | |
536 | static void |
537 | pdf_out_g(fz_context *ctx, pdf_processor *proc, float g) |
538 | { |
539 | fz_output *out = ((pdf_output_processor*)proc)->out; |
540 | fz_write_printf(ctx, out, "%g g\n" , g); |
541 | } |
542 | |
543 | static void |
544 | pdf_out_RG(fz_context *ctx, pdf_processor *proc, float r, float g, float b) |
545 | { |
546 | fz_output *out = ((pdf_output_processor*)proc)->out; |
547 | fz_write_printf(ctx, out, "%g %g %g RG\n" , r, g, b); |
548 | } |
549 | |
550 | static void |
551 | pdf_out_rg(fz_context *ctx, pdf_processor *proc, float r, float g, float b) |
552 | { |
553 | fz_output *out = ((pdf_output_processor*)proc)->out; |
554 | fz_write_printf(ctx, out, "%g %g %g rg\n" , r, g, b); |
555 | } |
556 | |
557 | static void |
558 | pdf_out_K(fz_context *ctx, pdf_processor *proc, float c, float m, float y, float k) |
559 | { |
560 | fz_output *out = ((pdf_output_processor*)proc)->out; |
561 | fz_write_printf(ctx, out, "%g %g %g %g K\n" , c, m, y, k); |
562 | } |
563 | |
564 | static void |
565 | pdf_out_k(fz_context *ctx, pdf_processor *proc, float c, float m, float y, float k) |
566 | { |
567 | fz_output *out = ((pdf_output_processor*)proc)->out; |
568 | fz_write_printf(ctx, out, "%g %g %g %g k\n" , c, m, y, k); |
569 | } |
570 | |
571 | /* shadings, images, xobjects */ |
572 | |
573 | static void |
574 | pdf_out_BI(fz_context *ctx, pdf_processor *proc, fz_image *img, const char *colorspace) |
575 | { |
576 | fz_output *out = ((pdf_output_processor*)proc)->out; |
577 | int ahx = ((pdf_output_processor*)proc)->ahxencode; |
578 | fz_compressed_buffer *cbuf; |
579 | fz_buffer *buf; |
580 | int i; |
581 | unsigned char *data; |
582 | size_t len; |
583 | |
584 | if (img == NULL) |
585 | return; |
586 | cbuf = fz_compressed_image_buffer(ctx, img); |
587 | if (cbuf == NULL) |
588 | return; |
589 | buf = cbuf->buffer; |
590 | if (buf == NULL) |
591 | return; |
592 | |
593 | fz_write_string(ctx, out, "BI\n" ); |
594 | fz_write_printf(ctx, out, "/W %d\n" , img->w); |
595 | fz_write_printf(ctx, out, "/H %d\n" , img->h); |
596 | fz_write_printf(ctx, out, "/BPC %d\n" , img->bpc); |
597 | if (img->imagemask) |
598 | fz_write_string(ctx, out, "/IM true\n" ); |
599 | else if (img->colorspace == fz_device_gray(ctx)) |
600 | fz_write_string(ctx, out, "/CS/G\n" ); |
601 | else if (img->colorspace == fz_device_rgb(ctx)) |
602 | fz_write_string(ctx, out, "/CS/RGB\n" ); |
603 | else if (img->colorspace == fz_device_cmyk(ctx)) |
604 | fz_write_string(ctx, out, "/CS/CMYK\n" ); |
605 | else if (colorspace) |
606 | fz_write_printf(ctx, out, "/CS%n/n" , colorspace); |
607 | else |
608 | fz_throw(ctx, FZ_ERROR_GENERIC, "BI operator can only show ImageMask, Gray, RGB, or CMYK images" ); |
609 | if (img->interpolate) |
610 | fz_write_string(ctx, out, "/I true\n" ); |
611 | fz_write_string(ctx, out, "/D[" ); |
612 | for (i = 0; i < img->n * 2; ++i) |
613 | { |
614 | if (i > 0) |
615 | fz_write_byte(ctx, out, ' '); |
616 | fz_write_printf(ctx, out, "%g" , img->decode[i]); |
617 | } |
618 | fz_write_string(ctx, out, "]\n" ); |
619 | |
620 | switch (cbuf->params.type) |
621 | { |
622 | default: |
623 | fz_throw(ctx, FZ_ERROR_GENERIC, "unknown compressed buffer type" ); |
624 | break; |
625 | |
626 | case FZ_IMAGE_JPEG: |
627 | fz_write_string(ctx, out, ahx ? "/F[/AHx/DCT]\n" : "/F/DCT\n" ); |
628 | if (cbuf->params.u.jpeg.color_transform != -1) |
629 | fz_write_printf(ctx, out, "/DP<</ColorTransform %d>>\n" , |
630 | cbuf->params.u.jpeg.color_transform); |
631 | break; |
632 | |
633 | case FZ_IMAGE_FAX: |
634 | fz_write_string(ctx, out, ahx ? "/F[/AHx/CCF]\n/DP[null<<\n" : "/F/CCF\n/DP<<\n" ); |
635 | fz_write_printf(ctx, out, "/K %d\n" , cbuf->params.u.fax.k); |
636 | if (cbuf->params.u.fax.columns != 1728) |
637 | fz_write_printf(ctx, out, "/Columns %d\n" , cbuf->params.u.fax.columns); |
638 | if (cbuf->params.u.fax.rows > 0) |
639 | fz_write_printf(ctx, out, "/Rows %d\n" , cbuf->params.u.fax.rows); |
640 | if (cbuf->params.u.fax.end_of_line) |
641 | fz_write_string(ctx, out, "/EndOfLine true\n" ); |
642 | if (cbuf->params.u.fax.encoded_byte_align) |
643 | fz_write_string(ctx, out, "/EncodedByteAlign true\n" ); |
644 | if (!cbuf->params.u.fax.end_of_block) |
645 | fz_write_string(ctx, out, "/EndOfBlock false\n" ); |
646 | if (cbuf->params.u.fax.black_is_1) |
647 | fz_write_string(ctx, out, "/BlackIs1 true\n" ); |
648 | if (cbuf->params.u.fax.damaged_rows_before_error > 0) |
649 | fz_write_printf(ctx, out, "/DamagedRowsBeforeError %d\n" , |
650 | cbuf->params.u.fax.damaged_rows_before_error); |
651 | fz_write_string(ctx, out, ahx ? ">>]\n" : ">>\n" ); |
652 | break; |
653 | |
654 | case FZ_IMAGE_RAW: |
655 | if (ahx) |
656 | fz_write_string(ctx, out, "/F/AHx\n" ); |
657 | break; |
658 | |
659 | case FZ_IMAGE_RLD: |
660 | fz_write_string(ctx, out, ahx ? "/F[/AHx/RL]\n" : "/F/RL\n" ); |
661 | break; |
662 | |
663 | case FZ_IMAGE_FLATE: |
664 | fz_write_string(ctx, out, ahx ? "/F[/AHx/Fl]\n" : "/F/Fl\n" ); |
665 | if (cbuf->params.u.flate.predictor > 1) |
666 | { |
667 | fz_write_string(ctx, out, ahx ? "/DP[null<<\n" : "/DP<<\n" ); |
668 | fz_write_printf(ctx, out, "/Predictor %d\n" , cbuf->params.u.flate.predictor); |
669 | if (cbuf->params.u.flate.columns != 1) |
670 | fz_write_printf(ctx, out, "/Columns %d\n" , cbuf->params.u.flate.columns); |
671 | if (cbuf->params.u.flate.colors != 1) |
672 | fz_write_printf(ctx, out, "/Colors %d\n" , cbuf->params.u.flate.colors); |
673 | if (cbuf->params.u.flate.bpc != 8) |
674 | fz_write_printf(ctx, out, "/BitsPerComponent %d\n" , cbuf->params.u.flate.bpc); |
675 | fz_write_string(ctx, out, ahx ? ">>]\n" : ">>\n" ); |
676 | } |
677 | break; |
678 | |
679 | case FZ_IMAGE_LZW: |
680 | fz_write_string(ctx, out, ahx ? "/F[/AHx/LZW]\n" : "/F/LZW\n" ); |
681 | if (cbuf->params.u.lzw.predictor > 1) |
682 | { |
683 | fz_write_string(ctx, out, ahx ? "/DP[<<null\n" : "/DP<<\n" ); |
684 | fz_write_printf(ctx, out, "/Predictor %d\n" , cbuf->params.u.lzw.predictor); |
685 | if (cbuf->params.u.lzw.columns != 1) |
686 | fz_write_printf(ctx, out, "/Columns %d\n" , cbuf->params.u.lzw.columns); |
687 | if (cbuf->params.u.lzw.colors != 1) |
688 | fz_write_printf(ctx, out, "/Colors %d\n" , cbuf->params.u.lzw.colors); |
689 | if (cbuf->params.u.lzw.bpc != 8) |
690 | fz_write_printf(ctx, out, "/BitsPerComponent %d\n" , cbuf->params.u.lzw.bpc); |
691 | if (cbuf->params.u.lzw.early_change != 1) |
692 | fz_write_printf(ctx, out, "/EarlyChange %d\n" , cbuf->params.u.lzw.early_change); |
693 | fz_write_string(ctx, out, ahx ? ">>]\n" : ">>\n" ); |
694 | } |
695 | break; |
696 | } |
697 | |
698 | fz_write_string(ctx, out, "ID\n" ); |
699 | len = fz_buffer_storage(ctx, buf, &data); |
700 | if (ahx) |
701 | { |
702 | size_t z; |
703 | for (z = 0; z < len; ++z) |
704 | { |
705 | int c = data[z]; |
706 | fz_write_byte(ctx, out, "0123456789abcdef" [(c >> 4) & 0xf]); |
707 | fz_write_byte(ctx, out, "0123456789abcdef" [c & 0xf]); |
708 | if ((z & 31) == 31) |
709 | fz_write_byte(ctx, out, '\n'); |
710 | } |
711 | fz_write_byte(ctx, out, '>'); |
712 | } |
713 | else |
714 | { |
715 | fz_write_data(ctx, out, data, len); |
716 | } |
717 | fz_write_string(ctx, out, "\nEI\n" ); |
718 | } |
719 | |
720 | static void |
721 | pdf_out_sh(fz_context *ctx, pdf_processor *proc, const char *name, fz_shade *shade) |
722 | { |
723 | fz_output *out = ((pdf_output_processor*)proc)->out; |
724 | fz_write_printf(ctx, out, "%n sh\n" , name); |
725 | } |
726 | |
727 | static void |
728 | pdf_out_Do_image(fz_context *ctx, pdf_processor *proc, const char *name, fz_image *image) |
729 | { |
730 | fz_output *out = ((pdf_output_processor*)proc)->out; |
731 | fz_write_printf(ctx, out, "%n Do\n" , name); |
732 | } |
733 | |
734 | static void |
735 | pdf_out_Do_form(fz_context *ctx, pdf_processor *proc, const char *name, pdf_obj *xobj, pdf_obj *page_resources) |
736 | { |
737 | fz_output *out = ((pdf_output_processor*)proc)->out; |
738 | fz_write_printf(ctx, out, "%n Do\n" , name); |
739 | } |
740 | |
741 | /* marked content */ |
742 | |
743 | static void |
744 | pdf_out_MP(fz_context *ctx, pdf_processor *proc, const char *tag) |
745 | { |
746 | fz_output *out = ((pdf_output_processor*)proc)->out; |
747 | fz_write_printf(ctx, out, "%n MP\n" , tag); |
748 | } |
749 | |
750 | static void |
751 | pdf_out_DP(fz_context *ctx, pdf_processor *proc, const char *tag, pdf_obj *raw, pdf_obj *cooked) |
752 | { |
753 | fz_output *out = ((pdf_output_processor*)proc)->out; |
754 | int ahx = ((pdf_output_processor*)proc)->ahxencode; |
755 | fz_write_printf(ctx, out, "%n " , tag); |
756 | pdf_print_obj(ctx, out, raw, 1, ahx); |
757 | fz_write_string(ctx, out, " DP\n" ); |
758 | } |
759 | |
760 | static void |
761 | pdf_out_BMC(fz_context *ctx, pdf_processor *proc, const char *tag) |
762 | { |
763 | fz_output *out = ((pdf_output_processor*)proc)->out; |
764 | fz_write_printf(ctx, out, "%n BMC\n" , tag); |
765 | } |
766 | |
767 | static void |
768 | pdf_out_BDC(fz_context *ctx, pdf_processor *proc, const char *tag, pdf_obj *raw, pdf_obj *cooked) |
769 | { |
770 | fz_output *out = ((pdf_output_processor*)proc)->out; |
771 | int ahx = ((pdf_output_processor*)proc)->ahxencode; |
772 | fz_write_printf(ctx, out, "%n " , tag); |
773 | pdf_print_obj(ctx, out, raw, 1, ahx); |
774 | fz_write_string(ctx, out, " BDC\n" ); |
775 | } |
776 | |
777 | static void |
778 | pdf_out_EMC(fz_context *ctx, pdf_processor *proc) |
779 | { |
780 | fz_output *out = ((pdf_output_processor*)proc)->out; |
781 | fz_write_string(ctx, out, "EMC\n" ); |
782 | } |
783 | |
784 | /* compatibility */ |
785 | |
786 | static void |
787 | pdf_out_BX(fz_context *ctx, pdf_processor *proc) |
788 | { |
789 | fz_output *out = ((pdf_output_processor*)proc)->out; |
790 | fz_write_string(ctx, out, "BX\n" ); |
791 | } |
792 | |
793 | static void |
794 | pdf_out_EX(fz_context *ctx, pdf_processor *proc) |
795 | { |
796 | fz_output *out = ((pdf_output_processor*)proc)->out; |
797 | fz_write_string(ctx, out, "EX\n" ); |
798 | } |
799 | |
800 | static void |
801 | pdf_close_output_processor(fz_context *ctx, pdf_processor *proc) |
802 | { |
803 | fz_output *out = ((pdf_output_processor*)proc)->out; |
804 | fz_close_output(ctx, out); |
805 | } |
806 | |
807 | static void |
808 | pdf_drop_output_processor(fz_context *ctx, pdf_processor *proc) |
809 | { |
810 | fz_output *out = ((pdf_output_processor*)proc)->out; |
811 | fz_drop_output(ctx, out); |
812 | } |
813 | |
814 | /* |
815 | Create an output processor. This |
816 | sends the incoming PDF operator stream to an fz_output stream. |
817 | |
818 | out: The output stream to which operators will be sent. |
819 | |
820 | ahxencode: If 0, then image streams will be send as binary, |
821 | otherwise they will be asciihexencoded. |
822 | */ |
823 | pdf_processor * |
824 | pdf_new_output_processor(fz_context *ctx, fz_output *out, int ahxencode) |
825 | { |
826 | pdf_output_processor *proc = pdf_new_processor(ctx, sizeof *proc); |
827 | { |
828 | proc->super.close_processor = pdf_close_output_processor; |
829 | proc->super.drop_processor = pdf_drop_output_processor; |
830 | |
831 | /* general graphics state */ |
832 | proc->super.op_w = pdf_out_w; |
833 | proc->super.op_j = pdf_out_j; |
834 | proc->super.op_J = pdf_out_J; |
835 | proc->super.op_M = pdf_out_M; |
836 | proc->super.op_d = pdf_out_d; |
837 | proc->super.op_ri = pdf_out_ri; |
838 | proc->super.op_i = pdf_out_i; |
839 | proc->super.op_gs_begin = pdf_out_gs_begin; |
840 | proc->super.op_gs_end = pdf_out_gs_end; |
841 | |
842 | /* transparency graphics state */ |
843 | proc->super.op_gs_BM = NULL; |
844 | proc->super.op_gs_CA = NULL; |
845 | proc->super.op_gs_ca = NULL; |
846 | proc->super.op_gs_SMask = NULL; |
847 | |
848 | /* special graphics state */ |
849 | proc->super.op_q = pdf_out_q; |
850 | proc->super.op_Q = pdf_out_Q; |
851 | proc->super.op_cm = pdf_out_cm; |
852 | |
853 | /* path construction */ |
854 | proc->super.op_m = pdf_out_m; |
855 | proc->super.op_l = pdf_out_l; |
856 | proc->super.op_c = pdf_out_c; |
857 | proc->super.op_v = pdf_out_v; |
858 | proc->super.op_y = pdf_out_y; |
859 | proc->super.op_h = pdf_out_h; |
860 | proc->super.op_re = pdf_out_re; |
861 | |
862 | /* path painting */ |
863 | proc->super.op_S = pdf_out_S; |
864 | proc->super.op_s = pdf_out_s; |
865 | proc->super.op_F = pdf_out_F; |
866 | proc->super.op_f = pdf_out_f; |
867 | proc->super.op_fstar = pdf_out_fstar; |
868 | proc->super.op_B = pdf_out_B; |
869 | proc->super.op_Bstar = pdf_out_Bstar; |
870 | proc->super.op_b = pdf_out_b; |
871 | proc->super.op_bstar = pdf_out_bstar; |
872 | proc->super.op_n = pdf_out_n; |
873 | |
874 | /* clipping paths */ |
875 | proc->super.op_W = pdf_out_W; |
876 | proc->super.op_Wstar = pdf_out_Wstar; |
877 | |
878 | /* text objects */ |
879 | proc->super.op_BT = pdf_out_BT; |
880 | proc->super.op_ET = pdf_out_ET; |
881 | |
882 | /* text state */ |
883 | proc->super.op_Tc = pdf_out_Tc; |
884 | proc->super.op_Tw = pdf_out_Tw; |
885 | proc->super.op_Tz = pdf_out_Tz; |
886 | proc->super.op_TL = pdf_out_TL; |
887 | proc->super.op_Tf = pdf_out_Tf; |
888 | proc->super.op_Tr = pdf_out_Tr; |
889 | proc->super.op_Ts = pdf_out_Ts; |
890 | |
891 | /* text positioning */ |
892 | proc->super.op_Td = pdf_out_Td; |
893 | proc->super.op_TD = pdf_out_TD; |
894 | proc->super.op_Tm = pdf_out_Tm; |
895 | proc->super.op_Tstar = pdf_out_Tstar; |
896 | |
897 | /* text showing */ |
898 | proc->super.op_TJ = pdf_out_TJ; |
899 | proc->super.op_Tj = pdf_out_Tj; |
900 | proc->super.op_squote = pdf_out_squote; |
901 | proc->super.op_dquote = pdf_out_dquote; |
902 | |
903 | /* type 3 fonts */ |
904 | proc->super.op_d0 = pdf_out_d0; |
905 | proc->super.op_d1 = pdf_out_d1; |
906 | |
907 | /* color */ |
908 | proc->super.op_CS = pdf_out_CS; |
909 | proc->super.op_cs = pdf_out_cs; |
910 | proc->super.op_SC_color = pdf_out_SC_color; |
911 | proc->super.op_sc_color = pdf_out_sc_color; |
912 | proc->super.op_SC_pattern = pdf_out_SC_pattern; |
913 | proc->super.op_sc_pattern = pdf_out_sc_pattern; |
914 | proc->super.op_SC_shade = pdf_out_SC_shade; |
915 | proc->super.op_sc_shade = pdf_out_sc_shade; |
916 | |
917 | proc->super.op_G = pdf_out_G; |
918 | proc->super.op_g = pdf_out_g; |
919 | proc->super.op_RG = pdf_out_RG; |
920 | proc->super.op_rg = pdf_out_rg; |
921 | proc->super.op_K = pdf_out_K; |
922 | proc->super.op_k = pdf_out_k; |
923 | |
924 | /* shadings, images, xobjects */ |
925 | proc->super.op_BI = pdf_out_BI; |
926 | proc->super.op_sh = pdf_out_sh; |
927 | proc->super.op_Do_image = pdf_out_Do_image; |
928 | proc->super.op_Do_form = pdf_out_Do_form; |
929 | |
930 | /* marked content */ |
931 | proc->super.op_MP = pdf_out_MP; |
932 | proc->super.op_DP = pdf_out_DP; |
933 | proc->super.op_BMC = pdf_out_BMC; |
934 | proc->super.op_BDC = pdf_out_BDC; |
935 | proc->super.op_EMC = pdf_out_EMC; |
936 | |
937 | /* compatibility */ |
938 | proc->super.op_BX = pdf_out_BX; |
939 | proc->super.op_EX = pdf_out_EX; |
940 | |
941 | /* extgstate */ |
942 | proc->super.op_gs_OP = pdf_out_gs_OP; |
943 | proc->super.op_gs_op = pdf_out_gs_op; |
944 | proc->super.op_gs_OPM = pdf_out_gs_OPM; |
945 | proc->super.op_gs_UseBlackPtComp = pdf_out_gs_UseBlackPtComp; |
946 | } |
947 | |
948 | proc->out = out; |
949 | proc->ahxencode = ahxencode; |
950 | |
951 | return (pdf_processor*)proc; |
952 | } |
953 | |
954 | /* |
955 | Create a buffer processor. This |
956 | collects the incoming PDF operator stream into an fz_buffer. |
957 | |
958 | buffer: The (possibly empty) buffer to which operators will be |
959 | appended. |
960 | |
961 | ahxencode: If 0, then image streams will be send as binary, |
962 | otherwise they will be asciihexencoded. |
963 | */ |
964 | pdf_processor * |
965 | pdf_new_buffer_processor(fz_context *ctx, fz_buffer *buffer, int ahxencode) |
966 | { |
967 | pdf_processor *proc = NULL; |
968 | fz_output *out = fz_new_output_with_buffer(ctx, buffer); |
969 | fz_try(ctx) |
970 | { |
971 | proc = pdf_new_output_processor(ctx, out, ahxencode); |
972 | } |
973 | fz_catch(ctx) |
974 | { |
975 | fz_drop_output(ctx, out); |
976 | fz_rethrow(ctx); |
977 | } |
978 | return proc; |
979 | } |
980 | |