11176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/*
21176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
31176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *             2005 Lars Knoll & Zack Rusin, Trolltech
41176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *             2008 Aaron Plattner, NVIDIA Corporation
51176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Copyright © 2000 SuSE, Inc.
61176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Copyright © 2007, 2009 Red Hat, Inc.
71176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Copyright © 2008 André Tupinambá <andrelrt@gmail.com>
81176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *
91176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Permission to use, copy, modify, distribute, and sell this software and its
101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * documentation for any purpose is hereby granted without fee, provided that
111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * the above copyright notice appear in all copies and that both that
121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * copyright notice and this permission notice appear in supporting
131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * documentation, and that the name of Keith Packard not be used in
141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * advertising or publicity pertaining to distribution of the software without
151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * specific, written prior permission.  Keith Packard makes no
161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * representations about the suitability of this software for any purpose.  It
171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * is provided "as is" without express or implied warranty.
181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *
191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * SOFTWARE.
271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */
281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifdef HAVE_CONFIG_H
301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include <config.h>
311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include <stdio.h>
331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include <stdlib.h>
341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include <string.h>
351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include "pixman-private.h"
361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include "pixman-combine32.h"
371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include "pixman-inlines.h"
381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
391176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic uint32_t *
401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck_pixman_image_get_scanline_generic_float (pixman_iter_t * iter,
411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck					  const uint32_t *mask)
421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_iter_get_scanline_t fetch_32 = iter->data;
441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t *buffer = iter->buffer;
451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    fetch_32 (iter, NULL);
471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_expand_to_float ((argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return iter->buffer;
511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/* Fetch functions */
541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
551176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic force_inline uint32_t
561176bdada62cabc6ec4b0308a930e83b679d5d36John Reckfetch_pixel_no_alpha (bits_image_t *image,
571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		      int x, int y, pixman_bool_t check_bounds)
581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (check_bounds &&
601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	(x < 0 || x >= image->width || y < 0 || y >= image->height))
611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return 0;
631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return image->fetch_pixel_32 (image, x, y);
661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
681176bdada62cabc6ec4b0308a930e83b679d5d36John Recktypedef uint32_t (* get_pixel_t) (bits_image_t *image,
691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				  int x, int y, pixman_bool_t check_bounds);
701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
711176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic force_inline uint32_t
721176bdada62cabc6ec4b0308a930e83b679d5d36John Reckbits_image_fetch_pixel_nearest (bits_image_t   *image,
731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				pixman_fixed_t  x,
741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				pixman_fixed_t  y,
751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				get_pixel_t	get_pixel)
761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int x0 = pixman_fixed_to_int (x - pixman_fixed_e);
781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int y0 = pixman_fixed_to_int (y - pixman_fixed_e);
791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (image->common.repeat != PIXMAN_REPEAT_NONE)
811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	repeat (image->common.repeat, &x0, image->width);
831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	repeat (image->common.repeat, &y0, image->height);
841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return get_pixel (image, x0, y0, FALSE);
861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    else
881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return get_pixel (image, x0, y0, TRUE);
901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
931176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic force_inline uint32_t
941176bdada62cabc6ec4b0308a930e83b679d5d36John Reckbits_image_fetch_pixel_bilinear (bits_image_t   *image,
951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				 pixman_fixed_t  x,
961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				 pixman_fixed_t  y,
971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				 get_pixel_t	 get_pixel)
981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_repeat_t repeat_mode = image->common.repeat;
1001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int width = image->width;
1011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int height = image->height;
1021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int x1, y1, x2, y2;
1031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t tl, tr, bl, br;
1041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int32_t distx, disty;
1051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    x1 = x - pixman_fixed_1 / 2;
1071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    y1 = y - pixman_fixed_1 / 2;
1081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    distx = pixman_fixed_to_bilinear_weight (x1);
1101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    disty = pixman_fixed_to_bilinear_weight (y1);
1111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    x1 = pixman_fixed_to_int (x1);
1131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    y1 = pixman_fixed_to_int (y1);
1141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    x2 = x1 + 1;
1151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    y2 = y1 + 1;
1161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (repeat_mode != PIXMAN_REPEAT_NONE)
1181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
1191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	repeat (repeat_mode, &x1, width);
1201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	repeat (repeat_mode, &y1, height);
1211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	repeat (repeat_mode, &x2, width);
1221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	repeat (repeat_mode, &y2, height);
1231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	tl = get_pixel (image, x1, y1, FALSE);
1251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	bl = get_pixel (image, x1, y2, FALSE);
1261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	tr = get_pixel (image, x2, y1, FALSE);
1271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	br = get_pixel (image, x2, y2, FALSE);
1281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
1291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    else
1301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
1311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	tl = get_pixel (image, x1, y1, TRUE);
1321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	tr = get_pixel (image, x2, y1, TRUE);
1331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	bl = get_pixel (image, x1, y2, TRUE);
1341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	br = get_pixel (image, x2, y2, TRUE);
1351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
1361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return bilinear_interpolation (tl, tr, bl, br, distx, disty);
1381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
1391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1401176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic uint32_t *
1411176bdada62cabc6ec4b0308a930e83b679d5d36John Reckbits_image_fetch_bilinear_no_repeat_8888 (pixman_iter_t *iter,
1421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck					  const uint32_t *mask)
1431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
1441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_image_t * ima = iter->image;
1461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int              offset = iter->x;
1471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int              line = iter->y++;
1481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int              width = iter->width;
1491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t *       buffer = iter->buffer;
1501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    bits_image_t *bits = &ima->bits;
1521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t x_top, x_bottom, x;
1531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t ux_top, ux_bottom, ux;
1541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_vector_t v;
1551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t top_mask, bottom_mask;
1561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t *top_row;
1571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t *bottom_row;
1581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t *end;
1591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t zero[2] = { 0, 0 };
1601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t one = 1;
1611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int y, y1, y2;
1621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int disty;
1631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int mask_inc;
1641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int w;
1651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /* reference point is the center of the pixel */
1671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
1681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
1691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    v.vector[2] = pixman_fixed_1;
1701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (!pixman_transform_point_3d (bits->common.transform, &v))
1721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return iter->buffer;
1731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    ux = ux_top = ux_bottom = bits->common.transform->matrix[0][0];
1751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    x = x_top = x_bottom = v.vector[0] - pixman_fixed_1/2;
1761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    y = v.vector[1] - pixman_fixed_1/2;
1781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    disty = pixman_fixed_to_bilinear_weight (y);
1791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /* Load the pointers to the first and second lines from the source
1811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     * image that bilinear code must read.
1821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     *
1831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     * The main trick in this code is about the check if any line are
1841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     * outside of the image;
1851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     *
1861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     * When I realize that a line (any one) is outside, I change
1871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     * the pointer to a dummy area with zeros. Once I change this, I
1881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     * must be sure the pointer will not change, so I set the
1891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     * variables to each pointer increments inside the loop.
1901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     */
1911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    y1 = pixman_fixed_to_int (y);
1921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    y2 = y1 + 1;
1931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (y1 < 0 || y1 >= bits->height)
1951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
1961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	top_row = zero;
1971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x_top = 0;
1981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	ux_top = 0;
1991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
2001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    else
2011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
2021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	top_row = bits->bits + y1 * bits->rowstride;
2031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x_top = x;
2041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	ux_top = ux;
2051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
2061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (y2 < 0 || y2 >= bits->height)
2081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
2091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	bottom_row = zero;
2101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x_bottom = 0;
2111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	ux_bottom = 0;
2121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
2131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    else
2141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
2151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	bottom_row = bits->bits + y2 * bits->rowstride;
2161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x_bottom = x;
2171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	ux_bottom = ux;
2181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
2191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /* Instead of checking whether the operation uses the mast in
2211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     * each loop iteration, verify this only once and prepare the
2221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     * variables to make the code smaller inside the loop.
2231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     */
2241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (!mask)
2251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
2261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        mask_inc = 0;
2271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        mask = &one;
2281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
2291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    else
2301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
2311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        /* If have a mask, prepare the variables to check it */
2321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        mask_inc = 1;
2331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
2341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /* If both are zero, then the whole thing is zero */
2361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (top_row == zero && bottom_row == zero)
2371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
2381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	memset (buffer, 0, width * sizeof (uint32_t));
2391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return iter->buffer;
2401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
2411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    else if (bits->format == PIXMAN_x8r8g8b8)
2421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
2431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (top_row == zero)
2441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
2451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    top_mask = 0;
2461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    bottom_mask = 0xff000000;
2471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
2481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	else if (bottom_row == zero)
2491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
2501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    top_mask = 0xff000000;
2511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    bottom_mask = 0;
2521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
2531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	else
2541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
2551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    top_mask = 0xff000000;
2561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    bottom_mask = 0xff000000;
2571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
2581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
2591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    else
2601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
2611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	top_mask = 0;
2621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	bottom_mask = 0;
2631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
2641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    end = buffer + width;
2661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /* Zero fill to the left of the image */
2681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    while (buffer < end && x < pixman_fixed_minus_1)
2691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
2701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	*buffer++ = 0;
2711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x += ux;
2721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x_top += ux_top;
2731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x_bottom += ux_bottom;
2741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	mask += mask_inc;
2751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
2761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /* Left edge
2781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     */
2791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    while (buffer < end && x < 0)
2801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
2811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	uint32_t tr, br;
2821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	int32_t distx;
2831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	tr = top_row[pixman_fixed_to_int (x_top) + 1] | top_mask;
2851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	br = bottom_row[pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;
2861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	distx = pixman_fixed_to_bilinear_weight (x);
2881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	*buffer++ = bilinear_interpolation (0, tr, 0, br, distx, disty);
2901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x += ux;
2921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x_top += ux_top;
2931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x_bottom += ux_bottom;
2941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	mask += mask_inc;
2951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
2961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /* Main part */
2981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    w = pixman_int_to_fixed (bits->width - 1);
2991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    while (buffer < end  &&  x < w)
3011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
3021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (*mask)
3031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
3041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    uint32_t tl, tr, bl, br;
3051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    int32_t distx;
3061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
3081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    tr = top_row [pixman_fixed_to_int (x_top) + 1] | top_mask;
3091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
3101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    br = bottom_row [pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;
3111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    distx = pixman_fixed_to_bilinear_weight (x);
3131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    *buffer = bilinear_interpolation (tl, tr, bl, br, distx, disty);
3151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
3161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	buffer++;
3181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x += ux;
3191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x_top += ux_top;
3201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x_bottom += ux_bottom;
3211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	mask += mask_inc;
3221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
3231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /* Right Edge */
3251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    w = pixman_int_to_fixed (bits->width);
3261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    while (buffer < end  &&  x < w)
3271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
3281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (*mask)
3291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
3301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    uint32_t tl, bl;
3311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    int32_t distx;
3321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
3341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
3351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    distx = pixman_fixed_to_bilinear_weight (x);
3371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    *buffer = bilinear_interpolation (tl, 0, bl, 0, distx, disty);
3391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
3401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	buffer++;
3421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x += ux;
3431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x_top += ux_top;
3441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x_bottom += ux_bottom;
3451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	mask += mask_inc;
3461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
3471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /* Zero fill to the left of the image */
3491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    while (buffer < end)
3501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	*buffer++ = 0;
3511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return iter->buffer;
3531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
3541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3551176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic force_inline uint32_t
3561176bdada62cabc6ec4b0308a930e83b679d5d36John Reckbits_image_fetch_pixel_convolution (bits_image_t   *image,
3571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				    pixman_fixed_t  x,
3581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				    pixman_fixed_t  y,
3591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				    get_pixel_t     get_pixel)
3601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
3611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t *params = image->common.filter_params;
3621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int x_off = (params[0] - pixman_fixed_1) >> 1;
3631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int y_off = (params[1] - pixman_fixed_1) >> 1;
3641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int32_t cwidth = pixman_fixed_to_int (params[0]);
3651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int32_t cheight = pixman_fixed_to_int (params[1]);
3661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int32_t i, j, x1, x2, y1, y2;
3671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_repeat_t repeat_mode = image->common.repeat;
3681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int width = image->width;
3691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int height = image->height;
3701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int srtot, sgtot, sbtot, satot;
3711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    params += 2;
3731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
3751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
3761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    x2 = x1 + cwidth;
3771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    y2 = y1 + cheight;
3781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    srtot = sgtot = sbtot = satot = 0;
3801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    for (i = y1; i < y2; ++i)
3821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
3831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	for (j = x1; j < x2; ++j)
3841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
3851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    int rx = j;
3861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    int ry = i;
3871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    pixman_fixed_t f = *params;
3891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    if (f)
3911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    {
3921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		uint32_t pixel;
3931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		if (repeat_mode != PIXMAN_REPEAT_NONE)
3951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		{
3961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    repeat (repeat_mode, &rx, width);
3971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    repeat (repeat_mode, &ry, height);
3981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    pixel = get_pixel (image, rx, ry, FALSE);
4001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		}
4011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		else
4021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		{
4031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    pixel = get_pixel (image, rx, ry, TRUE);
4041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		}
4051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		srtot += (int)RED_8 (pixel) * f;
4071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		sgtot += (int)GREEN_8 (pixel) * f;
4081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		sbtot += (int)BLUE_8 (pixel) * f;
4091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		satot += (int)ALPHA_8 (pixel) * f;
4101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    }
4111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    params++;
4131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
4141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
4151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    satot = (satot + 0x8000) >> 16;
4171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    srtot = (srtot + 0x8000) >> 16;
4181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    sgtot = (sgtot + 0x8000) >> 16;
4191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    sbtot = (sbtot + 0x8000) >> 16;
4201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    satot = CLIP (satot, 0, 0xff);
4221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    srtot = CLIP (srtot, 0, 0xff);
4231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    sgtot = CLIP (sgtot, 0, 0xff);
4241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    sbtot = CLIP (sbtot, 0, 0xff);
4251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return ((satot << 24) | (srtot << 16) | (sgtot <<  8) | (sbtot));
4271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
4281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4291176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic uint32_t
4301176bdada62cabc6ec4b0308a930e83b679d5d36John Reckbits_image_fetch_pixel_separable_convolution (bits_image_t *image,
4311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                                              pixman_fixed_t x,
4321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                                              pixman_fixed_t y,
4331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                                              get_pixel_t    get_pixel)
4341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
4351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t *params = image->common.filter_params;
4361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_repeat_t repeat_mode = image->common.repeat;
4371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int width = image->width;
4381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int height = image->height;
4391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int cwidth = pixman_fixed_to_int (params[0]);
4401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int cheight = pixman_fixed_to_int (params[1]);
4411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int x_phase_bits = pixman_fixed_to_int (params[2]);
4421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int y_phase_bits = pixman_fixed_to_int (params[3]);
4431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int x_phase_shift = 16 - x_phase_bits;
4441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int y_phase_shift = 16 - y_phase_bits;
4451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1;
4461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int y_off = ((cheight << 16) - pixman_fixed_1) >> 1;
4471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t *y_params;
4481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int srtot, sgtot, sbtot, satot;
4491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int32_t x1, x2, y1, y2;
4501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int32_t px, py;
4511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int i, j;
4521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /* Round x and y to the middle of the closest phase before continuing. This
4541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     * ensures that the convolution matrix is aligned right, since it was
4551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     * positioned relative to a particular phase (and not relative to whatever
4561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     * exact fraction we happen to get here).
4571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     */
4581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    x = ((x >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1);
4591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    y = ((y >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1);
4601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    px = (x & 0xffff) >> x_phase_shift;
4621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    py = (y & 0xffff) >> y_phase_shift;
4631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight;
4651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
4671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
4681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    x2 = x1 + cwidth;
4691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    y2 = y1 + cheight;
4701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    srtot = sgtot = sbtot = satot = 0;
4721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    for (i = y1; i < y2; ++i)
4741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
4751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        pixman_fixed_48_16_t fy = *y_params++;
4761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        pixman_fixed_t *x_params = params + 4 + px * cwidth;
4771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        if (fy)
4791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        {
4801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            for (j = x1; j < x2; ++j)
4811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            {
4821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                pixman_fixed_t fx = *x_params++;
4831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		int rx = j;
4841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		int ry = i;
4851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                if (fx)
4871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                {
4881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    pixman_fixed_t f;
4891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    uint32_t pixel;
4901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    if (repeat_mode != PIXMAN_REPEAT_NONE)
4921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    {
4931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                        repeat (repeat_mode, &rx, width);
4941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                        repeat (repeat_mode, &ry, height);
4951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                        pixel = get_pixel (image, rx, ry, FALSE);
4971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    }
4981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    else
4991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    {
5001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                        pixel = get_pixel (image, rx, ry, TRUE);
5011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    }
5021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    f = (fy * fx + 0x8000) >> 16;
5041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    srtot += (int)RED_8 (pixel) * f;
5061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    sgtot += (int)GREEN_8 (pixel) * f;
5071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    sbtot += (int)BLUE_8 (pixel) * f;
5081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    satot += (int)ALPHA_8 (pixel) * f;
5091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                }
5101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            }
5111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
5121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
5131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    satot = (satot + 0x8000) >> 16;
5151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    srtot = (srtot + 0x8000) >> 16;
5161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    sgtot = (sgtot + 0x8000) >> 16;
5171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    sbtot = (sbtot + 0x8000) >> 16;
5181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    satot = CLIP (satot, 0, 0xff);
5201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    srtot = CLIP (srtot, 0, 0xff);
5211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    sgtot = CLIP (sgtot, 0, 0xff);
5221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    sbtot = CLIP (sbtot, 0, 0xff);
5231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return ((satot << 24) | (srtot << 16) | (sgtot <<  8) | (sbtot));
5251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
5261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5271176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic force_inline uint32_t
5281176bdada62cabc6ec4b0308a930e83b679d5d36John Reckbits_image_fetch_pixel_filtered (bits_image_t *image,
5291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				 pixman_fixed_t x,
5301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				 pixman_fixed_t y,
5311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				 get_pixel_t    get_pixel)
5321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
5331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    switch (image->common.filter)
5341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
5351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    case PIXMAN_FILTER_NEAREST:
5361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    case PIXMAN_FILTER_FAST:
5371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return bits_image_fetch_pixel_nearest (image, x, y, get_pixel);
5381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	break;
5391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    case PIXMAN_FILTER_BILINEAR:
5411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    case PIXMAN_FILTER_GOOD:
5421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    case PIXMAN_FILTER_BEST:
5431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return bits_image_fetch_pixel_bilinear (image, x, y, get_pixel);
5441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	break;
5451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    case PIXMAN_FILTER_CONVOLUTION:
5471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return bits_image_fetch_pixel_convolution (image, x, y, get_pixel);
5481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	break;
5491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
5511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        return bits_image_fetch_pixel_separable_convolution (image, x, y, get_pixel);
5521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        break;
5531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    default:
5551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        break;
5561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
5571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return 0;
5591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
5601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5611176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic uint32_t *
5621176bdada62cabc6ec4b0308a930e83b679d5d36John Reckbits_image_fetch_affine_no_alpha (pixman_iter_t *  iter,
5631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				  const uint32_t * mask)
5641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
5651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_image_t *image  = iter->image;
5661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int             offset = iter->x;
5671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int             line   = iter->y++;
5681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int             width  = iter->width;
5691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t *      buffer = iter->buffer;
5701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t x, y;
5721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t ux, uy;
5731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_vector_t v;
5741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int i;
5751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /* reference point is the center of the pixel */
5771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
5781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
5791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    v.vector[2] = pixman_fixed_1;
5801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (image->common.transform)
5821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
5831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (!pixman_transform_point_3d (image->common.transform, &v))
5841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    return iter->buffer;
5851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	ux = image->common.transform->matrix[0][0];
5871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	uy = image->common.transform->matrix[1][0];
5881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
5891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    else
5901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
5911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	ux = pixman_fixed_1;
5921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	uy = 0;
5931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
5941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    x = v.vector[0];
5961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    y = v.vector[1];
5971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    for (i = 0; i < width; ++i)
5991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
6001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (!mask || mask[i])
6011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
6021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    buffer[i] = bits_image_fetch_pixel_filtered (
6031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		&image->bits, x, y, fetch_pixel_no_alpha);
6041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
6051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x += ux;
6071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	y += uy;
6081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
6091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return buffer;
6111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
6121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/* General fetcher */
6141176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic force_inline uint32_t
6151176bdada62cabc6ec4b0308a930e83b679d5d36John Reckfetch_pixel_general (bits_image_t *image, int x, int y, pixman_bool_t check_bounds)
6161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
6171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t pixel;
6181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (check_bounds &&
6201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	(x < 0 || x >= image->width || y < 0 || y >= image->height))
6211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
6221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return 0;
6231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
6241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixel = image->fetch_pixel_32 (image, x, y);
6261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (image->common.alpha_map)
6281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
6291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	uint32_t pixel_a;
6301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x -= image->common.alpha_origin_x;
6321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	y -= image->common.alpha_origin_y;
6331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (x < 0 || x >= image->common.alpha_map->width ||
6351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    y < 0 || y >= image->common.alpha_map->height)
6361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
6371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    pixel_a = 0;
6381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
6391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	else
6401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
6411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    pixel_a = image->common.alpha_map->fetch_pixel_32 (
6421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		image->common.alpha_map, x, y);
6431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    pixel_a = ALPHA_8 (pixel_a);
6451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
6461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	pixel &= 0x00ffffff;
6481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	pixel |= (pixel_a << 24);
6491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
6501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return pixel;
6521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
6531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6541176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic uint32_t *
6551176bdada62cabc6ec4b0308a930e83b679d5d36John Reckbits_image_fetch_general (pixman_iter_t  *iter,
6561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			  const uint32_t *mask)
6571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
6581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_image_t *image  = iter->image;
6591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int             offset = iter->x;
6601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int             line   = iter->y++;
6611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int             width  = iter->width;
6621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t *      buffer = iter->buffer;
6631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t x, y, w;
6651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t ux, uy, uw;
6661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_vector_t v;
6671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int i;
6681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /* reference point is the center of the pixel */
6701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
6711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
6721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    v.vector[2] = pixman_fixed_1;
6731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (image->common.transform)
6751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
6761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (!pixman_transform_point_3d (image->common.transform, &v))
6771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    return buffer;
6781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	ux = image->common.transform->matrix[0][0];
6801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	uy = image->common.transform->matrix[1][0];
6811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	uw = image->common.transform->matrix[2][0];
6821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
6831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    else
6841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
6851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	ux = pixman_fixed_1;
6861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	uy = 0;
6871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	uw = 0;
6881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
6891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    x = v.vector[0];
6911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    y = v.vector[1];
6921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    w = v.vector[2];
6931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    for (i = 0; i < width; ++i)
6951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
6961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	pixman_fixed_t x0, y0;
6971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (!mask || mask[i])
6991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
7001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    if (w != 0)
7011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    {
7021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		x0 = ((pixman_fixed_48_16_t)x << 16) / w;
7031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		y0 = ((pixman_fixed_48_16_t)y << 16) / w;
7041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    }
7051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    else
7061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    {
7071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		x0 = 0;
7081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		y0 = 0;
7091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    }
7101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
7111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    buffer[i] = bits_image_fetch_pixel_filtered (
7121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		&image->bits, x0, y0, fetch_pixel_general);
7131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
7141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
7151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x += ux;
7161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	y += uy;
7171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	w += uw;
7181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
7191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
7201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return buffer;
7211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
7221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
7231176bdada62cabc6ec4b0308a930e83b679d5d36John Recktypedef uint32_t (* convert_pixel_t) (const uint8_t *row, int x);
7241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
7251176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic force_inline void
7261176bdada62cabc6ec4b0308a930e83b679d5d36John Reckbits_image_fetch_separable_convolution_affine (pixman_image_t * image,
7271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck					       int              offset,
7281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck					       int              line,
7291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck					       int              width,
7301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck					       uint32_t *       buffer,
7311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck					       const uint32_t * mask,
7321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
7331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck					       convert_pixel_t	convert_pixel,
7341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck					       pixman_format_code_t	format,
7351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck					       pixman_repeat_t	repeat_mode)
7361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
7371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    bits_image_t *bits = &image->bits;
7381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t *params = image->common.filter_params;
7391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int cwidth = pixman_fixed_to_int (params[0]);
7401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int cheight = pixman_fixed_to_int (params[1]);
7411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1;
7421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int y_off = ((cheight << 16) - pixman_fixed_1) >> 1;
7431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int x_phase_bits = pixman_fixed_to_int (params[2]);
7441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int y_phase_bits = pixman_fixed_to_int (params[3]);
7451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int x_phase_shift = 16 - x_phase_bits;
7461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int y_phase_shift = 16 - y_phase_bits;
7471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t vx, vy;
7481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t ux, uy;
7491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_vector_t v;
7501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int k;
7511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
7521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /* reference point is the center of the pixel */
7531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
7541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
7551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    v.vector[2] = pixman_fixed_1;
7561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
7571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (!pixman_transform_point_3d (image->common.transform, &v))
7581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return;
7591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
7601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    ux = image->common.transform->matrix[0][0];
7611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uy = image->common.transform->matrix[1][0];
7621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
7631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    vx = v.vector[0];
7641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    vy = v.vector[1];
7651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
7661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    for (k = 0; k < width; ++k)
7671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
7681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	pixman_fixed_t *y_params;
7691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	int satot, srtot, sgtot, sbtot;
7701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	pixman_fixed_t x, y;
7711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	int32_t x1, x2, y1, y2;
7721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	int32_t px, py;
7731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	int i, j;
7741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
7751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (mask && !mask[k])
7761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    goto next;
7771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
7781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	/* Round x and y to the middle of the closest phase before continuing. This
7791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	 * ensures that the convolution matrix is aligned right, since it was
7801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	 * positioned relative to a particular phase (and not relative to whatever
7811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	 * exact fraction we happen to get here).
7821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	 */
7831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x = ((vx >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1);
7841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	y = ((vy >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1);
7851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
7861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	px = (x & 0xffff) >> x_phase_shift;
7871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	py = (y & 0xffff) >> y_phase_shift;
7881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
7891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
7901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
7911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x2 = x1 + cwidth;
7921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	y2 = y1 + cheight;
7931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
7941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	satot = srtot = sgtot = sbtot = 0;
7951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
7961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight;
7971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
7981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	for (i = y1; i < y2; ++i)
7991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
8001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    pixman_fixed_t fy = *y_params++;
8011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
8021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    if (fy)
8031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    {
8041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		pixman_fixed_t *x_params = params + 4 + px * cwidth;
8051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
8061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		for (j = x1; j < x2; ++j)
8071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		{
8081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    pixman_fixed_t fx = *x_params++;
8091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    int rx = j;
8101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    int ry = i;
8111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
8121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    if (fx)
8131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    {
8141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			pixman_fixed_t f;
8151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			uint32_t pixel, mask;
8161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			uint8_t *row;
8171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
8181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
8191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
8201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			if (repeat_mode != PIXMAN_REPEAT_NONE)
8211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			{
8221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    repeat (repeat_mode, &rx, bits->width);
8231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    repeat (repeat_mode, &ry, bits->height);
8241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
8251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    row = (uint8_t *)bits->bits + bits->rowstride * 4 * ry;
8261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    pixel = convert_pixel (row, rx) | mask;
8271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			}
8281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			else
8291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			{
8301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    if (rx < 0 || ry < 0 || rx >= bits->width || ry >= bits->height)
8311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    {
8321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				pixel = 0;
8331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    }
8341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    else
8351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    {
8361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				row = (uint8_t *)bits->bits + bits->rowstride * 4 * ry;
8371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				pixel = convert_pixel (row, rx) | mask;
8381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    }
8391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			}
8401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
8411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			f = ((pixman_fixed_32_32_t)fx * fy + 0x8000) >> 16;
8421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			srtot += (int)RED_8 (pixel) * f;
8431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			sgtot += (int)GREEN_8 (pixel) * f;
8441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			sbtot += (int)BLUE_8 (pixel) * f;
8451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			satot += (int)ALPHA_8 (pixel) * f;
8461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    }
8471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		}
8481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    }
8491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
8501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
8511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	satot = (satot + 0x8000) >> 16;
8521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	srtot = (srtot + 0x8000) >> 16;
8531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	sgtot = (sgtot + 0x8000) >> 16;
8541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	sbtot = (sbtot + 0x8000) >> 16;
8551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
8561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	satot = CLIP (satot, 0, 0xff);
8571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	srtot = CLIP (srtot, 0, 0xff);
8581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	sgtot = CLIP (sgtot, 0, 0xff);
8591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	sbtot = CLIP (sbtot, 0, 0xff);
8601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
8611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	buffer[k] = (satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot << 0);
8621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
8631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    next:
8641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	vx += ux;
8651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	vy += uy;
8661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
8671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
8681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
8691176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
8701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
8711176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic force_inline void
8721176bdada62cabc6ec4b0308a930e83b679d5d36John Reckbits_image_fetch_bilinear_affine (pixman_image_t * image,
8731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				  int              offset,
8741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				  int              line,
8751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				  int              width,
8761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				  uint32_t *       buffer,
8771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				  const uint32_t * mask,
8781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
8791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				  convert_pixel_t	convert_pixel,
8801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				  pixman_format_code_t	format,
8811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				  pixman_repeat_t	repeat_mode)
8821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
8831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t x, y;
8841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t ux, uy;
8851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_vector_t v;
8861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    bits_image_t *bits = &image->bits;
8871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int i;
8881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
8891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /* reference point is the center of the pixel */
8901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
8911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
8921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    v.vector[2] = pixman_fixed_1;
8931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
8941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (!pixman_transform_point_3d (image->common.transform, &v))
8951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return;
8961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
8971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    ux = image->common.transform->matrix[0][0];
8981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uy = image->common.transform->matrix[1][0];
8991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
9001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    x = v.vector[0];
9011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    y = v.vector[1];
9021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
9031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    for (i = 0; i < width; ++i)
9041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
9051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	int x1, y1, x2, y2;
9061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	uint32_t tl, tr, bl, br;
9071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	int32_t distx, disty;
9081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	int width = image->bits.width;
9091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	int height = image->bits.height;
9101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	const uint8_t *row1;
9111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	const uint8_t *row2;
9121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
9131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (mask && !mask[i])
9141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    goto next;
9151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
9161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x1 = x - pixman_fixed_1 / 2;
9171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	y1 = y - pixman_fixed_1 / 2;
9181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
9191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	distx = pixman_fixed_to_bilinear_weight (x1);
9201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	disty = pixman_fixed_to_bilinear_weight (y1);
9211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
9221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	y1 = pixman_fixed_to_int (y1);
9231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	y2 = y1 + 1;
9241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x1 = pixman_fixed_to_int (x1);
9251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x2 = x1 + 1;
9261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
9271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (repeat_mode != PIXMAN_REPEAT_NONE)
9281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
9291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    uint32_t mask;
9301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
9311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
9321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
9331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    repeat (repeat_mode, &x1, width);
9341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    repeat (repeat_mode, &y1, height);
9351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    repeat (repeat_mode, &x2, width);
9361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    repeat (repeat_mode, &y2, height);
9371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
9381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
9391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
9401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
9411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    tl = convert_pixel (row1, x1) | mask;
9421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    tr = convert_pixel (row1, x2) | mask;
9431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    bl = convert_pixel (row2, x1) | mask;
9441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    br = convert_pixel (row2, x2) | mask;
9451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
9461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	else
9471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
9481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    uint32_t mask1, mask2;
9491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    int bpp;
9501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
9511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    /* Note: PIXMAN_FORMAT_BPP() returns an unsigned value,
9521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	     * which means if you use it in expressions, those
9531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	     * expressions become unsigned themselves. Since
9541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	     * the variables below can be negative in some cases,
9551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	     * that will lead to crashes on 64 bit architectures.
9561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	     *
9571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	     * So this line makes sure bpp is signed
9581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	     */
9591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    bpp = PIXMAN_FORMAT_BPP (format);
9601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
9611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    if (x1 >= width || x2 < 0 || y1 >= height || y2 < 0)
9621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    {
9631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		buffer[i] = 0;
9641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		goto next;
9651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    }
9661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
9671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    if (y2 == 0)
9681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    {
9691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		row1 = zero;
9701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		mask1 = 0;
9711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    }
9721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    else
9731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    {
9741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
9751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		row1 += bpp / 8 * x1;
9761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
9771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		mask1 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
9781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    }
9791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
9801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    if (y1 == height - 1)
9811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    {
9821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		row2 = zero;
9831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		mask2 = 0;
9841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    }
9851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    else
9861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    {
9871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
9881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		row2 += bpp / 8 * x1;
9891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
9901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		mask2 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
9911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    }
9921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
9931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    if (x2 == 0)
9941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    {
9951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		tl = 0;
9961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		bl = 0;
9971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    }
9981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    else
9991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    {
10001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		tl = convert_pixel (row1, 0) | mask1;
10011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		bl = convert_pixel (row2, 0) | mask2;
10021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    }
10031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
10041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    if (x1 == width - 1)
10051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    {
10061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		tr = 0;
10071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		br = 0;
10081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    }
10091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    else
10101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    {
10111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		tr = convert_pixel (row1, 1) | mask1;
10121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		br = convert_pixel (row2, 1) | mask2;
10131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    }
10141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
10151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
10161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	buffer[i] = bilinear_interpolation (
10171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    tl, tr, bl, br, distx, disty);
10181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
10191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    next:
10201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x += ux;
10211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	y += uy;
10221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
10231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
10241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
10251176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic force_inline void
10261176bdada62cabc6ec4b0308a930e83b679d5d36John Reckbits_image_fetch_nearest_affine (pixman_image_t * image,
10271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				 int              offset,
10281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				 int              line,
10291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				 int              width,
10301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				 uint32_t *       buffer,
10311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				 const uint32_t * mask,
10321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
10331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				 convert_pixel_t	convert_pixel,
10341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				 pixman_format_code_t	format,
10351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				 pixman_repeat_t	repeat_mode)
10361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
10371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t x, y;
10381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t ux, uy;
10391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_vector_t v;
10401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    bits_image_t *bits = &image->bits;
10411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int i;
10421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
10431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /* reference point is the center of the pixel */
10441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
10451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
10461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    v.vector[2] = pixman_fixed_1;
10471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
10481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (!pixman_transform_point_3d (image->common.transform, &v))
10491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return;
10501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
10511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    ux = image->common.transform->matrix[0][0];
10521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uy = image->common.transform->matrix[1][0];
10531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
10541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    x = v.vector[0];
10551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    y = v.vector[1];
10561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
10571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    for (i = 0; i < width; ++i)
10581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
10591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	int width, height, x0, y0;
10601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	const uint8_t *row;
10611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
10621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (mask && !mask[i])
10631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    goto next;
10641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
10651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	width = image->bits.width;
10661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	height = image->bits.height;
10671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x0 = pixman_fixed_to_int (x - pixman_fixed_e);
10681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	y0 = pixman_fixed_to_int (y - pixman_fixed_e);
10691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
10701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (repeat_mode == PIXMAN_REPEAT_NONE &&
10711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    (y0 < 0 || y0 >= height || x0 < 0 || x0 >= width))
10721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
10731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    buffer[i] = 0;
10741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
10751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	else
10761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
10771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    uint32_t mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
10781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
10791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    if (repeat_mode != PIXMAN_REPEAT_NONE)
10801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    {
10811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		repeat (repeat_mode, &x0, width);
10821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		repeat (repeat_mode, &y0, height);
10831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    }
10841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
10851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    row = (uint8_t *)bits->bits + bits->rowstride * 4 * y0;
10861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
10871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    buffer[i] = convert_pixel (row, x0) | mask;
10881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
10891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
10901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    next:
10911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x += ux;
10921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	y += uy;
10931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
10941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
10951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
10961176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic force_inline uint32_t
10971176bdada62cabc6ec4b0308a930e83b679d5d36John Reckconvert_a8r8g8b8 (const uint8_t *row, int x)
10981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
10991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return *(((uint32_t *)row) + x);
11001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
11011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
11021176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic force_inline uint32_t
11031176bdada62cabc6ec4b0308a930e83b679d5d36John Reckconvert_x8r8g8b8 (const uint8_t *row, int x)
11041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
11051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return *(((uint32_t *)row) + x);
11061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
11071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
11081176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic force_inline uint32_t
11091176bdada62cabc6ec4b0308a930e83b679d5d36John Reckconvert_a8 (const uint8_t *row, int x)
11101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
11111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return *(row + x) << 24;
11121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
11131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
11141176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic force_inline uint32_t
11151176bdada62cabc6ec4b0308a930e83b679d5d36John Reckconvert_r5g6b5 (const uint8_t *row, int x)
11161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
11171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return convert_0565_to_0888 (*((uint16_t *)row + x));
11181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
11191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
11201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#define MAKE_SEPARABLE_CONVOLUTION_FETCHER(name, format, repeat_mode)  \
11211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    static uint32_t *							\
11221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    bits_image_fetch_separable_convolution_affine_ ## name (pixman_iter_t   *iter, \
11231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck							    const uint32_t * mask) \
11241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {									\
11251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	bits_image_fetch_separable_convolution_affine (                 \
11261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    iter->image,                                                \
11271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    iter->x, iter->y++,                                         \
11281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    iter->width,                                                \
11291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    iter->buffer, mask,                                         \
11301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    convert_ ## format,                                         \
11311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    PIXMAN_ ## format,                                          \
11321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    repeat_mode);                                               \
11331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck									\
11341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return iter->buffer;                                            \
11351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
11361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
11371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#define MAKE_BILINEAR_FETCHER(name, format, repeat_mode)		\
11381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    static uint32_t *							\
11391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    bits_image_fetch_bilinear_affine_ ## name (pixman_iter_t   *iter,	\
11401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck					       const uint32_t * mask)	\
11411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {									\
11421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	bits_image_fetch_bilinear_affine (iter->image,			\
11431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck					  iter->x, iter->y++,		\
11441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck					  iter->width,			\
11451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck					  iter->buffer, mask,		\
11461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck					  convert_ ## format,		\
11471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck					  PIXMAN_ ## format,		\
11481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck					  repeat_mode);			\
11491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return iter->buffer;						\
11501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
11511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
11521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#define MAKE_NEAREST_FETCHER(name, format, repeat_mode)			\
11531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    static uint32_t *							\
11541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    bits_image_fetch_nearest_affine_ ## name (pixman_iter_t   *iter,	\
11551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck					      const uint32_t * mask)	\
11561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {									\
11571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	bits_image_fetch_nearest_affine (iter->image,			\
11581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck					 iter->x, iter->y++,		\
11591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck					 iter->width,			\
11601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck					 iter->buffer, mask,		\
11611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck					 convert_ ## format,		\
11621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck					 PIXMAN_ ## format,		\
11631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck					 repeat_mode);			\
11641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return iter->buffer;						\
11651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
11661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
11671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#define MAKE_FETCHERS(name, format, repeat_mode)			\
11681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    MAKE_NEAREST_FETCHER (name, format, repeat_mode)			\
11691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    MAKE_BILINEAR_FETCHER (name, format, repeat_mode)			\
11701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    MAKE_SEPARABLE_CONVOLUTION_FETCHER (name, format, repeat_mode)
11711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
11721176bdada62cabc6ec4b0308a930e83b679d5d36John ReckMAKE_FETCHERS (pad_a8r8g8b8,     a8r8g8b8, PIXMAN_REPEAT_PAD)
11731176bdada62cabc6ec4b0308a930e83b679d5d36John ReckMAKE_FETCHERS (none_a8r8g8b8,    a8r8g8b8, PIXMAN_REPEAT_NONE)
11741176bdada62cabc6ec4b0308a930e83b679d5d36John ReckMAKE_FETCHERS (reflect_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_REFLECT)
11751176bdada62cabc6ec4b0308a930e83b679d5d36John ReckMAKE_FETCHERS (normal_a8r8g8b8,  a8r8g8b8, PIXMAN_REPEAT_NORMAL)
11761176bdada62cabc6ec4b0308a930e83b679d5d36John ReckMAKE_FETCHERS (pad_x8r8g8b8,     x8r8g8b8, PIXMAN_REPEAT_PAD)
11771176bdada62cabc6ec4b0308a930e83b679d5d36John ReckMAKE_FETCHERS (none_x8r8g8b8,    x8r8g8b8, PIXMAN_REPEAT_NONE)
11781176bdada62cabc6ec4b0308a930e83b679d5d36John ReckMAKE_FETCHERS (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT)
11791176bdada62cabc6ec4b0308a930e83b679d5d36John ReckMAKE_FETCHERS (normal_x8r8g8b8,  x8r8g8b8, PIXMAN_REPEAT_NORMAL)
11801176bdada62cabc6ec4b0308a930e83b679d5d36John ReckMAKE_FETCHERS (pad_a8,           a8,       PIXMAN_REPEAT_PAD)
11811176bdada62cabc6ec4b0308a930e83b679d5d36John ReckMAKE_FETCHERS (none_a8,          a8,       PIXMAN_REPEAT_NONE)
11821176bdada62cabc6ec4b0308a930e83b679d5d36John ReckMAKE_FETCHERS (reflect_a8,	 a8,       PIXMAN_REPEAT_REFLECT)
11831176bdada62cabc6ec4b0308a930e83b679d5d36John ReckMAKE_FETCHERS (normal_a8,	 a8,       PIXMAN_REPEAT_NORMAL)
11841176bdada62cabc6ec4b0308a930e83b679d5d36John ReckMAKE_FETCHERS (pad_r5g6b5,       r5g6b5,   PIXMAN_REPEAT_PAD)
11851176bdada62cabc6ec4b0308a930e83b679d5d36John ReckMAKE_FETCHERS (none_r5g6b5,      r5g6b5,   PIXMAN_REPEAT_NONE)
11861176bdada62cabc6ec4b0308a930e83b679d5d36John ReckMAKE_FETCHERS (reflect_r5g6b5,   r5g6b5,   PIXMAN_REPEAT_REFLECT)
11871176bdada62cabc6ec4b0308a930e83b679d5d36John ReckMAKE_FETCHERS (normal_r5g6b5,    r5g6b5,   PIXMAN_REPEAT_NORMAL)
11881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
11891176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic void
11901176bdada62cabc6ec4b0308a930e83b679d5d36John Reckreplicate_pixel_32 (bits_image_t *   bits,
11911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    int              x,
11921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    int              y,
11931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    int              width,
11941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    uint32_t *       buffer)
11951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
11961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t color;
11971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t *end;
11981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
11991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    color = bits->fetch_pixel_32 (bits, x, y);
12001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
12011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    end = buffer + width;
12021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    while (buffer < end)
12031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	*(buffer++) = color;
12041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
12051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
12061176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic void
12071176bdada62cabc6ec4b0308a930e83b679d5d36John Reckreplicate_pixel_float (bits_image_t *   bits,
12081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		       int              x,
12091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		       int              y,
12101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		       int              width,
12111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		       uint32_t *       b)
12121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
12131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    argb_t color;
12141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    argb_t *buffer = (argb_t *)b;
12151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    argb_t *end;
12161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
12171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    color = bits->fetch_pixel_float (bits, x, y);
12181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
12191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    end = buffer + width;
12201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    while (buffer < end)
12211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	*(buffer++) = color;
12221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
12231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
12241176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic void
12251176bdada62cabc6ec4b0308a930e83b679d5d36John Reckbits_image_fetch_untransformed_repeat_none (bits_image_t *image,
12261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                                            pixman_bool_t wide,
12271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                                            int           x,
12281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                                            int           y,
12291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                                            int           width,
12301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                                            uint32_t *    buffer)
12311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
12321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t w;
12331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
12341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (y < 0 || y >= image->height)
12351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
12361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	memset (buffer, 0, width * (wide? sizeof (argb_t) : 4));
12371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return;
12381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
12391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
12401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (x < 0)
12411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
12421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	w = MIN (width, -x);
12431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
12441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	memset (buffer, 0, w * (wide ? sizeof (argb_t) : 4));
12451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
12461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	width -= w;
12471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	buffer += w * (wide? 4 : 1);
12481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x += w;
12491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
12501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
12511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (x < image->width)
12521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
12531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	w = MIN (width, image->width - x);
12541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
12551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (wide)
12561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL);
12571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	else
12581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
12591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
12601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	width -= w;
12611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	buffer += w * (wide? 4 : 1);
12621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x += w;
12631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
12641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
12651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    memset (buffer, 0, width * (wide ? sizeof (argb_t) : 4));
12661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
12671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
12681176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic void
12691176bdada62cabc6ec4b0308a930e83b679d5d36John Reckbits_image_fetch_untransformed_repeat_normal (bits_image_t *image,
12701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                                              pixman_bool_t wide,
12711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                                              int           x,
12721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                                              int           y,
12731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                                              int           width,
12741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                                              uint32_t *    buffer)
12751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
12761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t w;
12771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
12781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    while (y < 0)
12791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	y += image->height;
12801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
12811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    while (y >= image->height)
12821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	y -= image->height;
12831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
12841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (image->width == 1)
12851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
12861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (wide)
12871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    replicate_pixel_float (image, 0, y, width, buffer);
12881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	else
12891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    replicate_pixel_32 (image, 0, y, width, buffer);
12901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
12911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return;
12921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
12931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
12941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    while (width)
12951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
12961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	while (x < 0)
12971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    x += image->width;
12981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	while (x >= image->width)
12991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    x -= image->width;
13001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
13011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	w = MIN (width, image->width - x);
13021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
13031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (wide)
13041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL);
13051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	else
13061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
13071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
13081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	buffer += w * (wide? 4 : 1);
13091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x += w;
13101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	width -= w;
13111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
13121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
13131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
13141176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic uint32_t *
13151176bdada62cabc6ec4b0308a930e83b679d5d36John Reckbits_image_fetch_untransformed_32 (pixman_iter_t * iter,
13161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				   const uint32_t *mask)
13171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
13181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_image_t *image  = iter->image;
13191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int             x      = iter->x;
13201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int             y      = iter->y;
13211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int             width  = iter->width;
13221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t *      buffer = iter->buffer;
13231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
13241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (image->common.repeat == PIXMAN_REPEAT_NONE)
13251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
13261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	bits_image_fetch_untransformed_repeat_none (
13271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    &image->bits, FALSE, x, y, width, buffer);
13281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
13291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    else
13301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
13311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	bits_image_fetch_untransformed_repeat_normal (
13321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    &image->bits, FALSE, x, y, width, buffer);
13331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
13341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
13351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    iter->y++;
13361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return buffer;
13371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
13381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
13391176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic uint32_t *
13401176bdada62cabc6ec4b0308a930e83b679d5d36John Reckbits_image_fetch_untransformed_float (pixman_iter_t * iter,
13411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				      const uint32_t *mask)
13421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
13431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_image_t *image  = iter->image;
13441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int             x      = iter->x;
13451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int             y      = iter->y;
13461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int             width  = iter->width;
13471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t *      buffer = iter->buffer;
13481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
13491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (image->common.repeat == PIXMAN_REPEAT_NONE)
13501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
13511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	bits_image_fetch_untransformed_repeat_none (
13521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    &image->bits, TRUE, x, y, width, buffer);
13531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
13541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    else
13551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
13561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	bits_image_fetch_untransformed_repeat_normal (
13571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    &image->bits, TRUE, x, y, width, buffer);
13581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
13591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
13601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    iter->y++;
13611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return buffer;
13621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
13631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
13641176bdada62cabc6ec4b0308a930e83b679d5d36John Recktypedef struct
13651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
13661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_format_code_t	format;
13671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t			flags;
13681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_iter_get_scanline_t	get_scanline_32;
13691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_iter_get_scanline_t  get_scanline_float;
13701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} fetcher_info_t;
13711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
13721176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic const fetcher_info_t fetcher_info[] =
13731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
13741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    { PIXMAN_any,
13751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck      (FAST_PATH_NO_ALPHA_MAP			|
13761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck       FAST_PATH_ID_TRANSFORM			|
13771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck       FAST_PATH_NO_CONVOLUTION_FILTER		|
13781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck       FAST_PATH_NO_PAD_REPEAT			|
13791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck       FAST_PATH_NO_REFLECT_REPEAT),
13801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck      bits_image_fetch_untransformed_32,
13811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck      bits_image_fetch_untransformed_float
13821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    },
13831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
13841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#define FAST_BILINEAR_FLAGS						\
13851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    (FAST_PATH_NO_ALPHA_MAP		|				\
13861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     FAST_PATH_NO_ACCESSORS		|				\
13871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     FAST_PATH_HAS_TRANSFORM		|				\
13881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     FAST_PATH_AFFINE_TRANSFORM		|				\
13891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     FAST_PATH_X_UNIT_POSITIVE		|				\
13901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     FAST_PATH_Y_UNIT_ZERO		|				\
13911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     FAST_PATH_NONE_REPEAT		|				\
13921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     FAST_PATH_BILINEAR_FILTER)
13931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
13941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    { PIXMAN_a8r8g8b8,
13951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck      FAST_BILINEAR_FLAGS,
13961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck      bits_image_fetch_bilinear_no_repeat_8888,
13971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck      _pixman_image_get_scanline_generic_float
13981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    },
13991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
14001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    { PIXMAN_x8r8g8b8,
14011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck      FAST_BILINEAR_FLAGS,
14021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck      bits_image_fetch_bilinear_no_repeat_8888,
14031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck      _pixman_image_get_scanline_generic_float
14041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    },
14051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
14061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#define GENERAL_BILINEAR_FLAGS						\
14071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    (FAST_PATH_NO_ALPHA_MAP		|				\
14081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     FAST_PATH_NO_ACCESSORS		|				\
14091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     FAST_PATH_HAS_TRANSFORM		|				\
14101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     FAST_PATH_AFFINE_TRANSFORM		|				\
14111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     FAST_PATH_BILINEAR_FILTER)
14121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
14131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#define GENERAL_NEAREST_FLAGS						\
14141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    (FAST_PATH_NO_ALPHA_MAP		|				\
14151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     FAST_PATH_NO_ACCESSORS		|				\
14161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     FAST_PATH_HAS_TRANSFORM		|				\
14171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     FAST_PATH_AFFINE_TRANSFORM		|				\
14181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     FAST_PATH_NEAREST_FILTER)
14191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
14201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#define GENERAL_SEPARABLE_CONVOLUTION_FLAGS				\
14211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    (FAST_PATH_NO_ALPHA_MAP            |				\
14221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     FAST_PATH_NO_ACCESSORS            |				\
14231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     FAST_PATH_HAS_TRANSFORM           |				\
14241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     FAST_PATH_AFFINE_TRANSFORM        |				\
14251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     FAST_PATH_SEPARABLE_CONVOLUTION_FILTER)
14261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
14271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#define SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat)   \
14281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    { PIXMAN_ ## format,                                               \
14291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck      GENERAL_SEPARABLE_CONVOLUTION_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \
14301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck      bits_image_fetch_separable_convolution_affine_ ## name,          \
14311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck      _pixman_image_get_scanline_generic_float			       \
14321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    },
14331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
14341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#define BILINEAR_AFFINE_FAST_PATH(name, format, repeat)			\
14351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    { PIXMAN_ ## format,						\
14361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck      GENERAL_BILINEAR_FLAGS | FAST_PATH_ ## repeat ## _REPEAT,		\
14371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck      bits_image_fetch_bilinear_affine_ ## name,			\
14381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck      _pixman_image_get_scanline_generic_float				\
14391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    },
14401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
14411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#define NEAREST_AFFINE_FAST_PATH(name, format, repeat)			\
14421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    { PIXMAN_ ## format,						\
14431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck      GENERAL_NEAREST_FLAGS | FAST_PATH_ ## repeat ## _REPEAT,		\
14441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck      bits_image_fetch_nearest_affine_ ## name,				\
14451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck      _pixman_image_get_scanline_generic_float				\
14461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    },
14471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
14481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#define AFFINE_FAST_PATHS(name, format, repeat)				\
14491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat)	\
14501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    BILINEAR_AFFINE_FAST_PATH(name, format, repeat)			\
14511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    NEAREST_AFFINE_FAST_PATH(name, format, repeat)
14521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
14531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    AFFINE_FAST_PATHS (pad_a8r8g8b8, a8r8g8b8, PAD)
14541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    AFFINE_FAST_PATHS (none_a8r8g8b8, a8r8g8b8, NONE)
14551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    AFFINE_FAST_PATHS (reflect_a8r8g8b8, a8r8g8b8, REFLECT)
14561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    AFFINE_FAST_PATHS (normal_a8r8g8b8, a8r8g8b8, NORMAL)
14571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    AFFINE_FAST_PATHS (pad_x8r8g8b8, x8r8g8b8, PAD)
14581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    AFFINE_FAST_PATHS (none_x8r8g8b8, x8r8g8b8, NONE)
14591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    AFFINE_FAST_PATHS (reflect_x8r8g8b8, x8r8g8b8, REFLECT)
14601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    AFFINE_FAST_PATHS (normal_x8r8g8b8, x8r8g8b8, NORMAL)
14611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    AFFINE_FAST_PATHS (pad_a8, a8, PAD)
14621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    AFFINE_FAST_PATHS (none_a8, a8, NONE)
14631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    AFFINE_FAST_PATHS (reflect_a8, a8, REFLECT)
14641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    AFFINE_FAST_PATHS (normal_a8, a8, NORMAL)
14651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    AFFINE_FAST_PATHS (pad_r5g6b5, r5g6b5, PAD)
14661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    AFFINE_FAST_PATHS (none_r5g6b5, r5g6b5, NONE)
14671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    AFFINE_FAST_PATHS (reflect_r5g6b5, r5g6b5, REFLECT)
14681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    AFFINE_FAST_PATHS (normal_r5g6b5, r5g6b5, NORMAL)
14691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
14701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /* Affine, no alpha */
14711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    { PIXMAN_any,
14721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck      (FAST_PATH_NO_ALPHA_MAP | FAST_PATH_HAS_TRANSFORM | FAST_PATH_AFFINE_TRANSFORM),
14731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck      bits_image_fetch_affine_no_alpha,
14741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck      _pixman_image_get_scanline_generic_float
14751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    },
14761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
14771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /* General */
14781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    { PIXMAN_any,
14791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck      0,
14801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck      bits_image_fetch_general,
14811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck      _pixman_image_get_scanline_generic_float
14821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    },
14831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
14841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    { PIXMAN_null },
14851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck};
14861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
14871176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic void
14881176bdada62cabc6ec4b0308a930e83b679d5d36John Reckbits_image_property_changed (pixman_image_t *image)
14891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
14901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    _pixman_bits_image_setup_accessors (&image->bits);
14911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
14921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
14931176bdada62cabc6ec4b0308a930e83b679d5d36John Reckvoid
14941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck_pixman_bits_image_src_iter_init (pixman_image_t *image, pixman_iter_t *iter)
14951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
14961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_format_code_t format = image->common.extended_format_code;
14971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t flags = image->common.flags;
14981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    const fetcher_info_t *info;
14991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
15001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    for (info = fetcher_info; info->format != PIXMAN_null; ++info)
15011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
15021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if ((info->format == format || info->format == PIXMAN_any)	&&
15031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    (info->flags & flags) == info->flags)
15041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
15051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    if (iter->iter_flags & ITER_NARROW)
15061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    {
15071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		iter->get_scanline = info->get_scanline_32;
15081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    }
15091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    else
15101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    {
15111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		iter->data = info->get_scanline_32;
15121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		iter->get_scanline = info->get_scanline_float;
15131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    }
15141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    return;
15151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
15161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
15171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
15181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /* Just in case we somehow didn't find a scanline function */
15191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    iter->get_scanline = _pixman_iter_get_scanline_noop;
15201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
15211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
15221176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic uint32_t *
15231176bdada62cabc6ec4b0308a930e83b679d5d36John Reckdest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
15241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
15251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_image_t *image  = iter->image;
15261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int             x      = iter->x;
15271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int             y      = iter->y;
15281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int             width  = iter->width;
15291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t *	    buffer = iter->buffer;
15301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
15311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    image->bits.fetch_scanline_32 (image, x, y, width, buffer, mask);
15321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (image->common.alpha_map)
15331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
15341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	uint32_t *alpha;
15351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
15361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if ((alpha = malloc (width * sizeof (uint32_t))))
15371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
15381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    int i;
15391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
15401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    x -= image->common.alpha_origin_x;
15411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    y -= image->common.alpha_origin_y;
15421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
15431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    image->common.alpha_map->fetch_scanline_32 (
15441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		(pixman_image_t *)image->common.alpha_map,
15451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		x, y, width, alpha, mask);
15461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
15471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    for (i = 0; i < width; ++i)
15481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    {
15491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		buffer[i] &= ~0xff000000;
15501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		buffer[i] |= (alpha[i] & 0xff000000);
15511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    }
15521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
15531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    free (alpha);
15541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
15551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
15561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
15571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return iter->buffer;
15581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
15591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
15601176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic uint32_t *
15611176bdada62cabc6ec4b0308a930e83b679d5d36John Reckdest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
15621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
15631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    bits_image_t *  image  = &iter->image->bits;
15641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int             x      = iter->x;
15651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int             y      = iter->y;
15661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int             width  = iter->width;
15671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    argb_t *	    buffer = (argb_t *)iter->buffer;
15681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
15691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    image->fetch_scanline_float (
15701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	(pixman_image_t *)image, x, y, width, (uint32_t *)buffer, mask);
15711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (image->common.alpha_map)
15721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
15731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	argb_t *alpha;
15741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
15751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if ((alpha = malloc (width * sizeof (argb_t))))
15761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
15771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    int i;
15781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
15791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    x -= image->common.alpha_origin_x;
15801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    y -= image->common.alpha_origin_y;
15811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
15821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    image->common.alpha_map->fetch_scanline_float (
15831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		(pixman_image_t *)image->common.alpha_map,
15841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		x, y, width, (uint32_t *)alpha, mask);
15851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
15861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    for (i = 0; i < width; ++i)
15871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		buffer[i].a = alpha[i].a;
15881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
15891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    free (alpha);
15901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
15911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
15921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
15931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return iter->buffer;
15941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
15951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
15961176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic void
15971176bdada62cabc6ec4b0308a930e83b679d5d36John Reckdest_write_back_narrow (pixman_iter_t *iter)
15981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
15991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    bits_image_t *  image  = &iter->image->bits;
16001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int             x      = iter->x;
16011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int             y      = iter->y;
16021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int             width  = iter->width;
16031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    const uint32_t *buffer = iter->buffer;
16041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
16051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    image->store_scanline_32 (image, x, y, width, buffer);
16061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
16071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (image->common.alpha_map)
16081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
16091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x -= image->common.alpha_origin_x;
16101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	y -= image->common.alpha_origin_y;
16111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
16121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	image->common.alpha_map->store_scanline_32 (
16131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    image->common.alpha_map, x, y, width, buffer);
16141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
16151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
16161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    iter->y++;
16171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
16181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
16191176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic void
16201176bdada62cabc6ec4b0308a930e83b679d5d36John Reckdest_write_back_wide (pixman_iter_t *iter)
16211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
16221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    bits_image_t *  image  = &iter->image->bits;
16231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int             x      = iter->x;
16241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int             y      = iter->y;
16251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int             width  = iter->width;
16261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    const uint32_t *buffer = iter->buffer;
16271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
16281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    image->store_scanline_float (image, x, y, width, buffer);
16291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
16301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (image->common.alpha_map)
16311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
16321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	x -= image->common.alpha_origin_x;
16331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	y -= image->common.alpha_origin_y;
16341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
16351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	image->common.alpha_map->store_scanline_float (
16361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    image->common.alpha_map, x, y, width, buffer);
16371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
16381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
16391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    iter->y++;
16401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
16411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
16421176bdada62cabc6ec4b0308a930e83b679d5d36John Reckvoid
16431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck_pixman_bits_image_dest_iter_init (pixman_image_t *image, pixman_iter_t *iter)
16441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
16451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (iter->iter_flags & ITER_NARROW)
16461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
16471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if ((iter->iter_flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) ==
16481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA))
16491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
16501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    iter->get_scanline = _pixman_iter_get_scanline_noop;
16511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
16521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	else
16531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
16541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    iter->get_scanline = dest_get_scanline_narrow;
16551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
16561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
16571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	iter->write_back = dest_write_back_narrow;
16581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
16591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    else
16601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
16611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	iter->get_scanline = dest_get_scanline_wide;
16621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	iter->write_back = dest_write_back_wide;
16631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
16641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
16651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
16661176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic uint32_t *
16671176bdada62cabc6ec4b0308a930e83b679d5d36John Reckcreate_bits (pixman_format_code_t format,
16681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck             int                  width,
16691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck             int                  height,
16701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck             int *		  rowstride_bytes,
16711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	     pixman_bool_t	  clear)
16721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
16731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int stride;
16741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    size_t buf_size;
16751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int bpp;
16761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
16771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /* what follows is a long-winded way, avoiding any possibility of integer
16781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     * overflows, of saying:
16791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     * stride = ((width * bpp + 0x1f) >> 5) * sizeof (uint32_t);
16801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     */
16811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
16821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    bpp = PIXMAN_FORMAT_BPP (format);
16831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (_pixman_multiply_overflows_int (width, bpp))
16841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return NULL;
16851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
16861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    stride = width * bpp;
16871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (_pixman_addition_overflows_int (stride, 0x1f))
16881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return NULL;
16891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
16901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    stride += 0x1f;
16911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    stride >>= 5;
16921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
16931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    stride *= sizeof (uint32_t);
16941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
16951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (_pixman_multiply_overflows_size (height, stride))
16961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return NULL;
16971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
16981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    buf_size = height * stride;
16991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
17001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (rowstride_bytes)
17011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	*rowstride_bytes = stride;
17021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
17031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (clear)
17041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return calloc (buf_size, 1);
17051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    else
17061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return malloc (buf_size);
17071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
17081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
17091176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_bool_t
17101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck_pixman_bits_image_init (pixman_image_t *     image,
17111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                         pixman_format_code_t format,
17121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                         int                  width,
17131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                         int                  height,
17141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                         uint32_t *           bits,
17151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                         int                  rowstride,
17161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			 pixman_bool_t	      clear)
17171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
17181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t *free_me = NULL;
17191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
17201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (!bits && width && height)
17211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
17221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	int rowstride_bytes;
17231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
17241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	free_me = bits = create_bits (format, width, height, &rowstride_bytes, clear);
17251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
17261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (!bits)
17271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    return FALSE;
17281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
17291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	rowstride = rowstride_bytes / (int) sizeof (uint32_t);
17301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
17311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
17321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    _pixman_image_init (image);
17331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
17341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    image->type = BITS;
17351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    image->bits.format = format;
17361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    image->bits.width = width;
17371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    image->bits.height = height;
17381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    image->bits.bits = bits;
17391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    image->bits.free_me = free_me;
17401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    image->bits.read_func = NULL;
17411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    image->bits.write_func = NULL;
17421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    image->bits.rowstride = rowstride;
17431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    image->bits.indexed = NULL;
17441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
17451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    image->common.property_changed = bits_image_property_changed;
17461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
17471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    _pixman_image_reset_clip_region (image);
17481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
17491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return TRUE;
17501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
17511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
17521176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic pixman_image_t *
17531176bdada62cabc6ec4b0308a930e83b679d5d36John Reckcreate_bits_image_internal (pixman_format_code_t format,
17541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    int                  width,
17551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    int                  height,
17561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    uint32_t *           bits,
17571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    int                  rowstride_bytes,
17581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    pixman_bool_t	 clear)
17591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
17601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_image_t *image;
17611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
17621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /* must be a whole number of uint32_t's
17631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     */
17641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return_val_if_fail (
17651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	bits == NULL || (rowstride_bytes % sizeof (uint32_t)) == 0, NULL);
17661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
17671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return_val_if_fail (PIXMAN_FORMAT_BPP (format) >= PIXMAN_FORMAT_DEPTH (format), NULL);
17681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
17691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    image = _pixman_image_allocate ();
17701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
17711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (!image)
17721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return NULL;
17731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
17741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (!_pixman_bits_image_init (image, format, width, height, bits,
17751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				  rowstride_bytes / (int) sizeof (uint32_t),
17761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				  clear))
17771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
17781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	free (image);
17791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return NULL;
17801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
17811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
17821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return image;
17831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
17841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
17851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/* If bits is NULL, a buffer will be allocated and initialized to 0 */
17861176bdada62cabc6ec4b0308a930e83b679d5d36John ReckPIXMAN_EXPORT pixman_image_t *
17871176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_image_create_bits (pixman_format_code_t format,
17881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                          int                  width,
17891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                          int                  height,
17901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                          uint32_t *           bits,
17911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                          int                  rowstride_bytes)
17921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
17931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return create_bits_image_internal (
17941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	format, width, height, bits, rowstride_bytes, TRUE);
17951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
17961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
17971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
17981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/* If bits is NULL, a buffer will be allocated and _not_ initialized */
17991176bdada62cabc6ec4b0308a930e83b679d5d36John ReckPIXMAN_EXPORT pixman_image_t *
18001176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_image_create_bits_no_clear (pixman_format_code_t format,
18011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				   int                  width,
18021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				   int                  height,
18031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				   uint32_t *           bits,
18041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				   int                  rowstride_bytes)
18051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
18061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return create_bits_image_internal (
18071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	format, width, height, bits, rowstride_bytes, FALSE);
18081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
1809