[gimp/wip/animation: 60/197] plug-ins: implement "combine" (blend mode "normal"/gegl:over) button.
- From: Jehan Pagès <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/wip/animation: 60/197] plug-ins: implement "combine" (blend mode "normal"/gegl:over) button.
- Date: Sat, 7 Oct 2017 03:03:26 +0000 (UTC)
commit 0458f5ad69d7b846542bc8095ab0a617862eb84f
Author: Jehan <jehan girinstud io>
Date: Sun Jul 24 22:50:56 2016 +0200
plug-ins: implement "combine" (blend mode "normal"/gegl:over) button.
We have now implemented all features previously available.
plug-ins/animation-play/core/animationanimatic.c | 97 +++++++++++++++++---
.../animation-play/widgets/animation-storyboard.c | 48 +++++++++-
2 files changed, 128 insertions(+), 17 deletions(-)
---
diff --git a/plug-ins/animation-play/core/animationanimatic.c
b/plug-ins/animation-play/core/animationanimatic.c
index 3b13365..34cd338 100644
--- a/plug-ins/animation-play/core/animationanimatic.c
+++ b/plug-ins/animation-play/core/animationanimatic.c
@@ -319,12 +319,28 @@ animation_animatic_set_combine (AnimationAnimatic *animatic,
gint panel_num,
gboolean combine)
{
- AnimationAnimaticPrivate *priv = GET_PRIVATE (animatic);
+ AnimationAnimaticPrivate *priv = GET_PRIVATE (animatic);
+ Animation *animation = ANIMATION (animatic);
+ gint position;
+
+ position = animation_get_position (animation);
g_return_if_fail (panel_num > 0 &&
panel_num <= priv->n_panels);
- priv->combine[panel_num] = combine;
+ priv->combine[panel_num - 1] = combine;
+ if (animation_animatic_get_panel (animatic, position) == panel_num)
+ {
+ GeglBuffer *buffer;
+
+ buffer = animation_get_frame (animation, position);
+ g_signal_emit_by_name (animation, "render",
+ position, buffer, TRUE);
+ if (buffer)
+ {
+ g_object_unref (buffer);
+ }
+ }
}
const gboolean
@@ -576,19 +592,63 @@ static GeglBuffer *
animation_animatic_get_frame (Animation *animation,
gint pos)
{
- AnimationAnimaticPrivate *priv = GET_PRIVATE (animation);
- GeglBuffer *buffer = NULL;
- gint panel;
+ GeglBuffer *buffer = NULL;
+ gint panel;
panel = animation_animatic_get_panel (ANIMATION_ANIMATIC (animation),
pos);
if (panel > 0)
{
- gint32 *layers;
- gint32 num_layers;
+ AnimationAnimaticPrivate *priv;
+ GeglBuffer *panel_buffer;
+ gint32 *layers;
+ gint32 num_layers;
+ priv = GET_PRIVATE (animation);
layers = gimp_image_get_layers (priv->panels, &num_layers);
- buffer = gimp_drawable_get_buffer(layers[num_layers - panel]);
+ panel_buffer = gimp_drawable_get_buffer (layers[num_layers - panel]);
+
+ if (panel > 1 && priv->combine[panel - 1] &&
+ gimp_drawable_has_alpha (layers[num_layers - panel]))
+ {
+ GeglNode *graph, *backdrop, *source, *blend, *target;
+ GeglBuffer *prev_panel_buffer;
+
+ prev_panel_buffer = gimp_drawable_get_buffer (layers[num_layers - panel + 1]);
+
+ graph = gegl_node_new ();
+ backdrop = gegl_node_new_child (graph,
+ "operation", "gegl:buffer-source",
+ "buffer", prev_panel_buffer,
+ NULL);
+ source = gegl_node_new_child (graph,
+ "operation", "gegl:buffer-source",
+ "buffer", panel_buffer,
+ NULL);
+ blend = gegl_node_new_child (graph,
+ "operation", "gegl:over",
+ NULL);
+
+ target = gegl_node_new_child (graph,
+ "operation", "gegl:buffer-sink",
+ "buffer", &buffer,
+ "format", gegl_buffer_get_format (panel_buffer),
+ NULL);
+
+ gegl_node_link_many (backdrop, blend, target, NULL);
+ gegl_node_connect_to (source, "output",
+ blend, "aux");
+ gegl_node_process (target);
+
+ g_object_unref (graph);
+ g_object_unref (panel_buffer);
+ g_object_unref (prev_panel_buffer);
+ }
+ else
+ {
+ buffer = panel_buffer;
+ }
+
g_free (layers);
}
@@ -612,10 +672,17 @@ animation_animatic_serialize (Animation *animation)
{
gchar *panel;
- panel = g_markup_printf_escaped ("<panel duration=\"%d\">"
- "<layer id=\"%d\"/></panel>",
- priv->durations[i],
- priv->tattoos[i]);
+ if (priv->combine[i])
+ panel = g_markup_printf_escaped ("<panel duration=\"%d\" "
+ "blend-mode=\"normal\">"
+ "<layer id=\"%d\"/></panel>",
+ priv->durations[i],
+ priv->tattoos[i]);
+ else
+ panel = g_markup_printf_escaped ("<panel duration=\"%d\">"
+ "<layer id=\"%d\"/></panel>",
+ priv->durations[i],
+ priv->tattoos[i]);
tmp = text;
text = g_strconcat (text, panel, NULL);
@@ -763,6 +830,12 @@ animation_animatic_start_element (GMarkupParseContext *context,
if (duration > 0)
priv->durations[status->panel - 1] = duration;
}
+ else if (strcmp (*names, "blend-mode") == 0 && **values &&
+ strcmp (*values, "normal") == 0)
+ {
+ /* Only the "normal" blend mode is supported currently. */
+ priv->combine[status->panel - 1] = TRUE;
+ }
names++;
values++;
diff --git a/plug-ins/animation-play/widgets/animation-storyboard.c
b/plug-ins/animation-play/widgets/animation-storyboard.c
index 7d79293..6787b02 100644
--- a/plug-ins/animation-play/widgets/animation-storyboard.c
+++ b/plug-ins/animation-play/widgets/animation-storyboard.c
@@ -45,6 +45,7 @@ struct _AnimationStoryboardPrivate
gint current_panel;
GList *panel_buttons;
+ GList *disposal_buttons;
GList *comments;
};
@@ -83,6 +84,8 @@ static gboolean animation_storyboard_comment_keypress (GtkWidget *ent
AnimationStoryboard *view);
static void animation_storyboard_comment_changed (GtkTextBuffer *text_buffer,
AnimationAnimatic *animatic);
+static void animation_storyboard_disposal_toggled (GtkToggleButton *button,
+ AnimationAnimatic *animatic);
static void animation_storyboard_button_clicked (GtkWidget *widget,
AnimationAnimatic *animatic);
@@ -206,6 +209,10 @@ animation_storyboard_finalize (GObject *object)
{
g_list_free (view->priv->panel_buttons);
}
+ if (view->priv->disposal_buttons)
+ {
+ g_list_free (view->priv->disposal_buttons);
+ }
if (view->priv->comments)
{
g_list_free (view->priv->comments);
@@ -230,10 +237,11 @@ animation_storyboard_load (Animation *animation,
gint preview_height,
AnimationStoryboard *view)
{
- gint *layers;
- gint32 image_id;
- gint n_images;
- gint i;
+ AnimationAnimatic *animatic = ANIMATION_ANIMATIC (animation);
+ gint *layers;
+ gint32 image_id;
+ gint n_images;
+ gint i;
image_id = animation_get_image_id (animation);
@@ -247,6 +255,12 @@ animation_storyboard_load (Animation *animation,
(GDestroyNotify) gtk_widget_destroy);
view->priv->panel_buttons = NULL;
}
+ if (view->priv->disposal_buttons)
+ {
+ g_list_free_full (view->priv->disposal_buttons,
+ (GDestroyNotify) gtk_widget_destroy);
+ view->priv->disposal_buttons = NULL;
+ }
if (view->priv->comments)
{
g_list_free_full (view->priv->comments,
@@ -363,7 +377,7 @@ animation_storyboard_load (Animation *animation,
gtk_spin_button_set_increments (GTK_SPIN_BUTTON (duration), 1.0, 10.0);
gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (duration), TRUE);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (duration),
- animation_animatic_get_duration (ANIMATION_ANIMATIC (animation),
+ animation_animatic_get_duration (animatic,
panel_num));
gtk_entry_set_width_chars (GTK_ENTRY (duration), 2);
/* Allowing non-numeric text to type "ms" or "s". */
@@ -384,6 +398,9 @@ animation_storyboard_load (Animation *animation,
gtk_widget_show (duration);
disposal = gtk_toggle_button_new ();
+ gtk_button_set_relief (GTK_BUTTON (disposal), GTK_RELIEF_NONE);
+ g_object_set_data (G_OBJECT (disposal), "panel-num",
+ GINT_TO_POINTER (panel_num));
image = gtk_image_new_from_icon_name (GIMP_STOCK_TRANSPARENCY,
GTK_ICON_SIZE_MENU);
gtk_container_add (GTK_CONTAINER (disposal), image);
@@ -394,6 +411,14 @@ animation_storyboard_load (Animation *animation,
5 * panel_num - 2,
GTK_EXPAND, GTK_EXPAND,
0, 1);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (disposal),
+ animation_animatic_get_combine (animatic,
+ panel_num));
+ g_signal_connect (disposal, "toggled",
+ G_CALLBACK (animation_storyboard_disposal_toggled),
+ animation);
+ view->priv->disposal_buttons = g_list_prepend (view->priv->disposal_buttons,
+ disposal);
gtk_widget_show (disposal);
}
g_signal_connect (animation, "render",
@@ -498,6 +523,19 @@ animation_storyboard_comment_changed (GtkTextBuffer *text_buffer,
}
static void
+animation_storyboard_disposal_toggled (GtkToggleButton *button,
+ AnimationAnimatic *animatic)
+{
+ gpointer panel_num;
+
+ panel_num = g_object_get_data (G_OBJECT (button), "panel-num");
+
+ animation_animatic_set_combine (animatic,
+ GPOINTER_TO_INT (panel_num),
+ gtk_toggle_button_get_active (button));
+}
+
+static void
animation_storyboard_button_clicked (GtkWidget *widget,
AnimationAnimatic *animatic)
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]