15bb6825f10d64834ad1d1d967f590aebae285360epoger@google.com 2f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com/* 35bb6825f10d64834ad1d1d967f590aebae285360epoger@google.com * Copyright 2006 The Android Open Source Project 4f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com * 55bb6825f10d64834ad1d1d967f590aebae285360epoger@google.com * Use of this source code is governed by a BSD-style license that can be 65bb6825f10d64834ad1d1d967f590aebae285360epoger@google.com * found in the LICENSE file. 7f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 8f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 95bb6825f10d64834ad1d1d967f590aebae285360epoger@google.com 10f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com#ifndef SkRect_DEFINED 11f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com#define SkRect_DEFINED 12f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 13f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com#include "SkPoint.h" 1408fc3cebc3c5a71ef5c3a1e3679036c142fd756ereed@android.com#include "SkSize.h" 15f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 16f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com/** \struct SkIRect 17f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 18f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkIRect holds four 32 bit integer coordinates for a rectangle 19f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com*/ 202083387d719b933797044ad07efd3bb67f99a5c5ctguil@chromium.orgstruct SK_API SkIRect { 21f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com int32_t fLeft, fTop, fRight, fBottom; 22f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 23e4464fdb4e9cebe8ad5fd39b2e5991ae5251d3b8robertphillips@google.com static SkIRect SK_WARN_UNUSED_RESULT MakeEmpty() { 24158509de51341f8cc66b4a80071614fbb036f9e9reed@android.com SkIRect r; 25158509de51341f8cc66b4a80071614fbb036f9e9reed@android.com r.setEmpty(); 26158509de51341f8cc66b4a80071614fbb036f9e9reed@android.com return r; 27158509de51341f8cc66b4a80071614fbb036f9e9reed@android.com } 281fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 29a91286212782b14f72f705be220e62b73e1f751fsenorblanco@chromium.org static SkIRect SK_WARN_UNUSED_RESULT MakeLargest() { 30a91286212782b14f72f705be220e62b73e1f751fsenorblanco@chromium.org SkIRect r; 31a91286212782b14f72f705be220e62b73e1f751fsenorblanco@chromium.org r.setLargest(); 32a91286212782b14f72f705be220e62b73e1f751fsenorblanco@chromium.org return r; 33a91286212782b14f72f705be220e62b73e1f751fsenorblanco@chromium.org } 34a91286212782b14f72f705be220e62b73e1f751fsenorblanco@chromium.org 35e4464fdb4e9cebe8ad5fd39b2e5991ae5251d3b8robertphillips@google.com static SkIRect SK_WARN_UNUSED_RESULT MakeWH(int32_t w, int32_t h) { 36158509de51341f8cc66b4a80071614fbb036f9e9reed@android.com SkIRect r; 37158509de51341f8cc66b4a80071614fbb036f9e9reed@android.com r.set(0, 0, w, h); 38158509de51341f8cc66b4a80071614fbb036f9e9reed@android.com return r; 39158509de51341f8cc66b4a80071614fbb036f9e9reed@android.com } 401fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 41e4464fdb4e9cebe8ad5fd39b2e5991ae5251d3b8robertphillips@google.com static SkIRect SK_WARN_UNUSED_RESULT MakeSize(const SkISize& size) { 42158509de51341f8cc66b4a80071614fbb036f9e9reed@android.com SkIRect r; 43158509de51341f8cc66b4a80071614fbb036f9e9reed@android.com r.set(0, 0, size.width(), size.height()); 44158509de51341f8cc66b4a80071614fbb036f9e9reed@android.com return r; 45158509de51341f8cc66b4a80071614fbb036f9e9reed@android.com } 461fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 47e4464fdb4e9cebe8ad5fd39b2e5991ae5251d3b8robertphillips@google.com static SkIRect SK_WARN_UNUSED_RESULT MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b) { 48158509de51341f8cc66b4a80071614fbb036f9e9reed@android.com SkIRect rect; 49158509de51341f8cc66b4a80071614fbb036f9e9reed@android.com rect.set(l, t, r, b); 50158509de51341f8cc66b4a80071614fbb036f9e9reed@android.com return rect; 51158509de51341f8cc66b4a80071614fbb036f9e9reed@android.com } 521fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 53e4464fdb4e9cebe8ad5fd39b2e5991ae5251d3b8robertphillips@google.com static SkIRect SK_WARN_UNUSED_RESULT MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h) { 54158509de51341f8cc66b4a80071614fbb036f9e9reed@android.com SkIRect r; 55158509de51341f8cc66b4a80071614fbb036f9e9reed@android.com r.set(x, y, x + w, y + h); 56158509de51341f8cc66b4a80071614fbb036f9e9reed@android.com return r; 57158509de51341f8cc66b4a80071614fbb036f9e9reed@android.com } 58f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 59495534299502bbdbe47ce114f8f83645e4ce966ereed@google.com int left() const { return fLeft; } 60495534299502bbdbe47ce114f8f83645e4ce966ereed@google.com int top() const { return fTop; } 61495534299502bbdbe47ce114f8f83645e4ce966ereed@google.com int right() const { return fRight; } 62495534299502bbdbe47ce114f8f83645e4ce966ereed@google.com int bottom() const { return fBottom; } 631fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 64495534299502bbdbe47ce114f8f83645e4ce966ereed@google.com /** return the left edge of the rect */ 65495534299502bbdbe47ce114f8f83645e4ce966ereed@google.com int x() const { return fLeft; } 66495534299502bbdbe47ce114f8f83645e4ce966ereed@google.com /** return the top edge of the rect */ 67495534299502bbdbe47ce114f8f83645e4ce966ereed@google.com int y() const { return fTop; } 68495534299502bbdbe47ce114f8f83645e4ce966ereed@google.com /** 69495534299502bbdbe47ce114f8f83645e4ce966ereed@google.com * Returns the rectangle's width. This does not check for a valid rect 70495534299502bbdbe47ce114f8f83645e4ce966ereed@google.com * (i.e. left <= right) so the result may be negative. 71495534299502bbdbe47ce114f8f83645e4ce966ereed@google.com */ 72f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com int width() const { return fRight - fLeft; } 731fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 74495534299502bbdbe47ce114f8f83645e4ce966ereed@google.com /** 75495534299502bbdbe47ce114f8f83645e4ce966ereed@google.com * Returns the rectangle's height. This does not check for a valid rect 76495534299502bbdbe47ce114f8f83645e4ce966ereed@google.com * (i.e. top <= bottom) so the result may be negative. 77495534299502bbdbe47ce114f8f83645e4ce966ereed@google.com */ 78f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com int height() const { return fBottom - fTop; } 791fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 80495534299502bbdbe47ce114f8f83645e4ce966ereed@google.com /** 81dffdb807da9d0feab44eaf7b7ebc531592dedda4reed@google.com * Since the center of an integer rect may fall on a factional value, this 82dffdb807da9d0feab44eaf7b7ebc531592dedda4reed@google.com * method is defined to return (right + left) >> 1. 83dffdb807da9d0feab44eaf7b7ebc531592dedda4reed@google.com * 84dffdb807da9d0feab44eaf7b7ebc531592dedda4reed@google.com * This is a specific "truncation" of the average, which is different than 85dffdb807da9d0feab44eaf7b7ebc531592dedda4reed@google.com * (right + left) / 2 when the sum is negative. 86dffdb807da9d0feab44eaf7b7ebc531592dedda4reed@google.com */ 87dffdb807da9d0feab44eaf7b7ebc531592dedda4reed@google.com int centerX() const { return (fRight + fLeft) >> 1; } 8803e92431db598cac40295f9bc269e7af1a1a9403skia.committer@gmail.com 89dffdb807da9d0feab44eaf7b7ebc531592dedda4reed@google.com /** 90dffdb807da9d0feab44eaf7b7ebc531592dedda4reed@google.com * Since the center of an integer rect may fall on a factional value, this 91dffdb807da9d0feab44eaf7b7ebc531592dedda4reed@google.com * method is defined to return (bottom + top) >> 1 92dffdb807da9d0feab44eaf7b7ebc531592dedda4reed@google.com * 93dffdb807da9d0feab44eaf7b7ebc531592dedda4reed@google.com * This is a specific "truncation" of the average, which is different than 94dffdb807da9d0feab44eaf7b7ebc531592dedda4reed@google.com * (bottom + top) / 2 when the sum is negative. 95dffdb807da9d0feab44eaf7b7ebc531592dedda4reed@google.com */ 96dffdb807da9d0feab44eaf7b7ebc531592dedda4reed@google.com int centerY() const { return (fBottom + fTop) >> 1; } 9703e92431db598cac40295f9bc269e7af1a1a9403skia.committer@gmail.com 98dffdb807da9d0feab44eaf7b7ebc531592dedda4reed@google.com /** 99495534299502bbdbe47ce114f8f83645e4ce966ereed@google.com * Return true if the rectangle's width or height are <= 0 100495534299502bbdbe47ce114f8f83645e4ce966ereed@google.com */ 101495534299502bbdbe47ce114f8f83645e4ce966ereed@google.com bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; } 1021fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 103a91286212782b14f72f705be220e62b73e1f751fsenorblanco@chromium.org bool isLargest() const { return SK_MinS32 == fLeft && 104a91286212782b14f72f705be220e62b73e1f751fsenorblanco@chromium.org SK_MinS32 == fTop && 105a91286212782b14f72f705be220e62b73e1f751fsenorblanco@chromium.org SK_MaxS32 == fRight && 106a91286212782b14f72f705be220e62b73e1f751fsenorblanco@chromium.org SK_MaxS32 == fBottom; } 107a91286212782b14f72f705be220e62b73e1f751fsenorblanco@chromium.org 108489eddd0cdfdb12dde092ac6a28c1a5ba3a716ddreed@google.com friend bool operator==(const SkIRect& a, const SkIRect& b) { 109f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return !memcmp(&a, &b, sizeof(a)); 110f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 111cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com 112489eddd0cdfdb12dde092ac6a28c1a5ba3a716ddreed@google.com friend bool operator!=(const SkIRect& a, const SkIRect& b) { 113489eddd0cdfdb12dde092ac6a28c1a5ba3a716ddreed@google.com return !(a == b); 114f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 115f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 11666d4a89f28466103410b96e8d091b944d6d6031areed@android.com bool is16Bit() const { 11766d4a89f28466103410b96e8d091b944d6d6031areed@android.com return SkIsS16(fLeft) && SkIsS16(fTop) && 11866d4a89f28466103410b96e8d091b944d6d6031areed@android.com SkIsS16(fRight) && SkIsS16(fBottom); 11966d4a89f28466103410b96e8d091b944d6d6031areed@android.com } 12066d4a89f28466103410b96e8d091b944d6d6031areed@android.com 121f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Set the rectangle to (0,0,0,0) 122f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 123f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void setEmpty() { memset(this, 0, sizeof(*this)); } 124f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 125cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com void set(int32_t left, int32_t top, int32_t right, int32_t bottom) { 126f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fLeft = left; 127f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fTop = top; 128f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fRight = right; 129f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fBottom = bottom; 130f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 131856071eaa7341e0e58419ea331f98afced09a285reed@google.com // alias for set(l, t, r, b) 132856071eaa7341e0e58419ea331f98afced09a285reed@google.com void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom) { 133856071eaa7341e0e58419ea331f98afced09a285reed@google.com this->set(left, top, right, bottom); 134856071eaa7341e0e58419ea331f98afced09a285reed@google.com } 135f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 1364bae66e75406a05ca34bb91e505aac1865c93fe9reed@google.com void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height) { 1374bae66e75406a05ca34bb91e505aac1865c93fe9reed@google.com fLeft = x; 1384bae66e75406a05ca34bb91e505aac1865c93fe9reed@google.com fTop = y; 1394bae66e75406a05ca34bb91e505aac1865c93fe9reed@google.com fRight = x + width; 1404bae66e75406a05ca34bb91e505aac1865c93fe9reed@google.com fBottom = y + height; 1414bae66e75406a05ca34bb91e505aac1865c93fe9reed@google.com } 142856071eaa7341e0e58419ea331f98afced09a285reed@google.com 143856071eaa7341e0e58419ea331f98afced09a285reed@google.com /** 144856071eaa7341e0e58419ea331f98afced09a285reed@google.com * Make the largest representable rectangle 145856071eaa7341e0e58419ea331f98afced09a285reed@google.com */ 146856071eaa7341e0e58419ea331f98afced09a285reed@google.com void setLargest() { 147856071eaa7341e0e58419ea331f98afced09a285reed@google.com fLeft = fTop = SK_MinS32; 148856071eaa7341e0e58419ea331f98afced09a285reed@google.com fRight = fBottom = SK_MaxS32; 149856071eaa7341e0e58419ea331f98afced09a285reed@google.com } 1501fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 151856071eaa7341e0e58419ea331f98afced09a285reed@google.com /** 152856071eaa7341e0e58419ea331f98afced09a285reed@google.com * Make the largest representable rectangle, but inverted (e.g. fLeft will 153856071eaa7341e0e58419ea331f98afced09a285reed@google.com * be max 32bit and right will be min 32bit). 154856071eaa7341e0e58419ea331f98afced09a285reed@google.com */ 155856071eaa7341e0e58419ea331f98afced09a285reed@google.com void setLargestInverted() { 156856071eaa7341e0e58419ea331f98afced09a285reed@google.com fLeft = fTop = SK_MaxS32; 157856071eaa7341e0e58419ea331f98afced09a285reed@google.com fRight = fBottom = SK_MinS32; 158856071eaa7341e0e58419ea331f98afced09a285reed@google.com } 1591fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 160f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Offset set the rectangle by adding dx to its left and right, 161f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com and adding dy to its top and bottom. 162f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 163cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com void offset(int32_t dx, int32_t dy) { 164f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fLeft += dx; 165f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fTop += dy; 166f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fRight += dx; 167f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fBottom += dy; 168f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 169f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 170cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com void offset(const SkIPoint& delta) { 171cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com this->offset(delta.fX, delta.fY); 172cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com } 173cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com 1743306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com /** 1753306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com * Offset this rect such its new x() and y() will equal newX and newY. 1763306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com */ 1773306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com void offsetTo(int32_t newX, int32_t newY) { 1783306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com fRight += newX - fLeft; 1793306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com fBottom += newY - fTop; 1803306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com fLeft = newX; 1813306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com fTop = newY; 1823306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com } 1833306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com 184f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Inset the rectangle by (dx,dy). If dx is positive, then the sides are moved inwards, 185f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com making the rectangle narrower. If dx is negative, then the sides are moved outwards, 186b0ded505e1cf419f24d775f1fce5f34fd62c7d65robertphillips@google.com making the rectangle wider. The same holds true for dy and the top and bottom. 187f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 188cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com void inset(int32_t dx, int32_t dy) { 189f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fLeft += dx; 190f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fTop += dy; 191f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fRight -= dx; 192f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fBottom -= dy; 193f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 194cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com 195b0ded505e1cf419f24d775f1fce5f34fd62c7d65robertphillips@google.com /** Outset the rectangle by (dx,dy). If dx is positive, then the sides are 196b0ded505e1cf419f24d775f1fce5f34fd62c7d65robertphillips@google.com moved outwards, making the rectangle wider. If dx is negative, then the 197b0ded505e1cf419f24d775f1fce5f34fd62c7d65robertphillips@google.com sides are moved inwards, making the rectangle narrower. The same holds 198b0ded505e1cf419f24d775f1fce5f34fd62c7d65robertphillips@google.com true for dy and the top and bottom. 199b0ded505e1cf419f24d775f1fce5f34fd62c7d65robertphillips@google.com */ 200b0ded505e1cf419f24d775f1fce5f34fd62c7d65robertphillips@google.com void outset(int32_t dx, int32_t dy) { this->inset(-dx, -dy); } 201b0ded505e1cf419f24d775f1fce5f34fd62c7d65robertphillips@google.com 202856071eaa7341e0e58419ea331f98afced09a285reed@google.com bool quickReject(int l, int t, int r, int b) const { 203856071eaa7341e0e58419ea331f98afced09a285reed@google.com return l >= fRight || fLeft >= r || t >= fBottom || fTop >= b; 204856071eaa7341e0e58419ea331f98afced09a285reed@google.com } 2051fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 206f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Returns true if (x,y) is inside the rectangle and the rectangle is not 207f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com empty. The left and top are considered to be inside, while the right 208f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com and bottom are not. Thus for the rectangle (0, 0, 5, 10), the 209f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com points (0,0) and (0,9) are inside, while (-1,0) and (5,9) are not. 210f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 211cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com bool contains(int32_t x, int32_t y) const { 212f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return (unsigned)(x - fLeft) < (unsigned)(fRight - fLeft) && 213f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com (unsigned)(y - fTop) < (unsigned)(fBottom - fTop); 214f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 215f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 216f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Returns true if the 4 specified sides of a rectangle are inside or equal to this rectangle. 217f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com If either rectangle is empty, contains() returns false. 218f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 219cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com bool contains(int32_t left, int32_t top, int32_t right, int32_t bottom) const { 220f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return left < right && top < bottom && !this->isEmpty() && // check for empties 221f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fLeft <= left && fTop <= top && 222f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fRight >= right && fBottom >= bottom; 223f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 224f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 225f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Returns true if the specified rectangle r is inside or equal to this rectangle. 226f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 227cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com bool contains(const SkIRect& r) const { 228f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return !r.isEmpty() && !this->isEmpty() && // check for empties 229f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fLeft <= r.fLeft && fTop <= r.fTop && 230f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fRight >= r.fRight && fBottom >= r.fBottom; 231f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 232f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 233f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Return true if this rectangle contains the specified rectangle. 234e4464fdb4e9cebe8ad5fd39b2e5991ae5251d3b8robertphillips@google.com For speed, this method does not check if either this or the specified 235e4464fdb4e9cebe8ad5fd39b2e5991ae5251d3b8robertphillips@google.com rectangles are empty, and if either is, its return value is undefined. 236e4464fdb4e9cebe8ad5fd39b2e5991ae5251d3b8robertphillips@google.com In the debugging build however, we assert that both this and the 237e4464fdb4e9cebe8ad5fd39b2e5991ae5251d3b8robertphillips@google.com specified rectangles are non-empty. 238f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 239f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool containsNoEmptyCheck(int32_t left, int32_t top, 240e4464fdb4e9cebe8ad5fd39b2e5991ae5251d3b8robertphillips@google.com int32_t right, int32_t bottom) const { 241e4464fdb4e9cebe8ad5fd39b2e5991ae5251d3b8robertphillips@google.com SkASSERT(fLeft < fRight && fTop < fBottom); 242f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkASSERT(left < right && top < bottom); 243f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 244f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return fLeft <= left && fTop <= top && 245e4464fdb4e9cebe8ad5fd39b2e5991ae5251d3b8robertphillips@google.com fRight >= right && fBottom >= bottom; 246f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 2471fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 24866fb674216ec0792d141feb43a8bcb27cbf42710reed@google.com bool containsNoEmptyCheck(const SkIRect& r) const { 24966fb674216ec0792d141feb43a8bcb27cbf42710reed@google.com return containsNoEmptyCheck(r.fLeft, r.fTop, r.fRight, r.fBottom); 25066fb674216ec0792d141feb43a8bcb27cbf42710reed@google.com } 2511fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 252f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** If r intersects this rectangle, return true and set this rectangle to that 253f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com intersection, otherwise return false and do not change this rectangle. 254f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com If either rectangle is empty, do nothing and return false. 255f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 256cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com bool intersect(const SkIRect& r) { 257f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkASSERT(&r); 258f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return this->intersect(r.fLeft, r.fTop, r.fRight, r.fBottom); 259f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 260f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 261f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** If rectangles a and b intersect, return true and set this rectangle to 262f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com that intersection, otherwise return false and do not change this 263f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com rectangle. If either rectangle is empty, do nothing and return false. 264f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 265cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com bool intersect(const SkIRect& a, const SkIRect& b) { 266f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkASSERT(&a && &b); 2671fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 268f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com if (!a.isEmpty() && !b.isEmpty() && 269cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com a.fLeft < b.fRight && b.fLeft < a.fRight && 270cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com a.fTop < b.fBottom && b.fTop < a.fBottom) { 271f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fLeft = SkMax32(a.fLeft, b.fLeft); 272f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fTop = SkMax32(a.fTop, b.fTop); 273f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fRight = SkMin32(a.fRight, b.fRight); 274f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fBottom = SkMin32(a.fBottom, b.fBottom); 275f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return true; 276f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 277f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return false; 278f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 2791fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 280f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** If rectangles a and b intersect, return true and set this rectangle to 281f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com that intersection, otherwise return false and do not change this 282f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com rectangle. For speed, no check to see if a or b are empty is performed. 283f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com If either is, then the return result is undefined. In the debug build, 284f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com we assert that both rectangles are non-empty. 285f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 286cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com bool intersectNoEmptyCheck(const SkIRect& a, const SkIRect& b) { 287f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkASSERT(&a && &b); 288f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkASSERT(!a.isEmpty() && !b.isEmpty()); 2891fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 290f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com if (a.fLeft < b.fRight && b.fLeft < a.fRight && 291cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com a.fTop < b.fBottom && b.fTop < a.fBottom) { 292f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fLeft = SkMax32(a.fLeft, b.fLeft); 293f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fTop = SkMax32(a.fTop, b.fTop); 294f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fRight = SkMin32(a.fRight, b.fRight); 295f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fBottom = SkMin32(a.fBottom, b.fBottom); 296f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return true; 297f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 298f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return false; 299f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 300f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 301f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** If the rectangle specified by left,top,right,bottom intersects this rectangle, 302f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return true and set this rectangle to that intersection, 303f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com otherwise return false and do not change this rectangle. 304f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com If either rectangle is empty, do nothing and return false. 305f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 306cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com bool intersect(int32_t left, int32_t top, int32_t right, int32_t bottom) { 307f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com if (left < right && top < bottom && !this->isEmpty() && 308cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com fLeft < right && left < fRight && fTop < bottom && top < fBottom) { 309f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com if (fLeft < left) fLeft = left; 310f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com if (fTop < top) fTop = top; 311f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com if (fRight > right) fRight = right; 312f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com if (fBottom > bottom) fBottom = bottom; 313f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return true; 314f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 315f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return false; 316f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 3171fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 318f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Returns true if a and b are not empty, and they intersect 31966fb674216ec0792d141feb43a8bcb27cbf42710reed@google.com */ 320cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com static bool Intersects(const SkIRect& a, const SkIRect& b) { 321f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return !a.isEmpty() && !b.isEmpty() && // check for empties 32266fb674216ec0792d141feb43a8bcb27cbf42710reed@google.com a.fLeft < b.fRight && b.fLeft < a.fRight && 32366fb674216ec0792d141feb43a8bcb27cbf42710reed@google.com a.fTop < b.fBottom && b.fTop < a.fBottom; 32466fb674216ec0792d141feb43a8bcb27cbf42710reed@google.com } 3251fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 32666fb674216ec0792d141feb43a8bcb27cbf42710reed@google.com /** 32766fb674216ec0792d141feb43a8bcb27cbf42710reed@google.com * Returns true if a and b intersect. debug-asserts that neither are empty. 32866fb674216ec0792d141feb43a8bcb27cbf42710reed@google.com */ 32966fb674216ec0792d141feb43a8bcb27cbf42710reed@google.com static bool IntersectsNoEmptyCheck(const SkIRect& a, const SkIRect& b) { 33066fb674216ec0792d141feb43a8bcb27cbf42710reed@google.com SkASSERT(!a.isEmpty()); 33166fb674216ec0792d141feb43a8bcb27cbf42710reed@google.com SkASSERT(!b.isEmpty()); 33266fb674216ec0792d141feb43a8bcb27cbf42710reed@google.com return a.fLeft < b.fRight && b.fLeft < a.fRight && 333f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com a.fTop < b.fBottom && b.fTop < a.fBottom; 334f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 3351fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 336f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Update this rectangle to enclose itself and the specified rectangle. 337f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com If this rectangle is empty, just set it to the specified rectangle. If the specified 338f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com rectangle is empty, do nothing. 339f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 340f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void join(int32_t left, int32_t top, int32_t right, int32_t bottom); 341f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 342f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Update this rectangle to enclose itself and the specified rectangle. 343f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com If this rectangle is empty, just set it to the specified rectangle. If the specified 344f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com rectangle is empty, do nothing. 345f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 346cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com void join(const SkIRect& r) { 347f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com this->join(r.fLeft, r.fTop, r.fRight, r.fBottom); 348f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 349f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 350f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Swap top/bottom or left/right if there are flipped. 351f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com This can be called if the edges are computed separately, 352f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com and may have crossed over each other. 353f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com When this returns, left <= right && top <= bottom 354f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 355f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void sort(); 356856071eaa7341e0e58419ea331f98afced09a285reed@google.com 357e4464fdb4e9cebe8ad5fd39b2e5991ae5251d3b8robertphillips@google.com static const SkIRect& SK_WARN_UNUSED_RESULT EmptyIRect() { 358989dc05e80ddd2b4aa445779b627bcedc244bbe3reed@google.com static const SkIRect gEmpty = { 0, 0, 0, 0 }; 359856071eaa7341e0e58419ea331f98afced09a285reed@google.com return gEmpty; 360856071eaa7341e0e58419ea331f98afced09a285reed@google.com } 361f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com}; 362f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 363f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com/** \struct SkRect 364f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com*/ 3652083387d719b933797044ad07efd3bb67f99a5c5ctguil@chromium.orgstruct SK_API SkRect { 366f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkScalar fLeft, fTop, fRight, fBottom; 367f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 368e4464fdb4e9cebe8ad5fd39b2e5991ae5251d3b8robertphillips@google.com static SkRect SK_WARN_UNUSED_RESULT MakeEmpty() { 369f38afdf51420b6c891f1e1079384e55ea65c7ad3reed@android.com SkRect r; 370f38afdf51420b6c891f1e1079384e55ea65c7ad3reed@android.com r.setEmpty(); 371f38afdf51420b6c891f1e1079384e55ea65c7ad3reed@android.com return r; 372f38afdf51420b6c891f1e1079384e55ea65c7ad3reed@android.com } 373f38afdf51420b6c891f1e1079384e55ea65c7ad3reed@android.com 374e4464fdb4e9cebe8ad5fd39b2e5991ae5251d3b8robertphillips@google.com static SkRect SK_WARN_UNUSED_RESULT MakeWH(SkScalar w, SkScalar h) { 375f38afdf51420b6c891f1e1079384e55ea65c7ad3reed@android.com SkRect r; 376f38afdf51420b6c891f1e1079384e55ea65c7ad3reed@android.com r.set(0, 0, w, h); 377f38afdf51420b6c891f1e1079384e55ea65c7ad3reed@android.com return r; 378f38afdf51420b6c891f1e1079384e55ea65c7ad3reed@android.com } 379f38afdf51420b6c891f1e1079384e55ea65c7ad3reed@android.com 380e4464fdb4e9cebe8ad5fd39b2e5991ae5251d3b8robertphillips@google.com static SkRect SK_WARN_UNUSED_RESULT MakeSize(const SkSize& size) { 38108fc3cebc3c5a71ef5c3a1e3679036c142fd756ereed@android.com SkRect r; 38208fc3cebc3c5a71ef5c3a1e3679036c142fd756ereed@android.com r.set(0, 0, size.width(), size.height()); 38308fc3cebc3c5a71ef5c3a1e3679036c142fd756ereed@android.com return r; 38408fc3cebc3c5a71ef5c3a1e3679036c142fd756ereed@android.com } 38597720eae923fe5f008a934a7ec4b751e7e9780bcskia.committer@gmail.com 386e4464fdb4e9cebe8ad5fd39b2e5991ae5251d3b8robertphillips@google.com static SkRect SK_WARN_UNUSED_RESULT MakeLTRB(SkScalar l, SkScalar t, SkScalar r, SkScalar b) { 38708fc3cebc3c5a71ef5c3a1e3679036c142fd756ereed@android.com SkRect rect; 38808fc3cebc3c5a71ef5c3a1e3679036c142fd756ereed@android.com rect.set(l, t, r, b); 38908fc3cebc3c5a71ef5c3a1e3679036c142fd756ereed@android.com return rect; 39008fc3cebc3c5a71ef5c3a1e3679036c142fd756ereed@android.com } 39108fc3cebc3c5a71ef5c3a1e3679036c142fd756ereed@android.com 392e4464fdb4e9cebe8ad5fd39b2e5991ae5251d3b8robertphillips@google.com static SkRect SK_WARN_UNUSED_RESULT MakeXYWH(SkScalar x, SkScalar y, SkScalar w, SkScalar h) { 39308fc3cebc3c5a71ef5c3a1e3679036c142fd756ereed@android.com SkRect r; 39408fc3cebc3c5a71ef5c3a1e3679036c142fd756ereed@android.com r.set(x, y, x + w, y + h); 3959613767e1f1d08ce627c665e8c0098cb59b10931bsalomon@google.com return r; 3969613767e1f1d08ce627c665e8c0098cb59b10931bsalomon@google.com } 3979613767e1f1d08ce627c665e8c0098cb59b10931bsalomon@google.com 39885801db3733c30403e0af142aa7ea53e84e2e98creed@google.com // DEPRECATED: call Make(r) 3999613767e1f1d08ce627c665e8c0098cb59b10931bsalomon@google.com static SkRect SK_WARN_UNUSED_RESULT MakeFromIRect(const SkIRect& irect) { 4009613767e1f1d08ce627c665e8c0098cb59b10931bsalomon@google.com SkRect r; 4019613767e1f1d08ce627c665e8c0098cb59b10931bsalomon@google.com r.set(SkIntToScalar(irect.fLeft), 4029613767e1f1d08ce627c665e8c0098cb59b10931bsalomon@google.com SkIntToScalar(irect.fTop), 4039613767e1f1d08ce627c665e8c0098cb59b10931bsalomon@google.com SkIntToScalar(irect.fRight), 4049613767e1f1d08ce627c665e8c0098cb59b10931bsalomon@google.com SkIntToScalar(irect.fBottom)); 40508fc3cebc3c5a71ef5c3a1e3679036c142fd756ereed@android.com return r; 40608fc3cebc3c5a71ef5c3a1e3679036c142fd756ereed@android.com } 4074c3b7eeb347315874063dcee15a081a888d2c732skia.committer@gmail.com 40885801db3733c30403e0af142aa7ea53e84e2e98creed@google.com static SkRect SK_WARN_UNUSED_RESULT Make(const SkIRect& irect) { 40985801db3733c30403e0af142aa7ea53e84e2e98creed@google.com SkRect r; 41085801db3733c30403e0af142aa7ea53e84e2e98creed@google.com r.set(SkIntToScalar(irect.fLeft), 41185801db3733c30403e0af142aa7ea53e84e2e98creed@google.com SkIntToScalar(irect.fTop), 41285801db3733c30403e0af142aa7ea53e84e2e98creed@google.com SkIntToScalar(irect.fRight), 41385801db3733c30403e0af142aa7ea53e84e2e98creed@google.com SkIntToScalar(irect.fBottom)); 41485801db3733c30403e0af142aa7ea53e84e2e98creed@google.com return r; 41585801db3733c30403e0af142aa7ea53e84e2e98creed@google.com } 4164c3b7eeb347315874063dcee15a081a888d2c732skia.committer@gmail.com 417b8ec7fae327747c6b1ef7d6fac06df8b87c857d9reed@google.com /** 418b8ec7fae327747c6b1ef7d6fac06df8b87c857d9reed@google.com * Return true if the rectangle's width or height are <= 0 419b8ec7fae327747c6b1ef7d6fac06df8b87c857d9reed@google.com */ 420b8ec7fae327747c6b1ef7d6fac06df8b87c857d9reed@google.com bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; } 4211fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 422b8ec7fae327747c6b1ef7d6fac06df8b87c857d9reed@google.com /** 423b8ec7fae327747c6b1ef7d6fac06df8b87c857d9reed@google.com * Returns true iff all values in the rect are finite. If any are 424b8ec7fae327747c6b1ef7d6fac06df8b87c857d9reed@google.com * infinite or NaN (or SK_FixedNaN when SkScalar is fixed) then this 425b8ec7fae327747c6b1ef7d6fac06df8b87c857d9reed@google.com * returns false. 426b8ec7fae327747c6b1ef7d6fac06df8b87c857d9reed@google.com */ 427b8ec7fae327747c6b1ef7d6fac06df8b87c857d9reed@google.com bool isFinite() const { 428b8ec7fae327747c6b1ef7d6fac06df8b87c857d9reed@google.com#ifdef SK_SCALAR_IS_FLOAT 429d508c3fc979429e45ed20788fc1a015ae01f9f52reed@google.com float accum = 0; 430d508c3fc979429e45ed20788fc1a015ae01f9f52reed@google.com accum *= fLeft; 431d508c3fc979429e45ed20788fc1a015ae01f9f52reed@google.com accum *= fTop; 432d508c3fc979429e45ed20788fc1a015ae01f9f52reed@google.com accum *= fRight; 433d508c3fc979429e45ed20788fc1a015ae01f9f52reed@google.com accum *= fBottom; 4341fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 435d508c3fc979429e45ed20788fc1a015ae01f9f52reed@google.com // accum is either NaN or it is finite (zero). 436d508c3fc979429e45ed20788fc1a015ae01f9f52reed@google.com SkASSERT(0 == accum || !(accum == accum)); 437d508c3fc979429e45ed20788fc1a015ae01f9f52reed@google.com 438b8ec7fae327747c6b1ef7d6fac06df8b87c857d9reed@google.com // value==value will be true iff value is not NaN 439d508c3fc979429e45ed20788fc1a015ae01f9f52reed@google.com // TODO: is it faster to say !accum or accum==accum? 440d508c3fc979429e45ed20788fc1a015ae01f9f52reed@google.com return accum == accum; 441b8ec7fae327747c6b1ef7d6fac06df8b87c857d9reed@google.com#else 442b8ec7fae327747c6b1ef7d6fac06df8b87c857d9reed@google.com // use bit-or for speed, since we don't care about short-circuting the 443b8ec7fae327747c6b1ef7d6fac06df8b87c857d9reed@google.com // tests, and we expect the common case will be that we need to check all. 444b8ec7fae327747c6b1ef7d6fac06df8b87c857d9reed@google.com int isNaN = (SK_FixedNaN == fLeft) | (SK_FixedNaN == fTop) | 445b8ec7fae327747c6b1ef7d6fac06df8b87c857d9reed@google.com (SK_FixedNaN == fRight) | (SK_FixedNaN == fBottom); 446b8ec7fae327747c6b1ef7d6fac06df8b87c857d9reed@google.com return !isNaN; 447b8ec7fae327747c6b1ef7d6fac06df8b87c857d9reed@google.com#endif 448b8ec7fae327747c6b1ef7d6fac06df8b87c857d9reed@google.com } 449b8ec7fae327747c6b1ef7d6fac06df8b87c857d9reed@google.com 450d665ab6f4d2e2ace800041b0352ebecb794c3f71reed@google.com SkScalar x() const { return fLeft; } 451d665ab6f4d2e2ace800041b0352ebecb794c3f71reed@google.com SkScalar y() const { return fTop; } 452856071eaa7341e0e58419ea331f98afced09a285reed@google.com SkScalar left() const { return fLeft; } 453856071eaa7341e0e58419ea331f98afced09a285reed@google.com SkScalar top() const { return fTop; } 454856071eaa7341e0e58419ea331f98afced09a285reed@google.com SkScalar right() const { return fRight; } 455856071eaa7341e0e58419ea331f98afced09a285reed@google.com SkScalar bottom() const { return fBottom; } 456f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkScalar width() const { return fRight - fLeft; } 457f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkScalar height() const { return fBottom - fTop; } 458f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkScalar centerX() const { return SkScalarHalf(fLeft + fRight); } 459f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkScalar centerY() const { return SkScalarHalf(fTop + fBottom); } 460f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 4612313151b072137a702d0338a25bd3d2f4aee881dbsalomon@google.com friend bool operator==(const SkRect& a, const SkRect& b) { 462ff6afdb698cb8b661761b72f4a086996c39d71d8reed@google.com return SkScalarsEqual((SkScalar*)&a, (SkScalar*)&b, 4); 463f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 464cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com 4652313151b072137a702d0338a25bd3d2f4aee881dbsalomon@google.com friend bool operator!=(const SkRect& a, const SkRect& b) { 466ff6afdb698cb8b661761b72f4a086996c39d71d8reed@google.com return !SkScalarsEqual((SkScalar*)&a, (SkScalar*)&b, 4); 467f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 468f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 469f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** return the 4 points that enclose the rectangle 470f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 471f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void toQuad(SkPoint quad[4]) const; 472f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 473f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Set this rectangle to the empty rectangle (0,0,0,0) 474f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 475f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void setEmpty() { memset(this, 0, sizeof(*this)); } 476f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 477cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com void set(const SkIRect& src) { 478f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fLeft = SkIntToScalar(src.fLeft); 479f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fTop = SkIntToScalar(src.fTop); 480f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fRight = SkIntToScalar(src.fRight); 481f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fBottom = SkIntToScalar(src.fBottom); 482f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 483f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 484cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com void set(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) { 485f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fLeft = left; 486f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fTop = top; 487f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fRight = right; 488f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fBottom = bottom; 489f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 490856071eaa7341e0e58419ea331f98afced09a285reed@google.com // alias for set(l, t, r, b) 491856071eaa7341e0e58419ea331f98afced09a285reed@google.com void setLTRB(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) { 492856071eaa7341e0e58419ea331f98afced09a285reed@google.com this->set(left, top, right, bottom); 493856071eaa7341e0e58419ea331f98afced09a285reed@google.com } 494856071eaa7341e0e58419ea331f98afced09a285reed@google.com 495f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Initialize the rect with the 4 specified integers. The routine handles 496f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com converting them to scalars (by calling SkIntToScalar) 497f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 498f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void iset(int left, int top, int right, int bottom) { 499f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fLeft = SkIntToScalar(left); 500f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fTop = SkIntToScalar(top); 501f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fRight = SkIntToScalar(right); 502f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fBottom = SkIntToScalar(bottom); 503f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 504f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 50585a0f0f746f29b6d733965e7f2eea743f1cb0869reed@google.com /** 50685a0f0f746f29b6d733965e7f2eea743f1cb0869reed@google.com * Set this rectangle to be left/top at 0,0, and have the specified width 50785a0f0f746f29b6d733965e7f2eea743f1cb0869reed@google.com * and height (automatically converted to SkScalar). 50885a0f0f746f29b6d733965e7f2eea743f1cb0869reed@google.com */ 50985a0f0f746f29b6d733965e7f2eea743f1cb0869reed@google.com void isetWH(int width, int height) { 51085a0f0f746f29b6d733965e7f2eea743f1cb0869reed@google.com fLeft = fTop = 0; 51185a0f0f746f29b6d733965e7f2eea743f1cb0869reed@google.com fRight = SkIntToScalar(width); 51285a0f0f746f29b6d733965e7f2eea743f1cb0869reed@google.com fBottom = SkIntToScalar(height); 51385a0f0f746f29b6d733965e7f2eea743f1cb0869reed@google.com } 51497720eae923fe5f008a934a7ec4b751e7e9780bcskia.committer@gmail.com 515f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Set this rectangle to be the bounds of the array of points. 516f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com If the array is empty (count == 0), then set this rectangle 517f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com to the empty rectangle (0,0,0,0) 518f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 519c2915a48f56d88dd9b0326bde40181a86415423areed@google.com void set(const SkPoint pts[], int count) { 520c2915a48f56d88dd9b0326bde40181a86415423areed@google.com // set() had been checking for non-finite values, so keep that behavior 521c2915a48f56d88dd9b0326bde40181a86415423areed@google.com // for now. Now that we have setBoundsCheck(), we may decide to make 522c2915a48f56d88dd9b0326bde40181a86415423areed@google.com // set() be simpler/faster, and not check for those. 523c2915a48f56d88dd9b0326bde40181a86415423areed@google.com (void)this->setBoundsCheck(pts, count); 524c2915a48f56d88dd9b0326bde40181a86415423areed@google.com } 525f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 526856071eaa7341e0e58419ea331f98afced09a285reed@google.com // alias for set(pts, count) 527856071eaa7341e0e58419ea331f98afced09a285reed@google.com void setBounds(const SkPoint pts[], int count) { 528c2915a48f56d88dd9b0326bde40181a86415423areed@google.com (void)this->setBoundsCheck(pts, count); 529856071eaa7341e0e58419ea331f98afced09a285reed@google.com } 5301fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 531c2915a48f56d88dd9b0326bde40181a86415423areed@google.com /** 532c2915a48f56d88dd9b0326bde40181a86415423areed@google.com * Compute the bounds of the array of points, and set this rect to that 533c2915a48f56d88dd9b0326bde40181a86415423areed@google.com * bounds and return true... unless a non-finite value is encountered, 534c2915a48f56d88dd9b0326bde40181a86415423areed@google.com * in which case this rect is set to empty and false is returned. 535c2915a48f56d88dd9b0326bde40181a86415423areed@google.com */ 536c2915a48f56d88dd9b0326bde40181a86415423areed@google.com bool setBoundsCheck(const SkPoint pts[], int count); 5371fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 538d508c3fc979429e45ed20788fc1a015ae01f9f52reed@google.com void set(const SkPoint& p0, const SkPoint& p1) { 539d508c3fc979429e45ed20788fc1a015ae01f9f52reed@google.com fLeft = SkMinScalar(p0.fX, p1.fX); 540d508c3fc979429e45ed20788fc1a015ae01f9f52reed@google.com fRight = SkMaxScalar(p0.fX, p1.fX); 541d508c3fc979429e45ed20788fc1a015ae01f9f52reed@google.com fTop = SkMinScalar(p0.fY, p1.fY); 542d508c3fc979429e45ed20788fc1a015ae01f9f52reed@google.com fBottom = SkMaxScalar(p0.fY, p1.fY); 543d508c3fc979429e45ed20788fc1a015ae01f9f52reed@google.com } 544d508c3fc979429e45ed20788fc1a015ae01f9f52reed@google.com 5454bae66e75406a05ca34bb91e505aac1865c93fe9reed@google.com void setXYWH(SkScalar x, SkScalar y, SkScalar width, SkScalar height) { 5464bae66e75406a05ca34bb91e505aac1865c93fe9reed@google.com fLeft = x; 5474bae66e75406a05ca34bb91e505aac1865c93fe9reed@google.com fTop = y; 5484bae66e75406a05ca34bb91e505aac1865c93fe9reed@google.com fRight = x + width; 5494bae66e75406a05ca34bb91e505aac1865c93fe9reed@google.com fBottom = y + height; 5504bae66e75406a05ca34bb91e505aac1865c93fe9reed@google.com } 5514bae66e75406a05ca34bb91e505aac1865c93fe9reed@google.com 552a588ffb6f5d538b3f7bb021b391dea78dc1312cfbsalomon@google.com void setWH(SkScalar width, SkScalar height) { 553a588ffb6f5d538b3f7bb021b391dea78dc1312cfbsalomon@google.com fLeft = 0; 554a588ffb6f5d538b3f7bb021b391dea78dc1312cfbsalomon@google.com fTop = 0; 555a588ffb6f5d538b3f7bb021b391dea78dc1312cfbsalomon@google.com fRight = width; 556a588ffb6f5d538b3f7bb021b391dea78dc1312cfbsalomon@google.com fBottom = height; 557a588ffb6f5d538b3f7bb021b391dea78dc1312cfbsalomon@google.com } 558a588ffb6f5d538b3f7bb021b391dea78dc1312cfbsalomon@google.com 559856071eaa7341e0e58419ea331f98afced09a285reed@google.com /** 560856071eaa7341e0e58419ea331f98afced09a285reed@google.com * Make the largest representable rectangle 561856071eaa7341e0e58419ea331f98afced09a285reed@google.com */ 562856071eaa7341e0e58419ea331f98afced09a285reed@google.com void setLargest() { 563856071eaa7341e0e58419ea331f98afced09a285reed@google.com fLeft = fTop = SK_ScalarMin; 564856071eaa7341e0e58419ea331f98afced09a285reed@google.com fRight = fBottom = SK_ScalarMax; 565856071eaa7341e0e58419ea331f98afced09a285reed@google.com } 5661fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 567856071eaa7341e0e58419ea331f98afced09a285reed@google.com /** 568856071eaa7341e0e58419ea331f98afced09a285reed@google.com * Make the largest representable rectangle, but inverted (e.g. fLeft will 569856071eaa7341e0e58419ea331f98afced09a285reed@google.com * be max and right will be min). 570856071eaa7341e0e58419ea331f98afced09a285reed@google.com */ 571856071eaa7341e0e58419ea331f98afced09a285reed@google.com void setLargestInverted() { 572856071eaa7341e0e58419ea331f98afced09a285reed@google.com fLeft = fTop = SK_ScalarMax; 573856071eaa7341e0e58419ea331f98afced09a285reed@google.com fRight = fBottom = SK_ScalarMin; 574856071eaa7341e0e58419ea331f98afced09a285reed@google.com } 575856071eaa7341e0e58419ea331f98afced09a285reed@google.com 576f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Offset set the rectangle by adding dx to its left and right, 577f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com and adding dy to its top and bottom. 578f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 579cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com void offset(SkScalar dx, SkScalar dy) { 580f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fLeft += dx; 581f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fTop += dy; 582f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fRight += dx; 583f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fBottom += dy; 5841fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com } 585f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 586cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com void offset(const SkPoint& delta) { 587cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com this->offset(delta.fX, delta.fY); 588cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com } 589cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com 5903306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com /** 5913306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com * Offset this rect such its new x() and y() will equal newX and newY. 5923306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com */ 5933306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com void offsetTo(SkScalar newX, SkScalar newY) { 5943306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com fRight += newX - fLeft; 5953306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com fBottom += newY - fTop; 5963306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com fLeft = newX; 5973306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com fTop = newY; 5983306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com } 5996fb3eff87cc38e851f40f42a624408850c87def4skia.committer@gmail.com 600a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com /** Inset the rectangle by (dx,dy). If dx is positive, then the sides are 601a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com moved inwards, making the rectangle narrower. If dx is negative, then 602a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com the sides are moved outwards, making the rectangle wider. The same holds 603a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com true for dy and the top and bottom. 604f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 605cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com void inset(SkScalar dx, SkScalar dy) { 606f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fLeft += dx; 607f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fTop += dy; 608f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fRight -= dx; 609f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fBottom -= dy; 610f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 611f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 612a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com /** Outset the rectangle by (dx,dy). If dx is positive, then the sides are 613a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com moved outwards, making the rectangle wider. If dx is negative, then the 614b0ded505e1cf419f24d775f1fce5f34fd62c7d65robertphillips@google.com sides are moved inwards, making the rectangle narrower. The same holds 615a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com true for dy and the top and bottom. 616a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com */ 617a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com void outset(SkScalar dx, SkScalar dy) { this->inset(-dx, -dy); } 618a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com 619f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** If this rectangle intersects r, return true and set this rectangle to that 620f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com intersection, otherwise return false and do not change this rectangle. 621f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com If either rectangle is empty, do nothing and return false. 622f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 623f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool intersect(const SkRect& r); 624f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 625f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** If this rectangle intersects the rectangle specified by left, top, right, bottom, 626f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return true and set this rectangle to that intersection, otherwise return false 627f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com and do not change this rectangle. 628f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com If either rectangle is empty, do nothing and return false. 629f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 630f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool intersect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom); 631f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 632bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com /** 633bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * Return true if this rectangle is not empty, and the specified sides of 634bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * a rectangle are not empty, and they intersect. 635bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com */ 636cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com bool intersects(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) const { 637f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return // first check that both are not empty 638f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com left < right && top < bottom && 639f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fLeft < fRight && fTop < fBottom && 640f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com // now check for intersection 641f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fLeft < right && left < fRight && 642f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fTop < bottom && top < fBottom; 643f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 644c3684ba092b73640aad92d56edcefceb1bcffc5freed@google.com 645c3684ba092b73640aad92d56edcefceb1bcffc5freed@google.com /** If rectangles a and b intersect, return true and set this rectangle to 646c3684ba092b73640aad92d56edcefceb1bcffc5freed@google.com * that intersection, otherwise return false and do not change this 647c3684ba092b73640aad92d56edcefceb1bcffc5freed@google.com * rectangle. If either rectangle is empty, do nothing and return false. 648c3684ba092b73640aad92d56edcefceb1bcffc5freed@google.com */ 649c3684ba092b73640aad92d56edcefceb1bcffc5freed@google.com bool intersect(const SkRect& a, const SkRect& b); 6501fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 651bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com /** 652bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * Return true if rectangles a and b are not empty and intersect. 653bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com */ 654cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com static bool Intersects(const SkRect& a, const SkRect& b) { 655bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com return !a.isEmpty() && !b.isEmpty() && 656bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com a.fLeft < b.fRight && b.fLeft < a.fRight && 657bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com a.fTop < b.fBottom && b.fTop < a.fBottom; 658f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 6591fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 660bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com /** 661bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * Update this rectangle to enclose itself and the specified rectangle. 662bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * If this rectangle is empty, just set it to the specified rectangle. 663bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * If the specified rectangle is empty, do nothing. 664bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com */ 665f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void join(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom); 666f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 667f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Update this rectangle to enclose itself and the specified rectangle. 668f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com If this rectangle is empty, just set it to the specified rectangle. If the specified 669f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com rectangle is empty, do nothing. 670f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 671cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com void join(const SkRect& r) { 672f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com this->join(r.fLeft, r.fTop, r.fRight, r.fBottom); 673f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 674856071eaa7341e0e58419ea331f98afced09a285reed@google.com // alias for join() 675856071eaa7341e0e58419ea331f98afced09a285reed@google.com void growToInclude(const SkRect& r) { this->join(r); } 676856071eaa7341e0e58419ea331f98afced09a285reed@google.com 677bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com /** 678bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * Grow the rect to include the specified (x,y). After this call, the 679bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * following will be true: fLeft <= x <= fRight && fTop <= y <= fBottom. 680bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * 681bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * This is close, but not quite the same contract as contains(), since 682bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * contains() treats the left and top different from the right and bottom. 683bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * contains(x,y) -> fLeft <= x < fRight && fTop <= y < fBottom. Also note 684bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * that contains(x,y) always returns false if the rect is empty. 685bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com */ 686856071eaa7341e0e58419ea331f98afced09a285reed@google.com void growToInclude(SkScalar x, SkScalar y) { 687856071eaa7341e0e58419ea331f98afced09a285reed@google.com fLeft = SkMinScalar(x, fLeft); 688f4968b8f7911d573d439eb8d4d3f0cbdfaccf153bsalomon@google.com fRight = SkMaxScalar(x, fRight); 689f4968b8f7911d573d439eb8d4d3f0cbdfaccf153bsalomon@google.com fTop = SkMinScalar(y, fTop); 690856071eaa7341e0e58419ea331f98afced09a285reed@google.com fBottom = SkMaxScalar(y, fBottom); 691856071eaa7341e0e58419ea331f98afced09a285reed@google.com } 6921fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 693bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com /** 694bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * Returns true if (p.fX,p.fY) is inside the rectangle, and the rectangle 695bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * is not empty. 696bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * 697bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * Contains treats the left and top differently from the right and bottom. 698bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * The left and top coordinates of the rectangle are themselves considered 699bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * to be inside, while the right and bottom are not. Thus for the rectangle 700bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * {0, 0, 5, 10}, (0,0) is contained, but (0,10), (5,0) and (5,10) are not. 701bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com */ 702cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com bool contains(const SkPoint& p) const { 703bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com return !this->isEmpty() && 704bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com fLeft <= p.fX && p.fX < fRight && fTop <= p.fY && p.fY < fBottom; 705f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 706f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 707bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com /** 708bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * Returns true if (x,y) is inside the rectangle, and the rectangle 709bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * is not empty. 710bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * 711bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * Contains treats the left and top differently from the right and bottom. 712bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * The left and top coordinates of the rectangle are themselves considered 713bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * to be inside, while the right and bottom are not. Thus for the rectangle 714bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * {0, 0, 5, 10}, (0,0) is contained, but (0,10), (5,0) and (5,10) are not. 715bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com */ 716cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com bool contains(SkScalar x, SkScalar y) const { 717f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return !this->isEmpty() && 718bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com fLeft <= x && x < fRight && fTop <= y && y < fBottom; 719f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 720f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 721bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com /** 722bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * Return true if this rectangle contains r, and if both rectangles are 723bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * not empty. 724bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com */ 725cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com bool contains(const SkRect& r) const { 726bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com return !r.isEmpty() && !this->isEmpty() && 727f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fLeft <= r.fLeft && fTop <= r.fTop && 728f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fRight >= r.fRight && fBottom >= r.fBottom; 729f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 730f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 731bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com /** 732bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * Set the dst rectangle by rounding this rectangle's coordinates to their 733bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * nearest integer values using SkScalarRound. 734bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com */ 735cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com void round(SkIRect* dst) const { 736f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkASSERT(dst); 7373306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com dst->set(SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop), 7383306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)); 739f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 740f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 741bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com /** 742bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * Set the dst rectangle by rounding "out" this rectangle, choosing the 743bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * SkScalarFloor of top and left, and the SkScalarCeil of right and bottom. 744bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com */ 745cc7f120e9e28059285825463ca8dfcc3ef8c0fdareed@android.com void roundOut(SkIRect* dst) const { 746f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkASSERT(dst); 7473306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com dst->set(SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop), 7483306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)); 749f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 750f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 751bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com /** 752a7b53f5a592a776308eb1ab0b4faf94e8d6657a3reed@google.com * Expand this rectangle by rounding its coordinates "out", choosing the 753a7b53f5a592a776308eb1ab0b4faf94e8d6657a3reed@google.com * floor of top and left, and the ceil of right and bottom. If this rect 754a7b53f5a592a776308eb1ab0b4faf94e8d6657a3reed@google.com * is already on integer coordinates, then it will be unchanged. 755a7b53f5a592a776308eb1ab0b4faf94e8d6657a3reed@google.com */ 756a7b53f5a592a776308eb1ab0b4faf94e8d6657a3reed@google.com void roundOut() { 757a7b53f5a592a776308eb1ab0b4faf94e8d6657a3reed@google.com this->set(SkScalarFloorToScalar(fLeft), 758a7b53f5a592a776308eb1ab0b4faf94e8d6657a3reed@google.com SkScalarFloorToScalar(fTop), 759a7b53f5a592a776308eb1ab0b4faf94e8d6657a3reed@google.com SkScalarCeilToScalar(fRight), 760a7b53f5a592a776308eb1ab0b4faf94e8d6657a3reed@google.com SkScalarCeilToScalar(fBottom)); 761a7b53f5a592a776308eb1ab0b4faf94e8d6657a3reed@google.com } 762a7b53f5a592a776308eb1ab0b4faf94e8d6657a3reed@google.com 763a7b53f5a592a776308eb1ab0b4faf94e8d6657a3reed@google.com /** 7643306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com * Set the dst rectangle by rounding "in" this rectangle, choosing the 7653306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com * ceil of top and left, and the floor of right and bottom. This does *not* 7663306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com * call sort(), so it is possible that the resulting rect is inverted... 7673306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com * e.g. left >= right or top >= bottom. Call isEmpty() to detect that. 7683306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com */ 7693306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com void roundIn(SkIRect* dst) const { 7703306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com SkASSERT(dst); 7713306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com dst->set(SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop), 7723306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom)); 7733306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com } 7746fb3eff87cc38e851f40f42a624408850c87def4skia.committer@gmail.com 7756fb3eff87cc38e851f40f42a624408850c87def4skia.committer@gmail.com 7763306b14f3ce35e95a8cc77fd112a856411f9e944reed@google.com /** 777bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * Swap top/bottom or left/right if there are flipped (i.e. if width() 778bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * or height() would have returned a negative value.) This should be called 779bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * if the edges are computed separately, and may have crossed over each 780bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com * other. When this returns, left <= right && top <= bottom 781bf4e96313ef35ec20158f35e9bbb33be51985f0areed@google.com */ 782f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void sort(); 783024be095908c3477a4a77007ca6d3303d55383ffskia.committer@gmail.com 7844edb764d2f488b86d430aae87a960b3c6e9409e2reed@google.com /** 7854edb764d2f488b86d430aae87a960b3c6e9409e2reed@google.com * cast-safe way to treat the rect as an array of (4) SkScalars. 7864edb764d2f488b86d430aae87a960b3c6e9409e2reed@google.com */ 7874edb764d2f488b86d430aae87a960b3c6e9409e2reed@google.com const SkScalar* asScalars() const { return &fLeft; } 788f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com}; 789f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 790f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com#endif 791