mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2024-12-29 01:29:59 +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,
|
||||
/// 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,
|
||||
/// 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.
|
||||
/// \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)
|
||||
{
|
||||
@ -467,16 +467,23 @@ void PDFRealizedFontImpl::fillTextSequence(const QByteArray& byteArray, TextSequ
|
||||
textSequence.items.reserve(textSequence.items.size() + cids.size());
|
||||
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;
|
||||
@ -1060,7 +1067,51 @@ PDFFontPointer PDFFont::createFont(const PDFObject& object, const PDFDocument* d
|
||||
|
||||
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:
|
||||
@ -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 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
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include <QFont>
|
||||
#include <QSharedPointer>
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
class QPainterPath;
|
||||
|
||||
namespace pdf
|
||||
@ -282,8 +284,8 @@ public:
|
||||
const encoding::EncodingTable* getEncoding() const { return &m_encoding; }
|
||||
const GlyphIndices* getGlyphIndices() const { return &m_glyphIndices; }
|
||||
|
||||
/// Returns the glyph width (or zero, if glyph width is invalid)
|
||||
PDFInteger getGlyphWidth(size_t index) const;
|
||||
/// Returns the glyph advance (or zero, if glyph advance is invalid)
|
||||
PDFInteger getGlyphAdvance(size_t index) const;
|
||||
|
||||
protected:
|
||||
QByteArray m_name;
|
||||
@ -466,10 +468,12 @@ private:
|
||||
class PDFType0Font : public PDFFont
|
||||
{
|
||||
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)),
|
||||
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 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:
|
||||
PDFFontCMap m_cmap;
|
||||
PDFCIDtoGIDMapper m_mapper;
|
||||
PDFReal m_defaultAdvance;
|
||||
std::unordered_map<CID, PDFReal> m_advances;
|
||||
};
|
||||
|
||||
/// Repository with predefined CMaps
|
||||
|
@ -1772,7 +1772,6 @@ void PDFPageContentProcessor::drawText(const TextSequence& textSequence)
|
||||
const bool fill = isTextRenderingModeFilled(textRenderingMode);
|
||||
const bool stroke = isTextRenderingModeStroked(textRenderingMode);
|
||||
const bool clipped = isTextRenderingModeClipped(textRenderingMode);
|
||||
// TODO: Pouzit pravdepodobne sirky z widths array?
|
||||
|
||||
// Detect horizontal writing system
|
||||
const bool isHorizontalWritingSystem = font->isHorizontalWritingSystem();
|
||||
|
Loading…
Reference in New Issue
Block a user