[poppler] glib/poppler-input-stream.cc glib/poppler-input-stream.h poppler/Annot.cc poppler/Array.cc poppler/Array.h poppler/ArthurOutputDev.cc poppler/ArthurOutputDev.h poppler/CairoFontEngine.cc poppler/CairoFontEngine.h poppler/CairoOutputDev.cc poppler/CairoOutputDev.h poppler/Catalog.cc poppler/Catalog.h poppler/Dict.cc poppler/Dict.h poppler/Gfx.cc poppler/Gfx.h poppler/GlobalParamsWin.cc poppler/Object.h poppler/OutputDev.h poppler/Page.cc poppler/Page.h poppler/Parser.cc poppler/PDFDoc.cc poppler/PDFDoc.h poppler/PreScanOutputDev.cc poppler/PreScanOutputDev.h poppler/PSOutputDev.cc poppler/PSOutputDev.h poppler/SplashOutputDev.cc poppler/SplashOutputDev.h poppler/Stream.cc poppler/Stream.h poppler/TextOutputDev.cc poppler/TextOutputDev.h poppler/XRef.cc poppler/XRef.h qt4/src test/gtk-test.cc utils/HtmlOutputDev.cc utils/HtmlOutputDev.h utils/ImageOutputDev.h
Albert Astals Cid
aacid at kemper.freedesktop.org
Sat Jan 19 08:44:34 PST 2013
glib/poppler-input-stream.cc | 4 +
glib/poppler-input-stream.h | 1
poppler/Annot.cc | 52 +++++++++----------
poppler/Array.cc | 48 ++++++++++++++++-
poppler/Array.h | 15 ++++-
poppler/ArthurOutputDev.cc | 3 -
poppler/ArthurOutputDev.h | 3 -
poppler/CairoFontEngine.cc | 33 +++++++++---
poppler/CairoFontEngine.h | 11 ++--
poppler/CairoOutputDev.cc | 15 +++--
poppler/CairoOutputDev.h | 5 +
poppler/Catalog.cc | 84 +++++++++++++++++++++++++++---
poppler/Catalog.h | 15 ++++-
poppler/Dict.cc | 67 +++++++++++++++++++++++-
poppler/Dict.h | 11 +++-
poppler/Gfx.cc | 18 +++---
poppler/Gfx.h | 8 +-
poppler/GlobalParamsWin.cc | 4 -
poppler/Object.h | 7 +-
poppler/OutputDev.h | 4 -
poppler/PDFDoc.cc | 66 ++++++++++++++++++------
poppler/PDFDoc.h | 11 ++--
poppler/PSOutputDev.cc | 12 ++--
poppler/PSOutputDev.h | 4 -
poppler/Page.cc | 75 ++++++++++++++++++++++++---
poppler/Page.h | 18 +++++-
poppler/Parser.cc | 3 -
poppler/PreScanOutputDev.cc | 4 -
poppler/PreScanOutputDev.h | 4 -
poppler/SplashOutputDev.cc | 16 +++--
poppler/SplashOutputDev.h | 5 +
poppler/Stream.cc | 117 ++++++++++++++++++++++++++++++++-----------
poppler/Stream.h | 35 +++++++++---
poppler/TextOutputDev.cc | 5 +
poppler/TextOutputDev.h | 3 -
poppler/XRef.cc | 99 +++++++++++++++++++++++++++++++++---
poppler/XRef.h | 16 +++++
qt4/src/poppler-document.cc | 23 ++++----
qt4/src/poppler-page.cc | 64 ++++++++++++++++++++---
qt4/src/poppler-private.cc | 3 -
qt4/src/poppler-private.h | 74 ---------------------------
test/gtk-test.cc | 2
utils/HtmlOutputDev.cc | 3 -
utils/HtmlOutputDev.h | 3 -
utils/ImageOutputDev.h | 3 -
45 files changed, 793 insertions(+), 283 deletions(-)
New commits:
commit 8eb489c355d734a72e140ce7e32470d048362499
Author: Thomas Freitag <Thomas.Freitag at alfa.de>
Date: Sat Jan 19 17:43:08 2013 +0100
Make rendering thread-safe
Bug #50992
diff --git a/glib/poppler-input-stream.cc b/glib/poppler-input-stream.cc
index 99fcb6f..4ac3149 100644
--- a/glib/poppler-input-stream.cc
+++ b/glib/poppler-input-stream.cc
@@ -41,6 +41,10 @@ PopplerInputStream::~PopplerInputStream()
g_object_unref(cancellable);
}
+BaseStream *PopplerInputStream::copy() {
+ return new PopplerInputStream(inputStream, cancellable, start, limited, length, &dict);
+}
+
Stream *PopplerInputStream::makeSubStream(Guint startA, GBool limitedA,
Guint lengthA, Object *dictA)
{
diff --git a/glib/poppler-input-stream.h b/glib/poppler-input-stream.h
index 0d795f4..639ea04 100644
--- a/glib/poppler-input-stream.h
+++ b/glib/poppler-input-stream.h
@@ -33,6 +33,7 @@ public:
PopplerInputStream(GInputStream *inputStream, GCancellable *cancellableA,
Guint startA, GBool limitedA, Guint lengthA, Object *dictA);
virtual ~PopplerInputStream();
+ virtual BaseStream *copy();
virtual Stream *makeSubStream(Guint start, GBool limited,
Guint lengthA, Object *dictA);
virtual StreamKind getKind() { return strWeird; }
diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index dae0f62..0b3c5e4 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -25,7 +25,7 @@
// Copyright (C) 2009 Ilya Gorenbein <igorenbein at finjan.com>
// Copyright (C) 2011 José Aliste <jaliste at src.gnome.org>
// Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
-// Copyright (C) 2012 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
// Copyright (C) 2012 Tobias Koenig <tokoe at kdab.com>
//
// To see a description of the changes please see the Changelog file that
@@ -1205,7 +1205,7 @@ void Annot::initialize(PDFDoc *docA, Dict *dict) {
if (dict->lookupNF("P", &obj1)->isRef()) {
Ref ref = obj1.getRef();
- page = doc->getCatalog()->findPage (ref.num, ref.gen);
+ page = doc->getCatalog()->findPage (ref.num, ref.gen, gFalse);
} else {
page = 0;
}
@@ -1748,7 +1748,7 @@ void Annot::draw(Gfx *gfx, GBool printing) {
return;
// draw the appearance stream
- appearance.fetch(xref, &obj);
+ appearance.fetch(gfx->getXRef(), &obj);
gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
rect->x1, rect->y1, rect->x2, rect->y2);
obj.free();
@@ -2412,7 +2412,7 @@ void AnnotText::draw(Gfx *gfx, GBool printing) {
}
// draw the appearance stream
- appearance.fetch(xref, &obj);
+ appearance.fetch(gfx->getXRef(), &obj);
if (appearBBox) {
gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
appearBBox->getPageXMin(), appearBBox->getPageYMin(),
@@ -2511,7 +2511,7 @@ void AnnotLink::draw(Gfx *gfx, GBool printing) {
return;
// draw the appearance stream
- appearance.fetch(xref, &obj);
+ appearance.fetch(gfx->getXRef(), &obj);
gfx->drawAnnot(&obj, border, color,
rect->x1, rect->y1, rect->x2, rect->y2);
obj.free();
@@ -2944,7 +2944,7 @@ void AnnotFreeText::draw(Gfx *gfx, GBool printing) {
}
// draw the appearance stream
- appearance.fetch(xref, &obj);
+ appearance.fetch(gfx->getXRef(), &obj);
gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
rect->x1, rect->y1, rect->x2, rect->y2);
obj.free();
@@ -3416,7 +3416,7 @@ void AnnotLine::draw(Gfx *gfx, GBool printing) {
}
// draw the appearance stream
- appearance.fetch(xref, &obj);
+ appearance.fetch(gfx->getXRef(), &obj);
if (appearBBox) {
gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
appearBBox->getPageXMin(), appearBBox->getPageYMin(),
@@ -3724,7 +3724,7 @@ void AnnotTextMarkup::draw(Gfx *gfx, GBool printing) {
}
// draw the appearance stream
- appearance.fetch(xref, &obj);
+ appearance.fetch(gfx->getXRef(), &obj);
if (appearBBox) {
gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
appearBBox->getPageXMin(), appearBBox->getPageYMin(),
@@ -3770,7 +3770,7 @@ AnnotWidget::~AnnotWidget() {
void AnnotWidget::initialize(PDFDoc *docA, Dict *dict) {
Object obj1;
- form = doc->getCatalog()->getForm();
+ form = doc->getCatalog()->getForm(gFalse);
if(dict->lookup("H", &obj1)->isName()) {
const char *modeName = obj1.getName();
@@ -4967,7 +4967,7 @@ void AnnotWidget::draw(Gfx *gfx, GBool printing) {
}
// draw the appearance stream
- appearance.fetch(xref, &obj);
+ appearance.fetch(gfx->getXRef(), &obj);
if (addDingbatsResource) {
// We are forcing ZaDb but the font does not exist
// so create a fake one
@@ -4976,19 +4976,19 @@ void AnnotWidget::draw(Gfx *gfx, GBool printing) {
subtypeObj.initName("Type1");
Object fontDictObj;
- Dict *fontDict = new Dict(xref);
+ Dict *fontDict = new Dict(gfx->getXRef());
fontDict->decRef();
fontDict->add(copyString("BaseFont"), &baseFontObj);
fontDict->add(copyString("Subtype"), &subtypeObj);
fontDictObj.initDict(fontDict);
Object fontsDictObj;
- Dict *fontsDict = new Dict(xref);
+ Dict *fontsDict = new Dict(gfx->getXRef());
fontsDict->decRef();
fontsDict->add(copyString("ZaDb"), &fontDictObj);
fontsDictObj.initDict(fontsDict);
- Dict *dict = new Dict(xref);
+ Dict *dict = new Dict(gfx->getXRef());
dict->add(copyString("Font"), &fontsDictObj);
gfx->pushResources(dict);
delete dict;
@@ -5084,25 +5084,25 @@ void AnnotMovie::draw(Gfx *gfx, GBool printing) {
appearBuf->append ("Q\n");
Object imgDict;
- imgDict.initDict(xref);
+ imgDict.initDict(gfx->getXRef());
imgDict.dictSet ("MImg", &poster);
Object resDict;
- resDict.initDict(xref);
+ resDict.initDict(gfx->getXRef());
resDict.dictSet ("XObject", &imgDict);
Object formDict, obj1, obj2;
- formDict.initDict(xref);
+ formDict.initDict(gfx->getXRef());
formDict.dictSet("Length", obj1.initInt(appearBuf->getLength()));
formDict.dictSet("Subtype", obj1.initName("Form"));
formDict.dictSet("Name", obj1.initName("FRM"));
- obj1.initArray(xref);
+ obj1.initArray(gfx->getXRef());
obj1.arrayAdd(obj2.initInt(0));
obj1.arrayAdd(obj2.initInt(0));
obj1.arrayAdd(obj2.initInt(width));
obj1.arrayAdd(obj2.initInt(height));
formDict.dictSet("BBox", &obj1);
- obj1.initArray(xref);
+ obj1.initArray(gfx->getXRef());
obj1.arrayAdd(obj2.initInt(1));
obj1.arrayAdd(obj2.initInt(0));
obj1.arrayAdd(obj2.initInt(0));
@@ -5120,10 +5120,10 @@ void AnnotMovie::draw(Gfx *gfx, GBool printing) {
delete appearBuf;
Object objDict;
- objDict.initDict(xref);
+ objDict.initDict(gfx->getXRef());
objDict.dictSet ("FRM", &aStream);
- resDict.initDict(xref);
+ resDict.initDict(gfx->getXRef());
resDict.dictSet ("XObject", &objDict);
appearBuf = new GooString ();
@@ -5147,7 +5147,7 @@ void AnnotMovie::draw(Gfx *gfx, GBool printing) {
}
// draw the appearance stream
- appearance.fetch(xref, &obj);
+ appearance.fetch(gfx->getXRef(), &obj);
gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
rect->x1, rect->y1, rect->x2, rect->y2);
obj.free();
@@ -5489,7 +5489,7 @@ void AnnotGeometry::draw(Gfx *gfx, GBool printing) {
}
// draw the appearance stream
- appearance.fetch(xref, &obj);
+ appearance.fetch(gfx->getXRef(), &obj);
gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
rect->x1, rect->y1, rect->x2, rect->y2);
obj.free();
@@ -5773,7 +5773,7 @@ void AnnotPolygon::draw(Gfx *gfx, GBool printing) {
}
// draw the appearance stream
- appearance.fetch(xref, &obj);
+ appearance.fetch(gfx->getXRef(), &obj);
if (appearBBox) {
gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
appearBBox->getPageXMin(), appearBBox->getPageYMin(),
@@ -5985,7 +5985,7 @@ void AnnotInk::draw(Gfx *gfx, GBool printing) {
}
// draw the appearance stream
- appearance.fetch(xref, &obj);
+ appearance.fetch(gfx->getXRef(), &obj);
if (appearBBox) {
gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
appearBBox->getPageXMin(), appearBBox->getPageYMin(),
@@ -6206,7 +6206,7 @@ void AnnotFileAttachment::draw(Gfx *gfx, GBool printing) {
}
// draw the appearance stream
- appearance.fetch(xref, &obj);
+ appearance.fetch(gfx->getXRef(), &obj);
gfx->drawAnnot(&obj, border, color,
rect->x1, rect->y1, rect->x2, rect->y2);
obj.free();
@@ -6367,7 +6367,7 @@ void AnnotSound::draw(Gfx *gfx, GBool printing) {
}
// draw the appearance stream
- appearance.fetch(xref, &obj);
+ appearance.fetch(gfx->getXRef(), &obj);
gfx->drawAnnot(&obj, border, color,
rect->x1, rect->y1, rect->x2, rect->y2);
obj.free();
diff --git a/poppler/Array.cc b/poppler/Array.cc
index cb22432..d23ed5d 100644
--- a/poppler/Array.cc
+++ b/poppler/Array.cc
@@ -15,6 +15,7 @@
//
// Copyright (C) 2005 Kristian Høgsberg <krh at redhat.com>
// Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -33,6 +34,13 @@
#include "Object.h"
#include "Array.h"
+#if MULTITHREADED
+# define lockArray gLockMutex(&mutex)
+# define unlockArray gUnlockMutex(&mutex)
+#else
+# define lockArray
+# define unlockArray
+#endif
//------------------------------------------------------------------------
// Array
//------------------------------------------------------------------------
@@ -42,6 +50,9 @@ Array::Array(XRef *xrefA) {
elems = NULL;
size = length = 0;
ref = 1;
+#if MULTITHREADED
+ gInitMutex(&mutex);
+#endif
}
Array::~Array() {
@@ -50,9 +61,38 @@ Array::~Array() {
for (i = 0; i < length; ++i)
elems[i].free();
gfree(elems);
+#if MULTITHREADED
+ gDestroyMutex(&mutex);
+#endif
+}
+
+Object *Array::copy(XRef *xrefA, Object *obj) {
+ lockArray;
+ obj->initArray(xrefA);
+ for (int i = 0; i < length; ++i) {
+ Object obj1;
+ obj->arrayAdd(elems[i].copy(&obj1));
+ }
+ unlockArray;
+ return obj;
+}
+
+int Array::incRef() {
+ lockArray;
+ ++ref;
+ unlockArray;
+ return ref;
+}
+
+int Array::decRef() {
+ lockArray;
+ --ref;
+ unlockArray;
+ return ref;
}
void Array::add(Object *elem) {
+ lockArray;
if (length == size) {
if (length == 0) {
size = 8;
@@ -63,21 +103,25 @@ void Array::add(Object *elem) {
}
elems[length] = *elem;
++length;
+ unlockArray;
}
void Array::remove(int i) {
+ lockArray;
if (i < 0 || i >= length) {
#ifdef DEBUG_MEM
abort();
#else
+ unlockArray;
return;
#endif
}
--length;
memmove( elems + i, elems + i + 1, sizeof(elems[0]) * (length - i) );
+ unlockArray;
}
-Object *Array::get(int i, Object *obj) {
+Object *Array::get(int i, Object *obj, int recursion) {
if (i < 0 || i >= length) {
#ifdef DEBUG_MEM
abort();
@@ -85,7 +129,7 @@ Object *Array::get(int i, Object *obj) {
return obj->initNull();
#endif
}
- return elems[i].fetch(xref, obj);
+ return elems[i].fetch(xref, obj, recursion);
}
Object *Array::getNF(int i, Object *obj) {
diff --git a/poppler/Array.h b/poppler/Array.h
index 666a409..e78e399 100644
--- a/poppler/Array.h
+++ b/poppler/Array.h
@@ -15,6 +15,7 @@
//
// Copyright (C) 2005 Kristian Høgsberg <krh at redhat.com>
// Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -28,7 +29,9 @@
#pragma interface
#endif
+#include "poppler-config.h"
#include "Object.h"
+#include "goo/GooMutex.h"
class XRef;
@@ -46,12 +49,15 @@ public:
~Array();
// Reference counting.
- int incRef() { return ++ref; }
- int decRef() { return --ref; }
+ int incRef();
+ int decRef();
// Get number of elements.
int getLength() { return length; }
+ // Copy array with new xref
+ Object *copy(XRef *xrefA, Object *obj);
+
// Add an element.
void add(Object *elem);
@@ -59,7 +65,7 @@ public:
void remove(int i);
// Accessors.
- Object *get(int i, Object *obj);
+ Object *get(int i, Object *obj, int resursion = 0);
Object *getNF(int i, Object *obj);
GBool getString(int i, GooString *string);
@@ -70,6 +76,9 @@ private:
int size; // size of <elems> array
int length; // number of elements in array
int ref; // reference count
+#if MULTITHREADED
+ GooMutex mutex;
+#endif
};
#endif
diff --git a/poppler/ArthurOutputDev.cc b/poppler/ArthurOutputDev.cc
index a1cb89d..5d57e93 100644
--- a/poppler/ArthurOutputDev.cc
+++ b/poppler/ArthurOutputDev.cc
@@ -20,6 +20,7 @@
// Copyright (C) 2009 Petr Gajdos <pgajdos at novell.com>
// Copyright (C) 2010 Matthias Fauconneau <matthias.fauconneau at gmail.com>
// Copyright (C) 2011 Andreas Hartmetz <ahartmetz at gmail.com>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -122,7 +123,7 @@ void ArthurOutputDev::startDoc(XRef *xrefA) {
#endif
}
-void ArthurOutputDev::startPage(int pageNum, GfxState *state)
+void ArthurOutputDev::startPage(int pageNum, GfxState *state, XRef *xref)
{
// fill page with white background.
int w = static_cast<int>(state->getPageWidth());
diff --git a/poppler/ArthurOutputDev.h b/poppler/ArthurOutputDev.h
index ed631a0..9d5e867 100644
--- a/poppler/ArthurOutputDev.h
+++ b/poppler/ArthurOutputDev.h
@@ -18,6 +18,7 @@
// Copyright (C) 2009, 2011 Carlos Garcia Campos <carlosgc at gnome.org>
// Copyright (C) 2010 Pino Toscano <pino at kde.org>
// Copyright (C) 2011 Andreas Hartmetz <ahartmetz at gmail.com>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -86,7 +87,7 @@ public:
//----- initialization and control
// Start a page.
- virtual void startPage(int pageNum, GfxState *state);
+ virtual void startPage(int pageNum, GfxState *state, XRef *xref);
// End a page.
virtual void endPage();
diff --git a/poppler/CairoFontEngine.cc b/poppler/CairoFontEngine.cc
index c4493e8..beb4e37 100644
--- a/poppler/CairoFontEngine.cc
+++ b/poppler/CairoFontEngine.cc
@@ -26,6 +26,7 @@
// Copyright (C) 2010 Suzuki Toshiya <mpsuzuki at hiroshima-u.ac.jp>
// Copyright (C) 2010 Jan Kümmel <jan+freedesktop at snorc.org>
// Copyright (C) 2012 Hib Eris <hib at hiberis.nl>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -58,6 +59,13 @@
#pragma implementation
#endif
+#if MULTITHREADED
+# define lockFontEngine gLockMutex(&mutex)
+# define unlockFontEngine gUnlockMutex(&mutex)
+#else
+# define lockFontEngine
+# define unlockFontEngine
+#endif
//------------------------------------------------------------------------
// CairoFont
@@ -558,6 +566,7 @@ typedef struct _type3_font_info {
PDFDoc *doc;
CairoFontEngine *fontEngine;
GBool printing;
+ XRef *xref;
} type3_font_info_t;
static void
@@ -645,7 +654,7 @@ _render_type3_glyph (cairo_scaled_font_t *scaled_font,
box.y2 = mat[3];
gfx = new Gfx(info->doc, output_dev, resDict, &box, NULL);
output_dev->startDoc(info->doc, info->fontEngine);
- output_dev->startPage (1, gfx->getState());
+ output_dev->startPage (1, gfx->getState(), gfx->getXRef());
output_dev->setInType3Char(gTrue);
gfx->display(charProcs->getVal(glyph, &charProc));
@@ -674,7 +683,7 @@ _render_type3_glyph (cairo_scaled_font_t *scaled_font,
CairoType3Font *CairoType3Font::create(GfxFont *gfxFont, PDFDoc *doc,
CairoFontEngine *fontEngine,
- GBool printing) {
+ GBool printing, XRef *xref) {
Object refObj, strObj;
type3_font_info_t *info;
cairo_font_face_t *font_face;
@@ -697,6 +706,7 @@ CairoType3Font *CairoType3Font::create(GfxFont *gfxFont, PDFDoc *doc,
info->doc = doc;
info->fontEngine = fontEngine;
info->printing = printing;
+ info->xref = xref;
cairo_font_face_set_user_data (font_face, &type3_font_key, (void *) info, _free_type3_font_info);
@@ -714,7 +724,7 @@ CairoType3Font *CairoType3Font::create(GfxFont *gfxFont, PDFDoc *doc,
}
}
- return new CairoType3Font(ref, doc, font_face, codeToGID, codeToGIDLen, printing);
+ return new CairoType3Font(ref, doc, font_face, codeToGID, codeToGIDLen, printing, xref);
}
CairoType3Font::CairoType3Font(Ref ref,
@@ -722,7 +732,7 @@ CairoType3Font::CairoType3Font(Ref ref,
cairo_font_face_t *cairo_font_face,
int *codeToGID,
Guint codeToGIDLen,
- GBool printing) : CairoFont(ref,
+ GBool printing, XRef *xref) : CairoFont(ref,
cairo_font_face,
codeToGID,
codeToGIDLen,
@@ -755,6 +765,9 @@ CairoFontEngine::CairoFontEngine(FT_Library libA) {
FT_Library_Version(lib, &major, &minor, &patch);
useCIDs = major > 2 ||
(major == 2 && (minor > 1 || (minor == 1 && patch > 7)));
+#if MULTITHREADED
+ gInitMutex(&mutex);
+#endif
}
CairoFontEngine::~CairoFontEngine() {
@@ -764,15 +777,19 @@ CairoFontEngine::~CairoFontEngine() {
if (fontCache[i])
delete fontCache[i];
}
+#if MULTITHREADED
+ gDestroyMutex(&mutex);
+#endif
}
CairoFont *
-CairoFontEngine::getFont(GfxFont *gfxFont, PDFDoc *doc, GBool printing) {
+CairoFontEngine::getFont(GfxFont *gfxFont, PDFDoc *doc, GBool printing, XRef *xref) {
int i, j;
Ref ref;
CairoFont *font;
GfxFontType fontType;
+ lockFontEngine;
ref = *gfxFont->getID();
for (i = 0; i < cairoFontCacheSize; ++i) {
@@ -782,15 +799,16 @@ CairoFontEngine::getFont(GfxFont *gfxFont, PDFDoc *doc, GBool printing) {
fontCache[j] = fontCache[j-1];
}
fontCache[0] = font;
+ unlockFontEngine;
return font;
}
}
fontType = gfxFont->getType();
if (fontType == fontType3)
- font = CairoType3Font::create (gfxFont, doc, this, printing);
+ font = CairoType3Font::create (gfxFont, doc, this, printing, xref);
else
- font = CairoFreeTypeFont::create (gfxFont, doc->getXRef(), lib, useCIDs);
+ font = CairoFreeTypeFont::create (gfxFont, xref, lib, useCIDs);
//XXX: if font is null should we still insert it into the cache?
if (fontCache[cairoFontCacheSize - 1]) {
@@ -800,5 +818,6 @@ CairoFontEngine::getFont(GfxFont *gfxFont, PDFDoc *doc, GBool printing) {
fontCache[j] = fontCache[j-1];
}
fontCache[0] = font;
+ unlockFontEngine;
return font;
}
diff --git a/poppler/CairoFontEngine.h b/poppler/CairoFontEngine.h
index 6335348..8c0dba1 100644
--- a/poppler/CairoFontEngine.h
+++ b/poppler/CairoFontEngine.h
@@ -19,6 +19,7 @@
// Copyright (C) 2006, 2007 Jeff Muizelaar <jeff at infidigm.net>
// Copyright (C) 2006, 2010 Carlos Garcia Campos <carlosgc at gnome.org>
// Copyright (C) 2008 Adrian Johnson <ajohnson at redneon.com>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -32,6 +33,7 @@
#pragma interface
#endif
+#include "poppler-config.h"
#include "goo/gtypes.h"
#include <cairo-ft.h>
@@ -85,7 +87,7 @@ class CairoType3Font : public CairoFont {
public:
static CairoType3Font *create(GfxFont *gfxFont, PDFDoc *doc,
CairoFontEngine *fontEngine,
- GBool printing);
+ GBool printing, XRef *xref);
virtual ~CairoType3Font();
virtual GBool matches(Ref &other, GBool printing);
@@ -94,7 +96,7 @@ private:
CairoType3Font(Ref ref, PDFDoc *doc,
cairo_font_face_t *cairo_font_face,
int *codeToGID, Guint codeToGIDLen,
- GBool printing);
+ GBool printing, XRef *xref);
PDFDoc *doc;
};
@@ -113,12 +115,15 @@ public:
CairoFontEngine(FT_Library libA);
~CairoFontEngine();
- CairoFont *getFont(GfxFont *gfxFont, PDFDoc *doc, GBool printing);
+ CairoFont *getFont(GfxFont *gfxFont, PDFDoc *doc, GBool printing, XRef *xref);
private:
CairoFont *fontCache[cairoFontCacheSize];
FT_Library lib;
GBool useCIDs;
+#if MULTITHREADED
+ GooMutex mutex;
+#endif
};
#endif
diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index 441ca45..10df30c 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -25,7 +25,7 @@
// Copyright (C) 2008, 2009 Chris Wilson <chris at chris-wilson.co.uk>
// Copyright (C) 2008, 2012 Hib Eris <hib at hiberis.nl>
// Copyright (C) 2009, 2010 David Benjamin <davidben at mit.edu>
-// Copyright (C) 2011, 2012 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2011-2013 Thomas Freitag <Thomas.Freitag at alfa.de>
// Copyright (C) 2012 Patrick Pfeifer <p2000 at mailinator.com>
// Copyright (C) 2012 Jason Crain <jason at aquaticape.us>
//
@@ -163,6 +163,7 @@ CairoOutputDev::CairoOutputDev() {
stroke_adjust = globalParams->getStrokeAdjust();
align_stroke_coords = gFalse;
adjusted_stroke_width = gFalse;
+ xref = NULL;
}
CairoOutputDev::~CairoOutputDev() {
@@ -235,9 +236,10 @@ void CairoOutputDev::startDoc(PDFDoc *docA,
fontEngine = new CairoFontEngine(ft_lib);
fontEngine_owner = gTrue;
}
+ xref = doc->getXRef();
}
-void CairoOutputDev::startPage(int pageNum, GfxState *state) {
+void CairoOutputDev::startPage(int pageNum, GfxState *state, XRef *xrefA) {
/* set up some per page defaults */
cairo_pattern_destroy(fill_pattern);
cairo_pattern_destroy(stroke_pattern);
@@ -249,6 +251,9 @@ void CairoOutputDev::startPage(int pageNum, GfxState *state) {
if (text)
text->startPage(state);
+ if (xrefA != NULL) {
+ xref = xrefA;
+ }
}
void CairoOutputDev::endPage() {
@@ -602,7 +607,7 @@ void CairoOutputDev::updateFont(GfxState *state) {
if (text)
text->updateFont(state);
- currentFont = fontEngine->getFont (state->getFont(), doc, printing);
+ currentFont = fontEngine->getFont (state->getFont(), doc, printing, xref);
if (!currentFont)
return;
@@ -805,7 +810,7 @@ void CairoOutputDev::eoFill(GfxState *state) {
}
-GBool CairoOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx1, Catalog *cat, Object *str,
+GBool CairoOutputDev::tilingPatternFill(GfxState *state, Gfx *gfxA, Catalog *cat, Object *str,
double *pmat, int paintType, int /*tilingType*/, Dict *resDict,
double *mat, double *bbox,
int x0, int y0, int x1, int y1,
@@ -846,7 +851,7 @@ GBool CairoOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx1, Catalog *cat
box.x2 = bbox[2]; box.y2 = bbox[3];
strokePathTmp = strokePathClip;
strokePathClip = NULL;
- gfx = new Gfx(doc, this, resDict, &box, NULL);
+ gfx = new Gfx(doc, this, resDict, &box, NULL, NULL, NULL, gfxA->getXRef());
gfx->display(str);
delete gfx;
strokePathClip = strokePathTmp;
diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h
index a699a7b..2ac1fd5 100644
--- a/poppler/CairoOutputDev.h
+++ b/poppler/CairoOutputDev.h
@@ -20,7 +20,7 @@
// Copyright (C) 2006-2011 Carlos Garcia Campos <carlosgc at gnome.org>
// Copyright (C) 2008, 2009, 2011, 2012 Adrian Johnson <ajohnson at redneon.com>
// Copyright (C) 2008 Michael Vrable <mvrable at cs.ucsd.edu>
-// Copyright (C) 2010-2012 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2010-2013 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -124,7 +124,7 @@ public:
//----- initialization and control
// Start a page.
- virtual void startPage(int pageNum, GfxState *state);
+ virtual void startPage(int pageNum, GfxState *state, XRef *xref);
// End a page.
virtual void endPage();
@@ -284,6 +284,7 @@ protected:
GBool adjusted_stroke_width;
GBool align_stroke_coords;
CairoFont *currentFont;
+ XRef *xref;
struct StrokePathClip {
GfxPath *path;
diff --git a/poppler/Catalog.cc b/poppler/Catalog.cc
index cf6dff0..b7f7ede 100644
--- a/poppler/Catalog.cc
+++ b/poppler/Catalog.cc
@@ -25,6 +25,7 @@
// Copyright (C) 2009 Ilya Gorenbein <igorenbein at finjan.com>
// Copyright (C) 2010 Hib Eris <hib at hiberis.nl>
// Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -55,6 +56,13 @@
#include "ViewerPreferences.h"
#include "FileSpec.h"
+#if MULTITHREADED
+# define lockCatalog gLockMutex(&mutex)
+# define unlockCatalog gUnlockMutex(&mutex)
+#else
+# define lockCatalog
+# define unlockCatalog
+#endif
//------------------------------------------------------------------------
// Catalog
//------------------------------------------------------------------------
@@ -64,6 +72,9 @@ Catalog::Catalog(PDFDoc *docA) {
Object obj, obj2;
Object optContentProps;
+#if MULTITHREADED
+ gInitMutex(&mutex);
+#endif
ok = gTrue;
doc = docA;
xref = doc->getXRef();
@@ -170,6 +181,9 @@ Catalog::~Catalog() {
outline.free();
acroForm.free();
viewerPreferences.free();
+#if MULTITHREADED
+ gDestroyMutex(&mutex);
+#endif
}
GooString *Catalog::readMetadata() {
@@ -177,6 +191,7 @@ GooString *Catalog::readMetadata() {
Dict *dict;
Object obj;
+ lockCatalog;
if (metadata.isNone()) {
Object catDict;
@@ -191,6 +206,7 @@ GooString *Catalog::readMetadata() {
}
if (!metadata.isStream()) {
+ unlockCatalog;
return NULL;
}
dict = metadata.streamGetDict();
@@ -202,6 +218,7 @@ GooString *Catalog::readMetadata() {
s = new GooString();
metadata.getStream()->fillGooString(s);
metadata.streamClose();
+ unlockCatalog;
return s;
}
@@ -209,19 +226,31 @@ Page *Catalog::getPage(int i)
{
if (i < 1) return NULL;
+ lockCatalog;
if (i > lastCachedPage) {
- if (cachePageTree(i) == gFalse) return NULL;
+ GBool cached = cachePageTree(i);
+ if ( cached == gFalse) {
+ unlockCatalog;
+ return NULL;
+ }
}
+ unlockCatalog;
return pages[i-1];
}
-Ref *Catalog::getPageRef(int i)
+Ref *Catalog::getPageRef(int i, GBool lock)
{
if (i < 1) return NULL;
+ if (lock) lockCatalog;
if (i > lastCachedPage) {
- if (cachePageTree(i) == gFalse) return NULL;
+ GBool cached = cachePageTree(i);
+ if ( cached == gFalse) {
+ if (lock) unlockCatalog;
+ return NULL;
+ }
}
+ if (lock) unlockCatalog;
return &pageRefs[i-1];
}
@@ -271,7 +300,7 @@ GBool Catalog::cachePageTree(int page)
return gFalse;
}
- pagesSize = getNumPages();
+ pagesSize = getNumPages(gFalse);
pages = (Page **)gmallocn(pagesSize, sizeof(Page *));
pageRefs = (Ref *)gmallocn(pagesSize, sizeof(Ref));
for (int i = 0; i < pagesSize; ++i) {
@@ -398,11 +427,11 @@ GBool Catalog::cachePageTree(int page)
return gFalse;
}
-int Catalog::findPage(int num, int gen) {
+int Catalog::findPage(int num, int gen, GBool lock) {
int i;
- for (i = 0; i < getNumPages(); ++i) {
- Ref *ref = getPageRef(i+1);
+ for (i = 0; i < getNumPages(lock); ++i) {
+ Ref *ref = getPageRef(i+1, lock);
if (ref != NULL && ref->num == num && ref->gen == gen)
return i + 1;
}
@@ -423,10 +452,12 @@ LinkDest *Catalog::findDest(GooString *name) {
obj1.free();
}
if (!found) {
+ lockCatalog;
if (getDestNameTree()->lookup(name, &obj1))
found = gTrue;
else
obj1.free();
+ unlockCatalog;
}
if (!found)
return NULL;
@@ -457,6 +488,7 @@ FileSpec *Catalog::embeddedFile(int i)
{
Object efDict;
Object obj;
+ lockCatalog;
obj = getEmbeddedFileNameTree()->getValue(i);
FileSpec *embeddedFile = 0;
if (obj.isRef()) {
@@ -469,6 +501,7 @@ FileSpec *Catalog::embeddedFile(int i)
Object null;
embeddedFile = new FileSpec(&null);
}
+ unlockCatalog;
return embeddedFile;
}
@@ -477,10 +510,12 @@ GooString *Catalog::getJS(int i)
Object obj;
// getJSNameTree()->getValue(i) returns a shallow copy of the object so we
// do not need to free it
+ lockCatalog;
getJSNameTree()->getValue(i).fetch(xref, &obj);
if (!obj.isDict()) {
obj.free();
+ unlockCatalog;
return 0;
}
Object obj2;
@@ -492,6 +527,7 @@ GooString *Catalog::getJS(int i)
if (strcmp(obj2.getName(), "JavaScript")) {
obj2.free();
obj.free();
+ unlockCatalog;
return 0;
}
obj2.free();
@@ -507,11 +543,13 @@ GooString *Catalog::getJS(int i)
}
obj2.free();
obj.free();
+ unlockCatalog;
return js;
}
Catalog::PageMode Catalog::getPageMode() {
+ lockCatalog;
if (pageMode == pageModeNull) {
Object catDict, obj;
@@ -522,6 +560,7 @@ Catalog::PageMode Catalog::getPageMode() {
if (!catDict.isDict()) {
error(errSyntaxError, -1, "Catalog object is wrong type ({0:s})", catDict.getTypeName());
catDict.free();
+ unlockCatalog;
return pageMode;
}
@@ -542,11 +581,13 @@ Catalog::PageMode Catalog::getPageMode() {
obj.free();
catDict.free();
}
+ unlockCatalog;
return pageMode;
}
Catalog::PageLayout Catalog::getPageLayout() {
+ lockCatalog;
if (pageLayout == pageLayoutNull) {
Object catDict, obj;
@@ -557,6 +598,7 @@ Catalog::PageLayout Catalog::getPageLayout() {
if (!catDict.isDict()) {
error(errSyntaxError, -1, "Catalog object is wrong type ({0:s})", catDict.getTypeName());
catDict.free();
+ unlockCatalog;
return pageLayout;
}
@@ -578,6 +620,7 @@ Catalog::PageLayout Catalog::getPageLayout() {
obj.free();
catDict.free();
}
+ unlockCatalog;
return pageLayout;
}
@@ -744,8 +787,13 @@ GBool Catalog::indexToLabel(int index, GooString *label)
}
}
-int Catalog::getNumPages()
+int Catalog::getNumPages(GBool lock)
{
+ GBool locked = gFalse;
+ if (lock && numPages == -1) {
+ locked = gTrue;
+ lockCatalog;
+ }
if (numPages == -1)
{
Object catDict, pagesDict, obj;
@@ -754,6 +802,7 @@ int Catalog::getNumPages()
if (!catDict.isDict()) {
error(errSyntaxError, -1, "Catalog object is wrong type ({0:s})", catDict.getTypeName());
catDict.free();
+ if (locked) unlockCatalog;
return 0;
}
catDict.dictLookup("Pages", &pagesDict);
@@ -765,6 +814,7 @@ int Catalog::getNumPages()
error(errSyntaxError, -1, "Top-level pages object is wrong type ({0:s})",
pagesDict.getTypeName());
pagesDict.free();
+ if (locked) unlockCatalog;
return 0;
}
@@ -782,11 +832,13 @@ int Catalog::getNumPages()
pagesDict.free();
}
+ if (locked) unlockCatalog;
return numPages;
}
PageLabelInfo *Catalog::getPageLabelInfo()
{
+ lockCatalog;
if (!pageLabelInfo) {
Object catDict;
Object obj;
@@ -795,21 +847,24 @@ PageLabelInfo *Catalog::getPageLabelInfo()
if (!catDict.isDict()) {
error(errSyntaxError, -1, "Catalog object is wrong type ({0:s})", catDict.getTypeName());
catDict.free();
+ unlockCatalog;
return NULL;
}
if (catDict.dictLookup("PageLabels", &obj)->isDict()) {
- pageLabelInfo = new PageLabelInfo(&obj, getNumPages());
+ pageLabelInfo = new PageLabelInfo(&obj, getNumPages(gFalse));
}
obj.free();
catDict.free();
}
+ unlockCatalog;
return pageLabelInfo;
}
Object *Catalog::getStructTreeRoot()
{
+ lockCatalog;
if (structTreeRoot.isNone())
{
Object catDict;
@@ -824,11 +879,13 @@ Object *Catalog::getStructTreeRoot()
catDict.free();
}
+ unlockCatalog;
return &structTreeRoot;
}
Object *Catalog::getOutline()
{
+ lockCatalog;
if (outline.isNone())
{
Object catDict;
@@ -843,11 +900,13 @@ Object *Catalog::getOutline()
catDict.free();
}
+ unlockCatalog;
return &outline;
}
Object *Catalog::getDests()
{
+ lockCatalog;
if (dests.isNone())
{
Object catDict;
@@ -862,6 +921,7 @@ Object *Catalog::getDests()
catDict.free();
}
+ unlockCatalog;
return &dests;
}
@@ -883,8 +943,9 @@ Catalog::FormType Catalog::getFormType()
return res;
}
-Form *Catalog::getForm()
+Form *Catalog::getForm(GBool lock)
{
+ if (lock) lockCatalog;
if (!form) {
if (acroForm.isDict()) {
form = new Form(doc, &acroForm);
@@ -893,17 +954,20 @@ Form *Catalog::getForm()
}
}
+ if (lock) unlockCatalog;
return form;
}
ViewerPreferences *Catalog::getViewerPreferences()
{
+ lockCatalog;
if (!viewerPrefs) {
if (viewerPreferences.isDict()) {
viewerPrefs = new ViewerPreferences(viewerPreferences.getDict());
}
}
+ unlockCatalog;
return viewerPrefs;
}
diff --git a/poppler/Catalog.h b/poppler/Catalog.h
index ef469ec..ac7505f 100644
--- a/poppler/Catalog.h
+++ b/poppler/Catalog.h
@@ -21,6 +21,7 @@
// Copyright (C) 2008, 2011 Pino Toscano <pino at kde.org>
// Copyright (C) 2010 Hib Eris <hib at hiberis.nl>
// Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -34,7 +35,9 @@
#pragma interface
#endif
+#include "poppler-config.h"
#include "Object.h"
+#include "goo/GooMutex.h"
#include <vector>
@@ -104,13 +107,13 @@ public:
GBool isOk() { return ok; }
// Get number of pages.
- int getNumPages();
+ int getNumPages(GBool lock = gTrue);
// Get a page.
Page *getPage(int i);
// Get the reference for a page object.
- Ref *getPageRef(int i);
+ Ref *getPageRef(int i, GBool lock = gTrue);
// Return base URI, or NULL if none.
GooString *getBaseURI() { return baseURI; }
@@ -124,7 +127,7 @@ public:
// Find a page, given its object ID. Returns page number, or 0 if
// not found.
- int findPage(int num, int gen);
+ int findPage(int num, int gen, GBool lock = gTrue);
// Find a named destination. Returns the link destination, or
// NULL if <name> is not a destination.
@@ -162,7 +165,7 @@ public:
};
FormType getFormType();
- Form* getForm();
+ Form* getForm(GBool lock = gTrue);
ViewerPreferences *getViewerPreferences();
@@ -225,6 +228,7 @@ private:
PageMode pageMode; // page mode
PageLayout pageLayout; // page layout
+ void createPages(); // create pages for caching
GBool cachePageTree(int page); // Cache first <page> pages.
Object *findDestInTree(Object *tree, GooString *name, Object *obj);
@@ -232,6 +236,9 @@ private:
NameTree *getDestNameTree();
NameTree *getEmbeddedFileNameTree();
NameTree *getJSNameTree();
+#if MULTITHREADED
+ GooMutex mutex;
+#endif
};
diff --git a/poppler/Dict.cc b/poppler/Dict.cc
index c4f667b..95ed585 100644
--- a/poppler/Dict.cc
+++ b/poppler/Dict.cc
@@ -19,6 +19,7 @@
// Copyright (C) 2008, 2010 Albert Astals Cid <aacid at kde.org>
// Copyright (C) 2010 PaweÅ Wiejacha <pawel.wiejacha at gmail.com>
// Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -39,6 +40,13 @@
#include "XRef.h"
#include "Dict.h"
+#if MULTITHREADED
+# define lockDict gLockMutex(&mutex)
+# define unlockDict gUnlockMutex(&mutex)
+#else
+# define lockDict
+# define unlockDict
+#endif
//------------------------------------------------------------------------
// Dict
//------------------------------------------------------------------------
@@ -74,12 +82,18 @@ Dict::Dict(XRef *xrefA) {
size = length = 0;
ref = 1;
sorted = gFalse;
+#if MULTITHREADED
+ gInitMutex(&mutex);
+#endif
}
Dict::Dict(Dict* dictA) {
xref = dictA->xref;
size = length = dictA->length;
ref = 1;
+#if MULTITHREADED
+ gInitMutex(&mutex);
+#endif
sorted = dictA->sorted;
entries = (DictEntry *)gmallocn(size, sizeof(DictEntry));
@@ -89,6 +103,24 @@ Dict::Dict(Dict* dictA) {
}
}
+Dict *Dict::copy(XRef *xrefA) {
+ lockDict;
+ Dict *dictA = new Dict(this);
+ dictA->xref = xrefA;
+ for (int i=0; i<length; i++) {
+ if (dictA->entries[i].val.getType() == objDict) {
+ Dict *dict = dictA->entries[i].val.getDict();
+ Object obj;
+ obj.initDict(dict->copy(xrefA));
+ dictA->entries[i].val.free();
+ dictA->entries[i].val = obj;
+ obj.free();
+ }
+ }
+ unlockDict;
+ return dictA;
+}
+
Dict::~Dict() {
int i;
@@ -97,9 +129,27 @@ Dict::~Dict() {
entries[i].val.free();
}
gfree(entries);
+#if MULTITHREADED
+ gDestroyMutex(&mutex);
+#endif
+}
+
+int Dict::incRef() {
+ lockDict;
+ ++ref;
+ unlockDict;
+ return ref;
+}
+
+int Dict::decRef() {
+ lockDict;
+ --ref;
+ unlockDict;
+ return ref;
}
void Dict::add(char *key, Object *val) {
+ lockDict;
if (sorted) {
// We use add on very few occasions so
// virtually this will never be hit
@@ -117,13 +167,16 @@ void Dict::add(char *key, Object *val) {
entries[length].key = key;
entries[length].val = *val;
++length;
+ unlockDict;
}
inline DictEntry *Dict::find(const char *key) {
if (!sorted && length >= SORT_LENGTH_LOWER_LIMIT)
{
+ lockDict;
sorted = gTrue;
std::sort(entries, entries+length, cmpDictEntries);
+ unlockDict;
}
if (sorted) {
@@ -147,6 +200,7 @@ GBool Dict::hasKey(const char *key) {
}
void Dict::remove(const char *key) {
+ lockDict;
if (sorted) {
const int pos = binarySearch(key, entries, length);
if (pos != -1) {
@@ -159,7 +213,10 @@ void Dict::remove(const char *key) {
int i;
bool found = false;
DictEntry tmp;
- if(length == 0) return;
+ if(length == 0) {
+ unlockDict;
+ return;
+ }
for(i=0; i<length; i++) {
if (!strcmp(key, entries[i].key)) {
@@ -167,13 +224,17 @@ void Dict::remove(const char *key) {
break;
}
}
- if(!found) return;
+ if(!found) {
+ unlockDict;
+ 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;
}
+ unlockDict;
}
void Dict::set(const char *key, Object *val) {
@@ -184,8 +245,10 @@ void Dict::set(const char *key, Object *val) {
}
e = find (key);
if (e) {
+ lockDict;
e->val.free();
e->val = *val;
+ unlockDict;
} else {
add (copyString(key), val);
}
diff --git a/poppler/Dict.h b/poppler/Dict.h
index 897f221..fba99ed 100644
--- a/poppler/Dict.h
+++ b/poppler/Dict.h
@@ -18,6 +18,7 @@
// Copyright (C) 2007-2008 Julien Rebetez <julienr at svn.gnome.org>
// Copyright (C) 2010 Albert Astals Cid <aacid at kde.org>
// Copyright (C) 2010 PaweÅ Wiejacha <pawel.wiejacha at gmail.com>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -31,7 +32,9 @@
#pragma interface
#endif
+#include "poppler-config.h"
#include "Object.h"
+#include "goo/GooMutex.h"
//------------------------------------------------------------------------
// Dict
@@ -48,13 +51,14 @@ public:
// Constructor.
Dict(XRef *xrefA);
Dict(Dict* dictA);
+ Dict *copy(XRef *xrefA);
// Destructor.
~Dict();
// Reference counting.
- int incRef() { return ++ref; }
- int decRef() { return --ref; }
+ int incRef();
+ int decRef();
// Get number of entries.
int getLength() { return length; }
@@ -98,6 +102,9 @@ private:
int size; // size of <entries> array
int length; // number of entries in dictionary
int ref; // reference count
+#if MULTITHREADED
+ GooMutex mutex;
+#endif
DictEntry *find(const char *key);
};
diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc
index 5c9ed35..454987e 100644
--- a/poppler/Gfx.cc
+++ b/poppler/Gfx.cc
@@ -28,7 +28,7 @@
// Copyright (C) 2008 Michael Vrable <mvrable at cs.ucsd.edu>
// Copyright (C) 2008 Hib Eris <hib at hiberis.nl>
// Copyright (C) 2009 M Joonas Pihlaja <jpihlaja at cc.helsinki.fi>
-// Copyright (C) 2009-2012 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2009-2013 Thomas Freitag <Thomas.Freitag at alfa.de>
// Copyright (C) 2009 William Bader <williambader at hotmail.com>
// Copyright (C) 2009, 2010 David Benjamin <davidben at mit.edu>
// Copyright (C) 2010 Nils Höglund <nils.hoglund at gmail.com>
@@ -322,14 +322,15 @@ static inline GBool isSameGfxColor(const GfxColor &colorA, const GfxColor &color
// GfxResources
//------------------------------------------------------------------------
-GfxResources::GfxResources(XRef *xref, Dict *resDict, GfxResources *nextA) :
+GfxResources::GfxResources(XRef *xref, Dict *resDictA, GfxResources *nextA) :
gStateCache(2, xref) {
Object obj1, obj2;
Ref r;
- if (resDict) {
+ if (resDictA) {
// build font dictionary
+ Dict *resDict = resDictA->copy(xref);
fonts = NULL;
resDict->lookupNF("Font", &obj1);
if (obj1.isRef()) {
@@ -362,6 +363,7 @@ GfxResources::GfxResources(XRef *xref, Dict *resDict, GfxResources *nextA) :
// get properties dictionary
resDict->lookup("Properties", &propertiesDict);
+ delete resDict;
} else {
fonts = NULL;
xObjDict.initNull();
@@ -534,7 +536,7 @@ Gfx::Gfx(PDFDoc *docA, OutputDev *outA, int pageNum, Dict *resDict,
double hDPI, double vDPI, PDFRectangle *box,
PDFRectangle *cropBox, int rotate,
GBool (*abortCheckCbkA)(void *data),
- void *abortCheckCbkDataA)
+ void *abortCheckCbkDataA, XRef *xrefA)
#ifdef USE_CMS
: iccColorSpaceCache(5)
#endif
@@ -542,7 +544,7 @@ Gfx::Gfx(PDFDoc *docA, OutputDev *outA, int pageNum, Dict *resDict,
int i;
doc = docA;
- xref = doc->getXRef();
+ xref = (xrefA == NULL) ? doc->getXRef() : xrefA;
catalog = doc->getCatalog();
subPage = gFalse;
printCommands = globalParams->getPrintCommands();
@@ -561,7 +563,7 @@ Gfx::Gfx(PDFDoc *docA, OutputDev *outA, int pageNum, Dict *resDict,
fontChanged = gFalse;
clip = clipNone;
ignoreUndef = 0;
- out->startPage(pageNum, state);
+ out->startPage(pageNum, state, xref);
out->setDefaultCTM(state->getCTM());
out->updateAll(state);
for (i = 0; i < 6; ++i) {
@@ -589,7 +591,7 @@ Gfx::Gfx(PDFDoc *docA, OutputDev *outA, int pageNum, Dict *resDict,
Gfx::Gfx(PDFDoc *docA, OutputDev *outA, Dict *resDict,
PDFRectangle *box, PDFRectangle *cropBox,
GBool (*abortCheckCbkA)(void *data),
- void *abortCheckCbkDataA)
+ void *abortCheckCbkDataA, XRef *xrefA)
#ifdef USE_CMS
: iccColorSpaceCache(5)
#endif
@@ -597,7 +599,7 @@ Gfx::Gfx(PDFDoc *docA, OutputDev *outA, Dict *resDict,
int i;
doc = docA;
- xref = doc->getXRef();
+ xref = (xrefA == NULL) ? doc->getXRef() : xrefA;
catalog = doc->getCatalog();
subPage = gTrue;
printCommands = globalParams->getPrintCommands();
diff --git a/poppler/Gfx.h b/poppler/Gfx.h
index 7c42f14..369bc4c 100644
--- a/poppler/Gfx.h
+++ b/poppler/Gfx.h
@@ -18,7 +18,7 @@
// Copyright (C) 2008 Brad Hards <bradh at kde.org>
// Copyright (C) 2008, 2010 Carlos Garcia Campos <carlosgc at gnome.org>
// Copyright (C) 2009-2012 Albert Astals Cid <aacid at kde.org>
-// Copyright (C) 2009, 2010, 2012 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2009, 2010, 2012, 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
// Copyright (C) 2010 David Benjamin <davidben at mit.edu>
// Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
//
@@ -148,16 +148,18 @@ public:
double hDPI, double vDPI, PDFRectangle *box,
PDFRectangle *cropBox, int rotate,
GBool (*abortCheckCbkA)(void *data) = NULL,
- void *abortCheckCbkDataA = NULL);
+ void *abortCheckCbkDataA = NULL, XRef *xrefA = NULL);
// Constructor for a sub-page object.
Gfx(PDFDoc *docA, OutputDev *outA, Dict *resDict,
PDFRectangle *box, PDFRectangle *cropBox,
GBool (*abortCheckCbkA)(void *data) = NULL,
- void *abortCheckCbkDataA = NULL);
+ void *abortCheckCbkDataA = NULL, XRef *xrefA = NULL);
~Gfx();
+ XRef *getXRef() { return xref; }
+
// Interpret a stream or array of streams.
void display(Object *obj, GBool topLevel = gTrue);
diff --git a/poppler/GlobalParamsWin.cc b/poppler/GlobalParamsWin.cc
index b76e156..e83c079 100644
--- a/poppler/GlobalParamsWin.cc
+++ b/poppler/GlobalParamsWin.cc
@@ -2,7 +2,7 @@
but mostly based on xpdf code.
// Copyright (C) 2010, 2012 Hib Eris <hib at hiberis.nl>
- // Copyright (C) 2012 Thomas Freitag <Thomas.Freitag at alfa.de>
+ // Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
// Copyright (C) 2012 Suzuki Toshiya <mpsuzuki at hiroshima-u.ac.jp>
// Copyright (C) 2012 Adrian Johnson <ajohnson at redneon.com>
// Copyright (C) 2012 Mark Brand <mabrand at mabrand.nl>
@@ -470,7 +470,7 @@ void GlobalParams::setupBaseFonts(char * dir)
obj1.initNull();
parser = new Parser(NULL,
new Lexer(NULL,
- new FileStream(file, 0, gFalse, size, &obj1)),
+ new FileStream(file, fileName->getCString(), 0, gFalse, size, &obj1)),
gTrue);
obj1.free();
parser->getObj(&obj1);
diff --git a/poppler/Object.h b/poppler/Object.h
index c885d73..09ac5dd 100644
--- a/poppler/Object.h
+++ b/poppler/Object.h
@@ -18,6 +18,7 @@
// Copyright (C) 2008, 2010 Albert Astals Cid <aacid at kde.org>
// Copyright (C) 2009 Jakub Wilk <ubanus at users.sf.net>
// Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -207,7 +208,7 @@ public:
int arrayGetLength();
void arrayAdd(Object *elem);
void arrayRemove(int i);
- Object *arrayGet(int i, Object *obj);
+ Object *arrayGet(int i, Object *obj, int recursion);
Object *arrayGetNF(int i, Object *obj);
// Dict accessors.
@@ -278,8 +279,8 @@ inline void Object::arrayAdd(Object *elem)
inline void Object::arrayRemove(int i)
{ OBJECT_TYPE_CHECK(objArray); array->remove(i); }
-inline Object *Object::arrayGet(int i, Object *obj)
- { OBJECT_TYPE_CHECK(objArray); return array->get(i, obj); }
+inline Object *Object::arrayGet(int i, Object *obj, int recursion = 0)
+ { OBJECT_TYPE_CHECK(objArray); return array->get(i, obj, recursion); }
inline Object *Object::arrayGetNF(int i, Object *obj)
{ OBJECT_TYPE_CHECK(objArray); return array->getNF(i, obj); }
diff --git a/poppler/OutputDev.h b/poppler/OutputDev.h
index f540d57..5cf87cc 100644
--- a/poppler/OutputDev.h
+++ b/poppler/OutputDev.h
@@ -17,7 +17,7 @@
// Copyright (C) 2006 Thorkild Stray <thorkild at ifi.uio.no>
// Copyright (C) 2007 Jeff Muizelaar <jeff at infidigm.net>
// Copyright (C) 2007, 2011 Adrian Johnson <ajohnson at redneon.com>
-// Copyright (C) 2009-2012 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2009-2013 Thomas Freitag <Thomas.Freitag at alfa.de>
// Copyright (C) 2009, 2011 Carlos Garcia Campos <carlosgc at gnome.org>
// Copyright (C) 2009, 2012 Albert Astals Cid <aacid at kde.org>
// Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
@@ -137,7 +137,7 @@ public:
{ return gTrue; }
// Start a page.
- virtual void startPage(int pageNum, GfxState *state) {}
+ virtual void startPage(int pageNum, GfxState *state, XRef *xref) {}
// End a page.
virtual void endPage() {}
diff --git a/poppler/PDFDoc.cc b/poppler/PDFDoc.cc
index 0d78588..7a3dc39 100644
--- a/poppler/PDFDoc.cc
+++ b/poppler/PDFDoc.cc
@@ -26,7 +26,7 @@
// Copyright (C) 2010 Ilya Gorenbein <igorenbein at finjan.com>
// Copyright (C) 2010 Srinivas Adicherla <srinivas.adicherla at geodesic.com>
// Copyright (C) 2010 Philip Lorenz <lorenzph+freedesktop at gmail.com>
-// Copyright (C) 2011, 2012 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2011-2013 Thomas Freitag <Thomas.Freitag at alfa.de>
// Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
//
// To see a description of the changes please see the Changelog file that
@@ -75,6 +75,14 @@
#include "PDFDoc.h"
#include "Hints.h"
+#if MULTITHREADED
+# define lockPDFDoc gLockMutex(&mutex)
+# define unlockPDFDoc gUnlockMutex(&mutex)
+#else
+# define lockPDFDoc
+# define unlockPDFDoc
+#endif
+
//------------------------------------------------------------------------
#define headerSearchSize 1024 // read this many bytes at beginning of
@@ -94,6 +102,9 @@
void PDFDoc::init()
{
+#if MULTITHREADED
+ gInitMutex(&mutex);
+#endif
ok = gFalse;
errCode = errNone;
fileName = NULL;
@@ -160,7 +171,7 @@ PDFDoc::PDFDoc(GooString *fileNameA, GooString *ownerPassword,
// create stream
obj.initNull();
- str = new FileStream(file, 0, gFalse, size, &obj);
+ str = new FileStream(file, fileName->getCString(), 0, gFalse, size, &obj);
ok = setup(ownerPassword, userPassword);
}
@@ -211,7 +222,7 @@ PDFDoc::PDFDoc(wchar_t *fileNameA, int fileNameLen, GooString *ownerPassword,
// create stream
obj.initNull();
- str = new FileStream(file, 0, gFalse, size, &obj);
+ str = new FileStream(file, fileName->getCString(), 0, gFalse, size, &obj);
ok = setup(ownerPassword, userPassword);
}
@@ -246,10 +257,12 @@ PDFDoc::PDFDoc(BaseStream *strA, GooString *ownerPassword,
}
GBool PDFDoc::setup(GooString *ownerPassword, GooString *userPassword) {
+ lockPDFDoc;
str->setPos(0, -1);
if (str->getPos() < 0)
{
error(errSyntaxError, -1, "Document base stream is not seekable");
+ unlockPDFDoc;
return gFalse;
}
@@ -269,12 +282,14 @@ GBool PDFDoc::setup(GooString *ownerPassword, GooString *userPassword) {
if (!xref->isOk()) {
error(errSyntaxError, -1, "Couldn't read xref table");
errCode = xref->getErrorCode();
+ unlockPDFDoc;
return gFalse;
}
// check for encryption
if (!checkEncryption(ownerPassword, userPassword)) {
errCode = errEncrypted;
+ unlockPDFDoc;
return gFalse;
}
@@ -293,11 +308,13 @@ GBool PDFDoc::setup(GooString *ownerPassword, GooString *userPassword) {
if (catalog && !catalog->isOk()) {
error(errSyntaxError, -1, "Couldn't read page catalog");
errCode = errBadCatalog;
+ unlockPDFDoc;
return gFalse;
}
}
// done
+ unlockPDFDoc;
return gTrue;
}
@@ -342,6 +359,9 @@ PDFDoc::~PDFDoc() {
gfree(fileNameU);
}
#endif
+#if MULTITHREADED
+ gDestroyMutex(&mutex);
+#endif
}
@@ -455,7 +475,7 @@ void PDFDoc::displayPage(OutputDev *out, int page,
GBool (*abortCheckCbk)(void *data),
void *abortCheckCbkData,
GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
- void *annotDisplayDecideCbkData) {
+ void *annotDisplayDecideCbkData, GBool copyXRef) {
if (globalParams->getPrintCommands()) {
printf("***** page %d *****\n", page);
}
@@ -464,7 +484,7 @@ void PDFDoc::displayPage(OutputDev *out, int page,
getPage(page)->display(out, hDPI, vDPI,
rotate, useMediaBox, crop, printing,
abortCheckCbk, abortCheckCbkData,
- annotDisplayDecideCbk, annotDisplayDecideCbkData);
+ annotDisplayDecideCbk, annotDisplayDecideCbkData, copyXRef);
}
@@ -491,14 +511,14 @@ void PDFDoc::displayPageSlice(OutputDev *out, int page,
GBool (*abortCheckCbk)(void *data),
void *abortCheckCbkData,
GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
- void *annotDisplayDecideCbkData) {
+ void *annotDisplayDecideCbkData, GBool copyXRef) {
if (getPage(page))
getPage(page)->displaySlice(out, hDPI, vDPI,
rotate, useMediaBox, crop,
sliceX, sliceY, sliceW, sliceH,
printing,
abortCheckCbk, abortCheckCbkData,
- annotDisplayDecideCbk, annotDisplayDecideCbkData);
+ annotDisplayDecideCbk, annotDisplayDecideCbkData, copyXRef);
}
Links *PDFDoc::getLinks(int page) {
@@ -826,11 +846,13 @@ int PDFDoc::saveWithoutChangesAs(GooString *name) {
int PDFDoc::saveWithoutChangesAs(OutStream *outStr) {
int c;
- str->reset();
- while ((c = str->getChar()) != EOF) {
+ BaseStream *copyStr = str->copy();
+ copyStr->reset();
+ while ((c = copyStr->getChar()) != EOF) {
outStr->put(c);
}
- str->close();
+ copyStr->close();
+ delete copyStr;
return errNone;
}
@@ -840,11 +862,13 @@ void PDFDoc::saveIncrementalUpdate (OutStream* outStr)
XRef *uxref;
int c;
//copy the original file
- str->reset();
- while ((c = str->getChar()) != EOF) {
+ BaseStream *copyStr = str->copy();
+ copyStr->reset();
+ while ((c = copyStr->getChar()) != EOF) {
outStr->put(c);
}
- str->close();
+ copyStr->close();
+ delete copyStr;
Guchar *fileKey;
CryptAlgorithm encAlgorithm;
@@ -853,6 +877,7 @@ void PDFDoc::saveIncrementalUpdate (OutStream* outStr)
uxref = new XRef();
uxref->add(0, 65535, 0, gFalse);
+ xref->lock();
for(int i=0; i<xref->getNumObjects(); i++) {
if ((xref->getEntry(i)->type == xrefEntryFree) &&
(xref->getEntry(i)->gen == 0)) //we skip the irrelevant free objects
@@ -864,7 +889,7 @@ void PDFDoc::saveIncrementalUpdate (OutStream* outStr)
ref.gen = xref->getEntry(i)->type == xrefEntryCompressed ? 0 : xref->getEntry(i)->gen;
if (xref->getEntry(i)->type != xrefEntryFree) {
Object obj1;
- xref->fetch(ref.num, ref.gen, &obj1);
+ xref->fetch(ref.num, ref.gen, &obj1, 1);
Guint offset = writeObjectHeader(&ref, outStr);
writeObject(&obj1, outStr, fileKey, encAlgorithm, keyLength, ref.num, ref.gen);
writeObjectFooter(outStr);
@@ -875,6 +900,7 @@ void PDFDoc::saveIncrementalUpdate (OutStream* outStr)
}
}
}
+ xref->unlock();
if (uxref->getNumObjects() == 0) { //we have nothing to update
delete uxref;
return;
@@ -922,6 +948,7 @@ void PDFDoc::saveCompleteRewrite (OutStream* outStr)
outStr->printf("%%PDF-%d.%d\r\n",pdfMajorVersion,pdfMinorVersion);
XRef *uxref = new XRef();
uxref->add(0, 65535, 0, gFalse);
+ xref->lock();
for(int i=0; i<xref->getNumObjects(); i++) {
Object obj1;
Ref ref;
@@ -941,7 +968,7 @@ void PDFDoc::saveCompleteRewrite (OutStream* outStr)
} else if (type == xrefEntryUncompressed){
ref.num = i;
ref.gen = xref->getEntry(i)->gen;
- xref->fetch(ref.num, ref.gen, &obj1);
+ xref->fetch(ref.num, ref.gen, &obj1, 1);
Guint offset = writeObjectHeader(&ref, outStr);
// Write unencrypted objects in unencrypted form
if (xref->getEntry(i)->getFlag(XRefEntry::Unencrypted)) {
@@ -955,7 +982,7 @@ void PDFDoc::saveCompleteRewrite (OutStream* outStr)
} else if (type == xrefEntryCompressed) {
ref.num = i;
ref.gen = 0; //compressed entries have gen == 0
- xref->fetch(ref.num, ref.gen, &obj1);
+ xref->fetch(ref.num, ref.gen, &obj1, 1);
Guint offset = writeObjectHeader(&ref, outStr);
writeObject(&obj1, outStr, fileKey, encAlgorithm, keyLength, ref.num, ref.gen);
writeObjectFooter(outStr);
@@ -963,6 +990,7 @@ void PDFDoc::saveCompleteRewrite (OutStream* outStr)
obj1.free();
}
}
+ xref->unlock();
Guint uxrefOffset = outStr->getPos();
writeXRefTableTrailer(uxrefOffset, uxref, gTrue /* write all entries */,
uxref->getNumObjects(), outStr, gFalse /* complete rewrite */);
@@ -1562,8 +1590,10 @@ Guint PDFDoc::writePageObjects(OutStream *outStr, XRef *xRef, Guint numOffset, G
Outline *PDFDoc::getOutline()
{
if (!outline) {
+ lockPDFDoc;
// read outline
outline = new Outline(catalog->getOutline(), xref);
+ unlockPDFDoc;
}
return outline;
@@ -1720,14 +1750,18 @@ Page *PDFDoc::getPage(int page)
if ((page < 1) || page > getNumPages()) return NULL;
if (isLinearized()) {
+ lockPDFDoc;
if (!pageCache) {
pageCache = (Page **) gmallocn(getNumPages(), sizeof(Page *));
for (int i = 0; i < getNumPages(); i++) {
pageCache[i] = NULL;
}
}
+ unlockPDFDoc;
if (!pageCache[page-1]) {
+ lockPDFDoc;
pageCache[page-1] = parsePage(page);
+ unlockPDFDoc;
}
if (pageCache[page-1]) {
return pageCache[page-1];
diff --git a/poppler/PDFDoc.h b/poppler/PDFDoc.h
index 4562346..75d0c40 100644
--- a/poppler/PDFDoc.h
+++ b/poppler/PDFDoc.h
@@ -22,7 +22,7 @@
// Copyright (C) 2009 Kovid Goyal <kovid at kovidgoyal.net>
// Copyright (C) 2010 Hib Eris <hib at hiberis.nl>
// Copyright (C) 2010 Srinivas Adicherla <srinivas.adicherla at geodesic.com>
-// Copyright (C) 2011, 2012 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2011, 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
// Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
//
// To see a description of the changes please see the Changelog file that
@@ -37,7 +37,9 @@
#pragma interface
#endif
+#include "poppler-config.h"
#include <stdio.h>
+#include "goo/GooMutex.h"
#include "XRef.h"
#include "Catalog.h"
#include "Page.h"
@@ -146,7 +148,7 @@ public:
GBool (*abortCheckCbk)(void *data) = NULL,
void *abortCheckCbkData = NULL,
GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data) = NULL,
- void *annotDisplayDecideCbkData = NULL);
+ void *annotDisplayDecideCbkData = NULL, GBool copyXRef = gFalse);
// Display a range of pages.
void displayPages(OutputDev *out, int firstPage, int lastPage,
@@ -165,7 +167,7 @@ public:
GBool (*abortCheckCbk)(void *data) = NULL,
void *abortCheckCbkData = NULL,
GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data) = NULL,
- void *annotDisplayDecideCbkData = NULL);
+ void *annotDisplayDecideCbkData = NULL, GBool copyXRef = gFalse);
// Find a page, given its object ID. Returns page number, or 0 if
// not found.
@@ -326,6 +328,9 @@ private:
int fopenErrno;
Guint startXRefPos; // offset of last xref table
+#if MULTITHREADED
+ GooMutex mutex;
+#endif
};
#endif
diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc
index 95be97f..9042297 100644
--- a/poppler/PSOutputDev.cc
+++ b/poppler/PSOutputDev.cc
@@ -20,7 +20,7 @@
// Copyright (C) 2007, 2008 Brad Hards <bradh at kde.org>
// Copyright (C) 2008, 2009 Koji Otani <sho at bbr.jp>
// Copyright (C) 2008, 2010 Hib Eris <hib at hiberis.nl>
-// Copyright (C) 2009-2012 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2009-2013 Thomas Freitag <Thomas.Freitag at alfa.de>
// Copyright (C) 2009 Till Kamppeter <till.kamppeter at gmail.com>
// Copyright (C) 2009 Carlos Garcia Campos <carlosgc at gnome.org>
// Copyright (C) 2009, 2011, 2012 William Bader <williambader at hotmail.com>
@@ -3085,7 +3085,7 @@ GBool PSOutputDev::checkPageSlice(Page *page, double /*hDPI*/, double /*vDPI*/,
rotateA += 360;
}
state = new GfxState(dpi, dpi, &box, rotateA, gFalse);
- startPage(page->getNum(), state);
+ startPage(page->getNum(), state, xref);
delete state;
// set up the SplashOutputDev
@@ -3471,14 +3471,14 @@ GBool PSOutputDev::checkPageSlice(Page *page, double /*hDPI*/, double /*vDPI*/,
#endif // HAVE_SPLASH
}
-void PSOutputDev::startPage(int pageNum, GfxState *state) {
+void PSOutputDev::startPage(int pageNum, GfxState *state, XRef *xrefA) {
Page *page;
int x1, y1, x2, y2, width, height, t;
int imgWidth, imgHeight, imgWidth2, imgHeight2;
GBool landscape;
GooString *s;
-
+ xref = xrefA;
if (mode == psModePS || mode == psModePSOrigPageSizes) {
GooString pageLabel;
const GBool gotLabel = doc->getCatalog()->indexToLabel(pageNum -1, &pageLabel);
@@ -4284,7 +4284,7 @@ GBool PSOutputDev::tilingPatternFillL2(GfxState *state, Catalog *cat, Object *st
return gTrue;
}
-GBool PSOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, Catalog *cat, Object *str,
+GBool PSOutputDev::tilingPatternFill(GfxState *state, Gfx *gfxA, Catalog *cat, Object *str,
double *pmat, int paintType, int tilingType, Dict *resDict,
double *mat, double *bbox,
int x0, int y0, int x1, int y1,
@@ -4303,7 +4303,7 @@ GBool PSOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, Catalog *cat, Ob
box.y1 = bbox[1];
box.x2 = bbox[2];
box.y2 = bbox[3];
- gfx = new Gfx(doc, this, resDict, &box, NULL);
+ gfx = new Gfx(doc, this, resDict, &box, NULL, NULL, NULL, gfxA->getXRef());
writePSFmt("[{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] cm\n", mat[0], mat[1], mat[2], mat[3], tx, ty);
inType3Char = gTrue;
gfx->display(str);
diff --git a/poppler/PSOutputDev.h b/poppler/PSOutputDev.h
index 6f29096..58cbe46 100644
--- a/poppler/PSOutputDev.h
+++ b/poppler/PSOutputDev.h
@@ -17,7 +17,7 @@
// Copyright (C) 2005 Kristian Høgsberg <krh at redhat.com>
// Copyright (C) 2006-2008, 2012 Albert Astals Cid <aacid at kde.org>
// Copyright (C) 2007 Brad Hards <bradh at kde.org>
-// Copyright (C) 2009-2012 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2009-2013 Thomas Freitag <Thomas.Freitag at alfa.de>
// Copyright (C) 2009 Till Kamppeter <till.kamppeter at gmail.com>
// Copyright (C) 2009 Carlos Garcia Campos <carlosgc at gnome.org>
// Copyright (C) 2009, 2011 William Bader <williambader at hotmail.com>
@@ -186,7 +186,7 @@ public:
void *annotDisplayDecideCbkData = NULL);
// Start a page.
- virtual void startPage(int pageNum, GfxState *state);
+ virtual void startPage(int pageNum, GfxState *state, XRef *xref);
// End a page.
virtual void endPage();
diff --git a/poppler/Page.cc b/poppler/Page.cc
index 8c2065b..fa6d2a9 100644
--- a/poppler/Page.cc
+++ b/poppler/Page.cc
@@ -25,6 +25,7 @@
// Copyright (C) 2008 Brad Hards <bradh at kde.org>
// Copyright (C) 2008 Ilya Gorenbein <igorenbein at finjan.com>
// Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -57,6 +58,13 @@
#include "Catalog.h"
#include "Form.h"
+#if MULTITHREADED
+# define lockPage gLockMutex(&mutex)
+# define unlockPage gUnlockMutex(&mutex)
+#else
+# define lockPage
+# define unlockPage
+#endif
//------------------------------------------------------------------------
// PDFRectangle
//------------------------------------------------------------------------
@@ -257,6 +265,9 @@ GBool PageAttrs::readBox(Dict *dict, const char *key, PDFRectangle *box) {
Page::Page(PDFDoc *docA, int numA, Dict *pageDict, Ref pageRefA, PageAttrs *attrsA, Form *form) {
Object tmp;
+#if MULTITHREADED
+ gInitMutex(&mutex);
+#endif
ok = gTrue;
doc = docA;
xref = doc->getXRef();
@@ -343,6 +354,36 @@ Page::~Page() {
trans.free();
thumb.free();
actions.free();
+#if MULTITHREADED
+ gDestroyMutex(&mutex);
+#endif
+}
+
+void Page::replaceXRef(XRef *xrefA) {
+ Object obj1;
+ Dict *pageDict = pageObj.getDict()->copy(xrefA);
+ xref = xrefA;
+ trans.free();
+ pageDict->lookupNF("Trans", &trans);
+ annotsObj.free();
+ pageDict->lookupNF("Annots", &annotsObj);
+ contents.free();
+ pageDict->lookupNF("Contents", &contents);
+ if (contents.isArray()) {
+ contents.free();
+ pageDict->lookupNF("Contents", &obj1)->getArray()->copy(xrefA, &contents);
+ obj1.free();
+ }
+ thumb.free();
+ pageDict->lookupNF("Thumb", &thumb);
+ actions.free();
+ pageDict->lookupNF("AA", &actions);
+ pageDict->lookup("Resources", &obj1);
+ if (obj1.isDict()) {
+ attrs->replaceResource(obj1);
+ }
+ obj1.free();
+ delete pageDict;
}
Annots *Page::getAnnots() {
@@ -363,6 +404,7 @@ void Page::addAnnot(Annot *annot) {
// Make sure we have annots before adding the new one
// even if it's an empty list so that we can safely
// call annots->appendAnnot(annot)
+ lockPage;
getAnnots();
if (annotsObj.isNull()) {
@@ -392,12 +434,14 @@ void Page::addAnnot(Annot *annot) {
annots->appendAnnot(annot);
annot->setPage(num, gTrue);
+ unlockPage;
}
void Page::removeAnnot(Annot *annot) {
Ref annotRef = annot->getRef();
Object annArray;
+ lockPage;
getAnnots(&annArray);
if (annArray.isArray()) {
int idx = -1;
@@ -414,6 +458,7 @@ void Page::removeAnnot(Annot *annot) {
if (idx == -1) {
error(errInternal, -1, "Annotation doesn't belong to this page");
annArray.free();
+ unlockPage;
return;
}
annots->removeAnnot(annot); // Gracefully fails on popup windows
@@ -429,6 +474,7 @@ void Page::removeAnnot(Annot *annot) {
annArray.free();
annot->removeReferencedObjects(); // Note: Might recurse in removeAnnot again
annot->setPage(0, gFalse);
+ unlockPage;
}
Links *Page::getLinks() {
@@ -445,10 +491,11 @@ void Page::display(OutputDev *out, double hDPI, double vDPI,
GBool (*abortCheckCbk)(void *data),
void *abortCheckCbkData,
GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
- void *annotDisplayDecideCbkData) {
+ void *annotDisplayDecideCbkData,
+ GBool copyXRef) {
displaySlice(out, hDPI, vDPI, rotate, useMediaBox, crop, -1, -1, -1, -1, printing,
abortCheckCbk, abortCheckCbkData,
- annotDisplayDecideCbk, annotDisplayDecideCbkData);
+ annotDisplayDecideCbk, annotDisplayDecideCbkData, copyXRef);
}
Gfx *Page::createGfx(OutputDev *out, double hDPI, double vDPI,
@@ -456,7 +503,7 @@ Gfx *Page::createGfx(OutputDev *out, double hDPI, double vDPI,
int sliceX, int sliceY, int sliceW, int sliceH,
GBool printing,
GBool (*abortCheckCbk)(void *data),
- void *abortCheckCbkData) {
+ void *abortCheckCbkData, XRef *xrefA) {
PDFRectangle *mediaBox, *cropBox;
PDFRectangle box;
Gfx *gfx;
@@ -486,7 +533,7 @@ Gfx *Page::createGfx(OutputDev *out, double hDPI, double vDPI,
}
gfx = new Gfx(doc, out, num, attrs->getResourceDict(),
hDPI, vDPI, &box, crop ? cropBox : (PDFRectangle *)NULL,
- rotate, abortCheckCbk, abortCheckCbkData);
+ rotate, abortCheckCbk, abortCheckCbkData, xrefA);
return gfx;
}
@@ -498,7 +545,8 @@ void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
GBool (*abortCheckCbk)(void *data),
void *abortCheckCbkData,
GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
- void *annotDisplayDecideCbkData) {
+ void *annotDisplayDecideCbkData,
+ GBool copyXRef) {
Gfx *gfx;
Object obj;
Annots *annotList;
@@ -511,13 +559,18 @@ void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
annotDisplayDecideCbk, annotDisplayDecideCbkData)) {
return;
}
+ lockPage;
+ XRef *localXRef = (copyXRef) ? xref->copy() : xref;
+ if (copyXRef) {
+ replaceXRef(localXRef);
+ }
gfx = createGfx(out, hDPI, vDPI, rotate, useMediaBox, crop,
sliceX, sliceY, sliceW, sliceH,
printing,
- abortCheckCbk, abortCheckCbkData);
+ abortCheckCbk, abortCheckCbkData, localXRef);
- contents.fetch(xref, &obj);
+ contents.fetch(localXRef, &obj);
if (!obj.isNull()) {
gfx->saveState();
gfx->display(&obj);
@@ -548,6 +601,11 @@ void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
}
delete gfx;
+ if (copyXRef) {
+ replaceXRef(doc->getXRef());
+ delete localXRef;
+ }
+ unlockPage;
}
void Page::display(Gfx *gfx) {
@@ -576,9 +634,11 @@ GBool Page::loadThumb(unsigned char **data_out,
GfxImageColorMap *colorMap;
/* Get stream dict */
+ lockPage;
thumb.fetch(xref, &fetched_thumb);
if (!fetched_thumb.isStream()) {
fetched_thumb.free();
+ unlockPage;
return gFalse;
}
@@ -661,6 +721,7 @@ GBool Page::loadThumb(unsigned char **data_out,
delete colorMap;
fail1:
+ unlockPage;
fetched_thumb.free();
return success;
diff --git a/poppler/Page.h b/poppler/Page.h
index a6098ed..100731d 100644
--- a/poppler/Page.h
+++ b/poppler/Page.h
@@ -21,6 +21,7 @@
// Copyright (C) 2008 Iñigo MartÃnez <inigomartinez at gmail.com>
// Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
// Copyright (C) 2012 Albert Astals Cid <aacid at kde.org>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -34,7 +35,9 @@
#pragma interface
#endif
+#include "poppler-config.h"
#include "Object.h"
+#include "goo/GooMutex.h"
class Dict;
class PDFDoc;
@@ -102,6 +105,8 @@ public:
? separationInfo.getDict() : (Dict *)NULL; }
Dict *getResourceDict()
{ return resources.isDict() ? resources.getDict() : (Dict *)NULL; }
+ void replaceResource(Object obj1)
+ { resources.free(); obj1.copy(&resources); }
// Clip all other boxes to the MediaBox.
void clipBoxes();
@@ -210,7 +215,7 @@ public:
int sliceX, int sliceY, int sliceW, int sliceH,
GBool printing,
GBool (*abortCheckCbk)(void *data),
- void *abortCheckCbkData);
+ void *abortCheckCbkData, XRef *xrefA = NULL);
// Display a page.
void display(OutputDev *out, double hDPI, double vDPI,
@@ -219,7 +224,8 @@ public:
GBool (*abortCheckCbk)(void *data) = NULL,
void *abortCheckCbkData = NULL,
GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data) = NULL,
- void *annotDisplayDecideCbkData = NULL);
+ void *annotDisplayDecideCbkData = NULL,
+ GBool copyXRef = gFalse);
// Display part of a page.
void displaySlice(OutputDev *out, double hDPI, double vDPI,
@@ -229,7 +235,8 @@ public:
GBool (*abortCheckCbk)(void *data) = NULL,
void *abortCheckCbkData = NULL,
GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data) = NULL,
- void *annotDisplayDecideCbkData = NULL);
+ void *annotDisplayDecideCbkData = NULL,
+ GBool copyXRef = gFalse);
void display(Gfx *gfx);
@@ -245,6 +252,8 @@ public:
int rotate, GBool useMediaBox, GBool upsideDown);
private:
+ // replace xref
+ void replaceXRef(XRef *xrefA);
PDFDoc *doc;
XRef *xref; // the xref table for this PDF file
@@ -260,6 +269,9 @@ private:
Object actions; // page addiction actions
double duration; // page duration
GBool ok; // true if page is valid
+#if MULTITHREADED
+ GooMutex mutex;
+#endif
};
#endif
diff --git a/poppler/Parser.cc b/poppler/Parser.cc
index 431a279..41c611d 100644
--- a/poppler/Parser.cc
+++ b/poppler/Parser.cc
@@ -17,6 +17,7 @@
// Copyright (C) 2006 Krzysztof Kowalczyk <kkowalczyk at gmail.com>
// Copyright (C) 2009 Ilya Gorenbein <igorenbein at finjan.com>
// Copyright (C) 2012 Hib Eris <hib at hiberis.nl>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -271,7 +272,7 @@ Stream *Parser::makeStream(Object *dict, Guchar *fileKey,
}
// get filters
- str = str->addFilters(dict);
+ str = str->addFilters(dict, recursion);
return str;
}
diff --git a/poppler/PreScanOutputDev.cc b/poppler/PreScanOutputDev.cc
index 3a86d52..6a01126 100644
--- a/poppler/PreScanOutputDev.cc
+++ b/poppler/PreScanOutputDev.cc
@@ -16,7 +16,7 @@
// Copyright (C) 2009 Carlos Garcia Campos <carlosgc at gnome.org>
// Copyright (C) 2010, 2011 Albert Astals Cid <aacid at kde.org>
// Copyright (C) 2011 William Bader <williambader at hotmail.com>
-// Copyright (C) 2011 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2011, 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
// Copyright (C) 2011 Adrian Johnson <ajohnson at redneon.com>
//
// To see a description of the changes please see the Changelog file that
@@ -52,7 +52,7 @@ PreScanOutputDev::PreScanOutputDev(PDFDoc *docA) {
PreScanOutputDev::~PreScanOutputDev() {
}
-void PreScanOutputDev::startPage(int /*pageNum*/, GfxState * /*state*/) {
+void PreScanOutputDev::startPage(int /*pageNum*/, GfxState * /*state*/, XRef * /*xref*/) {
}
void PreScanOutputDev::endPage() {
diff --git a/poppler/PreScanOutputDev.h b/poppler/PreScanOutputDev.h
index 5260a3b..0fc9d3e 100644
--- a/poppler/PreScanOutputDev.h
+++ b/poppler/PreScanOutputDev.h
@@ -16,7 +16,7 @@
// Copyright (C) 2009 Carlos Garcia Campos <carlosgc at gnome.org>
// Copyright (C) 2010 Albert Astals Cid <aacid at kde.org>
// Copyright (C) 2011 William Bader <williambader at hotmail.com>
-// Copyright (C) 2011 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2011, 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
// Copyright (C) 2011 Adrian Johnson <ajohnson at redneon.com>
//
// To see a description of the changes please see the Changelog file that
@@ -76,7 +76,7 @@ public:
//----- initialization and control
// Start a page.
- virtual void startPage(int pageNum, GfxState *state);
+ virtual void startPage(int pageNum, GfxState *state, XRef *xref);
// End a page.
virtual void endPage();
diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc
index 6f2d4d6..c55a2a2 100644
--- a/poppler/SplashOutputDev.cc
+++ b/poppler/SplashOutputDev.cc
@@ -20,7 +20,7 @@
// Copyright (C) 2006 Scott Turner <scotty1024 at mac.com>
// Copyright (C) 2007 Koji Otani <sho at bbr.jp>
// Copyright (C) 2009 Petr Gajdos <pgajdos at novell.com>
-// Copyright (C) 2009-2012 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2009-2013 Thomas Freitag <Thomas.Freitag at alfa.de>
// Copyright (C) 2009 Carlos Garcia Campos <carlosgc at gnome.org>
// Copyright (C) 2009 William Bader <williambader at hotmail.com>
// Copyright (C) 2010 Patrick Spendrin <ps_ml at gmx.de>
@@ -1250,6 +1250,7 @@ SplashOutputDev::SplashOutputDev(SplashColorMode colorModeA,
textClipPath = NULL;
transpGroupStack = NULL;
nestCount = 0;
+ xref = NULL;
}
void SplashOutputDev::setupScreenParams(double hDPI, double vDPI) {
@@ -1345,12 +1346,13 @@ void SplashOutputDev::startDoc(PDFDoc *docA) {
nT3Fonts = 0;
}
-void SplashOutputDev::startPage(int pageNum, GfxState *state) {
+void SplashOutputDev::startPage(int pageNum, GfxState *state, XRef *xrefA) {
int w, h;
double *ctm;
SplashCoord mat[6];
SplashColor color;
+ xref = xrefA;
if (state) {
setupScreenParams(state->getHDPI(), state->getVDPI());
w = (int)(state->getPageWidth() + 0.5);
@@ -1840,7 +1842,7 @@ void SplashOutputDev::doUpdateFont(GfxState *state) {
} else {
- if (!(fontLoc = gfxFont->locateFont(doc->getXRef(), gFalse))) {
+ if (!(fontLoc = gfxFont->locateFont((xref) ? xref : doc->getXRef(), gFalse))) {
error(errSyntaxError, -1, "Couldn't find a font for '{0:s}'",
gfxFont->getName() ? gfxFont->getName()->getCString()
: "(unnamed)");
@@ -1850,7 +1852,7 @@ void SplashOutputDev::doUpdateFont(GfxState *state) {
// embedded font
if (fontLoc->locType == gfxFontLocEmbedded) {
// if there is an embedded font, read it to memory
- tmpBuf = gfxFont->readEmbFontFile(doc->getXRef(), &tmpBufLen);
+ tmpBuf = gfxFont->readEmbFontFile((xref) ? xref : doc->getXRef(), &tmpBufLen);
if (! tmpBuf)
goto err2;
@@ -3385,7 +3387,7 @@ void SplashOutputDev::drawMaskedImage(GfxState *state, Object *ref,
if (maskWidth > width || maskHeight > height) {
decodeLow.initInt(maskInvert ? 0 : 1);
decodeHigh.initInt(maskInvert ? 1 : 0);
- maskDecode.initArray(doc->getXRef());
+ maskDecode.initArray((xref) ? xref : doc->getXRef());
maskDecode.arrayAdd(&decodeLow);
maskDecode.arrayAdd(&decodeHigh);
maskColorMap = new GfxImageColorMap(1, &maskDecode,
@@ -4075,7 +4077,7 @@ void SplashOutputDev::setFreeTypeHinting(GBool enable, GBool enableSlightHinting
enableSlightHinting = enableSlightHintingA;
}
-GBool SplashOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx1, Catalog *catalog, Object *str,
+GBool SplashOutputDev::tilingPatternFill(GfxState *state, Gfx *gfxA, Catalog *catalog, Object *str,
double *ptm, int paintType, int /*tilingType*/, Dict *resDict,
double *mat, double *bbox,
int x0, int y0, int x1, int y1,
@@ -4207,7 +4209,7 @@ GBool SplashOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx1, Catalog *ca
box.x1 = bbox[0]; box.y1 = bbox[1];
box.x2 = bbox[2]; box.y2 = bbox[3];
- gfx = new Gfx(doc, this, resDict, &box, NULL);
+ gfx = new Gfx(doc, this, resDict, &box, NULL, NULL, NULL, gfxA->getXRef());
// set pattern transformation matrix
gfx->getState()->setCTM(m1.m[0], m1.m[1], m1.m[2], m1.m[3], m1.m[4], m1.m[5]);
updateCTM(gfx->getState(), m1.m[0], m1.m[1], m1.m[2], m1.m[3], m1.m[4], m1.m[5]);
diff --git a/poppler/SplashOutputDev.h b/poppler/SplashOutputDev.h
index de7934d..830356a 100644
--- a/poppler/SplashOutputDev.h
+++ b/poppler/SplashOutputDev.h
@@ -14,7 +14,7 @@
// under GPL version 2 or later
//
// Copyright (C) 2005 Takashi Iwai <tiwai at suse.de>
-// Copyright (C) 2009-2012 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2009-2013 Thomas Freitag <Thomas.Freitag at alfa.de>
// Copyright (C) 2009 Carlos Garcia Campos <carlosgc at gnome.org>
// Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
// Copyright (C) 2011 Andreas Hartmetz <ahartmetz at gmail.com>
@@ -195,7 +195,7 @@ public:
//----- initialization and control
// Start a page.
- virtual void startPage(int pageNum, GfxState *state);
+ virtual void startPage(int pageNum, GfxState *state, XRef *xref);
// End a page.
virtual void endPage();
@@ -399,6 +399,7 @@ private:
GBool skipRotatedText;
PDFDoc *doc; // the current document
+ XRef *xref; // the xref of the current document
SplashBitmap *bitmap;
Splash *splash;
diff --git a/poppler/Stream.cc b/poppler/Stream.cc
index 4cb3326..482bcbf 100644
--- a/poppler/Stream.cc
+++ b/poppler/Stream.cc
@@ -23,7 +23,7 @@
// Copyright (C) 2010 Hib Eris <hib at hiberis.nl>
// Copyright (C) 2010 Tomas Hoger <thoger at redhat.com>
// Copyright (C) 2011, 2012 William Bader <williambader at hotmail.com>
-// Copyright (C) 2012 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
// Copyright (C) 2012 Oliver Sander <sander at mi.fu-berlin.de>
// Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
// Copyright (C) 2012 Even Rouault <even.rouault at mines-paris.org>
@@ -86,15 +86,42 @@ static GBool setDJSYSFLAGS = gFalse;
#endif
#endif
+#if MULTITHREADED
+# define lockStream gLockMutex(&mutex)
+# define unlockStream gUnlockMutex(&mutex)
+#else
+# define lockStream
+# define unlockStream
+#endif
//------------------------------------------------------------------------
// Stream (base class)
//------------------------------------------------------------------------
Stream::Stream() {
ref = 1;
+#if MULTITHREADED
+ gInitMutex(&mutex);
+#endif
}
Stream::~Stream() {
+#if MULTITHREADED
+ gDestroyMutex(&mutex);
+#endif
+}
+
+int Stream::incRef() {
+ lockStream;
+ ++ref;
+ unlockStream;
+ return ref;
+}
+
+int Stream::decRef() {
+ lockStream;
+ --ref;
+ unlockStream;
+ return ref;
}
void Stream::close() {
@@ -139,34 +166,34 @@ GooString *Stream::getPSFilter(int psLevel, const char *indent) {
return new GooString();
}
-Stream *Stream::addFilters(Object *dict) {
+Stream *Stream::addFilters(Object *dict, int recursion) {
Object obj, obj2;
Object params, params2;
Stream *str;
int i;
str = this;
- dict->dictLookup("Filter", &obj);
+ dict->dictLookup("Filter", &obj, recursion);
if (obj.isNull()) {
obj.free();
dict->dictLookup("F", &obj);
}
- dict->dictLookup("DecodeParms", ¶ms);
+ dict->dictLookup("DecodeParms", ¶ms, recursion);
if (params.isNull()) {
params.free();
dict->dictLookup("DP", ¶ms);
}
if (obj.isName()) {
- str = makeFilter(obj.getName(), str, ¶ms);
+ str = makeFilter(obj.getName(), str, ¶ms, recursion);
} else if (obj.isArray()) {
for (i = 0; i < obj.arrayGetLength(); ++i) {
obj.arrayGet(i, &obj2);
if (params.isArray())
- params.arrayGet(i, ¶ms2);
+ params.arrayGet(i, ¶ms2, recursion);
else
params2.initNull();
if (obj2.isName()) {
- str = makeFilter(obj2.getName(), str, ¶ms2);
+ str = makeFilter(obj2.getName(), str, ¶ms2, recursion);
} else {
error(errSyntaxError, getPos(), "Bad filter name");
str = new EOFStream(str);
@@ -183,7 +210,7 @@ Stream *Stream::addFilters(Object *dict) {
return str;
}
-Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
+Stream *Stream::makeFilter(char *name, Stream *str, Object *params, int recursion) {
int pred; // parameters
int colors;
int bits;
@@ -205,23 +232,23 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
bits = 8;
early = 1;
if (params->isDict()) {
- params->dictLookup("Predictor", &obj);
+ params->dictLookup("Predictor", &obj, recursion);
if (obj.isInt())
pred = obj.getInt();
obj.free();
- params->dictLookup("Columns", &obj);
+ params->dictLookup("Columns", &obj, recursion);
if (obj.isInt())
columns = obj.getInt();
obj.free();
- params->dictLookup("Colors", &obj);
+ params->dictLookup("Colors", &obj, recursion);
if (obj.isInt())
colors = obj.getInt();
obj.free();
- params->dictLookup("BitsPerComponent", &obj);
+ params->dictLookup("BitsPerComponent", &obj, recursion);
if (obj.isInt())
bits = obj.getInt();
obj.free();
- params->dictLookup("EarlyChange", &obj);
+ params->dictLookup("EarlyChange", &obj, recursion);
if (obj.isInt())
early = obj.getInt();
obj.free();
@@ -238,37 +265,37 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
endOfBlock = gTrue;
black = gFalse;
if (params->isDict()) {
- params->dictLookup("K", &obj);
+ params->dictLookup("K", &obj, recursion);
if (obj.isInt()) {
encoding = obj.getInt();
}
obj.free();
- params->dictLookup("EndOfLine", &obj);
+ params->dictLookup("EndOfLine", &obj, recursion);
if (obj.isBool()) {
endOfLine = obj.getBool();
}
obj.free();
- params->dictLookup("EncodedByteAlign", &obj);
+ params->dictLookup("EncodedByteAlign", &obj, recursion);
if (obj.isBool()) {
byteAlign = obj.getBool();
}
obj.free();
- params->dictLookup("Columns", &obj);
+ params->dictLookup("Columns", &obj, recursion);
if (obj.isInt()) {
columns = obj.getInt();
}
obj.free();
- params->dictLookup("Rows", &obj);
+ params->dictLookup("Rows", &obj, recursion);
if (obj.isInt()) {
rows = obj.getInt();
}
obj.free();
- params->dictLookup("EndOfBlock", &obj);
+ params->dictLookup("EndOfBlock", &obj, recursion);
if (obj.isBool()) {
endOfBlock = obj.getBool();
}
obj.free();
- params->dictLookup("BlackIs1", &obj);
+ params->dictLookup("BlackIs1", &obj, recursion);
if (obj.isBool()) {
black = obj.getBool();
}
@@ -279,7 +306,7 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
} else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
colorXform = -1;
if (params->isDict()) {
- if (params->dictLookup("ColorTransform", &obj)->isInt()) {
+ if (params->dictLookup("ColorTransform", &obj, recursion)->isInt()) {
colorXform = obj.getInt();
}
obj.free();
@@ -291,19 +318,19 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
colors = 1;
bits = 8;
if (params->isDict()) {
- params->dictLookup("Predictor", &obj);
+ params->dictLookup("Predictor", &obj, recursion);
if (obj.isInt())
pred = obj.getInt();
obj.free();
- params->dictLookup("Columns", &obj);
+ params->dictLookup("Columns", &obj, recursion);
if (obj.isInt())
columns = obj.getInt();
obj.free();
- params->dictLookup("Colors", &obj);
+ params->dictLookup("Colors", &obj, recursion);
if (obj.isInt())
colors = obj.getInt();
obj.free();
- params->dictLookup("BitsPerComponent", &obj);
+ params->dictLookup("BitsPerComponent", &obj, recursion);
if (obj.isInt())
bits = obj.getInt();
obj.free();
@@ -311,7 +338,7 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
str = new FlateStream(str, pred, columns, colors, bits);
} else if (!strcmp(name, "JBIG2Decode")) {
if (params->isDict()) {
- params->dictLookup("JBIG2Globals", &globals);
+ params->dictLookup("JBIG2Globals", &globals, recursion);
}
str = new JBIG2Stream(str, &globals);
globals.free();
@@ -726,13 +753,29 @@ GBool StreamPredictor::getNextLine() {
}
//------------------------------------------------------------------------
+// UniqueFileStream
+//------------------------------------------------------------------------
+
+UniqueFileStream::UniqueFileStream(FILE *fA, char *fileNameA, Guint startA, GBool limitedA,
+ Guint lengthA, Object *dictA):
+ FileStream(fA, fileNameA, startA, limitedA, lengthA, dictA) {
+ f = fopen(fileName, "rb");
+}
+
+UniqueFileStream::~UniqueFileStream() {
+ close();
+ fclose(f);
+}
+
+//------------------------------------------------------------------------
// FileStream
//------------------------------------------------------------------------
-FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA,
+FileStream::FileStream(FILE *fA, char *fileNameA, Guint startA, GBool limitedA,
Guint lengthA, Object *dictA):
BaseStream(dictA, lengthA) {
f = fA;
+ fileName = fileNameA;
start = startA;
limited = limitedA;
length = lengthA;
@@ -746,9 +789,13 @@ FileStream::~FileStream() {
close();
}
+BaseStream *FileStream::copy() {
+ return new UniqueFileStream(f, fileName, start, limited, length, &dict);
+}
+
Stream *FileStream::makeSubStream(Guint startA, GBool limitedA,
Guint lengthA, Object *dictA) {
- return new FileStream(f, startA, limitedA, lengthA, dictA);
+ return new FileStream(f, fileName, startA, limitedA, lengthA, dictA);
}
void FileStream::reset() {
@@ -870,6 +917,11 @@ CachedFileStream::~CachedFileStream()
cc->decRefCnt();
}
+BaseStream *CachedFileStream::copy() {
+ cc->incRefCnt();
+ return new CachedFileStream(cc, start, limited, length, &dict);
+}
+
Stream *CachedFileStream::makeSubStream(Guint startA, GBool limitedA,
Guint lengthA, Object *dictA)
{
@@ -965,6 +1017,10 @@ MemStream::~MemStream() {
}
}
+BaseStream *MemStream::copy() {
+ return new MemStream(buf, start, length, &dict);
+}
+
Stream *MemStream::makeSubStream(Guint startA, GBool limited,
Guint lengthA, Object *dictA) {
MemStream *subStr;
@@ -1039,6 +1095,11 @@ EmbedStream::EmbedStream(Stream *strA, Object *dictA,
EmbedStream::~EmbedStream() {
}
+BaseStream *EmbedStream::copy() {
+ error(errInternal, -1, "Called copy() on EmbedStream");
+ return NULL;
+}
+
Stream *EmbedStream::makeSubStream(Guint start, GBool limitedA,
Guint lengthA, Object *dictA) {
error(errInternal, -1, "Called makeSubStream() on EmbedStream");
diff --git a/poppler/Stream.h b/poppler/Stream.h
index 20b5fd6..9dd5459 100644
--- a/poppler/Stream.h
+++ b/poppler/Stream.h
@@ -20,7 +20,7 @@
// Copyright (C) 2009 Stefan Thomas <thomas at eload24.com>
// Copyright (C) 2010 Hib Eris <hib at hiberis.nl>
// Copyright (C) 2011, 2012 William Bader <williambader at hotmail.com>
-// Copyright (C) 2012 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
// Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
//
// To see a description of the changes please see the Changelog file that
@@ -39,6 +39,7 @@
#include <stdio.h>
#include "goo/gtypes.h"
#include "Object.h"
+#include "goo/GooMutex.h"
class BaseStream;
class CachedFile;
@@ -98,8 +99,8 @@ public:
virtual ~Stream();
// Reference counting.
- int incRef() { return ++ref; }
- int decRef() { return --ref; }
+ int incRef();
+ int decRef();
// Get kind of stream.
virtual StreamKind getKind() = 0;
@@ -218,15 +219,18 @@ public:
// Add filters to this stream according to the parameters in <dict>.
// Returns the new stream.
- Stream *addFilters(Object *dict);
+ Stream *addFilters(Object *dict, int recursion = 0);
private:
virtual GBool hasGetChars() { return false; }
virtual int getChars(int nChars, Guchar *buffer);
- Stream *makeFilter(char *name, Stream *str, Object *params);
+ Stream *makeFilter(char *name, Stream *str, Object *params, int recursion = 0);
int ref; // reference count
+#if MULTITHREADED
+ GooMutex mutex;
+#endif
};
@@ -299,6 +303,7 @@ public:
BaseStream(Object *dictA, Guint lengthA);
virtual ~BaseStream();
+ virtual BaseStream *copy() = 0;
virtual Stream *makeSubStream(Guint start, GBool limited,
Guint length, Object *dict) = 0;
virtual void setPos(Guint pos, int dir = 0) = 0;
@@ -316,9 +321,6 @@ public:
protected:
Guint length;
-
-private:
-
Object dict;
};
@@ -439,9 +441,10 @@ private:
class FileStream: public BaseStream {
public:
- FileStream(FILE *fA, Guint startA, GBool limitedA,
+ FileStream(FILE *fA, char *fileName, Guint startA, GBool limitedA,
Guint lengthA, Object *dictA);
virtual ~FileStream();
+ virtual BaseStream *copy();
virtual Stream *makeSubStream(Guint startA, GBool limitedA,
Guint lengthA, Object *dictA);
virtual StreamKind getKind() { return strFile; }
@@ -486,7 +489,10 @@ private:
return n;
}
+protected:
FILE *f;
+ char *fileName;
+private:
Guint start;
GBool limited;
char buf[fileStreamBufSize];
@@ -497,6 +503,14 @@ private:
GBool saved;
};
+class UniqueFileStream: public FileStream {
+public:
+
+ UniqueFileStream(FILE *fA, char *fileNameA, Guint startA, GBool limitedA,
+ Guint lengthA, Object *dictA);
+ virtual ~UniqueFileStream();
+};
+
//------------------------------------------------------------------------
// CachedFileStream
//------------------------------------------------------------------------
@@ -509,6 +523,7 @@ public:
CachedFileStream(CachedFile *ccA, Guint startA, GBool limitedA,
Guint lengthA, Object *dictA);
virtual ~CachedFileStream();
+ virtual BaseStream *copy();
virtual Stream *makeSubStream(Guint startA, GBool limitedA,
Guint lengthA, Object *dictA);
virtual StreamKind getKind() { return strCachedFile; }
@@ -551,6 +566,7 @@ public:
MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA);
virtual ~MemStream();
+ virtual BaseStream *copy();
virtual Stream *makeSubStream(Guint start, GBool limited,
Guint lengthA, Object *dictA);
virtual StreamKind getKind() { return strWeird; }
@@ -599,6 +615,7 @@ public:
EmbedStream(Stream *strA, Object *dictA, GBool limitedA, Guint lengthA);
virtual ~EmbedStream();
+ virtual BaseStream *copy();
virtual Stream *makeSubStream(Guint start, GBool limitedA,
Guint lengthA, Object *dictA);
virtual StreamKind getKind() { return str->getKind(); }
diff --git a/poppler/TextOutputDev.cc b/poppler/TextOutputDev.cc
index b0b53fc..3ff9b70 100644
--- a/poppler/TextOutputDev.cc
+++ b/poppler/TextOutputDev.cc
@@ -33,6 +33,7 @@
// Copyright (C) 2012 Jason Crain <jason at aquaticape.us>
// Copyright (C) 2012 Peter Breitenlohner <peb at mppmu.mpg.de>
// Copyright (C) 2013 José Aliste <jaliste at src.gnome.org>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -4267,7 +4268,7 @@ TextSelectionPainter::TextSelectionPainter(TextPage *page,
state = new GfxState(72 * scale, 72 * scale, &box, rotation, gFalse);
- out->startPage (0, state);
+ out->startPage (0, state, NULL);
out->setDefaultCTM (state->getCTM());
state->setTextMat(1, 0, 0, -1, 0, 0);
@@ -5313,7 +5314,7 @@ TextOutputDev::~TextOutputDev() {
delete actualText;
}
-void TextOutputDev::startPage(int pageNum, GfxState *state) {
+void TextOutputDev::startPage(int pageNum, GfxState *state, XRef *xref) {
text->startPage(state);
}
diff --git a/poppler/TextOutputDev.h b/poppler/TextOutputDev.h
index 100f23e..38be378 100644
--- a/poppler/TextOutputDev.h
+++ b/poppler/TextOutputDev.h
@@ -20,6 +20,7 @@
// Copyright (C) 2008, 2010 Albert Astals Cid <aacid at kde.org>
// Copyright (C) 2010 Brian Ewins <brian.ewins at gmail.com>
// Copyright (C) 2012 Jason Crain <jason at aquaticape.us>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -718,7 +719,7 @@ public:
//----- initialization and control
// Start a page.
- virtual void startPage(int pageNum, GfxState *state);
+ virtual void startPage(int pageNum, GfxState *state, XRef *xref);
// End a page.
virtual void endPage();
diff --git a/poppler/XRef.cc b/poppler/XRef.cc
index 81e939a..0ff17f0 100644
--- a/poppler/XRef.cc
+++ b/poppler/XRef.cc
@@ -20,7 +20,7 @@
// Copyright (C) 2007 Carlos Garcia Campos <carlosgc at gnome.org>
// Copyright (C) 2009, 2010 Ilya Gorenbein <igorenbein at finjan.com>
// Copyright (C) 2010 Hib Eris <hib at hiberis.nl>
-// Copyright (C) 2012 Thomas Freitag <Thomas.Freitag at kabelmail.de>
+// Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag at kabelmail.de>
// Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
//
// To see a description of the changes please see the Changelog file that
@@ -65,6 +65,14 @@
#define permHighResPrint (1<<11) // bit 12
#define defPermFlags 0xfffc
+#if MULTITHREADED
+# define lockXRef gLockMutex(&mutex)
+# define unlockXRef gUnlockMutex(&mutex)
+#else
+# define lockXRef
+# define unlockXRef
+#endif
+
//------------------------------------------------------------------------
// ObjectStream
//------------------------------------------------------------------------
@@ -74,7 +82,7 @@ public:
// Create an object stream, using object number <objStrNum>,
// generation 0.
- ObjectStream(XRef *xref, int objStrNumA);
+ ObjectStream(XRef *xref, int objStrNumA, int recursion = 0);
GBool isOk() { return ok; }
@@ -127,7 +135,7 @@ class ObjectStreamItem : public PopplerCacheItem
ObjectStream *objStream;
};
-ObjectStream::ObjectStream(XRef *xref, int objStrNumA) {
+ObjectStream::ObjectStream(XRef *xref, int objStrNumA, int recursion) {
Stream *str;
Parser *parser;
int *offsets;
@@ -140,11 +148,11 @@ ObjectStream::ObjectStream(XRef *xref, int objStrNumA) {
objNums = NULL;
ok = gFalse;
- if (!xref->fetch(objStrNum, 0, &objStr)->isStream()) {
+ if (!xref->fetch(objStrNum, 0, &objStr, recursion)->isStream()) {
goto err1;
}
- if (!objStr.streamGetDict()->lookup("N", &obj1)->isInt()) {
+ if (!objStr.streamGetDict()->lookup("N", &obj1, recursion)->isInt()) {
obj1.free();
goto err1;
}
@@ -154,7 +162,7 @@ ObjectStream::ObjectStream(XRef *xref, int objStrNumA) {
goto err1;
}
- if (!objStr.streamGetDict()->lookup("First", &obj1)->isInt()) {
+ if (!objStr.streamGetDict()->lookup("First", &obj1, recursion)->isInt()) {
obj1.free();
goto err1;
}
@@ -257,6 +265,9 @@ Object *ObjectStream::getObject(int objIdx, int objNum, Object *obj) {
//------------------------------------------------------------------------
void XRef::init() {
+#if MULTITHREADED
+ gInitMutex(&mutex);
+#endif
ok = gTrue;
errCode = errNone;
entries = NULL;
@@ -272,6 +283,7 @@ void XRef::init() {
permFlags = defPermFlags;
ownerPasswordOk = gFalse;
rootNum = -1;
+ strOwner = gFalse;
}
XRef::XRef() {
@@ -375,6 +387,59 @@ XRef::~XRef() {
if (objStrs) {
delete objStrs;
}
+ if (strOwner) {
+ delete str;
+ }
+#if MULTITHREADED
+ gDestroyMutex(&mutex);
+#endif
+}
+
+XRef *XRef::copy() {
+ XRef *xref = new XRef();
+ xref->str = str->copy();
+ xref->strOwner = gTrue;
+ xref->encrypted = encrypted;
+ xref->permFlags = permFlags;
+ xref->ownerPasswordOk = ownerPasswordOk;
+ xref->rootGen = rootGen;
+ xref->rootNum = rootNum;
+
+ xref->start = start;
+ xref->prevXRefOffset = prevXRefOffset;
+ xref->mainXRefEntriesOffset = mainXRefEntriesOffset;
+ xref->xRefStream = xRefStream;
+ trailerDict.copy(&xref->trailerDict);
+ xref->encAlgorithm = encAlgorithm;
+ xref->encRevision = encRevision;
+ xref->encVersion = encVersion;
+ xref->permFlags = permFlags;
+ xref->keyLength = keyLength;
+ xref->permFlags = permFlags;
+ for (int i = 0; i < 32; i++) {
+ xref->fileKey[i] = fileKey[i];
+ }
+
+ if (xref->reserve(size) == 0) {
+ error(errSyntaxError, -1, "unable to allocate {0:d} entries", size);
+ return NULL;
+ }
+ xref->size = size;
+ for (int i = 0; i < size; ++i) {
+ xref->entries[i].offset = entries[i].offset;
+ xref->entries[i].type = entries[i].type;
+ xref->entries[i].obj.initNull ();
+ xref->entries[i].flags = entries[i].flags;
+ xref->entries[i].gen = entries[i].gen;
+ }
+ xref->streamEndsLen = streamEndsLen;
+ if (streamEndsLen != 0) {
+ xref->streamEnds = (Guint *)gmalloc(streamEndsLen * sizeof(Guint));
+ for (int i = 0; i < streamEndsLen; i++) {
+ xref->streamEnds[i] = streamEnds[i];
+ }
+ }
+ return xref;
}
int XRef::reserve(int newSize)
@@ -1036,6 +1101,7 @@ Object *XRef::fetch(int num, int gen, Object *obj, int recursion) {
Parser *parser;
Object obj1, obj2, obj3;
+ if (recursion == 0) lockXRef;
// check for bogus ref - this can happen in corrupted PDF files
if (num < 0 || num >= size) {
goto err;
@@ -1044,6 +1110,7 @@ Object *XRef::fetch(int num, int gen, Object *obj, int recursion) {
e = getEntry(num);
if(!e->obj.isNull ()) { //check for updated object
obj = e->obj.copy(obj);
+ if (recursion == 0) unlockXRef;
return obj;
}
@@ -1124,7 +1191,7 @@ Object *XRef::fetch(int num, int gen, Object *obj, int recursion) {
}
if (!objStr) {
- objStr = new ObjectStream(this, e->offset);
+ objStr = new ObjectStream(this, e->offset, recursion + 1);
if (!objStr->isOk()) {
delete objStr;
objStr = NULL;
@@ -1145,12 +1212,22 @@ Object *XRef::fetch(int num, int gen, Object *obj, int recursion) {
goto err;
}
+ if (recursion == 0) unlockXRef;
return obj;
err:
+ if (recursion == 0) unlockXRef;
return obj->initNull();
}
+void XRef::lock() {
+ lockXRef;
+}
+
+void XRef::unlock() {
+ unlockXRef;
+}
+
Object *XRef::getDocInfo(Object *obj) {
return trailerDict.dictLookup("Info", obj);
}
@@ -1205,6 +1282,7 @@ int XRef::getNumEntry(Guint offset)
}
void XRef::add(int num, int gen, Guint offs, GBool used) {
+ lockXRef;
if (num >= size) {
if (num >= capacity) {
entries = (XRefEntry *)greallocn(entries, num + 1, sizeof(XRefEntry));
@@ -1230,17 +1308,21 @@ void XRef::add(int num, int gen, Guint offs, GBool used) {
e->type = xrefEntryFree;
e->offset = 0;
}
+ unlockXRef;
}
void XRef::setModifiedObject (Object* o, Ref r) {
+ lockXRef;
if (r.num < 0 || r.num >= size) {
error(errInternal, -1,"XRef::setModifiedObject on unknown ref: {0:d}, {1:d}\n", r.num, r.gen);
+ unlockXRef;
return;
}
XRefEntry *e = getEntry(r.num);
e->obj.free();
o->copy(&(e->obj));
e->setFlag(XRefEntry::Updated, gTrue);
+ unlockXRef;
}
Ref XRef::addIndirectObject (Object* o) {
@@ -1274,8 +1356,10 @@ Ref XRef::addIndirectObject (Object* o) {
}
void XRef::removeIndirectObject(Ref r) {
+ lockXRef;
if (r.num < 0 || r.num >= size) {
error(errInternal, -1,"XRef::removeIndirectObject on unknown ref: {0:d}, {1:d}\n", r.num, r.gen);
+ unlockXRef;
return;
}
XRefEntry *e = getEntry(r.num);
@@ -1285,6 +1369,7 @@ void XRef::removeIndirectObject(Ref r) {
e->type = xrefEntryFree;
e->gen++;
e->setFlag(XRefEntry::Updated, gTrue);
+ unlockXRef;
}
void XRef::writeXRef(XRef::XRefWriter *writer, GBool writeAllEntries) {
diff --git a/poppler/XRef.h b/poppler/XRef.h
index 9af4a13..cbef85b 100644
--- a/poppler/XRef.h
+++ b/poppler/XRef.h
@@ -19,7 +19,7 @@
// Copyright (C) 2007 Carlos Garcia Campos <carlosgc at gnome.org>
// Copyright (C) 2010 Ilya Gorenbein <igorenbein at finjan.com>
// Copyright (C) 2010 Hib Eris <hib at hiberis.nl>
-// Copyright (C) 2012 Thomas Freitag <Thomas.Freitag at kabelmail.de>
+// Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag at kabelmail.de>
// Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
//
// To see a description of the changes please see the Changelog file that
@@ -34,7 +34,10 @@
#pragma interface
#endif
+#include <config.h>
+#include "poppler-config.h"
#include "goo/gtypes.h"
+#include "goo/GooMutex.h"
#include "Object.h"
#include "Stream.h"
@@ -100,6 +103,9 @@ public:
// Destructor.
~XRef();
+ // Copy xref but with new base stream!
+ XRef *copy();
+
// Is xref table valid?
GBool isOk() { return ok; }
@@ -180,6 +186,10 @@ public:
// Output XRef stream contents to GooString and fill trailerDict fields accordingly
void writeStreamToBuffer(GooString *stmBuf, Dict *xrefDict, XRef *xref);
+ // to be thread safe during write where changes are not allowed
+ void lock();
+ void unlock();
+
private:
BaseStream *str; // input stream
@@ -209,6 +219,10 @@ private:
GBool xRefStream; // true if last XRef section is a stream
Guint mainXRefOffset; // position of the main XRef table/stream
GBool scannedSpecialFlags; // true if scanSpecialFlags has been called
+ GBool strOwner; // true if str is owned by the instance
+#if MULTITHREADED
+ GooMutex mutex;
+#endif
void init();
int reserve(int newSize);
diff --git a/qt4/src/poppler-document.cc b/qt4/src/poppler-document.cc
index ee56ed6..7d13656 100644
--- a/qt4/src/poppler-document.cc
+++ b/qt4/src/poppler-document.cc
@@ -5,7 +5,7 @@
* Copyright (C) 2006-2010, Pino Toscano <pino at kde.org>
* Copyright (C) 2010, 2011 Hib Eris <hib at hiberis.nl>
* Copyright (C) 2012 Koji Otani <sho at bbr.jp>
- * Copyright (C) 2012 Thomas Freitag <Thomas.Freitag at alfa.de>
+ * Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
* Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
*
* This program is free software; you can redistribute it and/or modify
@@ -239,8 +239,10 @@ namespace Poppler {
if (fi.isEmbedded())
{
Object refObj, strObj;
+ XRef *xref = m_doc->doc->getXRef()->copy();
+
refObj.initRef(fi.m_data->embRef.num, fi.m_data->embRef.gen);
- refObj.fetch(m_doc->doc->getXRef(), &strObj);
+ refObj.fetch(xref, &strObj);
refObj.free();
if (strObj.isStream())
{
@@ -253,6 +255,7 @@ namespace Poppler {
strObj.streamClose();
}
strObj.free();
+ delete xref;
}
return result;
}
@@ -265,7 +268,8 @@ namespace Poppler {
if ( m_doc->locked )
return QString();
- m_doc->doc->getDocInfo( &info );
+ QScopedPointer<XRef> xref(m_doc->doc->getXRef()->copy());
+ xref->getDocInfo(&info);
if ( !info.isDict() )
return QString();
@@ -295,7 +299,8 @@ namespace Poppler {
if ( m_doc->locked )
return QStringList();
- m_doc->doc->getDocInfo( &info );
+ QScopedPointer<XRef> xref(m_doc->doc->getXRef()->copy());
+ xref->getDocInfo(&info);
if ( !info.isDict() )
return QStringList();
@@ -317,7 +322,8 @@ namespace Poppler {
return QDateTime();
Object info;
- m_doc->doc->getDocInfo( &info );
+ QScopedPointer<XRef> xref(m_doc->doc->getXRef()->copy());
+ xref->getDocInfo(&info);
if ( !info.isDict() ) {
info.free();
return QDateTime();
@@ -521,7 +527,6 @@ namespace Poppler {
void Document::setRenderHint( Document::RenderHint hint, bool on )
{
- const bool touchesAntialias = hint & ( Document::Antialiasing | Document::TextAntialiasing | Document::TextHinting );
const bool touchesOverprinting = hint & Document::OverprintPreview;
int hintForOperation = hint;
@@ -533,12 +538,6 @@ namespace Poppler {
else
m_doc->m_hints &= ~hintForOperation;
- // the only way to set antialiasing for Splash is on creation
- if ( m_doc->m_backend == Document::SplashBackend && (touchesAntialias || touchesOverprinting) )
- {
- delete m_doc->m_outputDev;
- m_doc->m_outputDev = NULL;
- }
}
Document::RenderHints Document::renderHints() const
diff --git a/qt4/src/poppler-page.cc b/qt4/src/poppler-page.cc
index 5475614..f9ac443 100644
--- a/qt4/src/poppler-page.cc
+++ b/qt4/src/poppler-page.cc
@@ -13,7 +13,7 @@
* Copyright (C) 2012 Tobias Koenig <tokoe at kdab.com>
* Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
* Copyright (C) 2012 Adam Reichold <adamreichold at myopera.com>
- * Copyright (C) 2012 Thomas Freitag <Thomas.Freitag at alfa.de>
+ * Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -258,10 +258,59 @@ QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h,
case Poppler::Document::SplashBackend:
{
#if defined(HAVE_SPLASH)
- SplashOutputDev *splash_output = static_cast<SplashOutputDev *>(m_page->parentDoc->getOutputDev());
+ SplashColor bgColor;
+#if defined(SPLASH_CMYK)
+ GBool overprint = m_page->parentDoc->m_hints & Document::OverprintPreview ? gTrue : gFalse;
+ globalParams->setOverprintPreview(overprint);
+ if (overprint)
+ {
+ Guchar c, m, y, k;
+
+ c = 255 - m_page->parentDoc->paperColor.blue();
+ m = 255 - m_page->parentDoc->paperColor.red();
+ y = 255 - m_page->parentDoc->paperColor.green();
+ k = c;
+ if (m < k) {
+ k = m;
+ }
+ if (y < k) {
+ k = y;
+ }
+ bgColor[0] = c - k;
+ bgColor[1] = m - k;
+ bgColor[2] = y - k;
+ bgColor[3] = k;
+ for (int i = 4; i < SPOT_NCOMPS + 4; i++) {
+ bgColor[i] = 0;
+ }
+ }
+ else
+#endif
+ {
+ bgColor[0] = m_page->parentDoc->paperColor.blue();
+ bgColor[1] = m_page->parentDoc->paperColor.green();
+ bgColor[2] = m_page->parentDoc->paperColor.red();
+ }
+
+ GBool AA = m_page->parentDoc->m_hints & Document::TextAntialiasing ? gTrue : gFalse;
+
+ SplashOutputDev * splash_output = new SplashOutputDev(
+#if defined(SPLASH_CMYK)
+ (overprint) ? splashModeDeviceN8 : splashModeXBGR8,
+#else
+ splashModeXBGR8,
+#endif
+ 4, gFalse, bgColor, gTrue, AA);
+
+ splash_output->setVectorAntialias(m_page->parentDoc->m_hints & Document::Antialiasing ? gTrue : gFalse);
+ splash_output->setFreeTypeHinting(m_page->parentDoc->m_hints & Document::TextHinting ? gTrue : gFalse,
+ m_page->parentDoc->m_hints & Document::TextSlightHinting ? gTrue : gFalse);
+
+ splash_output->startDoc(m_page->parentDoc->doc);
m_page->parentDoc->doc->displayPageSlice(splash_output, m_page->index + 1, xres, yres,
- rotation, false, true, false, x, y, w, h);
+ rotation, false, true, false, x, y, w, h,
+ NULL, NULL, NULL, NULL, gTrue);
SplashBitmap *bitmap = splash_output->getBitmap();
int bw = bitmap->getWidth();
@@ -291,8 +340,7 @@ QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h,
QImage tmpimg( dataPtr, bw, bh, QImage::Format_ARGB32 );
img = tmpimg.copy();
}
- // unload underlying xpdf bitmap
- splash_output->startPage( 0, NULL );
+ delete splash_output;
#endif
break;
}
@@ -381,7 +429,8 @@ QString Page::text(const QRectF &r, TextLayout textLayout) const
const GBool rawOrder = textLayout == RawOrderLayout;
output_dev = new TextOutputDev(0, gFalse, 0, rawOrder, gFalse);
m_page->parentDoc->doc->displayPageSlice(output_dev, m_page->index + 1, 72, 72,
- 0, false, true, false, -1, -1, -1, -1);
+ 0, false, true, false, -1, -1, -1, -1,
+ NULL, NULL, NULL, NULL, gTrue);
if (r.isNull())
{
rect = m_page->page->getCropBox();
@@ -482,7 +531,8 @@ QList<TextBox*> Page::textList(Rotation rotate) const
int rotation = (int)rotate * 90;
m_page->parentDoc->doc->displayPageSlice(output_dev, m_page->index + 1, 72, 72,
- rotation, false, false, false, -1, -1, -1, -1);
+ rotation, false, false, false, -1, -1, -1, -1,
+ NULL, NULL, NULL, NULL, gTrue);
TextWordList *word_list = output_dev->makeWordList();
diff --git a/qt4/src/poppler-private.cc b/qt4/src/poppler-private.cc
index ffb5b92..7022147 100644
--- a/qt4/src/poppler-private.cc
+++ b/qt4/src/poppler-private.cc
@@ -2,6 +2,7 @@
* Copyright (C) 2005, Net Integration Technologies, Inc.
* Copyright (C) 2006, 2011 by Albert Astals Cid <aacid at kde.org>
* Copyright (C) 2008, 2010, 2011 by Pino Toscano <pino at kde.org>
+ * Copyright (C) 2013 by Thomas Freitag <Thomas.Freitag at alfa.de>
* Inspired on code by
* Copyright (C) 2004 by Albert Astals Cid <tsdgeos at terra.es>
* Copyright (C) 2004 by Enrico Ros <eros.kde at email.it>
@@ -226,7 +227,6 @@ namespace Debug {
qDeleteAll(m_embeddedFiles);
delete (OptContentModel *)m_optContentModel;
delete doc;
- delete m_outputDev;
delete m_fontInfoIterator;
count --;
@@ -241,7 +241,6 @@ namespace Debug {
{
m_fontInfoIterator = 0;
m_backend = Document::SplashBackend;
- m_outputDev = 0;
paperColor = Qt::white;
m_hints = 0;
m_optContentModel = 0;
diff --git a/qt4/src/poppler-private.h b/qt4/src/poppler-private.h
index 5a9e1b8..5759a4e 100644
--- a/qt4/src/poppler-private.h
+++ b/qt4/src/poppler-private.h
@@ -5,7 +5,7 @@
* Copyright (C) 2007-2009, 2011 by Pino Toscano <pino at kde.org>
* Copyright (C) 2011 Andreas Hartmetz <ahartmetz at gmail.com>
* Copyright (C) 2011 Hib Eris <hib at hiberis.nl>
- * Copyright (C) 2012 Thomas Freitag <Thomas.Freitag at alfa.de>
+ * Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
* Inspired on code by
* Copyright (C) 2004 by Albert Astals Cid <tsdgeos at terra.es>
* Copyright (C) 2004 by Enrico Ros <eros.kde at email.it>
@@ -113,82 +113,11 @@ namespace Poppler {
~DocumentData();
- OutputDev *getOutputDev()
- {
- if (!m_outputDev)
- {
- switch (m_backend)
- {
- case Document::ArthurBackend:
- // create a splash backend even in case of the Arthur Backend
- case Document::SplashBackend:
- {
-#if defined(HAVE_SPLASH)
- SplashColor bgColor;
- GBool overprint = m_hints & Document::OverprintPreview ? gTrue : gFalse;
- globalParams->setOverprintPreview(overprint);
-#if defined(SPLASH_CMYK)
- if (overprint)
- {
- Guchar c, m, y, k;
-
- c = 255 - paperColor.blue();
- m = 255 - paperColor.red();
- y = 255 - paperColor.green();
- k = c;
- if (m < k) {
- k = m;
- }
- if (y < k) {
- k = y;
- }
- bgColor[0] = c - k;
- bgColor[1] = m - k;
- bgColor[2] = y - k;
- bgColor[3] = k;
- for (int i = 4; i < SPOT_NCOMPS + 4; i++) {
- bgColor[i] = 0;
- }
- }
- else
-#endif
- {
- bgColor[0] = paperColor.blue();
- bgColor[1] = paperColor.green();
- bgColor[2] = paperColor.red();
- }
- GBool AA = m_hints & Document::TextAntialiasing ? gTrue : gFalse;
- SplashOutputDev * splashOutputDev = new SplashOutputDev(
-#if defined(SPLASH_CMYK)
- (overprint) ? splashModeDeviceN8 : splashModeXBGR8,
-#else
- splashModeXBGR8,
-#endif
- 4, gFalse, bgColor, gTrue, AA);
- splashOutputDev->setVectorAntialias(m_hints & Document::Antialiasing ? gTrue : gFalse);
- splashOutputDev->setFreeTypeHinting(m_hints & Document::TextHinting ? gTrue : gFalse, m_hints & Document::TextSlightHinting ? gTrue : gFalse);
- splashOutputDev->startDoc(doc);
- m_outputDev = splashOutputDev;
-#endif
- break;
- }
- }
- }
- return m_outputDev;
- }
-
void addTocChildren( QDomDocument * docSyn, QDomNode * parent, GooList * items );
void setPaperColor(const QColor &color)
{
- if (color == paperColor)
- return;
-
paperColor = color;
-
- // Make sure the new paper color will be picked up for the next rendering
- delete m_outputDev;
- m_outputDev = NULL;
}
void fillMembers()
@@ -212,7 +141,6 @@ namespace Poppler {
bool locked;
FontIterator *m_fontInfoIterator;
Document::RenderBackend m_backend;
- OutputDev *m_outputDev;
QList<EmbeddedFile*> m_embeddedFiles;
QPointer<OptContentModel> m_optContentModel;
QColor paperColor;
diff --git a/test/gtk-test.cc b/test/gtk-test.cc
index a5759d7..6deb401 100644
--- a/test/gtk-test.cc
+++ b/test/gtk-test.cc
@@ -116,7 +116,7 @@ GDKSplashOutputDev::~GDKSplashOutputDev() {
void GDKSplashOutputDev::clear() {
startDoc(NULL);
- startPage(0, NULL);
+ startPage(0, NULL, NULL);
}
void GDKSplashOutputDev::endPage() {
diff --git a/utils/HtmlOutputDev.cc b/utils/HtmlOutputDev.cc
index a718380..8d0ffea 100644
--- a/utils/HtmlOutputDev.cc
+++ b/utils/HtmlOutputDev.cc
@@ -34,6 +34,7 @@
// Copyright (C) 2012 Ihar Filipau <thephilips at gmail.com>
// Copyright (C) 2012 Gerald Schmidt <solahcin at gmail.com>
// Copyright (C) 2012 Pino Toscano <pino at kde.org>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -1229,7 +1230,7 @@ HtmlOutputDev::~HtmlOutputDev() {
delete pages;
}
-void HtmlOutputDev::startPage(int pageNum, GfxState *state) {
+void HtmlOutputDev::startPage(int pageNum, GfxState *state, XRef *xref) {
#if 0
if (mode&&!xml){
if (write){
diff --git a/utils/HtmlOutputDev.h b/utils/HtmlOutputDev.h
index 12b16bf..c9fd28c 100644
--- a/utils/HtmlOutputDev.h
+++ b/utils/HtmlOutputDev.h
@@ -23,6 +23,7 @@
// Copyright (C) 2011 Stephen Reichling <sreichling at chegg.com>
// Copyright (C) 2012 Igor Slepchin <igor.redhat at gmail.com>
// Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -279,7 +280,7 @@ public:
// Start a page.
- virtual void startPage(int pageNum, GfxState *state);
+ virtual void startPage(int pageNum, GfxState *state, XRef *xref);
// End a page.
virtual void endPage();
diff --git a/utils/ImageOutputDev.h b/utils/ImageOutputDev.h
index 6201a24..13911ed 100644
--- a/utils/ImageOutputDev.h
+++ b/utils/ImageOutputDev.h
@@ -18,6 +18,7 @@
// Copyright (C) 2009 Carlos Garcia Campos <carlosgc at gnome.org>
// Copyright (C) 2010 Jakob Voss <jakob.voss at gbv.de>
// Copyright (C) 2012 Adrian Johnson <ajohnson at redneon.com>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -78,7 +79,7 @@ public:
virtual GBool needNonText() { return gTrue; }
// Start a page
- virtual void startPage(int pageNumA, GfxState *state)
+ virtual void startPage(int pageNumA, GfxState *state, XRef *xref)
{ pageNum = pageNumA; }
//---- get info about output device
More information about the poppler
mailing list