2 * Copyright (C) 2003-2006 David Schleef <ds@schleef.org>
3 * 2005-2006 Eric Anholt <eric@anholt.net>
4 * 2006-2007 Benjamin Otte <otte@gnome.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
27 #include "swfdec_color.h"
28 #include "swfdec_debug.h"
31 swfdec_color_apply_morph (SwfdecColor start
, SwfdecColor end
, guint ratio
)
34 guint start_ratio
, end_ratio
;
36 g_assert (ratio
< 65536);
41 start_ratio
= 65535 - ratio
;
43 r
= (SWFDEC_COLOR_RED (start
) * start_ratio
+ SWFDEC_COLOR_RED (end
) * end_ratio
) / 65535;
44 g
= (SWFDEC_COLOR_GREEN (start
) * start_ratio
+ SWFDEC_COLOR_GREEN (end
) * end_ratio
) / 65535;
45 b
= (SWFDEC_COLOR_BLUE (start
) * start_ratio
+ SWFDEC_COLOR_BLUE (end
) * end_ratio
) / 65535;
46 a
= (SWFDEC_COLOR_ALPHA (start
) * start_ratio
+ SWFDEC_COLOR_ALPHA (end
) * end_ratio
) / 65535;
48 return SWFDEC_COLOR_COMBINE (r
, g
, b
, a
);
52 swfdec_color_set_source (cairo_t
*cr
, SwfdecColor color
)
54 cairo_set_source_rgba (cr
,
55 SWFDEC_COLOR_RED (color
) / 255.0, SWFDEC_COLOR_GREEN (color
) / 255.0,
56 SWFDEC_COLOR_BLUE (color
) / 255.0, SWFDEC_COLOR_ALPHA (color
) / 255.0);
60 swfdec_color_apply_transform_premultiplied (SwfdecColor in
,
61 const SwfdecColorTransform
* trans
)
66 return SWFDEC_COLOR_COMBINE (0, 0, 0, 255);
68 aold
= SWFDEC_COLOR_ALPHA (in
);
72 r
= SWFDEC_COLOR_RED (in
);
73 g
= SWFDEC_COLOR_GREEN (in
);
74 b
= SWFDEC_COLOR_BLUE (in
);
76 a
= (aold
* trans
->aa
>> 8) + trans
->ab
;
77 a
= CLAMP (a
, 0, 255);
79 r
= (r
* trans
->ra
* a
/ aold
>> 8) + trans
->rb
* a
/ 255;
81 g
= (g
* trans
->ga
* a
/ aold
>> 8) + trans
->gb
* a
/ 255;
83 b
= (b
* trans
->ba
* a
/ aold
>> 8) + trans
->bb
* a
/ 255;
86 return SWFDEC_COLOR_COMBINE (r
, g
, b
, a
);
90 swfdec_color_apply_transform (SwfdecColor in
, const SwfdecColorTransform
* trans
)
95 return SWFDEC_COLOR_COMBINE (0, 0, 0, 255);
97 r
= SWFDEC_COLOR_RED (in
);
98 g
= SWFDEC_COLOR_GREEN (in
);
99 b
= SWFDEC_COLOR_BLUE (in
);
100 a
= SWFDEC_COLOR_ALPHA (in
);
102 SWFDEC_LOG ("in rgba %d,%d,%d,%d", r
, g
, b
, a
);
104 r
= (r
* trans
->ra
>> 8) + trans
->rb
;
105 g
= (g
* trans
->ga
>> 8) + trans
->gb
;
106 b
= (b
* trans
->ba
>> 8) + trans
->bb
;
107 a
= (a
* trans
->aa
>> 8) + trans
->ab
;
109 r
= CLAMP (r
, 0, 255);
110 g
= CLAMP (g
, 0, 255);
111 b
= CLAMP (b
, 0, 255);
112 a
= CLAMP (a
, 0, 255);
114 SWFDEC_LOG ("out rgba %d,%d,%d,%d", r
, g
, b
, a
);
116 return SWFDEC_COLOR_COMBINE (r
, g
, b
, a
);
120 * swfdec_color_transform_init_identity:
121 * @trans: a #SwfdecColorTransform
123 * Initializes the color transform so it doesn't transform any colors.
126 swfdec_color_transform_init_identity (SwfdecColorTransform
* trans
)
128 g_return_if_fail (trans
!= NULL
);
142 swfdec_color_transform_init_mask (SwfdecColorTransform
*trans
)
144 g_return_if_fail (trans
!= NULL
);
147 /* don't init the other values so valgrind complains when they get accessed */
151 * swfdec_color_transform_init_color:
152 * @trans: a #SwfdecColorTransform
153 * @color: a #SwfdecColor to transform to
155 * Initializes this color transform so it results in exactly @color no matter
159 swfdec_color_transform_init_color (SwfdecColorTransform
*trans
, SwfdecColor color
)
163 trans
->rb
= SWFDEC_COLOR_RED (color
);
165 trans
->gb
= SWFDEC_COLOR_GREEN (color
);
167 trans
->bb
= SWFDEC_COLOR_BLUE (color
);
169 trans
->ab
= SWFDEC_COLOR_ALPHA (color
);
173 swfdec_color_transform_is_identity (const SwfdecColorTransform
* trans
)
175 return trans
->mask
== FALSE
&&
176 trans
->ra
== 256 && trans
->ga
== 256 && trans
->ba
== 256 && trans
->aa
== 256 &&
177 trans
->rb
== 0 && trans
->gb
== 0 && trans
->bb
== 0 && trans
->ab
== 0;
181 * swfdec_color_transform_is_alpha:
182 * @trans: a color transform
184 * Checks if the color transform is an alpha transform. Note that the identity
185 * transform is not considered an alpha transform.
187 * Returns: %TRUE if the color transform is an alpha transform
190 swfdec_color_transform_is_alpha (const SwfdecColorTransform
* trans
)
192 return trans
->mask
== FALSE
&&
193 trans
->ra
== 256 && trans
->ga
== 256 && trans
->ba
== 256 && trans
->aa
!= 256 &&
194 trans
->rb
== 0 && trans
->gb
== 0 && trans
->bb
== 0 && trans
->ab
== 0;
198 * swfdec_color_transform_chain:
199 * @dest: #SwfdecColorTransform to take the result
200 * @last: a #SwfdecColorTransform
201 * @first: a #SwfdecColorTransform
203 * Computes a color transform that has the same effect as if the color
204 * transforms @first and @last would have been applied one after another.
207 swfdec_color_transform_chain (SwfdecColorTransform
*dest
,
208 const SwfdecColorTransform
*last
, const SwfdecColorTransform
*first
)
210 g_return_if_fail (dest
!= NULL
);
211 g_return_if_fail (last
!= NULL
);
212 g_return_if_fail (first
!= NULL
);
213 g_return_if_fail (!last
->mask
);
216 swfdec_color_transform_init_mask (dest
);
220 dest
->ra
= last
->ra
* first
->ra
>> 8;
221 dest
->rb
= (last
->ra
* first
->rb
>> 8) + last
->rb
;
222 dest
->ga
= last
->ga
* first
->ga
>> 8;
223 dest
->gb
= (last
->ga
* first
->gb
>> 8) + last
->gb
;
224 dest
->ba
= last
->ba
* first
->ba
>> 8;
225 dest
->bb
= (last
->ba
* first
->bb
>> 8) + last
->bb
;
226 dest
->aa
= last
->aa
* first
->aa
>> 8;
227 dest
->ab
= (last
->aa
* first
->ab
>> 8) + last
->ab
;
231 swfdec_matrix_ensure_invertible (cairo_matrix_t
*matrix
, cairo_matrix_t
*inverse
)
235 g_return_if_fail (matrix
!= NULL
);
240 g_assert (isfinite (matrix
->xx
) && isfinite (matrix
->yx
) && isfinite (matrix
->xy
) && isfinite (matrix
->yy
));
242 while (cairo_matrix_invert (inverse
)) {
243 SWFDEC_INFO ("matrix not invertible, adding epsilon to smallest member");
244 /* add epsilon at point closest to zero */
245 #define EPSILON (1.0 / SWFDEC_FIXED_SCALE_FACTOR)
246 if (ABS (matrix
->xx
) <= ABS (matrix
->xy
) &&
247 ABS (matrix
->xx
) <= ABS (matrix
->yx
) &&
248 ABS (matrix
->xx
) <= ABS (matrix
->yy
))
249 matrix
->xx
+= (matrix
->xx
>= 0) ? EPSILON
: -EPSILON
;
250 else if (ABS (matrix
->yy
) <= ABS (matrix
->xy
) &&
251 ABS (matrix
->yy
) <= ABS (matrix
->yx
))
252 matrix
->yy
+= (matrix
->yy
>= 0) ? EPSILON
: -EPSILON
;
253 else if (ABS (matrix
->xy
) <= ABS (matrix
->yx
))
254 matrix
->xy
+= (matrix
->xy
>= 0) ? EPSILON
: -EPSILON
;
256 matrix
->yx
+= (matrix
->yx
>= 0) ? EPSILON
: -EPSILON
;
262 swfdec_matrix_get_xscale (const cairo_matrix_t
*matrix
)
267 alpha
= atan2 (matrix
->yx
, matrix
->xx
);
269 return matrix
->xx
/ alpha
* 100;
271 return matrix
->yx
* 100;
276 swfdec_matrix_get_yscale (const cairo_matrix_t
*matrix
)
281 alpha
= atan2 (matrix
->xy
, matrix
->yy
);
283 return matrix
->yy
/ alpha
* 100;
285 return matrix
->xy
* 100;
290 swfdec_matrix_get_rotation (const cairo_matrix_t
*matrix
)
292 return atan2 (matrix
->yx
, matrix
->xx
) * 180 / G_PI
;
296 swfdec_matrix_morph (cairo_matrix_t
*dest
, const cairo_matrix_t
*start
,
297 const cairo_matrix_t
*end
, guint ratio
)
299 guint inv_ratio
= 65535 - ratio
;
300 g_assert (ratio
< 65536);
306 if (ratio
== 65535) {
310 dest
->xx
= (start
->xx
* inv_ratio
+ end
->xx
* ratio
) / 65535;
311 dest
->xy
= (start
->xy
* inv_ratio
+ end
->xy
* ratio
) / 65535;
312 dest
->yy
= (start
->yy
* inv_ratio
+ end
->yy
* ratio
) / 65535;
313 dest
->yx
= (start
->yx
* inv_ratio
+ end
->yx
* ratio
) / 65535;
314 dest
->x0
= (start
->x0
* inv_ratio
+ end
->x0
* ratio
) / 65535;
315 dest
->y0
= (start
->y0
* inv_ratio
+ end
->y0
* ratio
) / 65535;