snapshot: Allow passing the bounds of the created paintable

This allows being more specific about the size.
It's useful in particular when the resulting render nodes might be
too small for the size, not only when they are too large. For the
latter case, using a clip node would be enough.

It also requires adding a clip node when rendering the resulting
paintable, but that should be optimized out by GtkSnapshot when not
necessary.
This commit is contained in:
Benjamin Otte 2018-04-02 06:15:50 +02:00
parent 12fedca726
commit ffc7b2bb0a
10 changed files with 51 additions and 35 deletions

View File

@ -330,7 +330,7 @@ set_color_icon (GdkDragContext *context,
rgba,
&GRAPHENE_RECT_INIT(0, 0, 48, 32),
"ColorDragColor");
paintable = gtk_snapshot_free_to_paintable (snapshot);
paintable = gtk_snapshot_free_to_paintable (snapshot, NULL);
gtk_drag_set_icon_paintable (context, paintable, 0, 0);
g_object_unref (paintable);

View File

@ -175,7 +175,7 @@ drag_set_color_icon (GdkDragContext *context,
color,
&GRAPHENE_RECT_INIT(0, 0, 48, 32),
"ColorDragColor");
paintable = gtk_snapshot_free_to_paintable (snapshot);
paintable = gtk_snapshot_free_to_paintable (snapshot, NULL);
gtk_drag_set_icon_paintable (context, paintable, 4, 4);
g_object_unref (paintable);

View File

@ -6711,7 +6711,7 @@ gtk_icon_view_create_drag_icon (GtkIconView *icon_view,
icon_view->priv->item_padding,
icon_view->priv->item_padding,
FALSE);
paintable = gtk_snapshot_free_to_paintable (snapshot);
paintable = gtk_snapshot_free_to_paintable (snapshot, NULL);
return paintable;
}

View File

@ -28,6 +28,7 @@ struct _GtkRenderNodePaintable
GObject parent_instance;
GskRenderNode *node;
graphene_rect_t bounds;
};
struct _GtkRenderNodePaintableClass
@ -42,29 +43,34 @@ gtk_render_node_paintable_paintable_snapshot (GdkPaintable *paintable,
double height)
{
GtkRenderNodePaintable *self = GTK_RENDER_NODE_PAINTABLE (paintable);
graphene_rect_t node_bounds;
gboolean needs_transform;
gsk_render_node_get_bounds (self->node, &node_bounds);
needs_transform = self->bounds.size.width != width ||
self->bounds.size.height != height;
if (node_bounds.origin.x + node_bounds.size.width != width ||
node_bounds.origin.y + node_bounds.size.height != height)
if (needs_transform)
{
graphene_matrix_t transform;
graphene_matrix_init_scale (&transform,
width / (node_bounds.origin.x + node_bounds.size.width),
height / (node_bounds.origin.y + node_bounds.size.height),
width / (self->bounds.size.width),
height / (self->bounds.size.height),
1.0);
gtk_snapshot_push_transform (snapshot,
&transform,
"RenderNodeScaleToFit");
gtk_snapshot_append_node (snapshot, self->node);
gtk_snapshot_pop (snapshot);
}
else
{
gtk_snapshot_append_node (snapshot, self->node);
}
gtk_snapshot_push_clip (snapshot, &self->bounds, "RenderNodePaintableClip");
gtk_snapshot_offset (snapshot, self->bounds.origin.x, self->bounds.origin.y);
gtk_snapshot_append_node (snapshot, self->node);
gtk_snapshot_offset (snapshot, -self->bounds.origin.x, -self->bounds.origin.y);
gtk_snapshot_pop (snapshot);
if (needs_transform)
gtk_snapshot_pop (snapshot);
}
static GdkPaintableFlags
@ -77,22 +83,16 @@ static int
gtk_render_node_paintable_paintable_get_intrinsic_width (GdkPaintable *paintable)
{
GtkRenderNodePaintable *self = GTK_RENDER_NODE_PAINTABLE (paintable);
graphene_rect_t node_bounds;
gsk_render_node_get_bounds (self->node, &node_bounds);
return node_bounds.origin.x + node_bounds.size.width;
return self->bounds.size.width;
}
static int
gtk_render_node_paintable_paintable_get_intrinsic_height (GdkPaintable *paintable)
{
GtkRenderNodePaintable *self = GTK_RENDER_NODE_PAINTABLE (paintable);
graphene_rect_t node_bounds;
gsk_render_node_get_bounds (self->node, &node_bounds);
return node_bounds.origin.y + node_bounds.size.height;
return self->bounds.size.height;
}
static void
@ -132,15 +132,18 @@ gtk_render_node_paintable_init (GtkRenderNodePaintable *self)
}
GdkPaintable *
gtk_render_node_paintable_new (GskRenderNode *node)
gtk_render_node_paintable_new (GskRenderNode *node,
const graphene_rect_t *bounds)
{
GtkRenderNodePaintable *self;
g_return_val_if_fail (GSK_IS_RENDER_NODE (node), NULL);
g_return_val_if_fail (bounds != NULL, NULL);
self = g_object_new (GTK_TYPE_RENDER_NODE_PAINTABLE, NULL);
self->node = gsk_render_node_ref (node);
self->bounds = *bounds;
return GDK_PAINTABLE (self);
}

View File

@ -28,7 +28,8 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (GtkRenderNodePaintable, gtk_render_node_paintable, GTK, RENDER_NODE_PAINTABLE, GObject)
GdkPaintable * gtk_render_node_paintable_new (GskRenderNode *node);
GdkPaintable * gtk_render_node_paintable_new (GskRenderNode *node,
const graphene_rect_t *bounds);
G_END_DECLS

View File

@ -277,6 +277,8 @@ gtk_snapshot_free_to_node (GtkSnapshot *snapshot)
/**
* gtk_snapshot_free_to_paintable: (skip)
* @snapshot: (transfer full): a #GtkSnapshot
* @size: (allow-none): The size of the resulting paintable
* or %NULL to use the bounds of the snapshot
*
* Returns a paintable for the node that was
* constructed by @snapshot and frees @snapshot.
@ -284,11 +286,12 @@ gtk_snapshot_free_to_node (GtkSnapshot *snapshot)
* Returns: (transfer full): a newly-created #GdkPaintable
*/
GdkPaintable *
gtk_snapshot_free_to_paintable (GtkSnapshot *snapshot)
gtk_snapshot_free_to_paintable (GtkSnapshot *snapshot,
const graphene_size_t *size)
{
GdkPaintable *result;
result = gtk_snapshot_to_paintable (snapshot);
result = gtk_snapshot_to_paintable (snapshot, size);
g_object_unref (snapshot);
return result;
@ -1286,6 +1289,8 @@ gtk_snapshot_to_node (GtkSnapshot *snapshot)
/**
* gtk_snapshot_to_paintable:
* @snapshot: a #GtkSnapshot
* @size: (allow-none): The size of the resulting paintable
* or %NULL to use the bounds of the snapshot
*
* Returns a paintable encapsulating the render node
* that was constructed by @snapshot. After calling
@ -1296,13 +1301,18 @@ gtk_snapshot_to_node (GtkSnapshot *snapshot)
* Returns: (transfer full): a new #GdkPaintable
*/
GdkPaintable *
gtk_snapshot_to_paintable (GtkSnapshot *snapshot)
gtk_snapshot_to_paintable (GtkSnapshot *snapshot,
const graphene_size_t *size)
{
GskRenderNode *node;
GdkPaintable *paintable;
graphene_rect_t bounds;
node = gtk_snapshot_to_node (snapshot);
paintable = gtk_render_node_paintable_new (node);
gsk_render_node_get_bounds (node, &bounds);
bounds.origin.x = 0;
bounds.origin.y = 0;
paintable = gtk_render_node_paintable_new (node, &bounds);
gsk_render_node_unref (node);
return paintable;

View File

@ -58,12 +58,14 @@ GtkSnapshot * gtk_snapshot_new (gboolean
GDK_AVAILABLE_IN_ALL
GskRenderNode * gtk_snapshot_free_to_node (GtkSnapshot *snapshot);
GDK_AVAILABLE_IN_ALL
GdkPaintable * gtk_snapshot_free_to_paintable (GtkSnapshot *snapshot);
GdkPaintable * gtk_snapshot_free_to_paintable (GtkSnapshot *snapshot,
const graphene_size_t *size);
GDK_AVAILABLE_IN_ALL
GskRenderNode * gtk_snapshot_to_node (GtkSnapshot *snapshot);
GDK_AVAILABLE_IN_ALL
GdkPaintable * gtk_snapshot_to_paintable (GtkSnapshot *snapshot);
GdkPaintable * gtk_snapshot_to_paintable (GtkSnapshot *snapshot,
const graphene_size_t *size);
GDK_AVAILABLE_IN_ALL
gboolean gtk_snapshot_get_record_names (GtkSnapshot *snapshot);

View File

@ -233,7 +233,7 @@ gtk_text_util_create_drag_icon (GtkWidget *widget,
&color);
gtk_snapshot_append_layout (snapshot, layout, &color, "TextDragIcon");
paintable = gtk_snapshot_free_to_paintable (snapshot);
paintable = gtk_snapshot_free_to_paintable (snapshot, NULL);
g_object_unref (layout);
return paintable;
@ -343,7 +343,7 @@ gtk_text_util_create_rich_drag_icon (GtkWidget *widget,
g_object_unref (layout);
g_object_unref (new_buffer);
paintable = gtk_snapshot_free_to_paintable (snapshot);
paintable = gtk_snapshot_free_to_paintable (snapshot, &(graphene_size_t) { layout_width, layout_height });
return paintable;
}

View File

@ -13944,7 +13944,7 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView *tree_view,
gtk_treeview_snapshot_border (snapshot,
&GRAPHENE_RECT_INIT(0, 0, bin_window_width + 2, background_area.height + 2));
paintable = gtk_snapshot_free_to_paintable (snapshot);
paintable = gtk_snapshot_free_to_paintable (snapshot, NULL);
return paintable;
}

View File

@ -28,7 +28,7 @@ drag_begin (GtkWidget *widget,
gtk_style_context_remove_class (gtk_widget_get_style_context (row), "during-dnd");
cairo_destroy (cr);
paintable = gtk_snapshot_free_to_paintable (snapshot);
paintable = gtk_snapshot_free_to_paintable (snapshot, NULL);
gtk_widget_translate_coordinates (widget, row, 0, 0, &x, &y);
gtk_drag_set_icon_paintable (context, paintable, -x, -y);