SkRect.h revision 363e546ed626b6dbbc42f5db87b3594bc0b5944b
1bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
2bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/*
3bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com * Copyright 2006 The Android Open Source Project
4bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com *
5bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com * Use of this source code is governed by a BSD-style license that can be
6bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com * found in the LICENSE file.
7bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com */
8bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
9bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
10bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifndef SkRect_DEFINED
11bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define SkRect_DEFINED
12bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
13bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkPoint.h"
14bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkSize.h"
15bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
16bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/** \struct SkIRect
17bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
18bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkIRect holds four 32 bit integer coordinates for a rectangle
19bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com*/
20bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstruct SK_API SkIRect {
21bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int32_t fLeft, fTop, fRight, fBottom;
22bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
23b35fe4e1b04229a849227ea6c2561fe84929ab8breed@android.com    static SkIRect SK_WARN_UNUSED_RESULT MakeEmpty() {
24bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkIRect r;
25bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        r.setEmpty();
26bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return r;
2797c4201c2ce2cad089d7a7edbf405bf2cbdf5329reed@android.com    }
28cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com
29bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    static SkIRect SK_WARN_UNUSED_RESULT MakeWH(int32_t w, int32_t h) {
30bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkIRect r;
31bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        r.set(0, 0, w, h);
32bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return r;
33bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
34bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
35bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    static SkIRect SK_WARN_UNUSED_RESULT MakeSize(const SkISize& size) {
36bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkIRect r;
37bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        r.set(0, 0, size.width(), size.height());
38bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return r;
39bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
40bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
41bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    static SkIRect SK_WARN_UNUSED_RESULT MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b) {
42bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkIRect rect;
43bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        rect.set(l, t, r, b);
44bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return rect;
45bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
46bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
47bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    static SkIRect SK_WARN_UNUSED_RESULT MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h) {
48bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkIRect r;
49bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        r.set(x, y, x + w, y + h);
50bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return r;
51bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
52bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
53bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int left() const { return fLeft; }
54bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int top() const { return fTop; }
55bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int right() const { return fRight; }
56bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int bottom() const { return fBottom; }
57bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
58bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /** return the left edge of the rect */
59bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int x() const { return fLeft; }
60bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /** return the top edge of the rect */
61bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int y() const { return fTop; }
62bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /**
63bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  Returns the rectangle's width. This does not check for a valid rect
64bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  (i.e. left <= right) so the result may be negative.
65bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     */
66bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int width() const { return fRight - fLeft; }
67bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
68bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /**
69bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  Returns the rectangle's height. This does not check for a valid rect
70bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  (i.e. top <= bottom) so the result may be negative.
71bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     */
72bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int height() const { return fBottom - fTop; }
73bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
74bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /**
75bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  Since the center of an integer rect may fall on a factional value, this
76bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  method is defined to return (right + left) >> 1.
77bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *
78bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  This is a specific "truncation" of the average, which is different than
79bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  (right + left) / 2 when the sum is negative.
80bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     */
81bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int centerX() const { return (fRight + fLeft) >> 1; }
82bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
83bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /**
84bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  Since the center of an integer rect may fall on a factional value, this
85bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  method is defined to return (bottom + top) >> 1
86bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *
87bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  This is a specific "truncation" of the average, which is different than
88bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  (bottom + top) / 2 when the sum is negative.
89bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     */
90bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int centerY() const { return (fBottom + fTop) >> 1; }
91bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
92bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /**
93bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  Return true if the rectangle's width or height are <= 0
94bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     */
95bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; }
96bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
97bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    friend bool operator==(const SkIRect& a, const SkIRect& b) {
98bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return !memcmp(&a, &b, sizeof(a));
99bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
100bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
101bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    friend bool operator!=(const SkIRect& a, const SkIRect& b) {
102bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return !(a == b);
103bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
104bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
105bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bool is16Bit() const {
106bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return  SkIsS16(fLeft) && SkIsS16(fTop) &&
107bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                SkIsS16(fRight) && SkIsS16(fBottom);
108bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
109bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
110bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /** Set the rectangle to (0,0,0,0)
111bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    */
112bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void setEmpty() { memset(this, 0, sizeof(*this)); }
113bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
114bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void set(int32_t left, int32_t top, int32_t right, int32_t bottom) {
115bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fLeft   = left;
116bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fTop    = top;
117bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fRight  = right;
118bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fBottom = bottom;
119bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
120bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // alias for set(l, t, r, b)
121bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom) {
122bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        this->set(left, top, right, bottom);
123bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
124bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
125bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height) {
126bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fLeft = x;
127bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fTop = y;
128bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fRight = x + width;
129bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fBottom = y + height;
130c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com    }
131c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com
132bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /**
133bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  Make the largest representable rectangle
134bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     */
135c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com    void setLargest() {
136bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fLeft = fTop = SK_MinS32;
137bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fRight = fBottom = SK_MaxS32;
138bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
139bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
140bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /**
141bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  Make the largest representable rectangle, but inverted (e.g. fLeft will
142bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  be max 32bit and right will be min 32bit).
143bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     */
144bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void setLargestInverted() {
145bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fLeft = fTop = SK_MaxS32;
146bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fRight = fBottom = SK_MinS32;
147bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
148bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
149bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /** Offset set the rectangle by adding dx to its left and right,
150bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        and adding dy to its top and bottom.
151bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    */
152bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void offset(int32_t dx, int32_t dy) {
153bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fLeft   += dx;
154bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fTop    += dy;
155bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fRight  += dx;
156bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fBottom += dy;
157bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
158bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
159bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void offset(const SkIPoint& delta) {
160bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        this->offset(delta.fX, delta.fY);
161bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
162bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
163bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /**
164bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  Offset this rect such its new x() and y() will equal newX and newY.
165bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     */
166bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void offsetTo(int32_t newX, int32_t newY) {
167bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fRight += newX - fLeft;
168bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fBottom += newY - fTop;
169bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fLeft = newX;
170bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fTop = newY;
171bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
172bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
173bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /** Inset the rectangle by (dx,dy). If dx is positive, then the sides are moved inwards,
174bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        making the rectangle narrower. If dx is negative, then the sides are moved outwards,
175bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        making the rectangle wider. The same holds true for dy and the top and bottom.
176bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    */
177bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void inset(int32_t dx, int32_t dy) {
178bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fLeft   += dx;
179bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fTop    += dy;
180bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fRight  -= dx;
181bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fBottom -= dy;
182bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
183bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
184bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com   /** Outset the rectangle by (dx,dy). If dx is positive, then the sides are
185bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com       moved outwards, making the rectangle wider. If dx is negative, then the
186bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com       sides are moved inwards, making the rectangle narrower. The same holds
187bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com       true for dy and the top and bottom.
188bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    */
189bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void outset(int32_t dx, int32_t dy)  { this->inset(-dx, -dy); }
190bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
191bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bool quickReject(int l, int t, int r, int b) const {
192bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return l >= fRight || fLeft >= r || t >= fBottom || fTop >= b;
193bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
194bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
195bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /** Returns true if (x,y) is inside the rectangle and the rectangle is not
196bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        empty. The left and top are considered to be inside, while the right
197bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        and bottom are not. Thus for the rectangle (0, 0, 5, 10), the
198bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        points (0,0) and (0,9) are inside, while (-1,0) and (5,9) are not.
199bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    */
200bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bool contains(int32_t x, int32_t y) const {
201bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return  (unsigned)(x - fLeft) < (unsigned)(fRight - fLeft) &&
202bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                (unsigned)(y - fTop) < (unsigned)(fBottom - fTop);
203bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
204bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
205bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /** Returns true if the 4 specified sides of a rectangle are inside or equal to this rectangle.
206bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        If either rectangle is empty, contains() returns false.
207bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    */
208bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bool contains(int32_t left, int32_t top, int32_t right, int32_t bottom) const {
209bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return  left < right && top < bottom && !this->isEmpty() && // check for empties
210bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                fLeft <= left && fTop <= top &&
211bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                fRight >= right && fBottom >= bottom;
212bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
213bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
214bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /** Returns true if the specified rectangle r is inside or equal to this rectangle.
215bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    */
216bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bool contains(const SkIRect& r) const {
217bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return  !r.isEmpty() && !this->isEmpty() &&     // check for empties
218bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                fLeft <= r.fLeft && fTop <= r.fTop &&
219bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                fRight >= r.fRight && fBottom >= r.fBottom;
220bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
221bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
222bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /** Return true if this rectangle contains the specified rectangle.
223bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        For speed, this method does not check if either this or the specified
224bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        rectangles are empty, and if either is, its return value is undefined.
225bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        In the debugging build however, we assert that both this and the
226bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        specified rectangles are non-empty.
227bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    */
228bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bool containsNoEmptyCheck(int32_t left, int32_t top,
229bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                              int32_t right, int32_t bottom) const {
230bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(fLeft < fRight && fTop < fBottom);
231bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(left < right && top < bottom);
232bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
233bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return fLeft <= left && fTop <= top &&
234bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com               fRight >= right && fBottom >= bottom;
235bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
236bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
237bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bool containsNoEmptyCheck(const SkIRect& r) const {
238bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return containsNoEmptyCheck(r.fLeft, r.fTop, r.fRight, r.fBottom);
239bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
240bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
241bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /** If r intersects this rectangle, return true and set this rectangle to that
242bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        intersection, otherwise return false and do not change this rectangle.
243bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        If either rectangle is empty, do nothing and return false.
244bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    */
245bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bool intersect(const SkIRect& r) {
246bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(&r);
247bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return this->intersect(r.fLeft, r.fTop, r.fRight, r.fBottom);
248bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
249bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
250bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /** If rectangles a and b intersect, return true and set this rectangle to
251bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        that intersection, otherwise return false and do not change this
252bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        rectangle. If either rectangle is empty, do nothing and return false.
253bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    */
254bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bool intersect(const SkIRect& a, const SkIRect& b) {
255bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(&a && &b);
256bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
257bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (!a.isEmpty() && !b.isEmpty() &&
258bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                a.fLeft < b.fRight && b.fLeft < a.fRight &&
259bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                a.fTop < b.fBottom && b.fTop < a.fBottom) {
260bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            fLeft   = SkMax32(a.fLeft,   b.fLeft);
261bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            fTop    = SkMax32(a.fTop,    b.fTop);
262bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            fRight  = SkMin32(a.fRight,  b.fRight);
263bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            fBottom = SkMin32(a.fBottom, b.fBottom);
264bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            return true;
265bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
266bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return false;
267bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
268bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
269bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /** If rectangles a and b intersect, return true and set this rectangle to
270bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        that intersection, otherwise return false and do not change this
271bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        rectangle. For speed, no check to see if a or b are empty is performed.
272bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        If either is, then the return result is undefined. In the debug build,
273bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        we assert that both rectangles are non-empty.
274bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    */
275bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bool intersectNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
276bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(&a && &b);
277bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(!a.isEmpty() && !b.isEmpty());
278bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
279bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (a.fLeft < b.fRight && b.fLeft < a.fRight &&
280bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                a.fTop < b.fBottom && b.fTop < a.fBottom) {
281bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            fLeft   = SkMax32(a.fLeft,   b.fLeft);
282bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            fTop    = SkMax32(a.fTop,    b.fTop);
283bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            fRight  = SkMin32(a.fRight,  b.fRight);
284bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            fBottom = SkMin32(a.fBottom, b.fBottom);
285bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            return true;
286bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
287bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return false;
288bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
289bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
290bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /** If the rectangle specified by left,top,right,bottom intersects this rectangle,
291bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return true and set this rectangle to that intersection,
292bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        otherwise return false and do not change this rectangle.
293bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        If either rectangle is empty, do nothing and return false.
294bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    */
295bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bool intersect(int32_t left, int32_t top, int32_t right, int32_t bottom) {
296bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (left < right && top < bottom && !this->isEmpty() &&
297bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                fLeft < right && left < fRight && fTop < bottom && top < fBottom) {
298bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            if (fLeft < left) fLeft = left;
299bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            if (fTop < top) fTop = top;
300bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            if (fRight > right) fRight = right;
301bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            if (fBottom > bottom) fBottom = bottom;
302bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            return true;
303bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
304bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return false;
305bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
306bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
307cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com    /** Returns true if a and b are not empty, and they intersect
308cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com     */
309cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com    static bool Intersects(const SkIRect& a, const SkIRect& b) {
310bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return  !a.isEmpty() && !b.isEmpty() &&              // check for empties
311bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        a.fLeft < b.fRight && b.fLeft < a.fRight &&
312bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        a.fTop < b.fBottom && b.fTop < a.fBottom;
313bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
314bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
315bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /**
316b35fe4e1b04229a849227ea6c2561fe84929ab8breed@android.com     *  Returns true if a and b intersect. debug-asserts that neither are empty.
317b35fe4e1b04229a849227ea6c2561fe84929ab8breed@android.com     */
318b35fe4e1b04229a849227ea6c2561fe84929ab8breed@android.com    static bool IntersectsNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
319b35fe4e1b04229a849227ea6c2561fe84929ab8breed@android.com        SkASSERT(!a.isEmpty());
320b35fe4e1b04229a849227ea6c2561fe84929ab8breed@android.com        SkASSERT(!b.isEmpty());
321b35fe4e1b04229a849227ea6c2561fe84929ab8breed@android.com        return  a.fLeft < b.fRight && b.fLeft < a.fRight &&
322b35fe4e1b04229a849227ea6c2561fe84929ab8breed@android.com                a.fTop < b.fBottom && b.fTop < a.fBottom;
323b35fe4e1b04229a849227ea6c2561fe84929ab8breed@android.com    }
324bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
325bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /** Update this rectangle to enclose itself and the specified rectangle.
326bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        If this rectangle is empty, just set it to the specified rectangle. If the specified
327bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        rectangle is empty, do nothing.
328bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    */
329bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void join(int32_t left, int32_t top, int32_t right, int32_t bottom);
330bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
331bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /** Update this rectangle to enclose itself and the specified rectangle.
332bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        If this rectangle is empty, just set it to the specified rectangle. If the specified
333bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        rectangle is empty, do nothing.
334b35fe4e1b04229a849227ea6c2561fe84929ab8breed@android.com    */
335bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void join(const SkIRect& r) {
336bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
337bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
338bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
339b35fe4e1b04229a849227ea6c2561fe84929ab8breed@android.com    /** Swap top/bottom or left/right if there are flipped.
340b35fe4e1b04229a849227ea6c2561fe84929ab8breed@android.com        This can be called if the edges are computed separately,
341b35fe4e1b04229a849227ea6c2561fe84929ab8breed@android.com        and may have crossed over each other.
342b35fe4e1b04229a849227ea6c2561fe84929ab8breed@android.com        When this returns, left <= right && top <= bottom
343b35fe4e1b04229a849227ea6c2561fe84929ab8breed@android.com    */
344b35fe4e1b04229a849227ea6c2561fe84929ab8breed@android.com    void sort();
345b35fe4e1b04229a849227ea6c2561fe84929ab8breed@android.com
346b35fe4e1b04229a849227ea6c2561fe84929ab8breed@android.com    static const SkIRect& SK_WARN_UNUSED_RESULT EmptyIRect() {
347bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        static const SkIRect gEmpty = { 0, 0, 0, 0 };
348bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return gEmpty;
349bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
350b35fe4e1b04229a849227ea6c2561fe84929ab8breed@android.com};
351bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
352bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/** \struct SkRect
353bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com*/
354bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstruct SK_API SkRect {
355bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkScalar    fLeft, fTop, fRight, fBottom;
356bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
357bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    static SkRect SK_WARN_UNUSED_RESULT MakeEmpty() {
358bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkRect r;
359bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        r.setEmpty();
360bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return r;
361bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
362bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
363bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    static SkRect SK_WARN_UNUSED_RESULT MakeWH(SkScalar w, SkScalar h) {
364bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkRect r;
365bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        r.set(0, 0, w, h);
366bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return r;
367bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
368bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
369bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    static SkRect SK_WARN_UNUSED_RESULT MakeSize(const SkSize& size) {
370bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkRect r;
371bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        r.set(0, 0, size.width(), size.height());
372bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return r;
373bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
374bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
375bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    static SkRect SK_WARN_UNUSED_RESULT MakeLTRB(SkScalar l, SkScalar t, SkScalar r, SkScalar b) {
376bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkRect rect;
377bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        rect.set(l, t, r, b);
378e5dd6cd1e1addbc58df3d0f55655448140490002reed@android.com        return rect;
379bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
380bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
381bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    static SkRect SK_WARN_UNUSED_RESULT MakeXYWH(SkScalar x, SkScalar y, SkScalar w, SkScalar h) {
382bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkRect r;
383bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        r.set(x, y, x + w, y + h);
384bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return r;
385bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
386bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
387bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    static SkRect SK_WARN_UNUSED_RESULT MakeFromIRect(const SkIRect& irect) {
388bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkRect r;
389bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        r.set(SkIntToScalar(irect.fLeft),
390bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com              SkIntToScalar(irect.fTop),
391bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com              SkIntToScalar(irect.fRight),
392bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com              SkIntToScalar(irect.fBottom));
393bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return r;
394bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
395bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
396bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /**
397bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  Return true if the rectangle's width or height are <= 0
398bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     */
399bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; }
400bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
401bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /**
402bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  Returns true iff all values in the rect are finite. If any are
403bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  infinite or NaN (or SK_FixedNaN when SkScalar is fixed) then this
404bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  returns false.
405bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     */
406bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bool isFinite() const {
407bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_SCALAR_IS_FLOAT
408bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        float accum = 0;
409bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        accum *= fLeft;
410bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        accum *= fTop;
411bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        accum *= fRight;
412bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        accum *= fBottom;
413bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
414e5dd6cd1e1addbc58df3d0f55655448140490002reed@android.com        // accum is either NaN or it is finite (zero).
415bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(0 == accum || !(accum == accum));
416bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
417bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        // value==value will be true iff value is not NaN
4186aa3c7b33e224af3ac3c75797de40498bd3d645creed@android.com        // TODO: is it faster to say !accum or accum==accum?
419bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return accum == accum;
4206aa3c7b33e224af3ac3c75797de40498bd3d645creed@android.com#else
4216aa3c7b33e224af3ac3c75797de40498bd3d645creed@android.com        // use bit-or for speed, since we don't care about short-circuting the
4226aa3c7b33e224af3ac3c75797de40498bd3d645creed@android.com        // tests, and we expect the common case will be that we need to check all.
4236aa3c7b33e224af3ac3c75797de40498bd3d645creed@android.com        int isNaN = (SK_FixedNaN == fLeft)  | (SK_FixedNaN == fTop) |
4246aa3c7b33e224af3ac3c75797de40498bd3d645creed@android.com                    (SK_FixedNaN == fRight) | (SK_FixedNaN == fBottom);
4256aa3c7b33e224af3ac3c75797de40498bd3d645creed@android.com        return !isNaN;
4266aa3c7b33e224af3ac3c75797de40498bd3d645creed@android.com#endif
4276aa3c7b33e224af3ac3c75797de40498bd3d645creed@android.com    }
4286aa3c7b33e224af3ac3c75797de40498bd3d645creed@android.com
4296aa3c7b33e224af3ac3c75797de40498bd3d645creed@android.com    SkScalar    x() const { return fLeft; }
4306aa3c7b33e224af3ac3c75797de40498bd3d645creed@android.com    SkScalar    y() const { return fTop; }
4316aa3c7b33e224af3ac3c75797de40498bd3d645creed@android.com    SkScalar    left() const { return fLeft; }
4326aa3c7b33e224af3ac3c75797de40498bd3d645creed@android.com    SkScalar    top() const { return fTop; }
4336aa3c7b33e224af3ac3c75797de40498bd3d645creed@android.com    SkScalar    right() const { return fRight; }
4346aa3c7b33e224af3ac3c75797de40498bd3d645creed@android.com    SkScalar    bottom() const { return fBottom; }
435bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkScalar    width() const { return fRight - fLeft; }
436bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkScalar    height() const { return fBottom - fTop; }
437cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com    SkScalar    centerX() const { return SkScalarHalf(fLeft + fRight); }
438bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkScalar    centerY() const { return SkScalarHalf(fTop + fBottom); }
439f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com
440f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com    friend bool operator==(const SkRect& a, const SkRect& b) {
441f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com        return SkScalarsEqual((SkScalar*)&a, (SkScalar*)&b, 4);
442f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com    }
443f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com
444f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com    friend bool operator!=(const SkRect& a, const SkRect& b) {
445f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com        return !SkScalarsEqual((SkScalar*)&a, (SkScalar*)&b, 4);
446f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com    }
447f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com
448f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com    /** return the 4 points that enclose the rectangle
449f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com    */
450f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com    void toQuad(SkPoint quad[4]) const;
451f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com
452f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com    /** Set this rectangle to the empty rectangle (0,0,0,0)
453f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com    */
454f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com    void setEmpty() { memset(this, 0, sizeof(*this)); }
455f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com
456f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com    void set(const SkIRect& src) {
457f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com        fLeft   = SkIntToScalar(src.fLeft);
458f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com        fTop    = SkIntToScalar(src.fTop);
459f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com        fRight  = SkIntToScalar(src.fRight);
460f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com        fBottom = SkIntToScalar(src.fBottom);
461f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com    }
462f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com
463f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com    void set(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
464f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com        fLeft   = left;
465f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com        fTop    = top;
466f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com        fRight  = right;
467f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com        fBottom = bottom;
468f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com    }
469f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com    // alias for set(l, t, r, b)
470f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com    void setLTRB(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
471f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com        this->set(left, top, right, bottom);
472f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com    }
473f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com
474bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /** Initialize the rect with the 4 specified integers. The routine handles
475bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        converting them to scalars (by calling SkIntToScalar)
476bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     */
477bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void iset(int left, int top, int right, int bottom) {
478bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fLeft   = SkIntToScalar(left);
479bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fTop    = SkIntToScalar(top);
480c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com        fRight  = SkIntToScalar(right);
481bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fBottom = SkIntToScalar(bottom);
482bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
483bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
484cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com    /** Set this rectangle to be the bounds of the array of points.
485cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com        If the array is empty (count == 0), then set this rectangle
486cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com        to the empty rectangle (0,0,0,0)
487cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com    */
488cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com    void set(const SkPoint pts[], int count) {
489cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com        // set() had been checking for non-finite values, so keep that behavior
490bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        // for now. Now that we have setBoundsCheck(), we may decide to make
491bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        // set() be simpler/faster, and not check for those.
492bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        (void)this->setBoundsCheck(pts, count);
493bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
494bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
495bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // alias for set(pts, count)
496bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void setBounds(const SkPoint pts[], int count) {
497bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        (void)this->setBoundsCheck(pts, count);
498bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
499bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
500bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /**
501bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  Compute the bounds of the array of points, and set this rect to that
502bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  bounds and return true... unless a non-finite value is encountered,
503bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  in which case this rect is set to empty and false is returned.
504cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com     */
505cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com    bool setBoundsCheck(const SkPoint pts[], int count);
506cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com
507bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void set(const SkPoint& p0, const SkPoint& p1) {
508cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com        fLeft =   SkMinScalar(p0.fX, p1.fX);
509cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com        fRight =  SkMaxScalar(p0.fX, p1.fX);
510b44d151b082d859c467808a843dc01a7118ce5cfreed@android.com        fTop =    SkMinScalar(p0.fY, p1.fY);
5117d27207b0d54e59a7b5722247322fbf4344d44a1agl@chromium.org        fBottom = SkMaxScalar(p0.fY, p1.fY);
5127d27207b0d54e59a7b5722247322fbf4344d44a1agl@chromium.org    }
5137d27207b0d54e59a7b5722247322fbf4344d44a1agl@chromium.org
5147d27207b0d54e59a7b5722247322fbf4344d44a1agl@chromium.org    void setXYWH(SkScalar x, SkScalar y, SkScalar width, SkScalar height) {
5157d27207b0d54e59a7b5722247322fbf4344d44a1agl@chromium.org        fLeft = x;
5167d27207b0d54e59a7b5722247322fbf4344d44a1agl@chromium.org        fTop = y;
5177d27207b0d54e59a7b5722247322fbf4344d44a1agl@chromium.org        fRight = x + width;
5187d27207b0d54e59a7b5722247322fbf4344d44a1agl@chromium.org        fBottom = y + height;
519bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
520bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
521bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void setWH(SkScalar width, SkScalar height) {
522cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com        fLeft = 0;
523bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fTop = 0;
524cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com        fRight = width;
525bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fBottom = height;
526bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
527bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
528bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /**
529bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  Make the largest representable rectangle
530bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     */
531bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void setLargest() {
532bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fLeft = fTop = SK_ScalarMin;
533bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fRight = fBottom = SK_ScalarMax;
534bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
535bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
536bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /**
537bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  Make the largest representable rectangle, but inverted (e.g. fLeft will
538bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  be max and right will be min).
539c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com     */
540bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void setLargestInverted() {
541c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com        fLeft = fTop = SK_ScalarMax;
542c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com        fRight = fBottom = SK_ScalarMin;
543c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com    }
544bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
545bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /** Offset set the rectangle by adding dx to its left and right,
546bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        and adding dy to its top and bottom.
547bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    */
548bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void offset(SkScalar dx, SkScalar dy) {
549bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fLeft   += dx;
550bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fTop    += dy;
551bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fRight  += dx;
552bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fBottom += dy;
553bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
554bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
555bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void offset(const SkPoint& delta) {
556bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        this->offset(delta.fX, delta.fY);
557c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com    }
558bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
559bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /**
560bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  Offset this rect such its new x() and y() will equal newX and newY.
561bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     */
562bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void offsetTo(SkScalar newX, SkScalar newY) {
563bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fRight += newX - fLeft;
564bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fBottom += newY - fTop;
565bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fLeft = newX;
566bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fTop = newY;
567bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
568bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
569bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /** Inset the rectangle by (dx,dy). If dx is positive, then the sides are
570bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        moved inwards, making the rectangle narrower. If dx is negative, then
571bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        the sides are moved outwards, making the rectangle wider. The same holds
572bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com         true for dy and the top and bottom.
573bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    */
574bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void inset(SkScalar dx, SkScalar dy)  {
575bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fLeft   += dx;
576bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fTop    += dy;
577bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fRight  -= dx;
578bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fBottom -= dy;
579bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
580bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
581bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com   /** Outset the rectangle by (dx,dy). If dx is positive, then the sides are
582bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com       moved outwards, making the rectangle wider. If dx is negative, then the
583bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com       sides are moved inwards, making the rectangle narrower. The same holds
584bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com       true for dy and the top and bottom.
585bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    */
586bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void outset(SkScalar dx, SkScalar dy)  { this->inset(-dx, -dy); }
587bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
588bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /** If this rectangle intersects r, return true and set this rectangle to that
589bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        intersection, otherwise return false and do not change this rectangle.
590bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        If either rectangle is empty, do nothing and return false.
591bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    */
592bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bool intersect(const SkRect& r);
593bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
594bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /** If this rectangle intersects the rectangle specified by left, top, right, bottom,
595bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return true and set this rectangle to that intersection, otherwise return false
596bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        and do not change this rectangle.
597bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        If either rectangle is empty, do nothing and return false.
598bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    */
599bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bool intersect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
600bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
601bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /**
602bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  Return true if this rectangle is not empty, and the specified sides of
603bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  a rectangle are not empty, and they intersect.
604bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     */
605bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bool intersects(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) const {
606bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return // first check that both are not empty
607bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com               left < right && top < bottom &&
608bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com               fLeft < fRight && fTop < fBottom &&
609bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com               // now check for intersection
610bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com               fLeft < right && left < fRight &&
611bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com               fTop < bottom && top < fBottom;
612bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
613bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
614bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /** If rectangles a and b intersect, return true and set this rectangle to
615bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  that intersection, otherwise return false and do not change this
616bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  rectangle. If either rectangle is empty, do nothing and return false.
617bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     */
618bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bool intersect(const SkRect& a, const SkRect& b);
619bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
620bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /**
621bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  Return true if rectangles a and b are not empty and intersect.
622bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     */
623bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    static bool Intersects(const SkRect& a, const SkRect& b) {
624bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return  !a.isEmpty() && !b.isEmpty() &&
625bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                a.fLeft < b.fRight && b.fLeft < a.fRight &&
626155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                a.fTop < b.fBottom && b.fTop < a.fBottom;
627bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
628bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
629bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /**
630bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  Update this rectangle to enclose itself and the specified rectangle.
631bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  If this rectangle is empty, just set it to the specified rectangle.
632bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  If the specified rectangle is empty, do nothing.
633bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     */
634bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void join(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
635bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
636bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /** Update this rectangle to enclose itself and the specified rectangle.
637bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        If this rectangle is empty, just set it to the specified rectangle. If the specified
638bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        rectangle is empty, do nothing.
639bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    */
640bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void join(const SkRect& r) {
641c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com        this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
642bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
643bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // alias for join()
644bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void growToInclude(const SkRect& r) { this->join(r); }
645bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
646bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /**
647bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  Grow the rect to include the specified (x,y). After this call, the
648bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  following will be true: fLeft <= x <= fRight && fTop <= y <= fBottom.
649bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *
650bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  This is close, but not quite the same contract as contains(), since
651bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  contains() treats the left and top different from the right and bottom.
652bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  contains(x,y) -> fLeft <= x < fRight && fTop <= y < fBottom. Also note
653bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  that contains(x,y) always returns false if the rect is empty.
654bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     */
655bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void growToInclude(SkScalar x, SkScalar y) {
656bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fLeft  = SkMinScalar(x, fLeft);
657bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fRight = SkMaxScalar(x, fRight);
658bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fTop    = SkMinScalar(y, fTop);
659bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fBottom = SkMaxScalar(y, fBottom);
660bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
661bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
662bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /**
663bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  Returns true if (p.fX,p.fY) is inside the rectangle, and the rectangle
664bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  is not empty.
665bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *
666bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  Contains treats the left and top differently from the right and bottom.
667bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  The left and top coordinates of the rectangle are themselves considered
6682258a80c91fa183971ea3ed987c528e835fe9481reed@android.com     *  to be inside, while the right and bottom are not. Thus for the rectangle
6692258a80c91fa183971ea3ed987c528e835fe9481reed@android.com     *  {0, 0, 5, 10}, (0,0) is contained, but (0,10), (5,0) and (5,10) are not.
670bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     */
671bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bool contains(const SkPoint& p) const {
672bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return !this->isEmpty() &&
673bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com               fLeft <= p.fX && p.fX < fRight && fTop <= p.fY && p.fY < fBottom;
674bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
675bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
676bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /**
677bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  Returns true if (x,y) is inside the rectangle, and the rectangle
678bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  is not empty.
679bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *
680bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  Contains treats the left and top differently from the right and bottom.
681bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  The left and top coordinates of the rectangle are themselves considered
682bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  to be inside, while the right and bottom are not. Thus for the rectangle
683bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  {0, 0, 5, 10}, (0,0) is contained, but (0,10), (5,0) and (5,10) are not.
684bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     */
685bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bool contains(SkScalar x, SkScalar y) const {
686bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return  !this->isEmpty() &&
687bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                fLeft <= x && x < fRight && fTop <= y && y < fBottom;
688bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
689bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
690bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /**
691bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  Return true if this rectangle contains r, and if both rectangles are
692bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  not empty.
693bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     */
694bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bool contains(const SkRect& r) const {
695bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return  !r.isEmpty() && !this->isEmpty() &&
696bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                fLeft <= r.fLeft && fTop <= r.fTop &&
697bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                fRight >= r.fRight && fBottom >= r.fBottom;
698bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
699bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
700bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /**
701c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com     *  Set the dst rectangle by rounding this rectangle's coordinates to their
702c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com     *  nearest integer values using SkScalarRound.
703c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com     */
704c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com    void round(SkIRect* dst) const {
705c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com        SkASSERT(dst);
706bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        dst->set(SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
707bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                 SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom));
708bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
709bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
710bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /**
711bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  Set the dst rectangle by rounding "out" this rectangle, choosing the
712bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  SkScalarFloor of top and left, and the SkScalarCeil of right and bottom.
713bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     */
714bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void roundOut(SkIRect* dst) const {
715bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(dst);
716bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        dst->set(SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
717bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom));
718bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
719bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
720bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    /**
721bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  Expand this rectangle by rounding its coordinates "out", choosing the
722bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  floor of top and left, and the ceil of right and bottom. If this rect
723bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     *  is already on integer coordinates, then it will be unchanged.
724bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com     */
725bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void roundOut() {
726bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        this->set(SkScalarFloorToScalar(fLeft),
727bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                  SkScalarFloorToScalar(fTop),
728bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                  SkScalarCeilToScalar(fRight),
729bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                  SkScalarCeilToScalar(fBottom));
730    }
731
732    /**
733     *  Set the dst rectangle by rounding "in" this rectangle, choosing the
734     *  ceil of top and left, and the floor of right and bottom. This does *not*
735     *  call sort(), so it is possible that the resulting rect is inverted...
736     *  e.g. left >= right or top >= bottom. Call isEmpty() to detect that.
737     */
738    void roundIn(SkIRect* dst) const {
739        SkASSERT(dst);
740        dst->set(SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
741                 SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom));
742    }
743
744
745    /**
746     *  Swap top/bottom or left/right if there are flipped (i.e. if width()
747     *  or height() would have returned a negative value.) This should be called
748     *  if the edges are computed separately, and may have crossed over each
749     *  other. When this returns, left <= right && top <= bottom
750     */
751    void sort();
752};
753
754#endif
755
756