snapshot: Convert GtkImage and GtkIconHelper

Adds a bunch of new APIs to render textures with theming.

FIXME: Cannot draw shadows for textures.
This commit is contained in:
Benjamin Otte 2016-11-15 06:19:16 +01:00
parent 92e6b3a000
commit c0aa065ac1
7 changed files with 176 additions and 63 deletions

View File

@ -857,27 +857,24 @@ _gtk_icon_helper_draw (GtkIconHelper *self,
}
}
GskRenderNode *
gtk_icon_helper_get_render_node (GtkIconHelper *self,
GskRenderer *renderer)
void
gtk_icon_helper_snapshot (GtkIconHelper *self,
GtkSnapshot *snapshot)
{
GskTexture *texture;
GskRenderNode *node;
graphene_rect_t bounds;
gtk_icon_helper_ensure_texture (self, renderer);
gtk_icon_helper_ensure_texture (self, gtk_snapshot_get_renderer (snapshot));
texture = self->priv->texture;
if (texture == NULL)
return NULL;
return;
graphene_rect_init (&bounds, 0, 0, gsk_texture_get_width (texture), gsk_texture_get_height (texture));
node = gsk_renderer_create_render_node (renderer);
gsk_render_node_set_name (node, "Icon Helper");
gsk_render_node_set_bounds (node, &bounds);
node = gtk_snapshot_append (snapshot, &bounds, "Icon Helper");
gsk_render_node_set_texture (node, texture);
return node;
gsk_render_node_unref (node);
}
gboolean

View File

@ -125,8 +125,8 @@ void _gtk_icon_helper_draw (GtkIconHelper *self,
cairo_t *cr,
gdouble x,
gdouble y);
GskRenderNode * gtk_icon_helper_get_render_node (GtkIconHelper *self,
GskRenderer *renderer);
void gtk_icon_helper_snapshot (GtkIconHelper *self,
GtkSnapshot *snapshot);
gboolean _gtk_icon_helper_get_force_scale_pixbuf (GtkIconHelper *self);
void _gtk_icon_helper_set_force_scale_pixbuf (GtkIconHelper *self,

View File

@ -142,8 +142,8 @@ struct _GtkImagePrivate
#define DEFAULT_ICON_SIZE GTK_ICON_SIZE_BUTTON
static GskRenderNode *gtk_image_get_render_node (GtkWidget *widget,
GskRenderer *renderer);
static void gtk_image_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot);
static void gtk_image_size_allocate (GtkWidget *widget,
GtkAllocation*allocation);
static void gtk_image_unmap (GtkWidget *widget);
@ -163,6 +163,13 @@ static void gtk_image_get_content_size (GtkCssGadget *gadget,
gint *minimum_baseline,
gint *natural_baseline,
gpointer unused);
static gboolean gtk_image_render_contents (GtkCssGadget *gadget,
GtkSnapshot *snapshot,
int x,
int y,
int width,
int height,
gpointer data);
static void gtk_image_style_updated (GtkWidget *widget);
static void gtk_image_finalize (GObject *object);
@ -211,7 +218,7 @@ gtk_image_class_init (GtkImageClass *class)
gobject_class->finalize = gtk_image_finalize;
widget_class = GTK_WIDGET_CLASS (class);
widget_class->get_render_node = gtk_image_get_render_node;
widget_class->snapshot = gtk_image_snapshot;
widget_class->measure = gtk_image_measure;
widget_class->size_allocate = gtk_image_size_allocate;
widget_class->unmap = gtk_image_unmap;
@ -367,8 +374,9 @@ gtk_image_init (GtkImage *image)
gtk_image_get_content_size,
NULL,
NULL,
NULL,
gtk_image_render_contents,
NULL, NULL);
}
static void
@ -1403,69 +1411,60 @@ gtk_image_get_content_size (GtkCssGadget *gadget,
}
static GskRenderNode *
gtk_image_get_render_node (GtkWidget *widget,
GskRenderer *renderer)
static void
gtk_image_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
GtkImage *image = GTK_IMAGE (widget);
GtkImagePrivate *priv = image->priv;
gtk_css_gadget_snapshot (GTK_IMAGE (widget)->priv->gadget,
snapshot);
}
static gboolean
gtk_image_render_contents (GtkCssGadget *gadget,
GtkSnapshot *snapshot,
int x,
int y,
int width,
int height,
gpointer data)
{
GtkWidget *widget;
GtkImage *image;
GtkImagePrivate *priv;
gint w, h, baseline;
gint x, y, width, height;
GskRenderNode *res;
GskRenderNode *node;
GtkAllocation alloc, clip;
cairo_t *cr;
res = gtk_css_gadget_get_render_node (priv->gadget, renderer, FALSE);
widget = gtk_css_gadget_get_owner (gadget);
image = GTK_IMAGE (widget);
priv = image->priv;
if (res == NULL)
return NULL;
_gtk_icon_helper_get_size (priv->icon_helper, &w, &h);
baseline = gtk_widget_get_allocated_baseline (widget);
if (baseline == -1)
y += floor(height - h) / 2;
else
y += CLAMP (baseline - h * gtk_image_get_baseline_align (image), 0, height - h);
x += (width - w) / 2;
gtk_snapshot_translate_2d (snapshot, x, y);
if (gtk_image_get_storage_type (image) == GTK_IMAGE_ANIMATION)
{
node = gtk_widget_create_render_node (widget, renderer, "Image Content");
gtk_widget_get_clip (widget, &clip);
_gtk_widget_get_allocation (widget, &alloc);
cr = gsk_render_node_get_draw_context (node, renderer);
cairo_translate (cr, alloc.x - clip.x, alloc.y - clip.y);
x = 0;
y = 0;
width = alloc.width;
height = alloc.height;
_gtk_icon_helper_get_size (priv->icon_helper, &w, &h);
baseline = gtk_widget_get_allocated_baseline (widget);
if (baseline == -1)
y += floor(height - h) / 2;
else
y += CLAMP (baseline - h * gtk_image_get_baseline_align (image), 0, height - h);
x += (width - w) / 2;
GtkStyleContext *context = gtk_widget_get_style_context (widget);
GdkPixbuf *pixbuf = get_animation_frame (image);
gtk_render_icon (context, cr, pixbuf, x, y);
gtk_snapshot_render_icon (snapshot, context, pixbuf, x, y);
g_object_unref (pixbuf);
cairo_destroy (cr);
}
else
{
node = gtk_icon_helper_get_render_node (priv->icon_helper, renderer);
gtk_icon_helper_snapshot (priv->icon_helper, snapshot);
}
gtk_snapshot_translate_2d (snapshot, -x, -y);
if (node != NULL)
{
gsk_render_node_append_child (res, node);
gsk_render_node_unref (node);
}
return res;
return FALSE;
}
static void

View File

@ -26,6 +26,7 @@
#include "gtkcssshadowsvalueprivate.h"
#include "gtkcssstyleprivate.h"
#include "gtkcsstransformvalueprivate.h"
#include "gtksnapshotprivate.h"
#include <math.h>
@ -222,3 +223,51 @@ gtk_css_style_render_icon_get_extents (GtkCssStyle *style,
extents->height += border.top + border.bottom;
}
void
gtk_css_style_snapshot_icon (GtkCssStyle *style,
GtkSnapshot *snapshot,
GskTexture *texture)
{
const GtkCssValue *shadows, *transform;
cairo_matrix_t transform_matrix;
graphene_matrix_t matrix, other, saved_matrix;
graphene_rect_t bounds;
GskRenderNode *node;
int width, height;
g_return_if_fail (GTK_IS_CSS_STYLE (style));
g_return_if_fail (snapshot != NULL);
g_return_if_fail (GSK_IS_TEXTURE (texture));
shadows = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_SHADOW);
transform = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_TRANSFORM);
width = gsk_texture_get_width (texture);
height = gsk_texture_get_height (texture);
if (!_gtk_css_transform_value_get_matrix (transform, &transform_matrix))
return;
graphene_matrix_init_from_matrix (&saved_matrix, gtk_snapshot_get_transform (snapshot));
/* XXX: Implement -gtk-icon-transform-origin instead of hardcoding "50% 50%" here */
graphene_matrix_init_translate (&matrix, &(graphene_point3d_t)GRAPHENE_POINT3D_INIT(width / 2.0, height / 2.0, 0));
graphene_matrix_init_from_2d (&other, transform_matrix.xx, transform_matrix.yx,
transform_matrix.xy, transform_matrix.yy,
transform_matrix.x0, transform_matrix.y0);
graphene_matrix_multiply (&other, &matrix, &matrix);
graphene_matrix_init_translate (&other, &(graphene_point3d_t)GRAPHENE_POINT3D_INIT(- width / 2.0, - height / 2.0, 0));
graphene_matrix_multiply (&matrix, &other, &matrix);
gtk_snapshot_transform (snapshot, &matrix);
graphene_rect_init (&bounds, 0, 0, width, height);
node = gtk_snapshot_append (snapshot, &bounds, "Icon");
if (!_gtk_css_shadows_value_is_none (shadows))
{
g_warning ("Painting shadows not implemented for textures yet.");
}
gsk_render_node_set_texture (node, texture);
gsk_render_node_unref (node);
gtk_snapshot_set_transform (snapshot, &saved_matrix);
}

View File

@ -22,8 +22,10 @@
#include <glib-object.h>
#include <cairo.h>
#include <gsk/gsk.h>
#include "gtkcsstypesprivate.h"
#include "gtksnapshot.h"
#include "gtktypes.h"
G_BEGIN_DECLS
@ -41,6 +43,9 @@ void gtk_css_style_render_icon_surface (GtkCssStyle *style,
cairo_surface_t *surface,
double x,
double y);
void gtk_css_style_snapshot_icon (GtkCssStyle *style,
GtkSnapshot *snapshot,
GskTexture *texture);
void gtk_css_style_render_icon_get_extents (GtkCssStyle *style,
GdkRectangle *extents,

View File

@ -24,6 +24,7 @@
#include "gtkcssshadowsvalueprivate.h"
#include "gtkrenderbackgroundprivate.h"
#include "gtkrenderborderprivate.h"
#include "gtkrendericonprivate.h"
#include "gtkstylecontextprivate.h"
#include "gsk/gskrendernodeprivate.h"
@ -185,6 +186,39 @@ gtk_snapshot_append_node (GtkSnapshot *state,
}
}
GskRenderNode *
gtk_snapshot_append (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);
return node;
}
cairo_t *
gtk_snapshot_append_cairo_node (GtkSnapshot *state,
const graphene_rect_t *bounds,
@ -357,3 +391,21 @@ gtk_snapshot_render_layout (GtkSnapshot *state,
gtk_snapshot_translate_2d (state, -x, -y);
}
void
gtk_snapshot_render_icon (GtkSnapshot *snapshot,
GtkStyleContext *context,
GdkPixbuf *pixbuf,
gdouble x,
gdouble y)
{
GskTexture *texture;
texture = gsk_texture_new_for_pixbuf (snapshot->renderer, pixbuf);
gtk_snapshot_translate_2d (snapshot, x, y);
gtk_css_style_snapshot_icon (gtk_style_context_lookup_style (context),
snapshot,
texture);
gtk_snapshot_translate_2d (snapshot, -x, -y);
gsk_texture_unref (texture);
}

View File

@ -73,6 +73,11 @@ GDK_AVAILABLE_IN_3_90
void gtk_snapshot_append_node (GtkSnapshot *state,
GskRenderNode *node);
GDK_AVAILABLE_IN_3_90
GskRenderNode * gtk_snapshot_append (GtkSnapshot *state,
const graphene_rect_t *bounds,
const char *name,
...) G_GNUC_PRINTF(3, 4);
GDK_AVAILABLE_IN_3_90
cairo_t * gtk_snapshot_append_cairo_node (GtkSnapshot *state,
const graphene_rect_t *bounds,
const char *name,
@ -117,6 +122,12 @@ void gtk_snapshot_render_insertion_cursor (GtkSnapshot
PangoLayout *layout,
int index,
PangoDirection direction);
GDK_AVAILABLE_IN_3_90
void gtk_snapshot_render_icon (GtkSnapshot *snapshot,
GtkStyleContext *context,
GdkPixbuf *pixbuf,
gdouble x,
gdouble y);
G_END_DECLS