gsk: Add GskFillNode
Take a rendernode as source and a GskPath and fill the region in the path just like cairo_fill() would.
This commit is contained in:
@@ -182,6 +182,12 @@ gsk_rounded_clip_node_new
|
||||
gsk_rounded_clip_node_get_child
|
||||
gsk_rounded_clip_node_get_clip
|
||||
<SUBSECTION>
|
||||
GskFillRule
|
||||
gsk_fill_node_new
|
||||
gsk_fill_node_get_child
|
||||
gsk_fill_node_get_path
|
||||
gsk_fill_node_get_fill_rule
|
||||
<SUBSECTION>
|
||||
GskShadow
|
||||
gsk_shadow_node_new
|
||||
gsk_shadow_node_get_shadow
|
||||
@@ -235,6 +241,7 @@ GSK_TYPE_CONTAINER_NODE
|
||||
GSK_TYPE_CONIC_GRADIENT_NODE
|
||||
GSK_TYPE_CROSS_FADE_NODE
|
||||
GSK_TYPE_DEBUG_NODE
|
||||
GSK_TYPE_FILL_NODE
|
||||
GSK_TYPE_GL_SHADER_NODE
|
||||
GSK_TYPE_INSET_SHADOW_NODE
|
||||
GSK_TYPE_LINEAR_GRADIENT_NODE
|
||||
@@ -265,6 +272,7 @@ gsk_conic_gradient_node_get_type
|
||||
gsk_container_node_get_type
|
||||
gsk_cross_fade_node_get_type
|
||||
gsk_debug_node_get_type
|
||||
gsk_fill_node_get_type
|
||||
gsk_gl_shader_node_get_type
|
||||
gsk_inset_shadow_node_get_type
|
||||
gsk_linear_gradient_node_get_type
|
||||
|
||||
@@ -269,6 +269,7 @@ collect_reused_child_nodes (GskRenderer *renderer,
|
||||
case GSK_BLEND_NODE:
|
||||
case GSK_CROSS_FADE_NODE:
|
||||
case GSK_BLUR_NODE:
|
||||
case GSK_FILL_NODE:
|
||||
|
||||
default:
|
||||
|
||||
@@ -855,6 +856,7 @@ gsk_broadway_renderer_add_node (GskRenderer *renderer,
|
||||
case GSK_CROSS_FADE_NODE:
|
||||
case GSK_BLUR_NODE:
|
||||
case GSK_GL_SHADER_NODE:
|
||||
case GSK_FILL_NODE:
|
||||
default:
|
||||
break; /* Fallback */
|
||||
}
|
||||
|
||||
@@ -3813,6 +3813,7 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
|
||||
|
||||
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
||||
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
|
||||
case GSK_FILL_NODE:
|
||||
case GSK_CAIRO_NODE:
|
||||
default:
|
||||
{
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
* @GSK_REPEAT_NODE: A node that repeats the child's contents
|
||||
* @GSK_CLIP_NODE: A node that clips its child to a rectangular area
|
||||
* @GSK_ROUNDED_CLIP_NODE: A node that clips its child to a rounded rectangle
|
||||
* @GSK_FILL_NODE: A node that fills a path
|
||||
* @GSK_SHADOW_NODE: A node that draws a shadow below its child
|
||||
* @GSK_BLEND_NODE: A node that blends two children together
|
||||
* @GSK_CROSS_FADE_NODE: A node that cross-fades between two children
|
||||
@@ -73,6 +74,7 @@ typedef enum {
|
||||
GSK_REPEAT_NODE,
|
||||
GSK_CLIP_NODE,
|
||||
GSK_ROUNDED_CLIP_NODE,
|
||||
GSK_FILL_NODE,
|
||||
GSK_SHADOW_NODE,
|
||||
GSK_BLEND_NODE,
|
||||
GSK_CROSS_FADE_NODE,
|
||||
@@ -167,6 +169,34 @@ typedef enum {
|
||||
GSK_CORNER_BOTTOM_LEFT
|
||||
} GskCorner;
|
||||
|
||||
/**
|
||||
* GskFillRule:
|
||||
* @GSK_FILL_RULE_WINDING: If the path crosses the ray from
|
||||
* left-to-right, counts +1. If the path crosses the ray
|
||||
* from right to left, counts -1. (Left and right are determined
|
||||
* from the perspective of looking along the ray from the starting
|
||||
* point.) If the total count is non-zero, the point will be filled.
|
||||
* @GSK_FILL_RULE_EVEN_ODD: Counts the total number of
|
||||
* intersections, without regard to the orientation of the contour. If
|
||||
* the total number of intersections is odd, the point will be
|
||||
* filled.
|
||||
*
|
||||
* #GskFillRule is used to select how paths are filled, for example in
|
||||
* gsk_fill_node_new(). Whether or not a point is included in the fill is
|
||||
* determined by taking a ray from that point to infinity and looking
|
||||
* at intersections with the path. The ray can be in any direction,
|
||||
* as long as it doesn't pass through the end point of a segment
|
||||
* or have a tricky intersection such as intersecting tangent to the path.
|
||||
* (Note that filling is not actually implemented in this way. This
|
||||
* is just a description of the rule that is applied.)
|
||||
*
|
||||
* New entries may be added in future versions.
|
||||
**/
|
||||
typedef enum {
|
||||
GSK_FILL_RULE_WINDING,
|
||||
GSK_FILL_RULE_EVEN_ODD
|
||||
} GskFillRule;
|
||||
|
||||
/**
|
||||
* GskSerializationError:
|
||||
* @GSK_SERIALIZATION_UNSUPPORTED_FORMAT: The format can not be
|
||||
|
||||
@@ -158,6 +158,7 @@ GskRenderNode * gsk_render_node_deserialize (GBytes
|
||||
#define GSK_TYPE_REPEAT_NODE (gsk_repeat_node_get_type())
|
||||
#define GSK_TYPE_CLIP_NODE (gsk_clip_node_get_type())
|
||||
#define GSK_TYPE_ROUNDED_CLIP_NODE (gsk_rounded_clip_node_get_type())
|
||||
#define GSK_TYPE_FILL_NODE (gsk_fill_node_get_type())
|
||||
#define GSK_TYPE_SHADOW_NODE (gsk_shadow_node_get_type())
|
||||
#define GSK_TYPE_BLEND_NODE (gsk_blend_node_get_type())
|
||||
#define GSK_TYPE_CROSS_FADE_NODE (gsk_cross_fade_node_get_type())
|
||||
@@ -184,6 +185,7 @@ typedef struct _GskColorMatrixNode GskColorMatrixNode;
|
||||
typedef struct _GskRepeatNode GskRepeatNode;
|
||||
typedef struct _GskClipNode GskClipNode;
|
||||
typedef struct _GskRoundedClipNode GskRoundedClipNode;
|
||||
typedef struct _GskFillNode GskFillNode;
|
||||
typedef struct _GskShadowNode GskShadowNode;
|
||||
typedef struct _GskBlendNode GskBlendNode;
|
||||
typedef struct _GskCrossFadeNode GskCrossFadeNode;
|
||||
@@ -443,6 +445,19 @@ GskRenderNode * gsk_rounded_clip_node_get_child (GskRenderNode
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
const GskRoundedRect * gsk_rounded_clip_node_get_clip (GskRenderNode *node);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gsk_fill_node_get_type (void) G_GNUC_CONST;
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GskRenderNode * gsk_fill_node_new (GskRenderNode *child,
|
||||
GskPath *path,
|
||||
GskFillRule fill_rule);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GskRenderNode * gsk_fill_node_get_child (GskRenderNode *node);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GskPath * gsk_fill_node_get_path (GskRenderNode *node);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GskFillRule gsk_fill_node_get_fill_rule (GskRenderNode *node);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gsk_shadow_node_get_type (void) G_GNUC_CONST;
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "gskcairoblurprivate.h"
|
||||
#include "gskdebugprivate.h"
|
||||
#include "gskdiffprivate.h"
|
||||
#include "gskpath.h"
|
||||
#include "gskrendererprivate.h"
|
||||
#include "gskroundedrectprivate.h"
|
||||
#include "gsktransformprivate.h"
|
||||
@@ -3682,6 +3683,178 @@ gsk_rounded_clip_node_get_clip (GskRenderNode *node)
|
||||
return &self->clip;
|
||||
}
|
||||
|
||||
/*** GSK_FILL_NODE ***/
|
||||
|
||||
struct _GskFillNode
|
||||
{
|
||||
GskRenderNode render_node;
|
||||
|
||||
GskRenderNode *child;
|
||||
GskPath *path;
|
||||
GskFillRule fill_rule;
|
||||
};
|
||||
|
||||
static void
|
||||
gsk_fill_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
GskFillNode *self = (GskFillNode *) node;
|
||||
GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_FILL_NODE));
|
||||
|
||||
gsk_render_node_unref (self->child);
|
||||
gsk_path_unref (self->path);
|
||||
|
||||
parent_class->finalize (node);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_fill_node_draw (GskRenderNode *node,
|
||||
cairo_t *cr)
|
||||
{
|
||||
GskFillNode *self = (GskFillNode *) node;
|
||||
|
||||
cairo_save (cr);
|
||||
|
||||
switch (self->fill_rule)
|
||||
{
|
||||
case GSK_FILL_RULE_WINDING:
|
||||
cairo_set_fill_rule (cr, CAIRO_FILL_RULE_WINDING);
|
||||
break;
|
||||
case GSK_FILL_RULE_EVEN_ODD:
|
||||
cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
gsk_path_to_cairo (self->path, cr);
|
||||
cairo_clip (cr);
|
||||
|
||||
gsk_render_node_draw (self->child, cr);
|
||||
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_fill_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GskFillNode *self1 = (GskFillNode *) node1;
|
||||
GskFillNode *self2 = (GskFillNode *) node2;
|
||||
|
||||
if (self1->path == self2->path)
|
||||
{
|
||||
cairo_region_t *sub;
|
||||
cairo_rectangle_int_t clip_rect;
|
||||
graphene_rect_t rect;
|
||||
|
||||
sub = cairo_region_create();
|
||||
gsk_render_node_diff (self1->child, self2->child, sub);
|
||||
graphene_rect_union (&node1->bounds, &node2->bounds, &rect);
|
||||
rectangle_init_from_graphene (&clip_rect, &rect);
|
||||
cairo_region_intersect_rectangle (sub, &clip_rect);
|
||||
cairo_region_union (region, sub);
|
||||
cairo_region_destroy (sub);
|
||||
}
|
||||
else
|
||||
{
|
||||
gsk_render_node_diff_impossible (node1, node2, region);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_fill_node_new:
|
||||
* @child: The node to fill the area with
|
||||
* @path: The path describing the area to fill
|
||||
* @fill_rule: The fill rule to use
|
||||
*
|
||||
* Creates a #GskRenderNode that will fill the @child in the area
|
||||
* given by @path and @fill_rule.
|
||||
*
|
||||
* Returns: (transfer none) (type GskFillNode): A new #GskRenderNode
|
||||
*/
|
||||
GskRenderNode *
|
||||
gsk_fill_node_new (GskRenderNode *child,
|
||||
GskPath *path,
|
||||
GskFillRule fill_rule)
|
||||
{
|
||||
GskFillNode *self;
|
||||
GskRenderNode *node;
|
||||
graphene_rect_t path_bounds;
|
||||
|
||||
g_return_val_if_fail (GSK_IS_RENDER_NODE (child), NULL);
|
||||
g_return_val_if_fail (path != NULL, NULL);
|
||||
|
||||
self = gsk_render_node_alloc (GSK_FILL_NODE);
|
||||
node = (GskRenderNode *) self;
|
||||
|
||||
self->child = gsk_render_node_ref (child);
|
||||
self->path = gsk_path_ref (path);
|
||||
self->fill_rule = fill_rule;
|
||||
|
||||
if (gsk_path_get_bounds (path, &path_bounds))
|
||||
graphene_rect_intersection (&path_bounds, &child->bounds, &node->bounds);
|
||||
else
|
||||
graphene_rect_init_from_rect (&node->bounds, graphene_rect_zero ());
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_fill_node_get_child:
|
||||
* @node: (type GskFillNode): a fill #GskRenderNode
|
||||
*
|
||||
* Gets the child node that is getting drawn by the given @node.
|
||||
*
|
||||
* Returns: (transfer none): The child that is getting drawn
|
||||
**/
|
||||
GskRenderNode *
|
||||
gsk_fill_node_get_child (GskRenderNode *node)
|
||||
{
|
||||
GskFillNode *self = (GskFillNode *) node;
|
||||
|
||||
g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_FILL_NODE), NULL);
|
||||
|
||||
return self->child;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_fill_node_get_path:
|
||||
* @node: (type GskFillNode): a fill #GskRenderNode
|
||||
*
|
||||
* Retrievs the path used to describe the area filled with the contents of
|
||||
* the @node.
|
||||
*
|
||||
* Returns: (transfer none): a #GskPath
|
||||
*/
|
||||
GskPath *
|
||||
gsk_fill_node_get_path (GskRenderNode *node)
|
||||
{
|
||||
GskFillNode *self = (GskFillNode *) node;
|
||||
|
||||
g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_FILL_NODE), NULL);
|
||||
|
||||
return self->path;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_fill_node_get_fill_rule:
|
||||
* @node: (type GskFillNode): a fill #GskRenderNode
|
||||
*
|
||||
* Retrievs the fill rule used to determine how the path is filled.
|
||||
*
|
||||
* Returns: a #GskFillRule
|
||||
*/
|
||||
GskFillRule
|
||||
gsk_fill_node_get_fill_rule (GskRenderNode *node)
|
||||
{
|
||||
GskFillNode *self = (GskFillNode *) node;
|
||||
|
||||
g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_FILL_NODE), GSK_FILL_RULE_WINDING);
|
||||
|
||||
return self->fill_rule;
|
||||
}
|
||||
|
||||
/*** GSK_SHADOW_NODE ***/
|
||||
|
||||
/**
|
||||
@@ -5230,6 +5403,7 @@ GSK_DEFINE_RENDER_NODE_TYPE (gsk_color_matrix_node, GSK_COLOR_MATRIX_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_repeat_node, GSK_REPEAT_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_clip_node, GSK_CLIP_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_rounded_clip_node, GSK_ROUNDED_CLIP_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_fill_node, GSK_FILL_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_shadow_node, GSK_SHADOW_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_blend_node, GSK_BLEND_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_cross_fade_node, GSK_CROSS_FADE_NODE)
|
||||
@@ -5529,6 +5703,22 @@ gsk_render_node_init_types_once (void)
|
||||
gsk_render_node_types[GSK_ROUNDED_CLIP_NODE] = node_type;
|
||||
}
|
||||
|
||||
{
|
||||
const GskRenderNodeTypeInfo node_info =
|
||||
{
|
||||
GSK_FILL_NODE,
|
||||
sizeof (GskFillNode),
|
||||
NULL,
|
||||
gsk_fill_node_finalize,
|
||||
gsk_fill_node_draw,
|
||||
NULL,
|
||||
gsk_fill_node_diff,
|
||||
};
|
||||
|
||||
GType node_type = gsk_render_node_type_register_static (I_("GskFillNode"), &node_info);
|
||||
gsk_render_node_types[GSK_FILL_NODE] = node_type;
|
||||
}
|
||||
|
||||
{
|
||||
const GskRenderNodeTypeInfo node_info =
|
||||
{
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "gskrendernodeparserprivate.h"
|
||||
|
||||
#include "gskpath.h"
|
||||
#include "gskroundedrectprivate.h"
|
||||
#include "gskrendernodeprivate.h"
|
||||
#include "gsktransformprivate.h"
|
||||
@@ -2536,6 +2537,20 @@ render_node_print (Printer *p,
|
||||
append_node_param (p, "child", gsk_rounded_clip_node_get_child (node));
|
||||
append_rounded_rect_param (p, "clip", gsk_rounded_clip_node_get_clip (node));
|
||||
|
||||
end_node (p);
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_FILL_NODE:
|
||||
{
|
||||
char *path_str;
|
||||
|
||||
start_node (p, "fill");
|
||||
|
||||
append_node_param (p, "child", gsk_fill_node_get_child (node));
|
||||
path_str = gsk_path_to_string (gsk_fill_node_get_path (node));
|
||||
append_string_param (p, "path", path_str);
|
||||
g_free (path_str);
|
||||
|
||||
end_node (p);
|
||||
}
|
||||
|
||||
@@ -260,6 +260,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
|
||||
case GSK_RADIAL_GRADIENT_NODE:
|
||||
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
|
||||
case GSK_CONIC_GRADIENT_NODE:
|
||||
case GSK_FILL_NODE:
|
||||
default:
|
||||
FALLBACK ("Unsupported node '%s'", g_type_name_from_instance ((GTypeInstance *) node));
|
||||
|
||||
|
||||
@@ -161,6 +161,9 @@ create_list_model_for_render_node (GskRenderNode *node)
|
||||
case GSK_ROUNDED_CLIP_NODE:
|
||||
return create_render_node_list_model ((GskRenderNode *[1]) { gsk_rounded_clip_node_get_child (node) }, 1);
|
||||
|
||||
case GSK_FILL_NODE:
|
||||
return create_render_node_list_model ((GskRenderNode *[1]) { gsk_fill_node_get_child (node) }, 1);
|
||||
|
||||
case GSK_SHADOW_NODE:
|
||||
return create_render_node_list_model ((GskRenderNode *[1]) { gsk_shadow_node_get_child (node) }, 1);
|
||||
|
||||
@@ -282,6 +285,8 @@ node_type_name (GskRenderNodeType type)
|
||||
return "Clip";
|
||||
case GSK_ROUNDED_CLIP_NODE:
|
||||
return "Rounded Clip";
|
||||
case GSK_FILL_NODE:
|
||||
return "Fill";
|
||||
case GSK_SHADOW_NODE:
|
||||
return "Shadow";
|
||||
case GSK_BLEND_NODE:
|
||||
@@ -321,6 +326,7 @@ node_name (GskRenderNode *node)
|
||||
case GSK_REPEAT_NODE:
|
||||
case GSK_CLIP_NODE:
|
||||
case GSK_ROUNDED_CLIP_NODE:
|
||||
case GSK_FILL_NODE:
|
||||
case GSK_SHADOW_NODE:
|
||||
case GSK_BLEND_NODE:
|
||||
case GSK_CROSS_FADE_NODE:
|
||||
@@ -1072,6 +1078,16 @@ populate_render_node_properties (GtkListStore *store,
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_FILL_NODE:
|
||||
{
|
||||
GskPath *path = gsk_fill_node_get_path (node);
|
||||
|
||||
tmp = gsk_path_to_string (path);
|
||||
add_text_row (store, "Path", tmp);
|
||||
g_free (tmp);
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_CONTAINER_NODE:
|
||||
tmp = g_strdup_printf ("%d", gsk_container_node_get_n_children (node));
|
||||
add_text_row (store, "Children", tmp);
|
||||
|
||||
Reference in New Issue
Block a user