- 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