1 /** 2 * Copyright (C) 2011-2012 Charlie Sharpsteen, Stefan Löffler 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License as published by the Free 6 * Software Foundation; either version 3, or (at your option) any later 7 * version. 8 * 9 * This program is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 */ 14 15 // NOTE: 16 // 17 // ** THIS HEADER IS NOT MENT TO BE INCLUDED DIRECTLY ** 18 // 19 // Instead, include `PDFBackend.h` which defines classes that this header 20 // relies on. 21 #ifndef MuPDFBackend_H 22 #define MuPDFBackend_H 23 24 #include "PDFBackend.h" 25 26 extern "C" 27 { 28 #include <fitz.h> 29 #include <mupdf.h> 30 } 31 32 namespace QtPDF { 33 34 namespace Backend { 35 36 namespace MuPDF { 37 38 class Document; 39 class Page; 40 41 class Document: public Backend::Document 42 { 43 typedef Backend::Document Super; 44 friend class Page; 45 46 void recursiveConvertToC(QList<PDFToCItem> & items, pdf_outline * node) const; 47 48 protected: 49 // The pdf_xref is the main MuPDF object that represents a Document. Calls 50 // that use it may have to be protected by a mutex. 51 pdf_xref *_mupdf_data; 52 fz_glyph_cache *_glyph_cache; 53 54 void loadMetaData(); 55 56 // The following two methods are not thread-safe because they don't acquire a 57 // read lock. This is to enable methods that have a write lock to use them. _isValid()58 bool _isValid() const { return (_mupdf_data != NULL); } _isLocked()59 bool _isLocked() const { return (_isValid() && _permissionLevel == PermissionLevel_Locked); } 60 61 public: 62 Document(QString fileName); 63 ~Document(); 64 isValid()65 bool isValid() const { QReadLocker docLocker(_docLock.data()); return _isValid(); } isLocked()66 bool isLocked() const { QReadLocker docLocker(_docLock.data()); return _isLocked(); } 67 68 bool unlock(const QString password); 69 void reload(); 70 71 QWeakPointer<Backend::Page> page(int at); 72 QWeakPointer<Backend::Page> page(int at) const; 73 PDFDestination resolveDestination(const PDFDestination & namedDestination) const; 74 75 PDFToC toc() const; 76 QList<PDFFontInfo> fonts() const; 77 78 private: 79 enum PermissionLevel { PermissionLevel_Locked, PermissionLevel_User, PermissionLevel_Owner }; 80 QString _password; 81 // NOTE: the MuPDF function pdf_needs_password actually tries to authenticate 82 // with an empty password under certain circumstances. This can effectively 83 // relock _mupdf_data, so we have to cache to `locked` state. 84 PermissionLevel _permissionLevel; 85 }; 86 87 88 class Page: public Backend::Page 89 { 90 friend class Document; 91 typedef Backend::Page Super; 92 93 // The `fz_display_list` is the main MuPDF object that represents the parsed 94 // contents of a Page. 95 fz_display_list *_mupdf_page; 96 97 // Keep as a Fitz object rather than QRect as it is used in rendering ops. 98 fz_rect _bbox; 99 QSizeF _size; 100 qreal _rotate; 101 102 QList< QSharedPointer<Annotation::AbstractAnnotation> > _annotations; 103 QList< QSharedPointer<Annotation::Link> > _links; 104 bool _annotationsLoaded; 105 bool _linksLoaded; 106 107 // requires a doc-lock and a page-write-lock 108 void loadTransitionData(); 109 110 protected: 111 Page(Document *parent, int at, QSharedPointer<QReadWriteLock> docLock); 112 113 public: 114 ~Page(); 115 116 QSizeF pageSizeF() const; 117 118 QImage renderToImage(double xres, double yres, QRect render_box = QRect(), bool cache = false); 119 120 QList< QSharedPointer<Annotation::Link> > loadLinks(); 121 QList< QSharedPointer<Annotation::AbstractAnnotation> > loadAnnotations(); 122 123 QList<SearchResult> search(QString searchText, SearchFlags flags); 124 virtual QList<Backend::Page::Box> boxes(); 125 virtual QString selectedText(const QList<QPolygonF> & selection, QMap<int, QRectF> * wordBoxes = NULL, QMap<int, QRectF> * charBoxes = NULL); 126 }; 127 128 } // namespace MuPDF 129 130 } // namespace Backend 131 132 class MuPDFBackend : public BackendInterface 133 { 134 Q_OBJECT Q_INTERFACES(QtPDF::BackendInterface)135 Q_INTERFACES(QtPDF::BackendInterface) 136 public: 137 MuPDFBackend() { } ~MuPDFBackend()138 virtual ~MuPDFBackend() { } 139 newDocument(const QString & fileName)140 virtual QSharedPointer<Backend::Document> newDocument(const QString & fileName) { 141 return QSharedPointer<Backend::Document>(new Backend::MuPDF::Document(fileName)); 142 } 143 name()144 virtual QString name() const { return QString::fromAscii("mupdf"); } canHandleFile(const QString & fileName)145 virtual bool canHandleFile(const QString & fileName) { return QFileInfo(fileName).suffix() == QString::fromAscii("pdf"); } 146 }; 147 148 } // namespace QtPDF 149 150 #endif // End header guard 151 // vim: set sw=2 ts=2 et 152 153