diff options
author | Paul Gardiner <paul@glidos.net> | 2012-05-31 16:38:54 +0100 |
---|---|---|
committer | Paul Gardiner <paul@glidos.net> | 2012-05-31 16:38:54 +0100 |
commit | 09f4fac813c208229ba2d33334db2f84be679d58 (patch) | |
tree | dfe1e8bb8ea618692fa6d754312bad9ac9176a31 /pdf | |
parent | ae62fb9e522a55ce2390dd20999b4a67392940e0 (diff) | |
download | mupdf-09f4fac813c208229ba2d33334db2f84be679d58.tar.xz |
A few general utility functions added for the sake of the forms work
Diffstat (limited to 'pdf')
-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 |
7 files changed, 382 insertions, 2 deletions
diff --git a/pdf/mupdf-internal.h b/pdf/mupdf-internal.h index 9a2676f7..508973bd 100644 --- a/pdf/mupdf-internal.h +++ b/pdf/mupdf-internal.h @@ -134,6 +134,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 */ @@ -294,8 +299,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 de32fb5f..2d93b793 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 fz_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 2a5e6d78..3fb48019 100644 --- a/pdf/pdf_object.c +++ b/pdf/pdf_object.c @@ -560,6 +560,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) @@ -736,6 +828,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) @@ -819,6 +941,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 e312006c..89d94004 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 61c4358a..779db03b 100644 --- a/pdf/pdf_xref.c +++ b/pdf/pdf_xref.c @@ -1126,6 +1126,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) { |