[poppler] 3 commits - poppler/CairoOutputDev.cc

Chris Wilson ickle at kemper.freedesktop.org
Wed Jul 8 09:41:09 PDT 2009


 poppler/CairoOutputDev.cc |  109 +++++++++++++++++++---------------------------
 1 file changed, 47 insertions(+), 62 deletions(-)

New commits:
commit 6ae0a6c0044713affa23eb1ee6a070785ed6c2f3
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jul 8 16:48:26 2009 +0100

    [cairo] premultiply image mask
    
    Cairo uses a premultiplied colour-space, so when creating the image mask
    in drawImage() we need to remember to multiply by the alpha. In this case
    it just requires zeroing out the masked pixels.

diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index b59e406..e033e50 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -1802,15 +1802,20 @@ void CairoOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
 
     if (maskColors) {
       for (int x = 0; x < width; x++) {
+	bool is_opaque = false;
 	for (int i = 0; i < colorMap->getNumPixelComps(); ++i) {
 	  if (pix[i] < maskColors[2*i] ||
 	      pix[i] > maskColors[2*i+1]) {
-	    *dest |= 0xff000000;
+	    is_opaque = true;
 	    break;
 	  }
 	}
-	pix += colorMap->getNumPixelComps();
+	if (is_opaque)
+	  *dest |= 0xff000000;
+	else
+	  *dest = 0;
 	dest++;
+	pix += colorMap->getNumPixelComps();
       }
     }
   }
commit 646e5884e748ecce7094c673400484aa1d902bdd
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jul 8 17:00:34 2009 +0100

    [cairo] maskColors is an array of ints, no scaling required
    
    drawImage() was erroneously scaling the maskColors from what it believed
    to be [0:1] to [0:255]. However maskColors is already an integer array,
    [0:255].

diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index eaabb50..b59e406 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -1803,8 +1803,8 @@ void CairoOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
     if (maskColors) {
       for (int x = 0; x < width; x++) {
 	for (int i = 0; i < colorMap->getNumPixelComps(); ++i) {
-	  if (pix[i] < 255*maskColors[2*i] ||
-	      pix[i] > 255*maskColors[2*i+1]) {
+	  if (pix[i] < maskColors[2*i] ||
+	      pix[i] > maskColors[2*i+1]) {
 	    *dest |= 0xff000000;
 	    break;
 	  }
commit d75feb1ee84385a9f94308cf47a43f4583092ddf
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jul 8 16:37:19 2009 +0100

    [cairo] cleanse DrawImage()
    
    Just a small bit of code rearrangement to reduce repetition and invalid checks.

diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index 2fa9815..eaabb50 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -1764,43 +1764,48 @@ void CairoOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
 			       GBool interpolate,
 			       int *maskColors, GBool inlineImg)
 {
-  unsigned char *buffer;
-  unsigned int *dest;
   cairo_surface_t *image;
   cairo_pattern_t *pattern;
-  int x, y;
   ImageStream *imgStr;
-  Guchar *pix;
-  int i;
   cairo_matrix_t matrix;
-  int is_identity_transform;
-  
-  buffer = (unsigned char *)gmallocn3 (width, height, 4);
+  unsigned char *buffer;
+  int stride;
 
   /* TODO: Do we want to cache these? */
   imgStr = new ImageStream(str, width,
 			   colorMap->getNumPixelComps(),
 			   colorMap->getBits());
   imgStr->reset();
-  
+
+#if 0
   /* ICCBased color space doesn't do any color correction
    * so check its underlying color space as well */
+  int is_identity_transform;
   is_identity_transform = colorMap->getColorSpace()->getMode() == csDeviceRGB ||
-		  (colorMap->getColorSpace()->getMode() == csICCBased && 
+		  (colorMap->getColorSpace()->getMode() == csICCBased &&
 		   ((GfxICCBasedColorSpace*)colorMap->getColorSpace())->getAlt()->getMode() == csDeviceRGB);
+#endif
+
+  image = cairo_image_surface_create (maskColors ?
+				      CAIRO_FORMAT_ARGB32 :
+				      CAIRO_FORMAT_RGB24,
+				      width, height);
+  if (cairo_surface_status (image))
+    goto cleanup;
+
+  buffer = cairo_image_surface_get_data (image);
+  stride = cairo_image_surface_get_stride (image);
+  for (int y = 0; y < height; y++) {
+    uint32_t *dest = (uint32_t *) (buffer + y * stride);
+    Guchar *pix = imgStr->getLine();
+    colorMap->getRGBLine (pix, dest, width);
 
-  if (maskColors) {
-    for (y = 0; y < height; y++) {
-      dest = (unsigned int *) (buffer + y * 4 * width);
-      pix = imgStr->getLine();
-      colorMap->getRGBLine (pix, dest, width);
-
-      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) {
-	    *dest = *dest | 0xff000000;
+    if (maskColors) {
+      for (int x = 0; x < width; x++) {
+	for (int i = 0; i < colorMap->getNumPixelComps(); ++i) {
+	  if (pix[i] < 255*maskColors[2*i] ||
+	      pix[i] > 255*maskColors[2*i+1]) {
+	    *dest |= 0xff000000;
 	    break;
 	  }
 	}
@@ -1808,64 +1813,39 @@ void CairoOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
 	dest++;
       }
     }
-
-    image = cairo_image_surface_create_for_data (buffer, CAIRO_FORMAT_ARGB32,
-						 width, height, width * 4);
   }
-  else {
-    for (y = 0; y < height; y++) {
-      dest = (unsigned int *) (buffer + y * 4 * width);
-      pix = imgStr->getLine();
-      colorMap->getRGBLine (pix, dest, width);
-    }
 
-    image = cairo_image_surface_create_for_data (buffer, CAIRO_FORMAT_RGB24,
-						 width, height, width * 4);
-  }
-
-  if (image == NULL) {
-   imgStr->close();
-   delete imgStr;
-   return;
-  }
   pattern = cairo_pattern_create_for_surface (image);
-  if (pattern == NULL) {
-    imgStr->close();
-    delete imgStr;
-    return;
-  }
+  cairo_surface_destroy (image);
+  if (cairo_pattern_status (pattern))
+    goto cleanup;
 
   LOG (printf ("drawImageMask %dx%d\n", width, height));
-  
+
   cairo_matrix_init_translate (&matrix, 0, height);
   cairo_matrix_scale (&matrix, width, -height);
 
   cairo_pattern_set_matrix (pattern, &matrix);
-
   cairo_pattern_set_filter (pattern,
-			    interpolate ? CAIRO_FILTER_BILINEAR : CAIRO_FILTER_FAST);
+			    interpolate ?
+			    CAIRO_FILTER_BILINEAR : CAIRO_FILTER_FAST);
+  cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
+
   cairo_set_source (cairo, pattern);
-  cairo_paint (cairo);
+  cairo_rectangle (cairo, 0., 0., width, height);
+  cairo_fill (cairo);
 
   if (cairo_shape) {
-#if 0
-    cairo_rectangle (cairo_shape, 0., 0., width, height);
-    cairo_fill (cairo_shape);
-#else
     cairo_save (cairo_shape);
-    /* this should draw a rectangle the size of the image
-     * we use this instead of rect,fill because of the lack
-     * of EXTEND_PAD */
-    /* NOTE: this will multiply the edges of the image twice */
+    cairo_rectangle (cairo_shape, 0., 0., width, height);
     cairo_set_source (cairo_shape, pattern);
-    cairo_paint(cairo_shape);
+    cairo_fill (cairo_shape);
     cairo_restore (cairo_shape);
-#endif
   }
 
   cairo_pattern_destroy (pattern);
-  cairo_surface_destroy (image);
-  free (buffer);
+
+cleanup:
   imgStr->close();
   delete imgStr;
 }


More information about the poppler mailing list