Compare commits

...

2 Commits

Author SHA1 Message Date
Timm Bäder
2b53f72481 snapshot: Add API for mask nodes 2018-03-28 20:24:48 +02:00
Timm Bäder
03267289d6 gsk: Add GskMaskNode 2018-03-28 19:06:39 +02:00
10 changed files with 248 additions and 2 deletions

View File

@@ -2197,6 +2197,7 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
case GSK_BLEND_NODE:
case GSK_REPEAT_NODE:
case GSK_CAIRO_NODE:
case GSK_MASK_NODE:
default:
{
render_fallback_node (self, node, builder, vertex_data);

View File

@@ -73,7 +73,8 @@ typedef enum {
GSK_CROSS_FADE_NODE,
GSK_TEXT_NODE,
GSK_BLUR_NODE,
GSK_OFFSET_NODE
GSK_OFFSET_NODE,
GSK_MASK_NODE,
} GskRenderNodeType;
/**

View File

@@ -325,6 +325,14 @@ GskRenderNode * gsk_blur_node_get_child (GskRenderNode
GDK_AVAILABLE_IN_ALL
double gsk_blur_node_get_radius (GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
GskRenderNode * gsk_mask_node_new (GskRenderNode *source_child,
GskRenderNode *mask_child);
GDK_AVAILABLE_IN_ALL
GskRenderNode * gsk_mask_node_get_source (GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
GskRenderNode * gsk_mask_node_get_mask (GskRenderNode *node);
G_END_DECLS
#endif /* __GSK_RENDER_NODE_H__ */

View File

@@ -4563,6 +4563,143 @@ gsk_blur_node_get_radius (GskRenderNode *node)
return self->radius;
}
/*** GSK_MASK_NODE ***/
typedef struct _GskMaskNode GskMaskNode;
struct _GskMaskNode
{
GskRenderNode render_node;
GskRenderNode *mask_child;
GskRenderNode *source_child;
};
static void
gsk_mask_node_finalize (GskRenderNode *node)
{
GskMaskNode *self = (GskMaskNode *) node;
gsk_render_node_unref (self->source_child);
gsk_render_node_unref (self->mask_child);
}
static void
gsk_mask_node_draw (GskRenderNode *node,
cairo_t *cr)
{
GskMaskNode *self = (GskMaskNode *) node;
cairo_pattern_t *mask_pattern;
cairo_push_group (cr);
gsk_render_node_draw (self->source_child, cr);
cairo_pop_group_to_source (cr);
cairo_push_group (cr);
gsk_render_node_draw (self->mask_child, cr);
mask_pattern = cairo_pop_group (cr);
cairo_mask (cr, mask_pattern);
}
#define GSK_MASK_NODE_VARIANT_TYPE "(uvuv)"
static GVariant *
gsk_mask_node_serialize (GskRenderNode *node)
{
GskMaskNode *self = (GskMaskNode *) node;
return g_variant_new (GSK_MASK_NODE_VARIANT_TYPE,
(guint32) gsk_render_node_get_node_type (self->source_child),
gsk_render_node_serialize_node (self->source_child),
(guint32) gsk_render_node_get_node_type (self->mask_child),
gsk_render_node_serialize_node (self->mask_child));
}
static GskRenderNode *
gsk_mask_node_deserialize (GVariant *variant,
GError **error)
{
guint32 source_type;
GskRenderNode *source_child;
GVariant *source_variant;
guint32 mask_type;
GskRenderNode *mask_child;
GVariant *mask_variant;
GskRenderNode *result;
g_variant_get (variant, GSK_MASK_NODE_VARIANT_TYPE,
&source_type, &source_variant,
&mask_type, &mask_variant);
source_child = gsk_render_node_deserialize_node (source_type, source_variant, error);
g_variant_unref (source_variant);
if (source_child == NULL)
return NULL;
mask_child = gsk_render_node_deserialize_node (mask_type, mask_variant, error);
g_variant_unref (mask_variant);
if (mask_child == NULL)
return NULL;
result = gsk_mask_node_new (source_child, mask_child);
gsk_render_node_unref (source_child);
gsk_render_node_unref (mask_child);
return result;
}
static const GskRenderNodeClass GSK_MASK_NODE_CLASS = {
GSK_MASK_NODE,
sizeof (GskMaskNode),
"GskMaskNode",
gsk_mask_node_finalize,
gsk_mask_node_draw,
gsk_mask_node_serialize,
gsk_mask_node_deserialize
};
GskRenderNode *
gsk_mask_node_new (GskRenderNode *source_child,
GskRenderNode *mask_child)
{
GskMaskNode *self;
g_return_val_if_fail (GSK_IS_RENDER_NODE (source_child), NULL);
g_return_val_if_fail (GSK_IS_RENDER_NODE (mask_child), NULL);
self = (GskMaskNode *) gsk_render_node_new (&GSK_MASK_NODE_CLASS, 0);
self->source_child = gsk_render_node_ref (source_child);
self->mask_child = gsk_render_node_ref (mask_child);
graphene_rect_union (&source_child->bounds, &mask_child->bounds, &self->render_node.bounds);
return &self->render_node;
}
GskRenderNode *
gsk_mask_node_get_source (GskRenderNode *node)
{
GskMaskNode *self = (GskMaskNode *) node;
g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_MASK_NODE), NULL);
return self->source_child;
}
GskRenderNode *
gsk_mask_node_get_mask (GskRenderNode *node)
{
GskMaskNode *self = (GskMaskNode *) node;
g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_MASK_NODE), NULL);
return self->mask_child;
}
static const GskRenderNodeClass *klasses[] = {
[GSK_CONTAINER_NODE] = &GSK_CONTAINER_NODE_CLASS,
[GSK_CAIRO_NODE] = &GSK_CAIRO_NODE_CLASS,
@@ -4584,7 +4721,8 @@ static const GskRenderNodeClass *klasses[] = {
[GSK_CROSS_FADE_NODE] = &GSK_CROSS_FADE_NODE_CLASS,
[GSK_TEXT_NODE] = &GSK_TEXT_NODE_CLASS,
[GSK_BLUR_NODE] = &GSK_BLUR_NODE_CLASS,
[GSK_OFFSET_NODE] = &GSK_OFFSET_NODE_CLASS
[GSK_OFFSET_NODE] = &GSK_OFFSET_NODE_CLASS,
[GSK_MASK_NODE] = &GSK_MASK_NODE_CLASS,
};
GskRenderNode *

View File

@@ -275,6 +275,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
g_assert_not_reached ();
return;
case GSK_SHADOW_NODE:
case GSK_MASK_NODE:
default:
FALLBACK ("Unsupported node '%s'", node->node_class->type_name);

View File

@@ -1076,6 +1076,90 @@ gtk_snapshot_push_blend (GtkSnapshot *snapshot,
gtk_snapshot_collect_blend_bottom);
}
static GskRenderNode *
gtk_snapshot_collect_mask_mask (GtkSnapshot *snapshot,
GtkSnapshotState *state,
GskRenderNode **nodes,
guint n_nodes,
const char *name)
{
GskRenderNode *source_child, *mask_child, *mask_node;
mask_child = gtk_snapshot_collect_default (snapshot, state, nodes, n_nodes, name);
source_child = state->data.mask.source_node;
if (source_child == NULL ||
mask_child == NULL)
return NULL;
mask_node = gsk_mask_node_new (source_child, mask_child);
gsk_render_node_set_name (mask_node, name);
gsk_render_node_unref (source_child);
gsk_render_node_unref (mask_child);
return mask_node;
}
static GskRenderNode *
gtk_snapshot_collect_mask_source (GtkSnapshot *snapshot,
GtkSnapshotState *state,
GskRenderNode **nodes,
guint n_nodes,
const char *name)
{
GtkSnapshotState *prev_state = gtk_snapshot_get_previous_state (snapshot);
g_assert (prev_state->collect_func == gtk_snapshot_collect_mask_mask);
prev_state->data.mask.source_node = gtk_snapshot_collect_default (snapshot, state, nodes, n_nodes, name);
return NULL;
}
/**
* gtk_snapshot_push_mask:
* @snapshot: a #GtkSnapshot
* @name: printf format string for name of the pushed node
* @...: printf-style arguments for the @name string
*
* Calling this function requires 2 subsequent calls to gtk_snapshot_pop().
**/
void
gtk_snapshot_push_mask (GtkSnapshot *snapshot,
const char *name,
...)
{
GtkSnapshotState *current_state = gtk_snapshot_get_current_state (snapshot);
GtkSnapshotState *source_state;
char *str;
if (name && snapshot->record_names)
{
va_list args;
va_start (args, name);
str = g_strdup_vprintf (name, args);
va_end (args);
}
else
str = NULL;
source_state = gtk_snapshot_push_state (snapshot,
str,
current_state->clip_region,
current_state->translate_x,
current_state->translate_y,
gtk_snapshot_collect_mask_mask);
gtk_snapshot_push_state (snapshot,
g_strdup (str),
source_state->clip_region,
source_state->translate_x,
source_state->translate_y,
gtk_snapshot_collect_mask_source);
}
static GskRenderNode *
gtk_snapshot_collect_cross_fade_end (GtkSnapshot *snapshot,
GtkSnapshotState *state,

View File

@@ -123,6 +123,10 @@ void gtk_snapshot_push_blend (GtkSnapshot
const char *name,
...) G_GNUC_PRINTF (3, 4);
GDK_AVAILABLE_IN_ALL
void gtk_snapshot_push_mask (GtkSnapshot *snapshot,
const char *name,
...) G_GNUC_PRINTF (2, 3);
GDK_AVAILABLE_IN_ALL
void gtk_snapshot_push_cross_fade (GtkSnapshot *snapshot,
double progress,
const char *name,

View File

@@ -73,6 +73,9 @@ struct _GtkSnapshotState {
GskBlendMode blend_mode;
GskRenderNode *bottom_node;
} blend;
struct {
GskRenderNode *source_node;
} mask;
struct {
double progress;
GskRenderNode *start_node;

View File

@@ -600,6 +600,9 @@ append_node (GtkTreeModelRenderNode *nodemodel,
}
}
break;
case GSK_MASK_NODE:
break;
}
}

View File

@@ -193,6 +193,8 @@ node_type_name (GskRenderNodeType type)
return "Text";
case GSK_BLUR_NODE:
return "Blur";
case GSK_MASK_NODE:
return "Mask";
}
}
@@ -662,6 +664,7 @@ populate_render_node_properties (GtkListStore *store,
case GSK_NOT_A_RENDER_NODE:
case GSK_TRANSFORM_NODE:
case GSK_MASK_NODE:
default:
break;
}