Rev 1891 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1891 | serge | 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á |
||
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 |
||
31 | #endif |
||
32 | #include |
||
33 | #include |
||
34 | #include |
||
35 | #include "pixman-private.h" |
||
36 | #include "pixman-combine32.h" |
||
3931 | Serge | 37 | #include "pixman-inlines.h" |
1891 | serge | 38 | |
3931 | Serge | 39 | static uint32_t * |
40 | _pixman_image_get_scanline_generic_float (pixman_iter_t * iter, |
||
41 | const uint32_t *mask) |
||
1891 | serge | 42 | { |
3931 | Serge | 43 | pixman_iter_get_scanline_t fetch_32 = iter->data; |
44 | uint32_t *buffer = iter->buffer; |
||
1891 | serge | 45 | |
3931 | Serge | 46 | fetch_32 (iter, NULL); |
1891 | serge | 47 | |
3931 | Serge | 48 | pixman_expand_to_float ((argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width); |
1891 | serge | 49 | |
3931 | Serge | 50 | return iter->buffer; |
1891 | serge | 51 | } |
52 | |||
53 | /* Fetch functions */ |
||
54 | |||
55 | static force_inline uint32_t |
||
56 | fetch_pixel_no_alpha (bits_image_t *image, |
||
57 | int x, int y, pixman_bool_t check_bounds) |
||
58 | { |
||
59 | if (check_bounds && |
||
60 | (x < 0 || x >= image->width || y < 0 || y >= image->height)) |
||
61 | { |
||
62 | return 0; |
||
63 | } |
||
64 | |||
65 | return image->fetch_pixel_32 (image, x, y); |
||
66 | } |
||
67 | |||
68 | typedef uint32_t (* get_pixel_t) (bits_image_t *image, |
||
69 | int x, int y, pixman_bool_t check_bounds); |
||
70 | |||
71 | static force_inline uint32_t |
||
72 | bits_image_fetch_pixel_nearest (bits_image_t *image, |
||
73 | pixman_fixed_t x, |
||
74 | pixman_fixed_t y, |
||
75 | get_pixel_t get_pixel) |
||
76 | { |
||
77 | int x0 = pixman_fixed_to_int (x - pixman_fixed_e); |
||
78 | int y0 = pixman_fixed_to_int (y - pixman_fixed_e); |
||
79 | |||
80 | if (image->common.repeat != PIXMAN_REPEAT_NONE) |
||
81 | { |
||
3931 | Serge | 82 | repeat (image->common.repeat, &x0, image->width); |
83 | repeat (image->common.repeat, &y0, image->height); |
||
1891 | serge | 84 | |
85 | return get_pixel (image, x0, y0, FALSE); |
||
86 | } |
||
87 | else |
||
88 | { |
||
89 | return get_pixel (image, x0, y0, TRUE); |
||
90 | } |
||
91 | } |
||
92 | |||
93 | static force_inline uint32_t |
||
94 | bits_image_fetch_pixel_bilinear (bits_image_t *image, |
||
95 | pixman_fixed_t x, |
||
96 | pixman_fixed_t y, |
||
97 | get_pixel_t get_pixel) |
||
98 | { |
||
99 | pixman_repeat_t repeat_mode = image->common.repeat; |
||
100 | int width = image->width; |
||
101 | int height = image->height; |
||
102 | int x1, y1, x2, y2; |
||
103 | uint32_t tl, tr, bl, br; |
||
104 | int32_t distx, disty; |
||
105 | |||
106 | x1 = x - pixman_fixed_1 / 2; |
||
107 | y1 = y - pixman_fixed_1 / 2; |
||
108 | |||
3931 | Serge | 109 | distx = pixman_fixed_to_bilinear_weight (x1); |
110 | disty = pixman_fixed_to_bilinear_weight (y1); |
||
1891 | serge | 111 | |
112 | x1 = pixman_fixed_to_int (x1); |
||
113 | y1 = pixman_fixed_to_int (y1); |
||
114 | x2 = x1 + 1; |
||
115 | y2 = y1 + 1; |
||
116 | |||
117 | if (repeat_mode != PIXMAN_REPEAT_NONE) |
||
118 | { |
||
3931 | Serge | 119 | repeat (repeat_mode, &x1, width); |
120 | repeat (repeat_mode, &y1, height); |
||
121 | repeat (repeat_mode, &x2, width); |
||
122 | repeat (repeat_mode, &y2, height); |
||
1891 | serge | 123 | |
124 | tl = get_pixel (image, x1, y1, FALSE); |
||
125 | bl = get_pixel (image, x1, y2, FALSE); |
||
126 | tr = get_pixel (image, x2, y1, FALSE); |
||
127 | br = get_pixel (image, x2, y2, FALSE); |
||
128 | } |
||
129 | else |
||
130 | { |
||
131 | tl = get_pixel (image, x1, y1, TRUE); |
||
132 | tr = get_pixel (image, x2, y1, TRUE); |
||
133 | bl = get_pixel (image, x1, y2, TRUE); |
||
134 | br = get_pixel (image, x2, y2, TRUE); |
||
135 | } |
||
136 | |||
137 | return bilinear_interpolation (tl, tr, bl, br, distx, disty); |
||
138 | } |
||
139 | |||
3931 | Serge | 140 | static uint32_t * |
141 | bits_image_fetch_bilinear_no_repeat_8888 (pixman_iter_t *iter, |
||
142 | const uint32_t *mask) |
||
1891 | serge | 143 | { |
3931 | Serge | 144 | |
145 | pixman_image_t * ima = iter->image; |
||
146 | int offset = iter->x; |
||
147 | int line = iter->y++; |
||
148 | int width = iter->width; |
||
149 | uint32_t * buffer = iter->buffer; |
||
150 | |||
1891 | serge | 151 | bits_image_t *bits = &ima->bits; |
152 | pixman_fixed_t x_top, x_bottom, x; |
||
153 | pixman_fixed_t ux_top, ux_bottom, ux; |
||
154 | pixman_vector_t v; |
||
155 | uint32_t top_mask, bottom_mask; |
||
156 | uint32_t *top_row; |
||
157 | uint32_t *bottom_row; |
||
158 | uint32_t *end; |
||
159 | uint32_t zero[2] = { 0, 0 }; |
||
160 | uint32_t one = 1; |
||
161 | int y, y1, y2; |
||
162 | int disty; |
||
163 | int mask_inc; |
||
164 | int w; |
||
165 | |||
166 | /* reference point is the center of the pixel */ |
||
167 | v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2; |
||
168 | v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2; |
||
169 | v.vector[2] = pixman_fixed_1; |
||
170 | |||
171 | if (!pixman_transform_point_3d (bits->common.transform, &v)) |
||
3931 | Serge | 172 | return iter->buffer; |
1891 | serge | 173 | |
174 | ux = ux_top = ux_bottom = bits->common.transform->matrix[0][0]; |
||
175 | x = x_top = x_bottom = v.vector[0] - pixman_fixed_1/2; |
||
176 | |||
177 | y = v.vector[1] - pixman_fixed_1/2; |
||
3931 | Serge | 178 | disty = pixman_fixed_to_bilinear_weight (y); |
1891 | serge | 179 | |
180 | /* Load the pointers to the first and second lines from the source |
||
181 | * image that bilinear code must read. |
||
182 | * |
||
183 | * The main trick in this code is about the check if any line are |
||
184 | * outside of the image; |
||
185 | * |
||
186 | * When I realize that a line (any one) is outside, I change |
||
187 | * the pointer to a dummy area with zeros. Once I change this, I |
||
188 | * must be sure the pointer will not change, so I set the |
||
189 | * variables to each pointer increments inside the loop. |
||
190 | */ |
||
191 | y1 = pixman_fixed_to_int (y); |
||
192 | y2 = y1 + 1; |
||
193 | |||
194 | if (y1 < 0 || y1 >= bits->height) |
||
195 | { |
||
196 | top_row = zero; |
||
197 | x_top = 0; |
||
198 | ux_top = 0; |
||
199 | } |
||
200 | else |
||
201 | { |
||
202 | top_row = bits->bits + y1 * bits->rowstride; |
||
203 | x_top = x; |
||
204 | ux_top = ux; |
||
205 | } |
||
206 | |||
207 | if (y2 < 0 || y2 >= bits->height) |
||
208 | { |
||
209 | bottom_row = zero; |
||
210 | x_bottom = 0; |
||
211 | ux_bottom = 0; |
||
212 | } |
||
213 | else |
||
214 | { |
||
215 | bottom_row = bits->bits + y2 * bits->rowstride; |
||
216 | x_bottom = x; |
||
217 | ux_bottom = ux; |
||
218 | } |
||
219 | |||
220 | /* Instead of checking whether the operation uses the mast in |
||
221 | * each loop iteration, verify this only once and prepare the |
||
222 | * variables to make the code smaller inside the loop. |
||
223 | */ |
||
224 | if (!mask) |
||
225 | { |
||
226 | mask_inc = 0; |
||
227 | mask = &one; |
||
228 | } |
||
229 | else |
||
230 | { |
||
231 | /* If have a mask, prepare the variables to check it */ |
||
232 | mask_inc = 1; |
||
233 | } |
||
234 | |||
235 | /* If both are zero, then the whole thing is zero */ |
||
236 | if (top_row == zero && bottom_row == zero) |
||
237 | { |
||
238 | memset (buffer, 0, width * sizeof (uint32_t)); |
||
3931 | Serge | 239 | return iter->buffer; |
1891 | serge | 240 | } |
241 | else if (bits->format == PIXMAN_x8r8g8b8) |
||
242 | { |
||
243 | if (top_row == zero) |
||
244 | { |
||
245 | top_mask = 0; |
||
246 | bottom_mask = 0xff000000; |
||
247 | } |
||
248 | else if (bottom_row == zero) |
||
249 | { |
||
250 | top_mask = 0xff000000; |
||
251 | bottom_mask = 0; |
||
252 | } |
||
253 | else |
||
254 | { |
||
255 | top_mask = 0xff000000; |
||
256 | bottom_mask = 0xff000000; |
||
257 | } |
||
258 | } |
||
259 | else |
||
260 | { |
||
261 | top_mask = 0; |
||
262 | bottom_mask = 0; |
||
263 | } |
||
264 | |||
265 | end = buffer + width; |
||
266 | |||
267 | /* Zero fill to the left of the image */ |
||
268 | while (buffer < end && x < pixman_fixed_minus_1) |
||
269 | { |
||
270 | *buffer++ = 0; |
||
271 | x += ux; |
||
272 | x_top += ux_top; |
||
273 | x_bottom += ux_bottom; |
||
274 | mask += mask_inc; |
||
275 | } |
||
276 | |||
277 | /* Left edge |
||
278 | */ |
||
279 | while (buffer < end && x < 0) |
||
280 | { |
||
281 | uint32_t tr, br; |
||
282 | int32_t distx; |
||
283 | |||
284 | tr = top_row[pixman_fixed_to_int (x_top) + 1] | top_mask; |
||
285 | br = bottom_row[pixman_fixed_to_int (x_bottom) + 1] | bottom_mask; |
||
286 | |||
3931 | Serge | 287 | distx = pixman_fixed_to_bilinear_weight (x); |
1891 | serge | 288 | |
289 | *buffer++ = bilinear_interpolation (0, tr, 0, br, distx, disty); |
||
290 | |||
291 | x += ux; |
||
292 | x_top += ux_top; |
||
293 | x_bottom += ux_bottom; |
||
294 | mask += mask_inc; |
||
295 | } |
||
296 | |||
297 | /* Main part */ |
||
298 | w = pixman_int_to_fixed (bits->width - 1); |
||
299 | |||
300 | while (buffer < end && x < w) |
||
301 | { |
||
302 | if (*mask) |
||
303 | { |
||
304 | uint32_t tl, tr, bl, br; |
||
305 | int32_t distx; |
||
306 | |||
307 | tl = top_row [pixman_fixed_to_int (x_top)] | top_mask; |
||
308 | tr = top_row [pixman_fixed_to_int (x_top) + 1] | top_mask; |
||
309 | bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask; |
||
310 | br = bottom_row [pixman_fixed_to_int (x_bottom) + 1] | bottom_mask; |
||
311 | |||
3931 | Serge | 312 | distx = pixman_fixed_to_bilinear_weight (x); |
1891 | serge | 313 | |
314 | *buffer = bilinear_interpolation (tl, tr, bl, br, distx, disty); |
||
315 | } |
||
316 | |||
317 | buffer++; |
||
318 | x += ux; |
||
319 | x_top += ux_top; |
||
320 | x_bottom += ux_bottom; |
||
321 | mask += mask_inc; |
||
322 | } |
||
323 | |||
324 | /* Right Edge */ |
||
325 | w = pixman_int_to_fixed (bits->width); |
||
326 | while (buffer < end && x < w) |
||
327 | { |
||
328 | if (*mask) |
||
329 | { |
||
330 | uint32_t tl, bl; |
||
331 | int32_t distx; |
||
332 | |||
333 | tl = top_row [pixman_fixed_to_int (x_top)] | top_mask; |
||
334 | bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask; |
||
335 | |||
3931 | Serge | 336 | distx = pixman_fixed_to_bilinear_weight (x); |
1891 | serge | 337 | |
338 | *buffer = bilinear_interpolation (tl, 0, bl, 0, distx, disty); |
||
339 | } |
||
340 | |||
341 | buffer++; |
||
342 | x += ux; |
||
343 | x_top += ux_top; |
||
344 | x_bottom += ux_bottom; |
||
345 | mask += mask_inc; |
||
346 | } |
||
347 | |||
348 | /* Zero fill to the left of the image */ |
||
349 | while (buffer < end) |
||
350 | *buffer++ = 0; |
||
3931 | Serge | 351 | |
352 | return iter->buffer; |
||
1891 | serge | 353 | } |
354 | |||
355 | static force_inline uint32_t |
||
356 | bits_image_fetch_pixel_convolution (bits_image_t *image, |
||
357 | pixman_fixed_t x, |
||
358 | pixman_fixed_t y, |
||
359 | get_pixel_t get_pixel) |
||
360 | { |
||
361 | pixman_fixed_t *params = image->common.filter_params; |
||
362 | int x_off = (params[0] - pixman_fixed_1) >> 1; |
||
363 | int y_off = (params[1] - pixman_fixed_1) >> 1; |
||
364 | int32_t cwidth = pixman_fixed_to_int (params[0]); |
||
365 | int32_t cheight = pixman_fixed_to_int (params[1]); |
||
366 | int32_t i, j, x1, x2, y1, y2; |
||
367 | pixman_repeat_t repeat_mode = image->common.repeat; |
||
368 | int width = image->width; |
||
369 | int height = image->height; |
||
3931 | Serge | 370 | int srtot, sgtot, sbtot, satot; |
1891 | serge | 371 | |
372 | params += 2; |
||
373 | |||
374 | x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off); |
||
375 | y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off); |
||
376 | x2 = x1 + cwidth; |
||
377 | y2 = y1 + cheight; |
||
378 | |||
379 | srtot = sgtot = sbtot = satot = 0; |
||
380 | |||
381 | for (i = y1; i < y2; ++i) |
||
382 | { |
||
383 | for (j = x1; j < x2; ++j) |
||
384 | { |
||
385 | int rx = j; |
||
386 | int ry = i; |
||
387 | |||
388 | pixman_fixed_t f = *params; |
||
389 | |||
390 | if (f) |
||
391 | { |
||
392 | uint32_t pixel; |
||
393 | |||
394 | if (repeat_mode != PIXMAN_REPEAT_NONE) |
||
395 | { |
||
3931 | Serge | 396 | repeat (repeat_mode, &rx, width); |
397 | repeat (repeat_mode, &ry, height); |
||
1891 | serge | 398 | |
399 | pixel = get_pixel (image, rx, ry, FALSE); |
||
400 | } |
||
401 | else |
||
402 | { |
||
403 | pixel = get_pixel (image, rx, ry, TRUE); |
||
404 | } |
||
405 | |||
3931 | Serge | 406 | srtot += (int)RED_8 (pixel) * f; |
407 | sgtot += (int)GREEN_8 (pixel) * f; |
||
408 | sbtot += (int)BLUE_8 (pixel) * f; |
||
409 | satot += (int)ALPHA_8 (pixel) * f; |
||
1891 | serge | 410 | } |
411 | |||
412 | params++; |
||
413 | } |
||
414 | } |
||
415 | |||
3931 | Serge | 416 | satot = (satot + 0x8000) >> 16; |
417 | srtot = (srtot + 0x8000) >> 16; |
||
418 | sgtot = (sgtot + 0x8000) >> 16; |
||
419 | sbtot = (sbtot + 0x8000) >> 16; |
||
1891 | serge | 420 | |
421 | satot = CLIP (satot, 0, 0xff); |
||
422 | srtot = CLIP (srtot, 0, 0xff); |
||
423 | sgtot = CLIP (sgtot, 0, 0xff); |
||
424 | sbtot = CLIP (sbtot, 0, 0xff); |
||
425 | |||
426 | return ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot)); |
||
427 | } |
||
428 | |||
3931 | Serge | 429 | static uint32_t |
430 | bits_image_fetch_pixel_separable_convolution (bits_image_t *image, |
||
431 | pixman_fixed_t x, |
||
432 | pixman_fixed_t y, |
||
433 | get_pixel_t get_pixel) |
||
434 | { |
||
435 | pixman_fixed_t *params = image->common.filter_params; |
||
436 | pixman_repeat_t repeat_mode = image->common.repeat; |
||
437 | int width = image->width; |
||
438 | int height = image->height; |
||
439 | int cwidth = pixman_fixed_to_int (params[0]); |
||
440 | int cheight = pixman_fixed_to_int (params[1]); |
||
441 | int x_phase_bits = pixman_fixed_to_int (params[2]); |
||
442 | int y_phase_bits = pixman_fixed_to_int (params[3]); |
||
443 | int x_phase_shift = 16 - x_phase_bits; |
||
444 | int y_phase_shift = 16 - y_phase_bits; |
||
445 | int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1; |
||
446 | int y_off = ((cheight << 16) - pixman_fixed_1) >> 1; |
||
447 | pixman_fixed_t *y_params; |
||
448 | int srtot, sgtot, sbtot, satot; |
||
449 | int32_t x1, x2, y1, y2; |
||
450 | int32_t px, py; |
||
451 | int i, j; |
||
452 | |||
453 | /* Round x and y to the middle of the closest phase before continuing. This |
||
454 | * ensures that the convolution matrix is aligned right, since it was |
||
455 | * positioned relative to a particular phase (and not relative to whatever |
||
456 | * exact fraction we happen to get here). |
||
457 | */ |
||
458 | x = ((x >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1); |
||
459 | y = ((y >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1); |
||
460 | |||
461 | px = (x & 0xffff) >> x_phase_shift; |
||
462 | py = (y & 0xffff) >> y_phase_shift; |
||
463 | |||
464 | y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight; |
||
465 | |||
466 | x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off); |
||
467 | y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off); |
||
468 | x2 = x1 + cwidth; |
||
469 | y2 = y1 + cheight; |
||
470 | |||
471 | srtot = sgtot = sbtot = satot = 0; |
||
472 | |||
473 | for (i = y1; i < y2; ++i) |
||
474 | { |
||
475 | pixman_fixed_48_16_t fy = *y_params++; |
||
476 | pixman_fixed_t *x_params = params + 4 + px * cwidth; |
||
477 | |||
478 | if (fy) |
||
479 | { |
||
480 | for (j = x1; j < x2; ++j) |
||
481 | { |
||
482 | pixman_fixed_t fx = *x_params++; |
||
483 | int rx = j; |
||
484 | int ry = i; |
||
485 | |||
486 | if (fx) |
||
487 | { |
||
488 | pixman_fixed_t f; |
||
489 | uint32_t pixel; |
||
490 | |||
491 | if (repeat_mode != PIXMAN_REPEAT_NONE) |
||
492 | { |
||
493 | repeat (repeat_mode, &rx, width); |
||
494 | repeat (repeat_mode, &ry, height); |
||
495 | |||
496 | pixel = get_pixel (image, rx, ry, FALSE); |
||
497 | } |
||
498 | else |
||
499 | { |
||
500 | pixel = get_pixel (image, rx, ry, TRUE); |
||
501 | } |
||
502 | |||
503 | f = (fy * fx + 0x8000) >> 16; |
||
504 | |||
505 | srtot += (int)RED_8 (pixel) * f; |
||
506 | sgtot += (int)GREEN_8 (pixel) * f; |
||
507 | sbtot += (int)BLUE_8 (pixel) * f; |
||
508 | satot += (int)ALPHA_8 (pixel) * f; |
||
509 | } |
||
510 | } |
||
511 | } |
||
512 | } |
||
513 | |||
514 | satot = (satot + 0x8000) >> 16; |
||
515 | srtot = (srtot + 0x8000) >> 16; |
||
516 | sgtot = (sgtot + 0x8000) >> 16; |
||
517 | sbtot = (sbtot + 0x8000) >> 16; |
||
518 | |||
519 | satot = CLIP (satot, 0, 0xff); |
||
520 | srtot = CLIP (srtot, 0, 0xff); |
||
521 | sgtot = CLIP (sgtot, 0, 0xff); |
||
522 | sbtot = CLIP (sbtot, 0, 0xff); |
||
523 | |||
524 | return ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot)); |
||
525 | } |
||
526 | |||
1891 | serge | 527 | static force_inline uint32_t |
528 | bits_image_fetch_pixel_filtered (bits_image_t *image, |
||
529 | pixman_fixed_t x, |
||
530 | pixman_fixed_t y, |
||
531 | get_pixel_t get_pixel) |
||
532 | { |
||
533 | switch (image->common.filter) |
||
534 | { |
||
535 | case PIXMAN_FILTER_NEAREST: |
||
536 | case PIXMAN_FILTER_FAST: |
||
537 | return bits_image_fetch_pixel_nearest (image, x, y, get_pixel); |
||
538 | break; |
||
539 | |||
540 | case PIXMAN_FILTER_BILINEAR: |
||
541 | case PIXMAN_FILTER_GOOD: |
||
542 | case PIXMAN_FILTER_BEST: |
||
543 | return bits_image_fetch_pixel_bilinear (image, x, y, get_pixel); |
||
544 | break; |
||
545 | |||
546 | case PIXMAN_FILTER_CONVOLUTION: |
||
547 | return bits_image_fetch_pixel_convolution (image, x, y, get_pixel); |
||
548 | break; |
||
549 | |||
3931 | Serge | 550 | case PIXMAN_FILTER_SEPARABLE_CONVOLUTION: |
551 | return bits_image_fetch_pixel_separable_convolution (image, x, y, get_pixel); |
||
552 | break; |
||
553 | |||
1891 | serge | 554 | default: |
555 | break; |
||
556 | } |
||
557 | |||
558 | return 0; |
||
559 | } |
||
560 | |||
3931 | Serge | 561 | static uint32_t * |
562 | bits_image_fetch_affine_no_alpha (pixman_iter_t * iter, |
||
1891 | serge | 563 | const uint32_t * mask) |
564 | { |
||
3931 | Serge | 565 | pixman_image_t *image = iter->image; |
566 | int offset = iter->x; |
||
567 | int line = iter->y++; |
||
568 | int width = iter->width; |
||
569 | uint32_t * buffer = iter->buffer; |
||
570 | |||
1891 | serge | 571 | pixman_fixed_t x, y; |
572 | pixman_fixed_t ux, uy; |
||
573 | pixman_vector_t v; |
||
574 | int i; |
||
575 | |||
576 | /* reference point is the center of the pixel */ |
||
577 | v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2; |
||
578 | v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2; |
||
579 | v.vector[2] = pixman_fixed_1; |
||
580 | |||
581 | if (image->common.transform) |
||
582 | { |
||
583 | if (!pixman_transform_point_3d (image->common.transform, &v)) |
||
3931 | Serge | 584 | return iter->buffer; |
1891 | serge | 585 | |
586 | ux = image->common.transform->matrix[0][0]; |
||
587 | uy = image->common.transform->matrix[1][0]; |
||
588 | } |
||
589 | else |
||
590 | { |
||
591 | ux = pixman_fixed_1; |
||
592 | uy = 0; |
||
593 | } |
||
594 | |||
595 | x = v.vector[0]; |
||
596 | y = v.vector[1]; |
||
597 | |||
598 | for (i = 0; i < width; ++i) |
||
599 | { |
||
600 | if (!mask || mask[i]) |
||
601 | { |
||
602 | buffer[i] = bits_image_fetch_pixel_filtered ( |
||
603 | &image->bits, x, y, fetch_pixel_no_alpha); |
||
604 | } |
||
605 | |||
606 | x += ux; |
||
607 | y += uy; |
||
608 | } |
||
3931 | Serge | 609 | |
610 | return buffer; |
||
1891 | serge | 611 | } |
612 | |||
613 | /* General fetcher */ |
||
614 | static force_inline uint32_t |
||
615 | fetch_pixel_general (bits_image_t *image, int x, int y, pixman_bool_t check_bounds) |
||
616 | { |
||
617 | uint32_t pixel; |
||
618 | |||
619 | if (check_bounds && |
||
620 | (x < 0 || x >= image->width || y < 0 || y >= image->height)) |
||
621 | { |
||
622 | return 0; |
||
623 | } |
||
624 | |||
625 | pixel = image->fetch_pixel_32 (image, x, y); |
||
626 | |||
627 | if (image->common.alpha_map) |
||
628 | { |
||
629 | uint32_t pixel_a; |
||
630 | |||
631 | x -= image->common.alpha_origin_x; |
||
632 | y -= image->common.alpha_origin_y; |
||
633 | |||
634 | if (x < 0 || x >= image->common.alpha_map->width || |
||
635 | y < 0 || y >= image->common.alpha_map->height) |
||
636 | { |
||
637 | pixel_a = 0; |
||
638 | } |
||
639 | else |
||
640 | { |
||
641 | pixel_a = image->common.alpha_map->fetch_pixel_32 ( |
||
642 | image->common.alpha_map, x, y); |
||
643 | |||
644 | pixel_a = ALPHA_8 (pixel_a); |
||
645 | } |
||
646 | |||
647 | pixel &= 0x00ffffff; |
||
648 | pixel |= (pixel_a << 24); |
||
649 | } |
||
650 | |||
651 | return pixel; |
||
652 | } |
||
653 | |||
3931 | Serge | 654 | static uint32_t * |
655 | bits_image_fetch_general (pixman_iter_t *iter, |
||
656 | const uint32_t *mask) |
||
1891 | serge | 657 | { |
3931 | Serge | 658 | pixman_image_t *image = iter->image; |
659 | int offset = iter->x; |
||
660 | int line = iter->y++; |
||
661 | int width = iter->width; |
||
662 | uint32_t * buffer = iter->buffer; |
||
663 | |||
1891 | serge | 664 | pixman_fixed_t x, y, w; |
665 | pixman_fixed_t ux, uy, uw; |
||
666 | pixman_vector_t v; |
||
667 | int i; |
||
668 | |||
669 | /* reference point is the center of the pixel */ |
||
670 | v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2; |
||
671 | v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2; |
||
672 | v.vector[2] = pixman_fixed_1; |
||
673 | |||
674 | if (image->common.transform) |
||
675 | { |
||
676 | if (!pixman_transform_point_3d (image->common.transform, &v)) |
||
3931 | Serge | 677 | return buffer; |
1891 | serge | 678 | |
679 | ux = image->common.transform->matrix[0][0]; |
||
680 | uy = image->common.transform->matrix[1][0]; |
||
681 | uw = image->common.transform->matrix[2][0]; |
||
682 | } |
||
683 | else |
||
684 | { |
||
685 | ux = pixman_fixed_1; |
||
686 | uy = 0; |
||
687 | uw = 0; |
||
688 | } |
||
689 | |||
690 | x = v.vector[0]; |
||
691 | y = v.vector[1]; |
||
692 | w = v.vector[2]; |
||
693 | |||
694 | for (i = 0; i < width; ++i) |
||
695 | { |
||
696 | pixman_fixed_t x0, y0; |
||
697 | |||
698 | if (!mask || mask[i]) |
||
699 | { |
||
700 | if (w != 0) |
||
701 | { |
||
702 | x0 = ((pixman_fixed_48_16_t)x << 16) / w; |
||
703 | y0 = ((pixman_fixed_48_16_t)y << 16) / w; |
||
704 | } |
||
705 | else |
||
706 | { |
||
707 | x0 = 0; |
||
708 | y0 = 0; |
||
709 | } |
||
710 | |||
711 | buffer[i] = bits_image_fetch_pixel_filtered ( |
||
712 | &image->bits, x0, y0, fetch_pixel_general); |
||
713 | } |
||
714 | |||
715 | x += ux; |
||
716 | y += uy; |
||
717 | w += uw; |
||
718 | } |
||
3931 | Serge | 719 | |
720 | return buffer; |
||
1891 | serge | 721 | } |
722 | |||
723 | typedef uint32_t (* convert_pixel_t) (const uint8_t *row, int x); |
||
724 | |||
725 | static force_inline void |
||
3931 | Serge | 726 | bits_image_fetch_separable_convolution_affine (pixman_image_t * image, |
727 | int offset, |
||
728 | int line, |
||
729 | int width, |
||
730 | uint32_t * buffer, |
||
731 | const uint32_t * mask, |
||
732 | |||
733 | convert_pixel_t convert_pixel, |
||
734 | pixman_format_code_t format, |
||
735 | pixman_repeat_t repeat_mode) |
||
736 | { |
||
737 | bits_image_t *bits = &image->bits; |
||
738 | pixman_fixed_t *params = image->common.filter_params; |
||
739 | int cwidth = pixman_fixed_to_int (params[0]); |
||
740 | int cheight = pixman_fixed_to_int (params[1]); |
||
741 | int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1; |
||
742 | int y_off = ((cheight << 16) - pixman_fixed_1) >> 1; |
||
743 | int x_phase_bits = pixman_fixed_to_int (params[2]); |
||
744 | int y_phase_bits = pixman_fixed_to_int (params[3]); |
||
745 | int x_phase_shift = 16 - x_phase_bits; |
||
746 | int y_phase_shift = 16 - y_phase_bits; |
||
747 | pixman_fixed_t vx, vy; |
||
748 | pixman_fixed_t ux, uy; |
||
749 | pixman_vector_t v; |
||
750 | int k; |
||
751 | |||
752 | /* reference point is the center of the pixel */ |
||
753 | v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2; |
||
754 | v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2; |
||
755 | v.vector[2] = pixman_fixed_1; |
||
756 | |||
757 | if (!pixman_transform_point_3d (image->common.transform, &v)) |
||
758 | return; |
||
759 | |||
760 | ux = image->common.transform->matrix[0][0]; |
||
761 | uy = image->common.transform->matrix[1][0]; |
||
762 | |||
763 | vx = v.vector[0]; |
||
764 | vy = v.vector[1]; |
||
765 | |||
766 | for (k = 0; k < width; ++k) |
||
767 | { |
||
768 | pixman_fixed_t *y_params; |
||
769 | int satot, srtot, sgtot, sbtot; |
||
770 | pixman_fixed_t x, y; |
||
771 | int32_t x1, x2, y1, y2; |
||
772 | int32_t px, py; |
||
773 | int i, j; |
||
774 | |||
775 | if (mask && !mask[k]) |
||
776 | goto next; |
||
777 | |||
778 | /* Round x and y to the middle of the closest phase before continuing. This |
||
779 | * ensures that the convolution matrix is aligned right, since it was |
||
780 | * positioned relative to a particular phase (and not relative to whatever |
||
781 | * exact fraction we happen to get here). |
||
782 | */ |
||
783 | x = ((vx >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1); |
||
784 | y = ((vy >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1); |
||
785 | |||
786 | px = (x & 0xffff) >> x_phase_shift; |
||
787 | py = (y & 0xffff) >> y_phase_shift; |
||
788 | |||
789 | x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off); |
||
790 | y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off); |
||
791 | x2 = x1 + cwidth; |
||
792 | y2 = y1 + cheight; |
||
793 | |||
794 | satot = srtot = sgtot = sbtot = 0; |
||
795 | |||
796 | y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight; |
||
797 | |||
798 | for (i = y1; i < y2; ++i) |
||
799 | { |
||
800 | pixman_fixed_t fy = *y_params++; |
||
801 | |||
802 | if (fy) |
||
803 | { |
||
804 | pixman_fixed_t *x_params = params + 4 + px * cwidth; |
||
805 | |||
806 | for (j = x1; j < x2; ++j) |
||
807 | { |
||
808 | pixman_fixed_t fx = *x_params++; |
||
809 | int rx = j; |
||
810 | int ry = i; |
||
811 | |||
812 | if (fx) |
||
813 | { |
||
814 | pixman_fixed_t f; |
||
815 | uint32_t pixel, mask; |
||
816 | uint8_t *row; |
||
817 | |||
818 | mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000; |
||
819 | |||
820 | if (repeat_mode != PIXMAN_REPEAT_NONE) |
||
821 | { |
||
822 | repeat (repeat_mode, &rx, bits->width); |
||
823 | repeat (repeat_mode, &ry, bits->height); |
||
824 | |||
825 | row = (uint8_t *)bits->bits + bits->rowstride * 4 * ry; |
||
826 | pixel = convert_pixel (row, rx) | mask; |
||
827 | } |
||
828 | else |
||
829 | { |
||
830 | if (rx < 0 || ry < 0 || rx >= bits->width || ry >= bits->height) |
||
831 | { |
||
832 | pixel = 0; |
||
833 | } |
||
834 | else |
||
835 | { |
||
836 | row = (uint8_t *)bits->bits + bits->rowstride * 4 * ry; |
||
837 | pixel = convert_pixel (row, rx) | mask; |
||
838 | } |
||
839 | } |
||
840 | |||
841 | f = ((pixman_fixed_32_32_t)fx * fy + 0x8000) >> 16; |
||
842 | srtot += (int)RED_8 (pixel) * f; |
||
843 | sgtot += (int)GREEN_8 (pixel) * f; |
||
844 | sbtot += (int)BLUE_8 (pixel) * f; |
||
845 | satot += (int)ALPHA_8 (pixel) * f; |
||
846 | } |
||
847 | } |
||
848 | } |
||
849 | } |
||
850 | |||
851 | satot = (satot + 0x8000) >> 16; |
||
852 | srtot = (srtot + 0x8000) >> 16; |
||
853 | sgtot = (sgtot + 0x8000) >> 16; |
||
854 | sbtot = (sbtot + 0x8000) >> 16; |
||
855 | |||
856 | satot = CLIP (satot, 0, 0xff); |
||
857 | srtot = CLIP (srtot, 0, 0xff); |
||
858 | sgtot = CLIP (sgtot, 0, 0xff); |
||
859 | sbtot = CLIP (sbtot, 0, 0xff); |
||
860 | |||
861 | buffer[k] = (satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot << 0); |
||
862 | |||
863 | next: |
||
864 | vx += ux; |
||
865 | vy += uy; |
||
866 | } |
||
867 | } |
||
868 | |||
869 | static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; |
||
870 | |||
871 | static force_inline void |
||
1891 | serge | 872 | bits_image_fetch_bilinear_affine (pixman_image_t * image, |
873 | int offset, |
||
874 | int line, |
||
875 | int width, |
||
876 | uint32_t * buffer, |
||
877 | const uint32_t * mask, |
||
878 | |||
879 | convert_pixel_t convert_pixel, |
||
880 | pixman_format_code_t format, |
||
881 | pixman_repeat_t repeat_mode) |
||
882 | { |
||
883 | pixman_fixed_t x, y; |
||
884 | pixman_fixed_t ux, uy; |
||
885 | pixman_vector_t v; |
||
886 | bits_image_t *bits = &image->bits; |
||
887 | int i; |
||
888 | |||
889 | /* reference point is the center of the pixel */ |
||
890 | v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2; |
||
891 | v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2; |
||
892 | v.vector[2] = pixman_fixed_1; |
||
893 | |||
894 | if (!pixman_transform_point_3d (image->common.transform, &v)) |
||
895 | return; |
||
896 | |||
897 | ux = image->common.transform->matrix[0][0]; |
||
898 | uy = image->common.transform->matrix[1][0]; |
||
899 | |||
900 | x = v.vector[0]; |
||
901 | y = v.vector[1]; |
||
902 | |||
903 | for (i = 0; i < width; ++i) |
||
904 | { |
||
905 | int x1, y1, x2, y2; |
||
906 | uint32_t tl, tr, bl, br; |
||
907 | int32_t distx, disty; |
||
908 | int width = image->bits.width; |
||
909 | int height = image->bits.height; |
||
910 | const uint8_t *row1; |
||
911 | const uint8_t *row2; |
||
912 | |||
913 | if (mask && !mask[i]) |
||
914 | goto next; |
||
915 | |||
916 | x1 = x - pixman_fixed_1 / 2; |
||
917 | y1 = y - pixman_fixed_1 / 2; |
||
918 | |||
3931 | Serge | 919 | distx = pixman_fixed_to_bilinear_weight (x1); |
920 | disty = pixman_fixed_to_bilinear_weight (y1); |
||
1891 | serge | 921 | |
922 | y1 = pixman_fixed_to_int (y1); |
||
923 | y2 = y1 + 1; |
||
924 | x1 = pixman_fixed_to_int (x1); |
||
925 | x2 = x1 + 1; |
||
926 | |||
927 | if (repeat_mode != PIXMAN_REPEAT_NONE) |
||
928 | { |
||
929 | uint32_t mask; |
||
930 | |||
931 | mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000; |
||
932 | |||
3931 | Serge | 933 | repeat (repeat_mode, &x1, width); |
934 | repeat (repeat_mode, &y1, height); |
||
935 | repeat (repeat_mode, &x2, width); |
||
936 | repeat (repeat_mode, &y2, height); |
||
1891 | serge | 937 | |
938 | row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1; |
||
939 | row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2; |
||
940 | |||
941 | tl = convert_pixel (row1, x1) | mask; |
||
942 | tr = convert_pixel (row1, x2) | mask; |
||
943 | bl = convert_pixel (row2, x1) | mask; |
||
944 | br = convert_pixel (row2, x2) | mask; |
||
945 | } |
||
946 | else |
||
947 | { |
||
948 | uint32_t mask1, mask2; |
||
949 | int bpp; |
||
950 | |||
951 | /* Note: PIXMAN_FORMAT_BPP() returns an unsigned value, |
||
952 | * which means if you use it in expressions, those |
||
953 | * expressions become unsigned themselves. Since |
||
954 | * the variables below can be negative in some cases, |
||
955 | * that will lead to crashes on 64 bit architectures. |
||
956 | * |
||
957 | * So this line makes sure bpp is signed |
||
958 | */ |
||
959 | bpp = PIXMAN_FORMAT_BPP (format); |
||
960 | |||
961 | if (x1 >= width || x2 < 0 || y1 >= height || y2 < 0) |
||
962 | { |
||
963 | buffer[i] = 0; |
||
964 | goto next; |
||
965 | } |
||
966 | |||
967 | if (y2 == 0) |
||
968 | { |
||
969 | row1 = zero; |
||
970 | mask1 = 0; |
||
971 | } |
||
972 | else |
||
973 | { |
||
974 | row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1; |
||
975 | row1 += bpp / 8 * x1; |
||
976 | |||
977 | mask1 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000; |
||
978 | } |
||
979 | |||
980 | if (y1 == height - 1) |
||
981 | { |
||
982 | row2 = zero; |
||
983 | mask2 = 0; |
||
984 | } |
||
985 | else |
||
986 | { |
||
987 | row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2; |
||
988 | row2 += bpp / 8 * x1; |
||
989 | |||
990 | mask2 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000; |
||
991 | } |
||
992 | |||
993 | if (x2 == 0) |
||
994 | { |
||
995 | tl = 0; |
||
996 | bl = 0; |
||
997 | } |
||
998 | else |
||
999 | { |
||
1000 | tl = convert_pixel (row1, 0) | mask1; |
||
1001 | bl = convert_pixel (row2, 0) | mask2; |
||
1002 | } |
||
1003 | |||
1004 | if (x1 == width - 1) |
||
1005 | { |
||
1006 | tr = 0; |
||
1007 | br = 0; |
||
1008 | } |
||
1009 | else |
||
1010 | { |
||
1011 | tr = convert_pixel (row1, 1) | mask1; |
||
1012 | br = convert_pixel (row2, 1) | mask2; |
||
1013 | } |
||
1014 | } |
||
1015 | |||
1016 | buffer[i] = bilinear_interpolation ( |
||
1017 | tl, tr, bl, br, distx, disty); |
||
1018 | |||
1019 | next: |
||
1020 | x += ux; |
||
1021 | y += uy; |
||
1022 | } |
||
1023 | } |
||
1024 | |||
3931 | Serge | 1025 | static force_inline void |
1026 | bits_image_fetch_nearest_affine (pixman_image_t * image, |
||
1027 | int offset, |
||
1028 | int line, |
||
1029 | int width, |
||
1030 | uint32_t * buffer, |
||
1031 | const uint32_t * mask, |
||
1032 | |||
1033 | convert_pixel_t convert_pixel, |
||
1034 | pixman_format_code_t format, |
||
1035 | pixman_repeat_t repeat_mode) |
||
1036 | { |
||
1037 | pixman_fixed_t x, y; |
||
1038 | pixman_fixed_t ux, uy; |
||
1039 | pixman_vector_t v; |
||
1040 | bits_image_t *bits = &image->bits; |
||
1041 | int i; |
||
1042 | |||
1043 | /* reference point is the center of the pixel */ |
||
1044 | v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2; |
||
1045 | v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2; |
||
1046 | v.vector[2] = pixman_fixed_1; |
||
1047 | |||
1048 | if (!pixman_transform_point_3d (image->common.transform, &v)) |
||
1049 | return; |
||
1050 | |||
1051 | ux = image->common.transform->matrix[0][0]; |
||
1052 | uy = image->common.transform->matrix[1][0]; |
||
1053 | |||
1054 | x = v.vector[0]; |
||
1055 | y = v.vector[1]; |
||
1056 | |||
1057 | for (i = 0; i < width; ++i) |
||
1058 | { |
||
1059 | int width, height, x0, y0; |
||
1060 | const uint8_t *row; |
||
1061 | |||
1062 | if (mask && !mask[i]) |
||
1063 | goto next; |
||
1064 | |||
1065 | width = image->bits.width; |
||
1066 | height = image->bits.height; |
||
1067 | x0 = pixman_fixed_to_int (x - pixman_fixed_e); |
||
1068 | y0 = pixman_fixed_to_int (y - pixman_fixed_e); |
||
1069 | |||
1070 | if (repeat_mode == PIXMAN_REPEAT_NONE && |
||
1071 | (y0 < 0 || y0 >= height || x0 < 0 || x0 >= width)) |
||
1072 | { |
||
1073 | buffer[i] = 0; |
||
1074 | } |
||
1075 | else |
||
1076 | { |
||
1077 | uint32_t mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000; |
||
1078 | |||
1079 | if (repeat_mode != PIXMAN_REPEAT_NONE) |
||
1080 | { |
||
1081 | repeat (repeat_mode, &x0, width); |
||
1082 | repeat (repeat_mode, &y0, height); |
||
1083 | } |
||
1084 | |||
1085 | row = (uint8_t *)bits->bits + bits->rowstride * 4 * y0; |
||
1086 | |||
1087 | buffer[i] = convert_pixel (row, x0) | mask; |
||
1088 | } |
||
1089 | |||
1090 | next: |
||
1091 | x += ux; |
||
1092 | y += uy; |
||
1093 | } |
||
1094 | } |
||
1095 | |||
1891 | serge | 1096 | static force_inline uint32_t |
1097 | convert_a8r8g8b8 (const uint8_t *row, int x) |
||
1098 | { |
||
1099 | return *(((uint32_t *)row) + x); |
||
1100 | } |
||
1101 | |||
1102 | static force_inline uint32_t |
||
1103 | convert_x8r8g8b8 (const uint8_t *row, int x) |
||
1104 | { |
||
1105 | return *(((uint32_t *)row) + x); |
||
1106 | } |
||
1107 | |||
1108 | static force_inline uint32_t |
||
1109 | convert_a8 (const uint8_t *row, int x) |
||
1110 | { |
||
1111 | return *(row + x) << 24; |
||
1112 | } |
||
1113 | |||
1114 | static force_inline uint32_t |
||
1115 | convert_r5g6b5 (const uint8_t *row, int x) |
||
1116 | { |
||
3931 | Serge | 1117 | return convert_0565_to_0888 (*((uint16_t *)row + x)); |
1891 | serge | 1118 | } |
1119 | |||
3931 | Serge | 1120 | #define MAKE_SEPARABLE_CONVOLUTION_FETCHER(name, format, repeat_mode) \ |
1121 | static uint32_t * \ |
||
1122 | bits_image_fetch_separable_convolution_affine_ ## name (pixman_iter_t *iter, \ |
||
1123 | const uint32_t * mask) \ |
||
1124 | { \ |
||
1125 | bits_image_fetch_separable_convolution_affine ( \ |
||
1126 | iter->image, \ |
||
1127 | iter->x, iter->y++, \ |
||
1128 | iter->width, \ |
||
1129 | iter->buffer, mask, \ |
||
1130 | convert_ ## format, \ |
||
1131 | PIXMAN_ ## format, \ |
||
1132 | repeat_mode); \ |
||
1133 | \ |
||
1134 | return iter->buffer; \ |
||
1135 | } |
||
1136 | |||
1891 | serge | 1137 | #define MAKE_BILINEAR_FETCHER(name, format, repeat_mode) \ |
3931 | Serge | 1138 | static uint32_t * \ |
1139 | bits_image_fetch_bilinear_affine_ ## name (pixman_iter_t *iter, \ |
||
1891 | serge | 1140 | const uint32_t * mask) \ |
1141 | { \ |
||
3931 | Serge | 1142 | bits_image_fetch_bilinear_affine (iter->image, \ |
1143 | iter->x, iter->y++, \ |
||
1144 | iter->width, \ |
||
1145 | iter->buffer, mask, \ |
||
1891 | serge | 1146 | convert_ ## format, \ |
1147 | PIXMAN_ ## format, \ |
||
1148 | repeat_mode); \ |
||
3931 | Serge | 1149 | return iter->buffer; \ |
1150 | } |
||
1891 | serge | 1151 | |
3931 | Serge | 1152 | #define MAKE_NEAREST_FETCHER(name, format, repeat_mode) \ |
1153 | static uint32_t * \ |
||
1154 | bits_image_fetch_nearest_affine_ ## name (pixman_iter_t *iter, \ |
||
1155 | const uint32_t * mask) \ |
||
1156 | { \ |
||
1157 | bits_image_fetch_nearest_affine (iter->image, \ |
||
1158 | iter->x, iter->y++, \ |
||
1159 | iter->width, \ |
||
1160 | iter->buffer, mask, \ |
||
1161 | convert_ ## format, \ |
||
1162 | PIXMAN_ ## format, \ |
||
1163 | repeat_mode); \ |
||
1164 | return iter->buffer; \ |
||
1165 | } |
||
1891 | serge | 1166 | |
3931 | Serge | 1167 | #define MAKE_FETCHERS(name, format, repeat_mode) \ |
1168 | MAKE_NEAREST_FETCHER (name, format, repeat_mode) \ |
||
1169 | MAKE_BILINEAR_FETCHER (name, format, repeat_mode) \ |
||
1170 | MAKE_SEPARABLE_CONVOLUTION_FETCHER (name, format, repeat_mode) |
||
1171 | |||
1172 | MAKE_FETCHERS (pad_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_PAD) |
||
1173 | MAKE_FETCHERS (none_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_NONE) |
||
1174 | MAKE_FETCHERS (reflect_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_REFLECT) |
||
1175 | MAKE_FETCHERS (normal_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_NORMAL) |
||
1176 | MAKE_FETCHERS (pad_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_PAD) |
||
1177 | MAKE_FETCHERS (none_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_NONE) |
||
1178 | MAKE_FETCHERS (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT) |
||
1179 | MAKE_FETCHERS (normal_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_NORMAL) |
||
1180 | MAKE_FETCHERS (pad_a8, a8, PIXMAN_REPEAT_PAD) |
||
1181 | MAKE_FETCHERS (none_a8, a8, PIXMAN_REPEAT_NONE) |
||
1182 | MAKE_FETCHERS (reflect_a8, a8, PIXMAN_REPEAT_REFLECT) |
||
1183 | MAKE_FETCHERS (normal_a8, a8, PIXMAN_REPEAT_NORMAL) |
||
1184 | MAKE_FETCHERS (pad_r5g6b5, r5g6b5, PIXMAN_REPEAT_PAD) |
||
1185 | MAKE_FETCHERS (none_r5g6b5, r5g6b5, PIXMAN_REPEAT_NONE) |
||
1186 | MAKE_FETCHERS (reflect_r5g6b5, r5g6b5, PIXMAN_REPEAT_REFLECT) |
||
1187 | MAKE_FETCHERS (normal_r5g6b5, r5g6b5, PIXMAN_REPEAT_NORMAL) |
||
1188 | |||
1891 | serge | 1189 | static void |
3931 | Serge | 1190 | replicate_pixel_32 (bits_image_t * bits, |
1191 | int x, |
||
1192 | int y, |
||
1193 | int width, |
||
1194 | uint32_t * buffer) |
||
1891 | serge | 1195 | { |
1196 | uint32_t color; |
||
1197 | uint32_t *end; |
||
1198 | |||
3931 | Serge | 1199 | color = bits->fetch_pixel_32 (bits, x, y); |
1891 | serge | 1200 | |
1201 | end = buffer + width; |
||
1202 | while (buffer < end) |
||
1203 | *(buffer++) = color; |
||
1204 | } |
||
1205 | |||
1206 | static void |
||
3931 | Serge | 1207 | replicate_pixel_float (bits_image_t * bits, |
1208 | int x, |
||
1209 | int y, |
||
1210 | int width, |
||
1211 | uint32_t * b) |
||
1891 | serge | 1212 | { |
3931 | Serge | 1213 | argb_t color; |
1214 | argb_t *buffer = (argb_t *)b; |
||
1215 | argb_t *end; |
||
1891 | serge | 1216 | |
3931 | Serge | 1217 | color = bits->fetch_pixel_float (bits, x, y); |
1891 | serge | 1218 | |
1219 | end = buffer + width; |
||
1220 | while (buffer < end) |
||
1221 | *(buffer++) = color; |
||
1222 | } |
||
1223 | |||
1224 | static void |
||
1225 | bits_image_fetch_untransformed_repeat_none (bits_image_t *image, |
||
1226 | pixman_bool_t wide, |
||
1227 | int x, |
||
1228 | int y, |
||
1229 | int width, |
||
1230 | uint32_t * buffer) |
||
1231 | { |
||
1232 | uint32_t w; |
||
1233 | |||
1234 | if (y < 0 || y >= image->height) |
||
1235 | { |
||
3931 | Serge | 1236 | memset (buffer, 0, width * (wide? sizeof (argb_t) : 4)); |
1891 | serge | 1237 | return; |
1238 | } |
||
1239 | |||
1240 | if (x < 0) |
||
1241 | { |
||
1242 | w = MIN (width, -x); |
||
1243 | |||
3931 | Serge | 1244 | memset (buffer, 0, w * (wide ? sizeof (argb_t) : 4)); |
1891 | serge | 1245 | |
1246 | width -= w; |
||
3931 | Serge | 1247 | buffer += w * (wide? 4 : 1); |
1891 | serge | 1248 | x += w; |
1249 | } |
||
1250 | |||
1251 | if (x < image->width) |
||
1252 | { |
||
1253 | w = MIN (width, image->width - x); |
||
1254 | |||
1255 | if (wide) |
||
3931 | Serge | 1256 | image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL); |
1891 | serge | 1257 | else |
1258 | image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL); |
||
1259 | |||
1260 | width -= w; |
||
3931 | Serge | 1261 | buffer += w * (wide? 4 : 1); |
1891 | serge | 1262 | x += w; |
1263 | } |
||
1264 | |||
3931 | Serge | 1265 | memset (buffer, 0, width * (wide ? sizeof (argb_t) : 4)); |
1891 | serge | 1266 | } |
1267 | |||
1268 | static void |
||
1269 | bits_image_fetch_untransformed_repeat_normal (bits_image_t *image, |
||
1270 | pixman_bool_t wide, |
||
1271 | int x, |
||
1272 | int y, |
||
1273 | int width, |
||
1274 | uint32_t * buffer) |
||
1275 | { |
||
1276 | uint32_t w; |
||
1277 | |||
1278 | while (y < 0) |
||
1279 | y += image->height; |
||
1280 | |||
1281 | while (y >= image->height) |
||
1282 | y -= image->height; |
||
1283 | |||
3931 | Serge | 1284 | if (image->width == 1) |
1285 | { |
||
1286 | if (wide) |
||
1287 | replicate_pixel_float (image, 0, y, width, buffer); |
||
1288 | else |
||
1289 | replicate_pixel_32 (image, 0, y, width, buffer); |
||
1290 | |||
1291 | return; |
||
1292 | } |
||
1293 | |||
1891 | serge | 1294 | while (width) |
1295 | { |
||
1296 | while (x < 0) |
||
1297 | x += image->width; |
||
1298 | while (x >= image->width) |
||
1299 | x -= image->width; |
||
1300 | |||
1301 | w = MIN (width, image->width - x); |
||
1302 | |||
1303 | if (wide) |
||
3931 | Serge | 1304 | image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL); |
1891 | serge | 1305 | else |
1306 | image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL); |
||
1307 | |||
3931 | Serge | 1308 | buffer += w * (wide? 4 : 1); |
1891 | serge | 1309 | x += w; |
1310 | width -= w; |
||
1311 | } |
||
1312 | } |
||
1313 | |||
3931 | Serge | 1314 | static uint32_t * |
1315 | bits_image_fetch_untransformed_32 (pixman_iter_t * iter, |
||
1316 | const uint32_t *mask) |
||
1891 | serge | 1317 | { |
3931 | Serge | 1318 | pixman_image_t *image = iter->image; |
1319 | int x = iter->x; |
||
1320 | int y = iter->y; |
||
1321 | int width = iter->width; |
||
1322 | uint32_t * buffer = iter->buffer; |
||
1323 | |||
1891 | serge | 1324 | if (image->common.repeat == PIXMAN_REPEAT_NONE) |
1325 | { |
||
1326 | bits_image_fetch_untransformed_repeat_none ( |
||
1327 | &image->bits, FALSE, x, y, width, buffer); |
||
1328 | } |
||
1329 | else |
||
1330 | { |
||
1331 | bits_image_fetch_untransformed_repeat_normal ( |
||
1332 | &image->bits, FALSE, x, y, width, buffer); |
||
1333 | } |
||
3931 | Serge | 1334 | |
1335 | iter->y++; |
||
1336 | return buffer; |
||
1891 | serge | 1337 | } |
1338 | |||
3931 | Serge | 1339 | static uint32_t * |
1340 | bits_image_fetch_untransformed_float (pixman_iter_t * iter, |
||
1341 | const uint32_t *mask) |
||
1891 | serge | 1342 | { |
3931 | Serge | 1343 | pixman_image_t *image = iter->image; |
1344 | int x = iter->x; |
||
1345 | int y = iter->y; |
||
1346 | int width = iter->width; |
||
1347 | uint32_t * buffer = iter->buffer; |
||
1348 | |||
1891 | serge | 1349 | if (image->common.repeat == PIXMAN_REPEAT_NONE) |
1350 | { |
||
1351 | bits_image_fetch_untransformed_repeat_none ( |
||
1352 | &image->bits, TRUE, x, y, width, buffer); |
||
1353 | } |
||
1354 | else |
||
1355 | { |
||
1356 | bits_image_fetch_untransformed_repeat_normal ( |
||
1357 | &image->bits, TRUE, x, y, width, buffer); |
||
1358 | } |
||
3931 | Serge | 1359 | |
1360 | iter->y++; |
||
1361 | return buffer; |
||
1891 | serge | 1362 | } |
1363 | |||
1364 | typedef struct |
||
1365 | { |
||
1366 | pixman_format_code_t format; |
||
1367 | uint32_t flags; |
||
3931 | Serge | 1368 | pixman_iter_get_scanline_t get_scanline_32; |
1369 | pixman_iter_get_scanline_t get_scanline_float; |
||
1891 | serge | 1370 | } fetcher_info_t; |
1371 | |||
1372 | static const fetcher_info_t fetcher_info[] = |
||
1373 | { |
||
1374 | { PIXMAN_any, |
||
1375 | (FAST_PATH_NO_ALPHA_MAP | |
||
1376 | FAST_PATH_ID_TRANSFORM | |
||
1377 | FAST_PATH_NO_CONVOLUTION_FILTER | |
||
1378 | FAST_PATH_NO_PAD_REPEAT | |
||
1379 | FAST_PATH_NO_REFLECT_REPEAT), |
||
1380 | bits_image_fetch_untransformed_32, |
||
3931 | Serge | 1381 | bits_image_fetch_untransformed_float |
1891 | serge | 1382 | }, |
1383 | |||
1384 | #define FAST_BILINEAR_FLAGS \ |
||
1385 | (FAST_PATH_NO_ALPHA_MAP | \ |
||
1386 | FAST_PATH_NO_ACCESSORS | \ |
||
1387 | FAST_PATH_HAS_TRANSFORM | \ |
||
1388 | FAST_PATH_AFFINE_TRANSFORM | \ |
||
1389 | FAST_PATH_X_UNIT_POSITIVE | \ |
||
1390 | FAST_PATH_Y_UNIT_ZERO | \ |
||
1391 | FAST_PATH_NONE_REPEAT | \ |
||
1392 | FAST_PATH_BILINEAR_FILTER) |
||
1393 | |||
1394 | { PIXMAN_a8r8g8b8, |
||
1395 | FAST_BILINEAR_FLAGS, |
||
1396 | bits_image_fetch_bilinear_no_repeat_8888, |
||
3931 | Serge | 1397 | _pixman_image_get_scanline_generic_float |
1891 | serge | 1398 | }, |
1399 | |||
1400 | { PIXMAN_x8r8g8b8, |
||
1401 | FAST_BILINEAR_FLAGS, |
||
1402 | bits_image_fetch_bilinear_no_repeat_8888, |
||
3931 | Serge | 1403 | _pixman_image_get_scanline_generic_float |
1891 | serge | 1404 | }, |
1405 | |||
1406 | #define GENERAL_BILINEAR_FLAGS \ |
||
1407 | (FAST_PATH_NO_ALPHA_MAP | \ |
||
1408 | FAST_PATH_NO_ACCESSORS | \ |
||
1409 | FAST_PATH_HAS_TRANSFORM | \ |
||
1410 | FAST_PATH_AFFINE_TRANSFORM | \ |
||
1411 | FAST_PATH_BILINEAR_FILTER) |
||
1412 | |||
3931 | Serge | 1413 | #define GENERAL_NEAREST_FLAGS \ |
1414 | (FAST_PATH_NO_ALPHA_MAP | \ |
||
1415 | FAST_PATH_NO_ACCESSORS | \ |
||
1416 | FAST_PATH_HAS_TRANSFORM | \ |
||
1417 | FAST_PATH_AFFINE_TRANSFORM | \ |
||
1418 | FAST_PATH_NEAREST_FILTER) |
||
1419 | |||
1420 | #define GENERAL_SEPARABLE_CONVOLUTION_FLAGS \ |
||
1421 | (FAST_PATH_NO_ALPHA_MAP | \ |
||
1422 | FAST_PATH_NO_ACCESSORS | \ |
||
1423 | FAST_PATH_HAS_TRANSFORM | \ |
||
1424 | FAST_PATH_AFFINE_TRANSFORM | \ |
||
1425 | FAST_PATH_SEPARABLE_CONVOLUTION_FILTER) |
||
1426 | |||
1427 | #define SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat) \ |
||
1428 | { PIXMAN_ ## format, \ |
||
1429 | GENERAL_SEPARABLE_CONVOLUTION_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \ |
||
1430 | bits_image_fetch_separable_convolution_affine_ ## name, \ |
||
1431 | _pixman_image_get_scanline_generic_float \ |
||
1432 | }, |
||
1433 | |||
1891 | serge | 1434 | #define BILINEAR_AFFINE_FAST_PATH(name, format, repeat) \ |
1435 | { PIXMAN_ ## format, \ |
||
1436 | GENERAL_BILINEAR_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \ |
||
1437 | bits_image_fetch_bilinear_affine_ ## name, \ |
||
3931 | Serge | 1438 | _pixman_image_get_scanline_generic_float \ |
1891 | serge | 1439 | }, |
1440 | |||
3931 | Serge | 1441 | #define NEAREST_AFFINE_FAST_PATH(name, format, repeat) \ |
1442 | { PIXMAN_ ## format, \ |
||
1443 | GENERAL_NEAREST_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \ |
||
1444 | bits_image_fetch_nearest_affine_ ## name, \ |
||
1445 | _pixman_image_get_scanline_generic_float \ |
||
1446 | }, |
||
1891 | serge | 1447 | |
3931 | Serge | 1448 | #define AFFINE_FAST_PATHS(name, format, repeat) \ |
1449 | SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat) \ |
||
1450 | BILINEAR_AFFINE_FAST_PATH(name, format, repeat) \ |
||
1451 | NEAREST_AFFINE_FAST_PATH(name, format, repeat) |
||
1452 | |||
1453 | AFFINE_FAST_PATHS (pad_a8r8g8b8, a8r8g8b8, PAD) |
||
1454 | AFFINE_FAST_PATHS (none_a8r8g8b8, a8r8g8b8, NONE) |
||
1455 | AFFINE_FAST_PATHS (reflect_a8r8g8b8, a8r8g8b8, REFLECT) |
||
1456 | AFFINE_FAST_PATHS (normal_a8r8g8b8, a8r8g8b8, NORMAL) |
||
1457 | AFFINE_FAST_PATHS (pad_x8r8g8b8, x8r8g8b8, PAD) |
||
1458 | AFFINE_FAST_PATHS (none_x8r8g8b8, x8r8g8b8, NONE) |
||
1459 | AFFINE_FAST_PATHS (reflect_x8r8g8b8, x8r8g8b8, REFLECT) |
||
1460 | AFFINE_FAST_PATHS (normal_x8r8g8b8, x8r8g8b8, NORMAL) |
||
1461 | AFFINE_FAST_PATHS (pad_a8, a8, PAD) |
||
1462 | AFFINE_FAST_PATHS (none_a8, a8, NONE) |
||
1463 | AFFINE_FAST_PATHS (reflect_a8, a8, REFLECT) |
||
1464 | AFFINE_FAST_PATHS (normal_a8, a8, NORMAL) |
||
1465 | AFFINE_FAST_PATHS (pad_r5g6b5, r5g6b5, PAD) |
||
1466 | AFFINE_FAST_PATHS (none_r5g6b5, r5g6b5, NONE) |
||
1467 | AFFINE_FAST_PATHS (reflect_r5g6b5, r5g6b5, REFLECT) |
||
1468 | AFFINE_FAST_PATHS (normal_r5g6b5, r5g6b5, NORMAL) |
||
1469 | |||
1891 | serge | 1470 | /* Affine, no alpha */ |
1471 | { PIXMAN_any, |
||
1472 | (FAST_PATH_NO_ALPHA_MAP | FAST_PATH_HAS_TRANSFORM | FAST_PATH_AFFINE_TRANSFORM), |
||
1473 | bits_image_fetch_affine_no_alpha, |
||
3931 | Serge | 1474 | _pixman_image_get_scanline_generic_float |
1891 | serge | 1475 | }, |
1476 | |||
1477 | /* General */ |
||
3931 | Serge | 1478 | { PIXMAN_any, |
1479 | 0, |
||
1480 | bits_image_fetch_general, |
||
1481 | _pixman_image_get_scanline_generic_float |
||
1482 | }, |
||
1891 | serge | 1483 | |
1484 | { PIXMAN_null }, |
||
1485 | }; |
||
1486 | |||
1487 | static void |
||
1488 | bits_image_property_changed (pixman_image_t *image) |
||
1489 | { |
||
3931 | Serge | 1490 | _pixman_bits_image_setup_accessors (&image->bits); |
1491 | } |
||
1492 | |||
1493 | void |
||
1494 | _pixman_bits_image_src_iter_init (pixman_image_t *image, pixman_iter_t *iter) |
||
1495 | { |
||
1496 | pixman_format_code_t format = image->common.extended_format_code; |
||
1891 | serge | 1497 | uint32_t flags = image->common.flags; |
1498 | const fetcher_info_t *info; |
||
1499 | |||
3931 | Serge | 1500 | for (info = fetcher_info; info->format != PIXMAN_null; ++info) |
1891 | serge | 1501 | { |
1502 | if ((info->format == format || info->format == PIXMAN_any) && |
||
1503 | (info->flags & flags) == info->flags) |
||
1504 | { |
||
3931 | Serge | 1505 | if (iter->iter_flags & ITER_NARROW) |
1506 | { |
||
1507 | iter->get_scanline = info->get_scanline_32; |
||
1508 | } |
||
1509 | else |
||
1510 | { |
||
1511 | iter->data = info->get_scanline_32; |
||
1512 | iter->get_scanline = info->get_scanline_float; |
||
1513 | } |
||
1514 | return; |
||
1891 | serge | 1515 | } |
3931 | Serge | 1516 | } |
1891 | serge | 1517 | |
3931 | Serge | 1518 | /* Just in case we somehow didn't find a scanline function */ |
1519 | iter->get_scanline = _pixman_iter_get_scanline_noop; |
||
1520 | } |
||
1521 | |||
1522 | static uint32_t * |
||
1523 | dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask) |
||
1524 | { |
||
1525 | pixman_image_t *image = iter->image; |
||
1526 | int x = iter->x; |
||
1527 | int y = iter->y; |
||
1528 | int width = iter->width; |
||
1529 | uint32_t * buffer = iter->buffer; |
||
1530 | |||
1531 | image->bits.fetch_scanline_32 (image, x, y, width, buffer, mask); |
||
1532 | if (image->common.alpha_map) |
||
1533 | { |
||
1534 | uint32_t *alpha; |
||
1535 | |||
1536 | if ((alpha = malloc (width * sizeof (uint32_t)))) |
||
1537 | { |
||
1538 | int i; |
||
1539 | |||
1540 | x -= image->common.alpha_origin_x; |
||
1541 | y -= image->common.alpha_origin_y; |
||
1542 | |||
1543 | image->common.alpha_map->fetch_scanline_32 ( |
||
1544 | (pixman_image_t *)image->common.alpha_map, |
||
1545 | x, y, width, alpha, mask); |
||
1546 | |||
1547 | for (i = 0; i < width; ++i) |
||
1548 | { |
||
1549 | buffer[i] &= ~0xff000000; |
||
1550 | buffer[i] |= (alpha[i] & 0xff000000); |
||
1551 | } |
||
1552 | |||
1553 | free (alpha); |
||
1554 | } |
||
1891 | serge | 1555 | } |
3931 | Serge | 1556 | |
1557 | return iter->buffer; |
||
1891 | serge | 1558 | } |
1559 | |||
1560 | static uint32_t * |
||
3931 | Serge | 1561 | dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask) |
1562 | { |
||
1563 | bits_image_t * image = &iter->image->bits; |
||
1564 | int x = iter->x; |
||
1565 | int y = iter->y; |
||
1566 | int width = iter->width; |
||
1567 | argb_t * buffer = (argb_t *)iter->buffer; |
||
1568 | |||
1569 | image->fetch_scanline_float ( |
||
1570 | (pixman_image_t *)image, x, y, width, (uint32_t *)buffer, mask); |
||
1571 | if (image->common.alpha_map) |
||
1572 | { |
||
1573 | argb_t *alpha; |
||
1574 | |||
1575 | if ((alpha = malloc (width * sizeof (argb_t)))) |
||
1576 | { |
||
1577 | int i; |
||
1578 | |||
1579 | x -= image->common.alpha_origin_x; |
||
1580 | y -= image->common.alpha_origin_y; |
||
1581 | |||
1582 | image->common.alpha_map->fetch_scanline_float ( |
||
1583 | (pixman_image_t *)image->common.alpha_map, |
||
1584 | x, y, width, (uint32_t *)alpha, mask); |
||
1585 | |||
1586 | for (i = 0; i < width; ++i) |
||
1587 | buffer[i].a = alpha[i].a; |
||
1588 | |||
1589 | free (alpha); |
||
1590 | } |
||
1591 | } |
||
1592 | |||
1593 | return iter->buffer; |
||
1594 | } |
||
1595 | |||
1596 | static void |
||
1597 | dest_write_back_narrow (pixman_iter_t *iter) |
||
1598 | { |
||
1599 | bits_image_t * image = &iter->image->bits; |
||
1600 | int x = iter->x; |
||
1601 | int y = iter->y; |
||
1602 | int width = iter->width; |
||
1603 | const uint32_t *buffer = iter->buffer; |
||
1604 | |||
1605 | image->store_scanline_32 (image, x, y, width, buffer); |
||
1606 | |||
1607 | if (image->common.alpha_map) |
||
1608 | { |
||
1609 | x -= image->common.alpha_origin_x; |
||
1610 | y -= image->common.alpha_origin_y; |
||
1611 | |||
1612 | image->common.alpha_map->store_scanline_32 ( |
||
1613 | image->common.alpha_map, x, y, width, buffer); |
||
1614 | } |
||
1615 | |||
1616 | iter->y++; |
||
1617 | } |
||
1618 | |||
1619 | static void |
||
1620 | dest_write_back_wide (pixman_iter_t *iter) |
||
1621 | { |
||
1622 | bits_image_t * image = &iter->image->bits; |
||
1623 | int x = iter->x; |
||
1624 | int y = iter->y; |
||
1625 | int width = iter->width; |
||
1626 | const uint32_t *buffer = iter->buffer; |
||
1627 | |||
1628 | image->store_scanline_float (image, x, y, width, buffer); |
||
1629 | |||
1630 | if (image->common.alpha_map) |
||
1631 | { |
||
1632 | x -= image->common.alpha_origin_x; |
||
1633 | y -= image->common.alpha_origin_y; |
||
1634 | |||
1635 | image->common.alpha_map->store_scanline_float ( |
||
1636 | image->common.alpha_map, x, y, width, buffer); |
||
1637 | } |
||
1638 | |||
1639 | iter->y++; |
||
1640 | } |
||
1641 | |||
1642 | void |
||
1643 | _pixman_bits_image_dest_iter_init (pixman_image_t *image, pixman_iter_t *iter) |
||
1644 | { |
||
1645 | if (iter->iter_flags & ITER_NARROW) |
||
1646 | { |
||
1647 | if ((iter->iter_flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) == |
||
1648 | (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) |
||
1649 | { |
||
1650 | iter->get_scanline = _pixman_iter_get_scanline_noop; |
||
1651 | } |
||
1652 | else |
||
1653 | { |
||
1654 | iter->get_scanline = dest_get_scanline_narrow; |
||
1655 | } |
||
1656 | |||
1657 | iter->write_back = dest_write_back_narrow; |
||
1658 | } |
||
1659 | else |
||
1660 | { |
||
1661 | iter->get_scanline = dest_get_scanline_wide; |
||
1662 | iter->write_back = dest_write_back_wide; |
||
1663 | } |
||
1664 | } |
||
1665 | |||
1666 | static uint32_t * |
||
1891 | serge | 1667 | create_bits (pixman_format_code_t format, |
1668 | int width, |
||
1669 | int height, |
||
3931 | Serge | 1670 | int * rowstride_bytes, |
1671 | pixman_bool_t clear) |
||
1891 | serge | 1672 | { |
1673 | int stride; |
||
3931 | Serge | 1674 | size_t buf_size; |
1891 | serge | 1675 | int bpp; |
1676 | |||
1677 | /* what follows is a long-winded way, avoiding any possibility of integer |
||
1678 | * overflows, of saying: |
||
1679 | * stride = ((width * bpp + 0x1f) >> 5) * sizeof (uint32_t); |
||
1680 | */ |
||
1681 | |||
1682 | bpp = PIXMAN_FORMAT_BPP (format); |
||
3931 | Serge | 1683 | if (_pixman_multiply_overflows_int (width, bpp)) |
1891 | serge | 1684 | return NULL; |
1685 | |||
1686 | stride = width * bpp; |
||
3931 | Serge | 1687 | if (_pixman_addition_overflows_int (stride, 0x1f)) |
1891 | serge | 1688 | return NULL; |
1689 | |||
1690 | stride += 0x1f; |
||
1691 | stride >>= 5; |
||
1692 | |||
1693 | stride *= sizeof (uint32_t); |
||
1694 | |||
3931 | Serge | 1695 | if (_pixman_multiply_overflows_size (height, stride)) |
1891 | serge | 1696 | return NULL; |
1697 | |||
1698 | buf_size = height * stride; |
||
1699 | |||
1700 | if (rowstride_bytes) |
||
1701 | *rowstride_bytes = stride; |
||
1702 | |||
3931 | Serge | 1703 | if (clear) |
1704 | return calloc (buf_size, 1); |
||
1705 | else |
||
1706 | return malloc (buf_size); |
||
1891 | serge | 1707 | } |
1708 | |||
3931 | Serge | 1709 | pixman_bool_t |
1710 | _pixman_bits_image_init (pixman_image_t * image, |
||
1711 | pixman_format_code_t format, |
||
1712 | int width, |
||
1713 | int height, |
||
1714 | uint32_t * bits, |
||
1715 | int rowstride, |
||
1716 | pixman_bool_t clear) |
||
1891 | serge | 1717 | { |
1718 | uint32_t *free_me = NULL; |
||
1719 | |||
1720 | if (!bits && width && height) |
||
1721 | { |
||
3931 | Serge | 1722 | int rowstride_bytes; |
1891 | serge | 1723 | |
3931 | Serge | 1724 | free_me = bits = create_bits (format, width, height, &rowstride_bytes, clear); |
1891 | serge | 1725 | |
3931 | Serge | 1726 | if (!bits) |
1727 | return FALSE; |
||
1891 | serge | 1728 | |
3931 | Serge | 1729 | rowstride = rowstride_bytes / (int) sizeof (uint32_t); |
1891 | serge | 1730 | } |
1731 | |||
3931 | Serge | 1732 | _pixman_image_init (image); |
1733 | |||
1891 | serge | 1734 | image->type = BITS; |
1735 | image->bits.format = format; |
||
1736 | image->bits.width = width; |
||
1737 | image->bits.height = height; |
||
1738 | image->bits.bits = bits; |
||
1739 | image->bits.free_me = free_me; |
||
1740 | image->bits.read_func = NULL; |
||
1741 | image->bits.write_func = NULL; |
||
3931 | Serge | 1742 | image->bits.rowstride = rowstride; |
1891 | serge | 1743 | image->bits.indexed = NULL; |
1744 | |||
1745 | image->common.property_changed = bits_image_property_changed; |
||
1746 | |||
1747 | _pixman_image_reset_clip_region (image); |
||
1748 | |||
3931 | Serge | 1749 | return TRUE; |
1750 | } |
||
1751 | |||
1752 | static pixman_image_t * |
||
1753 | create_bits_image_internal (pixman_format_code_t format, |
||
1754 | int width, |
||
1755 | int height, |
||
1756 | uint32_t * bits, |
||
1757 | int rowstride_bytes, |
||
1758 | pixman_bool_t clear) |
||
1759 | { |
||
1760 | pixman_image_t *image; |
||
1761 | |||
1762 | /* must be a whole number of uint32_t's |
||
1763 | */ |
||
1764 | return_val_if_fail ( |
||
1765 | bits == NULL || (rowstride_bytes % sizeof (uint32_t)) == 0, NULL); |
||
1766 | |||
1767 | return_val_if_fail (PIXMAN_FORMAT_BPP (format) >= PIXMAN_FORMAT_DEPTH (format), NULL); |
||
1768 | |||
1769 | image = _pixman_image_allocate (); |
||
1770 | |||
1771 | if (!image) |
||
1772 | return NULL; |
||
1773 | |||
1774 | if (!_pixman_bits_image_init (image, format, width, height, bits, |
||
1775 | rowstride_bytes / (int) sizeof (uint32_t), |
||
1776 | clear)) |
||
1777 | { |
||
1778 | free (image); |
||
1779 | return NULL; |
||
1780 | } |
||
1781 | |||
1891 | serge | 1782 | return image; |
1783 | } |
||
3931 | Serge | 1784 | |
1785 | /* If bits is NULL, a buffer will be allocated and initialized to 0 */ |
||
1786 | PIXMAN_EXPORT pixman_image_t * |
||
1787 | pixman_image_create_bits (pixman_format_code_t format, |
||
1788 | int width, |
||
1789 | int height, |
||
1790 | uint32_t * bits, |
||
1791 | int rowstride_bytes) |
||
1792 | { |
||
1793 | return create_bits_image_internal ( |
||
1794 | format, width, height, bits, rowstride_bytes, TRUE); |
||
1795 | } |
||
1796 | |||
1797 | |||
1798 | /* If bits is NULL, a buffer will be allocated and _not_ initialized */ |
||
1799 | PIXMAN_EXPORT pixman_image_t * |
||
1800 | pixman_image_create_bits_no_clear (pixman_format_code_t format, |
||
1801 | int width, |
||
1802 | int height, |
||
1803 | uint32_t * bits, |
||
1804 | int rowstride_bytes) |
||
1805 | { |
||
1806 | return create_bits_image_internal ( |
||
1807 | format, width, height, bits, rowstride_bytes, FALSE); |
||
1808 | }>>>>>>>>>><>>>>>>>><>><>><>><>>>>>><>><>><>><>><>>><>><>><>><>>><>>>>>>><>><>><>>>><>><>><>><>><>><>><>><>><>><>>>>>>>>>>>>>>>> |