Index: PDFDoc.cc =================================================================== RCS file: /cvs/poppler/poppler/poppler/PDFDoc.cc,v retrieving revision 1.10 diff -r1.10 PDFDoc.cc 127a128 > form = NULL; 203a205 > 212c214 < #ifndef DISABLE_OUTLINE --- > #ifndef DISABLE_OUTLINE 464c466 < GBool PDFDoc::saveAs(GooString *name) { --- > GBool PDFDoc::saveAs(GooString *name, PDFWriteMode mode) { 466d467 < int c; 471a473,491 > > 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; 476a497,499 > } > } > 480a504,741 > void PDFDoc::saveIncrementalUpdate (FILE *f) > { > XRef *uxref; > int c; > //copy the original file > str->reset(); > while ((c = str->getChar()) != EOF) { > fputc(c, f); > } > str->close(); > > 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: 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);