[gegl] operations/transform: add border-align op



commit 91458b1f1cc0cc1828964175474b3c378c749148
Author: Øyvind Kolås <pippin gimp org>
Date:   Tue May 19 20:56:16 2020 +0200

    operations/transform: add border-align op
    
    border-align applies a translation on the input that aligns it with the
    borders of a compositing target, in normal use the compositing target
    does not need to be specified but it can be specified with the aux pad.

 operations/transform/border-align.c | 184 ++++++++++++++++++++++++++++++++++++
 operations/transform/meson.build    |   1 +
 operations/transform/module.c       |   2 +
 po/POTFILES.in                      |   1 +
 4 files changed, 188 insertions(+)
---
diff --git a/operations/transform/border-align.c b/operations/transform/border-align.c
new file mode 100644
index 000000000..2657f5323
--- /dev/null
+++ b/operations/transform/border-align.c
@@ -0,0 +1,184 @@
+/* This file is part of GEGL
+ *
+ * GEGL 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 3 of the License, or (at your option) any later version.
+ *
+ * GEGL 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 GEGL; if not, see <https://www.gnu.org/licenses/>.
+ *
+ * Copyright 2020 Øyvind Kolås
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+#ifdef GEGL_PROPERTIES
+
+property_double (x, _("X"), 0.5)
+    description (_("Horizontal justification 0.0 is left 0.5 centered and 1.0 right."))
+    value_range (-2.0, 3.0)
+    ui_range (0.0, 1.0)
+    ui_meta ("axis", "x")
+
+property_double (y, _("Y"), 0.5)
+    description (_("Vertical justification 0.0 is top 0.5 middle and 1.0 bottom."))
+    value_range (-2.0, 3.0)
+    ui_range (0.0, 1.0)
+    ui_meta ("axis", "y")
+
+property_double (horizontal_margin, "Horizontal Margin", 0.0)
+property_double (vertical_margin, "Vertical Margin", 0.0)
+
+property_boolean (snap_integer, "snap to integer position", TRUE)
+
+
+#else
+
+#include "gegl-operation-filter.h"
+#include "transform-core.h"
+#define GEGL_OP_NO_SOURCE
+#define GEGL_OP_Parent  OpTransform
+#define GEGL_OP_PARENT  TYPE_OP_TRANSFORM
+#define GEGL_OP_NAME    border_align 
+#define GEGL_OP_BUNDLE
+#define GEGL_OP_C_FILE  "border-align.c"
+
+#include "gegl-op.h"
+
+#include <math.h>
+#include <stdio.h>
+
+static GeglNode *gegl_node_get_consumer_no (GeglNode *node,
+                                            const char *output_pad,
+                                            const char **consumer_pad,
+                                            int no)
+{
+  GeglNode *consumer = NULL;
+  GeglNode **nodes = NULL;
+  const gchar **consumer_names = NULL;
+  int count;
+  if (node == NULL)
+    return NULL;
+
+  count = gegl_node_get_consumers (node, "output", &nodes, &consumer_names);
+  if (count > no){
+     /* XXX : look into inverting list in get_consumers */
+     //consumer = nodes[count-no-1];
+     consumer = nodes[no];
+     if (consumer_pad)
+       *consumer_pad = g_intern_string (consumer_names[count-no-1]);
+  }
+  g_free (nodes);
+  g_free (consumer_names);
+  return consumer;
+}
+
+static GeglNode *gegl_node_find_composite_target (GeglNode *node)
+{
+  const char *dest_pad = NULL;
+  GeglNode *iter = node;
+  iter = gegl_node_get_consumer_no (iter, "output", &dest_pad, 0);
+  while (iter && dest_pad && g_str_equal (dest_pad, "input"))
+  {
+    iter = gegl_node_get_consumer_no (iter, "output", &dest_pad, 0);
+  }
+  if (dest_pad && !strcmp (dest_pad, "aux"))
+  {
+    return gegl_node_get_producer (iter, "input", NULL);
+  }
+  return NULL;
+}
+
+static void
+create_matrix (OpTransform *op,
+               GeglMatrix3 *matrix)
+{
+  GeglOperation *operation = GEGL_OPERATION (op);
+  GeglProperties *o = GEGL_PROPERTIES (op);
+
+  gdouble x = 0.0;
+  gdouble y = 0.0;
+
+  GeglNode *border_node = gegl_operation_get_source_node (operation, "aux");
+  GeglNode *box_node    = gegl_operation_get_source_node (operation, "input");
+
+  GeglRectangle box_rect = {0,};
+  GeglRectangle border_rect = {0,};
+ 
+  if (box_node)
+    box_rect = gegl_node_get_bounding_box (box_node);
+
+  if (border_node)
+  {
+    border_rect = gegl_node_get_bounding_box (border_node);
+  }
+  else
+  {
+     border_node = gegl_node_find_composite_target (operation->node);
+     if (border_node)
+       border_rect = gegl_node_get_bounding_box (border_node);
+  }
+
+  x = o->x * (border_rect.width - box_rect.width - o->horizontal_margin * 2) +
+             o->horizontal_margin;
+  y = o->y * (border_rect.height - box_rect.height - o->vertical_margin * 2)+
+             o->vertical_margin;
+
+  if (o->snap_integer)
+  {
+    x = roundf (x);
+    y = roundf (y);
+  }
+
+  matrix->coeff [0][2] = x;
+  matrix->coeff [1][2] = y;
+}
+
+static void attach (GeglOperation *operation)
+{
+  GeglOperationComposerClass *klass = GEGL_OPERATION_COMPOSER_GET_CLASS (operation); 
+  GParamSpec    *pspec;
+  GeglOperationClass *parent_class = g_type_class_peek_parent (klass);
+
+  if (parent_class->attach)
+    parent_class->attach (operation);
+
+  pspec = g_param_spec_object ("aux",
+      klass->aux_label?klass->aux_label:"Aux",
+      klass->aux_description?klass->aux_description:_("Auxiliary image buffer input pad."),
+      GEGL_TYPE_BUFFER,
+      G_PARAM_READWRITE |
+      GEGL_PARAM_PAD_INPUT);
+  gegl_operation_create_pad (operation, pspec);
+  g_param_spec_sink (pspec);
+
+}
+
+static void
+gegl_op_class_init (GeglOpClass *klass)
+{
+  GeglOperationClass *operation_class;
+  OpTransformClass   *transform_class;
+
+  operation_class = GEGL_OPERATION_CLASS (klass);
+  transform_class = OP_TRANSFORM_CLASS (klass);
+
+  operation_class->attach = attach;
+  transform_class->create_matrix = create_matrix;
+
+  gegl_operation_class_set_keys (operation_class,
+    "name", "gegl:border-align",
+    "title", _("Border Align"),
+    "categories", "transform",
+    "description", _("Aligns box of input rectangle with border of compositing target or aux' bounding-box 
border, if aux pad is not connectd the op tries to figure out which bounding box' border applies."),
+    NULL);
+}
+
+#endif
diff --git a/operations/transform/meson.build b/operations/transform/meson.build
index 129882222..2ca378fea 100644
--- a/operations/transform/meson.build
+++ b/operations/transform/meson.build
@@ -1,5 +1,6 @@
 gegl_transformops_sources = files(
   'module.c',
+  'border-align.c',
   'reflect.c',
   'rotate-on-center.c',
   'rotate.c',
diff --git a/operations/transform/module.c b/operations/transform/module.c
index 9ec3ee277..4309767cb 100644
--- a/operations/transform/module.c
+++ b/operations/transform/module.c
@@ -39,6 +39,7 @@ gegl_module_query (GTypeModule *module)
   return &modinfo;
 }
 
+GType gegl_op_border_align_register_type          (GTypeModule *module);
 GType gegl_op_rotate_register_type                (GTypeModule *module);
 GType gegl_op_rotate_on_center_register_type      (GTypeModule *module);
 GType gegl_op_reflect_register_type               (GTypeModule *module);
@@ -58,6 +59,7 @@ gegl_module_register (GTypeModule *module)
   transform_module = module;
 
   dummy = op_transform_get_type ();
+  dummy = gegl_op_border_align_register_type (module);
   dummy = gegl_op_scale_ratio_register_type (module);
   dummy = gegl_op_scale_size_register_type (module);
   dummy = gegl_op_scale_size_keepaspect_register_type (module);
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 8806cb50f..525e4dca6 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -251,6 +251,7 @@ operations/generated/subtract.c
 operations/generated/xor.c
 operations/seamless-clone/seamless-clone.c
 operations/seamless-clone/seamless-clone-compose.c
+operations/transform/border-align.c
 operations/transform/reflect.c
 operations/transform/rotate.c
 operations/transform/rotate-on-center.c


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