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_R (start
) * start_ratio
+ SWFDEC_COLOR_R (end
) * end_ratio
) / 65535;
44 g
= (SWFDEC_COLOR_G (start
) * start_ratio
+ SWFDEC_COLOR_G (end
) * end_ratio
) / 65535;
45 b
= (SWFDEC_COLOR_B (start
) * start_ratio
+ SWFDEC_COLOR_B (end
) * end_ratio
) / 65535;
46 a
= (SWFDEC_COLOR_A (start
) * start_ratio
+ SWFDEC_COLOR_A (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_R (color
) / 255.0, SWFDEC_COLOR_G (color
) / 255.0,
56 SWFDEC_COLOR_B (color
) / 255.0, SWFDEC_COLOR_A (color
) / 255.0);
60 swfdec_color_apply_transform_premultiplied (SwfdecColor in
,
61 const SwfdecColorTransform
* trans
)
65 aold
= SWFDEC_COLOR_A (in
);
69 a
= (aold
* trans
->aa
>> 8) + trans
->ab
;
70 a
= CLAMP (a
, 0, 255);
72 r
= SWFDEC_COLOR_R (in
);
73 g
= SWFDEC_COLOR_G (in
);
74 b
= SWFDEC_COLOR_B (in
);
75 r
= (r
* trans
->ra
* a
/ aold
>> 8) + trans
->rb
* a
/ 255;
77 g
= (g
* trans
->ga
* a
/ aold
>> 8) + trans
->gb
* a
/ 255;
79 b
= (b
* trans
->ba
* a
/ aold
>> 8) + trans
->bb
* a
/ 255;
82 return SWFDEC_COLOR_COMBINE (r
, g
, b
, a
);
86 swfdec_color_apply_transform (SwfdecColor in
, const SwfdecColorTransform
* trans
)
90 r
= SWFDEC_COLOR_R (in
);
91 g
= SWFDEC_COLOR_G (in
);
92 b
= SWFDEC_COLOR_B (in
);
93 a
= SWFDEC_COLOR_A (in
);
95 SWFDEC_LOG ("in rgba %d,%d,%d,%d", r
, g
, b
, a
);
97 r
= (r
* trans
->ra
>> 8) + trans
->rb
;
98 g
= (g
* trans
->ga
>> 8) + trans
->gb
;
99 b
= (b
* trans
->ba
>> 8) + trans
->bb
;
100 a
= (a
* trans
->aa
>> 8) + trans
->ab
;
102 r
= CLAMP (r
, 0, 255);
103 g
= CLAMP (g
, 0, 255);
104 b
= CLAMP (b
, 0, 255);
105 a
= CLAMP (a
, 0, 255);
107 SWFDEC_LOG ("out rgba %d,%d,%d,%d", r
, g
, b
, a
);
109 return SWFDEC_COLOR_COMBINE (r
, g
, b
, a
);
113 * swfdec_color_transform_init_identity:
114 * @trans: a #SwfdecColorTransform
116 * Initializes the color transform so it doesn't transform any colors.
119 swfdec_color_transform_init_identity (SwfdecColorTransform
* trans
)
121 g_return_if_fail (trans
!= NULL
);
134 * swfdec_color_transform_init_color:
135 * @trans: a #SwfdecColorTransform
136 * @color: a #SwfdecColor to transform to
138 * Initializes this color transform so it results in exactly @color no matter
142 swfdec_color_transform_init_color (SwfdecColorTransform
*trans
, SwfdecColor color
)
145 trans
->rb
= SWFDEC_COLOR_R (color
);
147 trans
->gb
= SWFDEC_COLOR_G (color
);
149 trans
->bb
= SWFDEC_COLOR_B (color
);
151 trans
->ab
= SWFDEC_COLOR_A (color
);
155 swfdec_color_transform_is_identity (const SwfdecColorTransform
* trans
)
157 return trans
->ra
== 256 && trans
->ga
== 256 && trans
->ba
== 256 && trans
->aa
== 256 &&
158 trans
->rb
== 0 && trans
->gb
== 0 && trans
->bb
== 0 && trans
->ab
== 0;
162 * swfdec_color_transform_chain:
163 * @dest: #SwfdecColorTransform to take the result
164 * @last: a #SwfdecColorTransform
165 * @first: a #SwfdecColorTransform
167 * Computes a color transform that has the same effect as if the color
168 * transforms @first and @last would have been applied one after another.
171 swfdec_color_transform_chain (SwfdecColorTransform
*dest
,
172 const SwfdecColorTransform
*last
, const SwfdecColorTransform
*first
)
174 g_return_if_fail (dest
!= NULL
);
175 g_return_if_fail (last
!= NULL
);
176 g_return_if_fail (first
!= NULL
);
178 /* FIXME: CLAMP here? */
179 dest
->ra
= last
->ra
* first
->ra
>> 8;
180 dest
->rb
= (last
->ra
* first
->rb
>> 8) + last
->rb
;
181 dest
->ga
= last
->ga
* first
->ga
>> 8;
182 dest
->gb
= (last
->ga
* first
->gb
>> 8) + last
->gb
;
183 dest
->ba
= last
->ba
* first
->ba
>> 8;
184 dest
->bb
= (last
->ba
* first
->bb
>> 8) + last
->bb
;
185 dest
->aa
= last
->aa
* first
->aa
>> 8;
186 dest
->ab
= (last
->aa
* first
->ab
>> 8) + last
->ab
;
190 swfdec_matrix_ensure_invertible (cairo_matrix_t
*matrix
, cairo_matrix_t
*inverse
)
194 g_return_if_fail (matrix
!= NULL
);
199 g_assert (isfinite (matrix
->xx
) && isfinite (matrix
->yx
) && isfinite (matrix
->xy
) && isfinite (matrix
->yy
));
201 while (cairo_matrix_invert (inverse
)) {
202 SWFDEC_INFO ("matrix not invertible, adding epsilon to smallest member");
203 /* add epsilon at point closest to zero */
204 #define EPSILON (1.0 / SWFDEC_FIXED_SCALE_FACTOR)
205 if (ABS (matrix
->xx
) <= ABS (matrix
->xy
) &&
206 ABS (matrix
->xx
) <= ABS (matrix
->yx
) &&
207 ABS (matrix
->xx
) <= ABS (matrix
->yy
))
208 matrix
->xx
+= (matrix
->xx
>= 0) ? EPSILON
: -EPSILON
;
209 else if (ABS (matrix
->yy
) <= ABS (matrix
->xy
) &&
210 ABS (matrix
->yy
) <= ABS (matrix
->yx
))
211 matrix
->yy
+= (matrix
->yy
>= 0) ? EPSILON
: -EPSILON
;
212 else if (ABS (matrix
->xy
) <= ABS (matrix
->yx
))
213 matrix
->xy
+= (matrix
->xy
>= 0) ? EPSILON
: -EPSILON
;
215 matrix
->yx
+= (matrix
->yx
>= 0) ? EPSILON
: -EPSILON
;
221 swfdec_matrix_get_xscale (const cairo_matrix_t
*matrix
)
226 alpha
= atan2 (matrix
->yx
, matrix
->xx
);
228 return matrix
->xx
/ alpha
* 100;
230 return matrix
->yx
* 100;
235 swfdec_matrix_get_yscale (const cairo_matrix_t
*matrix
)
240 alpha
= atan2 (matrix
->xy
, matrix
->yy
);
242 return matrix
->yy
/ alpha
* 100;
244 return matrix
->xy
* 100;
249 swfdec_matrix_get_rotation (const cairo_matrix_t
*matrix
)
251 return atan2 (matrix
->yx
, matrix
->xx
) * 180 / G_PI
;
255 swfdec_matrix_morph (cairo_matrix_t
*dest
, const cairo_matrix_t
*start
,
256 const cairo_matrix_t
*end
, guint ratio
)
258 guint inv_ratio
= 65535 - ratio
;
259 g_assert (ratio
< 65536);
265 if (ratio
== 65535) {
269 dest
->xx
= (start
->xx
* inv_ratio
+ end
->xx
* ratio
) / 65535;
270 dest
->xy
= (start
->xy
* inv_ratio
+ end
->xy
* ratio
) / 65535;
271 dest
->yy
= (start
->yy
* inv_ratio
+ end
->yy
* ratio
) / 65535;
272 dest
->yx
= (start
->yx
* inv_ratio
+ end
->yx
* ratio
) / 65535;
273 dest
->x0
= (start
->x0
* inv_ratio
+ end
->x0
* ratio
) / 65535;
274 dest
->y0
= (start
->y0
* inv_ratio
+ end
->y0
* ratio
) / 65535;