From 4035b26615e8e6b44b924499ceeb8ce4b3b404ff Mon Sep 17 00:00:00 2001 From: Jakub Melka Date: Wed, 26 Jan 2022 20:06:23 +0100 Subject: [PATCH] XFA: Use fonts from font dictionary --- Pdf4QtLib/sources/pdffont.h | 7 ++- Pdf4QtLib/sources/pdfpainter.cpp | 6 +-- Pdf4QtLib/sources/pdfxfaengine.cpp | 84 ++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 9 deletions(-) diff --git a/Pdf4QtLib/sources/pdffont.h b/Pdf4QtLib/sources/pdffont.h index 9c892b9..4946f51 100644 --- a/Pdf4QtLib/sources/pdffont.h +++ b/Pdf4QtLib/sources/pdffont.h @@ -287,14 +287,13 @@ public: /// \param document Document static PDFFontPointer createFont(const PDFObject& object, const PDFDocument* document); -protected: - FontDescriptor m_fontDescriptor; - -private: /// Tries to read font descriptor from the object /// \param fontDescriptorObject Font descriptor dictionary /// \param document Document static FontDescriptor readFontDescriptor(const PDFObject& fontDescriptorObject, const PDFDocument* document); + +protected: + FontDescriptor m_fontDescriptor; }; /// Simple font, see PDF reference 1.7, chapter 5.5. Simple fonts have encoding table, diff --git a/Pdf4QtLib/sources/pdfpainter.cpp b/Pdf4QtLib/sources/pdfpainter.cpp index a871c2f..b285335 100644 --- a/Pdf4QtLib/sources/pdfpainter.cpp +++ b/Pdf4QtLib/sources/pdfpainter.cpp @@ -819,11 +819,7 @@ void PDFPrecompiledPage::finalize(qint64 compilingTimeNS, QList }; for (const PathPaintData& data : m_paths) { - // Texts are shared from the font - if (!data.isText) - { - m_memoryConsumptionEstimate += calculateQPathMemoryConsumption(data.path); - } + m_memoryConsumptionEstimate += calculateQPathMemoryConsumption(data.path); } for (const ClipData& data : m_clips) { diff --git a/Pdf4QtLib/sources/pdfxfaengine.cpp b/Pdf4QtLib/sources/pdfxfaengine.cpp index 6bec5f6..2ac1132 100644 --- a/Pdf4QtLib/sources/pdfxfaengine.cpp +++ b/Pdf4QtLib/sources/pdfxfaengine.cpp @@ -18,6 +18,7 @@ #include "pdfxfaengine.h" #include "pdfform.h" #include "pdfpainterutils.h" +#include "pdffont.h" #include #include @@ -26,6 +27,7 @@ #include #include #include +#include #include #include @@ -9699,6 +9701,7 @@ private: std::vector paragraphSettings; }; + void updateResources(const PDFObject& resources); void clear(); QMarginsF createMargin(const xfa::XFA_margin* margin); @@ -9850,6 +9853,7 @@ private: const PDFDocument* m_document; PDFForm* m_form; Layout m_layout; + std::map m_fonts; }; class PDFXFALayoutEngine : public xfa::XFA_AbstractVisitor @@ -11641,6 +11645,7 @@ void PDFXFAEngineImpl::setDocument(const PDFModifiedDocument& document, PDFForm* try { const PDFObject& xfaObject = m_document->getObject(form->getXFA()); + updateResources(m_document->getObject(form->getResources())); std::map xfaData; if (xfaObject.isArray()) @@ -11725,6 +11730,79 @@ void PDFXFAEngineImpl::draw(const QMatrix& pagePointToDevicePointMatrix, } } +void PDFXFAEngineImpl::updateResources(const PDFObject& resources) +{ + try + { + std::set usedFonts; + + if (m_document) + { + if (const PDFDictionary* resourcesDictionary = m_document->getDictionaryFromObject(resources)) + { + if (const PDFDictionary* fontsDictionary = m_document->getDictionaryFromObject(resourcesDictionary->get("Font"))) + { + const size_t size = fontsDictionary->getCount(); + for (size_t i = 0; i < size; ++i) + { + const PDFDictionary* fontDictionary = m_document->getDictionaryFromObject(fontsDictionary->getValue(i)); + FontDescriptor descriptor = PDFFont::readFontDescriptor(m_document->getObject(fontDictionary->get("FontDescriptor")), m_document); + + if (const QByteArray* data = descriptor.getEmbeddedFontData()) + { + int fontId = -1; + + for (const auto& font : m_fonts) + { + if (font.second == *data) + { + fontId = font.first; + break; + } + } + + if (fontId == -1) + { + // Try to create application font from data + fontId = QFontDatabase::addApplicationFontFromData(*data); + } + + if (fontId != -1) + { + if (!m_fonts.count(fontId)) + { + m_fonts[fontId] = *data; + } + + // Mark font as used + usedFonts.insert(fontId); + } + } + } + } + } + } + + // Remove unused fonts + for (auto it = m_fonts.begin(); it != m_fonts.end();) + { + if (usedFonts.count(it->first)) + { + ++it; + } + else + { + QFontDatabase::removeApplicationFont(it->first); + it = m_fonts.erase(it); + } + } + } + catch (const PDFException&) + { + // Just clear the fonts + } +} + void PDFXFAEngineImpl::drawItemValue(const xfa::XFA_value* value, const xfa::XFA_ui* ui, QList& errors, @@ -13041,6 +13119,12 @@ void PDFXFAEngineImpl::clear() // Clear the template m_template = xfa::XFA_Node(); m_layout = Layout(); + + for (const auto& font : m_fonts) + { + QFontDatabase::removeApplicationFont(font.first); + } + m_fonts.clear(); } QMarginsF PDFXFAEngineImpl::createMargin(const xfa::XFA_margin* margin)