diff options
-rw-r--r-- | fitz/fitz-internal.h | 7 | ||||
-rw-r--r-- | fitz/fitz.h | 2 | ||||
-rw-r--r-- | fitz/stm_buffer.c | 15 | ||||
-rw-r--r-- | pdf/mupdf-internal.h | 8 | ||||
-rw-r--r-- | pdf/mupdf.h | 9 | ||||
-rw-r--r-- | pdf/pdf_lex.c | 52 | ||||
-rw-r--r-- | pdf/pdf_object.c | 179 | ||||
-rw-r--r-- | pdf/pdf_stream.c | 2 | ||||
-rw-r--r-- | pdf/pdf_xobject.c | 120 | ||||
-rw-r--r-- | pdf/pdf_xref.c | 14 |
10 files changed, 405 insertions, 3 deletions
diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h index 05d7b52f..2f7f8041 100644 --- a/fitz/fitz-internal.h +++ b/fitz/fitz-internal.h @@ -419,6 +419,13 @@ void fz_write_buffer_bits(fz_context *ctx, fz_buffer *buf, int val, int bits); void fz_write_buffer_pad(fz_context *ctx, fz_buffer *buf); +/* + fz_buffer_printf: print formatted to a buffer. The buffer will + grow, but the caller must ensure that no more than 256 bytes are + added to the buffer per call. +*/ +void fz_buffer_printf(fz_context *ctx, fz_buffer *buffer, char *fmt, ...); + struct fz_stream_s { fz_context *ctx; diff --git a/fitz/fitz.h b/fitz/fitz.h index ee00b2ed..a66976af 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -403,7 +403,7 @@ void *fz_calloc(fz_context *ctx, unsigned int count, unsigned int size); exception on failure to allocate. */ #define fz_malloc_struct(CTX, STRUCT) \ - Memento_label(fz_calloc(CTX,1,sizeof(STRUCT)), #STRUCT) + ((STRUCT *)Memento_label(fz_calloc(CTX,1,sizeof(STRUCT)), #STRUCT)) /* fz_malloc_array: Allocate a block of (non zeroed) memory (with diff --git a/fitz/stm_buffer.c b/fitz/stm_buffer.c index 58539bf8..d14b738f 100644 --- a/fitz/stm_buffer.c +++ b/fitz/stm_buffer.c @@ -159,3 +159,18 @@ void fz_write_buffer_pad(fz_context *ctx, fz_buffer *buf) { buf->unused_bits = 0; } + +void +fz_buffer_printf(fz_context *ctx, fz_buffer *buffer, char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + + /* Caller guarantees not to generate more than 256 bytes per call */ + while(buffer->cap - buffer->len < 256) + fz_grow_buffer(ctx, buffer); + + buffer->len += vsprintf(buffer->data + buffer->len, fmt, args); + + va_end(args); +} diff --git a/pdf/mupdf-internal.h b/pdf/mupdf-internal.h index aa4334b7..b178494c 100644 --- a/pdf/mupdf-internal.h +++ b/pdf/mupdf-internal.h @@ -135,6 +135,11 @@ pdf_obj *pdf_parse_stm_obj(pdf_document *doc, fz_stream *f, pdf_lexbuf *buf); pdf_obj *pdf_parse_ind_obj(pdf_document *doc, fz_stream *f, pdf_lexbuf *buf, int *num, int *gen, int *stm_ofs); /* + pdf_print_token: print a lexed token to a buffer, growing if necessary +*/ +void pdf_print_token(fz_context *ctx, fz_buffer *buf, int tok, pdf_lexbuf *lex); + +/* * xref and object / stream api */ @@ -296,8 +301,11 @@ struct pdf_xobject_s }; pdf_xobject *pdf_load_xobject(pdf_document *doc, pdf_obj *obj); +pdf_obj *pdf_new_xobject(pdf_document *doc, fz_rect *bbox, fz_matrix *mat); pdf_xobject *pdf_keep_xobject(fz_context *ctx, pdf_xobject *xobj); void pdf_drop_xobject(fz_context *ctx, pdf_xobject *xobj); +void pdf_xobject_set_contents(pdf_document *xref, pdf_xobject *from, fz_buffer *buffer); + /* * CMap diff --git a/pdf/mupdf.h b/pdf/mupdf.h index bda0e2fa..10cc6f08 100644 --- a/pdf/mupdf.h +++ b/pdf/mupdf.h @@ -22,6 +22,8 @@ pdf_obj *pdf_new_string(fz_context *ctx, char *str, int len); pdf_obj *pdf_new_indirect(fz_context *ctx, int num, int gen, void *doc); pdf_obj *pdf_new_array(fz_context *ctx, int initialcap); pdf_obj *pdf_new_dict(fz_context *ctx, int initialcap); +pdf_obj *pdf_new_rect(fz_context *ctx, fz_rect *rect); +pdf_obj *pdf_new_matrix(fz_context *ctx, fz_matrix *mtx); pdf_obj *pdf_copy_array(fz_context *ctx, pdf_obj *array); pdf_obj *pdf_copy_dict(fz_context *ctx, pdf_obj *dict); @@ -70,9 +72,11 @@ pdf_obj *pdf_dict_get_key(pdf_obj *dict, int idx); pdf_obj *pdf_dict_get_val(pdf_obj *dict, int idx); pdf_obj *pdf_dict_get(pdf_obj *dict, pdf_obj *key); pdf_obj *pdf_dict_gets(pdf_obj *dict, char *key); +pdf_obj *pdf_dict_getp(pdf_obj *dict, char *key); pdf_obj *pdf_dict_getsa(pdf_obj *dict, char *key, char *abbrev); void pdf_dict_put(pdf_obj *dict, pdf_obj *key, pdf_obj *val); void pdf_dict_puts(pdf_obj *dict, char *key, pdf_obj *val); +void pdf_dict_putp(pdf_obj *dict, char *key, pdf_obj *val); void pdf_dict_del(pdf_obj *dict, pdf_obj *key); void pdf_dict_dels(pdf_obj *dict, char *key); void pdf_sort_dict(pdf_obj *dict); @@ -118,6 +122,11 @@ void pdf_delete_object(pdf_document *xref, int num); void pdf_update_object(pdf_document *xref, int num, pdf_obj *obj); /* + pdf_get_stream: Return the contents for object in xref table +*/ +fz_buffer *pdf_get_stream(pdf_document *xref, int num); + +/* pdf_update_stream: Replace stream contents for object in xref table with the passed in buffer. The buffer contents must match the /Filter setting. diff --git a/pdf/pdf_lex.c b/pdf/pdf_lex.c index 6774167a..c6ab6604 100644 --- a/pdf/pdf_lex.c +++ b/pdf/pdf_lex.c @@ -461,3 +461,55 @@ pdf_lex(fz_stream *f, pdf_lexbuf *buf) } } } + +void pdf_print_token(fz_context *ctx, fz_buffer *fzbuf, int tok, pdf_lexbuf *buf) +{ + switch(tok) + { + case PDF_TOK_NAME: + fz_buffer_printf(ctx, fzbuf, "/%s", buf->scratch); + break; + case PDF_TOK_STRING: + { + int i; + fz_buffer_printf(ctx, fzbuf, "<"); + for (i = 0; i < buf->len; i++) + fz_buffer_printf(ctx, fzbuf, "%02X", buf->scratch[i]); + fz_buffer_printf(ctx, fzbuf, ">"); + } + break; + case PDF_TOK_OPEN_DICT: + fz_buffer_printf(ctx, fzbuf, "<<"); + break; + case PDF_TOK_CLOSE_DICT: + fz_buffer_printf(ctx, fzbuf, ">>"); + break; + case PDF_TOK_OPEN_ARRAY: + fz_buffer_printf(ctx, fzbuf, "["); + break; + case PDF_TOK_CLOSE_ARRAY: + fz_buffer_printf(ctx, fzbuf, "]"); + break; + case PDF_TOK_OPEN_BRACE: + fz_buffer_printf(ctx, fzbuf, "{"); + break; + case PDF_TOK_CLOSE_BRACE: + fz_buffer_printf(ctx, fzbuf, "}"); + break; + case PDF_TOK_INT: + fz_buffer_printf(ctx, fzbuf, "%d", buf->i); + break; + case PDF_TOK_REAL: + { + char sbuf[256]; + sprintf(sbuf, "%g", buf->f); + if (strchr(sbuf, 'e')) /* bad news! */ + sprintf(sbuf, fabsf(buf->f) > 1 ? "%1.1f" : "%1.8f", buf->f); + fz_buffer_printf(ctx, fzbuf, "%s", sbuf); + } + break; + default: + fz_buffer_printf(ctx, fzbuf, "%s", buf->scratch); + break; + } +} diff --git a/pdf/pdf_object.c b/pdf/pdf_object.c index cc5cc662..60f10a54 100644 --- a/pdf/pdf_object.c +++ b/pdf/pdf_object.c @@ -567,6 +567,98 @@ pdf_array_contains(pdf_obj *arr, pdf_obj *obj) return 0; } +pdf_obj *pdf_new_rect(fz_context *ctx, fz_rect *rect) +{ + pdf_obj *arr = NULL; + pdf_obj *item = NULL; + + fz_var(arr); + fz_var(item); + fz_try(ctx) + { + arr = pdf_new_array(ctx, 4); + + item = pdf_new_real(ctx, rect->x0); + pdf_array_put(arr, 0, item); + pdf_drop_obj(item); + item = NULL; + + item = pdf_new_real(ctx, rect->y0); + pdf_array_put(arr, 1, item); + pdf_drop_obj(item); + item = NULL; + + item = pdf_new_real(ctx, rect->x1 - rect->x0); + pdf_array_put(arr, 2, item); + pdf_drop_obj(item); + item = NULL; + + item = pdf_new_real(ctx, rect->y1 - rect->y0); + pdf_array_put(arr, 3, item); + pdf_drop_obj(item); + item = NULL; + } + fz_catch(ctx) + { + pdf_drop_obj(item); + pdf_drop_obj(arr); + fz_rethrow(ctx); + } + + return arr; +} + +pdf_obj *pdf_new_matrix(fz_context *ctx, fz_matrix *mtx) +{ + pdf_obj *arr = NULL; + pdf_obj *item = NULL; + + fz_var(arr); + fz_var(item); + fz_try(ctx) + { + arr = pdf_new_array(ctx, 6); + + item = pdf_new_real(ctx, mtx->a); + pdf_array_put(arr, 0, item); + pdf_drop_obj(item); + item = NULL; + + item = pdf_new_real(ctx, mtx->b); + pdf_array_put(arr, 1, item); + pdf_drop_obj(item); + item = NULL; + + item = pdf_new_real(ctx, mtx->c); + pdf_array_put(arr, 2, item); + pdf_drop_obj(item); + item = NULL; + + item = pdf_new_real(ctx, mtx->d); + pdf_array_put(arr, 3, item); + pdf_drop_obj(item); + item = NULL; + + item = pdf_new_real(ctx, mtx->e); + pdf_array_put(arr, 4, item); + pdf_drop_obj(item); + item = NULL; + + item = pdf_new_real(ctx, mtx->f); + pdf_array_put(arr, 5, item); + pdf_drop_obj(item); + item = NULL; + } + fz_catch(ctx) + { + pdf_drop_obj(item); + pdf_drop_obj(arr); + fz_rethrow(ctx); + } + + return arr; +} + /* dicts may only have names as keys! */ static int keyvalcmp(const void *ap, const void *bp) @@ -743,6 +835,36 @@ pdf_dict_gets(pdf_obj *obj, char *key) } pdf_obj * +pdf_dict_getp(pdf_obj *obj, char *keys) +{ + char buf[256]; + char *k, *e; + + if (strlen(keys)+1 > 256) + fz_throw(obj->ctx, "buffer overflow in pdf_dict_getp"); + + strcpy(buf, keys); + + e = buf; + while (*e && obj) + { + k = e; + while (*e != '/' && *e != '\0') + e++; + + if (*e == '/') + { + *e = '\0'; + e++; + } + + obj = pdf_dict_gets(obj, k); + } + + return obj; +} + +pdf_obj * pdf_dict_get(pdf_obj *obj, pdf_obj *key) { if (!key || key->kind != PDF_NAME) @@ -829,6 +951,63 @@ pdf_dict_puts(pdf_obj *obj, char *key, pdf_obj *val) } void +pdf_dict_putp(pdf_obj *obj, char *keys, pdf_obj *val) +{ + fz_context *ctx = obj->ctx; + char buf[256]; + char *k, *e; + pdf_obj *cobj = NULL; + + if (strlen(keys)+1 > 256) + fz_throw(obj->ctx, "buffer overflow in pdf_dict_getp"); + + strcpy(buf, keys); + + e = buf; + while (*e) + { + k = e; + while (*e != '/' && *e != '\0') + e++; + + if (*e == '/') + { + *e = '\0'; + e++; + } + + if (*e) + { + /* Not the last key in the key path. Create subdict if not already there. */ + cobj = pdf_dict_gets(obj, k); + if (cobj == NULL) + { + cobj = pdf_new_dict(ctx, 1); + fz_try(ctx) + { + pdf_dict_puts(obj, k, cobj); + } + fz_always(ctx) + { + pdf_drop_obj(cobj); + } + fz_catch(ctx) + { + fz_rethrow(ctx); + } + } + /* Move to subdict */ + obj = cobj; + } + else + { + /* Last key. Use it to store the value */ + pdf_dict_puts(obj, k, val); + } + } +} + +void pdf_dict_dels(pdf_obj *obj, char *key) { RESOLVE(obj); diff --git a/pdf/pdf_stream.c b/pdf/pdf_stream.c index fcf9acdc..829210ea 100644 --- a/pdf/pdf_stream.c +++ b/pdf/pdf_stream.c @@ -358,7 +358,7 @@ pdf_open_image_stream(pdf_document *xref, int num, int gen, int orig_num, int or pdf_cache_object(xref, num, gen); /* RJW: "cannot load stream object (%d %d R)", num, gen */ - if (x->stm_ofs == 0) + if (x->stm_ofs == 0 && x->stm_buf == NULL) fz_throw(xref->ctx, "object is not a stream"); return pdf_open_filter(xref->file, xref, x->obj, orig_num, orig_gen, x->stm_ofs, params); diff --git a/pdf/pdf_xobject.c b/pdf/pdf_xobject.c index 1de0b20e..88ab5a01 100644 --- a/pdf/pdf_xobject.c +++ b/pdf/pdf_xobject.c @@ -23,7 +23,6 @@ pdf_free_xobject_imp(fz_context *ctx, fz_storable *xobj_) if (xobj->resources) pdf_drop_obj(xobj->resources); if (xobj->contents) - //fz_drop_buffer(ctx, xobj->contents); pdf_drop_obj(xobj->contents); pdf_drop_obj(xobj->me); fz_free(ctx, xobj); @@ -111,3 +110,122 @@ pdf_load_xobject(pdf_document *xref, pdf_obj *dict) return form; } + +pdf_obj * +pdf_new_xobject(pdf_document *xref, fz_rect *bbox, fz_matrix *mat) +{ + int idict_num; + pdf_obj *idict = NULL; + pdf_obj *dict = NULL; + pdf_xobject *form = NULL; + pdf_obj *obj = NULL; + pdf_obj *res = NULL; + pdf_obj *procset = NULL; + fz_context *ctx = xref->ctx; + + fz_var(idict); + fz_var(dict); + fz_var(form); + fz_var(obj); + fz_var(res); + fz_var(procset); + fz_try(ctx) + { + dict = pdf_new_dict(ctx, 0); + + obj = pdf_new_rect(ctx, bbox); + pdf_dict_puts(dict, "BBox", obj); + pdf_drop_obj(obj); + obj = NULL; + + obj = pdf_new_int(ctx, 1); + pdf_dict_puts(dict, "FormType", obj); + pdf_drop_obj(obj); + obj = NULL; + + obj = pdf_new_int(ctx, 0); + pdf_dict_puts(dict, "Length", obj); + pdf_drop_obj(obj); + obj = NULL; + + obj = pdf_new_matrix(ctx, mat); + pdf_dict_puts(dict, "Matrix", obj); + pdf_drop_obj(obj); + obj = NULL; + + res = pdf_new_dict(ctx, 0); + procset = pdf_new_array(ctx, 2); + obj = fz_new_name(ctx, "PDF"); + pdf_array_put(procset, 0, obj); + pdf_drop_obj(obj); + obj = NULL; + obj = fz_new_name(ctx, "Text"); + pdf_array_put(procset, 1, obj); + pdf_drop_obj(obj); + obj = NULL; + pdf_dict_puts(res, "ProcSet", procset); + pdf_drop_obj(procset); + procset = NULL; + pdf_dict_puts(dict, "Resources", res); + + obj = fz_new_name(ctx, "Form"); + pdf_dict_puts(dict, "Subtype", obj); + pdf_drop_obj(obj); + obj = NULL; + + obj = fz_new_name(ctx, "XObject"); + pdf_dict_puts(dict, "Type", obj); + pdf_drop_obj(obj); + obj = NULL; + + form = fz_malloc_struct(ctx, pdf_xobject); + FZ_INIT_STORABLE(form, 1, pdf_free_xobject_imp); + form->resources = NULL; + form->contents = NULL; + form->colorspace = NULL; + form->me = NULL; + + form->bbox = *bbox; + + form->matrix = fz_identity; + + form->isolated = 0; + form->knockout = 0; + form->transparency = 0; + + form->resources = res; + res = NULL; + + idict_num = pdf_create_object(xref); + pdf_update_object(xref, idict_num, dict); + idict = pdf_new_indirect(ctx, idict_num, 0, xref); + pdf_drop_obj(dict); + dict = NULL; + + pdf_store_item(ctx, idict, form, pdf_xobject_size(form)); + + form->contents = pdf_keep_obj(idict); + form->me = pdf_keep_obj(idict); + + pdf_drop_xobject(ctx, form); + form = NULL; + } + fz_catch(ctx) + { + pdf_drop_obj(procset); + pdf_drop_obj(res); + pdf_drop_obj(obj); + pdf_drop_obj(dict); + pdf_drop_obj(idict); + pdf_drop_xobject(ctx, form); + fz_throw(ctx, "failed to create xobject)"); + } + + return idict; +} + +void pdf_xobject_set_contents(pdf_document *xref, pdf_xobject *form, fz_buffer *buffer) +{ + pdf_dict_dels(form->contents, "Filter"); + pdf_update_stream(xref, pdf_to_num(form->contents), buffer); +} diff --git a/pdf/pdf_xref.c b/pdf/pdf_xref.c index 9b8a3ee8..af72bc09 100644 --- a/pdf/pdf_xref.c +++ b/pdf/pdf_xref.c @@ -1135,6 +1135,20 @@ pdf_update_object(pdf_document *xref, int num, pdf_obj *newobj) x->ofs = 0; x->obj = pdf_keep_obj(newobj); } + +fz_buffer * +pdf_get_stream(pdf_document *xref, int num) +{ + pdf_xref_entry *x; + + if (num < 0 || num >= xref->len) + fz_throw(xref->ctx, "object out of range (%d 0 R); xref size %d", num, xref->len); + + x = &xref->table[num]; + + return x->stm_buf; +} + void pdf_update_stream(pdf_document *xref, int num, fz_buffer *newbuf) { |