From ec13df4903f88ce8e83899a80f963e6d808de249 Mon Sep 17 00:00:00 2001
From: Marek Kasik <mkasik@redhat.com>
Date: Thu, 5 Apr 2018 16:21:38 +0200
Subject: [PATCH] Fix tiling patterns when pattern cell is too far

Tiling pattern which has pattern matrix moving pattern cell far away
can fail on allocation of memory (e.g. in CairoOutputDev). This commit
solves the issue by moving the pattern cell as close to (0,0) as possible
by integer number of cells in pattern matrix.

https://bugs.freedesktop.org/show_bug.cgi?id=105905
---
 poppler/Gfx.cc | 30 +++++++++++++++++++++++++-----
 1 file changed, 25 insertions(+), 5 deletions(-)

diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc
index 4f6c33f8..9d6c98bd 100644
--- a/poppler/Gfx.cc
+++ b/poppler/Gfx.cc
@@ -39,6 +39,7 @@
 // Copyright (C) 2012 Lu Wang <coolwanglu@gmail.com>
 // Copyright (C) 2014 Jason Crain <jason@aquaticape.us>
 // Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by the LiMux project of the city of Munich
+// Copyright (C) 2018 Marek Kasik <mkasik@redhat.com>
 //
 // 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
@@ -2037,10 +2038,11 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat,
   double xMin, yMin, xMax, yMax, x, y, x1, y1;
   double cxMin, cyMin, cxMax, cyMax;
   int xi0, yi0, xi1, yi1, xi, yi;
-  double *ctm, *btm, *ptm;
+  double *ctm, *btm, ptm[6];
   double m[6], ictm[6], m1[6], imb[6];
   double det;
   double xstep, ystep;
+  double xoffset, yoffset;
   int i;
 
   // get color space
@@ -2050,13 +2052,31 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat,
   // construct a (pattern space) -> (current space) transform matrix
   ctm = state->getCTM();
   btm = baseMatrix;
-  ptm = tPat->getMatrix();
-  // iCTM = invert CTM
-  det = ctm[0] * ctm[3] - ctm[1] * ctm[2];
+
+  ptm[0] = tPat->getMatrix()[0];
+  ptm[1] = tPat->getMatrix()[1];
+  ptm[2] = tPat->getMatrix()[2];
+  ptm[3] = tPat->getMatrix()[3];
+  ptm[4] = tPat->getMatrix()[4];
+  ptm[5] = tPat->getMatrix()[5];
+
+  det = ptm[0] * ptm[3] - ptm[1] * ptm[2];
   if (fabs(det) < 0.000001) {
     error(errSyntaxError, getPos(), "Singular matrix in tiling pattern fill");
     return;
   }
+
+  xstep = tPat->getXStep();
+  ystep = tPat->getYStep();
+
+  // move the pattern cell close to (0,0)
+  xoffset = round ((ptm[3] * ptm[4] - ptm[2] * ptm[5]) / (xstep * det));
+  yoffset = - round ((ptm[1] * ptm[4] - ptm[0] * ptm[5]) / (ystep * det));
+  ptm[4] = ptm[4] - xoffset * ptm[0] * xstep - yoffset * ptm[2] * ystep;
+  ptm[5] = ptm[5] - xoffset * ptm[1] * xstep - yoffset * ptm[3] * ystep;
+
+  // iCTM = invert CTM
+  det = ctm[0] * ctm[3] - ctm[1] * ctm[2];
   det = 1 / det;
   ictm[0] = ctm[3] * det;
   ictm[1] = -ctm[1] * det;
@@ -2214,7 +2234,7 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat,
   m1[5] = m[5];
   if (out->useTilingPatternFill() &&
 	out->tilingPatternFill(state, this, catalog, tPat->getContentStream(),
-		       tPat->getMatrix(), tPat->getPaintType(), tPat->getTilingType(),
+		       ptm, tPat->getPaintType(), tPat->getTilingType(),
 		       tPat->getResDict(), m1, tPat->getBBox(),
 		       xi0, yi0, xi1, yi1, xstep, ystep)) {
     goto restore;
-- 
2.14.3