Index: glib/poppler-document.cc =================================================================== RCS file: /cvs/poppler/poppler/glib/poppler-document.cc,v retrieving revision 1.37 diff -u -8 -p -r1.37 poppler-document.cc --- glib/poppler-document.cc 19 May 2006 22:12:38 -0000 1.37 +++ glib/poppler-document.cc 30 Jun 2006 21:29:44 -0000 @@ -1343,8 +1343,57 @@ poppler_ps_file_set_duplex (PopplerPSFil * **/ void poppler_ps_file_free (PopplerPSFile *ps_file) { g_return_if_fail (ps_file != NULL); g_object_unref (ps_file); } + +void +poppler_document_set_form_field_content (PopplerDocument *document, int id, char *content) +{ + Catalog *catalog = document->doc->getCatalog(); + int numPages = catalog->getNumPages(); + for (int i=1; i<=numPages; i++) { + Form *form = catalog->getPage(i)->getForm(); + FormField *field = form->getFieldById(id); + if (field) { + field->setContentCopy(content); + document->doc->addIncrementalObject(field->getObj(), field->getRef()); + return; + } + } +} + +gchar * +poppler_document_get_form_field_content (PopplerDocument *document, int id) +{ + PopplerFormField *field = poppler_document_find_form_field_by_id(document, id); + if (field) + return field->content; + else { + g_warning("poppler_document_get_form_field_content, unknown id: %i", id); + return NULL; + } +} + +PopplerFormField * +poppler_document_find_form_field_by_id (PopplerDocument *document, int id) +{ + Catalog *catalog = document->doc->getCatalog(); + //decode id + int pageNum = id >> 16; + int fieldNum = (id << 16) >> 16; + FormField *field = catalog->getPage(pageNum)->getForm()->getField(fieldNum); + if (field != NULL) { + PopplerFormField *poppler_field; + poppler_field = g_new(PopplerFormField, 1); + field->getRect ((&poppler_field->area.x1), &(poppler_field->area.y1), + &(poppler_field->area.x2), &(poppler_field->area.y2)); + poppler_field->type = (PopplerFormFieldType)field->getType(); + poppler_field->id = field->getID(); + poppler_field->content = field->getContentCopy(); + return poppler_field; + } else + return NULL; +} Index: glib/poppler-document.h =================================================================== RCS file: /cvs/poppler/poppler/glib/poppler-document.h,v retrieving revision 1.21 diff -u -8 -p -r1.21 poppler-document.h --- glib/poppler-document.h 19 May 2006 22:19:21 -0000 1.21 +++ glib/poppler-document.h 30 Jun 2006 21:29:44 -0000 @@ -103,16 +103,27 @@ PopplerPage *poppler_document_get_pa /* Attachments */ gboolean poppler_document_has_attachments (PopplerDocument *document); GList *poppler_document_get_attachments (PopplerDocument *document); /* Links */ PopplerDest *poppler_document_find_dest (PopplerDocument *document, const gchar *link_name); +/* Form */ +void poppler_document_set_form_field_content (PopplerDocument *document, + int id, + char *content); +PopplerFormField *poppler_document_find_form_field_by_id (PopplerDocument *document, + int id); + +gchar * +poppler_document_get_form_field_content (PopplerDocument *document, int id); + + /* Interface for getting the Index of a poppler_document */ #define POPPLER_TYPE_INDEX_ITER (poppler_index_iter_get_type ()) GType poppler_index_iter_get_type (void) G_GNUC_CONST; PopplerIndexIter *poppler_index_iter_new (PopplerDocument *document); PopplerIndexIter *poppler_index_iter_copy (PopplerIndexIter *iter); void poppler_index_iter_free (PopplerIndexIter *iter); PopplerIndexIter *poppler_index_iter_get_child (PopplerIndexIter *parent); Index: glib/poppler-page.cc =================================================================== RCS file: /cvs/poppler/poppler/glib/poppler-page.cc,v retrieving revision 1.50 diff -u -8 -p -r1.50 poppler-page.cc --- glib/poppler-page.cc 19 May 2006 21:42:54 -0000 1.50 +++ glib/poppler-page.cc 30 Jun 2006 21:29:45 -0000 @@ -980,8 +980,104 @@ poppler_link_mapping_copy (PopplerLinkMa void poppler_link_mapping_free (PopplerLinkMapping *mapping) { if (mapping) poppler_action_free (mapping->action); g_free (mapping); } + + +/* Form Type */ +GType +poppler_form_field_get_type (void) +{ + static GType our_type = 0; + if (our_type == 0) + our_type = g_boxed_type_register_static("PopplerFormField", + (GBoxedCopyFunc) poppler_form_field_copy, + (GBoxedFreeFunc) poppler_form_field_free); + return our_type; +} + +PopplerFormField* +poppler_form_field_new (void) +{ + return (PopplerFormField *) g_new0 (PopplerFormField, 1); +} + +PopplerFormField* +poppler_form_field_copy (PopplerFormField* field) +{ + PopplerFormField* new_field; + new_field = poppler_form_field_new(); + new_field = field; + return new_field; +} + +void +poppler_form_field_free (PopplerFormField* field) +{ + g_free (field); +} + +/** + * poppler_page_get_form_fields + **/ + +GList* +poppler_page_get_form_fields (PopplerPage *page) +{ + GList *field_list = NULL; + Form *form; + gint i; + Object obj; + + g_return_val_if_fail (POPPLER_IS_PAGE (page), NULL); + + //form = new Form(page->page->getAnnots (&obj)); + form = page->page->getForm(); + + obj.free (); + if(form == NULL) + return NULL; + + + for(i = 0; i < form->getNumFields(); i++) { + PopplerFormField *poppler_field; + FormField *field; + field = form->getField(i); + + poppler_field = g_new(PopplerFormField, 1); + field->getRect (&(poppler_field->area.x1), &(poppler_field->area.y1), + &(poppler_field->area.x2), &(poppler_field->area.y2)); + + poppler_field->type = (PopplerFormFieldType)field->getType(); + poppler_field->id = field->getID(); + poppler_field->content = field->getContentCopy(); + field_list = g_list_prepend(field_list,poppler_field); + } + return field_list; + +} + +void +poppler_page_free_form_fields (GList *list) +{ + if (list == NULL) + return; + + g_list_foreach (list, (GFunc) (poppler_form_field_free), NULL); + g_list_free (list); + +} + +void +poppler_page_get_crop_box (PopplerPage *page, PopplerRectangle *rect) +{ + PDFRectangle* cropBox = page->page->getCropBox(); + rect->x1 = cropBox->x1; + rect->x2 = cropBox->x2; + rect->y1 = cropBox->y1; + rect->y2 = cropBox->y2; +} + Index: glib/poppler-page.h =================================================================== RCS file: /cvs/poppler/poppler/glib/poppler-page.h,v retrieving revision 1.21 diff -u -8 -p -r1.21 poppler-page.h --- glib/poppler-page.h 12 Apr 2006 02:07:07 -0000 1.21 +++ glib/poppler-page.h 30 Jun 2006 21:29:45 -0000 @@ -75,16 +75,21 @@ GdkRegion * poppler_page_get_sel void poppler_page_render_selection (PopplerPage *page, gdouble scale, int rotation, GdkPixbuf *pixbuf, PopplerRectangle *selection, PopplerRectangle *old_selection, GdkColor *glyph_color, GdkColor *background_color); +GList *poppler_page_get_form_fields (PopplerPage *page); +void poppler_page_free_form_fields (GList *list); + +void poppler_page_get_crop_box (PopplerPage *page, + PopplerRectangle *rect); /* A rectangle on a page, with coordinates in PDF points. */ #define POPPLER_TYPE_RECTANGLE (poppler_rectangle_get_type ()) struct _PopplerRectangle { gdouble x1; gdouble y1; @@ -107,11 +112,27 @@ struct _PopplerLinkMapping PopplerAction *action; }; GType poppler_link_mapping_get_type (void) G_GNUC_CONST; PopplerLinkMapping *poppler_link_mapping_new (void); PopplerLinkMapping *poppler_link_mapping_copy (PopplerLinkMapping *mapping); void poppler_link_mapping_free (PopplerLinkMapping *mapping); +/* FormField */ +#define POPPLER_TYPE_FORM_FIELD (poppler_form_field_get_type ()) +struct _PopplerFormField +{ + PopplerRectangle area; + PopplerFormFieldType type; + gchar *content; + int id; + +}; + +GType poppler_form_field_get_type (void) G_GNUC_CONST; +PopplerFormField *poppler_form_field_new (void); +PopplerFormField *poppler_form_field_copy (PopplerFormField *field); +void poppler_form_field_free (PopplerFormField *field); + G_END_DECLS #endif /* __POPPLER_PAGE_H__ */ Index: glib/poppler-private.h =================================================================== RCS file: /cvs/poppler/poppler/glib/poppler-private.h,v retrieving revision 1.16 diff -u -8 -p -r1.16 poppler-private.h --- glib/poppler-private.h 19 May 2006 20:54:13 -0000 1.16 +++ glib/poppler-private.h 30 Jun 2006 21:29:45 -0000 @@ -1,15 +1,16 @@ #ifndef __POPPLER_PRIVATE_H__ #define __POPPLER_PRIVATE_H__ #include #include #include #include +#include #include #include #include #include #include "poppler-attachment.h" #if defined (HAVE_CAIRO) Index: glib/poppler.h =================================================================== RCS file: /cvs/poppler/poppler/glib/poppler.h,v retrieving revision 1.12 diff -u -8 -p -r1.12 poppler.h --- glib/poppler.h 16 Apr 2006 22:59:44 -0000 1.12 +++ glib/poppler.h 30 Jun 2006 21:29:49 -0000 @@ -37,21 +37,32 @@ typedef enum typedef enum { POPPLER_ORIENTATION_PORTRAIT, POPPLER_ORIENTATION_LANDSCAPE, POPPLER_ORIENTATION_UPSIDEDOWN, POPPLER_ORIENTATION_SEASCAPE } PopplerOrientation; +/* MUST be the same than poppler/Form.h fieldType */ +typedef enum +{ + POPPLER_FORM_FIELD_BUTTON, + POPPLER_FORM_FIELD_TEXT, + POPPLER_FORM_FIELD_CHOICE, + POPPLER_FORM_FIELD_SIGNATURE +} PopplerFormFieldType; + + typedef struct _PopplerDocument PopplerDocument; typedef struct _PopplerIndexIter PopplerIndexIter; typedef struct _PopplerFontsIter PopplerFontsIter; typedef struct _PopplerRectangle PopplerRectangle; typedef struct _PopplerLinkMapping PopplerLinkMapping; +typedef struct _PopplerFormField PopplerFormField; typedef struct _PopplerPage PopplerPage; typedef struct _PopplerFontInfo PopplerFontInfo; typedef struct _PopplerPSFile PopplerPSFile; typedef union _PopplerAction PopplerAction; typedef struct _PopplerDest PopplerDest; typedef enum Index: poppler/Dict.cc =================================================================== RCS file: /cvs/poppler/poppler/poppler/Dict.cc,v retrieving revision 1.4 diff -u -8 -p -r1.4 Dict.cc --- poppler/Dict.cc 18 Jan 2006 22:32:13 -0000 1.4 +++ poppler/Dict.cc 30 Jun 2006 21:29:49 -0000 @@ -50,16 +50,28 @@ void Dict::add(const UGooString &key, Ob } entries = (DictEntry *)greallocn(entries, size, sizeof(DictEntry)); } entries[length].key = new UGooString(key); entries[length].val = *val; ++length; } +void Dict::set(const UGooString &key, Object *val) { + DictEntry *e; + e = find (key); + //printf("%s\n", val->getString()->getCString()); + if (e) { + e->val.free(); + e->val = *val; + } else { + add (key, val); + } +} + inline DictEntry *Dict::find(const UGooString &key) { int i; for (i = 0; i < length; ++i) { if (!key.cmp(entries[i].key)) return &entries[i]; } return NULL; Index: poppler/Dict.h =================================================================== RCS file: /cvs/poppler/poppler/poppler/Dict.h,v retrieving revision 1.3 diff -u -8 -p -r1.3 Dict.h --- poppler/Dict.h 18 Jan 2006 22:32:13 -0000 1.3 +++ poppler/Dict.h 30 Jun 2006 21:29:49 -0000 @@ -38,16 +38,18 @@ public: int incRef() { return ++ref; } int decRef() { return --ref; } // Get number of entries. int getLength() { return length; } // Add an entry void add(const UGooString &key, Object *val); + // Update the value of an existing entry, otherwise create it + void set(const UGooString &key, Object *val); // Check if dictionary is of specified type. GBool is(char *type); // Look up an entry and return the value. Returns a null object // if is not in the dictionary. Object *lookup(const UGooString &key, Object *obj); Object *lookupNF(const UGooString &key, Object *obj); Index: poppler/Form.cc =================================================================== RCS file: poppler/Form.cc diff -N poppler/Form.cc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ poppler/Form.cc 30 Jun 2006 21:29:49 -0000 @@ -0,0 +1,279 @@ +//======================================================================== +// +// Form.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// Copyright 2006 Julien Rebetez +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "goo/gmem.h" +#include "goo/GooString.h" +#include "Error.h" +#include "Object.h" +#include "Array.h" +#include "Dict.h" +#include "Form.h" +#include "UGooString.h" + + +//======================================================================== +// FormField +//======================================================================== + +FormField::FormField(Object *aobj, unsigned id, Ref aref) { + Object obj1, obj2, obj3i; + double t; + ref = aref; + ID = id; + ok = gFalse; + content = NULL; + aobj->copy(&obj); + Dict *dict = obj.getDict(); + + // get rectangle + if (!dict->lookup("Rect", &obj1)->isArray()) { + error(-1, "Annotation rectangle is wrong type"); + goto err2; + } + if (!obj1.arrayGet(0, &obj2)->isNum()) { + error(-1, "Bad annotation rectangle"); + goto err1; + } + x1 = obj2.getNum(); + obj2.free(); + if (!obj1.arrayGet(1, &obj2)->isNum()) { + error(-1, "Bad annotation rectangle"); + goto err1; + } + y1 = obj2.getNum(); + obj2.free(); + if (!obj1.arrayGet(2, &obj2)->isNum()) { + error(-1, "Bad annotation rectangle"); + goto err1; + } + x2 = obj2.getNum(); + obj2.free(); + if (!obj1.arrayGet(3, &obj2)->isNum()) { + error(-1, "Bad annotation rectangle"); + goto err1; + } + y2 = obj2.getNum(); + obj2.free(); + obj1.free(); + //swap coords if needed + if (x1 > x2) { + t = x1; + x1 = x2; + x2 = t; + } + if (y1 > y2) { + t = y1; + y1 = y2; + y2 = t; + } + + + + ok = gTrue; + + err1: + obj2.free(); + err2: + obj1.free(); +} + +FormField::FormField(FormField *dest) +{ + x1 = dest->x1; + y1 = dest->y1; + x2 = dest->x2; + y2 = dest->x2; + + ok = dest->ok; + + type = dest->type; +} + +FormField::~FormField() +{ + obj.free(); +} + +void FormField::setContentCopy(char* new_content) +{ + Object obj1; + + if(content) + delete [] content; + + if (new_content == NULL) + content = NULL; + else { + content = strdup(new_content); + + GooString *cont = new GooString(content); + Object *obj1 = new Object(); + obj1->initString(cont); + //printf("%s, %s, %s\n", content, cont->getCString(), obj1->getString()); + obj.getDict()->set("V", obj1); + } +} + +//------------------------------------------------------------------------ +// FormFieldButton +//------------------------------------------------------------------------ +FormFieldButton::FormFieldButton(Object *dict, unsigned id, Ref ref) : FormField(dict, id, ref) +{ + type = fieldButton; +} + +FormFieldButton::~FormFieldButton() +{ + +} + +//------------------------------------------------------------------------ +// FormFieldText +//------------------------------------------------------------------------ +FormFieldText::FormFieldText(Object *dict, unsigned id, Ref ref) : FormField(dict, id, ref) +{ + type = fieldText; +} + +FormFieldText::~FormFieldText() +{ + +} + +//------------------------------------------------------------------------ +// FormFieldChoice +//------------------------------------------------------------------------ +FormFieldChoice::FormFieldChoice(Object *dict, unsigned id, Ref ref) : FormField(dict, id, ref) +{ + type = fieldChoice; +} + +FormFieldChoice::~FormFieldChoice() +{ + +} + +//------------------------------------------------------------------------ +// FormFieldSignature +//------------------------------------------------------------------------ +FormFieldSignature::FormFieldSignature(Object *dict, unsigned id, Ref ref): FormField(dict, id, ref) +{ + type = fieldSignature; +} + +FormFieldSignature::~FormFieldSignature() +{ + +} + +//------------------------------------------------------------------------ +// Form +//------------------------------------------------------------------------ + +Form::Form(Object* annots, unsigned page) +{ + FormField* field; + Object obj1, obj2; + int size; + int i; + unsigned count = 0; + + fields = NULL; + size = 0; + numFields = 0; + pageNum = page; + + if (annots->isArray()) { + for (i = 0; i < annots->arrayGetLength(); ++i) { + if (annots->arrayGet(i, &obj1)->isDict()) { + if (obj1.dictLookup("Subtype", &obj2)->isName("Widget")) { + unsigned id = ((unsigned)pageNum << 16) + count; + obj2.free(); + annots->arrayGetNF(i, &obj2); //store the indirect ref for further update + Ref objRef = obj2.getRef(); + obj2.free(); + //printf("num: %i\t gen:%i\n", objRef.num, objRef.gen); + if(obj1.dictLookup("FT", &obj2)->isName("Btn")) { + field = new FormFieldButton(&obj1,id,objRef); + count++; + } else if (obj2.isName("Tx")) { + field = new FormFieldText(&obj1,id,objRef); + count++; + } else if (obj2.isName("Ch")) { + field = new FormFieldChoice(&obj1,id,objRef); + count++; + } else if (obj2.isName("Sig")) { + field = new FormFieldSignature(&obj1,id,objRef); + count++; + } else { + goto err1; + } + if (field->isOk()) { + if (numFields >= size) { + size += 16; + fields = (FormField**)greallocn(fields,size,sizeof(FormField*)); + } + fields[numFields++] = field; + } else { + delete field; + } + + } +err1: + obj2.free(); + } + obj1.free(); + } + } + +} + +Form::~Form() { + int i; + for(i = 0; i< numFields; ++i) + delete fields[i]; + gfree(fields); +} + +FormField *Form::find(double x, double y) const { + int i; + for (i = numFields -1; i>= 0; --i) { + if (fields[i]->inRect(x, y)) { + return fields[i]; + } + } + return NULL; +} + +FormField* Form::getFieldById (unsigned int id) const { + int i; + for (i=0; igetID() == id) { + return fields[i]; + } + } + return NULL; +} +GBool Form::onField(double x, double y) const { + int i; + for (i =0; iinRect(x,y)) + return gTrue; + } + return gFalse; +} + Index: poppler/Form.h =================================================================== RCS file: poppler/Form.h diff -N poppler/Form.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ poppler/Form.h 30 Jun 2006 21:29:49 -0000 @@ -0,0 +1,176 @@ +//======================================================================== +// +// Form.h +// +// Copyright 2006 Julien Rebetez +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef FORM_H +#define FORM_H + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "Object.h" + +class GooString; +class UGooString; +class Array; +class Dict; + + +//------------------------------------------------------------------------ +// FormFieldType +//------------------------------------------------------------------------ + +enum FormFieldType { + fieldButton, + fieldText, + fieldChoice, + fieldSignature +}; + +class FormField { +public: + // Destructor + virtual ~FormField(); + + // Copy a FormField + FormField *copy() { return new FormField(this); } + + // Was the FormField created successfully ? + GBool isOk() { return ok; } + + // Check if point is inside the field rectangle + GBool inRect(double x, double y) + { return x1 <= x && x <= x2 && y1 <= y && y <= y2; } + + // Get the field rectangle + void getRect(double *xa1, double *ya1, double *xa2, double *ya2) + { *xa1 = x1; *ya1 = y1; *xa2 = x2; *ya2 = y2; } + + + + // Accessors. + FormFieldType getType() { return type; } + unsigned getID () { return ID; } + Object* getObj() { return &obj; } + char* getContentCopy() { if (content == NULL) return NULL; + else return strdup(content); } + void setContentCopy(char* new_content); + Ref getRef() { return ref; } +protected: + // Build a FormField from the dict, only callable from child-classes + FormField(Object *aobj, unsigned id, Ref aref); + FormFieldType type; // field type + GBool ok; // set if created successfully + char* content; + Ref ref; + Object obj; + + + +private: + FormField() {} + FormField(FormField *dest); + /* + Field ID is a 32bits integer, calculated as follow : + the first 16 bits are the field number, relative to the page + the last 16 bits are the page number + [page number | field number] + (encoding) id = (pageNum << 16) + fieldNum; + (decoding) pageNum = id >> 16; fieldNum = (id << 16) >> 16; + */ + unsigned ID; + + double x1, y1; // lower left corner + double x2, y2; // upper right corner +}; + + +//------------------------------------------------------------------------ +// FormFieldButton +//------------------------------------------------------------------------ + +class FormFieldButton: public FormField { +public: + // Build a fieldButton from flags + FormFieldButton(Object *dict, unsigned id, Ref ref); + + // Destructor + virtual ~FormFieldButton(); +}; + +//------------------------------------------------------------------------ +// FormFieldText +//------------------------------------------------------------------------ + +class FormFieldText: public FormField { +public: + // Build a fieldText from flags + FormFieldText(Object *dict, unsigned id, Ref ref); + + // Destructor + virtual ~FormFieldText(); +}; + +//------------------------------------------------------------------------ +// FormFieldChoice +//------------------------------------------------------------------------ + +class FormFieldChoice: public FormField { +public: + // Build a fieldChoice from flags + FormFieldChoice(Object *dict, unsigned id, Ref ref); + + // Destructor + virtual ~FormFieldChoice(); +}; + +//------------------------------------------------------------------------ +// FormFieldSignature +//------------------------------------------------------------------------ + +class FormFieldSignature: public FormField { +public: + // Build a fieldSignature from flags + FormFieldSignature(Object *dict, unsigned id, Ref ref); + + // Destructor + virtual ~FormFieldSignature(); +}; + +//------------------------------------------------------------------------ +// Form +//------------------------------------------------------------------------ + +class Form { +public: + // Extract form from array of annotations + Form(Object* annots, unsigned page); + + // Destructor + ~Form(); + + // Iterate through list of fields. + int getNumFields() const { return numFields; } + FormField* getField(int i) const { return fields[i]; } + FormField* getFieldById (unsigned int id) const; + + // If point , is in a field, return the associated field; + // else return NULL + FormField *find(double x, double y) const; + + // Return true if , is in a field. + GBool onField(double x, double y) const; + +private: + FormField** fields; + int numFields; + unsigned pageNum; +}; +#endif + Index: poppler/Makefile.am =================================================================== RCS file: /cvs/poppler/poppler/poppler/Makefile.am,v retrieving revision 1.23 diff -u -8 -p -r1.23 Makefile.am --- poppler/Makefile.am 19 May 2006 22:04:17 -0000 1.23 +++ poppler/Makefile.am 30 Jun 2006 21:29:49 -0000 @@ -105,16 +105,17 @@ poppler_include_HEADERS = \ Catalog.h \ CharCodeToUnicode.h \ CMap.h \ Decrypt.h \ Dict.h \ Error.h \ FontEncodingTables.h \ FontInfo.h \ + Form.h \ Function.cc \ Function.h \ Gfx.h \ GfxFont.h \ GfxState.h \ GlobalParams.h \ JArithmeticDecoder.h \ JBIG2Stream.h \ @@ -167,16 +168,17 @@ libpoppler_la_SOURCES = \ Catalog.cc \ CharCodeToUnicode.cc \ CMap.cc \ Decrypt.cc \ Dict.cc \ Error.cc \ FontEncodingTables.cc \ FontInfo.cc \ + Form.cc \ Function.cc \ Gfx.cc \ GfxFont.cc \ GfxState.cc \ GlobalParams.cc \ JArithmeticDecoder.cc \ JBIG2Stream.cc \ JPXStream.cc \ Index: poppler/PDFDoc.cc =================================================================== RCS file: /cvs/poppler/poppler/poppler/PDFDoc.cc,v retrieving revision 1.10 diff -u -8 -p -r1.10 PDFDoc.cc --- poppler/PDFDoc.cc 18 Jan 2006 22:32:13 -0000 1.10 +++ poppler/PDFDoc.cc 30 Jun 2006 21:29:50 -0000 @@ -237,16 +237,20 @@ PDFDoc::~PDFDoc() { fclose(file); } if (fileName) { delete fileName; } if (links) { delete links; } + + for (int i=0; igetPos(); @@ -456,31 +460,138 @@ GBool PDFDoc::isLinearized() { obj4.free(); obj3.free(); obj2.free(); obj1.free(); delete parser; return lin; } +void PDFDoc::addIncrementalObject (Object *obj, Ref ref) +{ + Object *cpy = new Object(); + obj->copy(cpy); + IncrObj tmp; + tmp.ref = ref; + tmp.obj = cpy; + incrementalObjects.push_back(tmp); + +} + + GBool PDFDoc::saveAs(GooString *name) { - FILE *f; + /*FILE *f; int c; if (!(f = fopen(name->getCString(), "wb"))) { error(-1, "Couldn't open file '%s'", name->getCString()); return gFalse; } str->reset(); while ((c = str->getChar()) != EOF) { fputc(c, f); } str->close(); - fclose(f); + fclose(f);*/ + XRef *xref = new XRef(); + //printf("objects that needs update\n"); + for(int i=0; igetDict()->lookup("V", &obj1)->isString()) { + printf("value: %s\n", obj1.getString()->getCString()); + } else { + printf("obj1 type: %s\n", obj1.getTypeName()); + }*/ + + Guint offset = addObjectToStream(incrementalObjects[i].obj, &incrementalObjects[i].ref); + xref->add(incrementalObjects[i].ref.num, incrementalObjects[i].ref.gen, incrementalObjects[i].obj, offset); + obj1.free(); + } + xref->print (); + + delete xref; return gTrue; } +Guint PDFDoc::addObjectToStream (Object* obj, Ref* ref) +{ + Dict *dict; + Array *array; + Object obj1; + + if(ref) + printf("%i %i obj\n", ref->num, ref->gen); + + switch (obj->getType()) { + case objBool: + printf("%s ", obj->getBool()?"true":"false"); + break; + case objInt: + printf("%i ", obj->getInt()); + break; + case objReal: + printf("%f ", obj->getReal()); + break; + case objString: + printf("(%s) ", obj->getString()->getCString()); + break; + case objName: + printf("/%s ", obj->getName()); + break; + case objNull: + printf("NULL"); + break; + case objArray: + array = obj->getArray(); + printf("["); + for (int i=0; igetLength(); i++) { + addObjectToStream(array->getNF(i, &obj1), NULL); + obj1.free(); + } + printf("]"); + break; + case objDict: + dict = obj->getDict(); + printf("<< "); + for (int i=0; igetLength(); i++) { + //printf("iterator %i, key:%s\n", i, dict->getKey(i)->getCString()); + printf("/%s ", dict->getKey(i)->getCString()); + addObjectToStream(dict->getValNF(i, &obj1), NULL); + obj1.free(); + } + printf(">>\n"); + break; + case objStream: + printf("STREAM HERE\n"); + break; + case objRef: + printf("%i %i R", obj->getRef().num, obj->getRef().gen); + break; + case objCmd: + printf("CMD HERE\n"); + break; + case objError: + printf("ERROR HERE\n"); + break; + case objEOF: + printf("EOF HERE\n"); + break; + case objNone: + printf("NONE HERE\n"); + break; + default: + printf("Unhandled objType : %i, please report a bug with a testcase\n", obj->getType()); + break; + } + if (ref) + printf("endobj\n\n"); + else + printf("\n"); + return 0; +} + void PDFDoc::getLinks(Page *page) { Object obj; links = new Links(page->getAnnots(&obj), catalog->getBaseURI()); obj.free(); } Index: poppler/PDFDoc.h =================================================================== RCS file: /cvs/poppler/poppler/poppler/PDFDoc.h,v retrieving revision 1.7 diff -u -8 -p -r1.7 PDFDoc.h --- poppler/PDFDoc.h 18 Jan 2006 22:32:13 -0000 1.7 +++ poppler/PDFDoc.h 30 Jun 2006 21:29:50 -0000 @@ -9,16 +9,17 @@ #ifndef PDFDOC_H #define PDFDOC_H #ifdef USE_GCC_PRAGMAS #pragma interface #endif #include +#include "goo/GooVector.h" #include "XRef.h" #include "Catalog.h" #include "Page.h" #include "Annot.h" class GooString; class BaseStream; class OutputDev; @@ -158,31 +159,43 @@ public: // Return the document's Info dictionary (if any). Object *getDocInfo(Object *obj) { return xref->getDocInfo(obj); } Object *getDocInfoNF(Object *obj) { return xref->getDocInfoNF(obj); } // Return the PDF version specified by the file. double getPDFVersion() { return pdfVersion; } + // Add an object to the file stream, using incremental update + void addIncrementalObject (Object *obj, Ref ref); + // Save this file with another name. GBool saveAs(GooString *name); // Return a pointer to the GUI (XPDFCore or WinPDFCore object). void *getGUIData() { return guiData; } private: + // Add object to current file stream and return the offset of the beginning of the object + Guint addObjectToStream (Object* obj, Ref* ref); + + struct IncrObj + { + Ref ref; + Object* obj; + }; GBool setup(GooString *ownerPassword, GooString *userPassword); GBool checkFooter(); void checkHeader(); GBool checkEncryption(GooString *ownerPassword, GooString *userPassword); void getLinks(Page *page); GooString *fileName; + GooVector incrementalObjects; FILE *file; BaseStream *str; void *guiData; double pdfVersion; XRef *xref; Catalog *catalog; Links *links; #ifndef DISABLE_OUTLINE Index: poppler/Page.cc =================================================================== RCS file: /cvs/poppler/poppler/poppler/Page.cc,v retrieving revision 1.12 diff -u -8 -p -r1.12 Page.cc --- poppler/Page.cc 16 Mar 2006 22:04:56 -0000 1.12 +++ poppler/Page.cc 30 Jun 2006 21:29:50 -0000 @@ -21,16 +21,17 @@ #include "XRef.h" #include "Link.h" #include "OutputDev.h" #ifndef PDF_PARSER_ONLY #include "Gfx.h" #include "GfxState.h" #include "Annot.h" #include "TextOutputDev.h" +#include "Form.h" #endif #include "Error.h" #include "Page.h" #include "UGooString.h" //------------------------------------------------------------------------ // PageAttrs //------------------------------------------------------------------------ @@ -184,16 +185,17 @@ GBool PageAttrs::readBox(Dict *dict, cha return ok; } //------------------------------------------------------------------------ // Page //------------------------------------------------------------------------ Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA) { + Object obj; ok = gTrue; xref = xrefA; num = numA; // get attributes attrs = attrsA; // transtion @@ -208,16 +210,20 @@ Page::Page(XRef *xrefA, int numA, Dict * pageDict->lookupNF("Annots", &annots); if (!(annots.isRef() || annots.isArray() || annots.isNull())) { error(-1, "Page annotations object (page %d) is wrong type (%s)", num, annots.getTypeName()); annots.free(); goto err2; } + // forms + form = new Form(this->getAnnots(&obj),num); + obj.free(); + // contents pageDict->lookupNF("Contents", &contents); if (!(contents.isRef() || contents.isArray() || contents.isNull())) { error(-1, "Page contents object (page %d) is wrong type (%s)", num, contents.getTypeName()); contents.free(); goto err1; Index: poppler/Page.h =================================================================== RCS file: /cvs/poppler/poppler/poppler/Page.h,v retrieving revision 1.5 diff -u -8 -p -r1.5 Page.h --- poppler/Page.h 30 Oct 2005 20:29:05 -0000 1.5 +++ poppler/Page.h 30 Jun 2006 21:29:51 -0000 @@ -18,16 +18,17 @@ class Dict; class XRef; class OutputDev; class Links; class Catalog; class Annots; class Annot; class Gfx; +class Form; //------------------------------------------------------------------------ class PDFRectangle { public: double x1, y1, x2, y2; PDFRectangle() { x1 = y1 = x2 = y2 = 0; } @@ -146,16 +147,19 @@ public: // Get thumb. Object *getThumb(Object *obj) { return thumb.fetch(xref, obj); } GBool loadThumb(unsigned char **data, int *width, int *height, int *rowstride); // Get transition. Object *getTrans(Object *obj) { return trans.fetch(xref, obj); } + // Get form. + Form *getForm() { return form; } + Gfx *createGfx(OutputDev *out, double hDPI, double vDPI, int rotate, GBool useMediaBox, GBool crop, int sliceX, int sliceY, int sliceW, int sliceH, Links *links, Catalog *catalog, GBool (*abortCheckCbk)(void *data), void *abortCheckCbkData, GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data), void *annotDisplayDecideCbkData); @@ -190,11 +194,12 @@ private: XRef *xref; // the xref table for this PDF file int num; // page number PageAttrs *attrs; // page attributes Object annots; // annotations array Object contents; // page contents Object thumb; // page thumbnail Object trans; // page transition GBool ok; // true if page is valid + Form *form; // the form for that page }; #endif Index: poppler/XRef.cc =================================================================== RCS file: /cvs/poppler/poppler/poppler/XRef.cc,v retrieving revision 1.13 diff -u -8 -p -r1.13 XRef.cc --- poppler/XRef.cc 1 Apr 2006 11:25:57 -0000 1.13 +++ poppler/XRef.cc 30 Jun 2006 21:29:52 -0000 @@ -196,16 +196,26 @@ Object *ObjectStream::getObject(int objI } return objs[objIdx].copy(obj); } //------------------------------------------------------------------------ // XRef //------------------------------------------------------------------------ +XRef::XRef() { + ok = gTrue; + errCode = errNone; + entries = NULL; + size = 0; + streamEnds = NULL; + streamEndsLen = 0; + objStr = NULL; +} + XRef::XRef(BaseStream *strA) { Guint pos; Object obj; ok = gTrue; errCode = errNone; size = 0; entries = NULL; @@ -962,8 +972,47 @@ Guint XRef::strToUnsigned(char *s) { int i; x = 0; for (p = s, i = 0; *p && isdigit(*p) && i < 10; ++p, ++i) { x = 10 * x + (*p - '0'); } return x; } + +void XRef::add(int num, int gen, Object *obj, Guint offs) { + size += 1; + entries = (XRefEntry *)greallocn(entries, size, sizeof(XRefEntry)); + entries[size-1].offset = offs; + entries[size-1].gen = gen; + entries[size-1].num = num; + entries[size-1].type = xrefEntryUncompressed; +} + +int compare (const void* a, const void* b) +{ + return (((XRefEntry*)a)->num - ((XRefEntry*)b)->num); +} + +void XRef::print() { + printf("XRef::print\n"); + qsort(entries, size, sizeof(XRefEntry), compare); + int lastNum = -1; + int j; + for (int i=0; i array int rootNum, rootGen; // catalog dict Index: test/gtk-splash-test.cc =================================================================== RCS file: /cvs/poppler/poppler/test/gtk-splash-test.cc,v retrieving revision 1.5 diff -u -8 -p -r1.5 gtk-splash-test.cc --- test/gtk-splash-test.cc 30 Oct 2005 20:29:05 -0000 1.5 +++ test/gtk-splash-test.cc 30 Jun 2006 21:29:54 -0000 @@ -271,16 +271,17 @@ int main (int argc, char *argv []) { View *v; int i; gtk_init (&argc, &argv); globalParams = new GlobalParams("/etc/xpdfrc"); + //globalParams->setPrintCommands(TRUE); if (argc == 1) { fprintf (stderr, "usage: %s PDF-FILES...\n", argv[0]); return -1; }