3 * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
4 * 2005 Lars Knoll & Zack Rusin, Trolltech
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.
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
29 #include "pixman-private.h"
32 _pixman_gradient_walker_init (pixman_gradient_walker_t
*walker
,
33 gradient_t
* gradient
,
34 pixman_repeat_t repeat
)
36 walker
->num_stops
= gradient
->n_stops
;
37 walker
->stops
= gradient
->stops
;
39 walker
->right_x
= 0x10000;
48 walker
->repeat
= repeat
;
50 walker
->need_reset
= TRUE
;
54 gradient_walker_reset (pixman_gradient_walker_t
*walker
,
55 pixman_fixed_48_16_t pos
)
57 int64_t x
, left_x
, right_x
;
58 pixman_color_t
*left_c
, *right_c
;
59 int n
, count
= walker
->num_stops
;
60 pixman_gradient_stop_t
*stops
= walker
->stops
;
65 if (walker
->repeat
== PIXMAN_REPEAT_NORMAL
)
67 x
= (int32_t)pos
& 0xffff;
69 else if (walker
->repeat
== PIXMAN_REPEAT_REFLECT
)
71 x
= (int32_t)pos
& 0xffff;
72 if ((int32_t)pos
& 0x10000)
80 for (n
= 0; n
< count
; n
++)
86 left_x
= stops
[n
- 1].x
;
87 left_c
= &stops
[n
- 1].color
;
90 right_c
= &stops
[n
].color
;
92 if (walker
->repeat
== PIXMAN_REPEAT_NORMAL
)
97 else if (walker
->repeat
== PIXMAN_REPEAT_REFLECT
)
99 if ((int32_t)pos
& 0x10000)
101 pixman_color_t
*tmp_c
;
104 tmp_x
= 0x10000 - right_x
;
105 right_x
= 0x10000 - left_x
;
115 right_x
+= (pos
- x
);
117 else if (walker
->repeat
== PIXMAN_REPEAT_NONE
)
125 /* The alpha channel is scaled to be in the [0, 255] interval,
126 * and the red/green/blue channels are scaled to be in [0, 1].
127 * This ensures that after premultiplication all channels will
128 * be in the [0, 255] interval.
130 la
= (left_c
->alpha
* (1.0f
/257.0f
));
131 lr
= (left_c
->red
* (1.0f
/257.0f
));
132 lg
= (left_c
->green
* (1.0f
/257.0f
));
133 lb
= (left_c
->blue
* (1.0f
/257.0f
));
135 ra
= (right_c
->alpha
* (1.0f
/257.0f
));
136 rr
= (right_c
->red
* (1.0f
/257.0f
));
137 rg
= (right_c
->green
* (1.0f
/257.0f
));
138 rb
= (right_c
->blue
* (1.0f
/257.0f
));
140 lx
= left_x
* (1.0f
/65536.0f
);
141 rx
= right_x
* (1.0f
/65536.0f
);
143 if (FLOAT_IS_ZERO (rx
- lx
) || left_x
== INT32_MIN
|| right_x
== INT32_MAX
)
145 walker
->a_s
= walker
->r_s
= walker
->g_s
= walker
->b_s
= 0.0f
;
146 walker
->a_b
= (la
+ ra
) / 2.0f
;
147 walker
->r_b
= (lr
+ rr
) / 510.0f
;
148 walker
->g_b
= (lg
+ rg
) / 510.0f
;
149 walker
->b_b
= (lb
+ rb
) / 510.0f
;
153 float w_rec
= 1.0f
/ (rx
- lx
);
155 walker
->a_b
= (la
* rx
- ra
* lx
) * w_rec
;
156 walker
->r_b
= (lr
* rx
- rr
* lx
) * w_rec
* (1.0f
/255.0f
);
157 walker
->g_b
= (lg
* rx
- rg
* lx
) * w_rec
* (1.0f
/255.0f
);
158 walker
->b_b
= (lb
* rx
- rb
* lx
) * w_rec
* (1.0f
/255.0f
);
160 walker
->a_s
= (ra
- la
) * w_rec
;
161 walker
->r_s
= (rr
- lr
) * w_rec
* (1.0f
/255.0f
);
162 walker
->g_s
= (rg
- lg
) * w_rec
* (1.0f
/255.0f
);
163 walker
->b_s
= (rb
- lb
) * w_rec
* (1.0f
/255.0f
);
166 walker
->left_x
= left_x
;
167 walker
->right_x
= right_x
;
169 walker
->need_reset
= FALSE
;
173 _pixman_gradient_walker_pixel (pixman_gradient_walker_t
*walker
,
174 pixman_fixed_48_16_t x
)
177 uint8_t a8
, r8
, g8
, b8
;
181 if (walker
->need_reset
|| x
< walker
->left_x
|| x
>= walker
->right_x
)
182 gradient_walker_reset (walker
, x
);
184 y
= x
* (1.0f
/ 65536.0f
);
186 a
= walker
->a_s
* y
+ walker
->a_b
;
187 r
= a
* (walker
->r_s
* y
+ walker
->r_b
);
188 g
= a
* (walker
->g_s
* y
+ walker
->g_b
);
189 b
= a
* (walker
->b_s
* y
+ walker
->b_b
);
196 v
= ((a8
<< 24) & 0xff000000) |
197 ((r8
<< 16) & 0x00ff0000) |
198 ((g8
<< 8) & 0x0000ff00) |
199 ((b8
>> 0) & 0x000000ff);