1#include "mupdf/fitz.h"
2#include "mupdf/pdf.h"
3
4typedef struct pdf_output_processor_s pdf_output_processor;
5
6struct 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
16static void
17pdf_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
24static void
25pdf_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
32static void
33pdf_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
40static void
41pdf_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
48static void
49pdf_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
60static void
61pdf_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
68static void
69pdf_out_gs_OP(fz_context *ctx, pdf_processor *proc, int b)
70{
71}
72
73static void
74pdf_out_gs_op(fz_context *ctx, pdf_processor *proc, int b)
75{
76}
77
78static void
79pdf_out_gs_OPM(fz_context *ctx, pdf_processor *proc, int i)
80{
81}
82
83static void
84pdf_out_gs_UseBlackPtComp(fz_context *ctx, pdf_processor *proc, pdf_obj *name)
85{
86}
87
88static void
89pdf_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
96static void
97pdf_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
104static void
105pdf_out_gs_end(fz_context *ctx, pdf_processor *proc)
106{
107 ((pdf_output_processor*)proc)->extgstate = 0;
108}
109
110/* special graphics state */
111
112static void
113pdf_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
119static void
120pdf_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
126static void
127pdf_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
135static void
136pdf_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
142static void
143pdf_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
149static void
150pdf_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
156static void
157pdf_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
163static void
164pdf_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
170static void
171pdf_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
177static void
178pdf_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
186static void
187pdf_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
193static void
194pdf_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
200static void
201pdf_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
207static void
208pdf_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
214static void
215pdf_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
221static void
222pdf_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
228static void
229pdf_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
235static void
236pdf_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
242static void
243pdf_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
249static void
250pdf_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
258static void
259pdf_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
265static void
266pdf_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
274static void
275pdf_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
281static void
282pdf_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
290static void
291pdf_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
297static void
298pdf_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
304static void
305pdf_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
312static void
313pdf_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
319static void
320pdf_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
329static void
330pdf_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
336static void
337pdf_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
345static void
346pdf_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
352static void
353pdf_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
359static void
360pdf_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
366static void
367pdf_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
375static void
376fz_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
409static void
410pdf_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
418static void
419pdf_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
426static void
427pdf_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
434static void
435pdf_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
445static void
446pdf_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
452static void
453pdf_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
461static void
462pdf_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
468static void
469pdf_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
475static void
476pdf_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
485static void
486pdf_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
495static void
496pdf_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
502static void
503pdf_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
509static void
510pdf_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
519static void
520pdf_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
529static void
530pdf_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
536static void
537pdf_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
543static void
544pdf_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
550static void
551pdf_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
557static void
558pdf_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
564static void
565pdf_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
573static void
574pdf_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
720static void
721pdf_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
727static void
728pdf_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
734static void
735pdf_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
743static void
744pdf_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
750static void
751pdf_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
760static void
761pdf_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
767static void
768pdf_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
777static void
778pdf_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
786static void
787pdf_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
793static void
794pdf_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
800static void
801pdf_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
807static void
808pdf_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*/
823pdf_processor *
824pdf_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*/
964pdf_processor *
965pdf_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