Bugfix: inexact font loading using font name, warning about font substitution

This commit is contained in:
Jakub Melka 2019-10-02 19:37:19 +02:00
parent 2dfb653233
commit efef799c09
5 changed files with 51 additions and 12 deletions

View File

@ -52,7 +52,7 @@ public:
/// Loads font from descriptor
/// \param descriptor Descriptor describing the font
QByteArray loadFont(const FontDescriptor* descriptor, StandardFontType standardFontType) const;
QByteArray loadFont(const FontDescriptor* descriptor, StandardFontType standardFontType, PDFRenderErrorReporter* reporter) const;
private:
explicit PDFSystemFontInfoStorage();
@ -91,7 +91,7 @@ const PDFSystemFontInfoStorage* PDFSystemFontInfoStorage::getInstance()
return &instance;
}
QByteArray PDFSystemFontInfoStorage::loadFont(const FontDescriptor* descriptor, StandardFontType standardFontType) const
QByteArray PDFSystemFontInfoStorage::loadFont(const FontDescriptor* descriptor, StandardFontType standardFontType, PDFRenderErrorReporter* reporter) const
{
QByteArray result;
@ -187,7 +187,7 @@ QByteArray PDFSystemFontInfoStorage::loadFont(const FontDescriptor* descriptor,
// and try to set weight
QString fontFamily = QString::fromLatin1(descriptor->fontFamily);
if (!fontFamily.isEmpty())
if (!fontFamily.isEmpty() && result.isEmpty())
{
for (const FontInfo& fontInfo : m_fontInfos)
{
@ -199,6 +199,7 @@ QByteArray PDFSystemFontInfoStorage::loadFont(const FontDescriptor* descriptor,
if (!result.isEmpty())
{
reporter->reportRenderError(RenderErrorType::Warning, PDFTranslationContext::tr("Inexact font substitution: font %1 replaced by %2 using font family %3.").arg(fontName, fontInfo.faceNameAdjusted, fontFamily));
break;
}
}
@ -218,6 +219,7 @@ QByteArray PDFSystemFontInfoStorage::loadFont(const FontDescriptor* descriptor,
if (!result.isEmpty())
{
reporter->reportRenderError(RenderErrorType::Warning, PDFTranslationContext::tr("Inexact font substitution: font %1 replaced by %2 using font family %3.").arg(fontName, fontInfo.faceNameAdjusted, fontFamily));
break;
}
}
@ -225,6 +227,27 @@ QByteArray PDFSystemFontInfoStorage::loadFont(const FontDescriptor* descriptor,
}
}
// Try to inexact match for font name - find similar font
if (!fontName.isEmpty() && result.isEmpty())
{
for (const FontInfo& fontInfo : m_fontInfos)
{
if (fontInfo.faceNameAdjusted.contains(fontName))
{
LOGFONT logFont = fontInfo.logFont;
logFont.lfWeight = descriptor->fontWeight;
logFont.lfItalic = lfItalic;
result = getFontData(&logFont, hdc);
if (!result.isEmpty())
{
reporter->reportRenderError(RenderErrorType::Warning, PDFTranslationContext::tr("Inexact font substitution: font %1 replaced by %2.").arg(fontName, fontInfo.faceNameAdjusted));
break;
}
}
}
}
ReleaseDC(NULL, hdc);
#endif
@ -624,7 +647,7 @@ bool PDFRealizedFont::isHorizontalWritingSystem() const
return m_impl->isHorizontalWritingSystem();
}
PDFRealizedFontPointer PDFRealizedFont::createRealizedFont(PDFFontPointer font, PDFReal pixelSize)
PDFRealizedFontPointer PDFRealizedFont::createRealizedFont(PDFFontPointer font, PDFReal pixelSize, PDFRenderErrorReporter* reporter)
{
PDFRealizedFontPointer result;
@ -669,7 +692,7 @@ PDFRealizedFontPointer PDFRealizedFont::createRealizedFont(PDFFontPointer font,
}
const PDFSystemFontInfoStorage* fontStorage = PDFSystemFontInfoStorage::getInstance();
impl->m_systemFontData = fontStorage->loadFont(descriptor, standardFontType);
impl->m_systemFontData = fontStorage->loadFont(descriptor, standardFontType, reporter);
if (impl->m_systemFontData.isEmpty())
{
@ -1393,7 +1416,7 @@ PDFFontPointer PDFFontCache::getFont(const PDFObject& fontObject) const
}
}
PDFRealizedFontPointer PDFFontCache::getRealizedFont(const PDFFontPointer& font, PDFReal size) const
PDFRealizedFontPointer PDFFontCache::getRealizedFont(const PDFFontPointer& font, PDFReal size, PDFRenderErrorReporter* reporter) const
{
Q_ASSERT(font);
@ -1402,7 +1425,7 @@ PDFRealizedFontPointer PDFFontCache::getRealizedFont(const PDFFontPointer& font,
if (it == m_realizedFontCache.cend())
{
// We must create the realized font
PDFRealizedFontPointer realizedFont = PDFRealizedFont::createRealizedFont(font, size);
PDFRealizedFontPointer realizedFont = PDFRealizedFont::createRealizedFont(font, size, reporter);
if (m_realizedFontCache.size() >= m_realizedFontCacheLimit)
{

View File

@ -233,7 +233,7 @@ public:
/// Creates new realized font from the standard font. If font can't be created,
/// then exception is thrown.
static PDFRealizedFontPointer createRealizedFont(PDFFontPointer font, PDFReal pixelSize);
static PDFRealizedFontPointer createRealizedFont(PDFFontPointer font, PDFReal pixelSize, PDFRenderErrorReporter* reporter);
private:
/// Constructs new realized font
@ -393,7 +393,8 @@ public:
/// then exception is thrown.
/// \param font Font, which should be realized
/// \param size Size of the font (in pixels)
PDFRealizedFontPointer getRealizedFont(const PDFFontPointer& font, PDFReal size) const;
/// \param reporter Error reporter
PDFRealizedFontPointer getRealizedFont(const PDFFontPointer& font, PDFReal size, PDFRenderErrorReporter* reporter) const;
private:
const size_t m_fontCacheLimit;

View File

@ -2917,11 +2917,11 @@ void PDFPageContentProcessor::drawText(const TextSequence& textSequence)
}
}
PDFRealizedFontPointer PDFPageContentProcessor::getRealizedFontImpl() const
PDFRealizedFontPointer PDFPageContentProcessor::getRealizedFontImpl()
{
if (m_graphicState.getTextFont())
{
return m_fontCache->getRealizedFont(m_graphicState.getTextFont(), m_graphicState.getTextFontSize());
return m_fontCache->getRealizedFont(m_graphicState.getTextFont(), m_graphicState.getTextFontSize(), this);
}
return PDFRealizedFontPointer();

View File

@ -785,7 +785,7 @@ private:
const PDFRealizedFontPointer& getRealizedFont() { return m_realizedFont.get(this, &PDFPageContentProcessor::getRealizedFontImpl); }
/// Returns realized font (or empty font, if font can't be realized)
PDFRealizedFontPointer getRealizedFontImpl() const;
PDFRealizedFontPointer getRealizedFontImpl();
/// Checks, if stroking color is valid
void checkStrokingColor();

View File

@ -59,6 +59,21 @@ public:
return m_object;
}
/// Returns the cached object. If object is dirty, then cached object is refreshed.
/// \param holder Holder object, which owns the cached item
/// \param function Refresh function
template<typename H>
inline const T& get(H* holder, T(H::* function)(void))
{
if (m_dirty)
{
m_object = (holder->*function)();
m_dirty = false;
}
return m_object;
}
/// Invalidates the cached item, so it must be refreshed from the cache next time,
/// if it is accessed.
inline void dirty()