diff --git a/PdfForQtLib/sources/pdfcatalog.cpp b/PdfForQtLib/sources/pdfcatalog.cpp index 43b25c1..d42fdae 100644 --- a/PdfForQtLib/sources/pdfcatalog.cpp +++ b/PdfForQtLib/sources/pdfcatalog.cpp @@ -69,10 +69,10 @@ size_t PDFCatalog::getPageIndexFromPageReference(PDFObjectReference reference) c return INVALID_PAGE_INDEX; } -const PDFDestination* PDFCatalog::getDestination(const QByteArray& key) const +const PDFDestination* PDFCatalog::getNamedDestination(const QByteArray& key) const { - auto it = m_destinations.find(key); - if (it != m_destinations.cend()) + auto it = m_namedDestinations.find(key); + if (it != m_namedDestinations.cend()) { return &it->second; } @@ -80,6 +80,94 @@ const PDFDestination* PDFCatalog::getDestination(const QByteArray& key) const return nullptr; } +PDFActionPtr PDFCatalog::getNamedJavaScriptAction(const QByteArray& key) const +{ + auto it = m_namedJavaScriptActions.find(key); + if (it != m_namedJavaScriptActions.cend()) + { + return it->second; + } + + return nullptr; +} + +PDFObject PDFCatalog::getNamedAppearanceStream(const QByteArray& key) const +{ + auto it = m_namedAppearanceStreams.find(key); + if (it != m_namedAppearanceStreams.cend()) + { + return it->second; + } + + return PDFObject(); +} + +PDFObject PDFCatalog::getNamedPage(const QByteArray& key) const +{ + auto it = m_namedPages.find(key); + if (it != m_namedPages.cend()) + { + return it->second; + } + + return PDFObject(); +} + +PDFObject PDFCatalog::getNamedTemplate(const QByteArray& key) const +{ + auto it = m_namedTemplates.find(key); + if (it != m_namedTemplates.cend()) + { + return it->second; + } + + return PDFObject(); +} + +PDFObject PDFCatalog::getNamedDigitalIdentifier(const QByteArray& key) const +{ + auto it = m_namedDigitalIdentifiers.find(key); + if (it != m_namedDigitalIdentifiers.cend()) + { + return it->second; + } + + return PDFObject(); +} + +PDFObject PDFCatalog::getNamedUrl(const QByteArray& key) const +{ + auto it = m_namedUniformResourceLocators.find(key); + if (it != m_namedUniformResourceLocators.cend()) + { + return it->second; + } + + return PDFObject(); +} + +PDFObject PDFCatalog::getNamedAlternateRepresentation(const QByteArray& key) const +{ + auto it = m_namedAlternateRepresentations.find(key); + if (it != m_namedAlternateRepresentations.cend()) + { + return it->second; + } + + return PDFObject(); +} + +PDFObject PDFCatalog::getNamedRendition(const QByteArray& key) const +{ + auto it = m_namedRenditions.find(key); + if (it != m_namedRenditions.cend()) + { + return it->second; + } + + return PDFObject(); +} + PDFCatalog PDFCatalog::parse(const PDFObject& catalog, const PDFDocument* document) { if (!catalog.isDictionary()) @@ -171,9 +259,21 @@ PDFCatalog PDFCatalog::parse(const PDFObject& catalog, const PDFDocument* docume return PDFDestination::parse(storage, qMove(object)); }; - catalogObject.m_destinations = PDFNameTreeLoader::parse(&document->getStorage(), namesDictionary->get("Dests"), parseDestination); - catalogObject.m_javaScriptActions = PDFNameTreeLoader::parse(&document->getStorage(), namesDictionary->get("JavaScript"), &PDFAction::parse); - catalogObject.m_embeddedFiles = PDFNameTreeLoader::parse(&document->getStorage(), namesDictionary->get("EmbeddedFiles"), &PDFFileSpecification::parse); + auto getObject = [](const PDFObjectStorage*, PDFObject object) + { + return qMove(object); + }; + + catalogObject.m_namedDestinations = PDFNameTreeLoader::parse(&document->getStorage(), namesDictionary->get("Dests"), parseDestination); + catalogObject.m_namedAppearanceStreams = PDFNameTreeLoader::parse(&document->getStorage(), namesDictionary->get("AP"), getObject); + catalogObject.m_namedJavaScriptActions = PDFNameTreeLoader::parse(&document->getStorage(), namesDictionary->get("JavaScript"), &PDFAction::parse); + catalogObject.m_namedPages = PDFNameTreeLoader::parse(&document->getStorage(), namesDictionary->get("Pages"), getObject); + catalogObject.m_namedTemplates = PDFNameTreeLoader::parse(&document->getStorage(), namesDictionary->get("Templates"), getObject); + catalogObject.m_namedDigitalIdentifiers = PDFNameTreeLoader::parse(&document->getStorage(), namesDictionary->get("IDS"), getObject); + catalogObject.m_namedUniformResourceLocators = PDFNameTreeLoader::parse(&document->getStorage(), namesDictionary->get("URLS"), getObject); + catalogObject.m_namedEmbeddedFiles = PDFNameTreeLoader::parse(&document->getStorage(), namesDictionary->get("EmbeddedFiles"), &PDFFileSpecification::parse); + catalogObject.m_namedAlternateRepresentations = PDFNameTreeLoader::parse(&document->getStorage(), namesDictionary->get("AlternatePresentations"), getObject); + catalogObject.m_namedRenditions = PDFNameTreeLoader::parse(&document->getStorage(), namesDictionary->get("Renditions"), getObject); } // Examine "Dests" dictionary @@ -182,7 +282,7 @@ PDFCatalog PDFCatalog::parse(const PDFObject& catalog, const PDFDocument* docume const size_t count = destsDictionary->getCount(); for (size_t i = 0; i < count; ++i) { - catalogObject.m_destinations[destsDictionary->getKey(i).getString()] = PDFDestination::parse(&document->getStorage(), destsDictionary->getValue(i)); + catalogObject.m_namedDestinations[destsDictionary->getKey(i).getString()] = PDFDestination::parse(&document->getStorage(), destsDictionary->getValue(i)); } } diff --git a/PdfForQtLib/sources/pdfcatalog.h b/PdfForQtLib/sources/pdfcatalog.h index 919a958..ba2109b 100644 --- a/PdfForQtLib/sources/pdfcatalog.h +++ b/PdfForQtLib/sources/pdfcatalog.h @@ -499,7 +499,7 @@ public: PageLayout getPageLayout() const { return m_pageLayout; } PageMode getPageMode() const { return m_pageMode; } const QByteArray& getBaseURI() const { return m_baseURI; } - const std::map& getEmbeddedFiles() const { return m_embeddedFiles; } + const std::map& getEmbeddedFiles() const { return m_namedEmbeddedFiles; } const PDFObject& getFormObject() const { return m_formObject; } const PDFDeveloperExtensions& getExtensions() const { return m_extensions; } const PDFDocumentSecurityStore& getDocumentSecurityStore() const { return m_documentSecurityStore; } @@ -532,7 +532,57 @@ public: /// then nullptr is returned. /// \param key Destination key /// \returns Pointer to the destination, or nullptr - const PDFDestination* getDestination(const QByteArray& key) const; + const PDFDestination* getNamedDestination(const QByteArray& key) const; + + /// Returns javascript action using the key. If javascript action is not found, + /// then nullptr is returned. + /// \param key Action key + /// \returns Javascript action, or nullptr + PDFActionPtr getNamedJavaScriptAction(const QByteArray& key) const; + + /// Returns appearance stream using the key. If appearance stream is not found, + /// then empty object is returned. + /// \param key Appearance stream key + /// \returns Appearance, or nullptr + PDFObject getNamedAppearanceStream(const QByteArray& key) const; + + /// Returns named page using the key. If named page is not found, + /// then empty object is returned. + /// \param key Page key + /// \returns Page, or nullptr + PDFObject getNamedPage(const QByteArray& key) const; + + /// Returns named template using the key. If named template is not found, + /// then empty object is returned. + /// \param key Template key + /// \returns Template, or nullptr + PDFObject getNamedTemplate(const QByteArray& key) const; + + /// Returns named digital identifier using the key. If named digital identifier is not found, + /// then empty object is returned. Digital identifiers are used in Web Capture functionality. + /// See also PDF 2.0 specification. + /// \param key Digital identifier key + /// \returns Digital identifier, or nullptr + PDFObject getNamedDigitalIdentifier(const QByteArray& key) const; + + /// Returns named url using the key. If named url is not found, + /// then empty object is returned. Urls are used in Web Capture functionality. + /// See also PDF 2.0 specification. + /// \param key Url key + /// \returns Url, or nullptr + PDFObject getNamedUrl(const QByteArray& key) const; + + /// Returns named alternate representation using the key. If named alternate representation is not found, + /// then empty object is returned. + /// \param key Alternate representation key + /// \returns Alternate representation, or nullptr + PDFObject getNamedAlternateRepresentation(const QByteArray& key) const; + + /// Returns named rendition using the key. If named rendition is not found, + /// then empty object is returned. + /// \param key Rendition key + /// \returns Rendition, or nullptr + PDFObject getNamedRendition(const QByteArray& key) const; /// Parses catalog from catalog dictionary. If object cannot be parsed, or error occurs, /// then exception is thrown. @@ -580,9 +630,16 @@ private: PDFObject m_documentPartRoot; // Maps from Names dictionary - std::map m_destinations; - std::map m_javaScriptActions; - std::map m_embeddedFiles; + std::map m_namedDestinations; + std::map m_namedAppearanceStreams; + std::map m_namedJavaScriptActions; + std::map m_namedPages; + std::map m_namedTemplates; + std::map m_namedDigitalIdentifiers; + std::map m_namedUniformResourceLocators; + std::map m_namedEmbeddedFiles; + std::map m_namedAlternateRepresentations; + std::map m_namedRenditions; }; } // namespace pdf diff --git a/PdfForQtLib/sources/pdfpage.cpp b/PdfForQtLib/sources/pdfpage.cpp index 6f4da35..7178c0b 100644 --- a/PdfForQtLib/sources/pdfpage.cpp +++ b/PdfForQtLib/sources/pdfpage.cpp @@ -59,6 +59,11 @@ PDFPageInheritableAttributes PDFPageInheritableAttributes::parse(const PDFPageIn rotation = rotation - fullCircles * 360; } + if (rotation < 0) + { + rotation += 360; + } + switch (rotation) { case 0: diff --git a/PdfForQtViewer/pdfviewermainwindow.cpp b/PdfForQtViewer/pdfviewermainwindow.cpp index 7d42ffa..36079c9 100644 --- a/PdfForQtViewer/pdfviewermainwindow.cpp +++ b/PdfForQtViewer/pdfviewermainwindow.cpp @@ -405,7 +405,7 @@ void PDFViewerMainWindow::onActionTriggered(const pdf::PDFAction* action) pdf::PDFDestination destination = typedAction->getDestination(); if (destination.getDestinationType() == pdf::DestinationType::Named) { - if (const pdf::PDFDestination* targetDestination = m_pdfDocument->getCatalog()->getDestination(destination.getName())) + if (const pdf::PDFDestination* targetDestination = m_pdfDocument->getCatalog()->getNamedDestination(destination.getName())) { destination = *targetDestination; }