ToUnicode map also in Type3 fonts

This commit is contained in:
Jakub Melka 2020-08-21 16:37:57 +02:00
parent b1beca8ef9
commit 9c260bb75a
2 changed files with 65 additions and 40 deletions

View File

@ -514,7 +514,8 @@ void PDFRealizedFontImpl::fillTextSequence(const QByteArray& byteArray, TextSequ
reporter->reportRenderError(RenderErrorType::Warning, PDFTranslationContext::tr("Glyph for simple font character code '%1' not found.").arg(static_cast<uint8_t>(byteArray[i]))); reporter->reportRenderError(RenderErrorType::Warning, PDFTranslationContext::tr("Glyph for simple font character code '%1' not found.").arg(static_cast<uint8_t>(byteArray[i])));
if (glyphWidth > 0) if (glyphWidth > 0)
{ {
textSequence.items.emplace_back(nullptr, QChar(), glyphWidth * m_pixelSize * FONT_WIDTH_MULTIPLIER); const QPainterPath* nullpath = nullptr;
textSequence.items.emplace_back(nullpath, QChar(), glyphWidth * m_pixelSize * FONT_WIDTH_MULTIPLIER);
} }
} }
} }
@ -555,7 +556,8 @@ void PDFRealizedFontImpl::fillTextSequence(const QByteArray& byteArray, TextSequ
{ {
// We do not multiply advance with font size and FONT_WIDTH_MULTIPLIER, because in the code, // We do not multiply advance with font size and FONT_WIDTH_MULTIPLIER, because in the code,
// "advance" is treated as in font space. // "advance" is treated as in font space.
textSequence.items.emplace_back(nullptr, QChar(), -glyphWidth); const QPainterPath* nullpath = nullptr;
textSequence.items.emplace_back(nullpath, QChar(), -glyphWidth);
} }
} }
} }
@ -1406,8 +1408,21 @@ PDFFontPointer PDFFont::createFont(const PDFObject& object, const PDFDocument* d
} }
} }
PDFFontCMap toUnicodeCMap;
const PDFObject& toUnicode = document->getObject(fontDictionary->get("ToUnicode"));
if (toUnicode.isName())
{
toUnicodeCMap = PDFFontCMap::createFromName(toUnicode.getString());
}
else if (toUnicode.isStream())
{
const PDFStream* stream = toUnicode.getStream();
QByteArray decodedStream = document->getDecodedStream(stream);
toUnicodeCMap = PDFFontCMap::createFromData(decodedStream);
}
std::vector<PDFReal> widths = fontLoader.readNumberArrayFromDictionary(fontDictionary, "Widths"); std::vector<PDFReal> widths = fontLoader.readNumberArrayFromDictionary(fontDictionary, "Widths");
return PDFFontPointer(new PDFType3Font(qMove(fontDescriptor), firstChar, lastChar, fontMatrix, qMove(characterContentStreams), qMove(widths), document->getObject(fontDictionary->get("Resources")))); return PDFFontPointer(new PDFType3Font(qMove(fontDescriptor), firstChar, lastChar, fontMatrix, qMove(characterContentStreams), qMove(widths), document->getObject(fontDictionary->get("Resources")), qMove(toUnicodeCMap)));
} }
default: default:
@ -2146,14 +2161,16 @@ PDFType3Font::PDFType3Font(FontDescriptor fontDescriptor,
QMatrix fontMatrix, QMatrix fontMatrix,
std::map<int, QByteArray>&& characterContentStreams, std::map<int, QByteArray>&& characterContentStreams,
std::vector<double>&& widths, std::vector<double>&& widths,
const PDFObject& resources) : const PDFObject& resources,
PDFFontCMap toUnicode) :
PDFFont(qMove(fontDescriptor)), PDFFont(qMove(fontDescriptor)),
m_firstCharacterIndex(firstCharacterIndex), m_firstCharacterIndex(firstCharacterIndex),
m_lastCharacterIndex(lastCharacterIndex), m_lastCharacterIndex(lastCharacterIndex),
m_fontMatrix(fontMatrix), m_fontMatrix(fontMatrix),
m_characterContentStreams(qMove(characterContentStreams)), m_characterContentStreams(qMove(characterContentStreams)),
m_widths(qMove(widths)), m_widths(qMove(widths)),
m_resources(resources) m_resources(resources),
m_toUnicode(qMove(toUnicode))
{ {
} }
@ -2203,11 +2220,12 @@ void PDFRealizedType3FontImpl::fillTextSequence(const QByteArray& byteArray, Tex
{ {
int index = static_cast<uint8_t>(byteArray[i]); int index = static_cast<uint8_t>(byteArray[i]);
const QByteArray* contentStream = parentFont->getContentStream(index); const QByteArray* contentStream = parentFont->getContentStream(index);
QChar character = parentFont->getUnicode(index);
const double width = parentFont->getWidth(index); const double width = parentFont->getWidth(index);
if (contentStream) if (contentStream)
{ {
textSequence.items.emplace_back(contentStream, width); textSequence.items.emplace_back(contentStream, character, width);
} }
else else
{ {

View File

@ -61,7 +61,7 @@ struct TextSequenceItem
inline explicit TextSequenceItem() = default; inline explicit TextSequenceItem() = default;
inline explicit TextSequenceItem(const QPainterPath* glyph, QChar character, PDFReal advance) : glyph(glyph), character(character), advance(advance) { } inline explicit TextSequenceItem(const QPainterPath* glyph, QChar character, PDFReal advance) : glyph(glyph), character(character), advance(advance) { }
inline explicit TextSequenceItem(PDFReal advance) : character(), advance(advance) { } inline explicit TextSequenceItem(PDFReal advance) : character(), advance(advance) { }
inline explicit TextSequenceItem(const QByteArray* characterContentStream, double advance) : characterContentStream(characterContentStream), advance(advance) { } inline explicit TextSequenceItem(const QByteArray* characterContentStream, QChar character, PDFReal advance) : characterContentStream(characterContentStream), character(character), advance(advance) { }
inline bool isContentStream() const { return characterContentStream; } inline bool isContentStream() const { return characterContentStream; }
inline bool isCharacter() const { return glyph; } inline bool isCharacter() const { return glyph; }
@ -354,39 +354,6 @@ public:
virtual FontType getFontType() const override; virtual FontType getFontType() const override;
}; };
class PDFType3Font : public PDFFont
{
public:
explicit PDFType3Font(FontDescriptor fontDescriptor,
int firstCharacterIndex,
int lastCharacterIndex,
QMatrix fontMatrix,
std::map<int, QByteArray>&& characterContentStreams,
std::vector<double>&& widths,
const PDFObject& resources);
virtual FontType getFontType() const override;
virtual void dumpFontToTreeItem(QTreeWidgetItem*item) const override;
/// Returns width of the character. If character doesn't exist, then zero is returned.
double getWidth(int characterIndex) const;
/// Return content stream for the character. If character doesn't exist, then nullptr
/// is returned.
const QByteArray* getContentStream(int characterIndex) const;
const QMatrix& getFontMatrix() const { return m_fontMatrix; }
const PDFObject& getResources() const { return m_resources; }
private:
int m_firstCharacterIndex;
int m_lastCharacterIndex;
QMatrix m_fontMatrix;
std::map<int, QByteArray> m_characterContentStreams;
std::vector<double> m_widths;
PDFObject m_resources;
};
/// Font cache which caches both fonts, and realized fonts. Cache has individual limit /// Font cache which caches both fonts, and realized fonts. Cache has individual limit
/// for fonts, and realized fonts. /// for fonts, and realized fonts.
class PDFFontCache class PDFFontCache
@ -542,6 +509,46 @@ private:
bool m_vertical = false; bool m_vertical = false;
}; };
class PDFType3Font : public PDFFont
{
public:
explicit PDFType3Font(FontDescriptor fontDescriptor,
int firstCharacterIndex,
int lastCharacterIndex,
QMatrix fontMatrix,
std::map<int, QByteArray>&& characterContentStreams,
std::vector<double>&& widths,
const PDFObject& resources,
PDFFontCMap toUnicode);
virtual FontType getFontType() const override;
virtual void dumpFontToTreeItem(QTreeWidgetItem*item) const override;
/// Returns width of the character. If character doesn't exist, then zero is returned.
double getWidth(int characterIndex) const;
/// Return content stream for the character. If character doesn't exist, then nullptr
/// is returned.
const QByteArray* getContentStream(int characterIndex) const;
const QMatrix& getFontMatrix() const { return m_fontMatrix; }
const PDFObject& getResources() const { return m_resources; }
const PDFFontCMap& getToUnicode() const { return m_toUnicode; }
/// Returns unicode character for given character index. If unicode mapping is not
/// present, empty (null) character is returned.
QChar getUnicode(int characterIndex) const { return m_toUnicode.getToUnicode(characterIndex); }
private:
int m_firstCharacterIndex;
int m_lastCharacterIndex;
QMatrix m_fontMatrix;
std::map<int, QByteArray> m_characterContentStreams;
std::vector<double> m_widths;
PDFObject m_resources;
PDFFontCMap m_toUnicode;
};
/// Composite font (CID-keyed font) /// Composite font (CID-keyed font)
class PDFType0Font : public PDFFont class PDFType0Font : public PDFFont
{ {