From 7c4844060a313833202b91767a878c1d87c4a61c Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Mon, 3 Mar 2014 18:20:12 +0000 Subject: Add pdf_process for writing operator streams out to a buffer. Using this, we can reconstruct pdf streams out of the process called. This will enable us to do filtering when used in combination with future commits. --- source/pdf/pdf-op-buffer.c | 845 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 845 insertions(+) create mode 100644 source/pdf/pdf-op-buffer.c (limited to 'source/pdf/pdf-op-buffer.c') diff --git a/source/pdf/pdf-op-buffer.c b/source/pdf/pdf-op-buffer.c new file mode 100644 index 00000000..ed7c28aa --- /dev/null +++ b/source/pdf/pdf-op-buffer.c @@ -0,0 +1,845 @@ +#include "pdf-interpret-imp.h" + +typedef struct pdf_buffer_state_s +{ + fz_context *ctx; + fz_buffer *buffer; + fz_output *out; +} +pdf_buffer_state; + +static void +put_hexstring(pdf_csi *csi, fz_output *out) +{ + int i; + + fz_printf(out, "<"); + for (i = 0; i < csi->string_len; i++) + fz_printf(out, "%02x", csi->string[i]); + fz_printf(out, ">"); +} + +static void +put_string(pdf_csi *csi, fz_output *out) +{ + int i; + + for (i=0; i < csi->string_len; i++) + if (csi->string[i] < 32 || csi->string[i] >= 127) + break; + if (i < csi->string_len) + put_hexstring(csi, out); + else + { + fz_printf(out, "("); + for (i = 0; i < csi->string_len; i++) + { + char c = csi->string[i]; + switch (c) + { + case '(': + fz_printf(out, "\\("); + break; + case ')': + fz_printf(out, "\\)"); + break; + case '\\': + fz_printf(out, "\\\\"); + break; + default: + fz_printf(out, "%c", csi->string[i]); + break; + } + } + fz_printf(out, ")"); + } +} + +static void +put_string_or_obj(pdf_csi *csi, fz_output *out) +{ + if (csi->string_len) + put_string(csi, out); + else + pdf_output_obj(out, csi->obj); +} + +static void +pdf_buffer_dquote(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f %f ", csi->stack[0], csi->stack[1]); + put_string_or_obj(csi, state->out); + fz_printf(state->out, " \"\n"); +} + +static void +pdf_buffer_squote(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + put_string_or_obj(csi, state->out); + fz_printf(state->out, " \'\n"); +} + +static void +pdf_buffer_B(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "B\n"); +} + +static void +pdf_buffer_Bstar(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "B*\n"); +} + +static void +pdf_buffer_BDC(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "/%s ", csi->name); + pdf_output_obj(state->out, csi->obj); + fz_printf(state->out, " BDC\n"); +} + +static void +pdf_buffer_BI(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + fz_stream *file = csi->file; + pdf_obj *obj; + int ch; + + obj = pdf_parse_dict(csi->doc, csi->file, &csi->doc->lexbuf.base); + + /* read whitespace after ID keyword */ + ch = fz_read_byte(file); + if (ch == '\r') + if (fz_peek_byte(file) == '\n') + fz_read_byte(file); + + fz_printf(state->out, "BI "); + pdf_output_obj(state->out, obj); + fz_printf(state->out, " ID\n"); + + /* FIXME */ + + fz_printf(state->out, "\nEI\n"); +} + +static void +pdf_buffer_BMC(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "/%s BMC\n", csi->name); +} + +static void +pdf_buffer_BT(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "BT\n"); +} + +static void +pdf_buffer_BX(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "BX\n"); +} + +static void +pdf_buffer_CS(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "/%s CS\n", csi->name); +} + +static void +pdf_buffer_DP(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "/%s ", csi->name); + pdf_output_obj(state->out, csi->obj); + fz_printf(state->out, " DP\n"); +} + +static void +pdf_buffer_EMC(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "EMC\n"); +} + +static void +pdf_buffer_ET(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "ET\n"); +} + +static void +pdf_buffer_EX(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "EX\n"); +} + +static void +pdf_buffer_F(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "F\n"); +} + +static void +pdf_buffer_G(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f G\n", csi->stack[0]); +} + +static void +pdf_buffer_J(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%d J\n", (int)csi->stack[0]); +} + +static void +pdf_buffer_K(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f %f %f %f K\n", csi->stack[0], + csi->stack[1], csi->stack[2], csi->stack[3]); +} + +static void +pdf_buffer_M(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f M\n", csi->stack[0]); +} + +static void +pdf_buffer_MP(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "/%s MP\n", csi->name); +} + +static void +pdf_buffer_Q(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "Q\n"); +} + +static void +pdf_buffer_RG(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f %f %f RG\n", csi->stack[0], csi->stack[1], csi->stack[2]); +} + +static void +pdf_buffer_S(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "S\n"); +} + +static void +pdf_buffer_SC(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + int i; + + for (i = 0; i < csi->top; i++) + fz_printf(state->out, "%f ", csi->stack[i]); + fz_printf(state->out, "SC\n"); +} + +static void +pdf_buffer_SCN(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + int i; + + for (i = 0; i < csi->top; i++) + fz_printf(state->out, "%f ", csi->stack[i]); + if (csi->name[0]) + fz_printf(state->out, "/%s ", csi->name); + fz_printf(state->out, "SCN\n"); +} + +static void +pdf_buffer_Tstar(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "T*\n"); +} + +static void +pdf_buffer_TD(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f %f TD\n", csi->stack[0], csi->stack[1]); +} + +static void +pdf_buffer_TJ(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + pdf_output_obj(state->out, csi->obj); + fz_printf(state->out, " TJ\n"); +} + +static void +pdf_buffer_TL(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f TL\n", csi->stack[0]); +} + +static void +pdf_buffer_Tc(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f Tc\n", csi->stack[0]); +} + +static void +pdf_buffer_Td(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f %f Td\n", csi->stack[0], csi->stack[1]); +} + +static void +pdf_buffer_Tj(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + put_string_or_obj(csi, state->out); + fz_printf(state->out, " Tj\n"); +} + +static void +pdf_buffer_Tm(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f %f %f %f %f %f Tm\n", + csi->stack[0], csi->stack[1], csi->stack[2], + csi->stack[3], csi->stack[4], csi->stack[5]); +} + +static void +pdf_buffer_Tr(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f Tr\n", csi->stack[0]); +} + +static void +pdf_buffer_Ts(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f Ts\n", csi->stack[0]); +} + +static void +pdf_buffer_Tw(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f Tw\n", csi->stack[0]); +} + +static void +pdf_buffer_Tz(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f Tz\n", csi->stack[0]); +} + +static void +pdf_buffer_W(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "W\n"); +} + +static void +pdf_buffer_Wstar(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "W*\n"); +} + +static void +pdf_buffer_b(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "b\n"); +} + +static void +pdf_buffer_bstar(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "b*\n"); +} + +static void +pdf_buffer_c(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f %f %f %f %f %f c\n", + csi->stack[0], csi->stack[1], csi->stack[2], + csi->stack[3], csi->stack[4], csi->stack[5]); +} + +static void +pdf_buffer_cm(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f %f %f %f %f %f cm\n", + csi->stack[0], csi->stack[1], csi->stack[2], + csi->stack[3], csi->stack[4], csi->stack[5]); +} + +static void +pdf_buffer_cs(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "/%s cs\n", csi->name); +} + +static void +pdf_buffer_d(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + pdf_output_obj(state->out, csi->obj); + fz_printf(state->out, " %f d\n", csi->stack[0]); +} + +static void +pdf_buffer_d0(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f %f d0\n", csi->stack[0], csi->stack[1]); +} + +static void +pdf_buffer_d1(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f %f %f %f %f %f d1\n", + csi->stack[0], csi->stack[1], csi->stack[2], + csi->stack[3], csi->stack[4], csi->stack[5]); +} + +static void +pdf_buffer_f(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "f\n"); +} + +static void +pdf_buffer_fstar(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "f*\n"); +} + +static void +pdf_buffer_g(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f g\n", csi->stack[0]); +} + +static void +pdf_buffer_h(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "h\n"); +} + +static void +pdf_buffer_i(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f i\n", csi->stack[0]); +} + +static void +pdf_buffer_j(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%d j\n", (int)csi->stack[0]); +} + +static void +pdf_buffer_k(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f %f %f %f k\n", csi->stack[0], + csi->stack[1], csi->stack[2], csi->stack[3]); +} + +static void +pdf_buffer_l(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f %f l\n", csi->stack[0], csi->stack[1]); +} + +static void +pdf_buffer_m(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f %f m\n", csi->stack[0], csi->stack[1]); +} + +static void +pdf_buffer_n(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "n\n"); +} + +static void +pdf_buffer_q(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "q\n"); +} + +static void +pdf_buffer_re(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f %f %f %f re\n", csi->stack[0], + csi->stack[1], csi->stack[2], csi->stack[3]); +} + +static void +pdf_buffer_rg(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f %f %f rg\n", + csi->stack[0], csi->stack[1], csi->stack[2]); +} + +static void +pdf_buffer_ri(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "/%s ri\n", csi->name); +} + +static void +pdf_buffer_s(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "s\n"); +} + +static void +pdf_buffer_sc(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + int i; + + for (i = 0; i < csi->top; i++) + fz_printf(state->out, "%f ", csi->stack[i]); + fz_printf(state->out, "sc\n"); +} + +static void +pdf_buffer_scn(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + int i; + + for (i = 0; i < csi->top; i++) + fz_printf(state->out, "%f ", csi->stack[i]); + if (csi->name[0]) + fz_printf(state->out, "/%s ", csi->name); + fz_printf(state->out, "scn\n"); +} + +static void +pdf_buffer_v(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f %f %f %f v\n", csi->stack[0], + csi->stack[1], csi->stack[2], csi->stack[3]); +} + +static void +pdf_buffer_w(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f w\n", csi->stack[0]); +} + +static void +pdf_buffer_y(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "%f %f %f %f y\n", csi->stack[0], + csi->stack[1], csi->stack[2], csi->stack[3]); +} + +static void +pdf_buffer_Do(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "/%s Do\n", csi->name); +} + +static void +pdf_buffer_Tf(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "/%s %f Tf\n", csi->name, csi->stack[0]); +} + +static void +pdf_buffer_gs(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "/%s gs\n", csi->name); +} + +static void +pdf_buffer_sh(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + + fz_printf(state->out, "/%s sh\n", csi->name); +} + +static void +free_processor_buffer(pdf_csi *csi, void *state_) +{ + pdf_buffer_state *state = (pdf_buffer_state *)state_; + fz_context *ctx = state->ctx; + + fz_close_output(state->out); + fz_free(ctx, state); +} + +static void +process_annot(pdf_csi *csi, void *state, pdf_obj *resources, pdf_annot *annot) +{ + fz_context *ctx = csi->doc->ctx; + pdf_xobject *xobj = annot->ap; + + /* Avoid infinite recursion */ + if (xobj == NULL || pdf_mark_obj(xobj->me)) + return; + + fz_try(ctx) + { + if (xobj->resources) + resources = xobj->resources; + + pdf_process_contents_object(csi, resources, xobj->contents); + } + fz_always(ctx) + { + pdf_unmark_obj(xobj->me); + } + fz_catch(ctx) + { + fz_rethrow(ctx); + } +} + +static void +process_stream(pdf_csi *csi, void *state, pdf_lexbuf *buf) +{ + pdf_process_stream(csi, buf); +} + +static void +process_contents(pdf_csi *csi, void *state, pdf_obj *resources, pdf_obj *contents) +{ + pdf_process_contents_object(csi, resources, contents); +} + +static const pdf_processor pdf_processor_buffer = +{ + { + pdf_buffer_dquote, + pdf_buffer_squote, + pdf_buffer_B, + pdf_buffer_Bstar, + pdf_buffer_BDC, + pdf_buffer_BI, + pdf_buffer_BMC, + pdf_buffer_BT, + pdf_buffer_BX, + pdf_buffer_CS, + pdf_buffer_DP, + pdf_buffer_EMC, + pdf_buffer_ET, + pdf_buffer_EX, + pdf_buffer_F, + pdf_buffer_G, + pdf_buffer_J, + pdf_buffer_K, + pdf_buffer_M, + pdf_buffer_MP, + pdf_buffer_Q, + pdf_buffer_RG, + pdf_buffer_S, + pdf_buffer_SC, + pdf_buffer_SCN, + pdf_buffer_Tstar, + pdf_buffer_TD, + pdf_buffer_TJ, + pdf_buffer_TL, + pdf_buffer_Tc, + pdf_buffer_Td, + pdf_buffer_Tj, + pdf_buffer_Tm, + pdf_buffer_Tr, + pdf_buffer_Ts, + pdf_buffer_Tw, + pdf_buffer_Tz, + pdf_buffer_W, + pdf_buffer_Wstar, + pdf_buffer_b, + pdf_buffer_bstar, + pdf_buffer_c, + pdf_buffer_cm, + pdf_buffer_cs, + pdf_buffer_d, + pdf_buffer_d0, + pdf_buffer_d1, + pdf_buffer_f, + pdf_buffer_fstar, + pdf_buffer_g, + pdf_buffer_h, + pdf_buffer_i, + pdf_buffer_j, + pdf_buffer_k, + pdf_buffer_l, + pdf_buffer_m, + pdf_buffer_n, + pdf_buffer_q, + pdf_buffer_re, + pdf_buffer_rg, + pdf_buffer_ri, + pdf_buffer_s, + pdf_buffer_sc, + pdf_buffer_scn, + pdf_buffer_v, + pdf_buffer_w, + pdf_buffer_y, + pdf_buffer_Do, + pdf_buffer_Tf, + pdf_buffer_gs, + pdf_buffer_sh, + free_processor_buffer + }, + process_annot, + process_stream, + process_contents +}; + +pdf_process *pdf_process_buffer(pdf_process *process, fz_context *ctx, fz_buffer *buffer) +{ + fz_output *out = fz_new_output_with_buffer(ctx, buffer); + pdf_buffer_state *p = NULL; + + fz_var(p); + + fz_try(ctx) + { + p = fz_malloc_struct(ctx, pdf_buffer_state); + p->buffer = buffer; + p->out = out; + p->ctx = ctx; + } + fz_catch(ctx) + { + fz_close_output(out); + fz_rethrow(ctx); + } + + process->state = p; + process->processor = &pdf_processor_buffer; + return process; +} -- cgit v1.2.3