Quelle gskrenderreplay.c
Sprache: C
/* GSK - The GTK Scene Kit
*
* Copyright 2025 Benjamin Otte
*
* 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 "gskrenderreplay.h"
#include "gskrendernodeprivate.h"
/**
* GskRenderReplay : ( free - func gsk_render_replay_free )
*
* A facility to replay a [ class @ Gsk . RenderNode ] and its children , potentially
* modifying them .
*
* This is a utility tool to walk a rendernode tree . The most powerful way
* is to provide a function via [ method @ Gsk . RenderReplay . set_node_filter ]
* to filter each individual node and then run
* [ method @ Gsk . RenderReplay . filter_node ] on the nodes you want to filter .
*
* If you want to just walk the node tree and extract information
* without any modifications , you can also use [ method @ Gsk . RenderNode . get_children ] .
*
* Here is a little example application that redacts text in a node file :
*
* ` ` `
* # include < gtk / gtk . h >
*
* static GskRenderNode *
* redact_nodes ( GskRenderReplay * replay ,
* GskRenderNode * node ,
* gpointer user_data )
* {
* GskRenderNode * result ;
*
* if ( gsk_render_node_get_node_type ( node ) = = GSK_TEXT_NODE )
* {
* graphene_rect_t bounds ;
* const GdkRGBA * color ;
*
* gsk_render_node_get_bounds ( node , & bounds ) ;
* color = gsk_text_node_get_color ( node ) ;
*
* result = gsk_color_node_new ( color , & bounds ) ;
* }
* else
* {
* result = gsk_render_replay_default ( replay , node ) ;
* }
*
* return result ;
* }
*
* int
* main ( int argc , char * argv [ ] )
* {
* GFile * file ;
* GBytes * bytes ;
* GskRenderNode * result , * node ;
* GskRenderReplay * replay ;
*
* gtk_init ( ) ;
*
* if ( argc ! = 3 )
* {
* g_print ( " usage : % s INFILE OUTFILE \ n " , argv [ 0 ] ) ;
* return 0 ;
* }
*
* file = g_file_new_for_commandline_arg ( argv [ 1 ] ) ;
* bytes = g_file_load_bytes ( file , NULL , NULL , NULL ) ;
* g_object_unref ( file ) ;
* if ( bytes = = NULL )
* return 1 ;
*
* node = gsk_render_node_deserialize ( bytes , NULL , NULL ) ;
* g_bytes_unref ( bytes ) ;
* if ( node = = NULL )
* return 1 ;
*
* replay = gsk_render_replay_new ( ) ;
* gsk_render_replay_set_node_filter ( replay , redact_nodes , NULL , NULL ) ;
* result = gsk_render_replay_filter_node ( replay , node ) ;
* gsk_render_replay_free ( replay ) ;
*
* if ( ! gsk_render_node_write_to_file ( result , argv [ 2 ] , NULL ) )
* return 1 ;
*
* gsk_render_node_unref ( result ) ;
* gsk_render_node_unref ( node ) ;
*
* return 0 ;
* }
* ` ` `
*
* Since : 4 . 22
*/
struct _GskRenderReplay
{
GskRenderReplayNodeFilter node_filter;
gpointer node_filter_data;
GDestroyNotify node_filter_destroy;
GskRenderReplayTextureFilter texture_filter;
gpointer texture_filter_data;
GDestroyNotify texture_filter_destroy;
GskRenderReplayFontFilter font_filter;
gpointer font_filter_data;
GDestroyNotify font_filter_destroy;
};
/**
* gsk_render_replay_new :
*
* Creates a new replay object to replay nodes .
*
* Returns : A new replay object to replay nodes
*
* Since : 4 . 22
**/
GskRenderReplay *
gsk_render_replay_new (void )
{
GskRenderReplay *self;
self = g_new0 (GskRenderReplay, 1 );
return self;
}
/**
* gsk_render_replay_free :
* @ self : the replay object to free
*
* Frees a ` GskRenderReplay ` .
*
* Since : 4 . 22
**/
void
gsk_render_replay_free (GskRenderReplay *self)
{
g_return_if_fail (self != NULL);
gsk_render_replay_set_node_filter (self, NULL, NULL, NULL);
gsk_render_replay_set_texture_filter (self, NULL, NULL, NULL);
gsk_render_replay_set_font_filter (self, NULL, NULL, NULL);
g_free (self);
}
/**
* gsk_render_replay_set_node_filter :
* @ filter : ( nullable ) ( scope notified ) ( closure user_data ) ( destroy user_destroy ) :
* the function to call to replay nodes
* @ user_data : user data to pass to @ func
* @ user_destroy : destroy notify that will be called to release
* the user data parameter
*
* Sets the function to use as a node filter .
*
* This is the most complex function to use for replaying nodes .
* It can either :
*
* * keep the node and just return it unchanged
*
* * create a replacement node and return that
*
* * discard the node by returning ` NULL `
*
* * call [ method @ Gsk . RenderReplay . default ] to have the default handler
* run for this node , which calls your function on its children
*
* Since : 4 . 22
*/
void
gsk_render_replay_set_node_filter (GskRenderReplay *self,
GskRenderReplayNodeFilter filter,
gpointer user_data,
GDestroyNotify user_destroy)
{
g_return_if_fail (self != NULL);
g_return_if_fail (filter || user_data == NULL);
g_return_if_fail (user_data || !user_destroy);
if (self->node_filter_destroy)
self->node_filter_destroy (self->node_filter_data);
self->node_filter = filter;
self->node_filter_data = user_data;
self->node_filter_destroy = user_destroy;
}
/**
* gsk_render_replay_filter_node :
* @ self : the replay
* @ node : the node to replay
*
* Replays a node using the replay ' s filter function .
*
* After the replay the node may be unchanged , or it may be
* removed , which will result in % NULL being returned .
*
* If no filter node is set , [ method @ Gsk . RenderReplay . default ] is
* called instead .
*
* Returns : ( transfer full ) ( nullable ) : The replayed node
*
* Since : 4 . 22
**/
GskRenderNode *
gsk_render_replay_filter_node (GskRenderReplay *self,
GskRenderNode *node)
{
g_return_val_if_fail (self != NULL, NULL);
g_return_val_if_fail (GSK_IS_RENDER_NODE (node), NULL);
if (self->node_filter)
return self->node_filter (self, node, self->node_filter_data);
else
return gsk_render_replay_default (self, node);
}
/**
* gsk_render_replay_default :
* @ self : the replay
* @ node : the node to replay
*
* Replays the node using the default method .
*
* The default method calls [ method @ Gsk . RenderReplay . filter_node ]
* on all its child nodes and the filter functions for all its
* properties . If none of them are changed , it returns the passed
* in node . Otherwise it constructs a new node with the changed
* children and properties .
*
* It may not be possible to construct a new node when any of the
* callbacks return NULL . In that case , this function will return
* NULL , too .
*
* Returns : ( transfer full ) ( nullable ) : The replayed node
*
* Since : 4 . 22
**/
GskRenderNode *
gsk_render_replay_default (GskRenderReplay *self,
GskRenderNode *node)
{
g_return_val_if_fail (self != NULL, NULL);
g_return_val_if_fail (GSK_IS_RENDER_NODE (node), NULL);
return GSK_RENDER_NODE_GET_CLASS (node)->replay (node, self);
}
/**
* gsk_render_replay_set_texture_filter :
* @ self : the replay
* @ filter : ( nullable ) ( scope notified ) ( closure user_data ) ( destroy user_destroy ) :
* the texture filter function
* @ user_data : user data to pass to @ filter
* @ user_destroy : destroy notify that will be called to release
* the user data parameter
*
* Sets a filter function to be called by [ method @ Gsk . RenderReplay . default ]
* for nodes that contain textures .
*
* You can call [ method @ GskRenderReplay . filter_texture ] to filter
* a texture yourself .
*
* Since : 4 . 22
**/
void
gsk_render_replay_set_texture_filter (GskRenderReplay *self,
GskRenderReplayTextureFilter filter,
gpointer user_data,
GDestroyNotify user_destroy)
{
g_return_if_fail (self != NULL);
g_return_if_fail (filter || user_data == NULL);
g_return_if_fail (user_data || !user_destroy);
if (self->texture_filter_destroy)
self->texture_filter_destroy (self->texture_filter_data);
if (filter)
self->texture_filter = filter;
self->texture_filter_data = user_data;
self->texture_filter_destroy = user_destroy;
}
/**
* gsk_render_replay_filter_texture :
* @ self : the replay
* @ texture : The texture to filter
*
* Filters a texture using the current filter function .
*
* Returns : ( transfer full ) : the filtered texture
*
* Since : 4 . 22
**/
GdkTexture *
gsk_render_replay_filter_texture (GskRenderReplay *self,
GdkTexture *texture)
{
GdkTexture *result;
g_return_val_if_fail (self != NULL, NULL);
g_return_val_if_fail (GDK_IS_TEXTURE (texture), NULL);
if (!self->texture_filter)
return g_object_ref (texture);
result = self->texture_filter (self, texture, self->texture_filter_data);
g_assert (result != NULL);
return result;
}
/**
* gsk_render_replay_set_font_filter :
* @ self : the replay
* @ filter : ( nullable ) ( scope notified ) ( closure user_data ) ( destroy user_destroy ) :
* the font filter function
* @ user_data : user data to pass to @ filter
* @ user_destroy : destroy notify that will be called to release
* the user data parameter
*
* Sets a filter function to be called by [ method @ Gsk . RenderReplay . default ]
* for nodes that contain fonts .
*
* You can call [ method @ GskRenderReplay . filter_font ] to filter
* a font yourself .
*
* Since : 4 . 22
**/
void
gsk_render_replay_set_font_filter (GskRenderReplay *self,
GskRenderReplayFontFilter filter,
gpointer user_data,
GDestroyNotify user_destroy)
{
g_return_if_fail (self != NULL);
g_return_if_fail (filter || user_data == NULL);
g_return_if_fail (user_data || !user_destroy);
if (self->font_filter_destroy)
self->font_filter_destroy (self->font_filter_data);
if (filter)
self->font_filter = filter;
self->font_filter_data = user_data;
self->font_filter_destroy = user_destroy;
}
/**
* gsk_render_replay_filter_font :
* @ self : the replay
* @ font : The font to filter
*
* Filters a font using the current filter function .
*
* Returns : ( transfer full ) : the filtered font
*
* Since : 4 . 22
**/
PangoFont *
gsk_render_replay_filter_font (GskRenderReplay *self,
PangoFont *font)
{
PangoFont *result;
g_return_val_if_fail (self != NULL, NULL);
g_return_val_if_fail (PANGO_IS_FONT (font), NULL);
if (!self->font_filter)
return g_object_ref (font);
result = self->font_filter (self, font, self->font_filter_data);
g_assert (result != NULL);
return result;
}
G_DEFINE_POINTER_TYPE (GskRenderReplay, gsk_render_replay)
Messung V0.5 in Prozent C=98 H=93 G=95
¤ Dauer der Verarbeitung: 0.18 Sekunden
(vorverarbeitet am 2026-07-03)
¤
*© Formatika GbR, Deutschland
2026-07-09