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 #ifdef SK_SCALAR_IS_FLOAT
     59     #define SkFLOATCODE(code)   code
     60 #else
     61     #define SkFLOATCODE(code)
     62 #endif
     63 
     64 // For float compares (at least on x86, by removing the else from the min/max
     65 // computation, we get MAXSS and MINSS instructions, and no branches.
     66 // Fixed point has no such opportunity (afaik), so we leave the else in that case
     67 #ifdef SK_SCALAR_IS_FLOAT
     68     #define MINMAX_ELSE
     69 #else
     70     #define MINMAX_ELSE else
     71 #endif
     72 
     73 bool SkRect::setBoundsCheck(const SkPoint pts[], int count) {
     74     SkASSERT((pts && count > 0) || count == 0);
     75 
     76     bool isFinite = true;
     77 
     78     if (count <= 0) {
     79         sk_bzero(this, sizeof(SkRect));
     80     } else {
     81 #ifdef SK_SCALAR_SLOW_COMPARES
     82         int32_t    l, t, r, b;
     83 
     84         l = r = SkScalarAs2sCompliment(pts[0].fX);
     85         t = b = SkScalarAs2sCompliment(pts[0].fY);
     86 
     87         for (int i = 1; i < count; i++) {
     88             int32_t x = SkScalarAs2sCompliment(pts[i].fX);
     89             int32_t y = SkScalarAs2sCompliment(pts[i].fY);
     90 
     91             if (x < l) l = x; else if (x > r) r = x;
     92             if (y < t) t = y; else if (y > b) b = y;
     93         }
     94         this->set(Sk2sComplimentAsScalar(l),
     95                   Sk2sComplimentAsScalar(t),
     96                   Sk2sComplimentAsScalar(r),
     97                   Sk2sComplimentAsScalar(b));
     98 #else
     99         SkScalar    l, t, r, b;
    100 
    101         l = r = pts[0].fX;
    102         t = b = pts[0].fY;
    103 
    104         // If all of the points are finite, accum should stay 0. If we encounter
    105         // a NaN or infinity, then accum should become NaN.
    106         SkFLOATCODE(float accum = 0;)
    107         SkFLOATCODE(accum *= l; accum *= t;)
    108 
    109         for (int i = 1; i < count; i++) {
    110             SkScalar x = pts[i].fX;
    111             SkScalar y = pts[i].fY;
    112 
    113             SkFLOATCODE(accum *= x; accum *= y;)
    114 
    115             if (x < l) l = x; MINMAX_ELSE if (x > r) r = x;
    116             if (y < t) t = y; MINMAX_ELSE if (y > b) b = y;
    117         }
    118 
    119 #ifdef SK_SCALAR_IS_FLOAT
    120         SkASSERT(!accum || !SkScalarIsFinite(accum));
    121         if (accum) {
    122             l = t = r = b = 0;
    123             isFinite = false;
    124         }
    125 #endif
    126         this->set(l, t, r, b);
    127 #endif
    128     }
    129 
    130     return isFinite;
    131 }
    132 
    133 bool SkRect::intersect(SkScalar left, SkScalar top, SkScalar right,
    134                        SkScalar bottom) {
    135     if (left < right && top < bottom && !this->isEmpty() && // check for empties
    136         fLeft < right && left < fRight && fTop < bottom && top < fBottom)
    137     {
    138         if (fLeft < left) fLeft = left;
    139         if (fTop < top) fTop = top;
    140         if (fRight > right) fRight = right;
    141         if (fBottom > bottom) fBottom = bottom;
    142         return true;
    143     }
    144     return false;
    145 }
    146 
    147 bool SkRect::intersect(const SkRect& r) {
    148     SkASSERT(&r);
    149     return this->intersect(r.fLeft, r.fTop, r.fRight, r.fBottom);
    150 }
    151 
    152 bool SkRect::intersect(const SkRect& a, const SkRect& b) {
    153     SkASSERT(&a && &b);
    154 
    155     if (!a.isEmpty() && !b.isEmpty() &&
    156         a.fLeft < b.fRight && b.fLeft < a.fRight &&
    157         a.fTop < b.fBottom && b.fTop < a.fBottom) {
    158         fLeft   = SkMaxScalar(a.fLeft,   b.fLeft);
    159         fTop    = SkMaxScalar(a.fTop,    b.fTop);
    160         fRight  = SkMinScalar(a.fRight,  b.fRight);
    161         fBottom = SkMinScalar(a.fBottom, b.fBottom);
    162         return true;
    163     }
    164     return false;
    165 }
    166 
    167 void SkRect::join(SkScalar left, SkScalar top, SkScalar right,
    168                   SkScalar bottom) {
    169     // do nothing if the params are empty
    170     if (left >= right || top >= bottom) {
    171         return;
    172     }
    173 
    174     // if we are empty, just assign
    175     if (fLeft >= fRight || fTop >= fBottom) {
    176         this->set(left, top, right, bottom);
    177     } else {
    178         if (left < fLeft) fLeft = left;
    179         if (top < fTop) fTop = top;
    180         if (right > fRight) fRight = right;
    181         if (bottom > fBottom) fBottom = bottom;
    182     }
    183 }
    184