| /* | |
| * Copyright 2006 The Android Open Source Project | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #ifndef SkRect_DEFINED | |
| #define SkRect_DEFINED | |
| #include "include/core/SkPathTypes.h" | |
| #include "include/core/SkPoint.h" | |
| #include "include/core/SkSize.h" | |
| #include "include/core/SkSpan.h" | |
| #include "include/core/SkTypes.h" | |
| #include "include/private/SkFloatingPoint.h" | |
| #include "include/private/SkSafe32.h" | |
| #include "include/private/SkTFitsIn.h" | |
| #include <algorithm> | |
| #include <array> | |
| #include <cmath> | |
| #include <cstdint> | |
| #include <cstring> | |
| #include <optional> | |
| struct SkRect; | |
| class SkString; | |
| /** \struct SkIRect | |
| SkIRect holds four 32-bit integer coordinates describing the upper and | |
| lower bounds of a rectangle. SkIRect may be created from outer bounds or | |
| from position, width, and height. SkIRect describes an area; if its right | |
| is less than or equal to its left, or if its bottom is less than or equal to | |
| its top, it is considered empty. | |
| */ | |
| struct SK_API SkIRect { | |
| int32_t fLeft = 0; //!< smaller x-axis bounds | |
| int32_t fTop = 0; //!< smaller y-axis bounds | |
| int32_t fRight = 0; //!< larger x-axis bounds | |
| int32_t fBottom = 0; //!< larger y-axis bounds | |
| /** Returns constructed SkIRect set to (0, 0, 0, 0). | |
| Many other rectangles are empty; if left is equal to or greater than right, | |
| or if top is equal to or greater than bottom. Setting all members to zero | |
| is a convenience, but does not designate a special empty rectangle. | |
| @return bounds (0, 0, 0, 0) | |
| */ | |
| [[nodiscard]] static constexpr SkIRect MakeEmpty() { | |
| return SkIRect{0, 0, 0, 0}; | |
| } | |
| /** Returns constructed SkIRect set to (0, 0, w, h). Does not validate input; w or h | |
| may be negative. | |
| @param w width of constructed SkIRect | |
| @param h height of constructed SkIRect | |
| @return bounds (0, 0, w, h) | |
| */ | |
| [[nodiscard]] static constexpr SkIRect MakeWH(int32_t w, int32_t h) { | |
| return SkIRect{0, 0, w, h}; | |
| } | |
| /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()). | |
| Does not validate input; size.width() or size.height() may be negative. | |
| @param size values for SkIRect width and height | |
| @return bounds (0, 0, size.width(), size.height()) | |
| */ | |
| [[nodiscard]] static constexpr SkIRect MakeSize(const SkISize& size) { | |
| return SkIRect{0, 0, size.fWidth, size.fHeight}; | |
| } | |
| /** Returns constructed SkIRect set to (pt.x(), pt.y(), pt.x() + size.width(), | |
| pt.y() + size.height()). Does not validate input; size.width() or size.height() may be | |
| negative. | |
| @param pt values for SkIRect fLeft and fTop | |
| @param size values for SkIRect width and height | |
| @return bounds at pt with width and height of size | |
| */ | |
| [[nodiscard]] static constexpr SkIRect MakePtSize(SkIPoint pt, SkISize size) { | |
| return MakeXYWH(pt.x(), pt.y(), size.width(), size.height()); | |
| } | |
| /** Returns constructed SkIRect set to (l, t, r, b). Does not sort input; SkIRect may | |
| result in fLeft greater than fRight, or fTop greater than fBottom. | |
| @param l integer stored in fLeft | |
| @param t integer stored in fTop | |
| @param r integer stored in fRight | |
| @param b integer stored in fBottom | |
| @return bounds (l, t, r, b) | |
| */ | |
| [[nodiscard]] static constexpr SkIRect MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b) { | |
| return SkIRect{l, t, r, b}; | |
| } | |
| /** Returns constructed SkIRect set to: (x, y, x + w, y + h). | |
| Does not validate input; w or h may be negative. | |
| @param x stored in fLeft | |
| @param y stored in fTop | |
| @param w added to x and stored in fRight | |
| @param h added to y and stored in fBottom | |
| @return bounds at (x, y) with width w and height h | |
| */ | |
| [[nodiscard]] static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h) { | |
| return { x, y, Sk32_sat_add(x, w), Sk32_sat_add(y, h) }; | |
| } | |
| /** Returns left edge of SkIRect, if sorted. | |
| Call sort() to reverse fLeft and fRight if needed. | |
| @return fLeft | |
| */ | |
| constexpr int32_t left() const { return fLeft; } | |
| /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid, | |
| and sort() to reverse fTop and fBottom if needed. | |
| @return fTop | |
| */ | |
| constexpr int32_t top() const { return fTop; } | |
| /** Returns right edge of SkIRect, if sorted. | |
| Call sort() to reverse fLeft and fRight if needed. | |
| @return fRight | |
| */ | |
| constexpr int32_t right() const { return fRight; } | |
| /** Returns bottom edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid, | |
| and sort() to reverse fTop and fBottom if needed. | |
| @return fBottom | |
| */ | |
| constexpr int32_t bottom() const { return fBottom; } | |
| /** Returns left edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid, | |
| and sort() to reverse fLeft and fRight if needed. | |
| @return fLeft | |
| */ | |
| constexpr int32_t x() const { return fLeft; } | |
| /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid, | |
| and sort() to reverse fTop and fBottom if needed. | |
| @return fTop | |
| */ | |
| constexpr int32_t y() const { return fTop; } | |
| // Experimental | |
| constexpr SkIPoint topLeft() const { return {fLeft, fTop}; } | |
| /** Returns span on the x-axis. This does not check if SkIRect is sorted, or if | |
| result fits in 32-bit signed integer; result may be negative. | |
| @return fRight minus fLeft | |
| */ | |
| constexpr int32_t width() const { return Sk32_can_overflow_sub(fRight, fLeft); } | |
| /** Returns span on the y-axis. This does not check if SkIRect is sorted, or if | |
| result fits in 32-bit signed integer; result may be negative. | |
| @return fBottom minus fTop | |
| */ | |
| constexpr int32_t height() const { return Sk32_can_overflow_sub(fBottom, fTop); } | |
| /** Returns spans on the x-axis and y-axis. This does not check if SkIRect is sorted, | |
| or if result fits in 32-bit signed integer; result may be negative. | |
| @return SkISize (width, height) | |
| */ | |
| constexpr SkISize size() const { return SkISize::Make(this->width(), this->height()); } | |
| /** Returns span on the x-axis. This does not check if SkIRect is sorted, so the | |
| result may be negative. This is safer than calling width() since width() might | |
| overflow in its calculation. | |
| @return fRight minus fLeft cast to int64_t | |
| */ | |
| constexpr int64_t width64() const { return (int64_t)fRight - (int64_t)fLeft; } | |
| /** Returns span on the y-axis. This does not check if SkIRect is sorted, so the | |
| result may be negative. This is safer than calling height() since height() might | |
| overflow in its calculation. | |
| @return fBottom minus fTop cast to int64_t | |
| */ | |
| constexpr int64_t height64() const { return (int64_t)fBottom - (int64_t)fTop; } | |
| /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal | |
| to or greater than fBottom. Call sort() to reverse rectangles with negative | |
| width64() or height64(). | |
| @return true if width64() or height64() are zero or negative | |
| */ | |
| bool isEmpty64() const { return fRight <= fLeft || fBottom <= fTop; } | |
| /** Returns true if width() or height() are zero or negative. | |
| @return true if width() or height() are zero or negative | |
| */ | |
| bool isEmpty() const { | |
| int64_t w = this->width64(); | |
| int64_t h = this->height64(); | |
| if (w <= 0 || h <= 0) { | |
| return true; | |
| } | |
| // Return true if either exceeds int32_t | |
| return !SkTFitsIn<int32_t>(w | h); | |
| } | |
| /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are | |
| identical to corresponding members in b. | |
| @param a SkIRect to compare | |
| @param b SkIRect to compare | |
| @return true if members are equal | |
| */ | |
| friend bool operator==(const SkIRect& a, const SkIRect& b) { | |
| return a.fLeft == b.fLeft && a.fTop == b.fTop && | |
| a.fRight == b.fRight && a.fBottom == b.fBottom; | |
| } | |
| /** Returns true if any member in a: fLeft, fTop, fRight, and fBottom; is not | |
| identical to the corresponding member in b. | |
| @param a SkIRect to compare | |
| @param b SkIRect to compare | |
| @return true if members are not equal | |
| */ | |
| friend bool operator!=(const SkIRect& a, const SkIRect& b) { | |
| return a.fLeft != b.fLeft || a.fTop != b.fTop || | |
| a.fRight != b.fRight || a.fBottom != b.fBottom; | |
| } | |
| /** Sets SkIRect to (0, 0, 0, 0). | |
| Many other rectangles are empty; if left is equal to or greater than right, | |
| or if top is equal to or greater than bottom. Setting all members to zero | |
| is a convenience, but does not designate a special empty rectangle. | |
| */ | |
| void setEmpty() { memset(this, 0, sizeof(*this)); } | |
| /** Sets SkIRect to (left, top, right, bottom). | |
| left and right are not sorted; left is not necessarily less than right. | |
| top and bottom are not sorted; top is not necessarily less than bottom. | |
| @param left stored in fLeft | |
| @param top stored in fTop | |
| @param right stored in fRight | |
| @param bottom stored in fBottom | |
| */ | |
| void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom) { | |
| fLeft = left; | |
| fTop = top; | |
| fRight = right; | |
| fBottom = bottom; | |
| } | |
| /** Sets SkIRect to: (x, y, x + width, y + height). | |
| Does not validate input; width or height may be negative. | |
| @param x stored in fLeft | |
| @param y stored in fTop | |
| @param width added to x and stored in fRight | |
| @param height added to y and stored in fBottom | |
| */ | |
| void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height) { | |
| fLeft = x; | |
| fTop = y; | |
| fRight = Sk32_sat_add(x, width); | |
| fBottom = Sk32_sat_add(y, height); | |
| } | |
| void setWH(int32_t width, int32_t height) { | |
| fLeft = 0; | |
| fTop = 0; | |
| fRight = width; | |
| fBottom = height; | |
| } | |
| void setSize(SkISize size) { | |
| fLeft = 0; | |
| fTop = 0; | |
| fRight = size.width(); | |
| fBottom = size.height(); | |
| } | |
| /** Returns SkIRect offset by (dx, dy). | |
| If dx is negative, SkIRect returned is moved to the left. | |
| If dx is positive, SkIRect returned is moved to the right. | |
| If dy is negative, SkIRect returned is moved upward. | |
| If dy is positive, SkIRect returned is moved downward. | |
| @param dx offset added to fLeft and fRight | |
| @param dy offset added to fTop and fBottom | |
| @return SkIRect offset by dx and dy, with original width and height | |
| */ | |
| constexpr SkIRect makeOffset(int32_t dx, int32_t dy) const { | |
| return { | |
| Sk32_sat_add(fLeft, dx), Sk32_sat_add(fTop, dy), | |
| Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy), | |
| }; | |
| } | |
| /** Returns SkIRect offset by (offset.x(), offset.y()). | |
| If offset.x() is negative, SkIRect returned is moved to the left. | |
| If offset.x() is positive, SkIRect returned is moved to the right. | |
| If offset.y() is negative, SkIRect returned is moved upward. | |
| If offset.y() is positive, SkIRect returned is moved downward. | |
| @param offset translation vector | |
| @return SkIRect translated by offset, with original width and height | |
| */ | |
| constexpr SkIRect makeOffset(SkIVector offset) const { | |
| return this->makeOffset(offset.x(), offset.y()); | |
| } | |
| /** Returns SkIRect, inset by (dx, dy). | |
| If dx is negative, SkIRect returned is wider. | |
| If dx is positive, SkIRect returned is narrower. | |
| If dy is negative, SkIRect returned is taller. | |
| If dy is positive, SkIRect returned is shorter. | |
| @param dx offset added to fLeft and subtracted from fRight | |
| @param dy offset added to fTop and subtracted from fBottom | |
| @return SkIRect inset symmetrically left and right, top and bottom | |
| */ | |
| SkIRect makeInset(int32_t dx, int32_t dy) const { | |
| return { | |
| Sk32_sat_add(fLeft, dx), Sk32_sat_add(fTop, dy), | |
| Sk32_sat_sub(fRight, dx), Sk32_sat_sub(fBottom, dy), | |
| }; | |
| } | |
| /** Returns SkIRect, outset by (dx, dy). | |
| If dx is negative, SkIRect returned is narrower. | |
| If dx is positive, SkIRect returned is wider. | |
| If dy is negative, SkIRect returned is shorter. | |
| If dy is positive, SkIRect returned is taller. | |
| @param dx offset subtracted to fLeft and added from fRight | |
| @param dy offset subtracted to fTop and added from fBottom | |
| @return SkIRect outset symmetrically left and right, top and bottom | |
| */ | |
| SkIRect makeOutset(int32_t dx, int32_t dy) const { | |
| return { | |
| Sk32_sat_sub(fLeft, dx), Sk32_sat_sub(fTop, dy), | |
| Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy), | |
| }; | |
| } | |
| /** Offsets SkIRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom. | |
| If dx is negative, moves SkIRect returned to the left. | |
| If dx is positive, moves SkIRect returned to the right. | |
| If dy is negative, moves SkIRect returned upward. | |
| If dy is positive, moves SkIRect returned downward. | |
| @param dx offset added to fLeft and fRight | |
| @param dy offset added to fTop and fBottom | |
| */ | |
| void offset(int32_t dx, int32_t dy) { | |
| fLeft = Sk32_sat_add(fLeft, dx); | |
| fTop = Sk32_sat_add(fTop, dy); | |
| fRight = Sk32_sat_add(fRight, dx); | |
| fBottom = Sk32_sat_add(fBottom, dy); | |
| } | |
| /** Offsets SkIRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to | |
| fTop, fBottom. | |
| If delta.fX is negative, moves SkIRect returned to the left. | |
| If delta.fX is positive, moves SkIRect returned to the right. | |
| If delta.fY is negative, moves SkIRect returned upward. | |
| If delta.fY is positive, moves SkIRect returned downward. | |
| @param delta offset added to SkIRect | |
| */ | |
| void offset(const SkIPoint& delta) { | |
| this->offset(delta.fX, delta.fY); | |
| } | |
| /** Offsets SkIRect so that fLeft equals newX, and fTop equals newY. width and height | |
| are unchanged. | |
| @param newX stored in fLeft, preserving width() | |
| @param newY stored in fTop, preserving height() | |
| */ | |
| void offsetTo(int32_t newX, int32_t newY) { | |
| fRight = Sk64_pin_to_s32((int64_t)fRight + newX - fLeft); | |
| fBottom = Sk64_pin_to_s32((int64_t)fBottom + newY - fTop); | |
| fLeft = newX; | |
| fTop = newY; | |
| } | |
| /** Insets SkIRect by (dx,dy). | |
| If dx is positive, makes SkIRect narrower. | |
| If dx is negative, makes SkIRect wider. | |
| If dy is positive, makes SkIRect shorter. | |
| If dy is negative, makes SkIRect taller. | |
| @param dx offset added to fLeft and subtracted from fRight | |
| @param dy offset added to fTop and subtracted from fBottom | |
| */ | |
| void inset(int32_t dx, int32_t dy) { | |
| fLeft = Sk32_sat_add(fLeft, dx); | |
| fTop = Sk32_sat_add(fTop, dy); | |
| fRight = Sk32_sat_sub(fRight, dx); | |
| fBottom = Sk32_sat_sub(fBottom, dy); | |
| } | |
| /** Outsets SkIRect by (dx, dy). | |
| If dx is positive, makes SkIRect wider. | |
| If dx is negative, makes SkIRect narrower. | |
| If dy is positive, makes SkIRect taller. | |
| If dy is negative, makes SkIRect shorter. | |
| @param dx subtracted to fLeft and added from fRight | |
| @param dy subtracted to fTop and added from fBottom | |
| */ | |
| void outset(int32_t dx, int32_t dy) { this->inset(-dx, -dy); } | |
| /** Adjusts SkIRect by adding dL to fLeft, dT to fTop, dR to fRight, and dB to fBottom. | |
| If dL is positive, narrows SkIRect on the left. If negative, widens it on the left. | |
| If dT is positive, shrinks SkIRect on the top. If negative, lengthens it on the top. | |
| If dR is positive, narrows SkIRect on the right. If negative, widens it on the right. | |
| If dB is positive, shrinks SkIRect on the bottom. If negative, lengthens it on the bottom. | |
| The resulting SkIRect is not checked for validity. Thus, if the resulting SkIRect left is | |
| greater than right, the SkIRect will be considered empty. Call sort() after this call | |
| if that is not the desired behavior. | |
| @param dL offset added to fLeft | |
| @param dT offset added to fTop | |
| @param dR offset added to fRight | |
| @param dB offset added to fBottom | |
| */ | |
| void adjust(int32_t dL, int32_t dT, int32_t dR, int32_t dB) { | |
| fLeft = Sk32_sat_add(fLeft, dL); | |
| fTop = Sk32_sat_add(fTop, dT); | |
| fRight = Sk32_sat_add(fRight, dR); | |
| fBottom = Sk32_sat_add(fBottom, dB); | |
| } | |
| /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom. | |
| Returns false if SkIRect is empty. | |
| Considers input to describe constructed SkIRect: (x, y, x + 1, y + 1) and | |
| returns true if constructed area is completely enclosed by SkIRect area. | |
| @param x test SkIPoint x-coordinate | |
| @param y test SkIPoint y-coordinate | |
| @return true if (x, y) is inside SkIRect | |
| */ | |
| bool contains(int32_t x, int32_t y) const { | |
| return x >= fLeft && x < fRight && y >= fTop && y < fBottom; | |
| } | |
| /** Returns true if SkIRect contains r. | |
| Returns false if SkIRect is empty or r is empty. | |
| SkIRect contains r when SkIRect area completely includes r area. | |
| @param r SkIRect contained | |
| @return true if all sides of SkIRect are outside r | |
| */ | |
| bool contains(const SkIRect& r) const { | |
| return !r.isEmpty() && !this->isEmpty() && // check for empties | |
| fLeft <= r.fLeft && fTop <= r.fTop && | |
| fRight >= r.fRight && fBottom >= r.fBottom; | |
| } | |
| /** Returns true if SkIRect contains r. | |
| Returns false if SkIRect is empty or r is empty. | |
| SkIRect contains r when SkIRect area completely includes r area. | |
| @param r SkRect contained | |
| @return true if all sides of SkIRect are outside r | |
| */ | |
| inline bool contains(const SkRect& r) const; | |
| /** Returns true if SkIRect contains construction. | |
| Asserts if SkIRect is empty or construction is empty, and if SK_DEBUG is defined. | |
| Return is undefined if SkIRect is empty or construction is empty. | |
| @param r SkIRect contained | |
| @return true if all sides of SkIRect are outside r | |
| */ | |
| bool containsNoEmptyCheck(const SkIRect& r) const { | |
| SkASSERT(fLeft < fRight && fTop < fBottom); | |
| SkASSERT(r.fLeft < r.fRight && r.fTop < r.fBottom); | |
| return fLeft <= r.fLeft && fTop <= r.fTop && fRight >= r.fRight && fBottom >= r.fBottom; | |
| } | |
| /** Returns true if SkIRect intersects r, and sets SkIRect to intersection. | |
| Returns false if SkIRect does not intersect r, and leaves SkIRect unchanged. | |
| Returns false if either r or SkIRect is empty, leaving SkIRect unchanged. | |
| @param r limit of result | |
| @return true if r and SkIRect have area in common | |
| */ | |
| bool intersect(const SkIRect& r) { | |
| return this->intersect(*this, r); | |
| } | |
| /** Returns true if a intersects b, and sets SkIRect to intersection. | |
| Returns false if a does not intersect b, and leaves SkIRect unchanged. | |
| Returns false if either a or b is empty, leaving SkIRect unchanged. | |
| @param a SkIRect to intersect | |
| @param b SkIRect to intersect | |
| @return true if a and b have area in common | |
| */ | |
| [[nodiscard]] bool intersect(const SkIRect& a, const SkIRect& b); | |
| /** Returns true if a intersects b. | |
| Returns false if either a or b is empty, or do not intersect. | |
| @param a SkIRect to intersect | |
| @param b SkIRect to intersect | |
| @return true if a and b have area in common | |
| */ | |
| static bool Intersects(const SkIRect& a, const SkIRect& b) { | |
| return SkIRect{}.intersect(a, b); | |
| } | |
| /** Sets SkIRect to the union of itself and r. | |
| Has no effect if r is empty. Otherwise, if SkIRect is empty, sets SkIRect to r. | |
| @param r expansion SkIRect | |
| example: https://fiddle.skia.org/c/@IRect_join_2 | |
| */ | |
| void join(const SkIRect& r); | |
| /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps | |
| fTop and fBottom if fTop is greater than fBottom. Result may be empty, | |
| and width() and height() will be zero or positive. | |
| */ | |
| void sort() { | |
| using std::swap; | |
| if (fLeft > fRight) { | |
| swap(fLeft, fRight); | |
| } | |
| if (fTop > fBottom) { | |
| swap(fTop, fBottom); | |
| } | |
| } | |
| /** Returns SkIRect with fLeft and fRight swapped if fLeft is greater than fRight; and | |
| with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty; | |
| and width() and height() will be zero or positive. | |
| @return sorted SkIRect | |
| */ | |
| SkIRect makeSorted() const { | |
| return MakeLTRB(std::min(fLeft, fRight), std::min(fTop, fBottom), | |
| std::max(fLeft, fRight), std::max(fTop, fBottom)); | |
| } | |
| /** Returns pointer to first int32 in SkIRect, to treat it as an array with four | |
| entries. | |
| @return pointer to fLeft | |
| */ | |
| const int32_t* asInt32s() const { return &fLeft; } | |
| }; | |
| /** \struct SkRect | |
| SkRect holds four float coordinates describing the upper and | |
| lower bounds of a rectangle. SkRect may be created from outer bounds or | |
| from position, width, and height. SkRect describes an area; if its right | |
| is less than or equal to its left, or if its bottom is less than or equal to | |
| its top, it is considered empty. | |
| */ | |
| struct SK_API SkRect { | |
| float fLeft = 0; //!< smaller x-axis bounds | |
| float fTop = 0; //!< smaller y-axis bounds | |
| float fRight = 0; //!< larger x-axis bounds | |
| float fBottom = 0; //!< larger y-axis bounds | |
| /** Returns constructed SkRect set to (0, 0, 0, 0). | |
| Many other rectangles are empty; if left is equal to or greater than right, | |
| or if top is equal to or greater than bottom. Setting all members to zero | |
| is a convenience, but does not designate a special empty rectangle. | |
| @return bounds (0, 0, 0, 0) | |
| */ | |
| [[nodiscard]] static constexpr SkRect MakeEmpty() { | |
| return SkRect{0, 0, 0, 0}; | |
| } | |
| /** Returns constructed SkRect set to float values (0, 0, w, h). Does not | |
| validate input; w or h may be negative. | |
| Passing integer values may generate a compiler warning since SkRect cannot | |
| represent 32-bit integers exactly. Use SkIRect for an exact integer rectangle. | |
| @param w float width of constructed SkRect | |
| @param h float height of constructed SkRect | |
| @return bounds (0, 0, w, h) | |
| */ | |
| [[nodiscard]] static constexpr SkRect MakeWH(float w, float h) { | |
| return SkRect{0, 0, w, h}; | |
| } | |
| /** Returns constructed SkRect set to integer values (0, 0, w, h). Does not validate | |
| input; w or h may be negative. | |
| Use to avoid a compiler warning that input may lose precision when stored. | |
| Use SkIRect for an exact integer rectangle. | |
| @param w integer width of constructed SkRect | |
| @param h integer height of constructed SkRect | |
| @return bounds (0, 0, w, h) | |
| */ | |
| [[nodiscard]] static SkRect MakeIWH(int w, int h) { | |
| return {0, 0, static_cast<float>(w), static_cast<float>(h)}; | |
| } | |
| /** Returns constructed SkRect set to (0, 0, size.width(), size.height()). Does not | |
| validate input; size.width() or size.height() may be negative. | |
| @param size float values for SkRect width and height | |
| @return bounds (0, 0, size.width(), size.height()) | |
| */ | |
| [[nodiscard]] static constexpr SkRect MakeSize(const SkSize& size) { | |
| return SkRect{0, 0, size.fWidth, size.fHeight}; | |
| } | |
| /** Returns constructed SkRect set to (l, t, r, b). Does not sort input; SkRect may | |
| result in fLeft greater than fRight, or fTop greater than fBottom. | |
| @param l float stored in fLeft | |
| @param t float stored in fTop | |
| @param r float stored in fRight | |
| @param b float stored in fBottom | |
| @return bounds (l, t, r, b) | |
| */ | |
| [[nodiscard]] static constexpr SkRect MakeLTRB(float l, float t, float r, float b) { | |
| return SkRect {l, t, r, b}; | |
| } | |
| /** Returns constructed SkRect set to (x, y, x + w, y + h). | |
| Does not validate input; w or h may be negative. | |
| @param x stored in fLeft | |
| @param y stored in fTop | |
| @param w added to x and stored in fRight | |
| @param h added to y and stored in fBottom | |
| @return bounds at (x, y) with width w and height h | |
| */ | |
| [[nodiscard]] static constexpr SkRect MakeXYWH(float x, float y, float w, float h) { | |
| return SkRect {x, y, x + w, y + h}; | |
| } | |
| /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()). | |
| Does not validate input; size.width() or size.height() may be negative. | |
| @param size integer values for SkRect width and height | |
| @return bounds (0, 0, size.width(), size.height()) | |
| */ | |
| static SkRect Make(const SkISize& size) { | |
| return MakeIWH(size.width(), size.height()); | |
| } | |
| /** Returns constructed SkIRect set to irect, promoting integers to float. | |
| Does not validate input; fLeft may be greater than fRight, fTop may be greater | |
| than fBottom. | |
| @param irect integer unsorted bounds | |
| @return irect members converted to float | |
| */ | |
| [[nodiscard]] static SkRect Make(const SkIRect& irect) { | |
| return { | |
| static_cast<float>(irect.fLeft), static_cast<float>(irect.fTop), | |
| static_cast<float>(irect.fRight), static_cast<float>(irect.fBottom) | |
| }; | |
| } | |
| /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal | |
| to or greater than fBottom. Call sort() to reverse rectangles with negative | |
| width() or height(). | |
| @return true if width() or height() are zero or negative | |
| */ | |
| bool isEmpty() const { | |
| // We write it as the NOT of a non-empty rect, so we will return true if any values | |
| // are NaN. | |
| return !(fLeft < fRight && fTop < fBottom); | |
| } | |
| /** Returns true if fLeft is equal to or less than fRight, or if fTop is equal | |
| to or less than fBottom. Call sort() to reverse rectangles with negative | |
| width() or height(). | |
| @return true if width() or height() are zero or positive | |
| */ | |
| bool isSorted() const { return fLeft <= fRight && fTop <= fBottom; } | |
| /** Returns true if all values in the rectangle are finite. | |
| @return true if no member is infinite or NaN | |
| */ | |
| bool isFinite() const { | |
| return SkIsFinite(fLeft, fTop, fRight, fBottom); | |
| } | |
| /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid. | |
| Call sort() to reverse fLeft and fRight if needed. | |
| @return fLeft | |
| */ | |
| constexpr float x() const { return fLeft; } | |
| /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid, | |
| and sort() to reverse fTop and fBottom if needed. | |
| @return fTop | |
| */ | |
| constexpr float y() const { return fTop; } | |
| /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid. | |
| Call sort() to reverse fLeft and fRight if needed. | |
| @return fLeft | |
| */ | |
| constexpr float left() const { return fLeft; } | |
| /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid, | |
| and sort() to reverse fTop and fBottom if needed. | |
| @return fTop | |
| */ | |
| constexpr float top() const { return fTop; } | |
| /** Returns right edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid. | |
| Call sort() to reverse fLeft and fRight if needed. | |
| @return fRight | |
| */ | |
| constexpr float right() const { return fRight; } | |
| /** Returns bottom edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid, | |
| and sort() to reverse fTop and fBottom if needed. | |
| @return fBottom | |
| */ | |
| constexpr float bottom() const { return fBottom; } | |
| /** Returns span on the x-axis. This does not check if SkRect is sorted, or if | |
| result fits in 32-bit float; result may be negative or infinity. | |
| @return fRight minus fLeft | |
| */ | |
| constexpr float width() const { return fRight - fLeft; } | |
| /** Returns span on the y-axis. This does not check if SkRect is sorted, or if | |
| result fits in 32-bit float; result may be negative or infinity. | |
| @return fBottom minus fTop | |
| */ | |
| constexpr float height() const { return fBottom - fTop; } | |
| /** Returns average of left edge and right edge. Result does not change if SkRect | |
| is sorted. Result may overflow to infinity if SkRect is far from the origin. | |
| @return midpoint on x-axis | |
| */ | |
| constexpr float centerX() const { | |
| return sk_float_midpoint(fLeft, fRight); | |
| } | |
| /** Returns average of top edge and bottom edge. Result does not change if SkRect | |
| is sorted. | |
| @return midpoint on y-axis | |
| */ | |
| constexpr float centerY() const { | |
| return sk_float_midpoint(fTop, fBottom); | |
| } | |
| /** Returns the point this->centerX(), this->centerY(). | |
| @return rectangle center | |
| */ | |
| constexpr SkPoint center() const { return {this->centerX(), this->centerY()}; } | |
| /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are | |
| equal to the corresponding members in b. | |
| a and b are not equal if either contain NaN. a and b are equal if members | |
| contain zeroes with different signs. | |
| @param a SkRect to compare | |
| @param b SkRect to compare | |
| @return true if members are equal | |
| */ | |
| friend bool operator==(const SkRect& a, const SkRect& b) { | |
| return a.fLeft == b.fLeft && | |
| a.fTop == b.fTop && | |
| a.fRight == b.fRight && | |
| a.fBottom == b.fBottom; | |
| } | |
| /** Returns true if any in a: fLeft, fTop, fRight, and fBottom; does not | |
| equal the corresponding members in b. | |
| a and b are not equal if either contain NaN. a and b are equal if members | |
| contain zeroes with different signs. | |
| @param a SkRect to compare | |
| @param b SkRect to compare | |
| @return true if members are not equal | |
| */ | |
| friend bool operator!=(const SkRect& a, const SkRect& b) { | |
| return !(a == b); | |
| } | |
| SkPoint TL() const { return {fLeft, fTop}; } | |
| SkPoint TR() const { return {fRight, fTop}; } | |
| SkPoint BL() const { return {fLeft, fBottom}; } | |
| SkPoint BR() const { return {fRight, fBottom}; } | |
| /** Returns four points in quad that enclose SkRect, | |
| * respect the specified path-direction. | |
| */ | |
| std::array<SkPoint, 4> toQuad(SkPathDirection dir = SkPathDirection::kCW) const { | |
| std::array<SkPoint, 4> storage; | |
| this->copyToQuad(storage, dir); | |
| return storage; | |
| } | |
| // Same as toQuad(), but copies the 4 points into the specified storage | |
| // which must be at least a size of 4. | |
| void copyToQuad(SkSpan<SkPoint> pts, SkPathDirection dir = SkPathDirection::kCW) const { | |
| SkASSERT(pts.size() >= 4); | |
| pts[0] = this->TL(); | |
| pts[2] = this->BR(); | |
| if (dir == SkPathDirection::kCW) { | |
| pts[1] = this->TR(); | |
| pts[3] = this->BL(); | |
| } else { | |
| pts[1] = this->BL(); | |
| pts[3] = this->TR(); | |
| } | |
| } | |
| // DEPRECATED: use std::array or copyToQuad versions | |
| void toQuad(SkPoint quad[4]) const { | |
| this->copyToQuad({quad, 4}); | |
| } | |
| /** Sets SkRect to (0, 0, 0, 0). | |
| Many other rectangles are empty; if left is equal to or greater than right, | |
| or if top is equal to or greater than bottom. Setting all members to zero | |
| is a convenience, but does not designate a special empty rectangle. | |
| */ | |
| void setEmpty() { *this = MakeEmpty(); } | |
| /** Sets SkRect to src, promoting src members from integer to float. | |
| Very large values in src may lose precision. | |
| @param src integer SkRect | |
| */ | |
| void set(const SkIRect& src) { | |
| fLeft = src.fLeft; | |
| fTop = src.fTop; | |
| fRight = src.fRight; | |
| fBottom = src.fBottom; | |
| } | |
| /** Sets SkRect to (left, top, right, bottom). | |
| left and right are not sorted; left is not necessarily less than right. | |
| top and bottom are not sorted; top is not necessarily less than bottom. | |
| @param left stored in fLeft | |
| @param top stored in fTop | |
| @param right stored in fRight | |
| @param bottom stored in fBottom | |
| */ | |
| void setLTRB(float left, float top, float right, float bottom) { | |
| fLeft = left; | |
| fTop = top; | |
| fRight = right; | |
| fBottom = bottom; | |
| } | |
| /** | |
| * Compute the bounds of the span of points. | |
| * If the span is empty, returns the empty-rect {0, 0, 0, 0. | |
| * If the span contains non-finite values (inf or nan), returns {} | |
| */ | |
| static std::optional<SkRect> Bounds(SkSpan<const SkPoint> pts); | |
| static SkRect BoundsOrEmpty(SkSpan<const SkPoint> pts) { | |
| if (auto bounds = Bounds(pts)) { | |
| return bounds.value(); | |
| } else { | |
| return MakeEmpty(); | |
| } | |
| } | |
| /** Sets to bounds of SkPoint array with count entries. If count is zero or smaller, | |
| or if SkPoint array contains an infinity or NaN, sets to (0, 0, 0, 0). | |
| Result is either empty or sorted: fLeft is less than or equal to fRight, and | |
| fTop is less than or equal to fBottom. | |
| @param pts SkPoint span | |
| */ | |
| void setBounds(SkSpan<const SkPoint> pts) { | |
| (void)this->setBoundsCheck(pts); | |
| } | |
| /** Sets to bounds of the span of points, and return true (if all point values were finite). | |
| * | |
| * If the span is empty, set the rect to empty() and return true. | |
| * If any point contains an infinity or NaN, set the rect to empty and return false. | |
| * | |
| * @param pts SkPoint span | |
| * example: https://fiddle.skia.org/c/@Rect_setBoundsCheck | |
| */ | |
| bool setBoundsCheck(SkSpan<const SkPoint> pts); | |
| /** Sets to bounds of the span of points. | |
| * | |
| * If the span is empty, set the rect to empty(). | |
| * If any point contains an infinity or NaN, set the rect to NaN. | |
| * | |
| * @param pts SkPoint span | |
| * example: https://fiddle.skia.org/c/@Rect_setBoundsNoCheck | |
| */ | |
| void setBoundsNoCheck(SkSpan<const SkPoint> pts); | |
| /** Sets bounds to the smallest SkRect enclosing SkPoint p0 and p1. The result is | |
| sorted and may be empty. Does not check to see if values are finite. | |
| @param p0 corner to include | |
| @param p1 corner to include | |
| */ | |
| void set(const SkPoint& p0, const SkPoint& p1) { | |
| fLeft = std::min(p0.fX, p1.fX); | |
| fRight = std::max(p0.fX, p1.fX); | |
| fTop = std::min(p0.fY, p1.fY); | |
| fBottom = std::max(p0.fY, p1.fY); | |
| } | |
| /** Sets SkRect to (x, y, x + width, y + height). | |
| Does not validate input; width or height may be negative. | |
| @param x stored in fLeft | |
| @param y stored in fTop | |
| @param width added to x and stored in fRight | |
| @param height added to y and stored in fBottom | |
| */ | |
| void setXYWH(float x, float y, float width, float height) { | |
| fLeft = x; | |
| fTop = y; | |
| fRight = x + width; | |
| fBottom = y + height; | |
| } | |
| /** Sets SkRect to (0, 0, width, height). Does not validate input; | |
| width or height may be negative. | |
| @param width stored in fRight | |
| @param height stored in fBottom | |
| */ | |
| void setWH(float width, float height) { | |
| fLeft = 0; | |
| fTop = 0; | |
| fRight = width; | |
| fBottom = height; | |
| } | |
| void setIWH(int32_t width, int32_t height) { | |
| this->setWH(width, height); | |
| } | |
| /** Returns SkRect offset by (dx, dy). | |
| If dx is negative, SkRect returned is moved to the left. | |
| If dx is positive, SkRect returned is moved to the right. | |
| If dy is negative, SkRect returned is moved upward. | |
| If dy is positive, SkRect returned is moved downward. | |
| @param dx added to fLeft and fRight | |
| @param dy added to fTop and fBottom | |
| @return SkRect offset on axes, with original width and height | |
| */ | |
| constexpr SkRect makeOffset(float dx, float dy) const { | |
| return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy); | |
| } | |
| /** Returns SkRect offset by v. | |
| @param v added to rect | |
| @return SkRect offset on axes, with original width and height | |
| */ | |
| constexpr SkRect makeOffset(SkVector v) const { return this->makeOffset(v.x(), v.y()); } | |
| /** Returns SkRect, inset by (dx, dy). | |
| If dx is negative, SkRect returned is wider. | |
| If dx is positive, SkRect returned is narrower. | |
| If dy is negative, SkRect returned is taller. | |
| If dy is positive, SkRect returned is shorter. | |
| @param dx added to fLeft and subtracted from fRight | |
| @param dy added to fTop and subtracted from fBottom | |
| @return SkRect inset symmetrically left and right, top and bottom | |
| */ | |
| SkRect makeInset(float dx, float dy) const { | |
| return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, fBottom - dy); | |
| } | |
| /** Returns SkRect, outset by (dx, dy). | |
| If dx is negative, SkRect returned is narrower. | |
| If dx is positive, SkRect returned is wider. | |
| If dy is negative, SkRect returned is shorter. | |
| If dy is positive, SkRect returned is taller. | |
| @param dx subtracted to fLeft and added from fRight | |
| @param dy subtracted to fTop and added from fBottom | |
| @return SkRect outset symmetrically left and right, top and bottom | |
| */ | |
| SkRect makeOutset(float dx, float dy) const { | |
| return MakeLTRB(fLeft - dx, fTop - dy, fRight + dx, fBottom + dy); | |
| } | |
| /** Offsets SkRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom. | |
| If dx is negative, moves SkRect to the left. | |
| If dx is positive, moves SkRect to the right. | |
| If dy is negative, moves SkRect upward. | |
| If dy is positive, moves SkRect downward. | |
| @param dx offset added to fLeft and fRight | |
| @param dy offset added to fTop and fBottom | |
| */ | |
| void offset(float dx, float dy) { | |
| fLeft += dx; | |
| fTop += dy; | |
| fRight += dx; | |
| fBottom += dy; | |
| } | |
| /** Offsets SkRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to | |
| fTop, fBottom. | |
| If delta.fX is negative, moves SkRect to the left. | |
| If delta.fX is positive, moves SkRect to the right. | |
| If delta.fY is negative, moves SkRect upward. | |
| If delta.fY is positive, moves SkRect downward. | |
| @param delta added to SkRect | |
| */ | |
| void offset(const SkPoint& delta) { | |
| this->offset(delta.fX, delta.fY); | |
| } | |
| /** Offsets SkRect so that fLeft equals newX, and fTop equals newY. width and height | |
| are unchanged. | |
| @param newX stored in fLeft, preserving width() | |
| @param newY stored in fTop, preserving height() | |
| */ | |
| void offsetTo(float newX, float newY) { | |
| fRight += newX - fLeft; | |
| fBottom += newY - fTop; | |
| fLeft = newX; | |
| fTop = newY; | |
| } | |
| /** Insets SkRect by (dx, dy). | |
| If dx is positive, makes SkRect narrower. | |
| If dx is negative, makes SkRect wider. | |
| If dy is positive, makes SkRect shorter. | |
| If dy is negative, makes SkRect taller. | |
| @param dx added to fLeft and subtracted from fRight | |
| @param dy added to fTop and subtracted from fBottom | |
| */ | |
| void inset(float dx, float dy) { | |
| fLeft += dx; | |
| fTop += dy; | |
| fRight -= dx; | |
| fBottom -= dy; | |
| } | |
| /** Outsets SkRect by (dx, dy). | |
| If dx is positive, makes SkRect wider. | |
| If dx is negative, makes SkRect narrower. | |
| If dy is positive, makes SkRect taller. | |
| If dy is negative, makes SkRect shorter. | |
| @param dx subtracted to fLeft and added from fRight | |
| @param dy subtracted to fTop and added from fBottom | |
| */ | |
| void outset(float dx, float dy) { this->inset(-dx, -dy); } | |
| /** Returns true if SkRect intersects r, and sets SkRect to intersection. | |
| Returns false if SkRect does not intersect r, and leaves SkRect unchanged. | |
| Returns false if either r or SkRect is empty, leaving SkRect unchanged. | |
| @param r limit of result | |
| @return true if r and SkRect have area in common | |
| example: https://fiddle.skia.org/c/@Rect_intersect | |
| */ | |
| bool intersect(const SkRect& r); | |
| /** Returns true if a intersects b, and sets SkRect to intersection. | |
| Returns false if a does not intersect b, and leaves SkRect unchanged. | |
| Returns false if either a or b is empty, leaving SkRect unchanged. | |
| @param a SkRect to intersect | |
| @param b SkRect to intersect | |
| @return true if a and b have area in common | |
| */ | |
| [[nodiscard]] bool intersect(const SkRect& a, const SkRect& b); | |
| private: | |
| static bool Intersects(float al, float at, float ar, float ab, | |
| float bl, float bt, float br, float bb) { | |
| float L = std::max(al, bl); | |
| float R = std::min(ar, br); | |
| float T = std::max(at, bt); | |
| float B = std::min(ab, bb); | |
| return L < R && T < B; | |
| } | |
| public: | |
| /** Returns true if SkRect intersects r. | |
| Returns false if either r or SkRect is empty, or do not intersect. | |
| @param r SkRect to intersect | |
| @return true if r and SkRect have area in common | |
| */ | |
| bool intersects(const SkRect& r) const { | |
| return Intersects(fLeft, fTop, fRight, fBottom, | |
| r.fLeft, r.fTop, r.fRight, r.fBottom); | |
| } | |
| /** Returns true if a intersects b. | |
| Returns false if either a or b is empty, or do not intersect. | |
| @param a SkRect to intersect | |
| @param b SkRect to intersect | |
| @return true if a and b have area in common | |
| */ | |
| static bool Intersects(const SkRect& a, const SkRect& b) { | |
| return Intersects(a.fLeft, a.fTop, a.fRight, a.fBottom, | |
| b.fLeft, b.fTop, b.fRight, b.fBottom); | |
| } | |
| /** Sets SkRect to the union of itself and r. | |
| Has no effect if r is empty. Otherwise, if SkRect is empty, sets | |
| SkRect to r. | |
| @param r expansion SkRect | |
| example: https://fiddle.skia.org/c/@Rect_join_2 | |
| */ | |
| void join(const SkRect& r); | |
| /** Sets SkRect to the union of itself and r. | |
| Asserts if r is empty and SK_DEBUG is defined. | |
| If SkRect is empty, sets SkRect to r. | |
| May produce incorrect results if r is empty. | |
| @param r expansion SkRect | |
| */ | |
| void joinNonEmptyArg(const SkRect& r) { | |
| SkASSERT(!r.isEmpty()); | |
| // if we are empty, just assign | |
| if (fLeft >= fRight || fTop >= fBottom) { | |
| *this = r; | |
| } else { | |
| this->joinPossiblyEmptyRect(r); | |
| } | |
| } | |
| /** Sets SkRect to the union of itself and the construction. | |
| May produce incorrect results if SkRect or r is empty. | |
| @param r expansion SkRect | |
| */ | |
| void joinPossiblyEmptyRect(const SkRect& r) { | |
| fLeft = std::min(fLeft, r.left()); | |
| fTop = std::min(fTop, r.top()); | |
| fRight = std::max(fRight, r.right()); | |
| fBottom = std::max(fBottom, r.bottom()); | |
| } | |
| /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom. | |
| Returns false if SkRect is empty. | |
| @param x test SkPoint x-coordinate | |
| @param y test SkPoint y-coordinate | |
| @return true if (x, y) is inside SkRect | |
| */ | |
| bool contains(float x, float y) const { | |
| return x >= fLeft && x < fRight && y >= fTop && y < fBottom; | |
| } | |
| /** Returns true if SkRect contains r. | |
| Returns false if SkRect is empty or r is empty. | |
| SkRect contains r when SkRect area completely includes r area. | |
| @param r SkRect contained | |
| @return true if all sides of SkRect are outside r | |
| */ | |
| bool contains(const SkRect& r) const { | |
| // todo: can we eliminate the this->isEmpty check? | |
| return !r.isEmpty() && !this->isEmpty() && | |
| fLeft <= r.fLeft && fTop <= r.fTop && | |
| fRight >= r.fRight && fBottom >= r.fBottom; | |
| } | |
| /** Returns true if SkRect contains r. | |
| Returns false if SkRect is empty or r is empty. | |
| SkRect contains r when SkRect area completely includes r area. | |
| @param r SkIRect contained | |
| @return true if all sides of SkRect are outside r | |
| */ | |
| bool contains(const SkIRect& r) const { | |
| // todo: can we eliminate the this->isEmpty check? | |
| return !r.isEmpty() && !this->isEmpty() && | |
| fLeft <= r.fLeft && fTop <= r.fTop && | |
| fRight >= r.fRight && fBottom >= r.fBottom; | |
| } | |
| /** Sets SkIRect by adding 0.5 and discarding the fractional portion of SkRect | |
| members, using (sk_float_round2int(fLeft), sk_float_round2int(fTop), | |
| sk_float_round2int(fRight), sk_float_round2int(fBottom)). | |
| @param dst storage for SkIRect | |
| */ | |
| void round(SkIRect* dst) const { | |
| SkASSERT(dst); | |
| dst->setLTRB(sk_float_round2int(fLeft), sk_float_round2int(fTop), | |
| sk_float_round2int(fRight), sk_float_round2int(fBottom)); | |
| } | |
| /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding | |
| up fRight and fBottom, using | |
| (sk_float_floor2int(fLeft), sk_float_floor2int(fTop), | |
| sk_float_ceil2int(fRight), sk_float_ceil2int(fBottom)). | |
| @param dst storage for SkIRect | |
| */ | |
| void roundOut(SkIRect* dst) const { | |
| SkASSERT(dst); | |
| dst->setLTRB(sk_float_floor2int(fLeft), sk_float_floor2int(fTop), | |
| sk_float_ceil2int(fRight), sk_float_ceil2int(fBottom)); | |
| } | |
| /** Sets SkRect by discarding the fractional portion of fLeft and fTop; and rounding | |
| up fRight and fBottom, using | |
| (std::floor(fLeft), std::floor(fTop), | |
| std::ceil(fRight), std::ceil(fBottom)). | |
| @param dst storage for SkRect | |
| */ | |
| void roundOut(SkRect* dst) const { | |
| dst->setLTRB(std::floor(fLeft), std::floor(fTop), | |
| std::ceil(fRight), std::ceil(fBottom)); | |
| } | |
| /** Sets SkRect by rounding up fLeft and fTop; and discarding the fractional portion | |
| of fRight and fBottom, using | |
| (sk_float_ceil2int(fLeft), sk_float_ceil2int(fTop), | |
| sk_float_floor2int(fRight), sk_float_floor2int(fBottom)). | |
| @param dst storage for SkIRect | |
| */ | |
| void roundIn(SkIRect* dst) const { | |
| SkASSERT(dst); | |
| dst->setLTRB(sk_float_ceil2int(fLeft), sk_float_ceil2int(fTop), | |
| sk_float_floor2int(fRight), sk_float_floor2int(fBottom)); | |
| } | |
| /** Returns SkIRect by adding 0.5 and discarding the fractional portion of SkRect | |
| members, using (sk_float_round2int(fLeft), sk_float_round2int(fTop), | |
| sk_float_round2int(fRight), sk_float_round2int(fBottom)). | |
| @return rounded SkIRect | |
| */ | |
| SkIRect round() const { | |
| SkIRect ir; | |
| this->round(&ir); | |
| return ir; | |
| } | |
| /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding | |
| up fRight and fBottom, using | |
| (sk_float_floor2int(fLeft), sk_float_floor2int(fTop), | |
| sk_float_ceil2int(fRight), sk_float_ceil2int(fBottom)). | |
| @return rounded SkIRect | |
| */ | |
| SkIRect roundOut() const { | |
| SkIRect ir; | |
| this->roundOut(&ir); | |
| return ir; | |
| } | |
| /** Sets SkIRect by rounding up fLeft and fTop; and discarding the fractional portion | |
| of fRight and fBottom, using | |
| (sk_float_ceil2int(fLeft), sk_float_ceil2int(fTop), | |
| sk_float_floor2int(fRight), sk_float_floor2int(fBottom)). | |
| @return rounded SkIRect | |
| */ | |
| SkIRect roundIn() const { | |
| SkIRect ir; | |
| this->roundIn(&ir); | |
| return ir; | |
| } | |
| /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps | |
| fTop and fBottom if fTop is greater than fBottom. Result may be empty; | |
| and width() and height() will be zero or positive. | |
| */ | |
| void sort() { | |
| using std::swap; | |
| if (fLeft > fRight) { | |
| swap(fLeft, fRight); | |
| } | |
| if (fTop > fBottom) { | |
| swap(fTop, fBottom); | |
| } | |
| } | |
| /** Returns SkRect with fLeft and fRight swapped if fLeft is greater than fRight; and | |
| with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty; | |
| and width() and height() will be zero or positive. | |
| @return sorted SkRect | |
| */ | |
| SkRect makeSorted() const { | |
| return MakeLTRB(std::min(fLeft, fRight), std::min(fTop, fBottom), | |
| std::max(fLeft, fRight), std::max(fTop, fBottom)); | |
| } | |
| /** Returns pointer to first float in SkRect, to treat it as an array with four | |
| entries. | |
| @return pointer to fLeft | |
| */ | |
| const float* asScalars() const { return &fLeft; } | |
| /** Writes text representation of SkRect to standard output. Set asHex to true to | |
| generate exact binary representations of floating point numbers. | |
| @param asHex true if SkScalar values are written as hexadecimal | |
| example: https://fiddle.skia.org/c/@Rect_dump | |
| */ | |
| void dump(bool asHex) const; | |
| SkString dumpToString(bool asHex) const; | |
| /** Writes text representation of SkRect to standard output. The representation may be | |
| directly compiled as C++ code. Floating point values are written | |
| with limited precision; it may not be possible to reconstruct original SkRect | |
| from output. | |
| */ | |
| void dump() const { this->dump(false); } | |
| /** Writes text representation of SkRect to standard output. The representation may be | |
| directly compiled as C++ code. Floating point values are written | |
| in hexadecimal to preserve their exact bit pattern. The output reconstructs the | |
| original SkRect. | |
| Use instead of dump() when submitting | |
| */ | |
| void dumpHex() const { this->dump(true); } | |
| }; | |
| inline bool SkIRect::contains(const SkRect& r) const { | |
| return !r.isEmpty() && !this->isEmpty() && // check for empties | |
| fLeft <= r.fLeft && fTop <= r.fTop && | |
| fRight >= r.fRight && fBottom >= r.fBottom; | |
| } | |
| #endif |