|
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 <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 |
|
39 static uint32_t * |
|
40 _pixman_image_get_scanline_generic_float (pixman_iter_t * iter, |
|
41 const uint32_t *mask) |
|
42 { |
|
43 pixman_iter_get_scanline_t fetch_32 = iter->data; |
|
44 uint32_t *buffer = iter->buffer; |
|
45 |
|
46 fetch_32 (iter, NULL); |
|
47 |
|
48 pixman_expand_to_float ((argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width); |
|
49 |
|
50 return iter->buffer; |
|
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 { |
|
82 repeat (image->common.repeat, &x0, image->width); |
|
83 repeat (image->common.repeat, &y0, image->height); |
|
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 |
|
109 distx = pixman_fixed_to_bilinear_weight (x1); |
|
110 disty = pixman_fixed_to_bilinear_weight (y1); |
|
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 { |
|
119 repeat (repeat_mode, &x1, width); |
|
120 repeat (repeat_mode, &y1, height); |
|
121 repeat (repeat_mode, &x2, width); |
|
122 repeat (repeat_mode, &y2, height); |
|
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 |
|
140 static uint32_t * |
|
141 bits_image_fetch_bilinear_no_repeat_8888 (pixman_iter_t *iter, |
|
142 const uint32_t *mask) |
|
143 { |
|
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 |
|
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)) |
|
172 return iter->buffer; |
|
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; |
|
178 disty = pixman_fixed_to_bilinear_weight (y); |
|
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)); |
|
239 return iter->buffer; |
|
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 |
|
287 distx = pixman_fixed_to_bilinear_weight (x); |
|
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 |
|
312 distx = pixman_fixed_to_bilinear_weight (x); |
|
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 |
|
336 distx = pixman_fixed_to_bilinear_weight (x); |
|
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; |
|
351 |
|
352 return iter->buffer; |
|
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; |
|
370 int srtot, sgtot, sbtot, satot; |
|
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 { |
|
396 repeat (repeat_mode, &rx, width); |
|
397 repeat (repeat_mode, &ry, height); |
|
398 |
|
399 pixel = get_pixel (image, rx, ry, FALSE); |
|
400 } |
|
401 else |
|
402 { |
|
403 pixel = get_pixel (image, rx, ry, TRUE); |
|
404 } |
|
405 |
|
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; |
|
410 } |
|
411 |
|
412 params++; |
|
413 } |
|
414 } |
|
415 |
|
416 satot = (satot + 0x8000) >> 16; |
|
417 srtot = (srtot + 0x8000) >> 16; |
|
418 sgtot = (sgtot + 0x8000) >> 16; |
|
419 sbtot = (sbtot + 0x8000) >> 16; |
|
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 |
|
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 |
|
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 |
|
550 case PIXMAN_FILTER_SEPARABLE_CONVOLUTION: |
|
551 return bits_image_fetch_pixel_separable_convolution (image, x, y, get_pixel); |
|
552 break; |
|
553 |
|
554 default: |
|
555 break; |
|
556 } |
|
557 |
|
558 return 0; |
|
559 } |
|
560 |
|
561 static uint32_t * |
|
562 bits_image_fetch_affine_no_alpha (pixman_iter_t * iter, |
|
563 const uint32_t * mask) |
|
564 { |
|
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 |
|
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)) |
|
584 return iter->buffer; |
|
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 } |
|
609 |
|
610 return buffer; |
|
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 |
|
654 static uint32_t * |
|
655 bits_image_fetch_general (pixman_iter_t *iter, |
|
656 const uint32_t *mask) |
|
657 { |
|
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 |
|
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)) |
|
677 return buffer; |
|
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 } |
|
719 |
|
720 return buffer; |
|
721 } |
|
722 |
|
723 typedef uint32_t (* convert_pixel_t) (const uint8_t *row, int x); |
|
724 |
|
725 static force_inline void |
|
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 |
|
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 |
|
919 distx = pixman_fixed_to_bilinear_weight (x1); |
|
920 disty = pixman_fixed_to_bilinear_weight (y1); |
|
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 |
|
933 repeat (repeat_mode, &x1, width); |
|
934 repeat (repeat_mode, &y1, height); |
|
935 repeat (repeat_mode, &x2, width); |
|
936 repeat (repeat_mode, &y2, height); |
|
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 |
|
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 |
|
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 { |
|
1117 return convert_0565_to_0888 (*((uint16_t *)row + x)); |
|
1118 } |
|
1119 |
|
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 |
|
1137 #define MAKE_BILINEAR_FETCHER(name, format, repeat_mode) \ |
|
1138 static uint32_t * \ |
|
1139 bits_image_fetch_bilinear_affine_ ## name (pixman_iter_t *iter, \ |
|
1140 const uint32_t * mask) \ |
|
1141 { \ |
|
1142 bits_image_fetch_bilinear_affine (iter->image, \ |
|
1143 iter->x, iter->y++, \ |
|
1144 iter->width, \ |
|
1145 iter->buffer, mask, \ |
|
1146 convert_ ## format, \ |
|
1147 PIXMAN_ ## format, \ |
|
1148 repeat_mode); \ |
|
1149 return iter->buffer; \ |
|
1150 } |
|
1151 |
|
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 } |
|
1166 |
|
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 |
|
1189 static void |
|
1190 replicate_pixel_32 (bits_image_t * bits, |
|
1191 int x, |
|
1192 int y, |
|
1193 int width, |
|
1194 uint32_t * buffer) |
|
1195 { |
|
1196 uint32_t color; |
|
1197 uint32_t *end; |
|
1198 |
|
1199 color = bits->fetch_pixel_32 (bits, x, y); |
|
1200 |
|
1201 end = buffer + width; |
|
1202 while (buffer < end) |
|
1203 *(buffer++) = color; |
|
1204 } |
|
1205 |
|
1206 static void |
|
1207 replicate_pixel_float (bits_image_t * bits, |
|
1208 int x, |
|
1209 int y, |
|
1210 int width, |
|
1211 uint32_t * b) |
|
1212 { |
|
1213 argb_t color; |
|
1214 argb_t *buffer = (argb_t *)b; |
|
1215 argb_t *end; |
|
1216 |
|
1217 color = bits->fetch_pixel_float (bits, x, y); |
|
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 { |
|
1236 memset (buffer, 0, width * (wide? sizeof (argb_t) : 4)); |
|
1237 return; |
|
1238 } |
|
1239 |
|
1240 if (x < 0) |
|
1241 { |
|
1242 w = MIN (width, -x); |
|
1243 |
|
1244 memset (buffer, 0, w * (wide ? sizeof (argb_t) : 4)); |
|
1245 |
|
1246 width -= w; |
|
1247 buffer += w * (wide? 4 : 1); |
|
1248 x += w; |
|
1249 } |
|
1250 |
|
1251 if (x < image->width) |
|
1252 { |
|
1253 w = MIN (width, image->width - x); |
|
1254 |
|
1255 if (wide) |
|
1256 image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL); |
|
1257 else |
|
1258 image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL); |
|
1259 |
|
1260 width -= w; |
|
1261 buffer += w * (wide? 4 : 1); |
|
1262 x += w; |
|
1263 } |
|
1264 |
|
1265 memset (buffer, 0, width * (wide ? sizeof (argb_t) : 4)); |
|
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 |
|
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 |
|
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) |
|
1304 image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL); |
|
1305 else |
|
1306 image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL); |
|
1307 |
|
1308 buffer += w * (wide? 4 : 1); |
|
1309 x += w; |
|
1310 width -= w; |
|
1311 } |
|
1312 } |
|
1313 |
|
1314 static uint32_t * |
|
1315 bits_image_fetch_untransformed_32 (pixman_iter_t * iter, |
|
1316 const uint32_t *mask) |
|
1317 { |
|
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 |
|
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 } |
|
1334 |
|
1335 iter->y++; |
|
1336 return buffer; |
|
1337 } |
|
1338 |
|
1339 static uint32_t * |
|
1340 bits_image_fetch_untransformed_float (pixman_iter_t * iter, |
|
1341 const uint32_t *mask) |
|
1342 { |
|
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 |
|
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 } |
|
1359 |
|
1360 iter->y++; |
|
1361 return buffer; |
|
1362 } |
|
1363 |
|
1364 typedef struct |
|
1365 { |
|
1366 pixman_format_code_t format; |
|
1367 uint32_t flags; |
|
1368 pixman_iter_get_scanline_t get_scanline_32; |
|
1369 pixman_iter_get_scanline_t get_scanline_float; |
|
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, |
|
1381 bits_image_fetch_untransformed_float |
|
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, |
|
1397 _pixman_image_get_scanline_generic_float |
|
1398 }, |
|
1399 |
|
1400 { PIXMAN_x8r8g8b8, |
|
1401 FAST_BILINEAR_FLAGS, |
|
1402 bits_image_fetch_bilinear_no_repeat_8888, |
|
1403 _pixman_image_get_scanline_generic_float |
|
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 |
|
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 |
|
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, \ |
|
1438 _pixman_image_get_scanline_generic_float \ |
|
1439 }, |
|
1440 |
|
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 }, |
|
1447 |
|
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 |
|
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, |
|
1474 _pixman_image_get_scanline_generic_float |
|
1475 }, |
|
1476 |
|
1477 /* General */ |
|
1478 { PIXMAN_any, |
|
1479 0, |
|
1480 bits_image_fetch_general, |
|
1481 _pixman_image_get_scanline_generic_float |
|
1482 }, |
|
1483 |
|
1484 { PIXMAN_null }, |
|
1485 }; |
|
1486 |
|
1487 static void |
|
1488 bits_image_property_changed (pixman_image_t *image) |
|
1489 { |
|
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; |
|
1497 uint32_t flags = image->common.flags; |
|
1498 const fetcher_info_t *info; |
|
1499 |
|
1500 for (info = fetcher_info; info->format != PIXMAN_null; ++info) |
|
1501 { |
|
1502 if ((info->format == format || info->format == PIXMAN_any) && |
|
1503 (info->flags & flags) == info->flags) |
|
1504 { |
|
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; |
|
1515 } |
|
1516 } |
|
1517 |
|
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_16 (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_16 (image, x, y, width, buffer, mask); |
|
1532 |
|
1533 return iter->buffer; |
|
1534 } |
|
1535 |
|
1536 static uint32_t * |
|
1537 dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask) |
|
1538 { |
|
1539 pixman_image_t *image = iter->image; |
|
1540 int x = iter->x; |
|
1541 int y = iter->y; |
|
1542 int width = iter->width; |
|
1543 uint32_t * buffer = iter->buffer; |
|
1544 |
|
1545 image->bits.fetch_scanline_32 (image, x, y, width, buffer, mask); |
|
1546 if (image->common.alpha_map) |
|
1547 { |
|
1548 uint32_t *alpha; |
|
1549 |
|
1550 if ((alpha = malloc (width * sizeof (uint32_t)))) |
|
1551 { |
|
1552 int i; |
|
1553 |
|
1554 x -= image->common.alpha_origin_x; |
|
1555 y -= image->common.alpha_origin_y; |
|
1556 |
|
1557 image->common.alpha_map->fetch_scanline_32 ( |
|
1558 (pixman_image_t *)image->common.alpha_map, |
|
1559 x, y, width, alpha, mask); |
|
1560 |
|
1561 for (i = 0; i < width; ++i) |
|
1562 { |
|
1563 buffer[i] &= ~0xff000000; |
|
1564 buffer[i] |= (alpha[i] & 0xff000000); |
|
1565 } |
|
1566 |
|
1567 free (alpha); |
|
1568 } |
|
1569 } |
|
1570 |
|
1571 return iter->buffer; |
|
1572 } |
|
1573 |
|
1574 static uint32_t * |
|
1575 dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask) |
|
1576 { |
|
1577 bits_image_t * image = &iter->image->bits; |
|
1578 int x = iter->x; |
|
1579 int y = iter->y; |
|
1580 int width = iter->width; |
|
1581 argb_t * buffer = (argb_t *)iter->buffer; |
|
1582 |
|
1583 image->fetch_scanline_float ( |
|
1584 (pixman_image_t *)image, x, y, width, (uint32_t *)buffer, mask); |
|
1585 if (image->common.alpha_map) |
|
1586 { |
|
1587 argb_t *alpha; |
|
1588 |
|
1589 if ((alpha = malloc (width * sizeof (argb_t)))) |
|
1590 { |
|
1591 int i; |
|
1592 |
|
1593 x -= image->common.alpha_origin_x; |
|
1594 y -= image->common.alpha_origin_y; |
|
1595 |
|
1596 image->common.alpha_map->fetch_scanline_float ( |
|
1597 (pixman_image_t *)image->common.alpha_map, |
|
1598 x, y, width, (uint32_t *)alpha, mask); |
|
1599 |
|
1600 for (i = 0; i < width; ++i) |
|
1601 buffer[i].a = alpha[i].a; |
|
1602 |
|
1603 free (alpha); |
|
1604 } |
|
1605 } |
|
1606 |
|
1607 return iter->buffer; |
|
1608 } |
|
1609 |
|
1610 static void |
|
1611 dest_write_back_16 (pixman_iter_t *iter) |
|
1612 { |
|
1613 bits_image_t * image = &iter->image->bits; |
|
1614 int x = iter->x; |
|
1615 int y = iter->y; |
|
1616 int width = iter->width; |
|
1617 const uint32_t *buffer = iter->buffer; |
|
1618 |
|
1619 image->store_scanline_16 (image, x, y, width, buffer); |
|
1620 |
|
1621 iter->y++; |
|
1622 } |
|
1623 |
|
1624 static void |
|
1625 dest_write_back_narrow (pixman_iter_t *iter) |
|
1626 { |
|
1627 bits_image_t * image = &iter->image->bits; |
|
1628 int x = iter->x; |
|
1629 int y = iter->y; |
|
1630 int width = iter->width; |
|
1631 const uint32_t *buffer = iter->buffer; |
|
1632 |
|
1633 image->store_scanline_32 (image, x, y, width, buffer); |
|
1634 |
|
1635 if (image->common.alpha_map) |
|
1636 { |
|
1637 x -= image->common.alpha_origin_x; |
|
1638 y -= image->common.alpha_origin_y; |
|
1639 |
|
1640 image->common.alpha_map->store_scanline_32 ( |
|
1641 image->common.alpha_map, x, y, width, buffer); |
|
1642 } |
|
1643 |
|
1644 iter->y++; |
|
1645 } |
|
1646 |
|
1647 static void |
|
1648 dest_write_back_wide (pixman_iter_t *iter) |
|
1649 { |
|
1650 bits_image_t * image = &iter->image->bits; |
|
1651 int x = iter->x; |
|
1652 int y = iter->y; |
|
1653 int width = iter->width; |
|
1654 const uint32_t *buffer = iter->buffer; |
|
1655 |
|
1656 image->store_scanline_float (image, x, y, width, buffer); |
|
1657 |
|
1658 if (image->common.alpha_map) |
|
1659 { |
|
1660 x -= image->common.alpha_origin_x; |
|
1661 y -= image->common.alpha_origin_y; |
|
1662 |
|
1663 image->common.alpha_map->store_scanline_float ( |
|
1664 image->common.alpha_map, x, y, width, buffer); |
|
1665 } |
|
1666 |
|
1667 iter->y++; |
|
1668 } |
|
1669 |
|
1670 void |
|
1671 _pixman_bits_image_dest_iter_init (pixman_image_t *image, pixman_iter_t *iter) |
|
1672 { |
|
1673 if (iter->iter_flags & ITER_16) |
|
1674 { |
|
1675 if ((iter->iter_flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) == |
|
1676 (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) |
|
1677 { |
|
1678 iter->get_scanline = _pixman_iter_get_scanline_noop; |
|
1679 } |
|
1680 else |
|
1681 { |
|
1682 iter->get_scanline = dest_get_scanline_16; |
|
1683 } |
|
1684 iter->write_back = dest_write_back_16; |
|
1685 } |
|
1686 else if (iter->iter_flags & ITER_NARROW) |
|
1687 { |
|
1688 if ((iter->iter_flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) == |
|
1689 (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) |
|
1690 { |
|
1691 iter->get_scanline = _pixman_iter_get_scanline_noop; |
|
1692 } |
|
1693 else |
|
1694 { |
|
1695 iter->get_scanline = dest_get_scanline_narrow; |
|
1696 } |
|
1697 |
|
1698 iter->write_back = dest_write_back_narrow; |
|
1699 } |
|
1700 else |
|
1701 { |
|
1702 iter->get_scanline = dest_get_scanline_wide; |
|
1703 iter->write_back = dest_write_back_wide; |
|
1704 } |
|
1705 } |
|
1706 |
|
1707 static uint32_t * |
|
1708 create_bits (pixman_format_code_t format, |
|
1709 int width, |
|
1710 int height, |
|
1711 int * rowstride_bytes, |
|
1712 pixman_bool_t clear) |
|
1713 { |
|
1714 int stride; |
|
1715 size_t buf_size; |
|
1716 int bpp; |
|
1717 |
|
1718 /* what follows is a long-winded way, avoiding any possibility of integer |
|
1719 * overflows, of saying: |
|
1720 * stride = ((width * bpp + 0x1f) >> 5) * sizeof (uint32_t); |
|
1721 */ |
|
1722 |
|
1723 bpp = PIXMAN_FORMAT_BPP (format); |
|
1724 if (_pixman_multiply_overflows_int (width, bpp)) |
|
1725 return NULL; |
|
1726 |
|
1727 stride = width * bpp; |
|
1728 if (_pixman_addition_overflows_int (stride, 0x1f)) |
|
1729 return NULL; |
|
1730 |
|
1731 stride += 0x1f; |
|
1732 stride >>= 5; |
|
1733 |
|
1734 stride *= sizeof (uint32_t); |
|
1735 |
|
1736 if (_pixman_multiply_overflows_size (height, stride)) |
|
1737 return NULL; |
|
1738 |
|
1739 buf_size = height * stride; |
|
1740 |
|
1741 if (rowstride_bytes) |
|
1742 *rowstride_bytes = stride; |
|
1743 |
|
1744 if (clear) |
|
1745 return calloc (buf_size, 1); |
|
1746 else |
|
1747 return malloc (buf_size); |
|
1748 } |
|
1749 |
|
1750 pixman_bool_t |
|
1751 _pixman_bits_image_init (pixman_image_t * image, |
|
1752 pixman_format_code_t format, |
|
1753 int width, |
|
1754 int height, |
|
1755 uint32_t * bits, |
|
1756 int rowstride, |
|
1757 pixman_bool_t clear) |
|
1758 { |
|
1759 uint32_t *free_me = NULL; |
|
1760 |
|
1761 if (!bits && width && height) |
|
1762 { |
|
1763 int rowstride_bytes; |
|
1764 |
|
1765 free_me = bits = create_bits (format, width, height, &rowstride_bytes, clear); |
|
1766 |
|
1767 if (!bits) |
|
1768 return FALSE; |
|
1769 |
|
1770 rowstride = rowstride_bytes / (int) sizeof (uint32_t); |
|
1771 } |
|
1772 |
|
1773 _pixman_image_init (image); |
|
1774 |
|
1775 image->type = BITS; |
|
1776 image->bits.format = format; |
|
1777 image->bits.width = width; |
|
1778 image->bits.height = height; |
|
1779 image->bits.bits = bits; |
|
1780 image->bits.free_me = free_me; |
|
1781 image->bits.read_func = NULL; |
|
1782 image->bits.write_func = NULL; |
|
1783 image->bits.rowstride = rowstride; |
|
1784 image->bits.indexed = NULL; |
|
1785 |
|
1786 image->common.property_changed = bits_image_property_changed; |
|
1787 |
|
1788 _pixman_image_reset_clip_region (image); |
|
1789 |
|
1790 return TRUE; |
|
1791 } |
|
1792 |
|
1793 static pixman_image_t * |
|
1794 create_bits_image_internal (pixman_format_code_t format, |
|
1795 int width, |
|
1796 int height, |
|
1797 uint32_t * bits, |
|
1798 int rowstride_bytes, |
|
1799 pixman_bool_t clear) |
|
1800 { |
|
1801 pixman_image_t *image; |
|
1802 |
|
1803 /* must be a whole number of uint32_t's |
|
1804 */ |
|
1805 return_val_if_fail ( |
|
1806 bits == NULL || (rowstride_bytes % sizeof (uint32_t)) == 0, NULL); |
|
1807 |
|
1808 return_val_if_fail (PIXMAN_FORMAT_BPP (format) >= PIXMAN_FORMAT_DEPTH (format), NULL); |
|
1809 |
|
1810 image = _pixman_image_allocate (); |
|
1811 |
|
1812 if (!image) |
|
1813 return NULL; |
|
1814 |
|
1815 if (!_pixman_bits_image_init (image, format, width, height, bits, |
|
1816 rowstride_bytes / (int) sizeof (uint32_t), |
|
1817 clear)) |
|
1818 { |
|
1819 free (image); |
|
1820 return NULL; |
|
1821 } |
|
1822 |
|
1823 return image; |
|
1824 } |
|
1825 |
|
1826 /* If bits is NULL, a buffer will be allocated and initialized to 0 */ |
|
1827 PIXMAN_EXPORT pixman_image_t * |
|
1828 pixman_image_create_bits (pixman_format_code_t format, |
|
1829 int width, |
|
1830 int height, |
|
1831 uint32_t * bits, |
|
1832 int rowstride_bytes) |
|
1833 { |
|
1834 return create_bits_image_internal ( |
|
1835 format, width, height, bits, rowstride_bytes, TRUE); |
|
1836 } |
|
1837 |
|
1838 |
|
1839 /* If bits is NULL, a buffer will be allocated and _not_ initialized */ |
|
1840 PIXMAN_EXPORT pixman_image_t * |
|
1841 pixman_image_create_bits_no_clear (pixman_format_code_t format, |
|
1842 int width, |
|
1843 int height, |
|
1844 uint32_t * bits, |
|
1845 int rowstride_bytes) |
|
1846 { |
|
1847 return create_bits_image_internal ( |
|
1848 format, width, height, bits, rowstride_bytes, FALSE); |
|
1849 } |