mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-12 11:50:21 +00:00
gsk: Add gsk_render_node_draw()
Draws a node to a given cairo_t. This is mostly intended for fallback usage.
This commit is contained in:
parent
02131d590e
commit
e82d02432e
@ -28,6 +28,7 @@ gsk_render_node_ref
|
||||
gsk_render_node_unref
|
||||
GskRenderNodeType
|
||||
gsk_render_node_get_node_type
|
||||
gsk_render_node_draw
|
||||
gsk_render_node_set_opacity
|
||||
GskBlendMode
|
||||
gsk_render_node_set_blend_mode
|
||||
|
@ -46,121 +46,6 @@ gsk_cairo_renderer_unrealize (GskRenderer *renderer)
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_cairo_renderer_render_node (GskCairoRenderer *self,
|
||||
GskRenderNode *node,
|
||||
cairo_t *cr)
|
||||
{
|
||||
gboolean pop_group = FALSE;
|
||||
graphene_rect_t frame;
|
||||
|
||||
cairo_save (cr);
|
||||
|
||||
gsk_render_node_get_bounds (node, &frame);
|
||||
GSK_NOTE (CAIRO, g_print ("CLIP = { .x = %g, .y = %g, .width = %g, .height = %g }\n",
|
||||
frame.origin.x, frame.origin.y,
|
||||
frame.size.width, frame.size.height));
|
||||
|
||||
if (!GSK_RENDER_MODE_CHECK (GEOMETRY))
|
||||
{
|
||||
cairo_rectangle (cr, frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
|
||||
cairo_clip (cr);
|
||||
}
|
||||
|
||||
if (gsk_render_node_get_opacity (node) != 1.0)
|
||||
{
|
||||
GSK_NOTE (CAIRO, g_print ("Pushing opacity group (opacity:%g)\n",
|
||||
gsk_render_node_get_opacity (node)));
|
||||
cairo_push_group (cr);
|
||||
pop_group = TRUE;
|
||||
}
|
||||
|
||||
GSK_NOTE (CAIRO, g_print ("Rendering node %s[%p] at %g, %g\n",
|
||||
node->name,
|
||||
node,
|
||||
frame.origin.x, frame.origin.y));
|
||||
|
||||
switch (gsk_render_node_get_node_type (node))
|
||||
{
|
||||
case GSK_NOT_A_RENDER_NODE:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
|
||||
case GSK_CONTAINER_NODE:
|
||||
{
|
||||
guint i;
|
||||
GSK_NOTE (CAIRO, g_print ("Drawing %d children of node [%p]\n",
|
||||
gsk_container_node_get_n_children (node),
|
||||
node));
|
||||
for (i = 0; i < gsk_container_node_get_n_children (node); i++)
|
||||
{
|
||||
gsk_cairo_renderer_render_node (self, gsk_container_node_get_child (node, i), cr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_TEXTURE_NODE:
|
||||
{
|
||||
GskTexture *texture = gsk_texture_node_get_texture (node);
|
||||
cairo_surface_t *surface = gsk_texture_download (texture);
|
||||
|
||||
cairo_set_source_surface (cr, surface, frame.origin.x, frame.origin.y);
|
||||
cairo_paint (cr);
|
||||
cairo_surface_destroy (surface);
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_CAIRO_NODE:
|
||||
{
|
||||
cairo_set_source_surface (cr, gsk_cairo_node_get_surface (node), frame.origin.x, frame.origin.y);
|
||||
cairo_paint (cr);
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_TRANSFORM_NODE:
|
||||
{
|
||||
graphene_matrix_t mat;
|
||||
cairo_matrix_t ctm;
|
||||
|
||||
gsk_transform_node_get_transform (node, &mat);
|
||||
if (graphene_matrix_to_2d (&mat, &ctm.xx, &ctm.yx, &ctm.xy, &ctm.yy, &ctm.x0, &ctm.y0))
|
||||
{
|
||||
GSK_NOTE (CAIRO, g_print ("CTM = { .xx = %g, .yx = %g, .xy = %g, .yy = %g, .x0 = %g, .y0 = %g }\n",
|
||||
ctm.xx, ctm.yx,
|
||||
ctm.xy, ctm.yy,
|
||||
ctm.x0, ctm.y0));
|
||||
cairo_transform (cr, &ctm);
|
||||
}
|
||||
else
|
||||
g_critical ("Invalid non-affine transformation for node %p", node);
|
||||
|
||||
gsk_cairo_renderer_render_node (self, gsk_transform_node_get_child (node), cr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (GSK_RENDER_MODE_CHECK (GEOMETRY))
|
||||
{
|
||||
cairo_save (cr);
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
|
||||
cairo_rectangle (cr, frame.origin.x - 1, frame.origin.y - 1, frame.size.width + 2, frame.size.height + 2);
|
||||
cairo_set_line_width (cr, 2);
|
||||
cairo_set_source_rgba (cr, 0, 0, 0, 0.5);
|
||||
cairo_stroke (cr);
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
if (pop_group)
|
||||
{
|
||||
cairo_pop_group_to_source (cr);
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
|
||||
cairo_paint_with_alpha (cr, gsk_render_node_get_opacity (node));
|
||||
}
|
||||
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_cairo_renderer_render (GskRenderer *renderer,
|
||||
GskRenderNode *root)
|
||||
@ -209,7 +94,7 @@ gsk_cairo_renderer_render (GskRenderer *renderer,
|
||||
gsk_profiler_timer_begin (profiler, self->profile_timers.cpu_time);
|
||||
#endif
|
||||
|
||||
gsk_cairo_renderer_render_node (self, root, cr);
|
||||
gsk_render_node_draw (root, cr);
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
cpu_time = gsk_profiler_timer_end (profiler, self->profile_timers.cpu_time);
|
||||
|
@ -335,3 +335,62 @@ gsk_render_node_make_immutable (GskRenderNode *node)
|
||||
node->is_mutable = FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_render_node_draw:
|
||||
* @node: a #GskRenderNode
|
||||
* @cr: cairo context to draw to
|
||||
*
|
||||
* Draw the contents of @node to the given cairo context.
|
||||
*
|
||||
* Typically, you'll use this function to implement fallback rendering
|
||||
* of #GskRenderNodes on an intermediate Cairo context, instead of using
|
||||
* the drawing context associated to a #GdkWindow's rendering buffer.
|
||||
*
|
||||
* For advanced nodes that cannot be supported using Cairo, in particular
|
||||
* for nodes doing 3D operations, this function may fail.
|
||||
**/
|
||||
void
|
||||
gsk_render_node_draw (GskRenderNode *node,
|
||||
cairo_t *cr)
|
||||
{
|
||||
g_return_if_fail (GSK_IS_RENDER_NODE (node));
|
||||
g_return_if_fail (cr != NULL);
|
||||
|
||||
cairo_save (cr);
|
||||
|
||||
if (!GSK_RENDER_MODE_CHECK (GEOMETRY))
|
||||
{
|
||||
graphene_rect_t frame;
|
||||
|
||||
gsk_render_node_get_bounds (node, &frame);
|
||||
GSK_NOTE (CAIRO, g_print ("CLIP = { .x = %g, .y = %g, .width = %g, .height = %g }\n",
|
||||
frame.origin.x, frame.origin.y,
|
||||
frame.size.width, frame.size.height));
|
||||
|
||||
cairo_rectangle (cr, frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
|
||||
cairo_clip (cr);
|
||||
}
|
||||
|
||||
GSK_NOTE (CAIRO, g_print ("Rendering node %s[%p]\n",
|
||||
node->name,
|
||||
node));
|
||||
|
||||
node->node_class->draw (node, cr);
|
||||
|
||||
if (GSK_RENDER_MODE_CHECK (GEOMETRY))
|
||||
{
|
||||
graphene_rect_t frame;
|
||||
|
||||
gsk_render_node_get_bounds (node, &frame);
|
||||
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
|
||||
cairo_rectangle (cr, frame.origin.x - 1, frame.origin.y - 1, frame.size.width + 2, frame.size.height + 2);
|
||||
cairo_set_line_width (cr, 2);
|
||||
cairo_set_source_rgba (cr, 0, 0, 0, 0.5);
|
||||
cairo_stroke (cr);
|
||||
}
|
||||
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
|
||||
|
@ -88,6 +88,9 @@ void gsk_render_node_set_name (GskRenderNode *
|
||||
GDK_AVAILABLE_IN_3_90
|
||||
const char * gsk_render_node_get_name (GskRenderNode *node);
|
||||
|
||||
GDK_AVAILABLE_IN_3_90
|
||||
void gsk_render_node_draw (GskRenderNode *node,
|
||||
cairo_t *cr);
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GSK_RENDER_NODE_H__ */
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
#include "gskdebugprivate.h"
|
||||
#include "gskrendererprivate.h"
|
||||
#include "gsktexture.h"
|
||||
#include "gsktextureprivate.h"
|
||||
|
||||
/*** GSK_TEXTURE_NODE ***/
|
||||
|
||||
@ -47,6 +47,30 @@ gsk_texture_node_make_immutable (GskRenderNode *node)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_texture_node_draw (GskRenderNode *node,
|
||||
cairo_t *cr)
|
||||
{
|
||||
GskTextureNode *self = (GskTextureNode *) node;
|
||||
cairo_surface_t *surface;
|
||||
|
||||
surface = gsk_texture_download (self->texture);
|
||||
|
||||
cairo_save (cr);
|
||||
|
||||
cairo_translate (cr, self->bounds.origin.x, self->bounds.origin.y);
|
||||
cairo_scale (cr,
|
||||
self->bounds.size.width / gsk_texture_get_width (self->texture),
|
||||
self->bounds.size.height / gsk_texture_get_height (self->texture));
|
||||
|
||||
cairo_set_source_surface (cr, surface, 0, 0);
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_restore (cr);
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_texture_node_get_bounds (GskRenderNode *node,
|
||||
graphene_rect_t *bounds)
|
||||
@ -62,6 +86,7 @@ static const GskRenderNodeClass GSK_TEXTURE_NODE_CLASS = {
|
||||
"GskTextureNode",
|
||||
gsk_texture_node_finalize,
|
||||
gsk_texture_node_make_immutable,
|
||||
gsk_texture_node_draw,
|
||||
gsk_texture_node_get_bounds
|
||||
};
|
||||
|
||||
@ -130,6 +155,19 @@ gsk_cairo_node_make_immutable (GskRenderNode *node)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_cairo_node_draw (GskRenderNode *node,
|
||||
cairo_t *cr)
|
||||
{
|
||||
GskCairoNode *self = (GskCairoNode *) node;
|
||||
|
||||
if (self->surface == NULL)
|
||||
return;
|
||||
|
||||
cairo_set_source_surface (cr, self->surface, self->bounds.origin.x, self->bounds.origin.y);
|
||||
cairo_paint (cr);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_cairo_node_get_bounds (GskRenderNode *node,
|
||||
graphene_rect_t *bounds)
|
||||
@ -145,6 +183,7 @@ static const GskRenderNodeClass GSK_CAIRO_NODE_CLASS = {
|
||||
"GskCairoNode",
|
||||
gsk_cairo_node_finalize,
|
||||
gsk_cairo_node_make_immutable,
|
||||
gsk_cairo_node_draw,
|
||||
gsk_cairo_node_get_bounds
|
||||
};
|
||||
|
||||
@ -313,6 +352,19 @@ gsk_container_node_make_immutable (GskRenderNode *node)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_container_node_draw (GskRenderNode *node,
|
||||
cairo_t *cr)
|
||||
{
|
||||
GskContainerNode *container = (GskContainerNode *) node;
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < container->n_children; i++)
|
||||
{
|
||||
gsk_render_node_draw (container->children[i], cr);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_container_node_get_bounds (GskRenderNode *node,
|
||||
graphene_rect_t *bounds)
|
||||
@ -343,6 +395,7 @@ static const GskRenderNodeClass GSK_CONTAINER_NODE_CLASS = {
|
||||
"GskContainerNode",
|
||||
gsk_container_node_finalize,
|
||||
gsk_container_node_make_immutable,
|
||||
gsk_container_node_draw,
|
||||
gsk_container_node_get_bounds
|
||||
};
|
||||
|
||||
@ -436,9 +489,38 @@ gsk_transform_node_make_immutable (GskRenderNode *node)
|
||||
gsk_render_node_make_immutable (self->child);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_transform_node_draw (GskRenderNode *node,
|
||||
cairo_t *cr)
|
||||
{
|
||||
GskTransformNode *self = (GskTransformNode *) node;
|
||||
cairo_matrix_t ctm;
|
||||
|
||||
if (graphene_matrix_to_2d (&self->transform, &ctm.xx, &ctm.yx, &ctm.xy, &ctm.yy, &ctm.x0, &ctm.y0))
|
||||
{
|
||||
GSK_NOTE (CAIRO, g_print ("CTM = { .xx = %g, .yx = %g, .xy = %g, .yy = %g, .x0 = %g, .y0 = %g }\n",
|
||||
ctm.xx, ctm.yx,
|
||||
ctm.xy, ctm.yy,
|
||||
ctm.x0, ctm.y0));
|
||||
cairo_transform (cr, &ctm);
|
||||
|
||||
gsk_render_node_draw (self->child, cr);
|
||||
}
|
||||
else
|
||||
{
|
||||
graphene_rect_t bounds;
|
||||
|
||||
gsk_render_node_get_bounds (node, &bounds);
|
||||
|
||||
cairo_set_source_rgb (cr, 255 / 255., 105 / 255., 180 / 255.);
|
||||
cairo_rectangle (cr, bounds.origin.x, bounds.origin.x, bounds.size.width, bounds.size.height);
|
||||
cairo_fill (cr);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_transform_node_get_bounds (GskRenderNode *node,
|
||||
graphene_rect_t *bounds)
|
||||
graphene_rect_t *bounds)
|
||||
{
|
||||
GskTransformNode *self = (GskTransformNode *) node;
|
||||
graphene_rect_t child_bounds;
|
||||
@ -456,6 +538,7 @@ static const GskRenderNodeClass GSK_TRANSFORM_NODE_CLASS = {
|
||||
"GskTransformNode",
|
||||
gsk_transform_node_finalize,
|
||||
gsk_transform_node_make_immutable,
|
||||
gsk_transform_node_draw,
|
||||
gsk_transform_node_get_bounds
|
||||
};
|
||||
|
||||
|
@ -40,6 +40,8 @@ struct _GskRenderNodeClass
|
||||
const char *type_name;
|
||||
void (* finalize) (GskRenderNode *node);
|
||||
void (* make_immutable) (GskRenderNode *node);
|
||||
void (* draw) (GskRenderNode *node,
|
||||
cairo_t *cr);
|
||||
void (* get_bounds) (GskRenderNode *node,
|
||||
graphene_rect_t *bounds);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user