• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *
_pixman_image_get_scanline_generic_float(pixman_iter_t * iter,const uint32_t * mask)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
fetch_pixel_no_alpha(bits_image_t * image,int x,int y,pixman_bool_t check_bounds)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
bits_image_fetch_pixel_nearest(bits_image_t * image,pixman_fixed_t x,pixman_fixed_t y,get_pixel_t get_pixel)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
bits_image_fetch_pixel_bilinear(bits_image_t * image,pixman_fixed_t x,pixman_fixed_t y,get_pixel_t get_pixel)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 *
bits_image_fetch_bilinear_no_repeat_8888(pixman_iter_t * iter,const uint32_t * mask)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
bits_image_fetch_pixel_convolution(bits_image_t * image,pixman_fixed_t x,pixman_fixed_t y,get_pixel_t get_pixel)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
bits_image_fetch_pixel_separable_convolution(bits_image_t * image,pixman_fixed_t x,pixman_fixed_t y,get_pixel_t get_pixel)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
bits_image_fetch_pixel_filtered(bits_image_t * image,pixman_fixed_t x,pixman_fixed_t y,get_pixel_t get_pixel)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 *
bits_image_fetch_affine_no_alpha(pixman_iter_t * iter,const uint32_t * mask)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
fetch_pixel_general(bits_image_t * image,int x,int y,pixman_bool_t check_bounds)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 *
bits_image_fetch_general(pixman_iter_t * iter,const uint32_t * mask)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
bits_image_fetch_separable_convolution_affine(pixman_image_t * image,int offset,int line,int width,uint32_t * buffer,const uint32_t * mask,convert_pixel_t convert_pixel,pixman_format_code_t format,pixman_repeat_t repeat_mode)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
bits_image_fetch_bilinear_affine(pixman_image_t * image,int offset,int line,int width,uint32_t * buffer,const uint32_t * mask,convert_pixel_t convert_pixel,pixman_format_code_t format,pixman_repeat_t repeat_mode)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
bits_image_fetch_nearest_affine(pixman_image_t * image,int offset,int line,int width,uint32_t * buffer,const uint32_t * mask,convert_pixel_t convert_pixel,pixman_format_code_t format,pixman_repeat_t repeat_mode)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
convert_a8r8g8b8(const uint8_t * row,int x)1097 convert_a8r8g8b8 (const uint8_t *row, int x)
1098 {
1099     return *(((uint32_t *)row) + x);
1100 }
1101 
1102 static force_inline uint32_t
convert_x8r8g8b8(const uint8_t * row,int x)1103 convert_x8r8g8b8 (const uint8_t *row, int x)
1104 {
1105     return *(((uint32_t *)row) + x);
1106 }
1107 
1108 static force_inline uint32_t
convert_a8(const uint8_t * row,int x)1109 convert_a8 (const uint8_t *row, int x)
1110 {
1111     return *(row + x) << 24;
1112 }
1113 
1114 static force_inline uint32_t
convert_r5g6b5(const uint8_t * row,int x)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 
MAKE_FETCHERS(pad_a8r8g8b8,a8r8g8b8,PIXMAN_REPEAT_PAD)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
replicate_pixel_float(bits_image_t * bits,int x,int y,int width,uint32_t * b)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
bits_image_fetch_untransformed_repeat_none(bits_image_t * image,pixman_bool_t wide,int x,int y,int width,uint32_t * buffer)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
bits_image_fetch_untransformed_repeat_normal(bits_image_t * image,pixman_bool_t wide,int x,int y,int width,uint32_t * buffer)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 *
bits_image_fetch_untransformed_32(pixman_iter_t * iter,const uint32_t * mask)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 *
bits_image_fetch_untransformed_float(pixman_iter_t * iter,const uint32_t * mask)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
bits_image_property_changed(pixman_image_t * image)1488 bits_image_property_changed (pixman_image_t *image)
1489 {
1490     _pixman_bits_image_setup_accessors (&image->bits);
1491 }
1492 
1493 void
_pixman_bits_image_src_iter_init(pixman_image_t * image,pixman_iter_t * iter)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 *
dest_get_scanline_narrow(pixman_iter_t * iter,const uint32_t * mask)1523 dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
1524 {
1525     pixman_image_t *image  = iter->image;
1526     int             x      = iter->x;
1527     int             y      = iter->y;
1528     int             width  = iter->width;
1529     uint32_t *	    buffer = iter->buffer;
1530 
1531     image->bits.fetch_scanline_32 (image, x, y, width, buffer, mask);
1532     if (image->common.alpha_map)
1533     {
1534 	uint32_t *alpha;
1535 
1536 	if ((alpha = malloc (width * sizeof (uint32_t))))
1537 	{
1538 	    int i;
1539 
1540 	    x -= image->common.alpha_origin_x;
1541 	    y -= image->common.alpha_origin_y;
1542 
1543 	    image->common.alpha_map->fetch_scanline_32 (
1544 		(pixman_image_t *)image->common.alpha_map,
1545 		x, y, width, alpha, mask);
1546 
1547 	    for (i = 0; i < width; ++i)
1548 	    {
1549 		buffer[i] &= ~0xff000000;
1550 		buffer[i] |= (alpha[i] & 0xff000000);
1551 	    }
1552 
1553 	    free (alpha);
1554 	}
1555     }
1556 
1557     return iter->buffer;
1558 }
1559 
1560 static uint32_t *
dest_get_scanline_wide(pixman_iter_t * iter,const uint32_t * mask)1561 dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
1562 {
1563     bits_image_t *  image  = &iter->image->bits;
1564     int             x      = iter->x;
1565     int             y      = iter->y;
1566     int             width  = iter->width;
1567     argb_t *	    buffer = (argb_t *)iter->buffer;
1568 
1569     image->fetch_scanline_float (
1570 	(pixman_image_t *)image, x, y, width, (uint32_t *)buffer, mask);
1571     if (image->common.alpha_map)
1572     {
1573 	argb_t *alpha;
1574 
1575 	if ((alpha = malloc (width * sizeof (argb_t))))
1576 	{
1577 	    int i;
1578 
1579 	    x -= image->common.alpha_origin_x;
1580 	    y -= image->common.alpha_origin_y;
1581 
1582 	    image->common.alpha_map->fetch_scanline_float (
1583 		(pixman_image_t *)image->common.alpha_map,
1584 		x, y, width, (uint32_t *)alpha, mask);
1585 
1586 	    for (i = 0; i < width; ++i)
1587 		buffer[i].a = alpha[i].a;
1588 
1589 	    free (alpha);
1590 	}
1591     }
1592 
1593     return iter->buffer;
1594 }
1595 
1596 static void
dest_write_back_narrow(pixman_iter_t * iter)1597 dest_write_back_narrow (pixman_iter_t *iter)
1598 {
1599     bits_image_t *  image  = &iter->image->bits;
1600     int             x      = iter->x;
1601     int             y      = iter->y;
1602     int             width  = iter->width;
1603     const uint32_t *buffer = iter->buffer;
1604 
1605     image->store_scanline_32 (image, x, y, width, buffer);
1606 
1607     if (image->common.alpha_map)
1608     {
1609 	x -= image->common.alpha_origin_x;
1610 	y -= image->common.alpha_origin_y;
1611 
1612 	image->common.alpha_map->store_scanline_32 (
1613 	    image->common.alpha_map, x, y, width, buffer);
1614     }
1615 
1616     iter->y++;
1617 }
1618 
1619 static void
dest_write_back_wide(pixman_iter_t * iter)1620 dest_write_back_wide (pixman_iter_t *iter)
1621 {
1622     bits_image_t *  image  = &iter->image->bits;
1623     int             x      = iter->x;
1624     int             y      = iter->y;
1625     int             width  = iter->width;
1626     const uint32_t *buffer = iter->buffer;
1627 
1628     image->store_scanline_float (image, x, y, width, buffer);
1629 
1630     if (image->common.alpha_map)
1631     {
1632 	x -= image->common.alpha_origin_x;
1633 	y -= image->common.alpha_origin_y;
1634 
1635 	image->common.alpha_map->store_scanline_float (
1636 	    image->common.alpha_map, x, y, width, buffer);
1637     }
1638 
1639     iter->y++;
1640 }
1641 
1642 void
_pixman_bits_image_dest_iter_init(pixman_image_t * image,pixman_iter_t * iter)1643 _pixman_bits_image_dest_iter_init (pixman_image_t *image, pixman_iter_t *iter)
1644 {
1645     if (iter->iter_flags & ITER_NARROW)
1646     {
1647 	if ((iter->iter_flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) ==
1648 	    (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA))
1649 	{
1650 	    iter->get_scanline = _pixman_iter_get_scanline_noop;
1651 	}
1652 	else
1653 	{
1654 	    iter->get_scanline = dest_get_scanline_narrow;
1655 	}
1656 
1657 	iter->write_back = dest_write_back_narrow;
1658     }
1659     else
1660     {
1661 	iter->get_scanline = dest_get_scanline_wide;
1662 	iter->write_back = dest_write_back_wide;
1663     }
1664 }
1665 
1666 static uint32_t *
create_bits(pixman_format_code_t format,int width,int height,int * rowstride_bytes,pixman_bool_t clear)1667 create_bits (pixman_format_code_t format,
1668              int                  width,
1669              int                  height,
1670              int *		  rowstride_bytes,
1671 	     pixman_bool_t	  clear)
1672 {
1673     int stride;
1674     size_t buf_size;
1675     int bpp;
1676 
1677     /* what follows is a long-winded way, avoiding any possibility of integer
1678      * overflows, of saying:
1679      * stride = ((width * bpp + 0x1f) >> 5) * sizeof (uint32_t);
1680      */
1681 
1682     bpp = PIXMAN_FORMAT_BPP (format);
1683     if (_pixman_multiply_overflows_int (width, bpp))
1684 	return NULL;
1685 
1686     stride = width * bpp;
1687     if (_pixman_addition_overflows_int (stride, 0x1f))
1688 	return NULL;
1689 
1690     stride += 0x1f;
1691     stride >>= 5;
1692 
1693     stride *= sizeof (uint32_t);
1694 
1695     if (_pixman_multiply_overflows_size (height, stride))
1696 	return NULL;
1697 
1698     buf_size = height * stride;
1699 
1700     if (rowstride_bytes)
1701 	*rowstride_bytes = stride;
1702 
1703     if (clear)
1704 	return calloc (buf_size, 1);
1705     else
1706 	return malloc (buf_size);
1707 }
1708 
1709 pixman_bool_t
_pixman_bits_image_init(pixman_image_t * image,pixman_format_code_t format,int width,int height,uint32_t * bits,int rowstride,pixman_bool_t clear)1710 _pixman_bits_image_init (pixman_image_t *     image,
1711                          pixman_format_code_t format,
1712                          int                  width,
1713                          int                  height,
1714                          uint32_t *           bits,
1715                          int                  rowstride,
1716 			 pixman_bool_t	      clear)
1717 {
1718     uint32_t *free_me = NULL;
1719 
1720     if (!bits && width && height)
1721     {
1722 	int rowstride_bytes;
1723 
1724 	free_me = bits = create_bits (format, width, height, &rowstride_bytes, clear);
1725 
1726 	if (!bits)
1727 	    return FALSE;
1728 
1729 	rowstride = rowstride_bytes / (int) sizeof (uint32_t);
1730     }
1731 
1732     _pixman_image_init (image);
1733 
1734     image->type = BITS;
1735     image->bits.format = format;
1736     image->bits.width = width;
1737     image->bits.height = height;
1738     image->bits.bits = bits;
1739     image->bits.free_me = free_me;
1740     image->bits.read_func = NULL;
1741     image->bits.write_func = NULL;
1742     image->bits.rowstride = rowstride;
1743     image->bits.indexed = NULL;
1744 
1745     image->common.property_changed = bits_image_property_changed;
1746 
1747     _pixman_image_reset_clip_region (image);
1748 
1749     return TRUE;
1750 }
1751 
1752 static pixman_image_t *
create_bits_image_internal(pixman_format_code_t format,int width,int height,uint32_t * bits,int rowstride_bytes,pixman_bool_t clear)1753 create_bits_image_internal (pixman_format_code_t format,
1754 			    int                  width,
1755 			    int                  height,
1756 			    uint32_t *           bits,
1757 			    int                  rowstride_bytes,
1758 			    pixman_bool_t	 clear)
1759 {
1760     pixman_image_t *image;
1761 
1762     /* must be a whole number of uint32_t's
1763      */
1764     return_val_if_fail (
1765 	bits == NULL || (rowstride_bytes % sizeof (uint32_t)) == 0, NULL);
1766 
1767     return_val_if_fail (PIXMAN_FORMAT_BPP (format) >= PIXMAN_FORMAT_DEPTH (format), NULL);
1768 
1769     image = _pixman_image_allocate ();
1770 
1771     if (!image)
1772 	return NULL;
1773 
1774     if (!_pixman_bits_image_init (image, format, width, height, bits,
1775 				  rowstride_bytes / (int) sizeof (uint32_t),
1776 				  clear))
1777     {
1778 	free (image);
1779 	return NULL;
1780     }
1781 
1782     return image;
1783 }
1784 
1785 /* If bits is NULL, a buffer will be allocated and initialized to 0 */
1786 PIXMAN_EXPORT pixman_image_t *
pixman_image_create_bits(pixman_format_code_t format,int width,int height,uint32_t * bits,int rowstride_bytes)1787 pixman_image_create_bits (pixman_format_code_t format,
1788                           int                  width,
1789                           int                  height,
1790                           uint32_t *           bits,
1791                           int                  rowstride_bytes)
1792 {
1793     return create_bits_image_internal (
1794 	format, width, height, bits, rowstride_bytes, TRUE);
1795 }
1796 
1797 
1798 /* If bits is NULL, a buffer will be allocated and _not_ initialized */
1799 PIXMAN_EXPORT pixman_image_t *
pixman_image_create_bits_no_clear(pixman_format_code_t format,int width,int height,uint32_t * bits,int rowstride_bytes)1800 pixman_image_create_bits_no_clear (pixman_format_code_t format,
1801 				   int                  width,
1802 				   int                  height,
1803 				   uint32_t *           bits,
1804 				   int                  rowstride_bytes)
1805 {
1806     return create_bits_image_internal (
1807 	format, width, height, bits, rowstride_bytes, FALSE);
1808 }
1809