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 +