Patch Detail
Show a patch.
GET /api/patches/10259/?format=api
{ "id": 10259, "url": "https://patchwork.libcamera.org/api/patches/10259/?format=api", "web_url": "https://patchwork.libcamera.org/patch/10259/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/projects/1/?format=api", "name": "libcamera", "link_name": "libcamera", "list_id": "libcamera_core", "list_email": "libcamera-devel@lists.libcamera.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20201026171908.21463-5-david.plowman@raspberrypi.com>", "date": "2020-10-26T17:19:06", "name": "[libcamera-devel,v6,4/6] libcamera: Add geometry helper functions", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "9e94aafe14da917d1a1059423aaba0be61b620c1", "submitter": { "id": 42, "url": "https://patchwork.libcamera.org/api/people/42/?format=api", "name": "David Plowman", "email": "david.plowman@raspberrypi.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/10259/mbox/", "series": [ { "id": 1417, "url": "https://patchwork.libcamera.org/api/series/1417/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=1417", "date": "2020-10-26T17:19:02", "name": "Digital zoom", "version": 6, "mbox": "https://patchwork.libcamera.org/series/1417/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/10259/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/10259/checks/", "tags": {}, "headers": { "Return-Path": "<libcamera-devel-bounces@lists.libcamera.org>", "X-Original-To": "parsemail@patchwork.libcamera.org", "Delivered-To": "parsemail@patchwork.libcamera.org", "Received": [ "from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 3A988BDB13\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 26 Oct 2020 17:19:22 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 090B56204A;\n\tMon, 26 Oct 2020 18:19:22 +0100 (CET)", "from mail-wr1-x431.google.com (mail-wr1-x431.google.com\n\t[IPv6:2a00:1450:4864:20::431])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id A735E62037\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 26 Oct 2020 18:19:19 +0100 (CET)", "by mail-wr1-x431.google.com with SMTP id n15so13594150wrq.2\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 26 Oct 2020 10:19:19 -0700 (PDT)", "from pi4-davidp.lan (plowpeople3.plus.com. [80.229.223.72])\n\tby smtp.gmail.com with ESMTPSA id\n\to63sm20955295wmo.2.2020.10.26.10.19.18\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tMon, 26 Oct 2020 10:19:18 -0700 (PDT)" ], "Authentication-Results": "lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=raspberrypi.com header.i=@raspberrypi.com\n\theader.b=\"eIvjs6xB\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references\n\t:mime-version:content-transfer-encoding;\n\tbh=+mUU3LGIBJG/X8d7IBu44bzlYXP7jfilBN5urrKRpgI=;\n\tb=eIvjs6xBcCO8OkdTS3dpaMOCeuUoOPAZEEW1P6WlDkfETHgPxSu69zm6J1VKFYKDdG\n\tyVWKoOrCK36mltiXsHMJz1FQUX3fgGpWjVyrn7mCLXbyvJ+L0ZQaxnLj4c2xaNMVdVUU\n\t6llATlDB/GhYlicnRkn2UnbVQNs3gYDMmifZkE60+yKxnznHZS/uPMsRTyppx7CVMq5X\n\tjHUene/neXcsYBujh2qx18Q4XpXNNkBvSTkq6SIzblqwSInxZ+DGEycCv4WVk65kImoM\n\tOuiWyEgCKavuqqnQ1RZfL0omR1Zh9Q/rekuVunUsZSxE43uWshtRo5l7BlkOb5QdgzY+\n\tAZrA==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references:mime-version:content-transfer-encoding;\n\tbh=+mUU3LGIBJG/X8d7IBu44bzlYXP7jfilBN5urrKRpgI=;\n\tb=S8jC6CYvoo7IhR43x0QQSOZO/OTHMOAqCJf8wA+RviqlNVP8zget8hX78A2wZkSBGH\n\tuyzV8bnELntxPVBY/jNcjE3nqpPqNQVjWCYI5NlIh9Hz/t74DKzYJ4TeCPMzQgIGK+An\n\tU4PWmc5VsIItljyEhqM3OZXGPHTAcL5IQQ/j5PO6ECWZ2ew4g0ZnKPRNOOg+Wz21vvsx\n\t5Vw23sEmvHnKZH/6iR6M/O9znxgQHZ/3AHqZ50o9edoHxgitdDA6qUnPgl3SFLSiqEfs\n\tjaUCKG4R/IikF9C1XT9nX2p8yl7aItjbyZ7Lu+nHM2ezcJ0ZqlBwWto0wHZ+GO+M6z1H\n\tuM5g==", "X-Gm-Message-State": "AOAM532XxbRMjQ8MH+L71Y1HV1DX5ZyyrLw3JCCldPNNM/8qr32/mQqh\n\tyrcoulHU9x8l0yPC/bctB+BBguSK/0VuAg==", "X-Google-Smtp-Source": "ABdhPJw0F4RakDYwAJsu39bAbz9KsTwAWczm6ztdXFLmkig0jatZDuZqTbjp6DWc0XYj50IRu4u3WA==", "X-Received": "by 2002:a5d:4b49:: with SMTP id w9mr20040710wrs.41.1603732758869;\n\tMon, 26 Oct 2020 10:19:18 -0700 (PDT)", "From": "David Plowman <david.plowman@raspberrypi.com>", "To": "libcamera-devel@lists.libcamera.org", "Date": "Mon, 26 Oct 2020 17:19:06 +0000", "Message-Id": "<20201026171908.21463-5-david.plowman@raspberrypi.com>", "X-Mailer": "git-send-email 2.20.1", "In-Reply-To": "<20201026171908.21463-1-david.plowman@raspberrypi.com>", "References": "<20201026171908.21463-1-david.plowman@raspberrypi.com>", "MIME-Version": "1.0", "Subject": "[libcamera-devel] [PATCH v6 4/6] libcamera: Add geometry helper\n\tfunctions", "X-BeenThere": "libcamera-devel@lists.libcamera.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "<libcamera-devel.lists.libcamera.org>", "List-Unsubscribe": "<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>", "List-Archive": "<https://lists.libcamera.org/pipermail/libcamera-devel/>", "List-Post": "<mailto:libcamera-devel@lists.libcamera.org>", "List-Help": "<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>", "List-Subscribe": "<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>", "Content-Type": "text/plain; charset=\"us-ascii\"", "Content-Transfer-Encoding": "7bit", "Errors-To": "libcamera-devel-bounces@lists.libcamera.org", "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>" }, "content": "These functions are aimed at making it easier to calculate cropping\nrectangles, particularly in order to implement digital zoom.\n\nSigned-off-by: David Plowman <david.plowman@raspberrypi.com>\nReviewed-by: Jacopo Mondi <jacopo@jmondi.org>\n---\n include/libcamera/geometry.h | 67 +++++++\n src/libcamera/geometry.cpp | 328 +++++++++++++++++++++++++++++++++++\n 2 files changed, 395 insertions(+)", "diff": "diff --git a/include/libcamera/geometry.h b/include/libcamera/geometry.h\nindex 02fb63c0..ca5687a7 100644\n--- a/include/libcamera/geometry.h\n+++ b/include/libcamera/geometry.h\n@@ -13,6 +13,38 @@\n \n namespace libcamera {\n \n+class Rectangle;\n+\n+class Point\n+{\n+public:\n+\tconstexpr Point()\n+\t\t: x(0), y(0)\n+\t{\n+\t}\n+\n+\tconstexpr Point(int xpos, int ypos)\n+\t\t: x(xpos), y(ypos)\n+\t{\n+\t}\n+\n+\tint x;\n+\tint y;\n+\n+\tconst std::string toString() const;\n+\n+\tconstexpr Point operator-() const\n+\t{\n+\t\treturn { -x, -y };\n+\t}\n+};\n+\n+bool operator==(const Point &lhs, const Point &rhs);\n+static inline bool operator!=(const Point &lhs, const Point &rhs)\n+{\n+\treturn !(lhs == rhs);\n+}\n+\n class Size\n {\n public:\n@@ -93,6 +125,17 @@ public:\n \t\t\tstd::max(height, expand.height)\n \t\t};\n \t}\n+\n+\tSize boundedToAspectRatio(const Size &ratio) const;\n+\tSize expandedToAspectRatio(const Size &ratio) const;\n+\n+\tRectangle centeredTo(const Point ¢er) const;\n+\n+\tSize operator*(float factor) const;\n+\tSize operator/(float factor) const;\n+\n+\tSize &operator*=(float factor);\n+\tSize &operator/=(float factor);\n };\n \n bool operator==(const Size &lhs, const Size &rhs);\n@@ -176,6 +219,11 @@ public:\n \t{\n \t}\n \n+\tconstexpr explicit Rectangle(const Size &size)\n+\t\t: x(0), y(0), width(size.width), height(size.height)\n+\t{\n+\t}\n+\n \tint x;\n \tint y;\n \tunsigned int width;\n@@ -183,6 +231,25 @@ public:\n \n \tbool isNull() const { return !width && !height; }\n \tconst std::string toString() const;\n+\tPoint center() const;\n+\n+\tSize size() const\n+\t{\n+\t\treturn { width, height };\n+\t}\n+\n+\tPoint topLeft() const\n+\t{\n+\t\treturn { x, y };\n+\t}\n+\n+\tRectangle &scaleBy(const Size &numerator, const Size &denominator);\n+\tRectangle &translateBy(const Point &point);\n+\n+\tRectangle boundedTo(const Rectangle &bound) const;\n+\tRectangle enclosedIn(const Rectangle &boundary) const;\n+\tRectangle scaledBy(const Size &numerator, const Size &denominator) const;\n+\tRectangle translatedBy(const Point &point) const;\n };\n \n bool operator==(const Rectangle &lhs, const Rectangle &rhs);\ndiff --git a/src/libcamera/geometry.cpp b/src/libcamera/geometry.cpp\nindex b12e1a62..438bf90b 100644\n--- a/src/libcamera/geometry.cpp\n+++ b/src/libcamera/geometry.cpp\n@@ -10,6 +10,8 @@\n #include <sstream>\n #include <stdint.h>\n \n+#include \"libcamera/internal/log.h\"\n+\n /**\n * \\file geometry.h\n * \\brief Data structures related to geometric objects\n@@ -17,6 +19,64 @@\n \n namespace libcamera {\n \n+/**\n+ * \\class Point\n+ * \\brief Describe a point in two-dimensional space\n+ *\n+ * The Point structure defines a point in two-dimensional space with integer\n+ * precision. The coordinates of a Point may be negative as well as positive.\n+ */\n+\n+/**\n+ * \\fn Point::Point()\n+ * \\brief Construct a Point with x and y set to 0\n+ */\n+\n+/**\n+ * \\fn Point::Point(int xpos, int ypos)\n+ * \\brief Construct a Point at given \\a xpos and \\a ypos values\n+ * \\param[in] xpos The x-coordinate\n+ * \\param[in] ypos The y-coordinate\n+ */\n+\n+/**\n+ * \\var Point::x\n+ * \\brief The x-coordinate of the Point\n+ */\n+\n+/**\n+ * \\var Point::y\n+ * \\brief The y-coordinate of the Point\n+ */\n+\n+/**\n+ * \\brief Assemble and return a string describing the point\n+ * \\return A string describing the point\n+ */\n+const std::string Point::toString() const\n+{\n+\tstd::stringstream ss;\n+\n+\tss << \"(\" << x << \",\" << y << \")\";\n+\n+\treturn ss.str();\n+}\n+\n+/**\n+ * \\fn Point Point::operator-() const\n+ * \\brief Negate a Point by negating both its x and y coordinates\n+ * \\return The negated point\n+ */\n+\n+/**\n+ * \\brief Compare points for equality\n+ * \\return True if the two points are equal, false otherwise\n+ */\n+bool operator==(const Point &lhs, const Point &rhs)\n+{\n+\treturn lhs.x == rhs.x && lhs.y == rhs.y;\n+}\n+\n /**\n * \\struct Size\n * \\brief Describe a two-dimensional size\n@@ -143,6 +203,117 @@ const std::string Size::toString() const\n * height of this size and the \\a expand size\n */\n \n+/**\n+ * \\brief Bound the size down to match the aspect ratio given by \\a ratio\n+ * \\param[in] ratio The size whose aspect ratio must be matched\n+ *\n+ * The behaviour of this function is undefined if either the width or the\n+ * height of the \\a ratio is zero.\n+ *\n+ * \\return A Size whose width and height are equal to the width and height\n+ * of this Size aligned down to the aspect ratio of \\a ratio\n+ */\n+Size Size::boundedToAspectRatio(const Size &ratio) const\n+{\n+\tASSERT(ratio.width && ratio.height);\n+\n+\tuint64_t ratio1 = static_cast<uint64_t>(width) *\n+\t\t\t static_cast<uint64_t>(ratio.height);\n+\tuint64_t ratio2 = static_cast<uint64_t>(ratio.width) *\n+\t\t\t static_cast<uint64_t>(height);\n+\n+\tif (ratio1 > ratio2)\n+\t\treturn { static_cast<unsigned int>(ratio2 / ratio.height), height };\n+\telse\n+\t\treturn { width, static_cast<unsigned int>(ratio1 / ratio.width) };\n+}\n+\n+/**\n+ * \\brief Expand the size to match the aspect ratio given by \\a ratio\n+ * \\param[in] ratio The size whose aspect ratio must be matched\n+ *\n+ * The behaviour of this function is undefined if either the width or the\n+ * height of the \\a ratio is zero.\n+ *\n+ * \\return A Size whose width and height are equal to the width and height\n+ * of this Size expanded up to the aspect ratio of \\a ratio\n+ */\n+Size Size::expandedToAspectRatio(const Size &ratio) const\n+{\n+\tASSERT(ratio.width && ratio.height);\n+\n+\tuint64_t ratio1 = static_cast<uint64_t>(width) *\n+\t\t\t static_cast<uint64_t>(ratio.height);\n+\tuint64_t ratio2 = static_cast<uint64_t>(ratio.width) *\n+\t\t\t static_cast<uint64_t>(height);\n+\n+\tif (ratio1 < ratio2)\n+\t\treturn { static_cast<unsigned int>(ratio2 / ratio.height), height };\n+\telse\n+\t\treturn { width, static_cast<unsigned int>(ratio1 / ratio.width) };\n+}\n+\n+/**\n+ * \\brief Center a rectangle of this size at a given Point\n+ * \\param[in] center The center point the Rectangle is to have\n+ *\n+ * A Rectangle of this object's size is positioned so that its center\n+ * is at the given Point.\n+ *\n+ * \\return A Rectangle of this size, centered at the given Point.\n+ */\n+Rectangle Size::centeredTo(const Point ¢er) const\n+{\n+\tint x = center.x - width / 2;\n+\tint y = center.y - height / 2;\n+\n+\treturn { x, y, width, height };\n+}\n+\n+/**\n+ * \\brief Scale size up by the given factor\n+ * \\param[in] factor The factor\n+ * \\return The scaled Size\n+ */\n+Size Size::operator*(float factor) const\n+{\n+\treturn Size(width * factor, height * factor);\n+}\n+\n+/**\n+ * \\brief Scale size down by the given factor\n+ * \\param[in] factor The factor\n+ * \\return The scaled Size\n+ */\n+Size Size::operator/(float factor) const\n+{\n+\treturn Size(width / factor, height / factor);\n+}\n+\n+/**\n+ * \\brief Scale this size up by the given factor in place\n+ * \\param[in] factor The factor\n+ * \\return A reference to this object\n+ */\n+Size &Size::operator*=(float factor)\n+{\n+\twidth *= factor;\n+\theight *= factor;\n+\treturn *this;\n+}\n+\n+/**\n+ * \\brief Scale this size down by the given factor in place\n+ * \\param[in] factor The factor\n+ * \\return A reference to this object\n+ */\n+Size &Size::operator/=(float factor)\n+{\n+\twidth /= factor;\n+\theight /= factor;\n+\treturn *this;\n+}\n+\n /**\n * \\brief Compare sizes for equality\n * \\return True if the two sizes are equal, false otherwise\n@@ -365,6 +536,13 @@ bool operator==(const SizeRange &lhs, const SizeRange &rhs)\n * \\param[in] height The height\n */\n \n+/**\n+ * \\fn Rectangle::Rectangle(const Size &size)\n+ * \\brief Construct a Rectangle of \\a size with its top left corner located\n+ * at (0,0)\n+ * \\param[in] size The desired Rectangle size\n+ */\n+\n /**\n * \\var Rectangle::x\n * \\brief The horizontal coordinate of the rectangle's top-left corner\n@@ -404,6 +582,156 @@ const std::string Rectangle::toString() const\n \treturn ss.str();\n }\n \n+/**\n+ * \\brief Retrieve the center point of this rectangle\n+ * \\return The center Point\n+ */\n+Point Rectangle::center() const\n+{\n+\treturn { x + static_cast<int>(width / 2), y + static_cast<int>(height / 2) };\n+}\n+\n+/**\n+ * \\fn Size Rectangle::size() const\n+ * \\brief Retrieve the size of this rectangle\n+ * \\return The Rectangle size\n+ */\n+\n+/**\n+ * \\fn Point Rectangle::topLeft() const\n+ * \\brief Retrieve the coordinates of the top left corner of this Rectangle\n+ * \\return The Rectangle's top left corner\n+ */\n+\n+/**\n+ * \\brief Apply a non-uniform rational scaling in place to this Rectangle\n+ * \\param[in] numerator The numerators of the x and y scaling factors\n+ * \\param[in] denominator The denominators of the x and y scaling factors\n+ *\n+ * A non-uniform scaling is applied in place such the resulting x\n+ * coordinates are multiplied by numerator.width / denominator.width,\n+ * and similarly for the y coordinates (using height in place of width).\n+ *\n+ * \\return A reference to this object\n+ */\n+Rectangle &Rectangle::scaleBy(const Size &numerator, const Size &denominator)\n+{\n+\tx = static_cast<int64_t>(x) * numerator.width / denominator.width;\n+\ty = static_cast<int64_t>(y) * numerator.height / denominator.height;\n+\twidth = static_cast<uint64_t>(width) * numerator.width / denominator.width;\n+\theight = static_cast<uint64_t>(height) * numerator.height / denominator.height;\n+\n+\treturn *this;\n+}\n+\n+/**\n+ * \\brief Translate this Rectangle in place by the given Point\n+ * \\param[in] point The amount to translate the Rectangle by\n+ *\n+ * The Rectangle is translated in the x-direction by the point's x coordinate\n+ * and in the y-direction by the point's y coordinate.\n+ *\n+ * \\return A reference to this object\n+ */\n+Rectangle &Rectangle::translateBy(const Point &point)\n+{\n+\tx += point.x;\n+\ty += point.y;\n+\n+\treturn *this;\n+}\n+\n+/**\n+ * \\brief Calculate the intersection of this Rectangle with another\n+ * \\param[in] bound The Rectangle that is intersected with this Rectangle\n+ *\n+ * This method calculates the standard intersection of two rectangles. If the\n+ * rectangles do not overlap in either the x or y direction, then the size\n+ * of that dimension in the result (its width or height) is set to zero. Even\n+ * when one dimension is set to zero, note that the other dimension may still\n+ * have a positive value if there was some overlap.\n+ *\n+ * \\return A Rectangle that is the intersection of the input rectangles\n+ */\n+Rectangle Rectangle::boundedTo(const Rectangle &bound) const\n+{\n+\tint topLeftX = std::max(x, bound.x);\n+\tint topLeftY = std::max(y, bound.y);\n+\tint bottomRightX = std::min<int>(x + width, bound.x + bound.width);\n+\tint bottomRightY = std::min<int>(y + height, bound.y + bound.height);\n+\n+\tunsigned int newWidth = std::max(bottomRightX - topLeftX, 0);\n+\tunsigned int newHeight = std::max(bottomRightY - topLeftY, 0);\n+\n+\treturn { topLeftX, topLeftY, newWidth, newHeight };\n+}\n+\n+/**\n+ * \\brief Enclose a Rectangle so as not to exceed another Rectangle\n+ * \\param[in] boundary The limit that the returned Rectangle will not exceed\n+ *\n+ * The Rectangle is modified so that it does not exceed the given \\a boundary.\n+ * This process involves translating the Rectangle if any of its edges\n+ * lie beyond \\a boundary, so that those edges then lie along the boundary\n+ * instead.\n+ *\n+ * If either width or height are larger than \\a boundary, then the returned\n+ * Rectangle is clipped to be no larger. But other than this, the\n+ * Rectangle is not clipped or reduced in size, merely translated.\n+ *\n+ * Note that this is not a conventional Rectangle intersection function\n+ * which is provided by boundedTo().\n+ *\n+ * \\return A Rectangle that does not extend beyond a boundary Rectangle\n+ */\n+Rectangle Rectangle::enclosedIn(const Rectangle &boundary) const\n+{\n+\t/* We can't be bigger than the boundary rectangle. */\n+\tRectangle result = boundedTo(Rectangle{ x, y, boundary.size() });\n+\n+\tresult.x = std::clamp<int>(result.x, boundary.x,\n+\t\t\t\t boundary.x + boundary.width - result.width);\n+\tresult.y = std::clamp<int>(result.y, boundary.y,\n+\t\t\t\t boundary.y + boundary.height - result.height);\n+\n+\treturn result;\n+}\n+\n+/**\n+ * \\brief Apply a non-uniform rational scaling to this Rectangle\n+ * \\param[in] numerator The numerators of the x and y scaling factors\n+ * \\param[in] denominator The denominators of the x and y scaling factors\n+ *\n+ * A non-uniform scaling is applied such the resulting x\n+ * coordinates are multiplied by numerator.width / denominator.width,\n+ * and similarly for the y coordinates (using height in place of width).\n+ *\n+ * \\return The non-uniformly scaled Rectangle\n+ */\n+Rectangle Rectangle::scaledBy(const Size &numerator, const Size &denominator) const\n+{\n+\tint scaledX = static_cast<int64_t>(x) * numerator.width / denominator.width;\n+\tint scaledY = static_cast<int64_t>(y) * numerator.height / denominator.height;\n+\tunsigned int scaledWidth = static_cast<uint64_t>(width) * numerator.width / denominator.width;\n+\tunsigned int scaledHeight = static_cast<uint64_t>(height) * numerator.height / denominator.height;\n+\n+\treturn { scaledX, scaledY, scaledWidth, scaledHeight };\n+}\n+\n+/**\n+ * \\brief Translate a Rectangle by the given amounts\n+ * \\param[in] point The amount to translate the Rectangle by\n+ *\n+ * The Rectangle is translated in the x-direction by the point's x coordinate\n+ * and in the y-direction by the point's y coordinate.\n+ *\n+ * \\return The translated Rectangle\n+ */\n+Rectangle Rectangle::translatedBy(const Point &point) const\n+{\n+\treturn { x + point.x, y + point.y, width, height };\n+}\n+\n /**\n * \\brief Compare rectangles for equality\n * \\return True if the two rectangles are equal, false otherwise\n", "prefixes": [ "libcamera-devel", "v6", "4/6" ] }