get rid of debugger bits
[swfdec.git] / libswfdec / swfdec_color.c
blobe609e5369657ca7c1743d630af5d979dc0573f30
1 /* Swfdec
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
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
26 #include <math.h>
27 #include "swfdec_color.h"
28 #include "swfdec_debug.h"
30 SwfdecColor
31 swfdec_color_apply_morph (SwfdecColor start, SwfdecColor end, guint ratio)
33 guint r, g, b, a;
34 guint start_ratio, end_ratio;
36 g_assert (ratio < 65536);
37 if (ratio == 0)
38 return start;
39 if (ratio == 65535)
40 return end;
41 start_ratio = 65535 - ratio;
42 end_ratio = 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);
51 void
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);
59 SwfdecColor
60 swfdec_color_apply_transform_premultiplied (SwfdecColor in,
61 const SwfdecColorTransform * trans)
63 int r, g, b, a, aold;
65 aold = SWFDEC_COLOR_A (in);
66 if (aold == 0)
67 return 0;
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;
76 r = CLAMP (r, 0, a);
77 g = (g * trans->ga * a / aold >> 8) + trans->gb * a / 255;
78 g = CLAMP (g, 0, a);
79 b = (b * trans->ba * a / aold >> 8) + trans->bb * a / 255;
80 b = CLAMP (b, 0, a);
82 return SWFDEC_COLOR_COMBINE (r, g, b, a);
85 SwfdecColor
86 swfdec_color_apply_transform (SwfdecColor in, const SwfdecColorTransform * trans)
88 int r, g, b, a;
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.
118 void
119 swfdec_color_transform_init_identity (SwfdecColorTransform * trans)
121 g_return_if_fail (trans != NULL);
123 trans->ra = 256;
124 trans->ga = 256;
125 trans->ba = 256;
126 trans->aa = 256;
127 trans->rb = 0;
128 trans->gb = 0;
129 trans->bb = 0;
130 trans->ab = 0;
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
139 * the input.
141 void
142 swfdec_color_transform_init_color (SwfdecColorTransform *trans, SwfdecColor color)
144 trans->ra = 0;
145 trans->rb = SWFDEC_COLOR_R (color);
146 trans->ga = 0;
147 trans->gb = SWFDEC_COLOR_G (color);
148 trans->ba = 0;
149 trans->bb = SWFDEC_COLOR_B (color);
150 trans->aa = 0;
151 trans->ab = SWFDEC_COLOR_A (color);
154 gboolean
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.
170 void
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;
189 void
190 swfdec_matrix_ensure_invertible (cairo_matrix_t *matrix, cairo_matrix_t *inverse)
192 cairo_matrix_t tmp;
194 g_return_if_fail (matrix != NULL);
196 if (inverse == NULL)
197 inverse = &tmp;
199 g_assert (isfinite (matrix->xx) && isfinite (matrix->yx) && isfinite (matrix->xy) && isfinite (matrix->yy));
200 *inverse = *matrix;
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;
214 else
215 matrix->yx += (matrix->yx >= 0) ? EPSILON : -EPSILON;
216 *inverse = *matrix;
220 double
221 swfdec_matrix_get_xscale (const cairo_matrix_t *matrix)
223 double alpha;
225 if (matrix->xx) {
226 alpha = atan2 (matrix->yx, matrix->xx);
227 alpha = cos (alpha);
228 return matrix->xx / alpha * 100;
229 } else {
230 return matrix->yx * 100;
234 double
235 swfdec_matrix_get_yscale (const cairo_matrix_t *matrix)
237 double alpha;
239 if (matrix->yy) {
240 alpha = atan2 (matrix->xy, matrix->yy);
241 alpha = cos (alpha);
242 return matrix->yy / alpha * 100;
243 } else {
244 return matrix->xy * 100;
248 double
249 swfdec_matrix_get_rotation (const cairo_matrix_t *matrix)
251 return atan2 (matrix->yx, matrix->xx) * 180 / G_PI;
254 void
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);
261 if (ratio == 0) {
262 *dest = *start;
263 return;
265 if (ratio == 65535) {
266 *dest = *end;
267 return;
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;