4 * An OpenGL based 'interactive canvas' library.
6 * Copyright (C) 2011 Intel Corporation.
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, see <http://www.gnu.org/licenses/>.
22 * Emmanuele Bassi <ebassi@linux.intel.com>
26 * SECTION:clutter-paint-node
27 * @Title: ClutterPaintNode
28 * @Short_Description: Paint objects
30 * #ClutterPaintNode is an element in the render graph.
32 * The render graph contains all the elements that need to be painted by
33 * Clutter when submitting a frame to the graphics system.
35 * The render graph is distinct from the scene graph: the scene graph is
36 * composed by actors, which can be visible or invisible; the scene graph
37 * elements also respond to events. The render graph, instead, is only
38 * composed by nodes that will be painted.
40 * Each #ClutterActor can submit multiple #ClutterPaintNode<!-- -->s to
47 * The <structname>ClutterPaintNode</structname> structure contains only
48 * private data and it should be accessed using the provided API.
50 * Ref Func: clutter_paint_node_ref
51 * Unref Func: clutter_paint_node_unref
52 * Set Value Func: clutter_value_set_paint_node
53 * Get Value Func: clutter_value_get_paint_node
59 * ClutterPaintNodeClass:
61 * The <structname>ClutterPaintNodeClass</structname> structure contains
71 #define CLUTTER_ENABLE_EXPERIMENTAL_API
73 #include <pango/pango.h>
74 #include <cogl/cogl.h>
75 #include <json-glib/json-glib.h>
77 #include "clutter-paint-node-private.h"
79 #include "clutter-debug.h"
80 #include "clutter-private.h"
82 #include <gobject/gvaluecollector.h>
84 static inline void clutter_paint_operation_clear (ClutterPaintOperation *op);
87 value_paint_node_init (GValue *value)
89 value->data[0].v_pointer = NULL;
93 value_paint_node_free_value (GValue *value)
95 if (value->data[0].v_pointer != NULL)
96 clutter_paint_node_unref (value->data[0].v_pointer);
100 value_paint_node_copy_value (const GValue *src,
103 if (src->data[0].v_pointer != NULL)
104 dst->data[0].v_pointer = clutter_paint_node_ref (src->data[0].v_pointer);
106 dst->data[0].v_pointer = NULL;
110 value_paint_node_peek_pointer (const GValue *value)
112 return value->data[0].v_pointer;
116 value_paint_node_collect_value (GValue *value,
117 guint n_collect_values,
118 GTypeCValue *collect_values,
121 ClutterPaintNode *node;
123 node = collect_values[0].v_pointer;
127 value->data[0].v_pointer = NULL;
131 if (node->parent_instance.g_class == NULL)
132 return g_strconcat ("invalid unclassed ClutterPaintNode pointer for "
134 G_VALUE_TYPE_NAME (value),
138 value->data[0].v_pointer = clutter_paint_node_ref (node);
144 value_paint_node_lcopy_value (const GValue *value,
145 guint n_collect_values,
146 GTypeCValue *collect_values,
149 ClutterPaintNode **node_p = collect_values[0].v_pointer;
152 return g_strconcat ("value location for '",
153 G_VALUE_TYPE_NAME (value),
157 if (value->data[0].v_pointer == NULL)
159 else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
160 *node_p = value->data[0].v_pointer;
162 *node_p = clutter_paint_node_ref (value->data[0].v_pointer);
168 clutter_paint_node_class_base_init (ClutterPaintNodeClass *klass)
173 clutter_paint_node_class_base_finalize (ClutterPaintNodeClass *klass)
178 clutter_paint_node_real_finalize (ClutterPaintNode *node)
180 ClutterPaintNode *iter;
184 if (node->operations != NULL)
188 for (i = 0; i < node->operations->len; i++)
190 ClutterPaintOperation *op;
192 op = &g_array_index (node->operations, ClutterPaintOperation, i);
193 clutter_paint_operation_clear (op);
196 g_array_unref (node->operations);
199 iter = node->first_child;
202 ClutterPaintNode *next = iter->next_sibling;
204 clutter_paint_node_remove_child (node, iter);
209 g_type_free_instance ((GTypeInstance *) node);
213 clutter_paint_node_real_pre_draw (ClutterPaintNode *node)
219 clutter_paint_node_real_draw (ClutterPaintNode *node)
224 clutter_paint_node_real_post_draw (ClutterPaintNode *node)
229 clutter_paint_node_class_init (ClutterPaintNodeClass *klass)
231 klass->pre_draw = clutter_paint_node_real_pre_draw;
232 klass->draw = clutter_paint_node_real_draw;
233 klass->post_draw = clutter_paint_node_real_post_draw;
234 klass->finalize = clutter_paint_node_real_finalize;
238 clutter_paint_node_init (ClutterPaintNode *self)
244 clutter_paint_node_get_type (void)
246 static volatile gsize paint_node_type_id__volatile = 0;
248 if (g_once_init_enter (&paint_node_type_id__volatile))
250 static const GTypeFundamentalInfo finfo = {
251 (G_TYPE_FLAG_CLASSED |
252 G_TYPE_FLAG_INSTANTIATABLE |
253 G_TYPE_FLAG_DERIVABLE |
254 G_TYPE_FLAG_DEEP_DERIVABLE),
257 static const GTypeValueTable value_table = {
258 value_paint_node_init,
259 value_paint_node_free_value,
260 value_paint_node_copy_value,
261 value_paint_node_peek_pointer,
263 value_paint_node_collect_value,
265 value_paint_node_lcopy_value,
268 const GTypeInfo node_info = {
269 sizeof (ClutterPaintNodeClass),
271 (GBaseInitFunc) clutter_paint_node_class_base_init,
272 (GBaseFinalizeFunc) clutter_paint_node_class_base_finalize,
273 (GClassInitFunc) clutter_paint_node_class_init,
274 (GClassFinalizeFunc) NULL,
277 sizeof (ClutterPaintNode),
279 (GInstanceInitFunc) clutter_paint_node_init,
284 GType paint_node_type_id =
285 g_type_register_fundamental (g_type_fundamental_next (),
286 I_("ClutterPaintNode"),
288 G_TYPE_FLAG_ABSTRACT);
290 g_once_init_leave (&paint_node_type_id__volatile, paint_node_type_id);
293 return paint_node_type_id__volatile;
297 * clutter_paint_node_set_name:
298 * @node: a #ClutterPaintNode
299 * @name: a string annotating the @node
301 * Sets a user-readable @name for @node.
303 * The @name will be used for debugging purposes.
305 * The @node will copy the passed string.
310 clutter_paint_node_set_name (ClutterPaintNode *node,
313 g_return_if_fail (CLUTTER_IS_PAINT_NODE (node));
316 node->name = g_strdup (name);
320 * clutter_paint_node_ref:
321 * @node: a #ClutterPaintNode
323 * Acquires a reference on @node.
325 * Return value: (transfer full): the #ClutterPaintNode
330 clutter_paint_node_ref (ClutterPaintNode *node)
332 g_return_val_if_fail (CLUTTER_IS_PAINT_NODE (node), NULL);
334 g_atomic_int_inc (&node->ref_count);
340 * clutter_paint_node_unref:
341 * @node: a #ClutterPaintNode
343 * Releases a reference on @node.
348 clutter_paint_node_unref (ClutterPaintNode *node)
350 g_return_if_fail (CLUTTER_IS_PAINT_NODE (node));
352 if (g_atomic_int_dec_and_test (&node->ref_count))
354 ClutterPaintNodeClass *klass = CLUTTER_PAINT_NODE_GET_CLASS (node);
356 klass->finalize (node);
361 * clutter_paint_node_add_child:
362 * @node: a #ClutterPaintNode
363 * @child: the child #ClutterPaintNode to add
365 * Adds @child to the list of children of @node.
367 * This function will acquire a reference on @child.
372 clutter_paint_node_add_child (ClutterPaintNode *node,
373 ClutterPaintNode *child)
375 g_return_if_fail (CLUTTER_IS_PAINT_NODE (node));
376 g_return_if_fail (CLUTTER_IS_PAINT_NODE (child));
377 g_return_if_fail (node != child);
378 g_return_if_fail (child->parent == NULL);
380 child->parent = node;
381 clutter_paint_node_ref (child);
383 node->n_children += 1;
385 child->prev_sibling = node->last_child;
387 if (node->last_child != NULL)
389 ClutterPaintNode *tmp = node->last_child;
391 tmp->next_sibling = child;
394 if (child->prev_sibling == NULL)
395 node->first_child = child;
397 if (child->next_sibling == NULL)
398 node->last_child = child;
402 * clutter_paint_node_remove_child:
403 * @node: a #ClutterPaintNode
404 * @child: the #ClutterPaintNode to remove
406 * Removes @child from the list of children of @node.
408 * This function will release the reference on @child acquired by
409 * using clutter_paint_node_add_child().
414 clutter_paint_node_remove_child (ClutterPaintNode *node,
415 ClutterPaintNode *child)
417 ClutterPaintNode *prev, *next;
419 g_return_if_fail (CLUTTER_IS_PAINT_NODE (node));
420 g_return_if_fail (CLUTTER_IS_PAINT_NODE (child));
421 g_return_if_fail (node != child);
422 g_return_if_fail (child->parent == node);
424 node->n_children -= 1;
426 prev = child->prev_sibling;
427 next = child->next_sibling;
430 prev->next_sibling = next;
433 next->prev_sibling = prev;
435 if (node->first_child == child)
436 node->first_child = next;
438 if (node->last_child == child)
439 node->last_child = prev;
441 child->prev_sibling = NULL;
442 child->next_sibling = NULL;
443 child->parent = NULL;
445 clutter_paint_node_unref (child);
449 * clutter_paint_node_replace_child:
450 * @node: a #ClutterPaintNode
451 * @old_child: the child replaced by @new_child
452 * @new_child: the child that replaces @old_child
454 * Atomically replaces @old_child with @new_child in the list of
457 * This function will release the reference on @old_child acquired
458 * by @node, and will acquire a new reference on @new_child.
463 clutter_paint_node_replace_child (ClutterPaintNode *node,
464 ClutterPaintNode *old_child,
465 ClutterPaintNode *new_child)
467 ClutterPaintNode *prev, *next;
469 g_return_if_fail (CLUTTER_IS_PAINT_NODE (node));
470 g_return_if_fail (CLUTTER_IS_PAINT_NODE (old_child));
471 g_return_if_fail (old_child->parent == node);
472 g_return_if_fail (CLUTTER_IS_PAINT_NODE (new_child));
473 g_return_if_fail (new_child->parent == NULL);
475 prev = old_child->prev_sibling;
476 next = old_child->next_sibling;
478 new_child->parent = node;
479 new_child->prev_sibling = prev;
480 new_child->next_sibling = next;
481 clutter_paint_node_ref (new_child);
484 prev->next_sibling = new_child;
487 next->prev_sibling = new_child;
489 if (node->first_child == old_child)
490 node->first_child = new_child;
492 if (node->last_child == old_child)
493 node->last_child = new_child;
495 old_child->prev_sibling = NULL;
496 old_child->next_sibling = NULL;
497 old_child->parent = NULL;
498 clutter_paint_node_unref (old_child);
502 * clutter_paint_node_remove_all:
503 * @node: a #ClutterPaintNode
505 * Removes all children of @node.
507 * This function releases the reference acquired by @node on its
513 clutter_paint_node_remove_all (ClutterPaintNode *node)
515 ClutterPaintNode *iter;
517 g_return_if_fail (CLUTTER_IS_PAINT_NODE (node));
519 iter = node->first_child;
522 ClutterPaintNode *next = iter->next_sibling;
524 clutter_paint_node_remove_child (node, iter);
531 * clutter_paint_node_get_first_child:
532 * @node: a #ClutterPaintNode
534 * Retrieves the first child of the @node.
536 * Return value: (transfer none): a pointer to the first child of
537 * the #ClutterPaintNode.
542 clutter_paint_node_get_first_child (ClutterPaintNode *node)
544 g_return_val_if_fail (CLUTTER_IS_PAINT_NODE (node), NULL);
546 return node->first_child;
550 * clutter_paint_node_get_previous_sibling:
551 * @node: a #ClutterPaintNode
553 * Retrieves the previous sibling of @node.
555 * Return value: (transfer none): a pointer to the previous sibling
556 * of the #ClutterPaintNode.
561 clutter_paint_node_get_previous_sibling (ClutterPaintNode *node)
563 g_return_val_if_fail (CLUTTER_IS_PAINT_NODE (node), NULL);
565 return node->prev_sibling;
569 * clutter_paint_node_get_next_sibling:
570 * @node: a #ClutterPaintNode
572 * Retrieves the next sibling of @node.
574 * Return value: (transfer none): a pointer to the next sibling
575 * of a #ClutterPaintNode
580 clutter_paint_node_get_next_sibling (ClutterPaintNode *node)
582 g_return_val_if_fail (CLUTTER_IS_PAINT_NODE (node), NULL);
584 return node->next_sibling;
588 * clutter_paint_node_get_last_child:
589 * @node: a #ClutterPaintNode
591 * Retrieves the last child of @node.
593 * Return value: (transfer none): a pointer to the last child
594 * of a #ClutterPaintNode
599 clutter_paint_node_get_last_child (ClutterPaintNode *node)
601 g_return_val_if_fail (CLUTTER_IS_PAINT_NODE (node), NULL);
603 return node->last_child;
607 * clutter_paint_node_get_parent:
608 * @node: a #ClutterPaintNode
610 * Retrieves the parent of @node.
612 * Return value: (transfer none): a pointer to the parent of
613 * a #ClutterPaintNode
618 clutter_paint_node_get_parent (ClutterPaintNode *node)
620 g_return_val_if_fail (CLUTTER_IS_PAINT_NODE (node), NULL);
626 * clutter_paint_node_get_n_children:
627 * @node: a #ClutterPaintNode
629 * Retrieves the number of children of @node.
631 * Return value: the number of children of a #ClutterPaintNode
636 clutter_paint_node_get_n_children (ClutterPaintNode *node)
638 g_return_val_if_fail (CLUTTER_IS_PAINT_NODE (node), 0);
640 return node->n_children;
644 * clutter_value_set_paint_node:
645 * @value: a #GValue initialized with %CLUTTER_TYPE_PAINT_NODE
646 * @node: (type Clutter.PaintNode) (allow-none): a #ClutterPaintNode, or %NULL
648 * Sets the contents of a #GValue initialized with %CLUTTER_TYPE_PAINT_NODE.
650 * This function increased the reference count of @node; if you do not wish
651 * to increase the reference count, use clutter_value_take_paint_node()
652 * instead. The reference count will be released by g_value_unset().
657 clutter_value_set_paint_node (GValue *value,
660 ClutterPaintNode *old_node;
662 g_return_if_fail (CLUTTER_VALUE_HOLDS_PAINT_NODE (value));
664 old_node = value->data[0].v_pointer;
668 g_return_if_fail (CLUTTER_IS_PAINT_NODE (node));
670 value->data[0].v_pointer = clutter_paint_node_ref (node);
673 value->data[0].v_pointer = NULL;
675 if (old_node != NULL)
676 clutter_paint_node_unref (old_node);
680 * clutter_value_take_paint_node:
681 * @value: a #GValue, initialized with %CLUTTER_TYPE_PAINT_NODE
682 * @node: (type Clutter.PaintNode) (allow-none): a #ClutterPaintNode, or %NULL
684 * Sets the contents of a #GValue initialized with %CLUTTER_TYPE_PAINT_NODE.
686 * Unlike clutter_value_set_paint_node(), this function will not take a
687 * reference on the passed @node: instead, it will take ownership of the
688 * current reference count.
693 clutter_value_take_paint_node (GValue *value,
696 ClutterPaintNode *old_node;
698 g_return_if_fail (CLUTTER_VALUE_HOLDS_PAINT_NODE (value));
700 old_node = value->data[0].v_pointer;
704 g_return_if_fail (CLUTTER_IS_PAINT_NODE (node));
706 /* take over ownership */
707 value->data[0].v_pointer = node;
710 value->data[0].v_pointer = NULL;
712 if (old_node != NULL)
713 clutter_paint_node_unref (old_node);
717 * clutter_value_get_paint_node:
718 * @value: a #GValue initialized with %CLUTTER_TYPE_PAINT_NODE
720 * Retrieves a pointer to the #ClutterPaintNode contained inside
721 * the passed #GValue.
723 * Return value: (transfer none) (type Clutter.PaintNode): a pointer to
724 * a #ClutterPaintNode, or %NULL
729 clutter_value_get_paint_node (const GValue *value)
731 g_return_val_if_fail (CLUTTER_VALUE_HOLDS_PAINT_NODE (value), NULL);
733 return value->data[0].v_pointer;
737 * clutter_value_dup_paint_node:
738 * @value: a #GValue initialized with %CLUTTER_TYPE_PAINT_NODE
740 * Retrieves a pointer to the #ClutterPaintNode contained inside
741 * the passed #GValue, and if not %NULL it will increase the
744 * Return value: (transfer full) (type Clutter.PaintNode): a pointer
745 * to the #ClutterPaintNode, with its reference count increased,
751 clutter_value_dup_paint_node (const GValue *value)
753 g_return_val_if_fail (CLUTTER_VALUE_HOLDS_PAINT_NODE (value), NULL);
755 if (value->data[0].v_pointer != NULL)
756 return clutter_paint_node_ref (value->data[0].v_pointer);
762 clutter_paint_operation_clear (ClutterPaintOperation *op)
766 case PAINT_OP_INVALID:
769 case PAINT_OP_TEX_RECT:
773 if (op->op.path != NULL)
774 cogl_object_unref (op->op.path);
777 case PAINT_OP_PRIMITIVE:
778 if (op->op.primitive != NULL)
779 cogl_object_unref (op->op.primitive);
785 clutter_paint_op_init_tex_rect (ClutterPaintOperation *op,
786 const ClutterActorBox *rect,
792 clutter_paint_operation_clear (op);
794 op->opcode = PAINT_OP_TEX_RECT;
795 op->op.texrect[0] = rect->x1;
796 op->op.texrect[1] = rect->y1;
797 op->op.texrect[2] = rect->x2;
798 op->op.texrect[3] = rect->y2;
799 op->op.texrect[4] = x_1;
800 op->op.texrect[5] = y_1;
801 op->op.texrect[6] = x_2;
802 op->op.texrect[7] = y_2;
806 clutter_paint_op_init_path (ClutterPaintOperation *op,
809 clutter_paint_operation_clear (op);
811 op->opcode = PAINT_OP_PATH;
812 op->op.path = cogl_object_ref (path);
816 clutter_paint_op_init_primitive (ClutterPaintOperation *op,
817 CoglPrimitive *primitive)
819 clutter_paint_operation_clear (op);
821 op->opcode = PAINT_OP_PRIMITIVE;
822 op->op.primitive = cogl_object_ref (primitive);
826 clutter_paint_node_maybe_init_operations (ClutterPaintNode *node)
828 if (node->operations != NULL)
832 g_array_new (FALSE, FALSE, sizeof (ClutterPaintOperation));
836 * clutter_paint_node_add_rectangle:
837 * @node: a #ClutterPaintNode
838 * @rect: a #ClutterActorBox
840 * Adds a rectangle region to the @node, as described by the
846 clutter_paint_node_add_rectangle (ClutterPaintNode *node,
847 const ClutterActorBox *rect)
849 ClutterPaintOperation operation = PAINT_OP_INIT;
851 g_return_if_fail (CLUTTER_IS_PAINT_NODE (node));
852 g_return_if_fail (rect != NULL);
854 clutter_paint_node_maybe_init_operations (node);
856 clutter_paint_op_init_tex_rect (&operation, rect, 0.0, 0.0, 1.0, 1.0);
857 g_array_append_val (node->operations, operation);
861 * clutter_paint_node_add_texture_rectangle:
862 * @node: a #ClutterPaintNode
863 * @rect: a #ClutterActorBox
864 * @x_1: the left X coordinate of the texture
865 * @y_1: the top Y coordinate of the texture
866 * @x_2: the right X coordinate of the texture
867 * @y_2: the bottom Y coordinate of the texture
869 * Adds a rectangle region to the @node, with texture coordinates.
874 clutter_paint_node_add_texture_rectangle (ClutterPaintNode *node,
875 const ClutterActorBox *rect,
881 ClutterPaintOperation operation = PAINT_OP_INIT;
883 g_return_if_fail (CLUTTER_IS_PAINT_NODE (node));
884 g_return_if_fail (rect != NULL);
886 clutter_paint_node_maybe_init_operations (node);
888 clutter_paint_op_init_tex_rect (&operation, rect, x_1, y_1, x_2, y_2);
889 g_array_append_val (node->operations, operation);
893 * clutter_paint_node_add_path:
894 * @node: a #ClutterPaintNode
897 * Adds a region described as a path to the @node.
899 * This function acquires a reference on the passed @path, so it
900 * is safe to call cogl_object_unref() when it returns.
903 * Stability: unstable
906 clutter_paint_node_add_path (ClutterPaintNode *node,
909 ClutterPaintOperation operation = PAINT_OP_INIT;
911 g_return_if_fail (CLUTTER_IS_PAINT_NODE (node));
912 g_return_if_fail (cogl_is_path (path));
914 clutter_paint_node_maybe_init_operations (node);
916 clutter_paint_op_init_path (&operation, path);
917 g_array_append_val (node->operations, operation);
921 * clutter_paint_node_add_primitive:
922 * @node: a #ClutterPaintNode
923 * @primitive: a Cogl primitive
925 * Adds a region described by a Cogl primitive to the @node.
927 * This function acquires a reference on @primitive, so it is safe
928 * to call cogl_object_unref() when it returns.
933 clutter_paint_node_add_primitive (ClutterPaintNode *node,
934 CoglPrimitive *primitive)
936 ClutterPaintOperation operation = PAINT_OP_INIT;
938 g_return_if_fail (CLUTTER_IS_PAINT_NODE (node));
939 g_return_if_fail (cogl_is_primitive (primitive));
941 clutter_paint_node_maybe_init_operations (node);
943 clutter_paint_op_init_primitive (&operation, primitive);
944 g_array_append_val (node->operations, operation);
948 * _clutter_paint_node_paint:
949 * @node: a #ClutterPaintNode
951 * Paints the @node using the class implementation, traversing
952 * its children, if any.
955 _clutter_paint_node_paint (ClutterPaintNode *node)
957 ClutterPaintNodeClass *klass = CLUTTER_PAINT_NODE_GET_CLASS (node);
958 ClutterPaintNode *iter;
961 res = klass->pre_draw (node);
968 for (iter = node->first_child;
970 iter = iter->next_sibling)
972 _clutter_paint_node_paint (iter);
977 klass->post_draw (node);
981 #ifdef CLUTTER_ENABLE_DEBUG
983 clutter_paint_node_serialize (ClutterPaintNode *node)
985 ClutterPaintNodeClass *klass = CLUTTER_PAINT_NODE_GET_CLASS (node);
987 if (klass->serialize != NULL)
988 return klass->serialize (node);
990 return json_node_new (JSON_NODE_NULL);
994 clutter_paint_node_to_json (ClutterPaintNode *node)
996 JsonBuilder *builder;
999 builder = json_builder_new ();
1001 json_builder_begin_object (builder);
1003 json_builder_set_member_name (builder, "type");
1004 json_builder_add_string_value (builder, g_type_name (G_TYPE_FROM_INSTANCE (node)));
1006 json_builder_set_member_name (builder, "name");
1007 json_builder_add_string_value (builder, node->name);
1009 json_builder_set_member_name (builder, "node-data");
1010 json_builder_add_value (builder, clutter_paint_node_serialize (node));
1012 json_builder_set_member_name (builder, "operations");
1013 json_builder_begin_array (builder);
1015 if (node->operations != NULL)
1019 for (i = 0; i < node->operations->len; i++)
1021 const ClutterPaintOperation *op;
1023 op = &g_array_index (node->operations, ClutterPaintOperation, i);
1024 json_builder_begin_object (builder);
1028 case PAINT_OP_TEX_RECT:
1029 json_builder_set_member_name (builder, "texrect");
1030 json_builder_begin_array (builder);
1031 json_builder_add_double_value (builder, op->op.texrect[0]);
1032 json_builder_add_double_value (builder, op->op.texrect[1]);
1033 json_builder_add_double_value (builder, op->op.texrect[2]);
1034 json_builder_add_double_value (builder, op->op.texrect[3]);
1035 json_builder_add_double_value (builder, op->op.texrect[4]);
1036 json_builder_add_double_value (builder, op->op.texrect[5]);
1037 json_builder_add_double_value (builder, op->op.texrect[6]);
1038 json_builder_add_double_value (builder, op->op.texrect[7]);
1039 json_builder_end_array (builder);
1043 json_builder_set_member_name (builder, "path");
1044 json_builder_add_int_value (builder, (gint64) op->op.path);
1047 case PAINT_OP_PRIMITIVE:
1048 json_builder_set_member_name (builder, "primitive");
1049 json_builder_add_int_value (builder, (gint64) op->op.primitive);
1052 case PAINT_OP_INVALID:
1056 json_builder_end_object (builder);
1060 json_builder_end_array (builder);
1062 json_builder_set_member_name (builder, "children");
1063 json_builder_begin_array (builder);
1065 if (node->first_child != NULL)
1067 ClutterPaintNode *child;
1069 for (child = node->first_child;
1071 child = child->next_sibling)
1073 JsonNode *n = clutter_paint_node_to_json (child);
1075 json_builder_add_value (builder, n);
1079 json_builder_end_array (builder);
1081 json_builder_end_object (builder);
1083 res = json_builder_get_root (builder);
1085 g_object_unref (builder);
1089 #endif /* CLUTTER_ENABLE_DEBUG */
1092 _clutter_paint_node_dump_tree (ClutterPaintNode *node)
1094 #ifdef CLUTTER_ENABLE_DEBUG
1095 JsonGenerator *gen = json_generator_new ();
1099 json_generator_set_root (gen, clutter_paint_node_to_json (node));
1100 str = json_generator_to_data (gen, &len);
1102 g_print ("Render tree starting from %p:\n%s\n", node, str);
1105 #endif /* CLUTTER_ENABLE_DEBUG */
1109 * _clutter_paint_node_create:
1110 * @gtype: a #ClutterPaintNode type
1112 * Creates a new #ClutterPaintNode instance using @gtype
1114 * Return value: (transfer full): the newly created #ClutterPaintNode
1115 * sub-class instance; use clutter_paint_node_unref() when done
1118 _clutter_paint_node_create (GType gtype)
1120 g_return_val_if_fail (g_type_is_a (gtype, CLUTTER_TYPE_PAINT_NODE), NULL);
1122 _clutter_paint_node_init_types ();
1124 return (gpointer) g_type_create_instance (gtype);