[poppler] 3 commits - poppler/GfxState.cc qt5/src

Albert Astals Cid aacid at kemper.freedesktop.org
Tue Apr 10 22:33:16 UTC 2018


 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 <aacid at kde.org>
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 <oliver.sander at tu-dresden.de>
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 <williambader at hotmail.com>
  * Copyright (C) 2016 Arseniy Lartsev <arseniy at alumni.chalmers.se>
  * Copyright (C) 2016, Hanno Meyer-Thurow <h.mth at web.de>
- * Copyright (C) 2017, Oliver Sander <oliver.sander at tu-dresden.de>
+ * Copyright (C) 2017, 2018, Oliver Sander <oliver.sander at tu-dresden.de>
  * Copyright (C) 2017 Adrian Johnson <ajohnson at redneon.com>
  * Copyright (C) 2017, 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, <info at kdab.com>. 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 <oliver.sander at tu-dresden.de>
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() {
 }


More information about the poppler mailing list