summaryrefslogtreecommitdiff
path: root/pdf
diff options
context:
space:
mode:
authorPaul Gardiner <paul@glidos.net>2012-05-31 16:38:54 +0100
committerPaul Gardiner <paul@glidos.net>2012-05-31 16:38:54 +0100
commit09f4fac813c208229ba2d33334db2f84be679d58 (patch)
treedfe1e8bb8ea618692fa6d754312bad9ac9176a31 /pdf
parentae62fb9e522a55ce2390dd20999b4a67392940e0 (diff)
downloadmupdf-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.h8
-rw-r--r--pdf/mupdf.h9
-rw-r--r--pdf/pdf_lex.c52
-rw-r--r--pdf/pdf_object.c179
-rw-r--r--pdf/pdf_stream.c2
-rw-r--r--pdf/pdf_xobject.c120
-rw-r--r--pdf/pdf_xref.c14
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)
{