summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fitz/fitz-internal.h5
-rw-r--r--fitz/fitz.h2
-rw-r--r--fitz/stm_buffer.c20
-rw-r--r--pdf/base_object.c88
-rw-r--r--pdf/mupdf-internal.h8
-rw-r--r--pdf/mupdf.h2
-rw-r--r--pdf/pdf_lex.c52
-rw-r--r--pdf/pdf_xobject.c115
-rw-r--r--pdf/pdf_xref.c12
9 files changed, 303 insertions, 1 deletions
diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h
index bd19886c..97bbfa5c 100644
--- a/fitz/fitz-internal.h
+++ b/fitz/fitz-internal.h
@@ -410,6 +410,11 @@ void fz_grow_buffer(fz_context *ctx, fz_buffer *buf);
*/
void fz_trim_buffer(fz_context *ctx, fz_buffer *buf);
+/*
+ fz_buffer_printf: print formatted to a buffer, growing if necessary
+*/
+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 04215c71..286aee55 100644
--- a/fitz/fitz.h
+++ b/fitz/fitz.h
@@ -377,7 +377,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 4be0165a..9b7a542c 100644
--- a/fitz/stm_buffer.c
+++ b/fitz/stm_buffer.c
@@ -78,3 +78,23 @@ fz_buffer_storage(fz_context *ctx, fz_buffer *buf, unsigned char **datap)
*datap = (buf ? buf->data : NULL);
return (buf ? buf->len : 0);
}
+
+void
+fz_buffer_printf(fz_context *ctx, fz_buffer *buffer, char *fmt, ...)
+{
+ int count;
+ int done = 0;
+ va_list args;
+ va_start(args, fmt);
+
+ while(!done)
+ {
+ count = vsnprintf(buffer->data + buffer->len, buffer->cap - buffer->len, fmt, args);
+ done = (count >= 0 && count < buffer->cap - buffer->len);
+ if (!done)
+ fz_grow_buffer(ctx, buffer);
+ }
+
+ buffer->len += count;
+ va_end(args);
+}
diff --git a/pdf/base_object.c b/pdf/base_object.c
index 97cb97cc..fbc40817 100644
--- a/pdf/base_object.c
+++ b/pdf/base_object.c
@@ -561,6 +561,94 @@ 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_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_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)
diff --git a/pdf/mupdf-internal.h b/pdf/mupdf-internal.h
index 3e4a4729..a66871dd 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
*/
@@ -203,6 +208,7 @@ void pdf_repair_xref(pdf_document *doc, pdf_lexbuf *buf);
void pdf_repair_obj_stms(pdf_document *doc);
void pdf_print_xref(pdf_document *);
void pdf_resize_xref(pdf_document *doc, int newcap);
+pdf_obj *pdf_new_stream_indirection(pdf_document *doc, pdf_obj *obj);
/*
* Encryption
@@ -285,8 +291,10 @@ 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);
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(fz_context *ctx, pdf_xobject *from, fz_buffer *buffer);
/*
* CMap
diff --git a/pdf/mupdf.h b/pdf/mupdf.h
index b88f7423..07bfa12d 100644
--- a/pdf/mupdf.h
+++ b/pdf/mupdf.h
@@ -23,6 +23,8 @@ 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);
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_xobject.c b/pdf/pdf_xobject.c
index ffa86184..655bc7fa 100644
--- a/pdf/pdf_xobject.c
+++ b/pdf/pdf_xobject.c
@@ -110,3 +110,118 @@ pdf_load_xobject(pdf_document *xref, pdf_obj *dict)
return form;
}
+
+pdf_obj *
+pdf_new_xobject(pdf_document *xref, fz_rect *bbox)
+{
+ 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, &fz_identity);
+ 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 = pdf_new_stream_indirection(xref, dict);
+ pdf_drop_obj(dict);
+ dict = NULL;
+
+ pdf_store_item(ctx, idict, form, pdf_xobject_size(form));
+
+ 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(fz_context *ctx, pdf_xobject *form, fz_buffer *buffer)
+{
+ fz_drop_buffer(ctx, form->contents);
+ form->contents = fz_keep_buffer(ctx, buffer);
+}
diff --git a/pdf/pdf_xref.c b/pdf/pdf_xref.c
index 89333107..30f4bd69 100644
--- a/pdf/pdf_xref.c
+++ b/pdf/pdf_xref.c
@@ -1115,6 +1115,18 @@ pdf_update_object(pdf_document *xref, int num, int gen, pdf_obj *newobj)
x->ofs = 0;
}
+pdf_obj *
+pdf_new_stream_indirection(pdf_document *xref, pdf_obj *obj)
+{
+ int num = xref->len;
+ pdf_resize_xref(xref, xref->len + 1);
+ pdf_update_object(xref, num, 0, obj);
+ /* Set stm_ofs, so that obj is treated as a stream */
+ xref->table[num].stm_ofs = 1;
+
+ return pdf_new_indirect(xref->ctx, num, 0, xref);
+}
+
/*
* Convenience function to open a file then call pdf_open_document_with_stream.
*/