gfx/skia/trunk/include/core/SkRect.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     2 /*
     3  * Copyright 2006 The Android Open Source Project
     4  *
     5  * Use of this source code is governed by a BSD-style license that can be
     6  * found in the LICENSE file.
     7  */
    10 #ifndef SkRect_DEFINED
    11 #define SkRect_DEFINED
    13 #include "SkPoint.h"
    14 #include "SkSize.h"
    16 /** \struct SkIRect
    18     SkIRect holds four 32 bit integer coordinates for a rectangle
    19 */
    20 struct SK_API SkIRect {
    21     int32_t fLeft, fTop, fRight, fBottom;
    23     static SkIRect SK_WARN_UNUSED_RESULT MakeEmpty() {
    24         SkIRect r;
    25         r.setEmpty();
    26         return r;
    27     }
    29     static SkIRect SK_WARN_UNUSED_RESULT MakeLargest() {
    30         SkIRect r;
    31         r.setLargest();
    32         return r;
    33     }
    35     static SkIRect SK_WARN_UNUSED_RESULT MakeWH(int32_t w, int32_t h) {
    36         SkIRect r;
    37         r.set(0, 0, w, h);
    38         return r;
    39     }
    41     static SkIRect SK_WARN_UNUSED_RESULT MakeSize(const SkISize& size) {
    42         SkIRect r;
    43         r.set(0, 0, size.width(), size.height());
    44         return r;
    45     }
    47     static SkIRect SK_WARN_UNUSED_RESULT MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b) {
    48         SkIRect rect;
    49         rect.set(l, t, r, b);
    50         return rect;
    51     }
    53     static SkIRect SK_WARN_UNUSED_RESULT MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h) {
    54         SkIRect r;
    55         r.set(x, y, x + w, y + h);
    56         return r;
    57     }
    59     int left() const { return fLeft; }
    60     int top() const { return fTop; }
    61     int right() const { return fRight; }
    62     int bottom() const { return fBottom; }
    64     /** return the left edge of the rect */
    65     int x() const { return fLeft; }
    66     /** return the top edge of the rect */
    67     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     int width() const { return fRight - fLeft; }
    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     int height() const { return fBottom - fTop; }
    80     /**
    81      *  Since the center of an integer rect may fall on a factional value, this
    82      *  method is defined to return (right + left) >> 1.
    83      *
    84      *  This is a specific "truncation" of the average, which is different than
    85      *  (right + left) / 2 when the sum is negative.
    86      */
    87     int centerX() const { return (fRight + fLeft) >> 1; }
    89     /**
    90      *  Since the center of an integer rect may fall on a factional value, this
    91      *  method is defined to return (bottom + top) >> 1
    92      *
    93      *  This is a specific "truncation" of the average, which is different than
    94      *  (bottom + top) / 2 when the sum is negative.
    95      */
    96     int centerY() const { return (fBottom + fTop) >> 1; }
    98     /**
    99      *  Return true if the rectangle's width or height are <= 0
   100      */
   101     bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; }
   103     bool isLargest() const { return SK_MinS32 == fLeft &&
   104                                     SK_MinS32 == fTop &&
   105                                     SK_MaxS32 == fRight &&
   106                                     SK_MaxS32 == fBottom; }
   108     friend bool operator==(const SkIRect& a, const SkIRect& b) {
   109         return !memcmp(&a, &b, sizeof(a));
   110     }
   112     friend bool operator!=(const SkIRect& a, const SkIRect& b) {
   113         return !(a == b);
   114     }
   116     bool is16Bit() const {
   117         return  SkIsS16(fLeft) && SkIsS16(fTop) &&
   118                 SkIsS16(fRight) && SkIsS16(fBottom);
   119     }
   121     /** Set the rectangle to (0,0,0,0)
   122     */
   123     void setEmpty() { memset(this, 0, sizeof(*this)); }
   125     void set(int32_t left, int32_t top, int32_t right, int32_t bottom) {
   126         fLeft   = left;
   127         fTop    = top;
   128         fRight  = right;
   129         fBottom = bottom;
   130     }
   131     // alias for set(l, t, r, b)
   132     void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom) {
   133         this->set(left, top, right, bottom);
   134     }
   136     void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height) {
   137         fLeft = x;
   138         fTop = y;
   139         fRight = x + width;
   140         fBottom = y + height;
   141     }
   143     /**
   144      *  Make the largest representable rectangle
   145      */
   146     void setLargest() {
   147         fLeft = fTop = SK_MinS32;
   148         fRight = fBottom = SK_MaxS32;
   149     }
   151     /**
   152      *  Make the largest representable rectangle, but inverted (e.g. fLeft will
   153      *  be max 32bit and right will be min 32bit).
   154      */
   155     void setLargestInverted() {
   156         fLeft = fTop = SK_MaxS32;
   157         fRight = fBottom = SK_MinS32;
   158     }
   160     /** Offset set the rectangle by adding dx to its left and right,
   161         and adding dy to its top and bottom.
   162     */
   163     void offset(int32_t dx, int32_t dy) {
   164         fLeft   += dx;
   165         fTop    += dy;
   166         fRight  += dx;
   167         fBottom += dy;
   168     }
   170     void offset(const SkIPoint& delta) {
   171         this->offset(delta.fX, delta.fY);
   172     }
   174     /**
   175      *  Offset this rect such its new x() and y() will equal newX and newY.
   176      */
   177     void offsetTo(int32_t newX, int32_t newY) {
   178         fRight += newX - fLeft;
   179         fBottom += newY - fTop;
   180         fLeft = newX;
   181         fTop = newY;
   182     }
   184     /** Inset the rectangle by (dx,dy). If dx is positive, then the sides are moved inwards,
   185         making the rectangle narrower. If dx is negative, then the sides are moved outwards,
   186         making the rectangle wider. The same holds true for dy and the top and bottom.
   187     */
   188     void inset(int32_t dx, int32_t dy) {
   189         fLeft   += dx;
   190         fTop    += dy;
   191         fRight  -= dx;
   192         fBottom -= dy;
   193     }
   195    /** Outset the rectangle by (dx,dy). If dx is positive, then the sides are
   196        moved outwards, making the rectangle wider. If dx is negative, then the
   197        sides are moved inwards, making the rectangle narrower. The same holds
   198        true for dy and the top and bottom.
   199     */
   200     void outset(int32_t dx, int32_t dy)  { this->inset(-dx, -dy); }
   202     bool quickReject(int l, int t, int r, int b) const {
   203         return l >= fRight || fLeft >= r || t >= fBottom || fTop >= b;
   204     }
   206     /** Returns true if (x,y) is inside the rectangle and the rectangle is not
   207         empty. The left and top are considered to be inside, while the right
   208         and bottom are not. Thus for the rectangle (0, 0, 5, 10), the
   209         points (0,0) and (0,9) are inside, while (-1,0) and (5,9) are not.
   210     */
   211     bool contains(int32_t x, int32_t y) const {
   212         return  (unsigned)(x - fLeft) < (unsigned)(fRight - fLeft) &&
   213                 (unsigned)(y - fTop) < (unsigned)(fBottom - fTop);
   214     }
   216     /** Returns true if the 4 specified sides of a rectangle are inside or equal to this rectangle.
   217         If either rectangle is empty, contains() returns false.
   218     */
   219     bool contains(int32_t left, int32_t top, int32_t right, int32_t bottom) const {
   220         return  left < right && top < bottom && !this->isEmpty() && // check for empties
   221                 fLeft <= left && fTop <= top &&
   222                 fRight >= right && fBottom >= bottom;
   223     }
   225     /** Returns true if the specified rectangle r is inside or equal to this rectangle.
   226     */
   227     bool contains(const SkIRect& r) const {
   228         return  !r.isEmpty() && !this->isEmpty() &&     // check for empties
   229                 fLeft <= r.fLeft && fTop <= r.fTop &&
   230                 fRight >= r.fRight && fBottom >= r.fBottom;
   231     }
   233     /** Return true if this rectangle contains the specified rectangle.
   234         For speed, this method does not check if either this or the specified
   235         rectangles are empty, and if either is, its return value is undefined.
   236         In the debugging build however, we assert that both this and the
   237         specified rectangles are non-empty.
   238     */
   239     bool containsNoEmptyCheck(int32_t left, int32_t top,
   240                               int32_t right, int32_t bottom) const {
   241         SkASSERT(fLeft < fRight && fTop < fBottom);
   242         SkASSERT(left < right && top < bottom);
   244         return fLeft <= left && fTop <= top &&
   245                fRight >= right && fBottom >= bottom;
   246     }
   248     bool containsNoEmptyCheck(const SkIRect& r) const {
   249         return containsNoEmptyCheck(r.fLeft, r.fTop, r.fRight, r.fBottom);
   250     }
   252     /** If r intersects this rectangle, return true and set this rectangle to that
   253         intersection, otherwise return false and do not change this rectangle.
   254         If either rectangle is empty, do nothing and return false.
   255     */
   256     bool intersect(const SkIRect& r) {
   257         SkASSERT(&r);
   258         return this->intersect(r.fLeft, r.fTop, r.fRight, r.fBottom);
   259     }
   261     /** If rectangles a and b intersect, return true and set this rectangle to
   262         that intersection, otherwise return false and do not change this
   263         rectangle. If either rectangle is empty, do nothing and return false.
   264     */
   265     bool intersect(const SkIRect& a, const SkIRect& b) {
   266         SkASSERT(&a && &b);
   268         if (!a.isEmpty() && !b.isEmpty() &&
   269                 a.fLeft < b.fRight && b.fLeft < a.fRight &&
   270                 a.fTop < b.fBottom && b.fTop < a.fBottom) {
   271             fLeft   = SkMax32(a.fLeft,   b.fLeft);
   272             fTop    = SkMax32(a.fTop,    b.fTop);
   273             fRight  = SkMin32(a.fRight,  b.fRight);
   274             fBottom = SkMin32(a.fBottom, b.fBottom);
   275             return true;
   276         }
   277         return false;
   278     }
   280     /** If rectangles a and b intersect, return true and set this rectangle to
   281         that intersection, otherwise return false and do not change this
   282         rectangle. For speed, no check to see if a or b are empty is performed.
   283         If either is, then the return result is undefined. In the debug build,
   284         we assert that both rectangles are non-empty.
   285     */
   286     bool intersectNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
   287         SkASSERT(&a && &b);
   288         SkASSERT(!a.isEmpty() && !b.isEmpty());
   290         if (a.fLeft < b.fRight && b.fLeft < a.fRight &&
   291                 a.fTop < b.fBottom && b.fTop < a.fBottom) {
   292             fLeft   = SkMax32(a.fLeft,   b.fLeft);
   293             fTop    = SkMax32(a.fTop,    b.fTop);
   294             fRight  = SkMin32(a.fRight,  b.fRight);
   295             fBottom = SkMin32(a.fBottom, b.fBottom);
   296             return true;
   297         }
   298         return false;
   299     }
   301     /** If the rectangle specified by left,top,right,bottom intersects this rectangle,
   302         return true and set this rectangle to that intersection,
   303         otherwise return false and do not change this rectangle.
   304         If either rectangle is empty, do nothing and return false.
   305     */
   306     bool intersect(int32_t left, int32_t top, int32_t right, int32_t bottom) {
   307         if (left < right && top < bottom && !this->isEmpty() &&
   308                 fLeft < right && left < fRight && fTop < bottom && top < fBottom) {
   309             if (fLeft < left) fLeft = left;
   310             if (fTop < top) fTop = top;
   311             if (fRight > right) fRight = right;
   312             if (fBottom > bottom) fBottom = bottom;
   313             return true;
   314         }
   315         return false;
   316     }
   318     /** Returns true if a and b are not empty, and they intersect
   319      */
   320     static bool Intersects(const SkIRect& a, const SkIRect& b) {
   321         return  !a.isEmpty() && !b.isEmpty() &&              // check for empties
   322         a.fLeft < b.fRight && b.fLeft < a.fRight &&
   323         a.fTop < b.fBottom && b.fTop < a.fBottom;
   324     }
   326     /**
   327      *  Returns true if a and b intersect. debug-asserts that neither are empty.
   328      */
   329     static bool IntersectsNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
   330         SkASSERT(!a.isEmpty());
   331         SkASSERT(!b.isEmpty());
   332         return  a.fLeft < b.fRight && b.fLeft < a.fRight &&
   333                 a.fTop < b.fBottom && b.fTop < a.fBottom;
   334     }
   336     /** Update this rectangle to enclose itself and the specified rectangle.
   337         If this rectangle is empty, just set it to the specified rectangle. If the specified
   338         rectangle is empty, do nothing.
   339     */
   340     void join(int32_t left, int32_t top, int32_t right, int32_t bottom);
   342     /** Update this rectangle to enclose itself and the specified rectangle.
   343         If this rectangle is empty, just set it to the specified rectangle. If the specified
   344         rectangle is empty, do nothing.
   345     */
   346     void join(const SkIRect& r) {
   347         this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
   348     }
   350     /** Swap top/bottom or left/right if there are flipped.
   351         This can be called if the edges are computed separately,
   352         and may have crossed over each other.
   353         When this returns, left <= right && top <= bottom
   354     */
   355     void sort();
   357     static const SkIRect& SK_WARN_UNUSED_RESULT EmptyIRect() {
   358         static const SkIRect gEmpty = { 0, 0, 0, 0 };
   359         return gEmpty;
   360     }
   361 };
   363 /** \struct SkRect
   364 */
   365 struct SK_API SkRect {
   366     SkScalar    fLeft, fTop, fRight, fBottom;
   368     static SkRect SK_WARN_UNUSED_RESULT MakeEmpty() {
   369         SkRect r;
   370         r.setEmpty();
   371         return r;
   372     }
   374     static SkRect SK_WARN_UNUSED_RESULT MakeLargest() {
   375         SkRect r;
   376         r.setLargest();
   377         return r;
   378     }
   380     static SkRect SK_WARN_UNUSED_RESULT MakeWH(SkScalar w, SkScalar h) {
   381         SkRect r;
   382         r.set(0, 0, w, h);
   383         return r;
   384     }
   386     static SkRect SK_WARN_UNUSED_RESULT MakeSize(const SkSize& size) {
   387         SkRect r;
   388         r.set(0, 0, size.width(), size.height());
   389         return r;
   390     }
   392     static SkRect SK_WARN_UNUSED_RESULT MakeLTRB(SkScalar l, SkScalar t, SkScalar r, SkScalar b) {
   393         SkRect rect;
   394         rect.set(l, t, r, b);
   395         return rect;
   396     }
   398     static SkRect SK_WARN_UNUSED_RESULT MakeXYWH(SkScalar x, SkScalar y, SkScalar w, SkScalar h) {
   399         SkRect r;
   400         r.set(x, y, x + w, y + h);
   401         return r;
   402     }
   404     SK_ATTR_DEPRECATED("use Make()")
   405     static SkRect SK_WARN_UNUSED_RESULT MakeFromIRect(const SkIRect& irect) {
   406         SkRect r;
   407         r.set(SkIntToScalar(irect.fLeft),
   408               SkIntToScalar(irect.fTop),
   409               SkIntToScalar(irect.fRight),
   410               SkIntToScalar(irect.fBottom));
   411         return r;
   412     }
   414     static SkRect SK_WARN_UNUSED_RESULT Make(const SkIRect& irect) {
   415         SkRect r;
   416         r.set(SkIntToScalar(irect.fLeft),
   417               SkIntToScalar(irect.fTop),
   418               SkIntToScalar(irect.fRight),
   419               SkIntToScalar(irect.fBottom));
   420         return r;
   421     }
   423     /**
   424      *  Return true if the rectangle's width or height are <= 0
   425      */
   426     bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; }
   428     bool isLargest() const { return SK_ScalarMin == fLeft &&
   429                                     SK_ScalarMin == fTop &&
   430                                     SK_ScalarMax == fRight &&
   431                                     SK_ScalarMax == fBottom; }
   433     /**
   434      *  Returns true iff all values in the rect are finite. If any are
   435      *  infinite or NaN (or SK_FixedNaN when SkScalar is fixed) then this
   436      *  returns false.
   437      */
   438     bool isFinite() const {
   439         float accum = 0;
   440         accum *= fLeft;
   441         accum *= fTop;
   442         accum *= fRight;
   443         accum *= fBottom;
   445         // accum is either NaN or it is finite (zero).
   446         SkASSERT(0 == accum || !(accum == accum));
   448         // value==value will be true iff value is not NaN
   449         // TODO: is it faster to say !accum or accum==accum?
   450         return accum == accum;
   451     }
   453     SkScalar    x() const { return fLeft; }
   454     SkScalar    y() const { return fTop; }
   455     SkScalar    left() const { return fLeft; }
   456     SkScalar    top() const { return fTop; }
   457     SkScalar    right() const { return fRight; }
   458     SkScalar    bottom() const { return fBottom; }
   459     SkScalar    width() const { return fRight - fLeft; }
   460     SkScalar    height() const { return fBottom - fTop; }
   461     SkScalar    centerX() const { return SkScalarHalf(fLeft + fRight); }
   462     SkScalar    centerY() const { return SkScalarHalf(fTop + fBottom); }
   464     friend bool operator==(const SkRect& a, const SkRect& b) {
   465         return SkScalarsEqual((SkScalar*)&a, (SkScalar*)&b, 4);
   466     }
   468     friend bool operator!=(const SkRect& a, const SkRect& b) {
   469         return !SkScalarsEqual((SkScalar*)&a, (SkScalar*)&b, 4);
   470     }
   472     /** return the 4 points that enclose the rectangle (top-left, top-right, bottom-right,
   473         bottom-left). TODO: Consider adding param to control whether quad is CW or CCW.
   474      */
   475     void toQuad(SkPoint quad[4]) const;
   477     /** Set this rectangle to the empty rectangle (0,0,0,0)
   478     */
   479     void setEmpty() { memset(this, 0, sizeof(*this)); }
   481     void set(const SkIRect& src) {
   482         fLeft   = SkIntToScalar(src.fLeft);
   483         fTop    = SkIntToScalar(src.fTop);
   484         fRight  = SkIntToScalar(src.fRight);
   485         fBottom = SkIntToScalar(src.fBottom);
   486     }
   488     void set(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
   489         fLeft   = left;
   490         fTop    = top;
   491         fRight  = right;
   492         fBottom = bottom;
   493     }
   494     // alias for set(l, t, r, b)
   495     void setLTRB(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
   496         this->set(left, top, right, bottom);
   497     }
   499     /** Initialize the rect with the 4 specified integers. The routine handles
   500         converting them to scalars (by calling SkIntToScalar)
   501      */
   502     void iset(int left, int top, int right, int bottom) {
   503         fLeft   = SkIntToScalar(left);
   504         fTop    = SkIntToScalar(top);
   505         fRight  = SkIntToScalar(right);
   506         fBottom = SkIntToScalar(bottom);
   507     }
   509     /**
   510      *  Set this rectangle to be left/top at 0,0, and have the specified width
   511      *  and height (automatically converted to SkScalar).
   512      */
   513     void isetWH(int width, int height) {
   514         fLeft = fTop = 0;
   515         fRight = SkIntToScalar(width);
   516         fBottom = SkIntToScalar(height);
   517     }
   519     /** Set this rectangle to be the bounds of the array of points.
   520         If the array is empty (count == 0), then set this rectangle
   521         to the empty rectangle (0,0,0,0)
   522     */
   523     void set(const SkPoint pts[], int count) {
   524         // set() had been checking for non-finite values, so keep that behavior
   525         // for now. Now that we have setBoundsCheck(), we may decide to make
   526         // set() be simpler/faster, and not check for those.
   527         (void)this->setBoundsCheck(pts, count);
   528     }
   530     // alias for set(pts, count)
   531     void setBounds(const SkPoint pts[], int count) {
   532         (void)this->setBoundsCheck(pts, count);
   533     }
   535     /**
   536      *  Compute the bounds of the array of points, and set this rect to that
   537      *  bounds and return true... unless a non-finite value is encountered,
   538      *  in which case this rect is set to empty and false is returned.
   539      */
   540     bool setBoundsCheck(const SkPoint pts[], int count);
   542     void set(const SkPoint& p0, const SkPoint& p1) {
   543         fLeft =   SkMinScalar(p0.fX, p1.fX);
   544         fRight =  SkMaxScalar(p0.fX, p1.fX);
   545         fTop =    SkMinScalar(p0.fY, p1.fY);
   546         fBottom = SkMaxScalar(p0.fY, p1.fY);
   547     }
   549     void setXYWH(SkScalar x, SkScalar y, SkScalar width, SkScalar height) {
   550         fLeft = x;
   551         fTop = y;
   552         fRight = x + width;
   553         fBottom = y + height;
   554     }
   556     void setWH(SkScalar width, SkScalar height) {
   557         fLeft = 0;
   558         fTop = 0;
   559         fRight = width;
   560         fBottom = height;
   561     }
   563     /**
   564      *  Make the largest representable rectangle
   565      */
   566     void setLargest() {
   567         fLeft = fTop = SK_ScalarMin;
   568         fRight = fBottom = SK_ScalarMax;
   569     }
   571     /**
   572      *  Make the largest representable rectangle, but inverted (e.g. fLeft will
   573      *  be max and right will be min).
   574      */
   575     void setLargestInverted() {
   576         fLeft = fTop = SK_ScalarMax;
   577         fRight = fBottom = SK_ScalarMin;
   578     }
   580     /** Offset set the rectangle by adding dx to its left and right,
   581         and adding dy to its top and bottom.
   582     */
   583     void offset(SkScalar dx, SkScalar dy) {
   584         fLeft   += dx;
   585         fTop    += dy;
   586         fRight  += dx;
   587         fBottom += dy;
   588     }
   590     void offset(const SkPoint& delta) {
   591         this->offset(delta.fX, delta.fY);
   592     }
   594     /**
   595      *  Offset this rect such its new x() and y() will equal newX and newY.
   596      */
   597     void offsetTo(SkScalar newX, SkScalar newY) {
   598         fRight += newX - fLeft;
   599         fBottom += newY - fTop;
   600         fLeft = newX;
   601         fTop = newY;
   602     }
   604     /** Inset the rectangle by (dx,dy). If dx is positive, then the sides are
   605         moved inwards, making the rectangle narrower. If dx is negative, then
   606         the sides are moved outwards, making the rectangle wider. The same holds
   607          true for dy and the top and bottom.
   608     */
   609     void inset(SkScalar dx, SkScalar dy)  {
   610         fLeft   += dx;
   611         fTop    += dy;
   612         fRight  -= dx;
   613         fBottom -= dy;
   614     }
   616    /** Outset the rectangle by (dx,dy). If dx is positive, then the sides are
   617        moved outwards, making the rectangle wider. If dx is negative, then the
   618        sides are moved inwards, making the rectangle narrower. The same holds
   619        true for dy and the top and bottom.
   620     */
   621     void outset(SkScalar dx, SkScalar dy)  { this->inset(-dx, -dy); }
   623     /** If this rectangle intersects r, return true and set this rectangle to that
   624         intersection, otherwise return false and do not change this rectangle.
   625         If either rectangle is empty, do nothing and return false.
   626     */
   627     bool intersect(const SkRect& r);
   628     bool intersect2(const SkRect& r);
   630     /** If this rectangle intersects the rectangle specified by left, top, right, bottom,
   631         return true and set this rectangle to that intersection, otherwise return false
   632         and do not change this rectangle.
   633         If either rectangle is empty, do nothing and return false.
   634     */
   635     bool intersect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
   637     /**
   638      *  Return true if this rectangle is not empty, and the specified sides of
   639      *  a rectangle are not empty, and they intersect.
   640      */
   641     bool intersects(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) const {
   642         return // first check that both are not empty
   643                left < right && top < bottom &&
   644                fLeft < fRight && fTop < fBottom &&
   645                // now check for intersection
   646                fLeft < right && left < fRight &&
   647                fTop < bottom && top < fBottom;
   648     }
   650     /** If rectangles a and b intersect, return true and set this rectangle to
   651      *  that intersection, otherwise return false and do not change this
   652      *  rectangle. If either rectangle is empty, do nothing and return false.
   653      */
   654     bool intersect(const SkRect& a, const SkRect& b);
   656     /**
   657      *  Return true if rectangles a and b are not empty and intersect.
   658      */
   659     static bool Intersects(const SkRect& a, const SkRect& b) {
   660         return  !a.isEmpty() && !b.isEmpty() &&
   661                 a.fLeft < b.fRight && b.fLeft < a.fRight &&
   662                 a.fTop < b.fBottom && b.fTop < a.fBottom;
   663     }
   665     /**
   666      *  Update this rectangle to enclose itself and the specified rectangle.
   667      *  If this rectangle is empty, just set it to the specified rectangle.
   668      *  If the specified rectangle is empty, do nothing.
   669      */
   670     void join(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
   672     /** Update this rectangle to enclose itself and the specified rectangle.
   673         If this rectangle is empty, just set it to the specified rectangle. If the specified
   674         rectangle is empty, do nothing.
   675     */
   676     void join(const SkRect& r) {
   677         this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
   678     }
   679     // alias for join()
   680     void growToInclude(const SkRect& r) { this->join(r); }
   682     /**
   683      *  Grow the rect to include the specified (x,y). After this call, the
   684      *  following will be true: fLeft <= x <= fRight && fTop <= y <= fBottom.
   685      *
   686      *  This is close, but not quite the same contract as contains(), since
   687      *  contains() treats the left and top different from the right and bottom.
   688      *  contains(x,y) -> fLeft <= x < fRight && fTop <= y < fBottom. Also note
   689      *  that contains(x,y) always returns false if the rect is empty.
   690      */
   691     void growToInclude(SkScalar x, SkScalar y) {
   692         fLeft  = SkMinScalar(x, fLeft);
   693         fRight = SkMaxScalar(x, fRight);
   694         fTop    = SkMinScalar(y, fTop);
   695         fBottom = SkMaxScalar(y, fBottom);
   696     }
   698     /** Bulk version of growToInclude */
   699     void growToInclude(const SkPoint pts[], int count) {
   700         this->growToInclude(pts, sizeof(SkPoint), count);
   701     }
   703     /** Bulk version of growToInclude with stride. */
   704     void growToInclude(const SkPoint pts[], size_t stride, int count) {
   705         SkASSERT(count >= 0);
   706         SkASSERT(stride >= sizeof(SkPoint));
   707         const SkPoint* end = (const SkPoint*)((intptr_t)pts + count * stride);
   708         for (; pts < end; pts = (const SkPoint*)((intptr_t)pts + stride)) {
   709             this->growToInclude(pts->fX, pts->fY);
   710         }
   711     }
   713     /**
   714      *  Return true if this rectangle contains r, and if both rectangles are
   715      *  not empty.
   716      */
   717     bool contains(const SkRect& r) const {
   718         // todo: can we eliminate the this->isEmpty check?
   719         return  !r.isEmpty() && !this->isEmpty() &&
   720                 fLeft <= r.fLeft && fTop <= r.fTop &&
   721                 fRight >= r.fRight && fBottom >= r.fBottom;
   722     }
   724     /**
   725      *  Set the dst rectangle by rounding this rectangle's coordinates to their
   726      *  nearest integer values using SkScalarRoundToInt.
   727      */
   728     void round(SkIRect* dst) const {
   729         SkASSERT(dst);
   730         dst->set(SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
   731                  SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom));
   732     }
   734     /**
   735      *  Set the dst rectangle by rounding "out" this rectangle, choosing the
   736      *  SkScalarFloor of top and left, and the SkScalarCeil of right and bottom.
   737      */
   738     void roundOut(SkIRect* dst) const {
   739         SkASSERT(dst);
   740         dst->set(SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
   741                  SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom));
   742     }
   744     /**
   745      *  Expand this rectangle by rounding its coordinates "out", choosing the
   746      *  floor of top and left, and the ceil of right and bottom. If this rect
   747      *  is already on integer coordinates, then it will be unchanged.
   748      */
   749     void roundOut() {
   750         this->set(SkScalarFloorToScalar(fLeft),
   751                   SkScalarFloorToScalar(fTop),
   752                   SkScalarCeilToScalar(fRight),
   753                   SkScalarCeilToScalar(fBottom));
   754     }
   756     /**
   757      *  Set the dst rectangle by rounding "in" this rectangle, choosing the
   758      *  ceil of top and left, and the floor of right and bottom. This does *not*
   759      *  call sort(), so it is possible that the resulting rect is inverted...
   760      *  e.g. left >= right or top >= bottom. Call isEmpty() to detect that.
   761      */
   762     void roundIn(SkIRect* dst) const {
   763         SkASSERT(dst);
   764         dst->set(SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
   765                  SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom));
   766     }
   768     /**
   769      *  Return a new SkIRect which is contains the rounded coordinates of this
   770      *  rect using SkScalarRoundToInt.
   771      */
   772     SkIRect round() const {
   773         SkIRect ir;
   774         this->round(&ir);
   775         return ir;
   776     }
   778     /**
   779      *  Swap top/bottom or left/right if there are flipped (i.e. if width()
   780      *  or height() would have returned a negative value.) This should be called
   781      *  if the edges are computed separately, and may have crossed over each
   782      *  other. When this returns, left <= right && top <= bottom
   783      */
   784     void sort();
   786     /**
   787      *  cast-safe way to treat the rect as an array of (4) SkScalars.
   788      */
   789     const SkScalar* asScalars() const { return &fLeft; }
   790 };
   792 #endif

mercurial