11176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/*
21176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
31176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Copyright © 2004 Keith Packard
41176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *
51176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Permission to use, copy, modify, distribute, and sell this software and its
61176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * documentation for any purpose is hereby granted without fee, provided that
71176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * the above copyright notice appear in all copies and that both that
81176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * copyright notice and this permission notice appear in supporting
91176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * documentation, and that the name of Keith Packard not be used in
101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * advertising or publicity pertaining to distribution of the software without
111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * specific, written prior permission.  Keith Packard makes no
121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * representations about the suitability of this software for any purpose.  It
131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * is provided "as is" without express or implied warranty.
141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *
151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * PERFORMANCE OF THIS SOFTWARE.
221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */
231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifdef HAVE_CONFIG_H
251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include <config.h>
261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include <stdio.h>
291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include <stdlib.h>
301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include "pixman-private.h"
311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/*
331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Compute the smallest value greater than or equal to y which is on a
341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * grid row.
351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */
361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
371176bdada62cabc6ec4b0308a930e83b679d5d36John ReckPIXMAN_EXPORT pixman_fixed_t
381176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_sample_ceil_y (pixman_fixed_t y, int n)
391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t f = pixman_fixed_frac (y);
411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t i = pixman_fixed_floor (y);
421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    f = DIV (f - Y_FRAC_FIRST (n) + (STEP_Y_SMALL (n) - pixman_fixed_e), STEP_Y_SMALL (n)) * STEP_Y_SMALL (n) +
441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	Y_FRAC_FIRST (n);
451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (f > Y_FRAC_LAST (n))
471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (pixman_fixed_to_int (i) == 0x7fff)
491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    f = 0xffff; /* saturate */
511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	else
531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    f = Y_FRAC_FIRST (n);
551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    i += pixman_fixed_1;
561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return (i | f);
591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/*
621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Compute the largest value strictly less than y which is on a
631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * grid row.
641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */
651176bdada62cabc6ec4b0308a930e83b679d5d36John ReckPIXMAN_EXPORT pixman_fixed_t
661176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_sample_floor_y (pixman_fixed_t y,
671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                       int            n)
681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t f = pixman_fixed_frac (y);
701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t i = pixman_fixed_floor (y);
711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    f = DIV (f - pixman_fixed_e - Y_FRAC_FIRST (n), STEP_Y_SMALL (n)) * STEP_Y_SMALL (n) +
731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	Y_FRAC_FIRST (n);
741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (f < Y_FRAC_FIRST (n))
761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (pixman_fixed_to_int (i) == 0x8000)
781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    f = 0; /* saturate */
801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	else
821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    f = Y_FRAC_LAST (n);
841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    i -= pixman_fixed_1;
851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return (i | f);
881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/*
911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Step an edge by any amount (including negative values)
921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */
931176bdada62cabc6ec4b0308a930e83b679d5d36John ReckPIXMAN_EXPORT void
941176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_edge_step (pixman_edge_t *e,
951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                  int            n)
961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_48_16_t ne;
981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    e->x += n * e->stepx;
1001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    ne = e->e + n * (pixman_fixed_48_16_t) e->dx;
1021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (n >= 0)
1041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
1051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (ne > 0)
1061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
1071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    int nx = (ne + e->dy - 1) / e->dy;
1081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    e->e = ne - nx * (pixman_fixed_48_16_t) e->dy;
1091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    e->x += nx * e->signdx;
1101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
1111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
1121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    else
1131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
1141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (ne <= -e->dy)
1151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
1161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    int nx = (-ne) / e->dy;
1171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    e->e = ne + nx * (pixman_fixed_48_16_t) e->dy;
1181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    e->x -= nx * e->signdx;
1191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
1201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
1211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
1221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/*
1241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * A private routine to initialize the multi-step
1251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * elements of an edge structure
1261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */
1271176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic void
1281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck_pixman_edge_multi_init (pixman_edge_t * e,
1291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                         int             n,
1301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                         pixman_fixed_t *stepx_p,
1311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                         pixman_fixed_t *dx_p)
1321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
1331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t stepx;
1341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_48_16_t ne;
1351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    ne = n * (pixman_fixed_48_16_t) e->dx;
1371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    stepx = n * e->stepx;
1381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (ne > 0)
1401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
1411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	int nx = ne / e->dy;
1421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	ne -= nx * (pixman_fixed_48_16_t)e->dy;
1431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	stepx += nx * e->signdx;
1441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
1451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    *dx_p = ne;
1471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    *stepx_p = stepx;
1481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
1491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/*
1511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Initialize one edge structure given the line endpoints and a
1521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * starting y value
1531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */
1541176bdada62cabc6ec4b0308a930e83b679d5d36John ReckPIXMAN_EXPORT void
1551176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_edge_init (pixman_edge_t *e,
1561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                  int            n,
1571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                  pixman_fixed_t y_start,
1581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                  pixman_fixed_t x_top,
1591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                  pixman_fixed_t y_top,
1601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                  pixman_fixed_t x_bot,
1611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                  pixman_fixed_t y_bot)
1621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
1631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t dx, dy;
1641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    e->x = x_top;
1661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    e->e = 0;
1671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    dx = x_bot - x_top;
1681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    dy = y_bot - y_top;
1691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    e->dy = dy;
1701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    e->dx = 0;
1711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (dy)
1731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
1741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (dx >= 0)
1751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
1761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    e->signdx = 1;
1771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    e->stepx = dx / dy;
1781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    e->dx = dx % dy;
1791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    e->e = -dy;
1801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
1811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	else
1821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
1831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    e->signdx = -1;
1841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    e->stepx = -(-dx / dy);
1851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    e->dx = -dx % dy;
1861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    e->e = 0;
1871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
1881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	_pixman_edge_multi_init (e, STEP_Y_SMALL (n),
1901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				 &e->stepx_small, &e->dx_small);
1911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	_pixman_edge_multi_init (e, STEP_Y_BIG (n),
1931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				 &e->stepx_big, &e->dx_big);
1941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
1951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_edge_step (e, y_start - y_top);
1961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
1971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/*
1991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Initialize one edge structure given a line, starting y value
2001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * and a pixel offset for the line
2011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */
2021176bdada62cabc6ec4b0308a930e83b679d5d36John ReckPIXMAN_EXPORT void
2031176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_line_fixed_edge_init (pixman_edge_t *            e,
2041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                             int                        n,
2051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                             pixman_fixed_t             y,
2061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                             const pixman_line_fixed_t *line,
2071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                             int                        x_off,
2081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                             int                        y_off)
2091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
2101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t x_off_fixed = pixman_int_to_fixed (x_off);
2111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t y_off_fixed = pixman_int_to_fixed (y_off);
2121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    const pixman_point_fixed_t *top, *bot;
2131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (line->p1.y <= line->p2.y)
2151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
2161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	top = &line->p1;
2171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	bot = &line->p2;
2181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
2191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    else
2201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
2211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	top = &line->p2;
2221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	bot = &line->p1;
2231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
2241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_edge_init (e, n, y,
2261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                      top->x + x_off_fixed,
2271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                      top->y + y_off_fixed,
2281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                      bot->x + x_off_fixed,
2291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                      bot->y + y_off_fixed);
2301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
2311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2321176bdada62cabc6ec4b0308a930e83b679d5d36John ReckPIXMAN_EXPORT void
2331176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_add_traps (pixman_image_t *     image,
2341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                  int16_t              x_off,
2351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                  int16_t              y_off,
2361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                  int                  ntrap,
2371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                  const pixman_trap_t *traps)
2381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
2391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int bpp;
2401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int height;
2411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t x_off_fixed;
2431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t y_off_fixed;
2441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_edge_t l, r;
2451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t t, b;
2461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    _pixman_image_validate (image);
2481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    height = image->bits.height;
2501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    bpp = PIXMAN_FORMAT_BPP (image->bits.format);
2511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    x_off_fixed = pixman_int_to_fixed (x_off);
2531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    y_off_fixed = pixman_int_to_fixed (y_off);
2541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    while (ntrap--)
2561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
2571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	t = traps->top.y + y_off_fixed;
2581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (t < 0)
2591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    t = 0;
2601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	t = pixman_sample_ceil_y (t, bpp);
2611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	b = traps->bot.y + y_off_fixed;
2631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (pixman_fixed_to_int (b) >= height)
2641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    b = pixman_int_to_fixed (height) - 1;
2651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	b = pixman_sample_floor_y (b, bpp);
2661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (b >= t)
2681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
2691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    /* initialize edge walkers */
2701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    pixman_edge_init (&l, bpp, t,
2711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	                      traps->top.l + x_off_fixed,
2721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	                      traps->top.y + y_off_fixed,
2731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	                      traps->bot.l + x_off_fixed,
2741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	                      traps->bot.y + y_off_fixed);
2751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    pixman_edge_init (&r, bpp, t,
2771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	                      traps->top.r + x_off_fixed,
2781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	                      traps->top.y + y_off_fixed,
2791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	                      traps->bot.r + x_off_fixed,
2801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	                      traps->bot.y + y_off_fixed);
2811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    pixman_rasterize_edges (image, &l, &r, t, b);
2831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
2841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	traps++;
2861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
2871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
2881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#if 0
2901176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic void
2911176bdada62cabc6ec4b0308a930e83b679d5d36John Reckdump_image (pixman_image_t *image,
2921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            const char *    title)
2931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
2941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int i, j;
2951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (!image->type == BITS)
2971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	printf ("%s is not a regular image\n", title);
2981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (!image->bits.format == PIXMAN_a8)
3001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	printf ("%s is not an alpha mask\n", title);
3011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    printf ("\n\n\n%s: \n", title);
3031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    for (i = 0; i < image->bits.height; ++i)
3051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
3061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	uint8_t *line =
3071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    (uint8_t *)&(image->bits.bits[i * image->bits.rowstride]);
3081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	for (j = 0; j < image->bits.width; ++j)
3101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    printf ("%c", line[j] ? '#' : ' ');
3111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	printf ("\n");
3131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
3141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
3151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
3161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3171176bdada62cabc6ec4b0308a930e83b679d5d36John ReckPIXMAN_EXPORT void
3181176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_add_trapezoids (pixman_image_t *          image,
3191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                       int16_t                   x_off,
3201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                       int                       y_off,
3211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                       int                       ntraps,
3221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                       const pixman_trapezoid_t *traps)
3231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
3241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int i;
3251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#if 0
3271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    dump_image (image, "before");
3281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
3291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    for (i = 0; i < ntraps; ++i)
3311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
3321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	const pixman_trapezoid_t *trap = &(traps[i]);
3331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (!pixman_trapezoid_valid (trap))
3351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    continue;
3361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	pixman_rasterize_trapezoid (image, trap, x_off, y_off);
3381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
3391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#if 0
3411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    dump_image (image, "after");
3421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
3431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
3441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3451176bdada62cabc6ec4b0308a930e83b679d5d36John ReckPIXMAN_EXPORT void
3461176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_rasterize_trapezoid (pixman_image_t *          image,
3471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                            const pixman_trapezoid_t *trap,
3481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                            int                       x_off,
3491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                            int                       y_off)
3501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
3511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int bpp;
3521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int height;
3531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t y_off_fixed;
3551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_edge_t l, r;
3561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t t, b;
3571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return_if_fail (image->type == BITS);
3591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    _pixman_image_validate (image);
3611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (!pixman_trapezoid_valid (trap))
3631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return;
3641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    height = image->bits.height;
3661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    bpp = PIXMAN_FORMAT_BPP (image->bits.format);
3671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    y_off_fixed = pixman_int_to_fixed (y_off);
3691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    t = trap->top + y_off_fixed;
3711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (t < 0)
3721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	t = 0;
3731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    t = pixman_sample_ceil_y (t, bpp);
3741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    b = trap->bottom + y_off_fixed;
3761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (pixman_fixed_to_int (b) >= height)
3771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	b = pixman_int_to_fixed (height) - 1;
3781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    b = pixman_sample_floor_y (b, bpp);
3791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (b >= t)
3811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
3821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	/* initialize edge walkers */
3831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	pixman_line_fixed_edge_init (&l, bpp, t, &trap->left, x_off, y_off);
3841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	pixman_line_fixed_edge_init (&r, bpp, t, &trap->right, x_off, y_off);
3851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	pixman_rasterize_edges (image, &l, &r, t, b);
3871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
3881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
3891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
3901176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic const pixman_bool_t zero_src_has_no_effect[PIXMAN_N_OPERATORS] =
3911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
3921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    FALSE,	/* Clear		0			0    */
3931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    FALSE,	/* Src			1			0    */
3941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    TRUE,	/* Dst			0			1    */
3951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    TRUE,	/* Over			1			1-Aa */
3961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    TRUE,	/* OverReverse		1-Ab			1    */
3971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    FALSE,	/* In			Ab			0    */
3981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    FALSE,	/* InReverse		0			Aa   */
3991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    FALSE,	/* Out			1-Ab			0    */
4001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    TRUE,	/* OutReverse		0			1-Aa */
4011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    TRUE,	/* Atop			Ab			1-Aa */
4021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    FALSE,	/* AtopReverse		1-Ab			Aa   */
4031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    TRUE,	/* Xor			1-Ab			1-Aa */
4041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    TRUE,	/* Add			1			1    */
4051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck};
4061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4071176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic pixman_bool_t
4081176bdada62cabc6ec4b0308a930e83b679d5d36John Reckget_trap_extents (pixman_op_t op, pixman_image_t *dest,
4091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		  const pixman_trapezoid_t *traps, int n_traps,
4101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		  pixman_box32_t *box)
4111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
4121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int i;
4131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /* When the operator is such that a zero source has an
4151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     * effect on the underlying image, we have to
4161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     * composite across the entire destination
4171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     */
4181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (!zero_src_has_no_effect [op])
4191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
4201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	box->x1 = 0;
4211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	box->y1 = 0;
4221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	box->x2 = dest->bits.width;
4231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	box->y2 = dest->bits.height;
4241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return TRUE;
4251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
4261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    box->x1 = INT32_MAX;
4281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    box->y1 = INT32_MAX;
4291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    box->x2 = INT32_MIN;
4301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    box->y2 = INT32_MIN;
4311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    for (i = 0; i < n_traps; ++i)
4331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
4341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	const pixman_trapezoid_t *trap = &(traps[i]);
4351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	int y1, y2;
4361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (!pixman_trapezoid_valid (trap))
4381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    continue;
4391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	y1 = pixman_fixed_to_int (trap->top);
4411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (y1 < box->y1)
4421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    box->y1 = y1;
4431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	y2 = pixman_fixed_to_int (pixman_fixed_ceil (trap->bottom));
4451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (y2 > box->y2)
4461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    box->y2 = y2;
4471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#define EXTEND_MIN(x)							\
4491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (pixman_fixed_to_int ((x)) < box->x1)			\
4501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    box->x1 = pixman_fixed_to_int ((x));
4511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#define EXTEND_MAX(x)							\
4521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (pixman_fixed_to_int (pixman_fixed_ceil ((x))) > box->x2)	\
4531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    box->x2 = pixman_fixed_to_int (pixman_fixed_ceil ((x)));
4541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#define EXTEND(x)							\
4561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	EXTEND_MIN(x);							\
4571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	EXTEND_MAX(x);
4581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	EXTEND(trap->left.p1.x);
4601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	EXTEND(trap->left.p2.x);
4611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	EXTEND(trap->right.p1.x);
4621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	EXTEND(trap->right.p2.x);
4631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
4641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (box->x1 >= box->x2 || box->y1 >= box->y2)
4661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return FALSE;
4671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return TRUE;
4691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
4701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/*
4721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * pixman_composite_trapezoids()
4731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *
4741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * All the trapezoids are conceptually rendered to an infinitely big image.
4751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * The (0, 0) coordinates of this image are then aligned with the (x, y)
4761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * coordinates of the source image, and then both images are aligned with
4771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * the (x, y) coordinates of the destination. Then these three images are
4781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * composited across the entire destination.
4791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */
4801176bdada62cabc6ec4b0308a930e83b679d5d36John ReckPIXMAN_EXPORT void
4811176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_composite_trapezoids (pixman_op_t		op,
4821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			     pixman_image_t *		src,
4831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			     pixman_image_t *		dst,
4841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			     pixman_format_code_t	mask_format,
4851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			     int			x_src,
4861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			     int			y_src,
4871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			     int			x_dst,
4881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			     int			y_dst,
4891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			     int			n_traps,
4901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			     const pixman_trapezoid_t *	traps)
4911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
4921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int i;
4931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return_if_fail (PIXMAN_FORMAT_TYPE (mask_format) == PIXMAN_TYPE_A);
4951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (n_traps <= 0)
4971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return;
4981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
4991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    _pixman_image_validate (src);
5001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    _pixman_image_validate (dst);
5011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (op == PIXMAN_OP_ADD &&
5031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	(src->common.flags & FAST_PATH_IS_OPAQUE)		&&
5041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	(mask_format == dst->common.extended_format_code)	&&
5051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	!(dst->common.have_clip_region))
5061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
5071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	for (i = 0; i < n_traps; ++i)
5081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
5091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    const pixman_trapezoid_t *trap = &(traps[i]);
5101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    if (!pixman_trapezoid_valid (trap))
5121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		continue;
5131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    pixman_rasterize_trapezoid (dst, trap, x_dst, y_dst);
5151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
5161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
5171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    else
5181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
5191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	pixman_image_t *tmp;
5201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	pixman_box32_t box;
5211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	int i;
5221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (!get_trap_extents (op, dst, traps, n_traps, &box))
5241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    return;
5251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (!(tmp = pixman_image_create_bits (
5271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		  mask_format, box.x2 - box.x1, box.y2 - box.y1, NULL, -1)))
5281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    return;
5291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	for (i = 0; i < n_traps; ++i)
5311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
5321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    const pixman_trapezoid_t *trap = &(traps[i]);
5331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    if (!pixman_trapezoid_valid (trap))
5351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		continue;
5361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    pixman_rasterize_trapezoid (tmp, trap, - box.x1, - box.y1);
5381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
5391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	pixman_image_composite (op, src, tmp, dst,
5411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				x_src + box.x1, y_src + box.y1,
5421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				0, 0,
5431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				x_dst + box.x1, y_dst + box.y1,
5441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				box.x2 - box.x1, box.y2 - box.y1);
5451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	pixman_image_unref (tmp);
5471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
5481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
5491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5501176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic int
5511176bdada62cabc6ec4b0308a930e83b679d5d36John Reckgreater_y (const pixman_point_fixed_t *a, const pixman_point_fixed_t *b)
5521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
5531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (a->y == b->y)
5541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return a->x > b->x;
5551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return a->y > b->y;
5561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
5571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/*
5591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Note that the definition of this function is a bit odd because
5601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * of the X coordinate space (y increasing downwards).
5611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */
5621176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic int
5631176bdada62cabc6ec4b0308a930e83b679d5d36John Reckclockwise (const pixman_point_fixed_t *ref,
5641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	   const pixman_point_fixed_t *a,
5651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	   const pixman_point_fixed_t *b)
5661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
5671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_point_fixed_t	ad, bd;
5681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    ad.x = a->x - ref->x;
5701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    ad.y = a->y - ref->y;
5711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    bd.x = b->x - ref->x;
5721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    bd.y = b->y - ref->y;
5731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return ((pixman_fixed_32_32_t) bd.y * ad.x -
5751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    (pixman_fixed_32_32_t) ad.y * bd.x) < 0;
5761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
5771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5781176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic void
5791176bdada62cabc6ec4b0308a930e83b679d5d36John Recktriangle_to_trapezoids (const pixman_triangle_t *tri, pixman_trapezoid_t *traps)
5801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
5811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    const pixman_point_fixed_t *top, *left, *right, *tmp;
5821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    top = &tri->p1;
5841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    left = &tri->p2;
5851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    right = &tri->p3;
5861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (greater_y (top, left))
5881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
5891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	tmp = left;
5901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	left = top;
5911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	top = tmp;
5921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
5931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
5941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (greater_y (top, right))
5951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
5961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	tmp = right;
5971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	right = top;
5981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	top = tmp;
5991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
6001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (clockwise (top, right, left))
6021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
6031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	tmp = right;
6041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	right = left;
6051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	left = tmp;
6061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
6071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /*
6091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     * Two cases:
6101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     *
6111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     *		+		+
6121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     *	       / \             / \
6131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     *	      /   \           /	  \
6141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     *	     /     +         +	   \
6151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     *      /    --           --    \
6161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     *     /   --               --   \
6171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     *    / ---                   --- \
6181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     *	 +--                         --+
6191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     */
6201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    traps->top = top->y;
6221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    traps->left.p1 = *top;
6231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    traps->left.p2 = *left;
6241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    traps->right.p1 = *top;
6251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    traps->right.p2 = *right;
6261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (right->y < left->y)
6281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	traps->bottom = right->y;
6291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    else
6301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	traps->bottom = left->y;
6311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    traps++;
6331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    *traps = *(traps - 1);
6351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (right->y < left->y)
6371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
6381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	traps->top = right->y;
6391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	traps->bottom = left->y;
6401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	traps->right.p1 = *right;
6411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	traps->right.p2 = *left;
6421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
6431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    else
6441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
6451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	traps->top = left->y;
6461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	traps->bottom = right->y;
6471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	traps->left.p1 = *left;
6481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	traps->left.p2 = *right;
6491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
6501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
6511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6521176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic pixman_trapezoid_t *
6531176bdada62cabc6ec4b0308a930e83b679d5d36John Reckconvert_triangles (int n_tris, const pixman_triangle_t *tris)
6541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
6551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_trapezoid_t *traps;
6561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int i;
6571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (n_tris <= 0)
6591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return NULL;
6601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    traps = pixman_malloc_ab (n_tris, 2 * sizeof (pixman_trapezoid_t));
6621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (!traps)
6631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return NULL;
6641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    for (i = 0; i < n_tris; ++i)
6661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	triangle_to_trapezoids (&(tris[i]), traps + 2 * i);
6671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return traps;
6691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
6701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6711176bdada62cabc6ec4b0308a930e83b679d5d36John ReckPIXMAN_EXPORT void
6721176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_composite_triangles (pixman_op_t			op,
6731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    pixman_image_t *		src,
6741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    pixman_image_t *		dst,
6751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    pixman_format_code_t	mask_format,
6761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    int				x_src,
6771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    int				y_src,
6781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    int				x_dst,
6791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    int				y_dst,
6801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    int				n_tris,
6811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    const pixman_triangle_t *	tris)
6821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
6831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_trapezoid_t *traps;
6841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if ((traps = convert_triangles (n_tris, tris)))
6861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
6871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	pixman_composite_trapezoids (op, src, dst, mask_format,
6881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				     x_src, y_src, x_dst, y_dst,
6891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck				     n_tris * 2, traps);
6901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	free (traps);
6921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
6931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
6941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
6951176bdada62cabc6ec4b0308a930e83b679d5d36John ReckPIXMAN_EXPORT void
6961176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_add_triangles (pixman_image_t          *image,
6971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		      int32_t	               x_off,
6981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		      int32_t	               y_off,
6991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		      int	               n_tris,
7001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		      const pixman_triangle_t *tris)
7011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
7021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_trapezoid_t *traps;
7031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
7041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if ((traps = convert_triangles (n_tris, tris)))
7051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
7061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	pixman_add_trapezoids (image, x_off, y_off,
7071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			       n_tris * 2, traps);
7081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
7091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	free (traps);
7101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
7111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
712