snapshot: Convert GtkLabel and GtkAccelLabel

Also adds gtk_snapshot_render_insertion_cursor().
This commit is contained in:
Benjamin Otte 2016-11-14 22:58:58 +01:00
parent ab47479045
commit 349f55f2fe
5 changed files with 252 additions and 78 deletions

View File

@ -139,8 +139,8 @@ static void gtk_accel_label_get_property (GObject *object,
GParamSpec *pspec);
static void gtk_accel_label_destroy (GtkWidget *widget);
static void gtk_accel_label_finalize (GObject *object);
static GskRenderNode *gtk_accel_label_get_render_node (GtkWidget *widget,
GskRenderer *renderer);
static void gtk_accel_label_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot);
static const gchar *gtk_accel_label_get_string (GtkAccelLabel *accel_label);
static void gtk_accel_label_measure (GtkWidget *widget,
GtkOrientation orientation,
@ -163,7 +163,7 @@ gtk_accel_label_class_init (GtkAccelLabelClass *class)
gobject_class->set_property = gtk_accel_label_set_property;
gobject_class->get_property = gtk_accel_label_get_property;
widget_class->get_render_node = gtk_accel_label_get_render_node;
widget_class->snapshot = gtk_accel_label_snapshot;
widget_class->measure = gtk_accel_label_measure;
widget_class->destroy = gtk_accel_label_destroy;
@ -457,20 +457,26 @@ get_first_baseline (PangoLayout *layout)
return PANGO_PIXELS (result);
}
static GskRenderNode *
gtk_accel_label_get_render_node (GtkWidget *widget,
GskRenderer *renderer)
static void
gtk_accel_label_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
GtkAccelLabel *accel_label = GTK_ACCEL_LABEL (widget);
guint ac_width;
GtkAllocation allocation;
GtkAllocation allocation, clip;
GtkRequisition requisition;
GskRenderNode *res;
graphene_rect_t bounds;
res = GTK_WIDGET_CLASS (gtk_accel_label_parent_class)->get_render_node (widget, renderer);
gtk_widget_get_clip (widget, &clip);
gtk_widget_get_allocation (widget, &allocation);
graphene_rect_init (&bounds,
clip.x - allocation.x, clip.y - allocation.y,
clip.width, clip.height);
gtk_snapshot_push (snapshot, &bounds, "AccelLabel");
GTK_WIDGET_CLASS (gtk_accel_label_parent_class)->snapshot (widget, snapshot);
ac_width = gtk_accel_label_get_accel_width (accel_label);
gtk_widget_get_allocation (widget, &allocation);
gtk_widget_get_preferred_size (widget, NULL, &requisition);
if (allocation.width >= requisition.width + ac_width)
@ -480,17 +486,6 @@ gtk_accel_label_get_render_node (GtkWidget *widget,
PangoLayout *accel_layout;
gint x;
gint y;
GtkAllocation alloc, clip;
GskRenderNode *node;
cairo_t *cr;
node = gtk_widget_create_render_node (widget, renderer, "AccelLabel 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);
context = gtk_widget_get_style_context (widget);
@ -507,18 +502,13 @@ gtk_accel_label_get_render_node (GtkWidget *widget,
y += get_first_baseline (label_layout) - get_first_baseline (accel_layout) - allocation.y;
gtk_style_context_save_to_node (context, accel_label->priv->accel_node);
gtk_render_layout (context, cr, x, y, accel_layout);
gtk_snapshot_render_layout (snapshot, context, x, y, accel_layout);
gtk_style_context_restore (context);
g_object_unref (accel_layout);
cairo_destroy (cr);
gsk_render_node_append_child (res, node);
gsk_render_node_unref (node);
}
return res;
gtk_snapshot_pop (snapshot);
}
static void

View File

@ -414,12 +414,11 @@ static void gtk_label_size_allocate (GtkWidget *widget,
static void gtk_label_state_flags_changed (GtkWidget *widget,
GtkStateFlags prev_state);
static void gtk_label_style_updated (GtkWidget *widget);
static void gtk_label_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot);
static gboolean gtk_label_focus (GtkWidget *widget,
GtkDirectionType direction);
static GskRenderNode *gtk_label_get_render_node (GtkWidget *label,
GskRenderer *renderer);
static void gtk_label_realize (GtkWidget *widget);
static void gtk_label_unrealize (GtkWidget *widget);
static void gtk_label_map (GtkWidget *widget);
@ -565,6 +564,13 @@ static void gtk_label_measure (GtkCssGadget *gadget,
int *minimum_baseline,
int *natural_baseline,
gpointer unused);
static gboolean gtk_label_render (GtkCssGadget *gadget,
GtkSnapshot *snapshot,
int x,
int y,
int width,
int height,
gpointer data);
static GtkBuildableIface *buildable_parent_iface = NULL;
@ -612,7 +618,7 @@ gtk_label_class_init (GtkLabelClass *class)
widget_class->state_flags_changed = gtk_label_state_flags_changed;
widget_class->style_updated = gtk_label_style_updated;
widget_class->query_tooltip = gtk_label_query_tooltip;
widget_class->get_render_node = gtk_label_get_render_node;
widget_class->snapshot = gtk_label_snapshot;
widget_class->realize = gtk_label_realize;
widget_class->unrealize = gtk_label_unrealize;
widget_class->map = gtk_label_map;
@ -1371,7 +1377,7 @@ gtk_label_init (GtkLabel *label)
gtk_label_measure,
NULL,
NULL,
NULL,
gtk_label_render,
NULL,
NULL);
}
@ -4153,41 +4159,38 @@ gtk_label_get_focus_link (GtkLabel *label)
return NULL;
}
static void
gtk_label_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
gtk_css_gadget_snapshot (GTK_LABEL (widget)->priv->gadget, snapshot);
}
static void layout_to_window_coords (GtkLabel *label,
gint *x,
gint *y);
#define GRAPHENE_RECT_FROM_RECT(_r) ((graphene_rect_t) GRAPHENE_RECT_INIT ((_r)->x, (_r)->y, (_r)->width, (_r)->height))
static GskRenderNode *
gtk_label_get_render_node (GtkWidget *widget,
GskRenderer *renderer)
static gboolean
gtk_label_render (GtkCssGadget *gadget,
GtkSnapshot *snapshot,
int x,
int y,
int width,
int height,
gpointer data)
{
GtkLabel *label = GTK_LABEL (widget);
GtkLabelPrivate *priv = label->priv;
GtkLabelSelectionInfo *info = priv->select_info;
GtkWidget *widget;
GtkLabel *label;
GtkLabelPrivate *priv;
GtkLabelSelectionInfo *info;
GtkStyleContext *context;
gint x, y, width, height;
gint lx, ly;
cairo_t *cr;
GtkAllocation alloc, clip;
GskRenderNode *node;
GskRenderNode *res;
res = gtk_css_gadget_get_render_node (priv->gadget, renderer, FALSE);
if (res == NULL)
return NULL;
node = gtk_widget_create_render_node (widget, renderer, "Label 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;
widget = gtk_css_gadget_get_owner (gadget);
label = GTK_LABEL (widget);
priv = label->priv;
info = priv->select_info;
gtk_label_ensure_layout (label);
@ -4206,12 +4209,14 @@ gtk_label_get_render_node (GtkWidget *widget,
lx = ly = 0;
layout_to_window_coords (label, &lx, &ly);
gtk_render_layout (context, cr, lx, ly, priv->layout);
gtk_snapshot_render_layout (snapshot, context, lx, ly, priv->layout);
if (info && (info->selection_anchor != info->selection_end))
{
gint range[2];
cairo_region_t *range_clip;
cairo_rectangle_int_t clip_extents;
cairo_t *cr;
range[0] = info->selection_anchor;
range[1] = info->selection_end;
@ -4224,8 +4229,10 @@ gtk_label_get_render_node (GtkWidget *widget,
}
range_clip = gdk_pango_layout_get_clip_region (priv->layout, lx, ly, range, 1);
cairo_save (cr);
cairo_region_get_extents (range_clip, &clip_extents);
cr = gtk_snapshot_append_cairo_node (snapshot,
&GRAPHENE_RECT_FROM_RECT(&clip_extents),
"Selected Text");
gtk_style_context_save_to_node (context, info->selection_node);
gdk_cairo_region (cr, range_clip);
@ -4235,7 +4242,7 @@ gtk_label_get_render_node (GtkWidget *widget,
gtk_render_layout (context, cr, lx, ly, priv->layout);
gtk_style_context_restore (context);
cairo_restore (cr);
cairo_destroy (cr);
cairo_region_destroy (range_clip);
}
else if (info)
@ -4244,7 +4251,9 @@ gtk_label_get_render_node (GtkWidget *widget,
GtkLabelLink *active_link;
gint range[2];
cairo_region_t *range_clip;
cairo_rectangle_int_t clip_extents;
GdkRectangle rect;
cairo_t *cr;
if (info->selectable &&
gtk_widget_has_focus (widget) &&
@ -4253,10 +4262,10 @@ gtk_label_get_render_node (GtkWidget *widget,
PangoDirection cursor_direction;
cursor_direction = get_cursor_direction (label);
gtk_render_insertion_cursor (context, cr,
lx, ly,
priv->layout, priv->select_info->selection_end,
cursor_direction);
gtk_snapshot_render_insertion_cursor (snapshot, context,
lx, ly,
priv->layout, priv->select_info->selection_end,
cursor_direction);
}
focus_link = gtk_label_get_focus_link (label);
@ -4267,11 +4276,13 @@ gtk_label_get_render_node (GtkWidget *widget,
range[0] = active_link->start;
range[1] = active_link->end;
cairo_save (cr);
gtk_style_context_save_to_node (context, active_link->cssnode);
range_clip = gdk_pango_layout_get_clip_region (priv->layout, lx, ly, range, 1);
cairo_region_get_extents (range_clip, &clip_extents);
cr = gtk_snapshot_append_cairo_node (snapshot,
&GRAPHENE_RECT_FROM_RECT(&clip_extents),
"Active Link");
gdk_cairo_region (cr, range_clip);
cairo_clip (cr);
cairo_region_destroy (range_clip);
@ -4291,19 +4302,14 @@ gtk_label_get_render_node (GtkWidget *widget,
range_clip = gdk_pango_layout_get_clip_region (priv->layout, lx, ly, range, 1);
cairo_region_get_extents (range_clip, &rect);
gtk_render_focus (context, cr, rect.x, rect.y, rect.width, rect.height);
gtk_snapshot_render_focus (snapshot, context, rect.x, rect.y, rect.width, rect.height);
cairo_region_destroy (range_clip);
}
}
}
cairo_destroy (cr);
gsk_render_node_append_child (res, node);
gsk_render_node_unref (node);
return res;
return FALSE;
}
static gboolean

View File

@ -298,6 +298,24 @@ gtk_snapshot_render_frame (GtkSnapshot *state,
gtk_snapshot_translate_2d (state, -x, -y);
}
void
gtk_snapshot_render_focus (GtkSnapshot *state,
GtkStyleContext *context,
gdouble x,
gdouble y,
gdouble width,
gdouble height)
{
g_return_if_fail (state != NULL);
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
gtk_snapshot_translate_2d (state, x, y);
gtk_css_style_snapshot_outline (gtk_style_context_lookup_style (context),
state,
width, height);
gtk_snapshot_translate_2d (state, -x, -y);
}
void
gtk_snapshot_render_layout (GtkSnapshot *state,
GtkStyleContext *context,

View File

@ -97,11 +97,26 @@ void gtk_snapshot_render_frame (GtkSnapshot
gdouble width,
gdouble height);
GDK_AVAILABLE_IN_3_90
void gtk_snapshot_render_focus (GtkSnapshot *state,
GtkStyleContext *context,
gdouble x,
gdouble y,
gdouble width,
gdouble height);
GDK_AVAILABLE_IN_3_90
void gtk_snapshot_render_layout (GtkSnapshot *state,
GtkStyleContext *context,
gdouble x,
gdouble y,
PangoLayout *layout);
GDK_AVAILABLE_IN_3_90 /* in gtkstylecontext.c */
void gtk_snapshot_render_insertion_cursor (GtkSnapshot *snapshot,
GtkStyleContext *context,
gdouble x,
gdouble y,
PangoLayout *layout,
int index,
PangoDirection direction);
G_END_DECLS

View File

@ -2060,7 +2060,6 @@ draw_insertion_cursor (GtkStyleContext *context,
gboolean is_primary,
PangoDirection direction,
gboolean draw_arrow)
{
GdkRGBA primary_color;
GdkRGBA secondary_color;
@ -2122,6 +2121,65 @@ draw_insertion_cursor (GtkStyleContext *context,
cairo_restore (cr);
}
static void
get_insertion_cursor_bounds (gdouble height,
PangoDirection direction,
gboolean draw_arrow,
graphene_rect_t *bounds)
{
gint stem_width;
gint offset;
stem_width = height * CURSOR_ASPECT_RATIO + 1;
if (direction == PANGO_DIRECTION_LTR)
offset = stem_width / 2;
else
offset = stem_width - stem_width / 2;
if (draw_arrow)
{
if (direction == PANGO_DIRECTION_LTR)
{
graphene_rect_init (bounds,
- offset, 0,
2 * stem_width + 1, height);
}
else
{
graphene_rect_init (bounds,
- offset - stem_width - 2, 0,
2 * stem_width + 2, height);
}
}
else
{
graphene_rect_init (bounds,
- offset, 0,
stem_width, height);
}
}
static void
snapshot_insertion_cursor (GtkSnapshot *snapshot,
GtkStyleContext *context,
gdouble height,
gboolean is_primary,
PangoDirection direction,
gboolean draw_arrow)
{
graphene_rect_t bounds;
cairo_t *cr;
get_insertion_cursor_bounds (height, direction, draw_arrow, &bounds);
cr = gtk_snapshot_append_cairo_node (snapshot,
&bounds,
"%s Cursor", is_primary ? "Primary" : "Secondary");
draw_insertion_cursor (context, cr, 0, 0, height, is_primary, direction, draw_arrow);
cairo_destroy (cr);
}
/**
* gtk_render_insertion_cursor:
* @context: a #GtkStyleContext
@ -2209,6 +2267,93 @@ gtk_render_insertion_cursor (GtkStyleContext *context,
}
}
/**
* gtk_snapshot_render_insertion_cursor:
* @snapshot: snapshot to render to
* @context: a #GtkStyleContext
* @x: X origin
* @y: Y origin
* @layout: the #PangoLayout of the text
* @index: the index in the #PangoLayout
* @direction: the #PangoDirection of the text
*
* Draws a text caret on @cr at the specified index of @layout.
*
* Since: 3.90
**/
void
gtk_snapshot_render_insertion_cursor (GtkSnapshot *snapshot,
GtkStyleContext *context,
gdouble x,
gdouble y,
PangoLayout *layout,
int index,
PangoDirection direction)
{
GtkStyleContextPrivate *priv;
gboolean split_cursor;
PangoRectangle strong_pos, weak_pos;
PangoRectangle *cursor1, *cursor2;
PangoDirection keymap_direction;
PangoDirection direction2;
g_return_if_fail (snapshot != NULL);
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (PANGO_IS_LAYOUT (layout));
g_return_if_fail (index >= 0);
priv = context->priv;
g_object_get (gtk_settings_get_for_screen (priv->screen),
"gtk-split-cursor", &split_cursor,
NULL);
keymap_direction = gdk_keymap_get_direction (gdk_keymap_get_for_display (gdk_screen_get_display (priv->screen)));
pango_layout_get_cursor_pos (layout, index, &strong_pos, &weak_pos);
direction2 = PANGO_DIRECTION_NEUTRAL;
if (split_cursor)
{
cursor1 = &strong_pos;
if (strong_pos.x != weak_pos.x || strong_pos.y != weak_pos.y)
{
direction2 = (direction == PANGO_DIRECTION_LTR) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
cursor2 = &weak_pos;
}
}
else
{
if (keymap_direction == direction)
cursor1 = &strong_pos;
else
cursor1 = &weak_pos;
}
gtk_snapshot_translate_2d (snapshot, x + PANGO_PIXELS (cursor1->x), y + PANGO_PIXELS (cursor1->y));
snapshot_insertion_cursor (snapshot,
context,
PANGO_PIXELS (cursor1->height),
TRUE,
direction,
direction2 != PANGO_DIRECTION_NEUTRAL);
gtk_snapshot_translate_2d (snapshot, - x - PANGO_PIXELS (cursor1->x), - y - PANGO_PIXELS (cursor1->y));
if (direction2 != PANGO_DIRECTION_NEUTRAL)
{
gtk_snapshot_translate_2d (snapshot, x + PANGO_PIXELS (cursor2->x), y + PANGO_PIXELS (cursor2->y));
snapshot_insertion_cursor (snapshot,
context,
PANGO_PIXELS (cursor2->height),
FALSE,
direction2,
TRUE);
gtk_snapshot_translate_2d (snapshot, - x - PANGO_PIXELS (cursor2->x), - y - PANGO_PIXELS (cursor2->y));
}
}
/**
* gtk_style_context_get_change:
* @context: the context to query