11176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/* 21176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Copyright © 2000 SuSE, Inc. 31176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Copyright © 2007 Red Hat, Inc. 41176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. 51176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 2005 Lars Knoll & Zack Rusin, Trolltech 61176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 71176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Permission to use, copy, modify, distribute, and sell this software and its 81176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * documentation for any purpose is hereby granted without fee, provided that 91176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * the above copyright notice appear in all copies and that both that 101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * copyright notice and this permission notice appear in supporting 111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * documentation, and that the name of Keith Packard not be used in 121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * advertising or publicity pertaining to distribution of the software without 131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * specific, written prior permission. Keith Packard makes no 141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * representations about the suitability of this software for any purpose. It 151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * is provided "as is" without express or implied warranty. 161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY 201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * SOFTWARE. 251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */ 261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifdef HAVE_CONFIG_H 281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include <config.h> 291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif 301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include <stdlib.h> 321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include <math.h> 331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include "pixman-private.h" 341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 351176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic force_inline double 361176bdada62cabc6ec4b0308a930e83b679d5d36John Reckcoordinates_to_parameter (double x, double y, double angle) 371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck double t; 391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck t = atan2 (y, x) + angle; 411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck while (t < 0) 431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck t += 2 * M_PI; 441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck while (t >= 2 * M_PI) 461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck t -= 2 * M_PI; 471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return 1 - t * (1 / (2 * M_PI)); /* Scale t to [0, 1] and 491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * make rotation CCW 501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */ 511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 531176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic uint32_t * 541176bdada62cabc6ec4b0308a930e83b679d5d36John Reckconical_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask) 551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_image_t *image = iter->image; 571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int x = iter->x; 581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int y = iter->y; 591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int width = iter->width; 601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck uint32_t *buffer = iter->buffer; 611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck gradient_t *gradient = (gradient_t *)image; 631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck conical_gradient_t *conical = (conical_gradient_t *)image; 641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck uint32_t *end = buffer + width; 651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_gradient_walker_t walker; 661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_bool_t affine = TRUE; 671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck double cx = 1.; 681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck double cy = 0.; 691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck double cz = 0.; 701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck double rx = x + 0.5; 711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck double ry = y + 0.5; 721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck double rz = 1.; 731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck _pixman_gradient_walker_init (&walker, gradient, image->common.repeat); 751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (image->common.transform) 771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_vector_t v; 791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck /* reference point is the center of the pixel */ 811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2; 821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2; 831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck v.vector[2] = pixman_fixed_1; 841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (!pixman_transform_point_3d (image->common.transform, &v)) 861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return iter->buffer; 871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck cx = image->common.transform->matrix[0][0] / 65536.; 891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck cy = image->common.transform->matrix[1][0] / 65536.; 901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck cz = image->common.transform->matrix[2][0] / 65536.; 911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck rx = v.vector[0] / 65536.; 931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck ry = v.vector[1] / 65536.; 941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck rz = v.vector[2] / 65536.; 951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck affine = 971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck image->common.transform->matrix[2][0] == 0 && 981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck v.vector[2] == pixman_fixed_1; 991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (affine) 1021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck rx -= conical->center.x / 65536.; 1041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck ry -= conical->center.y / 65536.; 1051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck while (buffer < end) 1071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (!mask || *mask++) 1091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck double t = coordinates_to_parameter (rx, ry, conical->angle); 1111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *buffer = _pixman_gradient_walker_pixel ( 1131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck &walker, (pixman_fixed_48_16_t)pixman_double_to_fixed (t)); 1141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck ++buffer; 1171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck rx += cx; 1191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck ry += cy; 1201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck else 1231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck while (buffer < end) 1251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck double x, y; 1271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (!mask || *mask++) 1291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck double t; 1311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (rz != 0) 1331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck x = rx / rz; 1351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck y = ry / rz; 1361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck else 1381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck x = y = 0.; 1401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck x -= conical->center.x / 65536.; 1431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck y -= conical->center.y / 65536.; 1441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck t = coordinates_to_parameter (x, y, conical->angle); 1461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *buffer = _pixman_gradient_walker_pixel ( 1481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck &walker, (pixman_fixed_48_16_t)pixman_double_to_fixed (t)); 1491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck ++buffer; 1521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck rx += cx; 1541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck ry += cy; 1551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck rz += cz; 1561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck iter->y++; 1601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return iter->buffer; 1611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 1621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1631176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic uint32_t * 1641176bdada62cabc6ec4b0308a930e83b679d5d36John Reckconical_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask) 1651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 1661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck uint32_t *buffer = conical_get_scanline_narrow (iter, NULL); 1671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_expand_to_float ( 1691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck (argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width); 1701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return buffer; 1721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 1731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1741176bdada62cabc6ec4b0308a930e83b679d5d36John Reckvoid 1751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck_pixman_conical_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter) 1761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 1771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (iter->iter_flags & ITER_NARROW) 1781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck iter->get_scanline = conical_get_scanline_narrow; 1791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck else 1801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck iter->get_scanline = conical_get_scanline_wide; 1811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 1821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1831176bdada62cabc6ec4b0308a930e83b679d5d36John ReckPIXMAN_EXPORT pixman_image_t * 1841176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_image_create_conical_gradient (const pixman_point_fixed_t * center, 1851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_fixed_t angle, 1861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck const pixman_gradient_stop_t *stops, 1871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int n_stops) 1881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 1891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_image_t *image = _pixman_image_allocate (); 1901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck conical_gradient_t *conical; 1911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (!image) 1931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return NULL; 1941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck conical = &image->conical; 1961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (!_pixman_init_gradient (&conical->common, stops, n_stops)) 1981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck free (image); 2001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return NULL; 2011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 2021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck angle = MOD (angle, pixman_int_to_fixed (360)); 2041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck image->type = CONICAL; 2061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck conical->center = *center; 2081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck conical->angle = (pixman_fixed_to_double (angle) / 180.0) * M_PI; 2091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return image; 2111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 2121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 213