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