[libcamera-devel,v2] libcamera: geometry: Add Size members to clamp to a min/max
diff mbox series

Message ID 20220412132614.317745-1-kieran.bingham@ideasonboard.com
State New
Delegated to: Kieran Bingham
Headers show
Series
  • [libcamera-devel,v2] libcamera: geometry: Add Size members to clamp to a min/max
Related show

Commit Message

Kieran Bingham April 12, 2022, 1:26 p.m. UTC
Provide two new operations to support clamping a Size to a given
minimum or maximum Size, or returning a const variant of the same
restriction.

Reviewed-by: Umang Jain <umang.jain@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
---
 include/libcamera/geometry.h | 16 ++++++++++++++++
 src/libcamera/geometry.cpp   | 23 +++++++++++++++++++++++
 test/geometry.cpp            | 24 ++++++++++++++++++++++--
 3 files changed, 61 insertions(+), 2 deletions(-)

Patch
diff mbox series

diff --git a/include/libcamera/geometry.h b/include/libcamera/geometry.h
index 7838b6793617..a447beb55965 100644
--- a/include/libcamera/geometry.h
+++ b/include/libcamera/geometry.h
@@ -93,6 +93,13 @@  public:
 		return *this;
 	}
 
+	Size &clamp(const Size &minimum, const Size &maximum)
+	{
+		width = std::clamp(width, minimum.width, maximum.width);
+		height = std::clamp(height, minimum.height, maximum.height);
+		return *this;
+	}
+
 	Size &growBy(const Size &margins)
 	{
 		width += margins.width;
@@ -141,6 +148,15 @@  public:
 		};
 	}
 
+	__nodiscard constexpr Size clampedTo(const Size &minimum,
+					     const Size &maximum) const
+	{
+		return {
+			std::clamp(width, minimum.width, maximum.width),
+			std::clamp(height, minimum.height, maximum.height)
+		};
+	}
+
 	__nodiscard constexpr Size grownBy(const Size &margins) const
 	{
 		return {
diff --git a/src/libcamera/geometry.cpp b/src/libcamera/geometry.cpp
index cb3c2de18d5e..6689b3996741 100644
--- a/src/libcamera/geometry.cpp
+++ b/src/libcamera/geometry.cpp
@@ -173,6 +173,19 @@  const std::string Size::toString() const
  * \return A reference to this object
  */
 
+/**
+ * \fn Size::clamp(const Size &minimum, const Size &maximum)
+ * \brief Clamp the size to be within the dimensions of both the \a minimum and
+ * \a maximum values.
+ * \param[in] minimum The minimum size
+ * \param[in] maximum The maximum size
+ *
+ * This function constrains and clamps the width and height of the size to be
+ * within the limits of the \a minimum and \a maximum sizes given.
+ *
+ * \return A reference to this object
+ */
+
 /**
  * \fn Size::growBy(const Size &margins)
  * \brief Grow the size by \a margins in place
@@ -231,6 +244,16 @@  const std::string Size::toString() const
  * height of this size and the \a expand size
  */
 
+/**
+ * \fn Size::clampedTo(const Size &minimum, const Size &maximum)
+ * \brief Clamp the size to be within the dimensions of both the \a minimum and
+ * \a maximum values
+ * \param[in] minimum The minimum size
+ * \param[in] maximum The maximum size
+ * \return A Size whose width and height are clamped to be within the limits of
+ * the \a minimum and \a maximum sizes given.
+ */
+
 /**
  * \fn Size::grownBy(const Size &margins)
  * \brief Grow the size by \a margins
diff --git a/test/geometry.cpp b/test/geometry.cpp
index 5125692496b3..8d29245b2568 100644
--- a/test/geometry.cpp
+++ b/test/geometry.cpp
@@ -106,7 +106,7 @@  protected:
 
 		/*
 		 * Test alignDownTo(), alignUpTo(), boundTo(), expandTo(),
-		 * growBy() and shrinkBy()
+		 * clamp(), growBy() and shrinkBy()
 		 */
 		Size s(50, 50);
 
@@ -134,6 +134,18 @@  protected:
 			return TestFail;
 		}
 
+		s.clamp({ 80, 120 }, { 160, 240 });
+		if (s != Size(80, 120)) {
+			cout << "Size::clamp (minium) test failed" << endl;
+			return TestFail;
+		}
+
+		s.clamp({ 20, 30 }, { 50, 50 });
+		if (s != Size(50, 50)) {
+			cout << "Size::clamp (maximum) test failed" << endl;
+			return TestFail;
+		}
+
 		s.growBy({ 10, 20 });
 		if (s != Size(60, 70)) {
 			cout << "Size::growBy() test failed" << endl;
@@ -162,7 +174,7 @@  protected:
 
 		/*
 		 * Test alignedDownTo(), alignedUpTo(), boundedTo(),
-		 * expandedTo(), grownBy() and shrunkBy()
+		 * expandedTo(), clampedTo(), grownBy() and shrunkBy()
 		 */
 		if (Size(0, 0).alignedDownTo(16, 8) != Size(0, 0) ||
 		    Size(1, 1).alignedDownTo(16, 8) != Size(0, 0) ||
@@ -192,6 +204,14 @@  protected:
 			return TestFail;
 		}
 
+		if (Size(0, 0).clampedTo({ 60, 40 }, { 80, 90 }) != Size(60, 40) ||
+		    Size(100, 100).clampedTo({ 60, 40 }, { 80, 90 }) != Size(80, 90) ||
+		    Size(30, 100).clampedTo({ 60, 40 }, { 80, 90 }) != Size(60, 90) ||
+		    Size(100, 30).clampedTo({ 60, 40 }, { 80, 90 }) != Size(80, 40)) {
+			cout << "Size::clampedTo() test failed" << endl;
+			return TestFail;
+		}
+
 		if (Size(0, 0).grownBy({ 10, 20 }) != Size(10, 20) ||
 		    Size(200, 50).grownBy({ 10, 20 }) != Size(210, 70)) {
 			cout << "Size::grownBy() test failed" << endl;