summaryrefslogtreecommitdiff
path: root/source/pdf/pdf-xobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/pdf/pdf-xobject.c')
-rw-r--r--source/pdf/pdf-xobject.c232
1 files changed, 232 insertions, 0 deletions
diff --git a/source/pdf/pdf-xobject.c b/source/pdf/pdf-xobject.c
new file mode 100644
index 00000000..61fc876a
--- /dev/null
+++ b/source/pdf/pdf-xobject.c
@@ -0,0 +1,232 @@
+#include "mupdf/pdf.h"
+
+pdf_xobject *
+pdf_keep_xobject(fz_context *ctx, pdf_xobject *xobj)
+{
+ return (pdf_xobject *)fz_keep_storable(ctx, &xobj->storable);
+}
+
+void
+pdf_drop_xobject(fz_context *ctx, pdf_xobject *xobj)
+{
+ fz_drop_storable(ctx, &xobj->storable);
+}
+
+static void
+pdf_free_xobject_imp(fz_context *ctx, fz_storable *xobj_)
+{
+ pdf_xobject *xobj = (pdf_xobject *)xobj_;
+
+ if (xobj->colorspace)
+ fz_drop_colorspace(ctx, xobj->colorspace);
+ pdf_drop_obj(xobj->resources);
+ pdf_drop_obj(xobj->contents);
+ pdf_drop_obj(xobj->me);
+ fz_free(ctx, xobj);
+}
+
+static unsigned int
+pdf_xobject_size(pdf_xobject *xobj)
+{
+ if (xobj == NULL)
+ return 0;
+ return sizeof(*xobj) + (xobj->colorspace ? xobj->colorspace->size : 0);
+}
+
+pdf_xobject *
+pdf_load_xobject(pdf_document *xref, pdf_obj *dict)
+{
+ pdf_xobject *form;
+ pdf_obj *obj;
+ fz_context *ctx = xref->ctx;
+
+ if ((form = pdf_find_item(ctx, pdf_free_xobject_imp, dict)))
+ {
+ return form;
+ }
+
+ 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->iteration = 0;
+
+ /* Store item immediately, to avoid possible recursion if objects refer back to this one */
+ pdf_store_item(ctx, dict, form, pdf_xobject_size(form));
+
+ fz_try(ctx)
+ {
+ obj = pdf_dict_gets(dict, "BBox");
+ pdf_to_rect(ctx, obj, &form->bbox);
+
+ obj = pdf_dict_gets(dict, "Matrix");
+ if (obj)
+ pdf_to_matrix(ctx, obj, &form->matrix);
+ else
+ form->matrix = fz_identity;
+
+ form->isolated = 0;
+ form->knockout = 0;
+ form->transparency = 0;
+
+ obj = pdf_dict_gets(dict, "Group");
+ if (obj)
+ {
+ pdf_obj *attrs = obj;
+
+ form->isolated = pdf_to_bool(pdf_dict_gets(attrs, "I"));
+ form->knockout = pdf_to_bool(pdf_dict_gets(attrs, "K"));
+
+ obj = pdf_dict_gets(attrs, "S");
+ if (pdf_is_name(obj) && !strcmp(pdf_to_name(obj), "Transparency"))
+ form->transparency = 1;
+
+ obj = pdf_dict_gets(attrs, "CS");
+ if (obj)
+ {
+ form->colorspace = pdf_load_colorspace(xref, obj);
+ if (!form->colorspace)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "cannot load xobject colorspace");
+ }
+ }
+
+ form->resources = pdf_dict_gets(dict, "Resources");
+ if (form->resources)
+ pdf_keep_obj(form->resources);
+
+ form->contents = pdf_keep_obj(dict);
+ }
+ fz_catch(ctx)
+ {
+ pdf_remove_item(ctx, pdf_free_xobject_imp, dict);
+ pdf_drop_xobject(ctx, form);
+ fz_rethrow_message(ctx, "cannot load xobject content stream (%d %d R)", pdf_to_num(dict), pdf_to_gen(dict));
+ }
+ form->me = pdf_keep_obj(dict);
+
+ return form;
+}
+
+pdf_obj *
+pdf_new_xobject(pdf_document *xref, const fz_rect *bbox, const 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 = pdf_new_name(ctx, "PDF");
+ pdf_array_push(procset, obj);
+ pdf_drop_obj(obj);
+ obj = NULL;
+ obj = pdf_new_name(ctx, "Text");
+ pdf_array_push(procset, 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 = pdf_new_name(ctx, "Form");
+ pdf_dict_puts(dict, "Subtype", obj);
+ pdf_drop_obj(obj);
+ obj = NULL;
+
+ obj = pdf_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->iteration = 0;
+
+ form->bbox = *bbox;
+
+ form->matrix = *mat;
+
+ 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_rethrow_message(ctx, "failed to create xobject)");
+ }
+
+ return idict;
+}
+
+void pdf_update_xobject_contents(pdf_document *xref, pdf_xobject *form, fz_buffer *buffer)
+{
+ pdf_dict_dels(form->contents, "Filter");
+ pdf_dict_puts_drop(form->contents, "Length", pdf_new_int(xref->ctx, buffer->len));
+ pdf_update_stream(xref, pdf_to_num(form->contents), buffer);
+ form->iteration ++;
+}