gsk: Add GskStrokeNode

This commit is contained in:
Benjamin Otte
2020-11-11 07:36:04 +01:00
committed by Matthias Clasen
parent 2b029af78f
commit c8928bf064
8 changed files with 265 additions and 4 deletions

View File

@@ -270,6 +270,7 @@ collect_reused_child_nodes (GskRenderer *renderer,
case GSK_CROSS_FADE_NODE:
case GSK_BLUR_NODE:
case GSK_FILL_NODE:
case GSK_STROKE_NODE:
default:
@@ -857,6 +858,7 @@ gsk_broadway_renderer_add_node (GskRenderer *renderer,
case GSK_BLUR_NODE:
case GSK_GL_SHADER_NODE:
case GSK_FILL_NODE:
case GSK_STROKE_NODE:
default:
break; /* Fallback */
}

View File

@@ -3768,6 +3768,7 @@ gsk_gl_render_job_visit_node (GskGLRenderJob *job,
break;
case GSK_FILL_NODE:
case GSK_STROKE_NODE:
gsk_gl_render_job_visit_as_fallback (job, node);
break;

View File

@@ -74,6 +74,7 @@ typedef enum {
GSK_CLIP_NODE,
GSK_ROUNDED_CLIP_NODE,
GSK_FILL_NODE,
GSK_STROKE_NODE,
GSK_SHADOW_NODE,
GSK_BLEND_NODE,
GSK_CROSS_FADE_NODE,

View File

@@ -159,6 +159,7 @@ GskRenderNode * gsk_render_node_deserialize (GBytes
#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_STROKE_NODE (gsk_stroke_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())
@@ -186,6 +187,7 @@ typedef struct _GskRepeatNode GskRepeatNode;
typedef struct _GskClipNode GskClipNode;
typedef struct _GskRoundedClipNode GskRoundedClipNode;
typedef struct _GskFillNode GskFillNode;
typedef struct _GskStrokeNode GskStrokeNode;
typedef struct _GskShadowNode GskShadowNode;
typedef struct _GskBlendNode GskBlendNode;
typedef struct _GskCrossFadeNode GskCrossFadeNode;
@@ -460,6 +462,19 @@ GskPath * gsk_fill_node_get_path (const GskRender
GDK_AVAILABLE_IN_ALL
GskFillRule gsk_fill_node_get_fill_rule (const GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
GType gsk_stroke_node_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GskRenderNode * gsk_stroke_node_new (GskRenderNode *child,
GskPath *path,
const GskStroke *stroke);
GDK_AVAILABLE_IN_ALL
GskRenderNode * gsk_stroke_node_get_child (const GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
GskPath * gsk_stroke_node_get_path (const GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
const GskStroke * gsk_stroke_node_get_stroke (const GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
GType gsk_shadow_node_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL

View File

@@ -26,6 +26,7 @@
#include "gskpath.h"
#include "gskrendererprivate.h"
#include "gskroundedrectprivate.h"
#include "gskstrokeprivate.h"
#include "gsktransformprivate.h"
#include "gdk/gdktextureprivate.h"
@@ -3934,6 +3935,168 @@ gsk_fill_node_get_fill_rule (const GskRenderNode *node)
return self->fill_rule;
}
/*** GSK_STROKE_NODE ***/
struct _GskStrokeNode
{
GskRenderNode render_node;
GskRenderNode *child;
GskPath *path;
GskStroke stroke;
};
static void
gsk_stroke_node_finalize (GskRenderNode *node)
{
GskStrokeNode *self = (GskStrokeNode *) node;
GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_STROKE_NODE));
gsk_render_node_unref (self->child);
gsk_path_unref (self->path);
gsk_stroke_clear (&self->stroke);
parent_class->finalize (node);
}
static void
gsk_stroke_node_draw (GskRenderNode *node,
cairo_t *cr)
{
GskStrokeNode *self = (GskStrokeNode *) node;
cairo_save (cr);
gsk_cairo_rectangle (cr, &self->child->bounds);
cairo_clip (cr);
cairo_push_group (cr);
gsk_render_node_draw (self->child, cr);
cairo_pop_group_to_source (cr);
gsk_stroke_to_cairo (&self->stroke, cr);
gsk_path_to_cairo (self->path, cr);
cairo_stroke (cr);
cairo_restore (cr);
}
static void
gsk_stroke_node_diff (GskRenderNode *node1,
GskRenderNode *node2,
cairo_region_t *region)
{
GskStrokeNode *self1 = (GskStrokeNode *) node1;
GskStrokeNode *self2 = (GskStrokeNode *) node2;
if (self1->path == self2->path &&
gsk_stroke_equal (&self1->stroke, &self2->stroke))
{
cairo_region_t *sub;
sub = cairo_region_create();
gsk_render_node_diff (self1->child, self2->child, sub);
cairo_region_union (region, sub);
cairo_region_destroy (sub);
}
else
{
gsk_render_node_diff_impossible (node1, node2, region);
}
}
/**
* gsk_stroke_node_new:
* @child: The node to stroke the area with
* @path: (transfer none): The path describing the area to stroke
* @stroke: (transfer none): The stroke attributes to use
*
* Creates a `GskRenderNode` that will stroke the @child along the given
* @path using the attributes defined in @stroke.
*
* Returns: (transfer none) (type GskStrokeNode): A new `GskRenderNode`
*/
GskRenderNode *
gsk_stroke_node_new (GskRenderNode *child,
GskPath *path,
const GskStroke *stroke)
{
GskStrokeNode *self;
GskRenderNode *node;
g_return_val_if_fail (GSK_IS_RENDER_NODE (child), NULL);
g_return_val_if_fail (path != NULL, NULL);
g_return_val_if_fail (stroke != NULL, NULL);
self = gsk_render_node_alloc (GSK_STROKE_NODE);
node = (GskRenderNode *) self;
self->child = gsk_render_node_ref (child);
self->path = gsk_path_ref (path);
gsk_stroke_init_copy (&self->stroke, stroke);
/* XXX: Figure out a way to compute bounds from the path */
graphene_rect_init_from_rect (&node->bounds, &child->bounds);
return node;
}
/**
* gsk_stroke_node_get_child:
* @node: (type GskStrokeNode): a stroke `GskRenderNode`
*
* Gets the child node that is getting drawn by the given @node.
*
* Returns: (transfer none): The child that is getting drawn
**/
GskRenderNode *
gsk_stroke_node_get_child (const GskRenderNode *node)
{
const GskStrokeNode *self = (const GskStrokeNode *) node;
g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_STROKE_NODE), NULL);
return self->child;
}
/**
* gsk_stroke_node_get_path:
* @node: (type GskStrokeNode): a stroke `GskRenderNode`
*
* Retrievs the path that will be stroked with the contents of
* the @node.
*
* Returns: (transfer none): a `GskPath`
*/
GskPath *
gsk_stroke_node_get_path (const GskRenderNode *node)
{
const GskStrokeNode *self = (const GskStrokeNode *) node;
g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_STROKE_NODE), NULL);
return self->path;
}
/**
* gsk_stroke_node_get_stroke:
* @node: (type GskStrokeNode): a stroke `GskRenderNode`
*
* Retrievs the stroke attributes used in this @node.
*
* Returns: a `GskStroke`
*/
const GskStroke *
gsk_stroke_node_get_stroke (const GskRenderNode *node)
{
const GskStrokeNode *self = (const GskStrokeNode *) node;
g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_STROKE_NODE), NULL);
return &self->stroke;
}
/*** GSK_SHADOW_NODE ***/
/**
@@ -5457,6 +5620,7 @@ 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_stroke_node, GSK_STROKE_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)
@@ -5772,6 +5936,22 @@ gsk_render_node_init_types_once (void)
gsk_render_node_types[GSK_FILL_NODE] = node_type;
}
{
const GskRenderNodeTypeInfo node_info =
{
GSK_STROKE_NODE,
sizeof (GskStrokeNode),
NULL,
gsk_stroke_node_finalize,
gsk_stroke_node_draw,
NULL,
gsk_stroke_node_diff,
};
GType node_type = gsk_render_node_type_register_static (I_("GskStrokeNode"), &node_info);
gsk_render_node_types[GSK_STROKE_NODE] = node_type;
}
{
const GskRenderNodeTypeInfo node_info =
{

View File

@@ -26,6 +26,7 @@
#include "gskpath.h"
#include "gskroundedrectprivate.h"
#include "gskrendernodeprivate.h"
#include "gskstroke.h"
#include "gsktransformprivate.h"
#include "gdk/gdkrgbaprivate.h"
@@ -2101,7 +2102,7 @@ append_float_param (Printer *p,
float value,
float default_value)
{
/* Don't approximate-compare here, better be topo verbose */
/* Don't approximate-compare here, better be too verbose */
if (value == default_value)
return;
@@ -2559,6 +2560,25 @@ render_node_print (Printer *p,
}
break;
case GSK_STROKE_NODE:
{
const GskStroke *stroke;
char *path_str;
start_node (p, "stroke");
append_node_param (p, "child", gsk_stroke_node_get_child (node));
path_str = gsk_path_to_string (gsk_stroke_node_get_path (node));
append_string_param (p, "path", path_str);
g_free (path_str);
stroke = gsk_stroke_node_get_stroke (node);
append_float_param (p, "line-width", gsk_stroke_get_line_width (stroke), 0.0);
end_node (p);
}
break;
case GSK_TRANSFORM_NODE:
{
GskTransform *transform = gsk_transform_node_get_transform (node);

View File

@@ -261,6 +261,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
case GSK_CONIC_GRADIENT_NODE:
case GSK_FILL_NODE:
case GSK_STROKE_NODE:
default:
FALLBACK ("Unsupported node '%s'", g_type_name_from_instance ((GTypeInstance *) node));

View File

@@ -167,6 +167,9 @@ create_list_model_for_render_node (GskRenderNode *node)
case GSK_FILL_NODE:
return create_render_node_list_model ((GskRenderNode *[1]) { gsk_fill_node_get_child (node) }, 1);
case GSK_STROKE_NODE:
return create_render_node_list_model ((GskRenderNode *[1]) { gsk_stroke_node_get_child (node) }, 1);
case GSK_SHADOW_NODE:
return create_render_node_list_model ((GskRenderNode *[1]) { gsk_shadow_node_get_child (node) }, 1);
@@ -290,6 +293,8 @@ node_type_name (GskRenderNodeType type)
return "Rounded Clip";
case GSK_FILL_NODE:
return "Fill";
case GSK_STROKE_NODE:
return "Stroke";
case GSK_SHADOW_NODE:
return "Shadow";
case GSK_BLEND_NODE:
@@ -330,6 +335,7 @@ node_name (GskRenderNode *node)
case GSK_CLIP_NODE:
case GSK_ROUNDED_CLIP_NODE:
case GSK_FILL_NODE:
case GSK_STROKE_NODE:
case GSK_SHADOW_NODE:
case GSK_BLEND_NODE:
case GSK_CROSS_FADE_NODE:
@@ -611,6 +617,20 @@ add_float_row (GtkListStore *store,
g_free (text);
}
static const char *
enum_to_nick (GType type,
int value)
{
GEnumClass *class;
GEnumValue *v;
class = g_type_class_ref (type);
v = g_enum_get_value (class, value);
g_type_class_unref (class);
return v->value_nick;
}
static void
populate_render_node_properties (GtkListStore *store,
GskRenderNode *node)
@@ -873,9 +893,7 @@ populate_render_node_properties (GtkListStore *store,
case GSK_BLEND_NODE:
{
GskBlendMode mode = gsk_blend_node_get_blend_mode (node);
tmp = g_enum_to_string (GSK_TYPE_BLEND_MODE, mode);
add_text_row (store, "Blendmode", tmp);
g_free (tmp);
add_text_row (store, "Blendmode", enum_to_nick (GSK_TYPE_BLEND_MODE, mode));
}
break;
@@ -1111,10 +1129,33 @@ populate_render_node_properties (GtkListStore *store,
case GSK_FILL_NODE:
{
GskPath *path = gsk_fill_node_get_path (node);
GskFillRule fill_rule = gsk_fill_node_get_fill_rule (node);
tmp = gsk_path_to_string (path);
add_text_row (store, "Path", tmp);
g_free (tmp);
add_text_row (store, "Fill rule", enum_to_nick (GSK_TYPE_FILL_RULE, fill_rule));
}
break;
case GSK_STROKE_NODE:
{
GskPath *path = gsk_stroke_node_get_path (node);
const GskStroke *stroke = gsk_stroke_node_get_stroke (node);
GskLineCap line_cap = gsk_stroke_get_line_cap (stroke);
GskLineJoin line_join = gsk_stroke_get_line_join (stroke);
tmp = gsk_path_to_string (path);
add_text_row (store, "Path", tmp);
g_free (tmp);
tmp = g_strdup_printf ("%.2f", gsk_stroke_get_line_width (stroke));
add_text_row (store, "Line width", tmp);
g_free (tmp);
add_text_row (store, "Line cap", enum_to_nick (GSK_TYPE_LINE_CAP, line_cap));
add_text_row (store, "Line join", enum_to_nick (GSK_TYPE_LINE_JOIN, line_join));
}
break;