diff --git a/Pdf4QtLib/sources/pdfaction.cpp b/Pdf4QtLib/sources/pdfaction.cpp index f9c9854..1493932 100644 --- a/Pdf4QtLib/sources/pdfaction.cpp +++ b/Pdf4QtLib/sources/pdfaction.cpp @@ -710,4 +710,14 @@ QString PDFActionURI::getURIString() const return QString::fromUtf8(m_URI); } +void PDFActionGoTo::setDestination(const PDFDestination& destination) +{ + m_destination = destination; +} + +void PDFActionGoTo::setStructureDestination(const PDFDestination& structureDestination) +{ + m_structureDestination = structureDestination; +} + } // namespace pdf diff --git a/Pdf4QtLib/sources/pdfaction.h b/Pdf4QtLib/sources/pdfaction.h index d601622..50dc769 100644 --- a/Pdf4QtLib/sources/pdfaction.h +++ b/Pdf4QtLib/sources/pdfaction.h @@ -191,6 +191,9 @@ public: const PDFDestination& getDestination() const { return m_destination; } const PDFDestination& getStructureDestination() const { return m_structureDestination; } + void setDestination(const PDFDestination& destination); + void setStructureDestination(const PDFDestination& structureDestination); + private: PDFDestination m_destination; PDFDestination m_structureDestination; diff --git a/Pdf4QtLib/sources/pdfoptimizer.cpp b/Pdf4QtLib/sources/pdfoptimizer.cpp index 5bd5a44..ff07774 100644 --- a/Pdf4QtLib/sources/pdfoptimizer.cpp +++ b/Pdf4QtLib/sources/pdfoptimizer.cpp @@ -367,6 +367,20 @@ bool PDFOptimizer::performMergeIdenticalObjects() auto processEntry = [this, &counter, &objects, &mutex, &replacementMap](size_t index) { const PDFObjectStorage::Entry& entry = objects[index]; + + // We do not merge special objects, such as pages + if (const PDFDictionary* dictionary = m_storage.getDictionaryFromObject(entry.object)) + { + PDFObject nameObject = m_storage.getObject(dictionary->get("Type")); + if (nameObject.isName()) + { + if (nameObject.getString() == "Page") + { + return; + } + } + } + for (size_t i = 0; i < index; ++i) { if (objects[i].object.isNull()) diff --git a/Pdf4QtLib/sources/pdfoutline.cpp b/Pdf4QtLib/sources/pdfoutline.cpp index 80fd415..85f4437 100644 --- a/Pdf4QtLib/sources/pdfoutline.cpp +++ b/Pdf4QtLib/sources/pdfoutline.cpp @@ -136,6 +136,16 @@ void PDFOutlineItem::setStructureElement(PDFObjectReference structureElement) m_structureElement = structureElement; } +void PDFOutlineItem::apply(const std::function& functor) +{ + functor(this); + + for (const auto& item : m_children) + { + item->apply(functor); + } +} + bool PDFOutlineItem::isFontBold() const { return m_fontBold; @@ -171,6 +181,11 @@ const PDFAction* PDFOutlineItem::getAction() const return m_action.get(); } +PDFAction* PDFOutlineItem::getAction() +{ + return m_action.get(); +} + void PDFOutlineItem::setAction(const PDFActionPtr& action) { m_action = action; diff --git a/Pdf4QtLib/sources/pdfoutline.h b/Pdf4QtLib/sources/pdfoutline.h index 7ae9ff3..9b67c37 100644 --- a/Pdf4QtLib/sources/pdfoutline.h +++ b/Pdf4QtLib/sources/pdfoutline.h @@ -48,6 +48,7 @@ public: static QSharedPointer parse(const PDFDocument* document, const PDFObject& root); const PDFAction* getAction() const; + PDFAction* getAction(); void setAction(const PDFActionPtr& action); QColor getTextColor() const; @@ -62,6 +63,8 @@ public: PDFObjectReference getStructureElement() const; void setStructureElement(PDFObjectReference structureElement); + void apply(const std::function& functor); + private: static void parseImpl(const PDFDocument* document, PDFOutlineItem* parent, diff --git a/Pdf4QtLib/sources/pdfredact.cpp b/Pdf4QtLib/sources/pdfredact.cpp index 04bdf3e..26fc664 100644 --- a/Pdf4QtLib/sources/pdfredact.cpp +++ b/Pdf4QtLib/sources/pdfredact.cpp @@ -51,6 +51,8 @@ PDFDocument PDFRedact::perform(Options options) PDFRenderer::None, *m_meshQualitySettings); + std::map mapOldPageRefToNewPageRef; + for (size_t i = 0; i < m_document->getCatalog()->getPageCount(); ++i) { const PDFPage* page = m_document->getCatalog()->getPage(i); @@ -59,6 +61,7 @@ PDFDocument PDFRedact::perform(Options options) renderer.compile(&compiledPage, i); PDFObjectReference newPageReference = builder.appendPage(page->getMediaBox()); + mapOldPageRefToNewPageRef[page->getPageReference()] = newPageReference; if (!page->getCropBox().isEmpty()) { @@ -127,11 +130,43 @@ PDFDocument PDFRedact::perform(Options options) if (options.testFlag(CopyOutline)) { - const PDFOutlineItem* outlineItem = m_document->getCatalog()->getOutlineRootPtr().data(); - - if (outlineItem) + PDFObject catalog = m_document->getObject(m_document->getTrailerDictionary()->get("Root")); + if (const PDFDictionary* catalogDictionary = m_document->getDictionaryFromObject(catalog)) { - builder.setOutline(outlineItem); + if (catalogDictionary->hasKey("Outlines")) + { + QSharedPointer outlineRoot = PDFOutlineItem::parse(m_document, catalogDictionary->get("Outlines")); + + if (outlineRoot) + { + auto resolveNamedDestination = [this, &mapOldPageRefToNewPageRef](PDFOutlineItem* item) + { + PDFActionGoTo* action = dynamic_cast(item->getAction()); + if (action) + { + if (action->getDestination().isNamedDestination()) + { + const PDFDestination* destination = m_document->getCatalog()->getNamedDestination(action->getDestination().getName()); + if (destination) + { + action->setDestination(*destination); + } + } + + PDFDestination destination = action->getDestination(); + auto it = mapOldPageRefToNewPageRef.find(destination.getPageReference()); + if (it != mapOldPageRefToNewPageRef.cend()) + { + destination.setPageReference(it->second); + action->setDestination(destination); + } + } + }; + outlineRoot->apply(resolveNamedDestination); + + builder.setOutline(outlineRoot.data()); + } + } } }