Commit d1fec79c authored by Benjamin Otte's avatar Benjamin Otte

snapshot: Completely reengineer API

We now try to emulate cairo_t:

We keep a stack of nodes via push/pop and a transform matrix.

So whenever a new node is added to the snapshot, we transform it
by the current transform matrix and append it to the current node.
parent 956edd83
......@@ -3260,32 +3260,21 @@ gtk_container_propagate_draw (GtkContainer *container,
void
gtk_container_snapshot_child (GtkContainer *container,
GskRenderNode *container_node,
GtkWidget *child,
const GtkSnapshot *snapshot)
GtkSnapshot *snapshot)
{
GtkSnapshot child_snapshot;
GskRenderNode *child_node;
int x, y;
g_return_if_fail (GTK_IS_CONTAINER (container));
g_return_if_fail (GTK_IS_WIDGET (child));
g_return_if_fail (_gtk_widget_get_parent (child) == GTK_WIDGET (container));
g_return_if_fail (GSK_IS_RENDER_NODE (container_node));
g_return_if_fail (snapshot != NULL);
gtk_container_get_translation_to_child (container, child, &x, &y);
gtk_snapshot_init_translate (&child_snapshot, snapshot, x, y);
child_node = gtk_widget_snapshot (child, &child_snapshot);
if (child_node)
{
gsk_render_node_append_child (container_node, child_node);
gsk_render_node_unref (child_node);
}
gtk_snapshot_finish (&child_snapshot);
gtk_snapshot_translate_2d (snapshot, x, y);
gtk_widget_snapshot (child, snapshot);
gtk_snapshot_translate_2d (snapshot, -x, -y);
}
/**
......
......@@ -50,10 +50,9 @@ void gtk_container_propagate_render_node_for_child (GtkContainer *contai
GtkWidget *child,
GskRenderer *renderer,
GskRenderNode *parent_node);
void gtk_container_snapshot_child (GtkContainer *container,
GskRenderNode *container_node,
GtkWidget *child,
const GtkSnapshot *snapshot);
void gtk_container_snapshot_child (GtkContainer *container,
GtkWidget *child,
GtkSnapshot *snapshot);
G_END_DECLS
......
......@@ -264,12 +264,11 @@ gtk_debug_updates_queue_get_extents (GQueue *updates,
}
}
GskRenderNode *
gtk_debug_updates_snapshot (GtkWidget *widget,
const GtkSnapshot *snapshot)
void
gtk_debug_updates_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
GQueue *updates;
GskRenderNode *node;
GtkDebugUpdate *draw;
GdkRectangle rect;
gint64 timestamp;
......@@ -278,20 +277,19 @@ gtk_debug_updates_snapshot (GtkWidget *widget,
GList *l;
if (!gtk_debug_updates_get_enabled_for_display (gtk_widget_get_display (widget)))
return NULL;
return;
updates = g_object_get_qdata (G_OBJECT (widget), _gtk_debug_updates_quark);
if (updates == NULL)
return NULL;
return;
timestamp = gdk_frame_clock_get_frame_time (gtk_widget_get_frame_clock (widget));
gtk_debug_updates_print (updates, NULL, "Painting at %lli", (long long) timestamp);
node = gtk_snapshot_create_render_node (snapshot, "Debug Updates");
gtk_debug_updates_queue_get_extents (updates, &rect);
gsk_render_node_set_bounds (node, &(graphene_rect_t) GRAPHENE_RECT_INIT(rect.x, rect.y, rect.width, rect.height));
cr = gsk_render_node_get_draw_context (node, gtk_snapshot_get_renderer (snapshot));
cr = gtk_snapshot_append_cairo_node (snapshot,
&(graphene_rect_t) GRAPHENE_RECT_INIT(rect.x, rect.y, rect.width, rect.height),
"Debug Updates");
for (l = g_queue_peek_head_link (updates); l != NULL; l = l->next)
{
......@@ -311,7 +309,5 @@ gtk_debug_updates_snapshot (GtkWidget *widget,
}
cairo_destroy (cr);
return node;
}
......@@ -31,8 +31,8 @@ void gtk_debug_updates_set_enabled_for_display (GdkDisplay
void gtk_debug_updates_add (GtkWidget *widget,
const cairo_region_t *region);
GskRenderNode * gtk_debug_updates_snapshot (GtkWidget *widget,
const GtkSnapshot *snapshot);
void gtk_debug_updates_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot);
G_END_DECLS
......
......@@ -20,44 +20,52 @@
#include "gtksnapshot.h"
#include "gtksnapshotprivate.h"
#include "gsk/gskrendernodeprivate.h"
void
gtk_snapshot_init (GtkSnapshot *state,
const GtkSnapshot *parent,
const graphene_matrix_t *transform)
gtk_snapshot_init (GtkSnapshot *state,
GskRenderer *renderer)
{
state->parent = parent;
state->renderer = parent->renderer;
graphene_matrix_init_from_matrix (&state->transform, transform);
state->node = NULL;
state->root = NULL;
state->renderer = renderer;
graphene_matrix_init_identity (&state->transform);
}
void
gtk_snapshot_init_translate (GtkSnapshot *state,
const GtkSnapshot *parent,
int x,
int y)
GskRenderNode *
gtk_snapshot_finish (GtkSnapshot *state)
{
graphene_matrix_t matrix;
graphene_matrix_init_translate (&matrix, &(graphene_point3d_t) GRAPHENE_POINT3D_INIT (x, y, 0));
if (state->node != NULL)
{
g_warning ("Too many gtk_snapshot_push() calls.");
}
gtk_snapshot_init (state, parent, &matrix);
return state->root;
}
void
gtk_snapshot_init_root (GtkSnapshot *state,
GskRenderer *renderer)
gtk_snapshot_push (GtkSnapshot *state,
GskRenderNode *node)
{
state->parent = NULL;
state->renderer = renderer;
gtk_snapshot_append_node (state, node);
state->node = node;
graphene_matrix_init_identity (&state->transform);
}
void
gtk_snapshot_finish (GtkSnapshot *state)
gtk_snapshot_pop (GtkSnapshot *state)
{
/* nothing to do so far */
if (state->node == NULL)
{
g_warning ("Too many gtk_snapshot_pop() calls.");
return;
}
gsk_render_node_get_transform (state->node, &state->transform);
state->node = gsk_render_node_get_parent (state->node);
}
GskRenderer *
......@@ -66,6 +74,7 @@ gtk_snapshot_get_renderer (const GtkSnapshot *state)
return state->renderer;
}
#if 0
GskRenderNode *
gtk_snapshot_create_render_node (const GtkSnapshot *state,
const char *name,
......@@ -91,3 +100,120 @@ gtk_snapshot_create_render_node (const GtkSnapshot *state,
return node;
}
#endif
void
gtk_snapshot_set_transform (GtkSnapshot *state,
const graphene_matrix_t *transform)
{
graphene_matrix_init_from_matrix (&state->transform, transform);
}
void
gtk_snapshot_transform (GtkSnapshot *state,
const graphene_matrix_t *transform)
{
graphene_matrix_t result;
graphene_matrix_multiply (&state->transform, transform, &result);
graphene_matrix_init_from_matrix (&state->transform, &result);
}
void
gtk_snapshot_translate_2d (GtkSnapshot *state,
int x,
int y)
{
graphene_matrix_t transform;
graphene_point3d_t point;
graphene_point3d_init (&point, x, y, 0);
graphene_matrix_init_translate (&transform, &point);
gtk_snapshot_transform (state, &transform);
}
void
gtk_snapshot_append_node (GtkSnapshot *state,
GskRenderNode *node)
{
g_return_if_fail (state != NULL);
g_return_if_fail (GSK_IS_RENDER_NODE (node));
gsk_render_node_set_transform (node, &state->transform);
if (state->node)
gsk_render_node_append_child (state->node, node);
else if (state->root == NULL)
state->root = gsk_render_node_ref (node);
else
{
g_warning ("Tried appending a node to an already finished snapshot.");
}
}
cairo_t *
gtk_snapshot_append_cairo_node (GtkSnapshot *state,
const graphene_rect_t *bounds,
const char *name,
...)
{
GskRenderNode *node;
g_return_val_if_fail (state != NULL, NULL);
g_return_val_if_fail (bounds != NULL, NULL);
node = gsk_renderer_create_render_node (state->renderer);
gsk_render_node_set_bounds (node, bounds);
if (name)
{
va_list args;
char *str;
va_start (args, name);
str = g_strdup_vprintf (name, args);
va_end (args);
gsk_render_node_set_name (node, str);
g_free (str);
}
gtk_snapshot_append_node (state, node);
gsk_render_node_unref (node);
return gsk_render_node_get_draw_context (node, state->renderer);
}
cairo_t *
gtk_snapshot_push_cairo_node (GtkSnapshot *state,
const graphene_rect_t *bounds,
const char *name,
...)
{
GskRenderNode *node;
g_return_val_if_fail (state != NULL, NULL);
g_return_val_if_fail (bounds != NULL, NULL);
node = gsk_renderer_create_render_node (state->renderer);
gsk_render_node_set_bounds (node, bounds);
if (name)
{
va_list args;
char *str;
va_start (args, name);
str = g_strdup_vprintf (name, args);
va_end (args);
gsk_render_node_set_name (node, str);
g_free (str);
}
gtk_snapshot_push (state, node);
gsk_render_node_unref (node);
return gsk_render_node_get_draw_context (node, state->renderer);
}
......@@ -38,12 +38,38 @@ typedef struct _GtkSnapshot GtkSnapshot;
GDK_AVAILABLE_IN_3_90
GskRenderer * gtk_snapshot_get_renderer (const GtkSnapshot *state);
GskRenderer * gtk_snapshot_get_renderer (const GtkSnapshot *state);
GDK_AVAILABLE_IN_3_90
GskRenderNode * gtk_snapshot_create_render_node (const GtkSnapshot *state,
const char *name,
...) G_GNUC_PRINTF(2, 3);
void gtk_snapshot_push (GtkSnapshot *state,
GskRenderNode *node);
GDK_AVAILABLE_IN_3_90
cairo_t * gtk_snapshot_push_cairo_node (GtkSnapshot *state,
const graphene_rect_t *bounds,
const char *name,
...) G_GNUC_PRINTF(3, 4);
GDK_AVAILABLE_IN_3_90
void gtk_snapshot_pop (GtkSnapshot *state);
GDK_AVAILABLE_IN_3_90
void gtk_snapshot_set_transform (GtkSnapshot *state,
const graphene_matrix_t *transform);
GDK_AVAILABLE_IN_3_90
void gtk_snapshot_transform (GtkSnapshot *state,
const graphene_matrix_t *matrix);
GDK_AVAILABLE_IN_3_90
void gtk_snapshot_translate_2d (GtkSnapshot *state,
int x,
int y);
GDK_AVAILABLE_IN_3_90
void gtk_snapshot_append_node (GtkSnapshot *state,
GskRenderNode *node);
GDK_AVAILABLE_IN_3_90
cairo_t * gtk_snapshot_append_cairo_node (GtkSnapshot *state,
const graphene_rect_t *bounds,
const char *name,
...) G_GNUC_PRINTF(3, 4);
G_END_DECLS
......
......@@ -23,7 +23,8 @@
G_BEGIN_DECLS
struct _GtkSnapshot {
const GtkSnapshot *parent;
GskRenderNode *node;
GskRenderNode *root;
GskRenderer *renderer;
......@@ -31,14 +32,8 @@ struct _GtkSnapshot {
};
void gtk_snapshot_init (GtkSnapshot *state,
const GtkSnapshot *parent,
const graphene_matrix_t *transform);
void gtk_snapshot_init_translate (GtkSnapshot *state,
const GtkSnapshot *parent,
int x,
int y);
void gtk_snapshot_init_root (GtkSnapshot *state,
GskRenderer *renderer);
GskRenderNode * gtk_snapshot_finish (GtkSnapshot *state);
static inline const graphene_matrix_t *
gtk_snapshot_get_transform (const GtkSnapshot *snapshot)
......@@ -46,8 +41,6 @@ gtk_snapshot_get_transform (const GtkSnapshot *snapshot)
return &snapshot->transform;
}
void gtk_snapshot_finish (GtkSnapshot *state);
G_END_DECLS
#endif /* __GTK_SNAPSHOT_PRIVATE_H__ */
......@@ -6389,14 +6389,14 @@ gtk_widget_draw_internal (GtkWidget *widget,
widget->priv->clip.width,
widget->priv->clip.height);
fallback = gsk_renderer_create_fallback (renderer, &viewport, cr);
gtk_snapshot_init_root (&snapshot, renderer);
node = gtk_widget_snapshot (widget, &snapshot);
gtk_snapshot_init (&snapshot, renderer);
gtk_widget_snapshot (widget, &snapshot);
node = gtk_snapshot_finish (&snapshot);
if (node != NULL)
{
gsk_renderer_render (fallback, node, NULL);
gsk_render_node_unref (node);
}
gtk_snapshot_finish (&snapshot);
g_object_unref (fallback);
}
......@@ -15657,34 +15657,30 @@ gtk_widget_get_render_node (GtkWidget *widget,
GtkSnapshot snapshot;
GskRenderNode *node;
gtk_snapshot_init_root (&snapshot, renderer);
gtk_snapshot_init (&snapshot, renderer);
node = gtk_widget_snapshot (widget, &snapshot);
gtk_widget_snapshot (widget, &snapshot);
gtk_snapshot_finish (&snapshot);
node = gtk_snapshot_finish (&snapshot);
return node;
}
GskRenderNode *
gtk_widget_snapshot (GtkWidget *widget,
const GtkSnapshot *snapshot)
void
gtk_widget_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
GtkWidgetClass *klass = GTK_WIDGET_GET_CLASS (widget);
GskRenderNode *node;
graphene_matrix_t m;
graphene_point3d_t p;
graphene_rect_t bounds;
GtkAllocation clip;
GtkAllocation alloc;
if (_gtk_widget_get_alloc_needed (widget))
return NULL;
return;
gtk_widget_get_clip (widget, &clip);
_gtk_widget_get_allocation (widget, &alloc);
graphene_rect_init (&bounds, 0, 0, clip.width, clip.height);
graphene_matrix_init_translate (&m, graphene_point3d_init (&p, clip.x, clip.y, 0.f));
graphene_rect_init (&bounds, alloc.x - clip.x, alloc.y - clip.y, clip.width, clip.height);
/* Compatibility mode: if the widget does not have a render node, we draw
* using gtk_widget_draw() on a temporary node
......@@ -15692,60 +15688,49 @@ gtk_widget_snapshot (GtkWidget *widget,
if (klass->get_render_node == NULL &&
klass->snapshot == NULL)
{
GskRenderNode *tmp;
cairo_t *cr;
tmp = gtk_snapshot_create_render_node (snapshot, "Fallback<%s>", G_OBJECT_TYPE_NAME (widget));
gsk_render_node_set_bounds (tmp, &bounds);
gsk_render_node_set_transform (tmp, &m);
cr = gsk_render_node_get_draw_context (tmp, gtk_snapshot_get_renderer (snapshot));
cairo_translate (cr, alloc.x - clip.x, alloc.y - clip.y);
cr = gtk_snapshot_append_cairo_node (snapshot,
&bounds, "Fallback<%s>",
G_OBJECT_TYPE_NAME (widget));
gtk_widget_draw_internal (widget, cr, TRUE);
cairo_destroy (cr);
node = tmp;
}
else
{
if (g_signal_has_handler_pending (widget, widget_signals[DRAW], 0, FALSE))
gtk_snapshot_push (snapshot, &bounds, "DrawSignal<%s>", G_OBJECT_TYPE_NAME (widget));
if (klass->snapshot)
node = klass->snapshot (widget, snapshot);
klass->snapshot (widget, snapshot);
else
node = klass->get_render_node (widget, gtk_snapshot_get_renderer (snapshot));
{
GskRenderNode *node;
node = klass->get_render_node (widget, gtk_snapshot_get_renderer (snapshot));
if (node)
{
gtk_snapshot_append_node (snapshot, node);
gsk_render_node_unref (node);
}
}
/* Compatibility mode: if there's a ::draw signal handler, we add a
* child node with the contents of the handler
*/
if (g_signal_has_handler_pending (widget, widget_signals[DRAW], 0, FALSE))
{
GskRenderNode *tmp;
gboolean result;
cairo_t *cr;
tmp = gtk_snapshot_create_render_node (snapshot, "DrawSignal<%s>", G_OBJECT_TYPE_NAME (widget));
gsk_render_node_set_bounds (tmp, &bounds);
cr = gsk_render_node_get_draw_context (tmp, gtk_snapshot_get_renderer (snapshot));
cairo_translate (cr, alloc.x - clip.x, alloc.y - clip.y);
cr = gtk_snapshot_append_cairo_node (snapshot,
&bounds,
"DrawSignalContents<%s>", G_OBJECT_TYPE_NAME (widget));
g_signal_emit (widget, widget_signals[DRAW], 0, cr, &result);
cairo_destroy (cr);
if (node != NULL)
{
gsk_render_node_append_child (node, tmp);
gsk_render_node_unref (tmp);
}
else
{
node = tmp;
}
gtk_snapshot_pop (snapshot);
}
}
if (node)
gsk_render_node_set_transform (node, gtk_snapshot_get_transform (snapshot));
return node;
}
void
......@@ -15766,9 +15751,9 @@ gtk_widget_render (GtkWidget *widget,
if (renderer == NULL)
return;
gtk_snapshot_init_root (&snapshot, renderer);
root = gtk_widget_snapshot (widget, &snapshot);
gtk_snapshot_finish (&snapshot);
gtk_snapshot_init (&snapshot, renderer);
gtk_widget_snapshot (widget, &snapshot);
root = gtk_snapshot_finish (&snapshot);
if (root == NULL)
return;
......
......@@ -529,8 +529,8 @@ struct _GtkWidgetClass
GskRenderNode *(* get_render_node) (GtkWidget *widget,
GskRenderer *renderer);
GskRenderNode *(* snapshot) (GtkWidget *widget,
const GtkSnapshot *snapshot);
void (* snapshot) (GtkWidget *widget,
GtkSnapshot *snapshot);
/*< private >*/
......
......@@ -286,8 +286,8 @@ void gtk_widget_render (GtkWidget
GskRenderNode * gtk_widget_get_render_node (GtkWidget *widget,
GskRenderer *renderer);
GskRenderNode * gtk_widget_snapshot (GtkWidget *widget,
const GtkSnapshot *snapshot);
void gtk_widget_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot);
GskRenderNode * gtk_widget_create_render_node (GtkWidget *widget,
GskRenderer *renderer,
......
......@@ -447,8 +447,8 @@ static void gtk_window_real_activate_focus (GtkWindow *window);
static void gtk_window_keys_changed (GtkWindow *window);
static gboolean gtk_window_enable_debugging (GtkWindow *window,
gboolean toggle);
static GskRenderNode *gtk_window_snapshot (GtkWidget *widget,
const GtkSnapshot *snapshot);
static void gtk_window_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot);
static void gtk_window_unset_transient_for (GtkWindow *window);
static void gtk_window_transient_parent_realized (GtkWidget *parent,
GtkWidget *window);
......@@ -9383,13 +9383,12 @@ gtk_window_compute_hints (GtkWindow *window,
* Redrawing functions *
***********************/
static GskRenderNode *
gtk_window_snapshot (GtkWidget *widget,
const GtkSnapshot *snapshot)
static void
gtk_window_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
GtkStyleContext *context;
GskRenderNode *node, *updates_node;
GtkAllocation allocation;
GtkBorder window_border;
gint title_height;
......@@ -9407,11 +9406,9 @@ gtk_window_snapshot (GtkWidget *widget,
graphene_rect_init (&bounds, allocation.x, allocation.y, allocation.width, allocation.height);
graphene_matrix_init_translate (&m, graphene_point3d_init (&p, allocation.x, allocation.y, 0.));
node = gtk_snapshot_create_render_node (snapshot, "Window Decoration");
gsk_render_node_set_bounds (node, &bounds);
gsk_render_node_set_transform (node, &m);
cr = gsk_render_node_get_draw_context (node, gtk_snapshot_get_renderer (snapshot));
cr = gtk_snapshot_push_cairo_node (snapshot,
&bounds,
"Window Decoration");
if (priv->client_decorated &&
priv->decorated &&
......@@ -9479,25 +9476,20 @@ gtk_window_snapshot (GtkWidget *widget,
cairo_destroy (cr);
if (priv->title_box != NULL)
gtk_container_snapshot_child (GTK_CONTAINER (widget), node, priv->title_box, snapshot);
gtk_container_snapshot_child (GTK_CONTAINER (widget), priv->title_box, snapshot);
if (gtk_bin_get_child (GTK_BIN (widget)))
gtk_container_snapshot_child (GTK_CONTAINER (widget), node, gtk_bin_get_child (GTK_BIN (widget)), snapshot);
gtk_container_snapshot_child (GTK_CONTAINER (widget), gtk_bin_get_child (GTK_BIN (widget)), snapshot);
for (l = priv->popovers; l; l = l->next)
{
GtkWindowPopover *data = l->data;
gtk_container_snapshot_child (GTK_CONTAINER (widget), node, data->widget, snapshot);
gtk_container_snapshot_child (GTK_CONTAINER (widget), data->widget, snapshot);
}
updates_node = gtk_debug_updates_snapshot (widget, snapshot);
if (updates_node)
{
gsk_render_node_append_child (node, updates_node);
gsk_render_node_unref (updates_node);
}
gtk_debug_updates_snapshot (widget, snapshot);
return node;
gtk_snapshot_pop (snapshot);
}
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment