diff options
-rw-r--r-- | kfile-plugins/pdf/Makefile.am | 6 | ||||
-rw-r--r-- | kfile-plugins/pdf/configure.in.in | 17 | ||||
-rw-r--r-- | kfile-plugins/pdf/poppler-qt/Makefile.am | 42 | ||||
-rw-r--r-- | kfile-plugins/pdf/poppler-qt/poppler-document.cc | 334 | ||||
-rw-r--r-- | kfile-plugins/pdf/poppler-qt/poppler-fontinfo.cc | 83 | ||||
-rw-r--r-- | kfile-plugins/pdf/poppler-qt/poppler-link-qt3.h | 188 | ||||
-rw-r--r-- | kfile-plugins/pdf/poppler-qt/poppler-link.cc | 267 | ||||
-rw-r--r-- | kfile-plugins/pdf/poppler-qt/poppler-page-transition-private.h | 33 | ||||
-rw-r--r-- | kfile-plugins/pdf/poppler-qt/poppler-page-transition.cc | 95 | ||||
-rw-r--r-- | kfile-plugins/pdf/poppler-qt/poppler-page-transition.h | 146 | ||||
-rw-r--r-- | kfile-plugins/pdf/poppler-qt/poppler-page.cc | 362 | ||||
-rw-r--r-- | kfile-plugins/pdf/poppler-qt/poppler-private.cc | 147 | ||||
-rw-r--r-- | kfile-plugins/pdf/poppler-qt/poppler-private.h | 97 | ||||
-rw-r--r-- | kfile-plugins/pdf/poppler-qt/poppler-qt.h | 310 | ||||
-rw-r--r-- | kfile-plugins/pdf/poppler-qt/test-poppler-qt.cpp | 122 |
15 files changed, 2239 insertions, 10 deletions
diff --git a/kfile-plugins/pdf/Makefile.am b/kfile-plugins/pdf/Makefile.am index 841d9980..c8af5244 100644 --- a/kfile-plugins/pdf/Makefile.am +++ b/kfile-plugins/pdf/Makefile.am @@ -1,7 +1,9 @@ ## Makefile.am for the pdf file meta info plugin +subdirs=poppler-qt + # set the include path for X, qt and KDE -INCLUDES = $(all_includes) $(POPPLER_CFLAGS) +INCLUDES = $(all_includes) -I$(top_srcdir)/kfile-plugins/pdf/poppler-qt # these are the headers for your project noinst_HEADERS = kfile_pdf.h @@ -10,7 +12,7 @@ kde_module_LTLIBRARIES = kfile_pdf.la kfile_pdf_la_SOURCES = kfile_pdf.cpp kfile_pdf_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) -kfile_pdf_la_LIBADD = $(LIB_KIO) $(POPPLER_LIBS) +kfile_pdf_la_LIBADD = $(LIB_KIO) -L$(top_builddir)/kfile-plugins/pdf/poppler-qt/ -lpoppler-qt # let automoc handle all of the meta source files (moc) METASOURCES = AUTO diff --git a/kfile-plugins/pdf/configure.in.in b/kfile-plugins/pdf/configure.in.in index 926497a5..ec2fff51 100644 --- a/kfile-plugins/pdf/configure.in.in +++ b/kfile-plugins/pdf/configure.in.in @@ -3,13 +3,14 @@ AC_ARG_WITH([poppler], [Enable PDF support through poppler @<:@default=check@:>@])], [], with_poppler=check) -# Compile the pdf meta info plugin only if Poppler is available -if test "x$with_poppler" != xno; then - PKG_CHECK_MODULES(POPPLER, poppler-qt >= 0.3.1, have_poppler=yes, have_poppler=no) - - if test "x$with_poppler" != xcheck && test "x$have_poppler" != xyes; then - AC_MSG_ERROR([--with-poppler was given, but test for poppler failed]) - fi -fi +## Compile the pdf meta info plugin only if Poppler is available +#if test "x$with_poppler" != xno; then +# PKG_CHECK_MODULES(POPPLER, poppler-qt >= 0.3.1, have_poppler=yes, have_poppler=no) +# +# if test "x$with_poppler" != xcheck && test "x$have_poppler" != xyes; then +# AC_MSG_ERROR([--with-poppler was given, but test for poppler failed]) +# fi +#fi +have_poppler=yes AM_CONDITIONAL(include_PDF, test "x$have_poppler" = xyes) diff --git a/kfile-plugins/pdf/poppler-qt/Makefile.am b/kfile-plugins/pdf/poppler-qt/Makefile.am new file mode 100644 index 00000000..f23d0307 --- /dev/null +++ b/kfile-plugins/pdf/poppler-qt/Makefile.am @@ -0,0 +1,42 @@ +INCLUDES = \ + -I$(top_srcdir) \ + -I/usr/include/poppler \ + $(cairo_includes) \ + $(QT_INCLUDES) \ + $(FREETYPE_CFLAGS) \ + $(FONTCONFIG_CFLAGS) + + +poppler_includedir = $(includedir)/poppler/qt3 +poppler_include_HEADERS = \ + poppler-qt.h \ + poppler-page-transition.h \ + poppler-link-qt3.h + +lib_LTLIBRARIES = libpoppler-qt.la +libpoppler_qt_la_SOURCES = \ + poppler-document.cc \ + poppler-fontinfo.cc \ + poppler-link.cc \ + poppler-page.cc \ + poppler-page-transition.cc \ + poppler-page-transition-private.h \ + poppler-private.cc \ + poppler-private.h + +libpoppler_qt_la_LIBADD = \ + -lpoppler \ + $(QT_LIBS) \ + $(FREETYPE_LIBS) \ + $(FONTCONFIG_LIBS) + +# libpoppler_qt_la_LDFLAGS = -version-info 2:0:0 @create_shared_lib@ + +test_poppler_qt_SOURCES = \ + test-poppler-qt.cpp + +test_poppler_qt_LDADD = \ + $(top_builddir)/poppler/libpoppler.la \ + libpoppler-qt.la \ + $(QT_LIBS) \ + $(FREETYPE_LIBS) diff --git a/kfile-plugins/pdf/poppler-qt/poppler-document.cc b/kfile-plugins/pdf/poppler-qt/poppler-document.cc new file mode 100644 index 00000000..a9a7a319 --- /dev/null +++ b/kfile-plugins/pdf/poppler-qt/poppler-document.cc @@ -0,0 +1,334 @@ +/* poppler-document.cc: qt interface to poppler + * Copyright (C) 2005, Net Integration Technologies, Inc. + * Copyright (C) 2005-2009, Albert Astals Cid <aacid@kde.org> + * Copyright (C) 2006, Stefan Kebekus <stefan.kebekus@math.uni-koeln.de> + * Copyright (C) 2006, Wilfried Huss <Wilfried.Huss@gmx.at> + * + * 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 + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <poppler-qt.h> +#include <qfile.h> +#include <GlobalParams.h> +#include <Outline.h> +#include <PDFDoc.h> +#include <PSOutputDev.h> +#include <Catalog.h> +#include <ErrorCodes.h> +#include <SplashOutputDev.h> +#include <splash/SplashBitmap.h> +#include <DateInfo.h> +#include "poppler-private.h" + +#undef bool + +namespace Poppler { + +Document *Document::load(const QString &filePath) +{ + if (!globalParams) { + globalParams = new GlobalParams(); + } + + DocumentData *doc = new DocumentData(new GooString(QFile::encodeName(filePath)), NULL); + Document *pdoc; + if (doc->doc.isOk() || doc->doc.getErrorCode() == errEncrypted) { + pdoc = new Document(doc); + if (doc->doc.getErrorCode() == errEncrypted) + pdoc->data->locked = true; + else + pdoc->data->locked = false; + pdoc->data->m_fontInfoScanner = new FontInfoScanner(&(doc->doc)); + return pdoc; + } + else + return NULL; +} + +Document::Document(DocumentData *dataA) +{ + data = dataA; +} + +Document::~Document() +{ + delete data; +} + +bool Document::isLocked() const +{ + return data->locked; +} + +bool Document::unlock(const QCString &password) +{ + if (data->locked) { + /* racier then it needs to be */ + GooString *filename = new GooString(data->doc.getFileName()); + GooString *pwd = new GooString(password.data()); + DocumentData *doc2 = new DocumentData(filename, pwd); + delete pwd; + if (!doc2->doc.isOk()) { + delete doc2; + } else { + delete data; + data = doc2; + data->locked = false; + data->m_fontInfoScanner = new FontInfoScanner(&(data->doc)); + } + } + return data->locked; +} + +Document::PageMode Document::getPageMode(void) const +{ + switch (data->doc.getCatalog()->getPageMode()) { + case Catalog::pageModeNone: + return UseNone; + case Catalog::pageModeOutlines: + return UseOutlines; + case Catalog::pageModeThumbs: + return UseThumbs; + case Catalog::pageModeFullScreen: + return FullScreen; + case Catalog::pageModeOC: + return UseOC; + default: + return UseNone; + } +} + +int Document::getNumPages() const +{ + return data->doc.getNumPages(); +} + +QValueList<FontInfo> Document::fonts() const +{ + QValueList<FontInfo> ourList; + scanForFonts(getNumPages(), &ourList); + return ourList; +} + +bool Document::scanForFonts( int numPages, QValueList<FontInfo> *fontList ) const +{ + GooList *items = data->m_fontInfoScanner->scan( numPages ); + + if ( NULL == items ) + return false; + + for ( int i = 0; i < items->getLength(); ++i ) { + QString fontName; + if (((::FontInfo*)items->get(i))->getName()) + fontName = ((::FontInfo*)items->get(i))->getName()->getCString(); + + FontInfo font(fontName, + ((::FontInfo*)items->get(i))->getEmbedded(), + ((::FontInfo*)items->get(i))->getSubset(), + (Poppler::FontInfo::Type)((::FontInfo*)items->get(i))->getType()); + fontList->append(font); + } + deleteGooList(items, ::FontInfo); + return true; +} + +/* borrowed from kpdf */ +QString Document::getInfo( const QString & type ) const +{ + // [Albert] Code adapted from pdfinfo.cc on xpdf + Object info; + if ( data->locked ) + return NULL; + + data->doc.getDocInfo( &info ); + if ( !info.isDict() ) + return NULL; + + QString result; + Object obj; + GooString *s1; + GBool isUnicode; + Unicode u; + int i; + Dict *infoDict = info.getDict(); + + if ( infoDict->lookup( (char*)type.latin1(), &obj )->isString() ) + { + s1 = obj.getString(); + if ( ( s1->getChar(0) & 0xff ) == 0xfe && ( s1->getChar(1) & 0xff ) == 0xff ) + { + isUnicode = gTrue; + i = 2; + } + else + { + isUnicode = gFalse; + i = 0; + } + while ( i < obj.getString()->getLength() ) + { + if ( isUnicode ) + { + u = ( ( s1->getChar(i) & 0xff ) << 8 ) | ( s1->getChar(i+1) & 0xff ); + i += 2; + } + else + { + u = s1->getChar(i) & 0xff; + ++i; + } + result += unicodeToQString( &u, 1 ); + } + obj.free(); + info.free(); + return result; + } + obj.free(); + info.free(); + return NULL; +} + +/* borrowed from kpdf */ +QDateTime Document::getDate( const QString & type ) const +{ + // [Albert] Code adapted from pdfinfo.cc on xpdf + if ( data->locked ) + return QDateTime(); + + Object info; + data->doc.getDocInfo( &info ); + if ( !info.isDict() ) { + info.free(); + return QDateTime(); + } + + Object obj; + int year, mon, day, hour, min, sec, tz_hour, tz_minute; + char tz; + Dict *infoDict = info.getDict(); + QString result; + + if ( infoDict->lookup( (char*)type.latin1(), &obj )->isString() ) + { + QString s = UnicodeParsedString(obj.getString()); + // TODO do something with the timezone information + if ( parseDateString( s.latin1(), &year, &mon, &day, &hour, &min, &sec, &tz, &tz_hour, &tz_minute ) ) + { + QDate d( year, mon, day ); //CHECK: it was mon-1, Jan->0 (??) + QTime t( hour, min, sec ); + if ( d.isValid() && t.isValid() ) { + obj.free(); + info.free(); + return QDateTime( d, t ); + } + } + } + obj.free(); + info.free(); + return QDateTime(); +} + +bool Document::isEncrypted() const +{ + return data->doc.isEncrypted(); +} + +bool Document::isLinearized() const +{ + return data->doc.isLinearized(); +} + +bool Document::okToPrint() const +{ + return data->doc.okToPrint(); +} + +bool Document::okToChange() const +{ + return data->doc.okToChange(); +} + +bool Document::okToCopy() const +{ + return data->doc.okToCopy(); +} + +bool Document::okToAddNotes() const +{ + return data->doc.okToAddNotes(); +} + +double Document::getPDFVersion() const +{ + return data->doc.getPDFMajorVersion () + data->doc.getPDFMinorVersion() / 10.0; +} + +void Document::getPdfVersion(int *major, int *minor) const +{ + if (major) + *major = data->doc.getPDFMajorVersion(); + if (minor) + *minor = data->doc.getPDFMinorVersion(); +} + +QDomDocument *Document::toc() const +{ + Outline * outline = data->doc.getOutline(); + if ( !outline ) + return NULL; + + GooList * items = outline->getItems(); + if ( !items || items->getLength() < 1 ) + return NULL; + + QDomDocument *toc = new QDomDocument(); + if ( items->getLength() > 0 ) + data->addTocChildren( toc, toc, items ); + + return toc; +} + +LinkDestination *Document::linkDestination( const QString &name ) +{ + GooString * namedDest = QStringToGooString( name ); + LinkDestinationData ldd(NULL, namedDest, data); + LinkDestination *ld = new LinkDestination(ldd); + delete namedDest; + return ld; +} + +bool Document::print(const QString &fileName, QValueList<int> pageList, double hDPI, double vDPI, int rotate) +{ + return print(fileName, pageList, hDPI, vDPI, rotate, -1, -1); +} + +bool Document::print(const QString &file, QValueList<int> pageList, double hDPI, double vDPI, int rotate, int paperWidth, int paperHeight) +{ + PSOutputDev *psOut = new PSOutputDev(file.latin1(), data->doc.getXRef(), data->doc.getCatalog(), NULL, 1, data->doc.getNumPages(), psModePS, paperWidth, paperHeight); + + if (psOut->isOk()) { + QValueList<int>::iterator it; + for (it = pageList.begin(); it != pageList.end(); ++it ) + data->doc.displayPage(psOut, *it, hDPI, vDPI, rotate, gFalse, gTrue, gTrue); + + delete psOut; + return true; + } else { + delete psOut; + return false; + } +} + +} diff --git a/kfile-plugins/pdf/poppler-qt/poppler-fontinfo.cc b/kfile-plugins/pdf/poppler-qt/poppler-fontinfo.cc new file mode 100644 index 00000000..6eb9d26f --- /dev/null +++ b/kfile-plugins/pdf/poppler-qt/poppler-fontinfo.cc @@ -0,0 +1,83 @@ +/* poppler-qt.h: qt interface to poppler + * Copyright (C) 2005, Albert Astals Cid <aacid@kde.org> + * + * 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 + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "poppler-qt.h" + +namespace Poppler { + +class FontInfoData +{ + public: + QString fontName; + bool isEmbedded; + bool isSubset; + FontInfo::Type type; +}; + +FontInfo::FontInfo( const QString &fontName, const bool isEmbedded, const bool isSubset, Type type ) +{ + data = new FontInfoData(); + data->fontName = fontName; + data->isEmbedded = isEmbedded; + data->isSubset = isSubset; + data->type = type; +} + +FontInfo::FontInfo( const FontInfo &fi ) +{ + data = new FontInfoData(); + data->fontName = fi.data->fontName; + data->isEmbedded = fi.data->isEmbedded; + data->isSubset = fi.data->isSubset; + data->type = fi.data->type; +} + +FontInfo::FontInfo() +{ + data = new FontInfoData(); + data->isEmbedded = false; + data->isSubset = false; + data->type = unknown; +} + +FontInfo::~FontInfo() +{ + delete data; +} + +const QString &FontInfo::name() const +{ + return data->fontName; +} + +bool FontInfo::isEmbedded() const +{ + return data->isEmbedded; +} + +bool FontInfo::isSubset() const +{ + return data->isSubset; +} + +FontInfo::Type FontInfo::type() const +{ + return data->type; +} + +} diff --git a/kfile-plugins/pdf/poppler-qt/poppler-link-qt3.h b/kfile-plugins/pdf/poppler-qt/poppler-link-qt3.h new file mode 100644 index 00000000..82127207 --- /dev/null +++ b/kfile-plugins/pdf/poppler-qt/poppler-link-qt3.h @@ -0,0 +1,188 @@ +/* poppler-link.h: qt interface to poppler + * Copyright (C) 2006, Albert Astals Cid <aacid@kde.org> + * Adapting code from + * Copyright (C) 2004 by Enrico Ros <eros.kde@email.it> + * + * 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 + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _POPPLER_LINK_H_ +#define _POPPLER_LINK_H_ + +#include <qstring.h> +#include <qrect.h> + +namespace Poppler { + +class LinkDestinationData; + +class LinkDestination +{ + public: + enum Kind + { + destXYZ = 1, + destFit = 2, + destFitH = 3, + destFitV = 4, + destFitR = 5, + destFitB = 6, + destFitBH = 7, + destFitBV = 8 + }; + + LinkDestination(const LinkDestinationData &data); + LinkDestination(const QString &description); + + // Accessors. + Kind kind() const; + int pageNumber() const; + double left() const; + double bottom() const; + double right() const; + double top() const; + double zoom() const; + bool isChangeLeft() const; + bool isChangeTop() const; + bool isChangeZoom() const; + + QString toString() const; + + private: + Kind m_kind; // destination type + int m_pageNum; // page number + double m_left, m_bottom; // position + double m_right, m_top; + double m_zoom; // zoom factor + bool m_changeLeft, m_changeTop; // for destXYZ links, which position + bool m_changeZoom; // components to change +}; + +/** + * @short Encapsulates data that describes a link. + * + * This is the base class for links. It makes mandatory for inherited + * widgets to reimplement the 'linkType' method and return the type of + * the link described by the reimplemented class. + */ +class Link +{ + public: + Link( const QRect &linkArea ); + + // get link type (inherited classes mustreturn an unique identifier) + enum LinkType { None, Goto, Execute, Browse, Action, Movie }; + virtual LinkType linkType() const; + + // virtual destructor + virtual ~Link(); + + QRect linkArea() const; + + private: + QRect m_linkArea; +}; + + +/** Goto: a viewport and maybe a reference to an external filename **/ +class LinkGoto : public Link +{ + public: + LinkGoto( const QRect &linkArea, QString extFileName, const LinkDestination & destination ); + + // query for goto parameters + bool isExternal() const; + const QString & fileName() const; + const LinkDestination & destination() const; + LinkType linkType() const; + + private: + QString m_extFileName; + LinkDestination m_destination; +}; + +/** Execute: filename and parameters to execute **/ +class LinkExecute : public Link +{ + public: + // query for filename / parameters + const QString & fileName() const; + const QString & parameters() const; + + // create a Link_Execute + LinkExecute( const QRect &linkArea, const QString & file, const QString & params ); + LinkType linkType() const; + + private: + QString m_fileName; + QString m_parameters; +}; + +/** Browse: an URL to open, ranging from 'http://' to 'mailto:' etc.. **/ +class LinkBrowse : public Link +{ + public: + // query for URL + const QString & url() const; + + // create a Link_Browse + LinkBrowse( const QRect &linkArea, const QString &url ); + LinkType linkType() const; + + private: + QString m_url; +}; + +/** Action: contains an action to perform on document / viewer **/ +class LinkAction : public Link +{ + public: + // define types of actions + enum ActionType { PageFirst = 1, + PagePrev = 2, + PageNext = 3, + PageLast = 4, + HistoryBack = 5, + HistoryForward = 6, + Quit = 7, + Presentation = 8, + EndPresentation = 9, + Find = 10, + GoToPage = 11, + Close = 12 }; + + // query for action type + ActionType actionType() const; + + // create a Link_Action + LinkAction( const QRect &linkArea, ActionType actionType ); + LinkType linkType() const; + + private: + ActionType m_type; +}; + +/** Movie: Not yet defined -> think renaming to 'Media' link **/ +class LinkMovie : public Link +// TODO this (Movie link) +{ + public: + LinkMovie( const QRect &linkArea ); + LinkType linkType() const; +}; + +} + +#endif diff --git a/kfile-plugins/pdf/poppler-qt/poppler-link.cc b/kfile-plugins/pdf/poppler-qt/poppler-link.cc new file mode 100644 index 00000000..af6d6452 --- /dev/null +++ b/kfile-plugins/pdf/poppler-qt/poppler-link.cc @@ -0,0 +1,267 @@ +/* poppler-link.cc: qt interface to poppler + * Copyright (C) 2006, 2008 Albert Astals Cid + * Adapting code from + * Copyright (C) 2004 by Enrico Ros <eros.kde@email.it> + * + * 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 + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <poppler-qt.h> +#include <poppler-private.h> + +#include <qstringlist.h> + +#include <Link.h> + +namespace Poppler { + + LinkDestination::LinkDestination(const LinkDestinationData &data) + { + bool deleteDest = false; + LinkDest *ld = data.ld; + + if ( data.namedDest && !ld ) + { + deleteDest = true; + ld = data.doc->doc.findDest( data.namedDest ); + } + + if (!ld) return; + + if (ld->getKind() == ::destXYZ) m_kind = destXYZ; + else if (ld->getKind() == ::destFit) m_kind = destFit; + else if (ld->getKind() == ::destFitH) m_kind = destFitH; + else if (ld->getKind() == ::destFitV) m_kind = destFitV; + else if (ld->getKind() == ::destFitR) m_kind = destFitR; + else if (ld->getKind() == ::destFitB) m_kind = destFitB; + else if (ld->getKind() == ::destFitBH) m_kind = destFitBH; + else if (ld->getKind() == ::destFitBV) m_kind = destFitBV; + + if ( !ld->isPageRef() ) m_pageNum = ld->getPageNum(); + else + { + Ref ref = ld->getPageRef(); + m_pageNum = data.doc->doc.findPage( ref.num, ref.gen ); + } + double left = ld->getLeft(); + double bottom = ld->getBottom(); + double right = ld->getRight(); + double top = ld->getTop(); + m_zoom = ld->getZoom(); + m_changeLeft = ld->getChangeLeft(); + m_changeTop = ld->getChangeTop(); + m_changeZoom = ld->getChangeZoom(); + + int leftAux = 0, topAux = 0, rightAux = 0, bottomAux = 0; + +#if defined(HAVE_SPLASH) + SplashOutputDev *sod = data.doc->getOutputDev(); + sod->cvtUserToDev( left, top, &leftAux, &topAux ); + sod->cvtUserToDev( right, bottom, &rightAux, &bottomAux ); +#endif + + m_left = leftAux; + m_top = topAux; + m_right = rightAux; + m_bottom = bottomAux; + + if (deleteDest) delete ld; + } + + LinkDestination::LinkDestination(const QString &description) + { + QStringList tokens = QStringList::split(';', description); + m_kind = static_cast<Kind>(tokens[0].toInt()); + m_pageNum = tokens[1].toInt(); + m_left = tokens[2].toDouble(); + m_bottom = tokens[3].toDouble(); + m_right = tokens[4].toDouble(); + m_top = tokens[5].toDouble(); + m_zoom = tokens[6].toDouble(); + m_changeLeft = static_cast<bool>(tokens[7].toInt()); + m_changeTop = static_cast<bool>(tokens[8].toInt()); + m_changeZoom = static_cast<bool>(tokens[9].toInt()); + } + + LinkDestination::Kind LinkDestination::kind() const + { + return m_kind; + } + + int LinkDestination::pageNumber() const + { + return m_pageNum; + } + + double LinkDestination::left() const + { + return m_left; + } + + double LinkDestination::bottom() const + { + return m_bottom; + } + + double LinkDestination::right() const + { + return m_right; + } + + double LinkDestination::top() const + { + return m_top; + } + + double LinkDestination::zoom() const + { + return m_zoom; + } + + bool LinkDestination::isChangeLeft() const + { + return m_changeLeft; + } + + bool LinkDestination::isChangeTop() const + { + return m_changeTop; + } + + bool LinkDestination::isChangeZoom() const + { + return m_changeZoom; + } + + QString LinkDestination::toString() const + { + QString s = QString::number( (Q_INT8)m_kind ); + s += ";" + QString::number( m_pageNum ); + s += ";" + QString::number( m_left ); + s += ";" + QString::number( m_bottom ); + s += ";" + QString::number( m_right ); + s += ";" + QString::number( m_top ); + s += ";" + QString::number( m_zoom ); + s += ";" + QString::number( (Q_INT8)m_changeLeft ); + s += ";" + QString::number( (Q_INT8)m_changeTop ); + s += ";" + QString::number( (Q_INT8)m_changeZoom ); + return s; + } + + + // Link + Link::~Link() + { + } + + Link::Link(const QRect &linkArea) : m_linkArea(linkArea) + { + } + + Link::LinkType Link::linkType() const + { + return None; + } + + QRect Link::linkArea() const + { + return m_linkArea; + } + + // LinkGoto + LinkGoto::LinkGoto( const QRect &linkArea, QString extFileName, const LinkDestination & destination ) : Link(linkArea), m_extFileName(extFileName), m_destination(destination) + { + } + + bool LinkGoto::isExternal() const + { + return !m_extFileName.isEmpty(); + } + + const QString &LinkGoto::fileName() const + { + return m_extFileName; + } + + const LinkDestination &LinkGoto::destination() const + { + return m_destination; + } + + Link::LinkType LinkGoto::linkType() const + { + return Goto; + } + + // LinkExecute + LinkExecute::LinkExecute( const QRect &linkArea, const QString & file, const QString & params ) : Link(linkArea), m_fileName(file), m_parameters(params) + { + } + + const QString & LinkExecute::fileName() const + { + return m_fileName; + } + const QString & LinkExecute::parameters() const + { + return m_parameters; + } + + Link::LinkType LinkExecute::linkType() const + { + return Execute; + } + + // LinkBrowse + LinkBrowse::LinkBrowse( const QRect &linkArea, const QString &url ) : Link(linkArea), m_url(url) + { + } + + const QString & LinkBrowse::url() const + { + return m_url; + } + + Link::LinkType LinkBrowse::linkType() const + { + return Browse; + } + + // LinkAction + LinkAction::LinkAction( const QRect &linkArea, ActionType actionType ) : Link(linkArea), m_type(actionType) + { + } + + LinkAction::ActionType LinkAction::actionType() const + { + return m_type; + } + + Link::LinkType LinkAction::linkType() const + { + return Action; + } + + // LinkMovie + LinkMovie::LinkMovie( const QRect &linkArea ) : Link(linkArea) + { + } + + Link::LinkType LinkMovie::linkType() const + { + return Movie; + } + +} diff --git a/kfile-plugins/pdf/poppler-qt/poppler-page-transition-private.h b/kfile-plugins/pdf/poppler-qt/poppler-page-transition-private.h new file mode 100644 index 00000000..8bc70825 --- /dev/null +++ b/kfile-plugins/pdf/poppler-qt/poppler-page-transition-private.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2005, Albert Astals Cid + * + * 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 + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef POPPLER_PAGE_TRANSITION_PRIVATE_H +#define POPPLER_PAGE_TRANSITION_PRIVATE_H + +class Object; + +namespace Poppler { + +class PageTransitionParams { + public: + Object *dictObj; +}; + +} + +#endif // POPPLER_PAGE_TRANSITION_PRIVATE_H diff --git a/kfile-plugins/pdf/poppler-qt/poppler-page-transition.cc b/kfile-plugins/pdf/poppler-qt/poppler-page-transition.cc new file mode 100644 index 00000000..cde8818d --- /dev/null +++ b/kfile-plugins/pdf/poppler-qt/poppler-page-transition.cc @@ -0,0 +1,95 @@ +/* PageTransition.cc + * Copyright (C) 2005, Net Integration Technologies, Inc. + * + * 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 + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "PageTransition.h" +#include "poppler-page-transition.h" +#include "poppler-page-transition-private.h" + +namespace Poppler { + +class PageTransitionData +{ + public: + PageTransitionData(Object *trans) + { + pt = new ::PageTransition(trans); + } + + PageTransitionData(const PageTransitionData &ptd) + { + pt = new ::PageTransition(*ptd.pt); + } + + ~PageTransitionData() + { + delete pt; + } + + ::PageTransition *pt; +}; + +PageTransition::PageTransition(const PageTransitionParams ¶ms) +{ + data = new PageTransitionData(params.dictObj); +} + +PageTransition::PageTransition(const PageTransition &pt) +{ + data = new PageTransitionData(*pt.data); +} + +PageTransition::~PageTransition() +{ + delete data; +} + +PageTransition::Type PageTransition::type() const +{ + return (Poppler::PageTransition::Type)data->pt->getType(); +} + +int PageTransition::duration() const +{ + return data->pt->getDuration(); +} + +PageTransition::Alignment PageTransition::alignment() const +{ + return (Poppler::PageTransition::Alignment)data->pt->getAlignment(); +} + +PageTransition::Direction PageTransition::direction() const +{ + return (Poppler::PageTransition::Direction)data->pt->getDirection(); +} + +int PageTransition::angle() const +{ + return data->pt->getAngle(); +} + +double PageTransition::scale() const +{ + return data->pt->getScale(); +} +bool PageTransition::isRectangular() const +{ + return data->pt->isRectangular(); +} + +} diff --git a/kfile-plugins/pdf/poppler-qt/poppler-page-transition.h b/kfile-plugins/pdf/poppler-qt/poppler-page-transition.h new file mode 100644 index 00000000..53002ff9 --- /dev/null +++ b/kfile-plugins/pdf/poppler-qt/poppler-page-transition.h @@ -0,0 +1,146 @@ +/* PageTransition.h + * Copyright (C) 2005, Net Integration Technologies, Inc. + * Copyright (C) 2005, Brad Hards <bradh@frogmouth.net> + * + * 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 + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __PAGETRANSITION_X_H__ +#define __PAGETRANSITION_X_H__ + +namespace Poppler { + +class PageTransitionParams; +class PageTransitionData; + +/** + \brief Describes how a PDF file viewer shall perform the transition + from one page to another + + In PDF files there is a way to specify if the viewer shall use + certain effects to perform the transition from one page to + another. This feature can be used, e.g., in a PDF-based beamer + presentation. + + This utility class represents the transition effect, and can be + used to extract the information from a PDF object. +*/ + + +class PageTransition { + public: + + /** \brief transition effect that shall be used + */ + // if changed remember to keep in sync with PageTransition.h enum + enum Type { + Replace = 0, + Split, + Blinds, + Box, + Wipe, + Dissolve, + Glitter, + Fly, + Push, + Cover, + Uncover, + Fade + }; + + /** \brief alignment of the transition effect that shall be used + */ + // if changed remember to keep in sync with PageTransition.h enum + enum Alignment { + Horizontal = 0, + Vertical + }; + + /** \brief direction of the transition effect that shall be used + */ + // if changed remember to keep in sync with PageTransition.h enum + enum Direction { + Inward = 0, + Outward + }; + + /** \brief Construct a new PageTransition object from a page dictionary. + + Users of the library will rarely need to construct a + PageTransition object themselves. Instead, the method + Poppler::Page::transition() can be used to find out if a certain + transition effect is specified. + + @warning In case or error, this method will print an error message to stderr, + and construct a default object. + + @param params an object whose dictionary will be read and + parsed. This must be a valid object, whose dictionaries are + accessed by the constructor. The object is only accessed by this + constructor, and may be deleted after the constructor returns. + */ + PageTransition(const PageTransitionParams ¶ms); + + /** \brief copy constructor */ + PageTransition(const PageTransition &pt); + + /** + Destructor + */ + ~PageTransition(); + + /** + \brief Get type of the transition. + */ + Type type() const; + + /** + \brief Get duration of the transition in seconds. + */ + int duration() const; + + /** + \brief Get dimension in which the transition effect occurs. + */ + Alignment alignment() const; + + /** + \brief Get direction of motion of the transition effect. + */ + Direction direction() const; + + /** + \brief Get direction in which the transition effect moves. + */ + int angle() const; + + /** + \brief Get starting or ending scale. + */ + double scale() const; + + /** + \brief Returns true if the area to be flown is rectangular and + opaque. + */ + bool isRectangular() const; + + private: + PageTransitionData *data; +}; + +} + +#endif diff --git a/kfile-plugins/pdf/poppler-qt/poppler-page.cc b/kfile-plugins/pdf/poppler-qt/poppler-page.cc new file mode 100644 index 00000000..a42aa15c --- /dev/null +++ b/kfile-plugins/pdf/poppler-qt/poppler-page.cc @@ -0,0 +1,362 @@ +/* poppler-page.cc: qt interface to poppler + * Copyright (C) 2005, Net Integration Technologies, Inc. + * Copyright (C) 2005-2006, Albert Astals Cid <aacid@kde.org> + * Copyright (C) 2005, Tobias Koening <tokoe@kde.org> + * Copyright (C) 2005, Stefan Kebekus <stefan.kebekus@math.uni-koeln.de> + * Copyright (C) 2006, Wilfried Huss <Wilfried.Huss@gmx.at> + * Copyright (C) 2006, Jerry Epplin <jepplin@globalvelocity.com> + * Copyright (C) 2007, 2010, Pino Toscano <pino@kde.org> + * + * 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 + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <poppler-qt.h> +#include <qfile.h> +#include <qimage.h> +#include <config.h> +#include <GlobalParams.h> +#include <PDFDoc.h> +#include <Catalog.h> +#include <ErrorCodes.h> +#include <TextOutputDev.h> +#include <Link.h> +#if defined(HAVE_SPLASH) +#include <SplashOutputDev.h> +#include <splash/SplashBitmap.h> +#endif + +#include "poppler-private.h" +#include "poppler-page-transition-private.h" + +namespace Poppler { + +class PageData { + public: + const Document *doc; + int index; + PageTransition *transition; +}; + +Page::Page(const Document *doc, int index) { + data = new PageData(); + data->index = index; + data->doc = doc; + data->transition = 0; +} + +Page::~Page() +{ + delete data->transition; + delete data; +} + +void Page::renderToPixmap(QPixmap **q, int x, int y, int w, int h, bool doLinks) const +{ + renderToPixmap(q, x, y, w, h, 72.0, 72.0, doLinks); +} + +void Page::renderToPixmap(QPixmap **q, int x, int y, int w, int h, double xres, double yres, bool doLinks) const +{ + QImage img = renderToImage(xres, yres, doLinks); + *q = new QPixmap( img ); +} + +QImage Page::renderToImage(double xres, double yres, bool doLinks) const +{ +#if defined(HAVE_SPLASH) + SplashOutputDev *output_dev; + SplashBitmap *bitmap; + SplashColorPtr color_ptr; + output_dev = data->doc->data->getOutputDev(); + + data->doc->data->doc.displayPageSlice(output_dev, data->index + 1, xres, yres, + 0, false, true, false, -1, -1, -1, -1); + bitmap = output_dev->getBitmap (); + color_ptr = bitmap->getDataPtr (); + int bw = output_dev->getBitmap()->getWidth(); + int bh = output_dev->getBitmap()->getHeight(); + SplashColorPtr dataPtr = output_dev->getBitmap()->getDataPtr(); + + if (QImage::BigEndian == QImage::systemByteOrder()) + { + uchar c; + int count = bw * bh * 4; + for (int k = 0; k < count; k += 4) + { + c = dataPtr[k]; + dataPtr[k] = dataPtr[k+3]; + dataPtr[k+3] = c; + + c = dataPtr[k+1]; + dataPtr[k+1] = dataPtr[k+2]; + dataPtr[k+2] = c; + } + } + + // construct a qimage SHARING the raw bitmap data in memory + QImage img( dataPtr, bw, bh, 32, 0, 0, QImage::IgnoreEndian ); + img = img.copy(); + // unload underlying xpdf bitmap + output_dev->startPage( 0, NULL ); + + return img; +#else + (void)xres; + (void)xres; + (void)doLinks; + + return QImage(); +#endif +} + +QString Page::getText(const Rectangle &r) const +{ + TextOutputDev *output_dev; + GooString *s; + PDFRectangle *rect; + QString result; + ::Page *p; + + output_dev = new TextOutputDev(0, gFalse, gFalse, gFalse); + data->doc->data->doc.displayPageSlice(output_dev, data->index + 1, 72, 72, + 0, false, false, false, -1, -1, -1, -1); + p = data->doc->data->doc.getCatalog()->getPage(data->index + 1); + if (r.isNull()) + { + rect = p->getCropBox(); + s = output_dev->getText(rect->x1, rect->y1, rect->x2, rect->y2); + } + else + { + double height, y1, y2; + height = p->getCropHeight(); + y1 = height - r.m_y2; + y2 = height - r.m_y1; + s = output_dev->getText(r.m_x1, y1, r.m_x2, y2); + } + + result = QString::fromUtf8(s->getCString()); + + delete output_dev; + delete s; + return result; +} + +QValueList<TextBox*> Page::textList() const +{ + TextOutputDev *output_dev; + + QValueList<TextBox*> output_list; + + output_dev = new TextOutputDev(0, gFalse, gFalse, gFalse); + + data->doc->data->doc.displayPageSlice(output_dev, data->index + 1, 72, 72, + 0, false, false, false, -1, -1, -1, -1); + + TextWordList *word_list = output_dev->makeWordList(); + + if (!word_list) { + delete output_dev; + return output_list; + } + + for (int i = 0; i < word_list->getLength(); i++) { + TextWord *word = word_list->get(i); + GooString *word_str = word->getText(); + QString string = QString::fromUtf8(word_str->getCString()); + delete word_str; + double xMin, yMin, xMax, yMax; + word->getBBox(&xMin, &yMin, &xMax, &yMax); + + TextBox* text_box = new TextBox(string, Rectangle(xMin, yMin, xMax, yMax)); + + output_list.append(text_box); + } + + delete word_list; + delete output_dev; + + return output_list; +} + +PageTransition *Page::getTransition() const +{ + if (!data->transition) + { + Object o; + PageTransitionParams params; + params.dictObj = data->doc->data->doc.getCatalog()->getPage(data->index + 1)->getTrans(&o); + data->transition = new PageTransition(params); + o.free(); + } + return data->transition; +} + +QSize Page::pageSize() const +{ + ::Page *p; + + p = data->doc->data->doc.getCatalog()->getPage(data->index + 1); + if ( ( Page::Landscape == orientation() ) || (Page::Seascape == orientation() ) ) { + return QSize( (int)p->getCropHeight(), (int)p->getCropWidth() ); + } else { + return QSize( (int)p->getCropWidth(), (int)p->getCropHeight() ); + } +} + +Page::Orientation Page::orientation() const +{ + ::Page *p = data->doc->data->doc.getCatalog()->getPage(data->index + 1); + + int rotation = p->getRotate(); + switch (rotation) { + case 90: + return Page::Landscape; + break; + case 180: + return Page::UpsideDown; + break; + case 270: + return Page::Seascape; + break; + default: + return Page::Portrait; + } +} + +QValueList<Link*> Page::links() const +{ + QValueList<Link*> popplerLinks; + +#if defined(HAVE_SPLASH) + Links *xpdfLinks = data->doc->data->doc.getLinks(data->index + 1); + for (int i = 0; i < xpdfLinks->getNumLinks(); ++i) + { + ::Link *xpdfLink = xpdfLinks->getLink(i); + + double left, top, right, bottom; + int leftAux, topAux, rightAux, bottomAux; + xpdfLink->getRect( &left, &top, &right, &bottom ); + QRect linkArea; + + data->doc->data->m_outputDev->cvtUserToDev( left, top, &leftAux, &topAux ); + data->doc->data->m_outputDev->cvtUserToDev( right, bottom, &rightAux, &bottomAux ); + linkArea.setLeft(leftAux); + linkArea.setTop(topAux); + linkArea.setRight(rightAux); + linkArea.setBottom(bottomAux); + + if (!xpdfLink->isOk()) continue; + + Link *popplerLink = NULL; + ::LinkAction *a = xpdfLink->getAction(); + if ( a ) + { + switch ( a->getKind() ) + { + case actionGoTo: + { + LinkGoTo * g = (LinkGoTo *) a; + // create link: no ext file, namedDest, object pointer + popplerLink = new LinkGoto( linkArea, QString::null, LinkDestination( LinkDestinationData(g->getDest(), g->getNamedDest(), data->doc->data ) ) ); + } + break; + + case actionGoToR: + { + LinkGoToR * g = (LinkGoToR *) a; + // copy link file + const QString fileName = UnicodeParsedString( g->getFileName() ); + // ceate link: fileName, namedDest, object pointer + popplerLink = new LinkGoto( linkArea, fileName, LinkDestination( LinkDestinationData(g->getDest(), g->getNamedDest(), data->doc->data ) ) ); + } + break; + + case actionLaunch: + { + LinkLaunch * e = (LinkLaunch *)a; + GooString * p = e->getParams(); + popplerLink = new LinkExecute( linkArea, e->getFileName()->getCString(), p ? p->getCString() : 0 ); + } + break; + + case actionNamed: + { + const char * name = ((LinkNamed *)a)->getName()->getCString(); + if ( !strcmp( name, "NextPage" ) ) + popplerLink = new LinkAction( linkArea, LinkAction::PageNext ); + else if ( !strcmp( name, "PrevPage" ) ) + popplerLink = new LinkAction( linkArea, LinkAction::PagePrev ); + else if ( !strcmp( name, "FirstPage" ) ) + popplerLink = new LinkAction( linkArea, LinkAction::PageFirst ); + else if ( !strcmp( name, "LastPage" ) ) + popplerLink = new LinkAction( linkArea, LinkAction::PageLast ); + else if ( !strcmp( name, "GoBack" ) ) + popplerLink = new LinkAction( linkArea, LinkAction::HistoryBack ); + else if ( !strcmp( name, "GoForward" ) ) + popplerLink = new LinkAction( linkArea, LinkAction::HistoryForward ); + else if ( !strcmp( name, "Quit" ) ) + popplerLink = new LinkAction( linkArea, LinkAction::Quit ); + else if ( !strcmp( name, "GoToPage" ) ) + popplerLink = new LinkAction( linkArea, LinkAction::GoToPage ); + else if ( !strcmp( name, "Find" ) ) + popplerLink = new LinkAction( linkArea, LinkAction::Find ); + else if ( !strcmp( name, "FullScreen" ) ) + popplerLink = new LinkAction( linkArea, LinkAction::Presentation ); + else if ( !strcmp( name, "Close" ) ) + { + // acroread closes the document always, doesnt care whether + // its presentation mode or not + // popplerLink = new LinkAction( linkArea, LinkAction::EndPresentation ); + popplerLink = new LinkAction( linkArea, LinkAction::Close ); + } + else + { + // TODO + } + } + break; + + case actionURI: + { + popplerLink = new LinkBrowse( linkArea, ((LinkURI *)a)->getURI()->getCString() ); + } + break; + + case actionMovie: + case actionSound: + case actionRendition: + case actionJavaScript: + case actionOCGState: + break; + + case actionUnknown: + break; + } + } + + if (popplerLink) + { + popplerLinks.append(popplerLink); + } + } + + delete xpdfLinks; +#endif + + return popplerLinks; +} + +} diff --git a/kfile-plugins/pdf/poppler-qt/poppler-private.cc b/kfile-plugins/pdf/poppler-qt/poppler-private.cc new file mode 100644 index 00000000..2388a1b5 --- /dev/null +++ b/kfile-plugins/pdf/poppler-qt/poppler-private.cc @@ -0,0 +1,147 @@ +/* poppler-private.h: qt interface to poppler + * Copyright (C) 2005, Net Integration Technologies, Inc. + * Copyright (C) 2005-2008, Albert Astals Cid <aacid@kde.org> + * Copyright (C) 2006, Kristian Høgsberg <krh@bitplanet.net> + * Copyright (C) 2006, Wilfried Huss <Wilfried.Huss@gmx.at> + * Copyright (C) 2007, Pino Toscano <pino@kde.org> + * + * 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 + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "poppler-private.h" +#include "poppler-link-qt3.h" + +#include <qstring.h> + +#include <Outline.h> +#include <Link.h> + +namespace Poppler { + +/* borrowed from kpdf */ +QString unicodeToQString(Unicode* u, int len) +{ + QString ret; + ret.setLength(len); + QChar* qch = (QChar*) ret.unicode(); + for (;len;--len) + *qch++ = (QChar) *u++; + return ret; +} + +QString UnicodeParsedString(GooString *s1) +{ + GBool isUnicode; + int i; + Unicode u; + QString result; + if ( ( s1->getChar(0) & 0xff ) == 0xfe && ( s1->getChar(1) & 0xff ) == 0xff ) + { + isUnicode = gTrue; + i = 2; + } + else + { + isUnicode = gFalse; + i = 0; + } + while ( i < s1->getLength() ) + { + if ( isUnicode ) + { + u = ( ( s1->getChar(i) & 0xff ) << 8 ) | ( s1->getChar(i+1) & 0xff ); + i += 2; + } + else + { + u = s1->getChar(i) & 0xff; + ++i; + } + result += unicodeToQString( &u, 1 ); + } + return result; +} + +GooString *QStringToGooString(const QString &s) +{ + int len = s.length(); + char *cstring = (char *)gmallocn(s.length(), sizeof(char)); + for (int i = 0; i < len; ++i) + cstring[i] = s.at(i).unicode(); + GooString *ret = new GooString(cstring, len); + gfree(cstring); + return ret; +} + + +void DocumentData::addTocChildren( QDomDocument * docSyn, QDomNode * parent, GooList * items ) +{ + int numItems = items->getLength(); + for ( int i = 0; i < numItems; ++i ) + { + // iterate over every object in 'items' + OutlineItem * outlineItem = (OutlineItem *)items->get( i ); + + // 1. create element using outlineItem's title as tagName + QString name; + Unicode * uniChar = outlineItem->getTitle(); + int titleLength = outlineItem->getTitleLength(); + name = unicodeToQString(uniChar, titleLength); + if ( name.isEmpty() ) + continue; + + QDomElement item = docSyn->createElement( name ); + parent->appendChild( item ); + + // 2. find the page the link refers to + ::LinkAction * a = outlineItem->getAction(); + if ( a && ( a->getKind() == actionGoTo || a->getKind() == actionGoToR ) ) + { + // page number is contained/referenced in a LinkGoTo + LinkGoTo * g = static_cast< LinkGoTo * >( a ); + LinkDest * destination = g->getDest(); + if ( !destination && g->getNamedDest() ) + { + // no 'destination' but an internal 'named reference'. we could + // get the destination for the page now, but it's VERY time consuming, + // so better storing the reference and provide the viewport on demand + GooString *s = g->getNamedDest(); + QChar *charArray = new QChar[s->getLength()]; + for (int i = 0; i < s->getLength(); ++i) charArray[i] = QChar(s->getCString()[i]); + QString aux(charArray, s->getLength()); + item.setAttribute( "DestinationName", aux ); + delete[] charArray; + } + else if ( destination && destination->isOk() ) + { + LinkDestinationData ldd(destination, NULL, this); + item.setAttribute( "Destination", LinkDestination(ldd).toString() ); + } + if ( a->getKind() == actionGoToR ) + { + LinkGoToR * g2 = static_cast< LinkGoToR * >( a ); + item.setAttribute( "ExternalFileName", g2->getFileName()->getCString() ); + } + } + + // 3. recursively descend over children + outlineItem->open(); + GooList * children = outlineItem->getKids(); + if ( children ) + addTocChildren( docSyn, &item, children ); + } +} + +} diff --git a/kfile-plugins/pdf/poppler-qt/poppler-private.h b/kfile-plugins/pdf/poppler-qt/poppler-private.h new file mode 100644 index 00000000..0d68e505 --- /dev/null +++ b/kfile-plugins/pdf/poppler-qt/poppler-private.h @@ -0,0 +1,97 @@ +/* poppler-private.h: qt interface to poppler + * Copyright (C) 2005, Net Integration Technologies, Inc. + * Copyright (C) 2005-2008, Albert Astals Cid <aacid@kde.org> + * Copyright (C) 2006, Kristian Høgsberg <krh@bitplanet.net> + * Copyright (C) 2006, Wilfried Huss <Wilfried.Huss@gmx.at> + * Copyright (C) 2007, Pino Toscano <pino@kde.org> + * + * 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 + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef POPPLER_PRIVATE_H +#define POPPLER_PRIVATE_H + +#include <qdom.h> + +#include <config.h> +#include <Object.h> +#include <PDFDoc.h> +#include <FontInfo.h> +#if defined(HAVE_SPLASH) +#include <SplashOutputDev.h> +#else +class SplashOutputDev; +#endif + +namespace Poppler { + +class DocumentData; + +QString unicodeToQString(Unicode* u, int len); + +QString UnicodeParsedString(GooString *s1); + +GooString *QStringToGooString(const QString &s); + +class LinkDestinationData { + public: + LinkDestinationData( LinkDest *l, GooString *nd, Poppler::DocumentData *pdfdoc ) : ld(l), namedDest(nd), doc(pdfdoc) + { + } + + LinkDest *ld; + GooString *namedDest; + Poppler::DocumentData *doc; +}; + +class DocumentData { + public: + DocumentData(GooString *filePath, GooString *password) : doc(filePath,password), m_fontInfoScanner(0), m_outputDev(0) {} + + ~DocumentData() + { +#if defined(HAVE_SPLASH) + delete m_outputDev; +#endif + delete m_fontInfoScanner; + } + + SplashOutputDev *getOutputDev() + { +#if defined(HAVE_SPLASH) + if (!m_outputDev) + { + SplashColor white; + white[0] = 255; + white[1] = 255; + white[2] = 255; + m_outputDev = new SplashOutputDev(splashModeXBGR8, 4, gFalse, white); + m_outputDev->startDoc(doc.getXRef()); + } +#endif + return m_outputDev; + } + + void addTocChildren( QDomDocument * docSyn, QDomNode * parent, GooList * items ); + + class PDFDoc doc; + bool locked; + FontInfoScanner *m_fontInfoScanner; + SplashOutputDev *m_outputDev; +}; + +} + +#endif // POPPLER_PRIVATE_H diff --git a/kfile-plugins/pdf/poppler-qt/poppler-qt.h b/kfile-plugins/pdf/poppler-qt/poppler-qt.h new file mode 100644 index 00000000..a6b1e6ec --- /dev/null +++ b/kfile-plugins/pdf/poppler-qt/poppler-qt.h @@ -0,0 +1,310 @@ +/* poppler-qt.h: qt interface to poppler + * Copyright (C) 2005, Net Integration Technologies, Inc. + * Copyright (C) 2005, Tobias Koening <tokoe@kde.org> + * Copyright (C) 2005-2007, Albert Astals Cid <aacid@kde.org> + * Copyright (C) 2005-2006, Stefan Kebekus <stefan.kebekus@math.uni-koeln.de> + * Copyright (C) 2006, Wilfried Huss <Wilfried.Huss@gmx.at> + * + * 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 + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __POPPLER_QT_H__ +#define __POPPLER_QT_H__ + +#include "poppler-link-qt3.h" +#include "poppler-page-transition.h" + +#include <qcstring.h> +#include <qdatetime.h> +#include <qdom.h> +#include <qpixmap.h> + +namespace Poppler { + +class Document; +class Page; + +/* A rectangle on a page, with coordinates in PDF points. */ +class Rectangle +{ + public: + Rectangle(double x1 = 0, double y1 = 0, double x2 = 0, double y2 = 0) : + m_x1(x1), m_y1(y1), m_x2(x2), m_y2(y2) {} + bool isNull() const { return m_x1 == 0 && m_y1 == 0 && m_x2 == 0 && m_y2 == 0; } + + double m_x1; + double m_y1; + double m_x2; + double m_y2; +}; + +class TextBox +{ + public: + TextBox(const QString& text, const Rectangle &bBox) : + m_text(text), m_bBox(bBox) {}; + + QString getText() const { return m_text; }; + Rectangle getBoundingBox() const { return m_bBox; }; + + private: + QString m_text; + Rectangle m_bBox; +}; + + +/** + Container class for information about a font within a PDF document +*/ +class FontInfoData; +class FontInfo { +public: + enum Type { + unknown, + Type1, + Type1C, + Type1COT, + Type3, + TrueType, + TrueTypeOT, + CIDType0, + CIDType0C, + CIDType0COT, + CIDTrueType, + CIDTrueTypeOT + }; + + /** + Create a new font information container + */ + FontInfo( const QString &fontName, const bool isEmbedded, + const bool isSubset, Type type ); + + FontInfo(); + + FontInfo( const FontInfo &fi ); + + ~FontInfo(); + + /** + The name of the font. Can be QString::null if the font has no name + */ + const QString &name() const; + + /** + Whether the font is embedded in the file, or not + + \return true if the font is embedded + */ + bool isEmbedded() const; + + /** + Whether the font provided is only a subset of the full + font or not. This only has meaning if the font is embedded. + + \return true if the font is only a subset + */ + bool isSubset() const; + + /** + The type of font encoding + */ + Type type() const; + + const QString &typeName() const; + +private: + FontInfoData *data; +}; + +class PageData; +class Page { + friend class Document; + public: + ~Page(); + void renderToPixmap(QPixmap **q, int x, int y, int w, int h, double xres, double yres, bool doLinks = false) const; + + /** + This is a convenience function that is equivalent to + renderToPixmap() with xres and yres set to 72.0. We keep it + only for binary compatibility + + \sa renderToImage() + */ + void renderToPixmap(QPixmap **q, int x, int y, int w, int h, bool doLinks = false) const; + + /** + \brief Render the page to a QImage using the Splash renderer + + This method can be used to render the page to a QImage. It + uses the "Splash" rendering engine. + + \param xres horizontal resolution of the graphics device, + in dots per inch (defaults to 72 dpi) + + \param yres vertical resolution of the graphics device, in + dots per inch (defaults to 72 dpi) + + \returns a QImage of the page. + + \sa renderToPixmap() + */ + QImage renderToImage(double xres = 72.0, double yres = 72.0, bool doLinks = false) const; + + /** + * Returns the size of the page in points + **/ + QSize pageSize() const; + + /** + * Returns the text that is inside the Rectangle r + * If r is a null Rectangle all text of the page is given + **/ + QString getText(const Rectangle &r) const; + + QValueList<TextBox*> textList() const; + + /** + * Returns the transition of this page + **/ + PageTransition *getTransition() const; + + enum Orientation { + Landscape, + Portrait, + Seascape, + UpsideDown + }; + + /** + * The orientation of the page + **/ + Orientation orientation() const; + + /** + Gets the links of the page once it has been rendered if doLinks was true + */ + QValueList<Link*> links() const; + + private: + Page(const Document *doc, int index); + PageData *data; +}; + +class DocumentData; + +class Document { + friend class Page; + +public: + enum PageMode { + UseNone, + UseOutlines, + UseThumbs, + FullScreen, + UseOC + }; + + static Document *load(const QString & filePath); + + Page *getPage(int index) const{ return new Page(this, index); } + + int getNumPages() const; + + PageMode getPageMode() const; + + bool unlock(const QCString &password); + + bool isLocked() const; + + QDateTime getDate( const QString & data ) const; + QString getInfo( const QString & data ) const; + bool isEncrypted() const; + bool isLinearized() const; + bool okToPrint() const; + bool okToChange() const; + bool okToCopy() const; + bool okToAddNotes() const; + double getPDFVersion() const; + /** + The version of the PDF specification that the document + conforms to + + \param major an optional pointer to a variable where store the + "major" number of the version + \param minor an optional pointer to a variable where store the + "minor" number of the version + + \since 0.12 + */ + void getPdfVersion(int *major, int *minor) const; + + bool print(const QString &fileName, QValueList<int> pageList, double hDPI, double vDPI, int rotate); + + // If you are using QPrinter you can get paper size doing + // QPrinter dummy(QPrinter::PrinterResolution); + // dummy.setFullPage(true); + // dummy.setPageSize(thePageSizeYouWant); + // QPaintDeviceMetrics metrics(&dummy); + // int width = metrics.width(); + // int height = metrics.height(); + bool print(const QString &fileName, QValueList<int> pageList, double hDPI, double vDPI, int rotate, int paperWidth, int paperHeight); + + /** + The fonts within the PDF document. + + \note this can take a very long time to run with a large + document. You may wish to use the call below if you have more + than say 20 pages + */ + QValueList<FontInfo> fonts() const; + + /** + \overload + + \param numPages the number of pages to scan + \param fontList pointer to the list where the font information + should be placed + + \return false if the end of the document has been reached + */ + bool scanForFonts( int numPages, QValueList<FontInfo> *fontList ) const; + + /** + Gets the TOC of the Document, it is application responsabiliy to delete + it when no longer needed + + * In the tree the tag name is the 'screen' name of the entry. A tag can have + * attributes. Here follows the list of tag attributes with meaning: + * - Destination: A string description of the referred destination + * - DestinationName: A 'named reference' to the viewport that must be converted + * using linkDestination( *destination_name* ) + * - ExternalFileName: A link to a external filename + + \returns NULL if the Document does not have TOC + */ + QDomDocument *toc() const; + + LinkDestination *linkDestination( const QString &name ); + + ~Document(); + +private: + DocumentData *data; + Document(DocumentData *dataA); +}; + +} +#endif diff --git a/kfile-plugins/pdf/poppler-qt/test-poppler-qt.cpp b/kfile-plugins/pdf/poppler-qt/test-poppler-qt.cpp new file mode 100644 index 00000000..d97954b8 --- /dev/null +++ b/kfile-plugins/pdf/poppler-qt/test-poppler-qt.cpp @@ -0,0 +1,122 @@ +#include <qapplication.h> +#include <qpainter.h> +#include <qpixmap.h> +#include <qwidget.h> +#include <qlabel.h> +#include <qmessagebox.h> +#include <qfile.h> +#include <ctype.h> +#include <poppler-qt.h> +#include <stdlib.h> + +class PDFDisplay : public QWidget // picture display widget +{ +public: + PDFDisplay( Poppler::Document *d ); + ~PDFDisplay(); +protected: + void paintEvent( QPaintEvent * ); + void keyPressEvent( QKeyEvent * ); +private: + void display(); + + int currentPage; + QPixmap *pixmap; + Poppler::Document *doc; +}; + +PDFDisplay::PDFDisplay( Poppler::Document *d ) +{ + doc = d; + pixmap = 0; + currentPage = 0; + display(); +} + +PDFDisplay::~PDFDisplay() +{ + delete doc; + delete pixmap; +} + +void PDFDisplay::paintEvent( QPaintEvent *e ) +{ + QPainter paint( this ); // paint widget + if (pixmap) + paint.drawPixmap(0, 0, *pixmap); +} + +void PDFDisplay::keyPressEvent( QKeyEvent *e ) +{ + if (e->key() == Qt::Key_Down) + { + if (currentPage + 1 < doc->getNumPages()) + { + currentPage++; + display(); + } + } + else if (e->key() == Qt::Key_Up) + { + if (currentPage > 0) + { + currentPage--; + display(); + } + } +} + +void PDFDisplay::display() +{ + if (doc) { + Poppler::Page *page = doc->getPage(currentPage); + if (page) { + delete pixmap; + page->renderToPixmap(&pixmap, -1, -1, -1, -1); + delete page; + update(); + } + } else { + printf("doc not loaded\n"); + } +} + +int main( int argc, char **argv ) +{ + QApplication a( argc, argv ); // QApplication required! + + if ( argc < 2 || (argc == 3 && strcmp(argv[2], "-extract") != 0) || argc > 3) + { + // use argument as file name + printf("usage: test-poppler-qt filename [-extract]\n"); + exit(1); + } + + Poppler::Document *doc = Poppler::Document::load(argv[1]); + if (!doc) + { + printf("doc not loaded\n"); + exit(1); + } + + if (argc == 2) + { + PDFDisplay test( doc ); // create picture display + a.setMainWidget( &test); // set main widget + test.setCaption("Poppler-Qt Test"); + test.show(); // show it + + return a.exec(); // start event loop + } + else + { + Poppler::Page *page = doc->getPage(0); + + QLabel *l = new QLabel(page->getText(Poppler::Rectangle()), 0); + l->show(); + a.setMainWidget(l); // set main widget + delete page; + delete doc; + return a.exec(); + } +} |