LCOV - code coverage report
Current view: top level - gfx/skia/skia/include/core - SkRect.h (source / functions) Hit Total Coverage
Test: output.info Lines: 217 353 61.5 %
Date: 2017-07-14 16:53:18 Functions: 62 105 59.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2006 The Android Open Source Project
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : #ifndef SkRect_DEFINED
       9             : #define SkRect_DEFINED
      10             : 
      11             : #include "SkPoint.h"
      12             : #include "SkSize.h"
      13             : 
      14             : struct SkRect;
      15             : 
      16             : /** \struct SkIRect
      17             : 
      18             :     SkIRect holds four 32 bit integer coordinates for a rectangle
      19             : */
      20             : struct SK_API SkIRect {
      21             :     int32_t fLeft, fTop, fRight, fBottom;
      22             : 
      23         126 :     static SkIRect SK_WARN_UNUSED_RESULT MakeEmpty() {
      24             :         SkIRect r;
      25         126 :         r.setEmpty();
      26         126 :         return r;
      27             :     }
      28             : 
      29           0 :     static SkIRect SK_WARN_UNUSED_RESULT MakeLargest() {
      30             :         SkIRect r;
      31           0 :         r.setLargest();
      32           0 :         return r;
      33             :     }
      34             : 
      35         365 :     static SkIRect SK_WARN_UNUSED_RESULT MakeWH(int32_t w, int32_t h) {
      36             :         SkIRect r;
      37         365 :         r.set(0, 0, w, h);
      38         365 :         return r;
      39             :     }
      40             : 
      41         127 :     static SkIRect SK_WARN_UNUSED_RESULT MakeSize(const SkISize& size) {
      42             :         SkIRect r;
      43         127 :         r.set(0, 0, size.width(), size.height());
      44         127 :         return r;
      45             :     }
      46             : 
      47          43 :     static SkIRect SK_WARN_UNUSED_RESULT MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b) {
      48             :         SkIRect rect;
      49          43 :         rect.set(l, t, r, b);
      50          43 :         return rect;
      51             :     }
      52             : 
      53        4103 :     static SkIRect SK_WARN_UNUSED_RESULT MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h) {
      54             :         SkIRect r;
      55        4103 :         r.set(x, y, x + w, y + h);
      56        4103 :         return r;
      57             :     }
      58             : 
      59       13061 :     int left() const { return fLeft; }
      60       13061 :     int top() const { return fTop; }
      61         467 :     int right() const { return fRight; }
      62         241 :     int bottom() const { return fBottom; }
      63             : 
      64             :     /** return the left edge of the rect */
      65        5291 :     int x() const { return fLeft; }
      66             :     /** return the top edge of the rect */
      67        5735 :     int y() const { return fTop; }
      68             :     /**
      69             :      *  Returns the rectangle's width. This does not check for a valid rect
      70             :      *  (i.e. left <= right) so the result may be negative.
      71             :      */
      72       53544 :     int width() const { return fRight - fLeft; }
      73             : 
      74             :     /**
      75             :      *  Returns the rectangle's height. This does not check for a valid rect
      76             :      *  (i.e. top <= bottom) so the result may be negative.
      77             :      */
      78       10505 :     int height() const { return fBottom - fTop; }
      79             : 
      80           0 :     SkISize size() const { return SkISize::Make(this->width(), this->height()); }
      81             : 
      82             :     /**
      83             :      *  Since the center of an integer rect may fall on a factional value, this
      84             :      *  method is defined to return (right + left) >> 1.
      85             :      *
      86             :      *  This is a specific "truncation" of the average, which is different than
      87             :      *  (right + left) / 2 when the sum is negative.
      88             :      */
      89             :     int centerX() const { return (fRight + fLeft) >> 1; }
      90             : 
      91             :     /**
      92             :      *  Since the center of an integer rect may fall on a factional value, this
      93             :      *  method is defined to return (bottom + top) >> 1
      94             :      *
      95             :      *  This is a specific "truncation" of the average, which is different than
      96             :      *  (bottom + top) / 2 when the sum is negative.
      97             :      */
      98             :     int centerY() const { return (fBottom + fTop) >> 1; }
      99             : 
     100             :     /**
     101             :      *  Return true if the rectangle's width or height are <= 0
     102             :      */
     103       34461 :     bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; }
     104             : 
     105             :     bool isLargest() const { return SK_MinS32 == fLeft &&
     106             :                                     SK_MinS32 == fTop &&
     107             :                                     SK_MaxS32 == fRight &&
     108             :                                     SK_MaxS32 == fBottom; }
     109             : 
     110        2080 :     friend bool operator==(const SkIRect& a, const SkIRect& b) {
     111        2080 :         return !memcmp(&a, &b, sizeof(a));
     112             :     }
     113             : 
     114         458 :     friend bool operator!=(const SkIRect& a, const SkIRect& b) {
     115         458 :         return !(a == b);
     116             :     }
     117             : 
     118           0 :     bool is16Bit() const {
     119           0 :         return  SkIsS16(fLeft) && SkIsS16(fTop) &&
     120           0 :                 SkIsS16(fRight) && SkIsS16(fBottom);
     121             :     }
     122             : 
     123             :     /** Set the rectangle to (0,0,0,0)
     124             :     */
     125        1360 :     void setEmpty() { memset(this, 0, sizeof(*this)); }
     126             : 
     127       10722 :     void set(int32_t left, int32_t top, int32_t right, int32_t bottom) {
     128       10722 :         fLeft   = left;
     129       10722 :         fTop    = top;
     130       10722 :         fRight  = right;
     131       10722 :         fBottom = bottom;
     132       10722 :     }
     133             :     // alias for set(l, t, r, b)
     134           0 :     void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom) {
     135           0 :         this->set(left, top, right, bottom);
     136           0 :     }
     137             : 
     138         129 :     void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height) {
     139         129 :         fLeft = x;
     140         129 :         fTop = y;
     141         129 :         fRight = x + width;
     142         129 :         fBottom = y + height;
     143         129 :     }
     144             : 
     145             :     /**
     146             :      *  Make the largest representable rectangle
     147             :      */
     148           0 :     void setLargest() {
     149           0 :         fLeft = fTop = SK_MinS32;
     150           0 :         fRight = fBottom = SK_MaxS32;
     151           0 :     }
     152             : 
     153             :     /**
     154             :      *  Make the largest representable rectangle, but inverted (e.g. fLeft will
     155             :      *  be max 32bit and right will be min 32bit).
     156             :      */
     157           0 :     void setLargestInverted() {
     158           0 :         fLeft = fTop = SK_MaxS32;
     159           0 :         fRight = fBottom = SK_MinS32;
     160           0 :     }
     161             : 
     162             :     /**
     163             :      *  Return a new IRect, built as an offset of this rect.
     164             :      */
     165           0 :     SkIRect makeOffset(int32_t dx, int32_t dy) const {
     166           0 :         return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy);
     167             :     }
     168             : 
     169             :     /**
     170             :      *  Return a new IRect, built as an inset of this rect.
     171             :      */
     172             :     SkIRect makeInset(int32_t dx, int32_t dy) const {
     173             :         return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, fBottom - dy);
     174             :     }
     175             : 
     176             :     /**
     177             :      *  Return a new Rect, built as an outset of this rect.
     178             :      */
     179           0 :     SkIRect makeOutset(int32_t dx, int32_t dy) const {
     180           0 :         return MakeLTRB(fLeft - dx, fTop - dy, fRight + dx, fBottom + dy);
     181             :     }
     182             : 
     183             :     /** Offset set the rectangle by adding dx to its left and right,
     184             :         and adding dy to its top and bottom.
     185             :     */
     186         127 :     void offset(int32_t dx, int32_t dy) {
     187         127 :         fLeft   += dx;
     188         127 :         fTop    += dy;
     189         127 :         fRight  += dx;
     190         127 :         fBottom += dy;
     191         127 :     }
     192             : 
     193           0 :     void offset(const SkIPoint& delta) {
     194           0 :         this->offset(delta.fX, delta.fY);
     195           0 :     }
     196             : 
     197             :     /**
     198             :      *  Offset this rect such its new x() and y() will equal newX and newY.
     199             :      */
     200           0 :     void offsetTo(int32_t newX, int32_t newY) {
     201           0 :         fRight += newX - fLeft;
     202           0 :         fBottom += newY - fTop;
     203           0 :         fLeft = newX;
     204           0 :         fTop = newY;
     205           0 :     }
     206             : 
     207             :     /** Inset the rectangle by (dx,dy). If dx is positive, then the sides are moved inwards,
     208             :         making the rectangle narrower. If dx is negative, then the sides are moved outwards,
     209             :         making the rectangle wider. The same holds true for dy and the top and bottom.
     210             :     */
     211          15 :     void inset(int32_t dx, int32_t dy) {
     212          15 :         fLeft   += dx;
     213          15 :         fTop    += dy;
     214          15 :         fRight  -= dx;
     215          15 :         fBottom -= dy;
     216          15 :     }
     217             : 
     218             :    /** Outset the rectangle by (dx,dy). If dx is positive, then the sides are
     219             :        moved outwards, making the rectangle wider. If dx is negative, then the
     220             :        sides are moved inwards, making the rectangle narrower. The same holds
     221             :        true for dy and the top and bottom.
     222             :     */
     223          15 :     void outset(int32_t dx, int32_t dy)  { this->inset(-dx, -dy); }
     224             : 
     225             :     bool quickReject(int l, int t, int r, int b) const {
     226             :         return l >= fRight || fLeft >= r || t >= fBottom || fTop >= b;
     227             :     }
     228             : 
     229             :     /** Returns true if (x,y) is inside the rectangle and the rectangle is not
     230             :         empty. The left and top are considered to be inside, while the right
     231             :         and bottom are not. Thus for the rectangle (0, 0, 5, 10), the
     232             :         points (0,0) and (0,9) are inside, while (-1,0) and (5,9) are not.
     233             :     */
     234       36021 :     bool contains(int32_t x, int32_t y) const {
     235       72042 :         return  (unsigned)(x - fLeft) < (unsigned)(fRight - fLeft) &&
     236       72042 :                 (unsigned)(y - fTop) < (unsigned)(fBottom - fTop);
     237             :     }
     238             : 
     239             :     /** Returns true if the 4 specified sides of a rectangle are inside or equal to this rectangle.
     240             :         If either rectangle is empty, contains() returns false.
     241             :     */
     242         298 :     bool contains(int32_t left, int32_t top, int32_t right, int32_t bottom) const {
     243         596 :         return  left < right && top < bottom && !this->isEmpty() && // check for empties
     244         885 :                 fLeft <= left && fTop <= top &&
     245         876 :                 fRight >= right && fBottom >= bottom;
     246             :     }
     247             : 
     248             :     /** Returns true if the specified rectangle r is inside or equal to this rectangle.
     249             :     */
     250        5754 :     bool contains(const SkIRect& r) const {
     251       17262 :         return  !r.isEmpty() && !this->isEmpty() &&     // check for empties
     252       17059 :                 fLeft <= r.fLeft && fTop <= r.fTop &&
     253       16995 :                 fRight >= r.fRight && fBottom >= r.fBottom;
     254             :     }
     255             : 
     256             :     /** Returns true if the specified rectangle r is inside or equal to this rectangle.
     257             :     */
     258             :     bool contains(const SkRect& r) const;
     259             : 
     260             :     /** Return true if this rectangle contains the specified rectangle.
     261             :         For speed, this method does not check if either this or the specified
     262             :         rectangles are empty, and if either is, its return value is undefined.
     263             :         In the debugging build however, we assert that both this and the
     264             :         specified rectangles are non-empty.
     265             :     */
     266         422 :     bool containsNoEmptyCheck(int32_t left, int32_t top,
     267             :                               int32_t right, int32_t bottom) const {
     268         422 :         SkASSERT(fLeft < fRight && fTop < fBottom);
     269         422 :         SkASSERT(left < right && top < bottom);
     270             : 
     271        1266 :         return fLeft <= left && fTop <= top &&
     272        1171 :                fRight >= right && fBottom >= bottom;
     273             :     }
     274             : 
     275         422 :     bool containsNoEmptyCheck(const SkIRect& r) const {
     276         422 :         return containsNoEmptyCheck(r.fLeft, r.fTop, r.fRight, r.fBottom);
     277             :     }
     278             : 
     279             :     /** If r intersects this rectangle, return true and set this rectangle to that
     280             :         intersection, otherwise return false and do not change this rectangle.
     281             :         If either rectangle is empty, do nothing and return false.
     282             :     */
     283        1332 :     bool intersect(const SkIRect& r) {
     284        1332 :         return this->intersect(r.fLeft, r.fTop, r.fRight, r.fBottom);
     285             :     }
     286             : 
     287             :     /** If rectangles a and b intersect, return true and set this rectangle to
     288             :         that intersection, otherwise return false and do not change this
     289             :         rectangle. If either rectangle is empty, do nothing and return false.
     290             :     */
     291        1089 :     bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& a, const SkIRect& b) {
     292             : 
     293        4356 :         if (!a.isEmpty() && !b.isEmpty() &&
     294        3259 :                 a.fLeft < b.fRight && b.fLeft < a.fRight &&
     295        3244 :                 a.fTop < b.fBottom && b.fTop < a.fBottom) {
     296        1073 :             fLeft   = SkMax32(a.fLeft,   b.fLeft);
     297        1073 :             fTop    = SkMax32(a.fTop,    b.fTop);
     298        1073 :             fRight  = SkMin32(a.fRight,  b.fRight);
     299        1073 :             fBottom = SkMin32(a.fBottom, b.fBottom);
     300        1073 :             return true;
     301             :         }
     302          16 :         return false;
     303             :     }
     304             : 
     305             :     /** If rectangles a and b intersect, return true and set this rectangle to
     306             :         that intersection, otherwise return false and do not change this
     307             :         rectangle. For speed, no check to see if a or b are empty is performed.
     308             :         If either is, then the return result is undefined. In the debug build,
     309             :         we assert that both rectangles are non-empty.
     310             :     */
     311          95 :     bool SK_WARN_UNUSED_RESULT intersectNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
     312          95 :         SkASSERT(!a.isEmpty() && !b.isEmpty());
     313             : 
     314          97 :         if (a.fLeft < b.fRight && b.fLeft < a.fRight &&
     315           4 :                 a.fTop < b.fBottom && b.fTop < a.fBottom) {
     316           2 :             fLeft   = SkMax32(a.fLeft,   b.fLeft);
     317           2 :             fTop    = SkMax32(a.fTop,    b.fTop);
     318           2 :             fRight  = SkMin32(a.fRight,  b.fRight);
     319           2 :             fBottom = SkMin32(a.fBottom, b.fBottom);
     320           2 :             return true;
     321             :         }
     322          93 :         return false;
     323             :     }
     324             : 
     325             :     /** If the rectangle specified by left,top,right,bottom intersects this rectangle,
     326             :         return true and set this rectangle to that intersection,
     327             :         otherwise return false and do not change this rectangle.
     328             :         If either rectangle is empty, do nothing and return false.
     329             :     */
     330        1332 :     bool intersect(int32_t left, int32_t top, int32_t right, int32_t bottom) {
     331        3996 :         if (left < right && top < bottom && !this->isEmpty() &&
     332        3996 :                 fLeft < right && left < fRight && fTop < bottom && top < fBottom) {
     333        1304 :             if (fLeft < left) fLeft = left;
     334        1304 :             if (fTop < top) fTop = top;
     335        1304 :             if (fRight > right) fRight = right;
     336        1304 :             if (fBottom > bottom) fBottom = bottom;
     337        1304 :             return true;
     338             :         }
     339          28 :         return false;
     340             :     }
     341             : 
     342             :     /** Returns true if a and b are not empty, and they intersect
     343             :      */
     344         846 :     static bool Intersects(const SkIRect& a, const SkIRect& b) {
     345        2538 :         return  !a.isEmpty() && !b.isEmpty() &&              // check for empties
     346        2535 :                 a.fLeft < b.fRight && b.fLeft < a.fRight &&
     347        2530 :                 a.fTop < b.fBottom && b.fTop < a.fBottom;
     348             :     }
     349             : 
     350             :     /**
     351             :      *  Returns true if a and b intersect. debug-asserts that neither are empty.
     352             :      */
     353           0 :     static bool IntersectsNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
     354           0 :         SkASSERT(!a.isEmpty());
     355           0 :         SkASSERT(!b.isEmpty());
     356           0 :         return  a.fLeft < b.fRight && b.fLeft < a.fRight &&
     357           0 :                 a.fTop < b.fBottom && b.fTop < a.fBottom;
     358             :     }
     359             : 
     360             :     /** Update this rectangle to enclose itself and the specified rectangle.
     361             :         If this rectangle is empty, just set it to the specified rectangle. If the specified
     362             :         rectangle is empty, do nothing.
     363             :     */
     364             :     void join(int32_t left, int32_t top, int32_t right, int32_t bottom);
     365             : 
     366             :     /** Update this rectangle to enclose itself and the specified rectangle.
     367             :         If this rectangle is empty, just set it to the specified rectangle. If the specified
     368             :         rectangle is empty, do nothing.
     369             :     */
     370        1771 :     void join(const SkIRect& r) {
     371        1771 :         this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
     372        1771 :     }
     373             : 
     374             :     /** Swap top/bottom or left/right if there are flipped.
     375             :         This can be called if the edges are computed separately,
     376             :         and may have crossed over each other.
     377             :         When this returns, left <= right && top <= bottom
     378             :     */
     379             :     void sort();
     380             : 
     381           0 :     static const SkIRect& SK_WARN_UNUSED_RESULT EmptyIRect() {
     382             :         static const SkIRect gEmpty = { 0, 0, 0, 0 };
     383           0 :         return gEmpty;
     384             :     }
     385             : };
     386             : 
     387             : /** \struct SkRect
     388             : */
     389             : struct SK_API SkRect {
     390             :     SkScalar    fLeft, fTop, fRight, fBottom;
     391             : 
     392          22 :     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeEmpty() {
     393          22 :         return SkRect{0, 0, 0, 0};
     394             :     }
     395             : 
     396           0 :     static SkRect SK_WARN_UNUSED_RESULT MakeLargest() {
     397             :         SkRect r;
     398           0 :         r.setLargest();
     399           0 :         return r;
     400             :     }
     401             : 
     402           0 :     static SkRect SK_WARN_UNUSED_RESULT MakeWH(SkScalar w, SkScalar h) {
     403             :         SkRect r;
     404           0 :         r.set(0, 0, w, h);
     405           0 :         return r;
     406             :     }
     407             : 
     408          22 :     static SkRect SK_WARN_UNUSED_RESULT MakeIWH(int w, int h) {
     409             :         SkRect r;
     410          22 :         r.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
     411          22 :         return r;
     412             :     }
     413             : 
     414             :     static SkRect SK_WARN_UNUSED_RESULT MakeSize(const SkSize& size) {
     415             :         SkRect r;
     416             :         r.set(0, 0, size.width(), size.height());
     417             :         return r;
     418             :     }
     419             : 
     420          89 :     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeLTRB(SkScalar l, SkScalar t, SkScalar r,
     421             :                                                            SkScalar b) {
     422          89 :         return SkRect {l, t, r, b};
     423             :     }
     424             : 
     425        1034 :     static SkRect SK_WARN_UNUSED_RESULT MakeXYWH(SkScalar x, SkScalar y, SkScalar w, SkScalar h) {
     426             :         SkRect r;
     427        1034 :         r.set(x, y, x + w, y + h);
     428        1034 :         return r;
     429             :     }
     430             : 
     431             :     SK_ATTR_DEPRECATED("use Make()")
     432             :     static SkRect SK_WARN_UNUSED_RESULT MakeFromIRect(const SkIRect& irect) {
     433             :         SkRect r;
     434             :         r.set(SkIntToScalar(irect.fLeft),
     435             :               SkIntToScalar(irect.fTop),
     436             :               SkIntToScalar(irect.fRight),
     437             :               SkIntToScalar(irect.fBottom));
     438             :         return r;
     439             :     }
     440             : 
     441             :     static SkRect Make(const SkISize& size) {
     442             :         return MakeIWH(size.width(), size.height());
     443             :     }
     444             :     
     445         131 :     static SkRect SK_WARN_UNUSED_RESULT Make(const SkIRect& irect) {
     446             :         SkRect r;
     447         393 :         r.set(SkIntToScalar(irect.fLeft),
     448         131 :               SkIntToScalar(irect.fTop),
     449         131 :               SkIntToScalar(irect.fRight),
     450         262 :               SkIntToScalar(irect.fBottom));
     451         131 :         return r;
     452             :     }
     453             : 
     454             :     /**
     455             :      *  Return true if the rectangle's width or height are <= 0
     456             :      */
     457        7022 :     bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; }
     458             : 
     459           0 :     bool isLargest() const { return SK_ScalarMin == fLeft &&
     460           0 :                                     SK_ScalarMin == fTop &&
     461           0 :                                     SK_ScalarMax == fRight &&
     462           0 :                                     SK_ScalarMax == fBottom; }
     463             : 
     464             :     /**
     465             :      *  Returns true iff all values in the rect are finite. If any are
     466             :      *  infinite or NaN then this returns false.
     467             :      */
     468         151 :     bool isFinite() const {
     469         151 :         float accum = 0;
     470         151 :         accum *= fLeft;
     471         151 :         accum *= fTop;
     472         151 :         accum *= fRight;
     473         151 :         accum *= fBottom;
     474             : 
     475             :         // accum is either NaN or it is finite (zero).
     476         151 :         SkASSERT(0 == accum || SkScalarIsNaN(accum));
     477             : 
     478             :         // value==value will be true iff value is not NaN
     479             :         // TODO: is it faster to say !accum or accum==accum?
     480         151 :         return !SkScalarIsNaN(accum);
     481             :     }
     482             : 
     483         112 :     SkScalar    x() const { return fLeft; }
     484         112 :     SkScalar    y() const { return fTop; }
     485           0 :     SkScalar    left() const { return fLeft; }
     486           0 :     SkScalar    top() const { return fTop; }
     487           0 :     SkScalar    right() const { return fRight; }
     488           0 :     SkScalar    bottom() const { return fBottom; }
     489         527 :     SkScalar    width() const { return fRight - fLeft; }
     490         466 :     SkScalar    height() const { return fBottom - fTop; }
     491           0 :     SkScalar    centerX() const { return SkScalarHalf(fLeft + fRight); }
     492           0 :     SkScalar    centerY() const { return SkScalarHalf(fTop + fBottom); }
     493             : 
     494         539 :     friend bool operator==(const SkRect& a, const SkRect& b) {
     495         539 :         return SkScalarsEqual((SkScalar*)&a, (SkScalar*)&b, 4);
     496             :     }
     497             : 
     498           0 :     friend bool operator!=(const SkRect& a, const SkRect& b) {
     499           0 :         return !SkScalarsEqual((SkScalar*)&a, (SkScalar*)&b, 4);
     500             :     }
     501             : 
     502             :     /** return the 4 points that enclose the rectangle (top-left, top-right, bottom-right,
     503             :         bottom-left). TODO: Consider adding param to control whether quad is CW or CCW.
     504             :      */
     505             :     void toQuad(SkPoint quad[4]) const;
     506             : 
     507             :     /** Set this rectangle to the empty rectangle (0,0,0,0)
     508             :     */
     509           0 :     void setEmpty() { *this = MakeEmpty(); }
     510             : 
     511         496 :     void set(const SkIRect& src) {
     512         496 :         fLeft   = SkIntToScalar(src.fLeft);
     513         496 :         fTop    = SkIntToScalar(src.fTop);
     514         496 :         fRight  = SkIntToScalar(src.fRight);
     515         496 :         fBottom = SkIntToScalar(src.fBottom);
     516         496 :     }
     517             : 
     518        2002 :     void set(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
     519        2002 :         fLeft   = left;
     520        2002 :         fTop    = top;
     521        2002 :         fRight  = right;
     522        2002 :         fBottom = bottom;
     523        2002 :     }
     524             :     // alias for set(l, t, r, b)
     525         361 :     void setLTRB(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
     526         361 :         this->set(left, top, right, bottom);
     527         361 :     }
     528             : 
     529             :     /** Initialize the rect with the 4 specified integers. The routine handles
     530             :         converting them to scalars (by calling SkIntToScalar)
     531             :      */
     532           0 :     void iset(int left, int top, int right, int bottom) {
     533           0 :         fLeft   = SkIntToScalar(left);
     534           0 :         fTop    = SkIntToScalar(top);
     535           0 :         fRight  = SkIntToScalar(right);
     536           0 :         fBottom = SkIntToScalar(bottom);
     537           0 :     }
     538             : 
     539             :     /**
     540             :      *  Set this rectangle to be left/top at 0,0, and have the specified width
     541             :      *  and height (automatically converted to SkScalar).
     542             :      */
     543         280 :     void isetWH(int width, int height) {
     544         280 :         fLeft = fTop = 0;
     545         280 :         fRight = SkIntToScalar(width);
     546         280 :         fBottom = SkIntToScalar(height);
     547         280 :     }
     548             : 
     549             :     /** Set this rectangle to be the bounds of the array of points.
     550             :         If the array is empty (count == 0), then set this rectangle
     551             :         to the empty rectangle (0,0,0,0)
     552             :     */
     553         145 :     void set(const SkPoint pts[], int count) {
     554             :         // set() had been checking for non-finite values, so keep that behavior
     555             :         // for now. Now that we have setBoundsCheck(), we may decide to make
     556             :         // set() be simpler/faster, and not check for those.
     557         145 :         (void)this->setBoundsCheck(pts, count);
     558         145 :     }
     559             : 
     560             :     // alias for set(pts, count)
     561           0 :     void setBounds(const SkPoint pts[], int count) {
     562           0 :         (void)this->setBoundsCheck(pts, count);
     563           0 :     }
     564             : 
     565             :     /**
     566             :      *  Compute the bounds of the array of points, and set this rect to that
     567             :      *  bounds and return true... unless a non-finite value is encountered,
     568             :      *  in which case this rect is set to empty and false is returned.
     569             :      */
     570             :     bool setBoundsCheck(const SkPoint pts[], int count);
     571             : 
     572          13 :     void set(const SkPoint& p0, const SkPoint& p1) {
     573          13 :         fLeft =   SkMinScalar(p0.fX, p1.fX);
     574          13 :         fRight =  SkMaxScalar(p0.fX, p1.fX);
     575          13 :         fTop =    SkMinScalar(p0.fY, p1.fY);
     576          13 :         fBottom = SkMaxScalar(p0.fY, p1.fY);
     577          13 :     }
     578             : 
     579             :     void setXYWH(SkScalar x, SkScalar y, SkScalar width, SkScalar height) {
     580             :         fLeft = x;
     581             :         fTop = y;
     582             :         fRight = x + width;
     583             :         fBottom = y + height;
     584             :     }
     585             : 
     586             :     void setWH(SkScalar width, SkScalar height) {
     587             :         fLeft = 0;
     588             :         fTop = 0;
     589             :         fRight = width;
     590             :         fBottom = height;
     591             :     }
     592             : 
     593             :     /**
     594             :      *  Make the largest representable rectangle
     595             :      */
     596           0 :     void setLargest() {
     597           0 :         fLeft = fTop = SK_ScalarMin;
     598           0 :         fRight = fBottom = SK_ScalarMax;
     599           0 :     }
     600             : 
     601             :     /**
     602             :      *  Make the largest representable rectangle, but inverted (e.g. fLeft will
     603             :      *  be max and right will be min).
     604             :      */
     605           0 :     void setLargestInverted() {
     606           0 :         fLeft = fTop = SK_ScalarMax;
     607           0 :         fRight = fBottom = SK_ScalarMin;
     608           0 :     }
     609             : 
     610             :     /**
     611             :      *  Return a new Rect, built as an offset of this rect.
     612             :      */
     613           0 :     SkRect makeOffset(SkScalar dx, SkScalar dy) const {
     614           0 :         return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy);
     615             :     }
     616             :     
     617             :     /**
     618             :      *  Return a new Rect, built as an inset of this rect.
     619             :      */
     620           0 :     SkRect makeInset(SkScalar dx, SkScalar dy) const {
     621           0 :         return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, fBottom - dy);
     622             :     }
     623             : 
     624             :     /**
     625             :      *  Return a new Rect, built as an outset of this rect.
     626             :      */
     627          89 :     SkRect makeOutset(SkScalar dx, SkScalar dy) const {
     628          89 :         return MakeLTRB(fLeft - dx, fTop - dy, fRight + dx, fBottom + dy);
     629             :     }
     630             : 
     631             :     /** Offset set the rectangle by adding dx to its left and right,
     632             :         and adding dy to its top and bottom.
     633             :     */
     634         213 :     void offset(SkScalar dx, SkScalar dy) {
     635         213 :         fLeft   += dx;
     636         213 :         fTop    += dy;
     637         213 :         fRight  += dx;
     638         213 :         fBottom += dy;
     639         213 :     }
     640             : 
     641             :     void offset(const SkPoint& delta) {
     642             :         this->offset(delta.fX, delta.fY);
     643             :     }
     644             : 
     645             :     /**
     646             :      *  Offset this rect such its new x() and y() will equal newX and newY.
     647             :      */
     648             :     void offsetTo(SkScalar newX, SkScalar newY) {
     649             :         fRight += newX - fLeft;
     650             :         fBottom += newY - fTop;
     651             :         fLeft = newX;
     652             :         fTop = newY;
     653             :     }
     654             : 
     655             :     /** Inset the rectangle by (dx,dy). If dx is positive, then the sides are
     656             :         moved inwards, making the rectangle narrower. If dx is negative, then
     657             :         the sides are moved outwards, making the rectangle wider. The same holds
     658             :          true for dy and the top and bottom.
     659             :     */
     660           0 :     void inset(SkScalar dx, SkScalar dy)  {
     661           0 :         fLeft   += dx;
     662           0 :         fTop    += dy;
     663           0 :         fRight  -= dx;
     664           0 :         fBottom -= dy;
     665           0 :     }
     666             : 
     667             :    /** Outset the rectangle by (dx,dy). If dx is positive, then the sides are
     668             :        moved outwards, making the rectangle wider. If dx is negative, then the
     669             :        sides are moved inwards, making the rectangle narrower. The same holds
     670             :        true for dy and the top and bottom.
     671             :     */
     672           0 :     void outset(SkScalar dx, SkScalar dy)  { this->inset(-dx, -dy); }
     673             : 
     674             :     /** If this rectangle intersects r, return true and set this rectangle to that
     675             :         intersection, otherwise return false and do not change this rectangle.
     676             :         If either rectangle is empty, do nothing and return false.
     677             :     */
     678             :     bool intersect(const SkRect& r);
     679             : 
     680             :     /** If this rectangle intersects the rectangle specified by left, top, right, bottom,
     681             :         return true and set this rectangle to that intersection, otherwise return false
     682             :         and do not change this rectangle.
     683             :         If either rectangle is empty, do nothing and return false.
     684             :     */
     685             :     bool intersect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
     686             : 
     687             :     /**
     688             :      *  If rectangles a and b intersect, return true and set this rectangle to
     689             :      *  that intersection, otherwise return false and do not change this
     690             :      *  rectangle. If either rectangle is empty, do nothing and return false.
     691             :      */
     692             :     bool SK_WARN_UNUSED_RESULT intersect(const SkRect& a, const SkRect& b);
     693             : 
     694             : 
     695             : private:
     696          74 :     static bool Intersects(SkScalar al, SkScalar at, SkScalar ar, SkScalar ab,
     697             :                            SkScalar bl, SkScalar bt, SkScalar br, SkScalar bb) {
     698          74 :         SkScalar L = SkMaxScalar(al, bl);
     699          74 :         SkScalar R = SkMinScalar(ar, br);
     700          74 :         SkScalar T = SkMaxScalar(at, bt);
     701          74 :         SkScalar B = SkMinScalar(ab, bb);
     702          74 :         return L < R && T < B;
     703             :     }
     704             : 
     705             : public:
     706             :     /**
     707             :      *  Return true if this rectangle is not empty, and the specified sides of
     708             :      *  a rectangle are not empty, and they intersect.
     709             :      */
     710             :     bool intersects(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) const {
     711             :         return Intersects(fLeft, fTop, fRight, fBottom, left, top, right, bottom);
     712             :     }
     713             : 
     714          74 :     bool intersects(const SkRect& r) const {
     715          74 :         return Intersects(fLeft, fTop, fRight, fBottom,
     716         148 :                           r.fLeft, r.fTop, r.fRight, r.fBottom);
     717             :     }
     718             : 
     719             :     /**
     720             :      *  Return true if rectangles a and b are not empty and intersect.
     721             :      */
     722           0 :     static bool Intersects(const SkRect& a, const SkRect& b) {
     723           0 :         return Intersects(a.fLeft, a.fTop, a.fRight, a.fBottom,
     724           0 :                           b.fLeft, b.fTop, b.fRight, b.fBottom);
     725             :     }
     726             : 
     727             :     /**
     728             :      *  Update this rectangle to enclose itself and the specified rectangle.
     729             :      *  If this rectangle is empty, just set it to the specified rectangle.
     730             :      *  If the specified rectangle is empty, do nothing.
     731             :      */
     732             :     void join(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
     733             : 
     734             :     /** Update this rectangle to enclose itself and the specified rectangle.
     735             :         If this rectangle is empty, just set it to the specified rectangle. If the specified
     736             :         rectangle is empty, do nothing.
     737             :     */
     738           0 :     void join(const SkRect& r) {
     739           0 :         this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
     740           0 :     }
     741             : 
     742           0 :     void joinNonEmptyArg(const SkRect& r) {
     743           0 :         SkASSERT(!r.isEmpty());
     744             :         // if we are empty, just assign
     745           0 :         if (fLeft >= fRight || fTop >= fBottom) {
     746           0 :             *this = r;
     747             :         } else {
     748           0 :             this->joinPossiblyEmptyRect(r);
     749             :         }
     750           0 :     }
     751             : 
     752             :     /**
     753             :      * Joins the rectangle with another without checking if either are empty (may produce unexpected
     754             :      * results if either rect is inverted).
     755             :      */
     756           0 :     void joinPossiblyEmptyRect(const SkRect& r) {
     757           0 :         fLeft   = SkMinScalar(fLeft, r.left());
     758           0 :         fTop    = SkMinScalar(fTop, r.top());
     759           0 :         fRight  = SkMaxScalar(fRight, r.right());
     760           0 :         fBottom = SkMaxScalar(fBottom, r.bottom());
     761           0 :     }
     762             : 
     763             :     /**
     764             :      *  Grow the rect to include the specified (x,y). After this call, the
     765             :      *  following will be true: fLeft <= x <= fRight && fTop <= y <= fBottom.
     766             :      *
     767             :      *  This is close, but not quite the same contract as contains(), since
     768             :      *  contains() treats the left and top different from the right and bottom.
     769             :      *  contains(x,y) -> fLeft <= x < fRight && fTop <= y < fBottom. Also note
     770             :      *  that contains(x,y) always returns false if the rect is empty.
     771             :      */
     772          15 :     void growToInclude(SkScalar x, SkScalar y) {
     773          15 :         fLeft  = SkMinScalar(x, fLeft);
     774          15 :         fRight = SkMaxScalar(x, fRight);
     775          15 :         fTop    = SkMinScalar(y, fTop);
     776          15 :         fBottom = SkMaxScalar(y, fBottom);
     777          15 :     }
     778             : 
     779             :     /** Bulk version of growToInclude */
     780           0 :     void growToInclude(const SkPoint pts[], int count) {
     781           0 :         this->growToInclude(pts, sizeof(SkPoint), count);
     782           0 :     }
     783             : 
     784             :     /** Bulk version of growToInclude with stride. */
     785           0 :     void growToInclude(const SkPoint pts[], size_t stride, int count) {
     786           0 :         SkASSERT(count >= 0);
     787           0 :         SkASSERT(stride >= sizeof(SkPoint));
     788           0 :         const SkPoint* end = (const SkPoint*)((intptr_t)pts + count * stride);
     789           0 :         for (; pts < end; pts = (const SkPoint*)((intptr_t)pts + stride)) {
     790           0 :             this->growToInclude(pts->fX, pts->fY);
     791             :         }
     792           0 :     }
     793             : 
     794             :     /**
     795             :      *  Return true if this rectangle contains r, and if both rectangles are
     796             :      *  not empty.
     797             :      */
     798         280 :     bool contains(const SkRect& r) const {
     799             :         // todo: can we eliminate the this->isEmpty check?
     800         840 :         return  !r.isEmpty() && !this->isEmpty() &&
     801         814 :                 fLeft <= r.fLeft && fTop <= r.fTop &&
     802         795 :                 fRight >= r.fRight && fBottom >= r.fBottom;
     803             :     }
     804             : 
     805             :     /**
     806             :      * Returns true if the specified rectangle r is inside or equal to this rectangle.
     807             :      */
     808           0 :     bool contains(const SkIRect& r) const {
     809             :         // todo: can we eliminate the this->isEmpty check?
     810           0 :         return  !r.isEmpty() && !this->isEmpty() &&
     811           0 :                 fLeft <= SkIntToScalar(r.fLeft) && fTop <= SkIntToScalar(r.fTop) &&
     812           0 :                 fRight >= SkIntToScalar(r.fRight) && fBottom >= SkIntToScalar(r.fBottom);
     813             :     }
     814             : 
     815             :     /**
     816             :      *  Set the dst rectangle by rounding this rectangle's coordinates to their
     817             :      *  nearest integer values using SkScalarRoundToInt.
     818             :      */
     819         582 :     void round(SkIRect* dst) const {
     820         582 :         SkASSERT(dst);
     821        1164 :         dst->set(SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
     822        1746 :                  SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom));
     823         582 :     }
     824             : 
     825             :     /**
     826             :      *  Set the dst rectangle by rounding "out" this rectangle, choosing the
     827             :      *  SkScalarFloor of top and left, and the SkScalarCeil of right and bottom.
     828             :      */
     829        1640 :     void roundOut(SkIRect* dst) const {
     830        1640 :         SkASSERT(dst);
     831        3280 :         dst->set(SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
     832        4920 :                  SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom));
     833        1640 :     }
     834             : 
     835             :     /**
     836             :      *  Set the dst rectangle by rounding "out" this rectangle, choosing the
     837             :      *  SkScalarFloorToScalar of top and left, and the SkScalarCeilToScalar of right and bottom.
     838             :      *
     839             :      *  It is safe for this == dst
     840             :      */
     841           0 :     void roundOut(SkRect* dst) const {
     842           0 :         dst->set(SkScalarFloorToScalar(fLeft),
     843           0 :                  SkScalarFloorToScalar(fTop),
     844           0 :                  SkScalarCeilToScalar(fRight),
     845           0 :                  SkScalarCeilToScalar(fBottom));
     846           0 :     }
     847             : 
     848             :     /**
     849             :      *  Set the dst rectangle by rounding "in" this rectangle, choosing the
     850             :      *  ceil of top and left, and the floor of right and bottom. This does *not*
     851             :      *  call sort(), so it is possible that the resulting rect is inverted...
     852             :      *  e.g. left >= right or top >= bottom. Call isEmpty() to detect that.
     853             :      */
     854           0 :     void roundIn(SkIRect* dst) const {
     855           0 :         SkASSERT(dst);
     856           0 :         dst->set(SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
     857           0 :                  SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom));
     858           0 :     }
     859             : 
     860             :     //! Returns the result of calling round(&dst)
     861           3 :     SkIRect round() const {
     862             :         SkIRect ir;
     863           3 :         this->round(&ir);
     864           3 :         return ir;
     865             :     }
     866             :     
     867             :     //! Returns the result of calling roundOut(&dst)
     868        1261 :     SkIRect roundOut() const {
     869             :         SkIRect ir;
     870        1261 :         this->roundOut(&ir);
     871        1261 :         return ir;
     872             :     }
     873             :     
     874             :     /**
     875             :      *  Swap top/bottom or left/right if there are flipped (i.e. if width()
     876             :      *  or height() would have returned a negative value.) This should be called
     877             :      *  if the edges are computed separately, and may have crossed over each
     878             :      *  other. When this returns, left <= right && top <= bottom
     879             :      */
     880         508 :     void sort() {
     881         508 :         if (fLeft > fRight) {
     882           0 :             SkTSwap<SkScalar>(fLeft, fRight);
     883             :         }
     884             : 
     885         508 :         if (fTop > fBottom) {
     886           0 :             SkTSwap<SkScalar>(fTop, fBottom);
     887             :         }
     888         508 :     }
     889             : 
     890             :     /**
     891             :      *  cast-safe way to treat the rect as an array of (4) SkScalars.
     892             :      */
     893           0 :     const SkScalar* asScalars() const { return &fLeft; }
     894             : 
     895             :     void dump(bool asHex) const;
     896           0 :     void dump() const { this->dump(false); }
     897             :     void dumpHex() const { this->dump(true); }
     898             : };
     899             : 
     900           0 : inline bool SkIRect::contains(const SkRect& r) const {
     901           0 :     return  !r.isEmpty() && !this->isEmpty() &&     // check for empties
     902           0 :             (SkScalar)fLeft <= r.fLeft && (SkScalar)fTop <= r.fTop &&
     903           0 :             (SkScalar)fRight >= r.fRight && (SkScalar)fBottom >= r.fBottom;
     904             : }
     905             : 
     906             : #endif

Generated by: LCOV version 1.13