Line data Source code
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 0 : _pixman_image_get_scanline_generic_float (pixman_iter_t * iter,
41 : const uint32_t *mask)
42 : {
43 0 : pixman_iter_get_scanline_t fetch_32 = iter->data;
44 0 : uint32_t *buffer = iter->buffer;
45 :
46 0 : fetch_32 (iter, NULL);
47 :
48 0 : pixman_expand_to_float ((argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
49 :
50 0 : return iter->buffer;
51 : }
52 :
53 : /* Fetch functions */
54 :
55 : static force_inline uint32_t
56 0 : fetch_pixel_no_alpha (bits_image_t *image,
57 : int x, int y, pixman_bool_t check_bounds)
58 : {
59 0 : if (check_bounds &&
60 0 : (x < 0 || x >= image->width || y < 0 || y >= image->height))
61 : {
62 0 : return 0;
63 : }
64 :
65 0 : 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 0 : int x0 = pixman_fixed_to_int (x - pixman_fixed_e);
78 0 : int y0 = pixman_fixed_to_int (y - pixman_fixed_e);
79 :
80 0 : if (image->common.repeat != PIXMAN_REPEAT_NONE)
81 : {
82 0 : repeat (image->common.repeat, &x0, image->width);
83 0 : repeat (image->common.repeat, &y0, image->height);
84 :
85 0 : return get_pixel (image, x0, y0, FALSE);
86 : }
87 : else
88 : {
89 0 : 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 0 : pixman_repeat_t repeat_mode = image->common.repeat;
100 0 : int width = image->width;
101 0 : int height = image->height;
102 : int x1, y1, x2, y2;
103 : uint32_t tl, tr, bl, br;
104 : int32_t distx, disty;
105 :
106 0 : x1 = x - pixman_fixed_1 / 2;
107 0 : y1 = y - pixman_fixed_1 / 2;
108 :
109 0 : distx = pixman_fixed_to_bilinear_weight (x1);
110 0 : disty = pixman_fixed_to_bilinear_weight (y1);
111 :
112 0 : x1 = pixman_fixed_to_int (x1);
113 0 : y1 = pixman_fixed_to_int (y1);
114 0 : x2 = x1 + 1;
115 0 : y2 = y1 + 1;
116 :
117 0 : 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 0 : tl = get_pixel (image, x1, y1, FALSE);
125 0 : bl = get_pixel (image, x1, y2, FALSE);
126 0 : tr = get_pixel (image, x2, y1, FALSE);
127 0 : br = get_pixel (image, x2, y2, FALSE);
128 : }
129 : else
130 : {
131 0 : tl = get_pixel (image, x1, y1, TRUE);
132 0 : tr = get_pixel (image, x2, y1, TRUE);
133 0 : bl = get_pixel (image, x1, y2, TRUE);
134 0 : br = get_pixel (image, x2, y2, TRUE);
135 : }
136 :
137 0 : return bilinear_interpolation (tl, tr, bl, br, distx, disty);
138 : }
139 :
140 : static uint32_t *
141 0 : bits_image_fetch_bilinear_no_repeat_8888 (pixman_iter_t *iter,
142 : const uint32_t *mask)
143 : {
144 :
145 0 : pixman_image_t * ima = iter->image;
146 0 : int offset = iter->x;
147 0 : int line = iter->y++;
148 0 : int width = iter->width;
149 0 : uint32_t * buffer = iter->buffer;
150 :
151 0 : 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 0 : uint32_t zero[2] = { 0, 0 };
160 0 : 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 0 : v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
168 0 : v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
169 0 : v.vector[2] = pixman_fixed_1;
170 :
171 0 : if (!pixman_transform_point_3d (bits->common.transform, &v))
172 0 : return iter->buffer;
173 :
174 0 : ux = ux_top = ux_bottom = bits->common.transform->matrix[0][0];
175 0 : x = x_top = x_bottom = v.vector[0] - pixman_fixed_1/2;
176 :
177 0 : y = v.vector[1] - pixman_fixed_1/2;
178 0 : 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 0 : y1 = pixman_fixed_to_int (y);
192 0 : y2 = y1 + 1;
193 :
194 0 : if (y1 < 0 || y1 >= bits->height)
195 : {
196 0 : top_row = zero;
197 0 : x_top = 0;
198 0 : ux_top = 0;
199 : }
200 : else
201 : {
202 0 : top_row = bits->bits + y1 * bits->rowstride;
203 0 : x_top = x;
204 0 : ux_top = ux;
205 : }
206 :
207 0 : if (y2 < 0 || y2 >= bits->height)
208 : {
209 0 : bottom_row = zero;
210 0 : x_bottom = 0;
211 0 : ux_bottom = 0;
212 : }
213 : else
214 : {
215 0 : bottom_row = bits->bits + y2 * bits->rowstride;
216 0 : x_bottom = x;
217 0 : 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 0 : if (!mask)
225 : {
226 0 : mask_inc = 0;
227 0 : mask = &one;
228 : }
229 : else
230 : {
231 : /* If have a mask, prepare the variables to check it */
232 0 : mask_inc = 1;
233 : }
234 :
235 : /* If both are zero, then the whole thing is zero */
236 0 : if (top_row == zero && bottom_row == zero)
237 : {
238 0 : memset (buffer, 0, width * sizeof (uint32_t));
239 0 : return iter->buffer;
240 : }
241 0 : else if (bits->format == PIXMAN_x8r8g8b8)
242 : {
243 0 : if (top_row == zero)
244 : {
245 0 : top_mask = 0;
246 0 : bottom_mask = 0xff000000;
247 : }
248 0 : else if (bottom_row == zero)
249 : {
250 0 : top_mask = 0xff000000;
251 0 : bottom_mask = 0;
252 : }
253 : else
254 : {
255 0 : top_mask = 0xff000000;
256 0 : bottom_mask = 0xff000000;
257 : }
258 : }
259 : else
260 : {
261 0 : top_mask = 0;
262 0 : bottom_mask = 0;
263 : }
264 :
265 0 : end = buffer + width;
266 :
267 : /* Zero fill to the left of the image */
268 0 : while (buffer < end && x < pixman_fixed_minus_1)
269 : {
270 0 : *buffer++ = 0;
271 0 : x += ux;
272 0 : x_top += ux_top;
273 0 : x_bottom += ux_bottom;
274 0 : mask += mask_inc;
275 : }
276 :
277 : /* Left edge
278 : */
279 0 : while (buffer < end && x < 0)
280 : {
281 : uint32_t tr, br;
282 : int32_t distx;
283 :
284 0 : tr = top_row[pixman_fixed_to_int (x_top) + 1] | top_mask;
285 0 : br = bottom_row[pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;
286 :
287 0 : distx = pixman_fixed_to_bilinear_weight (x);
288 :
289 0 : *buffer++ = bilinear_interpolation (0, tr, 0, br, distx, disty);
290 :
291 0 : x += ux;
292 0 : x_top += ux_top;
293 0 : x_bottom += ux_bottom;
294 0 : mask += mask_inc;
295 : }
296 :
297 : /* Main part */
298 0 : w = pixman_int_to_fixed (bits->width - 1);
299 :
300 0 : while (buffer < end && x < w)
301 : {
302 0 : if (*mask)
303 : {
304 : uint32_t tl, tr, bl, br;
305 : int32_t distx;
306 :
307 0 : tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
308 0 : tr = top_row [pixman_fixed_to_int (x_top) + 1] | top_mask;
309 0 : bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
310 0 : br = bottom_row [pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;
311 :
312 0 : distx = pixman_fixed_to_bilinear_weight (x);
313 :
314 0 : *buffer = bilinear_interpolation (tl, tr, bl, br, distx, disty);
315 : }
316 :
317 0 : buffer++;
318 0 : x += ux;
319 0 : x_top += ux_top;
320 0 : x_bottom += ux_bottom;
321 0 : mask += mask_inc;
322 : }
323 :
324 : /* Right Edge */
325 0 : w = pixman_int_to_fixed (bits->width);
326 0 : while (buffer < end && x < w)
327 : {
328 0 : if (*mask)
329 : {
330 : uint32_t tl, bl;
331 : int32_t distx;
332 :
333 0 : tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
334 0 : bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
335 :
336 0 : distx = pixman_fixed_to_bilinear_weight (x);
337 :
338 0 : *buffer = bilinear_interpolation (tl, 0, bl, 0, distx, disty);
339 : }
340 :
341 0 : buffer++;
342 0 : x += ux;
343 0 : x_top += ux_top;
344 0 : x_bottom += ux_bottom;
345 0 : mask += mask_inc;
346 : }
347 :
348 : /* Zero fill to the left of the image */
349 0 : while (buffer < end)
350 0 : *buffer++ = 0;
351 :
352 0 : 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 0 : pixman_fixed_t *params = image->common.filter_params;
362 0 : int x_off = (params[0] - pixman_fixed_1) >> 1;
363 0 : int y_off = (params[1] - pixman_fixed_1) >> 1;
364 0 : int32_t cwidth = pixman_fixed_to_int (params[0]);
365 0 : int32_t cheight = pixman_fixed_to_int (params[1]);
366 : int32_t i, j, x1, x2, y1, y2;
367 0 : pixman_repeat_t repeat_mode = image->common.repeat;
368 0 : int width = image->width;
369 0 : int height = image->height;
370 : int srtot, sgtot, sbtot, satot;
371 :
372 0 : params += 2;
373 :
374 0 : x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
375 0 : y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
376 0 : x2 = x1 + cwidth;
377 0 : y2 = y1 + cheight;
378 :
379 0 : srtot = sgtot = sbtot = satot = 0;
380 :
381 0 : for (i = y1; i < y2; ++i)
382 : {
383 0 : for (j = x1; j < x2; ++j)
384 : {
385 0 : int rx = j;
386 0 : int ry = i;
387 :
388 0 : pixman_fixed_t f = *params;
389 :
390 0 : if (f)
391 : {
392 : uint32_t pixel;
393 :
394 0 : if (repeat_mode != PIXMAN_REPEAT_NONE)
395 : {
396 : repeat (repeat_mode, &rx, width);
397 : repeat (repeat_mode, &ry, height);
398 :
399 0 : pixel = get_pixel (image, rx, ry, FALSE);
400 : }
401 : else
402 : {
403 0 : pixel = get_pixel (image, rx, ry, TRUE);
404 : }
405 :
406 0 : srtot += (int)RED_8 (pixel) * f;
407 0 : sgtot += (int)GREEN_8 (pixel) * f;
408 0 : sbtot += (int)BLUE_8 (pixel) * f;
409 0 : satot += (int)ALPHA_8 (pixel) * f;
410 : }
411 :
412 0 : params++;
413 : }
414 : }
415 :
416 0 : satot = (satot + 0x8000) >> 16;
417 0 : srtot = (srtot + 0x8000) >> 16;
418 0 : sgtot = (sgtot + 0x8000) >> 16;
419 0 : sbtot = (sbtot + 0x8000) >> 16;
420 :
421 0 : satot = CLIP (satot, 0, 0xff);
422 0 : srtot = CLIP (srtot, 0, 0xff);
423 0 : sgtot = CLIP (sgtot, 0, 0xff);
424 0 : sbtot = CLIP (sbtot, 0, 0xff);
425 :
426 0 : return ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot));
427 : }
428 :
429 : static uint32_t
430 0 : 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 0 : pixman_fixed_t *params = image->common.filter_params;
436 0 : pixman_repeat_t repeat_mode = image->common.repeat;
437 0 : int width = image->width;
438 0 : int height = image->height;
439 0 : int cwidth = pixman_fixed_to_int (params[0]);
440 0 : int cheight = pixman_fixed_to_int (params[1]);
441 0 : int x_phase_bits = pixman_fixed_to_int (params[2]);
442 0 : int y_phase_bits = pixman_fixed_to_int (params[3]);
443 0 : int x_phase_shift = 16 - x_phase_bits;
444 0 : int y_phase_shift = 16 - y_phase_bits;
445 0 : int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1;
446 0 : 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 0 : x = ((x >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1);
459 0 : y = ((y >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1);
460 :
461 0 : px = (x & 0xffff) >> x_phase_shift;
462 0 : py = (y & 0xffff) >> y_phase_shift;
463 :
464 0 : y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight;
465 :
466 0 : x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
467 0 : y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
468 0 : x2 = x1 + cwidth;
469 0 : y2 = y1 + cheight;
470 :
471 0 : srtot = sgtot = sbtot = satot = 0;
472 :
473 0 : for (i = y1; i < y2; ++i)
474 : {
475 0 : pixman_fixed_48_16_t fy = *y_params++;
476 0 : pixman_fixed_t *x_params = params + 4 + px * cwidth;
477 :
478 0 : if (fy)
479 : {
480 0 : for (j = x1; j < x2; ++j)
481 : {
482 0 : pixman_fixed_t fx = *x_params++;
483 0 : int rx = j;
484 0 : int ry = i;
485 :
486 0 : if (fx)
487 : {
488 : pixman_fixed_t f;
489 : uint32_t pixel;
490 :
491 0 : if (repeat_mode != PIXMAN_REPEAT_NONE)
492 : {
493 : repeat (repeat_mode, &rx, width);
494 : repeat (repeat_mode, &ry, height);
495 :
496 0 : pixel = get_pixel (image, rx, ry, FALSE);
497 : }
498 : else
499 : {
500 0 : pixel = get_pixel (image, rx, ry, TRUE);
501 : }
502 :
503 0 : f = (fy * fx + 0x8000) >> 16;
504 :
505 0 : srtot += (int)RED_8 (pixel) * f;
506 0 : sgtot += (int)GREEN_8 (pixel) * f;
507 0 : sbtot += (int)BLUE_8 (pixel) * f;
508 0 : satot += (int)ALPHA_8 (pixel) * f;
509 : }
510 : }
511 : }
512 : }
513 :
514 0 : satot = (satot + 0x8000) >> 16;
515 0 : srtot = (srtot + 0x8000) >> 16;
516 0 : sgtot = (sgtot + 0x8000) >> 16;
517 0 : sbtot = (sbtot + 0x8000) >> 16;
518 :
519 0 : satot = CLIP (satot, 0, 0xff);
520 0 : srtot = CLIP (srtot, 0, 0xff);
521 0 : sgtot = CLIP (sgtot, 0, 0xff);
522 0 : sbtot = CLIP (sbtot, 0, 0xff);
523 :
524 0 : 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 0 : switch (image->common.filter)
534 : {
535 : case PIXMAN_FILTER_NEAREST:
536 : case PIXMAN_FILTER_FAST:
537 0 : 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 0 : return bits_image_fetch_pixel_bilinear (image, x, y, get_pixel);
544 : break;
545 :
546 : case PIXMAN_FILTER_CONVOLUTION:
547 0 : return bits_image_fetch_pixel_convolution (image, x, y, get_pixel);
548 : break;
549 :
550 : case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
551 0 : return bits_image_fetch_pixel_separable_convolution (image, x, y, get_pixel);
552 : break;
553 :
554 : default:
555 : break;
556 : }
557 :
558 0 : return 0;
559 : }
560 :
561 : static uint32_t *
562 0 : bits_image_fetch_affine_no_alpha (pixman_iter_t * iter,
563 : const uint32_t * mask)
564 : {
565 0 : pixman_image_t *image = iter->image;
566 0 : int offset = iter->x;
567 0 : int line = iter->y++;
568 0 : int width = iter->width;
569 0 : 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 0 : v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
578 0 : v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
579 0 : v.vector[2] = pixman_fixed_1;
580 :
581 0 : if (image->common.transform)
582 : {
583 0 : if (!pixman_transform_point_3d (image->common.transform, &v))
584 0 : return iter->buffer;
585 :
586 0 : ux = image->common.transform->matrix[0][0];
587 0 : uy = image->common.transform->matrix[1][0];
588 : }
589 : else
590 : {
591 0 : ux = pixman_fixed_1;
592 0 : uy = 0;
593 : }
594 :
595 0 : x = v.vector[0];
596 0 : y = v.vector[1];
597 :
598 0 : for (i = 0; i < width; ++i)
599 : {
600 0 : if (!mask || mask[i])
601 : {
602 0 : buffer[i] = bits_image_fetch_pixel_filtered (
603 : &image->bits, x, y, fetch_pixel_no_alpha);
604 : }
605 :
606 0 : x += ux;
607 0 : y += uy;
608 : }
609 :
610 0 : return buffer;
611 : }
612 :
613 : /* General fetcher */
614 : static force_inline uint32_t
615 0 : fetch_pixel_general (bits_image_t *image, int x, int y, pixman_bool_t check_bounds)
616 : {
617 : uint32_t pixel;
618 :
619 0 : if (check_bounds &&
620 0 : (x < 0 || x >= image->width || y < 0 || y >= image->height))
621 : {
622 0 : return 0;
623 : }
624 :
625 0 : pixel = image->fetch_pixel_32 (image, x, y);
626 :
627 0 : if (image->common.alpha_map)
628 : {
629 : uint32_t pixel_a;
630 :
631 0 : x -= image->common.alpha_origin_x;
632 0 : y -= image->common.alpha_origin_y;
633 :
634 0 : if (x < 0 || x >= image->common.alpha_map->width ||
635 0 : y < 0 || y >= image->common.alpha_map->height)
636 : {
637 0 : pixel_a = 0;
638 : }
639 : else
640 : {
641 0 : pixel_a = image->common.alpha_map->fetch_pixel_32 (
642 : image->common.alpha_map, x, y);
643 :
644 0 : pixel_a = ALPHA_8 (pixel_a);
645 : }
646 :
647 0 : pixel &= 0x00ffffff;
648 0 : pixel |= (pixel_a << 24);
649 : }
650 :
651 0 : return pixel;
652 : }
653 :
654 : static uint32_t *
655 0 : bits_image_fetch_general (pixman_iter_t *iter,
656 : const uint32_t *mask)
657 : {
658 0 : pixman_image_t *image = iter->image;
659 0 : int offset = iter->x;
660 0 : int line = iter->y++;
661 0 : int width = iter->width;
662 0 : 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 0 : v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
671 0 : v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
672 0 : v.vector[2] = pixman_fixed_1;
673 :
674 0 : if (image->common.transform)
675 : {
676 0 : if (!pixman_transform_point_3d (image->common.transform, &v))
677 0 : return buffer;
678 :
679 0 : ux = image->common.transform->matrix[0][0];
680 0 : uy = image->common.transform->matrix[1][0];
681 0 : uw = image->common.transform->matrix[2][0];
682 : }
683 : else
684 : {
685 0 : ux = pixman_fixed_1;
686 0 : uy = 0;
687 0 : uw = 0;
688 : }
689 :
690 0 : x = v.vector[0];
691 0 : y = v.vector[1];
692 0 : w = v.vector[2];
693 :
694 0 : for (i = 0; i < width; ++i)
695 : {
696 : pixman_fixed_t x0, y0;
697 :
698 0 : if (!mask || mask[i])
699 : {
700 0 : if (w != 0)
701 : {
702 0 : x0 = ((pixman_fixed_48_16_t)x << 16) / w;
703 0 : y0 = ((pixman_fixed_48_16_t)y << 16) / w;
704 : }
705 : else
706 : {
707 0 : x0 = 0;
708 0 : y0 = 0;
709 : }
710 :
711 0 : buffer[i] = bits_image_fetch_pixel_filtered (
712 : &image->bits, x0, y0, fetch_pixel_general);
713 : }
714 :
715 0 : x += ux;
716 0 : y += uy;
717 0 : w += uw;
718 : }
719 :
720 0 : 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 0 : bits_image_t *bits = &image->bits;
738 0 : pixman_fixed_t *params = image->common.filter_params;
739 0 : int cwidth = pixman_fixed_to_int (params[0]);
740 0 : int cheight = pixman_fixed_to_int (params[1]);
741 0 : int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1;
742 0 : int y_off = ((cheight << 16) - pixman_fixed_1) >> 1;
743 0 : int x_phase_bits = pixman_fixed_to_int (params[2]);
744 0 : int y_phase_bits = pixman_fixed_to_int (params[3]);
745 0 : int x_phase_shift = 16 - x_phase_bits;
746 0 : 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 0 : v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
754 0 : v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
755 0 : v.vector[2] = pixman_fixed_1;
756 :
757 0 : if (!pixman_transform_point_3d (image->common.transform, &v))
758 0 : return;
759 :
760 0 : ux = image->common.transform->matrix[0][0];
761 0 : uy = image->common.transform->matrix[1][0];
762 :
763 0 : vx = v.vector[0];
764 0 : vy = v.vector[1];
765 :
766 0 : 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 0 : 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 0 : x = ((vx >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1);
784 0 : y = ((vy >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1);
785 :
786 0 : px = (x & 0xffff) >> x_phase_shift;
787 0 : py = (y & 0xffff) >> y_phase_shift;
788 :
789 0 : x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
790 0 : y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
791 0 : x2 = x1 + cwidth;
792 0 : y2 = y1 + cheight;
793 :
794 0 : satot = srtot = sgtot = sbtot = 0;
795 :
796 0 : y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight;
797 :
798 0 : for (i = y1; i < y2; ++i)
799 : {
800 0 : pixman_fixed_t fy = *y_params++;
801 :
802 0 : if (fy)
803 : {
804 0 : pixman_fixed_t *x_params = params + 4 + px * cwidth;
805 :
806 0 : for (j = x1; j < x2; ++j)
807 : {
808 0 : pixman_fixed_t fx = *x_params++;
809 0 : int rx = j;
810 0 : int ry = i;
811 :
812 0 : if (fx)
813 : {
814 : pixman_fixed_t f;
815 : uint32_t pixel, mask;
816 : uint8_t *row;
817 :
818 0 : mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
819 :
820 0 : if (repeat_mode != PIXMAN_REPEAT_NONE)
821 : {
822 0 : repeat (repeat_mode, &rx, bits->width);
823 0 : repeat (repeat_mode, &ry, bits->height);
824 :
825 0 : row = (uint8_t *)bits->bits + bits->rowstride * 4 * ry;
826 0 : pixel = convert_pixel (row, rx) | mask;
827 : }
828 : else
829 : {
830 0 : if (rx < 0 || ry < 0 || rx >= bits->width || ry >= bits->height)
831 : {
832 0 : pixel = 0;
833 : }
834 : else
835 : {
836 0 : row = (uint8_t *)bits->bits + bits->rowstride * 4 * ry;
837 0 : pixel = convert_pixel (row, rx) | mask;
838 : }
839 : }
840 :
841 0 : f = ((pixman_fixed_32_32_t)fx * fy + 0x8000) >> 16;
842 0 : srtot += (int)RED_8 (pixel) * f;
843 0 : sgtot += (int)GREEN_8 (pixel) * f;
844 0 : sbtot += (int)BLUE_8 (pixel) * f;
845 0 : satot += (int)ALPHA_8 (pixel) * f;
846 : }
847 : }
848 : }
849 : }
850 :
851 0 : satot = (satot + 0x8000) >> 16;
852 0 : srtot = (srtot + 0x8000) >> 16;
853 0 : sgtot = (sgtot + 0x8000) >> 16;
854 0 : sbtot = (sbtot + 0x8000) >> 16;
855 :
856 0 : satot = CLIP (satot, 0, 0xff);
857 0 : srtot = CLIP (srtot, 0, 0xff);
858 0 : sgtot = CLIP (sgtot, 0, 0xff);
859 0 : sbtot = CLIP (sbtot, 0, 0xff);
860 :
861 0 : buffer[k] = (satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot << 0);
862 :
863 : next:
864 0 : vx += ux;
865 0 : 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 0 : bits_image_t *bits = &image->bits;
887 : int i;
888 :
889 : /* reference point is the center of the pixel */
890 0 : v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
891 0 : v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
892 0 : v.vector[2] = pixman_fixed_1;
893 :
894 0 : if (!pixman_transform_point_3d (image->common.transform, &v))
895 0 : return;
896 :
897 0 : ux = image->common.transform->matrix[0][0];
898 0 : uy = image->common.transform->matrix[1][0];
899 :
900 0 : x = v.vector[0];
901 0 : y = v.vector[1];
902 :
903 0 : 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 0 : int width = image->bits.width;
909 0 : int height = image->bits.height;
910 : const uint8_t *row1;
911 : const uint8_t *row2;
912 :
913 0 : if (mask && !mask[i])
914 : goto next;
915 :
916 0 : x1 = x - pixman_fixed_1 / 2;
917 0 : y1 = y - pixman_fixed_1 / 2;
918 :
919 0 : distx = pixman_fixed_to_bilinear_weight (x1);
920 0 : disty = pixman_fixed_to_bilinear_weight (y1);
921 :
922 0 : y1 = pixman_fixed_to_int (y1);
923 0 : y2 = y1 + 1;
924 0 : x1 = pixman_fixed_to_int (x1);
925 0 : x2 = x1 + 1;
926 :
927 0 : if (repeat_mode != PIXMAN_REPEAT_NONE)
928 : {
929 : uint32_t mask;
930 :
931 0 : 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 0 : row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
939 0 : row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
940 :
941 0 : tl = convert_pixel (row1, x1) | mask;
942 0 : tr = convert_pixel (row1, x2) | mask;
943 0 : bl = convert_pixel (row2, x1) | mask;
944 0 : 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 0 : bpp = PIXMAN_FORMAT_BPP (format);
960 :
961 0 : if (x1 >= width || x2 < 0 || y1 >= height || y2 < 0)
962 : {
963 0 : buffer[i] = 0;
964 : goto next;
965 : }
966 :
967 0 : if (y2 == 0)
968 : {
969 0 : row1 = zero;
970 0 : mask1 = 0;
971 : }
972 : else
973 : {
974 0 : row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
975 0 : row1 += bpp / 8 * x1;
976 :
977 0 : mask1 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
978 : }
979 :
980 0 : if (y1 == height - 1)
981 : {
982 0 : row2 = zero;
983 0 : mask2 = 0;
984 : }
985 : else
986 : {
987 0 : row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
988 0 : row2 += bpp / 8 * x1;
989 :
990 0 : mask2 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
991 : }
992 :
993 0 : if (x2 == 0)
994 : {
995 0 : tl = 0;
996 0 : bl = 0;
997 : }
998 : else
999 : {
1000 0 : tl = convert_pixel (row1, 0) | mask1;
1001 0 : bl = convert_pixel (row2, 0) | mask2;
1002 : }
1003 :
1004 0 : if (x1 == width - 1)
1005 : {
1006 0 : tr = 0;
1007 0 : br = 0;
1008 : }
1009 : else
1010 : {
1011 0 : tr = convert_pixel (row1, 1) | mask1;
1012 0 : br = convert_pixel (row2, 1) | mask2;
1013 : }
1014 : }
1015 :
1016 0 : buffer[i] = bilinear_interpolation (
1017 : tl, tr, bl, br, distx, disty);
1018 :
1019 : next:
1020 0 : x += ux;
1021 0 : 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 0 : bits_image_t *bits = &image->bits;
1041 : int i;
1042 :
1043 : /* reference point is the center of the pixel */
1044 0 : v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
1045 0 : v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
1046 0 : v.vector[2] = pixman_fixed_1;
1047 :
1048 0 : if (!pixman_transform_point_3d (image->common.transform, &v))
1049 0 : return;
1050 :
1051 0 : ux = image->common.transform->matrix[0][0];
1052 0 : uy = image->common.transform->matrix[1][0];
1053 :
1054 0 : x = v.vector[0];
1055 0 : y = v.vector[1];
1056 :
1057 0 : for (i = 0; i < width; ++i)
1058 : {
1059 : int width, height, x0, y0;
1060 : const uint8_t *row;
1061 :
1062 0 : if (mask && !mask[i])
1063 : goto next;
1064 :
1065 0 : width = image->bits.width;
1066 0 : height = image->bits.height;
1067 0 : x0 = pixman_fixed_to_int (x - pixman_fixed_e);
1068 0 : y0 = pixman_fixed_to_int (y - pixman_fixed_e);
1069 :
1070 0 : if (repeat_mode == PIXMAN_REPEAT_NONE &&
1071 0 : (y0 < 0 || y0 >= height || x0 < 0 || x0 >= width))
1072 : {
1073 0 : buffer[i] = 0;
1074 : }
1075 : else
1076 : {
1077 0 : uint32_t mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
1078 :
1079 0 : if (repeat_mode != PIXMAN_REPEAT_NONE)
1080 : {
1081 : repeat (repeat_mode, &x0, width);
1082 : repeat (repeat_mode, &y0, height);
1083 : }
1084 :
1085 0 : row = (uint8_t *)bits->bits + bits->rowstride * 4 * y0;
1086 :
1087 0 : buffer[i] = convert_pixel (row, x0) | mask;
1088 : }
1089 :
1090 : next:
1091 0 : x += ux;
1092 0 : y += uy;
1093 : }
1094 : }
1095 :
1096 : static force_inline uint32_t
1097 0 : convert_a8r8g8b8 (const uint8_t *row, int x)
1098 : {
1099 0 : return *(((uint32_t *)row) + x);
1100 : }
1101 :
1102 : static force_inline uint32_t
1103 0 : convert_x8r8g8b8 (const uint8_t *row, int x)
1104 : {
1105 0 : return *(((uint32_t *)row) + x);
1106 : }
1107 :
1108 : static force_inline uint32_t
1109 0 : convert_a8 (const uint8_t *row, int x)
1110 : {
1111 0 : return *(row + x) << 24;
1112 : }
1113 :
1114 : static force_inline uint32_t
1115 0 : convert_r5g6b5 (const uint8_t *row, int x)
1116 : {
1117 0 : 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 0 : MAKE_FETCHERS (pad_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_PAD)
1173 0 : MAKE_FETCHERS (none_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_NONE)
1174 0 : MAKE_FETCHERS (reflect_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_REFLECT)
1175 0 : MAKE_FETCHERS (normal_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_NORMAL)
1176 0 : MAKE_FETCHERS (pad_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_PAD)
1177 0 : MAKE_FETCHERS (none_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_NONE)
1178 0 : MAKE_FETCHERS (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT)
1179 0 : MAKE_FETCHERS (normal_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_NORMAL)
1180 0 : MAKE_FETCHERS (pad_a8, a8, PIXMAN_REPEAT_PAD)
1181 0 : MAKE_FETCHERS (none_a8, a8, PIXMAN_REPEAT_NONE)
1182 0 : MAKE_FETCHERS (reflect_a8, a8, PIXMAN_REPEAT_REFLECT)
1183 0 : MAKE_FETCHERS (normal_a8, a8, PIXMAN_REPEAT_NORMAL)
1184 0 : MAKE_FETCHERS (pad_r5g6b5, r5g6b5, PIXMAN_REPEAT_PAD)
1185 0 : MAKE_FETCHERS (none_r5g6b5, r5g6b5, PIXMAN_REPEAT_NONE)
1186 0 : MAKE_FETCHERS (reflect_r5g6b5, r5g6b5, PIXMAN_REPEAT_REFLECT)
1187 0 : MAKE_FETCHERS (normal_r5g6b5, r5g6b5, PIXMAN_REPEAT_NORMAL)
1188 :
1189 : static void
1190 0 : 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 0 : color = bits->fetch_pixel_32 (bits, x, y);
1200 :
1201 0 : end = buffer + width;
1202 0 : while (buffer < end)
1203 0 : *(buffer++) = color;
1204 0 : }
1205 :
1206 : static void
1207 0 : 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 0 : argb_t *buffer = (argb_t *)b;
1215 : argb_t *end;
1216 :
1217 0 : color = bits->fetch_pixel_float (bits, x, y);
1218 :
1219 0 : end = buffer + width;
1220 0 : while (buffer < end)
1221 0 : *(buffer++) = color;
1222 0 : }
1223 :
1224 : static void
1225 0 : 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 0 : if (y < 0 || y >= image->height)
1235 : {
1236 0 : memset (buffer, 0, width * (wide? sizeof (argb_t) : 4));
1237 0 : return;
1238 : }
1239 :
1240 0 : if (x < 0)
1241 : {
1242 0 : w = MIN (width, -x);
1243 :
1244 0 : memset (buffer, 0, w * (wide ? sizeof (argb_t) : 4));
1245 :
1246 0 : width -= w;
1247 0 : buffer += w * (wide? 4 : 1);
1248 0 : x += w;
1249 : }
1250 :
1251 0 : if (x < image->width)
1252 : {
1253 0 : w = MIN (width, image->width - x);
1254 :
1255 0 : if (wide)
1256 0 : image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL);
1257 : else
1258 0 : image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
1259 :
1260 0 : width -= w;
1261 0 : buffer += w * (wide? 4 : 1);
1262 0 : x += w;
1263 : }
1264 :
1265 0 : memset (buffer, 0, width * (wide ? sizeof (argb_t) : 4));
1266 : }
1267 :
1268 : static void
1269 0 : 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 0 : while (y < 0)
1279 0 : y += image->height;
1280 :
1281 0 : while (y >= image->height)
1282 0 : y -= image->height;
1283 :
1284 0 : if (image->width == 1)
1285 : {
1286 0 : if (wide)
1287 0 : replicate_pixel_float (image, 0, y, width, buffer);
1288 : else
1289 0 : replicate_pixel_32 (image, 0, y, width, buffer);
1290 :
1291 0 : return;
1292 : }
1293 :
1294 0 : while (width)
1295 : {
1296 0 : while (x < 0)
1297 0 : x += image->width;
1298 0 : while (x >= image->width)
1299 0 : x -= image->width;
1300 :
1301 0 : w = MIN (width, image->width - x);
1302 :
1303 0 : if (wide)
1304 0 : image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL);
1305 : else
1306 0 : image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
1307 :
1308 0 : buffer += w * (wide? 4 : 1);
1309 0 : x += w;
1310 0 : width -= w;
1311 : }
1312 : }
1313 :
1314 : static uint32_t *
1315 0 : bits_image_fetch_untransformed_32 (pixman_iter_t * iter,
1316 : const uint32_t *mask)
1317 : {
1318 0 : pixman_image_t *image = iter->image;
1319 0 : int x = iter->x;
1320 0 : int y = iter->y;
1321 0 : int width = iter->width;
1322 0 : uint32_t * buffer = iter->buffer;
1323 :
1324 0 : if (image->common.repeat == PIXMAN_REPEAT_NONE)
1325 : {
1326 0 : bits_image_fetch_untransformed_repeat_none (
1327 : &image->bits, FALSE, x, y, width, buffer);
1328 : }
1329 : else
1330 : {
1331 0 : bits_image_fetch_untransformed_repeat_normal (
1332 : &image->bits, FALSE, x, y, width, buffer);
1333 : }
1334 :
1335 0 : iter->y++;
1336 0 : return buffer;
1337 : }
1338 :
1339 : static uint32_t *
1340 0 : bits_image_fetch_untransformed_float (pixman_iter_t * iter,
1341 : const uint32_t *mask)
1342 : {
1343 0 : pixman_image_t *image = iter->image;
1344 0 : int x = iter->x;
1345 0 : int y = iter->y;
1346 0 : int width = iter->width;
1347 0 : uint32_t * buffer = iter->buffer;
1348 :
1349 0 : if (image->common.repeat == PIXMAN_REPEAT_NONE)
1350 : {
1351 0 : bits_image_fetch_untransformed_repeat_none (
1352 : &image->bits, TRUE, x, y, width, buffer);
1353 : }
1354 : else
1355 : {
1356 0 : bits_image_fetch_untransformed_repeat_normal (
1357 : &image->bits, TRUE, x, y, width, buffer);
1358 : }
1359 :
1360 0 : iter->y++;
1361 0 : 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 44 : bits_image_property_changed (pixman_image_t *image)
1489 : {
1490 44 : _pixman_bits_image_setup_accessors (&image->bits);
1491 44 : }
1492 :
1493 : void
1494 0 : _pixman_bits_image_src_iter_init (pixman_image_t *image, pixman_iter_t *iter)
1495 : {
1496 0 : pixman_format_code_t format = image->common.extended_format_code;
1497 0 : uint32_t flags = image->common.flags;
1498 : const fetcher_info_t *info;
1499 :
1500 0 : for (info = fetcher_info; info->format != PIXMAN_null; ++info)
1501 : {
1502 0 : if ((info->format == format || info->format == PIXMAN_any) &&
1503 0 : (info->flags & flags) == info->flags)
1504 : {
1505 0 : if (iter->iter_flags & ITER_NARROW)
1506 : {
1507 0 : iter->get_scanline = info->get_scanline_32;
1508 : }
1509 : else
1510 : {
1511 0 : iter->data = info->get_scanline_32;
1512 0 : iter->get_scanline = info->get_scanline_float;
1513 : }
1514 0 : return;
1515 : }
1516 : }
1517 :
1518 : /* Just in case we somehow didn't find a scanline function */
1519 0 : iter->get_scanline = _pixman_iter_get_scanline_noop;
1520 : }
1521 :
1522 : static uint32_t *
1523 0 : dest_get_scanline_16 (pixman_iter_t *iter, const uint32_t *mask)
1524 : {
1525 0 : pixman_image_t *image = iter->image;
1526 0 : int x = iter->x;
1527 0 : int y = iter->y;
1528 0 : int width = iter->width;
1529 0 : uint32_t * buffer = iter->buffer;
1530 :
1531 0 : image->bits.fetch_scanline_16 (image, x, y, width, buffer, mask);
1532 :
1533 0 : return iter->buffer;
1534 : }
1535 :
1536 : static uint32_t *
1537 0 : dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
1538 : {
1539 0 : pixman_image_t *image = iter->image;
1540 0 : int x = iter->x;
1541 0 : int y = iter->y;
1542 0 : int width = iter->width;
1543 0 : uint32_t * buffer = iter->buffer;
1544 :
1545 0 : image->bits.fetch_scanline_32 (image, x, y, width, buffer, mask);
1546 0 : if (image->common.alpha_map)
1547 : {
1548 : uint32_t *alpha;
1549 :
1550 0 : if ((alpha = malloc (width * sizeof (uint32_t))))
1551 : {
1552 : int i;
1553 :
1554 0 : x -= image->common.alpha_origin_x;
1555 0 : y -= image->common.alpha_origin_y;
1556 :
1557 0 : image->common.alpha_map->fetch_scanline_32 (
1558 0 : (pixman_image_t *)image->common.alpha_map,
1559 : x, y, width, alpha, mask);
1560 :
1561 0 : for (i = 0; i < width; ++i)
1562 : {
1563 0 : buffer[i] &= ~0xff000000;
1564 0 : buffer[i] |= (alpha[i] & 0xff000000);
1565 : }
1566 :
1567 0 : free (alpha);
1568 : }
1569 : }
1570 :
1571 0 : return iter->buffer;
1572 : }
1573 :
1574 : static uint32_t *
1575 0 : dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
1576 : {
1577 0 : bits_image_t * image = &iter->image->bits;
1578 0 : int x = iter->x;
1579 0 : int y = iter->y;
1580 0 : int width = iter->width;
1581 0 : argb_t * buffer = (argb_t *)iter->buffer;
1582 :
1583 0 : image->fetch_scanline_float (
1584 : (pixman_image_t *)image, x, y, width, (uint32_t *)buffer, mask);
1585 0 : if (image->common.alpha_map)
1586 : {
1587 : argb_t *alpha;
1588 :
1589 0 : if ((alpha = malloc (width * sizeof (argb_t))))
1590 : {
1591 : int i;
1592 :
1593 0 : x -= image->common.alpha_origin_x;
1594 0 : y -= image->common.alpha_origin_y;
1595 :
1596 0 : image->common.alpha_map->fetch_scanline_float (
1597 0 : (pixman_image_t *)image->common.alpha_map,
1598 : x, y, width, (uint32_t *)alpha, mask);
1599 :
1600 0 : for (i = 0; i < width; ++i)
1601 0 : buffer[i].a = alpha[i].a;
1602 :
1603 0 : free (alpha);
1604 : }
1605 : }
1606 :
1607 0 : return iter->buffer;
1608 : }
1609 :
1610 : static void
1611 0 : dest_write_back_16 (pixman_iter_t *iter)
1612 : {
1613 0 : bits_image_t * image = &iter->image->bits;
1614 0 : int x = iter->x;
1615 0 : int y = iter->y;
1616 0 : int width = iter->width;
1617 0 : const uint32_t *buffer = iter->buffer;
1618 :
1619 0 : image->store_scanline_16 (image, x, y, width, buffer);
1620 :
1621 0 : iter->y++;
1622 0 : }
1623 :
1624 : static void
1625 0 : dest_write_back_narrow (pixman_iter_t *iter)
1626 : {
1627 0 : bits_image_t * image = &iter->image->bits;
1628 0 : int x = iter->x;
1629 0 : int y = iter->y;
1630 0 : int width = iter->width;
1631 0 : const uint32_t *buffer = iter->buffer;
1632 :
1633 0 : image->store_scanline_32 (image, x, y, width, buffer);
1634 :
1635 0 : if (image->common.alpha_map)
1636 : {
1637 0 : x -= image->common.alpha_origin_x;
1638 0 : y -= image->common.alpha_origin_y;
1639 :
1640 0 : image->common.alpha_map->store_scanline_32 (
1641 : image->common.alpha_map, x, y, width, buffer);
1642 : }
1643 :
1644 0 : iter->y++;
1645 0 : }
1646 :
1647 : static void
1648 0 : dest_write_back_wide (pixman_iter_t *iter)
1649 : {
1650 0 : bits_image_t * image = &iter->image->bits;
1651 0 : int x = iter->x;
1652 0 : int y = iter->y;
1653 0 : int width = iter->width;
1654 0 : const uint32_t *buffer = iter->buffer;
1655 :
1656 0 : image->store_scanline_float (image, x, y, width, buffer);
1657 :
1658 0 : if (image->common.alpha_map)
1659 : {
1660 0 : x -= image->common.alpha_origin_x;
1661 0 : y -= image->common.alpha_origin_y;
1662 :
1663 0 : image->common.alpha_map->store_scanline_float (
1664 : image->common.alpha_map, x, y, width, buffer);
1665 : }
1666 :
1667 0 : iter->y++;
1668 0 : }
1669 :
1670 : void
1671 0 : _pixman_bits_image_dest_iter_init (pixman_image_t *image, pixman_iter_t *iter)
1672 : {
1673 0 : if (iter->iter_flags & ITER_16)
1674 : {
1675 0 : if ((iter->iter_flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) ==
1676 : (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA))
1677 : {
1678 0 : iter->get_scanline = _pixman_iter_get_scanline_noop;
1679 : }
1680 : else
1681 : {
1682 0 : iter->get_scanline = dest_get_scanline_16;
1683 : }
1684 0 : iter->write_back = dest_write_back_16;
1685 : }
1686 0 : else if (iter->iter_flags & ITER_NARROW)
1687 : {
1688 0 : if ((iter->iter_flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) ==
1689 : (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA))
1690 : {
1691 0 : iter->get_scanline = _pixman_iter_get_scanline_noop;
1692 : }
1693 : else
1694 : {
1695 0 : iter->get_scanline = dest_get_scanline_narrow;
1696 : }
1697 :
1698 0 : iter->write_back = dest_write_back_narrow;
1699 : }
1700 : else
1701 : {
1702 0 : iter->get_scanline = dest_get_scanline_wide;
1703 0 : iter->write_back = dest_write_back_wide;
1704 : }
1705 0 : }
1706 :
1707 : static uint32_t *
1708 0 : 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 0 : bpp = PIXMAN_FORMAT_BPP (format);
1724 0 : if (_pixman_multiply_overflows_int (width, bpp))
1725 0 : return NULL;
1726 :
1727 0 : stride = width * bpp;
1728 0 : if (_pixman_addition_overflows_int (stride, 0x1f))
1729 0 : return NULL;
1730 :
1731 0 : stride += 0x1f;
1732 0 : stride >>= 5;
1733 :
1734 0 : stride *= sizeof (uint32_t);
1735 :
1736 0 : if (_pixman_multiply_overflows_size (height, stride))
1737 0 : return NULL;
1738 :
1739 0 : buf_size = (size_t)height * stride;
1740 :
1741 0 : if (rowstride_bytes)
1742 0 : *rowstride_bytes = stride;
1743 :
1744 0 : if (clear)
1745 0 : return calloc (buf_size, 1);
1746 : else
1747 0 : return malloc (buf_size);
1748 : }
1749 :
1750 : pixman_bool_t
1751 47 : _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 47 : uint32_t *free_me = NULL;
1760 :
1761 47 : if (!bits && width && height)
1762 : {
1763 : int rowstride_bytes;
1764 :
1765 0 : free_me = bits = create_bits (format, width, height, &rowstride_bytes, clear);
1766 :
1767 0 : if (!bits)
1768 0 : return FALSE;
1769 :
1770 0 : rowstride = rowstride_bytes / (int) sizeof (uint32_t);
1771 : }
1772 :
1773 47 : _pixman_image_init (image);
1774 :
1775 47 : image->type = BITS;
1776 47 : image->bits.format = format;
1777 47 : image->bits.width = width;
1778 47 : image->bits.height = height;
1779 47 : image->bits.bits = bits;
1780 47 : image->bits.free_me = free_me;
1781 47 : image->bits.read_func = NULL;
1782 47 : image->bits.write_func = NULL;
1783 47 : image->bits.rowstride = rowstride;
1784 47 : image->bits.indexed = NULL;
1785 :
1786 47 : image->common.property_changed = bits_image_property_changed;
1787 :
1788 47 : _pixman_image_reset_clip_region (image);
1789 :
1790 47 : return TRUE;
1791 : }
1792 :
1793 : static pixman_image_t *
1794 47 : 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 47 : return_val_if_fail (
1806 : bits == NULL || (rowstride_bytes % sizeof (uint32_t)) == 0, NULL);
1807 :
1808 47 : return_val_if_fail (PIXMAN_FORMAT_BPP (format) >= PIXMAN_FORMAT_DEPTH (format), NULL);
1809 :
1810 47 : image = _pixman_image_allocate ();
1811 :
1812 47 : if (!image)
1813 0 : return NULL;
1814 :
1815 47 : if (!_pixman_bits_image_init (image, format, width, height, bits,
1816 : rowstride_bytes / (int) sizeof (uint32_t),
1817 : clear))
1818 : {
1819 0 : free (image);
1820 0 : return NULL;
1821 : }
1822 :
1823 47 : 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 47 : 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 47 : 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 0 : 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 0 : return create_bits_image_internal (
1848 : format, width, height, bits, rowstride_bytes, FALSE);
1849 : }
|