@@ -13,6 +13,8 @@
namespace libcamera {
+class Rectangle;
+
class Size
{
public:
@@ -93,8 +95,17 @@ public:
std::max(height, expand.height)
};
}
+
+ Size alignedDownToAspectRatio(const Size &ratio) const;
+ Size alignedUpToAspectRatio(const Size &ratio) const;
+
+ Rectangle centredTo(const Rectangle ®ion,
+ int offsetX = 0, int offsetY = 0) const;
};
+Size operator*(const Size &size, float f);
+Size operator/(const Size &size, float f);
+
bool operator==(const Size &lhs, const Size &rhs);
bool operator<(const Size &lhs, const Size &rhs);
@@ -176,6 +187,11 @@ public:
{
}
+ constexpr explicit Rectangle(const Size &size)
+ : x(0), y(0), width(size.width), height(size.height)
+ {
+ }
+
int x;
int y;
unsigned int width;
@@ -183,6 +199,10 @@ public:
bool isNull() const { return !width && !height; }
const std::string toString() const;
+
+ Size size() const;
+
+ Rectangle boundedTo(const Rectangle &boundary) const;
};
bool operator==(const Rectangle &lhs, const Rectangle &rhs);
@@ -143,6 +143,88 @@ const std::string Size::toString() const
* height of this size and the \a expand size
*/
+/**
+ * \brief Align down to the aspect ratio given by \a ratio
+ * \param[in] ratio The size whose aspect ratio to align down to
+ * \return A Size whose width and height are equal to the width and height
+ * of this Size aligned down to the aspect ratio of \a ratio
+ */
+Size Size::alignedDownToAspectRatio(const Size &ratio) const
+{
+ uint64_t ratio1 = static_cast<uint64_t>(width) *
+ static_cast<uint64_t>(ratio.height);
+ uint64_t ratio2 = static_cast<uint64_t>(ratio.width) *
+ static_cast<uint64_t>(height);
+
+ if (ratio1 > ratio2)
+ return { static_cast<unsigned int>(ratio2 / ratio.height), height };
+ else
+ return { width, static_cast<unsigned int>(ratio1 / ratio.width) };
+}
+
+/**
+ * \brief Align up to the aspect ratio given by \a ratio
+ * \param[in] ratio The size whose aspect ratio to align up to
+ * \return A Size whose width and height are equal to the width and height
+ * of this Size aligned up to the aspect ratio of \a ratio
+ */
+Size Size::alignedUpToAspectRatio(const Size &ratio) const
+{
+ uint64_t ratio1 = static_cast<uint64_t>(width) *
+ static_cast<uint64_t>(ratio.height);
+ uint64_t ratio2 = static_cast<uint64_t>(ratio.width) *
+ static_cast<uint64_t>(height);
+
+ if (ratio1 < ratio2)
+ return { static_cast<unsigned int>(ratio2 / ratio.height), height };
+ else
+ return { width, static_cast<unsigned int>(ratio1 / ratio.width) };
+}
+
+/**
+ * \brief Centre a rectangle of this size within another rectangular region,
+ * with optional offsets
+ * \param[in] region The rectangular region relative to which the returned
+ * rectangle can be position
+ * \param[in] offsetX The X offset of the mid-point of the returned rectangle
+ * relative to the mid-point of the region
+ * \param[in] offsetY The Y offset of the mid-point of the returned rectangle
+ * relative to the mid-point of the region
+ *
+ * A Rectangle of this object's size is positioned within the Rectangle
+ * given by \a region. It is positioned so that its mid-point coincides
+ * with the mid-point of \a region, and is then further offset by the
+ * values \a offsetX and \a offsetY.
+ *
+ * \return A Rectangle with the horizontal and vertical sizes of
+ * this Size instance, centred with offsets within a region
+ */
+Rectangle Size::centredTo(const Rectangle ®ion, int offsetX, int offsetY) const
+{
+ int x = (region.width - width) / 2 + region.x + offsetX;
+ int y = (region.height - height) / 2 + region.y + offsetY;
+
+ return Rectangle(x, y, width, height);
+}
+
+/**
+ * \brief Scale size up by the given factor
+ * \return The scaled Size
+ */
+Size operator*(const Size &size, float f)
+{
+ return Size(size.width * f, size.height * f);
+}
+
+/**
+ * \brief Scale size down by the given factor
+ * \return The scaled Size
+ */
+Size operator/(const Size &size, float f)
+{
+ return Size(size.width / f, size.height / f);
+}
+
/**
* \brief Compare sizes for equality
* \return True if the two sizes are equal, false otherwise
@@ -365,6 +447,12 @@ bool operator==(const SizeRange &lhs, const SizeRange &rhs)
* \param[in] height The height
*/
+/**
+ * \fn Rectangle::Rectangle(const Size &size)
+ * \brief Construct a Rectangle with zero offsets and the given \a size
+ * \param[in] size The desired Rectangle size
+ */
+
/**
* \var Rectangle::x
* \brief The horizontal coordinate of the rectangle's top-left corner
@@ -404,6 +492,47 @@ const std::string Rectangle::toString() const
return ss.str();
}
+/**
+ * \brief Retrieve the size of this rectangle
+ * \return A Size reporting the Rectangle horizontal and vertical sizes
+ */
+Size Rectangle::size() const
+{
+ return Size(width, height);
+}
+
+/**
+ * \brief Bound a Rectangle so as not to exceeed another Rectangle
+ * \param[in] boundary The limit that the returned Rectangle will not exceed
+ *
+ * The Rectangle is bounded so that it does not exceeed the given \a boundary.
+ * This process involves translating the Rectangle if any of its edges
+ * lie beyond \a boundary, so that those edges then lie along the boundary
+ * instead.
+ *
+ * If either width or height are larger than \a bounary, then the returned
+ * Rectangle is clipped to be no larger. But other than this, the
+ * Rectangle is not clipped or reduced in size, merely translated.
+ *
+ * We note that this is not a conventional Rectangle intersection function.
+ *
+ * \return A Rectangle that does not extend beyond a boundary Rectangle
+ */
+Rectangle Rectangle::boundedTo(const Rectangle &boundary) const
+{
+ Rectangle result(*this);
+
+ result.width = std::min(result.width, boundary.width);
+ result.x = std::clamp<int>(result.x, boundary.x,
+ boundary.x + boundary.width - result.width);
+
+ result.height = std::min(result.height, boundary.height);
+ result.y = std::clamp<int>(result.y, boundary.y,
+ boundary.y + boundary.height - result.height);
+
+ return result;
+}
+
/**
* \brief Compare rectangles for equality
* \return True if the two rectangles are equal, false otherwise