mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-03-20 21:30:03 +01:00
Bugfixes in the font drawing
This commit is contained in:
parent
9d982747e2
commit
e167e2463d
@ -27,6 +27,7 @@
|
|||||||
#include <freetype/ftoutln.h>
|
#include <freetype/ftoutln.h>
|
||||||
|
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
|
#include <QPainterPath>
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
#include "Windows.h"
|
#include "Windows.h"
|
||||||
@ -405,7 +406,7 @@ void PDFRealizedFontImpl::checkFreeTypeError(FT_Error error)
|
|||||||
message = QString::fromLatin1(errorString);
|
message = QString::fromLatin1(errorString);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw PDFParserException(PDFTranslationContext::tr("FreeType error code %1: message").arg(error).arg(message));
|
throw PDFParserException(PDFTranslationContext::tr("FreeType error code %1: %2").arg(error).arg(message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,21 +436,10 @@ PDFRealizedFontPointer PDFRealizedFont::createRealizedFont(PDFFontPointer font,
|
|||||||
const FontDescriptor* descriptor = font->getFontDescriptor();
|
const FontDescriptor* descriptor = font->getFontDescriptor();
|
||||||
if (descriptor->isEmbedded())
|
if (descriptor->isEmbedded())
|
||||||
{
|
{
|
||||||
|
|
||||||
PDFRealizedFontImpl::checkFreeTypeError(FT_Init_FreeType(&impl->m_library));
|
PDFRealizedFontImpl::checkFreeTypeError(FT_Init_FreeType(&impl->m_library));
|
||||||
|
const QByteArray* embeddedFontData = descriptor->getEmbeddedFontData();
|
||||||
if (!descriptor->fontFile.isEmpty())
|
Q_ASSERT(embeddedFontData);
|
||||||
{
|
impl->m_embeddedFontData = *embeddedFontData;
|
||||||
impl->m_embeddedFontData = descriptor->fontFile;
|
|
||||||
}
|
|
||||||
else if (!descriptor->fontFile2.isEmpty())
|
|
||||||
{
|
|
||||||
impl->m_embeddedFontData = descriptor->fontFile2;
|
|
||||||
}
|
|
||||||
else if (!descriptor->fontFile3.isEmpty())
|
|
||||||
{
|
|
||||||
impl->m_embeddedFontData = descriptor->fontFile3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// At this time, embedded font data should not be empty!
|
// At this time, embedded font data should not be empty!
|
||||||
Q_ASSERT(!impl->m_embeddedFontData.isEmpty());
|
Q_ASSERT(!impl->m_embeddedFontData.isEmpty());
|
||||||
@ -689,7 +679,8 @@ PDFFontPointer PDFFont::createFont(const PDFObject& object, const PDFDocument* d
|
|||||||
throw PDFParserException(PDFTranslationContext::tr("Invalid encoding entry of the font."));
|
throw PDFParserException(PDFTranslationContext::tr("Invalid encoding entry of the font."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (encoding == PDFEncoding::Encoding::Invalid)
|
||||||
{
|
{
|
||||||
// We get encoding for the standard font. If we have invalid standard font,
|
// We get encoding for the standard font. If we have invalid standard font,
|
||||||
// then we get standard encoding. So we shouldn't test it.
|
// then we get standard encoding. So we shouldn't test it.
|
||||||
@ -703,6 +694,73 @@ PDFFontPointer PDFFont::createFont(const PDFObject& object, const PDFDocument* d
|
|||||||
|
|
||||||
simpleFontEncodingTable = *PDFEncoding::getTableForEncoding(encoding);
|
simpleFontEncodingTable = *PDFEncoding::getTableForEncoding(encoding);
|
||||||
|
|
||||||
|
if (fontDescriptor.isEmbedded())
|
||||||
|
{
|
||||||
|
// Return encoding from the embedded font
|
||||||
|
const QByteArray* embeddedFontData = fontDescriptor.getEmbeddedFontData();
|
||||||
|
Q_ASSERT(embeddedFontData);
|
||||||
|
|
||||||
|
FT_Library library;
|
||||||
|
if (!FT_Init_FreeType(&library))
|
||||||
|
{
|
||||||
|
FT_Face face;
|
||||||
|
if (!FT_New_Memory_Face(library, reinterpret_cast<const FT_Byte*>(embeddedFontData->constData()), embeddedFontData->size(), 0, &face))
|
||||||
|
{
|
||||||
|
if (FT_Has_PS_Glyph_Names(face))
|
||||||
|
{
|
||||||
|
for (FT_Int i = 0; i < face->num_charmaps; ++i)
|
||||||
|
{
|
||||||
|
FT_CharMap charMap = face->charmaps[i];
|
||||||
|
switch (charMap->encoding)
|
||||||
|
{
|
||||||
|
case FT_ENCODING_ADOBE_STANDARD:
|
||||||
|
case FT_ENCODING_ADOBE_LATIN_1:
|
||||||
|
case FT_ENCODING_ADOBE_CUSTOM:
|
||||||
|
case FT_ENCODING_ADOBE_EXPERT:
|
||||||
|
{
|
||||||
|
// Try to load data from the encoding
|
||||||
|
if (!FT_Set_Charmap(face, charMap))
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < simpleFontEncodingTable.size(); ++i)
|
||||||
|
{
|
||||||
|
FT_UInt glyphIndex = FT_Get_Char_Index(face, static_cast<FT_ULong>(i));
|
||||||
|
if (glyphIndex > 0)
|
||||||
|
{
|
||||||
|
char buffer[128] = { };
|
||||||
|
if (!FT_Get_Glyph_Name(face, glyphIndex, buffer, static_cast<FT_ULong>(std::size(buffer))))
|
||||||
|
{
|
||||||
|
QByteArray byteArrayBuffer(buffer);
|
||||||
|
QChar character = PDFNameToUnicode::getUnicodeForName(byteArrayBuffer);
|
||||||
|
if (character.isNull())
|
||||||
|
{
|
||||||
|
character = PDFNameToUnicode::getUnicodeForNameZapfDingbats(byteArrayBuffer);
|
||||||
|
}
|
||||||
|
if (!character.isNull())
|
||||||
|
{
|
||||||
|
encoding = PDFEncoding::Encoding::Custom;
|
||||||
|
simpleFontEncodingTable[i] = character;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FT_Done_Face(face);
|
||||||
|
}
|
||||||
|
|
||||||
|
FT_Done_FreeType(library);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Fill in differences
|
// Fill in differences
|
||||||
if (hasDifferences)
|
if (hasDifferences)
|
||||||
{
|
{
|
||||||
@ -784,45 +842,7 @@ PDFSimpleFont::PDFSimpleFont(FontDescriptor fontDescriptor,
|
|||||||
|
|
||||||
PDFRealizedFontPointer PDFSimpleFont::getRealizedFont(PDFFontPointer font, PDFReal fontSize) const
|
PDFRealizedFontPointer PDFSimpleFont::getRealizedFont(PDFFontPointer font, PDFReal fontSize) const
|
||||||
{
|
{
|
||||||
// TODO: Fix font creation to use also embedded fonts, font descriptor, etc.
|
|
||||||
// TODO: Remove QRawFont
|
|
||||||
|
|
||||||
return PDFRealizedFont::createRealizedFont(font, fontSize);
|
return PDFRealizedFont::createRealizedFont(font, fontSize);
|
||||||
/*
|
|
||||||
QRawFont rawFont;
|
|
||||||
|
|
||||||
if (m_fontDescriptor.isEmbedded())
|
|
||||||
{
|
|
||||||
// Type 1 font
|
|
||||||
if (!m_fontDescriptor.fontFile.isEmpty())
|
|
||||||
{
|
|
||||||
rawFont.loadFromData(m_fontDescriptor.fontFile, fontSize, QFont::PreferNoHinting);
|
|
||||||
}
|
|
||||||
else if (!m_fontDescriptor.fontFile2.isEmpty())
|
|
||||||
{
|
|
||||||
rawFont.loadFromData(m_fontDescriptor.fontFile2, fontSize, QFont::PreferNoHinting);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rawFont.isValid())
|
|
||||||
{
|
|
||||||
throw PDFParserException(PDFTranslationContext::tr("Can't load embedded font."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// TODO: Zkontrolovat, zda se zde opravdu prebiraji spravne fonty
|
|
||||||
const int weight = qBound<int>(0, m_fontDescriptor.fontWeight / 10.0, 99);
|
|
||||||
const int stretch = qBound<int>(1, m_fontDescriptor.fontStretch, 4000);
|
|
||||||
|
|
||||||
QFont font(m_baseFont);
|
|
||||||
font.setHintingPreference(QFont::PreferNoHinting);
|
|
||||||
font.setStretch(stretch);
|
|
||||||
font.setWeight(weight);
|
|
||||||
font.setPixelSize(fontSize);
|
|
||||||
rawFont = QRawFont::fromFont(font, QFontDatabase::Any);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rawFont;*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString PDFSimpleFont::getTextUsingEncoding(const QByteArray& byteArray) const
|
QString PDFSimpleFont::getTextUsingEncoding(const QByteArray& byteArray) const
|
||||||
@ -928,4 +948,22 @@ PDFRealizedFontPointer PDFFontCache::getRealizedFont(const PDFFontPointer& font,
|
|||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QByteArray* FontDescriptor::getEmbeddedFontData() const
|
||||||
|
{
|
||||||
|
if (!fontFile.isEmpty())
|
||||||
|
{
|
||||||
|
return &fontFile;
|
||||||
|
}
|
||||||
|
else if (!fontFile2.isEmpty())
|
||||||
|
{
|
||||||
|
return &fontFile2;
|
||||||
|
}
|
||||||
|
else if (!fontFile3.isEmpty())
|
||||||
|
{
|
||||||
|
return &fontFile3;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace pdf
|
} // namespace pdf
|
||||||
|
@ -22,9 +22,11 @@
|
|||||||
#include "pdfencoding.h"
|
#include "pdfencoding.h"
|
||||||
#include "pdfobject.h"
|
#include "pdfobject.h"
|
||||||
|
|
||||||
#include <QRawFont>
|
#include <QFont>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
|
|
||||||
|
class QPainterPath;
|
||||||
|
|
||||||
namespace pdf
|
namespace pdf
|
||||||
{
|
{
|
||||||
class PDFDocument;
|
class PDFDocument;
|
||||||
@ -154,6 +156,9 @@ struct FontDescriptor
|
|||||||
{
|
{
|
||||||
bool isEmbedded() const { return !fontFile.isEmpty() || !fontFile2.isEmpty() || !fontFile3.isEmpty(); }
|
bool isEmbedded() const { return !fontFile.isEmpty() || !fontFile2.isEmpty() || !fontFile3.isEmpty(); }
|
||||||
|
|
||||||
|
/// Returns embedded font data, or nullptr, if font is not embedded
|
||||||
|
const QByteArray* getEmbeddedFontData() const;
|
||||||
|
|
||||||
QByteArray fontName;
|
QByteArray fontName;
|
||||||
QByteArray fontFamily;
|
QByteArray fontFamily;
|
||||||
QFont::Stretch fontStretch = QFont::AnyStretch;
|
QFont::Stretch fontStretch = QFont::AnyStretch;
|
||||||
@ -233,7 +238,7 @@ public:
|
|||||||
virtual FontType getFontType() const = 0;
|
virtual FontType getFontType() const = 0;
|
||||||
|
|
||||||
/// Realizes the font (physical materialization of the font using pixel size,
|
/// Realizes the font (physical materialization of the font using pixel size,
|
||||||
/// if font can't be realized, then empty QRawFont is returned).
|
/// if font can't be realized, then exception is thrown).
|
||||||
/// \param fontSize Size of the font
|
/// \param fontSize Size of the font
|
||||||
virtual PDFRealizedFontPointer getRealizedFont(PDFFontPointer font, PDFReal fontSize) const = 0;
|
virtual PDFRealizedFontPointer getRealizedFont(PDFFontPointer font, PDFReal fontSize) const = 0;
|
||||||
|
|
||||||
|
@ -1818,43 +1818,6 @@ void PDFPageContentProcessor::drawText(const TextSequence& textSequence)
|
|||||||
|
|
||||||
m_graphicState.setTextMatrix(textMatrix);
|
m_graphicState.setTextMatrix(textMatrix);
|
||||||
updateGraphicState();
|
updateGraphicState();
|
||||||
|
|
||||||
|
|
||||||
/*std::vector<QChar> chars;
|
|
||||||
chars.reserve(textSequence.items.size());
|
|
||||||
for (const TextSequenceItem& item : textSequence.items)
|
|
||||||
{
|
|
||||||
if (item.isCharacter())
|
|
||||||
{
|
|
||||||
chars.push_back(item.character);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int numGlyphs = static_cast<int>(chars.size());
|
|
||||||
std::vector<uint32_t> glyphIndices;
|
|
||||||
glyphIndices.resize(chars.size(), 0);
|
|
||||||
if (font.glyphIndexesForChars(chars.data(), static_cast<int>(chars.size()), glyphIndices.data(), &numGlyphs))
|
|
||||||
{
|
|
||||||
if (chars.size() != static_cast<size_t>(numGlyphs))
|
|
||||||
{
|
|
||||||
throw PDFRendererException(RenderErrorType::Error, PDFTranslationContext::tr("Cant convert unicode to glyph indices, text can't be printed."));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<QPointF> advances;
|
|
||||||
advances.resize(numGlyphs, QPointF());
|
|
||||||
if (font.advancesForGlyphIndexes(glyphIndices.data(), advances.data(), numGlyphs, QRawFont::SeparateAdvances | QRawFont::UseDesignMetrics))
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw PDFRendererException(RenderErrorType::Error, PDFTranslationContext::tr("Cant convert unicode to glyph indices, text can't be printed."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw PDFRendererException(RenderErrorType::Error, PDFTranslationContext::tr("Cant convert unicode to glyph indices, text can't be printed."));
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
#include "pdfutils.h"
|
#include "pdfutils.h"
|
||||||
|
|
||||||
#include <QMatrix>
|
#include <QMatrix>
|
||||||
#include <QRawFont>
|
|
||||||
#include <QPainterPath>
|
#include <QPainterPath>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user