[gimp] Issue #5313: consistent "file-pat-save-internal" procedure with…



commit 6905b0bbef7c670f0187854f56e5810b99522c9f
Author: Jehan <jehan girinstud io>
Date:   Thu Oct 14 23:48:36 2021 +0200

    Issue #5313: consistent "file-pat-save-internal" procedure with…
    
    … multiple drawables as parameter.
    
    Previous commit 7bb892f3 was "making it work" by making the API
    inconsistent and also only using the first drawable, which is making the
    logics meaningless.
    
    Instead accept multiple drawables, and export only the selected drawable
    (when alone) or the merged-down image containing only the selected
    drawables (when many).
    
    Note that in current implementation, this is not useful from GUI calls
    because the fully merged image is always exported when run interactively
    or with last vals (i.e. from the GUI) because gimp_export_image()
    flattens the image. So this change would only work when called
    non-interactively from other plug-ins. In such a case, multi-layer
    images do no longer return an error and whatever items are selected
    would change the export result.
    
    See also #7370 for a discussion about how to handle the selected items
    during export (because currently the `drawables` parameter of
    GimpSaveProcedure's run function is clearly a mostly bogus parameter).

 app/file-data/file-data-pat.c | 89 ++++++++++++++++++++++++++++++-------------
 app/file-data/file-data.c     | 17 ++++++---
 plug-ins/common/file-pat.c    | 35 ++++++++---------
 3 files changed, 90 insertions(+), 51 deletions(-)
---
diff --git a/app/file-data/file-data-pat.c b/app/file-data/file-data-pat.c
index 94e1cc61a2..a3b62e68b4 100644
--- a/app/file-data/file-data-pat.c
+++ b/app/file-data/file-data-pat.c
@@ -28,12 +28,16 @@
 #include "gegl/gimp-babl.h"
 
 #include "core/gimp.h"
+#include "core/gimpcontainer.h"
 #include "core/gimpdrawable.h"
 #include "core/gimpimage.h"
+#include "core/gimpimage-new.h"
+#include "core/gimpimage-resize.h"
 #include "core/gimplayer-new.h"
 #include "core/gimpparamspecs.h"
 #include "core/gimppattern.h"
 #include "core/gimppattern-load.h"
+#include "core/gimppickable.h"
 #include "core/gimptempbuf.h"
 
 #include "pdb/gimpprocedure.h"
@@ -45,11 +49,13 @@
 
 /*  local function prototypes  */
 
-static GimpImage   * file_pat_pattern_to_image (Gimp         *gimp,
-                                                GimpPattern  *pattern);
-static GimpPattern * file_pat_image_to_pattern (GimpImage    *image,
-                                                GimpDrawable *drawable,
-                                                const gchar  *name);
+static GimpImage   * file_pat_pattern_to_image (Gimp          *gimp,
+                                                GimpPattern   *pattern);
+static GimpPattern * file_pat_image_to_pattern (GimpImage     *image,
+                                                GimpContext   *context,
+                                                gint           n_drawables,
+                                                GimpDrawable **drawables,
+                                                const gchar   *name);
 
 
 /*  public functions  */
@@ -116,22 +122,24 @@ file_pat_save_invoker (GimpProcedure         *procedure,
                        const GimpValueArray  *args,
                        GError               **error)
 {
-  GimpValueArray *return_vals;
-  GimpImage      *image;
-  GimpDrawable   *drawable;
-  GimpPattern    *pattern;
-  const gchar    *name;
-  GFile          *file;
-  gboolean        success;
+  GimpValueArray  *return_vals;
+  GimpImage       *image;
+  GimpPattern     *pattern;
+  const gchar     *name;
+  GFile           *file;
+  GimpDrawable   **drawables;
+  gint             n_drawables;
+  gboolean         success;
 
   gimp_set_busy (gimp);
 
-  image    = g_value_get_object (gimp_value_array_index (args, 1));
-  drawable = g_value_get_object (gimp_value_array_index (args, 2));
-  file     = g_value_get_object (gimp_value_array_index (args, 3));
-  name     = g_value_get_string (gimp_value_array_index (args, 4));
+  image       = g_value_get_object (gimp_value_array_index (args, 1));
+  n_drawables = g_value_get_int (gimp_value_array_index (args, 2));
+  drawables   = (GimpDrawable **) gimp_value_get_object_array (gimp_value_array_index (args, 3));
+  file        = g_value_get_object (gimp_value_array_index (args, 4));
+  name        = g_value_get_string (gimp_value_array_index (args, 5));
 
-  pattern = file_pat_image_to_pattern (image, drawable, name);
+  pattern = file_pat_image_to_pattern (image, context, n_drawables, drawables, name);
 
   gimp_data_set_file (GIMP_DATA (pattern), file, TRUE, TRUE);
 
@@ -235,24 +243,50 @@ file_pat_pattern_to_image (Gimp        *gimp,
 }
 
 static GimpPattern *
-file_pat_image_to_pattern (GimpImage    *image,
-                           GimpDrawable *drawable,
-                           const gchar  *name)
+file_pat_image_to_pattern (GimpImage     *image,
+                           GimpContext   *context,
+                           gint           n_drawables,
+                           GimpDrawable **drawables,
+                           const gchar   *name)
 {
   GimpPattern *pattern;
+  GimpImage   *subimage = NULL;
   const Babl  *format;
   gint         width;
   gint         height;
 
-  format = gimp_babl_format (gimp_drawable_is_gray (drawable) ?
+  g_return_val_if_fail (n_drawables > 0, NULL);
+
+  if (n_drawables > 1)
+    {
+      GList *drawable_list = NULL;
+
+      for (gint i = 0; i < n_drawables; i++)
+        drawable_list = g_list_prepend (drawable_list, drawables[i]);
+
+      subimage = gimp_image_new_from_drawables (image->gimp, drawable_list, FALSE);
+      g_list_free (drawable_list);
+      gimp_container_remove (image->gimp->images, GIMP_OBJECT (subimage));
+      gimp_image_resize_to_layers (subimage, context,
+                                   NULL, NULL, NULL, NULL, NULL);
+      width  = gimp_image_get_width (subimage);
+      height = gimp_image_get_width (subimage);
+
+      gimp_pickable_flush (GIMP_PICKABLE (subimage));
+    }
+  else
+    {
+      width  = gimp_item_get_width  (GIMP_ITEM (drawables[0]));
+      height = gimp_item_get_height (GIMP_ITEM (drawables[0]));
+    }
+
+  format = gimp_babl_format (gimp_drawable_is_gray (drawables[0]) ?
                              GIMP_GRAY : GIMP_RGB,
                              GIMP_PRECISION_U8_NON_LINEAR,
-                             gimp_drawable_has_alpha (drawable),
+                             (subimage && gimp_image_has_alpha (subimage)) ||
+                             gimp_drawable_has_alpha (drawables[0]),
                              NULL);
 
-  width  = gimp_item_get_width  (GIMP_ITEM (drawable));
-  height = gimp_item_get_height (GIMP_ITEM (drawable));
-
   pattern = g_object_new (GIMP_TYPE_PATTERN,
                           "name",      name,
                           "mime-type", "image/x-gimp-pat",
@@ -260,10 +294,13 @@ file_pat_image_to_pattern (GimpImage    *image,
 
   pattern->mask = gimp_temp_buf_new (width, height, format);
 
-  gegl_buffer_get (gimp_drawable_get_buffer (drawable),
+  gegl_buffer_get (subimage != NULL ? gimp_pickable_get_buffer (GIMP_PICKABLE (subimage)) :
+                                      gimp_drawable_get_buffer (drawables[0]),
                    GEGL_RECTANGLE (0, 0, width, height), 1.0,
                    format, gimp_temp_buf_get_data (pattern->mask),
                    GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
 
+  g_clear_object (&subimage);
+
   return pattern;
 }
diff --git a/app/file-data/file-data.c b/app/file-data/file-data.c
index e105267154..7deb6a6826 100644
--- a/app/file-data/file-data.c
+++ b/app/file-data/file-data.c
@@ -429,12 +429,17 @@ file_data_init (Gimp *gimp)
                                                       FALSE,
                                                       GIMP_PARAM_READWRITE));
   gimp_procedure_add_argument (procedure,
-                               gimp_param_spec_drawable ("drawable",
-                                                         "Drawable",
-                                                         "Active drawable "
-                                                         "of input image",
-                                                         FALSE,
-                                                         GIMP_PARAM_READWRITE));
+                               g_param_spec_int ("n-drawables",
+                                                 "Num drawables",
+                                                 "Number of drawables",
+                                                 1, G_MAXINT, 1,
+                                                 GIMP_PARAM_READWRITE));
+  gimp_procedure_add_argument (procedure,
+                               gimp_param_spec_object_array ("drawables",
+                                                             "Drawables",
+                                                             "Selected drawables",
+                                                             GIMP_TYPE_DRAWABLE,
+                                                             GIMP_PARAM_READWRITE | GIMP_PARAM_NO_VALIDATE));
   gimp_procedure_add_argument (procedure,
                                g_param_spec_object ("file",
                                                     "File",
diff --git a/plug-ins/common/file-pat.c b/plug-ins/common/file-pat.c
index 024b0a0087..53f26ddcb1 100644
--- a/plug-ins/common/file-pat.c
+++ b/plug-ins/common/file-pat.c
@@ -200,16 +200,6 @@ pat_save (GimpProcedure        *procedure,
       break;
     }
 
-  if (n_drawables != 1)
-    {
-      g_set_error (&error, G_FILE_ERROR, 0,
-                   _("PAT format does not support multiple layers."));
-
-      return gimp_procedure_new_return_values (procedure,
-                                               GIMP_PDB_CALLING_ERROR,
-                                               error);
-    }
-
   if (run_mode == GIMP_RUN_INTERACTIVE)
     {
       if (! save_dialog (procedure, G_OBJECT (config)))
@@ -219,20 +209,27 @@ pat_save (GimpProcedure        *procedure,
   if (status == GIMP_PDB_SUCCESS)
     {
       GimpValueArray *save_retvals;
+      GimpValueArray *args;
 
       g_object_get (config,
                     "description", &description,
                     NULL);
 
-      save_retvals =
-        gimp_pdb_run_procedure (gimp_get_pdb (),
-                                "file-pat-save-internal",
-                                GIMP_TYPE_RUN_MODE,     GIMP_RUN_NONINTERACTIVE,
-                                GIMP_TYPE_IMAGE,        image,
-                                GIMP_TYPE_DRAWABLE,     drawables[0],
-                                G_TYPE_FILE,            file,
-                                G_TYPE_STRING,          description,
-                                G_TYPE_NONE);
+      args = gimp_value_array_new_from_types (NULL,
+                                              GIMP_TYPE_RUN_MODE,     GIMP_RUN_NONINTERACTIVE,
+                                              GIMP_TYPE_IMAGE,        image,
+                                              G_TYPE_INT,             n_drawables,
+                                              GIMP_TYPE_OBJECT_ARRAY, NULL,
+                                              G_TYPE_FILE,            file,
+                                              G_TYPE_STRING,          description,
+                                              G_TYPE_NONE);
+      gimp_value_set_object_array (gimp_value_array_index (args, 3),
+                                   GIMP_TYPE_ITEM, (GObject **) drawables, n_drawables);
+
+      save_retvals = gimp_pdb_run_procedure_array (gimp_get_pdb (),
+                                                   "file-pat-save-internal",
+                                                   args);
+      gimp_value_array_unref (args);
 
       if (GIMP_VALUES_GET_ENUM (save_retvals, 0) != GIMP_PDB_SUCCESS)
         {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]