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", ¶ms);
+ dict->dictLookup("DecodeParms", ¶ms, recursion);
if (params.isNull()) {
params.free();
dict->dictLookup("DP", ¶ms);
}
if (obj.isName()) {
- str = makeFilter(obj.getName(), str, ¶ms, dict);
+ str = makeFilter(obj.getName(), str, ¶ms, recursion, dict);
} else if (obj.isArray()) {
for (i = 0; i < obj.arrayGetLength(); ++i) {
obj.arrayGet(i, &obj2);
if (params.isArray())
- params.arrayGet(i, ¶ms2);
+ params.arrayGet(i, ¶ms2, recursion);
else
params2.initNull();
if (obj2.isName()) {
- str = makeFilter(obj2.getName(), str, ¶ms2);
+ str = makeFilter(obj2.getName(), str, ¶ms2, recursion);
} else {
error(errSyntaxError, getPos(), "Bad filter name");
str = new EOFStream(str);
@@ -183,7 +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;