From ec13df4903f88ce8e83899a80f963e6d808de249 Mon Sep 17 00:00:00 2001 From: Marek Kasik 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 // Copyright (C) 2014 Jason Crain // Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, . Work sponsored by the LiMux project of the city of Munich +// Copyright (C) 2018 Marek Kasik // // 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