[poppler] 2 commits - poppler/CairoOutputDev.cc poppler/CairoOutputDev.h
Carlos Garcia Campos
carlosgc at kemper.freedesktop.org
Sun Feb 28 04:57:58 PST 2010
poppler/CairoOutputDev.cc | 116 ++++++++++++++++++++++++++++------------------
poppler/CairoOutputDev.h | 4 +
2 files changed, 77 insertions(+), 43 deletions(-)
New commits:
commit 5453cff5b7cb47cadfdae585a58409117af8c1f1
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date: Sun Feb 28 13:51:22 2010 +0100
[cairo] Select filter for images based on scale factor
When rendering images and interpolate flag is disabled or missing, we
always interpolate unless scale factor is >= 400%
See bugs #25268, #9860
diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index 41a3ff0..5cad4e7 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -1456,6 +1456,25 @@ cairo_surface_t *CairoOutputDev::downscaleSurface(cairo_surface_t *orig_surface)
}
+cairo_filter_t
+CairoOutputDev::getFilterForSurface(cairo_surface_t *image,
+ GBool interpolate)
+{
+ if (interpolate)
+ return CAIRO_FILTER_BILINEAR;
+
+ int orig_width = cairo_image_surface_get_width (image);
+ int orig_height = cairo_image_surface_get_height (image);
+ int scaled_width, scaled_height;
+ getScaledSize (orig_width, orig_height, &scaled_width, &scaled_height);
+
+ /* When scale factor is >= 400% we don't interpolate. See bugs #25268, #9860 */
+ if (scaled_width / orig_width >= 4 || scaled_height / orig_height >= 4)
+ return CAIRO_FILTER_NEAREST;
+
+ return CAIRO_FILTER_BILINEAR;
+}
+
void CairoOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
int width, int height, GBool invert,
GBool interpolate, GBool inlineImg) {
@@ -1518,6 +1537,7 @@ void CairoOutputDev::drawImageMaskRegular(GfxState *state, Object *ref, Stream *
cairo_matrix_t matrix;
int invert_bit;
int row_stride;
+ cairo_filter_t filter;
/* TODO: Do we want to cache these? */
imgStr = new ImageStream(str, width, 1, 1);
@@ -1544,6 +1564,8 @@ void CairoOutputDev::drawImageMaskRegular(GfxState *state, Object *ref, Stream *
}
}
+ filter = getFilterForSurface (image, interpolate);
+
cairo_surface_mark_dirty (image);
pattern = cairo_pattern_create_for_surface (image);
cairo_surface_destroy (image);
@@ -1552,11 +1574,8 @@ void CairoOutputDev::drawImageMaskRegular(GfxState *state, Object *ref, Stream *
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_filter (pattern, filter);
+
if (!printing)
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
@@ -1897,6 +1916,8 @@ void CairoOutputDev::drawMaskedImage(GfxState *state, Object *ref,
Guchar *pix;
int x, y;
int invert_bit;
+ cairo_filter_t filter;
+ cairo_filter_t maskFilter;
maskImgStr = new ImageStream(maskStr, maskWidth, 1, 1);
maskImgStr->reset();
@@ -1927,6 +1948,8 @@ void CairoOutputDev::drawMaskedImage(GfxState *state, Object *ref,
maskImgStr->close();
delete maskImgStr;
+ maskFilter = getFilterForSurface (maskImage, maskInterpolate);
+
cairo_surface_mark_dirty (maskImage);
maskPattern = cairo_pattern_create_for_surface (maskImage);
cairo_surface_destroy (maskImage);
@@ -1960,6 +1983,8 @@ void CairoOutputDev::drawMaskedImage(GfxState *state, Object *ref,
colorMap->getRGBLine (pix, dest, width);
}
+ filter = getFilterForSurface (image, interpolate);
+
cairo_surface_mark_dirty (image);
pattern = cairo_pattern_create_for_surface (image);
cairo_surface_destroy (image);
@@ -1968,10 +1993,9 @@ void CairoOutputDev::drawMaskedImage(GfxState *state, Object *ref,
LOG (printf ("drawMaskedImage %dx%d\n", width, height));
- 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_pattern_set_filter (pattern, filter);
+ cairo_pattern_set_filter (maskPattern, maskFilter);
+
if (!printing) {
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
cairo_pattern_set_extend (maskPattern, CAIRO_EXTEND_PAD);
@@ -2038,6 +2062,8 @@ void CairoOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *s
cairo_matrix_t maskMatrix, matrix;
Guchar *pix;
int y;
+ cairo_filter_t filter;
+ cairo_filter_t maskFilter;
maskImgStr = new ImageStream(maskStr, maskWidth,
maskColorMap->getNumPixelComps(),
@@ -2062,6 +2088,8 @@ void CairoOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *s
maskImgStr->close();
delete maskImgStr;
+ maskFilter = getFilterForSurface (maskImage, maskInterpolate);
+
cairo_surface_mark_dirty (maskImage);
maskPattern = cairo_pattern_create_for_surface (maskImage);
cairo_surface_destroy (maskImage);
@@ -2095,6 +2123,8 @@ void CairoOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *s
colorMap->getRGBLine (pix, dest, width);
}
+ filter = getFilterForSurface (image, interpolate);
+
cairo_surface_mark_dirty (image);
pattern = cairo_pattern_create_for_surface (image);
cairo_surface_destroy (image);
@@ -2103,11 +2133,9 @@ void CairoOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *s
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_filter (maskPattern,
- maskInterpolate ? CAIRO_FILTER_BILINEAR : CAIRO_FILTER_FAST);
+ cairo_pattern_set_filter (pattern, filter);
+ cairo_pattern_set_filter (maskPattern, maskFilter);
+
if (!printing) {
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
cairo_pattern_set_extend (maskPattern, CAIRO_EXTEND_PAD);
@@ -2193,6 +2221,7 @@ void CairoOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
unsigned char *buffer;
int stride, i;
GfxRGB *lookup = NULL;
+ cairo_filter_t filter = CAIRO_FILTER_BILINEAR;
/* TODO: Do we want to cache these? */
imgStr = new ImageStream(str, width,
@@ -2286,6 +2315,8 @@ void CairoOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
image = scaled_surface;
width = cairo_image_surface_get_width (image);
height = cairo_image_surface_get_height (image);
+ } else {
+ filter = getFilterForSurface (image, interpolate);
}
cairo_surface_mark_dirty (image);
@@ -2313,9 +2344,8 @@ void CairoOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
if (cairo_pattern_status (pattern))
goto cleanup;
- cairo_pattern_set_filter (pattern,
- interpolate ?
- CAIRO_FILTER_BILINEAR : CAIRO_FILTER_FAST);
+ cairo_pattern_set_filter (pattern, filter);
+
if (!printing)
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h
index 17c060b..02a4955 100644
--- a/poppler/CairoOutputDev.h
+++ b/poppler/CairoOutputDev.h
@@ -272,6 +272,8 @@ protected:
cairo_surface_t *downscaleSurface(cairo_surface_t *orig_surface);
void getScaledSize(int orig_width, int orig_height,
int *scaledWidth, int *scaledHeight);
+ cairo_filter_t getFilterForSurface(cairo_surface_t *image,
+ GBool interpolate);
GBool getStreamData (Stream *str, char **buffer, int *length);
GfxRGB fill_color, stroke_color;
commit e65456cbd5cae2750426aabeb2d66a10537616f0
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date: Sun Feb 28 13:13:13 2010 +0100
[cairo] Refactor scaled size computation into a new method
diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index d421431..41a3ff0 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -1370,27 +1370,13 @@ get_singular_values (const cairo_matrix_t *matrix,
*minor = sqrt (f - delta);
}
-
-cairo_surface_t *CairoOutputDev::downscaleSurface(cairo_surface_t *orig_surface) {
- cairo_surface_t *dest_surface;
- unsigned char *dest_buffer;
- int dest_stride;
- unsigned char *orig_buffer;
- int orig_width, orig_height;
- int orig_stride;
- GBool res;
-
- if (printing)
- return NULL;
-
-
- orig_width = cairo_image_surface_get_width (orig_surface);
- orig_height = cairo_image_surface_get_height (orig_surface);
-
+void CairoOutputDev::getScaledSize(int orig_width,
+ int orig_height,
+ int *scaledWidth,
+ int *scaledHeight) {
cairo_matrix_t matrix;
cairo_get_matrix(cairo, &matrix);
- /* this whole computation should be factored out */
double xScale;
double yScale;
if (orig_width > orig_height)
@@ -1399,8 +1385,6 @@ cairo_surface_t *CairoOutputDev::downscaleSurface(cairo_surface_t *orig_surface)
get_singular_values (&matrix, &yScale, &xScale);
int tx, tx2, ty, ty2; /* the integer co-oridinates of the resulting image */
- int scaledHeight;
- int scaledWidth;
if (xScale >= 0) {
tx = splashRound(matrix.x0 - 0.01);
tx2 = splashRound(matrix.x0 + xScale + 0.01) - 1;
@@ -1408,13 +1392,13 @@ cairo_surface_t *CairoOutputDev::downscaleSurface(cairo_surface_t *orig_surface)
tx = splashRound(matrix.x0 + 0.01) - 1;
tx2 = splashRound(matrix.x0 + xScale - 0.01);
}
- scaledWidth = abs(tx2 - tx) + 1;
+ *scaledWidth = abs(tx2 - tx) + 1;
//scaledWidth = splashRound(fabs(xScale));
- if (scaledWidth == 0) {
+ if (*scaledWidth == 0) {
// technically, this should draw nothing, but it generally seems
// better to draw a one-pixel-wide stripe rather than throwing it
// away
- scaledWidth = 1;
+ *scaledWidth = 1;
}
if (yScale >= 0) {
ty = splashFloor(matrix.y0 + 0.01);
@@ -1423,13 +1407,29 @@ cairo_surface_t *CairoOutputDev::downscaleSurface(cairo_surface_t *orig_surface)
ty = splashCeil(matrix.y0 - 0.01);
ty2 = splashFloor(matrix.y0 + yScale + 0.01);
}
- scaledHeight = abs(ty2 - ty);
- if (scaledHeight == 0) {
- scaledHeight = 1;
+ *scaledHeight = abs(ty2 - ty);
+ if (*scaledHeight == 0) {
+ *scaledHeight = 1;
}
+}
+
+cairo_surface_t *CairoOutputDev::downscaleSurface(cairo_surface_t *orig_surface) {
+ cairo_surface_t *dest_surface;
+ unsigned char *dest_buffer;
+ int dest_stride;
+ unsigned char *orig_buffer;
+ int orig_width, orig_height;
+ int orig_stride;
+ int scaledHeight;
+ int scaledWidth;
+ GBool res;
+
+ if (printing)
+ return NULL;
orig_width = cairo_image_surface_get_width (orig_surface);
orig_height = cairo_image_surface_get_height (orig_surface);
+ getScaledSize (orig_width, orig_height, &scaledWidth, &scaledHeight);
if (scaledWidth >= orig_width || scaledHeight >= orig_height)
return NULL;
diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h
index e47825e..17c060b 100644
--- a/poppler/CairoOutputDev.h
+++ b/poppler/CairoOutputDev.h
@@ -270,6 +270,8 @@ public:
protected:
void doPath(cairo_t *cairo, GfxState *state, GfxPath *path);
cairo_surface_t *downscaleSurface(cairo_surface_t *orig_surface);
+ void getScaledSize(int orig_width, int orig_height,
+ int *scaledWidth, int *scaledHeight);
GBool getStreamData (Stream *str, char **buffer, int *length);
GfxRGB fill_color, stroke_color;
More information about the poppler
mailing list