cc309eb9b1
The latest, minor changes on includes already generated, plus four new ones. TBR=reed@google.com Bug: skia:6898 Change-Id: If06ae9b9aaa3a0a9fae570aa7a6698ff340c43b8 Reviewed-on: https://skia-review.googlesource.com/62862 Commit-Queue: Cary Clark <caryclark@skia.org> Reviewed-by: Cary Clark <caryclark@skia.org>
1700 lines
62 KiB
C++
1700 lines
62 KiB
C++
/*
|
|
* 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 "SkPoint.h"
|
|
#include "SkSize.h"
|
|
#include "../private/SkTFitsIn.h"
|
|
|
|
struct SkRect;
|
|
|
|
/** \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 {
|
|
|
|
/** May contain any value. The smaller of the horizontal values when sorted.
|
|
When equal to or greater than fRight, SkIRect is empty.
|
|
*/
|
|
int32_t fLeft;
|
|
|
|
/** May contain any value. The smaller of the horizontal values when sorted.
|
|
When equal to or greater than fBottom, SkIRect is empty.
|
|
*/
|
|
int32_t fTop;
|
|
|
|
/** May contain any value. The larger of the vertical values when sorted.
|
|
When equal to or less than fLeft, SkIRect is empty.
|
|
*/
|
|
int32_t fRight;
|
|
|
|
/** May contain any value. The larger of the vertical values when sorted.
|
|
When equal to or less than fTop, SkIRect is empty.
|
|
*/
|
|
int32_t fBottom;
|
|
|
|
/** 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)
|
|
*/
|
|
static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeEmpty() {
|
|
return SkIRect{0, 0, 0, 0};
|
|
}
|
|
|
|
/** Returns constructed SkIRect setting left and top to most negative value, and
|
|
setting right and bottom to most positive value.
|
|
|
|
@return bounds (SK_MinS32, SK_MinS32, SK_MaxS32, SK_MaxS32)
|
|
*/
|
|
static SkIRect SK_WARN_UNUSED_RESULT MakeLargest() {
|
|
SkIRect r;
|
|
r.setLargest();
|
|
return r;
|
|
}
|
|
|
|
/** Returns constructed SkIRect set to (0, 0, w, h). Does not validate input; w or h
|
|
may be negative.
|
|
|
|
@param w width of constructed SkRect
|
|
@param h height of constructed SkRect
|
|
@return bounds (0, 0, w, h)
|
|
*/
|
|
static constexpr SkIRect SK_WARN_UNUSED_RESULT 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 SkRect width and height
|
|
@return bounds (0, 0, size.width(), size.height())
|
|
*/
|
|
static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeSize(const SkISize& size) {
|
|
return SkIRect{0, 0, size.fWidth, size.fHeight};
|
|
}
|
|
|
|
/** Returns constructed SkIRect 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 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)
|
|
*/
|
|
static constexpr SkIRect SK_WARN_UNUSED_RESULT 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
|
|
*/
|
|
static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h) {
|
|
return SkIRect{x, y, x + w, y + h};
|
|
}
|
|
|
|
/** Returns left edge of SkIRect, if sorted.
|
|
Call sort() to reverse fLeft and fRight if needed.
|
|
|
|
@return fLeft
|
|
*/
|
|
int 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
|
|
*/
|
|
int top() const { return fTop; }
|
|
|
|
/** Returns right edge of SkIRect, if sorted.
|
|
Call sort() to reverse fLeft and fRight if needed.
|
|
|
|
@return fRight
|
|
*/
|
|
int 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
|
|
*/
|
|
int 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
|
|
*/
|
|
int 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
|
|
*/
|
|
int y() const { return 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
|
|
*/
|
|
int width() const { return 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
|
|
*/
|
|
int height() const { return 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)
|
|
*/
|
|
SkISize size() const { return SkISize::Make(this->width(), this->height()); }
|
|
|
|
/** Returns average of left edge and right edge. Result does not change if SkRect
|
|
is sorted. Result may be incorrect if SkRect is far from the origin.
|
|
|
|
Result is rounded down.
|
|
|
|
@return midpoint in x
|
|
*/
|
|
int centerX() const { return (fRight + fLeft) >> 1; }
|
|
|
|
/** Returns average of top edge and bottom edge. Result does not change if SkRect
|
|
is sorted. Result may be incorrect if SkRect is far from the origin.
|
|
|
|
Result is rounded down.
|
|
|
|
@return midpoint in y
|
|
*/
|
|
int centerY() const { return (fBottom + fTop) >> 1; }
|
|
|
|
/** 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 { return fLeft >= fRight || fTop >= fBottom; }
|
|
|
|
/** Returns true if SkIRect encloses largest possible area.
|
|
|
|
@return true if equal to (SK_MinS32, SK_MinS32, SK_MaxS32, SK_MaxS32)
|
|
*/
|
|
bool isLargest() const { return SK_MinS32 == fLeft &&
|
|
SK_MinS32 == fTop &&
|
|
SK_MaxS32 == fRight &&
|
|
SK_MaxS32 == fBottom; }
|
|
|
|
/** 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 !memcmp(&a, &b, sizeof(a));
|
|
}
|
|
|
|
/** 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 == b);
|
|
}
|
|
|
|
/** Returns true if all members: fLeft, fTop, fRight, and fBottom; values are
|
|
equal to or larger than -32768 and equal to or smaller than 32767.
|
|
|
|
@return true if members fit in 16-bit word
|
|
*/
|
|
bool is16Bit() const {
|
|
return SkTFitsIn<int16_t>(fLeft) && SkTFitsIn<int16_t>(fTop) &&
|
|
SkTFitsIn<int16_t>(fRight) && SkTFitsIn<int16_t>(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 assigned to fLeft
|
|
@param top assigned to fTop
|
|
@param right assigned to fRight
|
|
@param bottom assigned to fBottom
|
|
*/
|
|
void set(int32_t left, int32_t top, int32_t right, int32_t bottom) {
|
|
fLeft = left;
|
|
fTop = top;
|
|
fRight = right;
|
|
fBottom = bottom;
|
|
}
|
|
|
|
/** 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) {
|
|
this->set(left, top, right, 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 = x + width;
|
|
fBottom = y + height;
|
|
}
|
|
|
|
/** Sets rectangle left and top to most negative value, and sets
|
|
right and bottom to most positive value.
|
|
*/
|
|
void setLargest() {
|
|
fLeft = fTop = SK_MinS32;
|
|
fRight = fBottom = SK_MaxS32;
|
|
}
|
|
|
|
/** Sets rectangle left and top to most positive value, and sets
|
|
right and bottom to most negative value. This is used internally to
|
|
flag that a condition is met, but otherwise has no special purpose.
|
|
*/
|
|
void setLargestInverted() {
|
|
fLeft = fTop = SK_MaxS32;
|
|
fRight = fBottom = SK_MinS32;
|
|
}
|
|
|
|
/** 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 SkRect offset in x or y, with original width and height
|
|
*/
|
|
SkIRect makeOffset(int32_t dx, int32_t dy) const {
|
|
return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy);
|
|
}
|
|
|
|
/** 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 SkRect inset symmetrically left and right, top and bottom
|
|
*/
|
|
SkIRect makeInset(int32_t dx, int32_t dy) const {
|
|
return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, 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 SkRect outset symmetrically left and right, top and bottom
|
|
*/
|
|
SkIRect makeOutset(int32_t dx, int32_t dy) const {
|
|
return MakeLTRB(fLeft - dx, fTop - dy, fRight + dx, 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 += dx;
|
|
fTop += dy;
|
|
fRight += dx;
|
|
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 += newX - fLeft;
|
|
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 += dx;
|
|
fTop += dy;
|
|
fRight -= dx;
|
|
fBottom -= dy;
|
|
}
|
|
|
|
/** Outsets SkIRect 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(int32_t dx, int32_t dy) { this->inset(-dx, -dy); }
|
|
|
|
/** Constructs SkIRect (l, t, r, b) and returns true if constructed SkIRect does not
|
|
intersect SkIRect. Does not check to see if construction or SkIRect is empty.
|
|
|
|
Is implemented with short circuit logic so that true can be returned after
|
|
a single compare.
|
|
|
|
@param l x minimum of constructed SkRect
|
|
@param t y minimum of constructed SkRect
|
|
@param r x maximum of constructed SkRect
|
|
@param b y maximum of constructed SkRect
|
|
@return true if construction and SkIRect have no area in common
|
|
*/
|
|
bool quickReject(int l, int t, int r, int b) const {
|
|
return l >= fRight || fLeft >= r || t >= fBottom || fTop >= b;
|
|
}
|
|
|
|
/** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
|
|
Returns false if SkRect 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 SkPoint x-coordinate
|
|
@param y test SkPoint y-coordinate
|
|
@return true if (x, y) is inside SkIRect
|
|
*/
|
|
bool contains(int32_t x, int32_t y) const {
|
|
return (unsigned)(x - fLeft) < (unsigned)(fRight - fLeft) &&
|
|
(unsigned)(y - fTop) < (unsigned)(fBottom - fTop);
|
|
}
|
|
|
|
/** Constructs SkRect to intersect from (left, top, right, bottom). Does not sort
|
|
construction.
|
|
|
|
Returns true if SkRect contains construction.
|
|
Returns false if SkRect is empty or construction is empty.
|
|
|
|
@param left x minimum of constructed SkRect
|
|
@param top y minimum of constructed SkRect
|
|
@param right x maximum of constructed SkRect
|
|
@param bottom y maximum of constructed SkRect
|
|
@return true if all sides of SkIRect are outside construction
|
|
*/
|
|
bool contains(int32_t left, int32_t top, int32_t right, int32_t bottom) const {
|
|
return left < right && top < bottom && !this->isEmpty() && // check for empties
|
|
fLeft <= left && fTop <= top &&
|
|
fRight >= right && fBottom >= bottom;
|
|
}
|
|
|
|
/** 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 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 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 SkIRect are outside r
|
|
*/
|
|
bool contains(const SkRect& r) const;
|
|
|
|
/** Constructs SkIRect from (left, top, right, bottom). Does not sort
|
|
construction.
|
|
|
|
Returns true if SkRect contains construction.
|
|
Asserts if SkIRect is empty or construction is empty, and if SK_DEBUG is defined.
|
|
|
|
Return is undefined if SkRect is empty or construction is empty.
|
|
|
|
@param left x minimum of constructed SkRect
|
|
@param top y minimum of constructed SkRect
|
|
@param right x maximum of constructed SkRect
|
|
@param bottom y maximum of constructed SkRect
|
|
@return true if all sides of SkIRect are outside construction
|
|
*/
|
|
bool containsNoEmptyCheck(int32_t left, int32_t top,
|
|
int32_t right, int32_t bottom) const {
|
|
SkASSERT(fLeft < fRight && fTop < fBottom);
|
|
SkASSERT(left < right && top < bottom);
|
|
|
|
return fLeft <= left && fTop <= top &&
|
|
fRight >= right && fBottom >= bottom;
|
|
}
|
|
|
|
/** Returns true if SkRect contains construction.
|
|
Asserts if SkIRect is empty or construction is empty, and if SK_DEBUG is defined.
|
|
|
|
Return is undefined if SkRect is empty or construction is empty.
|
|
|
|
@param r SkRect contained
|
|
@return true if all sides of SkIRect are outside r
|
|
*/
|
|
bool containsNoEmptyCheck(const SkIRect& r) const {
|
|
return containsNoEmptyCheck(r.fLeft, r.fTop, r.fRight, 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 SkRect have area in common
|
|
*/
|
|
bool intersect(const SkIRect& r) {
|
|
return this->intersect(r.fLeft, r.fTop, r.fRight, r.fBottom);
|
|
}
|
|
|
|
/** 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
|
|
*/
|
|
bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& a, const SkIRect& b) {
|
|
|
|
if (!a.isEmpty() && !b.isEmpty() &&
|
|
a.fLeft < b.fRight && b.fLeft < a.fRight &&
|
|
a.fTop < b.fBottom && b.fTop < a.fBottom) {
|
|
fLeft = SkMax32(a.fLeft, b.fLeft);
|
|
fTop = SkMax32(a.fTop, b.fTop);
|
|
fRight = SkMin32(a.fRight, b.fRight);
|
|
fBottom = SkMin32(a.fBottom, b.fBottom);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/** Returns true if a intersects b, and sets SkIRect to intersection.
|
|
Returns false if a does not intersect b, and leaves SkIRect unchanged.
|
|
|
|
Asserts if either a or b is empty, and if SK_DEBUG is defined.
|
|
|
|
@param a SkIRect to intersect
|
|
@param b SkIRect to intersect
|
|
@return true if a and b have area in common
|
|
*/
|
|
bool SK_WARN_UNUSED_RESULT intersectNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
|
|
SkASSERT(!a.isEmpty() && !b.isEmpty());
|
|
|
|
if (a.fLeft < b.fRight && b.fLeft < a.fRight &&
|
|
a.fTop < b.fBottom && b.fTop < a.fBottom) {
|
|
fLeft = SkMax32(a.fLeft, b.fLeft);
|
|
fTop = SkMax32(a.fTop, b.fTop);
|
|
fRight = SkMin32(a.fRight, b.fRight);
|
|
fBottom = SkMin32(a.fBottom, b.fBottom);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/** Constructs SkIRect to intersect from (left, top, right, bottom). Does not sort
|
|
construction.
|
|
|
|
Returns true if SkIRect intersects construction, and sets SkIRect to intersection.
|
|
Returns false if SkIRect does not intersect construction, and leaves SkIRect unchanged.
|
|
|
|
Returns false if either construction or SkIRect is empty, leaving SkIRect unchanged.
|
|
|
|
@param left x minimum of constructed SkIRect
|
|
@param top y minimum of constructed SkIRect
|
|
@param right x maximum of constructed SkIRect
|
|
@param bottom y maximum of constructed SkIRect
|
|
@return true if construction and SkIRect have area in common
|
|
*/
|
|
bool intersect(int32_t left, int32_t top, int32_t right, int32_t bottom) {
|
|
if (left < right && top < bottom && !this->isEmpty() &&
|
|
fLeft < right && left < fRight && fTop < bottom && top < fBottom) {
|
|
if (fLeft < left) fLeft = left;
|
|
if (fTop < top) fTop = top;
|
|
if (fRight > right) fRight = right;
|
|
if (fBottom > bottom) fBottom = bottom;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/** 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 !a.isEmpty() && !b.isEmpty() && // check for empties
|
|
a.fLeft < b.fRight && b.fLeft < a.fRight &&
|
|
a.fTop < b.fBottom && b.fTop < a.fBottom;
|
|
}
|
|
|
|
/** Returns true if a intersects b.
|
|
Asserts if either a or b is empty, and if SK_DEBUG is defined.
|
|
|
|
@param a SkIRect to intersect
|
|
@param b SkIRect to intersect
|
|
@return true if a and b have area in common
|
|
*/
|
|
static bool IntersectsNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
|
|
SkASSERT(!a.isEmpty());
|
|
SkASSERT(!b.isEmpty());
|
|
return a.fLeft < b.fRight && b.fLeft < a.fRight &&
|
|
a.fTop < b.fBottom && b.fTop < a.fBottom;
|
|
}
|
|
|
|
/** Constructs SkRect to intersect from (left, top, right, bottom). Does not sort
|
|
construction.
|
|
|
|
Sets SkRect to the union of itself and the construction.
|
|
|
|
Has no effect if construction is empty. Otherwise, if SkRect is empty, sets
|
|
SkRect to construction.
|
|
|
|
@param left x minimum of constructed SkRect
|
|
@param top y minimum of constructed SkRect
|
|
@param right x maximum of constructed SkRect
|
|
@param bottom y maximum of constructed SkRect
|
|
*/
|
|
void join(int32_t left, int32_t top, int32_t right, int32_t bottom);
|
|
|
|
/** 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
|
|
*/
|
|
void join(const SkIRect& r) {
|
|
this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
|
|
}
|
|
|
|
/** 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() {
|
|
if (fLeft > fRight) {
|
|
SkTSwap<int32_t>(fLeft, fRight);
|
|
}
|
|
if (fTop > fBottom) {
|
|
SkTSwap<int32_t>(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 SkIRect
|
|
*/
|
|
SkIRect makeSorted() const {
|
|
return MakeLTRB(SkMin32(fLeft, fRight), SkMin32(fTop, fBottom),
|
|
SkMax32(fLeft, fRight), SkMax32(fTop, fBottom));
|
|
}
|
|
|
|
/** Returns a reference to immutable empty SkIRect, set to (0, 0, 0, 0).
|
|
|
|
@return global SkIRect set to all zeroes
|
|
*/
|
|
static const SkIRect& SK_WARN_UNUSED_RESULT EmptyIRect() {
|
|
static const SkIRect gEmpty = { 0, 0, 0, 0 };
|
|
return gEmpty;
|
|
}
|
|
};
|
|
|
|
/** \struct SkRect
|
|
SkRect holds four SkScalar 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 {
|
|
|
|
/** May contain any value, including infinities and NaN. The smaller of the
|
|
horizontal values when sorted. When equal to or greater than fRight, SkRect is empty.
|
|
*/
|
|
SkScalar fLeft;
|
|
|
|
/** May contain any value, including infinities and NaN. The smaller of the
|
|
vertical values when sorted. When equal to or greater than fBottom, SkRect is empty.
|
|
*/
|
|
SkScalar fTop;
|
|
|
|
/** May contain any value, including infinities and NaN. The larger of the
|
|
horizontal values when sorted. When equal to or less than fLeft, SkRect is empty.
|
|
*/
|
|
SkScalar fRight;
|
|
|
|
/** May contain any value, including infinities and NaN. The larger of the
|
|
vertical values when sorted. When equal to or less than fTop, SkRect is empty.
|
|
*/
|
|
SkScalar fBottom;
|
|
|
|
/** 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)
|
|
*/
|
|
static constexpr SkRect SK_WARN_UNUSED_RESULT MakeEmpty() {
|
|
return SkRect{0, 0, 0, 0};
|
|
}
|
|
|
|
/** Returns constructed SkRect setting left and top to most negative finite value, and
|
|
setting right and bottom to most positive finite value.
|
|
|
|
@return bounds (SK_ScalarMin, SK_ScalarMin, SK_ScalarMax, SK_ScalarMax)
|
|
*/
|
|
static SkRect SK_WARN_UNUSED_RESULT MakeLargest() {
|
|
SkRect r;
|
|
r.setLargest();
|
|
return r;
|
|
}
|
|
|
|
/** Returns constructed SkRect that can be represented exactly with SkIRect. The left
|
|
and top are set to the most negative integer value that fits in a 32-bit float,
|
|
and the right and bottom are set to the most positive finite value that fits in
|
|
a 32-bit float.
|
|
|
|
These are the largest values for which round() is well defined.
|
|
|
|
@return bounds (SK_MinS32FitsInFloat, SK_MinS32FitsInFloat,
|
|
SK_MaxS32FitsInFloat, SK_MaxS32FitsInFloat)
|
|
*/
|
|
static SkRect SK_WARN_UNUSED_RESULT MakeLargestS32() {
|
|
const SkRect r = MakeLTRB(SK_MinS32FitsInFloat, SK_MinS32FitsInFloat,
|
|
SK_MaxS32FitsInFloat, SK_MaxS32FitsInFloat);
|
|
SkASSERT(r == Make(r.roundOut()));
|
|
return r;
|
|
}
|
|
|
|
/** Returns constructed SkRect set to SkScalar 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 SkScalar width of constructed SkRect
|
|
@param h SkScalar height of constructed SkRect
|
|
@return bounds (0, 0, w, h)
|
|
*/
|
|
static constexpr SkRect SK_WARN_UNUSED_RESULT MakeWH(SkScalar w, SkScalar 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)
|
|
*/
|
|
static SkRect SK_WARN_UNUSED_RESULT MakeIWH(int w, int h) {
|
|
SkRect r;
|
|
r.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
|
|
return r;
|
|
}
|
|
|
|
/** 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 SkScalar values for SkRect width and height
|
|
@return bounds (0, 0, size.width(), size.height())
|
|
*/
|
|
static constexpr SkRect SK_WARN_UNUSED_RESULT 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 SkScalar stored in fLeft
|
|
@param t SkScalar stored in fTop
|
|
@param r SkScalar stored in fRight
|
|
@param b SkScalar stored in fBottom
|
|
@return bounds (l, t, r, b)
|
|
*/
|
|
static constexpr SkRect SK_WARN_UNUSED_RESULT MakeLTRB(SkScalar l, SkScalar t, SkScalar r,
|
|
SkScalar 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
|
|
*/
|
|
static constexpr SkRect SK_WARN_UNUSED_RESULT MakeXYWH(SkScalar x, SkScalar y, SkScalar w, SkScalar h) {
|
|
return SkRect {x, y, x + w, y + h};
|
|
}
|
|
|
|
/** Deprecated.
|
|
|
|
@param irect integer rect
|
|
@return irect as SkRect
|
|
*/
|
|
SK_ATTR_DEPRECATED("use Make()")
|
|
static SkRect SK_WARN_UNUSED_RESULT MakeFromIRect(const SkIRect& irect) {
|
|
SkRect r;
|
|
r.set(SkIntToScalar(irect.fLeft),
|
|
SkIntToScalar(irect.fTop),
|
|
SkIntToScalar(irect.fRight),
|
|
SkIntToScalar(irect.fBottom));
|
|
return r;
|
|
}
|
|
|
|
/** 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 scalar.
|
|
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 SkScalar
|
|
*/
|
|
static SkRect SK_WARN_UNUSED_RESULT Make(const SkIRect& irect) {
|
|
SkRect r;
|
|
r.set(SkIntToScalar(irect.fLeft),
|
|
SkIntToScalar(irect.fTop),
|
|
SkIntToScalar(irect.fRight),
|
|
SkIntToScalar(irect.fBottom));
|
|
return r;
|
|
}
|
|
|
|
/** 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 { 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 SkRect encloses largest possible area.
|
|
|
|
@return true if equal to (SK_ScalarMin, SK_ScalarMin, SK_ScalarMax, SK_ScalarMax)
|
|
*/
|
|
bool isLargest() const { return SK_ScalarMin == fLeft &&
|
|
SK_ScalarMin == fTop &&
|
|
SK_ScalarMax == fRight &&
|
|
SK_ScalarMax == fBottom; }
|
|
|
|
/** Returns true if all values in the rectangle are finite: SK_ScalarMin or larger,
|
|
and SK_ScalarMax or smaller.
|
|
|
|
@return true if no member is infinite or NaN
|
|
*/
|
|
bool isFinite() const {
|
|
float accum = 0;
|
|
accum *= fLeft;
|
|
accum *= fTop;
|
|
accum *= fRight;
|
|
accum *= fBottom;
|
|
|
|
// accum is either NaN or it is finite (zero).
|
|
SkASSERT(0 == accum || SkScalarIsNaN(accum));
|
|
|
|
// value==value will be true iff value is not NaN
|
|
// TODO: is it faster to say !accum or accum==accum?
|
|
return !SkScalarIsNaN(accum);
|
|
}
|
|
|
|
/** 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
|
|
*/
|
|
SkScalar 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
|
|
*/
|
|
SkScalar 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
|
|
*/
|
|
SkScalar 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
|
|
*/
|
|
SkScalar 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
|
|
*/
|
|
SkScalar 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
|
|
*/
|
|
SkScalar 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
|
|
*/
|
|
SkScalar width() const { return fRight - fLeft; }
|
|
|
|
/** Returns span on the y-axis. This does not check if SkIRect is sorted, or if
|
|
result fits in 32-bit float; result may be negative or infinity.
|
|
|
|
@return fBottom minus fTop
|
|
*/
|
|
SkScalar 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 in x
|
|
*/
|
|
SkScalar centerX() const { return SkScalarHalf(fLeft + fRight); }
|
|
|
|
/** Returns average of top edge and bottom edge. Result does not change if SkRect
|
|
is sorted. Result may overflow to infinity if SkRect is far from the origin.
|
|
|
|
@return midpoint in y
|
|
*/
|
|
SkScalar centerY() const { return SkScalarHalf(fTop + fBottom); }
|
|
|
|
/** 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 width 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 SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);
|
|
}
|
|
|
|
/** 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 width 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 !SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);
|
|
}
|
|
|
|
/** Returns four points in quad that enclose SkRect ordered as: top-left, top-right,
|
|
bottom-right, bottom-left.
|
|
Consider adding param to control whether quad is CW or CCW.
|
|
|
|
@param quad storage for corners of SkRect
|
|
*/
|
|
void toQuad(SkPoint quad[4]) const;
|
|
|
|
/** 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 scalar.
|
|
Very large values in src may lose precision.
|
|
|
|
@param src integer SkRect
|
|
*/
|
|
void set(const SkIRect& src) {
|
|
fLeft = SkIntToScalar(src.fLeft);
|
|
fTop = SkIntToScalar(src.fTop);
|
|
fRight = SkIntToScalar(src.fRight);
|
|
fBottom = SkIntToScalar(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 set(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
|
|
fLeft = left;
|
|
fTop = top;
|
|
fRight = right;
|
|
fBottom = bottom;
|
|
}
|
|
|
|
/** 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(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
|
|
this->set(left, top, right, bottom);
|
|
}
|
|
|
|
/** Sets SkRect to (left, top, right, bottom).
|
|
All parameters are promoted from integer to scalar.
|
|
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 promoted to SkScalar and stored in fLeft
|
|
@param top promoted to SkScalar and stored in fTop
|
|
@param right promoted to SkScalar and stored in fRight
|
|
@param bottom promoted to SkScalar and stored in fBottom
|
|
*/
|
|
void iset(int left, int top, int right, int bottom) {
|
|
fLeft = SkIntToScalar(left);
|
|
fTop = SkIntToScalar(top);
|
|
fRight = SkIntToScalar(right);
|
|
fBottom = SkIntToScalar(bottom);
|
|
}
|
|
|
|
/** Sets SkRect to (0, 0, width, height).
|
|
width and height may be zero or negative. width and height are promoted from
|
|
integer to SkScalar, large values may lose precision.
|
|
|
|
@param width promoted to SkScalar and stored in fRight
|
|
@param height promoted to SkScalar and stored in fBottom
|
|
*/
|
|
void isetWH(int width, int height) {
|
|
fLeft = fTop = 0;
|
|
fRight = SkIntToScalar(width);
|
|
fBottom = SkIntToScalar(height);
|
|
}
|
|
|
|
/** 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 SkRect 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 array
|
|
@param count entries in array
|
|
*/
|
|
void set(const SkPoint pts[], int count) {
|
|
// set() had been checking for non-finite values, so keep that behavior
|
|
// for now. Now that we have setBoundsCheck(), we may decide to make
|
|
// set() be simpler/faster, and not check for those.
|
|
(void)this->setBoundsCheck(pts, count);
|
|
}
|
|
|
|
/** 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 array
|
|
@param count entries in array
|
|
*/
|
|
void setBounds(const SkPoint pts[], int count) {
|
|
(void)this->setBoundsCheck(pts, count);
|
|
}
|
|
|
|
/** Sets to bounds of SkPoint array with count entries. Returns false if count is
|
|
zero or smaller, or if SkPoint array contains an infinity or NaN; in these cases
|
|
sets SkRect 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 array
|
|
@param count entries in array
|
|
@return true if all SkPoint values are finite
|
|
*/
|
|
bool setBoundsCheck(const SkPoint pts[], int count);
|
|
|
|
/** Sets bounds to the smallest SkRect enclosing points 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 = SkMinScalar(p0.fX, p1.fX);
|
|
fRight = SkMaxScalar(p0.fX, p1.fX);
|
|
fTop = SkMinScalar(p0.fY, p1.fY);
|
|
fBottom = SkMaxScalar(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(SkScalar x, SkScalar y, SkScalar width, SkScalar 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(SkScalar width, SkScalar height) {
|
|
fLeft = 0;
|
|
fTop = 0;
|
|
fRight = width;
|
|
fBottom = height;
|
|
}
|
|
|
|
/** Sets rectangle left and top to most negative finite value, and sets
|
|
right and bottom to most positive finite value.
|
|
*/
|
|
void setLargest() {
|
|
fLeft = fTop = SK_ScalarMin;
|
|
fRight = fBottom = SK_ScalarMax;
|
|
}
|
|
|
|
/** Sets rectangle left and top to most positive finite value, and sets
|
|
right and bottom to most negative finite value.
|
|
|
|
Use to initial SkRect before one or more calls to growToInclude().
|
|
*/
|
|
void setLargestInverted() {
|
|
fLeft = fTop = SK_ScalarMax;
|
|
fRight = fBottom = SK_ScalarMin;
|
|
}
|
|
|
|
/** 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 in x or y, with original width and height
|
|
*/
|
|
SkRect makeOffset(SkScalar dx, SkScalar dy) const {
|
|
return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy);
|
|
}
|
|
|
|
/** 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(SkScalar dx, SkScalar 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(SkScalar dx, SkScalar 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(SkScalar dx, SkScalar 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(SkScalar newX, SkScalar 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(SkScalar dx, SkScalar 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(SkScalar dx, SkScalar 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
|
|
*/
|
|
bool intersect(const SkRect& r);
|
|
|
|
/** Constructs SkRect to intersect from (left, top, right, bottom). Does not sort
|
|
construction.
|
|
|
|
Returns true if SkRect intersects construction, and sets SkRect to intersection.
|
|
Returns false if SkRect does not intersect construction, and leaves SkRect unchanged.
|
|
|
|
Returns false if either construction or SkRect is empty, leaving SkRect unchanged.
|
|
|
|
@param left x minimum of constructed SkRect
|
|
@param top y minimum of constructed SkRect
|
|
@param right x maximum of constructed SkRect
|
|
@param bottom y maximum of constructed SkRect
|
|
@return true if construction and SkRect have area in common
|
|
*/
|
|
bool intersect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
|
|
|
|
/** 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
|
|
*/
|
|
bool SK_WARN_UNUSED_RESULT intersect(const SkRect& a, const SkRect& b);
|
|
|
|
|
|
private:
|
|
static bool Intersects(SkScalar al, SkScalar at, SkScalar ar, SkScalar ab,
|
|
SkScalar bl, SkScalar bt, SkScalar br, SkScalar bb) {
|
|
SkScalar L = SkMaxScalar(al, bl);
|
|
SkScalar R = SkMinScalar(ar, br);
|
|
SkScalar T = SkMaxScalar(at, bt);
|
|
SkScalar B = SkMinScalar(ab, bb);
|
|
return L < R && T < B;
|
|
}
|
|
|
|
public:
|
|
|
|
/** Constructs SkRect to intersect from (left, top, right, bottom). Does not sort
|
|
construction.
|
|
|
|
Returns true if SkRect intersects construction.
|
|
Returns false if either construction or SkRect is empty, or do not intersect.
|
|
|
|
@param left x minimum of constructed SkRect
|
|
@param top y minimum of constructed SkRect
|
|
@param right x maximum of constructed SkRect
|
|
@param bottom y maximum of constructed SkRect
|
|
@return true if construction and SkRect have area in common
|
|
*/
|
|
bool intersects(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) const {
|
|
return Intersects(fLeft, fTop, fRight, fBottom, left, top, right, bottom);
|
|
}
|
|
|
|
/** 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);
|
|
}
|
|
|
|
/** Constructs SkRect to intersect from (left, top, right, bottom). Does not sort
|
|
construction.
|
|
|
|
Sets SkRect to the union of itself and the construction.
|
|
|
|
Has no effect if construction is empty. Otherwise, if SkRect is empty, sets
|
|
SkRect to construction.
|
|
|
|
@param left x minimum of constructed SkRect
|
|
@param top y minimum of constructed SkRect
|
|
@param right x maximum of constructed SkRect
|
|
@param bottom y maximum of constructed SkRect
|
|
*/
|
|
void join(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
|
|
|
|
/** 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
|
|
*/
|
|
void join(const SkRect& r) {
|
|
this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
|
|
}
|
|
|
|
/** 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 = SkMinScalar(fLeft, r.left());
|
|
fTop = SkMinScalar(fTop, r.top());
|
|
fRight = SkMaxScalar(fRight, r.right());
|
|
fBottom = SkMaxScalar(fBottom, r.bottom());
|
|
}
|
|
|
|
/** Grows SkRect to include (pt.fX, pt.fY), modifying it so that:
|
|
fLeft <= pt.fX <= fRight && fTop <= pt.fY <= fBottom.
|
|
|
|
If SkRect is initialized with setLargestInverted(), then SkRect will contain bounds of
|
|
points after one or more calls. In this case, SkRect is empty after first call.
|
|
|
|
@param pt SkPoint to include
|
|
*/
|
|
void growToInclude(SkPoint pt) {
|
|
fLeft = SkMinScalar(pt.fX, fLeft);
|
|
fRight = SkMaxScalar(pt.fX, fRight);
|
|
fTop = SkMinScalar(pt.fY, fTop);
|
|
fBottom = SkMaxScalar(pt.fY, fBottom);
|
|
}
|
|
|
|
/** For each of count SkPoint in pts, grows SkRect to include (pt.fX, pt.fY), modifying
|
|
it so that: fLeft <= pt.fX <= fRight && fTop <= pt.fY <= fBottom.
|
|
|
|
If SkRect is initialized with setLargestInverted(), then SkRect will contain bounds of
|
|
points after one or more calls. In this case, SkRect is empty after first call.
|
|
|
|
@param pts SkPoint array
|
|
@param count number of points in array
|
|
*/
|
|
void growToInclude(const SkPoint pts[], int count) {
|
|
this->growToInclude(pts, sizeof(SkPoint), count);
|
|
}
|
|
|
|
/** For each of count SkPoint in pts, grows SkRect to include (pt.fX, pt.fY), modifying
|
|
it so that: fLeft <= pt.fX <= fRight && fTop <= pt.fY <= fBottom.
|
|
|
|
SkPoint may be followed with other data in each array element. stride is number
|
|
of bytes in element; the interval to skip to advance from one SkPoint to
|
|
the next.
|
|
|
|
If SkRect is initialized with setLargestInverted(), then SkRect will contain bounds of
|
|
points after one or more calls. In this case, SkRect is empty after first call.
|
|
|
|
@param pts array of elements beginning with SkPoint
|
|
@param stride size of pts elements in 32-bit words; zero or greater
|
|
@param count number of elements in array
|
|
*/
|
|
void growToInclude(const SkPoint pts[], size_t stride, int count) {
|
|
SkASSERT(count >= 0);
|
|
SkASSERT(stride >= sizeof(SkPoint));
|
|
const SkPoint* end = (const SkPoint*)((intptr_t)pts + count * stride);
|
|
for (; pts < end; pts = (const SkPoint*)((intptr_t)pts + stride)) {
|
|
this->growToInclude(*pts);
|
|
}
|
|
}
|
|
|
|
/** 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 <= SkIntToScalar(r.fLeft) && fTop <= SkIntToScalar(r.fTop) &&
|
|
fRight >= SkIntToScalar(r.fRight) && fBottom >= SkIntToScalar(r.fBottom);
|
|
}
|
|
|
|
/** Sets SkIRect by adding 0.5 and discarding the fractional portion of SkRect
|
|
members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
|
|
SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).
|
|
|
|
@param dst storage for SkIRect
|
|
*/
|
|
void round(SkIRect* dst) const {
|
|
SkASSERT(dst);
|
|
dst->set(SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
|
|
SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom));
|
|
}
|
|
|
|
/** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and
|
|
rounding up fRight and fbottom, using (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
|
|
SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
|
|
|
|
@param dst storage for SkIRect
|
|
*/
|
|
void roundOut(SkIRect* dst) const {
|
|
SkASSERT(dst);
|
|
dst->set(SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
|
|
SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom));
|
|
}
|
|
|
|
/** Sets SkRect by discarding the fractional portion of fLeft and fTop; and
|
|
rounding up fRight and fbottom, using (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
|
|
SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
|
|
|
|
@param dst storage for SkRect
|
|
*/
|
|
void roundOut(SkRect* dst) const {
|
|
dst->set(SkScalarFloorToScalar(fLeft),
|
|
SkScalarFloorToScalar(fTop),
|
|
SkScalarCeilToScalar(fRight),
|
|
SkScalarCeilToScalar(fBottom));
|
|
}
|
|
|
|
/** Sets SkRect by rounding up fLeft and fTop; and
|
|
discarding the fractional portion of fRight and fbottom, using
|
|
(SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
|
|
SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom)).
|
|
|
|
@param dst storage for SkIRect
|
|
*/
|
|
void roundIn(SkIRect* dst) const {
|
|
SkASSERT(dst);
|
|
dst->set(SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
|
|
SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom));
|
|
}
|
|
|
|
/** Returns SkIRect by adding 0.5 and discarding the fractional portion of SkRect
|
|
members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
|
|
SkScalarRoundToInt(fRight), SkScalarRoundToInt(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 (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
|
|
SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
|
|
|
|
@return rounded SkIRect
|
|
*/
|
|
SkIRect roundOut() const {
|
|
SkIRect ir;
|
|
this->roundOut(&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() {
|
|
if (fLeft > fRight) {
|
|
SkTSwap<SkScalar>(fLeft, fRight);
|
|
}
|
|
|
|
if (fTop > fBottom) {
|
|
SkTSwap<SkScalar>(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(SkMinScalar(fLeft, fRight), SkMinScalar(fTop, fBottom),
|
|
SkMaxScalar(fLeft, fRight), SkMaxScalar(fTop, fBottom));
|
|
}
|
|
|
|
/** Returns pointer to first scalar in SkRect, to treat it as an array with four
|
|
entries.
|
|
|
|
@return pointer to fLeft
|
|
*/
|
|
const SkScalar* 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
|
|
*/
|
|
void dump(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
|
|
(SkScalar)fLeft <= r.fLeft && (SkScalar)fTop <= r.fTop &&
|
|
(SkScalar)fRight >= r.fRight && (SkScalar)fBottom >= r.fBottom;
|
|
}
|
|
|
|
#endif
|