[poppler] Branch 'qt5' - poppler/ArthurOutputDev.cc poppler/ArthurOutputDev.h poppler/Makefile.am qt4/src qt5/src

Albert Astals Cid aacid at kemper.freedesktop.org
Tue Jun 18 11:51:20 PDT 2013


 poppler/ArthurOutputDev.cc    |  816 ------------------------------------------
 poppler/ArthurOutputDev.h     |  170 --------
 poppler/Makefile.am           |   23 -
 qt4/src/ArthurOutputDev.cc    |  816 ++++++++++++++++++++++++++++++++++++++++++
 qt4/src/ArthurOutputDev.h     |  170 ++++++++
 qt4/src/CMakeLists.txt        |    2 
 qt4/src/Makefile.am           |    5 
 qt5/src/ArthurOutputDev.cc    |  816 ++++++++++++++++++++++++++++++++++++++++++
 qt5/src/ArthurOutputDev.h     |  170 ++++++++
 qt5/src/CMakeLists.txt        |    2 
 qt5/src/Makefile.am           |    5 
 qt5/src/poppler-optcontent.cc |    2 
 12 files changed, 1983 insertions(+), 1014 deletions(-)

New commits:
commit 1adb1ab7aee026e227d25716a4b7be22b19b5b84
Author: Albert Astals Cid <aacid at kde.org>
Date:   Tue Jun 18 20:50:49 2013 +0200

    Make it build with autotools

diff --git a/poppler/ArthurOutputDev.cc b/poppler/ArthurOutputDev.cc
deleted file mode 100644
index 5d57e93..0000000
--- a/poppler/ArthurOutputDev.cc
+++ /dev/null
@@ -1,816 +0,0 @@
-//========================================================================
-//
-// ArthurOutputDev.cc
-//
-// Copyright 2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-//========================================================================
-//
-// Modified under the Poppler project - http://poppler.freedesktop.org
-//
-// All changes made under the Poppler project to this file are licensed
-// under GPL version 2 or later
-//
-// Copyright (C) 2005 Brad Hards <bradh at frogmouth.net>
-// Copyright (C) 2005-2009, 2011, 2012 Albert Astals Cid <aacid at kde.org>
-// Copyright (C) 2008, 2010 Pino Toscano <pino at kde.org>
-// Copyright (C) 2009, 2011 Carlos Garcia Campos <carlosgc at gnome.org>
-// Copyright (C) 2009 Petr Gajdos <pgajdos at novell.com>
-// Copyright (C) 2010 Matthias Fauconneau <matthias.fauconneau at gmail.com>
-// Copyright (C) 2011 Andreas Hartmetz <ahartmetz at gmail.com>
-// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
-//
-// To see a description of the changes please see the Changelog file that
-// came with your tarball or type make ChangeLog if you are building from git
-//
-//========================================================================
-
-#include <config.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <string.h>
-#include <math.h>
-
-#include "goo/gfile.h"
-#include "GlobalParams.h"
-#include "Error.h"
-#include "Object.h"
-#include "GfxState.h"
-#include "GfxFont.h"
-#include "Link.h"
-#include "FontEncodingTables.h"
-#include <fofi/FoFiTrueType.h>
-#include "ArthurOutputDev.h"
-
-#include <QtCore/QtDebug>
-#include <QtGui/QPainterPath>
-//------------------------------------------------------------------------
-
-#ifdef HAVE_SPLASH
-#include "splash/SplashFontFileID.h"
-#include "splash/SplashFontFile.h"
-#include "splash/SplashFontEngine.h"
-#include "splash/SplashFont.h"
-#include "splash/SplashMath.h"
-#include "splash/SplashPath.h"
-#include "splash/SplashGlyphBitmap.h"
-//------------------------------------------------------------------------
-// SplashOutFontFileID
-//------------------------------------------------------------------------
-
-class SplashOutFontFileID: public SplashFontFileID {
-public:
-
-  SplashOutFontFileID(Ref *rA) { r = *rA; }
-
-  ~SplashOutFontFileID() {}
-
-  GBool matches(SplashFontFileID *id) {
-    return ((SplashOutFontFileID *)id)->r.num == r.num &&
-           ((SplashOutFontFileID *)id)->r.gen == r.gen;
-  }
-
-private:
-
-  Ref r;
-};
-
-#endif
-
-//------------------------------------------------------------------------
-// ArthurOutputDev
-//------------------------------------------------------------------------
-
-ArthurOutputDev::ArthurOutputDev(QPainter *painter):
-  m_painter(painter),
-  m_fontHinting(NoHinting)
-{
-  m_currentBrush = QBrush(Qt::SolidPattern);
-  m_fontEngine = 0;
-  m_font = 0;
-}
-
-ArthurOutputDev::~ArthurOutputDev()
-{
-#ifdef HAVE_SPLASH
-  delete m_fontEngine;
-#endif
-}
-
-void ArthurOutputDev::startDoc(XRef *xrefA) {
-  xref = xrefA;
-#ifdef HAVE_SPLASH
-  delete m_fontEngine;
-
-  const bool isHintingEnabled = m_fontHinting != NoHinting;
-  const bool isSlightHinting = m_fontHinting == SlightHinting;
-
-  m_fontEngine = new SplashFontEngine(
-#if HAVE_T1LIB_H
-  globalParams->getEnableT1lib(),
-#endif
-#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
-  globalParams->getEnableFreeType(),
-  isHintingEnabled,
-  isSlightHinting,
-#endif
-  m_painter->testRenderHint(QPainter::TextAntialiasing));
-#endif
-}
-
-void ArthurOutputDev::startPage(int pageNum, GfxState *state, XRef *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->save();
-  m_painter->setPen(fillColour);
-  m_painter->setBrush(fill);
-  m_painter->drawRect(0, 0, w, h);
-  m_painter->restore();
-}
-
-void ArthurOutputDev::endPage() {
-}
-
-void ArthurOutputDev::saveState(GfxState *state)
-{
-  m_painter->save();
-}
-
-void ArthurOutputDev::restoreState(GfxState *state)
-{
-  m_painter->restore();
-}
-
-void ArthurOutputDev::updateAll(GfxState *state)
-{
-  OutputDev::updateAll(state);
-  m_needFontUpdate = gTrue;
-}
-
-// This looks wrong - why aren't adjusting the matrix?
-void ArthurOutputDev::updateCTM(GfxState *state, double m11, double m12,
-				double m21, double m22,
-				double m31, double m32)
-{
-  updateLineDash(state);
-  updateLineJoin(state);
-  updateLineCap(state);
-  updateLineWidth(state);
-}
-
-void ArthurOutputDev::updateLineDash(GfxState *state)
-{
-  double *dashPattern;
-  int dashLength;
-  double dashStart;
-  state->getLineDash(&dashPattern, &dashLength, &dashStart);
-  QVector<qreal> pattern(dashLength);
-  for (int i = 0; i < dashLength; ++i) {
-    pattern[i] = dashPattern[i];
-  }
-  m_currentPen.setDashPattern(pattern);
-  m_currentPen.setDashOffset(dashStart);
-  m_painter->setPen(m_currentPen);
-}
-
-void ArthurOutputDev::updateFlatness(GfxState *state)
-{
-  // qDebug() << "updateFlatness";
-}
-
-void ArthurOutputDev::updateLineJoin(GfxState *state)
-{
-  switch (state->getLineJoin()) {
-  case 0:
-    m_currentPen.setJoinStyle(Qt::MiterJoin);
-    break;
-  case 1:
-    m_currentPen.setJoinStyle(Qt::RoundJoin);
-    break;
-  case 2:
-    m_currentPen.setJoinStyle(Qt::BevelJoin);
-    break;
-  }
-  m_painter->setPen(m_currentPen);
-}
-
-void ArthurOutputDev::updateLineCap(GfxState *state)
-{
-  switch (state->getLineCap()) {
-  case 0:
-    m_currentPen.setCapStyle(Qt::FlatCap);
-    break;
-  case 1:
-    m_currentPen.setCapStyle(Qt::RoundCap);
-    break;
-  case 2:
-    m_currentPen.setCapStyle(Qt::SquareCap);
-    break;
-  }
-  m_painter->setPen(m_currentPen);
-}
-
-void ArthurOutputDev::updateMiterLimit(GfxState *state)
-{
-  m_currentPen.setMiterLimit(state->getMiterLimit());
-  m_painter->setPen(m_currentPen);
-}
-
-void ArthurOutputDev::updateLineWidth(GfxState *state)
-{
-  m_currentPen.setWidthF(state->getLineWidth());
-  m_painter->setPen(m_currentPen);
-}
-
-void ArthurOutputDev::updateFillColor(GfxState *state)
-{
-  GfxRGB rgb;
-  QColor brushColour = m_currentBrush.color();
-  state->getFillRGB(&rgb);
-  brushColour.setRgbF(colToDbl(rgb.r), colToDbl(rgb.g), colToDbl(rgb.b), brushColour.alphaF());
-  m_currentBrush.setColor(brushColour);
-}
-
-void ArthurOutputDev::updateStrokeColor(GfxState *state)
-{
-  GfxRGB rgb;
-  QColor penColour = m_currentPen.color();
-  state->getStrokeRGB(&rgb);
-  penColour.setRgbF(colToDbl(rgb.r), colToDbl(rgb.g), colToDbl(rgb.b), penColour.alphaF());
-  m_currentPen.setColor(penColour);
-  m_painter->setPen(m_currentPen);
-}
-
-void ArthurOutputDev::updateFillOpacity(GfxState *state)
-{
-  QColor brushColour= m_currentBrush.color();
-  brushColour.setAlphaF(state->getFillOpacity());
-  m_currentBrush.setColor(brushColour);
-}
-
-void ArthurOutputDev::updateStrokeOpacity(GfxState *state)
-{
-  QColor penColour= m_currentPen.color();
-  penColour.setAlphaF(state->getStrokeOpacity());
-  m_currentPen.setColor(penColour);
-  m_painter->setPen(m_currentPen);
-}
-
-void ArthurOutputDev::updateFont(GfxState *state)
-{
-#ifdef HAVE_SPLASH
-  GfxFont *gfxFont;
-  GfxFontLoc *fontLoc;
-  GfxFontType fontType;
-  SplashOutFontFileID *id;
-  SplashFontFile *fontFile;
-  SplashFontSrc *fontsrc = NULL;
-  FoFiTrueType *ff;
-  Object refObj, strObj;
-  GooString *fileName;
-  char *tmpBuf;
-  int tmpBufLen;
-  int *codeToGID;
-  double *textMat;
-  double m11, m12, m21, m22, fontSize;
-  SplashCoord mat[4];
-  int n;
-  int faceIndex = 0;
-  SplashCoord matrix[6];
-
-  m_needFontUpdate = false;
-  m_font = NULL;
-  fileName = NULL;
-  tmpBuf = NULL;
-  fontLoc = NULL;
-
-  if (!(gfxFont = state->getFont())) {
-    goto err1;
-  }
-  fontType = gfxFont->getType();
-  if (fontType == fontType3) {
-    goto err1;
-  }
-
-  // check the font file cache
-  id = new SplashOutFontFileID(gfxFont->getID());
-  if ((fontFile = m_fontEngine->getFontFile(id))) {
-    delete id;
-
-  } else {
-
-    if (!(fontLoc = gfxFont->locateFont(xref, gFalse))) {
-      error(errSyntaxError, -1, "Couldn't find a font for '{0:s}'",
-	    gfxFont->getName() ? gfxFont->getName()->getCString()
-	                       : "(unnamed)");
-      goto err2;
-    }
-
-    // embedded font
-    if (fontLoc->locType == gfxFontLocEmbedded) {
-      // if there is an embedded font, read it to memory
-      tmpBuf = gfxFont->readEmbFontFile(xref, &tmpBufLen);
-      if (! tmpBuf)
-	goto err2;
-
-    // external font
-    } else { // gfxFontLocExternal
-      fileName = fontLoc->path;
-      fontType = fontLoc->fontType;
-    }
-
-    fontsrc = new SplashFontSrc;
-    if (fileName)
-      fontsrc->setFile(fileName, gFalse);
-    else
-      fontsrc->setBuf(tmpBuf, tmpBufLen, gTrue);
-    
-    // load the font file
-    switch (fontType) {
-    case fontType1:
-      if (!(fontFile = m_fontEngine->loadType1Font(
-			   id,
-			   fontsrc,
-			   (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) {
-	error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
-	      gfxFont->getName() ? gfxFont->getName()->getCString()
-	                         : "(unnamed)");
-	goto err2;
-      }
-      break;
-    case fontType1C:
-      if (!(fontFile = m_fontEngine->loadType1CFont(
-			   id,
-			   fontsrc,
-			   (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) {
-	error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
-	      gfxFont->getName() ? gfxFont->getName()->getCString()
-	                         : "(unnamed)");
-	goto err2;
-      }
-      break;
-    case fontType1COT:
-      if (!(fontFile = m_fontEngine->loadOpenTypeT1CFont(
-			   id,
-			   fontsrc,
-			   (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) {
-	error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
-	      gfxFont->getName() ? gfxFont->getName()->getCString()
-	                         : "(unnamed)");
-	goto err2;
-      }
-      break;
-    case fontTrueType:
-    case fontTrueTypeOT:
-	if (fileName)
-	 ff = FoFiTrueType::load(fileName->getCString());
-	else
-	ff = FoFiTrueType::make(tmpBuf, tmpBufLen);
-      if (ff) {
-	codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff);
-	n = 256;
-	delete ff;
-      } else {
-	codeToGID = NULL;
-	n = 0;
-      }
-      if (!(fontFile = m_fontEngine->loadTrueTypeFont(
-			   id,
-			   fontsrc,
-			   codeToGID, n))) {
-	error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
-	      gfxFont->getName() ? gfxFont->getName()->getCString()
-	                         : "(unnamed)");
-	goto err2;
-      }
-      break;
-    case fontCIDType0:
-    case fontCIDType0C:
-      if (!(fontFile = m_fontEngine->loadCIDFont(
-			   id,
-			   fontsrc))) {
-	error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
-	      gfxFont->getName() ? gfxFont->getName()->getCString()
-	                         : "(unnamed)");
-	goto err2;
-      }
-      break;
-    case fontCIDType0COT:
-      if (((GfxCIDFont *)gfxFont)->getCIDToGID()) {
-	n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen();
-	codeToGID = (int *)gmallocn(n, sizeof(int));
-	memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(),
-	       n * sizeof(int));
-      } else {
-	codeToGID = NULL;
-	n = 0;
-      }      
-      if (!(fontFile = m_fontEngine->loadOpenTypeCFFFont(
-			   id,
-			   fontsrc,
-			   codeToGID, n))) {
-	error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
-	      gfxFont->getName() ? gfxFont->getName()->getCString()
-	                         : "(unnamed)");
-	goto err2;
-      }
-      break;
-    case fontCIDType2:
-    case fontCIDType2OT:
-      codeToGID = NULL;
-      n = 0;
-      if (((GfxCIDFont *)gfxFont)->getCIDToGID()) {
-	n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen();
-	if (n) {
-	  codeToGID = (int *)gmallocn(n, sizeof(int));
-	  memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(),
-		  n * sizeof(Gushort));
-	}
-      } else {
-	if (fileName)
-	  ff = FoFiTrueType::load(fileName->getCString());
-	else
-	  ff = FoFiTrueType::make(tmpBuf, tmpBufLen);
-	if (! ff)
-	  goto err2;
-	codeToGID = ((GfxCIDFont *)gfxFont)->getCodeToGIDMap(ff, &n);
-	delete ff;
-      }
-      if (!(fontFile = m_fontEngine->loadTrueTypeFont(
-			   id,
-			   fontsrc,
-			   codeToGID, n, faceIndex))) {
-	error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
-	      gfxFont->getName() ? gfxFont->getName()->getCString()
-	                         : "(unnamed)");
-	goto err2;
-      }
-      break;
-    default:
-      // this shouldn't happen
-      goto err2;
-    }
-  }
-
-  // get the font matrix
-  textMat = state->getTextMat();
-  fontSize = state->getFontSize();
-  m11 = textMat[0] * fontSize * state->getHorizScaling();
-  m12 = textMat[1] * fontSize * state->getHorizScaling();
-  m21 = textMat[2] * fontSize;
-  m22 = textMat[3] * fontSize;
-
-  {
-  QMatrix painterMatrix = m_painter->worldMatrix();
-  matrix[0] = painterMatrix.m11();
-  matrix[1] = painterMatrix.m12();
-  matrix[2] = painterMatrix.m21();
-  matrix[3] = painterMatrix.m22();
-  matrix[4] = painterMatrix.dx();
-  matrix[5] = painterMatrix.dy();
-  }
-
-  // create the scaled font
-  mat[0] = m11;  mat[1] = -m12;
-  mat[2] = m21;  mat[3] = -m22;
-  m_font = m_fontEngine->getFont(fontFile, mat, matrix);
-
-  delete fontLoc;
-  if (fontsrc && !fontsrc->isFile)
-      fontsrc->unref();
-  return;
-
- err2:
-  delete id;
-  delete fontLoc;
- err1:
-  if (fontsrc && !fontsrc->isFile)
-      fontsrc->unref();
-  return;
-#endif
-}
-
-static QPainterPath convertPath(GfxState *state, GfxPath *path, Qt::FillRule fillRule)
-{
-  GfxSubpath *subpath;
-  double x1, y1, x2, y2, x3, y3;
-  int i, j;
-
-  QPainterPath qPath;
-  qPath.setFillRule(fillRule);
-  for (i = 0; i < path->getNumSubpaths(); ++i) {
-    subpath = path->getSubpath(i);
-    if (subpath->getNumPoints() > 0) {
-      state->transform(subpath->getX(0), subpath->getY(0), &x1, &y1);
-      qPath.moveTo(x1, y1);
-      j = 1;
-      while (j < subpath->getNumPoints()) {
-	if (subpath->getCurve(j)) {
-	  state->transform(subpath->getX(j), subpath->getY(j), &x1, &y1);
-	  state->transform(subpath->getX(j+1), subpath->getY(j+1), &x2, &y2);
-	  state->transform(subpath->getX(j+2), subpath->getY(j+2), &x3, &y3);
-	  qPath.cubicTo( x1, y1, x2, y2, x3, y3);
-	  j += 3;
-	} else {
-	  state->transform(subpath->getX(j), subpath->getY(j), &x1, &y1);
-	  qPath.lineTo(x1, y1);
-	  ++j;
-	}
-      }
-      if (subpath->isClosed()) {
-	qPath.closeSubpath();
-      }
-    }
-  }
-  return qPath;
-}
-
-void ArthurOutputDev::stroke(GfxState *state)
-{
-  m_painter->strokePath( convertPath( state, state->getPath(), Qt::OddEvenFill ), m_currentPen );
-}
-
-void ArthurOutputDev::fill(GfxState *state)
-{
-  m_painter->fillPath( convertPath( state, state->getPath(), Qt::WindingFill ), m_currentBrush );
-}
-
-void ArthurOutputDev::eoFill(GfxState *state)
-{
-  m_painter->fillPath( convertPath( state, state->getPath(), Qt::OddEvenFill ), m_currentBrush );
-}
-
-void ArthurOutputDev::clip(GfxState *state)
-{
-  m_painter->setClipPath(convertPath( state, state->getPath(), Qt::WindingFill ) );
-}
-
-void ArthurOutputDev::eoClip(GfxState *state)
-{
-  m_painter->setClipPath(convertPath( state, state->getPath(), Qt::OddEvenFill ) );
-}
-
-void ArthurOutputDev::drawChar(GfxState *state, double x, double y,
-			       double dx, double dy,
-			       double originX, double originY,
-			       CharCode code, int nBytes, Unicode *u, int uLen) {
-#ifdef HAVE_SPLASH
-  double x1, y1;
-  double x2, y2;
-//   SplashPath *path;
-  int render;
-
-  if (m_needFontUpdate) {
-    updateFont(state);
-  }
-  if (!m_font) {
-    return;
-  }
-
-  // check for invisible text -- this is used by Acrobat Capture
-  render = state->getRender();
-  if (render == 3) {
-    return;
-  }
-
-  x -= originX;
-  y -= originY;
-
-  // fill
-  if (!(render & 1)) {
-    SplashPath * fontPath;
-    fontPath = m_font->getGlyphPath(code);
-    if (fontPath) {
-      QPainterPath qPath;
-      qPath.setFillRule(Qt::WindingFill);
-      for (int i = 0; i < fontPath->length; ++i) {
-        if (fontPath->flags[i] & splashPathFirst) {
-            state->transform(fontPath->pts[i].x+x, -fontPath->pts[i].y+y, &x1, &y1);
-            qPath.moveTo(x1,y1);
-        } else if (fontPath->flags[i] & splashPathCurve) {
-            state->transform(fontPath->pts[i].x+x, -fontPath->pts[i].y+y, &x1, &y1);
-            state->transform(fontPath->pts[i+1].x+x, -fontPath->pts[i+1].y+y, &x2, &y2);
-            qPath.quadTo(x1,y1,x2,y2);
-            ++i;
-        }
-        // FIXME fix this
-        // 	else if (fontPath->flags[i] & splashPathArcCW) {
-        // 	  qDebug() << "Need to implement arc";
-        // 	}
-        else {
-            state->transform(fontPath->pts[i].x+x, -fontPath->pts[i].y+y, &x1, &y1);
-            qPath.lineTo(x1,y1);
-        }
-        if (fontPath->flags[i] & splashPathLast) {
-            qPath.closeSubpath();
-        }
-      }
-      GfxRGB rgb;
-      QColor brushColour = m_currentBrush.color();
-      state->getFillRGB(&rgb);
-      brushColour.setRgbF(colToDbl(rgb.r), colToDbl(rgb.g), colToDbl(rgb.b), state->getFillOpacity());
-      m_painter->setBrush(brushColour);
-      QColor penColour = m_currentPen.color();
-      state->getStrokeRGB(&rgb);
-      penColour.setRgbF(colToDbl(rgb.r), colToDbl(rgb.g), colToDbl(rgb.b), state->getStrokeOpacity());
-      m_painter->setPen(penColour);
-      m_painter->drawPath( qPath );
-      delete fontPath;
-    }
-  }
-
-  // stroke
-  if ((render & 3) == 1 || (render & 3) == 2) {
-    qDebug() << "no stroke";
-    /*
-    if ((path = m_font->getGlyphPath(code))) {
-      path->offset((SplashCoord)x1, (SplashCoord)y1);
-      splash->stroke(path);
-      delete path;
-    }
-    */
-  }
-
-  // clip
-  if (render & 4) {
-    qDebug() << "no clip";
-    /*
-    path = m_font->getGlyphPath(code);
-    path->offset((SplashCoord)x1, (SplashCoord)y1);
-    if (textClipPath) {
-      textClipPath->append(path);
-      delete path;
-    } else {
-      textClipPath = path;
-    }
-    */
-  }
-#endif
-}
-
-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)
-{
-}
-
-void ArthurOutputDev::type3D1(GfxState *state, double wx, double wy,
-			      double llx, double lly, double urx, double ury)
-{
-}
-
-void ArthurOutputDev::endTextObject(GfxState *state)
-{
-}
-
-
-void ArthurOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
-				    int width, int height, GBool invert,
-				    GBool interpolate, GBool inlineImg)
-{
-  qDebug() << "drawImageMask";
-#if 0
-  unsigned char *buffer;
-  unsigned char *dest;
-  cairo_surface_t *image;
-  cairo_pattern_t *pattern;
-  int x, y;
-  ImageStream *imgStr;
-  Guchar *pix;
-  double *ctm;
-  cairo_matrix_t matrix;
-  int invert_bit;
-  int row_stride;
-
-  row_stride = (width + 3) & ~3;
-  buffer = (unsigned char *) malloc (height * row_stride);
-  if (buffer == NULL) {
-    error(-1, "Unable to allocate memory for image.");
-    return;
-  }
-
-  /* TODO: Do we want to cache these? */
-  imgStr = new ImageStream(str, width, 1, 1);
-  imgStr->reset();
-
-  invert_bit = invert ? 1 : 0;
-
-  for (y = 0; y < height; y++) {
-    pix = imgStr->getLine();
-    dest = buffer + y * row_stride;
-    for (x = 0; x < width; x++) {
-
-      if (pix[x] ^ invert_bit)
-	*dest++ = 0;
-      else
-	*dest++ = 255;
-    }
-  }
-
-  image = cairo_image_surface_create_for_data (buffer, CAIRO_FORMAT_A8,
-					  width, height, row_stride);
-  if (image == NULL)
-    return;
-  pattern = cairo_pattern_create_for_surface (image);
-  if (pattern == NULL)
-    return;
-
-  ctm = state->getCTM();
-  LOG (printf ("drawImageMask %dx%d, matrix: %f, %f, %f, %f, %f, %f\n",
-	       width, height, ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]));
-  matrix.xx = ctm[0] / width;
-  matrix.xy = -ctm[2] / height;
-  matrix.yx = ctm[1] / width;
-  matrix.yy = -ctm[3] / height;
-  matrix.x0 = ctm[2] + ctm[4];
-  matrix.y0 = ctm[3] + ctm[5];
-  cairo_matrix_invert (&matrix);
-  cairo_pattern_set_matrix (pattern, &matrix);
-
-  cairo_pattern_set_filter (pattern, CAIRO_FILTER_BEST);
-  /* FIXME: Doesn't the image mask support any colorspace? */
-  cairo_set_source_rgb (cairo, fill_color.r, fill_color.g, fill_color.b);
-  cairo_mask (cairo, pattern);
-
-  cairo_pattern_destroy (pattern);
-  cairo_surface_destroy (image);
-  free (buffer);
-  imgStr->close ();
-  delete imgStr;
-#endif
-}
-
-//TODO: lots more work here.
-void ArthurOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
-				int width, int height,
-				GfxImageColorMap *colorMap,
-				GBool interpolate, int *maskColors, GBool inlineImg)
-{
-  unsigned int *data;
-  unsigned int *line;
-  int x, y;
-  ImageStream *imgStr;
-  Guchar *pix;
-  int i;
-  double *ctm;
-  QMatrix matrix;
-  QImage image;
-  int stride;
-  
-  /* TODO: Do we want to cache these? */
-  imgStr = new ImageStream(str, width,
-			   colorMap->getNumPixelComps(),
-			   colorMap->getBits());
-  imgStr->reset();
-  
-  image = QImage(width, height, QImage::Format_ARGB32);
-  data = (unsigned int *)image.bits();
-  stride = image.bytesPerLine()/4;
-  for (y = 0; y < height; y++) {
-    pix = imgStr->getLine();
-    line = data+y*stride;
-    colorMap->getRGBLine(pix, line, width);
-
-    if (maskColors) {
-      for (x = 0; x < width; x++) {
-        for (i = 0; i < colorMap->getNumPixelComps(); ++i) {
-            if (pix[i] < maskColors[2*i] * 255||
-                pix[i] > maskColors[2*i+1] * 255) {
-                *line = *line | 0xff000000;
-                break;
-            }
-        }
-        pix += colorMap->getNumPixelComps();
-        line++;
-      }
-    } else {
-      for (x = 0; x < width; x++) { *line = *line | 0xff000000; line++; }
-    }
-  }
-
-  ctm = state->getCTM();
-  matrix.setMatrix(ctm[0] / width, ctm[1] / width, -ctm[2] / height, -ctm[3] / height, ctm[2] + ctm[4], ctm[3] + ctm[5]);
-
-  m_painter->setMatrix(matrix, true);
-  m_painter->drawImage( QPoint(0,0), image );
-  delete imgStr;
-
-}
diff --git a/poppler/ArthurOutputDev.h b/poppler/ArthurOutputDev.h
deleted file mode 100644
index 9d5e867..0000000
--- a/poppler/ArthurOutputDev.h
+++ /dev/null
@@ -1,170 +0,0 @@
-//========================================================================
-//
-// ArthurOutputDev.h
-//
-// Copyright 2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-//========================================================================
-//
-// Modified under the Poppler project - http://poppler.freedesktop.org
-//
-// All changes made under the Poppler project to this file are licensed
-// under GPL version 2 or later
-//
-// Copyright (C) 2005 Brad Hards <bradh at frogmouth.net>
-// Copyright (C) 2005 Albert Astals Cid <aacid at kde.org>
-// Copyright (C) 2009, 2011 Carlos Garcia Campos <carlosgc at gnome.org>
-// Copyright (C) 2010 Pino Toscano <pino at kde.org>
-// Copyright (C) 2011 Andreas Hartmetz <ahartmetz at gmail.com>
-// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
-//
-// To see a description of the changes please see the Changelog file that
-// came with your tarball or type make ChangeLog if you are building from git
-//
-//========================================================================
-
-#ifndef ARTHUROUTPUTDEV_H
-#define ARTHUROUTPUTDEV_H
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "goo/gtypes.h"
-#include "OutputDev.h"
-#include "GfxState.h"
-
-#include <QtGui/QPainter>
-
-class GfxState;
-class GfxPath;
-class Gfx8BitFont;
-struct GfxRGB;
-
-class SplashFont;
-class SplashFontEngine;
-struct SplashGlyphBitmap;
-
-//------------------------------------------------------------------------
-// ArthurOutputDev - Qt 4 QPainter renderer
-//------------------------------------------------------------------------
-
-class ArthurOutputDev: public OutputDev {
-public:
-  /**
-   * Describes how fonts are distorted (aka hinted) to fit the pixel grid.
-   * More hinting means sharper edges and less adherence to the true letter shapes.
-   */
-  enum FontHinting {
-    NoHinting = 0, ///< Font shapes are left unchanged
-    SlightHinting, ///< Font shapes are distorted vertically only
-    FullHinting ///< Font shapes are distorted horizontally and vertically
-  };
-
-  // Constructor.
-  ArthurOutputDev(QPainter *painter );
-
-  // Destructor.
-  virtual ~ArthurOutputDev();
-
-  void setFontHinting(FontHinting hinting) { m_fontHinting = hinting; }
-
-  //----- get info about output device
-
-  // Does this device use upside-down coordinates?
-  // (Upside-down means (0,0) is the top left corner of the page.)
-  virtual GBool upsideDown() { return gTrue; }
-
-  // Does this device use drawChar() or drawString()?
-  virtual GBool useDrawChar() { return gTrue; }
-
-  // Does this device use beginType3Char/endType3Char?  Otherwise,
-  // text in Type 3 fonts will be drawn with drawChar/drawString.
-  virtual GBool interpretType3Chars() { return gTrue; }
-
-  //----- initialization and control
-
-  // Start a page.
-  virtual void startPage(int pageNum, GfxState *state, XRef *xref);
-
-  // End a page.
-  virtual void endPage();
-
-  //----- save/restore graphics state
-  virtual void saveState(GfxState *state);
-  virtual void restoreState(GfxState *state);
-
-  //----- update graphics state
-  virtual void updateAll(GfxState *state);
-  virtual void updateCTM(GfxState *state, double m11, double m12,
-			 double m21, double m22, double m31, double m32);
-  virtual void updateLineDash(GfxState *state);
-  virtual void updateFlatness(GfxState *state);
-  virtual void updateLineJoin(GfxState *state);
-  virtual void updateLineCap(GfxState *state);
-  virtual void updateMiterLimit(GfxState *state);
-  virtual void updateLineWidth(GfxState *state);
-  virtual void updateFillColor(GfxState *state);
-  virtual void updateStrokeColor(GfxState *state);
-  virtual void updateFillOpacity(GfxState *state);
-  virtual void updateStrokeOpacity(GfxState *state);
-
-  //----- update text state
-  virtual void updateFont(GfxState *state);
-
-  //----- path painting
-  virtual void stroke(GfxState *state);
-  virtual void fill(GfxState *state);
-  virtual void eoFill(GfxState *state);
-
-  //----- path clipping
-  virtual void clip(GfxState *state);
-  virtual void eoClip(GfxState *state);
-
-  //----- text drawing
-  //   virtual void drawString(GfxState *state, GooString *s);
-  virtual void drawChar(GfxState *state, double x, double y,
-			double dx, double dy,
-			double originX, double originY,
-			CharCode code, int nBytes, Unicode *u, int uLen);
-  virtual GBool beginType3Char(GfxState *state, double x, double y,
-			       double dx, double dy,
-			       CharCode code, Unicode *u, int uLen);
-  virtual void endType3Char(GfxState *state);
-  virtual void endTextObject(GfxState *state);
-
-  //----- image drawing
-  virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
-			     int width, int height, GBool invert,
-			     GBool interpolate, GBool inlineImg);
-  virtual void drawImage(GfxState *state, Object *ref, Stream *str,
-			 int width, int height, GfxImageColorMap *colorMap,
-			 GBool interpolate, int *maskColors, GBool inlineImg);
-
-  //----- Type 3 font operators
-  virtual void type3D0(GfxState *state, double wx, double wy);
-  virtual void type3D1(GfxState *state, double wx, double wy,
-		       double llx, double lly, double urx, double ury);
-
-  //----- special access
-
-  // Called to indicate that a new PDF document has been loaded.
-  void startDoc(XRef *xrefA);
- 
-  GBool isReverseVideo() { return gFalse; }
-  
-private:
-  QPainter *m_painter;
-  FontHinting m_fontHinting;
-  QFont m_currentFont;
-  QPen m_currentPen;
-  QBrush m_currentBrush;
-  GBool m_needFontUpdate;		// set when the font needs to be updated
-  SplashFontEngine *m_fontEngine;
-  SplashFont *m_font;		// current font
-  XRef *xref;			// xref table for current document
-};
-
-#endif
diff --git a/poppler/Makefile.am b/poppler/Makefile.am
index 8786e12..db6b34e 100644
--- a/poppler/Makefile.am
+++ b/poppler/Makefile.am
@@ -15,24 +15,6 @@ splash_libs =					\
 
 endif
 
-if BUILD_POPPLER_QT4
-
-poppler_arthur = libpoppler-arthur.la
-
-libpoppler_arthur_la_SOURCES =			\
-	ArthurOutputDev.h			\
-	ArthurOutputDev.cc
-
-arthur_includes =				\
-	$(POPPLER_QT4_CFLAGS)
-
-arthur_libs =					\
-	$(POPPLER_QT4_LIBS)
-
-endif
-
-
-
 if BUILD_CAIRO_OUTPUT
 
 poppler_cairo = libpoppler-cairo.la
@@ -144,7 +126,6 @@ INCLUDES =					\
 	$(cms_includes)				\
 	$(splash_includes)			\
 	$(cairo_includes)			\
-	$(arthur_includes)			\
 	$(libjpeg_includes)			\
 	$(libtiff_includes)			\
 	$(libjpeg2000_includes)			\
@@ -155,8 +136,7 @@ INCLUDES =					\
 
 lib_LTLIBRARIES = libpoppler.la
 
-noinst_LTLIBRARIES = $(poppler_cairo)		\
-	$(poppler_arthur)
+noinst_LTLIBRARIES = $(poppler_cairo)
 
 CFLAGS+=$(PTHREAD_CFLAGS)
 CXXFLAGS+=$(PTHREAD_CFLAGS)
@@ -262,7 +242,6 @@ endif
 libpoppler_la_SOURCES =		\
 	$(splash_sources)	\
 	$(cairo_sources)	\
-	$(arthur_sources)	\
 	$(libjpeg_sources)	\
 	$(zlib_sources)		\
 	$(libjpeg2000_sources)	\
diff --git a/qt4/src/ArthurOutputDev.cc b/qt4/src/ArthurOutputDev.cc
new file mode 100644
index 0000000..5d57e93
--- /dev/null
+++ b/qt4/src/ArthurOutputDev.cc
@@ -0,0 +1,816 @@
+//========================================================================
+//
+// ArthurOutputDev.cc
+//
+// Copyright 2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+//========================================================================
+//
+// Modified under the Poppler project - http://poppler.freedesktop.org
+//
+// All changes made under the Poppler project to this file are licensed
+// under GPL version 2 or later
+//
+// Copyright (C) 2005 Brad Hards <bradh at frogmouth.net>
+// Copyright (C) 2005-2009, 2011, 2012 Albert Astals Cid <aacid at kde.org>
+// Copyright (C) 2008, 2010 Pino Toscano <pino at kde.org>
+// Copyright (C) 2009, 2011 Carlos Garcia Campos <carlosgc at gnome.org>
+// Copyright (C) 2009 Petr Gajdos <pgajdos at novell.com>
+// Copyright (C) 2010 Matthias Fauconneau <matthias.fauconneau at gmail.com>
+// Copyright (C) 2011 Andreas Hartmetz <ahartmetz at gmail.com>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
+//
+// To see a description of the changes please see the Changelog file that
+// came with your tarball or type make ChangeLog if you are building from git
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <string.h>
+#include <math.h>
+
+#include "goo/gfile.h"
+#include "GlobalParams.h"
+#include "Error.h"
+#include "Object.h"
+#include "GfxState.h"
+#include "GfxFont.h"
+#include "Link.h"
+#include "FontEncodingTables.h"
+#include <fofi/FoFiTrueType.h>
+#include "ArthurOutputDev.h"
+
+#include <QtCore/QtDebug>
+#include <QtGui/QPainterPath>
+//------------------------------------------------------------------------
+
+#ifdef HAVE_SPLASH
+#include "splash/SplashFontFileID.h"
+#include "splash/SplashFontFile.h"
+#include "splash/SplashFontEngine.h"
+#include "splash/SplashFont.h"
+#include "splash/SplashMath.h"
+#include "splash/SplashPath.h"
+#include "splash/SplashGlyphBitmap.h"
+//------------------------------------------------------------------------
+// SplashOutFontFileID
+//------------------------------------------------------------------------
+
+class SplashOutFontFileID: public SplashFontFileID {
+public:
+
+  SplashOutFontFileID(Ref *rA) { r = *rA; }
+
+  ~SplashOutFontFileID() {}
+
+  GBool matches(SplashFontFileID *id) {
+    return ((SplashOutFontFileID *)id)->r.num == r.num &&
+           ((SplashOutFontFileID *)id)->r.gen == r.gen;
+  }
+
+private:
+
+  Ref r;
+};
+
+#endif
+
+//------------------------------------------------------------------------
+// ArthurOutputDev
+//------------------------------------------------------------------------
+
+ArthurOutputDev::ArthurOutputDev(QPainter *painter):
+  m_painter(painter),
+  m_fontHinting(NoHinting)
+{
+  m_currentBrush = QBrush(Qt::SolidPattern);
+  m_fontEngine = 0;
+  m_font = 0;
+}
+
+ArthurOutputDev::~ArthurOutputDev()
+{
+#ifdef HAVE_SPLASH
+  delete m_fontEngine;
+#endif
+}
+
+void ArthurOutputDev::startDoc(XRef *xrefA) {
+  xref = xrefA;
+#ifdef HAVE_SPLASH
+  delete m_fontEngine;
+
+  const bool isHintingEnabled = m_fontHinting != NoHinting;
+  const bool isSlightHinting = m_fontHinting == SlightHinting;
+
+  m_fontEngine = new SplashFontEngine(
+#if HAVE_T1LIB_H
+  globalParams->getEnableT1lib(),
+#endif
+#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+  globalParams->getEnableFreeType(),
+  isHintingEnabled,
+  isSlightHinting,
+#endif
+  m_painter->testRenderHint(QPainter::TextAntialiasing));
+#endif
+}
+
+void ArthurOutputDev::startPage(int pageNum, GfxState *state, XRef *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->save();
+  m_painter->setPen(fillColour);
+  m_painter->setBrush(fill);
+  m_painter->drawRect(0, 0, w, h);
+  m_painter->restore();
+}
+
+void ArthurOutputDev::endPage() {
+}
+
+void ArthurOutputDev::saveState(GfxState *state)
+{
+  m_painter->save();
+}
+
+void ArthurOutputDev::restoreState(GfxState *state)
+{
+  m_painter->restore();
+}
+
+void ArthurOutputDev::updateAll(GfxState *state)
+{
+  OutputDev::updateAll(state);
+  m_needFontUpdate = gTrue;
+}
+
+// This looks wrong - why aren't adjusting the matrix?
+void ArthurOutputDev::updateCTM(GfxState *state, double m11, double m12,
+				double m21, double m22,
+				double m31, double m32)
+{
+  updateLineDash(state);
+  updateLineJoin(state);
+  updateLineCap(state);
+  updateLineWidth(state);
+}
+
+void ArthurOutputDev::updateLineDash(GfxState *state)
+{
+  double *dashPattern;
+  int dashLength;
+  double dashStart;
+  state->getLineDash(&dashPattern, &dashLength, &dashStart);
+  QVector<qreal> pattern(dashLength);
+  for (int i = 0; i < dashLength; ++i) {
+    pattern[i] = dashPattern[i];
+  }
+  m_currentPen.setDashPattern(pattern);
+  m_currentPen.setDashOffset(dashStart);
+  m_painter->setPen(m_currentPen);
+}
+
+void ArthurOutputDev::updateFlatness(GfxState *state)
+{
+  // qDebug() << "updateFlatness";
+}
+
+void ArthurOutputDev::updateLineJoin(GfxState *state)
+{
+  switch (state->getLineJoin()) {
+  case 0:
+    m_currentPen.setJoinStyle(Qt::MiterJoin);
+    break;
+  case 1:
+    m_currentPen.setJoinStyle(Qt::RoundJoin);
+    break;
+  case 2:
+    m_currentPen.setJoinStyle(Qt::BevelJoin);
+    break;
+  }
+  m_painter->setPen(m_currentPen);
+}
+
+void ArthurOutputDev::updateLineCap(GfxState *state)
+{
+  switch (state->getLineCap()) {
+  case 0:
+    m_currentPen.setCapStyle(Qt::FlatCap);
+    break;
+  case 1:
+    m_currentPen.setCapStyle(Qt::RoundCap);
+    break;
+  case 2:
+    m_currentPen.setCapStyle(Qt::SquareCap);
+    break;
+  }
+  m_painter->setPen(m_currentPen);
+}
+
+void ArthurOutputDev::updateMiterLimit(GfxState *state)
+{
+  m_currentPen.setMiterLimit(state->getMiterLimit());
+  m_painter->setPen(m_currentPen);
+}
+
+void ArthurOutputDev::updateLineWidth(GfxState *state)
+{
+  m_currentPen.setWidthF(state->getLineWidth());
+  m_painter->setPen(m_currentPen);
+}
+
+void ArthurOutputDev::updateFillColor(GfxState *state)
+{
+  GfxRGB rgb;
+  QColor brushColour = m_currentBrush.color();
+  state->getFillRGB(&rgb);
+  brushColour.setRgbF(colToDbl(rgb.r), colToDbl(rgb.g), colToDbl(rgb.b), brushColour.alphaF());
+  m_currentBrush.setColor(brushColour);
+}
+
+void ArthurOutputDev::updateStrokeColor(GfxState *state)
+{
+  GfxRGB rgb;
+  QColor penColour = m_currentPen.color();
+  state->getStrokeRGB(&rgb);
+  penColour.setRgbF(colToDbl(rgb.r), colToDbl(rgb.g), colToDbl(rgb.b), penColour.alphaF());
+  m_currentPen.setColor(penColour);
+  m_painter->setPen(m_currentPen);
+}
+
+void ArthurOutputDev::updateFillOpacity(GfxState *state)
+{
+  QColor brushColour= m_currentBrush.color();
+  brushColour.setAlphaF(state->getFillOpacity());
+  m_currentBrush.setColor(brushColour);
+}
+
+void ArthurOutputDev::updateStrokeOpacity(GfxState *state)
+{
+  QColor penColour= m_currentPen.color();
+  penColour.setAlphaF(state->getStrokeOpacity());
+  m_currentPen.setColor(penColour);
+  m_painter->setPen(m_currentPen);
+}
+
+void ArthurOutputDev::updateFont(GfxState *state)
+{
+#ifdef HAVE_SPLASH
+  GfxFont *gfxFont;
+  GfxFontLoc *fontLoc;
+  GfxFontType fontType;
+  SplashOutFontFileID *id;
+  SplashFontFile *fontFile;
+  SplashFontSrc *fontsrc = NULL;
+  FoFiTrueType *ff;
+  Object refObj, strObj;
+  GooString *fileName;
+  char *tmpBuf;
+  int tmpBufLen;
+  int *codeToGID;
+  double *textMat;
+  double m11, m12, m21, m22, fontSize;
+  SplashCoord mat[4];
+  int n;
+  int faceIndex = 0;
+  SplashCoord matrix[6];
+
+  m_needFontUpdate = false;
+  m_font = NULL;
+  fileName = NULL;
+  tmpBuf = NULL;
+  fontLoc = NULL;
+
+  if (!(gfxFont = state->getFont())) {
+    goto err1;
+  }
+  fontType = gfxFont->getType();
+  if (fontType == fontType3) {
+    goto err1;
+  }
+
+  // check the font file cache
+  id = new SplashOutFontFileID(gfxFont->getID());
+  if ((fontFile = m_fontEngine->getFontFile(id))) {
+    delete id;
+
+  } else {
+
+    if (!(fontLoc = gfxFont->locateFont(xref, gFalse))) {
+      error(errSyntaxError, -1, "Couldn't find a font for '{0:s}'",
+	    gfxFont->getName() ? gfxFont->getName()->getCString()
+	                       : "(unnamed)");
+      goto err2;
+    }
+
+    // embedded font
+    if (fontLoc->locType == gfxFontLocEmbedded) {
+      // if there is an embedded font, read it to memory
+      tmpBuf = gfxFont->readEmbFontFile(xref, &tmpBufLen);
+      if (! tmpBuf)
+	goto err2;
+
+    // external font
+    } else { // gfxFontLocExternal
+      fileName = fontLoc->path;
+      fontType = fontLoc->fontType;
+    }
+
+    fontsrc = new SplashFontSrc;
+    if (fileName)
+      fontsrc->setFile(fileName, gFalse);
+    else
+      fontsrc->setBuf(tmpBuf, tmpBufLen, gTrue);
+    
+    // load the font file
+    switch (fontType) {
+    case fontType1:
+      if (!(fontFile = m_fontEngine->loadType1Font(
+			   id,
+			   fontsrc,
+			   (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) {
+	error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
+	      gfxFont->getName() ? gfxFont->getName()->getCString()
+	                         : "(unnamed)");
+	goto err2;
+      }
+      break;
+    case fontType1C:
+      if (!(fontFile = m_fontEngine->loadType1CFont(
+			   id,
+			   fontsrc,
+			   (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) {
+	error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
+	      gfxFont->getName() ? gfxFont->getName()->getCString()
+	                         : "(unnamed)");
+	goto err2;
+      }
+      break;
+    case fontType1COT:
+      if (!(fontFile = m_fontEngine->loadOpenTypeT1CFont(
+			   id,
+			   fontsrc,
+			   (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) {
+	error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
+	      gfxFont->getName() ? gfxFont->getName()->getCString()
+	                         : "(unnamed)");
+	goto err2;
+      }
+      break;
+    case fontTrueType:
+    case fontTrueTypeOT:
+	if (fileName)
+	 ff = FoFiTrueType::load(fileName->getCString());
+	else
+	ff = FoFiTrueType::make(tmpBuf, tmpBufLen);
+      if (ff) {
+	codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff);
+	n = 256;
+	delete ff;
+      } else {
+	codeToGID = NULL;
+	n = 0;
+      }
+      if (!(fontFile = m_fontEngine->loadTrueTypeFont(
+			   id,
+			   fontsrc,
+			   codeToGID, n))) {
+	error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
+	      gfxFont->getName() ? gfxFont->getName()->getCString()
+	                         : "(unnamed)");
+	goto err2;
+      }
+      break;
+    case fontCIDType0:
+    case fontCIDType0C:
+      if (!(fontFile = m_fontEngine->loadCIDFont(
+			   id,
+			   fontsrc))) {
+	error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
+	      gfxFont->getName() ? gfxFont->getName()->getCString()
+	                         : "(unnamed)");
+	goto err2;
+      }
+      break;
+    case fontCIDType0COT:
+      if (((GfxCIDFont *)gfxFont)->getCIDToGID()) {
+	n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen();
+	codeToGID = (int *)gmallocn(n, sizeof(int));
+	memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(),
+	       n * sizeof(int));
+      } else {
+	codeToGID = NULL;
+	n = 0;
+      }      
+      if (!(fontFile = m_fontEngine->loadOpenTypeCFFFont(
+			   id,
+			   fontsrc,
+			   codeToGID, n))) {
+	error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
+	      gfxFont->getName() ? gfxFont->getName()->getCString()
+	                         : "(unnamed)");
+	goto err2;
+      }
+      break;
+    case fontCIDType2:
+    case fontCIDType2OT:
+      codeToGID = NULL;
+      n = 0;
+      if (((GfxCIDFont *)gfxFont)->getCIDToGID()) {
+	n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen();
+	if (n) {
+	  codeToGID = (int *)gmallocn(n, sizeof(int));
+	  memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(),
+		  n * sizeof(Gushort));
+	}
+      } else {
+	if (fileName)
+	  ff = FoFiTrueType::load(fileName->getCString());
+	else
+	  ff = FoFiTrueType::make(tmpBuf, tmpBufLen);
+	if (! ff)
+	  goto err2;
+	codeToGID = ((GfxCIDFont *)gfxFont)->getCodeToGIDMap(ff, &n);
+	delete ff;
+      }
+      if (!(fontFile = m_fontEngine->loadTrueTypeFont(
+			   id,
+			   fontsrc,
+			   codeToGID, n, faceIndex))) {
+	error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
+	      gfxFont->getName() ? gfxFont->getName()->getCString()
+	                         : "(unnamed)");
+	goto err2;
+      }
+      break;
+    default:
+      // this shouldn't happen
+      goto err2;
+    }
+  }
+
+  // get the font matrix
+  textMat = state->getTextMat();
+  fontSize = state->getFontSize();
+  m11 = textMat[0] * fontSize * state->getHorizScaling();
+  m12 = textMat[1] * fontSize * state->getHorizScaling();
+  m21 = textMat[2] * fontSize;
+  m22 = textMat[3] * fontSize;
+
+  {
+  QMatrix painterMatrix = m_painter->worldMatrix();
+  matrix[0] = painterMatrix.m11();
+  matrix[1] = painterMatrix.m12();
+  matrix[2] = painterMatrix.m21();
+  matrix[3] = painterMatrix.m22();
+  matrix[4] = painterMatrix.dx();
+  matrix[5] = painterMatrix.dy();
+  }
+
+  // create the scaled font
+  mat[0] = m11;  mat[1] = -m12;
+  mat[2] = m21;  mat[3] = -m22;
+  m_font = m_fontEngine->getFont(fontFile, mat, matrix);
+
+  delete fontLoc;
+  if (fontsrc && !fontsrc->isFile)
+      fontsrc->unref();
+  return;
+
+ err2:
+  delete id;
+  delete fontLoc;
+ err1:
+  if (fontsrc && !fontsrc->isFile)
+      fontsrc->unref();
+  return;
+#endif
+}
+
+static QPainterPath convertPath(GfxState *state, GfxPath *path, Qt::FillRule fillRule)
+{
+  GfxSubpath *subpath;
+  double x1, y1, x2, y2, x3, y3;
+  int i, j;
+
+  QPainterPath qPath;
+  qPath.setFillRule(fillRule);
+  for (i = 0; i < path->getNumSubpaths(); ++i) {
+    subpath = path->getSubpath(i);
+    if (subpath->getNumPoints() > 0) {
+      state->transform(subpath->getX(0), subpath->getY(0), &x1, &y1);
+      qPath.moveTo(x1, y1);
+      j = 1;
+      while (j < subpath->getNumPoints()) {
+	if (subpath->getCurve(j)) {
+	  state->transform(subpath->getX(j), subpath->getY(j), &x1, &y1);
+	  state->transform(subpath->getX(j+1), subpath->getY(j+1), &x2, &y2);
+	  state->transform(subpath->getX(j+2), subpath->getY(j+2), &x3, &y3);
+	  qPath.cubicTo( x1, y1, x2, y2, x3, y3);
+	  j += 3;
+	} else {
+	  state->transform(subpath->getX(j), subpath->getY(j), &x1, &y1);
+	  qPath.lineTo(x1, y1);
+	  ++j;
+	}
+      }
+      if (subpath->isClosed()) {
+	qPath.closeSubpath();
+      }
+    }
+  }
+  return qPath;
+}
+
+void ArthurOutputDev::stroke(GfxState *state)
+{
+  m_painter->strokePath( convertPath( state, state->getPath(), Qt::OddEvenFill ), m_currentPen );
+}
+
+void ArthurOutputDev::fill(GfxState *state)
+{
+  m_painter->fillPath( convertPath( state, state->getPath(), Qt::WindingFill ), m_currentBrush );
+}
+
+void ArthurOutputDev::eoFill(GfxState *state)
+{
+  m_painter->fillPath( convertPath( state, state->getPath(), Qt::OddEvenFill ), m_currentBrush );
+}
+
+void ArthurOutputDev::clip(GfxState *state)
+{
+  m_painter->setClipPath(convertPath( state, state->getPath(), Qt::WindingFill ) );
+}
+
+void ArthurOutputDev::eoClip(GfxState *state)
+{
+  m_painter->setClipPath(convertPath( state, state->getPath(), Qt::OddEvenFill ) );
+}
+
+void ArthurOutputDev::drawChar(GfxState *state, double x, double y,
+			       double dx, double dy,
+			       double originX, double originY,
+			       CharCode code, int nBytes, Unicode *u, int uLen) {
+#ifdef HAVE_SPLASH
+  double x1, y1;
+  double x2, y2;
+//   SplashPath *path;
+  int render;
+
+  if (m_needFontUpdate) {
+    updateFont(state);
+  }
+  if (!m_font) {
+    return;
+  }
+
+  // check for invisible text -- this is used by Acrobat Capture
+  render = state->getRender();
+  if (render == 3) {
+    return;
+  }
+
+  x -= originX;
+  y -= originY;
+
+  // fill
+  if (!(render & 1)) {
+    SplashPath * fontPath;
+    fontPath = m_font->getGlyphPath(code);
+    if (fontPath) {
+      QPainterPath qPath;
+      qPath.setFillRule(Qt::WindingFill);
+      for (int i = 0; i < fontPath->length; ++i) {
+        if (fontPath->flags[i] & splashPathFirst) {
+            state->transform(fontPath->pts[i].x+x, -fontPath->pts[i].y+y, &x1, &y1);
+            qPath.moveTo(x1,y1);
+        } else if (fontPath->flags[i] & splashPathCurve) {
+            state->transform(fontPath->pts[i].x+x, -fontPath->pts[i].y+y, &x1, &y1);
+            state->transform(fontPath->pts[i+1].x+x, -fontPath->pts[i+1].y+y, &x2, &y2);
+            qPath.quadTo(x1,y1,x2,y2);
+            ++i;
+        }
+        // FIXME fix this
+        // 	else if (fontPath->flags[i] & splashPathArcCW) {
+        // 	  qDebug() << "Need to implement arc";
+        // 	}
+        else {
+            state->transform(fontPath->pts[i].x+x, -fontPath->pts[i].y+y, &x1, &y1);
+            qPath.lineTo(x1,y1);
+        }
+        if (fontPath->flags[i] & splashPathLast) {
+            qPath.closeSubpath();
+        }
+      }
+      GfxRGB rgb;
+      QColor brushColour = m_currentBrush.color();
+      state->getFillRGB(&rgb);
+      brushColour.setRgbF(colToDbl(rgb.r), colToDbl(rgb.g), colToDbl(rgb.b), state->getFillOpacity());
+      m_painter->setBrush(brushColour);
+      QColor penColour = m_currentPen.color();
+      state->getStrokeRGB(&rgb);
+      penColour.setRgbF(colToDbl(rgb.r), colToDbl(rgb.g), colToDbl(rgb.b), state->getStrokeOpacity());
+      m_painter->setPen(penColour);
+      m_painter->drawPath( qPath );
+      delete fontPath;
+    }
+  }
+
+  // stroke
+  if ((render & 3) == 1 || (render & 3) == 2) {
+    qDebug() << "no stroke";
+    /*
+    if ((path = m_font->getGlyphPath(code))) {
+      path->offset((SplashCoord)x1, (SplashCoord)y1);
+      splash->stroke(path);
+      delete path;
+    }
+    */
+  }
+
+  // clip
+  if (render & 4) {
+    qDebug() << "no clip";
+    /*
+    path = m_font->getGlyphPath(code);
+    path->offset((SplashCoord)x1, (SplashCoord)y1);
+    if (textClipPath) {
+      textClipPath->append(path);
+      delete path;
+    } else {
+      textClipPath = path;
+    }
+    */
+  }
+#endif
+}
+
+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)
+{
+}
+
+void ArthurOutputDev::type3D1(GfxState *state, double wx, double wy,
+			      double llx, double lly, double urx, double ury)
+{
+}
+
+void ArthurOutputDev::endTextObject(GfxState *state)
+{
+}
+
+
+void ArthurOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
+				    int width, int height, GBool invert,
+				    GBool interpolate, GBool inlineImg)
+{
+  qDebug() << "drawImageMask";
+#if 0
+  unsigned char *buffer;
+  unsigned char *dest;
+  cairo_surface_t *image;
+  cairo_pattern_t *pattern;
+  int x, y;
+  ImageStream *imgStr;
+  Guchar *pix;
+  double *ctm;
+  cairo_matrix_t matrix;
+  int invert_bit;
+  int row_stride;
+
+  row_stride = (width + 3) & ~3;
+  buffer = (unsigned char *) malloc (height * row_stride);
+  if (buffer == NULL) {
+    error(-1, "Unable to allocate memory for image.");
+    return;
+  }
+
+  /* TODO: Do we want to cache these? */
+  imgStr = new ImageStream(str, width, 1, 1);
+  imgStr->reset();
+
+  invert_bit = invert ? 1 : 0;
+
+  for (y = 0; y < height; y++) {
+    pix = imgStr->getLine();
+    dest = buffer + y * row_stride;
+    for (x = 0; x < width; x++) {
+
+      if (pix[x] ^ invert_bit)
+	*dest++ = 0;
+      else
+	*dest++ = 255;
+    }
+  }
+
+  image = cairo_image_surface_create_for_data (buffer, CAIRO_FORMAT_A8,
+					  width, height, row_stride);
+  if (image == NULL)
+    return;
+  pattern = cairo_pattern_create_for_surface (image);
+  if (pattern == NULL)
+    return;
+
+  ctm = state->getCTM();
+  LOG (printf ("drawImageMask %dx%d, matrix: %f, %f, %f, %f, %f, %f\n",
+	       width, height, ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]));
+  matrix.xx = ctm[0] / width;
+  matrix.xy = -ctm[2] / height;
+  matrix.yx = ctm[1] / width;
+  matrix.yy = -ctm[3] / height;
+  matrix.x0 = ctm[2] + ctm[4];
+  matrix.y0 = ctm[3] + ctm[5];
+  cairo_matrix_invert (&matrix);
+  cairo_pattern_set_matrix (pattern, &matrix);
+
+  cairo_pattern_set_filter (pattern, CAIRO_FILTER_BEST);
+  /* FIXME: Doesn't the image mask support any colorspace? */
+  cairo_set_source_rgb (cairo, fill_color.r, fill_color.g, fill_color.b);
+  cairo_mask (cairo, pattern);
+
+  cairo_pattern_destroy (pattern);
+  cairo_surface_destroy (image);
+  free (buffer);
+  imgStr->close ();
+  delete imgStr;
+#endif
+}
+
+//TODO: lots more work here.
+void ArthurOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
+				int width, int height,
+				GfxImageColorMap *colorMap,
+				GBool interpolate, int *maskColors, GBool inlineImg)
+{
+  unsigned int *data;
+  unsigned int *line;
+  int x, y;
+  ImageStream *imgStr;
+  Guchar *pix;
+  int i;
+  double *ctm;
+  QMatrix matrix;
+  QImage image;
+  int stride;
+  
+  /* TODO: Do we want to cache these? */
+  imgStr = new ImageStream(str, width,
+			   colorMap->getNumPixelComps(),
+			   colorMap->getBits());
+  imgStr->reset();
+  
+  image = QImage(width, height, QImage::Format_ARGB32);
+  data = (unsigned int *)image.bits();
+  stride = image.bytesPerLine()/4;
+  for (y = 0; y < height; y++) {
+    pix = imgStr->getLine();
+    line = data+y*stride;
+    colorMap->getRGBLine(pix, line, width);
+
+    if (maskColors) {
+      for (x = 0; x < width; x++) {
+        for (i = 0; i < colorMap->getNumPixelComps(); ++i) {
+            if (pix[i] < maskColors[2*i] * 255||
+                pix[i] > maskColors[2*i+1] * 255) {
+                *line = *line | 0xff000000;
+                break;
+            }
+        }
+        pix += colorMap->getNumPixelComps();
+        line++;
+      }
+    } else {
+      for (x = 0; x < width; x++) { *line = *line | 0xff000000; line++; }
+    }
+  }
+
+  ctm = state->getCTM();
+  matrix.setMatrix(ctm[0] / width, ctm[1] / width, -ctm[2] / height, -ctm[3] / height, ctm[2] + ctm[4], ctm[3] + ctm[5]);
+
+  m_painter->setMatrix(matrix, true);
+  m_painter->drawImage( QPoint(0,0), image );
+  delete imgStr;
+
+}
diff --git a/qt4/src/ArthurOutputDev.h b/qt4/src/ArthurOutputDev.h
new file mode 100644
index 0000000..9d5e867
--- /dev/null
+++ b/qt4/src/ArthurOutputDev.h
@@ -0,0 +1,170 @@
+//========================================================================
+//
+// ArthurOutputDev.h
+//
+// Copyright 2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+//========================================================================
+//
+// Modified under the Poppler project - http://poppler.freedesktop.org
+//
+// All changes made under the Poppler project to this file are licensed
+// under GPL version 2 or later
+//
+// Copyright (C) 2005 Brad Hards <bradh at frogmouth.net>
+// Copyright (C) 2005 Albert Astals Cid <aacid at kde.org>
+// Copyright (C) 2009, 2011 Carlos Garcia Campos <carlosgc at gnome.org>
+// Copyright (C) 2010 Pino Toscano <pino at kde.org>
+// Copyright (C) 2011 Andreas Hartmetz <ahartmetz at gmail.com>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
+//
+// To see a description of the changes please see the Changelog file that
+// came with your tarball or type make ChangeLog if you are building from git
+//
+//========================================================================
+
+#ifndef ARTHUROUTPUTDEV_H
+#define ARTHUROUTPUTDEV_H
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "goo/gtypes.h"
+#include "OutputDev.h"
+#include "GfxState.h"
+
+#include <QtGui/QPainter>
+
+class GfxState;
+class GfxPath;
+class Gfx8BitFont;
+struct GfxRGB;
+
+class SplashFont;
+class SplashFontEngine;
+struct SplashGlyphBitmap;
+
+//------------------------------------------------------------------------
+// ArthurOutputDev - Qt 4 QPainter renderer
+//------------------------------------------------------------------------
+
+class ArthurOutputDev: public OutputDev {
+public:
+  /**
+   * Describes how fonts are distorted (aka hinted) to fit the pixel grid.
+   * More hinting means sharper edges and less adherence to the true letter shapes.
+   */
+  enum FontHinting {
+    NoHinting = 0, ///< Font shapes are left unchanged
+    SlightHinting, ///< Font shapes are distorted vertically only
+    FullHinting ///< Font shapes are distorted horizontally and vertically
+  };
+
+  // Constructor.
+  ArthurOutputDev(QPainter *painter );
+
+  // Destructor.
+  virtual ~ArthurOutputDev();
+
+  void setFontHinting(FontHinting hinting) { m_fontHinting = hinting; }
+
+  //----- get info about output device
+
+  // Does this device use upside-down coordinates?
+  // (Upside-down means (0,0) is the top left corner of the page.)
+  virtual GBool upsideDown() { return gTrue; }
+
+  // Does this device use drawChar() or drawString()?
+  virtual GBool useDrawChar() { return gTrue; }
+
+  // Does this device use beginType3Char/endType3Char?  Otherwise,
+  // text in Type 3 fonts will be drawn with drawChar/drawString.
+  virtual GBool interpretType3Chars() { return gTrue; }
+
+  //----- initialization and control
+
+  // Start a page.
+  virtual void startPage(int pageNum, GfxState *state, XRef *xref);
+
+  // End a page.
+  virtual void endPage();
+
+  //----- save/restore graphics state
+  virtual void saveState(GfxState *state);
+  virtual void restoreState(GfxState *state);
+
+  //----- update graphics state
+  virtual void updateAll(GfxState *state);
+  virtual void updateCTM(GfxState *state, double m11, double m12,
+			 double m21, double m22, double m31, double m32);
+  virtual void updateLineDash(GfxState *state);
+  virtual void updateFlatness(GfxState *state);
+  virtual void updateLineJoin(GfxState *state);
+  virtual void updateLineCap(GfxState *state);
+  virtual void updateMiterLimit(GfxState *state);
+  virtual void updateLineWidth(GfxState *state);
+  virtual void updateFillColor(GfxState *state);
+  virtual void updateStrokeColor(GfxState *state);
+  virtual void updateFillOpacity(GfxState *state);
+  virtual void updateStrokeOpacity(GfxState *state);
+
+  //----- update text state
+  virtual void updateFont(GfxState *state);
+
+  //----- path painting
+  virtual void stroke(GfxState *state);
+  virtual void fill(GfxState *state);
+  virtual void eoFill(GfxState *state);
+
+  //----- path clipping
+  virtual void clip(GfxState *state);
+  virtual void eoClip(GfxState *state);
+
+  //----- text drawing
+  //   virtual void drawString(GfxState *state, GooString *s);
+  virtual void drawChar(GfxState *state, double x, double y,
+			double dx, double dy,
+			double originX, double originY,
+			CharCode code, int nBytes, Unicode *u, int uLen);
+  virtual GBool beginType3Char(GfxState *state, double x, double y,
+			       double dx, double dy,
+			       CharCode code, Unicode *u, int uLen);
+  virtual void endType3Char(GfxState *state);
+  virtual void endTextObject(GfxState *state);
+
+  //----- image drawing
+  virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
+			     int width, int height, GBool invert,
+			     GBool interpolate, GBool inlineImg);
+  virtual void drawImage(GfxState *state, Object *ref, Stream *str,
+			 int width, int height, GfxImageColorMap *colorMap,
+			 GBool interpolate, int *maskColors, GBool inlineImg);
+
+  //----- Type 3 font operators
+  virtual void type3D0(GfxState *state, double wx, double wy);
+  virtual void type3D1(GfxState *state, double wx, double wy,
+		       double llx, double lly, double urx, double ury);
+
+  //----- special access
+
+  // Called to indicate that a new PDF document has been loaded.
+  void startDoc(XRef *xrefA);
+ 
+  GBool isReverseVideo() { return gFalse; }
+  
+private:
+  QPainter *m_painter;
+  FontHinting m_fontHinting;
+  QFont m_currentFont;
+  QPen m_currentPen;
+  QBrush m_currentBrush;
+  GBool m_needFontUpdate;		// set when the font needs to be updated
+  SplashFontEngine *m_fontEngine;
+  SplashFont *m_font;		// current font
+  XRef *xref;			// xref table for current document
+};
+
+#endif
diff --git a/qt4/src/CMakeLists.txt b/qt4/src/CMakeLists.txt
index dff7aa6..59953ed 100644
--- a/qt4/src/CMakeLists.txt
+++ b/qt4/src/CMakeLists.txt
@@ -26,7 +26,7 @@ set(poppler_qt4_SRCS
   poppler-textbox.cc
   poppler-page-transition.cc
   poppler-media.cc
-  ${CMAKE_SOURCE_DIR}/poppler/ArthurOutputDev.cc
+  ArthurOutputDev.cc
 )
 qt4_automoc(${poppler_qt4_SRCS})
 add_library(poppler-qt4 SHARED ${poppler_qt4_SRCS})
diff --git a/qt4/src/Makefile.am b/qt4/src/Makefile.am
index efa0e14..13ab7ff 100644
--- a/qt4/src/Makefile.am
+++ b/qt4/src/Makefile.am
@@ -51,14 +51,15 @@ libpoppler_qt4_la_SOURCES =			\
 	poppler-export.h			\
 	poppler-private.h			\
 	poppler-page-transition-private.h	\
-	poppler-embeddedfile-private.h
+	poppler-embeddedfile-private.h		\
+	ArthurOutputDev.h			\
+	ArthurOutputDev.cc
 
 libpoppler_qt4_la_CXXFLAGS = 			\
 	-Dpoppler_qt4_EXPORTS
 
 libpoppler_qt4_la_LIBADD = 			\
 	$(top_builddir)/poppler/libpoppler.la	\
-	$(top_builddir)/poppler/libpoppler-arthur.la	\
 	$(POPPLER_QT4_LIBS)
 
 libpoppler_qt4_la_LDFLAGS = -version-info 7:0:3 @create_shared_lib@ @auto_import_flags@
diff --git a/qt5/src/ArthurOutputDev.cc b/qt5/src/ArthurOutputDev.cc
new file mode 100644
index 0000000..5d57e93
--- /dev/null
+++ b/qt5/src/ArthurOutputDev.cc
@@ -0,0 +1,816 @@
+//========================================================================
+//
+// ArthurOutputDev.cc
+//
+// Copyright 2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+//========================================================================
+//
+// Modified under the Poppler project - http://poppler.freedesktop.org
+//
+// All changes made under the Poppler project to this file are licensed
+// under GPL version 2 or later
+//
+// Copyright (C) 2005 Brad Hards <bradh at frogmouth.net>
+// Copyright (C) 2005-2009, 2011, 2012 Albert Astals Cid <aacid at kde.org>
+// Copyright (C) 2008, 2010 Pino Toscano <pino at kde.org>
+// Copyright (C) 2009, 2011 Carlos Garcia Campos <carlosgc at gnome.org>
+// Copyright (C) 2009 Petr Gajdos <pgajdos at novell.com>
+// Copyright (C) 2010 Matthias Fauconneau <matthias.fauconneau at gmail.com>
+// Copyright (C) 2011 Andreas Hartmetz <ahartmetz at gmail.com>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
+//
+// To see a description of the changes please see the Changelog file that
+// came with your tarball or type make ChangeLog if you are building from git
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <string.h>
+#include <math.h>
+
+#include "goo/gfile.h"
+#include "GlobalParams.h"
+#include "Error.h"
+#include "Object.h"
+#include "GfxState.h"
+#include "GfxFont.h"
+#include "Link.h"
+#include "FontEncodingTables.h"
+#include <fofi/FoFiTrueType.h>
+#include "ArthurOutputDev.h"
+
+#include <QtCore/QtDebug>
+#include <QtGui/QPainterPath>
+//------------------------------------------------------------------------
+
+#ifdef HAVE_SPLASH
+#include "splash/SplashFontFileID.h"
+#include "splash/SplashFontFile.h"
+#include "splash/SplashFontEngine.h"
+#include "splash/SplashFont.h"
+#include "splash/SplashMath.h"
+#include "splash/SplashPath.h"
+#include "splash/SplashGlyphBitmap.h"
+//------------------------------------------------------------------------
+// SplashOutFontFileID
+//------------------------------------------------------------------------
+
+class SplashOutFontFileID: public SplashFontFileID {
+public:
+
+  SplashOutFontFileID(Ref *rA) { r = *rA; }
+
+  ~SplashOutFontFileID() {}
+
+  GBool matches(SplashFontFileID *id) {
+    return ((SplashOutFontFileID *)id)->r.num == r.num &&
+           ((SplashOutFontFileID *)id)->r.gen == r.gen;
+  }
+
+private:
+
+  Ref r;
+};
+
+#endif
+
+//------------------------------------------------------------------------
+// ArthurOutputDev
+//------------------------------------------------------------------------
+
+ArthurOutputDev::ArthurOutputDev(QPainter *painter):
+  m_painter(painter),
+  m_fontHinting(NoHinting)
+{
+  m_currentBrush = QBrush(Qt::SolidPattern);
+  m_fontEngine = 0;
+  m_font = 0;
+}
+
+ArthurOutputDev::~ArthurOutputDev()
+{
+#ifdef HAVE_SPLASH
+  delete m_fontEngine;
+#endif
+}
+
+void ArthurOutputDev::startDoc(XRef *xrefA) {
+  xref = xrefA;
+#ifdef HAVE_SPLASH
+  delete m_fontEngine;
+
+  const bool isHintingEnabled = m_fontHinting != NoHinting;
+  const bool isSlightHinting = m_fontHinting == SlightHinting;
+
+  m_fontEngine = new SplashFontEngine(
+#if HAVE_T1LIB_H
+  globalParams->getEnableT1lib(),
+#endif
+#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+  globalParams->getEnableFreeType(),
+  isHintingEnabled,
+  isSlightHinting,
+#endif
+  m_painter->testRenderHint(QPainter::TextAntialiasing));
+#endif
+}
+
+void ArthurOutputDev::startPage(int pageNum, GfxState *state, XRef *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->save();
+  m_painter->setPen(fillColour);
+  m_painter->setBrush(fill);
+  m_painter->drawRect(0, 0, w, h);
+  m_painter->restore();
+}
+
+void ArthurOutputDev::endPage() {
+}
+
+void ArthurOutputDev::saveState(GfxState *state)
+{
+  m_painter->save();
+}
+
+void ArthurOutputDev::restoreState(GfxState *state)
+{
+  m_painter->restore();
+}
+
+void ArthurOutputDev::updateAll(GfxState *state)
+{
+  OutputDev::updateAll(state);
+  m_needFontUpdate = gTrue;
+}
+
+// This looks wrong - why aren't adjusting the matrix?
+void ArthurOutputDev::updateCTM(GfxState *state, double m11, double m12,
+				double m21, double m22,
+				double m31, double m32)
+{
+  updateLineDash(state);
+  updateLineJoin(state);
+  updateLineCap(state);
+  updateLineWidth(state);
+}
+
+void ArthurOutputDev::updateLineDash(GfxState *state)
+{
+  double *dashPattern;
+  int dashLength;
+  double dashStart;
+  state->getLineDash(&dashPattern, &dashLength, &dashStart);
+  QVector<qreal> pattern(dashLength);
+  for (int i = 0; i < dashLength; ++i) {
+    pattern[i] = dashPattern[i];
+  }
+  m_currentPen.setDashPattern(pattern);
+  m_currentPen.setDashOffset(dashStart);
+  m_painter->setPen(m_currentPen);
+}
+
+void ArthurOutputDev::updateFlatness(GfxState *state)
+{
+  // qDebug() << "updateFlatness";
+}
+
+void ArthurOutputDev::updateLineJoin(GfxState *state)
+{
+  switch (state->getLineJoin()) {
+  case 0:
+    m_currentPen.setJoinStyle(Qt::MiterJoin);
+    break;
+  case 1:
+    m_currentPen.setJoinStyle(Qt::RoundJoin);
+    break;
+  case 2:
+    m_currentPen.setJoinStyle(Qt::BevelJoin);
+    break;
+  }
+  m_painter->setPen(m_currentPen);
+}
+
+void ArthurOutputDev::updateLineCap(GfxState *state)
+{
+  switch (state->getLineCap()) {
+  case 0:
+    m_currentPen.setCapStyle(Qt::FlatCap);
+    break;
+  case 1:
+    m_currentPen.setCapStyle(Qt::RoundCap);
+    break;
+  case 2:
+    m_currentPen.setCapStyle(Qt::SquareCap);
+    break;
+  }
+  m_painter->setPen(m_currentPen);
+}
+
+void ArthurOutputDev::updateMiterLimit(GfxState *state)
+{
+  m_currentPen.setMiterLimit(state->getMiterLimit());
+  m_painter->setPen(m_currentPen);
+}
+
+void ArthurOutputDev::updateLineWidth(GfxState *state)
+{
+  m_currentPen.setWidthF(state->getLineWidth());
+  m_painter->setPen(m_currentPen);
+}
+
+void ArthurOutputDev::updateFillColor(GfxState *state)
+{
+  GfxRGB rgb;
+  QColor brushColour = m_currentBrush.color();
+  state->getFillRGB(&rgb);
+  brushColour.setRgbF(colToDbl(rgb.r), colToDbl(rgb.g), colToDbl(rgb.b), brushColour.alphaF());
+  m_currentBrush.setColor(brushColour);
+}
+
+void ArthurOutputDev::updateStrokeColor(GfxState *state)
+{
+  GfxRGB rgb;
+  QColor penColour = m_currentPen.color();
+  state->getStrokeRGB(&rgb);
+  penColour.setRgbF(colToDbl(rgb.r), colToDbl(rgb.g), colToDbl(rgb.b), penColour.alphaF());
+  m_currentPen.setColor(penColour);
+  m_painter->setPen(m_currentPen);
+}
+
+void ArthurOutputDev::updateFillOpacity(GfxState *state)
+{
+  QColor brushColour= m_currentBrush.color();
+  brushColour.setAlphaF(state->getFillOpacity());
+  m_currentBrush.setColor(brushColour);
+}
+
+void ArthurOutputDev::updateStrokeOpacity(GfxState *state)
+{
+  QColor penColour= m_currentPen.color();
+  penColour.setAlphaF(state->getStrokeOpacity());
+  m_currentPen.setColor(penColour);
+  m_painter->setPen(m_currentPen);
+}
+
+void ArthurOutputDev::updateFont(GfxState *state)
+{
+#ifdef HAVE_SPLASH
+  GfxFont *gfxFont;
+  GfxFontLoc *fontLoc;
+  GfxFontType fontType;
+  SplashOutFontFileID *id;
+  SplashFontFile *fontFile;
+  SplashFontSrc *fontsrc = NULL;
+  FoFiTrueType *ff;
+  Object refObj, strObj;
+  GooString *fileName;
+  char *tmpBuf;
+  int tmpBufLen;
+  int *codeToGID;
+  double *textMat;
+  double m11, m12, m21, m22, fontSize;
+  SplashCoord mat[4];
+  int n;
+  int faceIndex = 0;
+  SplashCoord matrix[6];
+
+  m_needFontUpdate = false;
+  m_font = NULL;
+  fileName = NULL;
+  tmpBuf = NULL;
+  fontLoc = NULL;
+
+  if (!(gfxFont = state->getFont())) {
+    goto err1;
+  }
+  fontType = gfxFont->getType();
+  if (fontType == fontType3) {
+    goto err1;
+  }
+
+  // check the font file cache
+  id = new SplashOutFontFileID(gfxFont->getID());
+  if ((fontFile = m_fontEngine->getFontFile(id))) {
+    delete id;
+
+  } else {
+
+    if (!(fontLoc = gfxFont->locateFont(xref, gFalse))) {
+      error(errSyntaxError, -1, "Couldn't find a font for '{0:s}'",
+	    gfxFont->getName() ? gfxFont->getName()->getCString()
+	                       : "(unnamed)");
+      goto err2;
+    }
+
+    // embedded font
+    if (fontLoc->locType == gfxFontLocEmbedded) {
+      // if there is an embedded font, read it to memory
+      tmpBuf = gfxFont->readEmbFontFile(xref, &tmpBufLen);
+      if (! tmpBuf)
+	goto err2;
+
+    // external font
+    } else { // gfxFontLocExternal
+      fileName = fontLoc->path;
+      fontType = fontLoc->fontType;
+    }
+
+    fontsrc = new SplashFontSrc;
+    if (fileName)
+      fontsrc->setFile(fileName, gFalse);
+    else
+      fontsrc->setBuf(tmpBuf, tmpBufLen, gTrue);
+    
+    // load the font file
+    switch (fontType) {
+    case fontType1:
+      if (!(fontFile = m_fontEngine->loadType1Font(
+			   id,
+			   fontsrc,
+			   (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) {
+	error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
+	      gfxFont->getName() ? gfxFont->getName()->getCString()
+	                         : "(unnamed)");
+	goto err2;
+      }
+      break;
+    case fontType1C:
+      if (!(fontFile = m_fontEngine->loadType1CFont(
+			   id,
+			   fontsrc,
+			   (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) {
+	error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
+	      gfxFont->getName() ? gfxFont->getName()->getCString()
+	                         : "(unnamed)");
+	goto err2;
+      }
+      break;
+    case fontType1COT:
+      if (!(fontFile = m_fontEngine->loadOpenTypeT1CFont(
+			   id,
+			   fontsrc,
+			   (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) {
+	error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
+	      gfxFont->getName() ? gfxFont->getName()->getCString()
+	                         : "(unnamed)");
+	goto err2;
+      }
+      break;
+    case fontTrueType:
+    case fontTrueTypeOT:
+	if (fileName)
+	 ff = FoFiTrueType::load(fileName->getCString());
+	else
+	ff = FoFiTrueType::make(tmpBuf, tmpBufLen);
+      if (ff) {
+	codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff);
+	n = 256;
+	delete ff;
+      } else {
+	codeToGID = NULL;
+	n = 0;
+      }
+      if (!(fontFile = m_fontEngine->loadTrueTypeFont(
+			   id,
+			   fontsrc,
+			   codeToGID, n))) {
+	error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
+	      gfxFont->getName() ? gfxFont->getName()->getCString()
+	                         : "(unnamed)");
+	goto err2;
+      }
+      break;
+    case fontCIDType0:
+    case fontCIDType0C:
+      if (!(fontFile = m_fontEngine->loadCIDFont(
+			   id,
+			   fontsrc))) {
+	error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
+	      gfxFont->getName() ? gfxFont->getName()->getCString()
+	                         : "(unnamed)");
+	goto err2;
+      }
+      break;
+    case fontCIDType0COT:
+      if (((GfxCIDFont *)gfxFont)->getCIDToGID()) {
+	n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen();
+	codeToGID = (int *)gmallocn(n, sizeof(int));
+	memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(),
+	       n * sizeof(int));
+      } else {
+	codeToGID = NULL;
+	n = 0;
+      }      
+      if (!(fontFile = m_fontEngine->loadOpenTypeCFFFont(
+			   id,
+			   fontsrc,
+			   codeToGID, n))) {
+	error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
+	      gfxFont->getName() ? gfxFont->getName()->getCString()
+	                         : "(unnamed)");
+	goto err2;
+      }
+      break;
+    case fontCIDType2:
+    case fontCIDType2OT:
+      codeToGID = NULL;
+      n = 0;
+      if (((GfxCIDFont *)gfxFont)->getCIDToGID()) {
+	n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen();
+	if (n) {
+	  codeToGID = (int *)gmallocn(n, sizeof(int));
+	  memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(),
+		  n * sizeof(Gushort));
+	}
+      } else {
+	if (fileName)
+	  ff = FoFiTrueType::load(fileName->getCString());
+	else
+	  ff = FoFiTrueType::make(tmpBuf, tmpBufLen);
+	if (! ff)
+	  goto err2;
+	codeToGID = ((GfxCIDFont *)gfxFont)->getCodeToGIDMap(ff, &n);
+	delete ff;
+      }
+      if (!(fontFile = m_fontEngine->loadTrueTypeFont(
+			   id,
+			   fontsrc,
+			   codeToGID, n, faceIndex))) {
+	error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
+	      gfxFont->getName() ? gfxFont->getName()->getCString()
+	                         : "(unnamed)");
+	goto err2;
+      }
+      break;
+    default:
+      // this shouldn't happen
+      goto err2;
+    }
+  }
+
+  // get the font matrix
+  textMat = state->getTextMat();
+  fontSize = state->getFontSize();
+  m11 = textMat[0] * fontSize * state->getHorizScaling();
+  m12 = textMat[1] * fontSize * state->getHorizScaling();
+  m21 = textMat[2] * fontSize;
+  m22 = textMat[3] * fontSize;
+
+  {
+  QMatrix painterMatrix = m_painter->worldMatrix();
+  matrix[0] = painterMatrix.m11();
+  matrix[1] = painterMatrix.m12();
+  matrix[2] = painterMatrix.m21();
+  matrix[3] = painterMatrix.m22();
+  matrix[4] = painterMatrix.dx();
+  matrix[5] = painterMatrix.dy();
+  }
+
+  // create the scaled font
+  mat[0] = m11;  mat[1] = -m12;
+  mat[2] = m21;  mat[3] = -m22;
+  m_font = m_fontEngine->getFont(fontFile, mat, matrix);
+
+  delete fontLoc;
+  if (fontsrc && !fontsrc->isFile)
+      fontsrc->unref();
+  return;
+
+ err2:
+  delete id;
+  delete fontLoc;
+ err1:
+  if (fontsrc && !fontsrc->isFile)
+      fontsrc->unref();
+  return;
+#endif
+}
+
+static QPainterPath convertPath(GfxState *state, GfxPath *path, Qt::FillRule fillRule)
+{
+  GfxSubpath *subpath;
+  double x1, y1, x2, y2, x3, y3;
+  int i, j;
+
+  QPainterPath qPath;
+  qPath.setFillRule(fillRule);
+  for (i = 0; i < path->getNumSubpaths(); ++i) {
+    subpath = path->getSubpath(i);
+    if (subpath->getNumPoints() > 0) {
+      state->transform(subpath->getX(0), subpath->getY(0), &x1, &y1);
+      qPath.moveTo(x1, y1);
+      j = 1;
+      while (j < subpath->getNumPoints()) {
+	if (subpath->getCurve(j)) {
+	  state->transform(subpath->getX(j), subpath->getY(j), &x1, &y1);
+	  state->transform(subpath->getX(j+1), subpath->getY(j+1), &x2, &y2);
+	  state->transform(subpath->getX(j+2), subpath->getY(j+2), &x3, &y3);
+	  qPath.cubicTo( x1, y1, x2, y2, x3, y3);
+	  j += 3;
+	} else {
+	  state->transform(subpath->getX(j), subpath->getY(j), &x1, &y1);
+	  qPath.lineTo(x1, y1);
+	  ++j;
+	}
+      }
+      if (subpath->isClosed()) {
+	qPath.closeSubpath();
+      }
+    }
+  }
+  return qPath;
+}
+
+void ArthurOutputDev::stroke(GfxState *state)
+{
+  m_painter->strokePath( convertPath( state, state->getPath(), Qt::OddEvenFill ), m_currentPen );
+}
+
+void ArthurOutputDev::fill(GfxState *state)
+{
+  m_painter->fillPath( convertPath( state, state->getPath(), Qt::WindingFill ), m_currentBrush );
+}
+
+void ArthurOutputDev::eoFill(GfxState *state)
+{
+  m_painter->fillPath( convertPath( state, state->getPath(), Qt::OddEvenFill ), m_currentBrush );
+}
+
+void ArthurOutputDev::clip(GfxState *state)
+{
+  m_painter->setClipPath(convertPath( state, state->getPath(), Qt::WindingFill ) );
+}
+
+void ArthurOutputDev::eoClip(GfxState *state)
+{
+  m_painter->setClipPath(convertPath( state, state->getPath(), Qt::OddEvenFill ) );
+}
+
+void ArthurOutputDev::drawChar(GfxState *state, double x, double y,
+			       double dx, double dy,
+			       double originX, double originY,
+			       CharCode code, int nBytes, Unicode *u, int uLen) {
+#ifdef HAVE_SPLASH
+  double x1, y1;
+  double x2, y2;
+//   SplashPath *path;
+  int render;
+
+  if (m_needFontUpdate) {
+    updateFont(state);
+  }
+  if (!m_font) {
+    return;
+  }
+
+  // check for invisible text -- this is used by Acrobat Capture
+  render = state->getRender();
+  if (render == 3) {
+    return;
+  }
+
+  x -= originX;
+  y -= originY;
+
+  // fill
+  if (!(render & 1)) {
+    SplashPath * fontPath;
+    fontPath = m_font->getGlyphPath(code);
+    if (fontPath) {
+      QPainterPath qPath;
+      qPath.setFillRule(Qt::WindingFill);
+      for (int i = 0; i < fontPath->length; ++i) {
+        if (fontPath->flags[i] & splashPathFirst) {
+            state->transform(fontPath->pts[i].x+x, -fontPath->pts[i].y+y, &x1, &y1);
+            qPath.moveTo(x1,y1);
+        } else if (fontPath->flags[i] & splashPathCurve) {
+            state->transform(fontPath->pts[i].x+x, -fontPath->pts[i].y+y, &x1, &y1);
+            state->transform(fontPath->pts[i+1].x+x, -fontPath->pts[i+1].y+y, &x2, &y2);
+            qPath.quadTo(x1,y1,x2,y2);
+            ++i;
+        }
+        // FIXME fix this
+        // 	else if (fontPath->flags[i] & splashPathArcCW) {
+        // 	  qDebug() << "Need to implement arc";
+        // 	}
+        else {
+            state->transform(fontPath->pts[i].x+x, -fontPath->pts[i].y+y, &x1, &y1);
+            qPath.lineTo(x1,y1);
+        }
+        if (fontPath->flags[i] & splashPathLast) {
+            qPath.closeSubpath();
+        }
+      }
+      GfxRGB rgb;
+      QColor brushColour = m_currentBrush.color();
+      state->getFillRGB(&rgb);
+      brushColour.setRgbF(colToDbl(rgb.r), colToDbl(rgb.g), colToDbl(rgb.b), state->getFillOpacity());
+      m_painter->setBrush(brushColour);
+      QColor penColour = m_currentPen.color();
+      state->getStrokeRGB(&rgb);
+      penColour.setRgbF(colToDbl(rgb.r), colToDbl(rgb.g), colToDbl(rgb.b), state->getStrokeOpacity());
+      m_painter->setPen(penColour);
+      m_painter->drawPath( qPath );
+      delete fontPath;
+    }
+  }
+
+  // stroke
+  if ((render & 3) == 1 || (render & 3) == 2) {
+    qDebug() << "no stroke";
+    /*
+    if ((path = m_font->getGlyphPath(code))) {
+      path->offset((SplashCoord)x1, (SplashCoord)y1);
+      splash->stroke(path);
+      delete path;
+    }
+    */
+  }
+
+  // clip
+  if (render & 4) {
+    qDebug() << "no clip";
+    /*
+    path = m_font->getGlyphPath(code);
+    path->offset((SplashCoord)x1, (SplashCoord)y1);
+    if (textClipPath) {
+      textClipPath->append(path);
+      delete path;
+    } else {
+      textClipPath = path;
+    }
+    */
+  }
+#endif
+}
+
+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)
+{
+}
+
+void ArthurOutputDev::type3D1(GfxState *state, double wx, double wy,
+			      double llx, double lly, double urx, double ury)
+{
+}
+
+void ArthurOutputDev::endTextObject(GfxState *state)
+{
+}
+
+
+void ArthurOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
+				    int width, int height, GBool invert,
+				    GBool interpolate, GBool inlineImg)
+{
+  qDebug() << "drawImageMask";
+#if 0
+  unsigned char *buffer;
+  unsigned char *dest;
+  cairo_surface_t *image;
+  cairo_pattern_t *pattern;
+  int x, y;
+  ImageStream *imgStr;
+  Guchar *pix;
+  double *ctm;
+  cairo_matrix_t matrix;
+  int invert_bit;
+  int row_stride;
+
+  row_stride = (width + 3) & ~3;
+  buffer = (unsigned char *) malloc (height * row_stride);
+  if (buffer == NULL) {
+    error(-1, "Unable to allocate memory for image.");
+    return;
+  }
+
+  /* TODO: Do we want to cache these? */
+  imgStr = new ImageStream(str, width, 1, 1);
+  imgStr->reset();
+
+  invert_bit = invert ? 1 : 0;
+
+  for (y = 0; y < height; y++) {
+    pix = imgStr->getLine();
+    dest = buffer + y * row_stride;
+    for (x = 0; x < width; x++) {
+
+      if (pix[x] ^ invert_bit)
+	*dest++ = 0;
+      else
+	*dest++ = 255;
+    }
+  }
+
+  image = cairo_image_surface_create_for_data (buffer, CAIRO_FORMAT_A8,
+					  width, height, row_stride);
+  if (image == NULL)
+    return;
+  pattern = cairo_pattern_create_for_surface (image);
+  if (pattern == NULL)
+    return;
+
+  ctm = state->getCTM();
+  LOG (printf ("drawImageMask %dx%d, matrix: %f, %f, %f, %f, %f, %f\n",
+	       width, height, ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]));
+  matrix.xx = ctm[0] / width;
+  matrix.xy = -ctm[2] / height;
+  matrix.yx = ctm[1] / width;
+  matrix.yy = -ctm[3] / height;
+  matrix.x0 = ctm[2] + ctm[4];
+  matrix.y0 = ctm[3] + ctm[5];
+  cairo_matrix_invert (&matrix);
+  cairo_pattern_set_matrix (pattern, &matrix);
+
+  cairo_pattern_set_filter (pattern, CAIRO_FILTER_BEST);
+  /* FIXME: Doesn't the image mask support any colorspace? */
+  cairo_set_source_rgb (cairo, fill_color.r, fill_color.g, fill_color.b);
+  cairo_mask (cairo, pattern);
+
+  cairo_pattern_destroy (pattern);
+  cairo_surface_destroy (image);
+  free (buffer);
+  imgStr->close ();
+  delete imgStr;
+#endif
+}
+
+//TODO: lots more work here.
+void ArthurOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
+				int width, int height,
+				GfxImageColorMap *colorMap,
+				GBool interpolate, int *maskColors, GBool inlineImg)
+{
+  unsigned int *data;
+  unsigned int *line;
+  int x, y;
+  ImageStream *imgStr;
+  Guchar *pix;
+  int i;
+  double *ctm;
+  QMatrix matrix;
+  QImage image;
+  int stride;
+  
+  /* TODO: Do we want to cache these? */
+  imgStr = new ImageStream(str, width,
+			   colorMap->getNumPixelComps(),
+			   colorMap->getBits());
+  imgStr->reset();
+  
+  image = QImage(width, height, QImage::Format_ARGB32);
+  data = (unsigned int *)image.bits();
+  stride = image.bytesPerLine()/4;
+  for (y = 0; y < height; y++) {
+    pix = imgStr->getLine();
+    line = data+y*stride;
+    colorMap->getRGBLine(pix, line, width);
+
+    if (maskColors) {
+      for (x = 0; x < width; x++) {
+        for (i = 0; i < colorMap->getNumPixelComps(); ++i) {
+            if (pix[i] < maskColors[2*i] * 255||
+                pix[i] > maskColors[2*i+1] * 255) {
+                *line = *line | 0xff000000;
+                break;
+            }
+        }
+        pix += colorMap->getNumPixelComps();
+        line++;
+      }
+    } else {
+      for (x = 0; x < width; x++) { *line = *line | 0xff000000; line++; }
+    }
+  }
+
+  ctm = state->getCTM();
+  matrix.setMatrix(ctm[0] / width, ctm[1] / width, -ctm[2] / height, -ctm[3] / height, ctm[2] + ctm[4], ctm[3] + ctm[5]);
+
+  m_painter->setMatrix(matrix, true);
+  m_painter->drawImage( QPoint(0,0), image );
+  delete imgStr;
+
+}
diff --git a/qt5/src/ArthurOutputDev.h b/qt5/src/ArthurOutputDev.h
new file mode 100644
index 0000000..9d5e867
--- /dev/null
+++ b/qt5/src/ArthurOutputDev.h
@@ -0,0 +1,170 @@
+//========================================================================
+//
+// ArthurOutputDev.h
+//
+// Copyright 2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+//========================================================================
+//
+// Modified under the Poppler project - http://poppler.freedesktop.org
+//
+// All changes made under the Poppler project to this file are licensed
+// under GPL version 2 or later
+//
+// Copyright (C) 2005 Brad Hards <bradh at frogmouth.net>
+// Copyright (C) 2005 Albert Astals Cid <aacid at kde.org>
+// Copyright (C) 2009, 2011 Carlos Garcia Campos <carlosgc at gnome.org>
+// Copyright (C) 2010 Pino Toscano <pino at kde.org>
+// Copyright (C) 2011 Andreas Hartmetz <ahartmetz at gmail.com>
+// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
+//
+// To see a description of the changes please see the Changelog file that
+// came with your tarball or type make ChangeLog if you are building from git
+//
+//========================================================================
+
+#ifndef ARTHUROUTPUTDEV_H
+#define ARTHUROUTPUTDEV_H
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "goo/gtypes.h"
+#include "OutputDev.h"
+#include "GfxState.h"
+
+#include <QtGui/QPainter>
+
+class GfxState;
+class GfxPath;
+class Gfx8BitFont;
+struct GfxRGB;
+
+class SplashFont;
+class SplashFontEngine;
+struct SplashGlyphBitmap;
+
+//------------------------------------------------------------------------
+// ArthurOutputDev - Qt 4 QPainter renderer
+//------------------------------------------------------------------------
+
+class ArthurOutputDev: public OutputDev {
+public:
+  /**
+   * Describes how fonts are distorted (aka hinted) to fit the pixel grid.
+   * More hinting means sharper edges and less adherence to the true letter shapes.
+   */
+  enum FontHinting {
+    NoHinting = 0, ///< Font shapes are left unchanged
+    SlightHinting, ///< Font shapes are distorted vertically only
+    FullHinting ///< Font shapes are distorted horizontally and vertically
+  };
+
+  // Constructor.
+  ArthurOutputDev(QPainter *painter );
+
+  // Destructor.
+  virtual ~ArthurOutputDev();
+
+  void setFontHinting(FontHinting hinting) { m_fontHinting = hinting; }
+
+  //----- get info about output device
+
+  // Does this device use upside-down coordinates?
+  // (Upside-down means (0,0) is the top left corner of the page.)
+  virtual GBool upsideDown() { return gTrue; }
+
+  // Does this device use drawChar() or drawString()?
+  virtual GBool useDrawChar() { return gTrue; }
+
+  // Does this device use beginType3Char/endType3Char?  Otherwise,
+  // text in Type 3 fonts will be drawn with drawChar/drawString.
+  virtual GBool interpretType3Chars() { return gTrue; }
+
+  //----- initialization and control
+
+  // Start a page.
+  virtual void startPage(int pageNum, GfxState *state, XRef *xref);
+
+  // End a page.
+  virtual void endPage();
+
+  //----- save/restore graphics state
+  virtual void saveState(GfxState *state);
+  virtual void restoreState(GfxState *state);
+
+  //----- update graphics state
+  virtual void updateAll(GfxState *state);
+  virtual void updateCTM(GfxState *state, double m11, double m12,
+			 double m21, double m22, double m31, double m32);
+  virtual void updateLineDash(GfxState *state);
+  virtual void updateFlatness(GfxState *state);
+  virtual void updateLineJoin(GfxState *state);
+  virtual void updateLineCap(GfxState *state);
+  virtual void updateMiterLimit(GfxState *state);
+  virtual void updateLineWidth(GfxState *state);
+  virtual void updateFillColor(GfxState *state);
+  virtual void updateStrokeColor(GfxState *state);
+  virtual void updateFillOpacity(GfxState *state);
+  virtual void updateStrokeOpacity(GfxState *state);
+
+  //----- update text state
+  virtual void updateFont(GfxState *state);
+
+  //----- path painting
+  virtual void stroke(GfxState *state);
+  virtual void fill(GfxState *state);
+  virtual void eoFill(GfxState *state);
+
+  //----- path clipping
+  virtual void clip(GfxState *state);
+  virtual void eoClip(GfxState *state);
+
+  //----- text drawing
+  //   virtual void drawString(GfxState *state, GooString *s);
+  virtual void drawChar(GfxState *state, double x, double y,
+			double dx, double dy,
+			double originX, double originY,
+			CharCode code, int nBytes, Unicode *u, int uLen);
+  virtual GBool beginType3Char(GfxState *state, double x, double y,
+			       double dx, double dy,
+			       CharCode code, Unicode *u, int uLen);
+  virtual void endType3Char(GfxState *state);
+  virtual void endTextObject(GfxState *state);
+
+  //----- image drawing
+  virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
+			     int width, int height, GBool invert,
+			     GBool interpolate, GBool inlineImg);
+  virtual void drawImage(GfxState *state, Object *ref, Stream *str,
+			 int width, int height, GfxImageColorMap *colorMap,
+			 GBool interpolate, int *maskColors, GBool inlineImg);
+
+  //----- Type 3 font operators
+  virtual void type3D0(GfxState *state, double wx, double wy);
+  virtual void type3D1(GfxState *state, double wx, double wy,
+		       double llx, double lly, double urx, double ury);
+
+  //----- special access
+
+  // Called to indicate that a new PDF document has been loaded.
+  void startDoc(XRef *xrefA);
+ 
+  GBool isReverseVideo() { return gFalse; }
+  
+private:
+  QPainter *m_painter;
+  FontHinting m_fontHinting;
+  QFont m_currentFont;
+  QPen m_currentPen;
+  QBrush m_currentBrush;
+  GBool m_needFontUpdate;		// set when the font needs to be updated
+  SplashFontEngine *m_fontEngine;
+  SplashFont *m_font;		// current font
+  XRef *xref;			// xref table for current document
+};
+
+#endif
diff --git a/qt5/src/CMakeLists.txt b/qt5/src/CMakeLists.txt
index 2d5ecaf..8679ae0 100644
--- a/qt5/src/CMakeLists.txt
+++ b/qt5/src/CMakeLists.txt
@@ -29,7 +29,7 @@ set(poppler_qt5_SRCS
   poppler-textbox.cc
   poppler-page-transition.cc
   poppler-media.cc
-  ${CMAKE_SOURCE_DIR}/poppler/ArthurOutputDev.cc
+  ArthurOutputDev.cc
 )
 add_library(poppler-qt5 SHARED ${poppler_qt5_SRCS})
 set_target_properties(poppler-qt5 PROPERTIES VERSION 1.0.0 SOVERSION 1)
diff --git a/qt5/src/Makefile.am b/qt5/src/Makefile.am
index 77f16df..e892f04 100644
--- a/qt5/src/Makefile.am
+++ b/qt5/src/Makefile.am
@@ -51,14 +51,15 @@ libpoppler_qt5_la_SOURCES =			\
 	poppler-export.h			\
 	poppler-private.h			\
 	poppler-page-transition-private.h	\
-	poppler-embeddedfile-private.h
+	poppler-embeddedfile-private.h		\
+	ArthurOutputDev.h			\
+	ArthurOutputDev.cc
 
 libpoppler_qt5_la_CXXFLAGS = 			\
 	-Dpoppler_qt5_EXPORTS -fPIC
 
 libpoppler_qt5_la_LIBADD = 			\
 	$(top_builddir)/poppler/libpoppler.la	\
-	$(top_builddir)/poppler/libpoppler-arthur.la	\
 	$(POPPLER_QT5_LIBS)
 
 libpoppler_qt5_la_LDFLAGS = -version-info 1:0:0 @create_shared_lib@ @auto_import_flags@
diff --git a/qt5/src/poppler-optcontent.cc b/qt5/src/poppler-optcontent.cc
index 81a9923..c8db680 100644
--- a/qt5/src/poppler-optcontent.cc
+++ b/qt5/src/poppler-optcontent.cc
@@ -425,3 +425,5 @@ namespace Poppler
     }
   }
 }
+
+#include "poppler-optcontent.moc"


More information about the poppler mailing list