gfx/cairo/libpixman/src/pixman-conical-gradient.c

changeset 0
6474c204b198
     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 +

mercurial