/src/mozilla-central/gfx/cairo/libpixman/src/pixman-gradient-walker.c
Line | Count | Source (jump to first uncovered line) |
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 | | #ifdef HAVE_CONFIG_H |
27 | | #include <config.h> |
28 | | #endif |
29 | | #include "pixman-private.h" |
30 | | |
31 | | void |
32 | | _pixman_gradient_walker_init (pixman_gradient_walker_t *walker, |
33 | | gradient_t * gradient, |
34 | | pixman_repeat_t repeat) |
35 | 0 | { |
36 | 0 | walker->num_stops = gradient->n_stops; |
37 | 0 | walker->stops = gradient->stops; |
38 | 0 | walker->left_x = 0; |
39 | 0 | walker->right_x = 0x10000; |
40 | 0 | walker->stepper = 0; |
41 | 0 | walker->left_ag = 0; |
42 | 0 | walker->left_rb = 0; |
43 | 0 | walker->right_ag = 0; |
44 | 0 | walker->right_rb = 0; |
45 | 0 | walker->repeat = repeat; |
46 | 0 |
|
47 | 0 | walker->need_reset = TRUE; |
48 | 0 | } |
49 | | |
50 | | static void |
51 | | gradient_walker_reset (pixman_gradient_walker_t *walker, |
52 | | pixman_fixed_48_16_t pos) |
53 | 0 | { |
54 | 0 | int32_t x, left_x, right_x; |
55 | 0 | pixman_color_t *left_c, *right_c; |
56 | 0 | int n, count = walker->num_stops; |
57 | 0 | pixman_gradient_stop_t *stops = walker->stops; |
58 | 0 |
|
59 | 0 | if (walker->repeat == PIXMAN_REPEAT_NORMAL) |
60 | 0 | { |
61 | 0 | x = (int32_t)pos & 0xffff; |
62 | 0 | } |
63 | 0 | else if (walker->repeat == PIXMAN_REPEAT_REFLECT) |
64 | 0 | { |
65 | 0 | x = (int32_t)pos & 0xffff; |
66 | 0 | if ((int32_t)pos & 0x10000) |
67 | 0 | x = 0x10000 - x; |
68 | 0 | } |
69 | 0 | else |
70 | 0 | { |
71 | 0 | x = pos; |
72 | 0 | } |
73 | 0 | |
74 | 0 | for (n = 0; n < count; n++) |
75 | 0 | { |
76 | 0 | if (x < stops[n].x) |
77 | 0 | break; |
78 | 0 | } |
79 | 0 | |
80 | 0 | left_x = stops[n - 1].x; |
81 | 0 | left_c = &stops[n - 1].color; |
82 | 0 | |
83 | 0 | right_x = stops[n].x; |
84 | 0 | right_c = &stops[n].color; |
85 | 0 |
|
86 | 0 | if (walker->repeat == PIXMAN_REPEAT_NORMAL) |
87 | 0 | { |
88 | 0 | left_x += (pos - x); |
89 | 0 | right_x += (pos - x); |
90 | 0 | } |
91 | 0 | else if (walker->repeat == PIXMAN_REPEAT_REFLECT) |
92 | 0 | { |
93 | 0 | if ((int32_t)pos & 0x10000) |
94 | 0 | { |
95 | 0 | pixman_color_t *tmp_c; |
96 | 0 | int32_t tmp_x; |
97 | 0 |
|
98 | 0 | tmp_x = 0x10000 - right_x; |
99 | 0 | right_x = 0x10000 - left_x; |
100 | 0 | left_x = tmp_x; |
101 | 0 |
|
102 | 0 | tmp_c = right_c; |
103 | 0 | right_c = left_c; |
104 | 0 | left_c = tmp_c; |
105 | 0 |
|
106 | 0 | x = 0x10000 - x; |
107 | 0 | } |
108 | 0 | left_x += (pos - x); |
109 | 0 | right_x += (pos - x); |
110 | 0 | } |
111 | 0 | else if (walker->repeat == PIXMAN_REPEAT_NONE) |
112 | 0 | { |
113 | 0 | if (n == 0) |
114 | 0 | right_c = left_c; |
115 | 0 | else if (n == count) |
116 | 0 | left_c = right_c; |
117 | 0 | } |
118 | 0 |
|
119 | 0 | walker->left_x = left_x; |
120 | 0 | walker->right_x = right_x; |
121 | 0 | walker->left_ag = ((left_c->alpha >> 8) << 16) | (left_c->green >> 8); |
122 | 0 | walker->left_rb = ((left_c->red & 0xff00) << 8) | (left_c->blue >> 8); |
123 | 0 | walker->right_ag = ((right_c->alpha >> 8) << 16) | (right_c->green >> 8); |
124 | 0 | walker->right_rb = ((right_c->red & 0xff00) << 8) | (right_c->blue >> 8); |
125 | 0 |
|
126 | 0 | if (walker->left_x == walker->right_x || |
127 | 0 | (walker->left_ag == walker->right_ag && |
128 | 0 | walker->left_rb == walker->right_rb)) |
129 | 0 | { |
130 | 0 | walker->stepper = 0; |
131 | 0 | } |
132 | 0 | else |
133 | 0 | { |
134 | 0 | int32_t width = right_x - left_x; |
135 | 0 | walker->stepper = ((1 << 24) + width / 2) / width; |
136 | 0 | } |
137 | 0 |
|
138 | 0 | walker->need_reset = FALSE; |
139 | 0 | } |
140 | | |
141 | | uint32_t |
142 | | _pixman_gradient_walker_pixel (pixman_gradient_walker_t *walker, |
143 | | pixman_fixed_48_16_t x) |
144 | 0 | { |
145 | 0 | int dist, idist; |
146 | 0 | uint32_t t1, t2, a, color; |
147 | 0 |
|
148 | 0 | if (walker->need_reset || x < walker->left_x || x >= walker->right_x) |
149 | 0 | gradient_walker_reset (walker, x); |
150 | 0 |
|
151 | 0 | dist = ((int)(x - walker->left_x) * walker->stepper) >> 16; |
152 | 0 | idist = 256 - dist; |
153 | 0 |
|
154 | 0 | /* combined INTERPOLATE and premultiply */ |
155 | 0 | t1 = walker->left_rb * idist + walker->right_rb * dist; |
156 | 0 | t1 = (t1 >> 8) & 0xff00ff; |
157 | 0 |
|
158 | 0 | t2 = walker->left_ag * idist + walker->right_ag * dist; |
159 | 0 | t2 &= 0xff00ff00; |
160 | 0 |
|
161 | 0 | color = t2 & 0xff000000; |
162 | 0 | a = t2 >> 24; |
163 | 0 |
|
164 | 0 | t1 = t1 * a + 0x800080; |
165 | 0 | t1 = (t1 + ((t1 >> 8) & 0xff00ff)) >> 8; |
166 | 0 |
|
167 | 0 | t2 = (t2 >> 8) * a + 0x800080; |
168 | 0 | t2 = (t2 + ((t2 >> 8) & 0xff00ff)); |
169 | 0 |
|
170 | 0 | return (color | (t1 & 0xff00ff) | (t2 & 0xff00)); |
171 | 0 | } |
172 | | |