Quelle gskcrossfadenode.c
Sprache: C
/* GSK - The GTK Scene Kit
*
* Copyright 2016 Endless
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library . If not , see < http : //www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gskcrossfadenode.h"
#include "gskrendernodeprivate.h"
#include "gskrectprivate.h"
#include "gskrenderreplay.h"
#include "gdk/gdkcairoprivate.h"
#include "gskopacitynode.h"
#include "gskrendernodeprivate.h"
/**
* GskCrossFadeNode :
*
* A render node cross fading between two child nodes .
*/
struct _GskCrossFadeNode
{
GskRenderNode render_node;
union {
GskRenderNode *children[2 ];
struct {
GskRenderNode *start;
GskRenderNode *end;
};
};
float progress;
};
static void
gsk_cross_fade_node_finalize (GskRenderNode *node)
{
GskCrossFadeNode *self = (GskCrossFadeNode *) node;
GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_CROSS_FADE_NODE));
gsk_render_node_unref (self->start);
gsk_render_node_unref (self->end);
parent_class->finalize (node);
}
static void
gsk_cross_fade_node_draw (GskRenderNode *node,
cairo_t *cr,
GskCairoData *data)
{
GskCrossFadeNode *self = (GskCrossFadeNode *) node;
if (gdk_cairo_is_all_clipped (cr))
return ;
cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA);
gsk_render_node_draw_full (self->start, cr, data);
cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA);
gsk_render_node_draw_full (self->end, cr, data);
cairo_pop_group_to_source (cr);
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
cairo_paint_with_alpha (cr, self->progress);
cairo_pop_group_to_source (cr); /* resets operator */
cairo_paint (cr);
}
static void
gsk_cross_fade_node_diff (GskRenderNode *node1,
GskRenderNode *node2,
GskDiffData *data)
{
GskCrossFadeNode *self1 = (GskCrossFadeNode *) node1;
GskCrossFadeNode *self2 = (GskCrossFadeNode *) node2;
if (self1->progress == self2->progress)
{
gsk_render_node_diff (self1->start, self2->start, data);
gsk_render_node_diff (self1->end, self2->end, data);
return ;
}
gsk_render_node_diff_impossible (node1, node2, data);
}
static GskRenderNode **
gsk_cross_fade_node_get_children (GskRenderNode *node,
gsize *n_children)
{
GskCrossFadeNode *self = (GskCrossFadeNode *) node;
*n_children = G_N_ELEMENTS (self->children);
return self->children;
}
static GskRenderNode *
gsk_cross_fade_node_replay (GskRenderNode *node,
GskRenderReplay *replay)
{
GskCrossFadeNode *self = (GskCrossFadeNode *) node;
GskRenderNode *result, *start, *end;
start = gsk_render_replay_filter_node (replay, self->start);
end = gsk_render_replay_filter_node (replay, self->end);
if (start == NULL)
{
if (end == NULL)
return NULL;
result = gsk_opacity_node_new (end, self->progress);
}
else if (end == NULL)
{
result = gsk_opacity_node_new (start, 1 .0 - self->progress);
}
else if (start == self->start && end == self->end)
{
result = gsk_render_node_ref (node);
}
else
{
result = gsk_cross_fade_node_new (start, end, self->progress);
}
g_clear_pointer (&start, gsk_render_node_unref);
g_clear_pointer (&end, gsk_render_node_unref);
return result;
}
static void
gsk_cross_fade_node_render_opacity (GskRenderNode *node,
GskOpacityData *data)
{
GskCrossFadeNode *self = (GskCrossFadeNode *) node;
GskOpacityData start_data = GSK_OPACITY_DATA_INIT_EMPTY (data->copies);
GskOpacityData end_data = GSK_OPACITY_DATA_INIT_EMPTY (data->copies);
graphene_rect_t intersect;
gsk_render_node_render_opacity (self->start, &start_data);
gsk_render_node_render_opacity (self->end, &end_data);
if (gsk_rect_intersection (&start_data.opaque, &end_data.opaque, &intersect))
{
if (gsk_rect_is_empty (&data->opaque))
data->opaque = intersect;
else
gsk_rect_coverage (&data->opaque, &intersect, &data->opaque);
}
}
static void
gsk_cross_fade_node_class_init (gpointer g_class,
gpointer class_data)
{
GskRenderNodeClass *node_class = g_class;
node_class->node_type = GSK_CROSS_FADE_NODE;
node_class->finalize = gsk_cross_fade_node_finalize;
node_class->draw = gsk_cross_fade_node_draw;
node_class->diff = gsk_cross_fade_node_diff;
node_class->get_children = gsk_cross_fade_node_get_children;
node_class->replay = gsk_cross_fade_node_replay;
node_class->render_opacity = gsk_cross_fade_node_render_opacity;
}
GSK_DEFINE_RENDER_NODE_TYPE (GskCrossFadeNode, gsk_cross_fade_node)
/**
* gsk_cross_fade_node_new :
* @ start : The start node to be drawn
* @ end : The node to be cross_fadeed onto the @ start node
* @ progress : How far the fade has progressed from start to end . The value will
* be clamped to the range [ 0 . . . 1 ]
*
* Creates a ` GskRenderNode ` that will do a cross - fade between @ start and @ end .
*
* Returns : ( transfer full ) ( type GskCrossFadeNode ) : A new ` GskRenderNode `
*/
GskRenderNode *
gsk_cross_fade_node_new (GskRenderNode *start,
GskRenderNode *end,
float progress)
{
GskCrossFadeNode *self;
GskRenderNode *node;
g_return_val_if_fail (GSK_IS_RENDER_NODE (start), NULL);
g_return_val_if_fail (GSK_IS_RENDER_NODE (end), NULL);
self = gsk_render_node_alloc (GSK_TYPE_CROSS_FADE_NODE);
node = (GskRenderNode *) self;
node->fully_opaque = start->fully_opaque && end->fully_opaque &&
gsk_rect_equal (&start->bounds, &end->bounds);
self->start = gsk_render_node_ref (start);
self->end = gsk_render_node_ref (end);
self->progress = CLAMP (progress, 0 .0 , 1 .0 );
graphene_rect_union (&start->bounds, &end->bounds, &node->bounds);
node->preferred_depth = gdk_memory_depth_merge (gsk_render_node_get_preferred_depth (start),
gsk_render_node_get_preferred_depth (end));
node->is_hdr = gsk_render_node_is_hdr (start) ||
gsk_render_node_is_hdr (end);
node->contains_subsurface_node = gsk_render_node_contains_subsurface_node (start) ||
gsk_render_node_contains_subsurface_node (end);
node->contains_paste_node = gsk_render_node_contains_paste_node (start) ||
gsk_render_node_contains_paste_node (end);
return node;
}
/**
* gsk_cross_fade_node_get_start_child :
* @ node : ( type GskCrossFadeNode ) : a cross - fading ` GskRenderNode `
*
* Retrieves the child ` GskRenderNode ` at the beginning of the cross - fade .
*
* Returns : ( transfer none ) : a ` GskRenderNode `
*/
GskRenderNode *
gsk_cross_fade_node_get_start_child (const GskRenderNode *node)
{
const GskCrossFadeNode *self = (const GskCrossFadeNode *) node;
return self->start;
}
/**
* gsk_cross_fade_node_get_end_child :
* @ node : ( type GskCrossFadeNode ) : a cross - fading ` GskRenderNode `
*
* Retrieves the child ` GskRenderNode ` at the end of the cross - fade .
*
* Returns : ( transfer none ) : a ` GskRenderNode `
*/
GskRenderNode *
gsk_cross_fade_node_get_end_child (const GskRenderNode *node)
{
const GskCrossFadeNode *self = (const GskCrossFadeNode *) node;
return self->end;
}
/**
* gsk_cross_fade_node_get_progress :
* @ node : ( type GskCrossFadeNode ) : a cross - fading ` GskRenderNode `
*
* Retrieves the progress value of the cross fade .
*
* Returns : the progress value , between 0 and 1
*/
float
gsk_cross_fade_node_get_progress (const GskRenderNode *node)
{
const GskCrossFadeNode *self = (const GskCrossFadeNode *) node;
return self->progress;
}
Messung V0.5 in Prozent C=98 H=96 G=96
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-07-02)
¤
*© Formatika GbR, Deutschland
2026-07-09