File indexing completed on 2024-05-12 16:06:50
0001 /* 0002 SPDX-FileCopyrightText: 2006 Brad Hards <bradh@frogmouth.net> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef _OKULAR_GENERATOR_XPS_H_ 0008 #define _OKULAR_GENERATOR_XPS_H_ 0009 0010 #include <core/generator.h> 0011 #include <core/textpage.h> 0012 0013 #include <QColor> 0014 #include <QDomDocument> 0015 #include <QFontDatabase> 0016 #include <QImage> 0017 #include <QLoggingCategory> 0018 #include <QStack> 0019 #include <QVariant> 0020 #include <QXmlStreamReader> 0021 0022 #include <kzip.h> 0023 0024 typedef enum { abtCommand, abtNumber, abtComma, abtEOF } AbbPathTokenType; 0025 0026 class AbbPathToken 0027 { 0028 public: 0029 QString data; 0030 int curPos; 0031 0032 AbbPathTokenType type; 0033 char command; 0034 double number; 0035 }; 0036 0037 /** 0038 Holds information about xml element during SAX parsing of page 0039 */ 0040 class XpsRenderNode 0041 { 0042 public: 0043 QString name; 0044 QVector<XpsRenderNode> children; 0045 QXmlStreamAttributes attributes; 0046 QVariant data; 0047 0048 const XpsRenderNode *findChild(const QString &name) const; 0049 QVariant getRequiredChildData(const QString &name) const; 0050 QVariant getChildData(const QString &name) const; 0051 }; 0052 0053 struct XpsGradient { 0054 XpsGradient(double o, const QColor &c) 0055 : offset(o) 0056 , color(c) 0057 { 0058 } 0059 0060 double offset; 0061 QColor color; 0062 }; 0063 0064 /** 0065 Types of data in XpsRenderNode::data. Name of each type consist of Xps and 0066 name of xml element which data it holds 0067 */ 0068 typedef QTransform XpsMatrixTransform; 0069 typedef QTransform XpsRenderTransform; 0070 typedef QBrush XpsFill; 0071 struct XpsPathFigure { 0072 XpsPathFigure(const QPainterPath &_path, bool filled) 0073 : path(_path) 0074 , isFilled(filled) 0075 { 0076 } 0077 0078 QPainterPath path; 0079 bool isFilled; 0080 }; 0081 0082 struct XpsPathGeometry { 0083 XpsPathGeometry() 0084 : fillRule(Qt::OddEvenFill) 0085 { 0086 } 0087 ~XpsPathGeometry() 0088 { 0089 qDeleteAll(paths); 0090 } 0091 0092 XpsPathGeometry(const XpsPathGeometry &) = delete; 0093 XpsPathGeometry &operator=(const XpsPathGeometry &) = delete; 0094 0095 QList<XpsPathFigure *> paths; 0096 Qt::FillRule fillRule; 0097 XpsMatrixTransform transform; 0098 }; 0099 0100 class XpsPage; 0101 class XpsFile; 0102 0103 class XpsPage 0104 { 0105 public: 0106 XpsPage(XpsFile *file, const QString &fileName); 0107 ~XpsPage(); 0108 0109 XpsPage(const XpsPage &) = delete; 0110 XpsPage &operator=(const XpsPage &) = delete; 0111 0112 QSizeF size() const; 0113 bool renderToImage(QImage *p); 0114 bool renderToPainter(QPainter *painter); 0115 Okular::TextPage *textPage(); 0116 0117 QImage loadImageFromFile(const QString &filename); 0118 QString fileName() const 0119 { 0120 return m_fileName; 0121 } 0122 0123 private: 0124 // Methods for processing of different xml elements 0125 void processStartElement(QPainter *painter, XpsRenderNode &node); 0126 void processEndElement(QPainter *painter, XpsRenderNode &node); 0127 void processGlyph(QPainter *painter, XpsRenderNode &node); 0128 void processPath(QPainter *painter, XpsRenderNode &node); 0129 void processPathData(XpsRenderNode &node); 0130 void processFill(XpsRenderNode &node); 0131 void processStroke(XpsRenderNode &node); 0132 void processImageBrush(XpsRenderNode &node); 0133 void processPathGeometry(XpsRenderNode &node); 0134 void processPathFigure(XpsRenderNode &node); 0135 0136 XpsFile *m_file; 0137 const QString m_fileName; 0138 QStack<XpsRenderNode> m_nodes; 0139 0140 QSizeF m_pageSize; 0141 0142 QString m_thumbnailFileName; 0143 bool m_thumbnailMightBeAvailable; 0144 QImage m_thumbnail; 0145 bool m_thumbnailIsLoaded; 0146 0147 QImage *m_pageImage; 0148 bool m_pageIsRendered; 0149 0150 friend class XpsHandler; 0151 friend class XpsTextExtractionHandler; 0152 }; 0153 0154 /** 0155 Represents one of the (perhaps the only) documents in an XpsFile 0156 */ 0157 class XpsDocument 0158 { 0159 public: 0160 XpsDocument(XpsFile *file, const QString &fileName); 0161 ~XpsDocument(); 0162 0163 XpsDocument(const XpsDocument &) = delete; 0164 XpsDocument &operator=(const XpsDocument &) = delete; 0165 0166 /** 0167 the total number of pages in this document 0168 */ 0169 int numPages() const; 0170 0171 /** 0172 obtain a certain page from this document 0173 0174 \param pageNum the number of the page to return 0175 0176 \note page numbers are zero based - they run from 0 to 0177 numPages() - 1 0178 */ 0179 XpsPage *page(int pageNum) const; 0180 0181 /** 0182 whether this document has a Document Structure 0183 */ 0184 bool hasDocumentStructure(); 0185 0186 /** 0187 the document structure for this document, if available 0188 */ 0189 const Okular::DocumentSynopsis *documentStructure(); 0190 0191 private: 0192 void parseDocumentStructure(const QString &documentStructureFileName); 0193 0194 std::vector<std::unique_ptr<XpsPage>> m_pages; 0195 XpsFile *m_file; 0196 bool m_haveDocumentStructure; 0197 std::unique_ptr<Okular::DocumentSynopsis> m_docStructure; 0198 QMap<QString, int> m_docStructurePageMap; 0199 }; 0200 0201 /** 0202 Represents the contents of a Microsoft XML Paper Specification 0203 format document. 0204 */ 0205 class XpsFile 0206 { 0207 public: 0208 XpsFile(); 0209 ~XpsFile(); 0210 0211 XpsFile(const XpsFile &) = delete; 0212 XpsFile &operator=(const XpsFile &) = delete; 0213 0214 bool loadDocument(const QString &fileName); 0215 bool closeDocument(); 0216 0217 Okular::DocumentInfo generateDocumentInfo() const; 0218 0219 QImage thumbnail(); 0220 0221 /** 0222 the total number of XpsDocuments with this file 0223 */ 0224 int numDocuments() const; 0225 0226 /** 0227 the total number of pages in all the XpsDocuments within this 0228 file 0229 */ 0230 int numPages() const; 0231 0232 /** 0233 a page from the file 0234 0235 \param pageNum the page number of the page to return 0236 0237 \note page numbers are zero based - they run from 0 to 0238 numPages() - 1 0239 */ 0240 XpsPage *page(int pageNum) const; 0241 0242 /** 0243 obtain a certain document from this file 0244 0245 \param documentNum the number of the document to return 0246 0247 \note document numbers are zero based - they run from 0 to 0248 numDocuments() - 1 0249 */ 0250 XpsDocument *document(int documentNum) const; 0251 0252 QFont getFontByName(const QString &absoluteFileName, float size); 0253 0254 KZip *xpsArchive(); 0255 0256 private: 0257 int loadFontByName(const QString &absoluteFileName); 0258 0259 std::vector<std::unique_ptr<XpsDocument>> m_documents; 0260 QList<XpsPage *> m_pages; 0261 0262 QString m_thumbnailFileName; 0263 bool m_thumbnailMightBeAvailable; 0264 QImage m_thumbnail; 0265 bool m_thumbnailIsLoaded; 0266 0267 QString m_corePropertiesFileName; 0268 0269 QString m_signatureOrigin; 0270 0271 std::unique_ptr<KZip> m_xpsArchive; 0272 0273 QMap<QString, int> m_fontCache; 0274 QFontDatabase m_fontDatabase; 0275 }; 0276 0277 class XpsGenerator : public Okular::Generator 0278 { 0279 Q_OBJECT 0280 Q_INTERFACES(Okular::Generator) 0281 public: 0282 XpsGenerator(QObject *parent, const QVariantList &args); 0283 ~XpsGenerator() override; 0284 0285 bool loadDocument(const QString &fileName, QVector<Okular::Page *> &pagesVector) override; 0286 0287 Okular::DocumentInfo generateDocumentInfo(const QSet<Okular::DocumentInfo::Key> &keys) const override; 0288 const Okular::DocumentSynopsis *generateDocumentSynopsis() override; 0289 0290 Okular::ExportFormat::List exportFormats() const override; 0291 bool exportTo(const QString &fileName, const Okular::ExportFormat &format) override; 0292 0293 Okular::Document::PrintError print(QPrinter &printer) override; 0294 0295 protected: 0296 bool doCloseDocument() override; 0297 QImage image(Okular::PixmapRequest *request) override; 0298 Okular::TextPage *textPage(Okular::TextRequest *request) override; 0299 0300 private: 0301 std::unique_ptr<XpsFile> m_xpsFile; 0302 }; 0303 0304 Q_DECLARE_LOGGING_CATEGORY(OkularXpsDebug) 0305 0306 #endif