diff --git a/PdfForQtLib/sources/pdfdocument.h b/PdfForQtLib/sources/pdfdocument.h index e288181..54d35b2 100644 --- a/PdfForQtLib/sources/pdfdocument.h +++ b/PdfForQtLib/sources/pdfdocument.h @@ -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 readNumberArrayFromDictionary(const PDFDictionary *dictionary, const char *key); + std::vector 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 readIntegerArrayFromDictionary(const PDFDictionary *dictionary, const char *key); + std::vector 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 diff --git a/PdfForQtLib/sources/pdffont.cpp b/PdfForQtLib/sources/pdffont.cpp index 5cf47d5..5d35c3c 100644 --- a/PdfForQtLib/sources/pdffont.cpp +++ b/PdfForQtLib/sources/pdffont.cpp @@ -436,7 +436,7 @@ void PDFRealizedFontImpl::fillTextSequence(const QByteArray& byteArray, TextSequ } } - const PDFReal glyphWidth = font->getGlyphWidth(static_cast(byteArray[i])); + const PDFReal glyphWidth = font->getGlyphAdvance(static_cast(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 dw2 = { }; + fontLoader.readNumberArrayFromDictionary(descendantFontDictionary, "DW2", dw2.begin(), dw2.end()); + PDFReal defaultWidth = descendantFontDictionary->hasKey("DW") ? dw : dw2.back(); + + // Read horizontal advances + std::unordered_map 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(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 diff --git a/PdfForQtLib/sources/pdffont.h b/PdfForQtLib/sources/pdffont.h index 4fdb99c..5dfc6dc 100644 --- a/PdfForQtLib/sources/pdffont.h +++ b/PdfForQtLib/sources/pdffont.h @@ -25,6 +25,8 @@ #include #include +#include + 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 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 m_advances; }; /// Repository with predefined CMaps diff --git a/PdfForQtLib/sources/pdfpagecontentprocessor.cpp b/PdfForQtLib/sources/pdfpagecontentprocessor.cpp index 06e9ac2..8f2f996 100644 --- a/PdfForQtLib/sources/pdfpagecontentprocessor.cpp +++ b/PdfForQtLib/sources/pdfpagecontentprocessor.cpp @@ -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();