File: | root/firefox-clang/gfx/cairo/libpixman/src/pixman-bits-image.c |
Warning: | line 790, column 2 Value stored to 'x' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. |
3 | * 2005 Lars Knoll & Zack Rusin, Trolltech |
4 | * 2008 Aaron Plattner, NVIDIA Corporation |
5 | * Copyright © 2000 SuSE, Inc. |
6 | * Copyright © 2007, 2009 Red Hat, Inc. |
7 | * Copyright © 2008 André Tupinambá <andrelrt@gmail.com> |
8 | * |
9 | * Permission to use, copy, modify, distribute, and sell this software and its |
10 | * documentation for any purpose is hereby granted without fee, provided that |
11 | * the above copyright notice appear in all copies and that both that |
12 | * copyright notice and this permission notice appear in supporting |
13 | * documentation, and that the name of Keith Packard not be used in |
14 | * advertising or publicity pertaining to distribution of the software without |
15 | * specific, written prior permission. Keith Packard makes no |
16 | * representations about the suitability of this software for any purpose. It |
17 | * is provided "as is" without express or implied warranty. |
18 | * |
19 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS |
20 | * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND |
21 | * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY |
22 | * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
23 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN |
24 | * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING |
25 | * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS |
26 | * SOFTWARE. |
27 | */ |
28 | |
29 | #ifdef HAVE_CONFIG_H |
30 | #include <pixman-config.h> |
31 | #endif |
32 | #include <stdio.h> |
33 | #include <stdlib.h> |
34 | #include <string.h> |
35 | #include "pixman-private.h" |
36 | #include "pixman-combine32.h" |
37 | #include "pixman-inlines.h" |
38 | #include "dither/blue-noise-64x64.h" |
39 | |
40 | /* Fetch functions */ |
41 | |
42 | static force_inline__inline__ __attribute__ ((__always_inline__)) void |
43 | fetch_pixel_no_alpha_32 (bits_image_t *image, |
44 | int x, int y, pixman_bool_t check_bounds, |
45 | void *out) |
46 | { |
47 | uint32_t *ret = out; |
48 | |
49 | if (check_bounds && |
50 | (x < 0 || x >= image->width || y < 0 || y >= image->height)) |
51 | *ret = 0; |
52 | else |
53 | *ret = image->fetch_pixel_32 (image, x, y); |
54 | } |
55 | |
56 | static force_inline__inline__ __attribute__ ((__always_inline__)) void |
57 | fetch_pixel_no_alpha_float (bits_image_t *image, |
58 | int x, int y, pixman_bool_t check_bounds, |
59 | void *out) |
60 | { |
61 | argb_t *ret = out; |
62 | |
63 | if (check_bounds && |
64 | (x < 0 || x >= image->width || y < 0 || y >= image->height)) |
65 | ret->a = ret->r = ret->g = ret->b = 0.f; |
66 | else |
67 | *ret = image->fetch_pixel_float (image, x, y); |
68 | } |
69 | |
70 | typedef void (* get_pixel_t) (bits_image_t *image, |
71 | int x, int y, pixman_bool_t check_bounds, void *out); |
72 | |
73 | static force_inline__inline__ __attribute__ ((__always_inline__)) void |
74 | bits_image_fetch_pixel_nearest (bits_image_t *image, |
75 | pixman_fixed_t x, |
76 | pixman_fixed_t y, |
77 | get_pixel_t get_pixel, |
78 | void *out) |
79 | { |
80 | int x0 = pixman_fixed_to_int (x - pixman_fixed_e)((int) ((x - ((pixman_fixed_t) 1)) >> 16)); |
81 | int y0 = pixman_fixed_to_int (y - pixman_fixed_e)((int) ((y - ((pixman_fixed_t) 1)) >> 16)); |
82 | |
83 | if (image->common.repeat != PIXMAN_REPEAT_NONE) |
84 | { |
85 | repeat (image->common.repeat, &x0, image->width); |
86 | repeat (image->common.repeat, &y0, image->height); |
87 | |
88 | get_pixel (image, x0, y0, FALSE0, out); |
89 | } |
90 | else |
91 | { |
92 | get_pixel (image, x0, y0, TRUE1, out); |
93 | } |
94 | } |
95 | |
96 | static force_inline__inline__ __attribute__ ((__always_inline__)) void |
97 | bits_image_fetch_pixel_bilinear_32 (bits_image_t *image, |
98 | pixman_fixed_t x, |
99 | pixman_fixed_t y, |
100 | get_pixel_t get_pixel, |
101 | void *out) |
102 | { |
103 | pixman_repeat_t repeat_mode = image->common.repeat; |
104 | int width = image->width; |
105 | int height = image->height; |
106 | int x1, y1, x2, y2; |
107 | uint32_t tl, tr, bl, br; |
108 | int32_t distx, disty; |
109 | uint32_t *ret = out; |
110 | |
111 | x1 = x - pixman_fixed_1(((pixman_fixed_t) ((uint32_t) (1) << 16))) / 2; |
112 | y1 = y - pixman_fixed_1(((pixman_fixed_t) ((uint32_t) (1) << 16))) / 2; |
113 | |
114 | distx = pixman_fixed_to_bilinear_weight (x1); |
115 | disty = pixman_fixed_to_bilinear_weight (y1); |
116 | |
117 | x1 = pixman_fixed_to_int (x1)((int) ((x1) >> 16)); |
118 | y1 = pixman_fixed_to_int (y1)((int) ((y1) >> 16)); |
119 | x2 = x1 + 1; |
120 | y2 = y1 + 1; |
121 | |
122 | if (repeat_mode != PIXMAN_REPEAT_NONE) |
123 | { |
124 | repeat (repeat_mode, &x1, width); |
125 | repeat (repeat_mode, &y1, height); |
126 | repeat (repeat_mode, &x2, width); |
127 | repeat (repeat_mode, &y2, height); |
128 | |
129 | get_pixel (image, x1, y1, FALSE0, &tl); |
130 | get_pixel (image, x2, y1, FALSE0, &tr); |
131 | get_pixel (image, x1, y2, FALSE0, &bl); |
132 | get_pixel (image, x2, y2, FALSE0, &br); |
133 | } |
134 | else |
135 | { |
136 | get_pixel (image, x1, y1, TRUE1, &tl); |
137 | get_pixel (image, x2, y1, TRUE1, &tr); |
138 | get_pixel (image, x1, y2, TRUE1, &bl); |
139 | get_pixel (image, x2, y2, TRUE1, &br); |
140 | } |
141 | |
142 | *ret = bilinear_interpolation (tl, tr, bl, br, distx, disty); |
143 | } |
144 | |
145 | static force_inline__inline__ __attribute__ ((__always_inline__)) void |
146 | bits_image_fetch_pixel_bilinear_float (bits_image_t *image, |
147 | pixman_fixed_t x, |
148 | pixman_fixed_t y, |
149 | get_pixel_t get_pixel, |
150 | void *out) |
151 | { |
152 | pixman_repeat_t repeat_mode = image->common.repeat; |
153 | int width = image->width; |
154 | int height = image->height; |
155 | int x1, y1, x2, y2; |
156 | argb_t tl, tr, bl, br; |
157 | float distx, disty; |
158 | argb_t *ret = out; |
159 | |
160 | x1 = x - pixman_fixed_1(((pixman_fixed_t) ((uint32_t) (1) << 16))) / 2; |
161 | y1 = y - pixman_fixed_1(((pixman_fixed_t) ((uint32_t) (1) << 16))) / 2; |
162 | |
163 | distx = ((float)pixman_fixed_fraction(x1)((x1) & ((((pixman_fixed_t) ((uint32_t) (1) << 16)) ) - ((pixman_fixed_t) 1)))) / 65536.f; |
164 | disty = ((float)pixman_fixed_fraction(y1)((y1) & ((((pixman_fixed_t) ((uint32_t) (1) << 16)) ) - ((pixman_fixed_t) 1)))) / 65536.f; |
165 | |
166 | x1 = pixman_fixed_to_int (x1)((int) ((x1) >> 16)); |
167 | y1 = pixman_fixed_to_int (y1)((int) ((y1) >> 16)); |
168 | x2 = x1 + 1; |
169 | y2 = y1 + 1; |
170 | |
171 | if (repeat_mode != PIXMAN_REPEAT_NONE) |
172 | { |
173 | repeat (repeat_mode, &x1, width); |
174 | repeat (repeat_mode, &y1, height); |
175 | repeat (repeat_mode, &x2, width); |
176 | repeat (repeat_mode, &y2, height); |
177 | |
178 | get_pixel (image, x1, y1, FALSE0, &tl); |
179 | get_pixel (image, x2, y1, FALSE0, &tr); |
180 | get_pixel (image, x1, y2, FALSE0, &bl); |
181 | get_pixel (image, x2, y2, FALSE0, &br); |
182 | } |
183 | else |
184 | { |
185 | get_pixel (image, x1, y1, TRUE1, &tl); |
186 | get_pixel (image, x2, y1, TRUE1, &tr); |
187 | get_pixel (image, x1, y2, TRUE1, &bl); |
188 | get_pixel (image, x2, y2, TRUE1, &br); |
189 | } |
190 | |
191 | *ret = bilinear_interpolation_float (tl, tr, bl, br, distx, disty); |
192 | } |
193 | |
194 | static force_inline__inline__ __attribute__ ((__always_inline__)) void accum_32(unsigned int *satot, unsigned int *srtot, |
195 | unsigned int *sgtot, unsigned int *sbtot, |
196 | const void *p, pixman_fixed_t f) |
197 | { |
198 | uint32_t pixel = *(uint32_t *)p; |
199 | |
200 | *srtot += (int)RED_8 (pixel)(((pixel) >> 8 * 2) & 0xff) * f; |
201 | *sgtot += (int)GREEN_8 (pixel)(((pixel) >> 8) & 0xff) * f; |
202 | *sbtot += (int)BLUE_8 (pixel)((pixel) & 0xff) * f; |
203 | *satot += (int)ALPHA_8 (pixel)((pixel) >> 8 * 3) * f; |
204 | } |
205 | |
206 | static force_inline__inline__ __attribute__ ((__always_inline__)) void reduce_32(unsigned int satot, unsigned int srtot, |
207 | unsigned int sgtot, unsigned int sbtot, |
208 | void *p) |
209 | { |
210 | uint32_t *ret = p; |
211 | |
212 | satot = (int32_t)(satot + 0x8000) / 65536; |
213 | srtot = (int32_t)(srtot + 0x8000) / 65536; |
214 | sgtot = (int32_t)(sgtot + 0x8000) / 65536; |
215 | sbtot = (int32_t)(sbtot + 0x8000) / 65536; |
216 | |
217 | satot = CLIP ((int32_t)satot, 0, 0xff)(((int32_t)satot) < (0) ? (0) : (((int32_t)satot) > (0xff ) ? (0xff) : ((int32_t)satot))); |
218 | srtot = CLIP ((int32_t)srtot, 0, 0xff)(((int32_t)srtot) < (0) ? (0) : (((int32_t)srtot) > (0xff ) ? (0xff) : ((int32_t)srtot))); |
219 | sgtot = CLIP ((int32_t)sgtot, 0, 0xff)(((int32_t)sgtot) < (0) ? (0) : (((int32_t)sgtot) > (0xff ) ? (0xff) : ((int32_t)sgtot))); |
220 | sbtot = CLIP ((int32_t)sbtot, 0, 0xff)(((int32_t)sbtot) < (0) ? (0) : (((int32_t)sbtot) > (0xff ) ? (0xff) : ((int32_t)sbtot))); |
221 | |
222 | *ret = ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot)); |
223 | } |
224 | |
225 | static force_inline__inline__ __attribute__ ((__always_inline__)) void accum_float(unsigned int *satot, unsigned int *srtot, |
226 | unsigned int *sgtot, unsigned int *sbtot, |
227 | const void *p, pixman_fixed_t f) |
228 | { |
229 | const argb_t *pixel = p; |
230 | |
231 | *satot += pixel->a * f; |
232 | *srtot += pixel->r * f; |
233 | *sgtot += pixel->g * f; |
234 | *sbtot += pixel->b * f; |
235 | } |
236 | |
237 | static force_inline__inline__ __attribute__ ((__always_inline__)) void reduce_float(unsigned int satot, unsigned int srtot, |
238 | unsigned int sgtot, unsigned int sbtot, |
239 | void *p) |
240 | { |
241 | argb_t *ret = p; |
242 | |
243 | ret->a = CLIP ((int32_t)satot / 65536.f, 0.f, 1.f)(((int32_t)satot / 65536.f) < (0.f) ? (0.f) : (((int32_t)satot / 65536.f) > (1.f) ? (1.f) : ((int32_t)satot / 65536.f))); |
244 | ret->r = CLIP ((int32_t)srtot / 65536.f, 0.f, 1.f)(((int32_t)srtot / 65536.f) < (0.f) ? (0.f) : (((int32_t)srtot / 65536.f) > (1.f) ? (1.f) : ((int32_t)srtot / 65536.f))); |
245 | ret->g = CLIP ((int32_t)sgtot / 65536.f, 0.f, 1.f)(((int32_t)sgtot / 65536.f) < (0.f) ? (0.f) : (((int32_t)sgtot / 65536.f) > (1.f) ? (1.f) : ((int32_t)sgtot / 65536.f))); |
246 | ret->b = CLIP ((int32_t)sbtot / 65536.f, 0.f, 1.f)(((int32_t)sbtot / 65536.f) < (0.f) ? (0.f) : (((int32_t)sbtot / 65536.f) > (1.f) ? (1.f) : ((int32_t)sbtot / 65536.f))); |
247 | } |
248 | |
249 | typedef void (* accumulate_pixel_t) (unsigned int *satot, unsigned int *srtot, |
250 | unsigned int *sgtot, unsigned int *sbtot, |
251 | const void *pixel, pixman_fixed_t f); |
252 | |
253 | typedef void (* reduce_pixel_t) (unsigned int satot, unsigned int srtot, |
254 | unsigned int sgtot, unsigned int sbtot, |
255 | void *out); |
256 | |
257 | static force_inline__inline__ __attribute__ ((__always_inline__)) void |
258 | bits_image_fetch_pixel_convolution (bits_image_t *image, |
259 | pixman_fixed_t x, |
260 | pixman_fixed_t y, |
261 | get_pixel_t get_pixel, |
262 | void *out, |
263 | accumulate_pixel_t accum, |
264 | reduce_pixel_t reduce) |
265 | { |
266 | pixman_fixed_t *params = image->common.filter_params; |
267 | int x_off = (params[0] - pixman_fixed_1(((pixman_fixed_t) ((uint32_t) (1) << 16)))) >> 1; |
268 | int y_off = (params[1] - pixman_fixed_1(((pixman_fixed_t) ((uint32_t) (1) << 16)))) >> 1; |
269 | int32_t cwidth = pixman_fixed_to_int (params[0])((int) ((params[0]) >> 16)); |
270 | int32_t cheight = pixman_fixed_to_int (params[1])((int) ((params[1]) >> 16)); |
271 | int32_t i, j, x1, x2, y1, y2; |
272 | pixman_repeat_t repeat_mode = image->common.repeat; |
273 | int width = image->width; |
274 | int height = image->height; |
275 | unsigned int srtot, sgtot, sbtot, satot; |
276 | |
277 | params += 2; |
278 | |
279 | x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off)((int) ((x - ((pixman_fixed_t) 1) - x_off) >> 16)); |
280 | y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off)((int) ((y - ((pixman_fixed_t) 1) - y_off) >> 16)); |
281 | x2 = x1 + cwidth; |
282 | y2 = y1 + cheight; |
283 | |
284 | srtot = sgtot = sbtot = satot = 0; |
285 | |
286 | for (i = y1; i < y2; ++i) |
287 | { |
288 | for (j = x1; j < x2; ++j) |
289 | { |
290 | int rx = j; |
291 | int ry = i; |
292 | |
293 | pixman_fixed_t f = *params; |
294 | |
295 | if (f) |
296 | { |
297 | /* Must be big enough to hold a argb_t */ |
298 | argb_t pixel; |
299 | |
300 | if (repeat_mode != PIXMAN_REPEAT_NONE) |
301 | { |
302 | repeat (repeat_mode, &rx, width); |
303 | repeat (repeat_mode, &ry, height); |
304 | |
305 | get_pixel (image, rx, ry, FALSE0, &pixel); |
306 | } |
307 | else |
308 | { |
309 | get_pixel (image, rx, ry, TRUE1, &pixel); |
310 | } |
311 | |
312 | accum (&satot, &srtot, &sgtot, &sbtot, &pixel, f); |
313 | } |
314 | |
315 | params++; |
316 | } |
317 | } |
318 | |
319 | reduce (satot, srtot, sgtot, sbtot, out); |
320 | } |
321 | |
322 | static void |
323 | bits_image_fetch_pixel_separable_convolution (bits_image_t *image, |
324 | pixman_fixed_t x, |
325 | pixman_fixed_t y, |
326 | get_pixel_t get_pixel, |
327 | void *out, |
328 | accumulate_pixel_t accum, |
329 | reduce_pixel_t reduce) |
330 | { |
331 | pixman_fixed_t *params = image->common.filter_params; |
332 | pixman_repeat_t repeat_mode = image->common.repeat; |
333 | int width = image->width; |
334 | int height = image->height; |
335 | int cwidth = pixman_fixed_to_int (params[0])((int) ((params[0]) >> 16)); |
336 | int cheight = pixman_fixed_to_int (params[1])((int) ((params[1]) >> 16)); |
337 | int x_phase_bits = pixman_fixed_to_int (params[2])((int) ((params[2]) >> 16)); |
338 | int y_phase_bits = pixman_fixed_to_int (params[3])((int) ((params[3]) >> 16)); |
339 | int x_phase_shift = 16 - x_phase_bits; |
340 | int y_phase_shift = 16 - y_phase_bits; |
341 | int x_off = ((cwidth << 16) - pixman_fixed_1(((pixman_fixed_t) ((uint32_t) (1) << 16)))) >> 1; |
342 | int y_off = ((cheight << 16) - pixman_fixed_1(((pixman_fixed_t) ((uint32_t) (1) << 16)))) >> 1; |
343 | pixman_fixed_t *y_params; |
344 | unsigned int srtot, sgtot, sbtot, satot; |
345 | int32_t x1, x2, y1, y2; |
346 | int32_t px, py; |
347 | int i, j; |
348 | |
349 | /* Round x and y to the middle of the closest phase before continuing. This |
350 | * ensures that the convolution matrix is aligned right, since it was |
351 | * positioned relative to a particular phase (and not relative to whatever |
352 | * exact fraction we happen to get here). |
353 | */ |
354 | x = ((x >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1); |
355 | y = ((y >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1); |
356 | |
357 | px = (x & 0xffff) >> x_phase_shift; |
358 | py = (y & 0xffff) >> y_phase_shift; |
359 | |
360 | y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight; |
361 | |
362 | x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off)((int) ((x - ((pixman_fixed_t) 1) - x_off) >> 16)); |
363 | y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off)((int) ((y - ((pixman_fixed_t) 1) - y_off) >> 16)); |
364 | x2 = x1 + cwidth; |
365 | y2 = y1 + cheight; |
366 | |
367 | srtot = sgtot = sbtot = satot = 0; |
368 | |
369 | for (i = y1; i < y2; ++i) |
370 | { |
371 | pixman_fixed_48_16_t fy = *y_params++; |
372 | pixman_fixed_t *x_params = params + 4 + px * cwidth; |
373 | |
374 | if (fy) |
375 | { |
376 | for (j = x1; j < x2; ++j) |
377 | { |
378 | pixman_fixed_t fx = *x_params++; |
379 | int rx = j; |
380 | int ry = i; |
381 | |
382 | if (fx) |
383 | { |
384 | /* Must be big enough to hold a argb_t */ |
385 | argb_t pixel; |
386 | pixman_fixed_t f; |
387 | |
388 | if (repeat_mode != PIXMAN_REPEAT_NONE) |
389 | { |
390 | repeat (repeat_mode, &rx, width); |
391 | repeat (repeat_mode, &ry, height); |
392 | |
393 | get_pixel (image, rx, ry, FALSE0, &pixel); |
394 | } |
395 | else |
396 | { |
397 | get_pixel (image, rx, ry, TRUE1, &pixel); |
398 | } |
399 | |
400 | f = (fy * fx + 0x8000) >> 16; |
401 | |
402 | accum(&satot, &srtot, &sgtot, &sbtot, &pixel, f); |
403 | } |
404 | } |
405 | } |
406 | } |
407 | |
408 | |
409 | reduce(satot, srtot, sgtot, sbtot, out); |
410 | } |
411 | |
412 | static force_inline__inline__ __attribute__ ((__always_inline__)) void |
413 | bits_image_fetch_pixel_filtered (bits_image_t *image, |
414 | pixman_bool_t wide, |
415 | pixman_fixed_t x, |
416 | pixman_fixed_t y, |
417 | get_pixel_t get_pixel, |
418 | void *out) |
419 | { |
420 | switch (image->common.filter) |
421 | { |
422 | case PIXMAN_FILTER_NEAREST: |
423 | case PIXMAN_FILTER_FAST: |
424 | bits_image_fetch_pixel_nearest (image, x, y, get_pixel, out); |
425 | break; |
426 | |
427 | case PIXMAN_FILTER_BILINEAR: |
428 | case PIXMAN_FILTER_GOOD: |
429 | case PIXMAN_FILTER_BEST: |
430 | if (wide) |
431 | bits_image_fetch_pixel_bilinear_float (image, x, y, get_pixel, out); |
432 | else |
433 | bits_image_fetch_pixel_bilinear_32 (image, x, y, get_pixel, out); |
434 | break; |
435 | |
436 | case PIXMAN_FILTER_CONVOLUTION: |
437 | if (wide) |
438 | { |
439 | bits_image_fetch_pixel_convolution (image, x, y, |
440 | get_pixel, out, |
441 | accum_float, |
442 | reduce_float); |
443 | } |
444 | else |
445 | { |
446 | bits_image_fetch_pixel_convolution (image, x, y, |
447 | get_pixel, out, |
448 | accum_32, reduce_32); |
449 | } |
450 | break; |
451 | |
452 | case PIXMAN_FILTER_SEPARABLE_CONVOLUTION: |
453 | if (wide) |
454 | { |
455 | bits_image_fetch_pixel_separable_convolution (image, x, y, |
456 | get_pixel, out, |
457 | accum_float, |
458 | reduce_float); |
459 | } |
460 | else |
461 | { |
462 | bits_image_fetch_pixel_separable_convolution (image, x, y, |
463 | get_pixel, out, |
464 | accum_32, reduce_32); |
465 | } |
466 | break; |
467 | |
468 | default: |
469 | assert (0)((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail ("0", "/root/firefox-clang/gfx/cairo/libpixman/src/pixman-bits-image.c" , 469, __extension__ __PRETTY_FUNCTION__); })); |
470 | break; |
471 | } |
472 | } |
473 | |
474 | static uint32_t * |
475 | __bits_image_fetch_affine_no_alpha (pixman_iter_t * iter, |
476 | pixman_bool_t wide, |
477 | const uint32_t * mask) |
478 | { |
479 | pixman_image_t *image = iter->image; |
480 | int offset = iter->x; |
481 | int line = iter->y++; |
482 | int width = iter->width; |
483 | uint32_t * buffer = iter->buffer; |
484 | |
485 | const uint32_t wide_zero[4] = {0}; |
486 | pixman_fixed_t x, y; |
487 | pixman_fixed_t ux, uy; |
488 | pixman_vector_t v; |
489 | int i; |
490 | get_pixel_t get_pixel = |
491 | wide ? fetch_pixel_no_alpha_float : fetch_pixel_no_alpha_32; |
492 | |
493 | /* reference point is the center of the pixel */ |
494 | v.vector[0] = pixman_int_to_fixed (offset)((pixman_fixed_t) ((uint32_t) (offset) << 16)) + pixman_fixed_1(((pixman_fixed_t) ((uint32_t) (1) << 16))) / 2; |
495 | v.vector[1] = pixman_int_to_fixed (line)((pixman_fixed_t) ((uint32_t) (line) << 16)) + pixman_fixed_1(((pixman_fixed_t) ((uint32_t) (1) << 16))) / 2; |
496 | v.vector[2] = pixman_fixed_1(((pixman_fixed_t) ((uint32_t) (1) << 16))); |
497 | |
498 | if (image->common.transform) |
499 | { |
500 | if (!pixman_transform_point_3d_moz_pixman_transform_point_3d (image->common.transform, &v)) |
501 | return iter->buffer; |
502 | |
503 | ux = image->common.transform->matrix[0][0]; |
504 | uy = image->common.transform->matrix[1][0]; |
505 | } |
506 | else |
507 | { |
508 | ux = pixman_fixed_1(((pixman_fixed_t) ((uint32_t) (1) << 16))); |
509 | uy = 0; |
510 | } |
511 | |
512 | x = v.vector[0]; |
513 | y = v.vector[1]; |
514 | |
515 | for (i = 0; i < width; ++i) |
516 | { |
517 | if (!mask || (!wide && mask[i]) || |
518 | (wide && memcmp(&mask[4 * i], wide_zero, 16) != 0)) |
519 | { |
520 | bits_image_fetch_pixel_filtered ( |
521 | &image->bits, wide, x, y, get_pixel, buffer); |
522 | } |
523 | |
524 | x += ux; |
525 | y += uy; |
526 | buffer += wide ? 4 : 1; |
527 | } |
528 | |
529 | return iter->buffer; |
530 | } |
531 | |
532 | static uint32_t * |
533 | bits_image_fetch_affine_no_alpha_32 (pixman_iter_t *iter, |
534 | const uint32_t *mask) |
535 | { |
536 | return __bits_image_fetch_affine_no_alpha(iter, FALSE0, mask); |
537 | } |
538 | |
539 | static uint32_t * |
540 | bits_image_fetch_affine_no_alpha_float (pixman_iter_t *iter, |
541 | const uint32_t *mask) |
542 | { |
543 | return __bits_image_fetch_affine_no_alpha(iter, TRUE1, mask); |
544 | } |
545 | |
546 | /* General fetcher */ |
547 | static force_inline__inline__ __attribute__ ((__always_inline__)) void |
548 | fetch_pixel_general_32 (bits_image_t *image, |
549 | int x, int y, pixman_bool_t check_bounds, |
550 | void *out) |
551 | { |
552 | uint32_t pixel, *ret = out; |
553 | |
554 | if (check_bounds && |
555 | (x < 0 || x >= image->width || y < 0 || y >= image->height)) |
556 | { |
557 | *ret = 0; |
558 | return; |
559 | } |
560 | |
561 | pixel = image->fetch_pixel_32 (image, x, y); |
562 | |
563 | if (image->common.alpha_map) |
564 | { |
565 | uint32_t pixel_a; |
566 | |
567 | x -= image->common.alpha_origin_x; |
568 | y -= image->common.alpha_origin_y; |
569 | |
570 | if (x < 0 || x >= image->common.alpha_map->width || |
571 | y < 0 || y >= image->common.alpha_map->height) |
572 | { |
573 | pixel_a = 0; |
574 | } |
575 | else |
576 | { |
577 | pixel_a = image->common.alpha_map->fetch_pixel_32 ( |
578 | image->common.alpha_map, x, y); |
579 | |
580 | pixel_a = ALPHA_8 (pixel_a)((pixel_a) >> 8 * 3); |
581 | } |
582 | |
583 | pixel &= 0x00ffffff; |
584 | pixel |= (pixel_a << 24); |
585 | } |
586 | |
587 | *ret = pixel; |
588 | } |
589 | |
590 | static force_inline__inline__ __attribute__ ((__always_inline__)) void |
591 | fetch_pixel_general_float (bits_image_t *image, |
592 | int x, int y, pixman_bool_t check_bounds, |
593 | void *out) |
594 | { |
595 | argb_t *ret = out; |
596 | |
597 | if (check_bounds && |
598 | (x < 0 || x >= image->width || y < 0 || y >= image->height)) |
599 | { |
600 | ret->a = ret->r = ret->g = ret->b = 0; |
601 | return; |
602 | } |
603 | |
604 | *ret = image->fetch_pixel_float (image, x, y); |
605 | |
606 | if (image->common.alpha_map) |
607 | { |
608 | x -= image->common.alpha_origin_x; |
609 | y -= image->common.alpha_origin_y; |
610 | |
611 | if (x < 0 || x >= image->common.alpha_map->width || |
612 | y < 0 || y >= image->common.alpha_map->height) |
613 | { |
614 | ret->a = 0.f; |
615 | } |
616 | else |
617 | { |
618 | argb_t alpha; |
619 | |
620 | alpha = image->common.alpha_map->fetch_pixel_float ( |
621 | image->common.alpha_map, x, y); |
622 | |
623 | ret->a = alpha.a; |
624 | } |
625 | } |
626 | } |
627 | |
628 | static uint32_t * |
629 | __bits_image_fetch_general (pixman_iter_t *iter, |
630 | pixman_bool_t wide, |
631 | const uint32_t *mask) |
632 | { |
633 | pixman_image_t *image = iter->image; |
634 | int offset = iter->x; |
635 | int line = iter->y++; |
636 | int width = iter->width; |
637 | uint32_t * buffer = iter->buffer; |
638 | get_pixel_t get_pixel = |
639 | wide ? fetch_pixel_general_float : fetch_pixel_general_32; |
640 | |
641 | const uint32_t wide_zero[4] = {0}; |
642 | pixman_fixed_t x, y, w; |
643 | pixman_fixed_t ux, uy, uw; |
644 | pixman_vector_t v; |
645 | int i; |
646 | |
647 | /* reference point is the center of the pixel */ |
648 | v.vector[0] = pixman_int_to_fixed (offset)((pixman_fixed_t) ((uint32_t) (offset) << 16)) + pixman_fixed_1(((pixman_fixed_t) ((uint32_t) (1) << 16))) / 2; |
649 | v.vector[1] = pixman_int_to_fixed (line)((pixman_fixed_t) ((uint32_t) (line) << 16)) + pixman_fixed_1(((pixman_fixed_t) ((uint32_t) (1) << 16))) / 2; |
650 | v.vector[2] = pixman_fixed_1(((pixman_fixed_t) ((uint32_t) (1) << 16))); |
651 | |
652 | if (image->common.transform) |
653 | { |
654 | if (!pixman_transform_point_3d_moz_pixman_transform_point_3d (image->common.transform, &v)) |
655 | return buffer; |
656 | |
657 | ux = image->common.transform->matrix[0][0]; |
658 | uy = image->common.transform->matrix[1][0]; |
659 | uw = image->common.transform->matrix[2][0]; |
660 | } |
661 | else |
662 | { |
663 | ux = pixman_fixed_1(((pixman_fixed_t) ((uint32_t) (1) << 16))); |
664 | uy = 0; |
665 | uw = 0; |
666 | } |
667 | |
668 | x = v.vector[0]; |
669 | y = v.vector[1]; |
670 | w = v.vector[2]; |
671 | |
672 | for (i = 0; i < width; ++i) |
673 | { |
674 | pixman_fixed_t x0, y0; |
675 | |
676 | if (!mask || (!wide && mask[i]) || |
677 | (wide && memcmp(&mask[4 * i], wide_zero, 16) != 0)) |
678 | { |
679 | if (w != 0) |
680 | { |
681 | x0 = ((uint64_t)x << 16) / w; |
682 | y0 = ((uint64_t)y << 16) / w; |
683 | } |
684 | else |
685 | { |
686 | x0 = 0; |
687 | y0 = 0; |
688 | } |
689 | |
690 | bits_image_fetch_pixel_filtered ( |
691 | &image->bits, wide, x0, y0, get_pixel, buffer); |
692 | } |
693 | |
694 | x += ux; |
695 | y += uy; |
696 | w += uw; |
697 | buffer += wide ? 4 : 1; |
698 | } |
699 | |
700 | return iter->buffer; |
701 | } |
702 | |
703 | static uint32_t * |
704 | bits_image_fetch_general_32 (pixman_iter_t *iter, |
705 | const uint32_t *mask) |
706 | { |
707 | return __bits_image_fetch_general(iter, FALSE0, mask); |
708 | } |
709 | |
710 | static uint32_t * |
711 | bits_image_fetch_general_float (pixman_iter_t *iter, |
712 | const uint32_t *mask) |
713 | { |
714 | return __bits_image_fetch_general(iter, TRUE1, mask); |
715 | } |
716 | |
717 | static void |
718 | replicate_pixel_32 (bits_image_t * bits, |
719 | int x, |
720 | int y, |
721 | int width, |
722 | uint32_t * buffer) |
723 | { |
724 | uint32_t color; |
725 | uint32_t *end; |
726 | |
727 | color = bits->fetch_pixel_32 (bits, x, y); |
728 | |
729 | end = buffer + width; |
730 | while (buffer < end) |
731 | *(buffer++) = color; |
732 | } |
733 | |
734 | static void |
735 | replicate_pixel_float (bits_image_t * bits, |
736 | int x, |
737 | int y, |
738 | int width, |
739 | uint32_t * b) |
740 | { |
741 | argb_t color; |
742 | argb_t *buffer = (argb_t *)b; |
743 | argb_t *end; |
744 | |
745 | color = bits->fetch_pixel_float (bits, x, y); |
746 | |
747 | end = buffer + width; |
748 | while (buffer < end) |
749 | *(buffer++) = color; |
750 | } |
751 | |
752 | static void |
753 | bits_image_fetch_untransformed_repeat_none (bits_image_t *image, |
754 | pixman_bool_t wide, |
755 | int x, |
756 | int y, |
757 | int width, |
758 | uint32_t * buffer) |
759 | { |
760 | uint32_t w; |
761 | |
762 | if (y < 0 || y >= image->height) |
763 | { |
764 | memset (buffer, 0, width * (wide? sizeof (argb_t) : 4)); |
765 | return; |
766 | } |
767 | |
768 | if (x < 0) |
769 | { |
770 | w = MIN (width, -x)((width < -x) ? width : -x); |
771 | |
772 | memset (buffer, 0, w * (wide ? sizeof (argb_t) : 4)); |
773 | |
774 | width -= w; |
775 | buffer += w * (wide? 4 : 1); |
776 | x += w; |
777 | } |
778 | |
779 | if (x < image->width) |
780 | { |
781 | w = MIN (width, image->width - x)((width < image->width - x) ? width : image->width - x); |
782 | |
783 | if (wide) |
784 | image->fetch_scanline_float (image, x, y, w, buffer, NULL((void*)0)); |
785 | else |
786 | image->fetch_scanline_32 (image, x, y, w, buffer, NULL((void*)0)); |
787 | |
788 | width -= w; |
789 | buffer += w * (wide? 4 : 1); |
790 | x += w; |
Value stored to 'x' is never read | |
791 | } |
792 | |
793 | memset (buffer, 0, width * (wide ? sizeof (argb_t) : 4)); |
794 | } |
795 | |
796 | static void |
797 | bits_image_fetch_untransformed_repeat_normal (bits_image_t *image, |
798 | pixman_bool_t wide, |
799 | int x, |
800 | int y, |
801 | int width, |
802 | uint32_t * buffer) |
803 | { |
804 | uint32_t w; |
805 | |
806 | while (y < 0) |
807 | y += image->height; |
808 | |
809 | while (y >= image->height) |
810 | y -= image->height; |
811 | |
812 | if (image->width == 1) |
813 | { |
814 | if (wide) |
815 | replicate_pixel_float (image, 0, y, width, buffer); |
816 | else |
817 | replicate_pixel_32 (image, 0, y, width, buffer); |
818 | |
819 | return; |
820 | } |
821 | |
822 | while (width) |
823 | { |
824 | while (x < 0) |
825 | x += image->width; |
826 | while (x >= image->width) |
827 | x -= image->width; |
828 | |
829 | w = MIN (width, image->width - x)((width < image->width - x) ? width : image->width - x); |
830 | |
831 | if (wide) |
832 | image->fetch_scanline_float (image, x, y, w, buffer, NULL((void*)0)); |
833 | else |
834 | image->fetch_scanline_32 (image, x, y, w, buffer, NULL((void*)0)); |
835 | |
836 | buffer += w * (wide? 4 : 1); |
837 | x += w; |
838 | width -= w; |
839 | } |
840 | } |
841 | |
842 | static uint32_t * |
843 | bits_image_fetch_untransformed_32 (pixman_iter_t * iter, |
844 | const uint32_t *mask) |
845 | { |
846 | pixman_image_t *image = iter->image; |
847 | int x = iter->x; |
848 | int y = iter->y; |
849 | int width = iter->width; |
850 | uint32_t * buffer = iter->buffer; |
851 | |
852 | if (image->common.repeat == PIXMAN_REPEAT_NONE) |
853 | { |
854 | bits_image_fetch_untransformed_repeat_none ( |
855 | &image->bits, FALSE0, x, y, width, buffer); |
856 | } |
857 | else |
858 | { |
859 | bits_image_fetch_untransformed_repeat_normal ( |
860 | &image->bits, FALSE0, x, y, width, buffer); |
861 | } |
862 | |
863 | iter->y++; |
864 | return buffer; |
865 | } |
866 | |
867 | static uint32_t * |
868 | bits_image_fetch_untransformed_float (pixman_iter_t * iter, |
869 | const uint32_t *mask) |
870 | { |
871 | pixman_image_t *image = iter->image; |
872 | int x = iter->x; |
873 | int y = iter->y; |
874 | int width = iter->width; |
875 | uint32_t * buffer = iter->buffer; |
876 | |
877 | if (image->common.repeat == PIXMAN_REPEAT_NONE) |
878 | { |
879 | bits_image_fetch_untransformed_repeat_none ( |
880 | &image->bits, TRUE1, x, y, width, buffer); |
881 | } |
882 | else |
883 | { |
884 | bits_image_fetch_untransformed_repeat_normal ( |
885 | &image->bits, TRUE1, x, y, width, buffer); |
886 | } |
887 | |
888 | iter->y++; |
889 | return buffer; |
890 | } |
891 | |
892 | typedef struct |
893 | { |
894 | pixman_format_code_t format; |
895 | uint32_t flags; |
896 | pixman_iter_get_scanline_t get_scanline_32; |
897 | pixman_iter_get_scanline_t get_scanline_float; |
898 | } fetcher_info_t; |
899 | |
900 | static const fetcher_info_t fetcher_info[] = |
901 | { |
902 | { PIXMAN_any(((0) << 24) | ((5) << 16) | ((0) << 12) | ( (0) << 8) | ((0) << 4) | ((0))), |
903 | (FAST_PATH_NO_ALPHA_MAP(1 << 1) | |
904 | FAST_PATH_ID_TRANSFORM(1 << 0) | |
905 | FAST_PATH_NO_CONVOLUTION_FILTER(1 << 2) | |
906 | FAST_PATH_NO_PAD_REPEAT(1 << 3) | |
907 | FAST_PATH_NO_REFLECT_REPEAT(1 << 4)), |
908 | bits_image_fetch_untransformed_32, |
909 | bits_image_fetch_untransformed_float |
910 | }, |
911 | |
912 | /* Affine, no alpha */ |
913 | { PIXMAN_any(((0) << 24) | ((5) << 16) | ((0) << 12) | ( (0) << 8) | ((0) << 4) | ((0))), |
914 | (FAST_PATH_NO_ALPHA_MAP(1 << 1) | FAST_PATH_HAS_TRANSFORM(1 << 12) | FAST_PATH_AFFINE_TRANSFORM(1 << 17)), |
915 | bits_image_fetch_affine_no_alpha_32, |
916 | bits_image_fetch_affine_no_alpha_float, |
917 | }, |
918 | |
919 | /* General */ |
920 | { PIXMAN_any(((0) << 24) | ((5) << 16) | ((0) << 12) | ( (0) << 8) | ((0) << 4) | ((0))), |
921 | 0, |
922 | bits_image_fetch_general_32, |
923 | bits_image_fetch_general_float, |
924 | }, |
925 | |
926 | { PIXMAN_null(((0) << 24) | ((0) << 16) | ((0) << 12) | ( (0) << 8) | ((0) << 4) | ((0))) }, |
927 | }; |
928 | |
929 | static void |
930 | bits_image_property_changed (pixman_image_t *image) |
931 | { |
932 | _pixman_bits_image_setup_accessors (&image->bits); |
933 | } |
934 | |
935 | void |
936 | _pixman_bits_image_src_iter_init (pixman_image_t *image, pixman_iter_t *iter) |
937 | { |
938 | pixman_format_code_t format = image->common.extended_format_code; |
939 | uint32_t flags = image->common.flags; |
940 | const fetcher_info_t *info; |
941 | |
942 | for (info = fetcher_info; info->format != PIXMAN_null(((0) << 24) | ((0) << 16) | ((0) << 12) | ( (0) << 8) | ((0) << 4) | ((0))); ++info) |
943 | { |
944 | if ((info->format == format || info->format == PIXMAN_any(((0) << 24) | ((5) << 16) | ((0) << 12) | ( (0) << 8) | ((0) << 4) | ((0)))) && |
945 | (info->flags & flags) == info->flags) |
946 | { |
947 | if (iter->iter_flags & ITER_NARROW) |
948 | { |
949 | iter->get_scanline = info->get_scanline_32; |
950 | } |
951 | else |
952 | { |
953 | iter->get_scanline = info->get_scanline_float; |
954 | } |
955 | return; |
956 | } |
957 | } |
958 | |
959 | /* Just in case we somehow didn't find a scanline function */ |
960 | iter->get_scanline = _pixman_iter_get_scanline_noop; |
961 | } |
962 | |
963 | static uint32_t * |
964 | dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask) |
965 | { |
966 | pixman_image_t *image = iter->image; |
967 | int x = iter->x; |
968 | int y = iter->y; |
969 | int width = iter->width; |
970 | uint32_t * buffer = iter->buffer; |
971 | |
972 | image->bits.fetch_scanline_32 (&image->bits, x, y, width, buffer, mask); |
973 | if (image->common.alpha_map) |
974 | { |
975 | uint32_t *alpha; |
976 | |
977 | if ((alpha = malloc (width * sizeof (uint32_t)))) |
978 | { |
979 | int i; |
980 | |
981 | x -= image->common.alpha_origin_x; |
982 | y -= image->common.alpha_origin_y; |
983 | |
984 | image->common.alpha_map->fetch_scanline_32 ( |
985 | image->common.alpha_map, x, y, width, alpha, mask); |
986 | |
987 | for (i = 0; i < width; ++i) |
988 | { |
989 | buffer[i] &= ~0xff000000; |
990 | buffer[i] |= (alpha[i] & 0xff000000); |
991 | } |
992 | |
993 | free (alpha); |
994 | } |
995 | } |
996 | |
997 | return iter->buffer; |
998 | } |
999 | |
1000 | static uint32_t * |
1001 | dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask) |
1002 | { |
1003 | bits_image_t * image = &iter->image->bits; |
1004 | int x = iter->x; |
1005 | int y = iter->y; |
1006 | int width = iter->width; |
1007 | argb_t * buffer = (argb_t *)iter->buffer; |
1008 | |
1009 | image->fetch_scanline_float ( |
1010 | image, x, y, width, (uint32_t *)buffer, mask); |
1011 | if (image->common.alpha_map) |
1012 | { |
1013 | argb_t *alpha; |
1014 | |
1015 | if ((alpha = malloc (width * sizeof (argb_t)))) |
1016 | { |
1017 | int i; |
1018 | |
1019 | x -= image->common.alpha_origin_x; |
1020 | y -= image->common.alpha_origin_y; |
1021 | |
1022 | image->common.alpha_map->fetch_scanline_float ( |
1023 | image->common.alpha_map, x, y, width, (uint32_t *)alpha, mask); |
1024 | |
1025 | for (i = 0; i < width; ++i) |
1026 | buffer[i].a = alpha[i].a; |
1027 | |
1028 | free (alpha); |
1029 | } |
1030 | } |
1031 | |
1032 | return iter->buffer; |
1033 | } |
1034 | |
1035 | static void |
1036 | dest_write_back_narrow (pixman_iter_t *iter) |
1037 | { |
1038 | bits_image_t * image = &iter->image->bits; |
1039 | int x = iter->x; |
1040 | int y = iter->y; |
1041 | int width = iter->width; |
1042 | const uint32_t *buffer = iter->buffer; |
1043 | |
1044 | image->store_scanline_32 (image, x, y, width, buffer); |
1045 | |
1046 | if (image->common.alpha_map) |
1047 | { |
1048 | x -= image->common.alpha_origin_x; |
1049 | y -= image->common.alpha_origin_y; |
1050 | |
1051 | image->common.alpha_map->store_scanline_32 ( |
1052 | image->common.alpha_map, x, y, width, buffer); |
1053 | } |
1054 | |
1055 | iter->y++; |
1056 | } |
1057 | |
1058 | static float |
1059 | dither_factor_blue_noise_64 (int x, int y) |
1060 | { |
1061 | float m = dither_blue_noise_64x64[((y & 0x3f) << 6) | (x & 0x3f)]; |
1062 | return m * (1. / 4096.f) + (1. / 8192.f); |
1063 | } |
1064 | |
1065 | static float |
1066 | dither_factor_bayer_8 (int x, int y) |
1067 | { |
1068 | uint32_t m; |
1069 | |
1070 | y ^= x; |
1071 | |
1072 | /* Compute reverse(interleave(xor(x mod n, y mod n), x mod n)) |
1073 | * Here n = 8 and `mod n` is the bottom 3 bits. |
1074 | */ |
1075 | m = ((y & 0x1) << 5) | ((x & 0x1) << 4) | |
1076 | ((y & 0x2) << 2) | ((x & 0x2) << 1) | |
1077 | ((y & 0x4) >> 1) | ((x & 0x4) >> 2); |
1078 | |
1079 | /* m is in range [0, 63]. We scale it to [0, 63.0f/64.0f], then |
1080 | * shift it to to [1.0f/128.0f, 127.0f/128.0f] so that 0 < d < 1. |
1081 | * This ensures exact values are not changed by dithering. |
1082 | */ |
1083 | return (float)(m) * (1 / 64.0f) + (1.0f / 128.0f); |
1084 | } |
1085 | |
1086 | typedef float (* dither_factor_t)(int x, int y); |
1087 | |
1088 | static force_inline__inline__ __attribute__ ((__always_inline__)) float |
1089 | dither_apply_channel (float f, float d, float s) |
1090 | { |
1091 | /* float_to_unorm splits the [0, 1] segment in (1 << n_bits) |
1092 | * subsections of equal length; however unorm_to_float does not |
1093 | * map to the center of those sections. In fact, pixel value u is |
1094 | * mapped to: |
1095 | * |
1096 | * u u u 1 |
1097 | * -------------- = ---------- + -------------- * ---------- |
1098 | * 2^n_bits - 1 2^n_bits 2^n_bits - 1 2^n_bits |
1099 | * |
1100 | * Hence if f = u / (2^n_bits - 1) is exactly representable on a |
1101 | * n_bits palette, all the numbers between |
1102 | * |
1103 | * u |
1104 | * ---------- = f - f * 2^n_bits = f + (0 - f) * 2^n_bits |
1105 | * 2^n_bits |
1106 | * |
1107 | * and |
1108 | * |
1109 | * u + 1 |
1110 | * ---------- = f - (f - 1) * 2^n_bits = f + (1 - f) * 2^n_bits |
1111 | * 2^n_bits |
1112 | * |
1113 | * are also mapped back to u. |
1114 | * |
1115 | * Hence the following calculation ensures that we add as much |
1116 | * noise as possible without perturbing values which are exactly |
1117 | * representable in the target colorspace. Note that this corresponds to |
1118 | * mixing the original color with noise with a ratio of `1 / 2^n_bits`. |
1119 | */ |
1120 | return f + (d - f) * s; |
1121 | } |
1122 | |
1123 | static force_inline__inline__ __attribute__ ((__always_inline__)) float |
1124 | dither_compute_scale (int n_bits) |
1125 | { |
1126 | // No dithering for wide formats |
1127 | if (n_bits == 0 || n_bits >= 32) |
1128 | return 0.f; |
1129 | |
1130 | return 1.f / (float)(1 << n_bits); |
1131 | } |
1132 | |
1133 | static const uint32_t * |
1134 | dither_apply_ordered (pixman_iter_t *iter, dither_factor_t factor) |
1135 | { |
1136 | bits_image_t *image = &iter->image->bits; |
1137 | int x = iter->x + image->dither_offset_x; |
1138 | int y = iter->y + image->dither_offset_y; |
1139 | int width = iter->width; |
1140 | argb_t *buffer = (argb_t *)iter->buffer; |
1141 | |
1142 | pixman_format_code_t format = image->format; |
1143 | int a_size = PIXMAN_FORMAT_A (format)(((format >> (12)) & ((1 << (4)) - 1)) << ((format >> 22) & 3)); |
1144 | int r_size = PIXMAN_FORMAT_R (format)(((format >> (8)) & ((1 << (4)) - 1)) << ((format >> 22) & 3)); |
1145 | int g_size = PIXMAN_FORMAT_G (format)(((format >> (4)) & ((1 << (4)) - 1)) << ((format >> 22) & 3)); |
1146 | int b_size = PIXMAN_FORMAT_B (format)(((format >> (0)) & ((1 << (4)) - 1)) << ((format >> 22) & 3)); |
1147 | |
1148 | float a_scale = dither_compute_scale (a_size); |
1149 | float r_scale = dither_compute_scale (r_size); |
1150 | float g_scale = dither_compute_scale (g_size); |
1151 | float b_scale = dither_compute_scale (b_size); |
1152 | |
1153 | int i; |
1154 | float d; |
1155 | |
1156 | for (i = 0; i < width; ++i) |
1157 | { |
1158 | d = factor (x + i, y); |
1159 | |
1160 | buffer->a = dither_apply_channel (buffer->a, d, a_scale); |
1161 | buffer->r = dither_apply_channel (buffer->r, d, r_scale); |
1162 | buffer->g = dither_apply_channel (buffer->g, d, g_scale); |
1163 | buffer->b = dither_apply_channel (buffer->b, d, b_scale); |
1164 | |
1165 | buffer++; |
1166 | } |
1167 | |
1168 | return iter->buffer; |
1169 | } |
1170 | |
1171 | static void |
1172 | dest_write_back_wide (pixman_iter_t *iter) |
1173 | { |
1174 | bits_image_t * image = &iter->image->bits; |
1175 | int x = iter->x; |
1176 | int y = iter->y; |
1177 | int width = iter->width; |
1178 | const uint32_t *buffer = iter->buffer; |
1179 | |
1180 | switch (image->dither) |
1181 | { |
1182 | case PIXMAN_DITHER_NONE: |
1183 | break; |
1184 | |
1185 | case PIXMAN_DITHER_GOOD: |
1186 | case PIXMAN_DITHER_BEST: |
1187 | case PIXMAN_DITHER_ORDERED_BLUE_NOISE_64: |
1188 | buffer = dither_apply_ordered (iter, dither_factor_blue_noise_64); |
1189 | break; |
1190 | |
1191 | case PIXMAN_DITHER_FAST: |
1192 | case PIXMAN_DITHER_ORDERED_BAYER_8: |
1193 | buffer = dither_apply_ordered (iter, dither_factor_bayer_8); |
1194 | break; |
1195 | } |
1196 | |
1197 | image->store_scanline_float (image, x, y, width, buffer); |
1198 | |
1199 | if (image->common.alpha_map) |
1200 | { |
1201 | x -= image->common.alpha_origin_x; |
1202 | y -= image->common.alpha_origin_y; |
1203 | |
1204 | image->common.alpha_map->store_scanline_float ( |
1205 | image->common.alpha_map, x, y, width, buffer); |
1206 | } |
1207 | |
1208 | iter->y++; |
1209 | } |
1210 | |
1211 | void |
1212 | _pixman_bits_image_dest_iter_init (pixman_image_t *image, pixman_iter_t *iter) |
1213 | { |
1214 | if (iter->iter_flags & ITER_NARROW) |
1215 | { |
1216 | if ((iter->iter_flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) == |
1217 | (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) |
1218 | { |
1219 | iter->get_scanline = _pixman_iter_get_scanline_noop; |
1220 | } |
1221 | else |
1222 | { |
1223 | iter->get_scanline = dest_get_scanline_narrow; |
1224 | } |
1225 | |
1226 | iter->write_back = dest_write_back_narrow; |
1227 | } |
1228 | else |
1229 | { |
1230 | iter->get_scanline = dest_get_scanline_wide; |
1231 | iter->write_back = dest_write_back_wide; |
1232 | } |
1233 | } |
1234 | |
1235 | static uint32_t * |
1236 | create_bits (pixman_format_code_t format, |
1237 | int width, |
1238 | int height, |
1239 | int * rowstride_bytes, |
1240 | pixman_bool_t clear) |
1241 | { |
1242 | int stride; |
1243 | size_t buf_size; |
1244 | int bpp; |
1245 | |
1246 | /* what follows is a long-winded way, avoiding any possibility of integer |
1247 | * overflows, of saying: |
1248 | * stride = ((width * bpp + 0x1f) >> 5) * sizeof (uint32_t); |
1249 | */ |
1250 | |
1251 | bpp = PIXMAN_FORMAT_BPP (format)(((format >> (24)) & ((1 << (8)) - 1)) << ((format >> 22) & 3)); |
1252 | if (_pixman_multiply_overflows_int (width, bpp)) |
1253 | return NULL((void*)0); |
1254 | |
1255 | stride = width * bpp; |
1256 | if (_pixman_addition_overflows_int (stride, 0x1f)) |
1257 | return NULL((void*)0); |
1258 | |
1259 | stride += 0x1f; |
1260 | stride >>= 5; |
1261 | |
1262 | stride *= sizeof (uint32_t); |
1263 | |
1264 | if (_pixman_multiply_overflows_size (height, stride)) |
1265 | return NULL((void*)0); |
1266 | |
1267 | buf_size = (size_t)height * stride; |
1268 | |
1269 | if (rowstride_bytes) |
1270 | *rowstride_bytes = stride; |
1271 | |
1272 | if (clear) |
1273 | return calloc (1, buf_size); |
1274 | else |
1275 | return malloc (buf_size); |
1276 | } |
1277 | |
1278 | pixman_bool_t |
1279 | _pixman_bits_image_init (pixman_image_t * image, |
1280 | pixman_format_code_t format, |
1281 | int width, |
1282 | int height, |
1283 | uint32_t * bits, |
1284 | int rowstride, |
1285 | pixman_bool_t clear) |
1286 | { |
1287 | uint32_t *free_me = NULL((void*)0); |
1288 | |
1289 | if (PIXMAN_FORMAT_BPP (format)(((format >> (24)) & ((1 << (8)) - 1)) << ((format >> 22) & 3)) == 128) |
1290 | return_val_if_fail(!(rowstride % 4), FALSE)do { if (__builtin_expect ((!(!(rowstride % 4))), 0)) { _pixman_log_error (((const char*) (__PRETTY_FUNCTION__)), "The expression " "!(rowstride % 4)" " was false"); return (0); } } while (0); |
1291 | |
1292 | if (!bits && width && height) |
1293 | { |
1294 | int rowstride_bytes; |
1295 | |
1296 | free_me = bits = create_bits (format, width, height, &rowstride_bytes, clear); |
1297 | |
1298 | if (!bits) |
1299 | return FALSE0; |
1300 | |
1301 | rowstride = rowstride_bytes / (int) sizeof (uint32_t); |
1302 | } |
1303 | |
1304 | _pixman_image_init (image); |
1305 | |
1306 | image->type = BITS; |
1307 | image->bits.format = format; |
1308 | image->bits.width = width; |
1309 | image->bits.height = height; |
1310 | image->bits.bits = bits; |
1311 | image->bits.free_me = free_me; |
1312 | image->bits.dither = PIXMAN_DITHER_NONE; |
1313 | image->bits.dither_offset_x = 0; |
1314 | image->bits.dither_offset_y = 0; |
1315 | image->bits.read_func = NULL((void*)0); |
1316 | image->bits.write_func = NULL((void*)0); |
1317 | image->bits.rowstride = rowstride; |
1318 | image->bits.indexed = NULL((void*)0); |
1319 | |
1320 | image->common.property_changed = bits_image_property_changed; |
1321 | |
1322 | _pixman_image_reset_clip_region (image); |
1323 | |
1324 | return TRUE1; |
1325 | } |
1326 | |
1327 | static pixman_image_t * |
1328 | create_bits_image_internal (pixman_format_code_t format, |
1329 | int width, |
1330 | int height, |
1331 | uint32_t * bits, |
1332 | int rowstride_bytes, |
1333 | pixman_bool_t clear) |
1334 | { |
1335 | pixman_image_t *image; |
1336 | |
1337 | /* must be a whole number of uint32_t's |
1338 | */ |
1339 | return_val_if_fail (do { if (__builtin_expect ((!(bits == ((void*)0) || (rowstride_bytes % sizeof (uint32_t)) == 0)), 0)) { _pixman_log_error (((const char*) (__PRETTY_FUNCTION__)), "The expression " "bits == NULL || (rowstride_bytes % sizeof (uint32_t)) == 0" " was false"); return (((void*)0)); } } while (0) |
1340 | bits == NULL || (rowstride_bytes % sizeof (uint32_t)) == 0, NULL)do { if (__builtin_expect ((!(bits == ((void*)0) || (rowstride_bytes % sizeof (uint32_t)) == 0)), 0)) { _pixman_log_error (((const char*) (__PRETTY_FUNCTION__)), "The expression " "bits == NULL || (rowstride_bytes % sizeof (uint32_t)) == 0" " was false"); return (((void*)0)); } } while (0); |
1341 | |
1342 | return_val_if_fail (PIXMAN_FORMAT_BPP (format) >= PIXMAN_FORMAT_DEPTH (format), NULL)do { if (__builtin_expect ((!((((format >> (24)) & ( (1 << (8)) - 1)) << ((format >> 22) & 3 )) >= ((((format >> (12)) & ((1 << (4)) - 1 )) << ((format >> 22) & 3)) + (((format >> (8)) & ((1 << (4)) - 1)) << ((format >> 22) & 3)) + (((format >> (4)) & ((1 << ( 4)) - 1)) << ((format >> 22) & 3)) + (((format >> (0)) & ((1 << (4)) - 1)) << ((format >> 22) & 3))))), 0)) { _pixman_log_error (((const char *) (__PRETTY_FUNCTION__)), "The expression " "PIXMAN_FORMAT_BPP (format) >= PIXMAN_FORMAT_DEPTH (format)" " was false"); return (((void*)0)); } } while (0); |
1343 | |
1344 | image = _pixman_image_allocate (); |
1345 | |
1346 | if (!image) |
1347 | return NULL((void*)0); |
1348 | |
1349 | if (!_pixman_bits_image_init (image, format, width, height, bits, |
1350 | rowstride_bytes / (int) sizeof (uint32_t), |
1351 | clear)) |
1352 | { |
1353 | free (image); |
1354 | return NULL((void*)0); |
1355 | } |
1356 | |
1357 | return image; |
1358 | } |
1359 | |
1360 | /* If bits is NULL, a buffer will be allocated and initialized to 0 */ |
1361 | PIXMAN_EXPORTextern __attribute__((visibility("hidden"))) pixman_image_t * |
1362 | pixman_image_create_bits_moz_pixman_image_create_bits (pixman_format_code_t format, |
1363 | int width, |
1364 | int height, |
1365 | uint32_t * bits, |
1366 | int rowstride_bytes) |
1367 | { |
1368 | return create_bits_image_internal ( |
1369 | format, width, height, bits, rowstride_bytes, TRUE1); |
1370 | } |
1371 | |
1372 | |
1373 | /* If bits is NULL, a buffer will be allocated and _not_ initialized */ |
1374 | PIXMAN_EXPORTextern __attribute__((visibility("hidden"))) pixman_image_t * |
1375 | pixman_image_create_bits_no_clear (pixman_format_code_t format, |
1376 | int width, |
1377 | int height, |
1378 | uint32_t * bits, |
1379 | int rowstride_bytes) |
1380 | { |
1381 | return create_bits_image_internal ( |
1382 | format, width, height, bits, rowstride_bytes, FALSE0); |
1383 | } |