1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkRect_DEFINED
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkRect_DEFINED
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPoint.h"
14233481ebd0b8644a319443cde33e75266e990ee6reed@android.com#include "SkSize.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** \struct SkIRect
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkIRect holds four 32 bit integer coordinates for a rectangle
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
207ffb1b21abcc7bbed5a0fc711f6dd7b9dbb4f577ctguil@chromium.orgstruct SK_API SkIRect {
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int32_t fLeft, fTop, fRight, fBottom;
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
235d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com    static SkIRect SK_WARN_UNUSED_RESULT MakeEmpty() {
24097a3513535ad854c1b049c32c080ec875ab1411reed@android.com        SkIRect r;
25097a3513535ad854c1b049c32c080ec875ab1411reed@android.com        r.setEmpty();
26097a3513535ad854c1b049c32c080ec875ab1411reed@android.com        return r;
27097a3513535ad854c1b049c32c080ec875ab1411reed@android.com    }
28fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
29194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    static SkIRect SK_WARN_UNUSED_RESULT MakeLargest() {
30194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org        SkIRect r;
31194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org        r.setLargest();
32194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org        return r;
33194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    }
34194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
355d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com    static SkIRect SK_WARN_UNUSED_RESULT MakeWH(int32_t w, int32_t h) {
36097a3513535ad854c1b049c32c080ec875ab1411reed@android.com        SkIRect r;
37097a3513535ad854c1b049c32c080ec875ab1411reed@android.com        r.set(0, 0, w, h);
38097a3513535ad854c1b049c32c080ec875ab1411reed@android.com        return r;
39097a3513535ad854c1b049c32c080ec875ab1411reed@android.com    }
40fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
415d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com    static SkIRect SK_WARN_UNUSED_RESULT MakeSize(const SkISize& size) {
42097a3513535ad854c1b049c32c080ec875ab1411reed@android.com        SkIRect r;
43097a3513535ad854c1b049c32c080ec875ab1411reed@android.com        r.set(0, 0, size.width(), size.height());
44097a3513535ad854c1b049c32c080ec875ab1411reed@android.com        return r;
45097a3513535ad854c1b049c32c080ec875ab1411reed@android.com    }
46fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
475d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com    static SkIRect SK_WARN_UNUSED_RESULT MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b) {
48097a3513535ad854c1b049c32c080ec875ab1411reed@android.com        SkIRect rect;
49097a3513535ad854c1b049c32c080ec875ab1411reed@android.com        rect.set(l, t, r, b);
50097a3513535ad854c1b049c32c080ec875ab1411reed@android.com        return rect;
51097a3513535ad854c1b049c32c080ec875ab1411reed@android.com    }
52fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
535d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com    static SkIRect SK_WARN_UNUSED_RESULT MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h) {
54097a3513535ad854c1b049c32c080ec875ab1411reed@android.com        SkIRect r;
55097a3513535ad854c1b049c32c080ec875ab1411reed@android.com        r.set(x, y, x + w, y + h);
56097a3513535ad854c1b049c32c080ec875ab1411reed@android.com        return r;
57097a3513535ad854c1b049c32c080ec875ab1411reed@android.com    }
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
59c74ab1813013b169ad500fcf1fa62be551041442reed@google.com    int left() const { return fLeft; }
60c74ab1813013b169ad500fcf1fa62be551041442reed@google.com    int top() const { return fTop; }
61c74ab1813013b169ad500fcf1fa62be551041442reed@google.com    int right() const { return fRight; }
62c74ab1813013b169ad500fcf1fa62be551041442reed@google.com    int bottom() const { return fBottom; }
63fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
64c74ab1813013b169ad500fcf1fa62be551041442reed@google.com    /** return the left edge of the rect */
65c74ab1813013b169ad500fcf1fa62be551041442reed@google.com    int x() const { return fLeft; }
66c74ab1813013b169ad500fcf1fa62be551041442reed@google.com    /** return the top edge of the rect */
67c74ab1813013b169ad500fcf1fa62be551041442reed@google.com    int y() const { return fTop; }
68c74ab1813013b169ad500fcf1fa62be551041442reed@google.com    /**
69c74ab1813013b169ad500fcf1fa62be551041442reed@google.com     *  Returns the rectangle's width. This does not check for a valid rect
70c74ab1813013b169ad500fcf1fa62be551041442reed@google.com     *  (i.e. left <= right) so the result may be negative.
71c74ab1813013b169ad500fcf1fa62be551041442reed@google.com     */
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int width() const { return fRight - fLeft; }
73fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
74c74ab1813013b169ad500fcf1fa62be551041442reed@google.com    /**
75c74ab1813013b169ad500fcf1fa62be551041442reed@google.com     *  Returns the rectangle's height. This does not check for a valid rect
76c74ab1813013b169ad500fcf1fa62be551041442reed@google.com     *  (i.e. top <= bottom) so the result may be negative.
77c74ab1813013b169ad500fcf1fa62be551041442reed@google.com     */
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int height() const { return fBottom - fTop; }
79fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
80c74ab1813013b169ad500fcf1fa62be551041442reed@google.com    /**
816898d52c371309d81c2184ea991785d2485323e4reed@google.com     *  Since the center of an integer rect may fall on a factional value, this
826898d52c371309d81c2184ea991785d2485323e4reed@google.com     *  method is defined to return (right + left) >> 1.
836898d52c371309d81c2184ea991785d2485323e4reed@google.com     *
846898d52c371309d81c2184ea991785d2485323e4reed@google.com     *  This is a specific "truncation" of the average, which is different than
856898d52c371309d81c2184ea991785d2485323e4reed@google.com     *  (right + left) / 2 when the sum is negative.
866898d52c371309d81c2184ea991785d2485323e4reed@google.com     */
876898d52c371309d81c2184ea991785d2485323e4reed@google.com    int centerX() const { return (fRight + fLeft) >> 1; }
88d9f7503e0cb0c4db856f53b4bdeec1332db6f296skia.committer@gmail.com
896898d52c371309d81c2184ea991785d2485323e4reed@google.com    /**
906898d52c371309d81c2184ea991785d2485323e4reed@google.com     *  Since the center of an integer rect may fall on a factional value, this
916898d52c371309d81c2184ea991785d2485323e4reed@google.com     *  method is defined to return (bottom + top) >> 1
926898d52c371309d81c2184ea991785d2485323e4reed@google.com     *
936898d52c371309d81c2184ea991785d2485323e4reed@google.com     *  This is a specific "truncation" of the average, which is different than
946898d52c371309d81c2184ea991785d2485323e4reed@google.com     *  (bottom + top) / 2 when the sum is negative.
956898d52c371309d81c2184ea991785d2485323e4reed@google.com     */
966898d52c371309d81c2184ea991785d2485323e4reed@google.com    int centerY() const { return (fBottom + fTop) >> 1; }
97d9f7503e0cb0c4db856f53b4bdeec1332db6f296skia.committer@gmail.com
986898d52c371309d81c2184ea991785d2485323e4reed@google.com    /**
99c74ab1813013b169ad500fcf1fa62be551041442reed@google.com     *  Return true if the rectangle's width or height are <= 0
100c74ab1813013b169ad500fcf1fa62be551041442reed@google.com     */
101c74ab1813013b169ad500fcf1fa62be551041442reed@google.com    bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; }
102fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
103194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    bool isLargest() const { return SK_MinS32 == fLeft &&
104194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org                                    SK_MinS32 == fTop &&
105194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org                                    SK_MaxS32 == fRight &&
106194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org                                    SK_MaxS32 == fBottom; }
107194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
108b530ef5869c5c64af8f3b3c62ed7711fe4325c9creed@google.com    friend bool operator==(const SkIRect& a, const SkIRect& b) {
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return !memcmp(&a, &b, sizeof(a));
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
111da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com
112b530ef5869c5c64af8f3b3c62ed7711fe4325c9creed@google.com    friend bool operator!=(const SkIRect& a, const SkIRect& b) {
113b530ef5869c5c64af8f3b3c62ed7711fe4325c9creed@google.com        return !(a == b);
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
116d4577757874d1dda1a3bffa3f2347c251859c27ereed@android.com    bool is16Bit() const {
117d4577757874d1dda1a3bffa3f2347c251859c27ereed@android.com        return  SkIsS16(fLeft) && SkIsS16(fTop) &&
118d4577757874d1dda1a3bffa3f2347c251859c27ereed@android.com                SkIsS16(fRight) && SkIsS16(fBottom);
119d4577757874d1dda1a3bffa3f2347c251859c27ereed@android.com    }
120d4577757874d1dda1a3bffa3f2347c251859c27ereed@android.com
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set the rectangle to (0,0,0,0)
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void setEmpty() { memset(this, 0, sizeof(*this)); }
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
125da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    void set(int32_t left, int32_t top, int32_t right, int32_t bottom) {
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLeft   = left;
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fTop    = top;
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fRight  = right;
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBottom = bottom;
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13120efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    // alias for set(l, t, r, b)
13220efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom) {
13320efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        this->set(left, top, right, bottom);
13420efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    }
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1361d12b1fd66e5be27fb4769ee09ce4fcd6bcc5979reed@google.com    void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height) {
1371d12b1fd66e5be27fb4769ee09ce4fcd6bcc5979reed@google.com        fLeft = x;
1381d12b1fd66e5be27fb4769ee09ce4fcd6bcc5979reed@google.com        fTop = y;
1391d12b1fd66e5be27fb4769ee09ce4fcd6bcc5979reed@google.com        fRight = x + width;
1401d12b1fd66e5be27fb4769ee09ce4fcd6bcc5979reed@google.com        fBottom = y + height;
1411d12b1fd66e5be27fb4769ee09ce4fcd6bcc5979reed@google.com    }
14220efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com
14320efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    /**
14420efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com     *  Make the largest representable rectangle
14520efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com     */
14620efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    void setLargest() {
14720efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        fLeft = fTop = SK_MinS32;
14820efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        fRight = fBottom = SK_MaxS32;
14920efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    }
150fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
15120efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    /**
15220efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com     *  Make the largest representable rectangle, but inverted (e.g. fLeft will
15320efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com     *  be max 32bit and right will be min 32bit).
15420efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com     */
15520efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    void setLargestInverted() {
15620efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        fLeft = fTop = SK_MaxS32;
15720efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        fRight = fBottom = SK_MinS32;
15820efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    }
159fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1605c404c55772973126d8b3c6942ee42c9361d3fadreed    /**
1615c404c55772973126d8b3c6942ee42c9361d3fadreed     *  Return a new IRect, built as an offset of this rect.
1625c404c55772973126d8b3c6942ee42c9361d3fadreed     */
1635c404c55772973126d8b3c6942ee42c9361d3fadreed    SkIRect makeOffset(int dx, int dy) const {
1645c404c55772973126d8b3c6942ee42c9361d3fadreed        return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy);
1655c404c55772973126d8b3c6942ee42c9361d3fadreed    }
1665c404c55772973126d8b3c6942ee42c9361d3fadreed
1675c404c55772973126d8b3c6942ee42c9361d3fadreed    /**
1685c404c55772973126d8b3c6942ee42c9361d3fadreed     *  Return a new IRect, built as an inset of this rect.
1695c404c55772973126d8b3c6942ee42c9361d3fadreed     */
1705c404c55772973126d8b3c6942ee42c9361d3fadreed    SkIRect makeInset(int dx, int dy) const {
1715c404c55772973126d8b3c6942ee42c9361d3fadreed        return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, fBottom - dy);
1725c404c55772973126d8b3c6942ee42c9361d3fadreed    }
1735c404c55772973126d8b3c6942ee42c9361d3fadreed
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Offset set the rectangle by adding dx to its left and right,
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        and adding dy to its top and bottom.
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
177da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    void offset(int32_t dx, int32_t dy) {
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLeft   += dx;
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fTop    += dy;
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fRight  += dx;
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBottom += dy;
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
184da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    void offset(const SkIPoint& delta) {
185da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com        this->offset(delta.fX, delta.fY);
186da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    }
187da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com
1884d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com    /**
1894d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com     *  Offset this rect such its new x() and y() will equal newX and newY.
1904d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com     */
1914d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com    void offsetTo(int32_t newX, int32_t newY) {
1924d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com        fRight += newX - fLeft;
1934d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com        fBottom += newY - fTop;
1944d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com        fLeft = newX;
1954d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com        fTop = newY;
1964d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com    }
1974d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Inset the rectangle by (dx,dy). If dx is positive, then the sides are moved inwards,
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        making the rectangle narrower. If dx is negative, then the sides are moved outwards,
2006623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com        making the rectangle wider. The same holds true for dy and the top and bottom.
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
202da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    void inset(int32_t dx, int32_t dy) {
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLeft   += dx;
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fTop    += dy;
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fRight  -= dx;
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBottom -= dy;
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
208da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com
2096623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com   /** Outset the rectangle by (dx,dy). If dx is positive, then the sides are
2106623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com       moved outwards, making the rectangle wider. If dx is negative, then the
2116623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com       sides are moved inwards, making the rectangle narrower. The same holds
2126623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com       true for dy and the top and bottom.
2136623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com    */
2146623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com    void outset(int32_t dx, int32_t dy)  { this->inset(-dx, -dy); }
2156623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com
21620efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    bool quickReject(int l, int t, int r, int b) const {
21720efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        return l >= fRight || fLeft >= r || t >= fBottom || fTop >= b;
21820efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    }
219fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns true if (x,y) is inside the rectangle and the rectangle is not
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        empty. The left and top are considered to be inside, while the right
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        and bottom are not. Thus for the rectangle (0, 0, 5, 10), the
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        points (0,0) and (0,9) are inside, while (-1,0) and (5,9) are not.
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
225da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    bool contains(int32_t x, int32_t y) const {
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return  (unsigned)(x - fLeft) < (unsigned)(fRight - fLeft) &&
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                (unsigned)(y - fTop) < (unsigned)(fBottom - fTop);
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns true if the 4 specified sides of a rectangle are inside or equal to this rectangle.
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        If either rectangle is empty, contains() returns false.
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
233da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    bool contains(int32_t left, int32_t top, int32_t right, int32_t bottom) const {
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return  left < right && top < bottom && !this->isEmpty() && // check for empties
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fLeft <= left && fTop <= top &&
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fRight >= right && fBottom >= bottom;
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns true if the specified rectangle r is inside or equal to this rectangle.
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
241da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    bool contains(const SkIRect& r) const {
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return  !r.isEmpty() && !this->isEmpty() &&     // check for empties
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fLeft <= r.fLeft && fTop <= r.fTop &&
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fRight >= r.fRight && fBottom >= r.fBottom;
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Return true if this rectangle contains the specified rectangle.
2485d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com        For speed, this method does not check if either this or the specified
2495d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com        rectangles are empty, and if either is, its return value is undefined.
2505d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com        In the debugging build however, we assert that both this and the
2515d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com        specified rectangles are non-empty.
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool containsNoEmptyCheck(int32_t left, int32_t top,
2545d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com                              int32_t right, int32_t bottom) const {
2555d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com        SkASSERT(fLeft < fRight && fTop < fBottom);
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(left < right && top < bottom);
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return fLeft <= left && fTop <= top &&
2595d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com               fRight >= right && fBottom >= bottom;
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
261fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2620d10280190c411b18feb569a2248552047d1aa93reed@google.com    bool containsNoEmptyCheck(const SkIRect& r) const {
2630d10280190c411b18feb569a2248552047d1aa93reed@google.com        return containsNoEmptyCheck(r.fLeft, r.fTop, r.fRight, r.fBottom);
2640d10280190c411b18feb569a2248552047d1aa93reed@google.com    }
265fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** If r intersects this rectangle, return true and set this rectangle to that
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        intersection, otherwise return false and do not change this rectangle.
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        If either rectangle is empty, do nothing and return false.
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
270da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    bool intersect(const SkIRect& r) {
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(&r);
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->intersect(r.fLeft, r.fTop, r.fRight, r.fBottom);
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** If rectangles a and b intersect, return true and set this rectangle to
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        that intersection, otherwise return false and do not change this
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rectangle. If either rectangle is empty, do nothing and return false.
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
279da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    bool intersect(const SkIRect& a, const SkIRect& b) {
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(&a && &b);
281fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!a.isEmpty() && !b.isEmpty() &&
283da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com                a.fLeft < b.fRight && b.fLeft < a.fRight &&
284da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com                a.fTop < b.fBottom && b.fTop < a.fBottom) {
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fLeft   = SkMax32(a.fLeft,   b.fLeft);
2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fTop    = SkMax32(a.fTop,    b.fTop);
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fRight  = SkMin32(a.fRight,  b.fRight);
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fBottom = SkMin32(a.fBottom, b.fBottom);
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
293fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** If rectangles a and b intersect, return true and set this rectangle to
2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        that intersection, otherwise return false and do not change this
2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rectangle. For speed, no check to see if a or b are empty is performed.
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        If either is, then the return result is undefined. In the debug build,
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        we assert that both rectangles are non-empty.
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
300da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    bool intersectNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(&a && &b);
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(!a.isEmpty() && !b.isEmpty());
303fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (a.fLeft < b.fRight && b.fLeft < a.fRight &&
305da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com                a.fTop < b.fBottom && b.fTop < a.fBottom) {
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fLeft   = SkMax32(a.fLeft,   b.fLeft);
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fTop    = SkMax32(a.fTop,    b.fTop);
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fRight  = SkMin32(a.fRight,  b.fRight);
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fBottom = SkMin32(a.fBottom, b.fBottom);
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** If the rectangle specified by left,top,right,bottom intersects this rectangle,
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true and set this rectangle to that intersection,
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        otherwise return false and do not change this rectangle.
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        If either rectangle is empty, do nothing and return false.
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
320da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    bool intersect(int32_t left, int32_t top, int32_t right, int32_t bottom) {
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (left < right && top < bottom && !this->isEmpty() &&
322da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com                fLeft < right && left < fRight && fTop < bottom && top < fBottom) {
3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (fLeft < left) fLeft = left;
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (fTop < top) fTop = top;
3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (fRight > right) fRight = right;
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (fBottom > bottom) fBottom = bottom;
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
331fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns true if a and b are not empty, and they intersect
3330d10280190c411b18feb569a2248552047d1aa93reed@google.com     */
334da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    static bool Intersects(const SkIRect& a, const SkIRect& b) {
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return  !a.isEmpty() && !b.isEmpty() &&              // check for empties
3360d10280190c411b18feb569a2248552047d1aa93reed@google.com        a.fLeft < b.fRight && b.fLeft < a.fRight &&
3370d10280190c411b18feb569a2248552047d1aa93reed@google.com        a.fTop < b.fBottom && b.fTop < a.fBottom;
3380d10280190c411b18feb569a2248552047d1aa93reed@google.com    }
339fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3400d10280190c411b18feb569a2248552047d1aa93reed@google.com    /**
3410d10280190c411b18feb569a2248552047d1aa93reed@google.com     *  Returns true if a and b intersect. debug-asserts that neither are empty.
3420d10280190c411b18feb569a2248552047d1aa93reed@google.com     */
3430d10280190c411b18feb569a2248552047d1aa93reed@google.com    static bool IntersectsNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
3440d10280190c411b18feb569a2248552047d1aa93reed@google.com        SkASSERT(!a.isEmpty());
3450d10280190c411b18feb569a2248552047d1aa93reed@google.com        SkASSERT(!b.isEmpty());
3460d10280190c411b18feb569a2248552047d1aa93reed@google.com        return  a.fLeft < b.fRight && b.fLeft < a.fRight &&
3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                a.fTop < b.fBottom && b.fTop < a.fBottom;
3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
349fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Update this rectangle to enclose itself and the specified rectangle.
3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        If this rectangle is empty, just set it to the specified rectangle. If the specified
3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rectangle is empty, do nothing.
3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void join(int32_t left, int32_t top, int32_t right, int32_t bottom);
3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Update this rectangle to enclose itself and the specified rectangle.
3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        If this rectangle is empty, just set it to the specified rectangle. If the specified
3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rectangle is empty, do nothing.
3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
360da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    void join(const SkIRect& r) {
3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Swap top/bottom or left/right if there are flipped.
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        This can be called if the edges are computed separately,
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        and may have crossed over each other.
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        When this returns, left <= right && top <= bottom
3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void sort();
37020efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com
3715d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com    static const SkIRect& SK_WARN_UNUSED_RESULT EmptyIRect() {
3724b4fb3a52c32cd4937d51d1315624545973b1322reed@google.com        static const SkIRect gEmpty = { 0, 0, 0, 0 };
37320efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        return gEmpty;
37420efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    }
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** \struct SkRect
3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
3797ffb1b21abcc7bbed5a0fc711f6dd7b9dbb4f577ctguil@chromium.orgstruct SK_API SkRect {
3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar    fLeft, fTop, fRight, fBottom;
3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3825d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com    static SkRect SK_WARN_UNUSED_RESULT MakeEmpty() {
3832687ae05cbd309072f0b5bb9d872d758108a2776reed@android.com        SkRect r;
3842687ae05cbd309072f0b5bb9d872d758108a2776reed@android.com        r.setEmpty();
3852687ae05cbd309072f0b5bb9d872d758108a2776reed@android.com        return r;
3862687ae05cbd309072f0b5bb9d872d758108a2776reed@android.com    }
3872687ae05cbd309072f0b5bb9d872d758108a2776reed@android.com
388b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org    static SkRect SK_WARN_UNUSED_RESULT MakeLargest() {
389b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org        SkRect r;
390b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org        r.setLargest();
391b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org        return r;
392b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org    }
393b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org
3945d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com    static SkRect SK_WARN_UNUSED_RESULT MakeWH(SkScalar w, SkScalar h) {
3952687ae05cbd309072f0b5bb9d872d758108a2776reed@android.com        SkRect r;
3962687ae05cbd309072f0b5bb9d872d758108a2776reed@android.com        r.set(0, 0, w, h);
3972687ae05cbd309072f0b5bb9d872d758108a2776reed@android.com        return r;
3982687ae05cbd309072f0b5bb9d872d758108a2776reed@android.com    }
3992687ae05cbd309072f0b5bb9d872d758108a2776reed@android.com
4005d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com    static SkRect SK_WARN_UNUSED_RESULT MakeSize(const SkSize& size) {
401233481ebd0b8644a319443cde33e75266e990ee6reed@android.com        SkRect r;
402233481ebd0b8644a319443cde33e75266e990ee6reed@android.com        r.set(0, 0, size.width(), size.height());
403233481ebd0b8644a319443cde33e75266e990ee6reed@android.com        return r;
404233481ebd0b8644a319443cde33e75266e990ee6reed@android.com    }
4054d28d9889b033777afc1950474296d37887ef71bskia.committer@gmail.com
4065d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com    static SkRect SK_WARN_UNUSED_RESULT MakeLTRB(SkScalar l, SkScalar t, SkScalar r, SkScalar b) {
407233481ebd0b8644a319443cde33e75266e990ee6reed@android.com        SkRect rect;
408233481ebd0b8644a319443cde33e75266e990ee6reed@android.com        rect.set(l, t, r, b);
409233481ebd0b8644a319443cde33e75266e990ee6reed@android.com        return rect;
410233481ebd0b8644a319443cde33e75266e990ee6reed@android.com    }
411233481ebd0b8644a319443cde33e75266e990ee6reed@android.com
4125d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com    static SkRect SK_WARN_UNUSED_RESULT MakeXYWH(SkScalar x, SkScalar y, SkScalar w, SkScalar h) {
413233481ebd0b8644a319443cde33e75266e990ee6reed@android.com        SkRect r;
414233481ebd0b8644a319443cde33e75266e990ee6reed@android.com        r.set(x, y, x + w, y + h);
4157b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com        return r;
4167b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com    }
4177b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com
4184469938e92d779dff05e745559e67907bbf21e78reed@google.com    SK_ATTR_DEPRECATED("use Make()")
4197b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com    static SkRect SK_WARN_UNUSED_RESULT MakeFromIRect(const SkIRect& irect) {
4207b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com        SkRect r;
4217b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com        r.set(SkIntToScalar(irect.fLeft),
4227b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com              SkIntToScalar(irect.fTop),
4237b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com              SkIntToScalar(irect.fRight),
4247b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com              SkIntToScalar(irect.fBottom));
425233481ebd0b8644a319443cde33e75266e990ee6reed@android.com        return r;
426233481ebd0b8644a319443cde33e75266e990ee6reed@android.com    }
42743a6b6a046774576378dfb725e19632a0c8530b7skia.committer@gmail.com
4281d6cff7293582c66b1b0a8b3f32ed5d993913d62reed@google.com    static SkRect SK_WARN_UNUSED_RESULT Make(const SkIRect& irect) {
4291d6cff7293582c66b1b0a8b3f32ed5d993913d62reed@google.com        SkRect r;
4301d6cff7293582c66b1b0a8b3f32ed5d993913d62reed@google.com        r.set(SkIntToScalar(irect.fLeft),
4311d6cff7293582c66b1b0a8b3f32ed5d993913d62reed@google.com              SkIntToScalar(irect.fTop),
4321d6cff7293582c66b1b0a8b3f32ed5d993913d62reed@google.com              SkIntToScalar(irect.fRight),
4331d6cff7293582c66b1b0a8b3f32ed5d993913d62reed@google.com              SkIntToScalar(irect.fBottom));
4341d6cff7293582c66b1b0a8b3f32ed5d993913d62reed@google.com        return r;
4351d6cff7293582c66b1b0a8b3f32ed5d993913d62reed@google.com    }
43643a6b6a046774576378dfb725e19632a0c8530b7skia.committer@gmail.com
4371607863b608b7db6c813228768ed5d72997bbc82reed@google.com    /**
4381607863b608b7db6c813228768ed5d72997bbc82reed@google.com     *  Return true if the rectangle's width or height are <= 0
4391607863b608b7db6c813228768ed5d72997bbc82reed@google.com     */
4401607863b608b7db6c813228768ed5d72997bbc82reed@google.com    bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; }
441fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
442b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org    bool isLargest() const { return SK_ScalarMin == fLeft &&
443b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org                                    SK_ScalarMin == fTop &&
444b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org                                    SK_ScalarMax == fRight &&
445b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org                                    SK_ScalarMax == fBottom; }
446b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org
4471607863b608b7db6c813228768ed5d72997bbc82reed@google.com    /**
4481607863b608b7db6c813228768ed5d72997bbc82reed@google.com     *  Returns true iff all values in the rect are finite. If any are
4491607863b608b7db6c813228768ed5d72997bbc82reed@google.com     *  infinite or NaN (or SK_FixedNaN when SkScalar is fixed) then this
4501607863b608b7db6c813228768ed5d72997bbc82reed@google.com     *  returns false.
4511607863b608b7db6c813228768ed5d72997bbc82reed@google.com     */
4521607863b608b7db6c813228768ed5d72997bbc82reed@google.com    bool isFinite() const {
4537b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com        float accum = 0;
4547b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com        accum *= fLeft;
4557b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com        accum *= fTop;
4567b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com        accum *= fRight;
4577b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com        accum *= fBottom;
458fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
4597b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com        // accum is either NaN or it is finite (zero).
4607b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com        SkASSERT(0 == accum || !(accum == accum));
4617b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com
4621607863b608b7db6c813228768ed5d72997bbc82reed@google.com        // value==value will be true iff value is not NaN
4637b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com        // TODO: is it faster to say !accum or accum==accum?
4647b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com        return accum == accum;
4651607863b608b7db6c813228768ed5d72997bbc82reed@google.com    }
4661607863b608b7db6c813228768ed5d72997bbc82reed@google.com
467d6195f956fdccef865224520a624e3fd968573d0reed@google.com    SkScalar    x() const { return fLeft; }
468d6195f956fdccef865224520a624e3fd968573d0reed@google.com    SkScalar    y() const { return fTop; }
46920efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    SkScalar    left() const { return fLeft; }
47020efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    SkScalar    top() const { return fTop; }
47120efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    SkScalar    right() const { return fRight; }
47220efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    SkScalar    bottom() const { return fBottom; }
4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar    width() const { return fRight - fLeft; }
4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar    height() const { return fBottom - fTop; }
4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar    centerX() const { return SkScalarHalf(fLeft + fRight); }
4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar    centerY() const { return SkScalarHalf(fTop + fBottom); }
4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
478e174ea4bb1f07c4d15c50716012e5c8429e9afebbsalomon@google.com    friend bool operator==(const SkRect& a, const SkRect& b) {
479e1e7d7a6b55504d97ce9f30202a179b63800093breed@google.com        return SkScalarsEqual((SkScalar*)&a, (SkScalar*)&b, 4);
4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
481da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com
482e174ea4bb1f07c4d15c50716012e5c8429e9afebbsalomon@google.com    friend bool operator!=(const SkRect& a, const SkRect& b) {
483e1e7d7a6b55504d97ce9f30202a179b63800093breed@google.com        return !SkScalarsEqual((SkScalar*)&a, (SkScalar*)&b, 4);
4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
48624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    /** return the 4 points that enclose the rectangle (top-left, top-right, bottom-right,
48724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        bottom-left). TODO: Consider adding param to control whether quad is CW or CCW.
48824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org     */
4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void toQuad(SkPoint quad[4]) const;
4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set this rectangle to the empty rectangle (0,0,0,0)
4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
4938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void setEmpty() { memset(this, 0, sizeof(*this)); }
4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
495da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    void set(const SkIRect& src) {
4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLeft   = SkIntToScalar(src.fLeft);
4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fTop    = SkIntToScalar(src.fTop);
4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fRight  = SkIntToScalar(src.fRight);
4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBottom = SkIntToScalar(src.fBottom);
5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
502da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    void set(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLeft   = left;
5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fTop    = top;
5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fRight  = right;
5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBottom = bottom;
5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
50820efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    // alias for set(l, t, r, b)
50920efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    void setLTRB(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
51020efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        this->set(left, top, right, bottom);
51120efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    }
51220efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com
5138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Initialize the rect with the 4 specified integers. The routine handles
5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        converting them to scalars (by calling SkIntToScalar)
5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com     */
5168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void iset(int left, int top, int right, int bottom) {
5178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLeft   = SkIntToScalar(left);
5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fTop    = SkIntToScalar(top);
5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fRight  = SkIntToScalar(right);
5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBottom = SkIntToScalar(bottom);
5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5236f54724c11ab739fa0d6deff1d4b564596fe3970reed@google.com    /**
5246f54724c11ab739fa0d6deff1d4b564596fe3970reed@google.com     *  Set this rectangle to be left/top at 0,0, and have the specified width
5256f54724c11ab739fa0d6deff1d4b564596fe3970reed@google.com     *  and height (automatically converted to SkScalar).
5266f54724c11ab739fa0d6deff1d4b564596fe3970reed@google.com     */
5276f54724c11ab739fa0d6deff1d4b564596fe3970reed@google.com    void isetWH(int width, int height) {
5286f54724c11ab739fa0d6deff1d4b564596fe3970reed@google.com        fLeft = fTop = 0;
5296f54724c11ab739fa0d6deff1d4b564596fe3970reed@google.com        fRight = SkIntToScalar(width);
5306f54724c11ab739fa0d6deff1d4b564596fe3970reed@google.com        fBottom = SkIntToScalar(height);
5316f54724c11ab739fa0d6deff1d4b564596fe3970reed@google.com    }
5324d28d9889b033777afc1950474296d37887ef71bskia.committer@gmail.com
5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set this rectangle to be the bounds of the array of points.
5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        If the array is empty (count == 0), then set this rectangle
5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        to the empty rectangle (0,0,0,0)
5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
5370bb18bb264b26afca45452910437c09445e23a3creed@google.com    void set(const SkPoint pts[], int count) {
5380bb18bb264b26afca45452910437c09445e23a3creed@google.com        // set() had been checking for non-finite values, so keep that behavior
5390bb18bb264b26afca45452910437c09445e23a3creed@google.com        // for now. Now that we have setBoundsCheck(), we may decide to make
5400bb18bb264b26afca45452910437c09445e23a3creed@google.com        // set() be simpler/faster, and not check for those.
5410bb18bb264b26afca45452910437c09445e23a3creed@google.com        (void)this->setBoundsCheck(pts, count);
5420bb18bb264b26afca45452910437c09445e23a3creed@google.com    }
5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
54420efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    // alias for set(pts, count)
54520efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    void setBounds(const SkPoint pts[], int count) {
5460bb18bb264b26afca45452910437c09445e23a3creed@google.com        (void)this->setBoundsCheck(pts, count);
54720efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    }
548fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
5490bb18bb264b26afca45452910437c09445e23a3creed@google.com    /**
5500bb18bb264b26afca45452910437c09445e23a3creed@google.com     *  Compute the bounds of the array of points, and set this rect to that
5510bb18bb264b26afca45452910437c09445e23a3creed@google.com     *  bounds and return true... unless a non-finite value is encountered,
5520bb18bb264b26afca45452910437c09445e23a3creed@google.com     *  in which case this rect is set to empty and false is returned.
5530bb18bb264b26afca45452910437c09445e23a3creed@google.com     */
5540bb18bb264b26afca45452910437c09445e23a3creed@google.com    bool setBoundsCheck(const SkPoint pts[], int count);
555fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
5567b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com    void set(const SkPoint& p0, const SkPoint& p1) {
5577b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com        fLeft =   SkMinScalar(p0.fX, p1.fX);
5587b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com        fRight =  SkMaxScalar(p0.fX, p1.fX);
5597b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com        fTop =    SkMinScalar(p0.fY, p1.fY);
5607b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com        fBottom = SkMaxScalar(p0.fY, p1.fY);
5617b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com    }
5627b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com
5631d12b1fd66e5be27fb4769ee09ce4fcd6bcc5979reed@google.com    void setXYWH(SkScalar x, SkScalar y, SkScalar width, SkScalar height) {
5641d12b1fd66e5be27fb4769ee09ce4fcd6bcc5979reed@google.com        fLeft = x;
5651d12b1fd66e5be27fb4769ee09ce4fcd6bcc5979reed@google.com        fTop = y;
5661d12b1fd66e5be27fb4769ee09ce4fcd6bcc5979reed@google.com        fRight = x + width;
5671d12b1fd66e5be27fb4769ee09ce4fcd6bcc5979reed@google.com        fBottom = y + height;
5681d12b1fd66e5be27fb4769ee09ce4fcd6bcc5979reed@google.com    }
5691d12b1fd66e5be27fb4769ee09ce4fcd6bcc5979reed@google.com
5703ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com    void setWH(SkScalar width, SkScalar height) {
5713ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com        fLeft = 0;
5723ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com        fTop = 0;
5733ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com        fRight = width;
5743ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com        fBottom = height;
5753ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com    }
5763ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com
57720efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    /**
57820efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com     *  Make the largest representable rectangle
57920efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com     */
58020efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    void setLargest() {
58120efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        fLeft = fTop = SK_ScalarMin;
58220efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        fRight = fBottom = SK_ScalarMax;
58320efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    }
584fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
58520efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    /**
58620efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com     *  Make the largest representable rectangle, but inverted (e.g. fLeft will
58720efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com     *  be max and right will be min).
58820efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com     */
58920efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    void setLargestInverted() {
59020efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        fLeft = fTop = SK_ScalarMax;
59120efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        fRight = fBottom = SK_ScalarMin;
59220efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    }
59320efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com
5945c404c55772973126d8b3c6942ee42c9361d3fadreed    /**
5955c404c55772973126d8b3c6942ee42c9361d3fadreed     *  Return a new Rect, built as an offset of this rect.
5965c404c55772973126d8b3c6942ee42c9361d3fadreed     */
5975c404c55772973126d8b3c6942ee42c9361d3fadreed    SkRect makeOffset(SkScalar dx, SkScalar dy) const {
5985c404c55772973126d8b3c6942ee42c9361d3fadreed        return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy);
5995c404c55772973126d8b3c6942ee42c9361d3fadreed    }
6005c404c55772973126d8b3c6942ee42c9361d3fadreed
6015c404c55772973126d8b3c6942ee42c9361d3fadreed    /**
6025c404c55772973126d8b3c6942ee42c9361d3fadreed     *  Return a new Rect, built as an inset of this rect.
6035c404c55772973126d8b3c6942ee42c9361d3fadreed     */
6045c404c55772973126d8b3c6942ee42c9361d3fadreed    SkRect makeInset(SkScalar dx, SkScalar dy) const {
6055c404c55772973126d8b3c6942ee42c9361d3fadreed        return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, fBottom - dy);
6065c404c55772973126d8b3c6942ee42c9361d3fadreed    }
6075c404c55772973126d8b3c6942ee42c9361d3fadreed
6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Offset set the rectangle by adding dx to its left and right,
6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        and adding dy to its top and bottom.
6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
611da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    void offset(SkScalar dx, SkScalar dy) {
6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLeft   += dx;
6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fTop    += dy;
6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fRight  += dx;
6158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBottom += dy;
616fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
618da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    void offset(const SkPoint& delta) {
619da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com        this->offset(delta.fX, delta.fY);
620da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    }
621da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com
6224d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com    /**
6234d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com     *  Offset this rect such its new x() and y() will equal newX and newY.
6244d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com     */
6254d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com    void offsetTo(SkScalar newX, SkScalar newY) {
6264d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com        fRight += newX - fLeft;
6274d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com        fBottom += newY - fTop;
6284d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com        fLeft = newX;
6294d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com        fTop = newY;
6304d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com    }
63172b2e6fff3f54c6aa80a98eab4c73f02a8cd450dskia.committer@gmail.com
632647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com    /** Inset the rectangle by (dx,dy). If dx is positive, then the sides are
633647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com        moved inwards, making the rectangle narrower. If dx is negative, then
634647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com        the sides are moved outwards, making the rectangle wider. The same holds
635647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com         true for dy and the top and bottom.
6368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
637da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    void inset(SkScalar dx, SkScalar dy)  {
6388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLeft   += dx;
6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fTop    += dy;
6408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fRight  -= dx;
6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBottom -= dy;
6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
644647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com   /** Outset the rectangle by (dx,dy). If dx is positive, then the sides are
645647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com       moved outwards, making the rectangle wider. If dx is negative, then the
6466623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com       sides are moved inwards, making the rectangle narrower. The same holds
647647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com       true for dy and the top and bottom.
648647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com    */
649647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com    void outset(SkScalar dx, SkScalar dy)  { this->inset(-dx, -dy); }
650647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com
6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** If this rectangle intersects r, return true and set this rectangle to that
6528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        intersection, otherwise return false and do not change this rectangle.
6538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        If either rectangle is empty, do nothing and return false.
6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
6558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool intersect(const SkRect& r);
656ae8f9528fd0052e06653272abb44a1f49a3b726bmike@reedtribe.org    bool intersect2(const SkRect& r);
6578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** If this rectangle intersects the rectangle specified by left, top, right, bottom,
6598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true and set this rectangle to that intersection, otherwise return false
6608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        and do not change this rectangle.
6618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        If either rectangle is empty, do nothing and return false.
6628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
6638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool intersect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
6648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
665af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com    /**
666af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  Return true if this rectangle is not empty, and the specified sides of
667af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  a rectangle are not empty, and they intersect.
668af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     */
669da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    bool intersects(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) const {
6708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return // first check that both are not empty
6718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com               left < right && top < bottom &&
6728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com               fLeft < fRight && fTop < fBottom &&
6738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com               // now check for intersection
6748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com               fLeft < right && left < fRight &&
6758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com               fTop < bottom && top < fBottom;
6768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
677f0f617a502ae9298056654811542c62769a906c8reed@google.com
678f0f617a502ae9298056654811542c62769a906c8reed@google.com    /** If rectangles a and b intersect, return true and set this rectangle to
679f0f617a502ae9298056654811542c62769a906c8reed@google.com     *  that intersection, otherwise return false and do not change this
680f0f617a502ae9298056654811542c62769a906c8reed@google.com     *  rectangle. If either rectangle is empty, do nothing and return false.
681f0f617a502ae9298056654811542c62769a906c8reed@google.com     */
682f0f617a502ae9298056654811542c62769a906c8reed@google.com    bool intersect(const SkRect& a, const SkRect& b);
683fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
684af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com    /**
685af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  Return true if rectangles a and b are not empty and intersect.
686af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     */
687da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    static bool Intersects(const SkRect& a, const SkRect& b) {
688af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com        return  !a.isEmpty() && !b.isEmpty() &&
689af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com                a.fLeft < b.fRight && b.fLeft < a.fRight &&
690af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com                a.fTop < b.fBottom && b.fTop < a.fBottom;
6918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
692fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
693af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com    /**
694af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  Update this rectangle to enclose itself and the specified rectangle.
695af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  If this rectangle is empty, just set it to the specified rectangle.
696af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  If the specified rectangle is empty, do nothing.
697af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     */
6988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void join(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
6998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Update this rectangle to enclose itself and the specified rectangle.
7018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        If this rectangle is empty, just set it to the specified rectangle. If the specified
7028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rectangle is empty, do nothing.
7038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
704da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    void join(const SkRect& r) {
7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
7068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
70720efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    // alias for join()
70820efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    void growToInclude(const SkRect& r) { this->join(r); }
70920efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com
710af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com    /**
711af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  Grow the rect to include the specified (x,y). After this call, the
712af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  following will be true: fLeft <= x <= fRight && fTop <= y <= fBottom.
713af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *
714af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  This is close, but not quite the same contract as contains(), since
715af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  contains() treats the left and top different from the right and bottom.
716af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  contains(x,y) -> fLeft <= x < fRight && fTop <= y < fBottom. Also note
717af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  that contains(x,y) always returns false if the rect is empty.
718af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     */
71920efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    void growToInclude(SkScalar x, SkScalar y) {
72020efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        fLeft  = SkMinScalar(x, fLeft);
721ee9aa304579b3d5314519372728187879456d49dbsalomon@google.com        fRight = SkMaxScalar(x, fRight);
722ee9aa304579b3d5314519372728187879456d49dbsalomon@google.com        fTop    = SkMinScalar(y, fTop);
72320efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        fBottom = SkMaxScalar(y, fBottom);
72420efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    }
725fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
726b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org    /** Bulk version of growToInclude */
727b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org    void growToInclude(const SkPoint pts[], int count) {
728b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org        this->growToInclude(pts, sizeof(SkPoint), count);
729b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org    }
730b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org
731b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org    /** Bulk version of growToInclude with stride. */
732b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org    void growToInclude(const SkPoint pts[], size_t stride, int count) {
733b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org        SkASSERT(count >= 0);
734b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org        SkASSERT(stride >= sizeof(SkPoint));
735b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org        const SkPoint* end = (const SkPoint*)((intptr_t)pts + count * stride);
736b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org        for (; pts < end; pts = (const SkPoint*)((intptr_t)pts + stride)) {
737b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org            this->growToInclude(pts->fX, pts->fY);
738b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org        }
739b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org    }
740b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org
741af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com    /**
742af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  Return true if this rectangle contains r, and if both rectangles are
743af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  not empty.
744af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     */
745da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    bool contains(const SkRect& r) const {
7464db592c4085afed2be27a208d778f9ee13e671abreed@google.com        // todo: can we eliminate the this->isEmpty check?
747af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com        return  !r.isEmpty() && !this->isEmpty() &&
7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fLeft <= r.fLeft && fTop <= r.fTop &&
7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fRight >= r.fRight && fBottom >= r.fBottom;
7508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
752af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com    /**
753af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  Set the dst rectangle by rounding this rectangle's coordinates to their
754126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com     *  nearest integer values using SkScalarRoundToInt.
755af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     */
756da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    void round(SkIRect* dst) const {
7578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(dst);
7584d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com        dst->set(SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
7594d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com                 SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom));
7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
762af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com    /**
7634e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org     *  Variant of round() that explicitly performs the rounding step (i.e. floor(x + 0.5)) using
7644e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org     *  double instead of SkScalar (float). It does this by calling SkDScalarRoundToInt(), which
7654e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org     *  may be slower than calling SkScalarRountToInt(), but gives slightly more accurate results.
7664e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org     *
7674e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org     *  e.g.
7684e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org     *      SkScalar x = 0.49999997f;
7694e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org     *      int ix = SkScalarRoundToInt(x);
7704e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org     *      SkASSERT(0 == ix);  // <--- fails
7714e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org     *      ix = SkDScalarRoundToInt(x);
7724e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org     *      SkASSERT(0 == ix);  // <--- succeeds
7734e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org     */
7744e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org    void dround(SkIRect* dst) const {
7754e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org        SkASSERT(dst);
7764e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org        dst->set(SkDScalarRoundToInt(fLeft), SkDScalarRoundToInt(fTop),
7774e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org                 SkDScalarRoundToInt(fRight), SkDScalarRoundToInt(fBottom));
7784e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org    }
7794e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org
7804e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org    /**
781af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  Set the dst rectangle by rounding "out" this rectangle, choosing the
782af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  SkScalarFloor of top and left, and the SkScalarCeil of right and bottom.
783af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     */
784da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    void roundOut(SkIRect* dst) const {
7858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(dst);
7864d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com        dst->set(SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
7874d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com                 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom));
7888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
790af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com    /**
791099d22dbce650abdda0c5c5a7ee89ee0850897f1reed@google.com     *  Expand this rectangle by rounding its coordinates "out", choosing the
792099d22dbce650abdda0c5c5a7ee89ee0850897f1reed@google.com     *  floor of top and left, and the ceil of right and bottom. If this rect
793099d22dbce650abdda0c5c5a7ee89ee0850897f1reed@google.com     *  is already on integer coordinates, then it will be unchanged.
794099d22dbce650abdda0c5c5a7ee89ee0850897f1reed@google.com     */
795099d22dbce650abdda0c5c5a7ee89ee0850897f1reed@google.com    void roundOut() {
796099d22dbce650abdda0c5c5a7ee89ee0850897f1reed@google.com        this->set(SkScalarFloorToScalar(fLeft),
797099d22dbce650abdda0c5c5a7ee89ee0850897f1reed@google.com                  SkScalarFloorToScalar(fTop),
798099d22dbce650abdda0c5c5a7ee89ee0850897f1reed@google.com                  SkScalarCeilToScalar(fRight),
799099d22dbce650abdda0c5c5a7ee89ee0850897f1reed@google.com                  SkScalarCeilToScalar(fBottom));
800099d22dbce650abdda0c5c5a7ee89ee0850897f1reed@google.com    }
801099d22dbce650abdda0c5c5a7ee89ee0850897f1reed@google.com
802099d22dbce650abdda0c5c5a7ee89ee0850897f1reed@google.com    /**
8034d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com     *  Set the dst rectangle by rounding "in" this rectangle, choosing the
8044d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com     *  ceil of top and left, and the floor of right and bottom. This does *not*
8054d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com     *  call sort(), so it is possible that the resulting rect is inverted...
8064d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com     *  e.g. left >= right or top >= bottom. Call isEmpty() to detect that.
8074d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com     */
8084d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com    void roundIn(SkIRect* dst) const {
8094d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com        SkASSERT(dst);
8104d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com        dst->set(SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
8114d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com                 SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom));
8124d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com    }
81372b2e6fff3f54c6aa80a98eab4c73f02a8cd450dskia.committer@gmail.com
814126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com    /**
815126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com     *  Return a new SkIRect which is contains the rounded coordinates of this
816126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com     *  rect using SkScalarRoundToInt.
817126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com     */
818126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com    SkIRect round() const {
819126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com        SkIRect ir;
820126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com        this->round(&ir);
821126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com        return ir;
822126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com    }
82372b2e6fff3f54c6aa80a98eab4c73f02a8cd450dskia.committer@gmail.com
8244d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com    /**
825af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  Swap top/bottom or left/right if there are flipped (i.e. if width()
826af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  or height() would have returned a negative value.) This should be called
827af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  if the edges are computed separately, and may have crossed over each
828af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  other. When this returns, left <= right && top <= bottom
829af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     */
8308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void sort();
831eed625df23ee83a94f1814c43744b1961b79adf1skia.committer@gmail.com
832c7d0ea3cd328566958bfcb86b4488dcbb94dd5ecreed@google.com    /**
833c7d0ea3cd328566958bfcb86b4488dcbb94dd5ecreed@google.com     *  cast-safe way to treat the rect as an array of (4) SkScalars.
834c7d0ea3cd328566958bfcb86b4488dcbb94dd5ecreed@google.com     */
835c7d0ea3cd328566958bfcb86b4488dcbb94dd5ecreed@google.com    const SkScalar* asScalars() const { return &fLeft; }
836b6b02526438d6839481fb40ccf610d28f7652397bsalomon
837b6b02526438d6839481fb40ccf610d28f7652397bsalomon#ifdef SK_DEVELOPER
838b6b02526438d6839481fb40ccf610d28f7652397bsalomon    /**
839b6b02526438d6839481fb40ccf610d28f7652397bsalomon     * Dumps the rect using SkDebugf. This is intended for Skia development debugging. Don't
840b6b02526438d6839481fb40ccf610d28f7652397bsalomon     * rely on the existence of this function or the formatting of its output.
841b6b02526438d6839481fb40ccf610d28f7652397bsalomon     */
842b6b02526438d6839481fb40ccf610d28f7652397bsalomon    void dump() const {
843b6b02526438d6839481fb40ccf610d28f7652397bsalomon        SkDebugf("{ l: %f, t: %f, r: %f, b: %f }", fLeft, fTop, fRight, fBottom);
844b6b02526438d6839481fb40ccf610d28f7652397bsalomon    }
845b6b02526438d6839481fb40ccf610d28f7652397bsalomon#endif
846b6b02526438d6839481fb40ccf610d28f7652397bsalomon
8478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
8488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
850