mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2024-12-31 18:47:38 +01:00
Better handling composite fonts
This commit is contained in:
parent
4d770fdfcf
commit
8667cbbf90
@ -191,11 +191,11 @@ public:
|
|||||||
|
|
||||||
/// Tries to read array of real values from dictionary. If entry dictionary doesn't exist,
|
/// Tries to read array of real values from dictionary. If entry dictionary doesn't exist,
|
||||||
/// or error occurs, empty record is returned.
|
/// or error occurs, empty record is returned.
|
||||||
std::vector<PDFReal> readNumberArrayFromDictionary(const PDFDictionary *dictionary, const char *key);
|
std::vector<PDFReal> readNumberArrayFromDictionary(const PDFDictionary* dictionary, const char* key);
|
||||||
|
|
||||||
/// Tries to read array of integer values from dictionary. If entry dictionary doesn't exist,
|
/// Tries to read array of integer values from dictionary. If entry dictionary doesn't exist,
|
||||||
/// or error occurs, empty record is returned.
|
/// or error occurs, empty record is returned.
|
||||||
std::vector<PDFInteger> readIntegerArrayFromDictionary(const PDFDictionary *dictionary, const char *key);
|
std::vector<PDFInteger> readIntegerArrayFromDictionary(const PDFDictionary* dictionary, const char* key);
|
||||||
|
|
||||||
/// Reads number from dictionary. If dictionary entry doesn't exist, or error occurs, default value is returned.
|
/// Reads number from dictionary. If dictionary entry doesn't exist, or error occurs, default value is returned.
|
||||||
/// \param dictionary Dictionary containing desired data
|
/// \param dictionary Dictionary containing desired data
|
||||||
|
@ -436,7 +436,7 @@ void PDFRealizedFontImpl::fillTextSequence(const QByteArray& byteArray, TextSequ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const PDFReal glyphWidth = font->getGlyphWidth(static_cast<uint8_t>(byteArray[i]));
|
const PDFReal glyphWidth = font->getGlyphAdvance(static_cast<uint8_t>(byteArray[i]));
|
||||||
|
|
||||||
if (glyphIndex)
|
if (glyphIndex)
|
||||||
{
|
{
|
||||||
@ -467,16 +467,23 @@ void PDFRealizedFontImpl::fillTextSequence(const QByteArray& byteArray, TextSequ
|
|||||||
textSequence.items.reserve(textSequence.items.size() + cids.size());
|
textSequence.items.reserve(textSequence.items.size() + cids.size());
|
||||||
for (CID cid : cids)
|
for (CID cid : cids)
|
||||||
{
|
{
|
||||||
GID glyphIndex = CIDtoGIDmapper->map(cid);
|
const GID glyphIndex = CIDtoGIDmapper->map(cid);
|
||||||
|
const PDFReal glyphWidth = font->getGlyphAdvance(cid);
|
||||||
|
|
||||||
if (!glyphIndex)
|
if (glyphIndex)
|
||||||
{
|
{
|
||||||
throw PDFParserException(PDFTranslationContext::tr("Glyph for composite font character not found."));
|
// TODO: Dodelat mapovani na unicode
|
||||||
|
const Glyph& glyph = getGlyph(glyphIndex);
|
||||||
|
textSequence.items.emplace_back(&glyph.glyph, QChar(), glyph.advance);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reporter->reportRenderError(RenderErrorType::Warning, PDFTranslationContext::tr("Glyph for composite font character with cid '%1' not found.").arg(cid));
|
||||||
|
if (glyphWidth > 0)
|
||||||
|
{
|
||||||
|
textSequence.items.emplace_back(nullptr, QChar(), glyphWidth * m_pixelSize * FONT_WIDTH_MULTIPLIER);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Dodelat mapovani na unicode
|
|
||||||
const Glyph& glyph = getGlyph(glyphIndex);
|
|
||||||
textSequence.items.emplace_back(&glyph.glyph, QChar(), glyph.advance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -1060,7 +1067,51 @@ PDFFontPointer PDFFont::createFont(const PDFObject& object, const PDFDocument* d
|
|||||||
|
|
||||||
baseFont = fontLoader.readNameFromDictionary(descendantFontDictionary, "BaseFont");
|
baseFont = fontLoader.readNameFromDictionary(descendantFontDictionary, "BaseFont");
|
||||||
|
|
||||||
return PDFFontPointer(new PDFType0Font(qMove(fontDescriptor), qMove(cmap), qMove(cidToGidMapper)));
|
// Read default advance
|
||||||
|
PDFReal dw = fontLoader.readNumberFromDictionary(descendantFontDictionary, "DW", 1000.0);
|
||||||
|
std::array<PDFReal, 2> dw2 = { };
|
||||||
|
fontLoader.readNumberArrayFromDictionary(descendantFontDictionary, "DW2", dw2.begin(), dw2.end());
|
||||||
|
PDFReal defaultWidth = descendantFontDictionary->hasKey("DW") ? dw : dw2.back();
|
||||||
|
|
||||||
|
// Read horizontal advances
|
||||||
|
std::unordered_map<CID, PDFReal> advances;
|
||||||
|
if (descendantFontDictionary->hasKey("W"))
|
||||||
|
{
|
||||||
|
const PDFObject& wArrayObject = document->getObject(descendantFontDictionary->get("W"));
|
||||||
|
if (wArrayObject.isArray())
|
||||||
|
{
|
||||||
|
const PDFArray* wArray = wArrayObject.getArray();
|
||||||
|
const size_t size = wArray->getCount();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < size;)
|
||||||
|
{
|
||||||
|
CID startCID = fontLoader.readInteger(wArray->getItem(i++), 0);
|
||||||
|
const PDFObject& arrayOrCID = document->getObject(wArray->getItem(i++));
|
||||||
|
|
||||||
|
if (arrayOrCID.isInt())
|
||||||
|
{
|
||||||
|
CID endCID = arrayOrCID.getInteger();
|
||||||
|
PDFReal width = fontLoader.readInteger(wArray->getItem(i++), 0);
|
||||||
|
for (CID currentCID = startCID; currentCID <= endCID; ++currentCID)
|
||||||
|
{
|
||||||
|
advances[currentCID] = width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (arrayOrCID.isArray())
|
||||||
|
{
|
||||||
|
const PDFArray* widthArray = arrayOrCID.getArray();
|
||||||
|
const size_t widthArraySize = widthArray->getCount();
|
||||||
|
for (size_t widthArrayIndex = 0; widthArrayIndex < widthArraySize; ++widthArrayIndex)
|
||||||
|
{
|
||||||
|
PDFReal width = fontLoader.readNumber(widthArray->getItem(widthArrayIndex), 0);
|
||||||
|
advances[startCID + static_cast<CID>(widthArrayIndex)] = width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return PDFFontPointer(new PDFType0Font(qMove(fontDescriptor), qMove(cmap), qMove(cidToGidMapper), defaultWidth, qMove(advances)));
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -1113,7 +1164,7 @@ PDFSimpleFont::PDFSimpleFont(FontDescriptor fontDescriptor,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFInteger PDFSimpleFont::getGlyphWidth(size_t index) const
|
PDFInteger PDFSimpleFont::getGlyphAdvance(size_t index) const
|
||||||
{
|
{
|
||||||
const size_t min = m_firstChar;
|
const size_t min = m_firstChar;
|
||||||
const size_t max = m_lastChar;
|
const size_t max = m_lastChar;
|
||||||
@ -1560,4 +1611,15 @@ PDFFontCMapRepository::PDFFontCMapRepository()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PDFReal PDFType0Font::getGlyphAdvance(CID cid) const
|
||||||
|
{
|
||||||
|
auto it = m_advances.find(cid);
|
||||||
|
if (it != m_advances.cend())
|
||||||
|
{
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_defaultAdvance;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace pdf
|
} // namespace pdf
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
#include <QFont>
|
#include <QFont>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
class QPainterPath;
|
class QPainterPath;
|
||||||
|
|
||||||
namespace pdf
|
namespace pdf
|
||||||
@ -282,8 +284,8 @@ public:
|
|||||||
const encoding::EncodingTable* getEncoding() const { return &m_encoding; }
|
const encoding::EncodingTable* getEncoding() const { return &m_encoding; }
|
||||||
const GlyphIndices* getGlyphIndices() const { return &m_glyphIndices; }
|
const GlyphIndices* getGlyphIndices() const { return &m_glyphIndices; }
|
||||||
|
|
||||||
/// Returns the glyph width (or zero, if glyph width is invalid)
|
/// Returns the glyph advance (or zero, if glyph advance is invalid)
|
||||||
PDFInteger getGlyphWidth(size_t index) const;
|
PDFInteger getGlyphAdvance(size_t index) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QByteArray m_name;
|
QByteArray m_name;
|
||||||
@ -466,10 +468,12 @@ private:
|
|||||||
class PDFType0Font : public PDFFont
|
class PDFType0Font : public PDFFont
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit inline PDFType0Font(FontDescriptor fontDescriptor, PDFFontCMap cmap, PDFCIDtoGIDMapper mapper) :
|
explicit inline PDFType0Font(FontDescriptor fontDescriptor, PDFFontCMap cmap, PDFCIDtoGIDMapper mapper, PDFReal defaultAdvance, std::unordered_map<CID, PDFReal> advances) :
|
||||||
PDFFont(qMove(fontDescriptor)),
|
PDFFont(qMove(fontDescriptor)),
|
||||||
m_cmap(qMove(cmap)),
|
m_cmap(qMove(cmap)),
|
||||||
m_mapper(qMove(mapper))
|
m_mapper(qMove(mapper)),
|
||||||
|
m_defaultAdvance(defaultAdvance),
|
||||||
|
m_advances(qMove(advances))
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -481,9 +485,16 @@ public:
|
|||||||
const PDFFontCMap* getCMap() const { return &m_cmap; }
|
const PDFFontCMap* getCMap() const { return &m_cmap; }
|
||||||
const PDFCIDtoGIDMapper* getCIDtoGIDMapper() const { return &m_mapper; }
|
const PDFCIDtoGIDMapper* getCIDtoGIDMapper() const { return &m_mapper; }
|
||||||
|
|
||||||
|
/// Returns the glyph advance, if it can be obtained, or zero, if it cannot
|
||||||
|
/// be obtained or error occurs.
|
||||||
|
/// \param cid CID of the glyph
|
||||||
|
PDFReal getGlyphAdvance(CID cid) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PDFFontCMap m_cmap;
|
PDFFontCMap m_cmap;
|
||||||
PDFCIDtoGIDMapper m_mapper;
|
PDFCIDtoGIDMapper m_mapper;
|
||||||
|
PDFReal m_defaultAdvance;
|
||||||
|
std::unordered_map<CID, PDFReal> m_advances;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Repository with predefined CMaps
|
/// Repository with predefined CMaps
|
||||||
|
@ -1772,7 +1772,6 @@ void PDFPageContentProcessor::drawText(const TextSequence& textSequence)
|
|||||||
const bool fill = isTextRenderingModeFilled(textRenderingMode);
|
const bool fill = isTextRenderingModeFilled(textRenderingMode);
|
||||||
const bool stroke = isTextRenderingModeStroked(textRenderingMode);
|
const bool stroke = isTextRenderingModeStroked(textRenderingMode);
|
||||||
const bool clipped = isTextRenderingModeClipped(textRenderingMode);
|
const bool clipped = isTextRenderingModeClipped(textRenderingMode);
|
||||||
// TODO: Pouzit pravdepodobne sirky z widths array?
|
|
||||||
|
|
||||||
// Detect horizontal writing system
|
// Detect horizontal writing system
|
||||||
const bool isHorizontalWritingSystem = font->isHorizontalWritingSystem();
|
const bool isHorizontalWritingSystem = font->isHorizontalWritingSystem();
|
||||||
|
Loading…
Reference in New Issue
Block a user