Gentoo Archives: gentoo-commits

From: "Ben de Groot (yngwin)" <yngwin@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] gentoo-x86 commit in app-text/poppler/files: poppler-0.12.3-cairo-image-downscale.patch poppler-CVE-2009-1188.patch poppler-0.8.3-page-init.patch poppler-0.10.5-xpdf-3.02pl3.patch poppler-0.6.1-xpdf-3.02pl2.patch
Date: Mon, 08 Feb 2010 23:37:40
Message-Id: E1NedAe-0006Tr-T1@stork.gentoo.org
1 yngwin 10/02/08 23:37:36
2
3 Added: poppler-0.12.3-cairo-image-downscale.patch
4 Removed: poppler-CVE-2009-1188.patch
5 poppler-0.8.3-page-init.patch
6 poppler-0.10.5-xpdf-3.02pl3.patch
7 poppler-0.6.1-xpdf-3.02pl2.patch
8 Log:
9 Remove obsoleted versions. Add cairo image downscale issue patch, which has been applied to upstream git (bug 303817).
10 (Portage version: 2.2_rc62/cvs/Linux x86_64)
11
12 Revision Changes Path
13 1.1 app-text/poppler/files/poppler-0.12.3-cairo-image-downscale.patch
14
15 file : http://sources.gentoo.org/viewcvs.py/gentoo-x86/app-text/poppler/files/poppler-0.12.3-cairo-image-downscale.patch?rev=1.1&view=markup
16 plain: http://sources.gentoo.org/viewcvs.py/gentoo-x86/app-text/poppler/files/poppler-0.12.3-cairo-image-downscale.patch?rev=1.1&content-type=text/plain
17
18 Index: poppler-0.12.3-cairo-image-downscale.patch
19 ===================================================================
20 diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
21 index 9a0f3be..42ac3a8 100644
22 --- a/poppler/CairoOutputDev.cc
23 +++ b/poppler/CairoOutputDev.cc
24 @@ -58,6 +58,7 @@
25 #include <splash/SplashBitmap.h>
26 #include "CairoOutputDev.h"
27 #include "CairoFontEngine.h"
28 +#include "CairoRescaleBox.h"
29 //------------------------------------------------------------------------
30
31 // #define LOG_CAIRO
32 @@ -1331,6 +1332,82 @@ void CairoOutputDev::endMaskClip(GfxState *state) {
33 clearSoftMask(state);
34 }
35
36 +cairo_surface_t *CairoOutputDev::downscaleSurface(cairo_surface_t *orig_surface) {
37 + cairo_surface_t *dest_surface;
38 + unsigned char *dest_buffer;
39 + int dest_stride;
40 + unsigned char *orig_buffer;
41 + int orig_width, orig_height;
42 + int orig_stride;
43 + GBool res;
44 +
45 + if (printing)
46 + return NULL;
47 +
48 + cairo_matrix_t matrix;
49 + cairo_get_matrix(cairo, &matrix);
50 +
51 + /* this whole computation should be factored out */
52 + double xScale = matrix.xx;
53 + double yScale = matrix.yy;
54 + int tx, tx2, ty, ty2; /* the integer co-oridinates of the resulting image */
55 + int scaledHeight;
56 + int scaledWidth;
57 + if (xScale >= 0) {
58 + tx = splashRound(matrix.x0 - 0.01);
59 + tx2 = splashRound(matrix.x0 + xScale + 0.01) - 1;
60 + } else {
61 + tx = splashRound(matrix.x0 + 0.01) - 1;
62 + tx2 = splashRound(matrix.x0 + xScale - 0.01);
63 + }
64 + scaledWidth = abs(tx2 - tx) + 1;
65 + //scaledWidth = splashRound(fabs(xScale));
66 + if (scaledWidth == 0) {
67 + // technically, this should draw nothing, but it generally seems
68 + // better to draw a one-pixel-wide stripe rather than throwing it
69 + // away
70 + scaledWidth = 1;
71 + }
72 + if (yScale >= 0) {
73 + ty = splashFloor(matrix.y0 + 0.01);
74 + ty2 = splashCeil(matrix.y0 + yScale - 0.01);
75 + } else {
76 + ty = splashCeil(matrix.y0 - 0.01);
77 + ty2 = splashFloor(matrix.y0 + yScale + 0.01);
78 + }
79 + scaledHeight = abs(ty2 - ty);
80 + if (scaledHeight == 0) {
81 + scaledHeight = 1;
82 + }
83 +
84 + orig_width = cairo_image_surface_get_width (orig_surface);
85 + orig_height = cairo_image_surface_get_height (orig_surface);
86 + if (scaledWidth >= orig_width || scaledHeight >= orig_height)
87 + return NULL;
88 +
89 + dest_surface = cairo_surface_create_similar (orig_surface,
90 + cairo_surface_get_content (orig_surface),
91 + scaledWidth, scaledHeight);
92 + dest_buffer = cairo_image_surface_get_data (dest_surface);
93 + dest_stride = cairo_image_surface_get_stride (dest_surface);
94 +
95 + orig_buffer = cairo_image_surface_get_data (orig_surface);
96 + orig_stride = cairo_image_surface_get_stride (orig_surface);
97 +
98 + res = downscale_box_filter((uint32_t *)orig_buffer,
99 + orig_stride, orig_width, orig_height,
100 + scaledWidth, scaledHeight, 0, 0,
101 + scaledWidth, scaledHeight,
102 + (uint32_t *)dest_buffer, dest_stride);
103 + if (!res) {
104 + cairo_surface_destroy (dest_surface);
105 + return NULL;
106 + }
107 +
108 + return dest_surface;
109 +
110 +}
111 +
112 void CairoOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
113 int width, int height, GBool invert,
114 GBool interpolate, GBool inlineImg) {
115 @@ -2094,6 +2171,18 @@ void CairoOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
116 }
117 gfree(lookup);
118
119 + cairo_surface_t *scaled_surface;
120 +
121 + scaled_surface = downscaleSurface (image);
122 + if (scaled_surface) {
123 + if (cairo_surface_status (scaled_surface))
124 + goto cleanup;
125 + cairo_surface_destroy (image);
126 + image = scaled_surface;
127 + width = cairo_image_surface_get_width (image);
128 + height = cairo_image_surface_get_height (image);
129 + }
130 +
131 cairo_surface_mark_dirty (image);
132 pattern = cairo_pattern_create_for_surface (image);
133 cairo_surface_destroy (image);
134 diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h
135 index fb9c0d7..266f0cb 100644
136 --- a/poppler/CairoOutputDev.h
137 +++ b/poppler/CairoOutputDev.h
138 @@ -268,6 +268,7 @@ public:
139
140 protected:
141 void doPath(cairo_t *cairo, GfxState *state, GfxPath *path);
142 + cairo_surface_t *downscaleSurface(cairo_surface_t *orig_surface);
143
144 GfxRGB fill_color, stroke_color;
145 cairo_pattern_t *fill_pattern, *stroke_pattern;
146 diff --git a/poppler/CairoRescaleBox.cc b/poppler/CairoRescaleBox.cc
147 new file mode 100644
148 index 0000000..dce5ddd
149 --- /dev/null
150 +++ b/poppler/CairoRescaleBox.cc
151 @@ -0,0 +1,352 @@
152 +/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
153 +/*
154 + * Copyright © 2009 Mozilla Corporation
155 + *
156 + * Permission to use, copy, modify, distribute, and sell this software and its
157 + * documentation for any purpose is hereby granted without fee, provided that
158 + * the above copyright notice appear in all copies and that both that
159 + * copyright notice and this permission notice appear in supporting
160 + * documentation, and that the name of Mozilla Corporation not be used in
161 + * advertising or publicity pertaining to distribution of the software without
162 + * specific, written prior permission. Mozilla Corporation makes no
163 + * representations about the suitability of this software for any purpose. It
164 + * is provided "as is" without express or implied warranty.
165 + *
166 + * MOZILLA CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
167 + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
168 + * SHALL MOZILLA CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
169 + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
170 + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
171 + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
172 + * OF THIS SOFTWARE.
173 + *
174 + * Author: Jeff Muizelaar, Mozilla Corp.
175 + */
176 +
177 +/* This implements a box filter that supports non-integer box sizes */
178 +
179 +#ifdef HAVE_CONFIG_H
180 +#include <config.h>
181 +#endif
182 +
183 +#include <stdint.h>
184 +#include <stdio.h>
185 +#include <assert.h>
186 +#include <stdlib.h>
187 +#include <math.h>
188 +#include "goo/gmem.h"
189 +#include "CairoRescaleBox.h"
190 +
191 +typedef unsigned short int uint16_t;
192 +typedef unsigned int uint32_t;
193 +
194 +/* we work in fixed point where 1. == 1 << 24 */
195 +#define FIXED_SHIFT 24
196 +
197 +static void downsample_row_box_filter (
198 + int start, int width,
199 + uint32_t *src, uint32_t *dest,
200 + int coverage[], int pixel_coverage)
201 +{
202 + /* we need an array of the pixel contribution of each destination pixel on the boundaries.
203 + * we invert the value to get the value on the other size of the box */
204 + /*
205 +
206 + value = a * contribution * 1/box_size
207 + value += a * 1/box_size
208 + value += a * 1/box_size
209 + value += a * 1/box_size
210 + value += a * (1 - contribution) * 1/box_size
211 + a * (1/box_size - contribution * 1/box_size)
212 +
213 + box size is constant
214 +
215 +
216 + value = a * contribtion_a * 1/box_size + b * contribution_b * 1/box_size
217 + contribution_b = (1 - contribution_a)
218 + = (1 - contribution_a_next)
219 + */
220 +
221 + /* box size = ceil(src_width/dest_width) */
222 + int x = 0;
223 +
224 + /* skip to start */
225 + /* XXX: it might be possible to do this directly instead of iteratively, however
226 + * the iterative solution is simple */
227 + while (x < start)
228 + {
229 + int box = 1 << FIXED_SHIFT;
230 + int start_coverage = coverage[x];
231 + box -= start_coverage;
232 + src++;
233 + while (box >= pixel_coverage)
234 + {
235 + src++;
236 + box -= pixel_coverage;
237 + }
238 + x++;
239 + }
240 +
241 + while (x < start + width)
242 + {
243 + uint32_t a = 0;
244 + uint32_t r = 0;
245 + uint32_t g = 0;
246 + uint32_t b = 0;
247 + int box = 1 << FIXED_SHIFT;
248 + int start_coverage = coverage[x];
249 +
250 + a = ((*src >> 24) & 0xff) * start_coverage;
251 + r = ((*src >> 16) & 0xff) * start_coverage;
252 + g = ((*src >> 8) & 0xff) * start_coverage;
253 + b = ((*src >> 0) & 0xff) * start_coverage;
254 + src++;
255 + x++;
256 + box -= start_coverage;
257 +
258 + while (box >= pixel_coverage)
259 + {
260 + a += ((*src >> 24) & 0xff) * pixel_coverage;
261 + r += ((*src >> 16) & 0xff) * pixel_coverage;
262 + g += ((*src >> 8) & 0xff) * pixel_coverage;
263 + b += ((*src >> 0) & 0xff) * pixel_coverage;
264 + src++;
265 +
266 + box -= pixel_coverage;
267 + }
268 +
269 + /* multiply by whatever is leftover
270 + * this ensures that we don't bias down.
271 + * i.e. start_coverage + n*pixel_coverage + box == 1 << 24 */
272 + if (box > 0)
273 + {
274 + a += ((*src >> 24) & 0xff) * box;
275 + r += ((*src >> 16) & 0xff) * box;
276 + g += ((*src >> 8) & 0xff) * box;
277 + b += ((*src >> 0) & 0xff) * box;
278 + }
279 +
280 + a >>= FIXED_SHIFT;
281 + r >>= FIXED_SHIFT;
282 + g >>= FIXED_SHIFT;
283 + b >>= FIXED_SHIFT;
284 +
285 + *dest = (a << 24) | (r << 16) | (g << 8) | b;
286 + dest++;
287 + }
288 +}
289 +
290 +static void downsample_columns_box_filter (
291 + int n,
292 + int start_coverage,
293 + int pixel_coverage,
294 + uint32_t *src, uint32_t *dest)
295 +{
296 + int stride = n;
297 + while (n--) {
298 + uint32_t a = 0;
299 + uint32_t r = 0;
300 + uint32_t g = 0;
301 + uint32_t b = 0;
302 + uint32_t *column_src = src;
303 + int box = 1 << FIXED_SHIFT;
304 +
305 + a = ((*column_src >> 24) & 0xff) * start_coverage;
306 + r = ((*column_src >> 16) & 0xff) * start_coverage;
307 + g = ((*column_src >> 8) & 0xff) * start_coverage;
308 + b = ((*column_src >> 0) & 0xff) * start_coverage;
309 + column_src += stride;
310 + box -= start_coverage;
311 +
312 + while (box >= pixel_coverage)
313 + {
314 + a += ((*column_src >> 24) & 0xff) * pixel_coverage;
315 + r += ((*column_src >> 16) & 0xff) * pixel_coverage;
316 + g += ((*column_src >> 8) & 0xff) * pixel_coverage;
317 + b += ((*column_src >> 0) & 0xff) * pixel_coverage;
318 + column_src += stride;
319 + box -= pixel_coverage;
320 + }
321 +
322 + if (box > 0) {
323 + a += ((*column_src >> 24) & 0xff) * box;
324 + r += ((*column_src >> 16) & 0xff) * box;
325 + g += ((*column_src >> 8) & 0xff) * box;
326 + b += ((*column_src >> 0) & 0xff) * box;
327 + }
328 +
329 + a >>= FIXED_SHIFT;
330 + r >>= FIXED_SHIFT;
331 + g >>= FIXED_SHIFT;
332 + b >>= FIXED_SHIFT;
333 +
334 + *dest = (a << 24) | (r << 16) | (g << 8) | b;
335 + dest++;
336 + src++;
337 + }
338 +}
339 +
340 +static int compute_coverage (int coverage[], int src_length, int dest_length)
341 +{
342 + int i;
343 + /* num = src_length/dest_length
344 + total = sum(pixel) / num
345 +
346 + pixel * 1/num == pixel * dest_length / src_length
347 + */
348 + /* the average contribution of each source pixel */
349 + int ratio = ((1 << 24)*(long long int)dest_length)/src_length;
350 + /* because ((1 << 24)*(long long int)dest_length) won't always be divisible by src_length
351 + * we'll need someplace to put the other bits.
352 + *
353 + * We want to ensure a + n*ratio < 1<<24
354 + *
355 + * 1<<24
356 + * */
357 +
358 + double scale = (double)src_length/dest_length;
359 +
360 + /* for each destination pixel compute the coverage of the left most pixel included in the box */
361 + /* I have a proof of this, which this margin is too narrow to contain */
362 + for (i=0; i<dest_length; i++)
363 + {
364 + float left_side = i*scale;
365 + float right_side = (i+1)*scale;
366 + float right_fract = right_side - floor (right_side);
367 + float left_fract = ceil (left_side) - left_side;
368 + int overage;
369 + /* find out how many source pixels will be used to fill the box */
370 + int count = floor (right_side) - ceil (left_side);
371 + /* what's the maximum value this expression can become?
372 + floor((i+1)*scale) - ceil(i*scale)
373 +
374 + (i+1)*scale - i*scale == scale
375 +
376 + since floor((i+1)*scale) <= (i+1)*scale
377 + and ceil(i*scale) >= i*scale
378 +
379 + floor((i+1)*scale) - ceil(i*scale) <= scale
380 +
381 + further since: floor((i+1)*scale) - ceil(i*scale) is an integer
382 +
383 + therefore:
384 + floor((i+1)*scale) - ceil(i*scale) <= floor(scale)
385 + */
386 +
387 + if (left_fract == 0.)
388 + count--;
389 +
390 + /* compute how much the right-most pixel contributes */
391 + overage = ratio*(right_fract);
392 +
393 + /* the remainder is the the amount that the left-most pixel
394 + * contributes */
395 + coverage[i] = (1<<24) - (count * ratio + overage);
396 + }
397 +
398 + return ratio;
399 +}
400 +
401 +GBool downscale_box_filter(uint32_t *orig, int orig_stride, unsigned orig_width, unsigned orig_height,
402 + signed scaled_width, signed scaled_height,
403 + uint16_t start_column, uint16_t start_row,
404 + uint16_t width, uint16_t height,
405 + uint32_t *dest, int dst_stride)
406 +{
407 + int pixel_coverage_x, pixel_coverage_y;
408 + int dest_y;
409 + int src_y = 0;
410 + uint32_t *scanline = orig;
411 + int *x_coverage = NULL;
412 + int *y_coverage = NULL;
413 + uint32_t *temp_buf = NULL;
414 + GBool retval = gFalse;
415 +
416 + x_coverage = (int *)gmallocn3 (orig_width, 1, sizeof(int));
417 + y_coverage = (int *)gmallocn3 (orig_height, 1, sizeof(int));
418 +
419 + /* we need to allocate enough room for ceil(src_height/dest_height)+1
420 + Example:
421 + src_height = 140
422 + dest_height = 50
423 + src_height/dest_height = 2.8
424 +
425 + |-------------| 2.8 pixels
426 + |----|----|----|----| 4 pixels
427 + need to sample 3 pixels
428 +
429 + |-------------| 2.8 pixels
430 + |----|----|----|----| 4 pixels
431 + need to sample 4 pixels
432 + */
433 +
434 + temp_buf = (uint32_t *)gmallocn3 ((orig_height + scaled_height-1)/scaled_height+1, scaled_width, sizeof(uint32_t));
435 +
436 + if (!x_coverage || !y_coverage || !scanline || !temp_buf)
437 + goto cleanup;
438 +
439 + pixel_coverage_x = compute_coverage (x_coverage, orig_width, scaled_width);
440 + pixel_coverage_y = compute_coverage (y_coverage, orig_height, scaled_height);
441 +
442 + assert (width + start_column <= scaled_width);
443 +
444 + /* skip the rows at the beginning */
445 + for (dest_y = 0; dest_y < start_row; dest_y++)
446 + {
447 + int box = 1 << FIXED_SHIFT;
448 + int start_coverage_y = y_coverage[dest_y];
449 + box -= start_coverage_y;
450 + src_y++;
451 + while (box >= pixel_coverage_y)
452 + {
453 + box -= pixel_coverage_y;
454 + src_y++;
455 + }
456 + }
457 +
458 + for (; dest_y < start_row + height; dest_y++)
459 + {
460 + int columns = 0;
461 + int box = 1 << FIXED_SHIFT;
462 + int start_coverage_y = y_coverage[dest_y];
463 +
464 + scanline = orig + src_y * orig_stride / 4;
465 + downsample_row_box_filter (start_column, width, scanline, temp_buf + width * columns, x_coverage, pixel_coverage_x);
466 + columns++;
467 + src_y++;
468 + box -= start_coverage_y;
469 +
470 + while (box >= pixel_coverage_y)
471 + {
472 + scanline = orig + src_y * orig_stride / 4;
473 + downsample_row_box_filter (start_column, width, scanline, temp_buf + width * columns, x_coverage, pixel_coverage_x);
474 + columns++;
475 + src_y++;
476 + box -= pixel_coverage_y;
477 + }
478 +
479 + /* downsample any leftovers */
480 + if (box > 0)
481 + {
482 + scanline = orig + src_y * orig_stride / 4;
483 + downsample_row_box_filter (start_column, width, scanline, temp_buf + width * columns, x_coverage, pixel_coverage_x);
484 + columns++;
485 + }
486 +
487 + /* now scale the rows we just downsampled in the y direction */
488 + downsample_columns_box_filter (width, start_coverage_y, pixel_coverage_y, temp_buf, dest);
489 + dest += dst_stride / 4;
490 +
491 +// assert(width*columns <= ((orig_height + scaled_height-1)/scaled_height+1) * width);
492 + }
493 +// assert (src_y<=orig_height);
494 +
495 + retval = gTrue;
496 +
497 +cleanup:
498 + free (x_coverage);
499 + free (y_coverage);
500 + free (temp_buf);
501 +
502 + return gTrue;
503 +}
504 diff --git a/poppler/CairoRescaleBox.h b/poppler/CairoRescaleBox.h
505 new file mode 100644
506 index 0000000..5349c87
507 --- /dev/null
508 +++ b/poppler/CairoRescaleBox.h
509 @@ -0,0 +1,12 @@
510 +#ifndef CAIRO_RESCALE_BOX_H
511 +#define CAIRO_RESCALE_BOX_H
512 +
513 +#include "goo/gtypes.h"
514 +
515 +GBool downscale_box_filter(unsigned int *orig, int orig_stride, unsigned orig_width, unsigned orig_height,
516 + signed scaled_width, signed scaled_height,
517 + unsigned short int start_column, unsigned short int start_row,
518 + unsigned short int width, unsigned short int height,
519 + unsigned int *dest, int dst_stride);
520 +
521 +#endif /* CAIRO_RESCALE_BOX_H */
522 diff --git a/poppler/Makefile.am b/poppler/Makefile.am
523 index ec79e31..096ea76 100644
524 --- a/poppler/Makefile.am
525 +++ b/poppler/Makefile.am
526 @@ -47,7 +47,9 @@ libpoppler_cairo_la_SOURCES = \
527 CairoFontEngine.cc \
528 CairoFontEngine.h \
529 CairoOutputDev.cc \
530 - CairoOutputDev.h
531 + CairoOutputDev.h \
532 + CairoRescaleBox.cc \
533 + CairoRescaleBox.h
534
535 endif