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