[gegl] buffer: add gegl_rectangle_align[_to_buffer]()



commit 8776cd17e49071fdc01d3ddcb874bb023dd93e1f
Author: Ell <ell_se yahoo com>
Date:   Mon Jul 29 22:16:13 2019 +0300

    buffer: add gegl_rectangle_align[_to_buffer]()
    
    ... which align a rectangle to a regular tile grid, specified
    either using a representative tile rect, or using a GeglBuffer.
    The result can be either the biggest aligned subset of, the
    smallest aligned superset of, or the nearest aligned rectangle to
    the input.

 gegl/buffer/gegl-buffer-enums.c | 26 +++++++++++
 gegl/buffer/gegl-buffer-enums.h | 10 +++++
 gegl/buffer/gegl-rectangle.c    | 97 +++++++++++++++++++++++++++++++++++++++++
 gegl/buffer/gegl-rectangle.h    | 51 ++++++++++++++++++++++
 4 files changed, 184 insertions(+)
---
diff --git a/gegl/buffer/gegl-buffer-enums.c b/gegl/buffer/gegl-buffer-enums.c
index 1dfcbf6f3..9b3113758 100644
--- a/gegl/buffer/gegl-buffer-enums.c
+++ b/gegl/buffer/gegl-buffer-enums.c
@@ -105,3 +105,29 @@ gegl_sampler_type_get_type (void)
 
   return etype;
 }
+
+GType
+gegl_rectangle_alignment_get_type (void)
+{
+  static GType etype = 0;
+
+  if (etype == 0)
+    {
+      static GEnumValue values[] = {
+        { GEGL_RECTANGLE_ALIGNMENT_SUBSET,   N_("Subset"),   "subset"   },
+        { GEGL_RECTANGLE_ALIGNMENT_SUPERSET, N_("Superset"), "superset" },
+        { GEGL_RECTANGLE_ALIGNMENT_NEAREST,  N_("Nesrest"),  "nesrest"  },
+        { 0, NULL, NULL }
+      };
+      gint i;
+
+      for (i = 0; i < G_N_ELEMENTS (values); i++)
+        if (values[i].value_name)
+          values[i].value_name =
+            dgettext (GETTEXT_PACKAGE, values[i].value_name);
+
+      etype = g_enum_register_static ("GeglRectangleAlignment", values);
+    }
+
+  return etype;
+}
diff --git a/gegl/buffer/gegl-buffer-enums.h b/gegl/buffer/gegl-buffer-enums.h
index aa110c6dd..0f756dc6a 100644
--- a/gegl/buffer/gegl-buffer-enums.h
+++ b/gegl/buffer/gegl-buffer-enums.h
@@ -87,6 +87,16 @@ GType gegl_sampler_type_get_type (void) G_GNUC_CONST;
 
 #define GEGL_TYPE_SAMPLER_TYPE (gegl_sampler_type_get_type ())
 
+typedef enum {
+  GEGL_RECTANGLE_ALIGNMENT_SUBSET,
+  GEGL_RECTANGLE_ALIGNMENT_SUPERSET,
+  GEGL_RECTANGLE_ALIGNMENT_NEAREST
+} GeglRectangleAlignment;
+
+GType gegl_rectangle_alignment_get_type (void) G_GNUC_CONST;
+
+#define GEGL_TYPE_RECTANGLE_ALIGNMENT (gegl_rectangle_alignment_get_type ())
+
 G_END_DECLS
 
 #endif /* __GEGL_ENUMS_H__ */
diff --git a/gegl/buffer/gegl-rectangle.c b/gegl/buffer/gegl-rectangle.c
index dde4c8fc5..99e69da3e 100644
--- a/gegl/buffer/gegl-rectangle.c
+++ b/gegl/buffer/gegl-rectangle.c
@@ -21,6 +21,7 @@
 #include <string.h>
 #include <glib-object.h>
 #include "gegl-buffer.h"
+#include "gegl-buffer-private.h"
 #include "gegl-rectangle.h"
 
 GeglRectangle *
@@ -52,6 +53,102 @@ gegl_rectangle_set (GeglRectangle *r,
   r->height = h;
 }
 
+gboolean
+gegl_rectangle_align (GeglRectangle          *dest,
+                      const GeglRectangle    *rectangle,
+                      const GeglRectangle    *tile,
+                      GeglRectangleAlignment  alignment)
+{
+  gint x1, x2;
+  gint y1, y2;
+
+  x1 = rectangle->x - tile->x;
+  x2 = x1 + rectangle->width;
+
+  y1 = rectangle->y - tile->y;
+  y2 = y1 + rectangle->height;
+
+  switch (alignment)
+    {
+    case GEGL_RECTANGLE_ALIGNMENT_SUBSET:
+      if (x1 > 0) x1 += tile->width  - 1;
+      if (x2 < 0) x2 -= tile->width  - 1;
+
+      if (y1 > 0) y1 += tile->height - 1;
+      if (y2 < 0) y2 -= tile->height - 1;
+
+      break;
+
+    case GEGL_RECTANGLE_ALIGNMENT_SUPERSET:
+      if (x1 < 0) x1 -= tile->width  - 1;
+      if (x2 > 0) x2 += tile->width  - 1;
+
+      if (y1 < 0) y1 -= tile->height - 1;
+      if (y2 > 0) y2 += tile->height - 1;
+
+      break;
+
+    case GEGL_RECTANGLE_ALIGNMENT_NEAREST:
+      if (x1 > 0) x1 += tile->width  / 2;
+      else        x1 -= tile->width  / 2;
+      if (x2 > 0) x2 += tile->width  / 2;
+      else        x2 -= tile->width  / 2;
+
+      if (y1 > 0) y1 += tile->height / 2;
+      else        y1 -= tile->height / 2;
+      if (y2 > 0) y2 += tile->height / 2;
+      else        y2 -= tile->height / 2;
+
+      break;
+    }
+
+  if (tile->width)
+    {
+      x1 = x1 / tile->width  * tile->width;
+      x2 = x2 / tile->width  * tile->width;
+    }
+  if (tile->height)
+    {
+      y1 = y1 / tile->height * tile->height;
+      y2 = y2 / tile->height * tile->height;
+    }
+
+  if (x1 > x2 && y1 > y2)
+    {
+      if (dest)
+        {
+          gegl_rectangle_set (dest,
+                              tile->x + x1,
+                              tile->y + y1,
+                              x2 - x1,
+                              y2 - y1);
+        }
+
+      return TRUE;
+    }
+  else
+    {
+      if (dest)
+        gegl_rectangle_set (dest, 0, 0, 0, 0);
+
+      return FALSE;
+    }
+}
+
+gboolean
+gegl_rectangle_align_to_buffer (GeglRectangle          *dest,
+                                const GeglRectangle    *rectangle,
+                                GeglBuffer             *buffer,
+                                GeglRectangleAlignment  alignment)
+{
+  return gegl_rectangle_align (dest, rectangle,
+                               GEGL_RECTANGLE (buffer->shift_x,
+                                               buffer->shift_y,
+                                               buffer->tile_width,
+                                               buffer->tile_height),
+                               alignment);
+}
+
 void
 gegl_rectangle_bounding_box (GeglRectangle       *dest,
                              const GeglRectangle *src1,
diff --git a/gegl/buffer/gegl-rectangle.h b/gegl/buffer/gegl-rectangle.h
index 36174cba7..7e164c1c9 100644
--- a/gegl/buffer/gegl-rectangle.h
+++ b/gegl/buffer/gegl-rectangle.h
@@ -156,6 +156,57 @@ GeglRectangle *gegl_rectangle_dup       (const GeglRectangle *rectangle);
 void        gegl_rectangle_copy          (GeglRectangle       *destination,
                                           const GeglRectangle *source);
 
+/**
+ * gegl_rectangle_align:
+ * @destination: a #GeglRectangle
+ * @rectangle: a #GeglRectangle
+ * @tile: a #GeglRectangle
+ * @alignment: a #GeglRectangleAlignment value
+ *
+ * Aligns @rectangle to a regular tile grid, of which @tile is a representative
+ * tile, and stores the result in @destination.
+ *
+ * @alignment can be one of:
+ *
+ *   GEGL_RECTANGLE_ALIGNMENT_SUBSET:  Calculate the biggest aligned rectangle
+ *   contained in @rectangle.
+ *
+ *   GEGL_RECTANGLE_ALIGNMENT_SUPERSET:  Calculate the smallest aligned
+ *   rectangle containing @rectangle.
+ *
+ *   GEGL_RECTANGLE_ALIGNMENT_NEAREST:  Calculate the nearest aligned rectangle
+ *   to @rectangle.
+ *
+ * @destination may point to the same object as @rectangle or @tile.
+ *
+ * Returns TRUE if the result is not empty.
+ */
+gboolean    gegl_rectangle_align         (GeglRectangle          *destination,
+                                          const GeglRectangle    *rectangle,
+                                          const GeglRectangle    *tile,
+                                          GeglRectangleAlignment  alignment);
+
+/**
+ * gegl_rectangle_align_to_buffer:
+ * @destination: a #GeglRectangle
+ * @rectangle: a #GeglRectangle
+ * @buffer: a #GeglBuffer
+ * @alignment: a #GeglRectangleAlignment value
+ *
+ * Aligns @rectangle to the tile grid of @buffer, and stores the result in
+ * @destination.
+ *
+ * @alignment has the same meaning as for gegl_rectangle_align().
+ *
+ * @destination may point to the same object as @rectangle.
+ *
+ * Returns TRUE if the result is not empty.
+ */
+gboolean  gegl_rectangle_align_to_buffer (GeglRectangle          *destination,
+                                          const GeglRectangle    *rectangle,
+                                          GeglBuffer             *buffer,
+                                          GeglRectangleAlignment  alignment);
+
 /**
  * gegl_rectangle_bounding_box:
  * @destination: a #GeglRectangle


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