18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkRect_DEFINED
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkRect_DEFINED
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPoint.h"
12233481ebd0b8644a319443cde33e75266e990ee6reed@android.com#include "SkSize.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1444701df5ce572ac3cccec785cf52103d3d5d14a5joshualittstruct SkRect;
1544701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
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
80157f36d358814a2235aa6284b78a67b725076063reed    SkISize size() const { return SkISize::Make(this->width(), this->height()); }
81157f36d358814a2235aa6284b78a67b725076063reed
82c74ab1813013b169ad500fcf1fa62be551041442reed@google.com    /**
836898d52c371309d81c2184ea991785d2485323e4reed@google.com     *  Since the center of an integer rect may fall on a factional value, this
846898d52c371309d81c2184ea991785d2485323e4reed@google.com     *  method is defined to return (right + left) >> 1.
856898d52c371309d81c2184ea991785d2485323e4reed@google.com     *
866898d52c371309d81c2184ea991785d2485323e4reed@google.com     *  This is a specific "truncation" of the average, which is different than
876898d52c371309d81c2184ea991785d2485323e4reed@google.com     *  (right + left) / 2 when the sum is negative.
886898d52c371309d81c2184ea991785d2485323e4reed@google.com     */
896898d52c371309d81c2184ea991785d2485323e4reed@google.com    int centerX() const { return (fRight + fLeft) >> 1; }
90d9f7503e0cb0c4db856f53b4bdeec1332db6f296skia.committer@gmail.com
916898d52c371309d81c2184ea991785d2485323e4reed@google.com    /**
926898d52c371309d81c2184ea991785d2485323e4reed@google.com     *  Since the center of an integer rect may fall on a factional value, this
936898d52c371309d81c2184ea991785d2485323e4reed@google.com     *  method is defined to return (bottom + top) >> 1
946898d52c371309d81c2184ea991785d2485323e4reed@google.com     *
956898d52c371309d81c2184ea991785d2485323e4reed@google.com     *  This is a specific "truncation" of the average, which is different than
966898d52c371309d81c2184ea991785d2485323e4reed@google.com     *  (bottom + top) / 2 when the sum is negative.
976898d52c371309d81c2184ea991785d2485323e4reed@google.com     */
986898d52c371309d81c2184ea991785d2485323e4reed@google.com    int centerY() const { return (fBottom + fTop) >> 1; }
99d9f7503e0cb0c4db856f53b4bdeec1332db6f296skia.committer@gmail.com
1006898d52c371309d81c2184ea991785d2485323e4reed@google.com    /**
101c74ab1813013b169ad500fcf1fa62be551041442reed@google.com     *  Return true if the rectangle's width or height are <= 0
102c74ab1813013b169ad500fcf1fa62be551041442reed@google.com     */
103c74ab1813013b169ad500fcf1fa62be551041442reed@google.com    bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; }
104fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
105194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    bool isLargest() const { return SK_MinS32 == fLeft &&
106194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org                                    SK_MinS32 == fTop &&
107194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org                                    SK_MaxS32 == fRight &&
108194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org                                    SK_MaxS32 == fBottom; }
109194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
110b530ef5869c5c64af8f3b3c62ed7711fe4325c9creed@google.com    friend bool operator==(const SkIRect& a, const SkIRect& b) {
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return !memcmp(&a, &b, sizeof(a));
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
113da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com
114b530ef5869c5c64af8f3b3c62ed7711fe4325c9creed@google.com    friend bool operator!=(const SkIRect& a, const SkIRect& b) {
115b530ef5869c5c64af8f3b3c62ed7711fe4325c9creed@google.com        return !(a == b);
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
118d4577757874d1dda1a3bffa3f2347c251859c27ereed@android.com    bool is16Bit() const {
119d4577757874d1dda1a3bffa3f2347c251859c27ereed@android.com        return  SkIsS16(fLeft) && SkIsS16(fTop) &&
120d4577757874d1dda1a3bffa3f2347c251859c27ereed@android.com                SkIsS16(fRight) && SkIsS16(fBottom);
121d4577757874d1dda1a3bffa3f2347c251859c27ereed@android.com    }
122d4577757874d1dda1a3bffa3f2347c251859c27ereed@android.com
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set the rectangle to (0,0,0,0)
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void setEmpty() { memset(this, 0, sizeof(*this)); }
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
127da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    void set(int32_t left, int32_t top, int32_t right, int32_t bottom) {
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLeft   = left;
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fTop    = top;
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fRight  = right;
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBottom = bottom;
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13320efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    // alias for set(l, t, r, b)
13420efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom) {
13520efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        this->set(left, top, right, bottom);
13620efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    }
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1381d12b1fd66e5be27fb4769ee09ce4fcd6bcc5979reed@google.com    void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height) {
1391d12b1fd66e5be27fb4769ee09ce4fcd6bcc5979reed@google.com        fLeft = x;
1401d12b1fd66e5be27fb4769ee09ce4fcd6bcc5979reed@google.com        fTop = y;
1411d12b1fd66e5be27fb4769ee09ce4fcd6bcc5979reed@google.com        fRight = x + width;
1421d12b1fd66e5be27fb4769ee09ce4fcd6bcc5979reed@google.com        fBottom = y + height;
1431d12b1fd66e5be27fb4769ee09ce4fcd6bcc5979reed@google.com    }
14420efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com
14520efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    /**
14620efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com     *  Make the largest representable rectangle
14720efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com     */
14820efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    void setLargest() {
14920efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        fLeft = fTop = SK_MinS32;
15020efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        fRight = fBottom = SK_MaxS32;
15120efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    }
152fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
15320efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    /**
15420efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com     *  Make the largest representable rectangle, but inverted (e.g. fLeft will
15520efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com     *  be max 32bit and right will be min 32bit).
15620efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com     */
15720efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    void setLargestInverted() {
15820efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        fLeft = fTop = SK_MaxS32;
15920efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        fRight = fBottom = SK_MinS32;
16020efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    }
161fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1625c404c55772973126d8b3c6942ee42c9361d3fadreed    /**
1635c404c55772973126d8b3c6942ee42c9361d3fadreed     *  Return a new IRect, built as an offset of this rect.
1645c404c55772973126d8b3c6942ee42c9361d3fadreed     */
16511fa2247b747eb75e2f158dc7571d458ed6c0115reed    SkIRect makeOffset(int32_t dx, int32_t dy) const {
1665c404c55772973126d8b3c6942ee42c9361d3fadreed        return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy);
1675c404c55772973126d8b3c6942ee42c9361d3fadreed    }
1685c404c55772973126d8b3c6942ee42c9361d3fadreed
1695c404c55772973126d8b3c6942ee42c9361d3fadreed    /**
1705c404c55772973126d8b3c6942ee42c9361d3fadreed     *  Return a new IRect, built as an inset of this rect.
1715c404c55772973126d8b3c6942ee42c9361d3fadreed     */
17211fa2247b747eb75e2f158dc7571d458ed6c0115reed    SkIRect makeInset(int32_t dx, int32_t dy) const {
1735c404c55772973126d8b3c6942ee42c9361d3fadreed        return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, fBottom - dy);
1745c404c55772973126d8b3c6942ee42c9361d3fadreed    }
1755c404c55772973126d8b3c6942ee42c9361d3fadreed
17611fa2247b747eb75e2f158dc7571d458ed6c0115reed    /**
17711fa2247b747eb75e2f158dc7571d458ed6c0115reed     *  Return a new Rect, built as an outset of this rect.
17811fa2247b747eb75e2f158dc7571d458ed6c0115reed     */
17911fa2247b747eb75e2f158dc7571d458ed6c0115reed    SkIRect makeOutset(int32_t dx, int32_t dy) const {
18011fa2247b747eb75e2f158dc7571d458ed6c0115reed        return MakeLTRB(fLeft - dx, fTop - dy, fRight + dx, fBottom + dy);
18111fa2247b747eb75e2f158dc7571d458ed6c0115reed    }
18211fa2247b747eb75e2f158dc7571d458ed6c0115reed
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Offset set the rectangle by adding dx to its left and right,
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        and adding dy to its top and bottom.
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
186da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    void offset(int32_t dx, int32_t dy) {
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLeft   += dx;
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fTop    += dy;
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fRight  += dx;
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBottom += dy;
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
193da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    void offset(const SkIPoint& delta) {
194da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com        this->offset(delta.fX, delta.fY);
195da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    }
196da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com
1974d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com    /**
1984d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com     *  Offset this rect such its new x() and y() will equal newX and newY.
1994d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com     */
2004d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com    void offsetTo(int32_t newX, int32_t newY) {
2014d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com        fRight += newX - fLeft;
2024d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com        fBottom += newY - fTop;
2034d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com        fLeft = newX;
2044d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com        fTop = newY;
2054d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com    }
2064d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Inset the rectangle by (dx,dy). If dx is positive, then the sides are moved inwards,
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        making the rectangle narrower. If dx is negative, then the sides are moved outwards,
2096623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com        making the rectangle wider. The same holds true for dy and the top and bottom.
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
211da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    void inset(int32_t dx, int32_t dy) {
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLeft   += dx;
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fTop    += dy;
2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fRight  -= dx;
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBottom -= dy;
2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
217da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com
2186623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com   /** Outset the rectangle by (dx,dy). If dx is positive, then the sides are
2196623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com       moved outwards, making the rectangle wider. If dx is negative, then the
2206623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com       sides are moved inwards, making the rectangle narrower. The same holds
2216623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com       true for dy and the top and bottom.
2226623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com    */
2236623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com    void outset(int32_t dx, int32_t dy)  { this->inset(-dx, -dy); }
2246623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com
22520efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    bool quickReject(int l, int t, int r, int b) const {
22620efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        return l >= fRight || fLeft >= r || t >= fBottom || fTop >= b;
22720efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    }
228fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns true if (x,y) is inside the rectangle and the rectangle is not
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        empty. The left and top are considered to be inside, while the right
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        and bottom are not. Thus for the rectangle (0, 0, 5, 10), the
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        points (0,0) and (0,9) are inside, while (-1,0) and (5,9) are not.
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
234da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    bool contains(int32_t x, int32_t y) const {
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return  (unsigned)(x - fLeft) < (unsigned)(fRight - fLeft) &&
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                (unsigned)(y - fTop) < (unsigned)(fBottom - fTop);
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns true if the 4 specified sides of a rectangle are inside or equal to this rectangle.
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        If either rectangle is empty, contains() returns false.
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
242da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    bool contains(int32_t left, int32_t top, int32_t right, int32_t bottom) const {
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return  left < right && top < bottom && !this->isEmpty() && // check for empties
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fLeft <= left && fTop <= top &&
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fRight >= right && fBottom >= bottom;
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns true if the specified rectangle r is inside or equal to this rectangle.
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
250da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    bool contains(const SkIRect& r) const {
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return  !r.isEmpty() && !this->isEmpty() &&     // check for empties
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fLeft <= r.fLeft && fTop <= r.fTop &&
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fRight >= r.fRight && fBottom >= r.fBottom;
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25644701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    /** Returns true if the specified rectangle r is inside or equal to this rectangle.
25744701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    */
25844701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    bool contains(const SkRect& r) const;
25944701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Return true if this rectangle contains the specified rectangle.
2615d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com        For speed, this method does not check if either this or the specified
2625d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com        rectangles are empty, and if either is, its return value is undefined.
2635d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com        In the debugging build however, we assert that both this and the
2645d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com        specified rectangles are non-empty.
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool containsNoEmptyCheck(int32_t left, int32_t top,
2675d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com                              int32_t right, int32_t bottom) const {
2685d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com        SkASSERT(fLeft < fRight && fTop < fBottom);
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(left < right && top < bottom);
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return fLeft <= left && fTop <= top &&
2725d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com               fRight >= right && fBottom >= bottom;
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
274fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2750d10280190c411b18feb569a2248552047d1aa93reed@google.com    bool containsNoEmptyCheck(const SkIRect& r) const {
2760d10280190c411b18feb569a2248552047d1aa93reed@google.com        return containsNoEmptyCheck(r.fLeft, r.fTop, r.fRight, r.fBottom);
2770d10280190c411b18feb569a2248552047d1aa93reed@google.com    }
278fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** If r intersects this rectangle, return true and set this rectangle to that
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        intersection, otherwise return false and do not change this rectangle.
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        If either rectangle is empty, do nothing and return false.
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
283f4e5995ac70d4614e0a05b92a8a03e2b7d76bd9crobertphillips    bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& r) {
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->intersect(r.fLeft, r.fTop, r.fRight, r.fBottom);
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** If rectangles a and b intersect, return true and set this rectangle to
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        that intersection, otherwise return false and do not change this
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rectangle. If either rectangle is empty, do nothing and return false.
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
291f4e5995ac70d4614e0a05b92a8a03e2b7d76bd9crobertphillips    bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& a, const SkIRect& b) {
292fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!a.isEmpty() && !b.isEmpty() &&
294da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com                a.fLeft < b.fRight && b.fLeft < a.fRight &&
295da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com                a.fTop < b.fBottom && b.fTop < a.fBottom) {
2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fLeft   = SkMax32(a.fLeft,   b.fLeft);
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fTop    = SkMax32(a.fTop,    b.fTop);
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fRight  = SkMin32(a.fRight,  b.fRight);
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fBottom = SkMin32(a.fBottom, b.fBottom);
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
304fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** If rectangles a and b intersect, return true and set this rectangle to
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        that intersection, otherwise return false and do not change this
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rectangle. For speed, no check to see if a or b are empty is performed.
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        If either is, then the return result is undefined. In the debug build,
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        we assert that both rectangles are non-empty.
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
311f4e5995ac70d4614e0a05b92a8a03e2b7d76bd9crobertphillips    bool SK_WARN_UNUSED_RESULT intersectNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(!a.isEmpty() && !b.isEmpty());
313fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (a.fLeft < b.fRight && b.fLeft < a.fRight &&
315da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com                a.fTop < b.fBottom && b.fTop < a.fBottom) {
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fLeft   = SkMax32(a.fLeft,   b.fLeft);
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fTop    = SkMax32(a.fTop,    b.fTop);
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fRight  = SkMin32(a.fRight,  b.fRight);
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fBottom = SkMin32(a.fBottom, b.fBottom);
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** If the rectangle specified by left,top,right,bottom intersects this rectangle,
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true and set this rectangle to that intersection,
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        otherwise return false and do not change this rectangle.
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        If either rectangle is empty, do nothing and return false.
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
330f4e5995ac70d4614e0a05b92a8a03e2b7d76bd9crobertphillips    bool SK_WARN_UNUSED_RESULT intersect(int32_t left, int32_t top,
331f4e5995ac70d4614e0a05b92a8a03e2b7d76bd9crobertphillips                                         int32_t right, int32_t bottom) {
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (left < right && top < bottom && !this->isEmpty() &&
333da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com                fLeft < right && left < fRight && fTop < bottom && top < fBottom) {
3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (fLeft < left) fLeft = left;
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (fTop < top) fTop = top;
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (fRight > right) fRight = right;
3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (fBottom > bottom) fBottom = bottom;
3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
342fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns true if a and b are not empty, and they intersect
3440d10280190c411b18feb569a2248552047d1aa93reed@google.com     */
345da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    static bool Intersects(const SkIRect& a, const SkIRect& b) {
3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return  !a.isEmpty() && !b.isEmpty() &&              // check for empties
347f4e5995ac70d4614e0a05b92a8a03e2b7d76bd9crobertphillips                a.fLeft < b.fRight && b.fLeft < a.fRight &&
348f4e5995ac70d4614e0a05b92a8a03e2b7d76bd9crobertphillips                a.fTop < b.fBottom && b.fTop < a.fBottom;
3490d10280190c411b18feb569a2248552047d1aa93reed@google.com    }
350fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3510d10280190c411b18feb569a2248552047d1aa93reed@google.com    /**
3520d10280190c411b18feb569a2248552047d1aa93reed@google.com     *  Returns true if a and b intersect. debug-asserts that neither are empty.
3530d10280190c411b18feb569a2248552047d1aa93reed@google.com     */
3540d10280190c411b18feb569a2248552047d1aa93reed@google.com    static bool IntersectsNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
3550d10280190c411b18feb569a2248552047d1aa93reed@google.com        SkASSERT(!a.isEmpty());
3560d10280190c411b18feb569a2248552047d1aa93reed@google.com        SkASSERT(!b.isEmpty());
3570d10280190c411b18feb569a2248552047d1aa93reed@google.com        return  a.fLeft < b.fRight && b.fLeft < a.fRight &&
3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                a.fTop < b.fBottom && b.fTop < a.fBottom;
3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
360fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Update this rectangle to enclose itself and the specified rectangle.
3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        If this rectangle is empty, just set it to the specified rectangle. If the specified
3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rectangle is empty, do nothing.
3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void join(int32_t left, int32_t top, int32_t right, int32_t bottom);
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Update this rectangle to enclose itself and the specified rectangle.
3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        If this rectangle is empty, just set it to the specified rectangle. If the specified
3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rectangle is empty, do nothing.
3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
371da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    void join(const SkIRect& r) {
3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Swap top/bottom or left/right if there are flipped.
3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        This can be called if the edges are computed separately,
3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        and may have crossed over each other.
3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        When this returns, left <= right && top <= bottom
3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void sort();
38120efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com
3825d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com    static const SkIRect& SK_WARN_UNUSED_RESULT EmptyIRect() {
3834b4fb3a52c32cd4937d51d1315624545973b1322reed@google.com        static const SkIRect gEmpty = { 0, 0, 0, 0 };
38420efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        return gEmpty;
38520efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    }
3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** \struct SkRect
3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
3907ffb1b21abcc7bbed5a0fc711f6dd7b9dbb4f577ctguil@chromium.orgstruct SK_API SkRect {
3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar    fLeft, fTop, fRight, fBottom;
3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3935d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com    static SkRect SK_WARN_UNUSED_RESULT MakeEmpty() {
3942687ae05cbd309072f0b5bb9d872d758108a2776reed@android.com        SkRect r;
3952687ae05cbd309072f0b5bb9d872d758108a2776reed@android.com        r.setEmpty();
3962687ae05cbd309072f0b5bb9d872d758108a2776reed@android.com        return r;
3972687ae05cbd309072f0b5bb9d872d758108a2776reed@android.com    }
3982687ae05cbd309072f0b5bb9d872d758108a2776reed@android.com
399b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org    static SkRect SK_WARN_UNUSED_RESULT MakeLargest() {
400b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org        SkRect r;
401b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org        r.setLargest();
402b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org        return r;
403b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org    }
404b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org
4055d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com    static SkRect SK_WARN_UNUSED_RESULT MakeWH(SkScalar w, SkScalar h) {
4062687ae05cbd309072f0b5bb9d872d758108a2776reed@android.com        SkRect r;
4072687ae05cbd309072f0b5bb9d872d758108a2776reed@android.com        r.set(0, 0, w, h);
4082687ae05cbd309072f0b5bb9d872d758108a2776reed@android.com        return r;
4092687ae05cbd309072f0b5bb9d872d758108a2776reed@android.com    }
4102687ae05cbd309072f0b5bb9d872d758108a2776reed@android.com
4110393912de72bc3d8b3640c122c53470dd0da1e6dreed    static SkRect SK_WARN_UNUSED_RESULT MakeIWH(int w, int h) {
4120393912de72bc3d8b3640c122c53470dd0da1e6dreed        SkRect r;
4130393912de72bc3d8b3640c122c53470dd0da1e6dreed        r.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
4140393912de72bc3d8b3640c122c53470dd0da1e6dreed        return r;
4150393912de72bc3d8b3640c122c53470dd0da1e6dreed    }
4160393912de72bc3d8b3640c122c53470dd0da1e6dreed
4175d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com    static SkRect SK_WARN_UNUSED_RESULT MakeSize(const SkSize& size) {
418233481ebd0b8644a319443cde33e75266e990ee6reed@android.com        SkRect r;
419233481ebd0b8644a319443cde33e75266e990ee6reed@android.com        r.set(0, 0, size.width(), size.height());
420233481ebd0b8644a319443cde33e75266e990ee6reed@android.com        return r;
421233481ebd0b8644a319443cde33e75266e990ee6reed@android.com    }
4224d28d9889b033777afc1950474296d37887ef71bskia.committer@gmail.com
4235d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com    static SkRect SK_WARN_UNUSED_RESULT MakeLTRB(SkScalar l, SkScalar t, SkScalar r, SkScalar b) {
424233481ebd0b8644a319443cde33e75266e990ee6reed@android.com        SkRect rect;
425233481ebd0b8644a319443cde33e75266e990ee6reed@android.com        rect.set(l, t, r, b);
426233481ebd0b8644a319443cde33e75266e990ee6reed@android.com        return rect;
427233481ebd0b8644a319443cde33e75266e990ee6reed@android.com    }
428233481ebd0b8644a319443cde33e75266e990ee6reed@android.com
4295d64068a36b190d820afe6108b09fd78c62368dbrobertphillips@google.com    static SkRect SK_WARN_UNUSED_RESULT MakeXYWH(SkScalar x, SkScalar y, SkScalar w, SkScalar h) {
430233481ebd0b8644a319443cde33e75266e990ee6reed@android.com        SkRect r;
431233481ebd0b8644a319443cde33e75266e990ee6reed@android.com        r.set(x, y, x + w, y + h);
4327b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com        return r;
4337b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com    }
4347b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com
4354469938e92d779dff05e745559e67907bbf21e78reed@google.com    SK_ATTR_DEPRECATED("use Make()")
4367b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com    static SkRect SK_WARN_UNUSED_RESULT MakeFromIRect(const SkIRect& irect) {
4377b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com        SkRect r;
4387b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com        r.set(SkIntToScalar(irect.fLeft),
4397b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com              SkIntToScalar(irect.fTop),
4407b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com              SkIntToScalar(irect.fRight),
4417b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com              SkIntToScalar(irect.fBottom));
442233481ebd0b8644a319443cde33e75266e990ee6reed@android.com        return r;
443233481ebd0b8644a319443cde33e75266e990ee6reed@android.com    }
44443a6b6a046774576378dfb725e19632a0c8530b7skia.committer@gmail.com
4451d6cff7293582c66b1b0a8b3f32ed5d993913d62reed@google.com    static SkRect SK_WARN_UNUSED_RESULT Make(const SkIRect& irect) {
4461d6cff7293582c66b1b0a8b3f32ed5d993913d62reed@google.com        SkRect r;
4471d6cff7293582c66b1b0a8b3f32ed5d993913d62reed@google.com        r.set(SkIntToScalar(irect.fLeft),
4481d6cff7293582c66b1b0a8b3f32ed5d993913d62reed@google.com              SkIntToScalar(irect.fTop),
4491d6cff7293582c66b1b0a8b3f32ed5d993913d62reed@google.com              SkIntToScalar(irect.fRight),
4501d6cff7293582c66b1b0a8b3f32ed5d993913d62reed@google.com              SkIntToScalar(irect.fBottom));
4511d6cff7293582c66b1b0a8b3f32ed5d993913d62reed@google.com        return r;
4521d6cff7293582c66b1b0a8b3f32ed5d993913d62reed@google.com    }
45343a6b6a046774576378dfb725e19632a0c8530b7skia.committer@gmail.com
4541607863b608b7db6c813228768ed5d72997bbc82reed@google.com    /**
4551607863b608b7db6c813228768ed5d72997bbc82reed@google.com     *  Return true if the rectangle's width or height are <= 0
4561607863b608b7db6c813228768ed5d72997bbc82reed@google.com     */
4571607863b608b7db6c813228768ed5d72997bbc82reed@google.com    bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; }
458fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
459b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org    bool isLargest() const { return SK_ScalarMin == fLeft &&
460b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org                                    SK_ScalarMin == fTop &&
461b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org                                    SK_ScalarMax == fRight &&
462b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org                                    SK_ScalarMax == fBottom; }
463b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org
4641607863b608b7db6c813228768ed5d72997bbc82reed@google.com    /**
4651607863b608b7db6c813228768ed5d72997bbc82reed@google.com     *  Returns true iff all values in the rect are finite. If any are
4661607863b608b7db6c813228768ed5d72997bbc82reed@google.com     *  infinite or NaN (or SK_FixedNaN when SkScalar is fixed) then this
4671607863b608b7db6c813228768ed5d72997bbc82reed@google.com     *  returns false.
4681607863b608b7db6c813228768ed5d72997bbc82reed@google.com     */
4691607863b608b7db6c813228768ed5d72997bbc82reed@google.com    bool isFinite() const {
4707b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com        float accum = 0;
4717b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com        accum *= fLeft;
4727b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com        accum *= fTop;
4737b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com        accum *= fRight;
4747b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com        accum *= fBottom;
475fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
4767b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com        // accum is either NaN or it is finite (zero).
4776f90475632b0ff8e9e83916ee6373d3c26cc9284ehsan.akhgari        SkASSERT(0 == accum || SkScalarIsNaN(accum));
4787b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com
4791607863b608b7db6c813228768ed5d72997bbc82reed@google.com        // value==value will be true iff value is not NaN
4807b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com        // TODO: is it faster to say !accum or accum==accum?
4816f90475632b0ff8e9e83916ee6373d3c26cc9284ehsan.akhgari        return !SkScalarIsNaN(accum);
4821607863b608b7db6c813228768ed5d72997bbc82reed@google.com    }
4831607863b608b7db6c813228768ed5d72997bbc82reed@google.com
484d6195f956fdccef865224520a624e3fd968573d0reed@google.com    SkScalar    x() const { return fLeft; }
485d6195f956fdccef865224520a624e3fd968573d0reed@google.com    SkScalar    y() const { return fTop; }
48620efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    SkScalar    left() const { return fLeft; }
48720efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    SkScalar    top() const { return fTop; }
48820efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    SkScalar    right() const { return fRight; }
48920efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    SkScalar    bottom() const { return fBottom; }
4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar    width() const { return fRight - fLeft; }
4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar    height() const { return fBottom - fTop; }
4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar    centerX() const { return SkScalarHalf(fLeft + fRight); }
4938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar    centerY() const { return SkScalarHalf(fTop + fBottom); }
4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
495e174ea4bb1f07c4d15c50716012e5c8429e9afebbsalomon@google.com    friend bool operator==(const SkRect& a, const SkRect& b) {
496e1e7d7a6b55504d97ce9f30202a179b63800093breed@google.com        return SkScalarsEqual((SkScalar*)&a, (SkScalar*)&b, 4);
4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
498da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com
499e174ea4bb1f07c4d15c50716012e5c8429e9afebbsalomon@google.com    friend bool operator!=(const SkRect& a, const SkRect& b) {
500e1e7d7a6b55504d97ce9f30202a179b63800093breed@google.com        return !SkScalarsEqual((SkScalar*)&a, (SkScalar*)&b, 4);
5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
50324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    /** return the 4 points that enclose the rectangle (top-left, top-right, bottom-right,
50424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        bottom-left). TODO: Consider adding param to control whether quad is CW or CCW.
50524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org     */
5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void toQuad(SkPoint quad[4]) const;
5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set this rectangle to the empty rectangle (0,0,0,0)
5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
5108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void setEmpty() { memset(this, 0, sizeof(*this)); }
5118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
512da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    void set(const SkIRect& src) {
5138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLeft   = SkIntToScalar(src.fLeft);
5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fTop    = SkIntToScalar(src.fTop);
5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fRight  = SkIntToScalar(src.fRight);
5168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBottom = SkIntToScalar(src.fBottom);
5178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
519da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    void set(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLeft   = left;
5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fTop    = top;
5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fRight  = right;
5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBottom = bottom;
5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
52520efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    // alias for set(l, t, r, b)
52620efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    void setLTRB(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
52720efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        this->set(left, top, right, bottom);
52820efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    }
52920efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com
5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Initialize the rect with the 4 specified integers. The routine handles
5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        converting them to scalars (by calling SkIntToScalar)
5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com     */
5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void iset(int left, int top, int right, int bottom) {
5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLeft   = SkIntToScalar(left);
5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fTop    = SkIntToScalar(top);
5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fRight  = SkIntToScalar(right);
5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBottom = SkIntToScalar(bottom);
5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5406f54724c11ab739fa0d6deff1d4b564596fe3970reed@google.com    /**
5416f54724c11ab739fa0d6deff1d4b564596fe3970reed@google.com     *  Set this rectangle to be left/top at 0,0, and have the specified width
5426f54724c11ab739fa0d6deff1d4b564596fe3970reed@google.com     *  and height (automatically converted to SkScalar).
5436f54724c11ab739fa0d6deff1d4b564596fe3970reed@google.com     */
5446f54724c11ab739fa0d6deff1d4b564596fe3970reed@google.com    void isetWH(int width, int height) {
5456f54724c11ab739fa0d6deff1d4b564596fe3970reed@google.com        fLeft = fTop = 0;
5466f54724c11ab739fa0d6deff1d4b564596fe3970reed@google.com        fRight = SkIntToScalar(width);
5476f54724c11ab739fa0d6deff1d4b564596fe3970reed@google.com        fBottom = SkIntToScalar(height);
5486f54724c11ab739fa0d6deff1d4b564596fe3970reed@google.com    }
5494d28d9889b033777afc1950474296d37887ef71bskia.committer@gmail.com
5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set this rectangle to be the bounds of the array of points.
5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        If the array is empty (count == 0), then set this rectangle
5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        to the empty rectangle (0,0,0,0)
5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
5540bb18bb264b26afca45452910437c09445e23a3creed@google.com    void set(const SkPoint pts[], int count) {
5550bb18bb264b26afca45452910437c09445e23a3creed@google.com        // set() had been checking for non-finite values, so keep that behavior
5560bb18bb264b26afca45452910437c09445e23a3creed@google.com        // for now. Now that we have setBoundsCheck(), we may decide to make
5570bb18bb264b26afca45452910437c09445e23a3creed@google.com        // set() be simpler/faster, and not check for those.
5580bb18bb264b26afca45452910437c09445e23a3creed@google.com        (void)this->setBoundsCheck(pts, count);
5590bb18bb264b26afca45452910437c09445e23a3creed@google.com    }
5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
56120efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    // alias for set(pts, count)
56220efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    void setBounds(const SkPoint pts[], int count) {
5630bb18bb264b26afca45452910437c09445e23a3creed@google.com        (void)this->setBoundsCheck(pts, count);
56420efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    }
565fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
5660bb18bb264b26afca45452910437c09445e23a3creed@google.com    /**
5670bb18bb264b26afca45452910437c09445e23a3creed@google.com     *  Compute the bounds of the array of points, and set this rect to that
5680bb18bb264b26afca45452910437c09445e23a3creed@google.com     *  bounds and return true... unless a non-finite value is encountered,
5690bb18bb264b26afca45452910437c09445e23a3creed@google.com     *  in which case this rect is set to empty and false is returned.
5700bb18bb264b26afca45452910437c09445e23a3creed@google.com     */
5710bb18bb264b26afca45452910437c09445e23a3creed@google.com    bool setBoundsCheck(const SkPoint pts[], int count);
572fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
5737b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com    void set(const SkPoint& p0, const SkPoint& p1) {
5747b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com        fLeft =   SkMinScalar(p0.fX, p1.fX);
5757b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com        fRight =  SkMaxScalar(p0.fX, p1.fX);
5767b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com        fTop =    SkMinScalar(p0.fY, p1.fY);
5777b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com        fBottom = SkMaxScalar(p0.fY, p1.fY);
5787b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com    }
5797b463acd46b8df866d3a27fbaf69b0090c842d1ereed@google.com
5801d12b1fd66e5be27fb4769ee09ce4fcd6bcc5979reed@google.com    void setXYWH(SkScalar x, SkScalar y, SkScalar width, SkScalar height) {
5811d12b1fd66e5be27fb4769ee09ce4fcd6bcc5979reed@google.com        fLeft = x;
5821d12b1fd66e5be27fb4769ee09ce4fcd6bcc5979reed@google.com        fTop = y;
5831d12b1fd66e5be27fb4769ee09ce4fcd6bcc5979reed@google.com        fRight = x + width;
5841d12b1fd66e5be27fb4769ee09ce4fcd6bcc5979reed@google.com        fBottom = y + height;
5851d12b1fd66e5be27fb4769ee09ce4fcd6bcc5979reed@google.com    }
5861d12b1fd66e5be27fb4769ee09ce4fcd6bcc5979reed@google.com
5873ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com    void setWH(SkScalar width, SkScalar height) {
5883ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com        fLeft = 0;
5893ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com        fTop = 0;
5903ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com        fRight = width;
5913ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com        fBottom = height;
5923ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com    }
5933ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com
59420efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    /**
59520efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com     *  Make the largest representable rectangle
59620efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com     */
59720efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    void setLargest() {
59820efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        fLeft = fTop = SK_ScalarMin;
59920efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        fRight = fBottom = SK_ScalarMax;
60020efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    }
601fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
60220efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    /**
60320efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com     *  Make the largest representable rectangle, but inverted (e.g. fLeft will
60420efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com     *  be max and right will be min).
60520efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com     */
60620efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    void setLargestInverted() {
60720efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        fLeft = fTop = SK_ScalarMax;
60820efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        fRight = fBottom = SK_ScalarMin;
60920efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    }
61020efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com
6115c404c55772973126d8b3c6942ee42c9361d3fadreed    /**
6125c404c55772973126d8b3c6942ee42c9361d3fadreed     *  Return a new Rect, built as an offset of this rect.
6135c404c55772973126d8b3c6942ee42c9361d3fadreed     */
6145c404c55772973126d8b3c6942ee42c9361d3fadreed    SkRect makeOffset(SkScalar dx, SkScalar dy) const {
6155c404c55772973126d8b3c6942ee42c9361d3fadreed        return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy);
6165c404c55772973126d8b3c6942ee42c9361d3fadreed    }
61711fa2247b747eb75e2f158dc7571d458ed6c0115reed
6185c404c55772973126d8b3c6942ee42c9361d3fadreed    /**
6195c404c55772973126d8b3c6942ee42c9361d3fadreed     *  Return a new Rect, built as an inset of this rect.
6205c404c55772973126d8b3c6942ee42c9361d3fadreed     */
6215c404c55772973126d8b3c6942ee42c9361d3fadreed    SkRect makeInset(SkScalar dx, SkScalar dy) const {
6225c404c55772973126d8b3c6942ee42c9361d3fadreed        return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, fBottom - dy);
6235c404c55772973126d8b3c6942ee42c9361d3fadreed    }
6245c404c55772973126d8b3c6942ee42c9361d3fadreed
62511fa2247b747eb75e2f158dc7571d458ed6c0115reed    /**
62611fa2247b747eb75e2f158dc7571d458ed6c0115reed     *  Return a new Rect, built as an outset of this rect.
62711fa2247b747eb75e2f158dc7571d458ed6c0115reed     */
62811fa2247b747eb75e2f158dc7571d458ed6c0115reed    SkRect makeOutset(SkScalar dx, SkScalar dy) const {
62911fa2247b747eb75e2f158dc7571d458ed6c0115reed        return MakeLTRB(fLeft - dx, fTop - dy, fRight + dx, fBottom + dy);
63011fa2247b747eb75e2f158dc7571d458ed6c0115reed    }
63111fa2247b747eb75e2f158dc7571d458ed6c0115reed
6328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Offset set the rectangle by adding dx to its left and right,
6338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        and adding dy to its top and bottom.
6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
635da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    void offset(SkScalar dx, SkScalar dy) {
6368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLeft   += dx;
6378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fTop    += dy;
6388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fRight  += dx;
6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBottom += dy;
640fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
642da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    void offset(const SkPoint& delta) {
643da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com        this->offset(delta.fX, delta.fY);
644da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    }
645da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com
6464d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com    /**
6474d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com     *  Offset this rect such its new x() and y() will equal newX and newY.
6484d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com     */
6494d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com    void offsetTo(SkScalar newX, SkScalar newY) {
6504d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com        fRight += newX - fLeft;
6514d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com        fBottom += newY - fTop;
6524d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com        fLeft = newX;
6534d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com        fTop = newY;
6544d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com    }
65572b2e6fff3f54c6aa80a98eab4c73f02a8cd450dskia.committer@gmail.com
656647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com    /** Inset the rectangle by (dx,dy). If dx is positive, then the sides are
657647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com        moved inwards, making the rectangle narrower. If dx is negative, then
658647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com        the sides are moved outwards, making the rectangle wider. The same holds
659647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com         true for dy and the top and bottom.
6608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
661da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    void inset(SkScalar dx, SkScalar dy)  {
6628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLeft   += dx;
6638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fTop    += dy;
6648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fRight  -= dx;
6658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBottom -= dy;
6668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
668647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com   /** Outset the rectangle by (dx,dy). If dx is positive, then the sides are
669647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com       moved outwards, making the rectangle wider. If dx is negative, then the
6706623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com       sides are moved inwards, making the rectangle narrower. The same holds
671647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com       true for dy and the top and bottom.
672647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com    */
673647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com    void outset(SkScalar dx, SkScalar dy)  { this->inset(-dx, -dy); }
674647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com
6758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** If this rectangle intersects r, return true and set this rectangle to that
6768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        intersection, otherwise return false and do not change this rectangle.
6778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        If either rectangle is empty, do nothing and return false.
6788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
679f4e5995ac70d4614e0a05b92a8a03e2b7d76bd9crobertphillips    bool SK_WARN_UNUSED_RESULT intersect(const SkRect& r);
6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** If this rectangle intersects the rectangle specified by left, top, right, bottom,
6828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true and set this rectangle to that intersection, otherwise return false
6838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        and do not change this rectangle.
6848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        If either rectangle is empty, do nothing and return false.
6858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
686f4e5995ac70d4614e0a05b92a8a03e2b7d76bd9crobertphillips    bool SK_WARN_UNUSED_RESULT intersect(SkScalar left, SkScalar top,
687f4e5995ac70d4614e0a05b92a8a03e2b7d76bd9crobertphillips                                         SkScalar right, SkScalar bottom);
6888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
689af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com    /**
6901119c870651ccd34c0acb8fb2cdfad2c07d3116creed     *  If rectangles a and b intersect, return true and set this rectangle to
6911119c870651ccd34c0acb8fb2cdfad2c07d3116creed     *  that intersection, otherwise return false and do not change this
6921119c870651ccd34c0acb8fb2cdfad2c07d3116creed     *  rectangle. If either rectangle is empty, do nothing and return false.
6931119c870651ccd34c0acb8fb2cdfad2c07d3116creed     */
694f4e5995ac70d4614e0a05b92a8a03e2b7d76bd9crobertphillips    bool SK_WARN_UNUSED_RESULT intersect(const SkRect& a, const SkRect& b);
6951119c870651ccd34c0acb8fb2cdfad2c07d3116creed
6961119c870651ccd34c0acb8fb2cdfad2c07d3116creed
6971119c870651ccd34c0acb8fb2cdfad2c07d3116creedprivate:
6981119c870651ccd34c0acb8fb2cdfad2c07d3116creed    static bool Intersects(SkScalar al, SkScalar at, SkScalar ar, SkScalar ab,
6991119c870651ccd34c0acb8fb2cdfad2c07d3116creed                           SkScalar bl, SkScalar bt, SkScalar br, SkScalar bb) {
7001119c870651ccd34c0acb8fb2cdfad2c07d3116creed        SkScalar L = SkMaxScalar(al, bl);
7011119c870651ccd34c0acb8fb2cdfad2c07d3116creed        SkScalar R = SkMinScalar(ar, br);
7021119c870651ccd34c0acb8fb2cdfad2c07d3116creed        SkScalar T = SkMaxScalar(at, bt);
7031119c870651ccd34c0acb8fb2cdfad2c07d3116creed        SkScalar B = SkMinScalar(ab, bb);
7041119c870651ccd34c0acb8fb2cdfad2c07d3116creed        return L < R && T < B;
7051119c870651ccd34c0acb8fb2cdfad2c07d3116creed    }
7061119c870651ccd34c0acb8fb2cdfad2c07d3116creed
7071119c870651ccd34c0acb8fb2cdfad2c07d3116creedpublic:
7081119c870651ccd34c0acb8fb2cdfad2c07d3116creed    /**
709af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  Return true if this rectangle is not empty, and the specified sides of
710af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  a rectangle are not empty, and they intersect.
711af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     */
712da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    bool intersects(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) const {
7131119c870651ccd34c0acb8fb2cdfad2c07d3116creed        return Intersects(fLeft, fTop, fRight, fBottom, left, top, right, bottom);
7148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
715f0f617a502ae9298056654811542c62769a906c8reed@google.com
716a7a8b10134f78d4ed55ff0370a54d8141daa7cacreed    bool intersects(const SkRect& r) const {
717a7a8b10134f78d4ed55ff0370a54d8141daa7cacreed        return Intersects(fLeft, fTop, fRight, fBottom,
718a7a8b10134f78d4ed55ff0370a54d8141daa7cacreed                          r.fLeft, r.fTop, r.fRight, r.fBottom);
719a7a8b10134f78d4ed55ff0370a54d8141daa7cacreed    }
720a7a8b10134f78d4ed55ff0370a54d8141daa7cacreed
721af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com    /**
722af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  Return true if rectangles a and b are not empty and intersect.
723af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     */
724da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    static bool Intersects(const SkRect& a, const SkRect& b) {
7251119c870651ccd34c0acb8fb2cdfad2c07d3116creed        return Intersects(a.fLeft, a.fTop, a.fRight, a.fBottom,
7261119c870651ccd34c0acb8fb2cdfad2c07d3116creed                          b.fLeft, b.fTop, b.fRight, b.fBottom);
7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
728fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
729af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com    /**
730af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  Update this rectangle to enclose itself and the specified rectangle.
731af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  If this rectangle is empty, just set it to the specified rectangle.
732af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  If the specified rectangle is empty, do nothing.
733af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     */
7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void join(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Update this rectangle to enclose itself and the specified rectangle.
7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        If this rectangle is empty, just set it to the specified rectangle. If the specified
7388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rectangle is empty, do nothing.
7398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
740da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    void join(const SkRect& r) {
7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
7428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
74310d0327c16bb748d6f73eb37dd2341c61e47ca8creed
74410d0327c16bb748d6f73eb37dd2341c61e47ca8creed    void joinNonEmptyArg(const SkRect& r) {
74510d0327c16bb748d6f73eb37dd2341c61e47ca8creed        SkASSERT(!r.isEmpty());
74610d0327c16bb748d6f73eb37dd2341c61e47ca8creed        // if we are empty, just assign
74710d0327c16bb748d6f73eb37dd2341c61e47ca8creed        if (fLeft >= fRight || fTop >= fBottom) {
74810d0327c16bb748d6f73eb37dd2341c61e47ca8creed            *this = r;
74910d0327c16bb748d6f73eb37dd2341c61e47ca8creed        } else {
7503dc2ccae6c0f0cf6ac951585a197bfb8a58cfee5joshualitt            this->joinPossiblyEmptyRect(r);
75110d0327c16bb748d6f73eb37dd2341c61e47ca8creed        }
75210d0327c16bb748d6f73eb37dd2341c61e47ca8creed    }
75320efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com
754af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com    /**
7553dc2ccae6c0f0cf6ac951585a197bfb8a58cfee5joshualitt     * Joins the rectangle with another without checking if either are empty (may produce unexpected
7563dc2ccae6c0f0cf6ac951585a197bfb8a58cfee5joshualitt     * results if either rect is inverted).
7573dc2ccae6c0f0cf6ac951585a197bfb8a58cfee5joshualitt     */
7583dc2ccae6c0f0cf6ac951585a197bfb8a58cfee5joshualitt    void joinPossiblyEmptyRect(const SkRect& r) {
7593dc2ccae6c0f0cf6ac951585a197bfb8a58cfee5joshualitt        fLeft   = SkMinScalar(fLeft, r.left());
7603dc2ccae6c0f0cf6ac951585a197bfb8a58cfee5joshualitt        fTop    = SkMinScalar(fTop, r.top());
7613dc2ccae6c0f0cf6ac951585a197bfb8a58cfee5joshualitt        fRight  = SkMaxScalar(fRight, r.right());
7623dc2ccae6c0f0cf6ac951585a197bfb8a58cfee5joshualitt        fBottom = SkMaxScalar(fBottom, r.bottom());
7633dc2ccae6c0f0cf6ac951585a197bfb8a58cfee5joshualitt    }
7643dc2ccae6c0f0cf6ac951585a197bfb8a58cfee5joshualitt
7653dc2ccae6c0f0cf6ac951585a197bfb8a58cfee5joshualitt    /**
766af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  Grow the rect to include the specified (x,y). After this call, the
767af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  following will be true: fLeft <= x <= fRight && fTop <= y <= fBottom.
768af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *
769af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  This is close, but not quite the same contract as contains(), since
770af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  contains() treats the left and top different from the right and bottom.
771af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  contains(x,y) -> fLeft <= x < fRight && fTop <= y < fBottom. Also note
772af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  that contains(x,y) always returns false if the rect is empty.
773af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     */
77420efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    void growToInclude(SkScalar x, SkScalar y) {
77520efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        fLeft  = SkMinScalar(x, fLeft);
776ee9aa304579b3d5314519372728187879456d49dbsalomon@google.com        fRight = SkMaxScalar(x, fRight);
777ee9aa304579b3d5314519372728187879456d49dbsalomon@google.com        fTop    = SkMinScalar(y, fTop);
77820efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        fBottom = SkMaxScalar(y, fBottom);
77920efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    }
780fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
781b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org    /** Bulk version of growToInclude */
782b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org    void growToInclude(const SkPoint pts[], int count) {
783b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org        this->growToInclude(pts, sizeof(SkPoint), count);
784b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org    }
785b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org
786b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org    /** Bulk version of growToInclude with stride. */
787b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org    void growToInclude(const SkPoint pts[], size_t stride, int count) {
788b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org        SkASSERT(count >= 0);
789b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org        SkASSERT(stride >= sizeof(SkPoint));
790b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org        const SkPoint* end = (const SkPoint*)((intptr_t)pts + count * stride);
791b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org        for (; pts < end; pts = (const SkPoint*)((intptr_t)pts + stride)) {
792b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org            this->growToInclude(pts->fX, pts->fY);
793b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org        }
794b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org    }
795b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org
796af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com    /**
797af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  Return true if this rectangle contains r, and if both rectangles are
798af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  not empty.
799af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     */
800da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    bool contains(const SkRect& r) const {
8014db592c4085afed2be27a208d778f9ee13e671abreed@google.com        // todo: can we eliminate the this->isEmpty check?
802af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com        return  !r.isEmpty() && !this->isEmpty() &&
8038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fLeft <= r.fLeft && fTop <= r.fTop &&
8048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fRight >= r.fRight && fBottom >= r.fBottom;
8058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
807af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com    /**
808570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt     * Returns true if the specified rectangle r is inside or equal to this rectangle.
809570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt     */
810570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt    bool contains(const SkIRect& r) const {
811570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt        // todo: can we eliminate the this->isEmpty check?
812570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt        return  !r.isEmpty() && !this->isEmpty() &&
813570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt                fLeft <= SkIntToScalar(r.fLeft) && fTop <= SkIntToScalar(r.fTop) &&
814570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt                fRight >= SkIntToScalar(r.fRight) && fBottom >= SkIntToScalar(r.fBottom);
815570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt    }
816570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt
817570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt    /**
818af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  Set the dst rectangle by rounding this rectangle's coordinates to their
819126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com     *  nearest integer values using SkScalarRoundToInt.
820af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     */
821da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    void round(SkIRect* dst) const {
8228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(dst);
8234d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com        dst->set(SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
8244d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com                 SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom));
8258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
827af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com    /**
8284e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org     *  Variant of round() that explicitly performs the rounding step (i.e. floor(x + 0.5)) using
8294e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org     *  double instead of SkScalar (float). It does this by calling SkDScalarRoundToInt(), which
8304e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org     *  may be slower than calling SkScalarRountToInt(), but gives slightly more accurate results.
8314e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org     *
8324e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org     *  e.g.
8334e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org     *      SkScalar x = 0.49999997f;
8344e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org     *      int ix = SkScalarRoundToInt(x);
8354e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org     *      SkASSERT(0 == ix);  // <--- fails
8364e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org     *      ix = SkDScalarRoundToInt(x);
8374e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org     *      SkASSERT(0 == ix);  // <--- succeeds
8384e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org     */
8394e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org    void dround(SkIRect* dst) const {
8404e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org        SkASSERT(dst);
8414e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org        dst->set(SkDScalarRoundToInt(fLeft), SkDScalarRoundToInt(fTop),
8424e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org                 SkDScalarRoundToInt(fRight), SkDScalarRoundToInt(fBottom));
8434e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org    }
8444e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org
8454e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org    /**
846af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  Set the dst rectangle by rounding "out" this rectangle, choosing the
847af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  SkScalarFloor of top and left, and the SkScalarCeil of right and bottom.
848af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     */
849da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    void roundOut(SkIRect* dst) const {
8508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(dst);
8514d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com        dst->set(SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
8524d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com                 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom));
8538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
855af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com    /**
856b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed     *  Set the dst rectangle by rounding "out" this rectangle, choosing the
857b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed     *  SkScalarFloorToScalar of top and left, and the SkScalarCeilToScalar of right and bottom.
858d02cf2664d0e453a6ec57cddc7f09bfc07fd91dbreed     *
859d02cf2664d0e453a6ec57cddc7f09bfc07fd91dbreed     *  It is safe for this == dst
860099d22dbce650abdda0c5c5a7ee89ee0850897f1reed@google.com     */
861d02cf2664d0e453a6ec57cddc7f09bfc07fd91dbreed    void roundOut(SkRect* dst) const {
862d02cf2664d0e453a6ec57cddc7f09bfc07fd91dbreed        dst->set(SkScalarFloorToScalar(fLeft),
863d02cf2664d0e453a6ec57cddc7f09bfc07fd91dbreed                 SkScalarFloorToScalar(fTop),
864d02cf2664d0e453a6ec57cddc7f09bfc07fd91dbreed                 SkScalarCeilToScalar(fRight),
865d02cf2664d0e453a6ec57cddc7f09bfc07fd91dbreed                 SkScalarCeilToScalar(fBottom));
866099d22dbce650abdda0c5c5a7ee89ee0850897f1reed@google.com    }
867099d22dbce650abdda0c5c5a7ee89ee0850897f1reed@google.com
868099d22dbce650abdda0c5c5a7ee89ee0850897f1reed@google.com    /**
8694d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com     *  Set the dst rectangle by rounding "in" this rectangle, choosing the
8704d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com     *  ceil of top and left, and the floor of right and bottom. This does *not*
8714d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com     *  call sort(), so it is possible that the resulting rect is inverted...
8724d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com     *  e.g. left >= right or top >= bottom. Call isEmpty() to detect that.
8734d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com     */
8744d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com    void roundIn(SkIRect* dst) const {
8754d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com        SkASSERT(dst);
8764d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com        dst->set(SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
8774d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com                 SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom));
8784d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com    }
87972b2e6fff3f54c6aa80a98eab4c73f02a8cd450dskia.committer@gmail.com
880b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed    //! Returns the result of calling round(&dst)
881126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com    SkIRect round() const {
882126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com        SkIRect ir;
883126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com        this->round(&ir);
884126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com        return ir;
885126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com    }
886b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed
887b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed    //! Returns the result of calling roundOut(&dst)
888b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed    SkIRect roundOut() const {
889b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed        SkIRect ir;
890b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed        this->roundOut(&ir);
891b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed        return ir;
892b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed    }
893b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed
8944d3038379d98074612a92ef2bc85250cd205cfa9reed@google.com    /**
895af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  Swap top/bottom or left/right if there are flipped (i.e. if width()
896af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  or height() would have returned a negative value.) This should be called
897af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  if the edges are computed separately, and may have crossed over each
898af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     *  other. When this returns, left <= right && top <= bottom
899af8edcc477ad36592adcf53d14e8bf4441143b31reed@google.com     */
90040636a53037eadd957b8e43f0961f640aaa93e84reed    void sort() {
901fb502f072f5a32ad122bfc2717fe56a3c22e482eqiankun.miao        if (fLeft > fRight) {
902fb502f072f5a32ad122bfc2717fe56a3c22e482eqiankun.miao            SkTSwap<SkScalar>(fLeft, fRight);
903fb502f072f5a32ad122bfc2717fe56a3c22e482eqiankun.miao        }
904fb502f072f5a32ad122bfc2717fe56a3c22e482eqiankun.miao
905fb502f072f5a32ad122bfc2717fe56a3c22e482eqiankun.miao        if (fTop > fBottom) {
906fb502f072f5a32ad122bfc2717fe56a3c22e482eqiankun.miao            SkTSwap<SkScalar>(fTop, fBottom);
907fb502f072f5a32ad122bfc2717fe56a3c22e482eqiankun.miao        }
90840636a53037eadd957b8e43f0961f640aaa93e84reed    }
909eed625df23ee83a94f1814c43744b1961b79adf1skia.committer@gmail.com
910c7d0ea3cd328566958bfcb86b4488dcbb94dd5ecreed@google.com    /**
911c7d0ea3cd328566958bfcb86b4488dcbb94dd5ecreed@google.com     *  cast-safe way to treat the rect as an array of (4) SkScalars.
912c7d0ea3cd328566958bfcb86b4488dcbb94dd5ecreed@google.com     */
913c7d0ea3cd328566958bfcb86b4488dcbb94dd5ecreed@google.com    const SkScalar* asScalars() const { return &fLeft; }
914b6b02526438d6839481fb40ccf610d28f7652397bsalomon
915e05fed0d6339c63c8cceff74af0b8d120c07e54creed    void dump(bool asHex) const;
916e05fed0d6339c63c8cceff74af0b8d120c07e54creed    void dump() const { this->dump(false); }
917e05fed0d6339c63c8cceff74af0b8d120c07e54creed    void dumpHex() const { this->dump(true); }
9188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
9198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
92044701df5ce572ac3cccec785cf52103d3d5d14a5joshualittinline bool SkIRect::contains(const SkRect& r) const {
92144701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    return  !r.isEmpty() && !this->isEmpty() &&     // check for empties
92244701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt            (SkScalar)fLeft <= r.fLeft && (SkScalar)fTop <= r.fTop &&
92344701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt            (SkScalar)fRight >= r.fRight && (SkScalar)fBottom >= r.fBottom;
92444701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt}
92544701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
9268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
927