pixman-conical-gradient.c revision 1176bdada62cabc6ec4b0308a930e83b679d5d36
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 2000 SuSE, Inc. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 2007 Red Hat, Inc. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 2005 Lars Knoll & Zack Rusin, Trolltech 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Permission to use, copy, modify, distribute, and sell this software and its 8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * documentation for any purpose is hereby granted without fee, provided that 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the above copyright notice appear in all copies and that both that 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * copyright notice and this permission notice appear in supporting 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * documentation, and that the name of Keith Packard not be used in 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * advertising or publicity pertaining to distribution of the software without 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * specific, written prior permission. Keith Packard makes no 14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * representations about the suitability of this software for any purpose. It 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * is provided "as is" without express or implied warranty. 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY 20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * SOFTWARE. 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifdef HAVE_CONFIG_H 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <config.h> 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <stdlib.h> 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <math.h> 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "pixman-private.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static force_inline double 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)coordinates_to_parameter (double x, double y, double angle) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double t; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t = atan2 (y, x) + angle; 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (t < 0) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t += 2 * M_PI; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (t >= 2 * M_PI) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t -= 2 * M_PI; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1 - t * (1 / (2 * M_PI)); /* Scale t to [0, 1] and 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * make rotation CCW 5003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) */ 5103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 5203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 5303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)static uint32_t * 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)conical_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pixman_image_t *image = iter->image; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x = iter->x; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int y = iter->y; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int width = iter->width; 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint32_t *buffer = iter->buffer; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gradient_t *gradient = (gradient_t *)image; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) conical_gradient_t *conical = (conical_gradient_t *)image; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t *end = buffer + width; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pixman_gradient_walker_t walker; 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pixman_bool_t affine = TRUE; 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) double cx = 1.; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double cy = 0.; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double cz = 0.; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double rx = x + 0.5; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double ry = y + 0.5; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double rz = 1.; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 74 _pixman_gradient_walker_init (&walker, gradient, image->common.repeat); 75 76 if (image->common.transform) 77 { 78 pixman_vector_t v; 79 80 /* reference point is the center of the pixel */ 81 v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2; 82 v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2; 83 v.vector[2] = pixman_fixed_1; 84 85 if (!pixman_transform_point_3d (image->common.transform, &v)) 86 return iter->buffer; 87 88 cx = image->common.transform->matrix[0][0] / 65536.; 89 cy = image->common.transform->matrix[1][0] / 65536.; 90 cz = image->common.transform->matrix[2][0] / 65536.; 91 92 rx = v.vector[0] / 65536.; 93 ry = v.vector[1] / 65536.; 94 rz = v.vector[2] / 65536.; 95 96 affine = 97 image->common.transform->matrix[2][0] == 0 && 98 v.vector[2] == pixman_fixed_1; 99 } 100 101 if (affine) 102 { 103 rx -= conical->center.x / 65536.; 104 ry -= conical->center.y / 65536.; 105 106 while (buffer < end) 107 { 108 if (!mask || *mask++) 109 { 110 double t = coordinates_to_parameter (rx, ry, conical->angle); 111 112 *buffer = _pixman_gradient_walker_pixel ( 113 &walker, (pixman_fixed_48_16_t)pixman_double_to_fixed (t)); 114 } 115 116 ++buffer; 117 118 rx += cx; 119 ry += cy; 120 } 121 } 122 else 123 { 124 while (buffer < end) 125 { 126 double x, y; 127 128 if (!mask || *mask++) 129 { 130 double t; 131 132 if (rz != 0) 133 { 134 x = rx / rz; 135 y = ry / rz; 136 } 137 else 138 { 139 x = y = 0.; 140 } 141 142 x -= conical->center.x / 65536.; 143 y -= conical->center.y / 65536.; 144 145 t = coordinates_to_parameter (x, y, conical->angle); 146 147 *buffer = _pixman_gradient_walker_pixel ( 148 &walker, (pixman_fixed_48_16_t)pixman_double_to_fixed (t)); 149 } 150 151 ++buffer; 152 153 rx += cx; 154 ry += cy; 155 rz += cz; 156 } 157 } 158 159 iter->y++; 160 return iter->buffer; 161} 162 163static uint32_t * 164conical_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask) 165{ 166 uint32_t *buffer = conical_get_scanline_narrow (iter, NULL); 167 168 pixman_expand_to_float ( 169 (argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width); 170 171 return buffer; 172} 173 174void 175_pixman_conical_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter) 176{ 177 if (iter->iter_flags & ITER_NARROW) 178 iter->get_scanline = conical_get_scanline_narrow; 179 else 180 iter->get_scanline = conical_get_scanline_wide; 181} 182 183PIXMAN_EXPORT pixman_image_t * 184pixman_image_create_conical_gradient (const pixman_point_fixed_t * center, 185 pixman_fixed_t angle, 186 const pixman_gradient_stop_t *stops, 187 int n_stops) 188{ 189 pixman_image_t *image = _pixman_image_allocate (); 190 conical_gradient_t *conical; 191 192 if (!image) 193 return NULL; 194 195 conical = &image->conical; 196 197 if (!_pixman_init_gradient (&conical->common, stops, n_stops)) 198 { 199 free (image); 200 return NULL; 201 } 202 203 angle = MOD (angle, pixman_int_to_fixed (360)); 204 205 image->type = CONICAL; 206 207 conical->center = *center; 208 conical->angle = (pixman_fixed_to_double (angle) / 180.0) * M_PI; 209 210 return image; 211} 212 213