util: Add box util 73/281273/1
authorSeunghun <chwila927@gmail.com>
Tue, 23 Aug 2022 07:32:09 +0000 (16:32 +0900)
committerTizen Window System <tizen.windowsystem@gmail.com>
Thu, 15 Sep 2022 06:16:03 +0000 (15:16 +0900)
Change-Id: I759c39e0dedf218f63064cd7e479de996d058987

include/libds/util/box.h [new file with mode: 0644]
src/meson.build
src/util/box.c [new file with mode: 0644]

diff --git a/include/libds/util/box.h b/include/libds/util/box.h
new file mode 100644 (file)
index 0000000..3777ec0
--- /dev/null
@@ -0,0 +1,88 @@
+#ifndef LIBDS_UTIL_BOX_H
+#define LIBDS_UTIL_BOX_H
+
+#include <stdbool.h>
+#include <wayland-server.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * A box representing a rectangle region in a 2D space.
+ *
+ * The x and y coordinates are inclusive, and the width and height lengths are
+ * exclusive. In other words, the box starts from the coordinates (x, y), and
+ * goes up to but not including (x + width, y + height)
+ */
+struct ds_box {
+    int x, y;
+    int width, height;
+};
+
+/**
+ * A floating-point box representing a rectangle region in a 2D space.
+ *
+ * ds_fbox has the same semantics as ds_box
+ */
+struct ds_fbox {
+    double x, y;
+    double width, height;
+};
+
+/**
+ * Finds the closest point within the box bounds
+ *
+ * Returns false if the box is empty
+ */
+bool ds_box_closest_point(const struct ds_box *box, double x, double y,
+        double *dest_x, double *dest_y);
+
+/**
+ * Gives the intersecting box between two ds_box.
+ *
+ * Returns an empty ds_box if the provided ds_box don't intersect.
+ */
+bool ds_box_intersection(struct ds_box *dest, const struct ds_box *box_a,
+       const struct ds_box *box_b);
+
+/**
+ * Verifies if a point is contained within the bounds of a given ds_box.
+ *
+ * For example:
+ *   - A point at (100, 50) is not contained in the box (0, 0, 100, 50).
+ *   - A point at (10, 10) is contained in the box (10, 0, 50, 50).
+ */
+bool ds_box_contains_point(const struct ds_box *box, double x, double y);
+
+/**
+ * Checks whether a box is empty or not.
+ *
+ * A ds_box is considered empty if its width and/or height is zero or negative.
+ */
+bool ds_box_empty(const struct ds_box *box);
+
+/**
+ * Transforms a box inside a (0, 0, width, height) box.
+ */
+void ds_box_transform(struct ds_box *dest, const struct ds_box *box,
+       enum wl_output_transform transform, int width, int height);
+
+/**
+ * Checks whether a box is empty or not.
+ *
+ * A ds_box is considered empty if its width and/or height is zero or negative.
+ */
+bool ds_fbox_empty(const struct ds_fbox *box);
+
+/**
+ * Transforms a floating-point box inside a (0, 0, width, height) box.
+ */
+void ds_fbox_transform(struct ds_fbox *dest, const struct ds_fbox *box,
+       enum wl_output_transform transform, double width, double height);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
index 55a0263..7b962a2 100644 (file)
@@ -10,6 +10,7 @@ libds_files = [
   'region.c',
   'util/time.c',
   'util/shm.c',
+  'util/box.c',
   'surface/surface.c',
   'surface/subsurface.c',
   'client_buffer/shm_client_buffer.c',
diff --git a/src/util/box.c b/src/util/box.c
new file mode 100644 (file)
index 0000000..b47041d
--- /dev/null
@@ -0,0 +1,180 @@
+#include "libds/util/box.h"
+
+WL_EXPORT bool
+ds_box_closest_point(const struct ds_box *box, double x, double y,
+               double *dest_x, double *dest_y)
+{
+       // if box is empty, then it contains no points, so no closest point either
+       if (box->width <= 0 || box->height <= 0)
+               return false;
+
+       // find the closest x point
+       if (x < box->x) {
+               *dest_x = box->x;
+       } else if (x >= box->x + box->width) {
+               *dest_x = box->x + box->width - 1;
+       } else {
+               *dest_x = x;
+       }
+
+       // find closest y point
+       if (y < box->y) {
+               *dest_y = box->y;
+       } else if (y >= box->y + box->height) {
+               *dest_y = box->y + box->height - 1;
+       } else {
+               *dest_y = y;
+       }
+
+    return true;
+}
+
+WL_EXPORT bool
+ds_box_empty(const struct ds_box *box)
+{
+       return box == NULL || box->width <= 0 || box->height <= 0;
+}
+
+WL_EXPORT bool
+ds_box_intersection(struct ds_box *dest,
+        const struct ds_box *box_a, const struct ds_box *box_b)
+{
+       bool a_empty = ds_box_empty(box_a);
+       bool b_empty = ds_box_empty(box_b);
+
+       if (a_empty || b_empty) {
+               dest->x = 0;
+               dest->y = 0;
+               dest->width = -100;
+               dest->height = -100;
+               return false;
+       }
+
+       int x1 = fmax(box_a->x, box_b->x);
+       int y1 = fmax(box_a->y, box_b->y);
+       int x2 = fmin(box_a->x + box_a->width, box_b->x + box_b->width);
+       int y2 = fmin(box_a->y + box_a->height, box_b->y + box_b->height);
+
+       dest->x = x1;
+       dest->y = y1;
+       dest->width = x2 - x1;
+       dest->height = y2 - y1;
+
+       return !ds_box_empty(dest);
+}
+
+WL_EXPORT bool
+ds_box_contains_point(const struct ds_box *box, double x, double y)
+{
+       if (ds_box_empty(box)) {
+               return false;
+       } else {
+               return x >= box->x && x < box->x + box->width &&
+                       y >= box->y && y < box->y + box->height;
+       }
+}
+
+WL_EXPORT void
+ds_box_transform(struct ds_box *dest, const struct ds_box *box,
+               enum wl_output_transform transform, int width, int height) {
+       struct ds_box src = *box;
+
+       if (transform % 2 == 0) {
+               dest->width = src.width;
+               dest->height = src.height;
+       } else {
+               dest->width = src.height;
+               dest->height = src.width;
+       }
+
+       switch (transform) {
+       case WL_OUTPUT_TRANSFORM_NORMAL:
+               dest->x = src.x;
+               dest->y = src.y;
+               break;
+       case WL_OUTPUT_TRANSFORM_90:
+               dest->x = height - src.y - src.height;
+               dest->y = src.x;
+               break;
+       case WL_OUTPUT_TRANSFORM_180:
+               dest->x = width - src.x - src.width;
+               dest->y = height - src.y - src.height;
+               break;
+       case WL_OUTPUT_TRANSFORM_270:
+               dest->x = src.y;
+               dest->y = width - src.x - src.width;
+               break;
+       case WL_OUTPUT_TRANSFORM_FLIPPED:
+               dest->x = width - src.x - src.width;
+               dest->y = src.y;
+               break;
+       case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+               dest->x = src.y;
+               dest->y = src.x;
+               break;
+       case WL_OUTPUT_TRANSFORM_FLIPPED_180:
+               dest->x = src.x;
+               dest->y = height - src.y - src.height;
+               break;
+       case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+               dest->x = height - src.y - src.height;
+               dest->y = width - src.x - src.width;
+               break;
+       }
+}
+
+WL_EXPORT bool
+ds_fbox_empty(const struct ds_fbox *box)
+{
+       return box == NULL || box->width <= 0 || box->height <= 0;
+}
+
+WL_EXPORT void
+ds_fbox_transform(struct ds_fbox *dest, const struct ds_fbox *box,
+               enum wl_output_transform transform, double width, double height)
+{
+       struct ds_fbox src = *box;
+
+       if (transform % 2 == 0) {
+               dest->width = src.width;
+               dest->height = src.height;
+       } else {
+               dest->width = src.height;
+               dest->height = src.width;
+       }
+
+       switch (transform) {
+       case WL_OUTPUT_TRANSFORM_NORMAL:
+               dest->x = src.x;
+               dest->y = src.y;
+               break;
+       case WL_OUTPUT_TRANSFORM_90:
+               dest->x = height - src.y - src.height;
+               dest->y = src.x;
+               break;
+       case WL_OUTPUT_TRANSFORM_180:
+               dest->x = width - src.x - src.width;
+               dest->y = height - src.y - src.height;
+               break;
+       case WL_OUTPUT_TRANSFORM_270:
+               dest->x = src.y;
+               dest->y = width - src.x - src.width;
+               break;
+       case WL_OUTPUT_TRANSFORM_FLIPPED:
+               dest->x = width - src.x - src.width;
+               dest->y = src.y;
+               break;
+       case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+               dest->x = src.y;
+               dest->y = src.x;
+               break;
+       case WL_OUTPUT_TRANSFORM_FLIPPED_180:
+               dest->x = src.x;
+               dest->y = height - src.y - src.height;
+               break;
+       case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+               dest->x = height - src.y - src.height;
+               dest->y = width - src.x - src.width;
+               break;
+       }
+}