? poppler/Form.cc ? poppler/Form.h ? test/pdf-modification-test ? test/pdf-modification-test.cc Index: glib/poppler-document.cc =================================================================== RCS file: /cvs/poppler/poppler/glib/poppler-document.cc,v retrieving revision 1.37 diff -r1.37 poppler-document.cc 1350a1351,1523 > > > //NeedAppearances needs to be set to 'true' in the AcroForm entry of the Catalog to enable dynamic appearance generation > void > check_for_need_appearances (PopplerDocument *document) > { > //FIXME: static var are bad in shared libs > static GBool appearanceSet = gFalse; > if(!appearanceSet) { > XRef* xref = document->doc->getXRef(); > Object* catalog = new Object(); > Object acroForm; > Ref catRef; > catRef.gen = xref->getRootGen(); > catRef.num = xref->getRootNum(); > catalog = xref->getCatalog(catalog); > catalog->dictLookup("AcroForm", &acroForm); > Object obj1; > obj1.initBool(true); > acroForm.dictSet("NeedAppearances", &obj1); > obj1.free(); > catalog->dictSet("AcroForm", &acroForm); > document->doc->getXRef()->setModifiedObject(catalog, catRef); > appearanceSet = gTrue; > } > } > > void decode_id (int id, int *pageNum, int *fieldNum) > { > (*pageNum) = id >> 16; > (*fieldNum) = (id << 16) >> 16; > } > > void > poppler_document_set_form_field_button_state (PopplerDocument *document, int id, gboolean state) > { > int pageNum, fieldNum; > decode_id(id, &pageNum, &fieldNum); > Catalog *catalog = document->doc->getCatalog(); > FormWidget *tmp = catalog->getPage(pageNum)->getPageWidgets()->getWidget(fieldNum); > FormWidgetButton *field = NULL; > if (tmp->getType() != formButton) { > g_warning("poppler_document_set_form_field_button_state, invalid field type: %i\n", tmp->getType()); > return; > } > field = static_cast(tmp); > if (field) { > field->setState((GBool)state); > //FIXME: should be moved to Form > check_for_need_appearances(document); > } > } > > gboolean > poppler_document_get_form_field_button_state (PopplerDocument *document, int id) > { > int pageNum, fieldNum; > decode_id(id, &pageNum, &fieldNum); > Catalog *catalog = document->doc->getCatalog(); > FormWidget *tmp = catalog->getPage(pageNum)->getPageWidgets()->getWidget(fieldNum); > FormWidgetButton *field = NULL; > if (tmp->getType() != formButton) { > g_warning("poppler_document_set_form_field_button_state, invalid field type: %i\n", tmp->getType()); > return FALSE; > } > field = static_cast(tmp); > if(field) { > return (gboolean)field->getState(); > } > return FALSE; > } > > void > poppler_document_set_form_field_text_content (PopplerDocument *document, int id, char *content, int length) > { > int pageNum, fieldNum; > decode_id(id, &pageNum, &fieldNum); > > Catalog *catalog = document->doc->getCatalog(); > FormWidget *tmp = catalog->getPage(pageNum)->getPageWidgets()->getWidget(fieldNum); > FormWidgetText *field = NULL; > if (tmp->getType() != formText) { > g_warning("poppler_document_set_form_field_text_content, invalid field type: %i\n", tmp->getType()); > return ; > } > field = static_cast(tmp); > if (field) { > printf("poppler_document_set_form_field_text_content: length: %i\n", strlen(content)); > field->setContentCopy(new GooString(content, length)); > //FIXME: should be moved to Form > check_for_need_appearances(document); > } > } > > gchar * > poppler_document_get_form_field_text_content (PopplerDocument *document, int id, int* length) > { > PopplerFormField *field = poppler_document_find_form_field_by_id(document, id); > if (field && field->type == POPPLER_FORM_FIELD_TEXT) { > *length = field->text.length; > return field->text.content; > } else { > g_warning("poppler_document_get_form_field_text_content, unknown id: %i", id); > return NULL; > } > } > > FormWidget * > _get_form_widget_by_id (PopplerDocument *document, int id) > { > Catalog *catalog = document->doc->getCatalog(); > //decode id > int pageNum = id >> 16; > int fieldNum = (id << 16) >> 16; > FormWidget *field = catalog->getPage(pageNum)->getPageWidgets()->getWidget(fieldNum); > if (field != NULL) { > return field; > } else > return NULL; > } > > gchar * > poppler_document_get_form_field_choice_content (PopplerDocument *document, int id, int index) > { > FormWidget *field = _get_form_widget_by_id(document, id); > if (field && field->getType() == formChoice) { > return static_cast(field)->getChoice(index)->getCString(); > } else { > g_warning("poppler_document_get_form_field_choice_content, unknown id: %i", id); > return NULL; > } > } > > int > poppler_document_get_form_field_choice_num_choices (PopplerDocument *document, int id) > { > FormWidget *field = _get_form_widget_by_id(document, id); > if (field && field->getType() == formChoice) { > printf("poppler_document %i\n", static_cast(field)->getNumChoices()); > return static_cast(field)->getNumChoices(); > }else { > g_warning("poppler_document_get_form_field_choice_content, unknown id: %i", id); > return -1; > } > } > > void poppler_document_set_form_field_choice_content (PopplerDocument *document, int id, int index) > { > FormWidget *field = _get_form_widget_by_id(document, id); > if (field && field->getType() == formChoice) { > static_cast(field)->setChoice(index); > } else { > g_warning("poppler_document_get_form_field_choice_content, unknown id: %i", id); > } > } > > > > 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; > FormWidget *field = catalog->getPage(pageNum)->getPageWidgets()->getWidget(fieldNum); > if (field != NULL) { > PopplerFormField *poppler_field = _form_field_new_from_widget (field); > 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 -r1.21 poppler-document.h 110a111,134 > /* Form */ > void poppler_document_set_form_field_text_content (PopplerDocument *document, > int id, > char *content, > int length); > PopplerFormField *poppler_document_find_form_field_by_id (PopplerDocument *document, > int id); > void poppler_document_set_form_field_button_state (PopplerDocument *document, int id, gboolean state); > > gboolean poppler_document_get_form_field_button_state (PopplerDocument *document, int id); > > gchar * > poppler_document_get_form_field_text_content (PopplerDocument *document, int id, int *length); > int > poppler_document_get_form_field_choice_num_choices (PopplerDocument *document, int id); > gchar * > poppler_document_get_form_field_choice_content (PopplerDocument *document, int id, int index); > void > poppler_document_set_form_field_choice_content (PopplerDocument *document, int id, int index); > > > > > Index: glib/poppler-page.cc =================================================================== RCS file: /cvs/poppler/poppler/glib/poppler-page.cc,v retrieving revision 1.51 diff -r1.51 poppler-page.cc 990a991,1098 > > > /* 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); > } > > PopplerFormField * > _form_field_new_from_widget (FormWidget* field) > { > PopplerFormField *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(); > if (poppler_field->type == POPPLER_FORM_FIELD_TEXT) { > GooString *tmp = static_cast(field)->getContentCopy(); > poppler_field->text.content = (tmp)?tmp->getCString():NULL; > poppler_field->text.length = (tmp)?tmp->getLength():0; > } else if (poppler_field->type == POPPLER_FORM_FIELD_BUTTON) { > poppler_field->button.state = (gboolean)static_cast(field)->getState(); > } else if (poppler_field->type == POPPLER_FORM_FIELD_CHOICE) { > > } > return poppler_field; > } > > /** > * poppler_page_get_form_fields > **/ > > GList* > poppler_page_get_form_fields (PopplerPage *page) > { > GList *field_list = NULL; > FormPageWidgets *form; > gint i; > Object obj; > > g_return_val_if_fail (POPPLER_IS_PAGE (page), NULL); > > form = page->page->getPageWidgets(); > > obj.free (); > if(form == NULL) > return NULL; > > for(i = 0; i < form->getNumWidgets(); i++) { > PopplerFormField *poppler_field; > FormWidget *field; > field = form->getWidget(i); > poppler_field = _form_field_new_from_widget (field); > 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 -r1.21 poppler-page.h 82a83,87 > 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); 114a120,174 > /* FormField */ > #define POPPLER_TYPE_FORM_FIELD (poppler_form_field_get_type ()) > struct _PopplerTextField > { > //flags > char multitine:1; > char password:1; > char fileselect:1; > char do_not_spell_check:1; > char do_not_scroll:1; > char comb:1; > char rich_text:1; > //content > gchar *content; > int length; > }; > > struct _PopplerButtonField > { > //flags > char no_toggle_to_of:1; > char radio:1; > char pushbutton:1; > char radios_in_unison:1; > //content > gboolean state; > }; > > struct _PopplerChoiceField > { > char combo:1; > char edit:1; > char sort:1; > char multi_select:1; > char do_not_spell_check:1; > char commit_on_sel_change:1; > }; > > struct _PopplerFormField > { > PopplerRectangle area; > PopplerFormFieldType type; > int id; > union { > PopplerTextField text; > PopplerButtonField button; > PopplerChoiceField choice; > }; > }; > > 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); > Index: glib/poppler-private.h =================================================================== RCS file: /cvs/poppler/poppler/glib/poppler-private.h,v retrieving revision 1.16 diff -r1.16 poppler-private.h 7a8 > #include 62a64,66 > PopplerFormField *_form_field_new_from_widget (FormWidget* field); > > Index: glib/poppler.h =================================================================== RCS file: /cvs/poppler/poppler/glib/poppler.h,v retrieving revision 1.12 diff -r1.12 poppler.h 44a45,58 > /* 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, > //kid type > POPPLER_FORM_FIELD_BUTTON_CHECK, > POPPLER_FORM_FIELD_BUTTON_PUSH, > POPPLER_FORM_FIELD_BUTTON_RADIO > } PopplerFormFieldType; > > 49a64 > typedef struct _PopplerFormField PopplerFormField; 55c70,72 < --- > typedef struct _PopplerTextField PopplerTextField; > typedef struct _PopplerButtonField PopplerButtonField; > typedef struct _PopplerChoiceField PopplerChoiceField; Index: poppler/Annot.cc =================================================================== RCS file: /cvs/poppler/poppler/poppler/Annot.cc,v retrieving revision 1.5 diff -r1.5 Annot.cc 22a23,24 > #include "GfxFont.h" > #include "CharCodeToUnicode.h" 30d31 < GBool regen, isTextField; 36c37 < --- > 73a75 > regen = gTrue; 79c81 < #if 0 //~ appearance stream generation is not finished yet --- > #if 1 //~ appearance stream generation is not finished yet 86,99c88,101 < if (apObj.dictLookup("N", &obj1)->isDict()) { < if (obj1.dictLookupNF(asObj.getName(), &obj2)->isRef()) { < obj2.copy(&appearance); < ok = gTrue; < } else { < obj2.free(); < if (obj1.dictLookupNF("Off", &obj2)->isRef()) { < obj2.copy(&appearance); < ok = gTrue; < } < } < obj2.free(); < } < obj1.free(); --- > if (apObj.dictLookup("N", &obj1)->isDict()) { > if (obj1.dictLookupNF(asObj.getName(), &obj2)->isRef()) { > obj2.copy(&appearance); > ok = gTrue; > } else { > obj2.free(); > if (obj1.dictLookupNF("Off", &obj2)->isRef()) { > obj2.copy(&appearance); > ok = gTrue; > } > } > obj2.free(); > } > obj1.free(); 101,105c103,107 < if (apObj.dictLookupNF("N", &obj1)->isRef()) { < obj1.copy(&appearance); < ok = gTrue; < } < obj1.free(); --- > if (apObj.dictLookupNF("N", &obj1)->isRef()) { > obj1.copy(&appearance); > ok = gTrue; > } > obj1.free(); 110c112 < #if 0 //~ appearance stream generation is not finished yet --- > #if 1 //~ appearance stream generation is not finished yet 121a124 > 125a129 > GooString *fontName=NULL; 138a143 > //printf("Annot::generateAppearance: %s\n", daStr->getCString()); 141,160c146,177 < for (--i1; i1 >= 0 && Lexer::isSpace(daStr->getChar(i1)); --i1) ; < for (i0 = i1; i0 >= 0 && !Lexer::isSpace(daStr->getChar(i0)); --i0) ; < if (i0 >= 0) { < ++i0; < ++i1; < s = new GooString(daStr, i0, i1 - i0); < fontSize = atof(s->getCString()); < delete s; < < // autosize the font < if (fontSize == 0) { < fontSize = 0.67 * (yMax - yMin); < daStr1 = new GooString(daStr, 0, i0); < sprintf(buf, "%.2f", fontSize); < daStr1->append(buf); < daStr1->append(daStr->getCString() + i1, < daStr->getLength() - i1); < } < } < break; --- > for (--i1; i1 >= 0 && Lexer::isSpace(daStr->getChar(i1)); --i1) ; > for (i0 = i1; i0 >= 0 && !Lexer::isSpace(daStr->getChar(i0)); --i0) ; > if (i0 >= 0) { > ++i0; > ++i1; > s = new GooString(daStr, i0, i1 - i0); > fontSize = atof(s->getCString()); > delete s; > > // autosize the font > if (fontSize == 0) { > fontSize = 0.67 * (yMax - yMin); > daStr1 = new GooString(daStr, 0, i0); > sprintf(buf, "%.2f", fontSize); > daStr1->append(buf); > daStr1->append(daStr->getCString() + i1, > daStr->getLength() - i1); > } > } > > //find the font name > i1=i0; > for (--i1; i1 >= 0 && Lexer::isSpace(daStr->getChar(i1)); --i1) ; > for (i0 = i1; i0 >= 0 && !Lexer::isSpace(daStr->getChar(i0)); --i0) ; > if (i0<0) i0=0; > if (i0 != i1) { > ++i0; > ++i1; > fontName = new GooString(daStr, i0, i1 - i0); > } > > break; 162a180,251 > > //init appearance dictionnary > appearDict.initDict(xref); > > // find the resource dictionary > dict->lookup("DR", &drObj); > if (!drObj.isDict()) { > dict->lookup("Parent", &obj1); > while (obj1.isDict()) { > drObj.free(); > obj1.dictLookup("DR", &drObj); > if (drObj.isDict()) { > break; > } > obj1.dictLookup("Parent", &obj2); > obj1.free(); > obj1 = obj2; > } > obj1.free(); > if (!drObj.isDict()) { > if (acroForm) { > drObj.free(); > acroForm->lookup("DR", &drObj); > } > } > } > CharCodeToUnicode* ccToUnicode = NULL; > if (drObj.isDict()) { > //Lookup for the font name in the font entry of the ressource dictionnary > if (fontName && drObj.dictLookup("Font", &obj1)->isDict()) { > Object obj3, obj4; > //printf("Annot::generateAppearance: looking for font name in ressources: %s\n", fontName->getCString()); > if (obj1.dictLookup(*fontName, &obj3)->isDict() && obj3.dictLookup("Type", &obj4)->isName("Font")) { > obj4.free(); > obj1.dictLookupNF(*fontName, &obj4); > Ref r; > if (obj4.isRef()) r = obj4.getRef(); > else r.gen = r.num = 0; > //FIXME: create the font only once at annot's creation > GfxFont *font = GfxFont::makeFont(xref, "temp", r, obj3.getDict()); > ccToUnicode = font->getToUnicode(); > //printf("Annot::generateAppearance: found font: type : %i\n", font->getType()); > /*if (font->getType() < fontCIDType0) { > ccToUnicode = static_cast(font)->getToUnicode(); > //printf("Annot::generateAppearance: encoding : %i\n", font8->getUsesMacRomanEnc()); > }*/ > #if 0 > if (obj3.dictLookup("Subtype", &obj4)->isName()) > printf("Annot::generateAppearance: -- Found, subtype %s\n", obj4.getName()); > obj4.free(); > // we have an encoding dictionnary -- see Table 5.11 in PDFReference > if (obj3.dictLookup("Encoding", &obj4)->isDict()) { > Object baseEncoding; > if (obj4.dictLookup("BaseEncoding", &baseEncoding)->isName()) { > printf("Annot::generateAppearance: BaseEncoding: %s\n", baseEncoding.getName()); > } else { //implicit BaseEncoding > printf("Annot::generateAppearance: no BaseEncoding\n"); > } > baseEncoding.free(); > } > obj4.free(); > #endif > } > obj3.free(); > } > obj1.free(); > > > appearDict.dictAdd("Resources", drObj.copy(&obj1)); > } > drObj.free(); > 167a257 > //FIXME: this is here that we put the line "Tf /Cour 12" 170,193c260,262 < //~ handle quadding -- this requires finding the font and using < //~ the encoding and char widths < sprintf(buf, "1 0 0 1 %.2f %.2f Tm\n", 2.0, yMax - yMin - fontSize); < appearBuf->append(buf); < sprintf(buf, "%g TL\n", fontSize); < appearBuf->append(buf); < vStr = vObj.getString(); < i0 = 0; < while (i0 < vStr->getLength()) { < for (i1 = i0; < i1 < vStr->getLength() && < vStr->getChar(i1) != '\n' && vStr->getChar(i1) != '\r'; < ++i1) ; < if (i0 > 0) { < appearBuf->append("T*\n"); < } < appearBuf->append('('); < for (; i0 < i1; ++i0) { < c = vStr->getChar(i0); < if (c == '(' || c == ')' || c == '\\') { < appearBuf->append('\\'); < appearBuf->append(c); < } else if (c < 0x20 || c >= 0x80) { < sprintf(buf, "\\%03o", c); --- > //~ handle quadding -- this requires finding the font and using > //~ the encoding and char widths > sprintf(buf, "1 0 0 1 %.2f %.2f Tm\n", 2.0, yMax - yMin - fontSize); 195,206c264,337 < } else { < appearBuf->append(c); < } < } < appearBuf->append(") Tj\n"); < if (i1 + 1 < vStr->getLength() && < vStr->getChar(i1) == '\r' && vStr->getChar(i1 + 1) == '\n') { < i0 = i1 + 2; < } else { < i0 = i1 + 1; < } < } --- > sprintf(buf, "%g TL\n", fontSize); > appearBuf->append(buf); > //FIXME: perhaps unicode handling could be better > printf("Annot.cc: vObj hasUnicodeMarker :%i\n", vObj.getString()->hasUnicodeMarker()); > //UGooString tmp (*vObj.getString()); > vStr = vObj.getString(); > //printf("Annot.cc: %s length %i\n", tmp->getCString(), tmp->getLength()); > //vStr = new GooString(tmp->getCString(), tmp->getLength()); > //skip the first two chars if they are the unicode marker > if (vStr->hasUnicodeMarker()) i0 = 2; > else i0 = 0; > while (i0 < vStr->getLength()) { > for (i1 = i0; > i1 < vStr->getLength() && > vStr->getChar(i1) != '\n' && vStr->getChar(i1) != '\r'; > ++i1) ; > if (i0 > 0 && !(i0 <= 2 && vStr->hasUnicodeMarker())) { // add a newline, excepted if we are in the unicode marker > appearBuf->append("T*\n"); > } > appearBuf->append('('); > //simple string, write it directly > if (!vStr->hasUnicodeMarker()) { > for (; i0 < i1; ++i0) { > c = vStr->getChar(i0); > if (c == '(' || c == ')' || c == '\\') { > appearBuf->append('\\'); > appearBuf->append(c); > } else if (c < 0x20 || c >= 0x80) { > sprintf(buf, "\\%03o", c); > appearBuf->append(buf); > } else { > appearBuf->append(c); > } > } > //unicode string, convert it > } else { > for (;i0 char ctmp[2]; > printf("vStr->getChar: 0x%x\n", vStr->getChar(i0+1)); > ctmp[0] = vStr->getChar(i0+1); > ctmp[1] = 0; > /*ctmp[1] = vStr->getChar(i0+1);*/ > CharCode ch; > if(ccToUnicode) { > ccToUnicode->mapToCharCode(*(Unicode*)ctmp, &ch, 1); > printf("Annot::generateAppearance, CharCode: %i\n", ch); > appearBuf->append(ch); > } else { > //FIXME: should this really happens ? > // we cannot translate this character from Unicode to CharCode. > // We write it directly, _hoping_ it will be understood correctly > printf("Annot::generateAppearance, NO ccToUnicode\n"); > ch = ctmp[0]; > if (ch == '(' || ch == ')' || c == '\\') { > appearBuf->append('\\'); > appearBuf->append(c); > } else if (ch < 0x20 || ch >= 0x80) { > sprintf(buf, "\\%03o", ch); > appearBuf->append(buf); > } else { > appearBuf->append(ch); > } > } > } > } > appearBuf->append(") Tj\n"); > if (i1 + 1 < vStr->getLength() && > vStr->getChar(i1) == '\r' && vStr->getChar(i1 + 1) == '\n') { > i0 = i1 + 2; > } else { > i0 = i1 + 1; > } > } > //delete vStr; 207a339 > 213d344 < appearDict.initDict(xref); 222,249c353 < < // find the resource dictionary < dict->lookup("DR", &drObj); < if (!drObj.isDict()) { < dict->lookup("Parent", &obj1); < while (obj1.isDict()) { < drObj.free(); < obj1.dictLookup("DR", &drObj); < if (drObj.isDict()) { < break; < } < obj1.dictLookup("Parent", &obj2); < obj1.free(); < obj1 = obj2; < } < obj1.free(); < if (!drObj.isDict()) { < if (acroForm) { < drObj.free(); < acroForm->lookup("DR", &drObj); < } < } < } < if (drObj.isDict()) { < appearDict.dictAdd("Resources", drObj.copy(&obj1)); < } < drObj.free(); < --- > 252c356 < appearBuf->getLength(), &appearDict); --- > appearBuf->getLength(), &appearDict); 260a365,366 > > if (fontName) delete fontName; 265d370 < 292,301c397,406 < annot = new Annot(xref, acroForm, obj1.getDict()); < if (annot->isOk()) { < if (nAnnots >= size) { < size += 16; < annots = (Annot **)greallocn(annots, size, sizeof(Annot *)); < } < annots[nAnnots++] = annot; < } else { < delete annot; < } --- > annot = new Annot(xref, acroForm, obj1.getDict()); > if (annot->isOk()) { > if (nAnnots >= size) { > size += 16; > annots = (Annot **)greallocn(annots, size, sizeof(Annot *)); > } > annots[nAnnots++] = annot; > } else { > delete annot; > } Index: poppler/Annot.h =================================================================== RCS file: /cvs/poppler/poppler/poppler/Annot.h,v retrieving revision 1.2 diff -r1.2 Annot.h 29a30 > GBool textField() { return isTextField; } 35c36,37 < --- > double getXMin() { return xMin; } > double getYMin() { return yMin; } 40,42c42,44 < XRef *xref; // the xref table for this PDF file < Object appearance; // a reference to the Form XObject stream < // for the normal appearance --- > XRef *xref; // the xref table for this PDF file > Object appearance; // a reference to the Form XObject stream > // for the normal appearance 44c46 < double xMin, yMin, // annotation rectangle --- > double xMin, yMin, // annotation rectangle 46a49,50 > > GBool regen, isTextField; Index: poppler/Catalog.cc =================================================================== RCS file: /cvs/poppler/poppler/poppler/Catalog.cc,v retrieving revision 1.17 diff -r1.17 Catalog.cc 27a28 > #include "Form.h" 45a47 > form = NULL; 51a54,63 > // get the AcroForm dictionary > catDict.dictLookup("AcroForm", &acroForm); > > // load Forms > printf("--------- Loading FORM for Document -------\n"); > if (acroForm.isDict()) { > form = new Form(xref,&acroForm); > } > printf("--------- done loading FORM -------\n"); > 155,157c167 < // get the AcroForm dictionary < catDict.dictLookup("AcroForm", &acroForm); < --- > 239c249 < page = new Page(xref, start+1, kid.getDict(), attrs2); --- > page = new Page(xref, start+1, kid.getDict(), attrs2, form); Index: poppler/Catalog.h =================================================================== RCS file: /cvs/poppler/poppler/poppler/Catalog.h,v retrieving revision 1.8 diff -r1.8 Catalog.h 23a24 > class Form; 180a182 > Form *form; Index: poppler/CharCodeToUnicode.cc =================================================================== RCS file: /cvs/poppler/poppler/poppler/CharCodeToUnicode.cc,v retrieving revision 1.4 diff -r1.4 CharCodeToUnicode.cc 506a507,544 > int CharCodeToUnicode::mapToCharCode(Unicode u, CharCode *c, int usize) { > //FIXME: .. > //look for charcode in map > /* if (usize == 1) {*/ > /* printf("CharCodeToUnicode::mapToCharCode: 0x%x \n", u&0xff);*/ > for (int i=0; i /* printf("0x%x\n", map[i]);*/ > if (map[i] == (u&0xff)) { > /* printf("FOUND ! \n");*/ > *c = (char)map[i]; > return 1; > } > } > *c = 'x'; > /* } else { > int i, j; > //for each entry in the sMap > for (i=0; i //if the entry's unicode length isn't the same are usize, the strings > // are obviously differents > if (sMap[i].len != usize) continue; > //compare the string char by char > for (j=0; j if (sMap[i].u[j] != u[j]) { > continue; > } > } > > //we have the same strings > if (j==sMap[i].len) { > *c = sMap[i].c; > return 1; > } > } > }*/ > return 0; > } > Index: poppler/CharCodeToUnicode.h =================================================================== RCS file: /cvs/poppler/poppler/poppler/CharCodeToUnicode.h,v retrieving revision 1.2 diff -r1.2 CharCodeToUnicode.h 29a30 > friend class UnicodeToCharCode; 68a70,71 > int mapToCharCode(Unicode u, CharCode *c, int usize); > Index: poppler/Dict.cc =================================================================== RCS file: /cvs/poppler/poppler/poppler/Dict.cc,v retrieving revision 1.5 diff -r1.5 Dict.cc 67a68,99 > void Dict::remove(const UGooString &key) { > int i; > bool found = false; > DictEntry tmp; > if(length == 0) return; > > for(i=0; i if (!key.cmp(entries[i].key)) { > found = true; > break; > } > } > if(!found) return; > //replace the deleted entry with the last entry > length -= 1; > tmp = entries[length]; > if (i!=length) //don't copy the last entry if it is deleted > entries[i] = tmp; > } > > void Dict::set(const UGooString &key, Object *val) { > DictEntry *e; > e = find (key); > if (e) { > e->val.free(); > e->val = *val; > } else { > add (key, val); > } > } > > Index: poppler/Dict.h =================================================================== RCS file: /cvs/poppler/poppler/poppler/Dict.h,v retrieving revision 1.4 diff -r1.4 Dict.h 52a53,56 > // Update the value of an existing entry, otherwise create it > void set(const UGooString &key, Object *val); > // Remove an entry. This invalidate indexes > void remove(const UGooString &key); Index: poppler/GfxFont.h =================================================================== RCS file: /cvs/poppler/poppler/poppler/GfxFont.h,v retrieving revision 1.4 diff -r1.4 GfxFont.h 169a170,172 > // Return the Unicode map. > virtual CharCodeToUnicode *getToUnicode() = 0; > Index: poppler/Makefile.am =================================================================== RCS file: /cvs/poppler/poppler/poppler/Makefile.am,v retrieving revision 1.26 diff -r1.26 Makefile.am 118a119 > Form.h \ 180a182 > Form.cc \ Index: poppler/Object.h =================================================================== RCS file: /cvs/poppler/poppler/poppler/Object.h,v retrieving revision 1.3 diff -r1.3 Object.h 173a174 > void dictSet(const UGooString &key, Object *val); 256a258,260 > inline void Object::dictSet(const UGooString &key, Object *val) > { dict->set(key, val); } > Index: poppler/PDFDoc.cc =================================================================== RCS file: /cvs/poppler/poppler/poppler/PDFDoc.cc,v retrieving revision 1.10 diff -r1.10 PDFDoc.cc 42d41 < 127a127 > form = NULL; 203a204 > 211,212c212,213 < < #ifndef DISABLE_OUTLINE --- > > #ifndef DISABLE_OUTLINE 464c465 < GBool PDFDoc::saveAs(GooString *name) { --- > GBool PDFDoc::saveAs(GooString *name, PDFWriteMode mode) { 466d466 < int c; 471a472,507 > > if (mode == writeForceRewrite) { > saveCompleteRewrite(f); > } else if (mode == writeForceIncremental) { > saveIncrementalUpdate(f); > } else { // let poppler decide > // find if we have updated objects > GBool updated = gFalse; > for(int i=0; igetNumObjects(); i++) { > if (xref->getEntry(i)->obj) { > updated = gTrue; > break; > } > } > if(updated) { > saveCompleteRewrite(f); > } else { > // simply copy the original file > int c; > str->reset(); > while ((c = str->getChar()) != EOF) { > fputc(c, f); > } > str->close(); > } > } > > fclose(f); > return gTrue; > } > > void PDFDoc::saveIncrementalUpdate (FILE *f) > { > XRef *uxref; > int c; > //copy the original file 477,478c513,738 < fclose(f); < return gTrue; --- > > uxref = new XRef(); > uxref->add(0, 65535, 0, gFalse); > int objectsCount = 0; //count the number of objects in the XRef(s) > for(int i=0; igetNumObjects(); i++) { > if ((xref->getEntry(i)->type == xrefEntryFree) && > (xref->getEntry(i)->gen == 0)) //we skip the irrelevant free objects > continue; > objectsCount++; > if (xref->getEntry(i)->obj) { //we have an updated object > Object obj1; > Ref ref; > ref.num = i; > ref.gen = xref->getEntry(i)->gen; > xref->fetch(ref.num, ref.gen, &obj1); > Guint offset = writeObject(&obj1, &ref, f); > uxref->add(ref.num, ref.gen, offset, gTrue); > obj1.free(); > } > } > if (uxref->getSize() == 0) { //we have nothing to update > delete uxref; > return; > } > > Guint uxrefOffset = ftell(f); > uxref->writeToFile(f); > > writeTrailer(uxrefOffset, objectsCount, f, gTrue); > > delete uxref; > } > > void PDFDoc::saveCompleteRewrite (FILE *f) > { > fprintf(f, "%%PDF-%.1f\r\n",pdfVersion); > XRef *uxref = new XRef(); > uxref->add(0, 65535, 0, gFalse); > for(int i=0; igetNumObjects(); i++) { > Object obj1; > Ref ref; > XRefEntryType type = xref->getEntry(i)->type; > if (type == xrefEntryFree) { > ref.num = i; > ref.gen = xref->getEntry(i)->gen; > /* the XRef class add a lot of unrelevant free entries, we only want the significant one > and we don't want the one with num=0 because it has already been added (gen = 65535)*/ > if (ref.gen > 0 && ref.num > 0) > uxref->add(ref.num, ref.gen, 0, gFalse); > } else if (type == xrefEntryUncompressed){ > ref.num = i; > ref.gen = xref->getEntry(i)->gen; > xref->fetch(ref.num, ref.gen, &obj1); > Guint offset = writeObject(&obj1, &ref, f); > uxref->add(ref.num, ref.gen, offset, gTrue); > obj1.free(); > } else if (type == xrefEntryCompressed) { > ref.num = i; > ref.gen = 0; //compressed entries have gen == 0 > xref->fetch(ref.num, ref.gen, &obj1); > Guint offset = writeObject(&obj1, &ref, f); > uxref->add(ref.num, ref.gen, offset, gTrue); > obj1.free(); > } > } > Guint uxrefOffset = ftell(f); > uxref->writeToFile(f); > > writeTrailer(uxrefOffset, uxref->getSize(), f, gFalse); > > > delete uxref; > > } > > void PDFDoc::writeDictionnary (Dict* dict, FILE *f) > { > Object obj1; > fprintf(f,"<< "); > for (int i=0; igetLength(); i++) { > fprintf(f,"/%s ", dict->getKey(i)->getCString()); > writeObject(dict->getValNF(i, &obj1), NULL, f); > fprintf(f,"\r\n"); > > obj1.free(); > } > fprintf(f,">>\r\n"); > } > > void PDFDoc::writeStream (Stream* str, FILE *f) > { > int c; > fprintf(f,"stream\r\n"); > str->reset(); > for (int c=str->getChar(); c!= EOF; c=str->getChar()) { > fprintf(f,"%c", c); > } > fprintf(f,"\r\nendstream\r\n"); > } > > void PDFDoc::writeString (GooString* s, FILE* f) > { > //write hexa string > const char* c = s->getCString(); > fprintf(f, "<"); > while(*c!='\0') { > fprintf(f, "%02x", *c); > c++; > } > fprintf(f, "> "); > } > > Guint PDFDoc::writeObject (Object* obj, Ref* ref, FILE *f) > { > Array *array; > Object obj1; > Guint offset = ftell(f); > int tmp; > > if(ref) > fprintf(f,"%i %i obj\r\n", ref->num, ref->gen); > > switch (obj->getType()) { > case objBool: > fprintf(f,"%s ", obj->getBool()?"true":"false"); > break; > case objInt: > fprintf(f,"%i ", obj->getInt()); > break; > case objReal: > fprintf(f,"%f ", obj->getReal()); > break; > case objString: > writeString(obj->getString(), f); > break; > case objName: > fprintf(f,"/%s ", obj->getName()); > break; > case objNull: > fprintf(f, "null\r\n"); > break; > case objArray: > array = obj->getArray(); > fprintf(f,"["); > for (int i=0; igetLength(); i++) { > writeObject(array->getNF(i, &obj1), NULL,f); > obj1.free(); > } > fprintf(f,"]"); > break; > case objDict: > writeDictionnary (obj->getDict(),f); > break; > case objStream: > //we write the stream unencoded => TODO: write stream encoder > obj->getStream()->reset(); > //recalculate stream length > tmp = 0; > for (int c=obj->getStream()->getChar(); c!=EOF; c=obj->getStream()->getChar()) { > tmp++; > } > obj1.initInt(tmp); > obj->getStream()->getDict()->set("Length", &obj1); > > //Remove Stream encoding > obj->getStream()->getDict()->remove("Filter"); > obj->getStream()->getDict()->remove("DecodeParms"); > > writeDictionnary (obj->getStream()->getDict(),f); > writeStream (obj->getStream(),f); > obj1.free(); > break; > case objRef: > fprintf(f,"%i %i R ", obj->getRef().num, obj->getRef().gen); > break; > case objCmd: > printf("objCmd\n"); > fprintf(f,"null\r\n"); > break; > case objError: > printf("objError\n"); > fprintf(f,"null\r\n"); > break; > case objEOF: > printf("objEOF\n"); > fprintf(f,"null\r\n"); > break; > case objNone: > printf("objNone\n"); > fprintf(f,"null\r\n"); > break; > default: > error(-1,"Unhandled objType : %i, please report a bug with a testcase\r\n", obj->getType()); > break; > } > if (ref) > fprintf(f,"endobj\r\n\r\n"); > return offset; > } > > void PDFDoc::writeTrailer (Guint uxrefOffset, int uxrefSize, FILE* f, GBool incrUpdate) > { > //Dict* trailerDict = xref->getTrailerDict()->getDict(); > Dict *trailerDict = new Dict(xref); > Object obj1; > obj1.initInt(uxrefSize); > trailerDict->set("Size", &obj1); > obj1.free(); > if(xref->getTrailerDict()->getDict()->lookup("ID", &obj1) != NULL) { > trailerDict->set("ID", &obj1); > obj1.free(); > } > obj1.initRef(xref->getRootNum(), xref->getRootGen()); > trailerDict->set("Root", &obj1); > obj1.free(); > > if (incrUpdate) { > obj1.initInt(xref->getLastXRefPos()); > trailerDict->set("Prev", &obj1); > obj1.free(); > } > fprintf(f, "trailer\r\n"); > writeDictionnary(trailerDict, f); > fprintf(f, "startxref\r\n"); > fprintf(f, "%i\r\n", uxrefOffset); > fprintf(f, "%%%%EOF\r\n"); Index: poppler/PDFDoc.h =================================================================== RCS file: /cvs/poppler/poppler/poppler/PDFDoc.h,v retrieving revision 1.7 diff -r1.7 PDFDoc.h 29a30,35 > enum PDFWriteMode { > writeStandard, > writeForceRewrite, > writeForceIncremental > }; > 166,167c172,173 < // Save this file with another name. < GBool saveAs(GooString *name); --- > // Save this file with another name > GBool saveAs(GooString *name, PDFWriteMode mode=writeStandard); 172a179,186 > // Add object to current file stream and return the offset of the beginning of the object > Guint writeObject (Object *obj, Ref *ref, FILE* f); > void writeDictionnary (Dict* dict, FILE* f); > void writeStream (Stream* str, FILE* f); > void writeTrailer (Guint uxrefOffset, int uxrefSize, FILE* f, GBool incrUpdate); > void writeString (GooString* s, FILE* f); > void saveIncrementalUpdate (FILE* f); > void saveCompleteRewrite (FILE* f); 191d204 < Index: poppler/Page.cc =================================================================== RCS file: /cvs/poppler/poppler/poppler/Page.cc,v retrieving revision 1.13 diff -r1.13 Page.cc 28a29 > #include "Form.h" 32a34 > #include "Form.h" 173c175 < t = tmp.x1; tmp.x1 = tmp.x2; tmp.x2 = t; --- > t = tmp.x1; tmp.x1 = tmp.x2; tmp.x2 = t; 176c178 < t = tmp.y1; tmp.y1 = tmp.y2; tmp.y2 = t; --- > t = tmp.y1; tmp.y1 = tmp.y2; tmp.y2 = t; 191c193,194 < Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA) { --- > Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA, Form *form) { > Object obj; 203c206 < num, trans.getTypeName()); --- > num, trans.getTypeName()); 211c214 < num, annots.getTypeName()); --- > num, annots.getTypeName()); 215a219,224 > // forms > printf("--------- Loading FORMS for Page %i -------\n", numA); > pageWidgets = new FormPageWidgets(xrefA, this->getAnnots(&obj),num,form); > obj.free(); > printf("--------- done loading FORMS\n"); > 219c228 < contents.isNull())) { --- > contents.isNull())) { 221c230 < num, contents.getTypeName()); --- > num, contents.getTypeName()); 260,263c269,272 < int rotate, GBool useMediaBox, GBool crop, < Links *links, Catalog *catalog, < GBool (*abortCheckCbk)(void *data), < void *abortCheckCbkData, --- > int rotate, GBool useMediaBox, GBool crop, > Links *links, Catalog *catalog, > GBool (*abortCheckCbk)(void *data), > void *abortCheckCbkData, 267c276 < abortCheckCbk, abortCheckCbkData, --- > abortCheckCbk, abortCheckCbkData, 272,278c281,287 < 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) { --- > 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) { 299,300c308,309 < box.x1 = baseBox->x1 + ky * sliceY; < box.x2 = baseBox->x1 + ky * (sliceY + sliceH); --- > box.x1 = baseBox->x1 + ky * sliceY; > box.x2 = baseBox->x1 + ky * (sliceY + sliceH); 302,303c311,312 < box.x1 = baseBox->x2 - ky * (sliceY + sliceH); < box.x2 = baseBox->x2 - ky * sliceY; --- > box.x1 = baseBox->x2 - ky * (sliceY + sliceH); > box.x2 = baseBox->x2 - ky * sliceY; 311,312c320,321 < box.y1 = baseBox->y1 + ky * sliceY; < box.y2 = baseBox->y1 + ky * (sliceY + sliceH); --- > box.y1 = baseBox->y1 + ky * sliceY; > box.y2 = baseBox->y1 + ky * (sliceY + sliceH); 314,315c323,324 < box.y1 = baseBox->y2 - ky * (sliceY + sliceH); < box.y2 = baseBox->y2 - ky * sliceY; --- > box.y1 = baseBox->y2 - ky * (sliceY + sliceH); > box.y2 = baseBox->y2 - ky * sliceY; 319,320c328,329 < box.x1 = baseBox->x2 - ky * (sliceY + sliceH); < box.x2 = baseBox->x2 - ky * sliceY; --- > box.x1 = baseBox->x2 - ky * (sliceY + sliceH); > box.x2 = baseBox->x2 - ky * sliceY; 322,323c331,332 < box.x1 = baseBox->x1 + ky * sliceY; < box.x2 = baseBox->x1 + ky * (sliceY + sliceH); --- > box.x1 = baseBox->x1 + ky * sliceY; > box.x2 = baseBox->x1 + ky * (sliceY + sliceH); 331,332c340,341 < box.y1 = baseBox->y2 - ky * (sliceY + sliceH); < box.y2 = baseBox->y2 - ky * sliceY; --- > box.y1 = baseBox->y2 - ky * (sliceY + sliceH); > box.y2 = baseBox->y2 - ky * sliceY; 334,335c343,344 < box.y1 = baseBox->y1 + ky * sliceY; < box.y2 = baseBox->y1 + ky * (sliceY + sliceH); --- > box.y1 = baseBox->y1 + ky * sliceY; > box.y2 = baseBox->y1 + ky * (sliceY + sliceH); 347c356 < mediaBox->x1, mediaBox->y1, mediaBox->x2, mediaBox->y2); --- > mediaBox->x1, mediaBox->y1, mediaBox->x2, mediaBox->y2); 349c358 < cropBox->x1, cropBox->y1, cropBox->x2, cropBox->y2); --- > cropBox->x1, cropBox->y1, cropBox->x2, cropBox->y2); 354,355c363,364 < hDPI, vDPI, &box, crop ? cropBox : (PDFRectangle *)NULL, < rotate, abortCheckCbk, abortCheckCbkData); --- > hDPI, vDPI, &box, crop ? cropBox : (PDFRectangle *)NULL, > rotate, abortCheckCbk, abortCheckCbkData); 361,365c370,374 < int rotate, GBool useMediaBox, GBool crop, < int sliceX, int sliceY, int sliceW, int sliceH, < Links *links, Catalog *catalog, < GBool (*abortCheckCbk)(void *data), < void *abortCheckCbkData, --- > int rotate, GBool useMediaBox, GBool crop, > int sliceX, int sliceY, int sliceW, int sliceH, > Links *links, Catalog *catalog, > GBool (*abortCheckCbk)(void *data), > void *abortCheckCbkData, 375,378c384,387 < sliceX, sliceY, sliceW, sliceH, < links, catalog, < abortCheckCbk, abortCheckCbkData, < annotDisplayDecideCbk, annotDisplayDecideCbkData); --- > sliceX, sliceY, sliceW, sliceH, > links, catalog, > abortCheckCbk, abortCheckCbkData, > annotDisplayDecideCbk, annotDisplayDecideCbkData); 410,411c419,421 < !annotDisplayDecideCbk) < annot->draw(gfx); --- > !annotDisplayDecideCbk) { > annot->draw(gfx); > } 433,434c443,444 < int *width_out, int *height_out, < int *rowstride_out) --- > int *width_out, int *height_out, > int *rowstride_out) 458c468 < --- > 465c475 < --- > 501,502c511,512 < colorMap->getNumPixelComps(), < colorMap->getBits()); --- > colorMap->getNumPixelComps(), > colorMap->getBits()); 538c548 < int rotate, GBool upsideDown) { --- > int rotate, GBool upsideDown) { Index: poppler/Page.h =================================================================== RCS file: /cvs/poppler/poppler/poppler/Page.h,v retrieving revision 1.6 diff -r1.6 Page.h 25a26,27 > class FormPageWidgets; > class Form; 107c109 < Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA); --- > Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA, Form *form); 153a156,158 > // Get form. > FormPageWidgets *getPageWidgets() { return pageWidgets; } > 197a203 > FormPageWidgets *pageWidgets; // the form for that page Index: poppler/XRef.cc =================================================================== RCS file: /cvs/poppler/poppler/poppler/XRef.cc,v retrieving revision 1.13 diff -r1.13 XRef.cc 203a204,213 > XRef::XRef() { > ok = gTrue; > errCode = errNone; > entries = NULL; > size = 0; > streamEnds = NULL; > streamEndsLen = 0; > objStr = NULL; > } > 266a277,280 > for(int i=0; i if (entries[i].obj) > delete entries[i].obj; > } 267a282 > 399a415 > entries[i].obj = NULL; 412a429 > entry.obj = NULL; 509a527 > entries[i].obj = NULL; 603a622 > entries[i].obj = NULL; 743a763 > entries[i].obj = NULL; 852a873,876 > if(e->obj) { //check for updated object > obj = e->obj->copy(obj); > return obj; > } 969a994,1056 > > void XRef::add(int num, int gen, Guint offs, GBool used) { > size += 1; > entries = (XRefEntry *)greallocn(entries, size, sizeof(XRefEntry)); > XRefEntry *e = &entries[size-1]; > > e->gen = gen; > e->num = num; > e->obj = NULL; > if (used) { > e->type = xrefEntryUncompressed; > e->offset = offs; > } else { > e->type = xrefEntryFree; > e->offset = 0; > } > } > > void XRef::setModifiedObject (Object* o, Ref r) { > if (r.num < 0 || r.num >= size) { > error(-1,"XRef::setModifiedObject on unknown ref: %i, %i\n", r.num, r.gen); > return; > } > entries[r.num].obj = new Object(); > o->copy(entries[r.num].obj); > } > > //used to sort the entries > int compare (const void* a, const void* b) > { > return (((XRefEntry*)a)->num - ((XRefEntry*)b)->num); > } > > void XRef::writeToFile(FILE* file) { > qsort(entries, size, sizeof(XRefEntry), compare); > //create free entries linked-list > if (entries[0].gen != 65535) { > error(-1, "XRef::writeToFile, entry 0 of the XRef is invalid (gen != 65535)\n"); > } > int lastFreeEntry = 0; > for (int i=0; i if (entries[i].type == xrefEntryFree) { > entries[lastFreeEntry].offset = entries[i].num; > lastFreeEntry = i; > } > } > //write the new xref > int j; > fprintf(file,"xref\r\n"); > for (int i=0; i for(j=i; j if (j!=i && entries[j].num != entries[j-1].num+1) > break; > } > fprintf(file,"%i %i\r\n", entries[i].num, j-i); > for (int k=i; k if(entries[k].gen > 65535) entries[k].gen = 65535; //cap generation number to 65535 (required by PDFReference) > fprintf(file,"%010i %05i %c\r\n", entries[k].offset, entries[k].gen, (entries[k].type==xrefEntryFree)?'f':'n'); > } > i = j-1; > } > } > Index: poppler/XRef.h =================================================================== RCS file: /cvs/poppler/poppler/poppler/XRef.h,v retrieving revision 1.6 diff -r1.6 XRef.h 36a37 > int num; 37a39 > Object* obj; 42a45,46 > // Constructor, create an empty XRef, used for PDF writing > XRef(); 104a109,113 > // Write access > void setModifiedObject(Object* o, Ref r); > void add(int num, int gen, Guint offs, GBool used); > void writeToFile(FILE* f); > Index: test/Makefile.am =================================================================== RCS file: /cvs/poppler/poppler/test/Makefile.am,v retrieving revision 1.8 diff -r1.8 Makefile.am 28a29,32 > pdf_modification_test = \ > pdf-modification-test > > 39c43 < noinst_PROGRAMS = $(gtk_splash_test) $(gtk_cairo_test) $(pdf_inspector) --- > noinst_PROGRAMS = $(gtk_splash_test) $(gtk_cairo_test) $(pdf_inspector) $(pdf_modification_test) 67a72,78 > pdf_modification_test_SOURCES = \ > pdf-modification-test.cc > > pdf_modification_test_LDADD = \ > $(top_builddir)/poppler/libpoppler.la > >