summaryrefslogtreecommitdiff
path: root/poppler
diff options
context:
space:
mode:
authorJeff Muizelaar <jeff@infidigm.net>2006-04-12 06:52:07 +0000
committerJeff Muizelaar <jeff@infidigm.net>2006-04-12 06:52:07 +0000
commit85687a1e0e4c6be2dbfb23ba00018b9c7c7454f5 (patch)
tree3a69f4af13e4f76f2613f23231a95c211ea2508e /poppler
parent6039d4fc65cb25bef20efa29bc29d42086fc0854 (diff)
2006-04-12 Jeff Muizelaar <jeff@infidigm.net>
* poppler/CairoOutputDev.cc: * poppler/CairoOutputDev.h: Add support for masked images to the cairo backend. CairoOutputDevice really should have been refactored before committing this, but the results were so pretty I couldn't resist. Fixes #6174.
Diffstat (limited to 'poppler')
-rw-r--r--poppler/CairoOutputDev.cc118
-rw-r--r--poppler/CairoOutputDev.h8
2 files changed, 126 insertions, 0 deletions
diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index 7e83ae5a..654df1bd 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -549,6 +549,124 @@ void CairoOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
delete imgStr;
}
+void CairoOutputDev::drawMaskedImage(GfxState *state, Object *ref,
+ Stream *str, int width, int height,
+ GfxImageColorMap *colorMap,
+ Stream *maskStr, int maskWidth,
+ int maskHeight, GBool maskInvert)
+{
+ ImageStream *maskImgStr;
+ maskImgStr = new ImageStream(maskStr, maskWidth, 1, 1);
+ maskImgStr->reset();
+
+ int row_stride = (maskWidth + 3) & ~3;
+ unsigned char *maskBuffer;
+ maskBuffer = (unsigned char *)gmalloc (row_stride * maskHeight);
+ unsigned char *maskDest;
+ cairo_surface_t *maskImage;
+ cairo_pattern_t *maskPattern;
+ Guchar *pix;
+ int x, y;
+
+ int invert_bit;
+
+ invert_bit = maskInvert ? 1 : 0;
+
+ for (y = 0; y < height; y++) {
+ pix = maskImgStr->getLine();
+ maskDest = maskBuffer + y * row_stride;
+ for (x = 0; x < width; x++) {
+ if (pix[x] ^ invert_bit)
+ *maskDest++ = 0;
+ else
+ *maskDest++ = 255;
+ }
+ }
+
+ maskImage = cairo_image_surface_create_for_data (maskBuffer, CAIRO_FORMAT_A8,
+ maskWidth, maskHeight, row_stride);
+
+ delete maskImgStr;
+ maskStr->close();
+
+ unsigned char *buffer;
+ unsigned int *dest;
+ cairo_surface_t *image;
+ cairo_pattern_t *pattern;
+ ImageStream *imgStr;
+ GfxRGB rgb;
+ int alpha, i;
+ double *ctm;
+ cairo_matrix_t matrix;
+ cairo_matrix_t maskMatrix;
+ int is_identity_transform;
+
+ buffer = (unsigned char *)gmalloc (width * height * 4);
+
+ /* 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;
+
+ 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)
+ return;
+ pattern = cairo_pattern_create_for_surface (image);
+ maskPattern = cairo_pattern_create_for_surface (maskImage);
+ if (pattern == NULL)
+ return;
+
+ ctm = state->getCTM();
+ LOG (printf ("drawImageMask %dx%d, matrix: %f, %f, %f, %f, %f, %f\n",
+ width, height, ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]));
+ matrix.xx = ctm[0] / width;
+ matrix.xy = -ctm[2] / height;
+ matrix.yx = ctm[1] / width;
+ matrix.yy = -ctm[3] / height;
+ matrix.x0 = ctm[2] + ctm[4];
+ matrix.y0 = ctm[3] + ctm[5];
+
+ maskMatrix.xx = ctm[0] / maskWidth;
+ maskMatrix.xy = -ctm[2] / maskHeight;
+ maskMatrix.yx = ctm[1] / maskWidth;
+ maskMatrix.yy = -ctm[3] / maskHeight;
+ maskMatrix.x0 = ctm[2] + ctm[4];
+ maskMatrix.y0 = ctm[3] + ctm[5];
+
+ cairo_matrix_invert (&matrix);
+ cairo_matrix_invert (&maskMatrix);
+
+ cairo_pattern_set_matrix (pattern, &matrix);
+ cairo_pattern_set_matrix (maskPattern, &maskMatrix);
+
+ cairo_pattern_set_filter (pattern, CAIRO_FILTER_BILINEAR);
+ cairo_set_source (cairo, pattern);
+ cairo_mask (cairo, maskPattern);
+
+ cairo_pattern_destroy (maskPattern);
+ cairo_surface_destroy (maskImage);
+ cairo_pattern_destroy (pattern);
+ cairo_surface_destroy (image);
+ free (buffer);
+ free (maskBuffer);
+ delete imgStr;
+}
+
void CairoOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str,
int width, int height,
GfxImageColorMap *colorMap,
diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h
index f2c7284a..7300fc49 100644
--- a/poppler/CairoOutputDev.h
+++ b/poppler/CairoOutputDev.h
@@ -124,6 +124,14 @@ public:
int maskWidth, int maskHeight,
GfxImageColorMap *maskColorMap);
+ virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str,
+ int width, int height,
+ GfxImageColorMap *colorMap,
+ Stream *maskStr,
+ int maskWidth, int maskHeight,
+ GBool maskInvert);
+
+
//----- Type 3 font operators
virtual void type3D0(GfxState *state, double wx, double wy);
virtual void type3D1(GfxState *state, double wx, double wy,