Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1891 | serge | 1 | /* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */ |
2 | /* |
||
3 | * Copyright © 2000 SuSE, Inc. |
||
4 | * Copyright © 2007 Red Hat, Inc. |
||
5 | * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. |
||
6 | * 2005 Lars Knoll & Zack Rusin, Trolltech |
||
7 | * |
||
8 | * Permission to use, copy, modify, distribute, and sell this software and its |
||
9 | * documentation for any purpose is hereby granted without fee, provided that |
||
10 | * the above copyright notice appear in all copies and that both that |
||
11 | * copyright notice and this permission notice appear in supporting |
||
12 | * documentation, and that the name of Keith Packard not be used in |
||
13 | * advertising or publicity pertaining to distribution of the software without |
||
14 | * specific, written prior permission. Keith Packard makes no |
||
15 | * representations about the suitability of this software for any purpose. It |
||
16 | * is provided "as is" without express or implied warranty. |
||
17 | * |
||
18 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS |
||
19 | * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND |
||
20 | * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY |
||
21 | * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||
22 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN |
||
23 | * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING |
||
24 | * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS |
||
25 | * SOFTWARE. |
||
26 | */ |
||
27 | |||
28 | #ifdef HAVE_CONFIG_H |
||
29 | #include |
||
30 | #endif |
||
31 | #include |
||
32 | #include "pixman-private.h" |
||
33 | |||
34 | static source_image_class_t |
||
35 | linear_gradient_classify (pixman_image_t *image, |
||
36 | int x, |
||
37 | int y, |
||
38 | int width, |
||
39 | int height) |
||
40 | { |
||
41 | source_image_t *source = (source_image_t *)image; |
||
42 | linear_gradient_t *linear = (linear_gradient_t *)image; |
||
43 | pixman_vector_t v; |
||
44 | pixman_fixed_32_32_t l; |
||
45 | pixman_fixed_48_16_t dx, dy; |
||
46 | double inc; |
||
47 | source_image_class_t class; |
||
48 | |||
49 | class = SOURCE_IMAGE_CLASS_UNKNOWN; |
||
50 | |||
51 | if (source->common.transform) |
||
52 | { |
||
53 | /* projective transformation */ |
||
54 | if (source->common.transform->matrix[2][0] != 0 || |
||
55 | source->common.transform->matrix[2][1] != 0 || |
||
56 | source->common.transform->matrix[2][2] == 0) |
||
57 | { |
||
58 | return class; |
||
59 | } |
||
60 | |||
61 | v.vector[0] = source->common.transform->matrix[0][1]; |
||
62 | v.vector[1] = source->common.transform->matrix[1][1]; |
||
63 | v.vector[2] = source->common.transform->matrix[2][2]; |
||
64 | } |
||
65 | else |
||
66 | { |
||
67 | v.vector[0] = 0; |
||
68 | v.vector[1] = pixman_fixed_1; |
||
69 | v.vector[2] = pixman_fixed_1; |
||
70 | } |
||
71 | |||
72 | dx = linear->p2.x - linear->p1.x; |
||
73 | dy = linear->p2.y - linear->p1.y; |
||
74 | |||
75 | l = dx * dx + dy * dy; |
||
76 | |||
77 | if (l == 0) |
||
78 | return class; |
||
79 | |||
80 | /* |
||
81 | * compute how much the input of the gradient walked changes |
||
82 | * when moving vertically through the whole image |
||
83 | */ |
||
84 | inc = height * (double) pixman_fixed_1 * pixman_fixed_1 * |
||
85 | (dx * v.vector[0] + dy * v.vector[1]) / |
||
86 | (v.vector[2] * (double) l); |
||
87 | |||
88 | /* check that casting to integer would result in 0 */ |
||
89 | if (-1 < inc && inc < 1) |
||
90 | class = SOURCE_IMAGE_CLASS_HORIZONTAL; |
||
91 | |||
92 | return class; |
||
93 | } |
||
94 | |||
95 | static void |
||
96 | linear_gradient_get_scanline_32 (pixman_image_t *image, |
||
97 | int x, |
||
98 | int y, |
||
99 | int width, |
||
100 | uint32_t * buffer, |
||
101 | const uint32_t *mask) |
||
102 | { |
||
103 | pixman_vector_t v, unit; |
||
104 | pixman_fixed_32_32_t l; |
||
105 | pixman_fixed_48_16_t dx, dy; |
||
106 | gradient_t *gradient = (gradient_t *)image; |
||
107 | source_image_t *source = (source_image_t *)image; |
||
108 | linear_gradient_t *linear = (linear_gradient_t *)image; |
||
109 | uint32_t *end = buffer + width; |
||
110 | pixman_gradient_walker_t walker; |
||
111 | |||
112 | _pixman_gradient_walker_init (&walker, gradient, source->common.repeat); |
||
113 | |||
114 | /* reference point is the center of the pixel */ |
||
115 | v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2; |
||
116 | v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2; |
||
117 | v.vector[2] = pixman_fixed_1; |
||
118 | |||
119 | if (source->common.transform) |
||
120 | { |
||
121 | if (!pixman_transform_point_3d (source->common.transform, &v)) |
||
122 | return; |
||
123 | |||
124 | unit.vector[0] = source->common.transform->matrix[0][0]; |
||
125 | unit.vector[1] = source->common.transform->matrix[1][0]; |
||
126 | unit.vector[2] = source->common.transform->matrix[2][0]; |
||
127 | } |
||
128 | else |
||
129 | { |
||
130 | unit.vector[0] = pixman_fixed_1; |
||
131 | unit.vector[1] = 0; |
||
132 | unit.vector[2] = 0; |
||
133 | } |
||
134 | |||
135 | dx = linear->p2.x - linear->p1.x; |
||
136 | dy = linear->p2.y - linear->p1.y; |
||
137 | |||
138 | l = dx * dx + dy * dy; |
||
139 | |||
140 | if (l == 0 || unit.vector[2] == 0) |
||
141 | { |
||
142 | /* affine transformation only */ |
||
143 | pixman_fixed_32_32_t t, next_inc; |
||
144 | double inc; |
||
145 | |||
146 | if (l == 0 || v.vector[2] == 0) |
||
147 | { |
||
148 | t = 0; |
||
149 | inc = 0; |
||
150 | } |
||
151 | else |
||
152 | { |
||
153 | double invden, v2; |
||
154 | |||
155 | invden = pixman_fixed_1 * (double) pixman_fixed_1 / |
||
156 | (l * (double) v.vector[2]); |
||
157 | v2 = v.vector[2] * (1. / pixman_fixed_1); |
||
158 | t = ((dx * v.vector[0] + dy * v.vector[1]) - |
||
159 | (dx * linear->p1.x + dy * linear->p1.y) * v2) * invden; |
||
160 | inc = (dx * unit.vector[0] + dy * unit.vector[1]) * invden; |
||
161 | } |
||
162 | next_inc = 0; |
||
163 | |||
164 | if (((pixman_fixed_32_32_t )(inc * width)) == 0) |
||
165 | { |
||
166 | register uint32_t color; |
||
167 | |||
168 | color = _pixman_gradient_walker_pixel (&walker, t); |
||
169 | while (buffer < end) |
||
170 | *buffer++ = color; |
||
171 | } |
||
172 | else |
||
173 | { |
||
174 | int i; |
||
175 | |||
176 | i = 0; |
||
177 | while (buffer < end) |
||
178 | { |
||
179 | if (!mask || *mask++) |
||
180 | { |
||
181 | *buffer = _pixman_gradient_walker_pixel (&walker, |
||
182 | t + next_inc); |
||
183 | } |
||
184 | i++; |
||
185 | next_inc = inc * i; |
||
186 | buffer++; |
||
187 | } |
||
188 | } |
||
189 | } |
||
190 | else |
||
191 | { |
||
192 | /* projective transformation */ |
||
193 | double t; |
||
194 | |||
195 | t = 0; |
||
196 | |||
197 | while (buffer < end) |
||
198 | { |
||
199 | if (!mask || *mask++) |
||
200 | { |
||
201 | if (v.vector[2] != 0) |
||
202 | { |
||
203 | double invden, v2; |
||
204 | |||
205 | invden = pixman_fixed_1 * (double) pixman_fixed_1 / |
||
206 | (l * (double) v.vector[2]); |
||
207 | v2 = v.vector[2] * (1. / pixman_fixed_1); |
||
208 | t = ((dx * v.vector[0] + dy * v.vector[1]) - |
||
209 | (dx * linear->p1.x + dy * linear->p1.y) * v2) * invden; |
||
210 | } |
||
211 | |||
212 | *buffer = _pixman_gradient_walker_pixel (&walker, t); |
||
213 | } |
||
214 | |||
215 | ++buffer; |
||
216 | |||
217 | v.vector[0] += unit.vector[0]; |
||
218 | v.vector[1] += unit.vector[1]; |
||
219 | v.vector[2] += unit.vector[2]; |
||
220 | } |
||
221 | } |
||
222 | } |
||
223 | |||
224 | static void |
||
225 | linear_gradient_property_changed (pixman_image_t *image) |
||
226 | { |
||
227 | image->common.get_scanline_32 = linear_gradient_get_scanline_32; |
||
228 | image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64; |
||
229 | } |
||
230 | |||
231 | PIXMAN_EXPORT pixman_image_t * |
||
232 | pixman_image_create_linear_gradient (pixman_point_fixed_t * p1, |
||
233 | pixman_point_fixed_t * p2, |
||
234 | const pixman_gradient_stop_t *stops, |
||
235 | int n_stops) |
||
236 | { |
||
237 | pixman_image_t *image; |
||
238 | linear_gradient_t *linear; |
||
239 | |||
240 | image = _pixman_image_allocate (); |
||
241 | |||
242 | if (!image) |
||
243 | return NULL; |
||
244 | |||
245 | linear = &image->linear; |
||
246 | |||
247 | if (!_pixman_init_gradient (&linear->common, stops, n_stops)) |
||
248 | { |
||
249 | free (image); |
||
250 | return NULL; |
||
251 | } |
||
252 | |||
253 | linear->p1 = *p1; |
||
254 | linear->p2 = *p2; |
||
255 | |||
256 | image->type = LINEAR; |
||
257 | image->common.classify = linear_gradient_classify; |
||
258 | image->common.property_changed = linear_gradient_property_changed; |
||
259 | |||
260 | return image; |
||
261 | }>>>>> |
||
262 |