git-svn-id: svn://svn.code.sf.net/p/xournal/svn/trunk@52 9fe2bcd3-a095-4d8b-a836-9b85dc8d7627

presentation
andreasb123 15 years ago
parent a5134535f4
commit 0b36d583ee
  1. 2
      src/Makefile.am
  2. 42
      src/Makefile.in
  3. 342
      src/pdf/PdfExport.cpp
  4. 24
      src/pdf/PdfExport.h
  5. 226
      src/pdf/PdfObjectWriter.cpp
  6. 41
      src/pdf/PdfObjectWriter.h
  7. 61
      src/pdf/PdfRefList.cpp
  8. 46
      src/pdf/PdfRefList.h

@ -90,7 +90,9 @@ xournalpp_SOURCES = \
pdf/PdfExport.cpp \
pdf/PdfExtGState.cpp \
pdf/PdfFont.cpp \
pdf/PdfObjectWriter.cpp \
pdf/PdfRefEntry.cpp \
pdf/PdfRefList.cpp \
pdf/PdfUtil.cpp \
pdf/PdfWriter.cpp \
pdf/PdfXRef.cpp \

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.11 from Makefile.am.
# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@ -111,9 +111,11 @@ am_xournalpp_OBJECTS = xournalpp-BlockingJob.$(OBJEXT) \
xournalpp-XojPopplerPage.$(OBJEXT) \
xournalpp-PdfBookmark.$(OBJEXT) xournalpp-PdfExport.$(OBJEXT) \
xournalpp-PdfExtGState.$(OBJEXT) xournalpp-PdfFont.$(OBJEXT) \
xournalpp-PdfRefEntry.$(OBJEXT) xournalpp-PdfUtil.$(OBJEXT) \
xournalpp-PdfWriter.$(OBJEXT) xournalpp-PdfXRef.$(OBJEXT) \
xournalpp-UpdateRef.$(OBJEXT) xournalpp-UpdateRefKey.$(OBJEXT) \
xournalpp-PdfObjectWriter.$(OBJEXT) \
xournalpp-PdfRefEntry.$(OBJEXT) xournalpp-PdfRefList.$(OBJEXT) \
xournalpp-PdfUtil.$(OBJEXT) xournalpp-PdfWriter.$(OBJEXT) \
xournalpp-PdfXRef.$(OBJEXT) xournalpp-UpdateRef.$(OBJEXT) \
xournalpp-UpdateRefKey.$(OBJEXT) \
xournalpp-ColorUndoAction.$(OBJEXT) \
xournalpp-DeleteUndoAction.$(OBJEXT) \
xournalpp-EraseUndoAction.$(OBJEXT) \
@ -376,7 +378,9 @@ xournalpp_SOURCES = \
pdf/PdfExport.cpp \
pdf/PdfExtGState.cpp \
pdf/PdfFont.cpp \
pdf/PdfObjectWriter.cpp \
pdf/PdfRefEntry.cpp \
pdf/PdfRefList.cpp \
pdf/PdfUtil.cpp \
pdf/PdfWriter.cpp \
pdf/PdfXRef.cpp \
@ -557,8 +561,10 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xournalpp-PdfExportJob.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xournalpp-PdfExtGState.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xournalpp-PdfFont.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xournalpp-PdfObjectWriter.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xournalpp-PdfPagesDialog.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xournalpp-PdfRefEntry.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xournalpp-PdfRefList.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xournalpp-PdfUtil.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xournalpp-PdfView.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xournalpp-PdfWriter.Po@am__quote@
@ -1830,6 +1836,20 @@ xournalpp-PdfFont.obj: pdf/PdfFont.cpp
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xournalpp_CXXFLAGS) $(CXXFLAGS) -c -o xournalpp-PdfFont.obj `if test -f 'pdf/PdfFont.cpp'; then $(CYGPATH_W) 'pdf/PdfFont.cpp'; else $(CYGPATH_W) '$(srcdir)/pdf/PdfFont.cpp'; fi`
xournalpp-PdfObjectWriter.o: pdf/PdfObjectWriter.cpp
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xournalpp_CXXFLAGS) $(CXXFLAGS) -MT xournalpp-PdfObjectWriter.o -MD -MP -MF $(DEPDIR)/xournalpp-PdfObjectWriter.Tpo -c -o xournalpp-PdfObjectWriter.o `test -f 'pdf/PdfObjectWriter.cpp' || echo '$(srcdir)/'`pdf/PdfObjectWriter.cpp
@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/xournalpp-PdfObjectWriter.Tpo $(DEPDIR)/xournalpp-PdfObjectWriter.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='pdf/PdfObjectWriter.cpp' object='xournalpp-PdfObjectWriter.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xournalpp_CXXFLAGS) $(CXXFLAGS) -c -o xournalpp-PdfObjectWriter.o `test -f 'pdf/PdfObjectWriter.cpp' || echo '$(srcdir)/'`pdf/PdfObjectWriter.cpp
xournalpp-PdfObjectWriter.obj: pdf/PdfObjectWriter.cpp
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xournalpp_CXXFLAGS) $(CXXFLAGS) -MT xournalpp-PdfObjectWriter.obj -MD -MP -MF $(DEPDIR)/xournalpp-PdfObjectWriter.Tpo -c -o xournalpp-PdfObjectWriter.obj `if test -f 'pdf/PdfObjectWriter.cpp'; then $(CYGPATH_W) 'pdf/PdfObjectWriter.cpp'; else $(CYGPATH_W) '$(srcdir)/pdf/PdfObjectWriter.cpp'; fi`
@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/xournalpp-PdfObjectWriter.Tpo $(DEPDIR)/xournalpp-PdfObjectWriter.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='pdf/PdfObjectWriter.cpp' object='xournalpp-PdfObjectWriter.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xournalpp_CXXFLAGS) $(CXXFLAGS) -c -o xournalpp-PdfObjectWriter.obj `if test -f 'pdf/PdfObjectWriter.cpp'; then $(CYGPATH_W) 'pdf/PdfObjectWriter.cpp'; else $(CYGPATH_W) '$(srcdir)/pdf/PdfObjectWriter.cpp'; fi`
xournalpp-PdfRefEntry.o: pdf/PdfRefEntry.cpp
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xournalpp_CXXFLAGS) $(CXXFLAGS) -MT xournalpp-PdfRefEntry.o -MD -MP -MF $(DEPDIR)/xournalpp-PdfRefEntry.Tpo -c -o xournalpp-PdfRefEntry.o `test -f 'pdf/PdfRefEntry.cpp' || echo '$(srcdir)/'`pdf/PdfRefEntry.cpp
@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/xournalpp-PdfRefEntry.Tpo $(DEPDIR)/xournalpp-PdfRefEntry.Po
@ -1844,6 +1864,20 @@ xournalpp-PdfRefEntry.obj: pdf/PdfRefEntry.cpp
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xournalpp_CXXFLAGS) $(CXXFLAGS) -c -o xournalpp-PdfRefEntry.obj `if test -f 'pdf/PdfRefEntry.cpp'; then $(CYGPATH_W) 'pdf/PdfRefEntry.cpp'; else $(CYGPATH_W) '$(srcdir)/pdf/PdfRefEntry.cpp'; fi`
xournalpp-PdfRefList.o: pdf/PdfRefList.cpp
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xournalpp_CXXFLAGS) $(CXXFLAGS) -MT xournalpp-PdfRefList.o -MD -MP -MF $(DEPDIR)/xournalpp-PdfRefList.Tpo -c -o xournalpp-PdfRefList.o `test -f 'pdf/PdfRefList.cpp' || echo '$(srcdir)/'`pdf/PdfRefList.cpp
@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/xournalpp-PdfRefList.Tpo $(DEPDIR)/xournalpp-PdfRefList.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='pdf/PdfRefList.cpp' object='xournalpp-PdfRefList.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xournalpp_CXXFLAGS) $(CXXFLAGS) -c -o xournalpp-PdfRefList.o `test -f 'pdf/PdfRefList.cpp' || echo '$(srcdir)/'`pdf/PdfRefList.cpp
xournalpp-PdfRefList.obj: pdf/PdfRefList.cpp
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xournalpp_CXXFLAGS) $(CXXFLAGS) -MT xournalpp-PdfRefList.obj -MD -MP -MF $(DEPDIR)/xournalpp-PdfRefList.Tpo -c -o xournalpp-PdfRefList.obj `if test -f 'pdf/PdfRefList.cpp'; then $(CYGPATH_W) 'pdf/PdfRefList.cpp'; else $(CYGPATH_W) '$(srcdir)/pdf/PdfRefList.cpp'; fi`
@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/xournalpp-PdfRefList.Tpo $(DEPDIR)/xournalpp-PdfRefList.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='pdf/PdfRefList.cpp' object='xournalpp-PdfRefList.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xournalpp_CXXFLAGS) $(CXXFLAGS) -c -o xournalpp-PdfRefList.obj `if test -f 'pdf/PdfRefList.cpp'; then $(CYGPATH_W) 'pdf/PdfRefList.cpp'; else $(CYGPATH_W) '$(srcdir)/pdf/PdfRefList.cpp'; fi`
xournalpp-PdfUtil.o: pdf/PdfUtil.cpp
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xournalpp_CXXFLAGS) $(CXXFLAGS) -MT xournalpp-PdfUtil.o -MD -MP -MF $(DEPDIR)/xournalpp-PdfUtil.Tpo -c -o xournalpp-PdfUtil.o `test -f 'pdf/PdfUtil.cpp' || echo '$(srcdir)/'`pdf/PdfUtil.cpp
@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/xournalpp-PdfUtil.Tpo $(DEPDIR)/xournalpp-PdfUtil.Po

@ -19,6 +19,7 @@ PdfExport::PdfExport(Document * doc, ProgressListener * progressListener) {
this->progressListener = progressListener;
this->xref = new PdfXRef();
this->writer = new PdfWriter(this->xref);
this->objectWriter = new PdfObjectWriter(this->writer, this->xref);
this->dataXrefStart = 0;
@ -27,22 +28,17 @@ PdfExport::PdfExport(Document * doc, ProgressListener * progressListener) {
this->fonts = NULL;
this->fontId = 1;
this->imageId = 1;
this->images = NULL;
this->images = new PdfRefList(this->xref, this->objectWriter, this->writer, "I");
this->extGStateId = 1;
this->extGState = NULL;
this->patternId = 1;
this->pattern = NULL;
this->pattern = new PdfRefList(this->xref, this->objectWriter, this->writer, "p");
this->documents = NULL;
this->resources = NULL;
this->updatedReferenced = g_hash_table_new_full((GHashFunc) UpdateRefKey::hashFunction, (GEqualFunc) UpdateRefKey::equalFunction,
(GDestroyNotify) UpdateRefKey::destroyDelete, (GDestroyNotify) UpdateRef::destroyDelete);
this->xref->addXref(0);
this->xref->addXref(0);
@ -50,12 +46,6 @@ PdfExport::PdfExport(Document * doc, ProgressListener * progressListener) {
}
PdfExport::~PdfExport() {
for (GList * l = this->images; l != NULL; l = l->next) {
PdfRefEntry * img = (PdfRefEntry *) l->data;
delete img;
}
g_list_free(this->images);
for (GList * l = this->documents; l != NULL; l = l->next) {
XojPopplerDocument * doc = (XojPopplerDocument *) l->data;
delete doc;
@ -74,24 +64,23 @@ PdfExport::~PdfExport() {
}
g_list_free(this->extGState);
for (GList * l = this->pattern; l != NULL; l = l->next) {
PdfRefEntry * pattern = (PdfRefEntry *) l->data;
delete pattern;
}
g_list_free(this->pattern);
delete this->pattern;
this->pattern = NULL;
g_hash_table_destroy(this->updatedReferenced);
delete this->images;
this->images = NULL;
this->fonts = NULL;
this->images = NULL;
this->documents = NULL;
this->progressListener = NULL;
this->extGState = NULL;
this->pattern = NULL;
delete this->writer;
this->writer = NULL;
delete this->objectWriter;
this->objectWriter = NULL;
delete this->xref;
this->xref = NULL;
}
@ -197,15 +186,6 @@ bool PdfExport::writeTrailer() {
return this->writer->getLastError().isEmpty();
}
bool PdfExport::writeRefList(GList * list, const char * type) {
for (GList * l = list; l != NULL; l = l->next) {
PdfRefEntry * img = (PdfRefEntry *) l->data;
this->writer->writef("/%s%i %i 0 R\n", type, img->imageId, img->objectId);
}
return true;
}
bool PdfExport::writeResourcedict() {
this->writer->write("/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]\n");
@ -221,9 +201,7 @@ bool PdfExport::writeResourcedict() {
if (this->images) {
this->writer->write("/XObject <<\n");
if (!writeRefList(this->images, "I")) {
return false;
}
this->images->writeRefList();
this->writer->write(">>\n");
}
@ -241,10 +219,7 @@ bool PdfExport::writeResourcedict() {
if (this->pattern) {
this->writer->write("/Pattern <<\n");
if (!writeRefList(this->pattern, "p")) {
return false;
}
this->pattern->writeRefList();
this->writer->write(">>\n");
}
@ -260,74 +235,21 @@ bool PdfExport::writeFonts() {
this->writer->writeObj();
font->objectId = this->writer->getObjectId() - 1;
writeObject(font->object, font->doc);
this->objectWriter->writeObject(font->object, font->doc);
this->writer->write("\nendobj\n");
}
return true;
}
bool PdfExport::writeReferencedObjects(GList * list) {
for (GList * l = list; l != NULL; l = l->next) {
PdfRefEntry * ref = (PdfRefEntry *) l->data;
this->xref->setXref(ref->objectId, this->writer->getDataCount());
bool res = this->writer->writef("%i 0 obj\n", ref->objectId);
writeObject(ref->object, ref->doc);
this->writer->write("\nendobj\n");
}
return true;
}
bool PdfExport::writeImages() {
return writeReferencedObjects(this->images);
}
bool PdfExport::writeCopiedObjects() {
bool allWritten = false;
while (!allWritten) {
allWritten = true;
for (GList * l = g_hash_table_get_values(this->updatedReferenced); l != NULL; l = l->next) {
UpdateRef * uref = (UpdateRef *) l->data;
if (!uref->wroteOut) {
this->xref->setXref(uref->objectId, this->writer->getDataCount());
this->writer->writef("%i 0 obj\n", uref->objectId);
writeObject(&uref->object, uref->doc);
this->writer->write("endobj\n");
uref->wroteOut = true;
break;
}
}
for (GList * l = g_hash_table_get_values(this->updatedReferenced); l != NULL; l = l->next) {
UpdateRef * uref = (UpdateRef *) l->data;
if (!uref->wroteOut) {
allWritten = false;
}
}
}
return true;
}
bool PdfExport::writeResources() {
if (!writeFonts()) {
return false;
}
if (!writeImages()) {
return false;
}
if (!writeReferencedObjects(this->pattern)) {
return false;
}
if (!writeCopiedObjects()) {
return false;
}
this->images->writeObjects();
this->pattern->writeObjects();
this->objectWriter->writeCopiedObjects();
//Resource dictionary
this->xref->setXref(2, this->writer->getDataCount());
@ -382,186 +304,6 @@ bool PdfExport::writeFooter() {
return true;
}
void PdfExport::writeObject(Object * obj, XojPopplerDocument doc) {
Array * array;
Object obj1;
switch (obj->getType()) {
case objBool:
this->writer->writef("%s ", obj->getBool() ? "true" : "false");
break;
case objInt:
this->writer->writef("%i ", obj->getInt());
break;
case objReal:
this->writer->writef("%g ", obj->getReal());
break;
case objString:
this->writeString(obj->getString());
break;
case objName: {
GooString name(obj->getName());
GooString * nameToPrint = name.sanitizedName(gFalse /* non ps mode */);
this->writer->writef("/%s ", nameToPrint->getCString());
delete nameToPrint;
break;
}
case objNull:
this->writer->write("null");
break;
case objArray:
array = obj->getArray();
this->writer->write("[");
for (int i = 0; i < array->getLength(); i++) {
writeObject(array->getNF(i, &obj1), doc);
obj1.free();
}
this->writer->write("] ");
break;
case objDict:
writeDictionnary(obj->getDict(), doc);
break;
case objStream: {
// Poppler: We can't modify stream with the current implementation (no write functions in Stream API)
// Poppler: => the only type of streams which that have been modified are internal streams (=strWeird)
Stream *stream = obj->getStream();
if (stream->getKind() == strWeird) {
//we write the stream unencoded
stream->reset();
//recalculate stream length
int tmp = 0;
for (int c = stream->getChar(); c != EOF; c = stream->getChar()) {
tmp++;
}
obj1.initInt(tmp);
stream->getDict()->set("Length", &obj1);
//Remove Stream encoding
stream->getDict()->remove("Filter");
stream->getDict()->remove("DecodeParms");
writeDictionnary(stream->getDict(), doc);
writeStream(stream);
obj1.free();
} else {
//raw stream copy
writeDictionnary(stream->getDict(), doc);
writeRawStream(stream, doc);
}
break;
}
case objRef: {
UpdateRefKey key(obj->getRef(), doc);
UpdateRef * uref = (UpdateRef *) g_hash_table_lookup(this->updatedReferenced, &key);
if (uref) {
this->writer->writef("%i %i R ", uref->objectId, 0);
} else {
UpdateRef * uref = new UpdateRef(this->writer->getNextObjectId(), doc);
this->xref->addXref(0);
this->writer->writef("%i %i R ", uref->objectId, 0);
obj->fetch(doc.getDoc()->getXRef(), &uref->object);
g_hash_table_insert(this->updatedReferenced, new UpdateRefKey(obj->getRef(), doc), uref);
}
}
break;
case objCmd:
this->writer->write("cmd\r\n");
break;
case objError:
this->writer->write("error\r\n");
break;
case objEOF:
this->writer->write("eof\r\n");
break;
case objNone:
this->writer->write("none\r\n");
break;
default:
g_error("Unhandled objType : %i, please report a bug with a testcase\r\n", obj->getType());
break;
}
}
void PdfExport::writeRawStream(Stream * str, XojPopplerDocument doc) {
Object obj1;
str->getDict()->lookup("Length", &obj1);
if (!obj1.isInt()) {
error(-1, "PDFDoc::writeRawStream, no Length in stream dict");
return;
}
const int length = obj1.getInt();
obj1.free();
this->writer->write("stream\r\n");
str->unfilteredReset();
char buffer[1];
for (int i = 0; i < length; i++) {
int c = str->getUnfilteredChar();
buffer[0] = c;
this->writer->writeLen(buffer, 1);
}
str->reset();
this->writer->write("\nendstream\n");
}
void PdfExport::writeString(GooString * s) {
if (s->hasUnicodeMarker()) {
//unicode string don't necessary end with \0
const char* c = s->getCString();
this->writer->write("(");
for (int i = 0; i < s->getLength(); i++) {
char unescaped = *(c + i) & 0x000000ff;
//escape if needed
if (unescaped == '(' || unescaped == ')' || unescaped == '\\') {
this->writer->writef("%c", '\\');
}
this->writer->writef("%c", unescaped);
}
this->writer->write(") ");
} else {
const char* c = s->getCString();
this->writer->write("(");
while (*c != '\0') {
char unescaped = (*c) & 0x000000ff;
//escape if needed
if (unescaped == '(' || unescaped == ')' || unescaped == '\\') {
this->writer->writef("%c", '\\');
}
this->writer->writef("%c", unescaped);
c++;
}
this->writer->write(") ");
}
}
void PdfExport::writeDictionnary(Dict * dict, XojPopplerDocument doc) {
Object obj1;
this->writer->write("<<");
for (int i = 0; i < dict->getLength(); i++) {
GooString keyName(dict->getKey(i));
GooString *keyNameToPrint = keyName.sanitizedName(gFalse /* non ps mode */);
this->writer->writef("/%s ", keyNameToPrint->getCString());
delete keyNameToPrint;
writeObject(dict->getValNF(i, &obj1), doc);
obj1.free();
}
this->writer->write(">> ");
}
void PdfExport::writeStream(Stream * str) {
this->writer->write("stream\r\n");
str->reset();
for (int c = str->getChar(); c != EOF; c = str->getChar()) {
this->writer->writef("%c", c);
}
this->writer->write("\r\nendstream\r\n");
}
void PdfExport::writeGzStream(Stream * str, GList * replacementList) {
Object obj1;
str->getDict()->lookup("Length", &obj1);
@ -590,52 +332,6 @@ void PdfExport::writeGzStream(Stream * str, GList * replacementList) {
str->reset();
}
int PdfExport::lookupImage(String name, Ref ref, Object * object) {
for (GList * l = this->images; l != NULL; l = l->next) {
PdfRefEntry * i = (PdfRefEntry *) l->data;
if (i->equalsRef(ref)) {
object->free();
delete object;
return i->objectId;
}
}
int id = this->imageId++;
PdfRefEntry * img = new PdfRefEntry(this->writer->getNextObjectId(), ref, object, id, this->currentPdfDoc);
this->xref->addXref(0);
this->images = g_list_append(this->images, img);
return id;
}
int PdfExport::lookupPattern(String name, Ref ref, Object * object) {
for (GList * l = this->pattern; l != NULL; l = l->next) {
PdfRefEntry * p = (PdfRefEntry *) l->data;
if (p->equalsRef(ref)) {
object->free();
delete object;
return p->objectId;
}
}
int id = this->patternId++;
PdfRefEntry * pattern = new PdfRefEntry(this->writer->getNextObjectId(), ref, object, id, this->currentPdfDoc);
this->xref->addXref(0);
this->pattern = g_list_append(this->pattern, pattern);
return id;
}
//int PdfExport::lookupExtGState() {
// TODO: impelementieren!!!!!!!!!!!!!!!!!!!!
// this->extGState = NULL;
// this->extGStateId;
//}
int PdfExport::lookupFont(String name, Ref ref) {
for (GList * l = this->fonts; l != NULL; l = l->next) {
PdfFont * font = (PdfFont *) l->data;
@ -671,7 +367,7 @@ void PdfExport::writePlainStream(Stream * str, GList * replacementList) {
Object obj1;
str->getDict()->lookup("Length", &obj1);
if (!obj1.isInt()) {
g_error("PDFDoc::writeRawStream, no Length in stream dict");
g_error("PDFDoc::writePlainStream, no Length in stream dict");
return;
}
@ -810,7 +506,7 @@ bool PdfExport::addPopplerPage(XojPopplerPage * pdf, XojPopplerDocument doc) {
xobjectDict->getValNF(u, &xobjectObject);
xobjectDict->getVal(u, objImage);
int image = this->lookupImage(xobjectDict->getKey(u), xobjectObject.getRef(), objImage);
int image = this->images->lookup(xobjectDict->getKey(u), xobjectObject.getRef(), objImage, this->currentPdfDoc);
RefReplacement * replacement = new RefReplacement(xobjectDict->getKey(u), image, 'I');
replacementList = g_list_append(replacementList, replacement);
@ -837,7 +533,7 @@ bool PdfExport::addPopplerPage(XojPopplerPage * pdf, XojPopplerDocument doc) {
patternDict->getValNF(u, &patternObject);
patternDict->getVal(u, objPattern);
int patternId = this->lookupPattern(patternDict->getKey(u), patternObject.getRef(), objPattern);
int patternId = this->pattern->lookup(patternDict->getKey(u), patternObject.getRef(), objPattern, this->currentPdfDoc);
RefReplacement * replacement = new RefReplacement(patternDict->getKey(u), patternId, 'p');
replacementList = g_list_append(replacementList, replacement);

@ -19,6 +19,8 @@
#include "PdfXRef.h"
#include "PdfBookmark.h"
#include "PdfWriter.h"
#include "PdfRefList.h"
#include "PdfObjectWriter.h"
#include <glib.h>
class PdfExport {
@ -37,20 +39,12 @@ private:
bool addPopplerPage(XojPopplerPage * pdf, XojPopplerDocument doc);
bool writePage(int page);
void writeDictionnary(Dict * dict, XojPopplerDocument doc);
void writeRawStream(Stream * str, XojPopplerDocument doc);
void writeStream(Stream * str);
void writeObject(Object * obj, XojPopplerDocument doc);
void writeString(GooString * s);
void writeGzStream(Stream * str, GList * replacementList);
void writePlainStream(Stream * str, GList * replacementList);
void writeStream(const char * str, int len, GList * replacementList);
int lookupFont(String name, Ref ref);
int lookupImage(String name, Ref ref, Object * object);
int lookupPattern(String name, Ref ref, Object * object);
bool parseFooter();
bool writeFooter();
@ -63,11 +57,6 @@ private:
bool writeResources();
bool writeFonts();
bool writeImages();
bool writeCopiedObjects();
bool writeReferencedObjects(GList * list);
bool writeRefList(GList * list, const char * type);
private:
Document * doc;
@ -90,22 +79,19 @@ private:
int fontId;
GList * fonts;
int imageId;
GList * images;
PdfRefList * images;
int extGStateId;
GList * extGState;
int patternId;
GList * pattern;
PdfRefList * pattern;
PdfXRef * xref;
PdfBookmarks bookmarks;
PdfWriter * writer;
PdfObjectWriter * objectWriter;
CairoPdf cPdf;
GHashTable * updatedReferenced;
};
#endif /* __PDFEXPORT_H__ */

@ -0,0 +1,226 @@
#include "PdfObjectWriter.h"
#include "UpdateRef.h"
#include "UpdateRefKey.h"
PdfObjectWriter::PdfObjectWriter(PdfWriter * writer, PdfXRef * xref) {
this->writer = writer;
this->xref = xref;
this->updatedReferenced = g_hash_table_new_full((GHashFunc) UpdateRefKey::hashFunction, (GEqualFunc) UpdateRefKey::equalFunction,
(GDestroyNotify) UpdateRefKey::destroyDelete, (GDestroyNotify) UpdateRef::destroyDelete);
}
PdfObjectWriter::~PdfObjectWriter() {
this->writer = NULL;
this->xref = NULL;
// TODO: free!?
g_hash_table_destroy(this->updatedReferenced);
this->updatedReferenced = NULL;
}
void PdfObjectWriter::writeCopiedObjects() {
bool allWritten = false;
while (!allWritten) {
allWritten = true;
for (GList * l = g_hash_table_get_values(this->updatedReferenced); l != NULL; l = l->next) {
UpdateRef * uref = (UpdateRef *) l->data;
if (!uref->wroteOut) {
this->xref->setXref(uref->objectId, this->writer->getDataCount());
this->writer->writef("%i 0 obj\n", uref->objectId);
writeObject(&uref->object, uref->doc);
this->writer->write("endobj\n");
uref->wroteOut = true;
break;
}
}
for (GList * l = g_hash_table_get_values(this->updatedReferenced); l != NULL; l = l->next) {
UpdateRef * uref = (UpdateRef *) l->data;
if (!uref->wroteOut) {
allWritten = false;
}
}
}
}
void PdfObjectWriter::writeObject(Object * obj, XojPopplerDocument doc) {
Array * array;
Object obj1;
switch (obj->getType()) {
case objBool:
this->writer->writef("%s ", obj->getBool() ? "true" : "false");
break;
case objInt:
this->writer->writef("%i ", obj->getInt());
break;
case objReal:
this->writer->writef("%g ", obj->getReal());
break;
case objString:
this->writeString(obj->getString());
break;
case objName: {
GooString name(obj->getName());
GooString * nameToPrint = name.sanitizedName(gFalse /* non ps mode */);
this->writer->writef("/%s ", nameToPrint->getCString());
delete nameToPrint;
break;
}
case objNull:
this->writer->write("null");
break;
case objArray:
array = obj->getArray();
this->writer->write("[");
for (int i = 0; i < array->getLength(); i++) {
writeObject(array->getNF(i, &obj1), doc);
obj1.free();
}
this->writer->write("] ");
break;
case objDict:
writeDictionnary(obj->getDict(), doc);
break;
case objStream: {
// Poppler: We can't modify stream with the current implementation (no write functions in Stream API)
// Poppler: => the only type of streams which that have been modified are internal streams (=strWeird)
Stream *stream = obj->getStream();
if (stream->getKind() == strWeird) {
//we write the stream unencoded
stream->reset();
//recalculate stream length
int tmp = 0;
for (int c = stream->getChar(); c != EOF; c = stream->getChar()) {
tmp++;
}
obj1.initInt(tmp);
stream->getDict()->set("Length", &obj1);
//Remove Stream encoding
stream->getDict()->remove("Filter");
stream->getDict()->remove("DecodeParms");
writeDictionnary(stream->getDict(), doc);
writeStream(stream);
obj1.free();
} else {
//raw stream copy
writeDictionnary(stream->getDict(), doc);
writeRawStream(stream, doc);
}
break;
}
case objRef: {
UpdateRefKey key(obj->getRef(), doc);
UpdateRef * uref = (UpdateRef *) g_hash_table_lookup(this->updatedReferenced, &key);
if (uref) {
this->writer->writef("%i %i R ", uref->objectId, 0);
} else {
UpdateRef * uref = new UpdateRef(this->writer->getNextObjectId(), doc);
this->xref->addXref(0);
this->writer->writef("%i %i R ", uref->objectId, 0);
obj->fetch(doc.getDoc()->getXRef(), &uref->object);
g_hash_table_insert(this->updatedReferenced, new UpdateRefKey(obj->getRef(), doc), uref);
}
}
break;
case objCmd:
this->writer->write("cmd\r\n");
break;
case objError:
this->writer->write("error\r\n");
break;
case objEOF:
this->writer->write("eof\r\n");
break;
case objNone:
this->writer->write("none\r\n");
break;
default:
g_error("Unhandled objType : %i, please report a bug with a testcase\r\n", obj->getType());
break;
}
}
void PdfObjectWriter::writeRawStream(Stream * str, XojPopplerDocument doc) {
Object obj1;
str->getDict()->lookup("Length", &obj1);
if (!obj1.isInt()) {
error(-1, "PDFDoc::writeRawStream, no Length in stream dict");
return;
}
const int length = obj1.getInt();
obj1.free();
this->writer->write("stream\r\n");
str->unfilteredReset();
char buffer[1];
for (int i = 0; i < length; i++) {
int c = str->getUnfilteredChar();
buffer[0] = c;
this->writer->writeLen(buffer, 1);
}
str->reset();
this->writer->write("\nendstream\n");
}
void PdfObjectWriter::writeStream(Stream * str) {
this->writer->write("stream\r\n");
str->reset();
for (int c = str->getChar(); c != EOF; c = str->getChar()) {
this->writer->writef("%c", c);
}
this->writer->write("\r\nendstream\r\n");
}
void PdfObjectWriter::writeDictionnary(Dict * dict, XojPopplerDocument doc) {
Object obj1;
this->writer->write("<<");
for (int i = 0; i < dict->getLength(); i++) {
GooString keyName(dict->getKey(i));
GooString *keyNameToPrint = keyName.sanitizedName(gFalse /* non ps mode */);
this->writer->writef("/%s ", keyNameToPrint->getCString());
delete keyNameToPrint;
writeObject(dict->getValNF(i, &obj1), doc);
obj1.free();
}
this->writer->write(">> ");
}
void PdfObjectWriter::writeString(GooString * s) {
if (s->hasUnicodeMarker()) {
//unicode string don't necessary end with \0
const char* c = s->getCString();
this->writer->write("(");
for (int i = 0; i < s->getLength(); i++) {
char unescaped = *(c + i) & 0x000000ff;
//escape if needed
if (unescaped == '(' || unescaped == ')' || unescaped == '\\') {
this->writer->writef("%c", '\\');
}
this->writer->writef("%c", unescaped);
}
this->writer->write(") ");
} else {
const char* c = s->getCString();
this->writer->write("(");
while (*c != '\0') {
char unescaped = (*c) & 0x000000ff;
//escape if needed
if (unescaped == '(' || unescaped == ')' || unescaped == '\\') {
this->writer->writef("%c", '\\');
}
this->writer->writef("%c", unescaped);
c++;
}
this->writer->write(") ");
}
}

@ -0,0 +1,41 @@
/*
* Xournal++
*
* Handles PDF Export
*
* @author Xournal Team
* http://xournal.sf.net
*
* @license GPL
*/
#ifndef __PDFOBJECTWRITER_H__
#define __PDFOBJECTWRITER_H__
#include "poppler/XojPopplerDocument.h"
#include <poppler/Object.h>
#include "PdfWriter.h"
#include "PdfXRef.h"
class PdfObjectWriter {
public:
PdfObjectWriter(PdfWriter * writer, PdfXRef * xref);
virtual ~PdfObjectWriter();
public:
void writeObject(Object * obj, XojPopplerDocument doc);
void writeString(GooString * s);
void writeDictionnary(Dict * dict, XojPopplerDocument doc);
void writeRawStream(Stream * str, XojPopplerDocument doc);
void writeStream(Stream * str);
void writeCopiedObjects();
private:
PdfWriter * writer;
PdfXRef * xref;
GHashTable * updatedReferenced;
};
#endif /* __PDFOBJECTWRITER_H__ */

@ -0,0 +1,61 @@
#include "PdfRefList.h"
#include "PdfRefEntry.h"
#include "PdfXRef.h"
PdfRefList::PdfRefList(PdfXRef * xref, PdfObjectWriter * objectWriter, PdfWriter * writer, const char * type) {
this->id = 1;
this->data = NULL;
this->xref = xref;
this->objectWriter = objectWriter;
this->writer = writer;
this->type = type;
}
PdfRefList::~PdfRefList() {
for (GList * l = this->data; l != NULL; l = l->next) {
PdfRefEntry * pattern = (PdfRefEntry *) l->data;
delete pattern;
}
g_list_free(this->data);
}
void PdfRefList::writeObjects() {
for (GList * l = this->data; l != NULL; l = l->next) {
PdfRefEntry * ref = (PdfRefEntry *) l->data;
this->xref->setXref(ref->objectId, this->writer->getDataCount());
bool res = this->writer->writef("%i 0 obj\n", ref->objectId);
this->objectWriter->writeObject(ref->object, ref->doc);
this->writer->write("\nendobj\n");
}
}
int PdfRefList::lookup(String name, Ref ref, Object * object, XojPopplerDocument doc) {
for (GList * l = this->data; l != NULL; l = l->next) {
PdfRefEntry * p = (PdfRefEntry *) l->data;
if (p->equalsRef(ref)) {
object->free();
delete object;
return p->objectId;
}
}
int id = this->id++;
PdfRefEntry * pattern = new PdfRefEntry(this->writer->getNextObjectId(), ref, object, id, doc);
this->xref->addXref(0);
this->data = g_list_append(this->data, pattern);
return id;
}
bool PdfRefList::writeRefList() {
for (GList * l = this->data; l != NULL; l = l->next) {
PdfRefEntry * img = (PdfRefEntry *) l->data;
this->writer->writef("/%s%i %i 0 R\n", this->type, img->imageId, img->objectId);
}
return true;
}

@ -0,0 +1,46 @@
/*
* Xournal++
*
* Handles PDF Export
*
* @author Xournal Team
* http://xournal.sf.net
*
* @license GPL
*/
#ifndef __PDFREFLIST_H__
#define __PDFREFLIST_H__
#include <glib.h>
#include "../util/String.h"
#include <poppler/Object.h>
#include "PdfObjectWriter.h"
#include "poppler/XojPopplerDocument.h"
class PdfXRef;
class PdfExport;
class PdfWriter;
class PdfRefList {
public:
PdfRefList(PdfXRef * xref, PdfObjectWriter * objectWriter, PdfWriter * writer, const char * type);
virtual ~PdfRefList();
public:
void writeObjects();
bool writeRefList();
int lookup(String name, Ref ref, Object * object, XojPopplerDocument doc);
private:
int id;
GList * data;
PdfXRef * xref;
PdfObjectWriter * objectWriter;
PdfWriter * writer;
const char * type;
};
#endif /* PDFREFLIST_H_ */
Loading…
Cancel
Save