#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "clutter-actor.h" #include "clutter-behaviour.h" #include "clutter-container.h" #include "clutter-script.h" #include "clutter-script-private.h" #include "clutter-scriptable.h" #include "clutter-debug.h" #include "clutter-private.h" GType clutter_script_get_type_from_symbol (const gchar *symbol) { static GModule *module = NULL; GTypeGetFunc func; GType gtype = G_TYPE_INVALID; if (!module) module = g_module_open (NULL, G_MODULE_BIND_LAZY); if (g_module_symbol (module, symbol, (gpointer)&func)) gtype = func (); return gtype; } GType clutter_script_get_type_from_class (const gchar *name) { static GModule *module = NULL; GTypeGetFunc func; GString *symbol_name = g_string_new (""); char c, *symbol; int i; GType gtype = G_TYPE_INVALID; if (!module) module = g_module_open (NULL, 0); for (i = 0; name[i] != '\0'; i++) { c = name[i]; /* skip if uppercase, first or previous is uppercase */ if ((c == g_ascii_toupper (c) && i > 0 && name[i-1] != g_ascii_toupper (name[i-1])) || (i > 2 && name[i] == g_ascii_toupper (name[i]) && name[i-1] == g_ascii_toupper (name[i-1]) && name[i-2] == g_ascii_toupper (name[i-2]))) g_string_append_c (symbol_name, '_'); g_string_append_c (symbol_name, g_ascii_tolower (c)); } g_string_append (symbol_name, "_get_type"); symbol = g_string_free (symbol_name, FALSE); if (g_module_symbol (module, symbol, (gpointer)&func)) { CLUTTER_NOTE (SCRIPT, "Type function: %s", symbol); gtype = func (); } g_free (symbol); return gtype; } gboolean clutter_script_enum_from_string (GType type, const gchar *string, gint *enum_value) { GEnumClass *eclass; GEnumValue *ev; gchar *endptr; gint value; gboolean retval = TRUE; g_return_val_if_fail (G_TYPE_IS_ENUM (type), 0); g_return_val_if_fail (string != NULL, 0); value = strtoul (string, &endptr, 0); if (endptr != string) /* parsed a number */ *enum_value = value; else { eclass = g_type_class_ref (type); ev = g_enum_get_value_by_name (eclass, string); if (!ev) ev = g_enum_get_value_by_nick (eclass, string); if (ev) *enum_value = ev->value; else retval = FALSE; g_type_class_unref (eclass); } return retval; } gboolean clutter_script_flags_from_string (GType type, const gchar *string, gint *flags_value) { GFlagsClass *fclass; gchar *endptr, *prevptr; guint i, j, ret, value; gchar *flagstr; GFlagsValue *fv; const gchar *flag; gunichar ch; gboolean eos; g_return_val_if_fail (G_TYPE_IS_FLAGS (type), 0); g_return_val_if_fail (string != 0, 0); ret = TRUE; value = strtoul (string, &endptr, 0); if (endptr != string) /* parsed a number */ *flags_value = value; else { fclass = g_type_class_ref (type); flagstr = g_strdup (string); for (value = i = j = 0; ; i++) { eos = flagstr[i] == '\0'; if (!eos && flagstr[i] != '|') continue; flag = &flagstr[j]; endptr = &flagstr[i]; if (!eos) { flagstr[i++] = '\0'; j = i; } /* trim spaces */ for (;;) { ch = g_utf8_get_char (flag); if (!g_unichar_isspace (ch)) break; flag = g_utf8_next_char (flag); } while (endptr > flag) { prevptr = g_utf8_prev_char (endptr); ch = g_utf8_get_char (prevptr); if (!g_unichar_isspace (ch)) break; endptr = prevptr; } if (endptr > flag) { *endptr = '\0'; fv = g_flags_get_value_by_name (fclass, flag); if (!fv) fv = g_flags_get_value_by_nick (fclass, flag); if (fv) value |= fv->value; else { ret = FALSE; break; } } if (eos) { *flags_value = value; break; } } g_free (flagstr); g_type_class_unref (fclass); } return ret; } static gboolean parse_knot_from_array (JsonArray *array, ClutterKnot *knot) { JsonNode *val; if (json_array_get_length (array) < 2) return FALSE; val = json_array_get_element (array, 0); if (JSON_NODE_TYPE (val) == JSON_NODE_VALUE) knot->x = json_node_get_int (val); val = json_array_get_element (array, 1); if (JSON_NODE_TYPE (val) == JSON_NODE_VALUE) knot->y = json_node_get_int (val); return TRUE; } static gboolean parse_knot_from_object (JsonObject *object, ClutterKnot *knot) { JsonNode *val; if (json_object_get_size (object) < 2) return FALSE; val = json_object_get_member (object, "x"); if (JSON_NODE_TYPE (val) == JSON_NODE_VALUE) knot->x = json_node_get_int (val); val = json_object_get_member (object, "y"); if (JSON_NODE_TYPE (val) == JSON_NODE_VALUE) knot->y = json_node_get_int (val); return TRUE; } gboolean clutter_script_parse_knot (ClutterScript *script, JsonNode *node, ClutterKnot *knot) { g_return_val_if_fail (CLUTTER_IS_SCRIPT (script), FALSE); g_return_val_if_fail (node != NULL, FALSE); g_return_val_if_fail (knot != NULL, FALSE); switch (JSON_NODE_TYPE (node)) { case JSON_NODE_ARRAY: return parse_knot_from_array (json_node_get_array (node), knot); case JSON_NODE_OBJECT: return parse_knot_from_object (json_node_get_object (node), knot); default: break; } return FALSE; } static gboolean parse_geometry_from_array (JsonArray *array, ClutterGeometry *geometry) { JsonNode *val; if (json_array_get_length (array) < 4) return FALSE; val = json_array_get_element (array, 0); if (JSON_NODE_TYPE (val) == JSON_NODE_VALUE) geometry->x = json_node_get_int (val); val = json_array_get_element (array, 1); if (JSON_NODE_TYPE (val) == JSON_NODE_VALUE) geometry->y = json_node_get_int (val); val = json_array_get_element (array, 2); if (JSON_NODE_TYPE (val) == JSON_NODE_VALUE) geometry->width = json_node_get_int (val); val = json_array_get_element (array, 3); if (JSON_NODE_TYPE (val) == JSON_NODE_VALUE) geometry->height = json_node_get_int (val); return TRUE; } static gboolean parse_geometry_from_object (JsonObject *object, ClutterGeometry *geometry) { JsonNode *val; if (json_object_get_size (object) < 4) return FALSE; val = json_object_get_member (object, "x"); if (JSON_NODE_TYPE (val) == JSON_NODE_VALUE) geometry->x = json_node_get_int (val); val = json_object_get_member (object, "y"); if (JSON_NODE_TYPE (val) == JSON_NODE_VALUE) geometry->y = json_node_get_int (val); val = json_object_get_member (object, "width"); if (JSON_NODE_TYPE (val) == JSON_NODE_VALUE) geometry->width = json_node_get_int (val); val = json_object_get_member (object, "height"); if (JSON_NODE_TYPE (val) == JSON_NODE_VALUE) geometry->height = json_node_get_int (val); return TRUE; } gboolean clutter_script_parse_geometry (ClutterScript *script, JsonNode *node, ClutterGeometry *geometry) { g_return_val_if_fail (CLUTTER_IS_SCRIPT (script), FALSE); g_return_val_if_fail (node != NULL, FALSE); g_return_val_if_fail (geometry != NULL, FALSE); switch (JSON_NODE_TYPE (node)) { case JSON_NODE_ARRAY: return parse_geometry_from_array (json_node_get_array (node), geometry); case JSON_NODE_OBJECT: return parse_geometry_from_object (json_node_get_object (node), geometry); default: break; } return FALSE; }