Add LaughSize, a type that handles absolute and relative values
[laugh.git] / src / laugh-layout.c
blob96cb93fde4da3340ee9d08ca77bd969badf92d87
1 /*
2 * Laugh.
4 * An glib SMIL library.
6 * Authored By Koos Vriezen <koos.vriezen@gmail.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
24 /**
25 * SECTION:laugh-layout
26 * @short_description: DOM layout classes.
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
33 #include "laugh-layout.h"
34 #include "laugh-io.h"
36 #include <string.h>
37 #include <stdlib.h>
38 #include <glib/gprintf.h>
40 #define LAUGH_LAYOUT_GET_PRIVATE(obj) \
41 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), LAUGH_TYPE_LAYOUT, LaughLayoutPrivate))
44 struct _LaughLayoutPrivate
46 /*ClutterGroup *clutter_group;
47 ClutterActor *background_actor;*/
48 LaughIO *io;
51 static gpointer laugh_layout_parent_class = ((void *)0);
53 static void laugh_layout_finalize (GObject *object)
55 G_OBJECT_CLASS (laugh_layout_parent_class)->finalize (object);
58 static void laugh_layout_dispose (GObject *object)
60 LaughLayout *layout = LAUGH_LAYOUT(object);
62 G_OBJECT_CLASS (laugh_layout_parent_class)->dispose (object);
65 void _lauch_layout_mime_type (LaughIO *io, const gchar *mime, gpointer d)
67 g_printf ("lauch_layout_mime_type: %s\n", mime);
68 if (strncmp (mime, "image/", 6)) {
69 LaughNode *node = LAUGH_NODE (d);
71 g_printerr ("region background not an image\n");
72 laugh_io_cancel (io);
74 g_object_unref (G_OBJECT (io));
76 laugh_node_base_emit_initialized (node);
80 static void
81 _lauch_layout_completed (LaughIO *io, gsize sz, gpointer data, gpointer d)
83 LaughNode *node = LAUGH_NODE (d);
85 g_printf ("_lauch_layout_completed: %u\n", sz);
86 if (data) {
87 /* create Pixbuf and ClutterActor*/
89 g_free (data);
91 g_object_unref (G_OBJECT (io));
93 laugh_node_base_emit_initialized (node);
96 static void _laugh_layout_init (LaughNode *node, LaughInitializer *initializer)
98 LaughLayoutPrivate *priv = LAUGH_LAYOUT (node)->priv;
99 const gchar *bg_image = laugh_node_get_attribute (node,
100 g_quark_from_string ("backgroundImage"));
102 if (bg_image) {
103 priv->io = laugh_io_new (bg_image);
105 g_signal_connect (G_OBJECT (priv->io), "mime-type",
106 (GCallback) _lauch_layout_mime_type, (gpointer) node);
107 g_signal_connect (G_OBJECT (priv->io), "completed",
108 (GCallback) _lauch_layout_completed, (gpointer) node);
110 laugh_io_open (priv->io);
111 } else {
112 laugh_node_base_emit_initialized (node);
116 static void laugh_layout_class_init (LaughLayoutClass *klass)
118 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
119 LaughNodeClass *node_class = (LaughNodeClass *) klass;
121 laugh_layout_parent_class = g_type_class_peek_parent (klass);
123 gobject_class->finalize = laugh_layout_finalize;
124 gobject_class->dispose = laugh_layout_dispose;
125 node_class->init = _laugh_layout_init;
127 g_type_class_add_private (gobject_class, sizeof (LaughLayoutPrivate));
130 static
131 void laugh_layout_instance_init (GTypeInstance *instance, gpointer g_class)
133 LaughLayout *self = (LaughLayout *)instance;
135 self->priv = LAUGH_LAYOUT_GET_PRIVATE (self);
138 GType laugh_layout_get_type (void)
140 static GType type = 0;
141 if (type == 0) {
142 static const GTypeInfo info = {
143 sizeof (LaughLayoutClass),
144 NULL, /* base_init */
145 NULL, /* base_finalize */
146 (GClassInitFunc) laugh_layout_class_init, /* class_init */
147 NULL, /* class_finalize */
148 NULL, /* class_data */
149 sizeof (LaughLayout),
150 0, /* n_preallocs */
151 laugh_layout_instance_init /* instance_init */
153 type = g_type_register_static (LAUGH_TYPE_NODE,
154 "LaughLayoutType",
155 &info, 0);
157 return type;
160 void laugh_size_set_string (LaughSize *size, const gchar *value)
162 char *ep;
163 char *p = strchr (value, '%');
165 if (p) {
166 size->abs_size = 0.0;
167 size->perc_size = strtod (value, &ep);
168 size->is_set = ep != value;
169 } else {
170 size->abs_size = strtod (value, &ep);
171 size->perc_size = 0.0;
172 size->is_set = ep != value;
176 float laugh_size_get_size (LaughSize *size, float relative_to)
178 return size->abs_size + size->perc_size * relative_to / 100;
181 void laugh_size_setting_get (LaughSizeSetting *sizes, float pw, float ph,
182 float *x, float *y, float *w, float *h) {
183 if (sizes->left.is_set) {
184 *x = laugh_size_get_size (&sizes->left, pw);
185 } else if (sizes->width.is_set) {
186 if (sizes->right.is_set)
187 *x = pw -
188 laugh_size_get_size (&sizes->width, pw) -
189 laugh_size_get_size (&sizes->right, pw);
190 else
191 *x = (pw - laugh_size_get_size (&sizes->width, pw)) / 2;
192 } else {
193 *x = 0;
196 if (sizes->top.is_set) {
197 *y = laugh_size_get_size (&sizes->top, ph);
198 } else if (sizes->height.is_set) {
199 if (sizes->bottom.is_set)
200 *y = ph -
201 laugh_size_get_size (&sizes->height, ph) -
202 laugh_size_get_size (&sizes->bottom, ph);
203 else
204 *y = (ph - laugh_size_get_size (&sizes->height, ph)) / 2;
205 } else {
206 *y = 0;
209 if (sizes->width.is_set)
210 *w = laugh_size_get_size (&sizes->width, pw);
211 else if (sizes->right.is_set)
212 *w = pw - *x -laugh_size_get_size (&sizes->right, pw);
213 else
214 *w = pw - *x;
215 if (*w < 0)
216 *w = 0;
218 if (sizes->height.is_set)
219 *h = laugh_size_get_size (&sizes->height, ph);
220 else if (sizes->bottom.is_set)
221 *h = ph - *y - laugh_size_get_size (&sizes->bottom, ph);
222 else
223 *h = ph - *y;
224 if (*h < 0)
225 *h = 0;
228 LaughNode *laugh_layout_new (LaughDocument *doc, LaughNodeTagId id,
229 GHashTable *attributes)
231 LaughNode *node = LAUGH_NODE(g_object_new (LAUGH_TYPE_LAYOUT, NULL));
233 laugh_node_base_init (doc, node, id, attributes);
235 return node;
238 #ifdef LAIGH_TEST_SIZES
239 /* gcc laugh-dom.c laugh-io.c laugh-layout.c -o sizestest `pkg-config --libs --cflags glib-2.0 gio-2.0 gthread-2.0` -lexpat -DLAIGH_TEST_SIZES */
240 void test_sizes (float pw, float ph,
241 const gchar *left, const gchar *top,
242 const gchar *width, const gchar *height,
243 const gchar *right, const gchar *bottom)
245 LaughSizeSetting sizes;
246 float x, y, w, h;
247 memset (&sizes, 0, sizeof (LaughSizeSetting));
248 if (left)
249 laugh_size_set_string (&sizes.left, left);
250 if (top)
251 laugh_size_set_string (&sizes.top, top);
252 if (width)
253 laugh_size_set_string (&sizes.width, width);
254 if (height)
255 laugh_size_set_string (&sizes.height, height);
256 if (right)
257 laugh_size_set_string (&sizes.right, right);
258 if (bottom)
259 laugh_size_set_string (&sizes.bottom, bottom);
260 laugh_size_setting_get (&sizes, pw, ph, &x, &y, &w, &h);
261 g_printf ("left %s top %s width %s height %s right %s bottom %s\n"
262 "\t(%.1fx%.1f) => [%.1f, %.1f %.1fx%.1f]\n",
263 pw, ph,
264 left, top, width, height, right, bottom,
265 x, y, w, h);
268 int main()
270 test_sizes (320, 240, "50", "30", "200", "180", NULL, NULL);
271 test_sizes (320, 240, "50", "30", NULL, NULL, "40", "20");
272 test_sizes (320, 240, "50", "30", "50%", "60%", NULL, NULL);
273 test_sizes (320, 240, "50", "30", NULL, NULL, "10%", "20%");
275 return 0;
278 #endif