diff --git a/clutter/clutter-paint-node-private.h b/clutter/clutter-paint-node-private.h index 346bda8f3..8e45f34f5 100644 --- a/clutter/clutter-paint-node-private.h +++ b/clutter/clutter-paint-node-private.h @@ -26,6 +26,7 @@ #define __CLUTTER_PAINT_NODE_PRIVATE_H__ #include +#include #include G_BEGIN_DECLS @@ -65,6 +66,8 @@ struct _ClutterPaintNodeClass gboolean (* pre_draw) (ClutterPaintNode *node); void (* draw) (ClutterPaintNode *node); void (* post_draw) (ClutterPaintNode *node); + + JsonNode*(* serialize) (ClutterPaintNode *node); }; typedef enum { diff --git a/clutter/clutter-paint-node.c b/clutter/clutter-paint-node.c index dc11191ea..a56f330ad 100644 --- a/clutter/clutter-paint-node.c +++ b/clutter/clutter-paint-node.c @@ -70,6 +70,7 @@ #include #include +#include #include "clutter-paint-node-private.h" @@ -778,47 +779,6 @@ clutter_paint_operation_clear (ClutterPaintOperation *op) } } -static void -clutter_paint_operation_to_string (const ClutterPaintOperation *op, - GString *buf, - int level) -{ - int i; - - for (i = 0; i < level; i++) - g_string_append (buf, " "); - - g_string_append (buf, "{ "); - - switch (op->opcode) - { - case PAINT_OP_INVALID: - break; - - case PAINT_OP_TEX_RECT: - g_string_append_printf (buf, "\"texrect\" : [ %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f ]", - op->op.texrect[0], - op->op.texrect[1], - op->op.texrect[2], - op->op.texrect[3], - op->op.texrect[4], - op->op.texrect[5], - op->op.texrect[6], - op->op.texrect[7]); - break; - - case PAINT_OP_PATH: - g_string_append_printf (buf, "\"path\" : \"0x%p\"", op->op.path); - break; - - case PAINT_OP_PRIMITIVE: - g_string_append_printf (buf, "\"primitive\" : \"0x%p\"", op->op.primitive); - break; - } - - g_string_append (buf, " }"); -} - static inline void clutter_paint_op_init_tex_rect (ClutterPaintOperation *op, const ClutterActorBox *rect, @@ -1016,113 +976,130 @@ _clutter_paint_node_paint (ClutterPaintNode *node) } } -static void -clutter_paint_node_to_string (ClutterPaintNode *node, - GString *buf, - int level) +#ifdef CLUTTER_ENABLE_DEBUG +static JsonNode * +clutter_paint_node_serialize (ClutterPaintNode *node) { - ClutterPaintNode *iter; - int i; + ClutterPaintNodeClass *klass = CLUTTER_PAINT_NODE_GET_CLASS (node); - for (i = 0; i < level; i++) - g_string_append (buf, " "); + if (klass->serialize != NULL) + return klass->serialize (node); - g_string_append_c (buf, '"'); - g_string_append (buf, g_type_name (G_TYPE_FROM_INSTANCE (node))); - g_string_append_c (buf, '"'); + return json_node_new (JSON_NODE_NULL); +} - g_string_append (buf, " : {\n"); +static JsonNode * +clutter_paint_node_to_json (ClutterPaintNode *node) +{ + JsonBuilder *builder; + JsonNode *res; - if (node->name != NULL) - { - for (i = 0; i < level + 1; i++) - g_string_append (buf, " "); + builder = json_builder_new (); - g_string_append_printf (buf, "\"name\" : \"%s\"", node->name); + json_builder_begin_object (builder); - if (node->operations != NULL || - node->first_child != NULL) - g_string_append_c (buf, ','); + json_builder_set_member_name (builder, "type"); + json_builder_add_string_value (builder, g_type_name (G_TYPE_FROM_INSTANCE (node))); - g_string_append_c (buf, '\n'); - } + json_builder_set_member_name (builder, "name"); + json_builder_add_string_value (builder, node->name); + + json_builder_set_member_name (builder, "node-data"); + json_builder_add_value (builder, clutter_paint_node_serialize (node)); + + json_builder_set_member_name (builder, "operations"); + json_builder_begin_array (builder); if (node->operations != NULL) { - guint o; + guint i; - for (i = 0; i < level + 1; i++) - g_string_append (buf, " "); - - g_string_append (buf, "\"operations\" : [\n"); - - for (o = 0; o < node->operations->len; o++) + for (i = 0; i < node->operations->len; i++) { const ClutterPaintOperation *op; - op = &g_array_index (node->operations, ClutterPaintOperation, o); - clutter_paint_operation_to_string (op, buf, level + 2); + op = &g_array_index (node->operations, ClutterPaintOperation, i); + json_builder_begin_object (builder); - if ((o + 1) != node->operations->len) - g_string_append_c (buf, ','); + switch (op->opcode) + { + case PAINT_OP_TEX_RECT: + json_builder_set_member_name (builder, "texrect"); + json_builder_begin_array (builder); + json_builder_add_double_value (builder, op->op.texrect[0]); + json_builder_add_double_value (builder, op->op.texrect[1]); + json_builder_add_double_value (builder, op->op.texrect[2]); + json_builder_add_double_value (builder, op->op.texrect[3]); + json_builder_add_double_value (builder, op->op.texrect[4]); + json_builder_add_double_value (builder, op->op.texrect[5]); + json_builder_add_double_value (builder, op->op.texrect[6]); + json_builder_add_double_value (builder, op->op.texrect[7]); + json_builder_end_array (builder); + break; - g_string_append_c (buf, '\n'); + case PAINT_OP_PATH: + json_builder_set_member_name (builder, "path"); + json_builder_add_int_value (builder, (gint64) op->op.path); + break; + + case PAINT_OP_PRIMITIVE: + json_builder_set_member_name (builder, "primitive"); + json_builder_add_int_value (builder, (gint64) op->op.primitive); + break; + + case PAINT_OP_INVALID: + break; + } + + json_builder_end_object (builder); } - - for (i = 0; i < level + 1; i++) - g_string_append (buf, " "); - - g_string_append (buf, "]"); - - if (node->first_child != NULL) - g_string_append_c (buf, ','); - - g_string_append_c (buf, '\n'); } - if (node->first_child == NULL) - goto out; + json_builder_end_array (builder); - for (i = 0; i < level + 1; i++) - g_string_append (buf, " "); + json_builder_set_member_name (builder, "children"); + json_builder_begin_array (builder); - g_string_append (buf, "\"children\" : [\n"); - - for (iter = node->first_child; - iter != NULL; - iter = iter->next_sibling) + if (node->first_child != NULL) { - clutter_paint_node_to_string (iter, buf, level + 2); + ClutterPaintNode *child; - if (iter->next_sibling != NULL) - g_string_append (buf, ",\n"); - else - g_string_append (buf, "\n"); + for (child = node->first_child; + child != NULL; + child = child->next_sibling) + { + JsonNode *n = clutter_paint_node_to_json (child); + + json_builder_add_value (builder, n); + } } - for (i = 0; i < level + 1; i++) - g_string_append (buf, " "); + json_builder_end_array (builder); - g_string_append (buf, "]\n"); + json_builder_end_object (builder); -out: - for (i = 0; i < level; i++) - g_string_append (buf, " "); + res = json_builder_get_root (builder); - g_string_append (buf, "}"); + g_object_unref (builder); + + return res; } +#endif /* CLUTTER_ENABLE_DEBUG */ void _clutter_paint_node_dump_tree (ClutterPaintNode *node) { #ifdef CLUTTER_ENABLE_DEBUG - GString *buf = g_string_sized_new (1024); + JsonGenerator *gen = json_generator_new (); + char *str; + gsize len; - clutter_paint_node_to_string (node, buf, 0); + json_generator_set_root (gen, clutter_paint_node_to_json (node)); + str = json_generator_to_data (gen, &len); - CLUTTER_NOTE (PAINT, "Render tree:\n%s", buf->str); + g_print ("Render tree starting from %p:\n%s\n", node, str); - g_string_free (buf, TRUE); + g_free (str); #endif /* CLUTTER_ENABLE_DEBUG */ } diff --git a/clutter/clutter-paint-nodes.c b/clutter/clutter-paint-nodes.c index c0868b3b5..4a4a6c323 100644 --- a/clutter/clutter-paint-nodes.c +++ b/clutter/clutter-paint-nodes.c @@ -398,6 +398,46 @@ clutter_pipeline_node_post_draw (ClutterPaintNode *node) cogl_pop_source (); } +static JsonNode * +clutter_pipeline_node_serialize (ClutterPaintNode *node) +{ + ClutterPipelineNode *pnode = CLUTTER_PIPELINE_NODE (node); + JsonBuilder *builder; + CoglColor color; + JsonNode *res; + + if (pnode->pipeline == NULL) + return json_node_new (JSON_NODE_NULL); + + builder = json_builder_new (); + json_builder_begin_object (builder); + + cogl_pipeline_get_color (pnode->pipeline, &color); + json_builder_set_member_name (builder, "color"); + json_builder_begin_array (builder); + json_builder_add_double_value (builder, cogl_color_get_red (&color)); + json_builder_add_double_value (builder, cogl_color_get_green (&color)); + json_builder_add_double_value (builder, cogl_color_get_blue (&color)); + json_builder_add_double_value (builder, cogl_color_get_alpha (&color)); + json_builder_end_array (builder); + +#if 0 + json_builder_set_member_name (builder, "layers"); + json_builder_begin_array (builder); + cogl_pipeline_foreach_layer (pnode->pipeline, + clutter_pipeline_node_serialize_layer, + builder); + json_builder_end_array (builder); +#endif + + json_builder_end_object (builder); + + res = json_builder_get_root (builder); + g_object_unref (builder); + + return res; +} + static void clutter_pipeline_node_class_init (ClutterPipelineNodeClass *klass) { @@ -408,6 +448,7 @@ clutter_pipeline_node_class_init (ClutterPipelineNodeClass *klass) node_class->draw = clutter_pipeline_node_draw; node_class->post_draw = clutter_pipeline_node_post_draw; node_class->finalize = clutter_pipeline_node_finalize; + node_class->serialize = clutter_pipeline_node_serialize; } static void @@ -714,6 +755,47 @@ clutter_text_node_draw (ClutterPaintNode *node) } } +static JsonNode * +clutter_text_node_serialize (ClutterPaintNode *node) +{ + ClutterTextNode *tnode = CLUTTER_TEXT_NODE (node); + JsonBuilder *builder; + JsonNode *res; + + builder = json_builder_new (); + + json_builder_begin_object (builder); + + json_builder_set_member_name (builder, "layout"); + + if (pango_layout_get_character_count (tnode->layout) > 12) + { + const char *text = pango_layout_get_text (tnode->layout); + char *str; + + str = g_strndup (text, 12); + json_builder_add_string_value (builder, str); + g_free (str); + } + else + json_builder_add_string_value (builder, pango_layout_get_text (tnode->layout)); + + json_builder_set_member_name (builder, "color"); + json_builder_begin_array (builder); + json_builder_add_double_value (builder, cogl_color_get_red (&tnode->color)); + json_builder_add_double_value (builder, cogl_color_get_green (&tnode->color)); + json_builder_add_double_value (builder, cogl_color_get_blue (&tnode->color)); + json_builder_add_double_value (builder, cogl_color_get_alpha (&tnode->color)); + json_builder_end_array (builder); + + json_builder_end_object (builder); + + res = json_builder_get_root (builder); + g_object_unref (builder); + + return res; +} + static void clutter_text_node_class_init (ClutterTextNodeClass *klass) { @@ -722,6 +804,7 @@ clutter_text_node_class_init (ClutterTextNodeClass *klass) node_class->pre_draw = clutter_text_node_pre_draw; node_class->draw = clutter_text_node_draw; node_class->finalize = clutter_text_node_finalize; + node_class->serialize = clutter_text_node_serialize; } static void