}
}
+/*
+ * gsk_render_node_can_diff:
+ * @node1: a #GskRenderNode
+ * @node2: the #GskRenderNode to compare with
+ *
+ * Checks if 2 render nodes can be expected to be compared via
+ * gsk_render_node_diff(). The node diffing algorithm uses this function
+ * to match up similar nodes to compare when trying to minimze the
+ * resulting region.
+ *
+ * Nodes of different type always return %FALSE here.
+ *
+ * Returns: %TRUE if @node1 and @node2 can be expected to be compared
+ **/
+gboolean
+gsk_render_node_can_diff (GskRenderNode *node1,
+ GskRenderNode *node2)
+{
+ if (node1 == node2)
+ return TRUE;
+
+ if (gsk_render_node_get_node_type (node1) != gsk_render_node_get_node_type (node2))
+ return FALSE;
+
+ return node1->node_class->can_diff (node1, node2);
+}
+
+static void
+rectangle_init_from_graphene (cairo_rectangle_int_t *cairo,
+ const graphene_rect_t *graphene)
+{
+ cairo->x = floorf (graphene->origin.x);
+ cairo->y = floorf (graphene->origin.y);
+ cairo->width = ceilf (graphene->origin.x + graphene->size.width) - cairo->x;
+ cairo->height = ceilf (graphene->origin.y + graphene->size.height) - cairo->y;
+}
+
+void
+gsk_render_node_diff_impossible (GskRenderNode *node1,
+ GskRenderNode *node2,
+ cairo_region_t *region)
+{
+ cairo_rectangle_int_t rect;
+
+ rectangle_init_from_graphene (&rect, &node1->bounds);
+ cairo_region_union_rectangle (region, &rect);
+ rectangle_init_from_graphene (&rect, &node2->bounds);
+ cairo_region_union_rectangle (region, &rect);
+}
+
+/**
+ * gsk_render_node_diff:
+ * @node1: a #GskRenderNode
+ * @node2: the #GskRenderNode to compare with
+ * @region: a #cairo_region_t to add the differences to
+ *
+ * Compares @node1 and @node2 trying to compute the minimal region of changes.
+ * In the worst case, this is the union of the bounds of @node1 and @node2.
+ *
+ * This function is used to compute the area that needs to be redrawn when
+ * the previous contents were drawn by @node1 and the new contents should
+ * correspond to @node2. As such, it is important that this comparison is
+ * faster than the time it takes to actually do the redraw.
+ *
+ * Note that the passed in @region may already contain previous results from
+ * previous node comparisons, so this function call will only add to it.
+ **/
+void
+gsk_render_node_diff (GskRenderNode *node1,
+ GskRenderNode *node2,
+ cairo_region_t *region)
+{
+ if (node1 == node2)
+ return;
+
+ if (gsk_render_node_get_node_type (node1) != gsk_render_node_get_node_type (node2))
+ return gsk_render_node_diff_impossible (node1, node2, region);
+
+ return node1->node_class->diff (node1, node2, region);
+}
+
#define GSK_RENDER_NODE_SERIALIZATION_VERSION 0
#define GSK_RENDER_NODE_SERIALIZATION_ID "GskRenderNode"
return TRUE;
}
+static gboolean
+gsk_render_node_can_diff_impossible (GskRenderNode *node1,
+ GskRenderNode *node2)
+{
+ return FALSE;
+}
+
/*** GSK_COLOR_NODE ***/
typedef struct _GskColorNode GskColorNode;
"GskColorNode",
gsk_color_node_finalize,
gsk_color_node_draw,
+ gsk_render_node_can_diff_impossible,
+ gsk_render_node_diff_impossible,
gsk_color_node_serialize,
gsk_color_node_deserialize,
};
"GskLinearGradientNode",
gsk_linear_gradient_node_finalize,
gsk_linear_gradient_node_draw,
+ gsk_render_node_can_diff_impossible,
+ gsk_render_node_diff_impossible,
gsk_linear_gradient_node_serialize,
gsk_linear_gradient_node_deserialize,
};
"GskRepeatingLinearGradientNode",
gsk_linear_gradient_node_finalize,
gsk_linear_gradient_node_draw,
+ gsk_render_node_can_diff_impossible,
+ gsk_render_node_diff_impossible,
gsk_linear_gradient_node_serialize,
gsk_repeating_linear_gradient_node_deserialize,
};
"GskBorderNode",
gsk_border_node_finalize,
gsk_border_node_draw,
+ gsk_render_node_can_diff_impossible,
+ gsk_render_node_diff_impossible,
gsk_border_node_serialize,
gsk_border_node_deserialize
};
"GskTextureNode",
gsk_texture_node_finalize,
gsk_texture_node_draw,
+ gsk_render_node_can_diff_impossible,
+ gsk_render_node_diff_impossible,
gsk_texture_node_serialize,
gsk_texture_node_deserialize
};
"GskInsetShadowNode",
gsk_inset_shadow_node_finalize,
gsk_inset_shadow_node_draw,
+ gsk_render_node_can_diff_impossible,
+ gsk_render_node_diff_impossible,
gsk_inset_shadow_node_serialize,
gsk_inset_shadow_node_deserialize
};
"GskOutsetShadowNode",
gsk_outset_shadow_node_finalize,
gsk_outset_shadow_node_draw,
+ gsk_render_node_can_diff_impossible,
+ gsk_render_node_diff_impossible,
gsk_outset_shadow_node_serialize,
gsk_outset_shadow_node_deserialize
};
"GskCairoNode",
gsk_cairo_node_finalize,
gsk_cairo_node_draw,
+ gsk_render_node_can_diff_impossible,
+ gsk_render_node_diff_impossible,
gsk_cairo_node_serialize,
gsk_cairo_node_deserialize
};
"GskContainerNode",
gsk_container_node_finalize,
gsk_container_node_draw,
+ gsk_render_node_can_diff_impossible,
+ gsk_render_node_diff_impossible,
gsk_container_node_serialize,
gsk_container_node_deserialize
};
"GskTransformNode",
gsk_transform_node_finalize,
gsk_transform_node_draw,
+ gsk_render_node_can_diff_impossible,
+ gsk_render_node_diff_impossible,
gsk_transform_node_serialize,
gsk_transform_node_deserialize
};
"GskOffsetNode",
gsk_offset_node_finalize,
gsk_offset_node_draw,
+ gsk_render_node_can_diff_impossible,
+ gsk_render_node_diff_impossible,
gsk_offset_node_serialize,
gsk_offset_node_deserialize
};
"GskOpacityNode",
gsk_opacity_node_finalize,
gsk_opacity_node_draw,
+ gsk_render_node_can_diff_impossible,
+ gsk_render_node_diff_impossible,
gsk_opacity_node_serialize,
gsk_opacity_node_deserialize
};
"GskColorMatrixNode",
gsk_color_matrix_node_finalize,
gsk_color_matrix_node_draw,
+ gsk_render_node_can_diff_impossible,
+ gsk_render_node_diff_impossible,
gsk_color_matrix_node_serialize,
gsk_color_matrix_node_deserialize
};
"GskRepeatNode",
gsk_repeat_node_finalize,
gsk_repeat_node_draw,
+ gsk_render_node_can_diff_impossible,
+ gsk_render_node_diff_impossible,
gsk_repeat_node_serialize,
gsk_repeat_node_deserialize
};
"GskClipNode",
gsk_clip_node_finalize,
gsk_clip_node_draw,
+ gsk_render_node_can_diff_impossible,
+ gsk_render_node_diff_impossible,
gsk_clip_node_serialize,
gsk_clip_node_deserialize
};
"GskRoundedClipNode",
gsk_rounded_clip_node_finalize,
gsk_rounded_clip_node_draw,
+ gsk_render_node_can_diff_impossible,
+ gsk_render_node_diff_impossible,
gsk_rounded_clip_node_serialize,
gsk_rounded_clip_node_deserialize
};
"GskShadowNode",
gsk_shadow_node_finalize,
gsk_shadow_node_draw,
+ gsk_render_node_can_diff_impossible,
+ gsk_render_node_diff_impossible,
gsk_shadow_node_serialize,
gsk_shadow_node_deserialize
};
"GskBlendNode",
gsk_blend_node_finalize,
gsk_blend_node_draw,
+ gsk_render_node_can_diff_impossible,
+ gsk_render_node_diff_impossible,
gsk_blend_node_serialize,
gsk_blend_node_deserialize
};
"GskCrossFadeNode",
gsk_cross_fade_node_finalize,
gsk_cross_fade_node_draw,
+ gsk_render_node_can_diff_impossible,
+ gsk_render_node_diff_impossible,
gsk_cross_fade_node_serialize,
gsk_cross_fade_node_deserialize
};
"GskTextNode",
gsk_text_node_finalize,
gsk_text_node_draw,
+ gsk_render_node_can_diff_impossible,
+ gsk_render_node_diff_impossible,
gsk_text_node_serialize,
gsk_text_node_deserialize
};
"GskBlurNode",
gsk_blur_node_finalize,
gsk_blur_node_draw,
+ gsk_render_node_can_diff_impossible,
+ gsk_render_node_diff_impossible,
gsk_blur_node_serialize,
gsk_blur_node_deserialize
};