aboutsummaryrefslogtreecommitdiff
path: root/xpdf-qt/XpdfWidget.cc
diff options
context:
space:
mode:
authorCalvin Morrison <calvin@pobox.com>2023-04-05 14:13:39 -0400
committerCalvin Morrison <calvin@pobox.com>2023-04-05 14:13:39 -0400
commit835e373b3eeaabcd0621ed6798ab500f37982fae (patch)
treedfa16b0e2e1b4956b38f693220eac4e607802133 /xpdf-qt/XpdfWidget.cc
xpdf-no-select-disableHEADmaster
Diffstat (limited to 'xpdf-qt/XpdfWidget.cc')
-rw-r--r--xpdf-qt/XpdfWidget.cc2256
1 files changed, 2256 insertions, 0 deletions
diff --git a/xpdf-qt/XpdfWidget.cc b/xpdf-qt/XpdfWidget.cc
new file mode 100644
index 0000000..f5ad763
--- /dev/null
+++ b/xpdf-qt/XpdfWidget.cc
@@ -0,0 +1,2256 @@
+//========================================================================
+//
+// XpdfWidget.cc
+//
+// Copyright 2009 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+#include <QApplication>
+#include <QMutex>
+#include <QKeyEvent>
+#include <QPaintEvent>
+#include <QTimer>
+#include <QAbstractScrollArea>
+#include <QGesture>
+#include <QGestureEvent>
+#if XPDFWIDGET_PRINTING
+# include <QPrinter>
+# include <QPrintDialog>
+#endif
+#include "gmem.h"
+#include "gmempp.h"
+#include "gfile.h"
+#include "GString.h"
+#include "GList.h"
+#include "SplashBitmap.h"
+#include "config.h"
+#include "GlobalParams.h"
+#include "PDFDoc.h"
+#include "Object.h"
+#include "SplashOutputDev.h"
+#include "Outline.h"
+#include "OptionalContent.h"
+#include "Link.h"
+#include "Annot.h"
+#include "AcroForm.h"
+#include "TextString.h"
+#include "QtPDFCore.h"
+#include "XpdfWidget.h"
+#if XPDFWIDGET_PRINTING
+# include "XpdfWidgetPrint.h"
+#endif
+
+//------------------------------------------------------------------------
+
+// Time (in ms) between incremental updates.
+#define incrementalUpdateInterval 100
+
+//------------------------------------------------------------------------
+
+QMutex XpdfWidget::initMutex;
+
+//------------------------------------------------------------------------
+
+XpdfWidget::XpdfWidget(const QColor &paperColor, const QColor &matteColor,
+ bool reverseVideo, QWidget *parentA):
+ QAbstractScrollArea(parentA)
+{
+ setup(paperColor, matteColor, reverseVideo);
+}
+
+XpdfWidget::XpdfWidget(QWidget *parentA, const QColor &paperColor,
+ const QColor &matteColor, bool reverseVideo):
+ QAbstractScrollArea(parentA)
+{
+ setup(paperColor, matteColor, reverseVideo);
+}
+
+void XpdfWidget::setup(const QColor &paperColor, const QColor &matteColor,
+ bool reverseVideo) {
+ SplashColor paperColor2, matteColor2;
+
+ init();
+
+ paperColor2[0] = (Guchar)paperColor.red();
+ paperColor2[1] = (Guchar)paperColor.green();
+ paperColor2[2] = (Guchar)paperColor.blue();
+ matteColor2[0] = (Guchar)matteColor.red();
+ matteColor2[1] = (Guchar)matteColor.green();
+ matteColor2[2] = (Guchar)matteColor.blue();
+ try {
+ core = new QtPDFCore(viewport(), horizontalScrollBar(),
+ verticalScrollBar(),
+ paperColor2, matteColor2, (GBool)reverseVideo);
+ core->setUpdateCbk(updateCbk, this);
+ core->setMidPageChangedCbk(midPageChangedCbk, this);
+ core->setPreLoadCbk(preLoadCbk, this);
+ core->setPostLoadCbk(postLoadCbk, this);
+ core->setLinkCbk(linkCbk, this);
+ core->setSelectDoneCbk(selectDoneCbk, this);
+ core->setPaintDoneCbk(paintDoneCbk, this);
+ core->setTileDoneCbk(tileDoneCbk, this);
+ connect(this, SIGNAL(tileDone()), viewport(), SLOT(update()));
+ scaleFactor = core->getScaleFactor();
+ } catch (GMemException e) {
+ //~ what should this do?
+ core = NULL;
+ }
+
+#if XPDFWIDGET_PRINTING
+ printerForDialog = NULL;
+ printDialog = NULL;
+ printHDPI = printVDPI = 0;
+#endif
+
+ keyPassthrough = false;
+ mousePassthrough = false;
+ lastMousePressX[0] = lastMousePressX[1] = lastMousePressX[2] = 0;
+ lastMousePressY[0] = lastMousePressY[1] = lastMousePressY[2] = 0;
+ lastMousePressTime[0] = lastMousePressTime[1] = lastMousePressTime[2] = 0;
+ lastMouseEventWasPress = false;
+
+ viewport()->installEventFilter(this);
+ touchPanEnabled = false;
+ touchZoomEnabled = false;
+ pinchZoomStart = 100;
+
+ tickTimer = new QTimer(this);
+ connect(tickTimer, SIGNAL(timeout()), this, SLOT(tick()));
+ tickTimer->start(incrementalUpdateInterval);
+}
+
+XpdfWidget::~XpdfWidget() {
+#if XPDFWIDGET_PRINTING
+ delete printerForDialog;
+ delete printDialog;
+#endif
+ delete tickTimer;
+ delete core;
+}
+
+void XpdfWidget::init(const QString &configFileName) {
+#ifdef _WIN32
+ char buf[512];
+ GString *dir, *path;
+ char *configFileName2;
+ int n;
+#endif
+
+ initMutex.lock();
+ if (!globalParams) {
+ try {
+#ifdef _WIN32
+ // get the executable directory
+ n = GetModuleFileNameA(NULL, buf, sizeof(buf));
+ if (n <= 0 || n >= sizeof(buf)) {
+ // error or path too long for buffer - just use the current dir
+ buf[0] = '\0';
+ }
+ dir = grabPath(buf);
+
+ // load the config file
+ path = NULL;
+ if (configFileName.isEmpty()) {
+ path = appendToPath(dir->copy(), xpdfSysConfigFile);
+ configFileName2 = path->getCString();
+ } else {
+ configFileName2 = (char *)configFileName.toLocal8Bit().constData();
+ }
+ globalParams = new GlobalParams(configFileName2);
+ globalParams->setBaseDir(dir->getCString());
+ globalParams->setErrQuiet(gTrue);
+ if (path) {
+ delete path;
+ }
+
+ // set up the base fonts
+ appendToPath(dir, "t1fonts");
+ globalParams->setupBaseFonts(dir->getCString());
+ delete dir;
+#else
+ globalParams = new GlobalParams(
+ (char *)configFileName.toLocal8Bit().constData());
+ globalParams->setErrQuiet(gTrue);
+ globalParams->setupBaseFonts(NULL);
+#endif
+ } catch (GMemException e) {
+ // there's no way to return an error code here
+ return;
+ }
+ }
+ initMutex.unlock();
+}
+
+void XpdfWidget::setConfig(const QString &command) {
+ GString *fileName;
+
+ init();
+ try {
+ fileName = new GString("(none)");
+ globalParams->parseLine((char *)command.toLocal8Bit().constData(),
+ fileName, 1);
+ delete fileName;
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::enableHyperlinks(bool on) {
+ try {
+ core->enableHyperlinks((GBool)on);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::enableExternalHyperlinks(bool on) {
+ try {
+ core->enableExternalHyperlinks((GBool)on);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::enableSelect(bool on) {
+ try {
+ core->enableSelect((GBool)on);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::enablePan(bool on) {
+ try {
+ core->enablePan((GBool)on);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::enableTouchPan(bool on) {
+ touchPanEnabled = on;
+ if (touchPanEnabled) {
+ viewport()->grabGesture(Qt::PanGesture);
+ } else {
+ viewport()->ungrabGesture(Qt::PanGesture);
+ }
+}
+
+void XpdfWidget::enableTouchZoom(bool on) {
+ touchZoomEnabled = on;
+ if (touchZoomEnabled) {
+ viewport()->grabGesture(Qt::PinchGesture);
+ } else {
+ viewport()->ungrabGesture(Qt::PinchGesture);
+ }
+}
+
+void XpdfWidget::showPasswordDialog(bool showDlg) {
+ try {
+ core->setShowPasswordDialog((GBool)showDlg);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::setMatteColor(const QColor &matteColor) {
+ SplashColor matteColor2;
+
+ matteColor2[0] = (Guchar)matteColor.red();
+ matteColor2[1] = (Guchar)matteColor.green();
+ matteColor2[2] = (Guchar)matteColor.blue();
+ try {
+ core->setMatteColor(matteColor2);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::setReverseVideo(bool reverse) {
+ try {
+ core->setReverseVideo((GBool)reverse);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::setCursor(const QCursor &cursor) {
+ core->doSetCursor(cursor);
+}
+
+void XpdfWidget::unsetCursor() {
+ core->doUnsetCursor();
+}
+
+XpdfWidget::ErrorCode XpdfWidget::loadFile(const QString &fileName,
+ const QString &password) {
+ GString *passwordStr;
+#ifdef _WIN32
+ wchar_t *fileNameStr;
+ int n, i;
+#else
+ GString *fileNameStr;
+#endif
+ int err;
+
+ try {
+ if (password.isEmpty()) {
+ passwordStr = NULL;
+ } else {
+ passwordStr = new GString(password.toLocal8Bit().constData());
+ }
+#ifdef _WIN32
+ // this should use QString::toWCharArray(), but Qt builds their
+ // library with /Zc:wchar_t-, which confuses things
+ n = fileName.length();
+ fileNameStr = (wchar_t *)gmallocn(n, sizeof(wchar_t));
+ for (i = 0; i < n; ++i) {
+ fileNameStr[i] = (wchar_t)fileName[i].unicode();
+ }
+ err = core->loadFile(fileNameStr, n, passwordStr, passwordStr);
+ gfree(fileNameStr);
+#else
+ fileNameStr = new GString(fileName.toLocal8Bit().constData());
+ err = core->loadFile(fileNameStr, passwordStr, passwordStr);
+ delete fileNameStr;
+#endif
+ if (passwordStr) {
+ delete passwordStr;
+ }
+ if (!err) {
+ core->displayPage(1, gTrue, gFalse);
+ }
+ return (ErrorCode)err;
+ } catch (GMemException e) {
+ return pdfErrOutOfMemory;
+ }
+}
+
+XpdfWidget::ErrorCode XpdfWidget::loadMem(const char *buffer,
+ unsigned int bufferLength,
+ const QString &password) {
+ Object obj;
+ MemStream *stream;
+ GString *passwordStr;
+ int err;
+
+ try {
+ obj.initNull();
+ stream = new MemStream((char *)buffer, 0, bufferLength, &obj);
+ if (password.isEmpty()) {
+ passwordStr = NULL;
+ } else {
+ passwordStr = new GString(password.toLocal8Bit().constData());
+ }
+ err = core->loadFile(stream, passwordStr, passwordStr);
+ if (passwordStr) {
+ delete passwordStr;
+ }
+ if (!err) {
+ core->displayPage(1, gTrue, gFalse);
+ }
+ return (ErrorCode)err;
+ } catch (GMemException e) {
+ return pdfErrOutOfMemory;
+ }
+}
+
+XpdfWidget::ErrorCode XpdfWidget::readDoc(XpdfDocHandle *docPtr,
+ const QString &fileName,
+ const QString &password) {
+ GString *passwordStr;
+#ifdef _WIN32
+ wchar_t *fileNameStr;
+ int n, i;
+#else
+ GString *fileNameStr;
+#endif
+ PDFDoc *doc;
+ ErrorCode err;
+
+ *docPtr = NULL;
+ try {
+ if (password.isEmpty()) {
+ passwordStr = NULL;
+ } else {
+ passwordStr = new GString(password.toLocal8Bit().constData());
+ }
+#ifdef _WIN32
+ // this should use QString::toWCharArray(), but Qt builds their
+ // library with /Zc:wchar_t-, which confuses things
+ n = fileName.length();
+ fileNameStr = (wchar_t *)gmallocn(n, sizeof(wchar_t));
+ for (i = 0; i < n; ++i) {
+ fileNameStr[i] = (wchar_t)fileName[i].unicode();
+ }
+ doc = new PDFDoc(fileNameStr, n, passwordStr, passwordStr, core);
+ gfree(fileNameStr);
+#else
+ fileNameStr = new GString(fileName.toLocal8Bit().constData());
+ doc = new PDFDoc(fileNameStr, passwordStr, passwordStr, core);
+#endif
+ if (passwordStr) {
+ delete passwordStr;
+ }
+ if (doc->isOk()) {
+ *docPtr = doc;
+ err = pdfOk;
+ } else {
+ err = (ErrorCode)doc->getErrorCode();
+ delete doc;
+ }
+ } catch (GMemException e) {
+ err = pdfErrOutOfMemory;
+ }
+ return err;
+}
+
+XpdfWidget::ErrorCode XpdfWidget::loadDoc(XpdfDocHandle doc) {
+ if (!doc) {
+ return pdfErrNoHandle;
+ }
+ core->loadDoc((PDFDoc *)doc);
+ core->displayPage(1, gTrue, gFalse, gTrue);
+ return pdfOk;
+}
+
+void XpdfWidget::freeDoc(XpdfDocHandle doc) {
+ if (!doc) {
+ return;
+ }
+ delete (PDFDoc *)doc;
+}
+
+XpdfWidget::ErrorCode XpdfWidget::reload() {
+ try {
+ return (ErrorCode)core->reload();
+ } catch (GMemException e) {
+ return pdfErrOutOfMemory;
+ }
+}
+
+void XpdfWidget::closeFile() {
+ try {
+ core->clear();
+ } catch (GMemException e) {
+ }
+}
+
+XpdfWidget::ErrorCode XpdfWidget::saveAs(const QString &fileName) {
+ GString *s;
+
+ try {
+ if (!core->getDoc()) {
+ return pdfErrNoHandle;
+ }
+ s = new GString(fileName.toLocal8Bit().constData());
+ if (!core->getDoc()->saveAs(s)) {
+ delete s;
+ return pdfErrOpenFile;
+ }
+ delete s;
+ return pdfOk;
+ } catch (GMemException e) {
+ return pdfErrOutOfMemory;
+ }
+}
+
+bool XpdfWidget::hasOpenDocument() const {
+ try {
+ return core->getDoc() != NULL;
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+QString XpdfWidget::getFileName() const {
+ try {
+ if (!core->getDoc() || !core->getDoc()->getFileName()) {
+ return QString();
+ }
+#ifdef _WIN32
+ return QString::fromWCharArray(core->getDoc()->getFileNameU());
+#else
+ return QString::fromLocal8Bit(core->getDoc()->getFileName()->getCString());
+#endif
+ } catch (GMemException e) {
+ return QString();
+ }
+}
+
+int XpdfWidget::getNumPages() const {
+ try {
+ if (!core->getDoc()) {
+ return -1;
+ }
+ return core->getDoc()->getNumPages();
+ } catch (GMemException e) {
+ return -1;
+ }
+}
+
+int XpdfWidget::getCurrentPage() const {
+ try {
+ return core->getPageNum();
+ } catch (GMemException e) {
+ return -1;
+ }
+}
+
+int XpdfWidget::getMidPage() const {
+ try {
+ return core->getMidPageNum();
+ } catch (GMemException e) {
+ return -1;
+ }
+}
+
+void XpdfWidget::gotoPage(int pageNum) {
+ try {
+ core->displayPage(pageNum, gTrue, gFalse);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::gotoFirstPage() {
+ try {
+ core->displayPage(1, gTrue, gFalse);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::gotoLastPage() {
+ try {
+ if (!core->getDoc()) {
+ return;
+ }
+ core->displayPage(core->getDoc()->getNumPages(), gTrue, gFalse);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::gotoNextPage(bool scrollToTop) {
+ try {
+ core->gotoNextPage(1, scrollToTop);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::gotoPreviousPage(bool scrollToTop) {
+ try {
+ core->gotoPrevPage(1, scrollToTop, gFalse);
+ } catch (GMemException e) {
+ }
+}
+
+bool XpdfWidget::gotoNamedDestination(const QString &dest) {
+ GString *destStr;
+
+ try {
+ destStr = new GString(dest.toLocal8Bit().constData());
+ if (!core->gotoNamedDestination(destStr)) {
+ delete destStr;
+ return false;
+ }
+ delete destStr;
+ return true;
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+void XpdfWidget::goForward() {
+ try {
+ core->goForward();
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::goBackward() {
+ try {
+ core->goBackward();
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::scrollPageUp() {
+ try {
+ core->scrollPageUp();
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::scrollPageDown() {
+ try {
+ core->scrollPageDown();
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::scrollTo(int xx, int yy) {
+ try {
+ core->scrollTo(xx, yy);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::scrollBy(int dx, int dy) {
+ try {
+ core->scrollTo(core->getScrollX() + dx, core->getScrollY()+ dy);
+ } catch (GMemException e) {
+ }
+}
+
+int XpdfWidget::getScrollX() const {
+ try {
+ return core->getScrollX();
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+int XpdfWidget::getScrollY() const {
+ try {
+ return core->getScrollY();
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+void XpdfWidget::setZoom(double zoom) {
+ try {
+ core->setZoom(zoom);
+ } catch (GMemException e) {
+ }
+}
+
+double XpdfWidget::getZoom() const {
+ try {
+ return core->getZoom();
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+double XpdfWidget::getZoomPercent(int page) const {
+ double zoom;
+
+ try {
+ if (!core->getDoc() ||
+ page < 1 || page > core->getDoc()->getNumPages()) {
+ return 0;
+ }
+ zoom = core->getZoom();
+ if (zoom <= 0) {
+ zoom = 100 * core->getZoomDPI(page) / 72;
+ }
+ return zoom;
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+void XpdfWidget::zoomToRect(int page, double xMin, double yMin,
+ double xMax, double yMax) {
+ try {
+ core->zoomToRect(page, xMin, yMin, xMax, yMax);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::zoomCentered(double zoom) {
+ try {
+ core->zoomCentered(zoom);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::zoomToCurrentWidth() {
+ try {
+ core->zoomToCurrentWidth();
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::setRotate(int rotate) {
+ if (!(rotate == 0 || rotate == 90 || rotate == 180 || rotate == 270)) {
+ return;
+ }
+ try {
+ core->setRotate(rotate);
+ } catch (GMemException e) {
+ }
+}
+
+int XpdfWidget::getRotate() const {
+ try {
+ return core->getRotate();
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+void XpdfWidget::setContinuousMode(bool continuous) {
+ try {
+ core->setDisplayMode(continuous ? displayContinuous
+ : displaySingle);
+ } catch (GMemException e) {
+ }
+}
+
+bool XpdfWidget::getContinuousMode() const {
+ try {
+ return core->getDisplayMode() == displayContinuous;
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+void XpdfWidget::setDisplayMode(XpdfWidget::DisplayMode mode) {
+ try {
+ core->setDisplayMode((::DisplayMode)mode);
+ } catch (GMemException e) {
+ }
+}
+
+XpdfWidget::DisplayMode XpdfWidget::getDisplayMode() {
+ try {
+ return (XpdfWidget::DisplayMode)core->getDisplayMode();
+ } catch (GMemException e) {
+ return pdfDisplaySingle;
+ }
+}
+
+bool XpdfWidget::mouseOverLink() {
+ QPoint pt;
+ int page;
+ double xx, yy;
+
+ try {
+ if (core->getHyperlinksEnabled()) {
+ return core->getLinkAction() != NULL;
+ } else {
+ pt = mapFromGlobal(QCursor::pos());
+ if (!convertWindowToPDFCoords(pt.x(), pt.y(), &page, &xx, &yy)) {
+ return false;
+ }
+ return core->findLink(page, xx, yy) != NULL;
+ }
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+bool XpdfWidget::onLink(int page, double xx, double yy) {
+ try {
+ if (!core->getDoc()) {
+ return false;
+ }
+ if (page < 1 || page > core->getDoc()->getNumPages()) {
+ return false;
+ }
+ return core->findLink(page, xx, yy) != NULL;
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+QString XpdfWidget::getLinkInfo(int page, double xx, double yy) {
+ LinkAction *action;
+
+ try {
+ if (!core->getDoc()) {
+ return QString();
+ }
+ if (page < 1 || page > core->getDoc()->getNumPages()) {
+ return QString();
+ }
+ if (!(action = core->findLink(page, xx, yy))) {
+ return QString();
+ }
+ return core->getLinkInfo(action);
+ } catch (GMemException e) {
+ return QString();
+ }
+}
+
+QString XpdfWidget::getMouseLinkInfo() {
+ try {
+ if (!core->getLinkAction()) {
+ return QString();
+ }
+ return core->getLinkInfo(core->getLinkAction());
+ } catch (GMemException e) {
+ return QString();
+ }
+}
+
+bool XpdfWidget::gotoLinkAt(int page, double xx, double yy) {
+ LinkAction *action;
+
+ try {
+ if (!core->getDoc()) {
+ return false;
+ }
+ if (page < 1 || page > core->getDoc()->getNumPages()) {
+ return false;
+ }
+ if ((action = core->findLink(page, xx, yy))) {
+ if (!core->doAction(action)) {
+ return false;
+ }
+ }
+ } catch (GMemException e) {
+ }
+ return true;
+}
+
+bool XpdfWidget::getLinkTarget(int page, double xx, double yy,
+ QString &targetFileName, int &targetPage,
+ QString &targetDest) {
+ LinkAction *action;
+ LinkDest *dest;
+ GString *fileName, *namedDest, *path;
+ Ref pageRef;
+ char *s;
+
+ try {
+ if (!core->getDoc()) {
+ return false;
+ }
+ if (page < 1 || page > core->getDoc()->getNumPages()) {
+ return false;
+ }
+ if (!(action = core->findLink(page, xx, yy))) {
+ return false;
+ }
+ switch (action->getKind()) {
+ case actionGoTo:
+ if (!core->getDoc()->getFileName()) {
+ return false;
+ }
+ targetFileName = core->getDoc()->getFileName()->getCString();
+ if ((dest = ((LinkGoTo *)action)->getDest())) {
+ if (dest->isPageRef()) {
+ pageRef = dest->getPageRef();
+ targetPage = core->getDoc()->findPage(pageRef.num, pageRef.gen);
+ } else {
+ targetPage = dest->getPageNum();
+ }
+ targetDest = "";
+ } else if ((namedDest = ((LinkGoTo *)action)->getNamedDest())) {
+ targetDest = namedDest->getCString();
+ targetPage = 1;
+ }
+ return true;
+ case actionGoToR:
+ s = ((LinkGoToR *)action)->getFileName()->getCString();
+ if (isAbsolutePath(s)) {
+ targetFileName = s;
+ } else {
+ if (!core->getDoc()->getFileName()) {
+ return false;
+ }
+ path = appendToPath(
+ grabPath(core->getDoc()->getFileName()->getCString()), s);
+ targetFileName = path->getCString();
+ delete path;
+ }
+ if ((dest = ((LinkGoToR *)action)->getDest())) {
+ if (dest->isPageRef()) {
+ return false;
+ }
+ targetPage = dest->getPageNum();
+ targetDest = "";
+ } else if ((namedDest = ((LinkGoToR *)action)->getNamedDest())) {
+ targetDest = namedDest->getCString();
+ targetPage = 1;
+ }
+ return true;
+ case actionLaunch:
+ fileName = ((LinkLaunch *)action)->getFileName();
+ s = fileName->getCString();
+ if (!(fileName->getLength() >= 4 &&
+ (!strcmp(s + fileName->getLength() - 4, ".pdf") ||
+ !strcmp(s + fileName->getLength() - 4, ".PDF")))) {
+ return false;
+ }
+ if (isAbsolutePath(s)) {
+ targetFileName = s;
+ } else {
+ if (!core->getDoc()->getFileName()) {
+ return false;
+ }
+ path = appendToPath(
+ grabPath(core->getDoc()->getFileName()->getCString()), s);
+ targetFileName = path->getCString();
+ delete path;
+ }
+ targetPage = 1;
+ targetDest = "";
+ return true;
+ default:
+ return false;
+ }
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+XpdfAnnotHandle XpdfWidget::onAnnot(int page, double xx, double yy) {
+ try {
+ if (!core->getDoc()) {
+ return NULL;
+ }
+ return (XpdfAnnotHandle)core->findAnnot(page, xx, yy);
+ } catch (GMemException e) {
+ return NULL;
+ }
+}
+
+QString XpdfWidget::getAnnotType(XpdfAnnotHandle annot) {
+ try {
+ return ((Annot *)annot)->getType()->getCString();
+ } catch (GMemException e) {
+ return QString();
+ }
+}
+
+QString XpdfWidget::getAnnotContent(XpdfAnnotHandle annot) {
+ QString s;
+ Object annotObj, contentsObj;
+ TextString *ts;
+ Unicode *u;
+ int i;
+
+ try {
+ if (((Annot *)annot)->getObject(&annotObj)->isDict()) {
+ if (annotObj.dictLookup("Contents", &contentsObj)->isString()) {
+ ts = new TextString(contentsObj.getString());
+ u = ts->getUnicode();
+ for (i = 0; i < ts->getLength(); ++i) {
+ s.append((QChar)u[i]);
+ }
+ }
+ contentsObj.free();
+ }
+ annotObj.free();
+ return s;
+ } catch (GMemException e) {
+ return QString();
+ }
+}
+
+XpdfFormFieldHandle XpdfWidget::onFormField(int page, double xx, double yy) {
+ try {
+ if (!core->getDoc()) {
+ return NULL;
+ }
+ return (XpdfFormFieldHandle)core->findFormField(page, xx, yy);
+ } catch (GMemException e) {
+ return NULL;
+ }
+}
+
+QString XpdfWidget::getFormFieldType(XpdfFormFieldHandle field) {
+ try {
+ return ((AcroFormField *)field)->getType();
+ } catch (GMemException e) {
+ return QString();
+ }
+}
+
+QString XpdfWidget::getFormFieldName(XpdfFormFieldHandle field) {
+ Unicode *u;
+ QString s;
+ int length, i;
+
+ try {
+ u = ((AcroFormField *)field)->getName(&length);
+ for (i = 0; i < length; ++i) {
+ s.append((QChar)u[i]);
+ }
+ gfree(u);
+ return s;
+ } catch (GMemException e) {
+ return QString();
+ }
+}
+
+QString XpdfWidget::getFormFieldValue(XpdfFormFieldHandle field) {
+ Unicode *u;
+ QString s;
+ int length, i;
+
+ try {
+ u = ((AcroFormField *)field)->getValue(&length);
+ for (i = 0; i < length; ++i) {
+ s.append((QChar)u[i]);
+ }
+ gfree(u);
+ return s;
+ } catch (GMemException e) {
+ return QString();
+ }
+}
+
+void XpdfWidget::getFormFieldBBox(XpdfFormFieldHandle field, int *pageNum,
+ double *xMin, double *yMin,
+ double *xMax, double *yMax) {
+ try {
+ *pageNum = ((AcroFormField *)field)->getPageNum();
+ ((AcroFormField *)field)->getBBox(xMin, yMin, xMax, yMax);
+ } catch (GMemException e) {
+ }
+}
+
+bool XpdfWidget::convertWindowToPDFCoords(int winX, int winY,
+ int *page,
+ double *pdfX, double *pdfY) {
+ try {
+ return core->cvtWindowToUser(winX, winY, page, pdfX, pdfY);
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+void XpdfWidget::convertPDFToWindowCoords(int page, double pdfX, double pdfY,
+ int *winX, int *winY) {
+ try {
+ core->cvtUserToWindow(page, pdfX, pdfY, winX, winY);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::enableRedraw(bool enable) {
+ setUpdatesEnabled(enable);
+}
+
+void XpdfWidget::getPageBox(int page, const QString &box,
+ double *xMin, double *yMin,
+ double *xMax, double *yMax) const {
+ PDFRectangle *r;
+
+ *xMin = *yMin = *xMax = *yMax = 0;
+ try {
+ if (!core->getDoc()) {
+ return;
+ }
+ if (page < 1 || page > core->getDoc()->getNumPages()) {
+ return;
+ }
+ if (!box.compare("media", Qt::CaseInsensitive)) {
+ r = core->getDoc()->getCatalog()->getPage(page)->getMediaBox();
+ } else if (!box.compare("crop", Qt::CaseInsensitive)) {
+ r = core->getDoc()->getCatalog()->getPage(page)->getCropBox();
+ } else if (!box.compare("bleed", Qt::CaseInsensitive)) {
+ r = core->getDoc()->getCatalog()->getPage(page)->getBleedBox();
+ } else if (!box.compare("trim", Qt::CaseInsensitive)) {
+ r = core->getDoc()->getCatalog()->getPage(page)->getTrimBox();
+ } else if (!box.compare("art", Qt::CaseInsensitive)) {
+ r = core->getDoc()->getCatalog()->getPage(page)->getArtBox();
+ } else {
+ return;
+ }
+ *xMin = r->x1;
+ *yMin = r->y1;
+ *xMax = r->x2;
+ *yMax = r->y2;
+ } catch (GMemException e) {
+ }
+}
+
+double XpdfWidget::getPageWidth(int page) const {
+ try {
+ if (!core->getDoc()) {
+ return 0;
+ }
+ if (page < 1 || page > core->getDoc()->getNumPages()) {
+ return 0;
+ }
+ return core->getDoc()->getPageCropWidth(page);
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+double XpdfWidget::getPageHeight(int page) const {
+ try {
+ if (!core->getDoc()) {
+ return 0;
+ }
+ if (page < 1 || page > core->getDoc()->getNumPages()) {
+ return 0;
+ }
+ return core->getDoc()->getPageCropHeight(page);
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+int XpdfWidget::getPageRotation(int page) const {
+ try {
+ if (!core->getDoc()) {
+ return 0;
+ }
+ if (page < 1 || page > core->getDoc()->getNumPages()) {
+ return 0;
+ }
+ return core->getDoc()->getCatalog()->getPage(page)->getRotate();
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+bool XpdfWidget::hasSelection() {
+ try {
+ return (bool)core->hasSelection();
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+bool XpdfWidget::getCurrentSelection(int *page, double *x0, double *y0,
+ double *x1, double *y1) const {
+ try {
+ return (bool)core->getSelection(page, x0, y0, x1, y1);
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+void XpdfWidget::setCurrentSelection(int page, double x0, double y0,
+ double x1, double y1) {
+ int ulx, uly, lrx, lry, t;
+
+ try {
+ core->cvtUserToDev(page, x0, y0, &ulx, &uly);
+ core->cvtUserToDev(page, x1, y1, &lrx, &lry);
+ if (ulx > lrx) {
+ t = ulx; ulx = lrx; lrx = t;
+ }
+ if (uly > lry) {
+ t = uly; uly = lry; lry = t;
+ }
+ core->setSelection(page, ulx, uly, lrx, lry);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::clearSelection() {
+ try {
+ core->clearSelection();
+ } catch (GMemException e) {
+ }
+}
+
+bool XpdfWidget::isBlockSelectMode() {
+ try {
+ return core->getSelectMode() == selectModeBlock;
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+bool XpdfWidget::isLinearSelectMode() {
+ try {
+ return core->getSelectMode() == selectModeLinear;
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+void XpdfWidget::setBlockSelectMode() {
+ try {
+ core->setSelectMode(selectModeBlock);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::setLinearSelectMode() {
+ try {
+ core->setSelectMode(selectModeLinear);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::setSelectionColor(const QColor &selectionColor) {
+ SplashColor col;
+
+ try {
+ col[0] = (Guchar)selectionColor.red();
+ col[1] = (Guchar)selectionColor.green();
+ col[2] = (Guchar)selectionColor.blue();
+ core->setSelectionColor(col);
+ } catch (GMemException e) {
+ }
+}
+
+
+void XpdfWidget::forceRedraw() {
+ try {
+ core->forceRedraw();
+ } catch (GMemException e) {
+ }
+}
+
+#if XPDFWIDGET_PRINTING
+
+bool XpdfWidget::okToPrint() const {
+ try {
+ if (!core->getDoc()) {
+ return false;
+ }
+ return (bool)core->getDoc()->okToPrint();
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+XpdfWidget::ErrorCode XpdfWidget::print(bool showDialog) {
+ GString *defaultPrinter;
+ ErrorCode err;
+
+ try {
+ if (!core->getDoc()) {
+ return pdfErrNoHandle;
+ }
+ if (!printerForDialog) {
+ printerForDialog = new QPrinter(QPrinter::HighResolution);
+ if ((defaultPrinter = globalParams->getDefaultPrinter())) {
+ printerForDialog->setPrinterName(
+ QString::fromUtf8(defaultPrinter->getCString()));
+ delete defaultPrinter;
+ }
+ }
+ printerForDialog->setFromTo(1, core->getDoc()->getNumPages());
+ if (showDialog) {
+ if (!printDialog) {
+ printDialog = new QPrintDialog(printerForDialog, this);
+ }
+ if (printDialog->exec() != QDialog::Accepted) {
+ return pdfErrPrinting;
+ }
+ }
+ printCanceled = false;
+ err = printPDF(core->getDoc(), printerForDialog,
+ printHDPI, printVDPI, this);
+ return err;
+ } catch (GMemException e) {
+ return pdfErrOutOfMemory;
+ }
+}
+
+XpdfWidget::ErrorCode XpdfWidget::print(QPrinter *prt) {
+ try {
+ if (!core->getDoc()) {
+ return pdfErrNoHandle;
+ }
+ printCanceled = false;
+ return printPDF(core->getDoc(), prt, printHDPI, printVDPI, this);
+ } catch (GMemException e) {
+ return pdfErrOutOfMemory;
+ }
+}
+
+void XpdfWidget::updatePrintStatus(int nextPage, int firstPage, int lastPage) {
+ emit printStatus(nextPage, firstPage, lastPage);
+}
+
+void XpdfWidget::setPrintDPI(int hDPI, int vDPI) {
+ printHDPI = hDPI;
+ printVDPI = vDPI;
+}
+
+#endif // XPDFWIDGET_PRINTING
+
+QImage XpdfWidget::convertPageToImage(int page, double dpi, bool transparent) {
+ try {
+ PDFDoc *doc = core->getDoc();
+ if (!doc) {
+ return QImage();
+ }
+ if (page < 1 || page > doc->getNumPages()) {
+ return QImage();
+ }
+ if (transparent) {
+ SplashColor paperColor;
+ paperColor[0] = paperColor[1] = paperColor[2] = 0xff; // unused
+ SplashOutputDev *out = new SplashOutputDev(splashModeRGB8, 1, gFalse,
+ paperColor);
+ out->setNoComposite(gTrue);
+ out->startDoc(doc->getXRef());
+ doc->displayPage(out, page, dpi, dpi, core->getRotate(),
+ gFalse, gTrue, gFalse);
+ SplashBitmap *bitmap = out->getBitmap();
+ QImage img(bitmap->getWidth(), bitmap->getHeight(),
+ QImage::Format_ARGB32);
+ Guchar *pix = bitmap->getDataPtr();
+ Guchar *alpha = bitmap->getAlphaPtr();
+ Guint *argb = (Guint *)img.bits();
+ for (int y = 0; y < bitmap->getHeight(); ++y) {
+ for (int x = 0; x < bitmap->getWidth(); ++x) {
+ *argb = (*alpha << 24) | (pix[0] << 16) | (pix[1] << 8) | pix[2];
+ pix += 3;
+ ++alpha;
+ ++argb;
+ }
+ }
+ delete out;
+ return img;
+ } else {
+ SplashColor paperColor;
+ paperColor[0] = paperColor[1] = paperColor[2] = 0xff;
+ SplashOutputDev *out = new SplashOutputDev(splashModeRGB8, 4, gFalse,
+ paperColor);
+ out->startDoc(doc->getXRef());
+ doc->displayPage(out, page, dpi, dpi, core->getRotate(),
+ gFalse, gTrue, gFalse);
+ SplashBitmap *bitmap = out->getBitmap();
+ QImage *img = new QImage((const uchar *)bitmap->getDataPtr(),
+ bitmap->getWidth(), bitmap->getHeight(),
+ QImage::Format_RGB888);
+ // force a copy
+ QImage img2(img->copy());
+ delete img;
+ delete out;
+ return img2;
+ }
+ } catch (GMemException e) {
+ return QImage();
+ }
+}
+
+QImage XpdfWidget::convertRegionToImage(int page, double x0, double y0,
+ double x1, double y1, double dpi,
+ bool transparent) {
+ try {
+ PDFDoc *doc = core->getDoc();
+ if (!doc) {
+ return QImage();
+ }
+ if (page < 1 || page > doc->getNumPages()) {
+ return QImage();
+ }
+
+ if (x0 > x1) {
+ double t = x0; x0 = x1; x1 = t;
+ }
+ if (y0 > y1) {
+ double t = y0; y0 = y1; y1 = t;
+ }
+ PDFRectangle *box = doc->getCatalog()->getPage(page)->getCropBox();
+ int rot = doc->getPageRotate(page);
+ double k = dpi / 72.0;
+ int sliceX, sliceY, sliceW, sliceH;
+ if (rot == 90) {
+ sliceX = (int)(k * (y0 - box->y1));
+ sliceY = (int)(k * (x0 - box->x1));
+ sliceW = (int)(k * (y1 - y0));
+ sliceH = (int)(k * (x1 - x0));
+ } else if (rot == 180) {
+ sliceX = (int)(k * (box->x2 - x1));
+ sliceY = (int)(k * (y0 - box->y1));
+ sliceW = (int)(k * (x1 - x0));
+ sliceH = (int)(k * (y1 - y0));
+ } else if (rot == 270) {
+ sliceX = (int)(k * (box->y2 - y1));
+ sliceY = (int)(k * (box->x2 - x1));
+ sliceW = (int)(k * (y1 - y0));
+ sliceH = (int)(k * (x1 - x0));
+ } else {
+ sliceX = (int)(k * (x0 - box->x1));
+ sliceY = (int)(k * (box->y2 - y1));
+ sliceW = (int)(k * (x1 - x0));
+ sliceH = (int)(k * (y1 - y0));
+ }
+
+ if (transparent) {
+ SplashColor paperColor;
+ paperColor[0] = paperColor[1] = paperColor[2] = 0xff; // unused
+ SplashOutputDev *out = new SplashOutputDev(splashModeRGB8, 1, gFalse,
+ paperColor);
+ out->setNoComposite(gTrue);
+ out->startDoc(doc->getXRef());
+ doc->displayPageSlice(out, page, dpi, dpi, core->getRotate(),
+ gFalse, gTrue, gFalse,
+ sliceX, sliceY, sliceW, sliceH);
+ SplashBitmap *bitmap = out->getBitmap();
+ QImage img(bitmap->getWidth(), bitmap->getHeight(),
+ QImage::Format_ARGB32);
+ Guchar *pix = bitmap->getDataPtr();
+ Guchar *alpha = bitmap->getAlphaPtr();
+ Guint *argb = (Guint *)img.bits();
+ for (int y = 0; y < bitmap->getHeight(); ++y) {
+ for (int x = 0; x < bitmap->getWidth(); ++x) {
+ *argb = (*alpha << 24) | (pix[0] << 16) | (pix[1] << 8) | pix[2];
+ pix += 3;
+ ++alpha;
+ ++argb;
+ }
+ }
+ delete out;
+ return img;
+ } else {
+ SplashColor paperColor;
+ paperColor[0] = paperColor[1] = paperColor[2] = 0xff;
+ SplashOutputDev *out = new SplashOutputDev(splashModeRGB8, 4, gFalse,
+ paperColor);
+ out->startDoc(doc->getXRef());
+ doc->displayPageSlice(out, page, dpi, dpi, core->getRotate(),
+ gFalse, gTrue, gFalse,
+ sliceX, sliceY, sliceW, sliceH);
+ SplashBitmap *bitmap = out->getBitmap();
+ QImage *img = new QImage((const uchar *)bitmap->getDataPtr(),
+ bitmap->getWidth(), bitmap->getHeight(),
+ QImage::Format_RGB888);
+ // force a copy
+ QImage img2(img->copy());
+ delete img;
+ delete out;
+ return img2;
+ }
+ } catch (GMemException e) {
+ return QImage();
+ }
+}
+
+QImage XpdfWidget::getThumbnail(int page) {
+ Object thumbObj, decodeObj, colorSpaceObj, obj;
+ Dict *thumbDict;
+ GfxColorSpace *colorSpace;
+ GfxImageColorMap *colorMap;
+ ImageStream *imgStream;
+ Guchar *line, *rgb;
+ int w, h, bpc, yy;
+
+ try {
+ if (!core->getDoc()) {
+ return QImage();
+ }
+ if (page < 1 || page > core->getDoc()->getNumPages()) {
+ return QImage();
+ }
+
+ // get the thumbnail image object
+ if (!core->getDoc()->getCatalog()->getPage(page)
+ ->getThumbnail(&thumbObj)->isStream()) {
+ thumbObj.free();
+ return QImage();
+ }
+
+ // get the image parameters
+ thumbDict = thumbObj.streamGetDict();
+ if (!thumbDict->lookup("Width", &obj)->isInt()) {
+ obj.free();
+ thumbObj.free();
+ return QImage();
+ }
+ w = obj.getInt();
+ obj.free();
+ if (!thumbDict->lookup("Height", &obj)->isInt()) {
+ obj.free();
+ thumbObj.free();
+ return QImage();
+ }
+ h = obj.getInt();
+ obj.free();
+ if (!thumbDict->lookup("BitsPerComponent", &obj)->isInt()) {
+ obj.free();
+ thumbObj.free();
+ return QImage();
+ }
+ bpc = obj.getInt();
+ obj.free();
+
+ // create the color space and color map
+ thumbDict->lookup("Decode", &decodeObj);
+ thumbDict->lookup("ColorSpace", &colorSpaceObj);
+ colorSpace = GfxColorSpace::parse(&colorSpaceObj
+ );
+ colorMap = new GfxImageColorMap(bpc, &decodeObj, colorSpace);
+ colorSpaceObj.free();
+ decodeObj.free();
+ imgStream = new ImageStream(thumbObj.getStream(),
+ w, colorSpace->getNComps(), bpc);
+
+ // create the QImage, and read the image data
+ QImage img(w, h, QImage::Format_RGB888);
+ rgb = (Guchar *)gmallocn(w, 3);
+ imgStream->reset();
+ for (yy = 0; yy < h; ++yy) {
+ line = imgStream->getLine();
+ colorMap->getRGBByteLine(line, rgb, w, gfxRenderingIntentPerceptual);
+ memcpy(img.scanLine(yy), rgb, 3 * w);
+ }
+ gfree(rgb);
+
+ delete colorMap;
+ delete imgStream;
+ thumbObj.free();
+
+ return img;
+ } catch (GMemException e) {
+ return QImage();
+ }
+}
+
+bool XpdfWidget::okToExtractText() const {
+ try {
+ if (!core->getDoc()) {
+ return false;
+ }
+ return (bool)core->getDoc()->okToCopy();
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+void XpdfWidget::setTextEncoding(const QString &encodingName) {
+ init();
+ try {
+ globalParams->setTextEncoding((char *)encodingName.toLatin1().constData());
+ } catch (GMemException e) {
+ }
+}
+
+QString XpdfWidget::extractText(int page, double x0, double y0,
+ double x1, double y1) {
+ GString *s, *enc;
+ GBool twoByte;
+ QString ret;
+ int i;
+
+ try {
+ if (!core->getDoc()) {
+ return QString();
+ }
+ if (!(s = core->extractText(page, x0, y0, x1, y1))) {
+ return QString();
+ }
+ enc = globalParams->getTextEncodingName();
+ twoByte = !enc->cmp("UCS-2");
+ delete enc;
+ if (twoByte) {
+ for (i = 0; i+1 < s->getLength(); i += 2) {
+ ret.append((QChar)(((s->getChar(i) & 0xff) << 8) +
+ (s->getChar(i+1) & 0xff)));
+ }
+ } else {
+ ret.append(s->getCString());
+ }
+ delete s;
+ return ret;
+ } catch (GMemException e) {
+ return QString();
+ }
+}
+
+QString XpdfWidget::getSelectedText() {
+ try {
+ return core->getSelectedTextQString();
+ } catch (GMemException e) {
+ return "";
+ }
+}
+
+void XpdfWidget::copySelection() {
+ try {
+ core->copySelection(gTrue);
+ } catch (GMemException e) {
+ }
+}
+
+bool XpdfWidget::find(const QString &text, int flags) {
+ Unicode *u;
+ bool ret;
+ int len, i;
+
+ try {
+ if (!core->getDoc()) {
+ return false;
+ }
+ len = text.length();
+ u = (Unicode *)gmallocn(len, sizeof(Unicode));
+ for (i = 0; i < len; ++i) {
+ u[i] = (Unicode)text[i].unicode();
+ }
+ ret = (bool)core->findU(u, len,
+ (flags & findCaseSensitive) ? gTrue : gFalse,
+ (flags & findNext) ? gTrue : gFalse,
+ (flags & findBackward) ? gTrue : gFalse,
+ (flags & findWholeWord) ? gTrue : gFalse,
+ (flags & findOnePageOnly) ? gTrue : gFalse);
+ gfree(u);
+ return ret;
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+QVector<XpdfFindResult> XpdfWidget::findAll(const QString &text, int firstPage,
+ int lastPage, int flags) {
+ QVector<XpdfFindResult> v;
+ try {
+ if (!core->getDoc()) {
+ return v;
+ }
+ int len = text.length();
+ Unicode *u = (Unicode *)gmallocn(len, sizeof(Unicode));
+ for (int i = 0; i < len; ++i) {
+ u[i] = (Unicode)text[i].unicode();
+ }
+ GList *results = core->findAll(u, len,
+ (flags & findCaseSensitive) ? gTrue : gFalse,
+ (flags & findWholeWord) ? gTrue : gFalse,
+ firstPage, lastPage);
+ gfree(u);
+ for (int i = 0; i < results->getLength(); ++i) {
+ FindResult *result = (FindResult *)results->get(i);
+ v.append(XpdfFindResult(result->page, result->xMin, result->yMin,
+ result->xMax, result->yMax));
+ }
+ deleteGList(results, FindResult);
+ return v;
+ } catch (GMemException e) {
+ return v;
+ }
+}
+
+bool XpdfWidget::hasPageLabels() {
+ try {
+ if (!core->getDoc()) {
+ return false;
+ }
+ return core->getDoc()->getCatalog()->hasPageLabels();
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+QString XpdfWidget::getPageLabelFromPageNum(int pageNum) {
+ try {
+ if (!core->getDoc()) {
+ return QString();
+ }
+ TextString *ts = core->getDoc()->getCatalog()->getPageLabel(pageNum);
+ if (!ts) {
+ return QString();
+ }
+ QString qs;
+ Unicode *u = ts->getUnicode();
+ for (int i = 0; i < ts->getLength(); ++i) {
+ qs.append((QChar)u[i]);
+ }
+ delete ts;
+ return qs;
+ } catch (GMemException e) {
+ return QString();
+ }
+}
+
+int XpdfWidget::getPageNumFromPageLabel(QString pageLabel) {
+ try {
+ if (!core->getDoc()) {
+ return -1;
+ }
+ TextString *ts = new TextString();
+ for (int i = 0; i < pageLabel.size(); ++i) {
+ ts->append((Unicode)pageLabel.at(i).unicode());
+ }
+ int pg = core->getDoc()->getCatalog()->getPageNumFromPageLabel(ts);
+ delete ts;
+ return pg;
+ } catch (GMemException e) {
+ return -1;
+ }
+}
+
+int XpdfWidget::getOutlineNumChildren(XpdfOutlineHandle outline) {
+ GList *items;
+
+ try {
+ if (!core->getDoc()) {
+ return 0;
+ }
+ if (outline) {
+ ((OutlineItem *)outline)->open();
+ items = ((OutlineItem *)outline)->getKids();
+ } else {
+ items = core->getDoc()->getOutline()->getItems();
+ }
+ if (!items) {
+ return 0;
+ }
+ return items->getLength();
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+XpdfOutlineHandle XpdfWidget::getOutlineChild(XpdfOutlineHandle outline,
+ int idx) {
+ GList *items;
+
+ try {
+ if (!core->getDoc()) {
+ return NULL;
+ }
+ if (outline) {
+ ((OutlineItem *)outline)->open();
+ items = ((OutlineItem *)outline)->getKids();
+ } else {
+ items = core->getDoc()->getOutline()->getItems();
+ }
+ if (!items) {
+ return NULL;
+ }
+ if (idx < 0 || idx >= items->getLength()) {
+ return NULL;
+ }
+ return (XpdfOutlineHandle)items->get(idx);
+ } catch (GMemException e) {
+ return NULL;
+ }
+}
+
+XpdfOutlineHandle XpdfWidget::getOutlineParent(XpdfOutlineHandle outline) {
+ if (!outline) {
+ return NULL;
+ }
+ return (XpdfOutlineHandle)((OutlineItem *)outline)->getParent();
+}
+
+QString XpdfWidget::getOutlineTitle(XpdfOutlineHandle outline) {
+ Unicode *title;
+ QString s;
+ int titleLen, i;
+
+ if (!outline) {
+ return QString();
+ }
+ try {
+ title = ((OutlineItem *)outline)->getTitle();
+ titleLen = ((OutlineItem *)outline)->getTitleLength();
+ for (i = 0; i < titleLen; ++i) {
+ s.append((QChar)title[i]);
+ }
+ return s;
+ } catch (GMemException e) {
+ return QString();
+ }
+}
+
+bool XpdfWidget::getOutlineStartsOpen(XpdfOutlineHandle outline) {
+ if (!outline) {
+ return false;
+ }
+ try {
+ return (bool)((OutlineItem *)outline)->isOpen();
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+int XpdfWidget::getOutlineTargetPage(XpdfOutlineHandle outline) {
+ try {
+ if (!outline || !core->getDoc()) {
+ return 0;
+ }
+ return core->getDoc()->getOutlineTargetPage((OutlineItem *)outline);
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+void XpdfWidget::gotoOutlineTarget(XpdfOutlineHandle outline) {
+ if (!outline) {
+ return;
+ }
+ try {
+ if (((OutlineItem *)outline)->getAction()) {
+ core->doAction(((OutlineItem *)outline)->getAction());
+ }
+ } catch (GMemException e) {
+ }
+}
+
+int XpdfWidget::getNumLayers() const {
+ try {
+ if (!core->getDoc()) {
+ return 0;
+ }
+ return core->getDoc()->getOptionalContent()->getNumOCGs();
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+XpdfLayerHandle XpdfWidget::getLayer(int idx) const {
+ try {
+ if (!core->getDoc() ||
+ idx < 0 ||
+ idx >= core->getDoc()->getOptionalContent()->getNumOCGs()) {
+ return NULL;
+ }
+ return (XpdfLayerHandle)core->getDoc()->getOptionalContent()->getOCG(idx);
+ } catch (GMemException e) {
+ return NULL;
+ }
+}
+
+QString XpdfWidget::getLayerName(XpdfLayerHandle layer) const {
+ Unicode *name;
+ QString s;
+ int nameLen, i;
+
+ if (!layer) {
+ return QString();
+ }
+ try {
+ name = ((OptionalContentGroup *)layer)->getName();
+ nameLen = ((OptionalContentGroup *)layer)->getNameLength();
+ for (i = 0; i < nameLen; ++i) {
+ s.append((QChar)name[i]);
+ }
+ return s;
+ } catch (GMemException e) {
+ return QString();
+ }
+}
+
+bool XpdfWidget::getLayerVisibility(XpdfLayerHandle layer) const {
+ if (!layer) {
+ return false;
+ }
+ try {
+ return (bool)((OptionalContentGroup *)layer)->getState();
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+void XpdfWidget::setLayerVisibility(XpdfLayerHandle layer, bool visibility) {
+ try {
+ if (!core->getDoc() || !layer) {
+ return;
+ }
+ core->setOCGState(((OptionalContentGroup *)layer), (GBool)visibility);
+ } catch (GMemException e) {
+ return;
+ }
+}
+
+int XpdfWidget::getLayerViewState(XpdfLayerHandle layer) const {
+ int s;
+
+ if (!layer) {
+ return 0;
+ }
+ try {
+ s = ((OptionalContentGroup *)layer)->getViewState();
+ return (s == ocUsageOn) ? 1 : (s == ocUsageOff) ? 0 : -1;
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+int XpdfWidget::getLayerPrintState(XpdfLayerHandle layer) const {
+ int s;
+
+ if (!layer) {
+ return 0;
+ }
+ try {
+ s = ((OptionalContentGroup *)layer)->getPrintState();
+ return (s == ocUsageOn) ? 1 : (s == ocUsageOff) ? 0 : -1;
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+XpdfLayerOrderHandle XpdfWidget::getLayerOrderRoot() const {
+ try {
+ if (!core->getDoc()) {
+ return NULL;
+ }
+ return (XpdfLayerOrderHandle)
+ core->getDoc()->getOptionalContent()->getDisplayRoot();
+ } catch (GMemException e) {
+ return NULL;
+ }
+}
+
+bool XpdfWidget::getLayerOrderIsName(XpdfLayerOrderHandle order) const {
+ if (!order) {
+ return false;
+ }
+ try {
+ return ((OCDisplayNode *)order)->getOCG() == NULL;
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+QString XpdfWidget::getLayerOrderName(XpdfLayerOrderHandle order) const {
+ Unicode *name;
+ QString s;
+ int nameLen, i;
+
+ if (!order) {
+ return QString();
+ }
+ try {
+ name = ((OCDisplayNode *)order)->getName();
+ nameLen = ((OCDisplayNode *)order)->getNameLength();
+ for (i = 0; i < nameLen; ++i) {
+ s.append((QChar)name[i]);
+ }
+ return s;
+ } catch (GMemException e) {
+ return QString();
+ }
+}
+
+XpdfLayerHandle XpdfWidget::getLayerOrderLayer(XpdfLayerOrderHandle order) {
+ if (!order) {
+ return NULL;
+ }
+ try {
+ return (XpdfLayerHandle)((OCDisplayNode *)order)->getOCG();
+ } catch (GMemException e) {
+ return NULL;
+ }
+}
+
+int XpdfWidget::getLayerOrderNumChildren(XpdfLayerOrderHandle order) {
+ if (!order) {
+ return 0;
+ }
+ try {
+ return ((OCDisplayNode *)order)->getNumChildren();
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+XpdfLayerOrderHandle XpdfWidget::getLayerOrderChild(XpdfLayerOrderHandle order,
+ int idx) {
+ if (!order) {
+ return NULL;
+ }
+ try {
+ if (idx < 0 || idx >= ((OCDisplayNode *)order)->getNumChildren()) {
+ return NULL;
+ }
+ return (XpdfLayerOrderHandle)((OCDisplayNode *)order)->getChild(idx);
+ } catch (GMemException e) {
+ return NULL;
+ }
+}
+
+XpdfLayerOrderHandle XpdfWidget::getLayerOrderParent(
+ XpdfLayerOrderHandle order) {
+ if (!order) {
+ return NULL;
+ }
+ try {
+ return (XpdfLayerOrderHandle)((OCDisplayNode *)order)->getParent();
+ } catch (GMemException e) {
+ return NULL;
+ }
+}
+
+int XpdfWidget::getNumEmbeddedFiles() {
+ try {
+ if (!core->getDoc()) {
+ return 0;
+ }
+ return core->getDoc()->getNumEmbeddedFiles();
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+QString XpdfWidget::getEmbeddedFileName(int idx) {
+ Unicode *name;
+ QString s;
+ int nameLen, i;
+
+ try {
+ if (!core->getDoc() ||
+ idx < 0 ||
+ idx >= core->getDoc()->getNumEmbeddedFiles()) {
+ return "";
+ }
+ name = core->getDoc()->getEmbeddedFileName(idx);
+ nameLen = core->getDoc()->getEmbeddedFileNameLength(idx);
+ for (i = 0; i < nameLen; ++i) {
+ s.append((QChar)name[i]);
+ }
+ return s;
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+bool XpdfWidget::saveEmbeddedFile(int idx, QString fileName) {
+ try {
+ if (!core->getDoc() ||
+ idx < 0 ||
+ idx >= core->getDoc()->getNumEmbeddedFiles()) {
+ return false;
+ }
+ return core->getDoc()->saveEmbeddedFile(
+ idx, fileName.toLocal8Bit().constData());
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+QSize XpdfWidget::sizeHint() const {
+ try {
+ return core->getBestSize();
+ } catch (GMemException e) {
+ }
+ return QSize(612, 792);
+}
+
+//------------------------------------------------------------------------
+// callbacks from QtPDFCore
+//------------------------------------------------------------------------
+
+void XpdfWidget::updateCbk(void *data, GString *fileName,
+ int pageNum, int numPages,
+ const char *linkLabel) {
+ XpdfWidget *xpdf = (XpdfWidget *)data;
+
+ if (fileName) {
+ if (pageNum >= 0) {
+ emit xpdf->pageChange(pageNum);
+ }
+ }
+}
+
+void XpdfWidget::midPageChangedCbk(void *data, int pageNum) {
+ XpdfWidget *xpdf = (XpdfWidget *)data;
+
+ emit xpdf->midPageChange(pageNum);
+}
+
+void XpdfWidget::preLoadCbk(void *data) {
+ XpdfWidget *xpdf = (XpdfWidget *)data;
+
+ emit xpdf->preLoad();
+}
+
+void XpdfWidget::postLoadCbk(void *data) {
+ XpdfWidget *xpdf = (XpdfWidget *)data;
+
+ emit xpdf->postLoad();
+}
+
+void XpdfWidget::linkCbk(void *data, const char *type,
+ const char *dest, int page) {
+ XpdfWidget *xpdf = (XpdfWidget *)data;
+
+ emit xpdf->linkClick(type, dest, page);
+}
+
+void XpdfWidget::selectDoneCbk(void *data) {
+ XpdfWidget *xpdf = (XpdfWidget *)data;
+
+ emit xpdf->selectDone();
+}
+
+void XpdfWidget::paintDoneCbk(void *data, bool finished) {
+ XpdfWidget *xpdf = (XpdfWidget *)data;
+
+ emit xpdf->paintDone(finished);
+}
+
+// NB: this function is called on a worker thread.
+void XpdfWidget::tileDoneCbk(void *data) {
+ XpdfWidget *xpdf = (XpdfWidget *)data;
+
+ emit xpdf->tileDone();
+}
+
+
+//------------------------------------------------------------------------
+// events from the QAbstractScrollArea
+//------------------------------------------------------------------------
+
+void XpdfWidget::paintEvent(QPaintEvent *eventA) {
+ core->paintEvent(eventA->rect().left(),
+ eventA->rect().top(),
+ eventA->rect().width(),
+ eventA->rect().height());
+}
+
+void XpdfWidget::resizeEvent(QResizeEvent *eventA) {
+ core->resizeEvent();
+ emit resized();
+}
+
+void XpdfWidget::scrollContentsBy(int dx, int dy) {
+ core->scrollEvent();
+}
+
+void XpdfWidget::keyPressEvent(QKeyEvent *e) {
+ int key;
+
+ if (!keyPassthrough) {
+ key = e->key();
+ if (key == Qt::Key_Left) {
+ core->scrollLeft();
+ return;
+ } else if (key == Qt::Key_Right) {
+ core->scrollRight();
+ return;
+ } else if (key == Qt::Key_Up) {
+ core->scrollUp();
+ return;
+ } else if (key == Qt::Key_Down) {
+ core->scrollDown();
+ return;
+ } else if (key == Qt::Key_PageUp) {
+ core->scrollPageUp();
+ return;
+ } else if (key == Qt::Key_PageDown ||
+ key == Qt::Key_Space) {
+ core->scrollPageDown();
+ return;
+ }
+ }
+ emit keyPress(e);
+}
+
+void XpdfWidget::mousePressEvent(QMouseEvent *e) {
+ int x, y;
+
+ lastMousePressX[0] = lastMousePressX[1];
+ lastMousePressY[0] = lastMousePressY[1];
+ lastMousePressTime[0] = lastMousePressTime[1];
+ lastMousePressX[1] = lastMousePressX[2];
+ lastMousePressY[1] = lastMousePressY[2];
+ lastMousePressTime[1] = lastMousePressTime[2];
+ lastMousePressX[2] = e->pos().x();
+ lastMousePressY[2] = e->pos().y();
+ lastMousePressTime[2] = e->timestamp();
+ lastMouseEventWasPress = true;
+ if (!mousePassthrough) {
+ x = (int)(e->pos().x() * scaleFactor);
+ y = (int)(e->pos().y() * scaleFactor);
+ if (e->button() == Qt::LeftButton) {
+ core->startSelection(x, y, e->modifiers() & Qt::ShiftModifier);
+ } else if (e->button() == Qt::MiddleButton) {
+ core->startPan(x, y);
+ }
+ }
+ emit mousePress(e);
+}
+
+void XpdfWidget::mouseReleaseEvent(QMouseEvent *e) {
+ int x, y;
+
+ // some versions of Qt drop mouse press events in double-clicks (?)
+ if (!lastMouseEventWasPress) {
+ mousePressEvent(e);
+ }
+ lastMouseEventWasPress = false;
+
+ x = y = 0;
+ if (!mousePassthrough) {
+ x = (int)(e->pos().x() * scaleFactor);
+ y = (int)(e->pos().y() * scaleFactor);
+ if (e->button() == Qt::LeftButton) {
+ core->endSelection(x, y);
+ } else if (e->button() == Qt::MiddleButton) {
+ core->endPan(x, y);
+ }
+ }
+ emit mouseRelease(e);
+
+ // double and triple clicks have to be "quick" and "nearby";
+ // single clicks just have to be "nearby"
+ ulong maxTime = (ulong)QApplication::doubleClickInterval();
+ int maxDistance = QApplication::startDragDistance();
+ if (e->timestamp() - lastMousePressTime[0] < 2 * maxTime &&
+ abs(e->pos().x() - lastMousePressX[0])
+ + abs(e->pos().y() - lastMousePressY[0]) <= maxDistance) {
+ if (!mousePassthrough && e->button() == Qt::LeftButton) {
+ core->selectLine(x, y);
+ }
+ emit mouseTripleClick(e);
+ } else if (e->timestamp() - lastMousePressTime[1] < maxTime &&
+ abs(e->pos().x() - lastMousePressX[1])
+ + abs(e->pos().y() - lastMousePressY[1]) <= maxDistance) {
+ if (!mousePassthrough && e->button() == Qt::LeftButton) {
+ core->selectWord(x, y);
+ }
+ emit mouseDoubleClick(e);
+ } else if (abs(e->pos().x() - lastMousePressX[2])
+ + abs(e->pos().y() - lastMousePressY[2]) <= maxDistance) {
+ emit mouseClick(e);
+ }
+}
+
+void XpdfWidget::mouseMoveEvent(QMouseEvent *e) {
+ int x, y;
+
+ x = (int)(e->pos().x() * scaleFactor);
+ y = (int)(e->pos().y() * scaleFactor);
+ core->mouseMove(x, y);
+ emit mouseMove(e);
+}
+
+void XpdfWidget::wheelEvent(QWheelEvent *e) {
+ if (!mousePassthrough) {
+ QAbstractScrollArea::wheelEvent(e);
+ }
+ emit mouseWheel(e);
+}
+
+bool XpdfWidget::eventFilter(QObject *obj, QEvent *event) {
+ QGestureEvent *gestureEvent;
+ QPanGesture *panGesture;
+ QPinchGesture *pinchGesture;
+ double z;
+
+ if (obj == viewport() && event->type() == QEvent::Gesture) {
+ gestureEvent = (QGestureEvent *)event;
+ if (touchPanEnabled &&
+ (panGesture = (QPanGesture *)gestureEvent->gesture(Qt::PanGesture))) {
+ core->scrollTo(core->getScrollX() - (int)panGesture->delta().x(),
+ core->getScrollY() - (int)panGesture->delta().y());
+ gestureEvent->accept();
+ return true;
+ } else if (touchZoomEnabled &&
+ (pinchGesture =
+ (QPinchGesture *)gestureEvent->gesture(Qt::PinchGesture))) {
+ if (pinchGesture->changeFlags() & QPinchGesture::ScaleFactorChanged) {
+ if (pinchGesture->state() == Qt::GestureStarted) {
+ pinchZoomStart = getZoomPercent(core->getMidPageNum());
+ } else {
+ z = pinchZoomStart * pinchGesture->totalScaleFactor();
+ if (z < 10) {
+ z = 10;
+ } else if (z > 800) {
+ z = 800;
+ }
+ core->zoomCentered(z);
+ }
+ }
+ gestureEvent->accept();
+ return true;
+ }
+ }
+ return QAbstractScrollArea::eventFilter(obj, event);
+}
+
+void XpdfWidget::tick() {
+ core->tick();
+}