diff options
author | Benjamin Otte <otte@redhat.com> | 2023-05-03 07:19:58 +0200 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2023-05-17 02:25:32 +0200 |
commit | 0e71898059415fe0fd0f96bcc5c5b365c7e0ebdd (patch) | |
tree | c5eed07fa0fafd1a238b0b29775bf8cfaffa562c /demos | |
parent | 69efa685fdb80b1b6ee7513c1312eb6a35ac64d1 (diff) | |
download | gtk+-0e71898059415fe0fd0f96bcc5c5b365c7e0ebdd.tar.gz |
node-editor: Add initial comparison UI
And yes, I'm aware of the icon I'm using.
Diffstat (limited to 'demos')
-rw-r--r-- | demos/node-editor/meson.build | 1 | ||||
-rw-r--r-- | demos/node-editor/node-editor-window.c | 72 | ||||
-rw-r--r-- | demos/node-editor/node-editor-window.ui | 76 | ||||
-rw-r--r-- | demos/node-editor/rendernodeutils.c | 433 | ||||
-rw-r--r-- | demos/node-editor/rendernodeutilsprivate.h | 30 |
5 files changed, 587 insertions, 25 deletions
diff --git a/demos/node-editor/meson.build b/demos/node-editor/meson.build index 91ea0d6d69..3358e69a6a 100644 --- a/demos/node-editor/meson.build +++ b/demos/node-editor/meson.build @@ -3,6 +3,7 @@ node_editor_sources = [ 'main.c', 'node-editor-application.c', 'node-editor-window.c', + 'rendernodeutils.c' ] node_editor_resources = gnome.compile_resources('node_editor_resources', diff --git a/demos/node-editor/node-editor-window.c b/demos/node-editor/node-editor-window.c index 298d72307f..71dd362f60 100644 --- a/demos/node-editor/node-editor-window.c +++ b/demos/node-editor/node-editor-window.c @@ -22,6 +22,7 @@ #include "node-editor-window.h" #include "gtkrendererpaintableprivate.h" +#include "rendernodeutilsprivate.h" #include "gsk/gskrendernodeparserprivate.h" #include "gsk/gl/gskglrenderer.h" @@ -64,6 +65,7 @@ struct _NodeEditorWindow GListStore *saved_nodes; GListStore *renderers; GskRenderNode *node; + GtkAdjustment *compare_progress; GFile *file; GFileMonitor *file_monitor; @@ -392,7 +394,8 @@ text_view_query_tooltip_cb (GtkWidget *widget, static gboolean load_bytes (NodeEditorWindow *self, - GBytes *bytes); + GBytes *bytes, + gboolean stash); static void load_error (NodeEditorWindow *self, @@ -410,7 +413,7 @@ load_error (NodeEditorWindow *self, node = gtk_snapshot_free_to_node (snapshot); bytes = gsk_render_node_serialize (node); - load_bytes (self, bytes); + load_bytes (self, bytes, TRUE); gsk_render_node_unref (node); g_object_unref (layout); @@ -418,7 +421,8 @@ load_error (NodeEditorWindow *self, static gboolean load_bytes (NodeEditorWindow *self, - GBytes *bytes) + GBytes *bytes, + gboolean stash) { if (!g_utf8_validate (g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes), NULL)) { @@ -427,7 +431,8 @@ load_bytes (NodeEditorWindow *self, return FALSE; } - stash_current_node (self); + if (stash) + stash_current_node (self); gtk_text_buffer_set_text (self->text_buffer, g_bytes_get_data (bytes, NULL), @@ -453,7 +458,7 @@ load_file_contents (NodeEditorWindow *self, return FALSE; } - return load_bytes (self, bytes); + return load_bytes (self, bytes, TRUE); } static void @@ -473,7 +478,7 @@ saved_node_activate_cb (GtkListView *listview, node = gtk_snapshot_free_to_node (snapshot); bytes = gsk_render_node_serialize (node); - load_bytes (self, bytes); + load_bytes (self, bytes, TRUE); g_object_unref (paintable); } @@ -504,7 +509,7 @@ on_picture_drop_read_done_cb (GObject *source, if (g_output_stream_splice_finish (stream, res, NULL) >= 0) { bytes = g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (stream)); - if (load_bytes (self, bytes)) + if (load_bytes (self, bytes, TRUE)) action = GDK_ACTION_COPY; } @@ -1127,8 +1132,54 @@ out: } static void -dark_mode_cb (GtkToggleButton *button, - GParamSpec *pspec, +update_compare (NodeEditorWindow *self) +{ + GdkPaintable *from, *to; + GtkSnapshot *snapshot; + GskRenderNode *node, *node_from, *node_to; + GBytes *bytes; + guint n; + + n = g_list_model_get_n_items (G_LIST_MODEL (self->saved_nodes)); + + from = g_list_model_get_item (G_LIST_MODEL (self->saved_nodes), n - 3); + snapshot = gtk_snapshot_new (); + gdk_paintable_snapshot (from, snapshot, gdk_paintable_get_intrinsic_width (from), gdk_paintable_get_intrinsic_height (from)); + node_from = gtk_snapshot_free_to_node (snapshot); + g_object_unref (from); + + to = g_list_model_get_item (G_LIST_MODEL (self->saved_nodes), n - 2); + snapshot = gtk_snapshot_new (); + gdk_paintable_snapshot (to, snapshot, gdk_paintable_get_intrinsic_width (to), gdk_paintable_get_intrinsic_height (to)); + node_to = gtk_snapshot_free_to_node (snapshot); + g_object_unref (to); + + node = render_node_interpolate (node_from, node_to, gtk_adjustment_get_value (self->compare_progress)); + + bytes = gsk_render_node_serialize (node); + load_bytes (self, bytes, FALSE); + + gsk_render_node_unref (node); + gsk_render_node_unref (node_to); + gsk_render_node_unref (node_from); +} + +static void +compare_toggled_cb (GtkToggleButton *button, + GParamSpec *pspec, + NodeEditorWindow *self) +{ + if (!gtk_toggle_button_get_active (button)) + return; + + stash_current_node (self); + + update_compare (self); +} + +static void +dark_mode_cb (GtkToggleButton *button, + GParamSpec *pspec, NodeEditorWindow *self) { g_object_set (gtk_widget_get_settings (GTK_WIDGET (self)), @@ -1602,6 +1653,7 @@ node_editor_window_class_init (NodeEditorWindowClass *class) gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, text_view); gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, picture); + gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, compare_progress); gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, renderer_listbox); gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, testcase_popover); gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, testcase_error_label); @@ -1619,10 +1671,12 @@ node_editor_window_class_init (NodeEditorWindowClass *class) gtk_widget_class_bind_template_callback (widget_class, clip_image_cb); gtk_widget_class_bind_template_callback (widget_class, testcase_save_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, testcase_name_entry_changed_cb); + gtk_widget_class_bind_template_callback (widget_class, compare_toggled_cb); gtk_widget_class_bind_template_callback (widget_class, dark_mode_cb); gtk_widget_class_bind_template_callback (widget_class, on_picture_drag_prepare_cb); gtk_widget_class_bind_template_callback (widget_class, on_picture_drop_cb); gtk_widget_class_bind_template_callback (widget_class, click_gesture_pressed); + gtk_widget_class_bind_template_callback (widget_class, update_compare); gtk_widget_class_install_action (widget_class, "smart-edit", NULL, edit_action_cb); diff --git a/demos/node-editor/node-editor-window.ui b/demos/node-editor/node-editor-window.ui index e3d58158c0..08e8adf250 100644 --- a/demos/node-editor/node-editor-window.ui +++ b/demos/node-editor/node-editor-window.ui @@ -166,6 +166,16 @@ </object> </child> <child type="end"> + <object class="GtkToggleButton" id="compare_button"> + <property name="focus-on-click">0</property> + <property name="valign">center</property> + <property name="has-frame">0</property> + <property name="icon-name">emblem-synchronizing-symbolic</property> + <property name="tooltip-text" translatable="yes">Compare the last 2 items</property> + <signal name="notify::active" handler="compare_toggled_cb" swapped="0"/> + </object> + </child> + <child type="end"> <object class="GtkScaleButton" id="scale_scale"> <property name="focus-on-click">0</property> <property name="valign">center</property> @@ -257,31 +267,65 @@ <property name="end-child"> <object class="GtkBox"> <child> - <object class="GtkScrolledWindow"> - <property name="hexpand">1</property> - <property name="vexpand">1</property> - <property name="min-content-height">100</property> - <property name="min-content-width">100</property> + <object class="GtkOverlay"> <child> - <object class="GtkViewport"> + <object class="GtkScrolledWindow"> + <property name="hexpand">1</property> + <property name="vexpand">1</property> + <property name="min-content-height">100</property> + <property name="min-content-width">100</property> <child> - <object class="GtkPicture" id="picture"> - <property name="can-shrink">0</property> - <property name="halign">center</property> - <property name="valign">center</property> + <object class="GtkViewport"> <child> - <object class="GtkDragSource"> + <object class="GtkPicture" id="picture"> + <property name="can-shrink">0</property> + <property name="halign">center</property> + <property name="valign">center</property> + <child> + <object class="GtkDragSource"> + <property name="actions">copy</property> + <signal name="prepare" handler="on_picture_drag_prepare_cb" swapped="no"/> + </object> + </child> + </object> + </child> + <child> + <object class="GtkDropTargetAsync"> <property name="actions">copy</property> - <signal name="prepare" handler="on_picture_drag_prepare_cb" swapped="no"/> + <property name="formats">application/x-gtk-render-node</property> + <signal name="drop" handler="on_picture_drop_cb" swapped="no"/> </object> </child> </object> </child> + </object> + </child> + <child type="overlay"> + <object class="GtkBox"> + <property name="margin-top">16</property> + <property name="margin-start">16</property> + <property name="margin-end">16</property> + <property name="margin-bottom">16</property> + <property name="halign">fill</property> + <property name="valign">end</property> + <property name="visible" bind-source="compare_button" bind-property="active">0</property> + <style> + <class name="osd" /> + </style> <child> - <object class="GtkDropTargetAsync"> - <property name="actions">copy</property> - <property name="formats">application/x-gtk-render-node</property> - <signal name="drop" handler="on_picture_drop_cb" swapped="no"/> + <object class="GtkScale"> + <property name="width-request">200</property> + <property name="draw-value">0</property> + <property name="adjustment"> + <object class="GtkAdjustment" id="compare_progress"> + <property name="upper">1</property> + <property name="value">0.5</property> + <property name="step-increment">0.01</property> + <property name="page-increment">0.1</property> + <signal name="notify::value" handler="update_compare" swapped="yes"/> + </object> + </property> + <property name="hexpand">1</property> </object> </child> </object> diff --git a/demos/node-editor/rendernodeutils.c b/demos/node-editor/rendernodeutils.c new file mode 100644 index 0000000000..a03e37d4a9 --- /dev/null +++ b/demos/node-editor/rendernodeutils.c @@ -0,0 +1,433 @@ +/* + * Copyright © 2023 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.1 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/>. + * + * Authors: Benjamin Otte <otte@gnome.org> + */ + +#include "config.h" + +#include "rendernodeutilsprivate.h" + +static inline double +double_interpolate (double start, + double end, + double progress) +{ + return start + (end - start) * progress; +} + +static inline float +float_interpolate (float start, + float end, + double progress) +{ + return start + (end - start) * progress; +} + +static void +rgba_interpolate (GdkRGBA *result, + const GdkRGBA *start, + const GdkRGBA *end, + double progress) +{ + result->alpha = CLAMP (double_interpolate (start->alpha, end->alpha, progress), 0, 1); + + if (result->alpha <= 0.0) + { + result->red = result->green = result->blue = 0.0; + } + else + { + result->red = CLAMP (double_interpolate (start->red * start->alpha, end->red * end->alpha, progress), 0, 1) / result->alpha; + result->green = CLAMP (double_interpolate (start->green * start->alpha, end->green * end->alpha, progress), 0, 1) / result->alpha; + result->blue = CLAMP (double_interpolate (start->blue * start->alpha, end->blue * end->alpha, progress), 0, 1) / result->alpha; + } +} + +static void +rounded_rect_interpolate (GskRoundedRect *dest, + const GskRoundedRect *start, + const GskRoundedRect *end, + double progress) +{ + guint i; + + graphene_rect_interpolate (&start->bounds, &end->bounds, progress, &dest->bounds); + for (i = 0; i < 4; i++) + graphene_size_interpolate (&start->corner[i], &end->corner[i], progress, &dest->corner[i]); +} + +static GskTransform * +transform_interpolate (GskTransform *start, + GskTransform *end, + double progress) +{ + switch (MIN (gsk_transform_get_category (start), gsk_transform_get_category (end))) + { + case GSK_TRANSFORM_CATEGORY_IDENTITY: + return NULL; + + case GSK_TRANSFORM_CATEGORY_2D_TRANSLATE: + { + float startx, starty, endx, endy; + + gsk_transform_to_translate (start, &startx, &starty); + gsk_transform_to_translate (end, &endx, &endy); + return gsk_transform_translate (NULL, + &GRAPHENE_POINT_INIT (float_interpolate (startx, endx, progress), + float_interpolate (starty, endy, progress))); + } + + case GSK_TRANSFORM_CATEGORY_2D_AFFINE: + case GSK_TRANSFORM_CATEGORY_2D: + { + float start_skew_x, start_skew_y, start_scale_x, start_scale_y, start_angle, start_dx, start_dy; + float end_skew_x, end_skew_y, end_scale_x, end_scale_y, end_angle, end_dx, end_dy; + GskTransform *transform; + + gsk_transform_to_2d_components (start, + &start_skew_x, &start_skew_y, + &start_scale_x, &start_scale_y, + &start_angle, + &start_dx, &start_dy); + gsk_transform_to_2d_components (end, + &end_skew_x, &end_skew_y, + &end_scale_x, &end_scale_y, + &end_angle, + &end_dx, &end_dy); + transform = gsk_transform_translate (NULL, + &GRAPHENE_POINT_INIT (float_interpolate (start_dx, end_dx, progress), + float_interpolate (start_dy, end_dy, progress))); + transform = gsk_transform_rotate (transform, + float_interpolate (start_angle, end_angle, progress)); + transform = gsk_transform_scale (transform, + float_interpolate (start_scale_x, end_scale_x, progress), + float_interpolate (start_scale_y, end_scale_y, progress)); + transform = gsk_transform_skew (transform, + float_interpolate (start_skew_x, end_skew_x, progress), + float_interpolate (start_skew_y, end_skew_y, progress)); + return transform; + } + + case GSK_TRANSFORM_CATEGORY_UNKNOWN: + case GSK_TRANSFORM_CATEGORY_ANY: + case GSK_TRANSFORM_CATEGORY_3D: + { + graphene_matrix_t start_matrix, end_matrix, matrix; + + gsk_transform_to_matrix (start, &start_matrix); + gsk_transform_to_matrix (end, &end_matrix); + graphene_matrix_interpolate (&start_matrix, &end_matrix, progress, &matrix); + return gsk_transform_matrix (NULL, &matrix); + } + + default: + g_return_val_if_reached (NULL); + } +} + +static void +color_stops_interpolate (GskColorStop *stops, + const GskColorStop *start_stops, + const GskColorStop *end_stops, + gsize n_stops, + double progress) +{ + guint i; + + for (i = 0; i < n_stops; i++) + { + stops[i].offset = float_interpolate (start_stops[i].offset, end_stops[i].offset, progress); + rgba_interpolate (&stops[i].color, &start_stops[i].color, &end_stops[i].color, progress); + } +} + +GskRenderNode * +render_node_interpolate (GskRenderNode *start, + GskRenderNode *end, + double progress) +{ + GskRenderNodeType start_type, end_type; + + if (progress <= 0) + return gsk_render_node_ref (start); + else if (progress >= 1) + return gsk_render_node_ref (end); + + start_type = gsk_render_node_get_node_type (start); + end_type = gsk_render_node_get_node_type (end); + + if (start_type == end_type) + { + switch (start_type) + { + case GSK_COLOR_NODE: + { + GdkRGBA rgba; + graphene_rect_t start_bounds, end_bounds, bounds; + + rgba_interpolate (&rgba, gsk_color_node_get_color (start), gsk_color_node_get_color (end), progress); + gsk_render_node_get_bounds (start, &start_bounds); + gsk_render_node_get_bounds (end, &end_bounds); + graphene_rect_interpolate (&start_bounds, &end_bounds, progress, &bounds); + return gsk_color_node_new (&rgba, &bounds); + } + + case GSK_DEBUG_NODE: + { + GskRenderNode *result, *child; + + /* xxx: do we need to interpolate the message somehow? */ + child = render_node_interpolate (gsk_debug_node_get_child (start), + gsk_debug_node_get_child (end), + progress); + result = gsk_debug_node_new (child, g_strdup_printf ("progress %g", progress)); + gsk_render_node_unref (child); + return result; + } + + case GSK_CONTAINER_NODE: + { + GskRenderNode **nodes; + GskRenderNode *result; + gsize i, n_nodes; + + if (gsk_container_node_get_n_children (start) != gsk_container_node_get_n_children (end)) + break; + + n_nodes = gsk_container_node_get_n_children (start); + nodes = g_new (GskRenderNode *, n_nodes); + + for (i = 0; i < n_nodes; i++) + { + nodes[i] = render_node_interpolate (gsk_container_node_get_child (start, i), + gsk_container_node_get_child (end, i), + progress); + } + + result = gsk_container_node_new (nodes, n_nodes); + for (i = 0; i < n_nodes; i++) + gsk_render_node_unref (nodes[i]); + g_free (nodes); + return result; + } + + case GSK_TEXTURE_NODE: + { + graphene_rect_t start_bounds, end_bounds, bounds; + + gsk_render_node_get_bounds (start, &start_bounds); + gsk_render_node_get_bounds (end, &end_bounds); + graphene_rect_interpolate (&start_bounds, &end_bounds, progress, &bounds); + return gsk_texture_node_new (gsk_texture_node_get_texture (progress > 0.5 ? end : start), + &bounds); + } + + case GSK_TEXTURE_SCALE_NODE: + { + graphene_rect_t start_bounds, end_bounds, bounds; + + gsk_render_node_get_bounds (start, &start_bounds); + gsk_render_node_get_bounds (end, &end_bounds); + graphene_rect_interpolate (&start_bounds, &end_bounds, progress, &bounds); + return gsk_texture_scale_node_new (gsk_texture_scale_node_get_texture (progress > 0.5 ? end : start), + &bounds, + gsk_texture_scale_node_get_filter (progress > 0.5 ? end : start)); + } + + case GSK_TRANSFORM_NODE: + { + GskRenderNode *result, *child; + GskTransform *transform; + + child = render_node_interpolate (gsk_transform_node_get_child (start), + gsk_transform_node_get_child (end), + progress); + transform = transform_interpolate (gsk_transform_node_get_transform (start), + gsk_transform_node_get_transform (end), + progress); + result = gsk_transform_node_new (child, transform); + gsk_transform_unref (transform); + gsk_render_node_unref (child); + return result; + } + + case GSK_CLIP_NODE: + { + GskRenderNode *result, *child; + graphene_rect_t clip; + + graphene_rect_interpolate (gsk_clip_node_get_clip (start), + gsk_clip_node_get_clip (end), + progress, + &clip); + child = render_node_interpolate (gsk_clip_node_get_child (start), + gsk_clip_node_get_child (end), + progress); + result = gsk_clip_node_new (child, &clip); + gsk_render_node_unref (child); + return result; + } + + case GSK_ROUNDED_CLIP_NODE: + { + GskRenderNode *result, *child; + GskRoundedRect clip; + + rounded_rect_interpolate (&clip, + gsk_rounded_clip_node_get_clip (start), + gsk_rounded_clip_node_get_clip (end), + progress); + child = render_node_interpolate (gsk_rounded_clip_node_get_child (start), + gsk_rounded_clip_node_get_child (end), + progress); + result = gsk_rounded_clip_node_new (child, &clip); + gsk_render_node_unref (child); + return result; + } + + case GSK_BORDER_NODE: + { + GdkRGBA color[4]; + const GdkRGBA *start_color, *end_color; + float width[4]; + const float *start_width, *end_width; + GskRoundedRect outline; + guint i; + + rounded_rect_interpolate (&outline, + gsk_border_node_get_outline (start), + gsk_border_node_get_outline (end), + progress); + start_color = gsk_border_node_get_colors (start); + end_color = gsk_border_node_get_colors (end); + start_width = gsk_border_node_get_widths (start); + end_width = gsk_border_node_get_widths (end); + for (i = 0; i < 4; i++) + { + rgba_interpolate (&color[i], &start_color[i], &end_color[i], progress); + width[i] = float_interpolate (start_width[i], end_width[i], progress); + } + return gsk_border_node_new (&outline, width, color); + } + + case GSK_MASK_NODE: + { + GskRenderNode *source, *mask, *result; + + source = render_node_interpolate (gsk_mask_node_get_source (start), + gsk_mask_node_get_source (end), + progress); + mask = render_node_interpolate (gsk_mask_node_get_mask (start), + gsk_mask_node_get_mask (end), + progress); + result = gsk_mask_node_new (source, + mask, + gsk_mask_node_get_mask_mode (progress > 0.5 ? end : start)); + gsk_render_node_unref (source); + gsk_render_node_unref (mask); + return result; + } + + case GSK_CONIC_GRADIENT_NODE: + { + graphene_rect_t start_bounds, end_bounds, bounds; + graphene_point_t center; + float rotation; + GskColorStop *color_stops; + gsize n_color_stops; + GskRenderNode *result; + + if (gsk_conic_gradient_node_get_n_color_stops (start) != gsk_conic_gradient_node_get_n_color_stops (end)) + break; + + n_color_stops = gsk_conic_gradient_node_get_n_color_stops (start); + color_stops = g_new (GskColorStop, n_color_stops); + + gsk_render_node_get_bounds (start, &start_bounds); + gsk_render_node_get_bounds (end, &end_bounds); + graphene_rect_interpolate (&start_bounds, &end_bounds, progress, &bounds); + graphene_point_interpolate (gsk_conic_gradient_node_get_center (start), + gsk_conic_gradient_node_get_center (end), + progress, + ¢er); + rotation = float_interpolate (gsk_conic_gradient_node_get_rotation (start), + gsk_conic_gradient_node_get_rotation (end), + progress); + color_stops_interpolate (color_stops, + gsk_conic_gradient_node_get_color_stops (start, NULL), + gsk_conic_gradient_node_get_color_stops (end, NULL), + n_color_stops, + progress); + result = gsk_conic_gradient_node_new (&bounds, + ¢er, + rotation, + color_stops, + n_color_stops); + g_free (color_stops); + return result; + } + + case GSK_REPEAT_NODE: + { + graphene_rect_t start_bounds, end_bounds, bounds, child_bounds; + GskRenderNode *child, *result; + + gsk_render_node_get_bounds (start, &start_bounds); + gsk_render_node_get_bounds (end, &end_bounds); + graphene_rect_interpolate (&start_bounds, &end_bounds, progress, &bounds); + graphene_rect_interpolate (gsk_repeat_node_get_child_bounds (start), + gsk_repeat_node_get_child_bounds (end), + progress, + &child_bounds); + child = render_node_interpolate (gsk_repeat_node_get_child (start), + gsk_repeat_node_get_child (end), + progress); + result = gsk_repeat_node_new (&bounds, child, &child_bounds); + gsk_render_node_unref (child); + return result; + } + + case GSK_LINEAR_GRADIENT_NODE: + case GSK_REPEATING_LINEAR_GRADIENT_NODE: + case GSK_RADIAL_GRADIENT_NODE: + case GSK_REPEATING_RADIAL_GRADIENT_NODE: + case GSK_INSET_SHADOW_NODE: + case GSK_OUTSET_SHADOW_NODE: + case GSK_OPACITY_NODE: + case GSK_COLOR_MATRIX_NODE: + case GSK_BLUR_NODE: + case GSK_SHADOW_NODE: + case GSK_BLEND_NODE: + case GSK_CROSS_FADE_NODE: + g_warning ("FIXME: not implemented"); + break; + + case GSK_GL_SHADER_NODE: + case GSK_CAIRO_NODE: + case GSK_TEXT_NODE: + break; + + case GSK_NOT_A_RENDER_NODE: + default: + g_assert_not_reached (); + break; + } + } + + return gsk_cross_fade_node_new (start, end, progress); +} + diff --git a/demos/node-editor/rendernodeutilsprivate.h b/demos/node-editor/rendernodeutilsprivate.h new file mode 100644 index 0000000000..cb8dc33d5f --- /dev/null +++ b/demos/node-editor/rendernodeutilsprivate.h @@ -0,0 +1,30 @@ +/* + * Copyright © 2019 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.1 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/>. + * + * Authors: Benjamin Otte <otte@gnome.org> + */ + +#pragma once + +#include <gsk/gsk.h> + +G_BEGIN_DECLS + +GskRenderNode * render_node_interpolate (GskRenderNode *start, + GskRenderNode *end, + double progress); + +G_END_DECLS |