Reindent and reformat pixman-gradient-walker.c
[profile/ivi/pixman.git] / pixman / pixman-gradient-walker.c
1 /*
2  *
3  * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
4  *             2005 Lars Knoll & Zack Rusin, Trolltech
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that
9  * copyright notice and this permission notice appear in supporting
10  * documentation, and that the name of Keith Packard not be used in
11  * advertising or publicity pertaining to distribution of the software without
12  * specific, written prior permission.  Keith Packard makes no
13  * representations about the suitability of this software for any purpose.  It
14  * is provided "as is" without express or implied warranty.
15  *
16  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
17  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
18  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
21  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
22  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
23  * SOFTWARE.
24  */
25
26 #include <config.h>
27 #include "pixman-private.h"
28
29 void
30 _pixman_gradient_walker_init (pixman_gradient_walker_t *walker,
31                               gradient_t *              gradient,
32                               unsigned int              spread)
33 {
34     walker->num_stops = gradient->n_stops;
35     walker->stops     = gradient->stops;
36     walker->left_x    = 0;
37     walker->right_x   = 0x10000;
38     walker->stepper   = 0;
39     walker->left_ag   = 0;
40     walker->left_rb   = 0;
41     walker->right_ag  = 0;
42     walker->right_rb  = 0;
43     walker->spread    = spread;
44
45     walker->need_reset = TRUE;
46 }
47
48 void
49 _pixman_gradient_walker_reset (pixman_gradient_walker_t *walker,
50                                pixman_fixed_32_32_t      pos)
51 {
52     int32_t x, left_x, right_x;
53     pixman_color_t          *left_c, *right_c;
54     int n, count = walker->num_stops;
55     pixman_gradient_stop_t *      stops = walker->stops;
56
57     static const pixman_color_t transparent_black = { 0, 0, 0, 0 };
58
59     switch (walker->spread)
60     {
61     case PIXMAN_REPEAT_NORMAL:
62         x = (int32_t)pos & 0xFFFF;
63         for (n = 0; n < count; n++)
64             if (x < stops[n].x)
65                 break;
66         if (n == 0)
67         {
68             left_x =  stops[count - 1].x - 0x10000;
69             left_c = &stops[count - 1].color;
70         }
71         else
72         {
73             left_x =  stops[n - 1].x;
74             left_c = &stops[n - 1].color;
75         }
76
77         if (n == count)
78         {
79             right_x =  stops[0].x + 0x10000;
80             right_c = &stops[0].color;
81         }
82         else
83         {
84             right_x =  stops[n].x;
85             right_c = &stops[n].color;
86         }
87         left_x  += (pos - x);
88         right_x += (pos - x);
89         break;
90
91     case PIXMAN_REPEAT_PAD:
92         for (n = 0; n < count; n++)
93             if (pos < stops[n].x)
94                 break;
95
96         if (n == 0)
97         {
98             left_x =  INT32_MIN;
99             left_c = &stops[0].color;
100         }
101         else
102         {
103             left_x =  stops[n - 1].x;
104             left_c = &stops[n - 1].color;
105         }
106
107         if (n == count)
108         {
109             right_x =  INT32_MAX;
110             right_c = &stops[n - 1].color;
111         }
112         else
113         {
114             right_x =  stops[n].x;
115             right_c = &stops[n].color;
116         }
117         break;
118
119     case PIXMAN_REPEAT_REFLECT:
120         x = (int32_t)pos & 0xFFFF;
121         if ((int32_t)pos & 0x10000)
122             x = 0x10000 - x;
123         for (n = 0; n < count; n++)
124             if (x < stops[n].x)
125                 break;
126
127         if (n == 0)
128         {
129             left_x =  -stops[0].x;
130             left_c = &stops[0].color;
131         }
132         else
133         {
134             left_x =  stops[n - 1].x;
135             left_c = &stops[n - 1].color;
136         }
137
138         if (n == count)
139         {
140             right_x = 0x20000 - stops[n - 1].x;
141             right_c = &stops[n - 1].color;
142         }
143         else
144         {
145             right_x =  stops[n].x;
146             right_c = &stops[n].color;
147         }
148
149         if ((int32_t)pos & 0x10000)
150         {
151             pixman_color_t  *tmp_c;
152             int32_t tmp_x;
153
154             tmp_x   = 0x10000 - right_x;
155             right_x = 0x10000 - left_x;
156             left_x  = tmp_x;
157
158             tmp_c   = right_c;
159             right_c = left_c;
160             left_c  = tmp_c;
161
162             x = 0x10000 - x;
163         }
164         left_x  += (pos - x);
165         right_x += (pos - x);
166         break;
167
168     default:  /* REPEAT_NONE */
169         for (n = 0; n < count; n++)
170             if (pos < stops[n].x)
171                 break;
172
173         if (n == 0)
174         {
175             left_x  =  INT32_MIN;
176             right_x =  stops[0].x;
177             left_c  = right_c = (pixman_color_t*) &transparent_black;
178         }
179         else if (n == count)
180         {
181             left_x  = stops[n - 1].x;
182             right_x = INT32_MAX;
183             left_c  = right_c = (pixman_color_t*) &transparent_black;
184         }
185         else
186         {
187             left_x  =  stops[n - 1].x;
188             right_x =  stops[n].x;
189             left_c  = &stops[n - 1].color;
190             right_c = &stops[n].color;
191         }
192     }
193
194     walker->left_x   = left_x;
195     walker->right_x  = right_x;
196     walker->left_ag  = ((left_c->alpha >> 8) << 16)   | (left_c->green >> 8);
197     walker->left_rb  = ((left_c->red & 0xff00) << 8)  | (left_c->blue >> 8);
198     walker->right_ag = ((right_c->alpha >> 8) << 16)  | (right_c->green >> 8);
199     walker->right_rb = ((right_c->red & 0xff00) << 8) | (right_c->blue >> 8);
200
201     if (walker->left_x == walker->right_x                ||
202         ( walker->left_ag == walker->right_ag &&
203           walker->left_rb == walker->right_rb )   )
204     {
205         walker->stepper = 0;
206     }
207     else
208     {
209         int32_t width = right_x - left_x;
210         walker->stepper = ((1 << 24) + width / 2) / width;
211     }
212
213     walker->need_reset = FALSE;
214 }
215
216 #define  PIXMAN_GRADIENT_WALKER_NEED_RESET(w, x)                         \
217     ( (w)->need_reset || (x) < (w)->left_x || (x) >= (w)->right_x)
218
219
220 /* the following assumes that PIXMAN_GRADIENT_WALKER_NEED_RESET(w,x) is FALSE */
221 uint32_t
222 _pixman_gradient_walker_pixel (pixman_gradient_walker_t *walker,
223                                pixman_fixed_32_32_t      x)
224 {
225     int dist, idist;
226     uint32_t t1, t2, a, color;
227
228     if (PIXMAN_GRADIENT_WALKER_NEED_RESET (walker, x))
229         _pixman_gradient_walker_reset (walker, x);
230
231     dist  = ((int)(x - walker->left_x) * walker->stepper) >> 16;
232     idist = 256 - dist;
233
234     /* combined INTERPOLATE and premultiply */
235     t1 = walker->left_rb * idist + walker->right_rb * dist;
236     t1 = (t1 >> 8) & 0xff00ff;
237
238     t2  = walker->left_ag * idist + walker->right_ag * dist;
239     t2 &= 0xff00ff00;
240
241     color = t2 & 0xff000000;
242     a     = t2 >> 24;
243
244     t1  = t1 * a + 0x800080;
245     t1  = (t1 + ((t1 >> 8) & 0xff00ff)) >> 8;
246
247     t2  = (t2 >> 8) * a + 0x800080;
248     t2  = (t2 + ((t2 >> 8) & 0xff00ff));
249
250     return (color | (t1 & 0xff00ff) | (t2 & 0xff00));
251 }
252