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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/cairo/libpixman/src/pixman-gradient-walker.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,172 @@
     1.4 +/*
     1.5 + *
     1.6 + * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
     1.7 + *             2005 Lars Knoll & Zack Rusin, Trolltech
     1.8 + *
     1.9 + * Permission to use, copy, modify, distribute, and sell this software and its
    1.10 + * documentation for any purpose is hereby granted without fee, provided that
    1.11 + * the above copyright notice appear in all copies and that both that
    1.12 + * copyright notice and this permission notice appear in supporting
    1.13 + * documentation, and that the name of Keith Packard not be used in
    1.14 + * advertising or publicity pertaining to distribution of the software without
    1.15 + * specific, written prior permission.  Keith Packard makes no
    1.16 + * representations about the suitability of this software for any purpose.  It
    1.17 + * is provided "as is" without express or implied warranty.
    1.18 + *
    1.19 + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
    1.20 + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
    1.21 + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
    1.22 + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    1.23 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
    1.24 + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
    1.25 + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
    1.26 + * SOFTWARE.
    1.27 + */
    1.28 +
    1.29 +#ifdef HAVE_CONFIG_H
    1.30 +#include <config.h>
    1.31 +#endif
    1.32 +#include "pixman-private.h"
    1.33 +
    1.34 +void
    1.35 +_pixman_gradient_walker_init (pixman_gradient_walker_t *walker,
    1.36 +                              gradient_t *              gradient,
    1.37 +                              pixman_repeat_t		repeat)
    1.38 +{
    1.39 +    walker->num_stops = gradient->n_stops;
    1.40 +    walker->stops     = gradient->stops;
    1.41 +    walker->left_x    = 0;
    1.42 +    walker->right_x   = 0x10000;
    1.43 +    walker->stepper   = 0;
    1.44 +    walker->left_ag   = 0;
    1.45 +    walker->left_rb   = 0;
    1.46 +    walker->right_ag  = 0;
    1.47 +    walker->right_rb  = 0;
    1.48 +    walker->repeat    = repeat;
    1.49 +
    1.50 +    walker->need_reset = TRUE;
    1.51 +}
    1.52 +
    1.53 +static void
    1.54 +gradient_walker_reset (pixman_gradient_walker_t *walker,
    1.55 +		       pixman_fixed_48_16_t      pos)
    1.56 +{
    1.57 +    int32_t x, left_x, right_x;
    1.58 +    pixman_color_t *left_c, *right_c;
    1.59 +    int n, count = walker->num_stops;
    1.60 +    pixman_gradient_stop_t *stops = walker->stops;
    1.61 +
    1.62 +    if (walker->repeat == PIXMAN_REPEAT_NORMAL)
    1.63 +    {
    1.64 +	x = (int32_t)pos & 0xffff;
    1.65 +    }
    1.66 +    else if (walker->repeat == PIXMAN_REPEAT_REFLECT)
    1.67 +    {
    1.68 +	x = (int32_t)pos & 0xffff;
    1.69 +	if ((int32_t)pos & 0x10000)
    1.70 +	    x = 0x10000 - x;
    1.71 +    }
    1.72 +    else
    1.73 +    {
    1.74 +	x = pos;
    1.75 +    }
    1.76 +    
    1.77 +    for (n = 0; n < count; n++)
    1.78 +    {
    1.79 +	if (x < stops[n].x)
    1.80 +	    break;
    1.81 +    }
    1.82 +    
    1.83 +    left_x =  stops[n - 1].x;
    1.84 +    left_c = &stops[n - 1].color;
    1.85 +    
    1.86 +    right_x =  stops[n].x;
    1.87 +    right_c = &stops[n].color;
    1.88 +
    1.89 +    if (walker->repeat == PIXMAN_REPEAT_NORMAL)
    1.90 +    {
    1.91 +	left_x  += (pos - x);
    1.92 +	right_x += (pos - x);
    1.93 +    }
    1.94 +    else if (walker->repeat == PIXMAN_REPEAT_REFLECT)
    1.95 +    {
    1.96 +	if ((int32_t)pos & 0x10000)
    1.97 +	{
    1.98 +	    pixman_color_t  *tmp_c;
    1.99 +	    int32_t tmp_x;
   1.100 +
   1.101 +	    tmp_x   = 0x10000 - right_x;
   1.102 +	    right_x = 0x10000 - left_x;
   1.103 +	    left_x  = tmp_x;
   1.104 +
   1.105 +	    tmp_c   = right_c;
   1.106 +	    right_c = left_c;
   1.107 +	    left_c  = tmp_c;
   1.108 +
   1.109 +	    x = 0x10000 - x;
   1.110 +	}
   1.111 +	left_x  += (pos - x);
   1.112 +	right_x += (pos - x);
   1.113 +    }
   1.114 +    else if (walker->repeat == PIXMAN_REPEAT_NONE)
   1.115 +    {
   1.116 +	if (n == 0)
   1.117 +	    right_c = left_c;
   1.118 +	else if (n == count)
   1.119 +	    left_c = right_c;
   1.120 +    }
   1.121 +
   1.122 +    walker->left_x   = left_x;
   1.123 +    walker->right_x  = right_x;
   1.124 +    walker->left_ag  = ((left_c->alpha >> 8) << 16)   | (left_c->green >> 8);
   1.125 +    walker->left_rb  = ((left_c->red & 0xff00) << 8)  | (left_c->blue >> 8);
   1.126 +    walker->right_ag = ((right_c->alpha >> 8) << 16)  | (right_c->green >> 8);
   1.127 +    walker->right_rb = ((right_c->red & 0xff00) << 8) | (right_c->blue >> 8);
   1.128 +
   1.129 +    if (walker->left_x == walker->right_x                ||
   1.130 +        (walker->left_ag == walker->right_ag &&
   1.131 +	 walker->left_rb == walker->right_rb))
   1.132 +    {
   1.133 +	walker->stepper = 0;
   1.134 +    }
   1.135 +    else
   1.136 +    {
   1.137 +	int32_t width = right_x - left_x;
   1.138 +	walker->stepper = ((1 << 24) + width / 2) / width;
   1.139 +    }
   1.140 +
   1.141 +    walker->need_reset = FALSE;
   1.142 +}
   1.143 +
   1.144 +uint32_t
   1.145 +_pixman_gradient_walker_pixel (pixman_gradient_walker_t *walker,
   1.146 +                               pixman_fixed_48_16_t      x)
   1.147 +{
   1.148 +    int dist, idist;
   1.149 +    uint32_t t1, t2, a, color;
   1.150 +
   1.151 +    if (walker->need_reset || x < walker->left_x || x >= walker->right_x)
   1.152 +	gradient_walker_reset (walker, x);
   1.153 +
   1.154 +    dist  = ((int)(x - walker->left_x) * walker->stepper) >> 16;
   1.155 +    idist = 256 - dist;
   1.156 +
   1.157 +    /* combined INTERPOLATE and premultiply */
   1.158 +    t1 = walker->left_rb * idist + walker->right_rb * dist;
   1.159 +    t1 = (t1 >> 8) & 0xff00ff;
   1.160 +
   1.161 +    t2  = walker->left_ag * idist + walker->right_ag * dist;
   1.162 +    t2 &= 0xff00ff00;
   1.163 +
   1.164 +    color = t2 & 0xff000000;
   1.165 +    a     = t2 >> 24;
   1.166 +
   1.167 +    t1  = t1 * a + 0x800080;
   1.168 +    t1  = (t1 + ((t1 >> 8) & 0xff00ff)) >> 8;
   1.169 +
   1.170 +    t2  = (t2 >> 8) * a + 0x800080;
   1.171 +    t2  = (t2 + ((t2 >> 8) & 0xff00ff));
   1.172 +
   1.173 +    return (color | (t1 & 0xff00ff) | (t2 & 0xff00));
   1.174 +}
   1.175 +

mercurial