Merge lp:~jshholland/ubuntu/lucid/poppler/backport-anti-alias into lp:ubuntu/lucid/poppler
- Lucid (10.04)
- backport-anti-alias
- Merge into lucid
Proposed by
Josh Holland
Status: | Work in progress |
---|---|
Proposed branch: | lp:~jshholland/ubuntu/lucid/poppler/backport-anti-alias |
Merge into: | lp:ubuntu/lucid/poppler |
Diff against target: |
534 lines (+522/-0) 2 files modified
debian/changelog (+7/-0) debian/patches/backport-anti-alias.patch (+515/-0) |
To merge this branch: | bzr merge lp:~jshholland/ubuntu/lucid/poppler/backport-anti-alias |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
James Westby (community) | Needs Fixing | ||
Sebastien Bacher | Pending | ||
Review via email: mp+22511@code.launchpad.net |
Commit message
Description of the change
Backport http://
To post a comment you must log in.
Unmerged revisions
- 80. By Josh Holland
-
Tagged patch as https:/
/wiki.ubuntu. com/UbuntuDevel opment/ PatchTaggingGui delines - 79. By Josh Holland
-
Fixed bug number
- 78. By Josh Holland
-
Add backport-
anti-alias. patch: Fix anti aliasing (fixed in upstream git)
(LP: #248335)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'debian/changelog' | |||
2 | --- debian/changelog 2010-03-19 13:51:55 +0000 | |||
3 | +++ debian/changelog 2010-03-31 09:29:27 +0000 | |||
4 | @@ -1,3 +1,10 @@ | |||
5 | 1 | poppler (0.12.4-0ubuntu3) lucid; urgency=low | ||
6 | 2 | |||
7 | 3 | * Add backport-anti-alias.patch: Fix anti aliasing (fixed in upstream git) | ||
8 | 4 | (LP: #248355) | ||
9 | 5 | |||
10 | 6 | -- Josh Holland <jrh@joshh.co.uk> Tue, 30 Mar 2010 23:35:59 +0100 | ||
11 | 7 | |||
12 | 1 | poppler (0.12.4-0ubuntu2) lucid; urgency=low | 8 | poppler (0.12.4-0ubuntu2) lucid; urgency=low |
13 | 2 | 9 | ||
14 | 3 | * Add psname-escape-backslash.patch: Don't use '\' character in PostScript | 10 | * Add psname-escape-backslash.patch: Don't use '\' character in PostScript |
15 | 4 | 11 | ||
16 | === added file 'debian/patches/backport-anti-alias.patch' | |||
17 | --- debian/patches/backport-anti-alias.patch 1970-01-01 00:00:00 +0000 | |||
18 | +++ debian/patches/backport-anti-alias.patch 2010-03-31 09:29:27 +0000 | |||
19 | @@ -0,0 +1,515 @@ | |||
20 | 1 | From: Carlos Garcia Campos <carlosgc@gnome.org> | ||
21 | 2 | Subject: Anti-alias graphics in PDF documents | ||
22 | 3 | Origin: upstream, http://bugs.freedesktop.org/attachment.cgi?id=32750 | ||
23 | 4 | Bug: http://bugs.freedesktop.org/show_bug.cgi?id=5589 | ||
24 | 5 | Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/poppler/+bug/248355 | ||
25 | 6 | diff -Nur -x '*.orig' -x '*~' poppler/poppler/CairoOutputDev.cc poppler.new/poppler/CairoOutputDev.cc | ||
26 | 7 | --- poppler/poppler/CairoOutputDev.cc 2010-03-30 23:08:49.306054000 +0100 | ||
27 | 8 | +++ poppler.new/poppler/CairoOutputDev.cc 2010-03-30 23:22:56.511527017 +0100 | ||
28 | 9 | @@ -58,6 +58,7 @@ | ||
29 | 10 | #include <splash/SplashBitmap.h> | ||
30 | 11 | #include "CairoOutputDev.h" | ||
31 | 12 | #include "CairoFontEngine.h" | ||
32 | 13 | +#include "CairoRescaleBox.h" | ||
33 | 14 | //------------------------------------------------------------------------ | ||
34 | 15 | |||
35 | 16 | // #define LOG_CAIRO | ||
36 | 17 | @@ -1291,6 +1292,82 @@ | ||
37 | 18 | clearSoftMask(state); | ||
38 | 19 | } | ||
39 | 20 | |||
40 | 21 | +cairo_surface_t *CairoOutputDev::downscaleSurface(cairo_surface_t *orig_surface) { | ||
41 | 22 | + cairo_surface_t *dest_surface; | ||
42 | 23 | + unsigned char *dest_buffer; | ||
43 | 24 | + int dest_stride; | ||
44 | 25 | + unsigned char *orig_buffer; | ||
45 | 26 | + int orig_width, orig_height; | ||
46 | 27 | + int orig_stride; | ||
47 | 28 | + GBool res; | ||
48 | 29 | + | ||
49 | 30 | + if (printing) | ||
50 | 31 | + return NULL; | ||
51 | 32 | + | ||
52 | 33 | + cairo_matrix_t matrix; | ||
53 | 34 | + cairo_get_matrix(cairo, &matrix); | ||
54 | 35 | + | ||
55 | 36 | + /* this whole computation should be factored out */ | ||
56 | 37 | + double xScale = matrix.xx; | ||
57 | 38 | + double yScale = matrix.yy; | ||
58 | 39 | + int tx, tx2, ty, ty2; /* the integer co-oridinates of the resulting image */ | ||
59 | 40 | + int scaledHeight; | ||
60 | 41 | + int scaledWidth; | ||
61 | 42 | + if (xScale >= 0) { | ||
62 | 43 | + tx = splashRound(matrix.x0 - 0.01); | ||
63 | 44 | + tx2 = splashRound(matrix.x0 + xScale + 0.01) - 1; | ||
64 | 45 | + } else { | ||
65 | 46 | + tx = splashRound(matrix.x0 + 0.01) - 1; | ||
66 | 47 | + tx2 = splashRound(matrix.x0 + xScale - 0.01); | ||
67 | 48 | + } | ||
68 | 49 | + scaledWidth = abs(tx2 - tx) + 1; | ||
69 | 50 | + //scaledWidth = splashRound(fabs(xScale)); | ||
70 | 51 | + if (scaledWidth == 0) { | ||
71 | 52 | + // technically, this should draw nothing, but it generally seems | ||
72 | 53 | + // better to draw a one-pixel-wide stripe rather than throwing it | ||
73 | 54 | + // away | ||
74 | 55 | + scaledWidth = 1; | ||
75 | 56 | + } | ||
76 | 57 | + if (yScale >= 0) { | ||
77 | 58 | + ty = splashFloor(matrix.y0 + 0.01); | ||
78 | 59 | + ty2 = splashCeil(matrix.y0 + yScale - 0.01); | ||
79 | 60 | + } else { | ||
80 | 61 | + ty = splashCeil(matrix.y0 - 0.01); | ||
81 | 62 | + ty2 = splashFloor(matrix.y0 + yScale + 0.01); | ||
82 | 63 | + } | ||
83 | 64 | + scaledHeight = abs(ty2 - ty); | ||
84 | 65 | + if (scaledHeight == 0) { | ||
85 | 66 | + scaledHeight = 1; | ||
86 | 67 | + } | ||
87 | 68 | + | ||
88 | 69 | + orig_width = cairo_image_surface_get_width (orig_surface); | ||
89 | 70 | + orig_height = cairo_image_surface_get_height (orig_surface); | ||
90 | 71 | + if (scaledWidth >= orig_width || scaledHeight >= orig_height) | ||
91 | 72 | + return NULL; | ||
92 | 73 | + | ||
93 | 74 | + dest_surface = cairo_surface_create_similar (orig_surface, | ||
94 | 75 | + cairo_surface_get_content (orig_surface), | ||
95 | 76 | + scaledWidth, scaledHeight); | ||
96 | 77 | + dest_buffer = cairo_image_surface_get_data (dest_surface); | ||
97 | 78 | + dest_stride = cairo_image_surface_get_stride (dest_surface); | ||
98 | 79 | + | ||
99 | 80 | + orig_buffer = cairo_image_surface_get_data (orig_surface); | ||
100 | 81 | + orig_stride = cairo_image_surface_get_stride (orig_surface); | ||
101 | 82 | + | ||
102 | 83 | + res = downscale_box_filter((uint32_t *)orig_buffer, | ||
103 | 84 | + orig_stride, orig_width, orig_height, | ||
104 | 85 | + scaledWidth, scaledHeight, 0, 0, | ||
105 | 86 | + scaledWidth, scaledHeight, | ||
106 | 87 | + (uint32_t *)dest_buffer, dest_stride); | ||
107 | 88 | + if (!res) { | ||
108 | 89 | + cairo_surface_destroy (dest_surface); | ||
109 | 90 | + return NULL; | ||
110 | 91 | + } | ||
111 | 92 | + | ||
112 | 93 | + return dest_surface; | ||
113 | 94 | + | ||
114 | 95 | +} | ||
115 | 96 | + | ||
116 | 97 | void CairoOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, | ||
117 | 98 | int width, int height, GBool invert, | ||
118 | 99 | GBool interpolate, GBool inlineImg) { | ||
119 | 100 | @@ -2043,6 +2120,18 @@ | ||
120 | 101 | } | ||
121 | 102 | gfree(lookup); | ||
122 | 103 | |||
123 | 104 | + cairo_surface_t *scaled_surface; | ||
124 | 105 | + | ||
125 | 106 | + scaled_surface = downscaleSurface (image); | ||
126 | 107 | + if (scaled_surface) { | ||
127 | 108 | + if (cairo_surface_status (scaled_surface)) | ||
128 | 109 | + goto cleanup; | ||
129 | 110 | + cairo_surface_destroy (image); | ||
130 | 111 | + image = scaled_surface; | ||
131 | 112 | + width = cairo_image_surface_get_width (image); | ||
132 | 113 | + height = cairo_image_surface_get_height (image); | ||
133 | 114 | + } | ||
134 | 115 | + | ||
135 | 116 | cairo_surface_mark_dirty (image); | ||
136 | 117 | pattern = cairo_pattern_create_for_surface (image); | ||
137 | 118 | cairo_surface_destroy (image); | ||
138 | 119 | diff -Nur -x '*.orig' -x '*~' poppler/poppler/CairoOutputDev.h poppler.new/poppler/CairoOutputDev.h | ||
139 | 120 | --- poppler/poppler/CairoOutputDev.h 2010-03-30 23:08:49.306054000 +0100 | ||
140 | 121 | +++ poppler.new/poppler/CairoOutputDev.h 2010-03-30 23:22:56.531526906 +0100 | ||
141 | 122 | @@ -268,6 +268,7 @@ | ||
142 | 123 | |||
143 | 124 | protected: | ||
144 | 125 | void doPath(cairo_t *cairo, GfxState *state, GfxPath *path); | ||
145 | 126 | + cairo_surface_t *downscaleSurface(cairo_surface_t *orig_surface); | ||
146 | 127 | |||
147 | 128 | GfxRGB fill_color, stroke_color; | ||
148 | 129 | cairo_pattern_t *fill_pattern, *stroke_pattern; | ||
149 | 130 | diff -Nur -x '*.orig' -x '*~' poppler/poppler/CairoRescaleBox.cc poppler.new/poppler/CairoRescaleBox.cc | ||
150 | 131 | --- poppler/poppler/CairoRescaleBox.cc 1970-01-01 01:00:00.000000000 +0100 | ||
151 | 132 | +++ poppler.new/poppler/CairoRescaleBox.cc 2010-03-30 23:22:56.559527323 +0100 | ||
152 | 133 | @@ -0,0 +1,352 @@ | ||
153 | 134 | +/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */ | ||
154 | 135 | +/* | ||
155 | 136 | + * Copyright © 2009 Mozilla Corporation | ||
156 | 137 | + * | ||
157 | 138 | + * Permission to use, copy, modify, distribute, and sell this software and its | ||
158 | 139 | + * documentation for any purpose is hereby granted without fee, provided that | ||
159 | 140 | + * the above copyright notice appear in all copies and that both that | ||
160 | 141 | + * copyright notice and this permission notice appear in supporting | ||
161 | 142 | + * documentation, and that the name of Mozilla Corporation not be used in | ||
162 | 143 | + * advertising or publicity pertaining to distribution of the software without | ||
163 | 144 | + * specific, written prior permission. Mozilla Corporation makes no | ||
164 | 145 | + * representations about the suitability of this software for any purpose. It | ||
165 | 146 | + * is provided "as is" without express or implied warranty. | ||
166 | 147 | + * | ||
167 | 148 | + * MOZILLA CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | ||
168 | 149 | + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT | ||
169 | 150 | + * SHALL MOZILLA CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR | ||
170 | 151 | + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | ||
171 | 152 | + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | ||
172 | 153 | + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | ||
173 | 154 | + * OF THIS SOFTWARE. | ||
174 | 155 | + * | ||
175 | 156 | + * Author: Jeff Muizelaar, Mozilla Corp. | ||
176 | 157 | + */ | ||
177 | 158 | + | ||
178 | 159 | +/* This implements a box filter that supports non-integer box sizes */ | ||
179 | 160 | + | ||
180 | 161 | +#ifdef HAVE_CONFIG_H | ||
181 | 162 | +#include <config.h> | ||
182 | 163 | +#endif | ||
183 | 164 | + | ||
184 | 165 | +#include <stdint.h> | ||
185 | 166 | +#include <stdio.h> | ||
186 | 167 | +#include <assert.h> | ||
187 | 168 | +#include <stdlib.h> | ||
188 | 169 | +#include <math.h> | ||
189 | 170 | +#include "goo/gmem.h" | ||
190 | 171 | +#include "CairoRescaleBox.h" | ||
191 | 172 | + | ||
192 | 173 | +typedef unsigned short int uint16_t; | ||
193 | 174 | +typedef unsigned int uint32_t; | ||
194 | 175 | + | ||
195 | 176 | +/* we work in fixed point where 1. == 1 << 24 */ | ||
196 | 177 | +#define FIXED_SHIFT 24 | ||
197 | 178 | + | ||
198 | 179 | +static void downsample_row_box_filter ( | ||
199 | 180 | + int start, int width, | ||
200 | 181 | + uint32_t *src, uint32_t *dest, | ||
201 | 182 | + int coverage[], int pixel_coverage) | ||
202 | 183 | +{ | ||
203 | 184 | + /* we need an array of the pixel contribution of each destination pixel on the boundaries. | ||
204 | 185 | + * we invert the value to get the value on the other size of the box */ | ||
205 | 186 | + /* | ||
206 | 187 | + | ||
207 | 188 | + value = a * contribution * 1/box_size | ||
208 | 189 | + value += a * 1/box_size | ||
209 | 190 | + value += a * 1/box_size | ||
210 | 191 | + value += a * 1/box_size | ||
211 | 192 | + value += a * (1 - contribution) * 1/box_size | ||
212 | 193 | + a * (1/box_size - contribution * 1/box_size) | ||
213 | 194 | + | ||
214 | 195 | + box size is constant | ||
215 | 196 | + | ||
216 | 197 | + | ||
217 | 198 | + value = a * contribtion_a * 1/box_size + b * contribution_b * 1/box_size | ||
218 | 199 | + contribution_b = (1 - contribution_a) | ||
219 | 200 | + = (1 - contribution_a_next) | ||
220 | 201 | + */ | ||
221 | 202 | + | ||
222 | 203 | + /* box size = ceil(src_width/dest_width) */ | ||
223 | 204 | + int x = 0; | ||
224 | 205 | + | ||
225 | 206 | + /* skip to start */ | ||
226 | 207 | + /* XXX: it might be possible to do this directly instead of iteratively, however | ||
227 | 208 | + * the iterative solution is simple */ | ||
228 | 209 | + while (x < start) | ||
229 | 210 | + { | ||
230 | 211 | + int box = 1 << FIXED_SHIFT; | ||
231 | 212 | + int start_coverage = coverage[x]; | ||
232 | 213 | + box -= start_coverage; | ||
233 | 214 | + src++; | ||
234 | 215 | + while (box >= pixel_coverage) | ||
235 | 216 | + { | ||
236 | 217 | + src++; | ||
237 | 218 | + box -= pixel_coverage; | ||
238 | 219 | + } | ||
239 | 220 | + x++; | ||
240 | 221 | + } | ||
241 | 222 | + | ||
242 | 223 | + while (x < start + width) | ||
243 | 224 | + { | ||
244 | 225 | + uint32_t a = 0; | ||
245 | 226 | + uint32_t r = 0; | ||
246 | 227 | + uint32_t g = 0; | ||
247 | 228 | + uint32_t b = 0; | ||
248 | 229 | + int box = 1 << FIXED_SHIFT; | ||
249 | 230 | + int start_coverage = coverage[x]; | ||
250 | 231 | + | ||
251 | 232 | + a = ((*src >> 24) & 0xff) * start_coverage; | ||
252 | 233 | + r = ((*src >> 16) & 0xff) * start_coverage; | ||
253 | 234 | + g = ((*src >> 8) & 0xff) * start_coverage; | ||
254 | 235 | + b = ((*src >> 0) & 0xff) * start_coverage; | ||
255 | 236 | + src++; | ||
256 | 237 | + x++; | ||
257 | 238 | + box -= start_coverage; | ||
258 | 239 | + | ||
259 | 240 | + while (box >= pixel_coverage) | ||
260 | 241 | + { | ||
261 | 242 | + a += ((*src >> 24) & 0xff) * pixel_coverage; | ||
262 | 243 | + r += ((*src >> 16) & 0xff) * pixel_coverage; | ||
263 | 244 | + g += ((*src >> 8) & 0xff) * pixel_coverage; | ||
264 | 245 | + b += ((*src >> 0) & 0xff) * pixel_coverage; | ||
265 | 246 | + src++; | ||
266 | 247 | + | ||
267 | 248 | + box -= pixel_coverage; | ||
268 | 249 | + } | ||
269 | 250 | + | ||
270 | 251 | + /* multiply by whatever is leftover | ||
271 | 252 | + * this ensures that we don't bias down. | ||
272 | 253 | + * i.e. start_coverage + n*pixel_coverage + box == 1 << 24 */ | ||
273 | 254 | + if (box > 0) | ||
274 | 255 | + { | ||
275 | 256 | + a += ((*src >> 24) & 0xff) * box; | ||
276 | 257 | + r += ((*src >> 16) & 0xff) * box; | ||
277 | 258 | + g += ((*src >> 8) & 0xff) * box; | ||
278 | 259 | + b += ((*src >> 0) & 0xff) * box; | ||
279 | 260 | + } | ||
280 | 261 | + | ||
281 | 262 | + a >>= FIXED_SHIFT; | ||
282 | 263 | + r >>= FIXED_SHIFT; | ||
283 | 264 | + g >>= FIXED_SHIFT; | ||
284 | 265 | + b >>= FIXED_SHIFT; | ||
285 | 266 | + | ||
286 | 267 | + *dest = (a << 24) | (r << 16) | (g << 8) | b; | ||
287 | 268 | + dest++; | ||
288 | 269 | + } | ||
289 | 270 | +} | ||
290 | 271 | + | ||
291 | 272 | +static void downsample_columns_box_filter ( | ||
292 | 273 | + int n, | ||
293 | 274 | + int start_coverage, | ||
294 | 275 | + int pixel_coverage, | ||
295 | 276 | + uint32_t *src, uint32_t *dest) | ||
296 | 277 | +{ | ||
297 | 278 | + int stride = n; | ||
298 | 279 | + while (n--) { | ||
299 | 280 | + uint32_t a = 0; | ||
300 | 281 | + uint32_t r = 0; | ||
301 | 282 | + uint32_t g = 0; | ||
302 | 283 | + uint32_t b = 0; | ||
303 | 284 | + uint32_t *column_src = src; | ||
304 | 285 | + int box = 1 << FIXED_SHIFT; | ||
305 | 286 | + | ||
306 | 287 | + a = ((*column_src >> 24) & 0xff) * start_coverage; | ||
307 | 288 | + r = ((*column_src >> 16) & 0xff) * start_coverage; | ||
308 | 289 | + g = ((*column_src >> 8) & 0xff) * start_coverage; | ||
309 | 290 | + b = ((*column_src >> 0) & 0xff) * start_coverage; | ||
310 | 291 | + column_src += stride; | ||
311 | 292 | + box -= start_coverage; | ||
312 | 293 | + | ||
313 | 294 | + while (box >= pixel_coverage) | ||
314 | 295 | + { | ||
315 | 296 | + a += ((*column_src >> 24) & 0xff) * pixel_coverage; | ||
316 | 297 | + r += ((*column_src >> 16) & 0xff) * pixel_coverage; | ||
317 | 298 | + g += ((*column_src >> 8) & 0xff) * pixel_coverage; | ||
318 | 299 | + b += ((*column_src >> 0) & 0xff) * pixel_coverage; | ||
319 | 300 | + column_src += stride; | ||
320 | 301 | + box -= pixel_coverage; | ||
321 | 302 | + } | ||
322 | 303 | + | ||
323 | 304 | + if (box > 0) { | ||
324 | 305 | + a += ((*column_src >> 24) & 0xff) * box; | ||
325 | 306 | + r += ((*column_src >> 16) & 0xff) * box; | ||
326 | 307 | + g += ((*column_src >> 8) & 0xff) * box; | ||
327 | 308 | + b += ((*column_src >> 0) & 0xff) * box; | ||
328 | 309 | + } | ||
329 | 310 | + | ||
330 | 311 | + a >>= FIXED_SHIFT; | ||
331 | 312 | + r >>= FIXED_SHIFT; | ||
332 | 313 | + g >>= FIXED_SHIFT; | ||
333 | 314 | + b >>= FIXED_SHIFT; | ||
334 | 315 | + | ||
335 | 316 | + *dest = (a << 24) | (r << 16) | (g << 8) | b; | ||
336 | 317 | + dest++; | ||
337 | 318 | + src++; | ||
338 | 319 | + } | ||
339 | 320 | +} | ||
340 | 321 | + | ||
341 | 322 | +static int compute_coverage (int coverage[], int src_length, int dest_length) | ||
342 | 323 | +{ | ||
343 | 324 | + int i; | ||
344 | 325 | + /* num = src_length/dest_length | ||
345 | 326 | + total = sum(pixel) / num | ||
346 | 327 | + | ||
347 | 328 | + pixel * 1/num == pixel * dest_length / src_length | ||
348 | 329 | + */ | ||
349 | 330 | + /* the average contribution of each source pixel */ | ||
350 | 331 | + int ratio = ((1 << 24)*(long long int)dest_length)/src_length; | ||
351 | 332 | + /* because ((1 << 24)*(long long int)dest_length) won't always be divisible by src_length | ||
352 | 333 | + * we'll need someplace to put the other bits. | ||
353 | 334 | + * | ||
354 | 335 | + * We want to ensure a + n*ratio < 1<<24 | ||
355 | 336 | + * | ||
356 | 337 | + * 1<<24 | ||
357 | 338 | + * */ | ||
358 | 339 | + | ||
359 | 340 | + double scale = (double)src_length/dest_length; | ||
360 | 341 | + | ||
361 | 342 | + /* for each destination pixel compute the coverage of the left most pixel included in the box */ | ||
362 | 343 | + /* I have a proof of this, which this margin is too narrow to contain */ | ||
363 | 344 | + for (i=0; i<dest_length; i++) | ||
364 | 345 | + { | ||
365 | 346 | + float left_side = i*scale; | ||
366 | 347 | + float right_side = (i+1)*scale; | ||
367 | 348 | + float right_fract = right_side - floor (right_side); | ||
368 | 349 | + float left_fract = ceil (left_side) - left_side; | ||
369 | 350 | + int overage; | ||
370 | 351 | + /* find out how many source pixels will be used to fill the box */ | ||
371 | 352 | + int count = floor (right_side) - ceil (left_side); | ||
372 | 353 | + /* what's the maximum value this expression can become? | ||
373 | 354 | + floor((i+1)*scale) - ceil(i*scale) | ||
374 | 355 | + | ||
375 | 356 | + (i+1)*scale - i*scale == scale | ||
376 | 357 | + | ||
377 | 358 | + since floor((i+1)*scale) <= (i+1)*scale | ||
378 | 359 | + and ceil(i*scale) >= i*scale | ||
379 | 360 | + | ||
380 | 361 | + floor((i+1)*scale) - ceil(i*scale) <= scale | ||
381 | 362 | + | ||
382 | 363 | + further since: floor((i+1)*scale) - ceil(i*scale) is an integer | ||
383 | 364 | + | ||
384 | 365 | + therefore: | ||
385 | 366 | + floor((i+1)*scale) - ceil(i*scale) <= floor(scale) | ||
386 | 367 | + */ | ||
387 | 368 | + | ||
388 | 369 | + if (left_fract == 0.) | ||
389 | 370 | + count--; | ||
390 | 371 | + | ||
391 | 372 | + /* compute how much the right-most pixel contributes */ | ||
392 | 373 | + overage = ratio*(right_fract); | ||
393 | 374 | + | ||
394 | 375 | + /* the remainder is the the amount that the left-most pixel | ||
395 | 376 | + * contributes */ | ||
396 | 377 | + coverage[i] = (1<<24) - (count * ratio + overage); | ||
397 | 378 | + } | ||
398 | 379 | + | ||
399 | 380 | + return ratio; | ||
400 | 381 | +} | ||
401 | 382 | + | ||
402 | 383 | +GBool downscale_box_filter(uint32_t *orig, int orig_stride, unsigned orig_width, unsigned orig_height, | ||
403 | 384 | + signed scaled_width, signed scaled_height, | ||
404 | 385 | + uint16_t start_column, uint16_t start_row, | ||
405 | 386 | + uint16_t width, uint16_t height, | ||
406 | 387 | + uint32_t *dest, int dst_stride) | ||
407 | 388 | +{ | ||
408 | 389 | + int pixel_coverage_x, pixel_coverage_y; | ||
409 | 390 | + int dest_y; | ||
410 | 391 | + int src_y = 0; | ||
411 | 392 | + uint32_t *scanline = orig; | ||
412 | 393 | + int *x_coverage = NULL; | ||
413 | 394 | + int *y_coverage = NULL; | ||
414 | 395 | + uint32_t *temp_buf = NULL; | ||
415 | 396 | + GBool retval = gFalse; | ||
416 | 397 | + | ||
417 | 398 | + x_coverage = (int *)gmallocn3 (orig_width, 1, sizeof(int)); | ||
418 | 399 | + y_coverage = (int *)gmallocn3 (orig_height, 1, sizeof(int)); | ||
419 | 400 | + | ||
420 | 401 | + /* we need to allocate enough room for ceil(src_height/dest_height)+1 | ||
421 | 402 | + Example: | ||
422 | 403 | + src_height = 140 | ||
423 | 404 | + dest_height = 50 | ||
424 | 405 | + src_height/dest_height = 2.8 | ||
425 | 406 | + | ||
426 | 407 | + |-------------| 2.8 pixels | ||
427 | 408 | + |----|----|----|----| 4 pixels | ||
428 | 409 | + need to sample 3 pixels | ||
429 | 410 | + | ||
430 | 411 | + |-------------| 2.8 pixels | ||
431 | 412 | + |----|----|----|----| 4 pixels | ||
432 | 413 | + need to sample 4 pixels | ||
433 | 414 | + */ | ||
434 | 415 | + | ||
435 | 416 | + temp_buf = (uint32_t *)gmallocn3 ((orig_height + scaled_height-1)/scaled_height+1, scaled_width, sizeof(uint32_t)); | ||
436 | 417 | + | ||
437 | 418 | + if (!x_coverage || !y_coverage || !scanline || !temp_buf) | ||
438 | 419 | + goto cleanup; | ||
439 | 420 | + | ||
440 | 421 | + pixel_coverage_x = compute_coverage (x_coverage, orig_width, scaled_width); | ||
441 | 422 | + pixel_coverage_y = compute_coverage (y_coverage, orig_height, scaled_height); | ||
442 | 423 | + | ||
443 | 424 | + assert (width + start_column <= scaled_width); | ||
444 | 425 | + | ||
445 | 426 | + /* skip the rows at the beginning */ | ||
446 | 427 | + for (dest_y = 0; dest_y < start_row; dest_y++) | ||
447 | 428 | + { | ||
448 | 429 | + int box = 1 << FIXED_SHIFT; | ||
449 | 430 | + int start_coverage_y = y_coverage[dest_y]; | ||
450 | 431 | + box -= start_coverage_y; | ||
451 | 432 | + src_y++; | ||
452 | 433 | + while (box >= pixel_coverage_y) | ||
453 | 434 | + { | ||
454 | 435 | + box -= pixel_coverage_y; | ||
455 | 436 | + src_y++; | ||
456 | 437 | + } | ||
457 | 438 | + } | ||
458 | 439 | + | ||
459 | 440 | + for (; dest_y < start_row + height; dest_y++) | ||
460 | 441 | + { | ||
461 | 442 | + int columns = 0; | ||
462 | 443 | + int box = 1 << FIXED_SHIFT; | ||
463 | 444 | + int start_coverage_y = y_coverage[dest_y]; | ||
464 | 445 | + | ||
465 | 446 | + scanline = orig + src_y * orig_stride / 4; | ||
466 | 447 | + downsample_row_box_filter (start_column, width, scanline, temp_buf + width * columns, x_coverage, pixel_coverage_x); | ||
467 | 448 | + columns++; | ||
468 | 449 | + src_y++; | ||
469 | 450 | + box -= start_coverage_y; | ||
470 | 451 | + | ||
471 | 452 | + while (box >= pixel_coverage_y) | ||
472 | 453 | + { | ||
473 | 454 | + scanline = orig + src_y * orig_stride / 4; | ||
474 | 455 | + downsample_row_box_filter (start_column, width, scanline, temp_buf + width * columns, x_coverage, pixel_coverage_x); | ||
475 | 456 | + columns++; | ||
476 | 457 | + src_y++; | ||
477 | 458 | + box -= pixel_coverage_y; | ||
478 | 459 | + } | ||
479 | 460 | + | ||
480 | 461 | + /* downsample any leftovers */ | ||
481 | 462 | + if (box > 0) | ||
482 | 463 | + { | ||
483 | 464 | + scanline = orig + src_y * orig_stride / 4; | ||
484 | 465 | + downsample_row_box_filter (start_column, width, scanline, temp_buf + width * columns, x_coverage, pixel_coverage_x); | ||
485 | 466 | + columns++; | ||
486 | 467 | + } | ||
487 | 468 | + | ||
488 | 469 | + /* now scale the rows we just downsampled in the y direction */ | ||
489 | 470 | + downsample_columns_box_filter (width, start_coverage_y, pixel_coverage_y, temp_buf, dest); | ||
490 | 471 | + dest += dst_stride / 4; | ||
491 | 472 | + | ||
492 | 473 | +// assert(width*columns <= ((orig_height + scaled_height-1)/scaled_height+1) * width); | ||
493 | 474 | + } | ||
494 | 475 | +// assert (src_y<=orig_height); | ||
495 | 476 | + | ||
496 | 477 | + retval = gTrue; | ||
497 | 478 | + | ||
498 | 479 | +cleanup: | ||
499 | 480 | + free (x_coverage); | ||
500 | 481 | + free (y_coverage); | ||
501 | 482 | + free (temp_buf); | ||
502 | 483 | + | ||
503 | 484 | + return gTrue; | ||
504 | 485 | +} | ||
505 | 486 | diff -Nur -x '*.orig' -x '*~' poppler/poppler/CairoRescaleBox.h poppler.new/poppler/CairoRescaleBox.h | ||
506 | 487 | --- poppler/poppler/CairoRescaleBox.h 1970-01-01 01:00:00.000000000 +0100 | ||
507 | 488 | +++ poppler.new/poppler/CairoRescaleBox.h 2010-03-30 23:22:56.559527323 +0100 | ||
508 | 489 | @@ -0,0 +1,12 @@ | ||
509 | 490 | +#ifndef CAIRO_RESCALE_BOX_H | ||
510 | 491 | +#define CAIRO_RESCALE_BOX_H | ||
511 | 492 | + | ||
512 | 493 | +#include "goo/gtypes.h" | ||
513 | 494 | + | ||
514 | 495 | +GBool downscale_box_filter(unsigned int *orig, int orig_stride, unsigned orig_width, unsigned orig_height, | ||
515 | 496 | + signed scaled_width, signed scaled_height, | ||
516 | 497 | + unsigned short int start_column, unsigned short int start_row, | ||
517 | 498 | + unsigned short int width, unsigned short int height, | ||
518 | 499 | + unsigned int *dest, int dst_stride); | ||
519 | 500 | + | ||
520 | 501 | +#endif /* CAIRO_RESCALE_BOX_H */ | ||
521 | 502 | diff -Nur -x '*.orig' -x '*~' poppler/poppler/Makefile.am poppler.new/poppler/Makefile.am | ||
522 | 503 | --- poppler/poppler/Makefile.am 2010-03-30 23:08:49.306054000 +0100 | ||
523 | 504 | +++ poppler.new/poppler/Makefile.am 2010-03-30 23:22:56.559527323 +0100 | ||
524 | 505 | @@ -47,7 +47,9 @@ | ||
525 | 506 | CairoFontEngine.cc \ | ||
526 | 507 | CairoFontEngine.h \ | ||
527 | 508 | CairoOutputDev.cc \ | ||
528 | 509 | - CairoOutputDev.h | ||
529 | 510 | + CairoOutputDev.h \ | ||
530 | 511 | + CairoRescaleBox.cc \ | ||
531 | 512 | + CairoRescaleBox.h | ||
532 | 513 | |||
533 | 514 | endif | ||
534 | 515 |
From the bug report:
"Josh: Your patch modifies Makefile.am without updating Makefile.in or causing the packaging to run automake. So it fails to build the new object and dies with a linker error.
After fixing that, it seems to work for me on the examples from this bug, such as ubuntu- manual- draft.pdf.
I would suggest annotating the patch to say where it came from: /wiki.ubuntu. com/UbuntuDevel opment/ PatchTaggingGui delines"
https:/
Thanks,
James