1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/cairo/libpixman/src/pixman-conical-gradient.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,212 @@ 1.4 +/* 1.5 + * Copyright © 2000 SuSE, Inc. 1.6 + * Copyright © 2007 Red Hat, Inc. 1.7 + * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. 1.8 + * 2005 Lars Knoll & Zack Rusin, Trolltech 1.9 + * 1.10 + * Permission to use, copy, modify, distribute, and sell this software and its 1.11 + * documentation for any purpose is hereby granted without fee, provided that 1.12 + * the above copyright notice appear in all copies and that both that 1.13 + * copyright notice and this permission notice appear in supporting 1.14 + * documentation, and that the name of Keith Packard not be used in 1.15 + * advertising or publicity pertaining to distribution of the software without 1.16 + * specific, written prior permission. Keith Packard makes no 1.17 + * representations about the suitability of this software for any purpose. It 1.18 + * is provided "as is" without express or implied warranty. 1.19 + * 1.20 + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 1.21 + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 1.22 + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY 1.23 + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1.24 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 1.25 + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 1.26 + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 1.27 + * SOFTWARE. 1.28 + */ 1.29 + 1.30 +#ifdef HAVE_CONFIG_H 1.31 +#include <config.h> 1.32 +#endif 1.33 + 1.34 +#include <stdlib.h> 1.35 +#include <math.h> 1.36 +#include "pixman-private.h" 1.37 + 1.38 +static force_inline double 1.39 +coordinates_to_parameter (double x, double y, double angle) 1.40 +{ 1.41 + double t; 1.42 + 1.43 + t = atan2 (y, x) + angle; 1.44 + 1.45 + while (t < 0) 1.46 + t += 2 * M_PI; 1.47 + 1.48 + while (t >= 2 * M_PI) 1.49 + t -= 2 * M_PI; 1.50 + 1.51 + return 1 - t * (1 / (2 * M_PI)); /* Scale t to [0, 1] and 1.52 + * make rotation CCW 1.53 + */ 1.54 +} 1.55 + 1.56 +static uint32_t * 1.57 +conical_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask) 1.58 +{ 1.59 + pixman_image_t *image = iter->image; 1.60 + int x = iter->x; 1.61 + int y = iter->y; 1.62 + int width = iter->width; 1.63 + uint32_t *buffer = iter->buffer; 1.64 + 1.65 + gradient_t *gradient = (gradient_t *)image; 1.66 + conical_gradient_t *conical = (conical_gradient_t *)image; 1.67 + uint32_t *end = buffer + width; 1.68 + pixman_gradient_walker_t walker; 1.69 + pixman_bool_t affine = TRUE; 1.70 + double cx = 1.; 1.71 + double cy = 0.; 1.72 + double cz = 0.; 1.73 + double rx = x + 0.5; 1.74 + double ry = y + 0.5; 1.75 + double rz = 1.; 1.76 + 1.77 + _pixman_gradient_walker_init (&walker, gradient, image->common.repeat); 1.78 + 1.79 + if (image->common.transform) 1.80 + { 1.81 + pixman_vector_t v; 1.82 + 1.83 + /* reference point is the center of the pixel */ 1.84 + v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2; 1.85 + v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2; 1.86 + v.vector[2] = pixman_fixed_1; 1.87 + 1.88 + if (!pixman_transform_point_3d (image->common.transform, &v)) 1.89 + return iter->buffer; 1.90 + 1.91 + cx = image->common.transform->matrix[0][0] / 65536.; 1.92 + cy = image->common.transform->matrix[1][0] / 65536.; 1.93 + cz = image->common.transform->matrix[2][0] / 65536.; 1.94 + 1.95 + rx = v.vector[0] / 65536.; 1.96 + ry = v.vector[1] / 65536.; 1.97 + rz = v.vector[2] / 65536.; 1.98 + 1.99 + affine = 1.100 + image->common.transform->matrix[2][0] == 0 && 1.101 + v.vector[2] == pixman_fixed_1; 1.102 + } 1.103 + 1.104 + if (affine) 1.105 + { 1.106 + rx -= conical->center.x / 65536.; 1.107 + ry -= conical->center.y / 65536.; 1.108 + 1.109 + while (buffer < end) 1.110 + { 1.111 + if (!mask || *mask++) 1.112 + { 1.113 + double t = coordinates_to_parameter (rx, ry, conical->angle); 1.114 + 1.115 + *buffer = _pixman_gradient_walker_pixel ( 1.116 + &walker, (pixman_fixed_48_16_t)pixman_double_to_fixed (t)); 1.117 + } 1.118 + 1.119 + ++buffer; 1.120 + 1.121 + rx += cx; 1.122 + ry += cy; 1.123 + } 1.124 + } 1.125 + else 1.126 + { 1.127 + while (buffer < end) 1.128 + { 1.129 + double x, y; 1.130 + 1.131 + if (!mask || *mask++) 1.132 + { 1.133 + double t; 1.134 + 1.135 + if (rz != 0) 1.136 + { 1.137 + x = rx / rz; 1.138 + y = ry / rz; 1.139 + } 1.140 + else 1.141 + { 1.142 + x = y = 0.; 1.143 + } 1.144 + 1.145 + x -= conical->center.x / 65536.; 1.146 + y -= conical->center.y / 65536.; 1.147 + 1.148 + t = coordinates_to_parameter (x, y, conical->angle); 1.149 + 1.150 + *buffer = _pixman_gradient_walker_pixel ( 1.151 + &walker, (pixman_fixed_48_16_t)pixman_double_to_fixed (t)); 1.152 + } 1.153 + 1.154 + ++buffer; 1.155 + 1.156 + rx += cx; 1.157 + ry += cy; 1.158 + rz += cz; 1.159 + } 1.160 + } 1.161 + 1.162 + iter->y++; 1.163 + return iter->buffer; 1.164 +} 1.165 + 1.166 +static uint32_t * 1.167 +conical_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask) 1.168 +{ 1.169 + uint32_t *buffer = conical_get_scanline_narrow (iter, NULL); 1.170 + 1.171 + pixman_expand_to_float ( 1.172 + (argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width); 1.173 + 1.174 + return buffer; 1.175 +} 1.176 + 1.177 +void 1.178 +_pixman_conical_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter) 1.179 +{ 1.180 + if (iter->iter_flags & ITER_NARROW) 1.181 + iter->get_scanline = conical_get_scanline_narrow; 1.182 + else 1.183 + iter->get_scanline = conical_get_scanline_wide; 1.184 +} 1.185 + 1.186 +PIXMAN_EXPORT pixman_image_t * 1.187 +pixman_image_create_conical_gradient (const pixman_point_fixed_t * center, 1.188 + pixman_fixed_t angle, 1.189 + const pixman_gradient_stop_t *stops, 1.190 + int n_stops) 1.191 +{ 1.192 + pixman_image_t *image = _pixman_image_allocate (); 1.193 + conical_gradient_t *conical; 1.194 + 1.195 + if (!image) 1.196 + return NULL; 1.197 + 1.198 + conical = &image->conical; 1.199 + 1.200 + if (!_pixman_init_gradient (&conical->common, stops, n_stops)) 1.201 + { 1.202 + free (image); 1.203 + return NULL; 1.204 + } 1.205 + 1.206 + angle = MOD (angle, pixman_int_to_fixed (360)); 1.207 + 1.208 + image->type = CONICAL; 1.209 + 1.210 + conical->center = *center; 1.211 + conical->angle = (pixman_fixed_to_double (angle) / 180.0) * M_PI; 1.212 + 1.213 + return image; 1.214 +} 1.215 +