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
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,

View File

@ -819,11 +819,7 @@ void PDFPrecompiledPage::finalize(qint64 compilingTimeNS, QList<PDFRenderError>
};
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)
{

View File

@ -18,6 +18,7 @@
#include "pdfxfaengine.h"
#include "pdfform.h"
#include "pdfpainterutils.h"
#include "pdffont.h"
#include <QDomElement>
#include <QDomDocument>
@ -26,6 +27,7 @@
#include <QImageReader>
#include <QTextDocument>
#include <QTextBlock>
#include <QFontDatabase>
#include <QAbstractTextDocumentLayout>
#include <stack>
@ -9699,6 +9701,7 @@ private:
std::vector<xfa::XFA_ParagraphSettings> 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<int, QByteArray> 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<QByteArray, QByteArray> xfaData;
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,
const xfa::XFA_ui* ui,
QList<PDFRenderError>& errors,
@ -13041,6 +13119,12 @@ void PDFXFAEngineImpl::clear()
// Clear the template
m_template = xfa::XFA_Node<xfa::XFA_template>();
m_layout = Layout();
for (const auto& font : m_fonts)
{
QFontDatabase::removeApplicationFont(font.first);
}
m_fonts.clear();
}
QMarginsF PDFXFAEngineImpl::createMargin(const xfa::XFA_margin* margin)