[poppler] 4 commits - poppler/CairoOutputDev.cc

Carlos Garcia Campos carlosgc at kemper.freedesktop.org
Sun Jul 26 10:36:27 PDT 2009


 poppler/CairoOutputDev.cc |  355 +++++++++++++++++++++-------------------------
 1 file changed, 166 insertions(+), 189 deletions(-)

New commits:
commit 512b2c654fd80c83b82e7adc828a478a18de17ab
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Sun Jul 26 19:35:06 2009 +0200

    [cairo] Use CAIRO_EXTEND_PAD in drawImageMaskPrescaled too

diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index 417c115..670ae40 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -1338,13 +1338,16 @@ void CairoOutputDev::drawImageMaskPrescaled(GfxState *state, Object *ref, Stream
 
   invert_bit = invert ? 1 : 0;
 
-  row_stride = (scaledWidth + 3) & ~3;
-  buffer = (unsigned char *) malloc (scaledHeight * row_stride);
-  if (buffer == NULL) {
-    error(-1, "Unable to allocate memory for image.");
+  image = cairo_image_surface_create (CAIRO_FORMAT_A8, scaledWidth, scaledHeight);
+  if (cairo_surface_status (image)) {
+    imgStr->close();
+    delete imgStr;
     return;
   }
 
+  buffer = cairo_image_surface_get_data (image);
+  row_stride = cairo_image_surface_get_stride (image);
+
   int yp = height / scaledHeight;
   int yq = height % scaledHeight;
   int xp = width / scaledWidth;
@@ -1458,16 +1461,9 @@ void CairoOutputDev::drawImageMaskPrescaled(GfxState *state, Object *ref, Stream
   }
   free(pixBuf);
 
-  //XXX: we should handle error's better than this
-  image = cairo_image_surface_create_for_data (buffer, CAIRO_FORMAT_A8,
-      scaledWidth, scaledHeight, row_stride);
-  if (image == NULL) {
-    imgStr->close();
-    delete imgStr;
-    return;
-  }
   pattern = cairo_pattern_create_for_surface (image);
-  if (pattern == NULL) {
+  cairo_surface_destroy (image);
+  if (cairo_pattern_status (pattern)) {
     imgStr->close();
     delete imgStr;
     return;
@@ -1478,6 +1474,7 @@ void CairoOutputDev::drawImageMaskPrescaled(GfxState *state, Object *ref, Stream
    * images with CAIRO_FILTER_NEAREST to look really bad */
   cairo_pattern_set_filter (pattern,
 			    interpolate ? CAIRO_FILTER_BEST : CAIRO_FILTER_FAST);
+  cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
 
   cairo_save (cairo);
 
@@ -1490,6 +1487,8 @@ void CairoOutputDev::drawImageMaskPrescaled(GfxState *state, Object *ref, Stream
   if (yScale > 0)
     cairo_scale(cairo, 1, -1);
 
+  cairo_rectangle (cairo, 0., 0., scaledWidth, scaledHeight);
+  cairo_clip (cairo);
   cairo_mask (cairo, pattern);
 
   //cairo_get_matrix(cairo, &matrix);
@@ -1508,15 +1507,14 @@ void CairoOutputDev::drawImageMaskPrescaled(GfxState *state, Object *ref, Stream
     if (yScale > 0)
       cairo_scale(cairo_shape, 1, -1);
 
-    cairo_mask (cairo_shape, pattern);
+    cairo_rectangle (cairo_shape, 0., 0., scaledWidth, scaledHeight);
+    cairo_fill (cairo_shape);
 
     cairo_restore(cairo_shape);
   }
 
-
   cairo_pattern_destroy (pattern);
-  cairo_surface_destroy (image);
-  free (buffer);
+
   imgStr->close();
   delete imgStr;
 }
commit ad26e34bede53cb6300bc463cbdcc2b5adf101c2
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Sun Jul 26 18:36:06 2009 +0200

    [cairo] Use rectangle + clip instead of invert + tranform
    
    This is just for consistency of drawImage methods

diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index 65364f8..417c115 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -1223,18 +1223,18 @@ void CairoOutputDev::drawImageMaskRegular(GfxState *state, Object *ref, Stream *
 
   cairo_matrix_init_translate (&matrix, 0, height);
   cairo_matrix_scale (&matrix, width, -height);
-  cairo_matrix_invert (&matrix);
+  cairo_pattern_set_matrix (pattern, &matrix);
 
   cairo_save (cairo);
-  cairo_transform (cairo, &matrix);
+  cairo_rectangle (cairo, 0., 0., 1., 1.);
+  cairo_clip (cairo);
   cairo_mask (cairo, pattern);
   cairo_restore (cairo);
 
   if (cairo_shape) {
     cairo_save (cairo_shape);
-    cairo_transform (cairo_shape, &matrix);
     cairo_set_source (cairo_shape, pattern);
-    cairo_rectangle (cairo_shape, 0., 0., width, height);
+    cairo_rectangle (cairo_shape, 0., 0., 1., 1.);
     cairo_fill (cairo_shape);
     cairo_restore (cairo_shape);
   }
@@ -1618,21 +1618,21 @@ void CairoOutputDev::drawMaskedImage(GfxState *state, Object *ref,
 
   cairo_matrix_init_translate (&matrix, 0, height);
   cairo_matrix_scale (&matrix, width, -height);
-  cairo_matrix_invert (&matrix);
+
+  cairo_pattern_set_matrix (pattern, &matrix);
+  cairo_pattern_set_matrix (maskPattern, &matrix);
 
   cairo_save (cairo);
-  cairo_transform (cairo, &matrix);
   cairo_set_source (cairo, pattern);
-  cairo_rectangle (cairo, 0, 0, width, height);
+  cairo_rectangle (cairo, 0., 0., 1., 1.);
   cairo_clip (cairo);
   cairo_mask (cairo, maskPattern);
   cairo_restore (cairo);
 
   if (cairo_shape) {
     cairo_save (cairo_shape);
-    cairo_transform (cairo_shape, &matrix);
     cairo_set_source (cairo_shape, pattern);
-    cairo_rectangle (cairo_shape, 0., 0., width, height);
+    cairo_rectangle (cairo_shape, 0., 0., 1., 1.);
     cairo_fill (cairo_shape);
     cairo_restore (cairo_shape);
   }
@@ -1668,8 +1668,8 @@ void CairoOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *s
   int y;
 
   maskImgStr = new ImageStream(maskStr, maskWidth,
-				       maskColorMap->getNumPixelComps(),
-				       maskColorMap->getBits());
+			       maskColorMap->getNumPixelComps(),
+			       maskColorMap->getBits());
   maskImgStr->reset();
 
   maskImage = cairo_image_surface_create (CAIRO_FORMAT_A8, maskWidth, maskHeight);
@@ -1880,20 +1880,18 @@ void CairoOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
 
   cairo_matrix_init_translate (&matrix, 0, height);
   cairo_matrix_scale (&matrix, width, -height);
-  cairo_matrix_invert (&matrix);
+  cairo_pattern_set_matrix (pattern, &matrix);
 
   cairo_save (cairo);
-  cairo_transform (cairo, &matrix);
   cairo_set_source (cairo, pattern);
-  cairo_rectangle (cairo, 0., 0., width, height);
+  cairo_rectangle (cairo, 0., 0., 1., 1.);
   cairo_fill (cairo);
   cairo_restore (cairo);
 
   if (cairo_shape) {
     cairo_save (cairo_shape);
-    cairo_transform (cairo_shape, &matrix);
     cairo_set_source (cairo_shape, pattern);
-    cairo_rectangle (cairo_shape, 0., 0., width, height);
+    cairo_rectangle (cairo_shape, 0., 0., 1., 1.);
     cairo_fill (cairo_shape);
     cairo_restore (cairo_shape);
   }
commit ee6b761a55baef4c3bbe4614b0c3b3d761a3111f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Jul 26 16:19:15 2009 +0200

    [cairo] Apply a clip for masked drawImage
    
    In order to use EXTEND_PAD with a mask, we need to apply a clip (to
    constrain the image to the appropriate region). The complicating factor for
    drawSoftImage() is that mask size is independent of the image size, so we
    need to compute the intersection of the mask with in the image in userspace.

diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index 6860922..65364f8 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -1623,6 +1623,8 @@ void CairoOutputDev::drawMaskedImage(GfxState *state, Object *ref,
   cairo_save (cairo);
   cairo_transform (cairo, &matrix);
   cairo_set_source (cairo, pattern);
+  cairo_rectangle (cairo, 0, 0, width, height);
+  cairo_clip (cairo);
   cairo_mask (cairo, maskPattern);
   cairo_restore (cairo);
 
@@ -1688,6 +1690,11 @@ void CairoOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *s
   maskImgStr->close();
   delete maskImgStr;
 
+  maskPattern = cairo_pattern_create_for_surface (maskImage);
+  cairo_surface_destroy (maskImage);
+  if (cairo_pattern_status (maskPattern))
+    return;
+
 #if 0
   /* ICCBased color space doesn't do any color correction
    * so check its underlying color space as well */
@@ -1719,12 +1726,6 @@ void CairoOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *s
   cairo_surface_destroy (image);
   if (cairo_pattern_status (pattern))
     goto cleanup;
-  maskPattern = cairo_pattern_create_for_surface (maskImage);
-  cairo_surface_destroy (maskImage);
-  if (cairo_pattern_status (maskPattern)) {
-    cairo_surface_destroy (image);
-    goto cleanup;
-  }
 
   LOG (printf ("drawSoftMaskedImage %dx%d\n", width, height));
 
@@ -1746,13 +1747,19 @@ void CairoOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *s
 
   cairo_save (cairo);
   cairo_set_source (cairo, pattern);
+  cairo_rectangle (cairo, 0., 0.,
+		   MIN (width, maskWidth) / (double)width,
+		   MIN (height, maskHeight) / (double)height);
+  cairo_clip (cairo);
   cairo_mask (cairo, maskPattern);
   cairo_restore (cairo);
 
   if (cairo_shape) {
     cairo_save (cairo_shape);
     cairo_set_source (cairo_shape, pattern);
-    cairo_rectangle (cairo_shape, 0., 0., width, height);
+    cairo_rectangle (cairo_shape, 0., 0.,
+		     MIN (width, maskWidth) / (double)width,
+		     MIN (height, maskHeight) / (double)height);
     cairo_fill (cairo_shape);
     cairo_restore (cairo_shape);
   }
commit 499c6c972bac14936b5370276da723a6e98861b3
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Sun Jul 26 11:30:08 2009 +0200

    [cairo] Use CAIRO_EXTEND_PAD when drawing images

diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index 0f9b621..6860922 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -1182,17 +1182,17 @@ void CairoOutputDev::drawImageMaskRegular(GfxState *state, Object *ref, Stream *
   int invert_bit;
   int row_stride;
 
-  row_stride = (width + 3) & ~3;
-  buffer = (unsigned char *) malloc (height * row_stride);
-  if (buffer == NULL) {
-    error(-1, "Unable to allocate memory for image.");
-    return;
-  }
-
   /* TODO: Do we want to cache these? */
   imgStr = new ImageStream(str, width, 1, 1);
   imgStr->reset();
 
+  image = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
+  if (cairo_surface_status (image))
+    goto cleanup;
+
+  buffer = cairo_image_surface_get_data (image);
+  row_stride = cairo_image_surface_get_stride (image);
+
   invert_bit = invert ? 1 : 0;
 
   for (y = 0; y < height; y++) {
@@ -1207,53 +1207,41 @@ void CairoOutputDev::drawImageMaskRegular(GfxState *state, Object *ref, Stream *
     }
   }
 
-  image = cairo_image_surface_create_for_data (buffer, CAIRO_FORMAT_A8,
-					       width, height, row_stride);
-  if (image == NULL) {
-    imgStr->close();
-    delete imgStr;
-    return;
-  }
   pattern = cairo_pattern_create_for_surface (image);
-  if (pattern == NULL) {
-    imgStr->close();
-    delete imgStr;
-    return;
-  }
-
-  cairo_matrix_init_translate (&matrix, 0, height);
-  cairo_matrix_scale (&matrix, width, -height);
+  cairo_surface_destroy (image);
+  if (cairo_pattern_status (pattern))
+    goto cleanup;
 
-  cairo_pattern_set_matrix (pattern, &matrix);
+  LOG (printf ("drawImageMask %dx%d\n", width, height));
 
   /* we should actually be using CAIRO_FILTER_NEAREST here. However,
    * cairo doesn't yet do minifaction filtering causing scaled down
    * images with CAIRO_FILTER_NEAREST to look really bad */
   cairo_pattern_set_filter (pattern,
 			    interpolate ? CAIRO_FILTER_BEST : CAIRO_FILTER_FAST);
+  cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
 
+  cairo_matrix_init_translate (&matrix, 0, height);
+  cairo_matrix_scale (&matrix, width, -height);
+  cairo_matrix_invert (&matrix);
+
+  cairo_save (cairo);
+  cairo_transform (cairo, &matrix);
   cairo_mask (cairo, pattern);
+  cairo_restore (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_transform (cairo_shape, &matrix);
     cairo_set_source (cairo_shape, pattern);
-    cairo_mask (cairo_shape, pattern);
+    cairo_rectangle (cairo_shape, 0., 0., width, height);
+    cairo_fill (cairo_shape);
     cairo_restore (cairo_shape);
-#endif
   }
 
-
   cairo_pattern_destroy (pattern);
-  cairo_surface_destroy (image);
-  free (buffer);
+
+cleanup:
   imgStr->close();
   delete imgStr;
 }
@@ -1541,21 +1529,31 @@ void CairoOutputDev::drawMaskedImage(GfxState *state, Object *ref,
 				     int maskHeight, GBool maskInvert,
 				     GBool maskInterpolate)
 {
-  ImageStream *maskImgStr;
-  maskImgStr = new ImageStream(maskStr, maskWidth, 1, 1);
-  maskImgStr->reset();
-
-  int row_stride = (maskWidth + 3) & ~3;
-  unsigned char *maskBuffer;
-  maskBuffer = (unsigned char *)gmallocn (row_stride, maskHeight);
+  ImageStream *maskImgStr, *imgStr;
+  int row_stride;
+  unsigned char *maskBuffer, *buffer;
   unsigned char *maskDest;
-  cairo_surface_t *maskImage;
-  cairo_pattern_t *maskPattern;
+  unsigned int *dest;
+  cairo_surface_t *maskImage, *image;
+  cairo_pattern_t *maskPattern, *pattern;
+  cairo_matrix_t matrix;
   Guchar *pix;
   int x, y;
-
   int invert_bit;
-  
+
+  maskImgStr = new ImageStream(maskStr, maskWidth, 1, 1);
+  maskImgStr->reset();
+
+  maskImage = cairo_image_surface_create (CAIRO_FORMAT_A8, maskWidth, maskHeight);
+  if (cairo_surface_status (maskImage)) {
+    maskImgStr->close();
+    delete maskImgStr;
+    return;
+  }
+
+  maskBuffer = cairo_image_surface_get_data (maskImage);
+  row_stride = cairo_image_surface_get_stride (maskImage);
+
   invert_bit = maskInvert ? 1 : 0;
 
   for (y = 0; y < maskHeight; y++) {
@@ -1569,93 +1567,78 @@ void CairoOutputDev::drawMaskedImage(GfxState *state, Object *ref,
     }
   }
 
-  maskImage = cairo_image_surface_create_for_data (maskBuffer, CAIRO_FORMAT_A8,
-						 maskWidth, maskHeight, row_stride);
   maskImgStr->close();
   delete maskImgStr;
 
-  unsigned char *buffer;
-  unsigned int *dest;
-  cairo_surface_t *image;
-  cairo_pattern_t *pattern;
-  ImageStream *imgStr;
-  cairo_matrix_t matrix;
-  int is_identity_transform;
+  maskPattern = cairo_pattern_create_for_surface (maskImage);
+  cairo_surface_destroy (maskImage);
+  if (cairo_pattern_status (maskPattern))
+    return;
 
-  buffer = (unsigned char *)gmallocn3 (width, height, 4);
+#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 && 
+		   ((GfxICCBasedColorSpace*)colorMap->getColorSpace())->getAlt()->getMode() == csDeviceRGB);
+#endif
 
   /* TODO: Do we want to cache these? */
   imgStr = new ImageStream(str, width,
 			   colorMap->getNumPixelComps(),
 			   colorMap->getBits());
   imgStr->reset();
-  
-  /* ICCBased color space doesn't do any color correction
-   * so check its underlying color space as well */
-  is_identity_transform = colorMap->getColorSpace()->getMode() == csDeviceRGB ||
-		  (colorMap->getColorSpace()->getMode() == csICCBased && 
-		   ((GfxICCBasedColorSpace*)colorMap->getColorSpace())->getAlt()->getMode() == csDeviceRGB);
 
+  image = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
+  if (cairo_surface_status (image))
+    goto cleanup;
+
+  buffer = cairo_image_surface_get_data (image);
+  row_stride = cairo_image_surface_get_stride (image);
   for (y = 0; y < height; y++) {
-    dest = (unsigned int *) (buffer + y * 4 * width);
+    dest = (unsigned int *) (buffer + y * row_stride);
     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);
-  maskPattern = cairo_pattern_create_for_surface (maskImage);
-  if (pattern == NULL) {
-    imgStr->close();
-    delete imgStr;
-    return;
-  }
+  cairo_surface_destroy (image);
+  if (cairo_pattern_status (pattern))
+    goto cleanup;
 
   LOG (printf ("drawMaskedImage %dx%d\n", width, height));
 
-  cairo_matrix_init_translate (&matrix, 0, height);
-  cairo_matrix_scale (&matrix, width, -height);
-
-  /* scale the mask to the size of the image unlike softMask */
-  cairo_pattern_set_matrix (pattern, &matrix);
-  cairo_pattern_set_matrix (maskPattern, &matrix);
-
   cairo_pattern_set_filter (pattern,
 			    interpolate ? CAIRO_FILTER_BILINEAR : CAIRO_FILTER_FAST);
+  cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
   cairo_pattern_set_filter (maskPattern,
 			    maskInterpolate ? CAIRO_FILTER_BILINEAR : CAIRO_FILTER_FAST);
+  cairo_pattern_set_extend (maskPattern, CAIRO_EXTEND_PAD);
+
+  cairo_matrix_init_translate (&matrix, 0, height);
+  cairo_matrix_scale (&matrix, width, -height);
+  cairo_matrix_invert (&matrix);
+
+  cairo_save (cairo);
+  cairo_transform (cairo, &matrix);
   cairo_set_source (cairo, pattern);
   cairo_mask (cairo, maskPattern);
+  cairo_restore (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_transform (cairo_shape, &matrix);
     cairo_set_source (cairo_shape, pattern);
-    cairo_mask (cairo_shape, pattern);
+    cairo_rectangle (cairo_shape, 0., 0., width, height);
+    cairo_fill (cairo_shape);
     cairo_restore (cairo_shape);
-#endif
   }
 
   cairo_pattern_destroy (maskPattern);
-  cairo_surface_destroy (maskImage);
   cairo_pattern_destroy (pattern);
-  cairo_surface_destroy (image);
-  free (buffer);
-  free (maskBuffer);
+
+cleanup:
   imgStr->close();
   delete imgStr;
 }
@@ -1671,122 +1654,117 @@ void CairoOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *s
 					 GfxImageColorMap *maskColorMap,
 					 GBool maskInterpolate)
 {
-  ImageStream *maskImgStr;
+  ImageStream *maskImgStr, *imgStr;
+  int row_stride;
+  unsigned char *maskBuffer, *buffer;
+  unsigned char *maskDest;
+  unsigned int *dest;
+  cairo_surface_t *maskImage, *image;
+  cairo_pattern_t *maskPattern, *pattern;
+  cairo_matrix_t maskMatrix, matrix;
+  Guchar *pix;
+  int y;
+
   maskImgStr = new ImageStream(maskStr, maskWidth,
 				       maskColorMap->getNumPixelComps(),
 				       maskColorMap->getBits());
   maskImgStr->reset();
 
-  int row_stride = (maskWidth + 3) & ~3;
-  unsigned char *maskBuffer;
-  maskBuffer = (unsigned char *)gmallocn (row_stride, maskHeight);
-  unsigned char *maskDest;
-  cairo_surface_t *maskImage;
-  cairo_pattern_t *maskPattern;
-  Guchar *pix;
-  int y;
+  maskImage = cairo_image_surface_create (CAIRO_FORMAT_A8, maskWidth, maskHeight);
+  if (cairo_surface_status (maskImage)) {
+    maskImgStr->close();
+    delete maskImgStr;
+    return;
+  }
+
+  maskBuffer = cairo_image_surface_get_data (maskImage);
+  row_stride = cairo_image_surface_get_stride (maskImage);
   for (y = 0; y < maskHeight; y++) {
     maskDest = (unsigned char *) (maskBuffer + y * row_stride);
     pix = maskImgStr->getLine();
     maskColorMap->getGrayLine (pix, maskDest, maskWidth);
   }
 
-  maskImage = cairo_image_surface_create_for_data (maskBuffer, CAIRO_FORMAT_A8,
-						 maskWidth, maskHeight, row_stride);
-
   maskImgStr->close();
   delete maskImgStr;
 
-  unsigned char *buffer;
-  unsigned int *dest;
-  cairo_surface_t *image;
-  cairo_pattern_t *pattern;
-  ImageStream *imgStr;
-  cairo_matrix_t matrix;
-  cairo_matrix_t maskMatrix;
+#if 0
+  /* ICCBased color space doesn't do any color correction
+   * so check its underlying color space as well */
   int is_identity_transform;
-
-  buffer = (unsigned char *)gmallocn3 (width, height, 4);
+  is_identity_transform = colorMap->getColorSpace()->getMode() == csDeviceRGB ||
+		  (colorMap->getColorSpace()->getMode() == csICCBased &&
+		   ((GfxICCBasedColorSpace*)colorMap->getColorSpace())->getAlt()->getMode() == csDeviceRGB);
+#endif
 
   /* TODO: Do we want to cache these? */
   imgStr = new ImageStream(str, width,
 			   colorMap->getNumPixelComps(),
 			   colorMap->getBits());
   imgStr->reset();
-  
-  /* ICCBased color space doesn't do any color correction
-   * so check its underlying color space as well */
-  is_identity_transform = colorMap->getColorSpace()->getMode() == csDeviceRGB ||
-		  (colorMap->getColorSpace()->getMode() == csICCBased && 
-		   ((GfxICCBasedColorSpace*)colorMap->getColorSpace())->getAlt()->getMode() == csDeviceRGB);
 
+  image = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
+  if (cairo_surface_status (image))
+    goto cleanup;
+
+  buffer = cairo_image_surface_get_data (image);
+  row_stride = cairo_image_surface_get_stride (image);
   for (y = 0; y < height; y++) {
-    dest = (unsigned int *) (buffer + y * 4 * width);
+    dest = (unsigned int *) (buffer + y * row_stride);
     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);
+  cairo_surface_destroy (image);
+  if (cairo_pattern_status (pattern))
+    goto cleanup;
   maskPattern = cairo_pattern_create_for_surface (maskImage);
-  if (pattern == NULL) {
-    imgStr->close();
-    delete imgStr;
-    return;
+  cairo_surface_destroy (maskImage);
+  if (cairo_pattern_status (maskPattern)) {
+    cairo_surface_destroy (image);
+    goto cleanup;
   }
 
   LOG (printf ("drawSoftMaskedImage %dx%d\n", width, height));
 
+  //XXX: should set mask filter
+  cairo_pattern_set_filter (pattern,
+			    interpolate ? CAIRO_FILTER_BILINEAR : CAIRO_FILTER_FAST);
+  cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
+  cairo_pattern_set_filter (maskPattern,
+			    maskInterpolate ? CAIRO_FILTER_BILINEAR : CAIRO_FILTER_FAST);
+  cairo_pattern_set_extend (maskPattern, CAIRO_EXTEND_PAD);
+
   cairo_matrix_init_translate (&matrix, 0, height);
   cairo_matrix_scale (&matrix, width, -height);
+  cairo_pattern_set_matrix (pattern, &matrix);
 
   cairo_matrix_init_translate (&maskMatrix, 0, maskHeight);
   cairo_matrix_scale (&maskMatrix, maskWidth, -maskHeight);
-
-  cairo_pattern_set_matrix (pattern, &matrix);
   cairo_pattern_set_matrix (maskPattern, &maskMatrix);
 
-  //XXX: should set mask filter
-  cairo_pattern_set_filter (pattern,
-			    interpolate ? CAIRO_FILTER_BILINEAR : CAIRO_FILTER_FAST);
-  cairo_pattern_set_filter (maskPattern,
-			    maskInterpolate ? CAIRO_FILTER_BILINEAR : CAIRO_FILTER_FAST);
+  cairo_save (cairo);
   cairo_set_source (cairo, pattern);
   cairo_mask (cairo, maskPattern);
+  cairo_restore (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_set_source (cairo_shape, pattern);
-    cairo_mask (cairo_shape, pattern);
+    cairo_rectangle (cairo_shape, 0., 0., width, height);
+    cairo_fill (cairo_shape);
     cairo_restore (cairo_shape);
-#endif
   }
 
   cairo_pattern_destroy (maskPattern);
-  cairo_surface_destroy (maskImage);
   cairo_pattern_destroy (pattern);
-  cairo_surface_destroy (image);
-  free (buffer);
-  free (maskBuffer);
 
+cleanup:
   imgStr->close();
   delete imgStr;
 }
+
 void CairoOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
 			       int width, int height,
 			       GfxImageColorMap *colorMap,
@@ -1886,17 +1864,13 @@ void CairoOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
   if (cairo_pattern_status (pattern))
     goto cleanup;
 
-  LOG (printf ("drawImageMask %dx%d\n", width, height));
+  LOG (printf ("drawImage %dx%d\n", width, height));
 
   cairo_pattern_set_filter (pattern,
 			    interpolate ?
 			    CAIRO_FILTER_BILINEAR : CAIRO_FILTER_FAST);
   cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
 
-  /* XXX Undo the transformation applied before drawImage(), once all
-   * painters have been fixed to use PAD we can then fix the callers
-   * not to apply useless transformations.
-   */
   cairo_matrix_init_translate (&matrix, 0, height);
   cairo_matrix_scale (&matrix, width, -height);
   cairo_matrix_invert (&matrix);
@@ -1911,8 +1885,8 @@ void CairoOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
   if (cairo_shape) {
     cairo_save (cairo_shape);
     cairo_transform (cairo_shape, &matrix);
-    cairo_rectangle (cairo_shape, 0., 0., width, height);
     cairo_set_source (cairo_shape, pattern);
+    cairo_rectangle (cairo_shape, 0., 0., width, height);
     cairo_fill (cairo_shape);
     cairo_restore (cairo_shape);
   }


More information about the poppler mailing list