[poppler] poppler/CairoOutputDev.cc poppler/CairoOutputDev.h poppler/Gfx.cc poppler/OutputDev.h poppler/PreScanOutputDev.cc poppler/PreScanOutputDev.h poppler/PSOutputDev.cc poppler/PSOutputDev.h poppler/SplashOutputDev.cc poppler/SplashOutputDev.h

Albert Astals Cid aacid at kemper.freedesktop.org
Mon Mar 21 14:32:08 PDT 2011


 poppler/CairoOutputDev.cc   |    5 
 poppler/CairoOutputDev.h    |   10 -
 poppler/Gfx.cc              |    6 
 poppler/OutputDev.h         |    6 
 poppler/PSOutputDev.cc      |    8 -
 poppler/PSOutputDev.h       |    6 
 poppler/PreScanOutputDev.cc |   22 +++
 poppler/PreScanOutputDev.h  |   16 ++
 poppler/SplashOutputDev.cc  |  265 ++++++++++++++++++++++++++++++++++++++++++++
 poppler/SplashOutputDev.h   |   12 +
 10 files changed, 334 insertions(+), 22 deletions(-)

New commits:
commit abf167af8b15e5f3b510275ce619e6fdb42edd40
Author: Thomas Freitag <Thomas.Freitag at alfa.de>
Date:   Mon Mar 21 21:34:46 2011 +0000

    Implement tiling/patterns in SplashOutputDev
    
    Fixes bug 13518

diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index de0663c..477030a 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -25,6 +25,7 @@
 // Copyright (C) 2008, 2009 Chris Wilson <chris at chris-wilson.co.uk>
 // Copyright (C) 2008 Hib Eris <hib at hiberis.nl>
 // Copyright (C) 2009, 2010 David Benjamin <davidben at mit.edu>
+// Copyright (C) 2011 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
@@ -690,8 +691,8 @@ void CairoOutputDev::eoFill(GfxState *state) {
 
 }
 
-GBool CairoOutputDev::tilingPatternFill(GfxState *state, Object *str,
-					int paintType, Dict *resDict,
+GBool CairoOutputDev::tilingPatternFill(GfxState *state, Catalog *cat, Object *str,
+					double *pmat, int paintType, Dict *resDict,
 					double *mat, double *bbox,
 					int x0, int y0, int x1, int y1,
 					double xStep, double yStep)
diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h
index 8ef2a93..730a23c 100644
--- a/poppler/CairoOutputDev.h
+++ b/poppler/CairoOutputDev.h
@@ -20,7 +20,7 @@
 // Copyright (C) 2006-2011 Carlos Garcia Campos <carlosgc at gnome.org>
 // Copyright (C) 2008, 2009, 2011 Adrian Johnson <ajohnson at redneon.com>
 // Copyright (C) 2008 Michael Vrable <mvrable at cs.ucsd.edu>
-// Copyright (C) 2010 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2010, 2011 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
@@ -158,8 +158,8 @@ public:
   virtual void fill(GfxState *state);
   virtual void eoFill(GfxState *state);
   virtual void clipToStrokePath(GfxState *state);
-  virtual GBool tilingPatternFill(GfxState *state, Object *str,
-				  int paintType, Dict *resDict,
+  virtual GBool tilingPatternFill(GfxState *state, Catalog *cat, Object *str,
+				  double *pmat, int paintType, Dict *resDict,
 				  double *mat, double *bbox,
 				  int x0, int y0, int x1, int y1,
 				  double xStep, double yStep);
@@ -411,8 +411,8 @@ public:
   virtual void stroke(GfxState *state) { }
   virtual void fill(GfxState *state) { }
   virtual void eoFill(GfxState *state) { }
-  virtual GBool tilingPatternFill(GfxState *state, Object *str,
-				  int paintType, Dict *resDict,
+  virtual GBool tilingPatternFill(GfxState *state, Catalog *cat, Object *str,
+				  double *pmat, int paintType, Dict *resDict,
 				  double *mat, double *bbox,
 				  int x0, int y0, int x1, int y1,
 				  double xStep, double yStep) { return gTrue; }
diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc
index daf50d3..dc5f8e3 100644
--- a/poppler/Gfx.cc
+++ b/poppler/Gfx.cc
@@ -28,7 +28,7 @@
 // Copyright (C) 2008 Michael Vrable <mvrable at cs.ucsd.edu>
 // Copyright (C) 2008 Hib Eris <hib at hiberis.nl>
 // Copyright (C) 2009 M Joonas Pihlaja <jpihlaja at cc.helsinki.fi>
-// Copyright (C) 2009, 2010 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2009-2011 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2009 William Bader <williambader at hotmail.com>
 // Copyright (C) 2009, 2010 David Benjamin <davidben at mit.edu>
 // Copyright (C) 2010 Nils Höglund <nils.hoglund at gmail.com>
@@ -2082,8 +2082,8 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat,
     m1[4] = m[4];
     m1[5] = m[5];
     if (out->useTilingPatternFill() &&
-	out->tilingPatternFill(state, tPat->getContentStream(),
-			       tPat->getPaintType(), tPat->getResDict(),
+    	out->tilingPatternFill(state, catalog, tPat->getContentStream(),
+			       tPat->getMatrix(), tPat->getPaintType(), tPat->getResDict(),
 			       m1, tPat->getBBox(),
 			       xi0, yi0, xi1, yi1, xstep, ystep)) {
 	    goto restore;
diff --git a/poppler/OutputDev.h b/poppler/OutputDev.h
index 065a4a2..c922c7a 100644
--- a/poppler/OutputDev.h
+++ b/poppler/OutputDev.h
@@ -17,7 +17,7 @@
 // Copyright (C) 2006 Thorkild Stray <thorkild at ifi.uio.no>
 // Copyright (C) 2007 Jeff Muizelaar <jeff at infidigm.net>
 // Copyright (C) 2007, 2011 Adrian Johnson <ajohnson at redneon.com>
-// Copyright (C) 2009, 2010 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2009-2011 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2009, 2011 Carlos Garcia Campos <carlosgc at gnome.org>
 // Copyright (C) 2009 Albert Astals Cid <aacid at kde.org>
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
@@ -195,8 +195,8 @@ public:
   virtual void stroke(GfxState * /*state*/) {}
   virtual void fill(GfxState * /*state*/) {}
   virtual void eoFill(GfxState * /*state*/) {}
-  virtual GBool tilingPatternFill(GfxState * /*state*/, Object * /*str*/,
-				  int /*paintType*/, Dict * /*resDict*/,
+  virtual GBool tilingPatternFill(GfxState * /*state*/, Catalog * /*cat*/, Object * /*str*/,
+				  double * /*pmat*/, int /*paintType*/, Dict * /*resDict*/,
 				  double * /*mat*/, double * /*bbox*/,
 				  int /*x0*/, int /*y0*/, int /*x1*/, int /*y1*/,
 				  double /*xStep*/, double /*yStep*/)
diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc
index 34f09a5..ca7c5cd 100644
--- a/poppler/PSOutputDev.cc
+++ b/poppler/PSOutputDev.cc
@@ -20,7 +20,7 @@
 // Copyright (C) 2007, 2008 Brad Hards <bradh at kde.org>
 // Copyright (C) 2008, 2009 Koji Otani <sho at bbr.jp>
 // Copyright (C) 2008, 2010 Hib Eris <hib at hiberis.nl>
-// Copyright (C) 2009, 2010 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2009-2011 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2009 Till Kamppeter <till.kamppeter at gmail.com>
 // Copyright (C) 2009 Carlos Garcia Campos <carlosgc at gnome.org>
 // Copyright (C) 2009, 2011 William Bader <williambader at hotmail.com>
@@ -2997,7 +2997,7 @@ GBool PSOutputDev::checkPageSlice(Page *page, double /*hDPI*/, double /*vDPI*/,
   GBool useBinary;
 
   if (!forceRasterize) {
-    scan = new PreScanOutputDev();
+    scan = new PreScanOutputDev(xref);
     page->displaySlice(scan, 72, 72, rotateA, useMediaBox, crop,
                      sliceX, sliceY, sliceW, sliceH,
                      printing, catalog, abortCheckCbk, abortCheckCbkData);
@@ -3876,8 +3876,8 @@ void PSOutputDev::eoFill(GfxState *state) {
   writePS("f*\n");
 }
 
-GBool PSOutputDev::tilingPatternFill(GfxState *state, Object *str,
-				     int paintType, Dict *resDict,
+GBool PSOutputDev::tilingPatternFill(GfxState *state, Catalog *cat, Object *str,
+				     double *pmat, int paintType, Dict *resDict,
 				     double *mat, double *bbox,
 				     int x0, int y0, int x1, int y1,
 				     double xStep, double yStep) {
diff --git a/poppler/PSOutputDev.h b/poppler/PSOutputDev.h
index d3eddec..6b37d18 100644
--- a/poppler/PSOutputDev.h
+++ b/poppler/PSOutputDev.h
@@ -17,7 +17,7 @@
 // Copyright (C) 2005 Kristian Høgsberg <krh at redhat.com>
 // Copyright (C) 2006-2008 Albert Astals Cid <aacid at kde.org>
 // Copyright (C) 2007 Brad Hards <bradh at kde.org>
-// Copyright (C) 2009, 2010 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2009-2011 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2009 Till Kamppeter <till.kamppeter at gmail.com>
 // Copyright (C) 2009 Carlos Garcia Campos <carlosgc at gnome.org>
 // Copyright (C) 2009, 2011 William Bader <williambader at hotmail.com>
@@ -209,8 +209,8 @@ public:
   virtual void stroke(GfxState *state);
   virtual void fill(GfxState *state);
   virtual void eoFill(GfxState *state);
-  virtual GBool tilingPatternFill(GfxState *state, Object *str,
-				  int paintType, Dict *resDict,
+  virtual GBool tilingPatternFill(GfxState *state, Catalog *cat, Object *str,
+				  double *pmat, int paintType, Dict *resDict,
 				  double *mat, double *bbox,
 				  int x0, int y0, int x1, int y1,
 				  double xStep, double yStep);
diff --git a/poppler/PreScanOutputDev.cc b/poppler/PreScanOutputDev.cc
index 8ccdfe6..239aef8 100644
--- a/poppler/PreScanOutputDev.cc
+++ b/poppler/PreScanOutputDev.cc
@@ -16,6 +16,7 @@
 // Copyright (C) 2009 Carlos Garcia Campos <carlosgc at gnome.org>
 // Copyright (C) 2010 Albert Astals Cid <aacid at kde.org>
 // Copyright (C) 2011 William Bader <williambader at hotmail.com>
+// Copyright (C) 2011 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
@@ -28,16 +29,20 @@
 
 #include <math.h>
 #include "GlobalParams.h"
+#include "Gfx.h"
 #include "GfxFont.h"
 #include "Link.h"
+#include "Catalog.h"
+#include "Page.h"
 #include "PreScanOutputDev.h"
 
 //------------------------------------------------------------------------
 // PreScanOutputDev
 //------------------------------------------------------------------------
 
-PreScanOutputDev::PreScanOutputDev() {
+PreScanOutputDev::PreScanOutputDev(XRef *xrefA) {
   level = globalParams->getPSLevel();
+  xref = xrefA;
   clearStats();
 }
 
@@ -73,6 +78,21 @@ void PreScanOutputDev::eoFill(GfxState *state) {
 	state->getFillOpacity(), state->getBlendMode());
 }
 
+GBool PreScanOutputDev::tilingPatternFill(GfxState *state, Catalog *catalog, Object *str,
+					double *pmat, int paintType, Dict *resDict,
+					double *mat, double *bbox,
+					int x0, int y0, int x1, int y1,
+					double xStep, double yStep) {
+  PDFRectangle box;
+  Gfx *gfx;
+  box.x1 = bbox[0]; box.y1 = bbox[1];
+  box.x2 = bbox[2]; box.y2 = bbox[3];
+  gfx = new Gfx(xref, this, resDict, catalog, &box, NULL);
+  gfx->display(str);
+  delete gfx;
+  return gTrue;
+}
+
 void PreScanOutputDev::clip(GfxState * /*state*/) {
   //~ check for a rectangle "near" the edge of the page;
   //~   else set gdi to false
diff --git a/poppler/PreScanOutputDev.h b/poppler/PreScanOutputDev.h
index f09ecca..d97f0f7 100644
--- a/poppler/PreScanOutputDev.h
+++ b/poppler/PreScanOutputDev.h
@@ -16,6 +16,7 @@
 // Copyright (C) 2009 Carlos Garcia Campos <carlosgc at gnome.org>
 // Copyright (C) 2010 Albert Astals Cid <aacid at kde.org>
 // Copyright (C) 2011 William Bader <williambader at hotmail.com>
+// Copyright (C) 2011 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
@@ -30,7 +31,9 @@
 #endif
 
 #include "goo/gtypes.h"
+#include "Object.h"
 #include "GfxState.h"
+#include "GlobalParams.h"
 #include "OutputDev.h"
 
 //------------------------------------------------------------------------
@@ -41,7 +44,7 @@ class PreScanOutputDev: public OutputDev {
 public:
 
   // Constructor.
-  PreScanOutputDev();
+  PreScanOutputDev(XRef *xrefA);
 
   // Destructor.
   virtual ~PreScanOutputDev();
@@ -55,6 +58,11 @@ public:
   // Does this device use drawChar() or drawString()?
   virtual GBool useDrawChar() { return gTrue; }
 
+  // Does this device use tilingPatternFill()?  If this returns false,
+  // tiling pattern fills will be reduced to a series of other drawing
+  // operations.
+  virtual GBool useTilingPatternFill() { 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; }
@@ -71,6 +79,11 @@ public:
   virtual void stroke(GfxState *state);
   virtual void fill(GfxState *state);
   virtual void eoFill(GfxState *state);
+  virtual GBool tilingPatternFill(GfxState *state, Catalog *cat, Object *str,
+				  double *pmat, int paintType, Dict *resDict,
+				  double *mat, double *bbox,
+				  int x0, int y0, int x1, int y1,
+				  double xStep, double yStep);
 
   //----- path clipping
   virtual void clip(GfxState *state);
@@ -145,6 +158,7 @@ private:
   void check(GfxColorSpace *colorSpace, GfxColor *color,
 	     double opacity, GfxBlendMode blendMode);
 
+  XRef *xref;
   GBool mono;
   GBool gray;
   GBool transparency;
diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc
index fc838d3..3a56a78 100644
--- a/poppler/SplashOutputDev.cc
+++ b/poppler/SplashOutputDev.cc
@@ -47,7 +47,9 @@
 #include "GlobalParams.h"
 #include "Error.h"
 #include "Object.h"
+#include "Gfx.h"
 #include "GfxFont.h"
+#include "Page.h"
 #include "Link.h"
 #include "CharCodeToUnicode.h"
 #include "FontEncodingTables.h"
@@ -2582,6 +2584,98 @@ GBool SplashOutputDev::alphaImageSrc(void *data, SplashColorPtr colorLine,
   return gTrue;
 }
 
+struct TilingSplashOutBitmap {
+  SplashBitmap *bitmap;
+  SplashPattern *pattern;
+  SplashColorMode colorMode;
+  int paintType;
+  int repeatX;
+  int repeatY;
+  int y;
+};
+
+GBool SplashOutputDev::tilingBitmapSrc(void *data, SplashColorPtr colorLine,
+                                       Guchar *alphaLine) {
+  TilingSplashOutBitmap *imgData = (TilingSplashOutBitmap *)data;
+
+  if (imgData->y == imgData->bitmap->getHeight()) {
+    imgData->repeatY--;
+    if (imgData->repeatY == 0)
+      return gFalse;
+    imgData->y = 0;
+  }
+
+  if (imgData->paintType == 1) {
+    const SplashColorMode cMode = imgData->bitmap->getMode();
+    SplashColorPtr q = colorLine;
+    // For splashModeBGR8 and splashModeXBGR8 we need to use getPixel
+    // for the others we can use raw access
+    if (cMode == splashModeBGR8 || cMode == splashModeXBGR8) {
+      for (int m = 0; m < imgData->repeatX; m++) {
+        for (int x = 0; x < imgData->bitmap->getWidth(); x++) {
+          imgData->bitmap->getPixel(x, imgData->y, q);
+          q += splashColorModeNComps[cMode]; 
+        }
+      }
+    } else {
+      const int n = imgData->bitmap->getRowSize();
+      SplashColorPtr p;
+      for (int m = 0; m < imgData->repeatX; m++) {   
+        p = imgData->bitmap->getDataPtr() + imgData->y * imgData->bitmap->getRowSize();
+        for (int x = 0; x < n; ++x) { // TODO memcopy?
+          *q++ = *p++;
+        }
+      }
+    }
+    if (alphaLine != NULL) {
+      SplashColorPtr aq = alphaLine;
+      SplashColorPtr p;
+      const int n = imgData->bitmap->getWidth() - 1;
+      for (int m = 0; m < imgData->repeatX; m++) {
+        p = imgData->bitmap->getAlphaPtr() + imgData->y * imgData->bitmap->getWidth();
+        for (int x = 0; x < n; ++x) { // TODO memcopy?
+          *aq++ = *p++;
+        }
+        // This is a hack, because of how Splash antialias works if we overwrite the
+        // last alpha pixel of the tile most/all of the files look much better
+        *aq++ = (n == 0) ? *p : *(p - 1);
+      }
+    }
+  } else {
+    SplashColor col, pat;
+    SplashColorPtr dest = colorLine;
+    for (int m = 0; m < imgData->repeatX; m++) {
+      for (int x = 0; x < imgData->bitmap->getWidth(); x++) {
+        imgData->bitmap->getPixel(x, imgData->y, col);
+        imgData->pattern->getColor(x, imgData->y, pat); 
+        for (int i = 0; i < splashColorModeNComps[imgData->colorMode]; ++i) {
+#if SPLASH_CMYK
+          if (imgData->colorMode == splashModeCMYK8)
+            dest[i] = div255(pat[i] * (255 - col[0]));
+          else
+#endif
+            dest[i] = 255 - div255((255 - pat[i]) * (255 - col[0]));
+        }
+        dest += splashColorModeNComps[imgData->colorMode]; 
+      }
+    }
+    if (alphaLine != NULL) {
+      const int y = (imgData->y == imgData->bitmap->getHeight() - 1 && imgData->y > 50) ? imgData->y - 1 : imgData->y; 
+      SplashColorPtr aq = alphaLine;
+      SplashColorPtr p;
+      const int n = imgData->bitmap->getWidth();
+      for (int m = 0; m < imgData->repeatX; m++) {
+        p = imgData->bitmap->getAlphaPtr() + y * imgData->bitmap->getWidth();
+        for (int x = 0; x < n; ++x) { // TODO memcopy?
+          *aq++ = *p++;
+        }
+      }
+    }
+  }
+  ++imgData->y;
+  return gTrue;
+}
+
 void SplashOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
 				int width, int height,
 				GfxImageColorMap *colorMap,
@@ -3472,6 +3566,177 @@ void SplashOutputDev::setFreeTypeHinting(GBool enable, GBool enableSlightHinting
   enableSlightHinting = enableSlightHintingA;
 }
 
+GBool SplashOutputDev::tilingPatternFill(GfxState *state, Catalog *catalog, Object *str,
+					double *ptm, int paintType, Dict *resDict,
+					double *mat, double *bbox,
+					int x0, int y0, int x1, int y1,
+					double xStep, double yStep) 
+{
+  PDFRectangle box;
+  Gfx *gfx;
+  Splash *formerSplash = splash;
+  SplashBitmap *formerBitmap = bitmap;
+  double width, height;
+  int surface_width, surface_height, result_width, result_height, i;
+  int xMin, xMax, yMin, yMax;
+  int repeatX, repeatY;
+  SplashCoord matc[6];
+  Matrix m1;
+  double *ctm, savedCTM[6];
+  double kx, ky, sx, sy;
+
+  width = bbox[2] - bbox[0];
+  height = bbox[3] - bbox[1];
+
+  if (xStep != width || yStep != height)
+    return gFalse;
+
+  // calculate offsets
+  ctm = state->getCTM();
+  for (i = 0; i < 6; ++i) {
+    savedCTM[i] = ctm[i];
+  }
+  state->concatCTM(mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
+  state->concatCTM(1, 0, 0, 1, bbox[0], bbox[1]);
+  ctm = state->getCTM();
+  for (i = 0; i < 6; ++i) {
+    if (!isfinite(ctm[i]))
+      return gFalse;
+  }
+  matc[4] = x0 * xStep * ctm[0] + y0 * yStep * ctm[2] + ctm[4];
+  matc[5] = x0 * xStep * ctm[1] + y0 * yStep * ctm[3] + ctm[5];
+  xMin = (int) ceil (matc[4]);
+  yMin = (int) ceil (matc[5]);
+  xMax = xMin;
+  yMax = yMin;
+  if (splashAbs(ctm[1]) > splashAbs(ctm[0])) {
+    kx = -ctm[1];
+    ky = ctm[2] - (ctm[0] * ctm[3]) / ctm[1];
+  } else {
+    kx = ctm[0];
+    ky = ctm[3] - (ctm[1] * ctm[2]) / ctm[0];
+  }
+  result_width = (int) ceil(fabs(kx * width * (x1 - x0)));
+  result_height = (int) ceil(fabs(ky * height * (y1 - y0)));
+  kx = state->getHDPI() / 72.0;
+  ky = state->getVDPI() / 72.0;
+  m1.m[0] = (ptm[0] == 0) ? fabs(ptm[2]) * kx : fabs(ptm[0]) * kx;
+  m1.m[1] = 0;
+  m1.m[2] = 0;
+  m1.m[3] = (ptm[3] == 0) ? fabs(ptm[1]) * ky : fabs(ptm[3]) * ky;
+  m1.m[4] = 0;
+  m1.m[5] = 0;
+  m1.transform(width, height, &kx, &ky);
+  surface_width = (int) ceil (fabs(kx));
+  surface_height = (int) ceil (fabs(ky));
+
+  sx = (double) result_width / (surface_width * (x1 - x0));
+  sy = (double) result_height / (surface_height * (y1 - y0));
+  m1.m[0] *= sx;
+  m1.m[3] *= sy;
+  m1.transform(width, height, &kx, &ky);
+
+  if(fabs(kx) < 1 && fabs(ky) < 1) {
+    kx = std::min<double>(kx, ky);
+    ky = 2 / kx;
+    m1.m[0] *= ky;
+    m1.m[3] *= ky;
+    m1.transform(width, height, &kx, &ky);
+    surface_width = (int) ceil (fabs(kx));
+    surface_height = (int) ceil (fabs(ky));
+    repeatX = x1 - x0;
+    repeatY = y1 - y0;
+  } else {
+    while(fabs(kx) > 16384 || fabs(ky) > 16384) {
+      // limit pattern bitmap size
+      m1.m[0] /= 2;
+      m1.m[3] /= 2;
+      m1.transform(width, height, &kx, &ky);
+    }
+    surface_width = (int) ceil (fabs(kx));
+    surface_height = (int) ceil (fabs(ky));
+    // adjust repeat values to completely fill region
+    repeatX = result_width / surface_width;
+    repeatY = result_height / surface_height;
+    if (surface_width * repeatX < result_width)
+      repeatX++;
+    if (surface_height * repeatY < result_height)
+      repeatY++;
+    if (x1 - x0 > repeatX)
+      repeatX = x1 - x0;
+    if (y1 - y0 > repeatY)
+      repeatY = y1 - y0;
+  }
+  // restore CTM and calculate rotate and scale with rounded matric
+  state->setCTM(savedCTM[0], savedCTM[1], savedCTM[2], savedCTM[3], savedCTM[4], savedCTM[5]);
+  state->concatCTM(mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
+  state->concatCTM(width * repeatX, 0, 0, height * repeatY, bbox[0], bbox[1]);
+  ctm = state->getCTM();
+  matc[0] = ctm[0];
+  matc[1] = ctm[1];
+  matc[2] = ctm[2];
+  matc[3] = ctm[3];
+
+  if (surface_width == 0 || surface_height == 0)
+    return gFalse;
+  m1.transform(bbox[0], bbox[1], &kx, &ky);
+  m1.m[4] = -kx;
+  m1.m[5] = -ky;
+
+  bitmap = new SplashBitmap(surface_width, surface_height, colorMode != splashModeMono1, 
+                            (paintType == 1) ? colorMode : splashModeMono8, gTrue);
+  memset(bitmap->getAlphaPtr(), 0, bitmap->getWidth() * bitmap->getHeight());
+  if (paintType == 2) {
+#ifdef SPLASH_CMYK
+    memset(bitmap->getDataPtr(), (colorMode == splashModeCMYK8) ? 0x00 : 0xFF, bitmap->getRowSize() * bitmap->getHeight());
+#else
+    memset(bitmap->getDataPtr(), 0xFF, bitmap->getRowSize() * bitmap->getHeight());
+#endif
+  }
+  splash = new Splash(bitmap, gTrue);
+
+  box.x1 = bbox[0]; box.y1 = bbox[1];
+  box.x2 = bbox[2]; box.y2 = bbox[3];
+  gfx = new Gfx(xref, this, resDict, catalog, &box, NULL);
+  // set pattern transformation matrix
+  gfx->getState()->setCTM(m1.m[0], m1.m[1], m1.m[2], m1.m[3], m1.m[4], m1.m[5]);
+  updateCTM(gfx->getState(), m1.m[0], m1.m[1], m1.m[2], m1.m[3], m1.m[4], m1.m[5]);
+  gfx->display(str);
+  splash = formerSplash;
+  TilingSplashOutBitmap imgData;
+  imgData.bitmap = bitmap;
+  imgData.paintType = paintType;
+  imgData.pattern = splash->getFillPattern();
+  imgData.colorMode = colorMode;
+  imgData.y = 0;
+  imgData.repeatX = repeatX;
+  imgData.repeatY = repeatY;
+  SplashBitmap *tBitmap = bitmap;
+  bitmap = formerBitmap;
+  result_width = tBitmap->getWidth() * imgData.repeatX;
+  result_height = tBitmap->getHeight() * imgData.repeatY;
+
+  if (splashAbs(matc[1]) > splashAbs(matc[0])) {
+    kx = -matc[1];
+    ky = matc[2] - (matc[0] * matc[3]) / matc[1];
+  } else {
+    kx = matc[0];
+    ky = matc[3] - (matc[1] * matc[2]) / matc[0];
+  }
+  kx = result_width / (fabs(kx) + 1);
+  ky = result_height / (fabs(ky) + 1);
+  state->concatCTM(kx, 0, 0, ky, 0, 0);
+  ctm = state->getCTM();
+  matc[0] = ctm[0];
+  matc[1] = ctm[1];
+  matc[2] = ctm[2];
+  matc[3] = ctm[3];
+  splash->drawImage(&tilingBitmapSrc, &imgData, colorMode, gTrue, result_width, result_height, matc);
+  delete tBitmap;
+  delete gfx;
+  return gTrue;
+}
+
 GBool SplashOutputDev::gouraudTriangleShadedFill(GfxState *state, GfxGouraudTriangleShading *shading)
 {
   GfxColorSpaceMode shadingMode = shading->getColorSpace()->getMode();
diff --git a/poppler/SplashOutputDev.h b/poppler/SplashOutputDev.h
index c8cb84f..26f3ddf 100644
--- a/poppler/SplashOutputDev.h
+++ b/poppler/SplashOutputDev.h
@@ -166,6 +166,11 @@ public:
 
   //----- get info about output device
 
+  // Does this device use tilingPatternFill()?  If this returns false,
+  // tiling pattern fills will be reduced to a series of other drawing
+  // operations.
+  virtual GBool useTilingPatternFill() { return gTrue; }
+
   // Does this device use functionShadedFill(), axialShadedFill(), and
   // radialShadedFill()?  If this returns false, these shaded fills
   // will be reduced to a series of other drawing operations.
@@ -223,6 +228,11 @@ public:
   virtual void stroke(GfxState *state);
   virtual void fill(GfxState *state);
   virtual void eoFill(GfxState *state);
+  virtual GBool tilingPatternFill(GfxState *state, Catalog *catalog, Object *str,
+				  double *pmat, int paintType, Dict *resDict,
+				  double *mat, double *bbox,
+				  int x0, int y0, int x1, int y1,
+				  double xStep, double yStep);
   virtual GBool axialShadedFill(GfxState *state, GfxAxialShading *shading, double tMin, double tMax);
   virtual GBool radialShadedFill(GfxState *state, GfxRadialShading *shading, double tMin, double tMax);
   virtual GBool gouraudTriangleShadedFill(GfxState *state, GfxGouraudTriangleShading *shading);
@@ -349,6 +359,8 @@ private:
 			     Guchar *alphaLine);
   static GBool maskedImageSrc(void *data, SplashColorPtr line,
 			      Guchar *alphaLine);
+  static GBool tilingBitmapSrc(void *data, SplashColorPtr line,
+			     Guchar *alphaLine);
 
   GBool haveCSPattern;		// set if text has been drawn with a
 							//   clipping render mode because of pattern colorspace


More information about the poppler mailing list