Merge remote-tracking branch 'origin/poppler-0.22'
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2c5715e..9d3f7ac 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -398,6 +398,9 @@
 endif(MSVC)
 set_target_properties(poppler PROPERTIES VERSION 37.0.0 SOVERSION 37)
 target_link_libraries(poppler ${poppler_LIBS})
+if(HAVE_PTHREAD)
+  target_link_libraries(poppler -lpthread)
+endif()
 target_link_libraries(poppler LINK_INTERFACE_LIBRARIES "")
 install(TARGETS poppler RUNTIME DESTINATION bin LIBRARY DESTINATION lib${LIB_SUFFIX} ARCHIVE DESTINATION lib${LIB_SUFFIX})
 
diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake
index 5b12ac4..d3f5732 100644
--- a/ConfigureChecks.cmake
+++ b/ConfigureChecks.cmake
@@ -27,6 +27,8 @@
 check_function_exists(fseek64 HAVE_FSEEK64)
 check_function_exists(fseeko HAVE_FSEEKO)
 check_function_exists(ftell64 HAVE_FTELL64)
+check_function_exists(pread64 HAVE_PREAD64)
+check_function_exists(lseek64 HAVE_LSEEK64)
 check_function_exists(gmtime_r HAVE_GMTIME_R)
 check_function_exists(gettimeofday HAVE_GETTIMEOFDAY)
 check_function_exists(localtime_r HAVE_LOCALTIME_R)
diff --git a/config.h.cmake b/config.h.cmake
index cde219f..c3b30db 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -46,6 +46,12 @@
 /* Define to 1 if you have the `ftell64' function. */
 #cmakedefine HAVE_FTELL64 1
 
+/* Define to 1 if you have the `pread64' function. */
+#cmakedefine HAVE_PREAD64 1
+
+/* Define to 1 if you have the `lseek64' function. */
+#cmakedefine HAVE_LSEEK64 1
+
 /* Defines if gettimeofday is available on your system */
 #cmakedefine HAVE_GETTIMEOFDAY 1
 
diff --git a/configure.ac b/configure.ac
index 86aa19c..460142b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -265,6 +265,7 @@
 if test "$xpdf_cv_func_fseek64" = yes -a "$xpdf_cv_func_ftell64" = yes; then
   AC_DEFINE(HAVE_FSEEK64)
 fi
+AC_CHECK_FUNCS(pread64 lseek64)
 
 dnl Test for zlib
 AC_ARG_ENABLE([zlib],
diff --git a/cpp/poppler-private.cpp b/cpp/poppler-private.cpp
index 2783bed..3bee619 100644
--- a/cpp/poppler-private.cpp
+++ b/cpp/poppler-private.cpp
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2009-2010, Pino Toscano <pino@kde.org>
+ * Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
  *
  * 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
@@ -28,7 +29,7 @@
 
 using namespace poppler;
 
-void detail::error_function(void * /*data*/, ErrorCategory /*category*/, int pos, char *msg)
+void detail::error_function(void * /*data*/, ErrorCategory /*category*/, Goffset pos, char *msg)
 {
     std::ostringstream oss;
     if (pos >= 0) {
diff --git a/cpp/poppler-private.h b/cpp/poppler-private.h
index a4b455c..3e8873f 100644
--- a/cpp/poppler-private.h
+++ b/cpp/poppler-private.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2009, Pino Toscano <pino@kde.org>
+ * Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
  *
  * 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
@@ -38,7 +39,7 @@
 namespace detail
 {
 
-void error_function(void *data, ErrorCategory category, int pos, char *msg);
+void error_function(void *data, ErrorCategory category, Goffset pos, char *msg);
 
 rectf pdfrectangle_to_rectf(const PDFRectangle &pdfrect);
 
diff --git a/glib/CMakeLists.txt b/glib/CMakeLists.txt
index bab5838..a3a9d4c 100644
--- a/glib/CMakeLists.txt
+++ b/glib/CMakeLists.txt
@@ -81,6 +81,9 @@
 add_library(poppler-glib SHARED ${poppler_glib_SRCS} ${poppler_glib_generated_SRCS})
 set_target_properties(poppler-glib PROPERTIES VERSION 8.6.0 SOVERSION 8)
 target_link_libraries(poppler-glib poppler ${GLIB2_LIBRARIES} ${CAIRO_LIBRARIES} ${FREETYPE_LIBRARIES})
+if(HAVE_PTHREAD)
+   target_link_libraries(poppler-glib -lpthread)
+endif()
 install(TARGETS poppler-glib RUNTIME DESTINATION bin LIBRARY DESTINATION lib${LIB_SUFFIX} ARCHIVE DESTINATION lib${LIB_SUFFIX})
 
 install(FILES
diff --git a/glib/poppler-input-stream.cc b/glib/poppler-input-stream.cc
index 99fcb6f..041cc2e 100644
--- a/glib/poppler-input-stream.cc
+++ b/glib/poppler-input-stream.cc
@@ -21,7 +21,7 @@
 #include "poppler-input-stream.h"
 
 PopplerInputStream::PopplerInputStream(GInputStream *inputStreamA, GCancellable *cancellableA,
-                                       Guint startA, GBool limitedA, Guint lengthA, Object *dictA)
+                                       Goffset startA, GBool limitedA, Goffset lengthA, Object *dictA)
   : BaseStream(dictA, lengthA)
 {
   inputStream = (GInputStream *)g_object_ref(inputStreamA);
@@ -41,8 +41,12 @@
     g_object_unref(cancellable);
 }
 
-Stream *PopplerInputStream::makeSubStream(Guint startA, GBool limitedA,
-                                          Guint lengthA, Object *dictA)
+BaseStream *PopplerInputStream::copy() {
+  return new PopplerInputStream(inputStream, cancellable, start, limited, length, &dict);
+}
+
+Stream *PopplerInputStream::makeSubStream(Goffset startA, GBool limitedA,
+                                          Goffset lengthA, Object *dictA)
 {
   return new PopplerInputStream(inputStream, cancellable, startA, limitedA, lengthA, dictA);
 }
@@ -66,7 +70,7 @@
   saved = gFalse;
 }
 
-void PopplerInputStream::setPos(Guint pos, int dir)
+void PopplerInputStream::setPos(Goffset pos, int dir)
 {
   Guint size;
   GSeekable *seekable = G_SEEKABLE(inputStream);
@@ -86,7 +90,7 @@
   bufPtr = bufEnd = buf;
 }
 
-void PopplerInputStream::moveStart(int delta)
+void PopplerInputStream::moveStart(Goffset delta)
 {
   start += delta;
   bufPtr = bufEnd = buf;
diff --git a/glib/poppler-input-stream.h b/glib/poppler-input-stream.h
index 0d795f4..74c198f 100644
--- a/glib/poppler-input-stream.h
+++ b/glib/poppler-input-stream.h
@@ -31,10 +31,11 @@
 public:
 
   PopplerInputStream(GInputStream *inputStream, GCancellable *cancellableA,
-                     Guint startA, GBool limitedA, Guint lengthA, Object *dictA);
+                     Goffset startA, GBool limitedA, Goffset lengthA, Object *dictA);
   virtual ~PopplerInputStream();
-  virtual Stream *makeSubStream(Guint start, GBool limited,
-                                Guint lengthA, Object *dictA);
+  virtual BaseStream *copy();
+  virtual Stream *makeSubStream(Goffset start, GBool limited,
+                                Goffset lengthA, Object *dictA);
   virtual StreamKind getKind() { return strWeird; }
   virtual void reset();
   virtual void close();
@@ -42,10 +43,10 @@
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
   virtual int lookChar()
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
-  virtual int getPos() { return bufPos + (bufPtr - buf); }
-  virtual void setPos(Guint pos, int dir = 0);
-  virtual Guint getStart() { return start; }
-  virtual void moveStart(int delta);
+  virtual Goffset getPos() { return bufPos + (bufPtr - buf); }
+  virtual void setPos(Goffset pos, int dir = 0);
+  virtual Goffset getStart() { return start; }
+  virtual void moveStart(Goffset delta);
 
   virtual int getUnfilteredChar() { return getChar(); }
   virtual void unfilteredReset() { reset(); }
@@ -59,12 +60,12 @@
 
   GInputStream *inputStream;
   GCancellable *cancellable;
-  Guint start;
+  Goffset start;
   GBool limited;
   char buf[inputStreamBufSize];
   char *bufPtr;
   char *bufEnd;
-  Guint bufPos;
+  Goffset bufPos;
   int savePos;
   GBool saved;
 };
diff --git a/goo/GooMutex.h b/goo/GooMutex.h
index 3f53a62..e9d5a54 100644
--- a/goo/GooMutex.h
+++ b/goo/GooMutex.h
@@ -16,6 +16,9 @@
 // under GPL version 2 or later
 //
 // Copyright (C) 2009 Kovid Goyal <kovid@kovidgoyal.net>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
+// Copyright (C) 2013 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2013 Adam Reichold <adamreichold@myopera.com>
 //
 // 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
@@ -53,11 +56,26 @@
 
 typedef pthread_mutex_t GooMutex;
 
-#define gInitMutex(m) pthread_mutex_init(m, NULL)
+inline void gInitMutex(GooMutex *m) {
+  pthread_mutexattr_t mutexattr;
+  pthread_mutexattr_init(&mutexattr);
+  pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
+  pthread_mutex_init(m, &mutexattr);
+  pthread_mutexattr_destroy(&mutexattr);
+}
 #define gDestroyMutex(m) pthread_mutex_destroy(m)
 #define gLockMutex(m) pthread_mutex_lock(m)
 #define gUnlockMutex(m) pthread_mutex_unlock(m)
 
 #endif
 
+class MutexLocker {
+public:
+  MutexLocker(GooMutex *mutexA) : mutex(mutexA) { gLockMutex(mutex); }
+  ~MutexLocker() { gUnlockMutex(mutex); }
+
+private:
+  GooMutex *mutex;
+};
+
 #endif
diff --git a/goo/gfile.cc b/goo/gfile.cc
index b075b2b..c46fd86 100644
--- a/goo/gfile.cc
+++ b/goo/gfile.cc
@@ -21,6 +21,7 @@
 // Copyright (C) 2008, 2010, 2012 Hib Eris <hib@hiberis.nl>
 // Copyright (C) 2009, 2012 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2009 Kovid Goyal <kovid@kovidgoyal.net>
+// Copyright (C) 2013 Adam Reichold <adamreichold@myopera.com>
 //
 // 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
@@ -49,6 +50,8 @@
 #    include <unixlib.h>
 #  endif
 #endif // _WIN32
+#include <stdio.h>
+#include <limits>
 #include "GooString.h"
 #include "gfile.h"
 
@@ -546,6 +549,121 @@
   return buf;
 }
 
+int Gfseek(FILE *f, Goffset offset, int whence) {
+#if HAVE_FSEEKO
+  return fseeko(f, offset, whence);
+#elif HAVE_FSEEK64
+  return fseek64(f, offset, whence);
+#elif _WIN32
+  return _fseeki64(f, offset, whence);
+#else
+  return fseek(f, offset, whence);
+#endif
+}
+
+Goffset Gftell(FILE *f) {
+#if HAVE_FSEEKO
+  return ftello(f);
+#elif HAVE_FSEEK64
+  return ftell64(f);
+#elif _WIN32
+  return _ftelli64(f);
+#else
+  return ftell(f);
+#endif
+}
+
+Goffset GoffsetMax() {
+#if HAVE_FSEEKO
+  return (std::numeric_limits<off_t>::max)();
+#elif HAVE_FSEEK64
+  return (std::numeric_limits<off64_t>::max)();
+#elif _WIN32
+  return (std::numeric_limits<__int64>::max)();
+#else
+  return (std::numeric_limits<long>::max)();
+#endif
+}
+
+//------------------------------------------------------------------------
+// GooFile
+//------------------------------------------------------------------------
+
+#ifdef _WIN32
+
+int GooFile::read(char *buf, int n, Goffset offset) const {
+  DWORD m;
+  
+  LARGE_INTEGER largeInteger = {0};
+  largeInteger.QuadPart = offset;
+  
+  OVERLAPPED overlapped = {0};
+  overlapped.Offset = largeInteger.LowPart;
+  overlapped.OffsetHigh = largeInteger.HighPart;
+
+  return FALSE == ReadFile(handle, buf, n, &m, &overlapped) ? -1 : m;
+}
+
+Goffset GooFile::size() const {
+  LARGE_INTEGER size = {-1,-1};
+  
+  GetFileSizeEx(handle, &size);
+
+  return size.QuadPart;
+}
+
+GooFile* GooFile::open(const GooString *fileName) {
+  HANDLE handle = CreateFile(fileName->getCString(),
+                              GENERIC_READ,
+                              FILE_SHARE_READ,
+                              NULL,
+                              OPEN_EXISTING,
+                              FILE_ATTRIBUTE_NORMAL, NULL);
+  
+  return handle == INVALID_HANDLE_VALUE ? NULL : new GooFile(handle);
+}
+
+GooFile* GooFile::open(const wchar_t *fileName) {
+  HANDLE handle = CreateFileW(fileName,
+                              GENERIC_READ,
+                              FILE_SHARE_READ,
+                              NULL,
+                              OPEN_EXISTING,
+                              FILE_ATTRIBUTE_NORMAL, NULL);
+  
+  return handle == INVALID_HANDLE_VALUE ? NULL : new GooFile(handle);
+}
+
+#else
+
+int GooFile::read(char *buf, int n, Goffset offset) const {
+#ifdef HAVE_PREAD64
+  return pread64(fd, buf, n, offset);
+#else
+  return pread(fd, buf, n, offset);
+#endif
+}
+
+Goffset GooFile::size() const {
+#ifdef HAVE_LSEEK64
+  return lseek64(fd, 0, SEEK_END);
+#else
+  return lseek(fd, 0, SEEK_END);
+#endif
+}
+
+GooFile* GooFile::open(const GooString *fileName) {
+#ifdef VMS
+  int fd = ::open(fileName->getCString(), Q_RDONLY, "ctx=stm");
+#else
+  int fd = ::open(fileName->getCString(), O_RDONLY);
+#endif
+  
+  return fd < 0 ? NULL : new GooFile(fd);
+}
+
+#endif // _WIN32
+
 //------------------------------------------------------------------------
 // GDir and GDirEntry
 //------------------------------------------------------------------------
diff --git a/goo/gfile.h b/goo/gfile.h
index 4e11023..0caee71 100644
--- a/goo/gfile.h
+++ b/goo/gfile.h
@@ -18,6 +18,7 @@
 // Copyright (C) 2006 Kristian Høgsberg <krh@redhat.com>
 // Copyright (C) 2009, 2011, 2012 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2009 Kovid Goyal <kovid@kovidgoyal.net>
+// Copyright (C) 2013 Adam Reichold <adamreichold@myopera.com>
 //
 // 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
@@ -114,6 +115,42 @@
 // conventions.
 extern char *getLine(char *buf, int size, FILE *f);
 
+// Like fseek/ftell but uses platform specific variants that support large files
+extern int Gfseek(FILE *f, Goffset offset, int whence);
+extern Goffset Gftell(FILE *f);
+
+// Largest offset supported by Gfseek/Gftell
+extern Goffset GoffsetMax();
+
+//------------------------------------------------------------------------
+// GooFile
+//------------------------------------------------------------------------
+
+class GooFile
+{
+public:
+  int read(char *buf, int n, Goffset offset) const;
+  Goffset size() const;
+  
+  static GooFile *open(const GooString *fileName);
+  
+#ifdef _WIN32
+  static GooFile *open(const wchar_t *fileName);
+  
+  ~GooFile() { CloseHandle(handle); }
+  
+private:
+  GooFile(HANDLE handleA): handle(handleA) {}
+  HANDLE handle;
+#else
+  ~GooFile() { close(fd); }
+    
+private:
+  GooFile(int fdA) : fd(fdA) {}
+  int fd;
+#endif // _WIN32
+};
+
 //------------------------------------------------------------------------
 // GDir and GDirEntry
 //------------------------------------------------------------------------
diff --git a/goo/gtypes.h b/goo/gtypes.h
index b7a2dd2..a8d4519 100644
--- a/goo/gtypes.h
+++ b/goo/gtypes.h
@@ -15,6 +15,7 @@
 //
 // Copyright (C) 2010 Patrick Spendrin <ps_ml@gmx.de>
 // Copyright (C) 2010 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
 //
 // 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
@@ -24,6 +25,8 @@
 #ifndef GTYPES_H
 #define GTYPES_H
 
+#include "poppler-config.h"
+
 /*
  * These have stupid names to avoid conflicts with some (but not all)
  * C++ compilers which define them.
@@ -44,5 +47,6 @@
 typedef unsigned short Gushort;
 typedef unsigned int Guint;
 typedef unsigned long Gulong;
+typedef long long Goffset;
 
 #endif
diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 064b550..2713fde 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -15,7 +15,7 @@
 //
 // Copyright (C) 2006 Scott Turner <scotty1024@mac.com>
 // Copyright (C) 2007, 2008 Julien Rebetez <julienr@svn.gnome.org>
-// Copyright (C) 2007-2012 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2007-2013 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2007-2012 Carlos Garcia Campos <carlosgc@gnome.org>
 // Copyright (C) 2007, 2008 Iñigo Martínez <inigomartinez@gmail.com>
 // Copyright (C) 2007 Jeff Muizelaar <jeff@infidigm.net>
@@ -25,7 +25,7 @@
 // Copyright (C) 2009 Ilya Gorenbein <igorenbein@finjan.com>
 // Copyright (C) 2011, 2013 José Aliste <jaliste@src.gnome.org>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
-// Copyright (C) 2012 Thomas Freitag <Thomas.Freitag@alfa.de>
+// Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
 // Copyright (C) 2012 Tobias Koenig <tokoe@kdab.com>
 //
 // To see a description of the changes please see the Changelog file that
@@ -67,6 +67,14 @@
 #include "Link.h"
 #include <string.h>
 
+#if MULTITHREADED
+#  define annotLocker()   MutexLocker locker(&mutex)
+#  define annotCondLocker(X)  MutexLocker locker(&mutex, (X))
+#else
+#  define annotLocker()
+#  define annotCondLocker(X)
+#endif
+
 #define fieldFlagReadOnly           0x00000001
 #define fieldFlagRequired           0x00000002
 #define fieldFlagNoExport           0x00000004
@@ -1293,6 +1301,10 @@
   obj1.free();
 
   dict->lookupNF("OC", &oc);
+
+#if MULTITHREADED
+  gInitMutex(&mutex);
+#endif
 }
 
 void Annot::getRect(double *x1, double *y1, double *x2, double *y2) const {
@@ -1339,6 +1351,7 @@
 }
 
 void Annot::update(const char *key, Object *value) {
+  annotLocker();
   /* Set M to current time, unless we are updating M itself */
   if (strcmp(key, "M") != 0) {
     delete modified;
@@ -1355,6 +1368,7 @@
 }
 
 void Annot::setContents(GooString *new_content) {
+  annotLocker();
   delete contents;
 
   if (new_content) {
@@ -1374,6 +1388,7 @@
 }
 
 void Annot::setName(GooString *new_name) {
+  annotLocker();
   delete name;
 
   if (new_name) {
@@ -1388,6 +1403,7 @@
 }
 
 void Annot::setModified(GooString *new_modified) {
+  annotLocker();
   delete modified;
 
   if (new_modified)
@@ -1401,6 +1417,7 @@
 }
 
 void Annot::setFlags(Guint new_flags) {
+  annotLocker();
   Object obj1;
   flags = new_flags;
   obj1.initInt(flags);
@@ -1408,6 +1425,7 @@
 }
 
 void Annot::setBorder(AnnotBorderArray *new_border) {
+  annotLocker();
   delete border;
 
   if (new_border) {
@@ -1421,6 +1439,7 @@
 }
 
 void Annot::setColor(AnnotColor *new_color) {
+  annotLocker();
   delete color;
 
   if (new_color) {
@@ -1434,6 +1453,7 @@
 }
 
 void Annot::setPage(int pageIndex, GBool updateP) {
+  annotLocker();
   Page *pageobj = doc->getPage(pageIndex);
   Object obj1;
 
@@ -1452,6 +1472,7 @@
 }
 
 void Annot::setAppearanceState(const char *state) {
+  annotLocker();
   if (!state)
     return;
 
@@ -1475,6 +1496,7 @@
 }
 
 void Annot::invalidateAppearance() {
+  annotLocker();
   if (appearStreams) { // Remove existing appearance streams
     appearStreams->removeAllStreams();
   }
@@ -1516,12 +1538,18 @@
 }
 
 void Annot::incRefCnt() {
+  annotLocker();
   refCnt++;
 }
 
 void Annot::decRefCnt() {
-  if (--refCnt == 0)
+  gLockMutex(&mutex);
+  if (--refCnt == 0) {
+    gUnlockMutex(&mutex);
     delete this;
+    return;
+  }
+  gUnlockMutex(&mutex);
 }
 
 Annot::~Annot() {
@@ -1552,6 +1580,10 @@
     delete color;
 
   oc.free();
+
+#if MULTITHREADED
+    gDestroyMutex(&mutex);
+#endif
 }
 
 void Annot::setColor(AnnotColor *color, GBool fill) {
@@ -1744,11 +1776,12 @@
 void Annot::draw(Gfx *gfx, GBool printing) {
   Object obj;
 
+  annotLocker();
   if (!isVisible (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();
@@ -2361,6 +2394,7 @@
   if (!isVisible (printing))
     return;
 
+  annotLocker();
   if (appearance.isNull()) {
     ca = opacity;
 
@@ -2412,7 +2446,7 @@
   }
 
   // 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(),
@@ -2510,8 +2544,9 @@
   if (!isVisible (printing))
     return;
 
+  annotLocker();
   // 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();
@@ -2939,12 +2974,13 @@
   if (!isVisible (printing))
     return;
 
+  annotLocker();
   if (appearance.isNull()) {
     generateFreeTextAppearance();
   }
 
   // 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();
@@ -3411,12 +3447,13 @@
   if (!isVisible (printing))
     return;
 
+  annotLocker();
   if (appearance.isNull()) {
     generateLineAppearance();
   }
 
   // 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(),
@@ -3576,6 +3613,7 @@
   if (!isVisible (printing))
     return;
 
+  annotLocker();
   if (appearance.isNull() || type == typeHighlight) {
     GBool blendMultiply = gTrue;
     ca = opacity;
@@ -3729,7 +3767,7 @@
   }
 
   // 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(),
@@ -4961,6 +4999,7 @@
   if (!isVisible (printing))
     return;
 
+  annotLocker();
   addDingbatsResource = gFalse;
 
   // Only construct the appearance stream when
@@ -4972,7 +5011,7 @@
   }
 
   // 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
@@ -4981,19 +5020,19 @@
     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;
@@ -5073,6 +5112,7 @@
   if (!isVisible (printing))
     return;
 
+  annotLocker();
   if (appearance.isNull() && movie->getShowPoster()) {
     int width, height;
     Object poster;
@@ -5089,25 +5129,25 @@
       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));
@@ -5125,10 +5165,10 @@
       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 ();
@@ -5152,7 +5192,7 @@
   }
 
   // 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();
@@ -5381,6 +5421,7 @@
   if (!isVisible (printing))
     return;
 
+  annotLocker();
   if (appearance.isNull()) {
     ca = opacity;
 
@@ -5494,7 +5535,7 @@
   }
 
   // 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();
@@ -5702,6 +5743,7 @@
   if (!isVisible (printing))
     return;
 
+  annotLocker();
   if (appearance.isNull()) {
     appearBBox = new AnnotAppearanceBBox(rect);
     ca = opacity;
@@ -5778,7 +5820,7 @@
   }
 
   // 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(),
@@ -5939,6 +5981,7 @@
   if (!isVisible (printing))
     return;
 
+  annotLocker();
   if (appearance.isNull()) {
     appearBBox = new AnnotAppearanceBBox(rect);
     ca = opacity;
@@ -5990,7 +6033,7 @@
   }
 
   // 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(),
@@ -6171,6 +6214,7 @@
   if (!isVisible (printing))
     return;
 
+  annotLocker();
   if (appearance.isNull()) {
     ca = opacity;
 
@@ -6211,7 +6255,7 @@
   }
 
   // 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();
@@ -6337,6 +6381,7 @@
   if (!isVisible (printing))
     return;
 
+  annotLocker();
   if (appearance.isNull()) {
     ca = opacity;
 
@@ -6372,7 +6417,7 @@
   }
 
   // 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/Annot.h b/poppler/Annot.h
index 68ddeb7..7be2114 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -21,9 +21,10 @@
 // Copyright (C) 2008 Hugo Mercier <hmercier31@gmail.com>
 // Copyright (C) 2008 Pino Toscano <pino@kde.org>
 // Copyright (C) 2008 Tomas Are Haavet <tomasare@gmail.com>
-// Copyright (C) 2009-2011 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2009-2011, 2013 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
 // Copyright (C) 2012 Tobias Koenig <tokoe@kdab.com>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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
@@ -660,6 +661,9 @@
   GBool ok;
 
   bool hasRef;
+#if MULTITHREADED
+  GooMutex mutex;
+#endif
 };
 
 //------------------------------------------------------------------------
diff --git a/poppler/Array.cc b/poppler/Array.cc
index cb22432..230c328 100644
--- a/poppler/Array.cc
+++ b/poppler/Array.cc
@@ -15,6 +15,8 @@
 //
 // Copyright (C) 2005 Kristian Høgsberg <krh@redhat.com>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
+// Copyright (C) 2013 Albert Astals Cid <aacid@kde.org>
 //
 // 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 +35,11 @@
 #include "Object.h"
 #include "Array.h"
 
+#if MULTITHREADED
+#  define arrayLocker()   MutexLocker locker(&mutex)
+#else
+#  define arrayLocker()
+#endif
 //------------------------------------------------------------------------
 // Array
 //------------------------------------------------------------------------
@@ -42,6 +49,9 @@
   elems = NULL;
   size = length = 0;
   ref = 1;
+#if MULTITHREADED
+  gInitMutex(&mutex);
+#endif
 }
 
 Array::~Array() {
@@ -50,9 +60,35 @@
   for (i = 0; i < length; ++i)
     elems[i].free();
   gfree(elems);
+#if MULTITHREADED
+  gDestroyMutex(&mutex);
+#endif
+}
+
+Object *Array::copy(XRef *xrefA, Object *obj) {
+  arrayLocker();
+  obj->initArray(xrefA);
+  for (int i = 0; i < length; ++i) {
+    Object obj1;
+    obj->arrayAdd(elems[i].copy(&obj1));
+  }
+  return obj;
+}
+
+int Array::incRef() {
+  arrayLocker();
+  ++ref;
+  return ref;
+}
+
+int Array::decRef() {
+  arrayLocker();
+  --ref;
+  return ref;
 }
 
 void Array::add(Object *elem) {
+  arrayLocker();
   if (length == size) {
     if (length == 0) {
       size = 8;
@@ -66,6 +102,7 @@
 }
 
 void Array::remove(int i) {
+  arrayLocker();
   if (i < 0 || i >= length) {
 #ifdef DEBUG_MEM
     abort();
@@ -77,7 +114,7 @@
   memmove( elems + i, elems + i + 1, sizeof(elems[0]) * (length - i) );
 }
 
-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 +122,7 @@
     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@redhat.com>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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 @@
   ~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 @@
   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 @@
   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@novell.com>
 // Copyright (C) 2010 Matthias Fauconneau <matthias.fauconneau@gmail.com>
 // Copyright (C) 2011 Andreas Hartmetz <ahartmetz@gmail.com>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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 @@
 #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@gnome.org>
 // Copyright (C) 2010 Pino Toscano <pino@kde.org>
 // Copyright (C) 2011 Andreas Hartmetz <ahartmetz@gmail.com>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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 @@
   //----- 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..1546594 100644
--- a/poppler/CairoFontEngine.cc
+++ b/poppler/CairoFontEngine.cc
@@ -17,7 +17,7 @@
 // Copyright (C) 2005-2007 Jeff Muizelaar <jeff@infidigm.net>
 // Copyright (C) 2005, 2006 Kristian Høgsberg <krh@redhat.com>
 // Copyright (C) 2005 Martin Kretzschmar <martink@gnome.org>
-// Copyright (C) 2005, 2009, 2012 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2005, 2009, 2012, 2013 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2006, 2007, 2010, 2011 Carlos Garcia Campos <carlosgc@gnome.org>
 // Copyright (C) 2007 Koji Otani <sho@bbr.jp>
 // Copyright (C) 2008, 2009 Chris Wilson <chris@chris-wilson.co.uk>
@@ -26,6 +26,7 @@
 // Copyright (C) 2010 Suzuki Toshiya <mpsuzuki@hiroshima-u.ac.jp>
 // Copyright (C) 2010 Jan Kümmel <jan+freedesktop@snorc.org>
 // Copyright (C) 2012 Hib Eris <hib@hiberis.nl>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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,11 @@
 #pragma implementation
 #endif
 
+#if MULTITHREADED
+#  define fontEngineLocker()   MutexLocker locker(&mutex)
+#else
+#  define fontEngineLocker()
+#endif
 
 //------------------------------------------------------------------------
 // CairoFont
@@ -558,6 +564,7 @@
   PDFDoc *doc;
   CairoFontEngine *fontEngine;
   GBool printing;
+  XRef *xref;
 } type3_font_info_t;
 
 static void
@@ -645,7 +652,7 @@
   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 +681,7 @@
 
 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 +704,7 @@
   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 +722,7 @@
     }
   }
 
-  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 +730,7 @@
 			       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 +763,9 @@
   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 +775,19 @@
     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;
   
+  fontEngineLocker();
   ref = *gfxFont->getID();
 
   for (i = 0; i < cairoFontCacheSize; ++i) {
@@ -788,9 +803,9 @@
   
   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]) {
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@infidigm.net>
 // Copyright (C) 2006, 2010 Carlos Garcia Campos <carlosgc@gnome.org>
 // Copyright (C) 2008 Adrian Johnson <ajohnson@redneon.com>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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 @@
 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 @@
   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 @@
   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 34d5a70..a50e189 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -25,7 +25,7 @@
 // Copyright (C) 2008, 2009 Chris Wilson <chris@chris-wilson.co.uk>
 // Copyright (C) 2008, 2012 Hib Eris <hib@hiberis.nl>
 // Copyright (C) 2009, 2010 David Benjamin <davidben@mit.edu>
-// Copyright (C) 2011, 2012 Thomas Freitag <Thomas.Freitag@alfa.de>
+// Copyright (C) 2011-2013 Thomas Freitag <Thomas.Freitag@alfa.de>
 // Copyright (C) 2012 Patrick Pfeifer <p2000@mailinator.com>
 // Copyright (C) 2012 Jason Crain <jason@aquaticape.us>
 //
@@ -144,6 +144,7 @@
   prescaleImages = gTrue;
   printing = gTrue;
   use_show_text_glyphs = gFalse;
+  inUncoloredPattern = gFalse;
   inType3Char = gFalse;
   t3_glyph_has_bbox = gFalse;
 
@@ -163,6 +164,7 @@
   stroke_adjust = globalParams->getStrokeAdjust();
   align_stroke_coords = gFalse;
   adjusted_stroke_width = gFalse;
+  xref = NULL;
 }
 
 CairoOutputDev::~CairoOutputDev() {
@@ -235,9 +237,10 @@
     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 +252,9 @@
 
   if (text)
     text->startPage(state);
+  if (xrefA != NULL) {
+    xref = xrefA;
+  }
 }
 
 void CairoOutputDev::endPage() {
@@ -456,6 +462,9 @@
 void CairoOutputDev::updateFillColor(GfxState *state) {
   GfxRGB color = fill_color;
 
+  if (inUncoloredPattern)
+    return;
+
   state->getFillRGB(&fill_color);
   if (cairo_pattern_get_type (fill_pattern) != CAIRO_PATTERN_TYPE_SOLID ||
       color.r != fill_color.r ||
@@ -476,6 +485,9 @@
 void CairoOutputDev::updateStrokeColor(GfxState *state) {
   GfxRGB color = stroke_color;
 
+  if (inUncoloredPattern)
+    return;
+
   state->getStrokeRGB(&stroke_color);
   if (cairo_pattern_get_type (fill_pattern) != CAIRO_PATTERN_TYPE_SOLID ||
       color.r != stroke_color.r ||
@@ -496,6 +508,9 @@
 void CairoOutputDev::updateFillOpacity(GfxState *state) {
   double opacity = fill_opacity;
 
+  if (inUncoloredPattern)
+    return;
+
   fill_opacity = state->getFillOpacity();
   if (opacity != fill_opacity) {
     cairo_pattern_destroy(fill_pattern);
@@ -511,6 +526,9 @@
 void CairoOutputDev::updateStrokeOpacity(GfxState *state) {
   double opacity = stroke_opacity;
 
+  if (inUncoloredPattern)
+    return;
+
   stroke_opacity = state->getStrokeOpacity();
   if (opacity != stroke_opacity) {
     cairo_pattern_destroy(stroke_pattern);
@@ -524,6 +542,9 @@
 }
 
 void CairoOutputDev::updateFillColorStop(GfxState *state, double offset) {
+  if (inUncoloredPattern)
+    return;
+
   state->getFillRGB(&fill_color);
 
   cairo_pattern_add_color_stop_rgba(fill_pattern, offset,
@@ -602,7 +623,7 @@
   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 +826,7 @@
 
 }
 
-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,8 +867,12 @@
   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());
+  if (paintType == 2)
+    inUncoloredPattern = gTrue;
   gfx->display(str);
+  if (paintType == 2)
+    inUncoloredPattern = gFalse;
   delete gfx;
   strokePathClip = strokePathTmp;
 
diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h
index a699a7b..483b161 100644
--- a/poppler/CairoOutputDev.h
+++ b/poppler/CairoOutputDev.h
@@ -20,7 +20,7 @@
 // Copyright (C) 2006-2011 Carlos Garcia Campos <carlosgc@gnome.org>
 // Copyright (C) 2008, 2009, 2011, 2012 Adrian Johnson <ajohnson@redneon.com>
 // Copyright (C) 2008 Michael Vrable <mvrable@cs.ucsd.edu>
-// Copyright (C) 2010-2012 Thomas Freitag <Thomas.Freitag@alfa.de>
+// Copyright (C) 2010-2013 Thomas Freitag <Thomas.Freitag@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 @@
   //----- 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();
@@ -192,7 +192,6 @@
 			       CharCode code, Unicode *u, int uLen);
   virtual void endType3Char(GfxState *state);
   virtual void beginTextObject(GfxState *state);
-  virtual GBool deviceHasTextClip(GfxState *state) { return textClipPath; }
   virtual void endTextObject(GfxState *state);
 
   //----- image drawing
@@ -284,6 +283,7 @@
   GBool adjusted_stroke_width;
   GBool align_stroke_coords;
   CairoFont *currentFont;
+  XRef *xref;
 
   struct StrokePathClip {
     GfxPath *path;
@@ -319,6 +319,7 @@
   int utf8Count;
   int utf8Max;
   cairo_path_t *textClipPath;
+  GBool inUncoloredPattern;     // inside a uncolored pattern (PaintType = 2)
   GBool inType3Char;		// inside a Type 3 CharProc
   double t3_glyph_wx, t3_glyph_wy;
   GBool t3_glyph_has_bbox;
diff --git a/poppler/Catalog.cc b/poppler/Catalog.cc
index cf6dff0..f49049a 100644
--- a/poppler/Catalog.cc
+++ b/poppler/Catalog.cc
@@ -14,7 +14,7 @@
 // under GPL version 2 or later
 //
 // Copyright (C) 2005 Kristian Høgsberg <krh@redhat.com>
-// Copyright (C) 2005-2012 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2005-2013 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2005 Jeff Muizelaar <jrmuizel@nit.ca>
 // Copyright (C) 2005 Jonathan Blandford <jrb@redhat.com>
 // Copyright (C) 2005 Marco Pesenti Gritti <mpg@redhat.com>
@@ -25,6 +25,7 @@
 // Copyright (C) 2009 Ilya Gorenbein <igorenbein@finjan.com>
 // Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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,11 @@
 #include "ViewerPreferences.h"
 #include "FileSpec.h"
 
+#if MULTITHREADED
+#  define catalogLocker()   MutexLocker locker(&mutex)
+#else
+#  define catalogLocker()
+#endif
 //------------------------------------------------------------------------
 // Catalog
 //------------------------------------------------------------------------
@@ -64,6 +70,9 @@
   Object obj, obj2;
   Object optContentProps;
 
+#if MULTITHREADED
+  gInitMutex(&mutex);
+#endif
   ok = gTrue;
   doc = docA;
   xref = doc->getXRef();
@@ -170,6 +179,9 @@
   outline.free();
   acroForm.free();
   viewerPreferences.free();
+#if MULTITHREADED
+  gDestroyMutex(&mutex);
+#endif
 }
 
 GooString *Catalog::readMetadata() {
@@ -177,6 +189,7 @@
   Dict *dict;
   Object obj;
 
+  catalogLocker();
   if (metadata.isNone()) {
     Object catDict;
 
@@ -209,8 +222,12 @@
 {
   if (i < 1) return NULL;
 
+  catalogLocker();
   if (i > lastCachedPage) {
-     if (cachePageTree(i) == gFalse) return NULL;
+     GBool cached = cachePageTree(i);
+     if ( cached == gFalse) {
+       return NULL;
+     }
   }
   return pages[i-1];
 }
@@ -219,8 +236,12 @@
 {
   if (i < 1) return NULL;
 
+  catalogLocker();
   if (i > lastCachedPage) {
-     if (cachePageTree(i) == gFalse) return NULL;
+     GBool cached = cachePageTree(i);
+     if ( cached == gFalse) {
+       return NULL;
+     }
   }
   return &pageRefs[i-1];
 }
@@ -423,6 +444,7 @@
       obj1.free();
   }
   if (!found) {
+    catalogLocker();
     if (getDestNameTree()->lookup(name, &obj1))
       found = gTrue;
     else
@@ -457,6 +479,7 @@
 {
     Object efDict;
     Object obj;
+    catalogLocker();
     obj = getEmbeddedFileNameTree()->getValue(i);
     FileSpec *embeddedFile = 0;
     if (obj.isRef()) {
@@ -477,6 +500,7 @@
   Object obj;
   // getJSNameTree()->getValue(i) returns a shallow copy of the object so we
   // do not need to free it
+  catalogLocker();
   getJSNameTree()->getValue(i).fetch(xref, &obj);
 
   if (!obj.isDict()) {
@@ -512,6 +536,7 @@
 
 Catalog::PageMode Catalog::getPageMode() {
 
+  catalogLocker();
   if (pageMode == pageModeNull) {
 
     Object catDict, obj;
@@ -547,6 +572,7 @@
 
 Catalog::PageLayout Catalog::getPageLayout() {
 
+  catalogLocker();
   if (pageLayout == pageLayoutNull) {
 
     Object catDict, obj;
@@ -746,6 +772,7 @@
 
 int Catalog::getNumPages()
 {
+  catalogLocker();
   if (numPages == -1)
   {
     Object catDict, pagesDict, obj;
@@ -787,6 +814,7 @@
 
 PageLabelInfo *Catalog::getPageLabelInfo()
 {
+  catalogLocker();
   if (!pageLabelInfo) {
     Object catDict;
     Object obj;
@@ -810,6 +838,7 @@
 
 Object *Catalog::getStructTreeRoot()
 {
+  catalogLocker();
   if (structTreeRoot.isNone())
   {
      Object catDict;
@@ -829,6 +858,7 @@
 
 Object *Catalog::getOutline()
 {
+  catalogLocker();
   if (outline.isNone())
   {
      Object catDict;
@@ -848,6 +878,7 @@
 
 Object *Catalog::getDests()
 {
+  catalogLocker();
   if (dests.isNone())
   {
      Object catDict;
@@ -885,6 +916,7 @@
 
 Form *Catalog::getForm()
 {
+  catalogLocker();
   if (!form) {
     if (acroForm.isDict()) {
       form = new Form(doc, &acroForm);
@@ -898,6 +930,7 @@
 
 ViewerPreferences *Catalog::getViewerPreferences()
 {
+  catalogLocker();
   if (!viewerPrefs) {
     if (viewerPreferences.isDict()) {
       viewerPrefs = new ViewerPreferences(viewerPreferences.getDict());
diff --git a/poppler/Catalog.h b/poppler/Catalog.h
index ef469ec..24a3dcf 100644
--- a/poppler/Catalog.h
+++ b/poppler/Catalog.h
@@ -14,13 +14,14 @@
 // under GPL version 2 or later
 //
 // Copyright (C) 2005 Kristian Høgsberg <krh@redhat.com>
-// Copyright (C) 2005, 2007, 2009-2011 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2005, 2007, 2009-2011, 2013 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2005 Jonathan Blandford <jrb@redhat.com>
 // Copyright (C) 2005, 2006, 2008 Brad Hards <bradh@frogmouth.net>
 // Copyright (C) 2007 Julien Rebetez <julienr@svn.gnome.org>
 // Copyright (C) 2008, 2011 Pino Toscano <pino@kde.org>
 // Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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>
 
@@ -232,6 +235,9 @@
   NameTree *getDestNameTree();
   NameTree *getEmbeddedFileNameTree();
   NameTree *getJSNameTree();
+#if MULTITHREADED
+  GooMutex mutex;
+#endif
 
 };
 
diff --git a/poppler/DCTStream.cc b/poppler/DCTStream.cc
index decfd0f..bfdb0ea 100644
--- a/poppler/DCTStream.cc
+++ b/poppler/DCTStream.cc
@@ -60,16 +60,16 @@
 {
 }
 
-DCTStream::DCTStream(Stream *strA, int colorXformA, Object *dict) :
+DCTStream::DCTStream(Stream *strA, int colorXformA, Object *dict, int recursion) :
   FilterStream(strA) {
   colorXform = colorXformA;
   if (dict != NULL) {
     Object obj;
 
-    dict->dictLookup("Width", &obj);
+    dict->dictLookup("Width", &obj, recursion);
     err.width = (obj.isInt() && obj.getInt() <= JPEG_MAX_DIMENSION) ? obj.getInt() : 0;
     obj.free();
-    dict->dictLookup("Height", &obj);
+    dict->dictLookup("Height", &obj, recursion);
     err.height = (obj.isInt() && obj.getInt() <= JPEG_MAX_DIMENSION) ? obj.getInt() : 0;
     obj.free();
   } else
@@ -159,40 +159,43 @@
     }
   }
 
-  if (!setjmp(err.setjmp_buffer) && jpeg_read_header(&cinfo, TRUE) != JPEG_SUSPENDED)
+  if (!setjmp(err.setjmp_buffer))
   {
-    // figure out color transform
-    if (colorXform == -1 && !cinfo.saw_Adobe_marker) {
-      if (cinfo.num_components == 3) {
-        if (cinfo.saw_JFIF_marker) {
-	  colorXform = 1;
-        } else if (cinfo.cur_comp_info[0]->component_id == 82 &&
-		   cinfo.cur_comp_info[1]->component_id == 71 &&
-		   cinfo.cur_comp_info[2]->component_id == 66) { // ASCII "RGB"
-	  colorXform = 0;
+    if (jpeg_read_header(&cinfo, TRUE) != JPEG_SUSPENDED)
+    {
+      // figure out color transform
+      if (colorXform == -1 && !cinfo.saw_Adobe_marker) {
+	if (cinfo.num_components == 3) {
+	  if (cinfo.saw_JFIF_marker) {
+	    colorXform = 1;
+	  } else if (cinfo.cur_comp_info[0]->component_id == 82 &&
+	      cinfo.cur_comp_info[1]->component_id == 71 &&
+	      cinfo.cur_comp_info[2]->component_id == 66) { // ASCII "RGB"
+	    colorXform = 0;
+	  } else {
+	    colorXform = 1;
+	  }
 	} else {
-	  colorXform = 1;
+	  colorXform = 0;
 	}
-      } else {
-        colorXform = 0;
+      } else if (cinfo.saw_Adobe_marker) {
+	colorXform = cinfo.Adobe_transform;
       }
-    } else if (cinfo.saw_Adobe_marker) {
-      colorXform = cinfo.Adobe_transform;
+
+      switch (cinfo.num_components) {
+      case 3:
+	cinfo.jpeg_color_space = colorXform ? JCS_YCbCr : JCS_RGB;
+	break;
+      case 4:
+	cinfo.jpeg_color_space = colorXform ? JCS_YCCK : JCS_CMYK;
+	break;
+      }
+
+      jpeg_start_decompress(&cinfo);
+
+      row_stride = cinfo.output_width * cinfo.output_components;
+      row_buffer = cinfo.mem->alloc_sarray((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
     }
-
-    switch (cinfo.num_components) {
-    case 3:
-	    cinfo.jpeg_color_space = colorXform ? JCS_YCbCr : JCS_RGB;
-	    break;
-    case 4:
-	    cinfo.jpeg_color_space = colorXform ? JCS_YCCK : JCS_CMYK;
-	    break;
-    }
-
-    jpeg_start_decompress(&cinfo);
-
-    row_stride = cinfo.output_width * cinfo.output_components;
-    row_buffer = cinfo.mem->alloc_sarray((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
   }
 }
 
diff --git a/poppler/DCTStream.h b/poppler/DCTStream.h
index 7a566ce..bc20a7a 100644
--- a/poppler/DCTStream.h
+++ b/poppler/DCTStream.h
@@ -64,7 +64,7 @@
 class DCTStream: public FilterStream {
 public:
 
-  DCTStream(Stream *strA, int colorXformA, Object *dict);
+  DCTStream(Stream *strA, int colorXformA, Object *dict, int recursion);
   virtual ~DCTStream();
   virtual StreamKind getKind() { return strDCT; }
   virtual void reset();
diff --git a/poppler/Decrypt.cc b/poppler/Decrypt.cc
index 44f6961..ba44f95 100644
--- a/poppler/Decrypt.cc
+++ b/poppler/Decrypt.cc
@@ -18,6 +18,7 @@
 // Copyright (C) 2009 Matthias Franz <matthias@ktug.or.kr>
 // Copyright (C) 2009 David Benjamin <davidben@mit.edu>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
+// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
 //
 // 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
@@ -341,7 +342,7 @@
   str->reset();
 }
 
-int BaseCryptStream::getPos() {
+Goffset BaseCryptStream::getPos() {
   return charactersRead;
 }
 
diff --git a/poppler/Decrypt.h b/poppler/Decrypt.h
index c049f5c..10a6386 100644
--- a/poppler/Decrypt.h
+++ b/poppler/Decrypt.h
@@ -16,6 +16,9 @@
 // Copyright (C) 2008 Julien Rebetez <julien@fhtagn.net>
 // Copyright (C) 2009 David Benjamin <davidben@mit.edu>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
+// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
+// Copyright (C) 2013 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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
@@ -103,11 +106,11 @@
   BaseCryptStream(Stream *strA, Guchar *fileKey, CryptAlgorithm algoA,
                   int keyLength, int objNum, int objGen);
   virtual ~BaseCryptStream();
-  virtual StreamKind getKind() { return strWeird; }
+  virtual StreamKind getKind() { return strCrypt; }
   virtual void reset();
   virtual int getChar();
   virtual int lookChar() = 0;
-  virtual int getPos();
+  virtual Goffset getPos();
   virtual GBool isBinary(GBool last);
   virtual Stream *getUndecodedStream() { return this; }
   void setAutoDelete(GBool val);
@@ -116,7 +119,7 @@
   CryptAlgorithm algo;
   int objKeyLength;
   Guchar objKey[32];
-  int charactersRead; // so that getPos() can be correct
+  Goffset charactersRead; // so that getPos() can be correct
   int nextCharBuff;   // EOF means not read yet
   GBool autoDelete;
 
diff --git a/poppler/Dict.cc b/poppler/Dict.cc
index c4f667b..3f3c022 100644
--- a/poppler/Dict.cc
+++ b/poppler/Dict.cc
@@ -16,9 +16,10 @@
 // Copyright (C) 2005 Kristian Høgsberg <krh@redhat.com>
 // Copyright (C) 2006 Krzysztof Kowalczyk <kkowalczyk@gmail.com>
 // Copyright (C) 2007-2008 Julien Rebetez <julienr@svn.gnome.org>
-// Copyright (C) 2008, 2010 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2008, 2010, 2013 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2010 Paweł Wiejacha <pawel.wiejacha@gmail.com>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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,11 @@
 #include "XRef.h"
 #include "Dict.h"
 
+#if MULTITHREADED
+#  define dictLocker()   MutexLocker locker(&mutex)
+#else
+#  define dictLocker()
+#endif
 //------------------------------------------------------------------------
 // Dict
 //------------------------------------------------------------------------
@@ -74,12 +80,18 @@
   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 +101,23 @@
   }
 }
 
+Dict *Dict::copy(XRef *xrefA) {
+  dictLocker();
+  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();
+    }
+  }
+  return dictA;
+}
+
 Dict::~Dict() {
   int i;
 
@@ -97,9 +126,25 @@
     entries[i].val.free();
   }
   gfree(entries);
+#if MULTITHREADED
+  gDestroyMutex(&mutex);
+#endif
+}
+
+int Dict::incRef() {
+  dictLocker();
+  ++ref;
+  return ref;
+}
+
+int Dict::decRef() {
+  dictLocker();
+  --ref;
+  return ref;
 }
 
 void Dict::add(char *key, Object *val) {
+  dictLocker();
   if (sorted) {
     // We use add on very few occasions so
     // virtually this will never be hit
@@ -122,6 +167,7 @@
 inline DictEntry *Dict::find(const char *key) {
   if (!sorted && length >= SORT_LENGTH_LOWER_LIMIT)
   {
+      dictLocker();
       sorted = gTrue;
       std::sort(entries, entries+length, cmpDictEntries);
   }
@@ -147,6 +193,7 @@
 }
 
 void Dict::remove(const char *key) {
+  dictLocker();
   if (sorted) {
     const int pos = binarySearch(key, entries, length);
     if (pos != -1) {
@@ -159,7 +206,9 @@
     int i; 
     bool found = false;
     DictEntry tmp;
-    if(length == 0) return;
+    if(length == 0) {
+      return;
+    }
 
     for(i=0; i<length; i++) {
       if (!strcmp(key, entries[i].key)) {
@@ -167,7 +216,9 @@
         break;
       }
     }
-    if(!found) return;
+    if(!found) {
+      return;
+    }
     //replace the deleted entry with the last entry
     length -= 1;
     tmp = entries[length];
@@ -184,6 +235,7 @@
   }
   e = find (key);
   if (e) {
+    dictLocker();
     e->val.free();
     e->val = *val;
   } else {
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@svn.gnome.org>
 // Copyright (C) 2010 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2010 Paweł Wiejacha <pawel.wiejacha@gmail.com>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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 @@
   // 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 @@
   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/Error.cc b/poppler/Error.cc
index ce71820..99ca3ad 100644
--- a/poppler/Error.cc
+++ b/poppler/Error.cc
@@ -17,6 +17,7 @@
 // Copyright (C) 2005 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2007 Krzysztof Kowalczyk <kkowalczyk@gmail.com>
 // Copyright (C) 2012 Marek Kasik <mkasik@redhat.com>
+// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
 //
 // 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
@@ -48,17 +49,17 @@
 };
 
 static void (*errorCbk)(void *data, ErrorCategory category,
-			int pos, char *msg) = NULL;
+			Goffset pos, char *msg) = NULL;
 static void *errorCbkData = NULL;
 
 void setErrorCallback(void (*cbk)(void *data, ErrorCategory category,
-				  int pos, char *msg),
+				  Goffset pos, char *msg),
 		      void *data) {
   errorCbk = cbk;
   errorCbkData = data;
 }
 
-void CDECL error(ErrorCategory category, int pos, const char *msg, ...) {
+void CDECL error(ErrorCategory category, Goffset pos, const char *msg, ...) {
   va_list args;
   GooString *s, *sanitized;
 
@@ -84,8 +85,8 @@
     (*errorCbk)(errorCbkData, category, pos, sanitized->getCString());
   } else {
     if (pos >= 0) {
-      fprintf(stderr, "%s (%d): %s\n",
-	      errorCategoryNames[category], pos, sanitized->getCString());
+      fprintf(stderr, "%s (%lld): %s\n",
+	      errorCategoryNames[category], (long long)pos, sanitized->getCString());
     } else {
       fprintf(stderr, "%s: %s\n",
 	      errorCategoryNames[category], sanitized->getCString());
diff --git a/poppler/Error.h b/poppler/Error.h
index d7a0991..88fc3ea 100644
--- a/poppler/Error.h
+++ b/poppler/Error.h
@@ -16,6 +16,7 @@
 // Copyright (C) 2005, 2007 Jeff Muizelaar <jeff@infidigm.net>
 // Copyright (C) 2005 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2005 Kristian Høgsberg <krh@redhat.com>
+// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
 //
 // 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,6 +32,7 @@
 
 #include <stdarg.h>
 #include "poppler-config.h"
+#include "goo/gtypes.h"
 
 enum ErrorCategory {
   errSyntaxWarning,    // PDF syntax error which can be worked around;
@@ -48,9 +50,9 @@
 };
 
 extern void setErrorCallback(void (*cbk)(void *data, ErrorCategory category,
-					 int pos, char *msg),
+					 Goffset pos, char *msg),
 			     void *data);
 
-extern void CDECL error(ErrorCategory category, int pos, const char *msg, ...);
+extern void CDECL error(ErrorCategory category, Goffset pos, const char *msg, ...);
 
 #endif
diff --git a/poppler/FontInfo.cc b/poppler/FontInfo.cc
index 35d5f5f..8fc89e9 100644
--- a/poppler/FontInfo.cc
+++ b/poppler/FontInfo.cc
@@ -9,7 +9,7 @@
 // Copyright (C) 2009 Pino Toscano <pino@kde.org>
 // Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
 // Copyright (C) 2010, 2012 Adrian Johnson <ajohnson@redneon.com>
-// Copyright (C) 2010 Thomas Freitag <Thomas.Freitag@alfa.de>
+// Copyright (C) 2010, 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
 // Copyright (C) 2011 Carlos Garcia Campos <carlosgc@gnome.org>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
 //
@@ -68,17 +68,19 @@
     lastPage = doc->getNumPages() + 1;
   }
 
+  XRef *xrefA = doc->getXRef()->copy();
   for (int pg = currentPage; pg < lastPage; ++pg) {
     page = doc->getPage(pg);
     if (!page) continue;
 
-    if ((resDict = page->getResourceDict())) {
-      scanFonts(resDict, result);
+    if ((resDict = page->getResourceDictCopy(xrefA))) {
+      scanFonts(xrefA, resDict, result);
+      delete resDict;
     }
     annots = page->getAnnots();
     for (int i = 0; i < annots->getNumAnnots(); ++i) {
       if (annots->getAnnot(i)->getAppearanceResDict(&obj1)->isDict()) {
-        scanFonts(obj1.getDict(), result);
+        scanFonts(xrefA, obj1.getDict(), result);
       }
       obj1.free();
     }
@@ -86,10 +88,11 @@
 
   currentPage = lastPage;
 
+  delete xrefA;
   return result;
 }
 
-void FontInfoScanner::scanFonts(Dict *resDict, GooList *fontsList) {
+void FontInfoScanner::scanFonts(XRef *xrefA, Dict *resDict, GooList *fontsList) {
   Object obj1, obj2, objDict, resObj;
   Ref r;
   GfxFontDict *gfxFontDict;
@@ -100,14 +103,14 @@
   gfxFontDict = NULL;
   resDict->lookupNF("Font", &obj1);
   if (obj1.isRef()) {
-    obj1.fetch(doc->getXRef(), &obj2);
+    obj1.fetch(xrefA, &obj2);
     if (obj2.isDict()) {
       r = obj1.getRef();
-      gfxFontDict = new GfxFontDict(doc->getXRef(), &r, obj2.getDict());
+      gfxFontDict = new GfxFontDict(xrefA, &r, obj2.getDict());
     }
     obj2.free();
   } else if (obj1.isDict()) {
-    gfxFontDict = new GfxFontDict(doc->getXRef(), NULL, obj1.getDict());
+    gfxFontDict = new GfxFontDict(xrefA, NULL, obj1.getDict());
   }
   if (gfxFontDict) {
     for (i = 0; i < gfxFontDict->getNumFonts(); ++i) {
@@ -116,7 +119,7 @@
 
         // add this font to the list if not already found
         if (fonts.find(fontRef.num) == fonts.end()) {
-          fontsList->append(new FontInfo(font, doc));
+          fontsList->append(new FontInfo(font, xrefA));
           fonts.insert(fontRef.num);
         }
       }
@@ -144,12 +147,12 @@
           visitedObjects.insert(r.num);
         }
 
-        obj1.fetch(doc->getXRef(), &obj2);
+        obj1.fetch(xrefA, &obj2);
 
         if (obj2.isStream()) {
           obj2.streamGetDict()->lookup("Resources", &resObj);
           if (resObj.isDict() && resObj.getDict() != resDict) {
-            scanFonts(resObj.getDict(), fontsList);
+            scanFonts(xrefA, resObj.getDict(), fontsList);
           }
           resObj.free();
         }
@@ -161,7 +164,7 @@
   }
 }
 
-FontInfo::FontInfo(GfxFont *font, PDFDoc *doc) {
+FontInfo::FontInfo(GfxFont *font, XRef *xref) {
   GooString *origName;
   Object fontObj, toUnicodeObj;
   int i;
@@ -201,7 +204,7 @@
 
   // look for a ToUnicode map
   hasToUnicode = gFalse;
-  if (doc->getXRef()->fetch(fontRef.num, fontRef.gen, &fontObj)->isDict()) {
+  if (xref->fetch(fontRef.num, fontRef.gen, &fontObj)->isDict()) {
     hasToUnicode = fontObj.dictLookup("ToUnicode", &toUnicodeObj)->isStream();
     toUnicodeObj.free();
   }
diff --git a/poppler/FontInfo.h b/poppler/FontInfo.h
index db90440..615b679 100644
--- a/poppler/FontInfo.h
+++ b/poppler/FontInfo.h
@@ -7,6 +7,7 @@
 // Copyright (C) 2005 Brad Hards <bradh@frogmouth.net>
 // Copyright (C) 2009 Pino Toscano <pino@kde.org>
 // Copyright (C) 2012 Adrian Johnson <ajohnson@redneon.com>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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
@@ -49,7 +50,7 @@
   };
     
   // Constructor.
-  FontInfo(GfxFont *fontA, PDFDoc *doc);
+  FontInfo(GfxFont *fontA, XRef *xrefA);
   // Copy constructor
   FontInfo(FontInfo& f);
   // Destructor.
@@ -96,7 +97,7 @@
   std::set<int> fonts;
   std::set<int> visitedObjects;
 
-  void scanFonts(Dict *resDict, GooList *fontsList);
+  void scanFonts(XRef *xrefA, Dict *resDict, GooList *fontsList);
 };
 
 #endif
diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc
index 2945234..775a2c9 100644
--- a/poppler/Gfx.cc
+++ b/poppler/Gfx.cc
@@ -322,14 +322,15 @@
 // 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 @@
     // get properties dictionary
     resDict->lookup("Properties", &propertiesDict);
 
+    delete resDict;
   } else {
     fonts = NULL;
     xObjDict.initNull();
@@ -534,7 +536,7 @@
 	 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 @@
   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 @@
   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, 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 @@
   int i;
 
   doc = docA;
-  xref = doc->getXRef();
+  xref = (xrefA == NULL) ? doc->getXRef() : xrefA;
   catalog = doc->getCatalog();
   subPage = gTrue;
   printCommands = globalParams->getPrintCommands();
@@ -893,7 +895,7 @@
   return gFalse;
 }
 
-int Gfx::getPos() {
+Goffset Gfx::getPos() {
   return parser ? parser->getPos() : -1;
 }
 
diff --git a/poppler/Gfx.h b/poppler/Gfx.h
index 9798f90..aa81e56 100644
--- a/poppler/Gfx.h
+++ b/poppler/Gfx.h
@@ -18,7 +18,7 @@
 // Copyright (C) 2008 Brad Hards <bradh@kde.org>
 // Copyright (C) 2008, 2010 Carlos Garcia Campos <carlosgc@gnome.org>
 // Copyright (C) 2009-2013 Albert Astals Cid <aacid@kde.org>
-// Copyright (C) 2009, 2010, 2012 Thomas Freitag <Thomas.Freitag@alfa.de>
+// Copyright (C) 2009, 2010, 2012, 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
 // Copyright (C) 2010 David Benjamin <davidben@mit.edu>
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger@googlemail.com>
 //
@@ -148,16 +148,18 @@
       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);
 
@@ -242,7 +244,7 @@
   void execOp(Object *cmd, Object args[], int numArgs);
   Operator *findOp(char *name);
   GBool checkArg(Object *arg, TchkType type);
-  int getPos();
+  Goffset getPos();
 
   int bottomGuard();
 
diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc
index 73a3781..3e5e053 100644
--- a/poppler/GfxState.cc
+++ b/poppler/GfxState.cc
@@ -24,6 +24,7 @@
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger@googlemail.com>
 // Copyright (C) 2011 Andrea Canciani <ranma42@gmail.com>
 // Copyright (C) 2012 William Bader <williambader@hotmail.com>
+// Copyright (C) 2013 Lu Wang <coolwanglu@gmail.com>
 //
 // 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
@@ -6160,7 +6161,7 @@
   ctm[5] = e * b1 + f * d1 + ctm[5];
 }
 
-void GfxState::shiftCTM(double tx, double ty) {
+void GfxState::shiftCTMAndClip(double tx, double ty) {
   ctm[4] += tx;
   ctm[5] += ty;
   clipXMin += tx;
diff --git a/poppler/GfxState.h b/poppler/GfxState.h
index f2ce6b2..aa15a75 100644
--- a/poppler/GfxState.h
+++ b/poppler/GfxState.h
@@ -21,6 +21,7 @@
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger@googlemail.com>
 // Copyright (C) 2011 Andrea Canciani <ranma42@gmail.com>
 // Copyright (C) 2011, 2012 Thomas Freitag <Thomas.Freitag@alfa.de>
+// Copyright (C) 2013 Lu Wang <coolwanglu@gmail.com>
 //
 // 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
@@ -1443,7 +1444,7 @@
 	      double d, double e, double f);
   void concatCTM(double a, double b, double c,
 		 double d, double e, double f);
-  void shiftCTM(double tx, double ty);
+  void shiftCTMAndClip(double tx, double ty);
   void setFillColorSpace(GfxColorSpace *colorSpace);
   void setStrokeColorSpace(GfxColorSpace *colorSpace);
   void setFillColor(GfxColor *color) { fillColor = *color; }
diff --git a/poppler/GlobalParamsWin.cc b/poppler/GlobalParamsWin.cc
index b76e156..084b49b 100644
--- a/poppler/GlobalParamsWin.cc
+++ b/poppler/GlobalParamsWin.cc
@@ -2,10 +2,11 @@
    but mostly based on xpdf code.
    
    // Copyright (C) 2010, 2012 Hib Eris <hib@hiberis.nl>
-   // Copyright (C) 2012 Thomas Freitag <Thomas.Freitag@alfa.de>
+   // Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
    // Copyright (C) 2012 Suzuki Toshiya <mpsuzuki@hiroshima-u.ac.jp>
    // Copyright (C) 2012 Adrian Johnson <ajohnson@redneon.com>
    // Copyright (C) 2012 Mark Brand <mabrand@mabrand.nl>
+   // Copyright (C) 2013 Adam Reichold <adamreichold@myopera.com>
 
 TODO: instead of a fixed mapping defined in displayFontTab, it could
 scan the whole fonts directory, parse TTF files and build font
@@ -408,9 +409,7 @@
 {
     const char *dataRoot = popplerDataDir ? popplerDataDir : POPPLER_DATADIR;
     GooString *fileName = NULL;
-    struct stat buf;
-    FILE *file;
-    int size = 0;
+    GooFile *file;
 
     if (baseFontsInitialized)
         return;
@@ -453,15 +452,9 @@
 
     fileName = new GooString(dataRoot);
     fileName->append("/cidfmap");
-    if (stat(fileName->getCString(), &buf) == 0) {
-      size = buf.st_size;
-    }
+
     // try to open file
-#ifdef VMS
-    file = fopen(fileName->getCString(), "rb", "ctx=stm");
-#else
-    file = fopen(fileName->getCString(), "rb");
-#endif
+    file = GooFile::open(fileName);
 
     if (file != NULL) {
       Parser *parser;
@@ -470,7 +463,7 @@
       obj1.initNull();
       parser = new Parser(NULL,
 	      new Lexer(NULL,
-	      new FileStream(file, 0, gFalse, size, &obj1)),
+	      new FileStream(file, 0, gFalse, file->size(), &obj1)),
 	      gTrue);
       obj1.free();
       parser->getObj(&obj1);
@@ -498,7 +491,7 @@
 	  parser->getObj(&obj1);
 	}
       }
-      fclose(file);
+      delete file;
       delete parser;
     }
 }
diff --git a/poppler/Hints.cc b/poppler/Hints.cc
index 13bcc90..d76e019 100644
--- a/poppler/Hints.cc
+++ b/poppler/Hints.cc
@@ -7,6 +7,7 @@
 // Copyright 2010, 2012 Hib Eris <hib@hiberis.nl>
 // Copyright 2010, 2011 Albert Astals Cid <aacid@kde.org>
 // Copyright 2010 Pino Toscano <pino@kde.org>
+// Copyright 2013 Adrian Johnson <ajohnson@redneon.com>
 //
 //========================================================================
 
@@ -51,7 +52,7 @@
   pageObjectNum = (int *) gmallocn_checkoverflow(nPages, sizeof(int));
   xRefOffset = (Guint *) gmallocn_checkoverflow(nPages, sizeof(Guint));
   pageLength = (Guint *) gmallocn_checkoverflow(nPages, sizeof(Guint));
-  pageOffset = (Guint *) gmallocn_checkoverflow(nPages, sizeof(Guint));
+  pageOffset = (Goffset *) gmallocn_checkoverflow(nPages, sizeof(Goffset));
   numSharedObject = (Guint *) gmallocn_checkoverflow(nPages, sizeof(Guint));
   sharedObjectId = (Guint **) gmallocn_checkoverflow(nPages, sizeof(Guint*));
   if (!nObjects || !pageObjectNum || !xRefOffset || !pageLength || !pageOffset ||
@@ -344,7 +345,7 @@
   }
 }
 
-Guint Hints::getPageOffset(int page)
+Goffset Hints::getPageOffset(int page)
 {
   if ((page < 1) || (page > nPages)) return 0;
 
diff --git a/poppler/Hints.h b/poppler/Hints.h
index d598e79..f5225f9 100644
--- a/poppler/Hints.h
+++ b/poppler/Hints.h
@@ -6,6 +6,7 @@
 //
 // Copyright 2010 Hib Eris <hib@hiberis.nl>
 // Copyright 2010 Albert Astals Cid <aacid@kde.org>
+// Copyright 2013 Adrian Johnson <ajohnson@redneon.com>
 //
 //========================================================================
 
@@ -33,7 +34,7 @@
   ~Hints();
 
   int getPageObjectNum(int page);
-  Guint getPageOffset(int page);
+  Goffset getPageOffset(int page);
   std::vector<ByteRange>* getPageRanges(int page);
 
 private:
@@ -54,7 +55,7 @@
   int nPages;
   int pageFirst;
   int pageObjectFirst;
-  Guint pageOffsetFirst;
+  Goffset pageOffsetFirst;
   Guint pageEndFirst;
   int objectNumberFirst;
 
@@ -76,7 +77,7 @@
   int *pageObjectNum;
   Guint *xRefOffset;
   Guint *pageLength;
-  Guint *pageOffset;
+  Goffset *pageOffset;
   Guint *numSharedObject;
   Guint **sharedObjectId;
 
diff --git a/poppler/JBIG2Stream.cc b/poppler/JBIG2Stream.cc
index afba8c6..12de50e 100644
--- a/poppler/JBIG2Stream.cc
+++ b/poppler/JBIG2Stream.cc
@@ -20,6 +20,7 @@
 // Copyright (C) 2011 Edward Jiang <ejiang@google.com>
 // Copyright (C) 2012 William Bader <williambader@hotmail.com>
 // Copyright (C) 2012 Thomas Freitag <Thomas.Freitag@alfa.de>
+// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
 //
 // 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
@@ -1284,7 +1285,7 @@
   return EOF;
 }
 
-int JBIG2Stream::getPos() {
+Goffset JBIG2Stream::getPos() {
   if (pageBitmap == NULL) {
     return 0;
   }
@@ -1320,7 +1321,7 @@
   Guint segNum, segFlags, segType, page, segLength;
   Guint refFlags, nRefSegs;
   Guint *refSegs;
-  int segDataPos;
+  Goffset segDataPos;
   int c1, c2, c3;
   Guint i;
 
@@ -1483,7 +1484,7 @@
 
     if (segLength != 0xffffffff) {
 
-      int segExtraBytes = segDataPos + segLength - curStr->getPos();
+      Goffset segExtraBytes = segDataPos + segLength - curStr->getPos();
       if (segExtraBytes > 0) {
 
 	// If we didn't read all of the bytes in the segment data,
@@ -1501,7 +1502,7 @@
 	// hopefully we're not doing this much
 	
 	int trash;
-	for (int i = segExtraBytes; i > 0; i--) {
+	for (Goffset i = segExtraBytes; i > 0; i--) {
 	  readByte(&trash);
 	}
 	
diff --git a/poppler/JBIG2Stream.h b/poppler/JBIG2Stream.h
index c518aa5..be1b3bd 100644
--- a/poppler/JBIG2Stream.h
+++ b/poppler/JBIG2Stream.h
@@ -14,6 +14,7 @@
 // under GPL version 2 or later
 //
 // Copyright (C) 2009 David Benjamin <davidben@mit.edu>
+// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
 //
 // 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
@@ -50,7 +51,7 @@
   virtual StreamKind getKind() { return strJBIG2; }
   virtual void reset();
   virtual void close();
-  virtual int getPos();
+  virtual Goffset getPos();
   virtual int getChar();
   virtual int lookChar();
   virtual GooString *getPSFilter(int psLevel, const char *indent);
diff --git a/poppler/JPEG2000Stream.cc b/poppler/JPEG2000Stream.cc
index e2fd808..703d471 100644
--- a/poppler/JPEG2000Stream.cc
+++ b/poppler/JPEG2000Stream.cc
@@ -6,6 +6,7 @@
 //
 // Copyright 2008-2010, 2012 Albert Astals Cid <aacid@kde.org>
 // Copyright 2011 Daniel Glöckner <daniel-gl@gmx.net>
+// Copyright 2013 Adrian Johnson <ajohnson@redneon.com>
 //
 // Licensed under GPLv2 or later
 //
@@ -46,7 +47,7 @@
   }
 }
 
-int JPXStream::getPos() {
+Goffset JPXStream::getPos() {
   return counter * ncomps + ccounter;
 }
 
diff --git a/poppler/JPEG2000Stream.h b/poppler/JPEG2000Stream.h
index 5aed32d..3feccbe 100644
--- a/poppler/JPEG2000Stream.h
+++ b/poppler/JPEG2000Stream.h
@@ -6,6 +6,7 @@
 //
 // Copyright 2008, 2010 Albert Astals Cid <aacid@kde.org>
 // Copyright 2011 Daniel Glöckner <daniel-gl@gmx.net>
+// Copyright 2013 Adrian Johnson <ajohnson@redneon.com>
 //
 // Licensed under GPLv2 or later
 //
@@ -29,7 +30,7 @@
   virtual StreamKind getKind() { return strJPX; }
   virtual void reset();
   virtual void close();
-  virtual int getPos();
+  virtual Goffset getPos();
   virtual int getChar();
   virtual int lookChar();
   virtual GooString *getPSFilter(int psLevel, const char *indent);
diff --git a/poppler/Lexer.cc b/poppler/Lexer.cc
index 01b730b..bd7546f 100644
--- a/poppler/Lexer.cc
+++ b/poppler/Lexer.cc
@@ -16,7 +16,8 @@
 // Copyright (C) 2006-2010, 2012 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2006 Krzysztof Kowalczyk <kkowalczyk@gmail.com>
 // Copyright (C) 2010 Carlos Garcia Campos <carlosgc@gnome.org>
-// Copyright (C) 2012 Adrian Johnson <ajohnson@redneon.com>
+// Copyright (C) 2012, 2013 Adrian Johnson <ajohnson@redneon.com>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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
@@ -62,6 +63,7 @@
 };
 
 static const int IntegerSafeLimit = (INT_MAX - 9) / 10;
+static const long long LongLongSafeLimit = (LLONG_MAX - 9) / 10;
 
 //------------------------------------------------------------------------
 // Lexer
@@ -155,10 +157,10 @@
 Object *Lexer::getObj(Object *obj, int objNum) {
   char *p;
   int c, c2;
-  GBool comment, neg, done, overflownInteger, overflownUnsignedInteger;
+  GBool comment, neg, done, overflownInteger, overflownLongLong;
   int numParen;
   int xi;
-  unsigned int xui = 0;
+  long long xll = 0;
   double xf = 0, scale;
   GooString *s;
   int n, m;
@@ -187,7 +189,7 @@
   case '5': case '6': case '7': case '8': case '9':
   case '+': case '-': case '.':
     overflownInteger = gFalse;
-    overflownUnsignedInteger = gFalse;
+    overflownLongLong = gFalse;
     neg = gFalse;
     xi = 0;
     if (c == '-') {
@@ -201,23 +203,21 @@
       c = lookChar();
       if (isdigit(c)) {
 	getChar();
-	if (unlikely(overflownInteger)) {
-	  if (overflownUnsignedInteger) {
-	    xf = xf * 10.0 + (c - '0');
+	if (unlikely(overflownLongLong)) {
+	  xf = xf * 10.0 + (c - '0');
+	} else if (unlikely (overflownInteger)) {
+	  if (unlikely(xll > LongLongSafeLimit) &&
+	      (xll > (LLONG_MAX - (c - '0')) / 10.0)) {
+	    overflownLongLong = gTrue;
+	    xf = xll * 10.0 + (c - '0');
 	  } else {
-	    overflownUnsignedInteger = gTrue;
-	    xf = xui * 10.0 + (c - '0');
+	    xll = xll * 10 + (c - '0');
 	  }
 	} else {
 	  if (unlikely(xi > IntegerSafeLimit) &&
 	      (xi > (INT_MAX - (c - '0')) / 10.0)) {
 	    overflownInteger = gTrue;
-	    if (xi > (UINT_MAX - (c - '0')) / 10.0) {
-	      overflownUnsignedInteger = gTrue;
-	      xf = xi * 10.0 + (c - '0');
-	    } else {
-	      xui = xi * 10.0 + (c - '0');
-	    }
+	    xll = xi * 10LL + (c - '0');
 	  } else {
 	    xi = xi * 10 + (c - '0');
 	  }
@@ -231,22 +231,17 @@
     }
     if (neg) {
       xi = -xi;
+      xll = -xll;
       xf = -xf;
     }
     if (unlikely(overflownInteger)) {
-      if (overflownUnsignedInteger) {
+      if (overflownLongLong) {
         obj->initReal(xf);
       } else {
-        if (neg) {
-          if (xui-1 == INT_MAX) {
-            obj->initInt(INT_MIN);
-          } else {
-            xf = xui;
-            xf = -xf;
-            obj->initReal(xf);
-          }
+        if (unlikely(xll == INT_MIN)) {
+          obj->initInt(INT_MIN);
         } else {
-          obj->initUint(xui);
+          obj->initInt64(xll);
         }
       }
     } else {
@@ -256,8 +251,8 @@
   doReal:
     if (likely(!overflownInteger)) {
       xf = xi;
-    } else if (!overflownUnsignedInteger) {
-      xf = xui;
+    } else if (!overflownLongLong) {
+      xf = xll;
     }
     scale = 0.1;
     while (1) {
@@ -586,6 +581,48 @@
   return obj;
 }
 
+Object *Lexer::getObj(Object *obj, const char *cmdA) {
+  char *p;
+  int c;
+  GBool comment;
+  int n;
+
+  // skip whitespace and comments
+  comment = gFalse;
+  const char *cmd1 = tokBuf;
+  *tokBuf = 0;
+  while (strcmp(cmdA, cmd1)) {
+    while (1) {
+      if ((c = getChar()) == EOF) {
+        return obj->initEOF();
+      }
+      if (comment) {
+        if (c == '\r' || c == '\n') {
+          comment = gFalse;
+        }
+      } else if (c == '%') {
+        comment = gTrue;
+      } else if (specialChars[c] != 1) {
+        break;
+      }
+    }
+    p = tokBuf;
+    *p++ = c;
+    n = 1;
+    while ((c = lookChar()) != EOF && specialChars[c] == 0) {
+      getChar();
+      if (++n == tokBufSize) {
+        break;
+      }
+      *p++ = c;
+    }
+    *p = '\0';
+  }
+  obj->initCmd(tokBuf);
+  
+  return obj;
+}
+
 void Lexer::skipToNextLine() {
   int c;
 
diff --git a/poppler/Lexer.h b/poppler/Lexer.h
index 284479d..d9c23dc 100644
--- a/poppler/Lexer.h
+++ b/poppler/Lexer.h
@@ -15,6 +15,8 @@
 //
 // Copyright (C) 2006, 2007, 2010 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2006 Krzysztof Kowalczyk <kkowalczyk@gmail.com>
+// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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 +57,7 @@
 
   // Get the next object from the input stream.
   Object *getObj(Object *obj, int objNum = -1);
+  Object *getObj(Object *obj, const char *cmdA);
 
   // Skip to the beginning of the next line in the input stream.
   void skipToNextLine();
@@ -67,12 +70,12 @@
     { return curStr.isStream() ? curStr.getStream() : (Stream *)NULL; }
 
   // Get current position in file.  This is only used for error
-  // messages, so it returns an int instead of a Guint.
-  int getPos()
-    { return curStr.isStream() ? (int)curStr.streamGetPos() : -1; }
+  // messages.
+  Goffset getPos()
+    { return curStr.isStream() ? curStr.streamGetPos() : -1; }
 
   // Set position in file.
-  void setPos(Guint pos, int dir = 0)
+  void setPos(Goffset pos, int dir = 0)
     { if (curStr.isStream()) curStr.streamSetPos(pos, dir); }
 
   // Returns true if <c> is a whitespace character.
diff --git a/poppler/Makefile.am b/poppler/Makefile.am
index 52fea4c..7451501 100644
--- a/poppler/Makefile.am
+++ b/poppler/Makefile.am
@@ -330,4 +330,5 @@
 	XpdfPluginAPI.cc
 
 EXTRA_DIST = gen-unicode-tables.py	\
-             GlobalParamsWin.cc
+             GlobalParamsWin.cc         \
+             PageLabelInfo_p.h
diff --git a/poppler/Object.cc b/poppler/Object.cc
index 1963b7f..d06bb39 100644
--- a/poppler/Object.cc
+++ b/poppler/Object.cc
@@ -14,6 +14,7 @@
 // under GPL version 2 or later
 //
 // Copyright (C) 2008, 2010, 2012 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
 //
 // 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
@@ -53,7 +54,7 @@
   "error",
   "eof",
   "none",
-  "unsigned integer"
+  "integer64"
 };
 
 #ifdef DEBUG_MEM
@@ -224,8 +225,8 @@
   case objNone:
     fprintf(f, "<none>");
     break;
-  case objUint:
-    fprintf(f, "%u", uintg);
+  case objInt64:
+    fprintf(f, "%lld", int64g);
     break;
   }
 }
diff --git a/poppler/Object.h b/poppler/Object.h
index c885d73..1b12354 100644
--- a/poppler/Object.h
+++ b/poppler/Object.h
@@ -18,6 +18,8 @@
 // Copyright (C) 2008, 2010 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2009 Jakub Wilk <ubanus@users.sf.net>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
+// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
 //
 // 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
@@ -47,10 +49,10 @@
         abort(); \
     }
 
-#define OBJECT_2TYPES_CHECK(wanted_type1, wanted_type2) \
-    if (unlikely(type != wanted_type1) && unlikely(type != wanted_type2)) { \
+#define OBJECT_3TYPES_CHECK(wanted_type1, wanted_type2, wanted_type3) \
+    if (unlikely(type != wanted_type1) && unlikely(type != wanted_type2) && unlikely(type != wanted_type3)) { \
         error(errInternal, 0, (char *) "Call to Object where the object was type {0:d}, " \
-                 "not the expected type {1:d} or {2:d}", type, wanted_type1, wanted_type2); \
+	      "not the expected type {1:d}, {2:d} or {3:d}", type, wanted_type1, wanted_type2, wanted_type3); \
         abort(); \
     }
 
@@ -94,7 +96,7 @@
   objNone,			// uninitialized object
 
   // poppler-only objects
-  objUint			// overflown integer that still fits in a unsigned integer
+  objInt64			// integer with at least 64-bits
 };
 
 #define numObjTypes 15		// total number of object types
@@ -143,8 +145,8 @@
     { initObj(objError); return this; }
   Object *initEOF()
     { initObj(objEOF); return this; }
-  Object *initUint(unsigned int uintgA)
-    { initObj(objUint); uintg = uintgA; return this; }
+  Object *initInt64(long long int64gA)
+    { initObj(objInt64); int64g = int64gA; return this; }
 
   // Copy an object.
   Object *copy(Object *obj);
@@ -165,7 +167,7 @@
   GBool isBool() { return type == objBool; }
   GBool isInt() { return type == objInt; }
   GBool isReal() { return type == objReal; }
-  GBool isNum() { return type == objInt || type == objReal; }
+  GBool isNum() { return type == objInt || type == objReal || type == objInt64; }
   GBool isString() { return type == objString; }
   GBool isName() { return type == objName; }
   GBool isNull() { return type == objNull; }
@@ -177,7 +179,7 @@
   GBool isError() { return type == objError; }
   GBool isEOF() { return type == objEOF; }
   GBool isNone() { return type == objNone; }
-  GBool isUint() { return type == objUint; }
+  GBool isInt64() { return type == objInt64; }
 
   // Special type checking.
   GBool isName(const char *nameA)
@@ -191,7 +193,11 @@
   GBool getBool() { OBJECT_TYPE_CHECK(objBool); return booln; }
   int getInt() { OBJECT_TYPE_CHECK(objInt); return intg; }
   double getReal() { OBJECT_TYPE_CHECK(objReal); return real; }
-  double getNum() { OBJECT_2TYPES_CHECK(objInt, objReal); return type == objInt ? (double)intg : real; }
+
+  // Note: integers larger than 2^53 can not be exactly represented by a double.
+  // Where the exact value of integers up to 2^63 is required, use isInt64()/getInt64().
+  double getNum() { OBJECT_3TYPES_CHECK(objInt, objInt64, objReal);
+    return type == objInt ? (double)intg : type == objInt64 ? (double)int64g : real; }
   GooString *getString() { OBJECT_TYPE_CHECK(objString); return string; }
   char *getName() { OBJECT_TYPE_CHECK(objName); return name; }
   Array *getArray() { OBJECT_TYPE_CHECK(objArray); return array; }
@@ -201,13 +207,13 @@
   int getRefNum() { OBJECT_TYPE_CHECK(objRef); return ref.num; }
   int getRefGen() { OBJECT_TYPE_CHECK(objRef); return ref.gen; }
   char *getCmd() { OBJECT_TYPE_CHECK(objCmd); return cmd; }
-  unsigned int getUint() { OBJECT_TYPE_CHECK(objUint); return uintg; }
+  long long getInt64() { OBJECT_TYPE_CHECK(objInt64); return int64g; }
 
   // Array accessors.
   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.
@@ -229,8 +235,8 @@
   int streamGetChars(int nChars, Guchar *buffer);
   int streamLookChar();
   char *streamGetLine(char *buf, int size);
-  Guint streamGetPos();
-  void streamSetPos(Guint pos, int dir = 0);
+  Goffset streamGetPos();
+  void streamSetPos(Goffset pos, int dir = 0);
   Dict *streamGetDict();
 
   // Output.
@@ -246,7 +252,7 @@
   union {			// value for each type:
     GBool booln;		//   boolean
     int intg;			//   integer
-    unsigned int uintg;		//   unsigned integer
+    long long int64g;           //   64-bit integer
     double real;		//   real
     GooString *string;		//   string
     char *name;			//   name
@@ -278,8 +284,8 @@
 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); }
@@ -350,10 +356,10 @@
 inline char *Object::streamGetLine(char *buf, int size)
   { OBJECT_TYPE_CHECK(objStream); return stream->getLine(buf, size); }
 
-inline Guint Object::streamGetPos()
+inline Goffset Object::streamGetPos()
   { OBJECT_TYPE_CHECK(objStream); return stream->getPos(); }
 
-inline void Object::streamSetPos(Guint pos, int dir)
+inline void Object::streamSetPos(Goffset pos, int dir)
   { OBJECT_TYPE_CHECK(objStream); stream->setPos(pos, dir); }
 
 inline Dict *Object::streamGetDict()
diff --git a/poppler/OutputDev.h b/poppler/OutputDev.h
index f540d57..abccffe 100644
--- a/poppler/OutputDev.h
+++ b/poppler/OutputDev.h
@@ -17,7 +17,7 @@
 // Copyright (C) 2006 Thorkild Stray <thorkild@ifi.uio.no>
 // Copyright (C) 2007 Jeff Muizelaar <jeff@infidigm.net>
 // Copyright (C) 2007, 2011 Adrian Johnson <ajohnson@redneon.com>
-// Copyright (C) 2009-2012 Thomas Freitag <Thomas.Freitag@alfa.de>
+// Copyright (C) 2009-2013 Thomas Freitag <Thomas.Freitag@alfa.de>
 // Copyright (C) 2009, 2011 Carlos Garcia Campos <carlosgc@gnome.org>
 // Copyright (C) 2009, 2012 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger@googlemail.com>
@@ -137,7 +137,7 @@
     { 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() {}
@@ -243,7 +243,6 @@
 			       CharCode /*code*/, Unicode * /*u*/, int /*uLen*/);
   virtual void endType3Char(GfxState * /*state*/) {}
   virtual void beginTextObject(GfxState * /*state*/) {}
-  virtual GBool deviceHasTextClip(GfxState * /*state*/) { return gFalse; }
   virtual void endTextObject(GfxState * /*state*/) {}
   virtual void incCharCount(int /*nChars*/) {}
   virtual void beginActualText(GfxState * /*state*/, GooString * /*text*/ ) {}
diff --git a/poppler/PDFDoc.cc b/poppler/PDFDoc.cc
index e8c5c09..9cfbc7a 100644
--- a/poppler/PDFDoc.cc
+++ b/poppler/PDFDoc.cc
@@ -26,8 +26,10 @@
 // Copyright (C) 2010 Ilya Gorenbein <igorenbein@finjan.com>
 // Copyright (C) 2010 Srinivas Adicherla <srinivas.adicherla@geodesic.com>
 // Copyright (C) 2010 Philip Lorenz <lorenzph+freedesktop@gmail.com>
-// Copyright (C) 2011, 2012 Thomas Freitag <Thomas.Freitag@alfa.de>
+// Copyright (C) 2011-2013 Thomas Freitag <Thomas.Freitag@alfa.de>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
+// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
+// Copyright (C) 2013 Adam Reichold <adamreichold@myopera.com>
 //
 // 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
@@ -54,6 +56,7 @@
 #include <sys/stat.h>
 #include "goo/gstrtod.h"
 #include "goo/GooString.h"
+#include "goo/gfile.h"
 #include "poppler-config.h"
 #include "GlobalParams.h"
 #include "Page.h"
@@ -75,6 +78,12 @@
 #include "PDFDoc.h"
 #include "Hints.h"
 
+#if MULTITHREADED
+#  define pdfdocLocker()   MutexLocker locker(&mutex)
+#else
+#  define pdfdocLocker()
+#endif
+
 //------------------------------------------------------------------------
 
 #define headerSearchSize 1024	// read this many bytes at beginning of
@@ -94,6 +103,9 @@
 
 void PDFDoc::init()
 {
+#if MULTITHREADED
+  gInitMutex(&mutex);
+#endif
   ok = gFalse;
   errCode = errNone;
   fileName = NULL;
@@ -106,7 +118,7 @@
 #ifndef DISABLE_OUTLINE
   outline = NULL;
 #endif
-  startXRefPos = ~(Guint)0;
+  startXRefPos = -1;
   secHdlr = NULL;
   pageCache = NULL;
 }
@@ -119,7 +131,6 @@
 PDFDoc::PDFDoc(GooString *fileNameA, GooString *ownerPassword,
 	       GooString *userPassword, void *guiDataA) {
   Object obj;
-  int size = 0;
 #ifdef _WIN32
   int n, i;
 #endif
@@ -137,17 +148,8 @@
   fileNameU[n] = L'\0';
 #endif
 
-  struct stat buf;
-  if (stat(fileName->getCString(), &buf) == 0) {
-     size = buf.st_size;
-  }
-
   // try to open file
-#ifdef VMS
-  file = fopen(fileName->getCString(), "rb", "ctx=stm");
-#else
-  file = fopen(fileName->getCString(), "rb");
-#endif
+  file = GooFile::open(fileName);
   if (file == NULL) {
     // fopen() has failed.
     // Keep a copy of the errno returned by fopen so that it can be 
@@ -160,7 +162,7 @@
 
   // create stream
   obj.initNull();
-  str = new FileStream(file, 0, gFalse, size, &obj);
+  str = new FileStream(file, 0, gFalse, file->size(), &obj);
 
   ok = setup(ownerPassword, userPassword);
 }
@@ -184,26 +186,17 @@
     fileNameU[i] = fileNameA[i];
   }
   fileNameU[fileNameLen] = L'\0';
-
-
+  
   // try to open file
   // NB: _wfopen is only available in NT
-  struct _stat buf;
-  int size = 0;
   version.dwOSVersionInfoSize = sizeof(version);
   GetVersionEx(&version);
   if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) {
-    if (_wstat(fileNameU, &buf) == 0) {
-      size = buf.st_size;
-    }
-    file = _wfopen(fileNameU, L"rb");
+    file = GooFile::open(fileNameU);
   } else {
-    if (_stat(fileName->getCString(), &buf) == 0) {
-      size = buf.st_size;
-    }
-    file = fopen(fileName->getCString(), "rb");
+    file = GooFile::open(fileName);
   }
-  if (!size || !file) {
+  if (!file) {
     error(errIO, -1, "Couldn't open file '{0:t}'", fileName);
     errCode = errOpenFile;
     return;
@@ -211,7 +204,7 @@
 
   // create stream
   obj.initNull();
-  str = new FileStream(file, 0, gFalse, size, &obj);
+  str = new FileStream(file, 0, gFalse, file->size(), &obj);
 
   ok = setup(ownerPassword, userPassword);
 }
@@ -246,6 +239,7 @@
 }
 
 GBool PDFDoc::setup(GooString *ownerPassword, GooString *userPassword) {
+  pdfdocLocker();
   str->setPos(0, -1);
   if (str->getPos() < 0)
   {
@@ -332,7 +326,7 @@
     delete str;
   }
   if (file) {
-    fclose(file);
+    delete file;
   }
   if (fileName) {
     delete fileName;
@@ -342,6 +336,9 @@
     gfree(fileNameU);
   }
 #endif
+#if MULTITHREADED
+  gDestroyMutex(&mutex);
+#endif
 }
 
 
@@ -349,7 +346,7 @@
 GBool PDFDoc::checkFooter() {
   // we look in the last 1024 chars because Adobe does the same
   char *eof = new char[1025];
-  int pos = str->getPos();
+  Goffset pos = str->getPos();
   str->setPos(1024, -1);
   int i, ch;
   for (i = 0; i < 1024; i++)
@@ -455,7 +452,7 @@
 			 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 +461,7 @@
     getPage(page)->display(out, hDPI, vDPI,
 				    rotate, useMediaBox, crop, printing,
 				    abortCheckCbk, abortCheckCbkData,
-				    annotDisplayDecideCbk, annotDisplayDecideCbkData);
+				    annotDisplayDecideCbk, annotDisplayDecideCbkData, copyXRef);
 
 }
 
@@ -491,14 +488,14 @@
 			      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) {
@@ -747,7 +744,7 @@
   objectsCount++;
   page.free();
 
-  Guint uxrefOffset = outStr->getPos();
+  Goffset uxrefOffset = outStr->getPos();
   Ref ref;
   ref.num = rootNum;
   ref.gen = 0;
@@ -826,11 +823,13 @@
 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 +839,13 @@
   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 +854,7 @@
 
   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,8 +866,8 @@
       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);
-        Guint offset = writeObjectHeader(&ref, outStr);
+        xref->fetch(ref.num, ref.gen, &obj1, 1);
+        Goffset offset = writeObjectHeader(&ref, outStr);
         writeObject(&obj1, outStr, fileKey, encAlgorithm, keyLength, ref.num, ref.gen);
         writeObjectFooter(outStr);
         uxref->add(ref.num, ref.gen, offset, gTrue);
@@ -875,12 +877,13 @@
       }
     }
   }
+  xref->unlock();
   if (uxref->getNumObjects() == 0) { //we have nothing to update
     delete uxref;
     return;
   }
 
-  Guint uxrefOffset = outStr->getPos();
+  Goffset uxrefOffset = outStr->getPos();
   int numobjects = xref->getNumObjects();
   const char *fileNameA = fileName ? fileName->getCString() : NULL;
   Ref rootRef, uxrefStreamRef;
@@ -922,6 +925,7 @@
   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,8 +945,8 @@
     } else if (type == xrefEntryUncompressed){ 
       ref.num = i;
       ref.gen = xref->getEntry(i)->gen;
-      xref->fetch(ref.num, ref.gen, &obj1);
-      Guint offset = writeObjectHeader(&ref, outStr);
+      xref->fetch(ref.num, ref.gen, &obj1, 1);
+      Goffset offset = writeObjectHeader(&ref, outStr);
       // Write unencrypted objects in unencrypted form
       if (xref->getEntry(i)->getFlag(XRefEntry::Unencrypted)) {
         writeObject(&obj1, outStr, NULL, cryptRC4, 0, 0, 0);
@@ -955,15 +959,16 @@
     } else if (type == xrefEntryCompressed) {
       ref.num = i;
       ref.gen = 0; //compressed entries have gen == 0
-      xref->fetch(ref.num, ref.gen, &obj1);
-      Guint offset = writeObjectHeader(&ref, outStr);
+      xref->fetch(ref.num, ref.gen, &obj1, 1);
+      Goffset offset = writeObjectHeader(&ref, outStr);
       writeObject(&obj1, outStr, fileKey, encAlgorithm, keyLength, ref.num, ref.gen);
       writeObjectFooter(outStr);
       uxref->add(ref.num, ref.gen, offset, gTrue);
       obj1.free();
     }
   }
-  Guint uxrefOffset = outStr->getPos();
+  xref->unlock();
+  Goffset uxrefOffset = outStr->getPos();
   writeXRefTableTrailer(uxrefOffset, uxref, gTrue /* write all entries */,
                         uxref->getNumObjects(), outStr, gFalse /* complete rewrite */);
   delete uxref;
@@ -999,17 +1004,21 @@
 {
   Object obj1;
   str->getDict()->lookup("Length", &obj1);
-  if (!obj1.isInt()) {
+  if (!obj1.isInt() && !obj1.isInt64()) {
     error (errSyntaxError, -1, "PDFDoc::writeRawStream, no Length in stream dict");
     return;
   }
 
-  const int length = obj1.getInt();
+  Goffset length;
+  if (obj1.isInt())
+    length = obj1.getInt();
+  else
+    length = obj1.getInt64();
   obj1.free();
 
   outStr->printf("stream\r\n");
   str->unfilteredReset();
-  for (int i=0; i<length; i++) {
+  for (Goffset i = 0; i < length; i++) {
     int c = str->getUnfilteredChar();
     outStr->printf("%c", c);  
   }
@@ -1073,9 +1082,9 @@
   delete sEnc;
 }
 
-Guint PDFDoc::writeObjectHeader (Ref *ref, OutStream* outStr)
+Goffset PDFDoc::writeObjectHeader (Ref *ref, OutStream* outStr)
 {
-  Guint offset = outStr->getPos();
+  Goffset offset = outStr->getPos();
   outStr->printf("%i %i obj ", ref->num, ref->gen);
   return offset;
 }
@@ -1085,7 +1094,7 @@
 {
   Array *array;
   Object obj1;
-  int tmp;
+  Goffset tmp;
 
   switch (obj->getType()) {
     case objBool:
@@ -1094,8 +1103,8 @@
     case objInt:
       outStr->printf("%i ", obj->getInt());
       break;
-    case objUint:
-      outStr->printf("%u ", obj->getUint());
+    case objInt64:
+      outStr->printf("%lli ", obj->getInt64());
       break;
     case objReal:
     {
@@ -1135,12 +1144,42 @@
         //We can't modify stream with the current implementation (no write functions in Stream API)
         // => the only type of streams which that have been modified are internal streams (=strWeird)
         Stream *stream = obj->getStream();
-        if (stream->getKind() == strWeird) {
+        if (stream->getKind() == strWeird || stream->getKind() == strCrypt) {
           //we write the stream unencoded => TODO: write stream encoder
 
           // Encrypt stream
           EncryptStream *encStream = NULL;
-          if (fileKey) {
+          GBool removeFilter = gTrue;
+          if (stream->getKind() == strWeird && fileKey) {
+            Object filter;
+            stream->getDict()->lookup("Filter", &filter);
+            if (!filter.isName("Crypt")) {
+              if (filter.isArray()) {
+                for (int i = 0; i < filter.arrayGetLength(); i++) {
+                  Object filterEle;
+                  filter.arrayGet(i, &filterEle);
+                  if (filterEle.isName("Crypt")) {
+                    filterEle.free();
+                    removeFilter = gFalse;
+                    break;
+                  }
+                  filterEle.free();
+                }
+                if (removeFilter) {
+                  encStream = new EncryptStream(stream, fileKey, encAlgorithm, keyLength, objNum, objGen);
+                  encStream->setAutoDelete(gFalse);
+                  stream = encStream;
+                }
+              } else {
+                encStream = new EncryptStream(stream, fileKey, encAlgorithm, keyLength, objNum, objGen);
+                encStream->setAutoDelete(gFalse);
+                stream = encStream;
+              }
+            } else {
+              removeFilter = gFalse;
+            }
+            filter.free();
+          } else if (fileKey != NULL) { // Encrypt stream
             encStream = new EncryptStream(stream, fileKey, encAlgorithm, keyLength, objNum, objGen);
             encStream->setAutoDelete(gFalse);
             stream = encStream;
@@ -1152,11 +1191,13 @@
           for (int c=stream->getChar(); c!=EOF; c=stream->getChar()) {
             tmp++;
           }
-          obj1.initInt(tmp);
+          obj1.initInt64(tmp);
           stream->getDict()->set("Length", &obj1);
 
           //Remove Stream encoding
-          stream->getDict()->remove("Filter");
+          if (removeFilter) {
+            stream->getDict()->remove("Filter");
+          }
           stream->getDict()->remove("DecodeParms");
 
           writeDictionnary (stream->getDict(),outStr, xRef, numOffset, fileKey, encAlgorithm, keyLength, objNum, objGen);
@@ -1169,10 +1210,10 @@
           if (fs) {
             BaseStream *bs = fs->getBaseStream();
             if (bs) {
-              Guint streamEnd;
+              Goffset streamEnd;
                 if (xRef->getStreamEnd(bs->getStart(), &streamEnd)) {
                   Object val;
-                  val.initInt(streamEnd - bs->getStart());
+                  val.initInt64(streamEnd - bs->getStart());
                   stream->getDict()->set("Length", &val);
                 }
               }
@@ -1208,8 +1249,8 @@
   outStr->printf("endobj\r\n");
 }
 
-Dict *PDFDoc::createTrailerDict(int uxrefSize, GBool incrUpdate, Guint startxRef,
-                                Ref *root, XRef *xRef, const char *fileName, Guint fileSize)
+Dict *PDFDoc::createTrailerDict(int uxrefSize, GBool incrUpdate, Goffset startxRef,
+                                Ref *root, XRef *xRef, const char *fileName, Goffset fileSize)
 {
   Dict *trailerDict = new Dict(xRef);
   Object obj1;
@@ -1230,7 +1271,7 @@
   if (fileName)
     message.append(fileName);
 
-  sprintf(buffer, "%i", fileSize);
+  sprintf(buffer, "%lli", (long long)fileSize);
   message.append(buffer);
 
   //info dict -- only use text string
@@ -1294,7 +1335,7 @@
   trailerDict->set("Root", &obj1);
 
   if (incrUpdate) { 
-    obj1.initInt(startxRef);
+    obj1.initInt64(startxRef);
     trailerDict->set("Prev", &obj1);
   }
   
@@ -1308,7 +1349,7 @@
   return trailerDict;
 }
 
-void PDFDoc::writeXRefTableTrailer(Dict *trailerDict, XRef *uxref, GBool writeAllEntries, Guint uxrefOffset, OutStream* outStr, XRef *xRef)
+void PDFDoc::writeXRefTableTrailer(Dict *trailerDict, XRef *uxref, GBool writeAllEntries, Goffset uxrefOffset, OutStream* outStr, XRef *xRef)
 {
   uxref->writeTableToFile( outStr, writeAllEntries );
   outStr->printf( "trailer\r\n");
@@ -1318,7 +1359,7 @@
   outStr->printf( "%%%%EOF\r\n");
 }
 
-void PDFDoc::writeXRefStreamTrailer (Dict *trailerDict, XRef *uxref, Ref *uxrefStreamRef, Guint uxrefOffset, OutStream* outStr, XRef *xRef)
+void PDFDoc::writeXRefStreamTrailer (Dict *trailerDict, XRef *uxref, Ref *uxrefStreamRef, Goffset uxrefOffset, OutStream* outStr, XRef *xRef)
 {
   GooString stmData;
 
@@ -1339,7 +1380,7 @@
   outStr->printf( "%%%%EOF\r\n");
 }
 
-void PDFDoc::writeXRefTableTrailer(Guint uxrefOffset, XRef *uxref, GBool writeAllEntries,
+void PDFDoc::writeXRefTableTrailer(Goffset uxrefOffset, XRef *uxref, GBool writeAllEntries,
                                    int uxrefSize, OutStream* outStr, GBool incrUpdate)
 {
   const char *fileNameA = fileName ? fileName->getCString() : NULL;
@@ -1542,7 +1583,7 @@
       ref.gen = xRef->getEntry(n)->gen;
       objectsCount++;
       getXRef()->fetch(ref.num - numOffset, ref.gen, &obj);
-      Guint offset = writeObjectHeader(&ref, outStr);
+      Goffset offset = writeObjectHeader(&ref, outStr);
       if (combine) {
         writeObject(&obj, outStr, getXRef(), numOffset, NULL, cryptRC4, 0, 0, 0);
       } else if (xRef->getEntry(n)->getFlag(XRefEntry::Unencrypted)) {
@@ -1562,6 +1603,7 @@
 Outline *PDFDoc::getOutline()
 {
   if (!outline) {
+    pdfdocLocker();
     // read outline
     outline = new Outline(catalog->getOutline(), xref);
   }
@@ -1579,14 +1621,14 @@
   return doc;
 }
 
-Guint PDFDoc::strToUnsigned(char *s) {
-  Guint x, d;
+long long PDFDoc::strToLongLong(char *s) {
+  long long x, d;
   char *p;
 
   x = 0;
   for (p = s; *p && isdigit(*p & 0xff); ++p) {
     d = *p - '0';
-    if (x > (UINT_MAX - d) / 10) {
+    if (x > (LLONG_MAX - d) / 10) {
       break;
     }
     x = 10 * x + d;
@@ -1595,9 +1637,9 @@
 }
 
 // Read the 'startxref' position.
-Guint PDFDoc::getStartXRef()
+Goffset PDFDoc::getStartXRef()
 {
-  if (startXRefPos == ~(Guint)0) {
+  if (startXRefPos == -1) {
 
     if (isLinearized()) {
       char buf[linearizationSearchSize+1];
@@ -1648,7 +1690,7 @@
         startXRefPos = 0;
       } else {
         for (p = &buf[i+9]; isspace(*p); ++p) ;
-        startXRefPos =  strToUnsigned(p);
+        startXRefPos =  strToLongLong(p);
       }
     }
 
@@ -1657,7 +1699,7 @@
   return startXRefPos;
 }
 
-Guint PDFDoc::getMainXRefEntriesOffset()
+Goffset PDFDoc::getMainXRefEntriesOffset()
 {
   Guint mainXRefEntriesOffset = 0;
 
@@ -1720,6 +1762,7 @@
   if ((page < 1) || page > getNumPages()) return NULL;
 
   if (isLinearized()) {
+    pdfdocLocker();
     if (!pageCache) {
       pageCache = (Page **) gmallocn(getNumPages(), sizeof(Page *));
       for (int i = 0; i < getNumPages(); i++) {
diff --git a/poppler/PDFDoc.h b/poppler/PDFDoc.h
index 4562346..da9bf5b 100644
--- a/poppler/PDFDoc.h
+++ b/poppler/PDFDoc.h
@@ -22,8 +22,10 @@
 // Copyright (C) 2009 Kovid Goyal <kovid@kovidgoyal.net>
 // Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
 // Copyright (C) 2010 Srinivas Adicherla <srinivas.adicherla@geodesic.com>
-// Copyright (C) 2011, 2012 Thomas Freitag <Thomas.Freitag@alfa.de>
+// Copyright (C) 2011, 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
+// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
+// Copyright (C) 2013 Adam Reichold <adamreichold@myopera.com>
 //
 // 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
@@ -37,7 +39,9 @@
 #pragma interface
 #endif
 
+#include "poppler-config.h"
 #include <stdio.h>
+#include "goo/GooMutex.h"
 #include "XRef.h"
 #include "Catalog.h"
 #include "Page.h"
@@ -46,6 +50,7 @@
 #include "Stream.h"
 
 class GooString;
+class GooFile;
 class BaseStream;
 class OutputDev;
 class Links;
@@ -146,7 +151,7 @@
 		   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 +170,7 @@
 			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.
@@ -249,12 +254,12 @@
   static void writeHeader(OutStream *outStr, int major, int minor);
 
   // Ownership goes to the caller
-  static Dict *createTrailerDict (int uxrefSize, GBool incrUpdate, Guint startxRef,
-                                  Ref *root, XRef *xRef, const char *fileName, Guint fileSize);
+  static Dict *createTrailerDict (int uxrefSize, GBool incrUpdate, Goffset startxRef,
+                                  Ref *root, XRef *xRef, const char *fileName, Goffset fileSize);
   static void writeXRefTableTrailer (Dict *trailerDict, XRef *uxref, GBool writeAllEntries,
-                                     Guint uxrefOffset, OutStream* outStr, XRef *xRef);
+                                     Goffset uxrefOffset, OutStream* outStr, XRef *xRef);
   static void writeXRefStreamTrailer (Dict *trailerDict, XRef *uxref, Ref *uxrefStreamRef,
-                                      Guint uxrefOffset, OutStream* outStr, XRef *xRef);
+                                      Goffset uxrefOffset, OutStream* outStr, XRef *xRef);
 
 private:
   // insert referenced objects in XRef
@@ -264,7 +269,7 @@
                                 CryptAlgorithm encAlgorithm, int keyLength, int objNum, int objGen);
 
   // Write object header to current file stream and return its offset
-  static Guint writeObjectHeader (Ref *ref, OutStream* outStr);
+  static Goffset writeObjectHeader (Ref *ref, OutStream* outStr);
   static void writeObjectFooter (OutStream* outStr);
 
   void writeObject (Object *obj, OutStream* outStr, Guchar *fileKey, CryptAlgorithm encAlgorithm,
@@ -275,7 +280,7 @@
   { writeDictionnary(dict, outStr, getXRef(), 0, fileKey, encAlgorithm, keyLength, objNum, objGen); }
   static void writeStream (Stream* str, OutStream* outStr);
   static void writeRawStream (Stream* str, OutStream* outStr);
-  void writeXRefTableTrailer (Guint uxrefOffset, XRef *uxref, GBool writeAllEntries,
+  void writeXRefTableTrailer (Goffset uxrefOffset, XRef *uxref, GBool writeAllEntries,
                               int uxrefSize, OutStream* outStr, GBool incrUpdate);
   static void writeString (GooString* s, OutStream* outStr, Guchar *fileKey,
                            CryptAlgorithm encAlgorithm, int keyLength, int objNum, int objGen);
@@ -294,17 +299,17 @@
   void checkHeader();
   GBool checkEncryption(GooString *ownerPassword, GooString *userPassword);
   // Get the offset of the start xref table.
-  Guint getStartXRef();
+  Goffset getStartXRef();
   // Get the offset of the entries in the main XRef table of a
   // linearized document (0 for non linearized documents).
-  Guint getMainXRefEntriesOffset();
-  Guint strToUnsigned(char *s);
+  Goffset getMainXRefEntriesOffset();
+  long long strToLongLong(char *s);
 
   GooString *fileName;
 #ifdef _WIN32
   wchar_t *fileNameU;
 #endif
-  FILE *file;
+  GooFile *file;
   BaseStream *str;
   void *guiData;
   int pdfMajorVersion;
@@ -325,7 +330,10 @@
   //then the POSIX errno will be here.
   int fopenErrno;
 
-  Guint startXRefPos;		// offset of last xref table
+  Goffset 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@kde.org>
 // Copyright (C) 2008, 2009 Koji Otani <sho@bbr.jp>
 // Copyright (C) 2008, 2010 Hib Eris <hib@hiberis.nl>
-// Copyright (C) 2009-2012 Thomas Freitag <Thomas.Freitag@alfa.de>
+// Copyright (C) 2009-2013 Thomas Freitag <Thomas.Freitag@alfa.de>
 // Copyright (C) 2009 Till Kamppeter <till.kamppeter@gmail.com>
 // Copyright (C) 2009 Carlos Garcia Campos <carlosgc@gnome.org>
 // Copyright (C) 2009, 2011, 2012 William Bader <williambader@hotmail.com>
@@ -3085,7 +3085,7 @@
     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 @@
 #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 @@
   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 @@
     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..f9dc63c 100644
--- a/poppler/PSOutputDev.h
+++ b/poppler/PSOutputDev.h
@@ -17,7 +17,7 @@
 // Copyright (C) 2005 Kristian Høgsberg <krh@redhat.com>
 // Copyright (C) 2006-2008, 2012 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2007 Brad Hards <bradh@kde.org>
-// Copyright (C) 2009-2012 Thomas Freitag <Thomas.Freitag@alfa.de>
+// Copyright (C) 2009-2013 Thomas Freitag <Thomas.Freitag@alfa.de>
 // Copyright (C) 2009 Till Kamppeter <till.kamppeter@gmail.com>
 // Copyright (C) 2009 Carlos Garcia Campos <carlosgc@gnome.org>
 // Copyright (C) 2009, 2011 William Bader <williambader@hotmail.com>
@@ -186,7 +186,7 @@
 			       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();
@@ -248,7 +248,6 @@
   //----- text drawing
   virtual void drawString(GfxState *state, GooString *s);
   virtual void beginTextObject(GfxState *state);
-  virtual GBool deviceHasTextClip(GfxState *state) { return haveTextClip; }
   virtual void endTextObject(GfxState *state);
 
   //----- image drawing
diff --git a/poppler/Page.cc b/poppler/Page.cc
index 8c2065b..a587b9b 100644
--- a/poppler/Page.cc
+++ b/poppler/Page.cc
@@ -15,7 +15,7 @@
 //
 // Copyright (C) 2005 Kristian Høgsberg <krh@redhat.com>
 // Copyright (C) 2005 Jeff Muizelaar <jeff@infidigm.net>
-// Copyright (C) 2005-2012 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2005-2013 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2006-2008 Pino Toscano <pino@kde.org>
 // Copyright (C) 2006 Nickolay V. Shmyrev <nshmyrev@yandex.ru>
 // Copyright (C) 2006 Scott Turner <scotty1024@mac.com>
@@ -25,6 +25,7 @@
 // Copyright (C) 2008 Brad Hards <bradh@kde.org>
 // Copyright (C) 2008 Ilya Gorenbein <igorenbein@finjan.com>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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,11 @@
 #include "Catalog.h"
 #include "Form.h"
 
+#if MULTITHREADED
+#  define pageLocker()   MutexLocker locker(&mutex)
+#else
+#  define pageLocker()
+#endif
 //------------------------------------------------------------------------
 // PDFRectangle
 //------------------------------------------------------------------------
@@ -257,6 +263,9 @@
 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,12 +352,51 @@
   trans.free();
   thumb.free();
   actions.free();
+#if MULTITHREADED
+  gDestroyMutex(&mutex);
+#endif
 }
 
-Annots *Page::getAnnots() {
+Dict *Page::getResourceDict() { 
+  return attrs->getResourceDict();
+}
+
+Dict *Page::getResourceDictCopy(XRef *xrefA) { 
+  pageLocker();
+  return attrs->getResourceDict()->copy(xrefA);
+}
+
+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(XRef *xrefA) {
   if (!annots) {
     Object obj;
-    annots = new Annots(doc, num, getAnnots(&obj));
+    annots = new Annots(doc, num, getAnnots(&obj, (xrefA == NULL) ? xref : xrefA));
     obj.free();
   }
 
@@ -363,6 +411,7 @@
   // 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)
+  pageLocker();
   getAnnots();
 
   if (annotsObj.isNull()) {
@@ -398,6 +447,7 @@
   Ref annotRef = annot->getRef();
   Object annArray;
 
+  pageLocker();
   getAnnots(&annArray);
   if (annArray.isArray()) {
     int idx = -1;
@@ -445,10 +495,11 @@
 		   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 +507,7 @@
 		     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 +537,7 @@
   }
   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 +549,8 @@
 			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 +563,18 @@
 			   annotDisplayDecideCbk, annotDisplayDecideCbkData)) {
     return;
   }
+  pageLocker();
+  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 +605,10 @@
   }
 
   delete gfx;
+  if (copyXRef) {
+    replaceXRef(doc->getXRef());
+    delete localXRef;
+  }
 }
 
 void Page::display(Gfx *gfx) {
@@ -576,6 +637,7 @@
   GfxImageColorMap *colorMap;
 
   /* Get stream dict */
+  pageLocker();
   thumb.fetch(xref, &fetched_thumb);
   if (!fetched_thumb.isStream()) {
     fetched_thumb.free();
diff --git a/poppler/Page.h b/poppler/Page.h
index a6098ed..1c9d0a9 100644
--- a/poppler/Page.h
+++ b/poppler/Page.h
@@ -21,6 +21,7 @@
 // Copyright (C) 2008 Iñigo Martínez <inigomartinez@gmail.com>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
 // Copyright (C) 2012 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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 @@
 	? 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();
@@ -169,10 +174,11 @@
   Ref getRef() { return pageRef; }
 
   // Get resource dictionary.
-  Dict *getResourceDict() { return attrs->getResourceDict(); }
+  Dict *getResourceDict();
+  Dict *getResourceDictCopy(XRef *xrefA);
 
   // Get annotations array.
-  Object *getAnnots(Object *obj) { return annotsObj.fetch(xref, obj); }
+  Object *getAnnots(Object *obj, XRef *xrefA = NULL) { return annotsObj.fetch((xrefA == NULL) ? xref : xrefA, obj); }
   // Add a new annotation to the page
   void addAnnot(Annot *annot);
   // Remove an existing annotation from the page
@@ -182,7 +188,7 @@
   Links *getLinks();
 
   // Return a list of annots. It will be valid until the page is destroyed
-  Annots *getAnnots();
+  Annots *getAnnots(XRef *xrefA = NULL);
 
   // Get contents.
   Object *getContents(Object *obj) { return contents.fetch(xref, obj); }
@@ -210,7 +216,7 @@
 		 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 +225,8 @@
 	       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 +236,8 @@
 		    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 +253,8 @@
 		     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 +270,9 @@
   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/PageLabelInfo.cc b/poppler/PageLabelInfo.cc
index 7a42299..3153377 100644
--- a/poppler/PageLabelInfo.cc
+++ b/poppler/PageLabelInfo.cc
@@ -19,138 +19,7 @@
 #include <assert.h>
 
 #include "PageLabelInfo.h"
-
-/* http://mathworld.wolfram.com/RomanNumerals.html */
-
-static int fromRoman(const char *buffer) {
-  int digit_value, prev_digit_value, value;
-  int i;
-
-  prev_digit_value = INT_MAX;
-  value = 0;
-  for (i = 0; buffer[i] != '\0'; i++) {
-    switch (buffer[i]) {
-    case 'm':
-    case 'M':
-      digit_value = 1000;
-      break;
-    case 'd':
-    case 'D':
-      digit_value = 500;
-      break;
-    case 'c':
-    case 'C':
-      digit_value = 100;
-      break;
-    case 'l':
-    case 'L':
-      digit_value = 50;
-      break;
-    case 'x':
-    case 'X':
-      digit_value = 10;
-      break;
-    case 'v':
-    case 'V':
-      digit_value = 5;
-      break;
-    case 'i':
-    case 'I':
-      digit_value = 1;
-      break;
-    default:
-      return -1;
-    }
-
-    if (digit_value <= prev_digit_value)
-      value += digit_value;
-    else
-      value += digit_value - prev_digit_value * 2;
-    prev_digit_value = digit_value;
-  }
-
-  return value;
-}
-
-static void toRoman(int number, GooString *str, GBool uppercase) {
-  static const char uppercaseNumerals[] = "IVXLCDM";
-  static const char lowercaseNumerals[] = "ivxlcdm";
-  int divisor;
-  int i, j, k;
-  const char *wh;
-
-  if (uppercase)
-    wh = uppercaseNumerals;
-  else
-    wh = lowercaseNumerals;
-
-  divisor = 1000;
-  for (k = 3; k >= 0; k--) {
-    i = number / divisor;
-    number = number % divisor;
-
-    switch (i) {
-    case 0:
-      break;
-    case 5:
-      str->append(wh[2 * k + 1]);
-      break;
-    case 9:
-      str->append(wh[2 * k + 0]);
-      str->append(wh[ 2 * k + 2]);
-      break;
-    case 4:
-      str->append(wh[2 * k + 0]);
-      str->append(wh[2 * k + 1]);
-      break;
-    default:
-      if (i > 5) {
-       str->append(wh[2 * k + 1]);
-       i -= 5;
-      }
-      for (j = 0; j < i; j++) {
-       str->append(wh[2 * k + 0]);
-      }
-    }
-       
-    divisor = divisor / 10;
-  }
-}
-
-static int fromLatin(const char *buffer)
-{
-  int count;
-  const char *p;
-
-  for (p = buffer; *p; p++) {
-    if (*p != buffer[0])
-      return -1;
-  }
-
-  count = p - buffer;
-  if (buffer[0] >= 'a' && buffer[0] <= 'z')
-    return 26 * (count - 1) + buffer[0] - 'a' + 1;
-  if (buffer[0] >= 'A' && buffer[0] <= 'Z')
-    return 26 * (count - 1) + buffer[0] - 'A' + 1;
-
-  return -1;
-}
-
-static void toLatin(int number, GooString *str, GBool uppercase) {
-  char base, letter;
-  int i, count;
-
-  if (uppercase)
-    base = 'A';
-  else
-    base = 'a';
-
-  count = (number - 1) / 26 + 1;
-  letter = base + (number - 1) % 26;
-
-  for (i = 0; i < count; i++)
-    str->append(letter);
-}
+#include "PageLabelInfo_p.h"
 
 PageLabelInfo::Interval::Interval(Object *dict, int baseA) {
   Object obj;
@@ -359,30 +228,3 @@
 
   return gTrue;
 }
-
-#ifdef TEST
-int main(int argc, char *argv[])
-{
-  {
-    GooString str;
-    toRoman(177, &str, gFalse);
-    assert (str.cmp("clxxvii") == 0);
-  }
-
-  {
-    GooString roman("clxxvii");
-    assert (fromRoman(roman.getCString()) == 177);
-  }
-
-  {
-    GooString str;
-    toLatin(54, &str, gFalse);
-    assert (str.cmp("bbb") == 0);
-  }
-
-  {
-    GooString latin("ddd");
-    assert (fromLatin(latin.getCString()) == 56);
-  }
-}
-#endif
diff --git a/poppler/PageLabelInfo_p.h b/poppler/PageLabelInfo_p.h
new file mode 100644
index 0000000..d3cd89f
--- /dev/null
+++ b/poppler/PageLabelInfo_p.h
@@ -0,0 +1,147 @@
+//========================================================================
+//
+// This file is under the GPLv2 or later license
+//
+// Copyright (C) 2005-2006 Kristian Høgsberg <krh@redhat.com>
+// Copyright (C) 2005, 2009 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2011 Simon Kellner <kellner@kit.edu>
+// Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
+//
+// 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
+//
+//========================================================================
+
+/* http://mathworld.wolfram.com/RomanNumerals.html */
+
+#include "goo/GooString.h"
+
+static int fromRoman(const char *buffer) {
+  int digit_value, prev_digit_value, value;
+  int i;
+
+  prev_digit_value = INT_MAX;
+  value = 0;
+  for (i = 0; buffer[i] != '\0'; i++) {
+    switch (buffer[i]) {
+    case 'm':
+    case 'M':
+      digit_value = 1000;
+      break;
+    case 'd':
+    case 'D':
+      digit_value = 500;
+      break;
+    case 'c':
+    case 'C':
+      digit_value = 100;
+      break;
+    case 'l':
+    case 'L':
+      digit_value = 50;
+      break;
+    case 'x':
+    case 'X':
+      digit_value = 10;
+      break;
+    case 'v':
+    case 'V':
+      digit_value = 5;
+      break;
+    case 'i':
+    case 'I':
+      digit_value = 1;
+      break;
+    default:
+      return -1;
+    }
+
+    if (digit_value <= prev_digit_value)
+      value += digit_value;
+    else
+      value += digit_value - prev_digit_value * 2;
+    prev_digit_value = digit_value;
+  }
+
+  return value;
+}
+
+static void toRoman(int number, GooString *str, GBool uppercase) {
+  static const char uppercaseNumerals[] = "IVXLCDM";
+  static const char lowercaseNumerals[] = "ivxlcdm";
+  int divisor;
+  int i, j, k;
+  const char *wh;
+
+  if (uppercase)
+    wh = uppercaseNumerals;
+  else
+    wh = lowercaseNumerals;
+
+  divisor = 1000;
+  for (k = 3; k >= 0; k--) {
+    i = number / divisor;
+    number = number % divisor;
+
+    switch (i) {
+    case 0:
+      break;
+    case 5:
+      str->append(wh[2 * k + 1]);
+      break;
+    case 9:
+      str->append(wh[2 * k + 0]);
+      str->append(wh[ 2 * k + 2]);
+      break;
+    case 4:
+      str->append(wh[2 * k + 0]);
+      str->append(wh[2 * k + 1]);
+      break;
+    default:
+      if (i > 5) {
+       str->append(wh[2 * k + 1]);
+       i -= 5;
+      }
+      for (j = 0; j < i; j++) {
+       str->append(wh[2 * k + 0]);
+      }
+    }
+       
+    divisor = divisor / 10;
+  }
+}
+
+static int fromLatin(const char *buffer)
+{
+  int count;
+  const char *p;
+
+  for (p = buffer; *p; p++) {
+    if (*p != buffer[0])
+      return -1;
+  }
+
+  count = p - buffer;
+  if (buffer[0] >= 'a' && buffer[0] <= 'z')
+    return 26 * (count - 1) + buffer[0] - 'a' + 1;
+  if (buffer[0] >= 'A' && buffer[0] <= 'Z')
+    return 26 * (count - 1) + buffer[0] - 'A' + 1;
+
+  return -1;
+}
+
+static void toLatin(int number, GooString *str, GBool uppercase) {
+  char base, letter;
+  int i, count;
+
+  if (uppercase)
+    base = 'A';
+  else
+    base = 'a';
+
+  count = (number - 1) / 26 + 1;
+  letter = base + (number - 1) % 26;
+
+  for (i = 0; i < count; i++)
+    str->append(letter);
+}
diff --git a/poppler/PageTransition.cc b/poppler/PageTransition.cc
index 3fbd0de..441634c 100644
--- a/poppler/PageTransition.cc
+++ b/poppler/PageTransition.cc
@@ -1,6 +1,7 @@
 /* PageTransition.cc
  * Copyright (C) 2005, Net Integration Technologies, Inc.
  * Copyright (C) 2010, Albert Astals Cid <aacid@kde.org>
+ * Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
  *
  * 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
@@ -118,9 +119,9 @@
   }
   obj.free();
 
-  // get sacle
-  if (dict->lookup("SS", &obj)->isReal()) {
-    scale = obj.getReal();
+  // get scale
+  if (dict->lookup("SS", &obj)->isNum()) {
+    scale = obj.getNum();
   }
   obj.free();
 
diff --git a/poppler/Parser.cc b/poppler/Parser.cc
index 69304c4..0370564 100644
--- a/poppler/Parser.cc
+++ b/poppler/Parser.cc
@@ -18,6 +18,7 @@
 // Copyright (C) 2009 Ilya Gorenbein <igorenbein@finjan.com>
 // Copyright (C) 2012 Hib Eris <hib@hiberis.nl>
 // Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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
@@ -194,7 +195,8 @@
   Object obj;
   BaseStream *baseStr;
   Stream *str;
-  Guint pos, endPos, length;
+  Goffset length;
+  Goffset pos, endPos;
 
   // get stream start position
   lexer->skipToNextLine();
@@ -206,7 +208,10 @@
   // get length
   dict->dictLookup("Length", &obj, recursion);
   if (obj.isInt()) {
-    length = (Guint)obj.getInt();
+    length = obj.getInt();
+    obj.free();
+  } else if (obj.isInt64()) {
+    length = obj.getInt64();
     obj.free();
   } else {
     error(errSyntaxError, getPos(), "Bad 'Length' attribute in stream");
@@ -237,7 +242,7 @@
 
   // refill token buffers and check for 'endstream'
   shift();  // kill '>>'
-  shift();  // kill 'stream'
+  shift("endstream");  // kill 'stream'
   if (buf1.isCmd("endstream")) {
     shift();
   } else {
@@ -246,11 +251,11 @@
     if (xref) {
       // shift until we find the proper endstream or we change to another object or reach eof
       while (!buf1.isCmd("endstream") && xref->getNumEntry(lexer->getPos()) == objNum && !buf1.isEOF()) {
-        shift();
+        shift("endstream");
       }
       length = lexer->getPos() - pos;
       if (buf1.isCmd("endstream")) {
-        obj.initInt(length);
+        obj.initInt64(length);
         dict->dictSet("Length", &obj);
         obj.free();
       }
@@ -272,7 +277,7 @@
   }
 
   // get filters
-  str = str->addFilters(dict);
+  str = str->addFilters(dict, recursion);
 
   return str;
 }
@@ -297,3 +302,27 @@
   else
     lexer->getObj(&buf2, objNum);
 }
+
+void Parser::shift(const char *cmdA) {
+  if (inlineImg > 0) {
+    if (inlineImg < 2) {
+      ++inlineImg;
+    } else {
+      // in a damaged content stream, if 'ID' shows up in the middle
+      // of a dictionary, we need to reset
+      inlineImg = 0;
+    }
+  } else if (buf2.isCmd("ID")) {
+    lexer->skipChar();		// skip char after 'ID' command
+    inlineImg = 1;
+  }
+  buf1.free();
+  buf2.shallowCopy(&buf1);
+  if (inlineImg > 0) {
+    buf2.initNull();
+  } else if (buf1.isCmd(cmdA)) {
+    lexer->getObj(&buf2, -1);
+  } else {
+    lexer->getObj(&buf2, cmdA);
+  }
+}
diff --git a/poppler/Parser.h b/poppler/Parser.h
index 5ab4099..9702716 100644
--- a/poppler/Parser.h
+++ b/poppler/Parser.h
@@ -15,6 +15,8 @@
 //
 // Copyright (C) 2006, 2010 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2012 Hib Eris <hib@hiberis.nl>
+// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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,7 +60,7 @@
   Stream *getStream() { return lexer->getStream(); }
 
   // Get current position in file.
-  int getPos() { return lexer->getPos(); }
+  Goffset getPos() { return lexer->getPos(); }
 
 private:
 
@@ -73,6 +75,7 @@
 		     int objNum, int objGen, int recursion,
 		     GBool strict);
   void shift(int objNum = -1);
+  void shift(const char *cmdA);
 };
 
 #endif
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@gnome.org>
 // Copyright (C) 2010, 2011 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2011 William Bader <williambader@hotmail.com>
-// Copyright (C) 2011 Thomas Freitag <Thomas.Freitag@alfa.de>
+// Copyright (C) 2011, 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
 // Copyright (C) 2011 Adrian Johnson <ajohnson@redneon.com>
 //
 // To see a description of the changes please see the Changelog file that
@@ -52,7 +52,7 @@
 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@gnome.org>
 // Copyright (C) 2010 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2011 William Bader <williambader@hotmail.com>
-// Copyright (C) 2011 Thomas Freitag <Thomas.Freitag@alfa.de>
+// Copyright (C) 2011, 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
 // Copyright (C) 2011 Adrian Johnson <ajohnson@redneon.com>
 //
 // To see a description of the changes please see the Changelog file that
@@ -76,7 +76,7 @@
   //----- 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/SecurityHandler.cc b/poppler/SecurityHandler.cc
index a48449a..8b85e60 100644
--- a/poppler/SecurityHandler.cc
+++ b/poppler/SecurityHandler.cc
@@ -14,6 +14,7 @@
 // under GPL version 2 or later
 //
 // Copyright (C) 2010, 2012 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
 //
 // 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
@@ -167,8 +168,8 @@
   encryptDictA->dictLookup("OE", &ownerEncObj);
   encryptDictA->dictLookup("UE", &userEncObj);
   encryptDictA->dictLookup("P", &permObj);
-  if (permObj.isUint()) {
-      unsigned int permUint = permObj.getUint();
+  if (permObj.isInt64()) {
+      unsigned int permUint = permObj.getInt64();
       int perms = permUint - UINT_MAX - 1;
       permObj.free();
       permObj.initInt(perms);
diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc
index 6e62720..171825f 100644
--- a/poppler/SplashOutputDev.cc
+++ b/poppler/SplashOutputDev.cc
@@ -30,6 +30,7 @@
 // Copyright (C) 2011 Andreas Hartmetz <ahartmetz@gmail.com>
 // Copyright (C) 2011 Andrea Canciani <ranma42@gmail.com>
 // Copyright (C) 2011, 2012 Adrian Johnson <ajohnson@redneon.com>
+// Copyright (C) 2013 Lu Wang <coolwanglu@gmail.com>
 //
 // 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
@@ -1210,7 +1211,9 @@
 				 GBool reverseVideoA,
 				 SplashColorPtr paperColorA,
 				 GBool bitmapTopDownA,
-				 GBool allowAntialiasA) {
+				 GBool allowAntialiasA, 
+         SplashThinLineMode thinLineMode,
+         GBool overprintPreviewA) {
   colorMode = colorModeA;
   bitmapRowPad = bitmapRowPadA;
   bitmapTopDown = bitmapTopDownA;
@@ -1219,6 +1222,7 @@
   vectorAntialias = allowAntialias &&
 		      globalParams->getVectorAntialias() &&
 		      colorMode != splashModeMono1;
+  overprintPreview = overprintPreviewA;
   enableFreeTypeHinting = gFalse;
   enableSlightHinting = gFalse;
   setupScreenParams(72.0, 72.0);
@@ -1238,6 +1242,7 @@
 			    colorMode != splashModeMono1, bitmapTopDown);
   splash = new Splash(bitmap, vectorAntialias, &screenParams);
   splash->setMinLineWidth(globalParams->getMinLineWidth());
+  splash->setThinLineMode(thinLineMode);
   splash->clear(paperColor, 0);
 
   fontEngine = NULL;
@@ -1250,6 +1255,7 @@
   textClipPath = NULL;
   transpGroupStack = NULL;
   nestCount = 0;
+  xref = NULL;
 }
 
 void SplashOutputDev::setupScreenParams(double hDPI, double vDPI) {
@@ -1345,12 +1351,13 @@
   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);
@@ -1364,7 +1371,9 @@
   } else {
     w = h = 1;
   }
+  SplashThinLineMode thinLineMode = splashThinLineDefault;
   if (splash) {
+    thinLineMode = splash->getThinLineMode();
     delete splash;
     splash = NULL;
   }
@@ -1377,6 +1386,7 @@
 			      colorMode != splashModeMono1, bitmapTopDown);
   }
   splash = new Splash(bitmap, vectorAntialias, &screenParams);
+  splash->setThinLineMode(thinLineMode);
   splash->setMinLineWidth(globalParams->getMinLineWidth());
   if (state) {
     ctm = state->getCTM();
@@ -1667,7 +1677,7 @@
 		     grayIndexed);
 		return;
 	}
-  if (overprintFlag && globalParams->getOverprintPreview()) {
+  if (overprintFlag && overprintPreview) {
     mask = colorSpace->getOverprintMask();
     if (singleColor && overprintMode &&
 	colorSpace->getMode() == csDeviceCMYK) {
@@ -1840,7 +1850,7 @@
 
   } 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 +1860,7 @@
     // 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;
 
@@ -2581,6 +2591,7 @@
     color[0] = 0xff;
   }
   splash->setMinLineWidth(globalParams->getMinLineWidth());
+  splash->setThinLineMode(splashThinLineDefault);
   splash->setFillPattern(new SplashSolidColor(color));
   splash->setStrokePattern(new SplashSolidColor(color));
   //~ this should copy other state from t3GlyphStack->origSplash?
@@ -3385,7 +3396,7 @@
   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,
@@ -3816,6 +3827,7 @@
 			    bitmapTopDown, bitmap->getSeparationList());
   splash = new Splash(bitmap, vectorAntialias,
 		      transpGroup->origSplash->getScreen());
+  splash->setThinLineMode(transpGroup->origSplash->getThinLineMode());
   splash->setMinLineWidth(globalParams->getMinLineWidth());
   //~ Acrobat apparently copies at least the fill and stroke colors, and
   //~ maybe other state(?) -- but not the clipping path (and not sure
@@ -3837,7 +3849,7 @@
     splash->setInNonIsolatedGroup(shape, tx, ty);
   }
   transpGroup->tBitmap = bitmap;
-  state->shiftCTM(-tx, -ty);
+  state->shiftCTMAndClip(-tx, -ty);
   updateCTM(state, 0, 0, 0, 0, 0, 0);
   ++nestCount;
 }
@@ -3849,7 +3861,7 @@
   bitmap = transpGroupStack->origBitmap;
   colorMode = bitmap->getMode();
   splash = transpGroupStack->origSplash;
-  state->shiftCTM(transpGroupStack->tx, transpGroupStack->ty);
+  state->shiftCTMAndClip(transpGroupStack->tx, transpGroupStack->ty);
   updateCTM(state, 0, 0, 0, 0, 0, 0);
 }
 
@@ -4080,7 +4092,7 @@
   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,
@@ -4203,22 +4215,24 @@
 
   bitmap = new SplashBitmap(surface_width, surface_height, 1,
                             (paintType == 1) ? colorMode : splashModeMono8, gTrue);
-  memset(bitmap->getAlphaPtr(), 0, bitmap->getWidth() * bitmap->getHeight());
-  if (paintType == 2) {
-#if SPLASH_CMYK
-    memset(bitmap->getDataPtr(), 
-      (colorMode == splashModeCMYK8 || colorMode == splashModeDeviceN8) ? 0x00 : 0xFF, 
-      bitmap->getRowSize() * bitmap->getHeight());
-#else
-    memset(bitmap->getDataPtr(), 0xFF, bitmap->getRowSize() * bitmap->getHeight());
-#endif
-  }
   splash = new Splash(bitmap, gTrue);
+  if (paintType == 2) {
+    SplashColor clearColor;
+#if SPLASH_CMYK
+    clearColor[0] = (colorMode == splashModeCMYK8 || colorMode == splashModeDeviceN8) ? 0x00 : 0xFF;
+#else
+    clearColor[0] = 0xFF;
+#endif
+    splash->clear(clearColor, 0);
+  } else {
+    splash->clear(paperColor, 0);
+  }
+  splash->setThinLineMode(formerSplash->getThinLineMode());
   splash->setMinLineWidth(globalParams->getMinLineWidth());
 
   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..ce1d50d 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@suse.de>
-// Copyright (C) 2009-2012 Thomas Freitag <Thomas.Freitag@alfa.de>
+// Copyright (C) 2009-2013 Thomas Freitag <Thomas.Freitag@alfa.de>
 // Copyright (C) 2009 Carlos Garcia Campos <carlosgc@gnome.org>
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger@googlemail.com>
 // Copyright (C) 2011 Andreas Hartmetz <ahartmetz@gmail.com>
@@ -40,6 +40,7 @@
 #include "poppler-config.h"
 #include "OutputDev.h"
 #include "GfxState.h"
+#include "GlobalParams.h"
 
 class PDFDoc;
 class Gfx8BitFont;
@@ -163,7 +164,9 @@
   SplashOutputDev(SplashColorMode colorModeA, int bitmapRowPadA,
 		  GBool reverseVideoA, SplashColorPtr paperColorA,
 		  GBool bitmapTopDownA = gTrue,
-		  GBool allowAntialiasA = gTrue);
+		  GBool allowAntialiasA = gTrue,
+		  SplashThinLineMode thinLineMode = splashThinLineDefault,
+      GBool overprintPreviewA = globalParams->getOverprintPreview());
 
   // Destructor.
   virtual ~SplashOutputDev();
@@ -195,7 +198,7 @@
   //----- 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();
@@ -258,7 +261,6 @@
 			       CharCode code, Unicode *u, int uLen);
   virtual void endType3Char(GfxState *state);
   virtual void beginTextObject(GfxState *state);
-  virtual GBool deviceHasTextClip(GfxState *state) { return textClipPath; }
   virtual void endTextObject(GfxState *state);
 
   //----- image drawing
@@ -390,6 +392,7 @@
   GBool bitmapUpsideDown;
   GBool allowAntialias;
   GBool vectorAntialias;
+  GBool overprintPreview;
   GBool enableFreeTypeHinting;
   GBool enableSlightHinting;
   GBool reverseVideo;		// reverse video mode
@@ -399,6 +402,7 @@
   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 e8f5ec7..e9533fa 100644
--- a/poppler/Stream.cc
+++ b/poppler/Stream.cc
@@ -27,6 +27,8 @@
 // Copyright (C) 2012 Oliver Sander <sander@mi.fu-berlin.de>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
 // Copyright (C) 2012 Even Rouault <even.rouault@mines-paris.org>
+// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
+// Copyright (C) 2013 Adam Reichold <adamreichold@myopera.com>
 //
 // 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,15 +88,38 @@
 #endif
 #endif
 
+#if MULTITHREADED
+#  define streamLocker()   MutexLocker locker(&mutex)
+#else
+#  define streamLocker()
+#endif
 //------------------------------------------------------------------------
 // Stream (base class)
 //------------------------------------------------------------------------
 
 Stream::Stream() {
   ref = 1;
+#if MULTITHREADED
+  gInitMutex(&mutex);
+#endif
 }
 
 Stream::~Stream() {
+#if MULTITHREADED
+  gDestroyMutex(&mutex);
+#endif
+}
+
+int Stream::incRef() {
+  streamLocker();
+  ++ref;
+  return ref;
+}
+
+int Stream::decRef() {
+  streamLocker();
+  --ref;
+  return ref;
 }
 
 void Stream::close() {
@@ -139,34 +164,34 @@
   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", &params);
+  dict->dictLookup("DecodeParms", &params, recursion);
   if (params.isNull()) {
     params.free();
     dict->dictLookup("DP", &params);
   }
   if (obj.isName()) {
-    str = makeFilter(obj.getName(), str, &params, dict);
+    str = makeFilter(obj.getName(), str, &params, recursion, dict);
   } else if (obj.isArray()) {
     for (i = 0; i < obj.arrayGetLength(); ++i) {
       obj.arrayGet(i, &obj2);
       if (params.isArray())
-	params.arrayGet(i, &params2);
+	params.arrayGet(i, &params2, recursion);
       else
 	params2.initNull();
       if (obj2.isName()) {
-	str = makeFilter(obj2.getName(), str, &params2);
+	str = makeFilter(obj2.getName(), str, &params2, recursion);
       } else {
 	error(errSyntaxError, getPos(), "Bad filter name");
 	str = new EOFStream(str);
@@ -183,7 +208,7 @@
   return str;
 }
 
-Stream *Stream::makeFilter(char *name, Stream *str, Object *params, Object *dict) {
+Stream *Stream::makeFilter(char *name, Stream *str, Object *params, int recursion, Object *dict) {
   int pred;			// parameters
   int colors;
   int bits;
@@ -205,23 +230,23 @@
     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 +263,37 @@
     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,31 +304,31 @@
   } 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();
     }
-    str = new DCTStream(str, colorXform, dict);
+    str = new DCTStream(str, colorXform, dict, recursion);
   } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
     pred = 1;
     columns = 1;
     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,12 +336,18 @@
     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();
   } else if (!strcmp(name, "JPXDecode")) {
     str = new JPXStream(str);
+  } else if (!strcmp(name, "Crypt")) {
+    if (str->getKind() == strCrypt) {
+      str = str->getBaseStream();
+    } else {
+      error(errSyntaxError, getPos(), "Can't revert non decrypt streams");
+    }
   } else {
     error(errSyntaxError, getPos(), "Unknown filter '{0:s}'", name);
     str = new EOFStream(str);
@@ -339,7 +370,7 @@
 //------------------------------------------------------------------------
 // FileOutStream
 //------------------------------------------------------------------------
-FileOutStream::FileOutStream (FILE* fa, Guint startA)
+FileOutStream::FileOutStream (FILE* fa, Goffset startA)
 {
   f = fa;
   start = startA;
@@ -355,9 +386,9 @@
 
 }
 
-int FileOutStream::getPos ()
+Goffset FileOutStream::getPos ()
 {
-  return ftell(f);
+  return Gftell(f);
 }
 
 void FileOutStream::put (char c)
@@ -378,7 +409,7 @@
 // BaseStream
 //------------------------------------------------------------------------
 
-BaseStream::BaseStream(Object *dictA, Guint lengthA) {
+BaseStream::BaseStream(Object *dictA, Goffset lengthA) {
   dict = *dictA;
   length = lengthA;
 }
@@ -402,7 +433,7 @@
   str->close();
 }
 
-void FilterStream::setPos(Guint pos, int dir) {
+void FilterStream::setPos(Goffset pos, int dir) {
   error(errInternal, -1, "Internal: called setPos() on FilterStream");
 }
 
@@ -729,11 +760,11 @@
 // FileStream
 //------------------------------------------------------------------------
 
-FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA,
-		       Guint lengthA, Object *dictA):
+FileStream::FileStream(GooFile* fileA, Goffset startA, GBool limitedA,
+		       Goffset lengthA, Object *dictA):
     BaseStream(dictA, lengthA) {
-  f = fA;
-  start = startA;
+  file = fileA;
+  offset = start = startA;
   limited = limitedA;
   length = lengthA;
   bufPtr = bufEnd = buf;
@@ -746,22 +777,18 @@
   close();
 }
 
-Stream *FileStream::makeSubStream(Guint startA, GBool limitedA,
-				  Guint lengthA, Object *dictA) {
-  return new FileStream(f, startA, limitedA, lengthA, dictA);
+BaseStream *FileStream::copy() {
+  return new FileStream(file, start, limited, length, &dict);
+}
+
+Stream *FileStream::makeSubStream(Goffset startA, GBool limitedA,
+				  Goffset lengthA, Object *dictA) {
+  return new FileStream(file, startA, limitedA, lengthA, dictA);
 }
 
 void FileStream::reset() {
-#if HAVE_FSEEKO
-  savePos = (Guint)ftello(f);
-  fseeko(f, start, SEEK_SET);
-#elif HAVE_FSEEK64
-  savePos = (Guint)ftell64(f);
-  fseek64(f, start, SEEK_SET);
-#else
-  savePos = (Guint)ftell(f);
-  fseek(f, start, SEEK_SET);
-#endif
+  savePos = offset;
+  offset = start;
   saved = gTrue;
   bufPtr = bufEnd = buf;
   bufPos = start;
@@ -769,13 +796,7 @@
 
 void FileStream::close() {
   if (saved) {
-#if HAVE_FSEEKO
-    fseeko(f, savePos, SEEK_SET);
-#elif HAVE_FSEEK64
-    fseek64(f, savePos, SEEK_SET);
-#else
-    fseek(f, savePos, SEEK_SET);
-#endif
+    offset = savePos;
     saved = gFalse;
   }
 }
@@ -793,7 +814,8 @@
   } else {
     n = fileStreamBufSize;
   }
-  n = fread(buf, 1, n, f);
+  n = file->read(buf, n, offset);
+  offset += n;
   bufEnd = buf + n;
   if (bufPtr >= bufEnd) {
     return gFalse;
@@ -801,46 +823,22 @@
   return gTrue;
 }
 
-void FileStream::setPos(Guint pos, int dir) {
-  Guint size;
+void FileStream::setPos(Goffset pos, int dir) {
+  Goffset size;
 
   if (dir >= 0) {
-#if HAVE_FSEEKO
-    fseeko(f, pos, SEEK_SET);
-#elif HAVE_FSEEK64
-    fseek64(f, pos, SEEK_SET);
-#else
-    fseek(f, pos, SEEK_SET);
-#endif
-    bufPos = pos;
+    offset = bufPos = pos;
   } else {
-#if HAVE_FSEEKO
-    fseeko(f, 0, SEEK_END);
-    size = (Guint)ftello(f);
-#elif HAVE_FSEEK64
-    fseek64(f, 0, SEEK_END);
-    size = (Guint)ftell64(f);
-#else
-    fseek(f, 0, SEEK_END);
-    size = (Guint)ftell(f);
-#endif
+    size = file->size();
     if (pos > size)
-      pos = (Guint)size;
-#if HAVE_FSEEKO
-    fseeko(f, -(int)pos, SEEK_END);
-    bufPos = (Guint)ftello(f);
-#elif HAVE_FSEEK64
-    fseek64(f, -(int)pos, SEEK_END);
-    bufPos = (Guint)ftell64(f);
-#else
-    fseek(f, -(int)pos, SEEK_END);
-    bufPos = (Guint)ftell(f);
-#endif
+      pos = size;
+    offset = size - pos;
+    bufPos = offset;
   }
   bufPtr = bufEnd = buf;
 }
 
-void FileStream::moveStart(int delta) {
+void FileStream::moveStart(Goffset delta) {
   start += delta;
   bufPtr = bufEnd = buf;
   bufPos = start;
@@ -850,8 +848,8 @@
 // CachedFileStream
 //------------------------------------------------------------------------
 
-CachedFileStream::CachedFileStream(CachedFile *ccA, Guint startA,
-        GBool limitedA, Guint lengthA, Object *dictA)
+CachedFileStream::CachedFileStream(CachedFile *ccA, Goffset startA,
+        GBool limitedA, Goffset lengthA, Object *dictA)
   : BaseStream(dictA, lengthA)
 {
   cc = ccA;
@@ -870,8 +868,13 @@
   cc->decRefCnt();
 }
 
-Stream *CachedFileStream::makeSubStream(Guint startA, GBool limitedA,
-        Guint lengthA, Object *dictA)
+BaseStream *CachedFileStream::copy() {
+  cc->incRefCnt();
+  return new CachedFileStream(cc, start, limited, length, &dict);
+}
+
+Stream *CachedFileStream::makeSubStream(Goffset startA, GBool limitedA,
+        Goffset lengthA, Object *dictA)
 {
   cc->incRefCnt();
   return new CachedFileStream(cc, startA, limitedA, lengthA, dictA);
@@ -917,7 +920,7 @@
   return gTrue;
 }
 
-void CachedFileStream::setPos(Guint pos, int dir)
+void CachedFileStream::setPos(Goffset pos, int dir)
 {
   Guint size;
 
@@ -938,7 +941,7 @@
   bufPtr = bufEnd = buf;
 }
 
-void CachedFileStream::moveStart(int delta)
+void CachedFileStream::moveStart(Goffset delta)
 {
   start += delta;
   bufPtr = bufEnd = buf;
@@ -949,7 +952,7 @@
 // MemStream
 //------------------------------------------------------------------------
 
-MemStream::MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA):
+MemStream::MemStream(char *bufA, Goffset startA, Goffset lengthA, Object *dictA):
     BaseStream(dictA, lengthA) {
   buf = bufA;
   start = startA;
@@ -965,10 +968,14 @@
   }
 }
 
-Stream *MemStream::makeSubStream(Guint startA, GBool limited,
-				 Guint lengthA, Object *dictA) {
+BaseStream *MemStream::copy() {
+  return new MemStream(buf, start, length, &dict);
+}
+
+Stream *MemStream::makeSubStream(Goffset startA, GBool limited,
+				 Goffset lengthA, Object *dictA) {
   MemStream *subStr;
-  Guint newLength;
+  Goffset newLength;
 
   if (!limited || startA + lengthA > start + length) {
     newLength = start + length - startA;
@@ -1002,7 +1009,7 @@
   return n;
 }
 
-void MemStream::setPos(Guint pos, int dir) {
+void MemStream::setPos(Goffset pos, int dir) {
   Guint i;
 
   if (dir >= 0) {
@@ -1018,7 +1025,7 @@
   bufPtr = buf + i;
 }
 
-void MemStream::moveStart(int delta) {
+void MemStream::moveStart(Goffset delta) {
   start += delta;
   length -= delta;
   bufPtr = buf + start;
@@ -1029,7 +1036,7 @@
 //------------------------------------------------------------------------
 
 EmbedStream::EmbedStream(Stream *strA, Object *dictA,
-			 GBool limitedA, Guint lengthA):
+			 GBool limitedA, Goffset lengthA):
     BaseStream(dictA, lengthA) {
   str = strA;
   limited = limitedA;
@@ -1039,8 +1046,13 @@
 EmbedStream::~EmbedStream() {
 }
 
-Stream *EmbedStream::makeSubStream(Guint start, GBool limitedA,
-				   Guint lengthA, Object *dictA) {
+BaseStream *EmbedStream::copy() {
+  error(errInternal, -1, "Called copy() on EmbedStream");
+  return NULL;
+}
+
+Stream *EmbedStream::makeSubStream(Goffset start, GBool limitedA,
+				   Goffset lengthA, Object *dictA) {
   error(errInternal, -1, "Called makeSubStream() on EmbedStream");
   return NULL;
 }
@@ -1064,22 +1076,22 @@
   if (nChars <= 0) {
     return 0;
   }
-  if (limited && length < (Guint)nChars) {
-    nChars = (int)length;
+  if (limited && length < nChars) {
+    nChars = length;
   }
   return str->doGetChars(nChars, buffer);
 }
 
-void EmbedStream::setPos(Guint pos, int dir) {
+void EmbedStream::setPos(Goffset pos, int dir) {
   error(errInternal, -1, "Internal: called setPos() on EmbedStream");
 }
 
-Guint EmbedStream::getStart() {
+Goffset EmbedStream::getStart() {
   error(errInternal, -1, "Internal: called getStart() on EmbedStream");
   return 0;
 }
 
-void EmbedStream::moveStart(int delta) {
+void EmbedStream::moveStart(Goffset delta) {
   error(errInternal, -1, "Internal: called moveStart() on EmbedStream");
 }
 
@@ -2410,7 +2422,7 @@
   63
 };
 
-DCTStream::DCTStream(Stream *strA, int colorXformA, Object *dict):
+DCTStream::DCTStream(Stream *strA, int colorXformA, Object *dict, int recursion):
     FilterStream(strA) {
   int i, j;
 
diff --git a/poppler/Stream.h b/poppler/Stream.h
index 76d6a1f..0a178b4 100644
--- a/poppler/Stream.h
+++ b/poppler/Stream.h
@@ -22,7 +22,9 @@
 // Copyright (C) 2011, 2012 William Bader <williambader@hotmail.com>
 // Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
+// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
 // Copyright (C) 2013 Peter Breitenlohner <peb@mppmu.mpg.de>
+// Copyright (C) 2013 Adam Reichold <adamreichold@myopera.com>
 //
 // 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
@@ -40,7 +42,9 @@
 #include <stdio.h>
 #include "goo/gtypes.h"
 #include "Object.h"
+#include "goo/GooMutex.h"
 
+class GooFile;
 class BaseStream;
 class CachedFile;
 
@@ -58,7 +62,8 @@
   strFlate,
   strJBIG2,
   strJPX,
-  strWeird			// internal-use stream types
+  strWeird,			// internal-use stream types
+  strCrypt			// internal-use to detect decode streams
 };
 
 enum StreamColorSpaceMode {
@@ -99,8 +104,8 @@
   virtual ~Stream();
 
   // Reference counting.
-  int incRef() { return ++ref; }
-  int decRef() { return --ref; }
+  int incRef();
+  int decRef();
 
   // Get kind of stream.
   virtual StreamKind getKind() = 0;
@@ -184,12 +189,12 @@
   virtual char *getLine(char *buf, int size);
 
   // Get current position in file.
-  virtual int getPos() = 0;
+  virtual Goffset getPos() = 0;
 
   // Go to a position in the stream.  If <dir> is negative, the
   // position is from the end of the file; otherwise the position is
   // from the start of the file.
-  virtual void setPos(Guint pos, int dir = 0) = 0;
+  virtual void setPos(Goffset pos, int dir = 0) = 0;
 
   // Get PostScript command for the filter(s).
   virtual GooString *getPSFilter(int psLevel, const char *indent);
@@ -219,15 +224,18 @@
 
   // 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, Object *dict = NULL);
+  Stream *makeFilter(char *name, Stream *str, Object *params, int recursion = 0, Object *dict = NULL);
 
   int ref;			// reference count
+#if MULTITHREADED
+  GooMutex mutex;
+#endif
 };
 
 
@@ -252,7 +260,7 @@
   virtual void close() = 0;
 
   // Return position in stream
-  virtual int getPos() = 0;
+  virtual Goffset getPos() = 0;
 
   // Put a char in the stream
   virtual void put (char c) = 0;
@@ -271,20 +279,20 @@
 //------------------------------------------------------------------------
 class FileOutStream : public OutStream {
 public:
-  FileOutStream (FILE* fa, Guint startA);
+  FileOutStream (FILE* fa, Goffset startA);
 
   virtual ~FileOutStream ();
 
   virtual void close();
 
-  virtual int getPos();
+  virtual Goffset getPos();
 
   virtual void put (char c);
 
   virtual void printf (const char *format, ...);
 private:
   FILE *f;
-  Guint start;
+  Goffset start;
 
 };
 
@@ -298,28 +306,26 @@
 class BaseStream: public Stream {
 public:
 
-  BaseStream(Object *dictA, Guint lengthA);
+  BaseStream(Object *dictA, Goffset lengthA);
   virtual ~BaseStream();
-  virtual Stream *makeSubStream(Guint start, GBool limited,
-				Guint length, Object *dict) = 0;
-  virtual void setPos(Guint pos, int dir = 0) = 0;
+  virtual BaseStream *copy() = 0;
+  virtual Stream *makeSubStream(Goffset start, GBool limited,
+				Goffset length, Object *dict) = 0;
+  virtual void setPos(Goffset pos, int dir = 0) = 0;
   virtual GBool isBinary(GBool last = gTrue) { return last; }
   virtual BaseStream *getBaseStream() { return this; }
   virtual Stream *getUndecodedStream() { return this; }
   virtual Dict *getDict() { return dict.getDict(); }
   virtual GooString *getFileName() { return NULL; }
-  virtual Guint getLength() { return length; }
+  virtual Goffset getLength() { return length; }
 
   // Get/set position of first byte of stream within the file.
-  virtual Guint getStart() = 0;
-  virtual void moveStart(int delta) = 0;
+  virtual Goffset getStart() = 0;
+  virtual void moveStart(Goffset delta) = 0;
 
 protected:
 
-  Guint length;
-
-private:
-
+  Goffset length;
   Object dict;
 };
 
@@ -335,8 +341,8 @@
   FilterStream(Stream *strA);
   virtual ~FilterStream();
   virtual void close();
-  virtual int getPos() { return str->getPos(); }
-  virtual void setPos(Guint pos, int dir = 0);
+  virtual Goffset getPos() { return str->getPos(); }
+  virtual void setPos(Goffset pos, int dir = 0);
   virtual BaseStream *getBaseStream() { return str->getBaseStream(); }
   virtual Stream *getUndecodedStream() { return str->getUndecodedStream(); }
   virtual Dict *getDict() { return str->getDict(); }
@@ -440,11 +446,12 @@
 class FileStream: public BaseStream {
 public:
 
-  FileStream(FILE *fA, Guint startA, GBool limitedA,
-	     Guint lengthA, Object *dictA);
+  FileStream(GooFile* fileA, Goffset startA, GBool limitedA,
+	     Goffset lengthA, Object *dictA);
   virtual ~FileStream();
-  virtual Stream *makeSubStream(Guint startA, GBool limitedA,
-				Guint lengthA, Object *dictA);
+  virtual BaseStream *copy();
+  virtual Stream *makeSubStream(Goffset startA, GBool limitedA,
+				Goffset lengthA, Object *dictA);
   virtual StreamKind getKind() { return strFile; }
   virtual void reset();
   virtual void close();
@@ -452,10 +459,10 @@
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
   virtual int lookChar()
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
-  virtual int getPos() { return bufPos + (bufPtr - buf); }
-  virtual void setPos(Guint pos, int dir = 0);
-  virtual Guint getStart() { return start; }
-  virtual void moveStart(int delta);
+  virtual Goffset getPos() { return bufPos + (bufPtr - buf); }
+  virtual void setPos(Goffset pos, int dir = 0);
+  virtual Goffset getStart() { return start; }
+  virtual void moveStart(Goffset delta);
 
   virtual int getUnfilteredChar () { return getChar(); }
   virtual void unfilteredReset () { reset(); }
@@ -487,14 +494,16 @@
       return n;
     }
 
-  FILE *f;
-  Guint start;
+private:
+  GooFile* file;
+  Goffset offset;
+  Goffset start;
   GBool limited;
   char buf[fileStreamBufSize];
   char *bufPtr;
   char *bufEnd;
-  Guint bufPos;
-  int savePos;
+  Goffset bufPos;
+  Goffset savePos;
   GBool saved;
 };
 
@@ -507,11 +516,12 @@
 class CachedFileStream: public BaseStream {
 public:
 
-  CachedFileStream(CachedFile *ccA, Guint startA, GBool limitedA,
-	     Guint lengthA, Object *dictA);
+  CachedFileStream(CachedFile *ccA, Goffset startA, GBool limitedA,
+	     Goffset lengthA, Object *dictA);
   virtual ~CachedFileStream();
-  virtual Stream *makeSubStream(Guint startA, GBool limitedA,
-				Guint lengthA, Object *dictA);
+  virtual BaseStream *copy();
+  virtual Stream *makeSubStream(Goffset startA, GBool limitedA,
+				Goffset lengthA, Object *dictA);
   virtual StreamKind getKind() { return strCachedFile; }
   virtual void reset();
   virtual void close();
@@ -519,10 +529,10 @@
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
   virtual int lookChar()
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
-  virtual int getPos() { return bufPos + (bufPtr - buf); }
-  virtual void setPos(Guint pos, int dir = 0);
-  virtual Guint getStart() { return start; }
-  virtual void moveStart(int delta);
+  virtual Goffset getPos() { return bufPos + (bufPtr - buf); }
+  virtual void setPos(Goffset pos, int dir = 0);
+  virtual Goffset getStart() { return start; }
+  virtual void moveStart(Goffset delta);
 
   virtual int getUnfilteredChar () { return getChar(); }
   virtual void unfilteredReset () { reset(); }
@@ -532,7 +542,7 @@
   GBool fillBuf();
 
   CachedFile *cc;
-  Guint start;
+  Goffset start;
   GBool limited;
   char buf[cachedStreamBufSize];
   char *bufPtr;
@@ -550,10 +560,11 @@
 class MemStream: public BaseStream {
 public:
 
-  MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA);
+  MemStream(char *bufA, Goffset startA, Goffset lengthA, Object *dictA);
   virtual ~MemStream();
-  virtual Stream *makeSubStream(Guint start, GBool limited,
-				Guint lengthA, Object *dictA);
+  virtual BaseStream *copy();
+  virtual Stream *makeSubStream(Goffset start, GBool limited,
+				Goffset lengthA, Object *dictA);
   virtual StreamKind getKind() { return strWeird; }
   virtual void reset();
   virtual void close();
@@ -561,10 +572,10 @@
     { return (bufPtr < bufEnd) ? (*bufPtr++ & 0xff) : EOF; }
   virtual int lookChar()
     { return (bufPtr < bufEnd) ? (*bufPtr & 0xff) : EOF; }
-  virtual int getPos() { return (int)(bufPtr - buf); }
-  virtual void setPos(Guint pos, int dir = 0);
-  virtual Guint getStart() { return start; }
-  virtual void moveStart(int delta);
+  virtual Goffset getPos() { return (int)(bufPtr - buf); }
+  virtual void setPos(Goffset pos, int dir = 0);
+  virtual Goffset getStart() { return start; }
+  virtual void moveStart(Goffset delta);
 
   //if needFree = true, the stream will delete buf when it is destroyed
   //otherwise it will not touch it. Default value is false
@@ -579,7 +590,7 @@
   virtual int getChars(int nChars, Guchar *buffer);
 
   char *buf;
-  Guint start;
+  Goffset start;
   char *bufEnd;
   char *bufPtr;
   GBool needFree;
@@ -598,18 +609,19 @@
 class EmbedStream: public BaseStream {
 public:
 
-  EmbedStream(Stream *strA, Object *dictA, GBool limitedA, Guint lengthA);
+  EmbedStream(Stream *strA, Object *dictA, GBool limitedA, Goffset lengthA);
   virtual ~EmbedStream();
-  virtual Stream *makeSubStream(Guint start, GBool limitedA,
-				Guint lengthA, Object *dictA);
+  virtual BaseStream *copy();
+  virtual Stream *makeSubStream(Goffset start, GBool limitedA,
+				Goffset lengthA, Object *dictA);
   virtual StreamKind getKind() { return str->getKind(); }
   virtual void reset() {}
   virtual int getChar();
   virtual int lookChar();
-  virtual int getPos() { return str->getPos(); }
-  virtual void setPos(Guint pos, int dir = 0);
-  virtual Guint getStart();
-  virtual void moveStart(int delta);
+  virtual Goffset getPos() { return str->getPos(); }
+  virtual void setPos(Goffset pos, int dir = 0);
+  virtual Goffset getStart();
+  virtual void moveStart(Goffset delta);
 
   virtual int getUnfilteredChar () { return str->getUnfilteredChar(); }
   virtual void unfilteredReset () { str->unfilteredReset(); }
@@ -851,7 +863,7 @@
 class DCTStream: public FilterStream {
 public:
 
-  DCTStream(Stream *strA, int colorXformA, Object *dict);
+  DCTStream(Stream *strA, int colorXformA, Object *dict, int recursion);
   virtual ~DCTStream();
   virtual StreamKind getKind() { return strDCT; }
   virtual void reset();
diff --git a/poppler/TextOutputDev.cc b/poppler/TextOutputDev.cc
index d054697..801f347 100644
--- a/poppler/TextOutputDev.cc
+++ b/poppler/TextOutputDev.cc
@@ -33,6 +33,7 @@
 // Copyright (C) 2012, 2013 Jason Crain <jason@aquaticape.us>
 // Copyright (C) 2012 Peter Breitenlohner <peb@mppmu.mpg.de>
 // Copyright (C) 2013 José Aliste <jaliste@src.gnome.org>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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
@@ -4278,7 +4279,7 @@
 
   state = new GfxState(72 * scale, 72 * scale, &box, rotation, gFalse);
 
-  out->startPage (0, state);
+  out->startPage (0, state, NULL);
   out->setDefaultCTM (state->getCTM());
 
   state->setFillColorSpace(new GfxDeviceRGBColorSpace());
@@ -5329,7 +5330,7 @@
   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 73109d6..664f9d1 100644
--- a/poppler/TextOutputDev.h
+++ b/poppler/TextOutputDev.h
@@ -20,6 +20,7 @@
 // Copyright (C) 2008, 2010 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2010 Brian Ewins <brian.ewins@gmail.com>
 // Copyright (C) 2012, 2013 Jason Crain <jason@aquaticape.us>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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
@@ -719,7 +720,7 @@
   //----- 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 2ba50b0..85745ff 100644
--- a/poppler/XRef.cc
+++ b/poppler/XRef.cc
@@ -15,13 +15,14 @@
 //
 // Copyright (C) 2005 Dan Sheridan <dan.sheridan@postman.org.uk>
 // Copyright (C) 2005 Brad Hards <bradh@frogmouth.net>
-// Copyright (C) 2006, 2008, 2010, 2012 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2006, 2008, 2010, 2012, 2013 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2007-2008 Julien Rebetez <julienr@svn.gnome.org>
 // Copyright (C) 2007 Carlos Garcia Campos <carlosgc@gnome.org>
 // Copyright (C) 2009, 2010 Ilya Gorenbein <igorenbein@finjan.com>
 // Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
 // Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag@kabelmail.de>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
+// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
 //
 // 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
@@ -37,8 +38,11 @@
 #include <stdlib.h>
 #include <stddef.h>
 #include <string.h>
+#include <math.h>
 #include <ctype.h>
 #include <limits.h>
+#include <float.h>
+#include "goo/gfile.h"
 #include "goo/gmem.h"
 #include "Object.h"
 #include "Stream.h"
@@ -65,6 +69,14 @@
 #define permHighResPrint  (1<<11) // bit 12
 #define defPermFlags 0xfffc
 
+#if MULTITHREADED
+#  define xrefLocker()   MutexLocker locker(&mutex)
+#  define xrefCondLocker(X)  MutexLocker locker(&mutex, (X))
+#else
+#  define xrefLocker()
+#  define xrefCondLocker(X)
+#endif
+
 //------------------------------------------------------------------------
 // ObjectStream
 //------------------------------------------------------------------------
@@ -74,7 +86,7 @@
 
   // 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,12 +139,13 @@
     ObjectStream *objStream;
 };
 
-ObjectStream::ObjectStream(XRef *xref, int objStrNumA) {
+ObjectStream::ObjectStream(XRef *xref, int objStrNumA, int recursion) {
   Stream *str;
   Parser *parser;
-  int *offsets;
+  Goffset *offsets;
   Object objStr, obj1, obj2;
-  int first, i;
+  Goffset first;
+  int i;
 
   objStrNum = objStrNumA;
   nObjects = 0;
@@ -140,11 +153,11 @@
   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,11 +167,15 @@
     goto err1;
   }
 
-  if (!objStr.streamGetDict()->lookup("First", &obj1)->isInt()) {
+  objStr.streamGetDict()->lookup("First", &obj1, recursion);
+  if (!obj1.isInt() && !obj1.isInt64()) {
     obj1.free();
     goto err1;
   }
-  first = obj1.getInt();
+  if (obj1.isInt())
+    first = obj1.getInt();
+  else
+    first = obj1.getInt64();
   obj1.free();
   if (first < 0) {
     goto err1;
@@ -173,7 +190,7 @@
   }
   objs = new Object[nObjects];
   objNums = (int *)gmallocn(nObjects, sizeof(int));
-  offsets = (int *)gmallocn(nObjects, sizeof(int));
+  offsets = (Goffset *)gmallocn(nObjects, sizeof(Goffset));
 
   // parse the header: object numbers and offsets
   objStr.streamReset();
@@ -183,7 +200,7 @@
   for (i = 0; i < nObjects; ++i) {
     parser->getObj(&obj1);
     parser->getObj(&obj2);
-    if (!obj1.isInt() || !obj2.isInt()) {
+    if (!obj1.isInt() || !(obj2.isInt() || obj2.isInt64())) {
       obj1.free();
       obj2.free();
       delete parser;
@@ -191,7 +208,10 @@
       goto err1;
     }
     objNums[i] = obj1.getInt();
-    offsets[i] = obj2.getInt();
+    if (obj2.isInt())
+      offsets[i] = obj2.getInt();
+    else
+      offsets[i] = obj2.getInt64();
     obj1.free();
     obj2.free();
     if (objNums[i] < 0 || offsets[i] < 0 ||
@@ -207,7 +227,7 @@
   // skip to the first object - this shouldn't be necessary because
   // the First key is supposed to be equal to offsets[0], but just in
   // case...
-  for (i = first; i < offsets[0]; ++i) {
+  for (Goffset pos = first; pos < offsets[0]; ++pos) {
     objStr.getStream()->getChar();
   }
 
@@ -257,6 +277,9 @@
 //------------------------------------------------------------------------
 
 void XRef::init() {
+#if MULTITHREADED
+  gInitMutex(&mutex);
+#endif
   ok = gTrue;
   errCode = errNone;
   entries = NULL;
@@ -272,6 +295,7 @@
   permFlags = defPermFlags;
   ownerPasswordOk = gFalse;
   rootNum = -1;
+  strOwner = gFalse;
 }
 
 XRef::XRef() {
@@ -285,7 +309,7 @@
     trailerDict.initDict(trailerDictA->getDict());
 }
 
-XRef::XRef(BaseStream *strA, Guint pos, Guint mainXRefEntriesOffsetA, GBool *wasReconstructed, GBool reconstruct) {
+XRef::XRef(BaseStream *strA, Goffset pos, Goffset mainXRefEntriesOffsetA, GBool *wasReconstructed, GBool reconstruct) {
   Object obj;
 
   init();
@@ -313,7 +337,7 @@
 
     // read the xref table
     } else {
-      std::vector<Guint> followedXRefStm;
+      std::vector<Goffset> followedXRefStm;
       readXRef(&prevXRefOffset, &followedXRefStm, NULL);
 
       // if there was a problem with the xref table,
@@ -375,6 +399,59 @@
   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 = (Goffset *)gmalloc(streamEndsLen * sizeof(Goffset));
+    for (int i = 0; i < streamEndsLen; i++) {
+      xref->streamEnds[i] = streamEnds[i];
+    }
+  }
+  return xref;
 }
 
 int XRef::reserve(int newSize)
@@ -410,7 +487,7 @@
     if (reserve(newSize) < newSize) return size;
 
     for (int i = size; i < newSize; ++i) {
-      entries[i].offset = 0xffffffff;
+      entries[i].offset = -1;
       entries[i].type = xrefEntryNone;
       entries[i].obj.initNull ();
       entries[i].flags = 0;
@@ -430,7 +507,7 @@
 /* Read one xref table section.  Also reads the associated trailer
  * dictionary, and returns the prev pointer (if any).
  * Arguments:
- *   pos                Points to a Guint containing the offset of the XRef
+ *   pos                Points to a Goffset containing the offset of the XRef
  *                      section to be read. If a prev pointer is found, *pos is
  *                      updated with its value
  *   followedXRefStm    Used in case of nested readXRef calls to spot circular
@@ -440,7 +517,7 @@
  * Return value:
  *   gTrue if a prev pointer is found, otherwise gFalse
  */
-GBool XRef::readXRef(Guint *pos, std::vector<Guint> *followedXRefStm, std::vector<int> *xrefStreamObjsNum) {
+GBool XRef::readXRef(Goffset *pos, std::vector<Goffset> *followedXRefStm, std::vector<int> *xrefStreamObjsNum) {
   Parser *parser;
   Object obj;
   GBool more;
@@ -496,11 +573,11 @@
   return gFalse;
 }
 
-GBool XRef::readXRefTable(Parser *parser, Guint *pos, std::vector<Guint> *followedXRefStm, std::vector<int> *xrefStreamObjsNum) {
+GBool XRef::readXRefTable(Parser *parser, Goffset *pos, std::vector<Goffset> *followedXRefStm, std::vector<int> *xrefStreamObjsNum) {
   XRefEntry entry;
   GBool more;
   Object obj, obj2;
-  Guint pos2;
+  Goffset pos2;
   int first, n, i;
 
   while (1) {
@@ -529,10 +606,14 @@
       }
     }
     for (i = first; i < first + n; ++i) {
-      if (!parser->getObj(&obj, gTrue)->isInt()) {
+      parser->getObj(&obj, gTrue);
+      if (obj.isInt()) {
+	entry.offset = obj.getInt();
+      } else if (obj.isInt64()) {
+	entry.offset = obj.getInt64();
+      } else {
 	goto err1;
       }
-      entry.offset = (Guint)obj.getInt();
       obj.free();
       if (!parser->getObj(&obj, gTrue)->isInt()) {
 	goto err1;
@@ -550,7 +631,7 @@
 	goto err1;
       }
       obj.free();
-      if (entries[i].offset == 0xffffffff) {
+      if (entries[i].offset == -1) {
 	entries[i] = entry;
 	// PDF files of patents from the IBM Intellectual Property
 	// Network have a bug: the xref table claims to start at 1
@@ -560,7 +641,7 @@
 	    entries[1].type == xrefEntryFree) {
 	  i = first = 0;
 	  entries[0] = entries[1];
-	  entries[1].offset = 0xffffffff;
+	  entries[1].offset = -1;
 	}
       }
     }
@@ -573,8 +654,11 @@
 
   // get the 'Prev' pointer
   obj.getDict()->lookupNF("Prev", &obj2);
-  if (obj2.isInt()) {
-    pos2 = (Guint)obj2.getInt();
+  if (obj2.isInt() || obj2.isInt64()) {
+    if (obj2.isInt())
+      pos2 = obj2.getInt();
+    else
+      pos2 = obj2.getInt64();
     if (pos2 != *pos) {
       *pos = pos2;
       more = gTrue;
@@ -604,8 +688,12 @@
   }
 
   // check for an 'XRefStm' key
-  if (obj.getDict()->lookup("XRefStm", &obj2)->isInt()) {
-    pos2 = (Guint)obj2.getInt();
+  obj.getDict()->lookup("XRefStm", &obj2);
+  if (obj2.isInt() || obj2.isInt64()) {
+    if (obj2.isInt())
+      pos2 = obj2.getInt();
+    else
+      pos2 = obj2.getInt64();
     for (size_t i = 0; ok == gTrue && i < followedXRefStm->size(); ++i) {
       if (followedXRefStm->at(i) == pos2) {
         ok = gFalse;
@@ -632,7 +720,7 @@
   return gFalse;
 }
 
-GBool XRef::readXRefStream(Stream *xrefStr, Guint *pos) {
+GBool XRef::readXRefStream(Stream *xrefStr, Goffset *pos) {
   Dict *dict;
   int w[3];
   GBool more;
@@ -667,11 +755,14 @@
     }
     w[i] = obj2.getInt();
     obj2.free();
-    if (w[i] < 0 || w[i] > 4) {
+    if (w[i] < 0) {
       goto err1;
     }
   }
   obj.free();
+  if (w[0] > (int)sizeof(int) || w[1] > (int)sizeof(long long) || w[2] > (int)sizeof(int)) {
+    goto err1;
+  }
 
   xrefStr->reset();
   dict->lookupNF("Index", &idx);
@@ -705,7 +796,10 @@
 
   dict->lookupNF("Prev", &obj);
   if (obj.isInt()) {
-    *pos = (Guint)obj.getInt();
+    *pos = obj.getInt();
+    more = gTrue;
+  } else if (obj.isInt64()) {
+    *pos = obj.getInt64();
     more = gTrue;
   } else {
     more = gFalse;
@@ -725,7 +819,7 @@
 }
 
 GBool XRef::readXRefStreamSection(Stream *xrefStr, int *w, int first, int n) {
-  Guint offset;
+  unsigned long long offset;
   int type, gen, c, i, j;
 
   if (first + n < 0) {
@@ -758,13 +852,17 @@
       }
       offset = (offset << 8) + c;
     }
+    if (offset > (unsigned long long)GoffsetMax()) {
+      error(errSyntaxError, -1, "Offset inside xref table too large for fseek");
+      return gFalse;
+    }
     for (gen = 0, j = 0; j < w[2]; ++j) {
       if ((c = xrefStr->getChar()) == EOF) {
 	return gFalse;
       }
       gen = (gen << 8) + c;
     }
-    if (entries[i].offset == 0xffffffff) {
+    if (entries[i].offset == -1) {
       switch (type) {
       case 0:
 	entries[i].offset = offset;
@@ -795,7 +893,7 @@
   Parser *parser;
   Object newTrailerDict, obj;
   char buf[256];
-  Guint pos;
+  Goffset pos;
   int num, gen;
   int newSize;
   int streamEndsSize;
@@ -916,8 +1014,8 @@
             error(errSyntaxError, -1, "Invalid 'endstream' parameter.");
             return gFalse;
           }
-	  streamEnds = (Guint *)greallocn(streamEnds,
-					streamEndsSize, sizeof(Guint));
+	  streamEnds = (Goffset *)greallocn(streamEnds,
+					streamEndsSize, sizeof(Goffset));
         }
         streamEnds[streamEndsLen++] = pos;
       }
@@ -1036,6 +1134,7 @@
   Parser *parser;
   Object obj1, obj2, obj3;
 
+  xrefLocker();
   // check for bogus ref - this can happen in corrupted PDF files
   if (num < 0 || num >= size) {
     goto err;
@@ -1124,7 +1223,7 @@
     }
 
     if (!objStr) {
-      objStr = new ObjectStream(this, e->offset);
+      objStr = new ObjectStream(this, e->offset, recursion + 1);
       if (!objStr->isOk()) {
 	delete objStr;
 	objStr = NULL;
@@ -1151,6 +1250,14 @@
   return obj->initNull();
 }
 
+void XRef::lock() {
+  gLockMutex(&mutex);
+}
+
+void XRef::unlock() {
+  gUnlockMutex(&mutex);
+}
+
 Object *XRef::getDocInfo(Object *obj) {
   return trailerDict.dictLookup("Info", obj);
 }
@@ -1160,7 +1267,7 @@
   return trailerDict.dictLookupNF("Info", obj);
 }
 
-GBool XRef::getStreamEnd(Guint streamStart, Guint *streamEnd) {
+GBool XRef::getStreamEnd(Goffset streamStart, Goffset *streamEnd) {
   int a, b, m;
 
   if (streamEndsLen == 0 ||
@@ -1183,12 +1290,12 @@
   return gTrue;
 }
 
-int XRef::getNumEntry(Guint offset)
+int XRef::getNumEntry(Goffset offset)
 {
   if (size > 0)
   {
     int res = 0;
-    Guint resOffset = getEntry(0)->offset;
+    Goffset resOffset = getEntry(0)->offset;
     XRefEntry *e;
     for (int i = 1; i < size; ++i)
     {
@@ -1204,14 +1311,15 @@
   else return -1;
 }
 
-void XRef::add(int num, int gen, Guint offs, GBool used) {
+void XRef::add(int num, int gen, Goffset offs, GBool used) {
+  xrefLocker();
   if (num >= size) {
     if (num >= capacity) {
       entries = (XRefEntry *)greallocn(entries, num + 1, sizeof(XRefEntry));
       capacity = num + 1;
     }
     for (int i = size; i < num + 1; ++i) {
-      entries[i].offset = 0xffffffff;
+      entries[i].offset = -1;
       entries[i].type = xrefEntryFree;
       entries[i].obj.initNull ();
       entries[i].flags = 0;
@@ -1233,6 +1341,7 @@
 }
 
 void XRef::setModifiedObject (Object* o, Ref r) {
+  xrefLocker();
   if (r.num < 0 || r.num >= size) {
     error(errInternal, -1,"XRef::setModifiedObject on unknown ref: {0:d}, {1:d}\n", r.num, r.gen);
     return;
@@ -1274,13 +1383,15 @@
 }
 
 void XRef::removeIndirectObject(Ref r) {
+  xrefLocker();
   if (r.num < 0 || r.num >= size) {
     error(errInternal, -1,"XRef::removeIndirectObject on unknown ref: {0:d}, {1:d}\n", r.num, r.gen);
     return;
   }
   XRefEntry *e = getEntry(r.num);
-  if (e->type == xrefEntryFree)
+  if (e->type == xrefEntryFree) {
     return;
+  }
   e->obj.free();
   e->type = xrefEntryFree;
   e->gen++;
@@ -1339,8 +1450,8 @@
   outStr->printf("%i %i\r\n", first, count);
 }
 
-void XRef::XRefTableWriter::writeEntry(Guint offset, int gen, XRefEntryType type) {
-  outStr->printf("%010i %05i %c\r\n", offset, gen, (type==xrefEntryFree)?'f':'n');
+void XRef::XRefTableWriter::writeEntry(Goffset offset, int gen, XRefEntryType type) {
+  outStr->printf("%010lli %05i %c\r\n", (long long)offset, gen, (type==xrefEntryFree)?'f':'n');
 }
 
 void XRef::writeTableToFile(OutStream* outStr, GBool writeAllEntries) {
@@ -1360,16 +1471,18 @@
   index->arrayAdd( obj.initInt(count) );
 }
 
-void XRef::XRefStreamWriter::writeEntry(Guint offset, int gen, XRefEntryType type) {
-  char data[7];
+void XRef::XRefStreamWriter::writeEntry(Goffset offset, int gen, XRefEntryType type) {
+  char data[16];
+  int i;
   data[0] = (type==xrefEntryFree) ? 0 : 1;
-  data[1] = (offset >> 24) & 0xff;
-  data[2] = (offset >> 16) & 0xff;
-  data[3] = (offset >> 8) & 0xff;
-  data[4] = offset & 0xff;
-  data[5] = (gen >> 8) & 0xff;
-  data[6] = gen & 0xff;
-  stmBuf->append(data, 7);
+  for (i = sizeof(Goffset); i > 0; i--) {
+    data[i] = offset & 0xff;
+    offset >>= 8;
+  }
+  i = sizeof(Goffset) + 1;
+  data[i] = (gen >> 8) & 0xff;
+  data[i+1] = gen & 0xff;
+  stmBuf->append(data, i+2);
 }
 
 void XRef::writeStreamToBuffer(GooString *stmBuf, Dict *xrefDict, XRef *xref) {
@@ -1385,12 +1498,12 @@
   xrefDict->set("Index", &index);
   obj2.initArray(xref);
   obj2.arrayAdd( obj1.initInt(1) );
-  obj2.arrayAdd( obj1.initInt(4) );
+  obj2.arrayAdd( obj1.initInt(sizeof(Goffset)) );
   obj2.arrayAdd( obj1.initInt(2) );
   xrefDict->set("W", &obj2);
 }
 
-GBool XRef::parseEntry(Guint offset, XRefEntry *entry)
+GBool XRef::parseEntry(Goffset offset, XRefEntry *entry)
 {
   GBool r;
 
@@ -1400,10 +1513,14 @@
      str->makeSubStream(offset, gFalse, 20, &obj)), gTrue);
 
   Object obj1, obj2, obj3;
-  if ((parser.getObj(&obj1)->isInt()) &&
+  if (((parser.getObj(&obj1)->isInt()) ||
+       parser.getObj(&obj1)->isInt64()) &&
       (parser.getObj(&obj2)->isInt()) &&
       (parser.getObj(&obj3)->isCmd("n") || obj3.isCmd("f"))) {
-    entry->offset = (Guint) obj1.getInt();
+    if (obj1.isInt64())
+      entry->offset = obj1.getInt64();
+    else
+      entry->offset = obj1.getInt();
     entry->gen = obj2.getInt();
     entry->type = obj3.isCmd("n") ? xrefEntryUncompressed : xrefEntryFree;
     entry->obj.initNull ();
@@ -1426,7 +1543,7 @@
  * numbers of the XRef streams that have been traversed */
 void XRef::readXRefUntil(int untilEntryNum, std::vector<int> *xrefStreamObjsNum)
 {
-  std::vector<Guint> followedPrev;
+  std::vector<Goffset> followedPrev;
   while (prevXRefOffset && (untilEntryNum == -1 || entries[untilEntryNum].type == xrefEntryNone)) {
     bool followed = false;
     for (size_t j = 0; j < followedPrev.size(); j++) {
@@ -1445,7 +1562,7 @@
 
     followedPrev.push_back (prevXRefOffset);
 
-    std::vector<Guint> followedXRefStm;
+    std::vector<Goffset> followedXRefStm;
     if (!readXRef(&prevXRefOffset, &followedXRefStm, xrefStreamObjsNum)) {
         prevXRefOffset = 0;
     }
diff --git a/poppler/XRef.h b/poppler/XRef.h
index 9af4a13..c9f17c2 100644
--- a/poppler/XRef.h
+++ b/poppler/XRef.h
@@ -14,13 +14,14 @@
 // under GPL version 2 or later
 //
 // Copyright (C) 2005 Brad Hards <bradh@frogmouth.net>
-// Copyright (C) 2006, 2008, 2010-2012 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2006, 2008, 2010-2013 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2007-2008 Julien Rebetez <julienr@svn.gnome.org>
 // Copyright (C) 2007 Carlos Garcia Campos <carlosgc@gnome.org>
 // Copyright (C) 2010 Ilya Gorenbein <igorenbein@finjan.com>
 // Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
-// Copyright (C) 2012 Thomas Freitag <Thomas.Freitag@kabelmail.de>
+// Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag@kabelmail.de>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
+// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
 //
 // 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 "goo/gtypes.h"
+#include "goo/GooMutex.h"
 #include "Object.h"
 #include "Stream.h"
 
@@ -57,7 +60,7 @@
 };
 
 struct XRefEntry {
-  Guint offset;
+  Goffset offset;
   int gen;
   XRefEntryType type;
   int flags;
@@ -95,11 +98,14 @@
   // Constructor, create an empty XRef but with info dict, used for PDF writing
   XRef(Object *trailerDictA);
   // Constructor.  Read xref table from stream.
-  XRef(BaseStream *strA, Guint pos, Guint mainXRefEntriesOffsetA = 0, GBool *wasReconstructed = NULL, GBool reconstruct = false);
+  XRef(BaseStream *strA, Goffset pos, Goffset mainXRefEntriesOffsetA = 0, GBool *wasReconstructed = NULL, GBool reconstruct = false);
 
   // Destructor.
   ~XRef();
 
+  // Copy xref but with new base stream!
+  XRef *copy();
+
   // Is xref table valid?
   GBool isOk() { return ok; }
 
@@ -152,10 +158,10 @@
 
   // Get end position for a stream in a damaged file.
   // Returns false if unknown or file is not damaged.
-  GBool getStreamEnd(Guint streamStart, Guint *streamEnd);
+  GBool getStreamEnd(Goffset streamStart, Goffset *streamEnd);
 
   // Retuns the entry that belongs to the offset
-  int getNumEntry(Guint offset);
+  int getNumEntry(Goffset offset);
 
   // Scans the document and sets special flags in all xref entries. One of those
   // flags is Unencrypted, which affects how the object is fetched. Therefore,
@@ -173,17 +179,21 @@
   void setModifiedObject(Object* o, Ref r);
   Ref addIndirectObject (Object* o);
   void removeIndirectObject(Ref r);
-  void add(int num, int gen,  Guint offs, GBool used);
+  void add(int num, int gen,  Goffset offs, GBool used);
 
   // Output XRef table to stream
   void writeTableToFile(OutStream* outStr, GBool writeAllEntries);
   // 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
-  Guint start;			// offset in file (to allow for garbage
+  Goffset start;		// offset in file (to allow for garbage
 				//   at beginning of file)
   XRefEntry *entries;		// xref entries
   int capacity;			// size of <entries> array
@@ -192,7 +202,7 @@
   GBool ok;			// true if xref table is valid
   int errCode;			// error code (if <ok> is false)
   Object trailerDict;		// trailer dictionary
-  Guint *streamEnds;		// 'endstream' positions - only used in
+  Goffset *streamEnds;		// 'endstream' positions - only used in
 				//   damaged files
   int streamEndsLen;		// number of valid entries in streamEnds
   PopplerCache *objStrs;	// cached object streams
@@ -204,28 +214,32 @@
   int permFlags;		// permission bits
   Guchar fileKey[32];		// file decryption key
   GBool ownerPasswordOk;	// true if owner password is correct
-  Guint prevXRefOffset;		// position of prev XRef section (= next to read)
-  Guint mainXRefEntriesOffset;	// offset of entries in main XRef table
+  Goffset prevXRefOffset;		// position of prev XRef section (= next to read)
+  Goffset mainXRefEntriesOffset; // offset of entries in main XRef table
   GBool xRefStream;		// true if last XRef section is a stream
-  Guint mainXRefOffset;		// position of the main XRef table/stream
+  Goffset 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);
   int resize(int newSize);
-  GBool readXRef(Guint *pos, std::vector<Guint> *followedXRefStm, std::vector<int> *xrefStreamObjsNum);
-  GBool readXRefTable(Parser *parser, Guint *pos, std::vector<Guint> *followedXRefStm, std::vector<int> *xrefStreamObjsNum);
+  GBool readXRef(Goffset *pos, std::vector<Goffset> *followedXRefStm, std::vector<int> *xrefStreamObjsNum);
+  GBool readXRefTable(Parser *parser, Goffset *pos, std::vector<Goffset> *followedXRefStm, std::vector<int> *xrefStreamObjsNum);
   GBool readXRefStreamSection(Stream *xrefStr, int *w, int first, int n);
-  GBool readXRefStream(Stream *xrefStr, Guint *pos);
+  GBool readXRefStream(Stream *xrefStr, Goffset *pos);
   GBool constructXRef(GBool *wasReconstructed, GBool needCatalogDict = gFalse);
-  GBool parseEntry(Guint offset, XRefEntry *entry);
+  GBool parseEntry(Goffset offset, XRefEntry *entry);
   void readXRefUntil(int untilEntryNum, std::vector<int> *xrefStreamObjsNum = NULL);
   void markUnencrypted(Object *obj);
 
   class XRefWriter {
   public:
     virtual void startSection(int first, int count) = 0;
-    virtual void writeEntry(Guint offset, int gen, XRefEntryType type) = 0;
+    virtual void writeEntry(Goffset offset, int gen, XRefEntryType type) = 0;
     virtual ~XRefWriter() {};
   };
 
@@ -233,7 +247,7 @@
   public:
     XRefTableWriter(OutStream* outStrA);
     void startSection(int first, int count);
-    void writeEntry(Guint offset, int gen, XRefEntryType type);
+    void writeEntry(Goffset offset, int gen, XRefEntryType type);
   private:
     OutStream* outStr;
   };
@@ -242,7 +256,7 @@
   public:
     XRefStreamWriter(Object *index, GooString *stmBuf);
     void startSection(int first, int count);
-    void writeEntry(Guint offset, int gen, XRefEntryType type);
+    void writeEntry(Goffset offset, int gen, XRefEntryType type);
   private:
     Object *index;
     GooString *stmBuf;
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@kde.org>
  * Copyright (C) 2010, 2011 Hib Eris <hib@hiberis.nl>
  * Copyright (C) 2012 Koji Otani <sho@bbr.jp>
- * Copyright (C) 2012 Thomas Freitag <Thomas.Freitag@alfa.de>
+ * Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
  * Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -239,8 +239,10 @@
 	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 @@
 			strObj.streamClose();
 		}
 		strObj.free();
+		delete xref;
 	}
 	return result;
     }
@@ -265,7 +268,8 @@
 	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 @@
 	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 @@
 	    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 @@
 
     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 @@
         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 c6d56ed..f7c2427 100644
--- a/qt4/src/poppler-page.cc
+++ b/qt4/src/poppler-page.cc
@@ -13,7 +13,7 @@
  * Copyright (C) 2012 Tobias Koenig <tokoe@kdab.com>
  * Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
  * Copyright (C) 2012 Adam Reichold <adamreichold@myopera.com>
- * Copyright (C) 2012 Thomas Freitag <Thomas.Freitag@alfa.de>
+ * Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag@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
@@ -229,7 +229,8 @@
 
   // fetch ourselves a textpage
   TextOutputDev td(NULL, gTrue, 0, gFalse, gFalse);
-  parentDoc->doc->displayPage( &td, index + 1, 72, 72, rotation, false, true, false );
+  parentDoc->doc->displayPage( &td, index + 1, 72, 72, rotation, false, true, false,
+    NULL, NULL, NULL, NULL, gTrue);
   TextPage *textPage=td.takeText();
   
   return textPage;
@@ -258,10 +259,62 @@
     case Poppler::Document::SplashBackend:
     {
 #if defined(HAVE_SPLASH)
-      SplashOutputDev *splash_output = static_cast<SplashOutputDev *>(m_page->parentDoc->getOutputDev());
+      SplashColor bgColor;
+      GBool overprint = gFalse;
+#if defined(SPLASH_CMYK)
+      overprint = m_page->parentDoc->m_hints & Document::OverprintPreview ? gTrue : gFalse;
+      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;
+      SplashThinLineMode thinLineMode = splashThinLineDefault;
+      if (m_page->parentDoc->m_hints & Document::ThinLineShape) thinLineMode = splashThinLineShape;
+      if (m_page->parentDoc->m_hints & Document::ThinLineSolid) thinLineMode = splashThinLineSolid;
+
+      SplashOutputDev * splash_output = new SplashOutputDev(
+#if defined(SPLASH_CMYK)
+                      (overprint) ? splashModeDeviceN8 : splashModeXBGR8,
+#else
+                      splashModeXBGR8,
+#endif 
+                      4, gFalse, bgColor, gTrue, AA, thinLineMode, overprint);
+
+      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 +344,7 @@
         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 +433,8 @@
   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 +535,8 @@
   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..308a966 100644
--- a/qt4/src/poppler-private.cc
+++ b/qt4/src/poppler-private.cc
@@ -2,6 +2,8 @@
  * Copyright (C) 2005, Net Integration Technologies, Inc.
  * Copyright (C) 2006, 2011 by Albert Astals Cid <aacid@kde.org>
  * Copyright (C) 2008, 2010, 2011 by Pino Toscano <pino@kde.org>
+ * Copyright (C) 2013 by Thomas Freitag <Thomas.Freitag@alfa.de>
+ * Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
  * Inspired on code by
  * Copyright (C) 2004 by Albert Astals Cid <tsdgeos@terra.es>
  * Copyright (C) 2004 by Enrico Ros <eros.kde@email.it>
@@ -53,7 +55,7 @@
         Debug::debugClosure = closure;
     }
 
-    void qt4ErrorFunction(void * /*data*/, ErrorCategory /*category*/, int pos, char *msg)
+    void qt4ErrorFunction(void * /*data*/, ErrorCategory /*category*/, Goffset pos, char *msg)
     {
         QString emsg;
 
@@ -226,7 +228,6 @@
         qDeleteAll(m_embeddedFiles);
         delete (OptContentModel *)m_optContentModel;
         delete doc;
-        delete m_outputDev;
         delete m_fontInfoIterator;
     
         count --;
@@ -241,7 +242,6 @@
     {
         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@kde.org>
  * Copyright (C) 2011 Andreas Hartmetz <ahartmetz@gmail.com>
  * Copyright (C) 2011 Hib Eris <hib@hiberis.nl>
- * Copyright (C) 2012 Thomas Freitag <Thomas.Freitag@alfa.de>
+ * Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
  * Inspired on code by
  * Copyright (C) 2004 by Albert Astals Cid <tsdgeos@terra.es>
  * Copyright (C) 2004 by Enrico Ros <eros.kde@email.it>
@@ -113,82 +113,11 @@
 	
 	~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 @@
 	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/qt4/src/poppler-ps-converter.cc b/qt4/src/poppler-ps-converter.cc
index 63fb7b4..ff8af65 100644
--- a/qt4/src/poppler-ps-converter.cc
+++ b/qt4/src/poppler-ps-converter.cc
@@ -4,6 +4,7 @@
  * Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
  * Copyright (C) 2011 Glad Deschrijver <glad.deschrijver@gmail.com>
  * Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
+ * Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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
@@ -253,7 +254,7 @@
 			                              NULL,
 			                              NULL,
 			                              annotDisplayDecideCbk,
-			                              &showAnnotations);
+			                              &showAnnotations, gTrue);
 			if (d->pageConvertedCallback)
 				(*d->pageConvertedCallback)(page, d->pageConvertedPayload);
 		}
diff --git a/qt4/src/poppler-qiodeviceoutstream-private.h b/qt4/src/poppler-qiodeviceoutstream-private.h
index e7faa29..d0d2007 100644
--- a/qt4/src/poppler-qiodeviceoutstream-private.h
+++ b/qt4/src/poppler-qiodeviceoutstream-private.h
@@ -1,5 +1,6 @@
 /* poppler-qiodevicestream-private.h: Qt4 interface to poppler
  * Copyright (C) 2008, Pino Toscano <pino@kde.org>
+ * Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
  *
  * 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
@@ -33,7 +34,7 @@
     virtual ~QIODeviceOutStream();
 
     virtual void close();
-    virtual int getPos();
+    virtual Goffset getPos();
     virtual void put(char c);
     virtual void printf(const char *format, ...);
 
diff --git a/qt4/src/poppler-qiodeviceoutstream.cc b/qt4/src/poppler-qiodeviceoutstream.cc
index b0054af..e3e9f89 100644
--- a/qt4/src/poppler-qiodeviceoutstream.cc
+++ b/qt4/src/poppler-qiodeviceoutstream.cc
@@ -1,5 +1,6 @@
 /* poppler-qiodevicestream.cc: Qt4 interface to poppler
  * Copyright (C) 2008, Pino Toscano <pino@kde.org>
+ * Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
  *
  * 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
@@ -39,9 +40,9 @@
 {
 }
 
-int QIODeviceOutStream::getPos()
+Goffset QIODeviceOutStream::getPos()
 {
-  return (int)m_device->pos();
+  return m_device->pos();
 }
 
 void QIODeviceOutStream::put(char c)
diff --git a/qt4/src/poppler-qt4.h b/qt4/src/poppler-qt4.h
index f4f6fc6..1e3efca 100644
--- a/qt4/src/poppler-qt4.h
+++ b/qt4/src/poppler-qt4.h
@@ -13,7 +13,7 @@
  * Copyright (C) 2012, Fabio D'Urso <fabiodurso@hotmail.it>
  * Copyright (C) 2012, Tobias Koenig <tobias.koenig@kdab.com>
  * Copyright (C) 2012 Adam Reichold <adamreichold@myopera.com>
- * Copyright (C) 2012 Thomas Freitag <Thomas.Freitag@alfa.de>
+ * Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag@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
@@ -848,7 +848,9 @@
 	    TextAntialiasing = 0x00000002,  ///< Antialiasing for text
 	    TextHinting = 0x00000004,       ///< Hinting for text \since 0.12.1
 	    TextSlightHinting = 0x00000008, ///< Lighter hinting for text when combined with TextHinting \since 0.18
-	    OverprintPreview = 0x00000010   ///< Overprint preview \since 0.22
+	    OverprintPreview = 0x00000010,  ///< Overprint preview \since 0.22
+	    ThinLineSolid = 0x00000020,     ///< Enhance thin lines solid \since 0.24
+	    ThinLineShape = 0x00000040      ///< Enhance thin lines shape. Wins over ThinLineSolid \since 0.24
 	};
 	Q_DECLARE_FLAGS( RenderHints, RenderHint )
 
diff --git a/qt4/tests/.gitignore b/qt4/tests/.gitignore
index 05b2dbf..5580611 100644
--- a/qt4/tests/.gitignore
+++ b/qt4/tests/.gitignore
@@ -16,6 +16,8 @@
 check_attachments
 check_dateConversion
 check_fonts
+check_goostring
+check_lexer
 check_links
 check_metadata
 check_optcontent
diff --git a/qt4/tests/CMakeLists.txt b/qt4/tests/CMakeLists.txt
index 187870f..9512617 100644
--- a/qt4/tests/CMakeLists.txt
+++ b/qt4/tests/CMakeLists.txt
@@ -57,6 +57,7 @@
 qt4_add_qtest(check_search check_search.cpp)
 qt4_add_qtest(check_actualtext check_actualtext.cpp)
 qt4_add_qtest(check_lexer check_lexer.cpp)
+qt4_add_qtest(check_pagelabelinfo check_pagelabelinfo.cpp)
 qt4_add_qtest(check_goostring check_goostring.cpp)
 if (NOT WIN32)
   qt4_add_qtest(check_strings check_strings.cpp)
diff --git a/qt4/tests/Makefile.am b/qt4/tests/Makefile.am
index 3dc6e13..05d2754 100644
--- a/qt4/tests/Makefile.am
+++ b/qt4/tests/Makefile.am
@@ -139,6 +139,10 @@
 check_lexer.$(OBJEXT): check_lexer.moc
 check_lexer_LDADD = $(LDADDS) $(POPPLER_QT4_TEST_LIBS)
 
+check_pagelabelinfo_SOURCES = check_pagelabelinfo.cpp
+check_pagelabelinfo.$(OBJEXT): check_pagelabelinfo.moc
+check_pagelabelinfo_LDADD = $(LDADDS) $(POPPLER_QT4_TEST_LIBS)
+
 check_goostring_SOURCES = check_goostring.cpp
 check_goostring.$(OBJEXT): check_goostring.moc
 check_goostring_LDADD = $(LDADDS) $(POPPLER_QT4_TEST_LIBS)
diff --git a/qt4/tests/check_lexer.cpp b/qt4/tests/check_lexer.cpp
index 1ae849f..ea834c8 100644
--- a/qt4/tests/check_lexer.cpp
+++ b/qt4/tests/check_lexer.cpp
@@ -12,7 +12,7 @@
 
 void TestLexer::testNumbers()
 {
-    char *data = "0 1 -1 2147483647 -2147483647 2147483648 -2147483648 4294967297 -2147483649 0.1 1.1 -1.1 2147483647.1 -2147483647.1 2147483648.1 -2147483648.1 4294967297.1 -2147483649.1";
+    char *data = "0 1 -1 2147483647 -2147483647 2147483648 -2147483648 4294967297 -2147483649 0.1 1.1 -1.1 2147483647.1 -2147483647.1 2147483648.1 -2147483648.1 4294967297.1 -2147483649.1 9223372036854775807 18446744073709551615";
     Object dummy;
     MemStream *stream = new MemStream(data, 0, strlen(data), &dummy);
     Lexer *lexer = new Lexer(NULL, stream);
@@ -46,8 +46,8 @@
     obj.free();
     
     lexer->getObj(&obj);
-    QCOMPARE(obj.getType(), objUint);
-    QCOMPARE(obj.getUint(), 2147483648u);
+    QCOMPARE(obj.getType(), objInt64);
+    QCOMPARE(obj.getInt64(), 2147483648ll);
     obj.free();
       
     lexer->getObj(&obj);
@@ -56,13 +56,13 @@
     obj.free();
     
     lexer->getObj(&obj);
-    QCOMPARE(obj.getType(), objReal);
-    QCOMPARE(obj.getReal(), 4294967297.);
+    QCOMPARE(obj.getType(), objInt64);
+    QCOMPARE(obj.getInt64(), 4294967297ll);
     obj.free();
     
     lexer->getObj(&obj);
-    QCOMPARE(obj.getType(), objReal);
-    QCOMPARE(obj.getReal(), -2147483649.);
+    QCOMPARE(obj.getType(), objInt64);
+    QCOMPARE(obj.getInt64(), -2147483649ll);
     obj.free();
 
     lexer->getObj(&obj);
@@ -110,6 +110,16 @@
     QCOMPARE(obj.getReal(), -2147483649.1);
     obj.free();
 
+    lexer->getObj(&obj);
+    QCOMPARE(obj.getType(), objInt64);
+    QCOMPARE(obj.getInt64(), 9223372036854775807ll);
+    obj.free();
+
+    lexer->getObj(&obj);
+    QCOMPARE(obj.getType(), objReal);
+    QCOMPARE(obj.getReal(), 18446744073709551616.);
+    obj.free();
+
     delete lexer;
 }
 
diff --git a/qt4/tests/check_pagelabelinfo.cpp b/qt4/tests/check_pagelabelinfo.cpp
new file mode 100644
index 0000000..4eb1ec3
--- /dev/null
+++ b/qt4/tests/check_pagelabelinfo.cpp
@@ -0,0 +1,43 @@
+#include <QtTest/QtTest>
+
+#include "PageLabelInfo_p.h"
+
+class TestPageLabelInfo : public QObject
+{
+    Q_OBJECT
+private slots:
+    void testToRoman();
+    void testFromRoman();
+    void testToLatin();
+    void testFromLatin();
+};
+
+void TestPageLabelInfo::testToRoman()
+{
+    GooString str;
+    toRoman(177, &str, gFalse);
+    QCOMPARE (str.getCString(), "clxxvii");
+}
+
+void TestPageLabelInfo::testFromRoman()
+{
+    GooString roman("clxxvii");
+    QCOMPARE(fromRoman(roman.getCString()), 177);
+}
+
+void TestPageLabelInfo::testToLatin()
+{
+    GooString str;
+    toLatin(54, &str, gFalse);
+    QCOMPARE(str.getCString(), "bbb");
+}
+
+void TestPageLabelInfo::testFromLatin()
+{
+    GooString latin("ddd");
+    QCOMPARE(fromLatin(latin.getCString()), 56);
+}
+
+QTEST_MAIN(TestPageLabelInfo)
+#include "check_pagelabelinfo.moc"
+
diff --git a/splash/Splash.cc b/splash/Splash.cc
index 0a2b212..fd618cd 100644
--- a/splash/Splash.cc
+++ b/splash/Splash.cc
@@ -13,7 +13,7 @@
 //
 // Copyright (C) 2005-2013 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2005 Marco Pesenti Gritti <mpg@redhat.com>
-// Copyright (C) 2010-2012 Thomas Freitag <Thomas.Freitag@alfa.de>
+// Copyright (C) 2010-2013 Thomas Freitag <Thomas.Freitag@alfa.de>
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger@googlemail.com>
 // Copyright (C) 2011, 2012 William Bader <williambader@hotmail.com>
 // Copyright (C) 2012 Markus Trippelsdorf <markus@trippelsdorf.de>
@@ -1451,7 +1451,7 @@
   }
 }
 
-inline void Splash::drawAALine(SplashPipe *pipe, int x0, int x1, int y) {
+inline void Splash::drawAALine(SplashPipe *pipe, int x0, int x1, int y, GBool adjustLine, Guchar lineOpacity) {
 #if splashAASize == 4
   static int bitCount4[16] = { 0, 1, 1, 2, 1, 2, 2, 3,
 			       1, 2, 2, 3, 2, 3, 3, 4 };
@@ -1494,7 +1494,7 @@
 #endif
 
     if (t != 0) {
-      pipe->shape = (double)aaGamma[t];
+      pipe->shape = (adjustLine) ? div255((int) lineOpacity * (double)aaGamma[t]) : (double)aaGamma[t];
       (this->*pipe->run)(pipe);
       updateModX(x);
       updateModY(y);
@@ -1543,6 +1543,7 @@
     aaBuf = NULL;
   }
   minLineWidth = 0;
+  thinLineMode = splashThinLineDefault;
   clearModRegion();
   debugMode = gFalse;
 }
@@ -1569,6 +1570,7 @@
     aaBuf = NULL;
   }
   minLineWidth = 0;
+  thinLineMode = splashThinLineDefault;
   clearModRegion();
   debugMode = gFalse;
 }
@@ -2358,6 +2360,31 @@
   return fillWithPattern(path, eo, state->fillPattern, state->fillAlpha);
 }
 
+inline void Splash::getBBoxFP(SplashPath *path, SplashCoord *xMinA, SplashCoord *yMinA,
+				   SplashCoord *xMaxA, SplashCoord *yMaxA) {
+  SplashCoord xMinFP, yMinFP, xMaxFP, yMaxFP, tx, ty;
+
+  // make compiler happy:
+  xMinFP = xMaxFP = yMinFP = yMaxFP = 0;
+  for (int i = 0; i < path->length; ++i) {
+    transform(state->matrix, path->pts[i].x, path->pts[i].y, &tx, &ty);
+    if (i == 0) {
+      xMinFP = xMaxFP = tx;
+      yMinFP = yMaxFP = ty;
+    } else {
+      if (tx < xMinFP) xMinFP = tx;
+      if (tx > xMaxFP) xMaxFP = tx;
+      if (ty < yMinFP) yMinFP = ty;
+      if (ty > yMaxFP) yMaxFP = ty;
+    }
+  }
+
+  *xMinA = xMinFP;
+  *yMinA = yMinFP;
+  *xMaxA = xMaxFP;
+  *yMaxA = yMaxFP;
+}
+
 SplashError Splash::fillWithPattern(SplashPath *path, GBool eo,
 				    SplashPattern *pattern,
 				    SplashCoord alpha) {
@@ -2366,6 +2393,8 @@
   SplashXPathScanner *scanner;
   int xMinI, yMinI, xMaxI, yMaxI, x0, x1, y;
   SplashClipResult clipRes, clipRes2;
+  GBool adjustLine = gFalse; 
+  int linePosI = 0;
 
   if (path->length == 0) {
     return splashErrEmptyPath;
@@ -2398,7 +2427,24 @@
     }
   }
 
-  xPath = new SplashXPath(path, state->matrix, state->flatness, gTrue);
+  if (thinLineMode != splashThinLineDefault) {
+    if (state->clip->getXMinI() == state->clip->getXMaxI()) {
+      linePosI = state->clip->getXMinI();
+      adjustLine = gTrue;
+    } else if (state->clip->getXMinI() == state->clip->getXMaxI() - 1) {
+      adjustLine = gTrue;
+      linePosI = splashFloor(state->clip->getXMin() + state->lineWidth);
+    } else if (state->clip->getYMinI() == state->clip->getYMaxI()) {
+      linePosI = state->clip->getYMinI();
+      adjustLine = gTrue;
+    } else if (state->clip->getYMinI() == state->clip->getYMaxI() - 1) {
+      adjustLine = gTrue;
+      linePosI = splashFloor(state->clip->getYMin() + state->lineWidth);
+    }
+  }
+
+  xPath = new SplashXPath(path, state->matrix, state->flatness, gTrue, 
+    adjustLine, linePosI);
   if (vectorAntialias && !inShading) {
     xPath->aaScale();
   }
@@ -2418,6 +2464,16 @@
     scanner->getBBox(&xMinI, &yMinI, &xMaxI, &yMaxI);
   }
 
+  if (eo && (yMinI == yMaxI || xMinI == xMaxI) && thinLineMode != splashThinLineDefault) {
+    SplashCoord delta, xMinFP, yMinFP, xMaxFP, yMaxFP;
+    getBBoxFP(path, &xMinFP, &yMinFP, &xMaxFP, &yMaxFP);
+    delta = (yMinI == yMaxI) ? yMaxFP - yMinFP : xMaxFP - xMinFP;
+    if (delta < 0.2) {
+      opClipRes = splashClipAllOutside;
+      return splashOk;
+    }
+  }
+
   // check clipping
   if ((clipRes = state->clip->testRect(xMinI, yMinI, xMaxI, yMaxI))
       != splashClipAllOutside) {
@@ -2431,11 +2487,21 @@
     // draw the spans
     if (vectorAntialias && !inShading) {
       for (y = yMinI; y <= yMaxI; ++y) {
-	scanner->renderAALine(aaBuf, &x0, &x1, y);
+	scanner->renderAALine(aaBuf, &x0, &x1, y, thinLineMode != splashThinLineDefault && xMinI == xMaxI);
 	if (clipRes != splashClipAllInside) {
-	  state->clip->clipAALine(aaBuf, &x0, &x1, y);
+	  state->clip->clipAALine(aaBuf, &x0, &x1, y, thinLineMode != splashThinLineDefault && xMinI == xMaxI);
 	}
-	drawAALine(&pipe, x0, x1, y);
+	Guchar lineShape = 255;
+	GBool adjustLine = gFalse;
+	if (thinLineMode == splashThinLineShape && (xMinI == xMaxI || yMinI == yMaxI)) {
+	  // compute line shape for thin lines:
+	  SplashCoord mx, my, delta;
+	  transform(state->matrix, 0, 0, &mx, &my);
+	  transform(state->matrix, state->lineWidth, 0, &delta, &my);
+	  adjustLine = gTrue;
+	  lineShape = clip255((delta - mx) * 255);
+	}
+	drawAALine(&pipe, x0, x1, y, adjustLine, lineShape);
       }
     } else {
       for (y = yMinI; y <= yMaxI; ++y) {
diff --git a/splash/Splash.h b/splash/Splash.h
index c31dbc8..8bcd1db 100644
--- a/splash/Splash.h
+++ b/splash/Splash.h
@@ -13,7 +13,7 @@
 //
 // Copyright (C) 2005 Marco Pesenti Gritti <mpg@redhat.com>
 // Copyright (C) 2007, 2011 Albert Astals Cid <aacid@kde.org>
-// Copyright (C) 2010-2012 Thomas Freitag <Thomas.Freitag@alfa.de>
+// Copyright (C) 2010-2013 Thomas Freitag <Thomas.Freitag@alfa.de>
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger@googlemail.com>
 // Copyright (C) 2012 Adrian Johnson <ajohnson@redneon.com>
 //
@@ -248,6 +248,10 @@
   // Set the minimum line width.
   void setMinLineWidth(SplashCoord w) { minLineWidth = w; }
 
+  // Setter/Getter for thin line mode
+  void setThinLineMode(SplashThinLineMode thinLineModeA) { thinLineMode = thinLineModeA; }
+  SplashThinLineMode getThinLineMode() { return thinLineMode; }
+
   // Get a bounding box which includes all modifications since the
   // last call to clearModRegion.
   void getModRegion(int *xMin, int *yMin, int *xMax, int *yMax)
@@ -307,7 +311,7 @@
   void drawAAPixelInit();
   void drawAAPixel(SplashPipe *pipe, int x, int y);
   void drawSpan(SplashPipe *pipe, int x0, int x1, int y, GBool noClip);
-  void drawAALine(SplashPipe *pipe, int x0, int x1, int y);
+  void drawAALine(SplashPipe *pipe, int x0, int x1, int y, GBool adjustLine = gFalse, Guchar lineOpacity = 0);
   void transform(SplashCoord *matrix, SplashCoord xi, SplashCoord yi,
 		 SplashCoord *xo, SplashCoord *yo);
   void updateModX(int x);
@@ -323,6 +327,7 @@
 		    SplashCoord *matrix, SplashCoord flatness2,
 		    SplashPath *fPath);
   SplashPath *makeDashedPath(SplashPath *xPath);
+  void getBBoxFP(SplashPath *path, SplashCoord *xMinA, SplashCoord *yMinA, SplashCoord *xMaxA, SplashCoord *yMaxA);
   SplashError fillWithPattern(SplashPath *path, GBool eo,
 			      SplashPattern *pattern, SplashCoord alpha);
   GBool pathAllOutside(SplashPath *path);
@@ -409,6 +414,7 @@
   int alpha0X, alpha0Y;		// offset within alpha0Bitmap
   SplashCoord aaGamma[splashAASize * splashAASize + 1];
   SplashCoord minLineWidth;
+  SplashThinLineMode thinLineMode;
   int modXMin, modYMin, modXMax, modYMax;
   SplashClipResult opClipRes;
   GBool vectorAntialias;
diff --git a/splash/SplashClip.cc b/splash/SplashClip.cc
index fb18831..85c6b11 100644
--- a/splash/SplashClip.cc
+++ b/splash/SplashClip.cc
@@ -12,6 +12,7 @@
 // under GPL version 2 or later
 //
 // Copyright (C) 2010 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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
@@ -334,7 +335,7 @@
   return splashClipAllInside;
 }
 
-void SplashClip::clipAALine(SplashBitmap *aaBuf, int *x0, int *x1, int y) {
+void SplashClip::clipAALine(SplashBitmap *aaBuf, int *x0, int *x1, int y, GBool adjustVertLine) {
   int xx0, xx1, xx, yy, i;
   SplashColorPtr p;
 
@@ -351,7 +352,7 @@
       for (xx = xx0; xx + 7 < xx1; xx += 8) {
 	*p++ = 0;
       }
-      if (xx < xx1) {
+      if (xx < xx1 && !adjustVertLine) {
 	*p &= 0xff >> (xx1 & 7);
       }
     }
@@ -364,7 +365,7 @@
     xx0 = 0;
   }
   xx1 = (*x1 + 1) * splashAASize;
-  if (xx0 < xx1) {
+  if (xx0 < xx1 && !adjustVertLine) {
     for (yy = 0; yy < splashAASize; ++yy) {
       p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx0 >> 3);
       xx = xx0;
diff --git a/splash/SplashClip.h b/splash/SplashClip.h
index 3eb2d78..5c0fdba 100644
--- a/splash/SplashClip.h
+++ b/splash/SplashClip.h
@@ -12,6 +12,7 @@
 // under GPL version 2 or later
 //
 // Copyright (C) 2010 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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
@@ -116,7 +117,8 @@
   // Clips an anti-aliased line by setting pixels to zero.  On entry,
   // all non-zero pixels are between <x0> and <x1>.  This function
   // will update <x0> and <x1>.
-  void clipAALine(SplashBitmap *aaBuf, int *x0, int *x1, int y);
+  void clipAALine(SplashBitmap *aaBuf, int *x0, int *x1, int y,
+    GBool adjustVertLine = gFalse);
 
   // Get the rectangle part of the clip region.
   SplashCoord getXMin() { return xMin; }
diff --git a/splash/SplashTypes.h b/splash/SplashTypes.h
index 531b945..fa4a379 100644
--- a/splash/SplashTypes.h
+++ b/splash/SplashTypes.h
@@ -13,7 +13,7 @@
 //
 // Copyright (C) 2006, 2010 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2008 Tomas Are Haavet <tomasare@gmail.com>
-// Copyright (C) 2009, 2011, 2012 Thomas Freitag <Thomas.Freitag@alfa.de>
+// Copyright (C) 2009, 2011-2013 Thomas Freitag <Thomas.Freitag@alfa.de>
 // Copyright (C) 2009 Stefan Thomas <thomas@eload24.com>
 // Copyright (C) 2010 William Bader <williambader@hotmail.com>
 //
@@ -76,6 +76,12 @@
 #endif
 };
 
+enum SplashThinLineMode {
+  splashThinLineDefault,  // if SA on: draw solid if requested line width, transformed into 
+                          // device space, is less than half a pixel and a shaped line else
+  splashThinLineSolid,     // draw line solid at least with 1 pixel 
+  splashThinLineShape     // draw line shaped at least with 1 pixel
+};
 // number of components in each color mode
 // (defined in SplashState.cc)
 extern int splashColorModeNComps[];
diff --git a/splash/SplashXPath.cc b/splash/SplashXPath.cc
index b82d355..27106ee 100644
--- a/splash/SplashXPath.cc
+++ b/splash/SplashXPath.cc
@@ -13,6 +13,7 @@
 //
 // Copyright (C) 2010 Paweł Wiejacha <pawel.wiejacha@gmail.com>
 // Copyright (C) 2010, 2011 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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
@@ -66,7 +67,8 @@
 //------------------------------------------------------------------------
 
 SplashXPath::SplashXPath(SplashPath *path, SplashCoord *matrix,
-			 SplashCoord flatness, GBool closeSubpaths) {
+			 SplashCoord flatness, GBool closeSubpaths,
+			 GBool adjustLines, int linePosI) {
   SplashPathHint *hint;
   SplashXPathPoint *pts;
   SplashXPathAdjust *adjusts, *adjust;
@@ -127,7 +129,15 @@
       x0 = splashRound(adj0);
       x1 = splashRound(adj1);
       if (x1 == x0) {
-	x1 = x1 + 1;
+        if (adjustLines) {
+          // the adjustment moves thin lines (clip rectangle with
+          // empty width or height) out of clip area, here we need
+          // a special adjustment:
+          x0 = linePosI;
+          x1 = x0 + 1;
+        } else {
+          x1 = x1 + 1;
+        }
       }
       adjusts[i].x0 = (SplashCoord)x0;
       adjusts[i].x1 = (SplashCoord)x1 - 0.01;
diff --git a/splash/SplashXPath.h b/splash/SplashXPath.h
index db06978..1c7040d 100644
--- a/splash/SplashXPath.h
+++ b/splash/SplashXPath.h
@@ -4,6 +4,20 @@
 //
 //========================================================================
 
+//========================================================================
+//
+// Modified under the Poppler project - http://poppler.freedesktop.org
+//
+// All changes made under the Poppler project to this file are licensed
+// under GPL version 2 or later
+//
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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
+//
+//========================================================================
+
 #ifndef SPLASHXPATH_H
 #define SPLASHXPATH_H
 
@@ -50,7 +64,8 @@
   // space, via <matrix>.  If <closeSubpaths> is true, closes all open
   // subpaths.
   SplashXPath(SplashPath *path, SplashCoord *matrix,
-	      SplashCoord flatness, GBool closeSubpaths);
+	      SplashCoord flatness, GBool closeSubpaths,
+	      GBool adjustLines = gFalse, int linePosI = 0);
 
   // Copy an expanded path.
   SplashXPath *copy() { return new SplashXPath(this); }
diff --git a/splash/SplashXPathScanner.cc b/splash/SplashXPathScanner.cc
index 738cef7..0fd5ccd 100644
--- a/splash/SplashXPathScanner.cc
+++ b/splash/SplashXPathScanner.cc
@@ -13,6 +13,7 @@
 //
 // Copyright (C) 2008, 2010 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2010 Paweł Wiejacha <pawel.wiejacha@gmail.com>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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
@@ -367,7 +368,7 @@
 }
 
 void SplashXPathScanner::renderAALine(SplashBitmap *aaBuf,
-				      int *x0, int *x1, int y) {
+				      int *x0, int *x1, int y, GBool adjustVertLine) {
   int xx0, xx1, xx, xxMin, xxMax, yy, interEnd;
   Guchar mask;
   SplashColorPtr p;
@@ -418,8 +419,8 @@
 	  xx = xx0;
 	  p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx >> 3);
 	  if (xx & 7) {
-	    mask = 0xff >> (xx & 7);
-	    if ((xx & ~7) == (xx1 & ~7)) {
+	    mask = adjustVertLine ? 0xff : 0xff >> (xx & 7);
+	    if (!adjustVertLine && (xx & ~7) == (xx1 & ~7)) {
 	      mask &= (Guchar)(0xff00 >> (xx1 & 7));
 	    }
 	    *p++ |= mask;
@@ -429,7 +430,7 @@
 	    *p++ |= 0xff;
 	  }
 	  if (xx < xx1) {
-	    *p |= (Guchar)(0xff00 >> (xx1 & 7));
+	    *p |= adjustVertLine ? 0xff : (Guchar)(0xff00 >> (xx1 & 7));
 	  }
 	}
 	if (xx0 < xxMin) {
diff --git a/splash/SplashXPathScanner.h b/splash/SplashXPathScanner.h
index 719fae4..b59e306 100644
--- a/splash/SplashXPathScanner.h
+++ b/splash/SplashXPathScanner.h
@@ -4,6 +4,20 @@
 //
 //========================================================================
 
+//========================================================================
+//
+// Modified under the Poppler project - http://poppler.freedesktop.org
+//
+// All changes made under the Poppler project to this file are licensed
+// under GPL version 2 or later
+//
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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
+//
+//========================================================================
+
 #ifndef SPLASHXPATHSCANNER_H
 #define SPLASHXPATHSCANNER_H
 
@@ -60,7 +74,8 @@
 
   // Renders one anti-aliased line into <aaBuf>.  Returns the min and
   // max x coordinates with non-zero pixels in <x0> and <x1>.
-  void renderAALine(SplashBitmap *aaBuf, int *x0, int *x1, int y);
+  void renderAALine(SplashBitmap *aaBuf, int *x0, int *x1, int y,
+    GBool adjustVertLine = gFalse);
 
   // Clips an anti-aliased line by setting pixels to zero.  On entry,
   // all non-zero pixels are between <x0> and <x1>.  This function
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 @@
 
 void GDKSplashOutputDev::clear() {
   startDoc(NULL);
-  startPage(0, NULL);
+  startPage(0, NULL, NULL);
 }
 
 void GDKSplashOutputDev::endPage() {
diff --git a/test/pdf-fullrewrite.cc b/test/pdf-fullrewrite.cc
index 2b912f7..8108372 100644
--- a/test/pdf-fullrewrite.cc
+++ b/test/pdf-fullrewrite.cc
@@ -149,6 +149,7 @@
       }
     }
     case objInt:
+    case objInt64:
     case objReal:
     {
       if (!objB->isNum()) {
@@ -159,14 +160,6 @@
         return (-0.01 < diff) && (diff < 0.01);
       }
     }
-    case objUint:
-    {
-      if (objB->getType() != objUint) {
-        return gFalse;
-      } else {
-        return (objA->getUint() == objB->getUint());
-      }
-    }
     case objString:
     {
       if (objB->getType() != objString) {
diff --git a/test/perf-test.cc b/test/perf-test.cc
index cb97bcf..da14a7c 100644
--- a/test/perf-test.cc
+++ b/test/perf-test.cc
@@ -744,7 +744,7 @@
 #define _vsnprintf vsnprintf

 #endif

 

-void my_error(void *, ErrorCategory, int pos, char *msg) {

+void my_error(void *, ErrorCategory, Goffset pos, char *msg) {

 #if 0

     char        buf[4096], *p = buf;

 

@@ -754,7 +754,7 @@
     }

 

     if (pos >= 0) {

-        p += _snprintf(p, sizeof(buf)-1, "Error (%d): ", pos);

+      p += _snprintf(p, sizeof(buf)-1, "Error (%lld): ", (long long)pos);

         *p   = '\0';

         OutputDebugString(p);

     } else {

@@ -771,7 +771,7 @@
     OutputDebugString(buf);

 

     if (pos >= 0) {

-        p += _snprintf(p, sizeof(buf)-1, "Error (%d): ", pos);

+        p += _snprintf(p, sizeof(buf)-1, "Error (%lld): ", (long long)pos);

         *p   = '\0';

         OutputDebugString(buf);

         if (gErrFile)

diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt
index 06378bd..609f7ed 100644
--- a/utils/CMakeLists.txt
+++ b/utils/CMakeLists.txt
@@ -36,6 +36,9 @@
   if(LCMS_FOUND)
     target_link_libraries(pdftocairo ${LCMS_LIBRARIES})
   endif(LCMS_FOUND)
+  if(HAVE_PTHREAD)
+    target_link_libraries(pdftocairo -lpthread)
+  endif()
   if(LCMS2_FOUND)
     target_link_libraries(pdftocairo ${LCMS2_LIBRARIES})
   endif(LCMS2_FOUND)
diff --git a/utils/HtmlOutputDev.cc b/utils/HtmlOutputDev.cc
index 9eaab42..03864b5 100644
--- a/utils/HtmlOutputDev.cc
+++ b/utils/HtmlOutputDev.cc
@@ -34,6 +34,7 @@
 // Copyright (C) 2012 Ihar Filipau <thephilips@gmail.com>
 // Copyright (C) 2012 Gerald Schmidt <solahcin@gmail.com>
 // Copyright (C) 2012 Pino Toscano <pino@kde.org>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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 @@
       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@chegg.com>
 // Copyright (C) 2012 Igor Slepchin <igor.redhat@gmail.com>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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 @@
 
 
   // 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@gnome.org>
 // Copyright (C) 2010 Jakob Voss <jakob.voss@gbv.de>
 // Copyright (C) 2012 Adrian Johnson <ajohnson@redneon.com>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@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 @@
   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
diff --git a/utils/pdfinfo.cc b/utils/pdfinfo.cc
index 10a6c31..14e4f6c 100644
--- a/utils/pdfinfo.cc
+++ b/utils/pdfinfo.cc
@@ -17,7 +17,7 @@
 // Copyright (C) 2007-2010, 2012 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
 // Copyright (C) 2011 Vittal Aithal <vittal.aithal@cognidox.com>
-// Copyright (C) 2012 Adrian Johnson <ajohnson@redneon.com>
+// Copyright (C) 2012, 2013 Adrian Johnson <ajohnson@redneon.com>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
 //
 // To see a description of the changes please see the Changelog file that
@@ -36,6 +36,7 @@
 #include "parseargs.h"
 #include "printencodings.h"
 #include "goo/GooString.h"
+#include "goo/gfile.h"
 #include "goo/gmem.h"
 #include "GlobalParams.h"
 #include "Object.h"
@@ -351,16 +352,8 @@
   f = fopen(fileName->getCString(), "rb");
 #endif
   if (f) {
-#if HAVE_FSEEKO
-    fseeko(f, 0, SEEK_END);
-    printf("File size:      %u bytes\n", (Guint)ftello(f));
-#elif HAVE_FSEEK64
-    fseek64(f, 0, SEEK_END);
-    printf("File size:      %u bytes\n", (Guint)ftell64(f));
-#else
-    fseek(f, 0, SEEK_END);
-    printf("File size:      %d bytes\n", (int)ftell(f));
-#endif
+    Gfseek(f, 0, SEEK_END);
+    printf("File size:      %lld bytes\n", (long long)Gftell(f));
     fclose(f);
   }
 
diff --git a/utils/pdftohtml.cc b/utils/pdftohtml.cc
index 97372be..bcec8cb 100644
--- a/utils/pdftohtml.cc
+++ b/utils/pdftohtml.cc
@@ -165,7 +165,6 @@
       CharCode code, Unicode *u, int uLen) { return false; }
   void endType3Char(GfxState *state) { }
   void beginTextObject(GfxState *state) { }
-  GBool deviceHasTextClip(GfxState *state) { return false; }
   void endTextObject(GfxState *state) { }
   GBool interpretType3Chars() { return gFalse; }
 };
diff --git a/utils/pdfunite.cc b/utils/pdfunite.cc
index 79d05f0..071a0d3 100644
--- a/utils/pdfunite.cc
+++ b/utils/pdfunite.cc
@@ -8,6 +8,7 @@
 // Copyright (C) 2012 Arseny Solokha <asolokha@gmx.com>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
 // Copyright (C) 2012 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
 //
 //========================================================================
 #include <PDFDoc.h>
@@ -163,7 +164,7 @@
     outStr->printf(" >>\nendobj\n");
     objectsCount++;
   }
-  Guint uxrefOffset = outStr->getPos();
+  Goffset uxrefOffset = outStr->getPos();
   Ref ref;
   ref.num = rootNum;
   ref.gen = 0;