Home | History | Annotate | Download | only in core
      1 
      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  */
      8 
      9 
     10 #include "SkRect.h"
     11 
     12 void SkIRect::join(int32_t left, int32_t top, int32_t right, int32_t bottom) {
     13     // do nothing if the params are empty
     14     if (left >= right || top >= bottom) {
     15         return;
     16     }
     17 
     18     // if we are empty, just assign
     19     if (fLeft >= fRight || fTop >= fBottom) {
     20         this->set(left, top, right, bottom);
     21     } else {
     22         if (left < fLeft) fLeft = left;
     23         if (top < fTop) fTop = top;
     24         if (right > fRight) fRight = right;
     25         if (bottom > fBottom) fBottom = bottom;
     26     }
     27 }
     28 
     29 void SkIRect::sort() {
     30     if (fLeft > fRight) {
     31         SkTSwap<int32_t>(fLeft, fRight);
     32     }
     33     if (fTop > fBottom) {
     34         SkTSwap<int32_t>(fTop, fBottom);
     35     }
     36 }
     37 
     38 /////////////////////////////////////////////////////////////////////////////
     39 
     40 void SkRect::sort() {
     41     if (fLeft > fRight) {
     42         SkTSwap<SkScalar>(fLeft, fRight);
     43     }
     44     if (fTop > fBottom) {
     45         SkTSwap<SkScalar>(fTop, fBottom);
     46     }
     47 }
     48 
     49 void SkRect::toQuad(SkPoint quad[4]) const {
     50     SkASSERT(quad);
     51 
     52     quad[0].set(fLeft, fTop);
     53     quad[1].set(fRight, fTop);
     54     quad[2].set(fRight, fBottom);
     55     quad[3].set(fLeft, fBottom);
     56 }
     57 
     58 bool SkRect::setBoundsCheck(const SkPoint pts[], int count) {
     59     SkASSERT((pts && count > 0) || count == 0);
     60 
     61     bool isFinite = true;
     62 
     63     if (count <= 0) {
     64         sk_bzero(this, sizeof(SkRect));
     65     } else {
     66         SkScalar    l, t, r, b;
     67 
     68         l = r = pts[0].fX;
     69         t = b = pts[0].fY;
     70 
     71         // If all of the points are finite, accum should stay 0. If we encounter
     72         // a NaN or infinity, then accum should become NaN.
     73         float accum = 0;
     74         accum *= l; accum *= t;
     75 
     76         for (int i = 1; i < count; i++) {
     77             SkScalar x = pts[i].fX;
     78             SkScalar y = pts[i].fY;
     79 
     80             accum *= x; accum *= y;
     81 
     82             // we use if instead of if/else, so we can generate min/max
     83             // float instructions (at least on SSE)
     84             if (x < l) l = x;
     85             if (x > r) r = x;
     86 
     87             if (y < t) t = y;
     88             if (y > b) b = y;
     89         }
     90 
     91         SkASSERT(!accum || !SkScalarIsFinite(accum));
     92         if (accum) {
     93             l = t = r = b = 0;
     94             isFinite = false;
     95         }
     96         this->set(l, t, r, b);
     97     }
     98 
     99     return isFinite;
    100 }
    101 
    102 bool SkRect::intersect(SkScalar left, SkScalar top, SkScalar right,
    103                        SkScalar bottom) {
    104     if (left < right && top < bottom && !this->isEmpty() && // check for empties
    105         fLeft < right && left < fRight && fTop < bottom && top < fBottom)
    106     {
    107         if (fLeft < left) fLeft = left;
    108         if (fTop < top) fTop = top;
    109         if (fRight > right) fRight = right;
    110         if (fBottom > bottom) fBottom = bottom;
    111         return true;
    112     }
    113     return false;
    114 }
    115 
    116 bool SkRect::intersect(const SkRect& r) {
    117     SkASSERT(&r);
    118     return this->intersect(r.fLeft, r.fTop, r.fRight, r.fBottom);
    119 }
    120 
    121 bool SkRect::intersect2(const SkRect& r) {
    122     SkASSERT(&r);
    123     SkScalar L = SkMaxScalar(fLeft, r.fLeft);
    124     SkScalar R = SkMinScalar(fRight, r.fRight);
    125     if (L >= R) {
    126         return false;
    127     }
    128     SkScalar T = SkMaxScalar(fTop, r.fTop);
    129     SkScalar B = SkMinScalar(fBottom, r.fBottom);
    130     if (T >= B) {
    131         return false;
    132     }
    133     this->set(L, T, R, B);
    134     return true;
    135 }
    136 
    137 bool SkRect::intersect(const SkRect& a, const SkRect& b) {
    138     SkASSERT(&a && &b);
    139 
    140     if (!a.isEmpty() && !b.isEmpty() &&
    141         a.fLeft < b.fRight && b.fLeft < a.fRight &&
    142         a.fTop < b.fBottom && b.fTop < a.fBottom) {
    143         fLeft   = SkMaxScalar(a.fLeft,   b.fLeft);
    144         fTop    = SkMaxScalar(a.fTop,    b.fTop);
    145         fRight  = SkMinScalar(a.fRight,  b.fRight);
    146         fBottom = SkMinScalar(a.fBottom, b.fBottom);
    147         return true;
    148     }
    149     return false;
    150 }
    151 
    152 void SkRect::join(SkScalar left, SkScalar top, SkScalar right,
    153                   SkScalar bottom) {
    154     // do nothing if the params are empty
    155     if (left >= right || top >= bottom) {
    156         return;
    157     }
    158 
    159     // if we are empty, just assign
    160     if (fLeft >= fRight || fTop >= fBottom) {
    161         this->set(left, top, right, bottom);
    162     } else {
    163         if (left < fLeft) fLeft = left;
    164         if (top < fTop) fTop = top;
    165         if (right > fRight) fRight = right;
    166         if (bottom > fBottom) fBottom = bottom;
    167     }
    168 }
    169