release 0.8.0
[swfdec.git] / swfdec / swfdec_draw.c
blob4fe9c26f88c8f72d76dff13c2e810ae5c792ab06
1 /* Swfdec
2 * Copyright (C) 2007 Benjamin Otte <otte@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301 USA
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include <string.h>
26 #include "swfdec_draw.h"
27 #include "swfdec_color.h"
28 #include "swfdec_debug.h"
29 #include "swfdec_path.h"
31 /*** DRAW ***/
33 G_DEFINE_ABSTRACT_TYPE (SwfdecDraw, swfdec_draw, G_TYPE_OBJECT);
35 static gboolean
36 swfdec_draw_can_morph (SwfdecDraw *draw)
38 return draw->end_path.num_data > 0;
41 static void
42 swfdec_draw_do_morph (SwfdecDraw* dest, SwfdecDraw *source, guint ratio)
44 if (swfdec_draw_can_morph (source)) {
45 swfdec_path_merge (&dest->path, &source->path, &source->end_path, ratio / 65535.);
46 } else {
47 swfdec_path_copy (&dest->path, &source->path);
51 static void
52 swfdec_draw_dispose (GObject *object)
54 SwfdecDraw *draw = SWFDEC_DRAW (object);
56 swfdec_path_reset (&draw->path);
57 swfdec_path_reset (&draw->end_path);
59 G_OBJECT_CLASS (swfdec_draw_parent_class)->dispose (object);
62 static void
63 swfdec_draw_class_init (SwfdecDrawClass *klass)
65 GObjectClass *object_class = G_OBJECT_CLASS (klass);
67 object_class->dispose = swfdec_draw_dispose;
69 klass->morph = swfdec_draw_do_morph;
72 static void
73 swfdec_draw_init (SwfdecDraw *draw)
75 swfdec_path_init (&draw->path);
76 swfdec_path_init (&draw->end_path);
79 /**
80 * swfdec_draw_morph:
81 * @draw: a #SwfdecDraw
82 * @ratio: ratio of the morph from 0 to 65535
84 * Applies a morph to the given drawing operation. If the drawing operation
85 * can not be morphed, it is returned unchanged. Otherwise a new drawing
86 * operation is created.
88 * Returns: a new reference to a #SwfdecDraw corresponding to the given morph
89 * ratio
90 **/
91 SwfdecDraw *
92 swfdec_draw_morph (SwfdecDraw *draw, guint ratio)
94 SwfdecDrawClass *klass;
95 SwfdecDraw *copy;
97 g_return_val_if_fail (SWFDEC_IS_DRAW (draw), NULL);
98 g_return_val_if_fail (ratio < 65536, NULL);
100 if (!swfdec_draw_can_morph (draw) || ratio == 0) {
101 /* not a morph */
102 g_object_ref (draw);
103 return draw;
105 klass = SWFDEC_DRAW_GET_CLASS (draw);
106 g_assert (klass->morph);
107 copy = g_object_new (G_OBJECT_CLASS_TYPE (klass), NULL);
108 klass->morph (copy, draw, ratio);
109 swfdec_draw_recompute (copy);
110 return copy;
113 SwfdecDraw *
114 swfdec_draw_copy (SwfdecDraw *draw)
116 SwfdecDrawClass *klass;
117 SwfdecDraw *copy;
119 g_return_val_if_fail (SWFDEC_IS_DRAW (draw), NULL);
121 klass = SWFDEC_DRAW_GET_CLASS (draw);
122 g_assert (klass->morph);
123 copy = g_object_new (G_OBJECT_CLASS_TYPE (klass), NULL);
124 klass->morph (copy, draw, 0);
125 swfdec_draw_recompute (copy);
126 return copy;
130 * swfdec_draw_paint:
131 * @draw: drawing operation to perform
132 * @cr: context to perform the operation on
133 * @trans: color transofrmation to apply
135 * Draws the given drawing operation on the given Cairo context.
137 void
138 swfdec_draw_paint (SwfdecDraw *draw, cairo_t *cr, const SwfdecColorTransform *trans)
140 SwfdecDrawClass *klass;
142 g_return_if_fail (SWFDEC_IS_DRAW (draw));
143 g_return_if_fail (draw->path.num_data > 0);
144 g_return_if_fail (cr != NULL);
145 g_return_if_fail (trans != NULL);
147 klass = SWFDEC_DRAW_GET_CLASS (draw);
148 g_assert (klass->paint);
149 klass->paint (draw, cr, trans);
152 static gpointer
153 swfdec_draw_init_empty_surface (gpointer unused)
155 return cairo_image_surface_create (CAIRO_FORMAT_A1, 1, 1);
159 * swfdec_draw_contains:
160 * @draw: a #SwfdecDraw
161 * @x: x coordinate to check
162 * @y: y coordinate to check
164 * Checks if the given @x and @y coordinate is inside or outside the area drawn
165 * by the given drawing operation.
167 * Returns: %TRUE if the coordinates are inside the drawing operation.
169 gboolean
170 swfdec_draw_contains (SwfdecDraw *draw, double x, double y)
172 static GOnce empty_surface = G_ONCE_INIT;
173 SwfdecDrawClass *klass;
174 cairo_t *cr;
175 gboolean result;
177 g_return_val_if_fail (SWFDEC_IS_DRAW (draw), FALSE);
179 if (!swfdec_rect_contains (&draw->extents, x, y))
180 return FALSE;
182 g_once (&empty_surface, swfdec_draw_init_empty_surface, NULL);
184 klass = SWFDEC_DRAW_GET_CLASS (draw);
185 g_assert (klass->contains);
186 cr = cairo_create (empty_surface.retval);
187 result = klass->contains (draw, cr, x, y);
188 cairo_destroy (cr);
189 return result;
193 * swfdec_draw_recompute:
194 * @draw: a #SwfdecDraw
196 * This function must be called after a call to swfdec_draw_append_path() but
197 * before using swfdec_draw_paint() again. It updates internal state and caches,
198 * in particular the extents of this drawing operation.
200 void
201 swfdec_draw_recompute (SwfdecDraw *draw)
203 SwfdecDrawClass *klass;
205 g_return_if_fail (SWFDEC_IS_DRAW (draw));
207 klass = SWFDEC_DRAW_GET_CLASS (draw);
208 g_assert (klass->compute_extents);
209 klass->compute_extents (draw);