tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pixman-conical-gradient.c (5662B)


      1 /*
      2 * Copyright © 2000 SuSE, Inc.
      3 * Copyright © 2007 Red Hat, Inc.
      4 * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
      5 *             2005 Lars Knoll & Zack Rusin, Trolltech
      6 *
      7 * Permission to use, copy, modify, distribute, and sell this software and its
      8 * documentation for any purpose is hereby granted without fee, provided that
      9 * the above copyright notice appear in all copies and that both that
     10 * copyright notice and this permission notice appear in supporting
     11 * documentation, and that the name of Keith Packard not be used in
     12 * advertising or publicity pertaining to distribution of the software without
     13 * specific, written prior permission.  Keith Packard makes no
     14 * representations about the suitability of this software for any purpose.  It
     15 * is provided "as is" without express or implied warranty.
     16 *
     17 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
     18 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
     19 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
     20 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     21 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
     22 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
     23 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     24 * SOFTWARE.
     25 */
     26 
     27 #ifdef HAVE_CONFIG_H
     28 #include <pixman-config.h>
     29 #endif
     30 
     31 #include <stdlib.h>
     32 #include <math.h>
     33 #include "pixman-private.h"
     34 
     35 static force_inline double
     36 coordinates_to_parameter (double x, double y, double angle)
     37 {
     38    double t;
     39 
     40    t = atan2 (y, x) + angle;
     41 
     42    while (t < 0)
     43 t += 2 * M_PI;
     44 
     45    while (t >= 2 * M_PI)
     46 t -= 2 * M_PI;
     47 
     48    return 1 - t * (1 / (2 * M_PI)); /* Scale t to [0, 1] and
     49 			      * make rotation CCW
     50 			      */
     51 }
     52 
     53 static uint32_t *
     54 conical_get_scanline (pixman_iter_t                 *iter,
     55 	      const uint32_t                *mask,
     56 	      int                            Bpp,
     57 	      pixman_gradient_walker_write_t write_pixel)
     58 {
     59    pixman_image_t *image = iter->image;
     60    int x = iter->x;
     61    int y = iter->y;
     62    int width = iter->width;
     63    uint32_t *buffer = iter->buffer;
     64 
     65    gradient_t *gradient = (gradient_t *)image;
     66    conical_gradient_t *conical = (conical_gradient_t *)image;
     67    uint32_t       *end = buffer + width * (Bpp / 4);
     68    pixman_gradient_walker_t walker;
     69    pixman_bool_t affine = TRUE;
     70    double cx = 1.;
     71    double cy = 0.;
     72    double cz = 0.;
     73    double rx = x + 0.5;
     74    double ry = y + 0.5;
     75    double rz = 1.;
     76 
     77    _pixman_gradient_walker_init (&walker, gradient, image->common.repeat);
     78 
     79    if (image->common.transform)
     80    {
     81 pixman_vector_t v;
     82 
     83 /* reference point is the center of the pixel */
     84 v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2;
     85 v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2;
     86 v.vector[2] = pixman_fixed_1;
     87 
     88 if (!pixman_transform_point_3d (image->common.transform, &v))
     89     return iter->buffer;
     90 
     91 cx = image->common.transform->matrix[0][0] / 65536.;
     92 cy = image->common.transform->matrix[1][0] / 65536.;
     93 cz = image->common.transform->matrix[2][0] / 65536.;
     94 
     95 rx = v.vector[0] / 65536.;
     96 ry = v.vector[1] / 65536.;
     97 rz = v.vector[2] / 65536.;
     98 
     99 affine =
    100     image->common.transform->matrix[2][0] == 0 &&
    101     v.vector[2] == pixman_fixed_1;
    102    }
    103 
    104    if (affine)
    105    {
    106 rx -= conical->center.x / 65536.;
    107 ry -= conical->center.y / 65536.;
    108 
    109 while (buffer < end)
    110 {
    111     if (!mask || *mask++)
    112     {
    113 	double t = coordinates_to_parameter (rx, ry, conical->angle);
    114 
    115 	write_pixel (&walker,
    116 		     (pixman_fixed_48_16_t)pixman_double_to_fixed (t),
    117 		     buffer);
    118     }
    119 
    120     buffer += (Bpp / 4);
    121 
    122     rx += cx;
    123     ry += cy;
    124 }
    125    }
    126    else
    127    {
    128 while (buffer < end)
    129 {
    130     double x, y;
    131 
    132     if (!mask || *mask++)
    133     {
    134 	double t;
    135 
    136 	if (rz != 0)
    137 	{
    138 	    x = rx / rz;
    139 	    y = ry / rz;
    140 	}
    141 	else
    142 	{
    143 	    x = y = 0.;
    144 	}
    145 
    146 	x -= conical->center.x / 65536.;
    147 	y -= conical->center.y / 65536.;
    148 
    149 	t = coordinates_to_parameter (x, y, conical->angle);
    150 
    151 	write_pixel (&walker,
    152 		     (pixman_fixed_48_16_t)pixman_double_to_fixed (t),
    153 		     buffer);
    154     }
    155 
    156     buffer += (Bpp / 4);
    157 
    158     rx += cx;
    159     ry += cy;
    160     rz += cz;
    161 }
    162    }
    163 
    164    iter->y++;
    165    return iter->buffer;
    166 }
    167 
    168 static uint32_t *
    169 conical_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
    170 {
    171    return conical_get_scanline (iter, mask, 4,
    172 			 _pixman_gradient_walker_write_narrow);
    173 }
    174 
    175 static uint32_t *
    176 conical_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
    177 {
    178    return conical_get_scanline (iter, NULL, 16,
    179 			 _pixman_gradient_walker_write_wide);
    180 }
    181 
    182 void
    183 _pixman_conical_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter)
    184 {
    185    if (iter->iter_flags & ITER_NARROW)
    186 iter->get_scanline = conical_get_scanline_narrow;
    187    else
    188 iter->get_scanline = conical_get_scanline_wide;
    189 }
    190 
    191 PIXMAN_EXPORT pixman_image_t *
    192 pixman_image_create_conical_gradient (const pixman_point_fixed_t *  center,
    193                                      pixman_fixed_t                angle,
    194                                      const pixman_gradient_stop_t *stops,
    195                                      int                           n_stops)
    196 {
    197    pixman_image_t *image = _pixman_image_allocate ();
    198    conical_gradient_t *conical;
    199 
    200    if (!image)
    201 return NULL;
    202 
    203    conical = &image->conical;
    204 
    205    if (!_pixman_init_gradient (&conical->common, stops, n_stops))
    206    {
    207 free (image);
    208 return NULL;
    209    }
    210 
    211    angle = MOD (angle, pixman_int_to_fixed (360));
    212 
    213    image->type = CONICAL;
    214 
    215    conical->center = *center;
    216    conical->angle = (pixman_fixed_to_double (angle) / 180.0) * M_PI;
    217 
    218    return image;
    219 }