[poppler] 2 commits - poppler/Gfx.cc poppler/GfxState.cc poppler/GfxState.h poppler/SplashOutputDev.cc poppler/SplashOutputDev.h

Albert Astals Cid aacid at kemper.freedesktop.org
Wed Mar 2 08:52:23 UTC 2016


 poppler/Gfx.cc             |   33 ++++++++++++++++--
 poppler/GfxState.cc        |    7 ++-
 poppler/GfxState.h         |    7 +++
 poppler/SplashOutputDev.cc |   80 ++++++++++++++++++++++++++++++++++++++++++++-
 poppler/SplashOutputDev.h  |    3 +
 5 files changed, 122 insertions(+), 8 deletions(-)

New commits:
commit 1f7cb78f8b771bae8bfd96a7a7ca3afbaf89c749
Author: Albert Astals Cid <aacid at kde.org>
Date:   Wed Mar 2 09:51:46 2016 +0100

    Fix memory leak in Matte parsing
    
    Also remove unneeded comment

diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc
index 4c10155..471bea6 100644
--- a/poppler/Gfx.cc
+++ b/poppler/Gfx.cc
@@ -14,7 +14,7 @@
 // under GPL version 2 or later
 //
 // Copyright (C) 2005 Jonathan Blandford <jrb at redhat.com>
-// Copyright (C) 2005-2013, 2015 Albert Astals Cid <aacid at kde.org>
+// Copyright (C) 2005-2013, 2015, 2016 Albert Astals Cid <aacid at kde.org>
 // Copyright (C) 2006 Thorkild Stray <thorkild at ifi.uio.no>
 // Copyright (C) 2006 Kristian Høgsberg <krh at redhat.com>
 // Copyright (C) 2006-2011 Carlos Garcia Campos <carlosgc at gnome.org>
@@ -4570,7 +4570,7 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
       }
       // handle the Matte entry
       maskDict->lookup("Matte", &obj1);
-      if (obj1.isArray()) { // && maskStr->getKind() != strDCT) {
+      if (obj1.isArray()) {
         if (obj1.getArray()->getLength() != colorSpace->getNComps()) {
           error(errSyntaxError, -1, "Matte entry should have {0:d} components but has {1:d}",
             colorSpace->getNComps(), obj1.getArray()->getLength());
@@ -4595,6 +4595,7 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
           }
         }
       }
+      obj1.free();
       haveSoftMask = gTrue;
     } else if (maskObj.isArray()) {
       // color key mask
commit 36c276f1af7e0f1d8a207f6cdcaa80a24e95e044
Author: Thomas Freitag <Thomas.Freitag at alfa.de>
Date:   Wed Mar 2 09:50:01 2016 +0100

    Splash: Implementation of matte entries in softmasks of softmasked images
    
    Bug #22473

diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc
index bb5f9b1..4c10155 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-2015 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2009-2016 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>
@@ -4568,7 +4568,33 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
 	delete maskColorMap;
 	goto err1;
       }
-      //~ handle the Matte entry
+      // handle the Matte entry
+      maskDict->lookup("Matte", &obj1);
+      if (obj1.isArray()) { // && maskStr->getKind() != strDCT) {
+        if (obj1.getArray()->getLength() != colorSpace->getNComps()) {
+          error(errSyntaxError, -1, "Matte entry should have {0:d} components but has {1:d}",
+            colorSpace->getNComps(), obj1.getArray()->getLength());
+        } else if (maskWidth != width || maskHeight != height) {
+          error(errSyntaxError, -1, "Softmask with matte entry {0:d} x {1:d} must have same geometry as the image {2:d} x {3:d}",
+            maskWidth, maskHeight, width, height);
+        } else {
+          GfxColor matteColor;
+          for (i = 0; i < colorSpace->getNComps(); i++) {
+            obj1.getArray()->get(i, &obj2);
+            if (!obj2.isNum()) {
+              obj2.free();
+              error(errSyntaxError, -1, "Matte entry {0:d} should be a number but it's of type {1:d}", i, obj2.getType());
+
+              break;
+            }
+            matteColor.c[i] = dblToCol(obj2.getNum());
+            obj2.free();
+          }
+          if (i == colorSpace->getNComps()) {
+            maskColorMap->setMatteColor(&matteColor);
+          }
+        }
+      }
       haveSoftMask = gTrue;
     } else if (maskObj.isArray()) {
       // color key mask
diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc
index bd3b42d..603bf5b 100644
--- a/poppler/GfxState.cc
+++ b/poppler/GfxState.cc
@@ -18,7 +18,7 @@
 // Copyright (C) 2006, 2010 Carlos Garcia Campos <carlosgc at gnome.org>
 // Copyright (C) 2006-2015 Albert Astals Cid <aacid at kde.org>
 // Copyright (C) 2009, 2012 Koji Otani <sho at bbr.jp>
-// Copyright (C) 2009, 2011-2015 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2009, 2011-2016 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2009 Christian Persch <chpe at gnome.org>
 // Copyright (C) 2010 Paweł Wiejacha <pawel.wiejacha at gmail.com>
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
@@ -5821,6 +5821,7 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
   GBool useByteLookup;
 
   ok = gTrue;
+  useMatte = gFalse;
 
   // bits per component and color space
   bits = bitsA;
@@ -5983,6 +5984,8 @@ GfxImageColorMap::GfxImageColorMap(GfxImageColorMap *colorMap) {
   bits = colorMap->bits;
   nComps = colorMap->nComps;
   nComps2 = colorMap->nComps2;
+  useMatte = colorMap->useMatte;
+  matteColor = colorMap->matteColor;
   colorSpace2 = NULL;
   for (k = 0; k < gfxColorMaxComps; ++k) {
     lookup[k] = NULL;
@@ -6570,7 +6573,7 @@ void GfxPath::offset(double dx, double dy) {
 }
 
 //------------------------------------------------------------------------
-// GfxState
+//
 //------------------------------------------------------------------------
 GfxState::ReusablePathIterator::ReusablePathIterator(GfxPath *path)
  : path(path),
diff --git a/poppler/GfxState.h b/poppler/GfxState.h
index c20438b..d359355 100644
--- a/poppler/GfxState.h
+++ b/poppler/GfxState.h
@@ -20,7 +20,7 @@
 // Copyright (C) 2009-2011, 2013 Albert Astals Cid <aacid at kde.org>
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
 // Copyright (C) 2011 Andrea Canciani <ranma42 at gmail.com>
-// Copyright (C) 2011-2014 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2011-2014, 2016 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2013 Lu Wang <coolwanglu at gmail.com>
 // Copyright (C) 2015 Adrian Johnson <ajohnson at redneon.com>
 //
@@ -1194,6 +1194,9 @@ public:
   void getDeviceN(Guchar *x, GfxColor *deviceN);
   void getColor(Guchar *x, GfxColor *color);
 
+  // Matte color ops
+  void setMatteColor(GfxColor *color) { useMatte = gTrue; matteColor = *color; }
+  GfxColor *getMatteColor() { return (useMatte) ? &matteColor : NULL; }
 private:
 
   GfxImageColorMap(GfxImageColorMap *colorMap);
@@ -1212,6 +1215,8 @@ private:
     decodeLow[gfxColorMaxComps];
   double			// max - min value for each component
     decodeRange[gfxColorMaxComps];
+  GBool useMatte;
+  GfxColor matteColor;
   GBool ok;
 };
 
diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc
index 7b11279..cc3199d 100644
--- a/poppler/SplashOutputDev.cc
+++ b/poppler/SplashOutputDev.cc
@@ -1760,6 +1760,51 @@ SplashPattern *SplashOutputDev::getColor(GfxColor *deviceN) {
 }
 #endif
 
+void SplashOutputDev::getMatteColor(SplashColorMode colorMode, GfxImageColorMap *colorMap, GfxColor *matteColorIn, SplashColor matteColor) {
+  GfxGray gray;
+  GfxRGB rgb;
+#if SPLASH_CMYK
+  GfxCMYK cmyk;
+  GfxColor deviceN;
+#endif
+
+  switch (colorMode) {
+    case splashModeMono1:
+    case splashModeMono8:
+      colorMap->getColorSpace()->getGray(matteColorIn, &gray);
+      matteColor[0] = colToByte(gray);
+      break;
+    case splashModeRGB8:
+    case splashModeBGR8:
+      colorMap->getColorSpace()->getRGB(matteColorIn, &rgb);
+      matteColor[0] = colToByte(rgb.r);
+      matteColor[1] = colToByte(rgb.g);
+      matteColor[2] = colToByte(rgb.b);
+      break;
+    case splashModeXBGR8:
+      colorMap->getColorSpace()->getRGB(matteColorIn, &rgb);
+      matteColor[0] = colToByte(rgb.r);
+      matteColor[1] = colToByte(rgb.g);
+      matteColor[2] = colToByte(rgb.b);
+      matteColor[3] = 255;
+      break;
+#if SPLASH_CMYK
+    case splashModeCMYK8:
+      colorMap->getColorSpace()->getCMYK(matteColorIn, &cmyk);
+      matteColor[0] = colToByte(cmyk.c);
+      matteColor[1] = colToByte(cmyk.m);
+      matteColor[2] = colToByte(cmyk.y);
+      matteColor[3] = colToByte(cmyk.k);
+      break;
+    case splashModeDeviceN8:
+      colorMap->getColorSpace()->getDeviceN(matteColorIn, &deviceN);
+      for (int cp = 0; cp < SPOT_NCOMPS+4; cp++)
+        matteColor[cp] = colToByte(deviceN.c[cp]);
+      break;
+#endif
+  }
+}
+
 void SplashOutputDev::setOverprintMask(GfxColorSpace *colorSpace,
 				       GBool overprintFlag,
 				       int overprintMode,
@@ -2899,6 +2944,9 @@ struct SplashOutImageData {
   int *maskColors;
   SplashColorMode colorMode;
   int width, height, y;
+  ImageStream *maskStr;
+  GfxImageColorMap *maskColorMap;
+  SplashColor matteColor;
 };
 
 #ifdef USE_CMS
@@ -2932,6 +2980,11 @@ GBool SplashOutputDev::useIccImageSrc(void *data) {
 }
 #endif
 
+// Clip x to lie in [0, 255].
+static inline Guchar clip255(int x) {
+  return x < 0 ? 0 : x > 255 ? 255 : x;
+}
+
 GBool SplashOutputDev::imageSrc(void *data, SplashColorPtr colorLine,
 				Guchar * /*alphaLine*/) {
   SplashOutImageData *imgData = (SplashOutImageData *)data;
@@ -3075,6 +3128,16 @@ GBool SplashOutputDev::imageSrc(void *data, SplashColorPtr colorLine,
     }
   }
 
+  if (imgData->maskStr != NULL && (p = imgData->maskStr->getLine()) != NULL) {
+    int destComps = splashColorModeNComps[imgData->colorMode];
+    int convComps = (imgData->colorMode == splashModeXBGR8) ? 3 : destComps;
+    imgData->maskColorMap->getGrayLine(p, p, imgData->width);
+    for (x = 0, q = colorLine; x < imgData->width; ++x, p++, q += destComps) {
+      for (int cp = 0; cp < convComps; cp++) {
+        q[cp] = (*p) ? clip255(imgData->matteColor[cp] + (int) (q[cp] - imgData->matteColor[cp]) * 255 / *p) : imgData->matteColor[cp];
+      }
+    }
+  }
   ++imgData->y;
   return gTrue;
 }
@@ -3415,6 +3478,8 @@ void SplashOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
   imgData.colorMode = colorMode;
   imgData.width = width;
   imgData.height = height;
+  imgData.maskStr = NULL;
+  imgData.maskColorMap = NULL;
   imgData.y = 0;
 
   // special case for one-channel (monochrome/gray/separation) images:
@@ -3879,6 +3944,8 @@ void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref,
   imgMaskData.width = maskWidth;
   imgMaskData.height = maskHeight;
   imgMaskData.y = 0;
+  imgMaskData.maskStr = NULL;
+  imgMaskData.maskColorMap = NULL;
   n = 1 << maskColorMap->getBits();
   imgMaskData.lookup = (SplashColorPtr)gmalloc(n);
   for (i = 0; i < n; ++i) {
@@ -3894,7 +3961,6 @@ void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref,
   maskSplash->drawImage(&imageSrc, NULL, &imgMaskData, splashModeMono8, gFalse,
 			maskWidth, maskHeight, mat, maskInterpolate);
   delete imgMaskData.imgStr;
-  maskStr->close();
   gfree(imgMaskData.lookup);
   delete maskSplash;
   splash->setSoftMask(maskBitmap);
@@ -3910,6 +3976,16 @@ void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref,
   imgData.colorMode = colorMode;
   imgData.width = width;
   imgData.height = height;
+  imgData.maskStr = NULL;
+  imgData.maskColorMap = NULL;
+  if (maskColorMap->getMatteColor() != NULL) {
+    getMatteColor(colorMode, colorMap, maskColorMap->getMatteColor(), imgData.matteColor);
+    imgData.maskColorMap = maskColorMap;
+    imgData.maskStr = new ImageStream(maskStr, maskWidth,
+				       maskColorMap->getNumPixelComps(),
+				       maskColorMap->getBits());
+    imgData.maskStr->reset();
+  }
   imgData.y = 0;
 
   // special case for one-channel (monochrome/gray/separation) images:
@@ -3982,7 +4058,9 @@ void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref,
   splash->drawImage(&imageSrc, NULL, &imgData, srcMode, gFalse, width, height, mat, interpolate);
   splash->setSoftMask(NULL);
   gfree(imgData.lookup);
+  delete imgData.maskStr;
   delete imgData.imgStr;
+  maskStr->close();
   str->close();
 }
 
diff --git a/poppler/SplashOutputDev.h b/poppler/SplashOutputDev.h
index ce4082f..16a6e81 100644
--- a/poppler/SplashOutputDev.h
+++ b/poppler/SplashOutputDev.h
@@ -14,7 +14,7 @@
 // under GPL version 2 or later
 //
 // Copyright (C) 2005 Takashi Iwai <tiwai at suse.de>
-// Copyright (C) 2009-2015 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2009-2016 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2009 Carlos Garcia Campos <carlosgc at gnome.org>
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
 // Copyright (C) 2011 Andreas Hartmetz <ahartmetz at gmail.com>
@@ -379,6 +379,7 @@ private:
   SplashPattern *getColor(GfxCMYK *cmyk);
   SplashPattern *getColor(GfxColor *deviceN);
 #endif
+  void getMatteColor( SplashColorMode colorMode, GfxImageColorMap *colorMap, GfxColor * matteColor, SplashColor splashMatteColor);
   void setOverprintMask(GfxColorSpace *colorSpace, GBool overprintFlag,
 			int overprintMode, GfxColor *singleColor, GBool grayIndexed = gFalse);
   SplashPath *convertPath(GfxState *state, GfxPath *path,


More information about the poppler mailing list