- use alternative/upstream downscale patch (#556549, fdo#5589)
This commit is contained in:
parent
93db35491e
commit
1314fce69a
517
poppler-0.12.3-downscale.patch
Normal file
517
poppler-0.12.3-downscale.patch
Normal file
@ -0,0 +1,517 @@
|
|||||||
|
diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
|
||||||
|
index 9a0f3be..42ac3a8 100644
|
||||||
|
--- a/poppler/CairoOutputDev.cc
|
||||||
|
+++ b/poppler/CairoOutputDev.cc
|
||||||
|
@@ -58,6 +58,7 @@
|
||||||
|
#include <splash/SplashBitmap.h>
|
||||||
|
#include "CairoOutputDev.h"
|
||||||
|
#include "CairoFontEngine.h"
|
||||||
|
+#include "CairoRescaleBox.h"
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// #define LOG_CAIRO
|
||||||
|
@@ -1331,6 +1332,82 @@ void CairoOutputDev::endMaskClip(GfxState *state) {
|
||||||
|
clearSoftMask(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
+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;
|
||||||
|
+
|
||||||
|
+ cairo_matrix_t matrix;
|
||||||
|
+ cairo_get_matrix(cairo, &matrix);
|
||||||
|
+
|
||||||
|
+ /* this whole computation should be factored out */
|
||||||
|
+ double xScale = matrix.xx;
|
||||||
|
+ double yScale = matrix.yy;
|
||||||
|
+ 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;
|
||||||
|
+ } else {
|
||||||
|
+ tx = splashRound(matrix.x0 + 0.01) - 1;
|
||||||
|
+ tx2 = splashRound(matrix.x0 + xScale - 0.01);
|
||||||
|
+ }
|
||||||
|
+ scaledWidth = abs(tx2 - tx) + 1;
|
||||||
|
+ //scaledWidth = splashRound(fabs(xScale));
|
||||||
|
+ 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;
|
||||||
|
+ }
|
||||||
|
+ if (yScale >= 0) {
|
||||||
|
+ ty = splashFloor(matrix.y0 + 0.01);
|
||||||
|
+ ty2 = splashCeil(matrix.y0 + yScale - 0.01);
|
||||||
|
+ } else {
|
||||||
|
+ ty = splashCeil(matrix.y0 - 0.01);
|
||||||
|
+ ty2 = splashFloor(matrix.y0 + yScale + 0.01);
|
||||||
|
+ }
|
||||||
|
+ scaledHeight = abs(ty2 - ty);
|
||||||
|
+ if (scaledHeight == 0) {
|
||||||
|
+ scaledHeight = 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ orig_width = cairo_image_surface_get_width (orig_surface);
|
||||||
|
+ orig_height = cairo_image_surface_get_height (orig_surface);
|
||||||
|
+ if (scaledWidth >= orig_width || scaledHeight >= orig_height)
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ dest_surface = cairo_surface_create_similar (orig_surface,
|
||||||
|
+ cairo_surface_get_content (orig_surface),
|
||||||
|
+ scaledWidth, scaledHeight);
|
||||||
|
+ dest_buffer = cairo_image_surface_get_data (dest_surface);
|
||||||
|
+ dest_stride = cairo_image_surface_get_stride (dest_surface);
|
||||||
|
+
|
||||||
|
+ orig_buffer = cairo_image_surface_get_data (orig_surface);
|
||||||
|
+ orig_stride = cairo_image_surface_get_stride (orig_surface);
|
||||||
|
+
|
||||||
|
+ res = downscale_box_filter((uint32_t *)orig_buffer,
|
||||||
|
+ orig_stride, orig_width, orig_height,
|
||||||
|
+ scaledWidth, scaledHeight, 0, 0,
|
||||||
|
+ scaledWidth, scaledHeight,
|
||||||
|
+ (uint32_t *)dest_buffer, dest_stride);
|
||||||
|
+ if (!res) {
|
||||||
|
+ cairo_surface_destroy (dest_surface);
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return dest_surface;
|
||||||
|
+
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void CairoOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
|
||||||
|
int width, int height, GBool invert,
|
||||||
|
GBool interpolate, GBool inlineImg) {
|
||||||
|
@@ -2094,6 +2171,18 @@ void CairoOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
|
||||||
|
}
|
||||||
|
gfree(lookup);
|
||||||
|
|
||||||
|
+ cairo_surface_t *scaled_surface;
|
||||||
|
+
|
||||||
|
+ scaled_surface = downscaleSurface (image);
|
||||||
|
+ if (scaled_surface) {
|
||||||
|
+ if (cairo_surface_status (scaled_surface))
|
||||||
|
+ goto cleanup;
|
||||||
|
+ cairo_surface_destroy (image);
|
||||||
|
+ image = scaled_surface;
|
||||||
|
+ width = cairo_image_surface_get_width (image);
|
||||||
|
+ height = cairo_image_surface_get_height (image);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
cairo_surface_mark_dirty (image);
|
||||||
|
pattern = cairo_pattern_create_for_surface (image);
|
||||||
|
cairo_surface_destroy (image);
|
||||||
|
diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h
|
||||||
|
index fb9c0d7..266f0cb 100644
|
||||||
|
--- a/poppler/CairoOutputDev.h
|
||||||
|
+++ b/poppler/CairoOutputDev.h
|
||||||
|
@@ -268,6 +268,7 @@ public:
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void doPath(cairo_t *cairo, GfxState *state, GfxPath *path);
|
||||||
|
+ cairo_surface_t *downscaleSurface(cairo_surface_t *orig_surface);
|
||||||
|
|
||||||
|
GfxRGB fill_color, stroke_color;
|
||||||
|
cairo_pattern_t *fill_pattern, *stroke_pattern;
|
||||||
|
diff --git a/poppler/CairoRescaleBox.cc b/poppler/CairoRescaleBox.cc
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..dce5ddd
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/poppler/CairoRescaleBox.cc
|
||||||
|
@@ -0,0 +1,352 @@
|
||||||
|
+/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
|
||||||
|
+/*
|
||||||
|
+ * Copyright © 2009 Mozilla Corporation
|
||||||
|
+ *
|
||||||
|
+ * Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
+ * documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
+ * the above copyright notice appear in all copies and that both that
|
||||||
|
+ * copyright notice and this permission notice appear in supporting
|
||||||
|
+ * documentation, and that the name of Mozilla Corporation not be used in
|
||||||
|
+ * advertising or publicity pertaining to distribution of the software without
|
||||||
|
+ * specific, written prior permission. Mozilla Corporation makes no
|
||||||
|
+ * representations about the suitability of this software for any purpose. It
|
||||||
|
+ * is provided "as is" without express or implied warranty.
|
||||||
|
+ *
|
||||||
|
+ * MOZILLA CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
|
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
|
||||||
|
+ * SHALL MOZILLA CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
|
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
|
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
|
+ * OF THIS SOFTWARE.
|
||||||
|
+ *
|
||||||
|
+ * Author: Jeff Muizelaar, Mozilla Corp.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+/* This implements a box filter that supports non-integer box sizes */
|
||||||
|
+
|
||||||
|
+#ifdef HAVE_CONFIG_H
|
||||||
|
+#include <config.h>
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#include <stdint.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <assert.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <math.h>
|
||||||
|
+#include "goo/gmem.h"
|
||||||
|
+#include "CairoRescaleBox.h"
|
||||||
|
+
|
||||||
|
+typedef unsigned short int uint16_t;
|
||||||
|
+typedef unsigned int uint32_t;
|
||||||
|
+
|
||||||
|
+/* we work in fixed point where 1. == 1 << 24 */
|
||||||
|
+#define FIXED_SHIFT 24
|
||||||
|
+
|
||||||
|
+static void downsample_row_box_filter (
|
||||||
|
+ int start, int width,
|
||||||
|
+ uint32_t *src, uint32_t *dest,
|
||||||
|
+ int coverage[], int pixel_coverage)
|
||||||
|
+{
|
||||||
|
+ /* we need an array of the pixel contribution of each destination pixel on the boundaries.
|
||||||
|
+ * we invert the value to get the value on the other size of the box */
|
||||||
|
+ /*
|
||||||
|
+
|
||||||
|
+ value = a * contribution * 1/box_size
|
||||||
|
+ value += a * 1/box_size
|
||||||
|
+ value += a * 1/box_size
|
||||||
|
+ value += a * 1/box_size
|
||||||
|
+ value += a * (1 - contribution) * 1/box_size
|
||||||
|
+ a * (1/box_size - contribution * 1/box_size)
|
||||||
|
+
|
||||||
|
+ box size is constant
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ value = a * contribtion_a * 1/box_size + b * contribution_b * 1/box_size
|
||||||
|
+ contribution_b = (1 - contribution_a)
|
||||||
|
+ = (1 - contribution_a_next)
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+ /* box size = ceil(src_width/dest_width) */
|
||||||
|
+ int x = 0;
|
||||||
|
+
|
||||||
|
+ /* skip to start */
|
||||||
|
+ /* XXX: it might be possible to do this directly instead of iteratively, however
|
||||||
|
+ * the iterative solution is simple */
|
||||||
|
+ while (x < start)
|
||||||
|
+ {
|
||||||
|
+ int box = 1 << FIXED_SHIFT;
|
||||||
|
+ int start_coverage = coverage[x];
|
||||||
|
+ box -= start_coverage;
|
||||||
|
+ src++;
|
||||||
|
+ while (box >= pixel_coverage)
|
||||||
|
+ {
|
||||||
|
+ src++;
|
||||||
|
+ box -= pixel_coverage;
|
||||||
|
+ }
|
||||||
|
+ x++;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ while (x < start + width)
|
||||||
|
+ {
|
||||||
|
+ uint32_t a = 0;
|
||||||
|
+ uint32_t r = 0;
|
||||||
|
+ uint32_t g = 0;
|
||||||
|
+ uint32_t b = 0;
|
||||||
|
+ int box = 1 << FIXED_SHIFT;
|
||||||
|
+ int start_coverage = coverage[x];
|
||||||
|
+
|
||||||
|
+ a = ((*src >> 24) & 0xff) * start_coverage;
|
||||||
|
+ r = ((*src >> 16) & 0xff) * start_coverage;
|
||||||
|
+ g = ((*src >> 8) & 0xff) * start_coverage;
|
||||||
|
+ b = ((*src >> 0) & 0xff) * start_coverage;
|
||||||
|
+ src++;
|
||||||
|
+ x++;
|
||||||
|
+ box -= start_coverage;
|
||||||
|
+
|
||||||
|
+ while (box >= pixel_coverage)
|
||||||
|
+ {
|
||||||
|
+ a += ((*src >> 24) & 0xff) * pixel_coverage;
|
||||||
|
+ r += ((*src >> 16) & 0xff) * pixel_coverage;
|
||||||
|
+ g += ((*src >> 8) & 0xff) * pixel_coverage;
|
||||||
|
+ b += ((*src >> 0) & 0xff) * pixel_coverage;
|
||||||
|
+ src++;
|
||||||
|
+
|
||||||
|
+ box -= pixel_coverage;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* multiply by whatever is leftover
|
||||||
|
+ * this ensures that we don't bias down.
|
||||||
|
+ * i.e. start_coverage + n*pixel_coverage + box == 1 << 24 */
|
||||||
|
+ if (box > 0)
|
||||||
|
+ {
|
||||||
|
+ a += ((*src >> 24) & 0xff) * box;
|
||||||
|
+ r += ((*src >> 16) & 0xff) * box;
|
||||||
|
+ g += ((*src >> 8) & 0xff) * box;
|
||||||
|
+ b += ((*src >> 0) & 0xff) * box;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ a >>= FIXED_SHIFT;
|
||||||
|
+ r >>= FIXED_SHIFT;
|
||||||
|
+ g >>= FIXED_SHIFT;
|
||||||
|
+ b >>= FIXED_SHIFT;
|
||||||
|
+
|
||||||
|
+ *dest = (a << 24) | (r << 16) | (g << 8) | b;
|
||||||
|
+ dest++;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void downsample_columns_box_filter (
|
||||||
|
+ int n,
|
||||||
|
+ int start_coverage,
|
||||||
|
+ int pixel_coverage,
|
||||||
|
+ uint32_t *src, uint32_t *dest)
|
||||||
|
+{
|
||||||
|
+ int stride = n;
|
||||||
|
+ while (n--) {
|
||||||
|
+ uint32_t a = 0;
|
||||||
|
+ uint32_t r = 0;
|
||||||
|
+ uint32_t g = 0;
|
||||||
|
+ uint32_t b = 0;
|
||||||
|
+ uint32_t *column_src = src;
|
||||||
|
+ int box = 1 << FIXED_SHIFT;
|
||||||
|
+
|
||||||
|
+ a = ((*column_src >> 24) & 0xff) * start_coverage;
|
||||||
|
+ r = ((*column_src >> 16) & 0xff) * start_coverage;
|
||||||
|
+ g = ((*column_src >> 8) & 0xff) * start_coverage;
|
||||||
|
+ b = ((*column_src >> 0) & 0xff) * start_coverage;
|
||||||
|
+ column_src += stride;
|
||||||
|
+ box -= start_coverage;
|
||||||
|
+
|
||||||
|
+ while (box >= pixel_coverage)
|
||||||
|
+ {
|
||||||
|
+ a += ((*column_src >> 24) & 0xff) * pixel_coverage;
|
||||||
|
+ r += ((*column_src >> 16) & 0xff) * pixel_coverage;
|
||||||
|
+ g += ((*column_src >> 8) & 0xff) * pixel_coverage;
|
||||||
|
+ b += ((*column_src >> 0) & 0xff) * pixel_coverage;
|
||||||
|
+ column_src += stride;
|
||||||
|
+ box -= pixel_coverage;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (box > 0) {
|
||||||
|
+ a += ((*column_src >> 24) & 0xff) * box;
|
||||||
|
+ r += ((*column_src >> 16) & 0xff) * box;
|
||||||
|
+ g += ((*column_src >> 8) & 0xff) * box;
|
||||||
|
+ b += ((*column_src >> 0) & 0xff) * box;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ a >>= FIXED_SHIFT;
|
||||||
|
+ r >>= FIXED_SHIFT;
|
||||||
|
+ g >>= FIXED_SHIFT;
|
||||||
|
+ b >>= FIXED_SHIFT;
|
||||||
|
+
|
||||||
|
+ *dest = (a << 24) | (r << 16) | (g << 8) | b;
|
||||||
|
+ dest++;
|
||||||
|
+ src++;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int compute_coverage (int coverage[], int src_length, int dest_length)
|
||||||
|
+{
|
||||||
|
+ int i;
|
||||||
|
+ /* num = src_length/dest_length
|
||||||
|
+ total = sum(pixel) / num
|
||||||
|
+
|
||||||
|
+ pixel * 1/num == pixel * dest_length / src_length
|
||||||
|
+ */
|
||||||
|
+ /* the average contribution of each source pixel */
|
||||||
|
+ int ratio = ((1 << 24)*(long long int)dest_length)/src_length;
|
||||||
|
+ /* because ((1 << 24)*(long long int)dest_length) won't always be divisible by src_length
|
||||||
|
+ * we'll need someplace to put the other bits.
|
||||||
|
+ *
|
||||||
|
+ * We want to ensure a + n*ratio < 1<<24
|
||||||
|
+ *
|
||||||
|
+ * 1<<24
|
||||||
|
+ * */
|
||||||
|
+
|
||||||
|
+ double scale = (double)src_length/dest_length;
|
||||||
|
+
|
||||||
|
+ /* for each destination pixel compute the coverage of the left most pixel included in the box */
|
||||||
|
+ /* I have a proof of this, which this margin is too narrow to contain */
|
||||||
|
+ for (i=0; i<dest_length; i++)
|
||||||
|
+ {
|
||||||
|
+ float left_side = i*scale;
|
||||||
|
+ float right_side = (i+1)*scale;
|
||||||
|
+ float right_fract = right_side - floor (right_side);
|
||||||
|
+ float left_fract = ceil (left_side) - left_side;
|
||||||
|
+ int overage;
|
||||||
|
+ /* find out how many source pixels will be used to fill the box */
|
||||||
|
+ int count = floor (right_side) - ceil (left_side);
|
||||||
|
+ /* what's the maximum value this expression can become?
|
||||||
|
+ floor((i+1)*scale) - ceil(i*scale)
|
||||||
|
+
|
||||||
|
+ (i+1)*scale - i*scale == scale
|
||||||
|
+
|
||||||
|
+ since floor((i+1)*scale) <= (i+1)*scale
|
||||||
|
+ and ceil(i*scale) >= i*scale
|
||||||
|
+
|
||||||
|
+ floor((i+1)*scale) - ceil(i*scale) <= scale
|
||||||
|
+
|
||||||
|
+ further since: floor((i+1)*scale) - ceil(i*scale) is an integer
|
||||||
|
+
|
||||||
|
+ therefore:
|
||||||
|
+ floor((i+1)*scale) - ceil(i*scale) <= floor(scale)
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+ if (left_fract == 0.)
|
||||||
|
+ count--;
|
||||||
|
+
|
||||||
|
+ /* compute how much the right-most pixel contributes */
|
||||||
|
+ overage = ratio*(right_fract);
|
||||||
|
+
|
||||||
|
+ /* the remainder is the the amount that the left-most pixel
|
||||||
|
+ * contributes */
|
||||||
|
+ coverage[i] = (1<<24) - (count * ratio + overage);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return ratio;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+GBool downscale_box_filter(uint32_t *orig, int orig_stride, unsigned orig_width, unsigned orig_height,
|
||||||
|
+ signed scaled_width, signed scaled_height,
|
||||||
|
+ uint16_t start_column, uint16_t start_row,
|
||||||
|
+ uint16_t width, uint16_t height,
|
||||||
|
+ uint32_t *dest, int dst_stride)
|
||||||
|
+{
|
||||||
|
+ int pixel_coverage_x, pixel_coverage_y;
|
||||||
|
+ int dest_y;
|
||||||
|
+ int src_y = 0;
|
||||||
|
+ uint32_t *scanline = orig;
|
||||||
|
+ int *x_coverage = NULL;
|
||||||
|
+ int *y_coverage = NULL;
|
||||||
|
+ uint32_t *temp_buf = NULL;
|
||||||
|
+ GBool retval = gFalse;
|
||||||
|
+
|
||||||
|
+ x_coverage = (int *)gmallocn3 (orig_width, 1, sizeof(int));
|
||||||
|
+ y_coverage = (int *)gmallocn3 (orig_height, 1, sizeof(int));
|
||||||
|
+
|
||||||
|
+ /* we need to allocate enough room for ceil(src_height/dest_height)+1
|
||||||
|
+ Example:
|
||||||
|
+ src_height = 140
|
||||||
|
+ dest_height = 50
|
||||||
|
+ src_height/dest_height = 2.8
|
||||||
|
+
|
||||||
|
+ |-------------| 2.8 pixels
|
||||||
|
+ |----|----|----|----| 4 pixels
|
||||||
|
+ need to sample 3 pixels
|
||||||
|
+
|
||||||
|
+ |-------------| 2.8 pixels
|
||||||
|
+ |----|----|----|----| 4 pixels
|
||||||
|
+ need to sample 4 pixels
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+ temp_buf = (uint32_t *)gmallocn3 ((orig_height + scaled_height-1)/scaled_height+1, scaled_width, sizeof(uint32_t));
|
||||||
|
+
|
||||||
|
+ if (!x_coverage || !y_coverage || !scanline || !temp_buf)
|
||||||
|
+ goto cleanup;
|
||||||
|
+
|
||||||
|
+ pixel_coverage_x = compute_coverage (x_coverage, orig_width, scaled_width);
|
||||||
|
+ pixel_coverage_y = compute_coverage (y_coverage, orig_height, scaled_height);
|
||||||
|
+
|
||||||
|
+ assert (width + start_column <= scaled_width);
|
||||||
|
+
|
||||||
|
+ /* skip the rows at the beginning */
|
||||||
|
+ for (dest_y = 0; dest_y < start_row; dest_y++)
|
||||||
|
+ {
|
||||||
|
+ int box = 1 << FIXED_SHIFT;
|
||||||
|
+ int start_coverage_y = y_coverage[dest_y];
|
||||||
|
+ box -= start_coverage_y;
|
||||||
|
+ src_y++;
|
||||||
|
+ while (box >= pixel_coverage_y)
|
||||||
|
+ {
|
||||||
|
+ box -= pixel_coverage_y;
|
||||||
|
+ src_y++;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (; dest_y < start_row + height; dest_y++)
|
||||||
|
+ {
|
||||||
|
+ int columns = 0;
|
||||||
|
+ int box = 1 << FIXED_SHIFT;
|
||||||
|
+ int start_coverage_y = y_coverage[dest_y];
|
||||||
|
+
|
||||||
|
+ scanline = orig + src_y * orig_stride / 4;
|
||||||
|
+ downsample_row_box_filter (start_column, width, scanline, temp_buf + width * columns, x_coverage, pixel_coverage_x);
|
||||||
|
+ columns++;
|
||||||
|
+ src_y++;
|
||||||
|
+ box -= start_coverage_y;
|
||||||
|
+
|
||||||
|
+ while (box >= pixel_coverage_y)
|
||||||
|
+ {
|
||||||
|
+ scanline = orig + src_y * orig_stride / 4;
|
||||||
|
+ downsample_row_box_filter (start_column, width, scanline, temp_buf + width * columns, x_coverage, pixel_coverage_x);
|
||||||
|
+ columns++;
|
||||||
|
+ src_y++;
|
||||||
|
+ box -= pixel_coverage_y;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* downsample any leftovers */
|
||||||
|
+ if (box > 0)
|
||||||
|
+ {
|
||||||
|
+ scanline = orig + src_y * orig_stride / 4;
|
||||||
|
+ downsample_row_box_filter (start_column, width, scanline, temp_buf + width * columns, x_coverage, pixel_coverage_x);
|
||||||
|
+ columns++;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* now scale the rows we just downsampled in the y direction */
|
||||||
|
+ downsample_columns_box_filter (width, start_coverage_y, pixel_coverage_y, temp_buf, dest);
|
||||||
|
+ dest += dst_stride / 4;
|
||||||
|
+
|
||||||
|
+// assert(width*columns <= ((orig_height + scaled_height-1)/scaled_height+1) * width);
|
||||||
|
+ }
|
||||||
|
+// assert (src_y<=orig_height);
|
||||||
|
+
|
||||||
|
+ retval = gTrue;
|
||||||
|
+
|
||||||
|
+cleanup:
|
||||||
|
+ free (x_coverage);
|
||||||
|
+ free (y_coverage);
|
||||||
|
+ free (temp_buf);
|
||||||
|
+
|
||||||
|
+ return gTrue;
|
||||||
|
+}
|
||||||
|
diff --git a/poppler/CairoRescaleBox.h b/poppler/CairoRescaleBox.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..5349c87
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/poppler/CairoRescaleBox.h
|
||||||
|
@@ -0,0 +1,12 @@
|
||||||
|
+#ifndef CAIRO_RESCALE_BOX_H
|
||||||
|
+#define CAIRO_RESCALE_BOX_H
|
||||||
|
+
|
||||||
|
+#include "goo/gtypes.h"
|
||||||
|
+
|
||||||
|
+GBool downscale_box_filter(unsigned int *orig, int orig_stride, unsigned orig_width, unsigned orig_height,
|
||||||
|
+ signed scaled_width, signed scaled_height,
|
||||||
|
+ unsigned short int start_column, unsigned short int start_row,
|
||||||
|
+ unsigned short int width, unsigned short int height,
|
||||||
|
+ unsigned int *dest, int dst_stride);
|
||||||
|
+
|
||||||
|
+#endif /* CAIRO_RESCALE_BOX_H */
|
||||||
|
diff --git a/poppler/Makefile.am b/poppler/Makefile.am
|
||||||
|
index ec79e31..096ea76 100644
|
||||||
|
--- a/poppler/Makefile.am
|
||||||
|
+++ b/poppler/Makefile.am
|
||||||
|
@@ -47,7 +47,9 @@ libpoppler_cairo_la_SOURCES = \
|
||||||
|
CairoFontEngine.cc \
|
||||||
|
CairoFontEngine.h \
|
||||||
|
CairoOutputDev.cc \
|
||||||
|
- CairoOutputDev.h
|
||||||
|
+ CairoOutputDev.h \
|
||||||
|
+ CairoRescaleBox.cc \
|
||||||
|
+ CairoRescaleBox.h
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
@ -1,153 +0,0 @@
|
|||||||
diff -up poppler-0.12.3/poppler/CairoOutputDev.cc.rex poppler-0.12.3/poppler/CairoOutputDev.cc
|
|
||||||
--- poppler-0.12.3/poppler/CairoOutputDev.cc.rex 2009-12-24 04:41:22.000000000 -0600
|
|
||||||
+++ poppler-0.12.3/poppler/CairoOutputDev.cc 2010-01-19 12:14:33.210386122 -0600
|
|
||||||
@@ -97,6 +97,69 @@ void CairoImage::setImage (cairo_surface
|
|
||||||
this->image = cairo_surface_reference (image);
|
|
||||||
}
|
|
||||||
|
|
||||||
+// basic 2D box filter
|
|
||||||
+void PrescaleARGB(unsigned int * source,int width,int height,int stride,unsigned int * dest,int scaledWidth,int scaledHeight,int scaledStride)
|
|
||||||
+{
|
|
||||||
+ stride/=4;
|
|
||||||
+ scaledStride/=4;
|
|
||||||
+ // sanity check
|
|
||||||
+ if (scaledHeight>height || scaledWidth>width || scaledHeight<=0 || scaledWidth<=0 || stride<width || scaledStride<scaledWidth) return;
|
|
||||||
+ if (source==NULL || dest==NULL) return;
|
|
||||||
+
|
|
||||||
+ unsigned int * pLine,*pt;
|
|
||||||
+
|
|
||||||
+ int x,y,z;
|
|
||||||
+ unsigned int sum1,sum2,sum3,sum4;
|
|
||||||
+ int sx,sy,oy;
|
|
||||||
+ int count,dx,dy;
|
|
||||||
+
|
|
||||||
+ // calculate pixelwidths
|
|
||||||
+ int * pixelwidth=new int[scaledWidth];
|
|
||||||
+ int n,l=0;
|
|
||||||
+ for(x=0;x<scaledWidth;x++)
|
|
||||||
+ {
|
|
||||||
+ n=((x+1)*width-1)/scaledWidth;
|
|
||||||
+ pixelwidth[x]=n-l;
|
|
||||||
+ // assert(pixelwidth[x]);
|
|
||||||
+ l=n;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ pLine=source;
|
|
||||||
+ oy=0;
|
|
||||||
+ for(y=0;y<scaledHeight;y++)
|
|
||||||
+ { // column
|
|
||||||
+ z=y*scaledStride;
|
|
||||||
+ pLine=source+oy*stride;
|
|
||||||
+ n=((y+1)*height-1)/scaledHeight;
|
|
||||||
+ dy=n-oy;
|
|
||||||
+ for(x=0;x<scaledWidth;x++)
|
|
||||||
+ { // row
|
|
||||||
+ dx=pixelwidth[x];
|
|
||||||
+ pt=pLine; // temp storage line pointer
|
|
||||||
+ sum1=sum2=sum3=sum4=0;
|
|
||||||
+ for(sy=0;sy<dy;sy++)
|
|
||||||
+ { // sum y
|
|
||||||
+ for(sx=0;sx<dx;sx++)
|
|
||||||
+ { // sum x
|
|
||||||
+ sum1+=pLine[sx]&0xFF;
|
|
||||||
+ sum2+=(pLine[sx]>>8)&0xFF;
|
|
||||||
+ sum3+=(pLine[sx]>>16)&0xFF;
|
|
||||||
+ sum4+=pLine[sx]>>24;
|
|
||||||
+ } // sum x
|
|
||||||
+ pLine+=stride;
|
|
||||||
+ } // sum y
|
|
||||||
+ pLine=pt+dx;
|
|
||||||
+ count=dx*dy;
|
|
||||||
+ dest[z++]=sum1/count+(sum2/count<<8)+(sum3/count<<16)+(sum4/count<<24);
|
|
||||||
+ } // row
|
|
||||||
+ oy+=dy;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ delete [] pixelwidth;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
// CairoOutputDev
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
@@ -1975,13 +2038,40 @@ void CairoOutputDev::drawImage(GfxState
|
|
||||||
((GfxICCBasedColorSpace*)colorMap->getColorSpace())->getAlt()->getMode() == csDeviceRGB);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+ int scaledWidth,scaledHeight,scaledStride;
|
|
||||||
+ unsigned char * scaledBuffer;
|
|
||||||
+
|
|
||||||
+ cairo_get_matrix(cairo, &matrix);
|
|
||||||
+ scaledWidth=fabs(matrix.xx+matrix.yx)+0.5;
|
|
||||||
+ scaledHeight=fabs(matrix.xy+matrix.yy)+0.5;
|
|
||||||
+
|
|
||||||
+ if (printing || scaledWidth>=width || scaledHeight>=height)
|
|
||||||
+ { // no prescaling => render directly to cairo_image
|
|
||||||
+ scaledWidth=width;
|
|
||||||
+ scaledHeight=height;
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ { // first render to ARGB buffer then downsample to cairo_image
|
|
||||||
+ stride = width*4;
|
|
||||||
+ buffer = new unsigned char [stride*height];
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
image = cairo_image_surface_create (maskColors ?
|
|
||||||
CAIRO_FORMAT_ARGB32 :
|
|
||||||
CAIRO_FORMAT_RGB24,
|
|
||||||
- width, height);
|
|
||||||
+ scaledWidth, scaledHeight);
|
|
||||||
if (cairo_surface_status (image))
|
|
||||||
goto cleanup;
|
|
||||||
+
|
|
||||||
+ scaledBuffer = cairo_image_surface_get_data (image);
|
|
||||||
+ scaledStride = cairo_image_surface_get_stride (image);
|
|
||||||
|
|
||||||
+ if (scaledWidth>=width || scaledHeight>=height)
|
|
||||||
+ { // no prescaling => render directly to cairo_image
|
|
||||||
+ stride = scaledStride;
|
|
||||||
+ buffer = scaledBuffer;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
// special case for one-channel (monochrome/gray/separation) images:
|
|
||||||
// build a lookup table here
|
|
||||||
if (colorMap->getNumPixelComps() == 1) {
|
|
||||||
@@ -1994,11 +2084,9 @@ void CairoOutputDev::drawImage(GfxState
|
|
||||||
pix = (Guchar)i;
|
|
||||||
|
|
||||||
colorMap->getRGB(&pix, &lookup[i]);
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- 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();
|
|
||||||
@@ -2040,6 +2128,12 @@ void CairoOutputDev::drawImage(GfxState
|
|
||||||
}
|
|
||||||
gfree(lookup);
|
|
||||||
|
|
||||||
+ if (scaledWidth<width)
|
|
||||||
+ {
|
|
||||||
+ PrescaleARGB((unsigned int *)buffer,width,height,stride,(unsigned int *)scaledBuffer,scaledWidth,scaledHeight,scaledStride);
|
|
||||||
+ delete [] buffer;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
cairo_surface_mark_dirty (image);
|
|
||||||
pattern = cairo_pattern_create_for_surface (image);
|
|
||||||
cairo_surface_destroy (image);
|
|
||||||
@@ -2053,8 +2147,8 @@ void CairoOutputDev::drawImage(GfxState
|
|
||||||
CAIRO_FILTER_BILINEAR : 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_init_translate (&matrix, 0, scaledHeight);
|
|
||||||
+ cairo_matrix_scale (&matrix, scaledWidth, -scaledHeight);
|
|
||||||
cairo_pattern_set_matrix (pattern, &matrix);
|
|
||||||
|
|
||||||
if (!mask && fill_opacity != 1.0) {
|
|
12
poppler.spec
12
poppler.spec
@ -2,7 +2,7 @@
|
|||||||
Summary: PDF rendering library
|
Summary: PDF rendering library
|
||||||
Name: poppler
|
Name: poppler
|
||||||
Version: 0.12.3
|
Version: 0.12.3
|
||||||
Release: 6%{?dist}
|
Release: 7%{?dist}
|
||||||
License: GPLv2
|
License: GPLv2
|
||||||
Group: Development/Libraries
|
Group: Development/Libraries
|
||||||
URL: http://poppler.freedesktop.org/
|
URL: http://poppler.freedesktop.org/
|
||||||
@ -12,11 +12,10 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
|||||||
## upstreamable patches
|
## upstreamable patches
|
||||||
|
|
||||||
## upstream patches
|
## upstream patches
|
||||||
# image scaling with cairo poor (http://bugs.freedesktop.org/show_bug.cgi?id=5589)
|
|
||||||
# based on http://bugs.freedesktop.org/attachment.cgi?id=31924
|
|
||||||
Patch50: poppler-0.12.3-fdo#5589.patch
|
|
||||||
# for texlive/pdftex, make ObjStream class public
|
# for texlive/pdftex, make ObjStream class public
|
||||||
Patch100: poppler-0.12.1-objstream.patch
|
Patch100: poppler-0.12.1-objstream.patch
|
||||||
|
# image scaling with cairo poor (http://bugs.freedesktop.org/show_bug.cgi?id=5589)
|
||||||
|
Patch101: poppler-0.12.3-downscale.patch
|
||||||
|
|
||||||
Requires: poppler-data >= 0.4.0
|
Requires: poppler-data >= 0.4.0
|
||||||
BuildRequires: automake libtool
|
BuildRequires: automake libtool
|
||||||
@ -121,8 +120,8 @@ converting PDF files to a number of other formats.
|
|||||||
%prep
|
%prep
|
||||||
%setup -q
|
%setup -q
|
||||||
|
|
||||||
%patch50 -p1 -b .fdo#5589
|
|
||||||
%patch100 -p1 -b .objstream
|
%patch100 -p1 -b .objstream
|
||||||
|
%patch101 -p1 -b .downscale
|
||||||
|
|
||||||
chmod -x goo/GooTimer.h
|
chmod -x goo/GooTimer.h
|
||||||
|
|
||||||
@ -226,6 +225,9 @@ rm -rf $RPM_BUILD_ROOT
|
|||||||
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Sun Jan 24 2010 Rex Dieter <rdieter@fedoraproject.org> - 0.12.3-7
|
||||||
|
- use alternative/upstream downscale patch (#556549, fdo#5589)
|
||||||
|
|
||||||
* Wed Jan 20 2010 Marek Kasik <mkasik@redhat.com> - 0.12.3-6
|
* Wed Jan 20 2010 Marek Kasik <mkasik@redhat.com> - 0.12.3-6
|
||||||
- Add dependency on poppler-data (#553991)
|
- Add dependency on poppler-data (#553991)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user