XFA: Use fonts from font dictionary

This commit is contained in:
Jakub Melka 2022-01-26 20:06:23 +01:00
parent 354b4cc69b
commit 4035b26615
3 changed files with 88 additions and 9 deletions

View File

@ -287,14 +287,13 @@ public:
/// \param document Document /// \param document Document
static PDFFontPointer createFont(const PDFObject& object, const PDFDocument* document); static PDFFontPointer createFont(const PDFObject& object, const PDFDocument* document);
protected:
FontDescriptor m_fontDescriptor;
private:
/// Tries to read font descriptor from the object /// Tries to read font descriptor from the object
/// \param fontDescriptorObject Font descriptor dictionary /// \param fontDescriptorObject Font descriptor dictionary
/// \param document Document /// \param document Document
static FontDescriptor readFontDescriptor(const PDFObject& fontDescriptorObject, const PDFDocument* 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, /// Simple font, see PDF reference 1.7, chapter 5.5. Simple fonts have encoding table,

View File

@ -819,11 +819,7 @@ void PDFPrecompiledPage::finalize(qint64 compilingTimeNS, QList<PDFRenderError>
}; };
for (const PathPaintData& data : m_paths) for (const PathPaintData& data : m_paths)
{ {
// Texts are shared from the font m_memoryConsumptionEstimate += calculateQPathMemoryConsumption(data.path);
if (!data.isText)
{
m_memoryConsumptionEstimate += calculateQPathMemoryConsumption(data.path);
}
} }
for (const ClipData& data : m_clips) for (const ClipData& data : m_clips)
{ {

View File

@ -18,6 +18,7 @@
#include "pdfxfaengine.h" #include "pdfxfaengine.h"
#include "pdfform.h" #include "pdfform.h"
#include "pdfpainterutils.h" #include "pdfpainterutils.h"
#include "pdffont.h"
#include <QDomElement> #include <QDomElement>
#include <QDomDocument> #include <QDomDocument>
@ -26,6 +27,7 @@
#include <QImageReader> #include <QImageReader>
#include <QTextDocument> #include <QTextDocument>
#include <QTextBlock> #include <QTextBlock>
#include <QFontDatabase>
#include <QAbstractTextDocumentLayout> #include <QAbstractTextDocumentLayout>
#include <stack> #include <stack>
@ -9699,6 +9701,7 @@ private:
std::vector<xfa::XFA_ParagraphSettings> paragraphSettings; std::vector<xfa::XFA_ParagraphSettings> paragraphSettings;
}; };
void updateResources(const PDFObject& resources);
void clear(); void clear();
QMarginsF createMargin(const xfa::XFA_margin* margin); QMarginsF createMargin(const xfa::XFA_margin* margin);
@ -9850,6 +9853,7 @@ private:
const PDFDocument* m_document; const PDFDocument* m_document;
PDFForm* m_form; PDFForm* m_form;
Layout m_layout; Layout m_layout;
std::map<int, QByteArray> m_fonts;
}; };
class PDFXFALayoutEngine : public xfa::XFA_AbstractVisitor class PDFXFALayoutEngine : public xfa::XFA_AbstractVisitor
@ -11641,6 +11645,7 @@ void PDFXFAEngineImpl::setDocument(const PDFModifiedDocument& document, PDFForm*
try try
{ {
const PDFObject& xfaObject = m_document->getObject(form->getXFA()); const PDFObject& xfaObject = m_document->getObject(form->getXFA());
updateResources(m_document->getObject(form->getResources()));
std::map<QByteArray, QByteArray> xfaData; std::map<QByteArray, QByteArray> xfaData;
if (xfaObject.isArray()) if (xfaObject.isArray())
@ -11725,6 +11730,79 @@ void PDFXFAEngineImpl::draw(const QMatrix& pagePointToDevicePointMatrix,
} }
} }
void PDFXFAEngineImpl::updateResources(const PDFObject& resources)
{
try
{
std::set<int> 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, void PDFXFAEngineImpl::drawItemValue(const xfa::XFA_value* value,
const xfa::XFA_ui* ui, const xfa::XFA_ui* ui,
QList<PDFRenderError>& errors, QList<PDFRenderError>& errors,
@ -13041,6 +13119,12 @@ void PDFXFAEngineImpl::clear()
// Clear the template // Clear the template
m_template = xfa::XFA_Node<xfa::XFA_template>(); m_template = xfa::XFA_Node<xfa::XFA_template>();
m_layout = Layout(); m_layout = Layout();
for (const auto& font : m_fonts)
{
QFontDatabase::removeApplicationFont(font.first);
}
m_fonts.clear();
} }
QMarginsF PDFXFAEngineImpl::createMargin(const xfa::XFA_margin* margin) QMarginsF PDFXFAEngineImpl::createMargin(const xfa::XFA_margin* margin)