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>
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.
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
35 #include "pixman-private.h"
36 #include "pixman-combine32.h"
37 #include "pixman-inlines.h"
40 * By default, just evaluate the image at 32bpp and expand. Individual image
41 * types can plug in a better scanline getter if they want to. For example
42 * we could produce smoother gradients by evaluating them at higher color
43 * depth, but that's a project for the future.
46 _pixman_image_get_scanline_generic_64 (pixman_image_t * image,
51 const uint32_t * mask)
53 uint32_t *mask8 = NULL;
55 /* Contract the mask image, if one exists, so that the 32-bit fetch
56 * function can use it.
60 mask8 = pixman_malloc_ab (width, sizeof(uint32_t));
64 pixman_contract (mask8, (uint64_t *)mask, width);
67 /* Fetch the source image into the first half of buffer. */
68 image->bits.get_scanline_32 (image, x, y, width, (uint32_t*)buffer, mask8);
70 /* Expand from 32bpp to 64bpp in place. */
71 pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, width);
78 static force_inline uint32_t
79 fetch_pixel_no_alpha (bits_image_t *image,
80 int x, int y, pixman_bool_t check_bounds)
83 (x < 0 || x >= image->width || y < 0 || y >= image->height))
88 return image->fetch_pixel_32 (image, x, y);
91 typedef uint32_t (* get_pixel_t) (bits_image_t *image,
92 int x, int y, pixman_bool_t check_bounds);
94 static force_inline uint32_t
95 bits_image_fetch_pixel_nearest (bits_image_t *image,
98 get_pixel_t get_pixel)
100 int x0 = pixman_fixed_to_int (x - pixman_fixed_e);
101 int y0 = pixman_fixed_to_int (y - pixman_fixed_e);
103 if (image->common.repeat != PIXMAN_REPEAT_NONE)
105 repeat (image->common.repeat, &x0, image->width);
106 repeat (image->common.repeat, &y0, image->height);
108 return get_pixel (image, x0, y0, FALSE);
112 return get_pixel (image, x0, y0, TRUE);
116 static force_inline uint32_t
117 bits_image_fetch_pixel_bilinear (bits_image_t *image,
120 get_pixel_t get_pixel)
122 pixman_repeat_t repeat_mode = image->common.repeat;
123 int width = image->width;
124 int height = image->height;
126 uint32_t tl, tr, bl, br;
127 int32_t distx, disty;
129 x1 = x - pixman_fixed_1 / 2;
130 y1 = y - pixman_fixed_1 / 2;
132 distx = (x1 >> 8) & 0xff;
133 disty = (y1 >> 8) & 0xff;
135 x1 = pixman_fixed_to_int (x1);
136 y1 = pixman_fixed_to_int (y1);
140 if (repeat_mode != PIXMAN_REPEAT_NONE)
142 repeat (repeat_mode, &x1, width);
143 repeat (repeat_mode, &y1, height);
144 repeat (repeat_mode, &x2, width);
145 repeat (repeat_mode, &y2, height);
147 tl = get_pixel (image, x1, y1, FALSE);
148 bl = get_pixel (image, x1, y2, FALSE);
149 tr = get_pixel (image, x2, y1, FALSE);
150 br = get_pixel (image, x2, y2, FALSE);
154 tl = get_pixel (image, x1, y1, TRUE);
155 tr = get_pixel (image, x2, y1, TRUE);
156 bl = get_pixel (image, x1, y2, TRUE);
157 br = get_pixel (image, x2, y2, TRUE);
160 return bilinear_interpolation (tl, tr, bl, br, distx, disty);
164 bits_image_fetch_bilinear_no_repeat_8888 (pixman_image_t * ima,
169 const uint32_t * mask)
171 bits_image_t *bits = &ima->bits;
172 pixman_fixed_t x_top, x_bottom, x;
173 pixman_fixed_t ux_top, ux_bottom, ux;
175 uint32_t top_mask, bottom_mask;
177 uint32_t *bottom_row;
179 uint32_t zero[2] = { 0, 0 };
186 /* reference point is the center of the pixel */
187 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
188 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
189 v.vector[2] = pixman_fixed_1;
191 if (!pixman_transform_point_3d (bits->common.transform, &v))
194 ux = ux_top = ux_bottom = bits->common.transform->matrix[0][0];
195 x = x_top = x_bottom = v.vector[0] - pixman_fixed_1/2;
197 y = v.vector[1] - pixman_fixed_1/2;
198 disty = (y >> 8) & 0xff;
200 /* Load the pointers to the first and second lines from the source
201 * image that bilinear code must read.
203 * The main trick in this code is about the check if any line are
204 * outside of the image;
206 * When I realize that a line (any one) is outside, I change
207 * the pointer to a dummy area with zeros. Once I change this, I
208 * must be sure the pointer will not change, so I set the
209 * variables to each pointer increments inside the loop.
211 y1 = pixman_fixed_to_int (y);
214 if (y1 < 0 || y1 >= bits->height)
222 top_row = bits->bits + y1 * bits->rowstride;
227 if (y2 < 0 || y2 >= bits->height)
235 bottom_row = bits->bits + y2 * bits->rowstride;
240 /* Instead of checking whether the operation uses the mast in
241 * each loop iteration, verify this only once and prepare the
242 * variables to make the code smaller inside the loop.
251 /* If have a mask, prepare the variables to check it */
255 /* If both are zero, then the whole thing is zero */
256 if (top_row == zero && bottom_row == zero)
258 memset (buffer, 0, width * sizeof (uint32_t));
261 else if (bits->format == PIXMAN_x8r8g8b8)
266 bottom_mask = 0xff000000;
268 else if (bottom_row == zero)
270 top_mask = 0xff000000;
275 top_mask = 0xff000000;
276 bottom_mask = 0xff000000;
285 end = buffer + width;
287 /* Zero fill to the left of the image */
288 while (buffer < end && x < pixman_fixed_minus_1)
293 x_bottom += ux_bottom;
299 while (buffer < end && x < 0)
304 tr = top_row[pixman_fixed_to_int (x_top) + 1] | top_mask;
305 br = bottom_row[pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;
307 distx = (x >> 8) & 0xff;
309 *buffer++ = bilinear_interpolation (0, tr, 0, br, distx, disty);
313 x_bottom += ux_bottom;
318 w = pixman_int_to_fixed (bits->width - 1);
320 while (buffer < end && x < w)
324 uint32_t tl, tr, bl, br;
327 tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
328 tr = top_row [pixman_fixed_to_int (x_top) + 1] | top_mask;
329 bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
330 br = bottom_row [pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;
332 distx = (x >> 8) & 0xff;
334 *buffer = bilinear_interpolation (tl, tr, bl, br, distx, disty);
340 x_bottom += ux_bottom;
345 w = pixman_int_to_fixed (bits->width);
346 while (buffer < end && x < w)
353 tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
354 bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
356 distx = (x >> 8) & 0xff;
358 *buffer = bilinear_interpolation (tl, 0, bl, 0, distx, disty);
364 x_bottom += ux_bottom;
368 /* Zero fill to the left of the image */
373 static force_inline uint32_t
374 bits_image_fetch_pixel_convolution (bits_image_t *image,
377 get_pixel_t get_pixel)
379 pixman_fixed_t *params = image->common.filter_params;
380 int x_off = (params[0] - pixman_fixed_1) >> 1;
381 int y_off = (params[1] - pixman_fixed_1) >> 1;
382 int32_t cwidth = pixman_fixed_to_int (params[0]);
383 int32_t cheight = pixman_fixed_to_int (params[1]);
384 int32_t srtot, sgtot, sbtot, satot;
385 int32_t i, j, x1, x2, y1, y2;
386 pixman_repeat_t repeat_mode = image->common.repeat;
387 int width = image->width;
388 int height = image->height;
392 x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
393 y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
397 srtot = sgtot = sbtot = satot = 0;
399 for (i = y1; i < y2; ++i)
401 for (j = x1; j < x2; ++j)
406 pixman_fixed_t f = *params;
412 if (repeat_mode != PIXMAN_REPEAT_NONE)
414 repeat (repeat_mode, &rx, width);
415 repeat (repeat_mode, &ry, height);
417 pixel = get_pixel (image, rx, ry, FALSE);
421 pixel = get_pixel (image, rx, ry, TRUE);
424 srtot += RED_8 (pixel) * f;
425 sgtot += GREEN_8 (pixel) * f;
426 sbtot += BLUE_8 (pixel) * f;
427 satot += ALPHA_8 (pixel) * f;
439 satot = CLIP (satot, 0, 0xff);
440 srtot = CLIP (srtot, 0, 0xff);
441 sgtot = CLIP (sgtot, 0, 0xff);
442 sbtot = CLIP (sbtot, 0, 0xff);
444 return ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot));
447 static force_inline uint32_t
448 bits_image_fetch_pixel_filtered (bits_image_t *image,
451 get_pixel_t get_pixel)
453 switch (image->common.filter)
455 case PIXMAN_FILTER_NEAREST:
456 case PIXMAN_FILTER_FAST:
457 return bits_image_fetch_pixel_nearest (image, x, y, get_pixel);
460 case PIXMAN_FILTER_BILINEAR:
461 case PIXMAN_FILTER_GOOD:
462 case PIXMAN_FILTER_BEST:
463 return bits_image_fetch_pixel_bilinear (image, x, y, get_pixel);
466 case PIXMAN_FILTER_CONVOLUTION:
467 return bits_image_fetch_pixel_convolution (image, x, y, get_pixel);
478 bits_image_fetch_affine_no_alpha (pixman_image_t * image,
483 const uint32_t * mask)
486 pixman_fixed_t ux, uy;
490 /* reference point is the center of the pixel */
491 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
492 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
493 v.vector[2] = pixman_fixed_1;
495 if (image->common.transform)
497 if (!pixman_transform_point_3d (image->common.transform, &v))
500 ux = image->common.transform->matrix[0][0];
501 uy = image->common.transform->matrix[1][0];
512 for (i = 0; i < width; ++i)
514 if (!mask || mask[i])
516 buffer[i] = bits_image_fetch_pixel_filtered (
517 &image->bits, x, y, fetch_pixel_no_alpha);
525 /* General fetcher */
526 static force_inline uint32_t
527 fetch_pixel_general (bits_image_t *image, int x, int y, pixman_bool_t check_bounds)
532 (x < 0 || x >= image->width || y < 0 || y >= image->height))
537 pixel = image->fetch_pixel_32 (image, x, y);
539 if (image->common.alpha_map)
543 x -= image->common.alpha_origin_x;
544 y -= image->common.alpha_origin_y;
546 if (x < 0 || x >= image->common.alpha_map->width ||
547 y < 0 || y >= image->common.alpha_map->height)
553 pixel_a = image->common.alpha_map->fetch_pixel_32 (
554 image->common.alpha_map, x, y);
556 pixel_a = ALPHA_8 (pixel_a);
560 pixel |= (pixel_a << 24);
567 bits_image_fetch_general (pixman_image_t * image,
572 const uint32_t * mask)
574 pixman_fixed_t x, y, w;
575 pixman_fixed_t ux, uy, uw;
579 /* reference point is the center of the pixel */
580 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
581 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
582 v.vector[2] = pixman_fixed_1;
584 if (image->common.transform)
586 if (!pixman_transform_point_3d (image->common.transform, &v))
589 ux = image->common.transform->matrix[0][0];
590 uy = image->common.transform->matrix[1][0];
591 uw = image->common.transform->matrix[2][0];
604 for (i = 0; i < width; ++i)
606 pixman_fixed_t x0, y0;
608 if (!mask || mask[i])
612 x0 = ((pixman_fixed_48_16_t)x << 16) / w;
613 y0 = ((pixman_fixed_48_16_t)y << 16) / w;
621 buffer[i] = bits_image_fetch_pixel_filtered (
622 &image->bits, x0, y0, fetch_pixel_general);
631 static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
633 typedef uint32_t (* convert_pixel_t) (const uint8_t *row, int x);
635 static force_inline void
636 bits_image_fetch_bilinear_affine (pixman_image_t * image,
641 const uint32_t * mask,
643 convert_pixel_t convert_pixel,
644 pixman_format_code_t format,
645 pixman_repeat_t repeat_mode)
648 pixman_fixed_t ux, uy;
650 bits_image_t *bits = &image->bits;
653 /* reference point is the center of the pixel */
654 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
655 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
656 v.vector[2] = pixman_fixed_1;
658 if (!pixman_transform_point_3d (image->common.transform, &v))
661 ux = image->common.transform->matrix[0][0];
662 uy = image->common.transform->matrix[1][0];
667 for (i = 0; i < width; ++i)
670 uint32_t tl, tr, bl, br;
671 int32_t distx, disty;
672 int width = image->bits.width;
673 int height = image->bits.height;
677 if (mask && !mask[i])
680 x1 = x - pixman_fixed_1 / 2;
681 y1 = y - pixman_fixed_1 / 2;
683 distx = (x1 >> 8) & 0xff;
684 disty = (y1 >> 8) & 0xff;
686 y1 = pixman_fixed_to_int (y1);
688 x1 = pixman_fixed_to_int (x1);
691 if (repeat_mode != PIXMAN_REPEAT_NONE)
695 mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
697 repeat (repeat_mode, &x1, width);
698 repeat (repeat_mode, &y1, height);
699 repeat (repeat_mode, &x2, width);
700 repeat (repeat_mode, &y2, height);
702 row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
703 row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
705 tl = convert_pixel (row1, x1) | mask;
706 tr = convert_pixel (row1, x2) | mask;
707 bl = convert_pixel (row2, x1) | mask;
708 br = convert_pixel (row2, x2) | mask;
712 uint32_t mask1, mask2;
715 /* Note: PIXMAN_FORMAT_BPP() returns an unsigned value,
716 * which means if you use it in expressions, those
717 * expressions become unsigned themselves. Since
718 * the variables below can be negative in some cases,
719 * that will lead to crashes on 64 bit architectures.
721 * So this line makes sure bpp is signed
723 bpp = PIXMAN_FORMAT_BPP (format);
725 if (x1 >= width || x2 < 0 || y1 >= height || y2 < 0)
738 row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
739 row1 += bpp / 8 * x1;
741 mask1 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
744 if (y1 == height - 1)
751 row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
752 row2 += bpp / 8 * x1;
754 mask2 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
764 tl = convert_pixel (row1, 0) | mask1;
765 bl = convert_pixel (row2, 0) | mask2;
775 tr = convert_pixel (row1, 1) | mask1;
776 br = convert_pixel (row2, 1) | mask2;
780 buffer[i] = bilinear_interpolation (
781 tl, tr, bl, br, distx, disty);
789 static force_inline void
790 bits_image_fetch_nearest_affine (pixman_image_t * image,
795 const uint32_t * mask,
797 convert_pixel_t convert_pixel,
798 pixman_format_code_t format,
799 pixman_repeat_t repeat_mode)
802 pixman_fixed_t ux, uy;
804 bits_image_t *bits = &image->bits;
807 /* reference point is the center of the pixel */
808 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
809 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
810 v.vector[2] = pixman_fixed_1;
812 if (!pixman_transform_point_3d (image->common.transform, &v))
815 ux = image->common.transform->matrix[0][0];
816 uy = image->common.transform->matrix[1][0];
821 for (i = 0; i < width; ++i)
823 int width, height, x0, y0;
826 if (mask && !mask[i])
829 width = image->bits.width;
830 height = image->bits.height;
831 x0 = pixman_fixed_to_int (x - pixman_fixed_e);
832 y0 = pixman_fixed_to_int (y - pixman_fixed_e);
834 if (repeat_mode == PIXMAN_REPEAT_NONE &&
835 (y0 < 0 || y0 >= height || x0 < 0 || x0 >= width))
841 uint32_t mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
843 if (repeat_mode != PIXMAN_REPEAT_NONE)
845 repeat (repeat_mode, &x0, width);
846 repeat (repeat_mode, &y0, height);
849 row = (uint8_t *)bits->bits + bits->rowstride * 4 * y0;
851 buffer[i] = convert_pixel (row, x0) | mask;
860 static force_inline uint32_t
861 convert_a8r8g8b8 (const uint8_t *row, int x)
863 return *(((uint32_t *)row) + x);
866 static force_inline uint32_t
867 convert_x8r8g8b8 (const uint8_t *row, int x)
869 return *(((uint32_t *)row) + x);
872 static force_inline uint32_t
873 convert_a8 (const uint8_t *row, int x)
875 return *(row + x) << 24;
878 static force_inline uint32_t
879 convert_r5g6b5 (const uint8_t *row, int x)
881 return CONVERT_0565_TO_0888 (*((uint16_t *)row + x));
884 #define MAKE_BILINEAR_FETCHER(name, format, repeat_mode) \
886 bits_image_fetch_bilinear_affine_ ## name (pixman_image_t *image, \
891 const uint32_t * mask) \
893 bits_image_fetch_bilinear_affine (image, offset, line, \
894 width, buffer, mask, \
895 convert_ ## format, \
900 #define MAKE_NEAREST_FETCHER(name, format, repeat_mode) \
902 bits_image_fetch_nearest_affine_ ## name (pixman_image_t *image, \
907 const uint32_t * mask) \
909 bits_image_fetch_nearest_affine (image, offset, line, \
910 width, buffer, mask, \
911 convert_ ## format, \
916 #define MAKE_FETCHERS(name, format, repeat_mode) \
917 MAKE_NEAREST_FETCHER (name, format, repeat_mode) \
918 MAKE_BILINEAR_FETCHER (name, format, repeat_mode)
920 MAKE_FETCHERS (pad_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_PAD)
921 MAKE_FETCHERS (none_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_NONE)
922 MAKE_FETCHERS (reflect_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_REFLECT)
923 MAKE_FETCHERS (normal_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_NORMAL)
924 MAKE_FETCHERS (pad_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_PAD)
925 MAKE_FETCHERS (none_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_NONE)
926 MAKE_FETCHERS (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT)
927 MAKE_FETCHERS (normal_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_NORMAL)
928 MAKE_FETCHERS (pad_a8, a8, PIXMAN_REPEAT_PAD)
929 MAKE_FETCHERS (none_a8, a8, PIXMAN_REPEAT_NONE)
930 MAKE_FETCHERS (reflect_a8, a8, PIXMAN_REPEAT_REFLECT)
931 MAKE_FETCHERS (normal_a8, a8, PIXMAN_REPEAT_NORMAL)
932 MAKE_FETCHERS (pad_r5g6b5, r5g6b5, PIXMAN_REPEAT_PAD)
933 MAKE_FETCHERS (none_r5g6b5, r5g6b5, PIXMAN_REPEAT_NONE)
934 MAKE_FETCHERS (reflect_r5g6b5, r5g6b5, PIXMAN_REPEAT_REFLECT)
935 MAKE_FETCHERS (normal_r5g6b5, r5g6b5, PIXMAN_REPEAT_NORMAL)
938 replicate_pixel_32 (bits_image_t * bits,
947 color = bits->fetch_pixel_32 (bits, x, y);
949 end = buffer + width;
955 replicate_pixel_64 (bits_image_t * bits,
962 uint64_t *buffer = (uint64_t *)b;
965 color = bits->fetch_pixel_64 (bits, x, y);
967 end = buffer + width;
973 bits_image_fetch_solid_32 (pixman_image_t * image,
978 const uint32_t * mask)
980 replicate_pixel_32 (&image->bits, 0, 0, width, buffer);
984 bits_image_fetch_solid_64 (pixman_image_t * image,
989 const uint32_t * unused)
991 replicate_pixel_64 (&image->bits, 0, 0, width, b);
995 bits_image_fetch_untransformed_repeat_none (bits_image_t *image,
1004 if (y < 0 || y >= image->height)
1006 memset (buffer, 0, width * (wide? 8 : 4));
1012 w = MIN (width, -x);
1014 memset (buffer, 0, w * (wide ? 8 : 4));
1017 buffer += w * (wide? 2 : 1);
1021 if (x < image->width)
1023 w = MIN (width, image->width - x);
1026 image->fetch_scanline_64 ((pixman_image_t *)image, x, y, w, buffer, NULL);
1028 image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
1031 buffer += w * (wide? 2 : 1);
1035 memset (buffer, 0, width * (wide ? 8 : 4));
1039 bits_image_fetch_untransformed_repeat_normal (bits_image_t *image,
1051 while (y >= image->height)
1054 if (image->width == 1)
1057 replicate_pixel_64 (image, 0, y, width, buffer);
1059 replicate_pixel_32 (image, 0, y, width, buffer);
1068 while (x >= image->width)
1071 w = MIN (width, image->width - x);
1074 image->fetch_scanline_64 ((pixman_image_t *)image, x, y, w, buffer, NULL);
1076 image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
1078 buffer += w * (wide? 2 : 1);
1085 bits_image_fetch_untransformed_32 (pixman_image_t * image,
1090 const uint32_t * mask)
1092 if (image->common.repeat == PIXMAN_REPEAT_NONE)
1094 bits_image_fetch_untransformed_repeat_none (
1095 &image->bits, FALSE, x, y, width, buffer);
1099 bits_image_fetch_untransformed_repeat_normal (
1100 &image->bits, FALSE, x, y, width, buffer);
1105 bits_image_fetch_untransformed_64 (pixman_image_t * image,
1110 const uint32_t * unused)
1112 if (image->common.repeat == PIXMAN_REPEAT_NONE)
1114 bits_image_fetch_untransformed_repeat_none (
1115 &image->bits, TRUE, x, y, width, buffer);
1119 bits_image_fetch_untransformed_repeat_normal (
1120 &image->bits, TRUE, x, y, width, buffer);
1126 pixman_format_code_t format;
1128 fetch_scanline_t fetch_32;
1129 fetch_scanline_t fetch_64;
1132 static const fetcher_info_t fetcher_info[] =
1135 FAST_PATH_NO_ALPHA_MAP,
1136 bits_image_fetch_solid_32,
1137 bits_image_fetch_solid_64
1141 (FAST_PATH_NO_ALPHA_MAP |
1142 FAST_PATH_ID_TRANSFORM |
1143 FAST_PATH_NO_CONVOLUTION_FILTER |
1144 FAST_PATH_NO_PAD_REPEAT |
1145 FAST_PATH_NO_REFLECT_REPEAT),
1146 bits_image_fetch_untransformed_32,
1147 bits_image_fetch_untransformed_64
1150 #define FAST_BILINEAR_FLAGS \
1151 (FAST_PATH_NO_ALPHA_MAP | \
1152 FAST_PATH_NO_ACCESSORS | \
1153 FAST_PATH_HAS_TRANSFORM | \
1154 FAST_PATH_AFFINE_TRANSFORM | \
1155 FAST_PATH_X_UNIT_POSITIVE | \
1156 FAST_PATH_Y_UNIT_ZERO | \
1157 FAST_PATH_NONE_REPEAT | \
1158 FAST_PATH_BILINEAR_FILTER)
1161 FAST_BILINEAR_FLAGS,
1162 bits_image_fetch_bilinear_no_repeat_8888,
1163 _pixman_image_get_scanline_generic_64
1167 FAST_BILINEAR_FLAGS,
1168 bits_image_fetch_bilinear_no_repeat_8888,
1169 _pixman_image_get_scanline_generic_64
1172 #define GENERAL_BILINEAR_FLAGS \
1173 (FAST_PATH_NO_ALPHA_MAP | \
1174 FAST_PATH_NO_ACCESSORS | \
1175 FAST_PATH_HAS_TRANSFORM | \
1176 FAST_PATH_AFFINE_TRANSFORM | \
1177 FAST_PATH_BILINEAR_FILTER)
1179 #define GENERAL_NEAREST_FLAGS \
1180 (FAST_PATH_NO_ALPHA_MAP | \
1181 FAST_PATH_NO_ACCESSORS | \
1182 FAST_PATH_HAS_TRANSFORM | \
1183 FAST_PATH_AFFINE_TRANSFORM | \
1184 FAST_PATH_NEAREST_FILTER)
1186 #define BILINEAR_AFFINE_FAST_PATH(name, format, repeat) \
1187 { PIXMAN_ ## format, \
1188 GENERAL_BILINEAR_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \
1189 bits_image_fetch_bilinear_affine_ ## name, \
1190 _pixman_image_get_scanline_generic_64 \
1193 #define NEAREST_AFFINE_FAST_PATH(name, format, repeat) \
1194 { PIXMAN_ ## format, \
1195 GENERAL_NEAREST_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \
1196 bits_image_fetch_nearest_affine_ ## name, \
1197 _pixman_image_get_scanline_generic_64 \
1200 #define AFFINE_FAST_PATHS(name, format, repeat) \
1201 BILINEAR_AFFINE_FAST_PATH(name, format, repeat) \
1202 NEAREST_AFFINE_FAST_PATH(name, format, repeat)
1204 AFFINE_FAST_PATHS (pad_a8r8g8b8, a8r8g8b8, PAD)
1205 AFFINE_FAST_PATHS (none_a8r8g8b8, a8r8g8b8, NONE)
1206 AFFINE_FAST_PATHS (reflect_a8r8g8b8, a8r8g8b8, REFLECT)
1207 AFFINE_FAST_PATHS (normal_a8r8g8b8, a8r8g8b8, NORMAL)
1208 AFFINE_FAST_PATHS (pad_x8r8g8b8, x8r8g8b8, PAD)
1209 AFFINE_FAST_PATHS (none_x8r8g8b8, x8r8g8b8, NONE)
1210 AFFINE_FAST_PATHS (reflect_x8r8g8b8, x8r8g8b8, REFLECT)
1211 AFFINE_FAST_PATHS (normal_x8r8g8b8, x8r8g8b8, NORMAL)
1212 AFFINE_FAST_PATHS (pad_a8, a8, PAD)
1213 AFFINE_FAST_PATHS (none_a8, a8, NONE)
1214 AFFINE_FAST_PATHS (reflect_a8, a8, REFLECT)
1215 AFFINE_FAST_PATHS (normal_a8, a8, NORMAL)
1216 AFFINE_FAST_PATHS (pad_r5g6b5, r5g6b5, PAD)
1217 AFFINE_FAST_PATHS (none_r5g6b5, r5g6b5, NONE)
1218 AFFINE_FAST_PATHS (reflect_r5g6b5, r5g6b5, REFLECT)
1219 AFFINE_FAST_PATHS (normal_r5g6b5, r5g6b5, NORMAL)
1221 /* Affine, no alpha */
1223 (FAST_PATH_NO_ALPHA_MAP | FAST_PATH_HAS_TRANSFORM | FAST_PATH_AFFINE_TRANSFORM),
1224 bits_image_fetch_affine_no_alpha,
1225 _pixman_image_get_scanline_generic_64
1229 { PIXMAN_any, 0, bits_image_fetch_general, _pixman_image_get_scanline_generic_64 },
1235 bits_image_property_changed (pixman_image_t *image)
1237 uint32_t flags = image->common.flags;
1238 pixman_format_code_t format = image->common.extended_format_code;
1239 const fetcher_info_t *info;
1241 _pixman_bits_image_setup_accessors (&image->bits);
1243 info = fetcher_info;
1244 while (info->format != PIXMAN_null)
1246 if ((info->format == format || info->format == PIXMAN_any) &&
1247 (info->flags & flags) == info->flags)
1249 image->bits.get_scanline_32 = info->fetch_32;
1250 image->bits.get_scanline_64 = info->fetch_64;
1259 src_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
1261 iter->image->bits.get_scanline_32 (
1262 iter->image, iter->x, iter->y++, iter->width, iter->buffer, mask);
1264 return iter->buffer;
1268 src_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
1270 iter->image->bits.get_scanline_64 (
1271 iter->image, iter->x, iter->y++, iter->width, iter->buffer, mask);
1273 return iter->buffer;
1277 _pixman_bits_image_src_iter_init (pixman_image_t *image, pixman_iter_t *iter)
1279 if (iter->flags & ITER_NARROW)
1280 iter->get_scanline = src_get_scanline_narrow;
1282 iter->get_scanline = src_get_scanline_wide;
1286 dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
1288 pixman_image_t *image = iter->image;
1291 int width = iter->width;
1292 uint32_t * buffer = iter->buffer;
1294 image->bits.fetch_scanline_32 (image, x, y, width, buffer, mask);
1295 if (image->common.alpha_map)
1297 x -= image->common.alpha_origin_x;
1298 y -= image->common.alpha_origin_y;
1300 image->common.alpha_map->fetch_scanline_32 (
1301 (pixman_image_t *)image->common.alpha_map,
1302 x, y, width, buffer, mask);
1305 return iter->buffer;
1309 dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
1311 bits_image_t * image = &iter->image->bits;
1314 int width = iter->width;
1315 uint32_t * buffer = iter->buffer;
1317 image->fetch_scanline_64 (
1318 (pixman_image_t *)image, x, y, width, buffer, mask);
1319 if (image->common.alpha_map)
1321 x -= image->common.alpha_origin_x;
1322 y -= image->common.alpha_origin_y;
1324 image->common.alpha_map->fetch_scanline_64 (
1325 (pixman_image_t *)image->common.alpha_map, x, y, width, buffer, mask);
1328 return iter->buffer;
1332 dest_write_back_narrow (pixman_iter_t *iter)
1334 bits_image_t * image = &iter->image->bits;
1337 int width = iter->width;
1338 const uint32_t *buffer = iter->buffer;
1340 image->store_scanline_32 (image, x, y, width, buffer);
1342 if (image->common.alpha_map)
1344 x -= image->common.alpha_origin_x;
1345 y -= image->common.alpha_origin_y;
1347 image->common.alpha_map->store_scanline_32 (
1348 image->common.alpha_map, x, y, width, buffer);
1355 dest_write_back_wide (pixman_iter_t *iter)
1357 bits_image_t * image = &iter->image->bits;
1360 int width = iter->width;
1361 const uint32_t *buffer = iter->buffer;
1363 image->store_scanline_64 (image, x, y, width, buffer);
1365 if (image->common.alpha_map)
1367 x -= image->common.alpha_origin_x;
1368 y -= image->common.alpha_origin_y;
1370 image->common.alpha_map->store_scanline_64 (
1371 image->common.alpha_map, x, y, width, buffer);
1378 _pixman_bits_image_dest_iter_init (pixman_image_t *image, pixman_iter_t *iter)
1380 if (iter->flags & ITER_NARROW)
1382 if ((iter->flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) ==
1383 (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA))
1385 iter->get_scanline = _pixman_iter_get_scanline_noop;
1389 iter->get_scanline = dest_get_scanline_narrow;
1392 iter->write_back = dest_write_back_narrow;
1396 iter->get_scanline = dest_get_scanline_wide;
1397 iter->write_back = dest_write_back_wide;
1402 create_bits (pixman_format_code_t format,
1405 int * rowstride_bytes)
1411 /* what follows is a long-winded way, avoiding any possibility of integer
1412 * overflows, of saying:
1413 * stride = ((width * bpp + 0x1f) >> 5) * sizeof (uint32_t);
1416 bpp = PIXMAN_FORMAT_BPP (format);
1417 if (_pixman_multiply_overflows_int (width, bpp))
1420 stride = width * bpp;
1421 if (_pixman_addition_overflows_int (stride, 0x1f))
1427 stride *= sizeof (uint32_t);
1429 if (_pixman_multiply_overflows_size (height, stride))
1432 buf_size = height * stride;
1434 if (rowstride_bytes)
1435 *rowstride_bytes = stride;
1437 return calloc (buf_size, 1);
1440 PIXMAN_EXPORT pixman_image_t *
1441 pixman_image_create_bits (pixman_format_code_t format,
1445 int rowstride_bytes)
1447 pixman_image_t *image;
1448 uint32_t *free_me = NULL;
1450 /* must be a whole number of uint32_t's
1452 return_val_if_fail (
1453 bits == NULL || (rowstride_bytes % sizeof (uint32_t)) == 0, NULL);
1455 return_val_if_fail (PIXMAN_FORMAT_BPP (format) >= PIXMAN_FORMAT_DEPTH (format), NULL);
1457 if (!bits && width && height)
1459 free_me = bits = create_bits (format, width, height, &rowstride_bytes);
1464 image = _pixman_image_allocate ();
1475 image->bits.format = format;
1476 image->bits.width = width;
1477 image->bits.height = height;
1478 image->bits.bits = bits;
1479 image->bits.free_me = free_me;
1480 image->bits.read_func = NULL;
1481 image->bits.write_func = NULL;
1483 /* The rowstride is stored in number of uint32_t */
1484 image->bits.rowstride = rowstride_bytes / (int) sizeof (uint32_t);
1486 image->bits.indexed = NULL;
1488 image->common.property_changed = bits_image_property_changed;
1490 _pixman_image_reset_clip_region (image);