[gimp/wip/animation: 60/197] plug-ins: implement "combine" (blend mode "normal"/gegl:over) button.



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]