poppler/GfxState.cc | 6 + qt5/src/ArthurOutputDev.cc | 190 +++++++++++++++++++++++++++++++++++++-------- qt5/src/ArthurOutputDev.h | 16 ++- qt5/src/poppler-page.cc | 4 4 files changed, 176 insertions(+), 40 deletions(-)
New commits: commit d80e7aac3366f93865581a783751abb528c120b3 Author: Albert Astals Cid <[email protected]> Date: Wed Apr 11 00:32:35 2018 +0200 Make GfxGouraudTriangleShading::parse more accepting of malformed documents Bug #105972 diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc index eaa3ab17..9ceae8fc 100644 --- a/poppler/GfxState.cc +++ b/poppler/GfxState.cc @@ -4918,7 +4918,11 @@ GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse(GfxResources *res, i if (typeA == 5 && nVerticesA > 0) { nRows = nVerticesA / vertsPerRow; nTrianglesA = (nRows - 1) * 2 * (vertsPerRow - 1); - trianglesA = (int (*)[3])gmallocn(nTrianglesA * 3, sizeof(int)); + trianglesA = (int (*)[3])gmallocn_checkoverflow(nTrianglesA * 3, sizeof(int)); + if (unlikely(!trianglesA)) { + gfree(verticesA); + return nullptr; + } k = 0; for (i = 0; i < nRows - 1; ++i) { for (j = 0; j < vertsPerRow - 1; ++j) { commit fee13e935e4c9eaadff434436eaceeb13afcfc13 Author: Oliver Sander <[email protected]> Date: Fri Mar 23 22:24:42 2018 +0100 Implement Type3 font support for ArthurOutputDev diff --git a/qt5/src/ArthurOutputDev.cc b/qt5/src/ArthurOutputDev.cc index b6620617..17da8f29 100644 --- a/qt5/src/ArthurOutputDev.cc +++ b/qt5/src/ArthurOutputDev.cc @@ -51,6 +51,9 @@ #include "FontEncodingTables.h" #include <fofi/FoFiTrueType.h> #include "ArthurOutputDev.h" +#include "Page.h" +#include "Gfx.h" +#include "PDFDoc.h" #include <QtCore/QtDebug> #include <QRawFont> @@ -87,6 +90,86 @@ private: #endif +class ArthurType3Font +{ +public: + + ArthurType3Font(PDFDoc* doc, Gfx8BitFont* font); + + const QPicture& getGlyph(int gid) const; + +private: + PDFDoc* m_doc; + Gfx8BitFont* m_font; + + mutable std::vector<std::unique_ptr<QPicture> > glyphs; + +public: + std::vector<int> codeToGID; +}; + +ArthurType3Font::ArthurType3Font(PDFDoc* doc, Gfx8BitFont* font) +: m_doc(doc), m_font(font) +{ + char *name; + const Dict* charProcs = font->getCharProcs(); + + // Storage for the rendered glyphs + glyphs.resize(charProcs->getLength()); + + // Compute the code-to-GID map + char **enc = font->getEncoding(); + + codeToGID.resize(256); + + for (int i = 0; i < 256; ++i) { + codeToGID[i] = 0; + if (charProcs && (name = enc[i])) { + for (int j = 0; j < charProcs->getLength(); j++) { + if (strcmp(name, charProcs->getKey(j)) == 0) { + codeToGID[i] = j; + } + } + } + } +} + +const QPicture& ArthurType3Font::getGlyph(int gid) const +{ + if (!glyphs[gid]) { + + // Glyph has not been rendered before: render it now + + // Smallest box that contains all the glyphs from this font + const double* fontBBox = m_font->getFontBBox(); + PDFRectangle box(fontBBox[0], fontBBox[1], fontBBox[2], fontBBox[3]); + + Dict* resDict = m_font->getResources(); + + QPainter glyphPainter; + glyphs[gid] = std::unique_ptr<QPicture>(new QPicture); + glyphPainter.begin(glyphs[gid].get()); + std::unique_ptr<ArthurOutputDev> output_dev(new ArthurOutputDev(&glyphPainter)); + + std::unique_ptr<Gfx> gfx(new Gfx(m_doc, output_dev.get(), resDict, + &box, // pagebox + nullptr)); // cropBox + + output_dev->startDoc(m_doc); + + output_dev->startPage (1, gfx->getState(), gfx->getXRef()); + + const Dict* charProcs = m_font->getCharProcs(); + Object charProc = charProcs->getVal(gid); + gfx->display(&charProc); + + glyphPainter.end(); + } + + return *glyphs[gid]; +} + + //------------------------------------------------------------------------ // ArthurOutputDev //------------------------------------------------------------------------ @@ -107,8 +190,9 @@ ArthurOutputDev::~ArthurOutputDev() #endif } -void ArthurOutputDev::startDoc(XRef *xrefA) { - xref = xrefA; +void ArthurOutputDev::startDoc(PDFDoc* doc) { + xref = doc->getXRef(); + m_doc = doc; #ifdef HAVE_SPLASH delete m_fontEngine; @@ -134,6 +218,7 @@ void ArthurOutputDev::saveState(GfxState *state) m_currentPenStack.push(m_currentPen); m_currentBrushStack.push(m_currentBrush); m_rawFontStack.push(m_rawFont); + m_type3FontStack.push(m_currentType3Font); m_codeToGIDStack.push(m_codeToGID); m_painter.top()->save(); @@ -147,6 +232,8 @@ void ArthurOutputDev::restoreState(GfxState *state) m_codeToGIDStack.pop(); m_rawFont = m_rawFontStack.top(); m_rawFontStack.pop(); + m_currentType3Font = m_type3FontStack.top(); + m_type3FontStack.pop(); m_currentBrush = m_currentBrushStack.top(); m_currentBrushStack.pop(); m_currentPen = m_currentPenStack.top(); @@ -362,8 +449,30 @@ void ArthurOutputDev::updateFont(GfxState *state) return; } - // is the font in the cache? + // The key to look in the font caches ArthurFontID fontID = {*gfxFont->getID(), state->getFontSize()}; + + // Current font is a type3 font + if (gfxFont->getType() == fontType3) + { + auto cacheEntry = m_type3FontCache.find(fontID); + + if (cacheEntry!=m_type3FontCache.end()) { + + // Take the font from the cache + m_currentType3Font = cacheEntry->second.get(); + + } else { + + m_currentType3Font = new ArthurType3Font(m_doc, (Gfx8BitFont*)gfxFont); + m_type3FontCache.insert(std::make_pair(fontID,std::unique_ptr<ArthurType3Font>(m_currentType3Font))); + + } + + return; + } + + // Non-type3: is the font in the cache? auto cacheEntry = m_rawFontCache.find(fontID); if (cacheEntry!=m_rawFontCache.end()) { @@ -818,6 +927,52 @@ void ArthurOutputDev::drawChar(GfxState *state, double x, double y, double originX, double originY, CharCode code, int nBytes, Unicode *u, int uLen) { + // First handle type3 fonts + GfxFont *gfxFont = state->getFont(); + + GfxFontType fontType = gfxFont->getType(); + if (fontType == fontType3) { + + ///////////////////////////////////////////////////////////////////// + // Draw the QPicture that contains the glyph onto the page + ///////////////////////////////////////////////////////////////////// + + // Store the QPainter state; we need to modify it temporarily + m_painter.top()->save(); + + // Make the glyph position the coordinate origin -- that's our center of scaling + m_painter.top()->translate(QPointF(x-originX, y-originY)); + + const double* mat = gfxFont->getFontMatrix(); + QTransform fontMatrix(mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]); + + // Scale with the font size + fontMatrix.scale(state->getFontSize(), state->getFontSize()); + m_painter.top()->setTransform(fontMatrix,true); + + // Apply the text matrix on top + const double *textMat = state->getTextMat(); + + QTransform textTransform(textMat[0] * state->getHorizScaling(), + textMat[1] * state->getHorizScaling(), + textMat[2], + textMat[3], + 0, + 0); + + m_painter.top()->setTransform(textTransform,true); + + // Actually draw the glyph + int gid = m_currentType3Font->codeToGID[code]; + m_painter.top()->drawPicture(QPointF(0,0), m_currentType3Font->getGlyph(gid)); + + // Restore transformation + m_painter.top()->restore(); + + return; + } + + // check for invisible text -- this is used by Acrobat Capture int render = state->getRender(); if (render == 3 || !m_rawFont) { @@ -825,11 +980,6 @@ void ArthurOutputDev::drawChar(GfxState *state, double x, double y, return; } - // Don't do anything for type3 fonts -- they are not yet supported - if (state->getFont()->getType() == fontType3) { - return; - } - if (!(render & 1)) { quint32 glyphIndex = (m_codeToGID) ? m_codeToGID[code] : code; @@ -889,17 +1039,6 @@ void ArthurOutputDev::drawChar(GfxState *state, double x, double y, } } -GBool ArthurOutputDev::beginType3Char(GfxState *state, double x, double y, - double dx, double dy, - CharCode code, Unicode *u, int uLen) -{ - return gFalse; -} - -void ArthurOutputDev::endType3Char(GfxState *state) -{ -} - void ArthurOutputDev::type3D0(GfxState *state, double wx, double wy) { } diff --git a/qt5/src/ArthurOutputDev.h b/qt5/src/ArthurOutputDev.h index 0e68ac99..6d20fb7b 100644 --- a/qt5/src/ArthurOutputDev.h +++ b/qt5/src/ArthurOutputDev.h @@ -45,11 +45,14 @@ #include <QtGui/QPainter> class GfxState; +class PDFDoc; class SplashFontEngine; class QRawFont; +class ArthurType3Font; + //------------------------------------------------------------------------ // ArthurOutputDev - Qt 5 QPainter renderer //------------------------------------------------------------------------ @@ -143,10 +146,6 @@ public: double dx, double dy, double originX, double originY, CharCode code, int nBytes, Unicode *u, int uLen) override; - GBool beginType3Char(GfxState *state, double x, double y, - double dx, double dy, - CharCode code, Unicode *u, int uLen) override; - void endType3Char(GfxState *state) override; void endTextObject(GfxState *state) override; //----- image drawing @@ -182,8 +181,8 @@ public: //----- special access // Called to indicate that a new PDF document has been loaded. - void startDoc(XRef *xrefA); - + void startDoc(PDFDoc* doc); + GBool isReverseVideo() { return gFalse; } private: @@ -211,12 +210,16 @@ private: GBool m_needFontUpdate; // set when the font needs to be updated SplashFontEngine *m_fontEngine; + PDFDoc* m_doc; XRef *xref; // xref table for current document // The current font in use QRawFont* m_rawFont; std::stack<QRawFont*> m_rawFontStack; + ArthurType3Font* m_currentType3Font; + std::stack<ArthurType3Font*> m_type3FontStack; + // Identify a font by its 'Ref' and its font size struct ArthurFontID { @@ -232,6 +235,7 @@ private: // Cache all fonts std::map<ArthurFontID,std::unique_ptr<QRawFont> > m_rawFontCache; + std::map<ArthurFontID,std::unique_ptr<ArthurType3Font> > m_type3FontCache; // The table that maps character codes to glyph indexes int* m_codeToGID; diff --git a/qt5/src/poppler-page.cc b/qt5/src/poppler-page.cc index 28ee1cd8..48dbe8ff 100644 --- a/qt5/src/poppler-page.cc +++ b/qt5/src/poppler-page.cc @@ -17,7 +17,7 @@ * Copyright (C) 2015 William Bader <[email protected]> * Copyright (C) 2016 Arseniy Lartsev <[email protected]> * Copyright (C) 2016, Hanno Meyer-Thurow <[email protected]> - * Copyright (C) 2017, Oliver Sander <[email protected]> + * Copyright (C) 2017, 2018, Oliver Sander <[email protected]> * Copyright (C) 2017 Adrian Johnson <[email protected]> * Copyright (C) 2017, 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, <[email protected]>. Work sponsored by the LiMux project of the city of Munich * @@ -456,7 +456,7 @@ static bool renderToArthur(QImageDumpingArthurOutputDev *arthur_output, QPainter painter->setRenderHint(QPainter::TextAntialiasing); painter->translate(x == -1 ? 0 : -x, y == -1 ? 0 : -y); - arthur_output->startDoc(page->parentDoc->doc->getXRef()); + arthur_output->startDoc(page->parentDoc->doc); const GBool hideAnnotations = page->parentDoc->m_hints & Document::HideAnnotations; commit 79c588912f41aa6ee81ea058e7e649199a252f90 Author: Oliver Sander <[email protected]> Date: Sun Mar 25 21:38:27 2018 +0200 Do not make ArthurOutputDev::startPage fill the page with white diff --git a/qt5/src/ArthurOutputDev.cc b/qt5/src/ArthurOutputDev.cc index 67485a2e..b6620617 100644 --- a/qt5/src/ArthurOutputDev.cc +++ b/qt5/src/ArthurOutputDev.cc @@ -124,18 +124,7 @@ void ArthurOutputDev::startDoc(XRef *xrefA) { } void ArthurOutputDev::startPage(int pageNum, GfxState *state, XRef *) -{ - // fill page with white background. - int w = static_cast<int>(state->getPageWidth()); - int h = static_cast<int>(state->getPageHeight()); - QColor fillColour(Qt::white); - QBrush fill(fillColour); - m_painter.top()->save(); - m_painter.top()->setPen(fillColour); - m_painter.top()->setBrush(fill); - m_painter.top()->drawRect(0, 0, w, h); - m_painter.top()->restore(); -} +{} void ArthurOutputDev::endPage() { } _______________________________________________ poppler mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/poppler
