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 #include "SkRect.h"
10
join(int32_t left,int32_t top,int32_t right,int32_t bottom)11 void SkIRect::join(int32_t left, int32_t top, int32_t right, int32_t bottom) {
12 // do nothing if the params are empty
13 if (left >= right || top >= bottom) {
14 return;
15 }
16
17 // if we are empty, just assign
18 if (fLeft >= fRight || fTop >= fBottom) {
19 this->set(left, top, right, bottom);
20 } else {
21 if (left < fLeft) fLeft = left;
22 if (top < fTop) fTop = top;
23 if (right > fRight) fRight = right;
24 if (bottom > fBottom) fBottom = bottom;
25 }
26 }
27
sort()28 void SkIRect::sort() {
29 if (fLeft > fRight) {
30 SkTSwap<int32_t>(fLeft, fRight);
31 }
32 if (fTop > fBottom) {
33 SkTSwap<int32_t>(fTop, fBottom);
34 }
35 }
36
37 /////////////////////////////////////////////////////////////////////////////
38
toQuad(SkPoint quad[4]) const39 void SkRect::toQuad(SkPoint quad[4]) const {
40 SkASSERT(quad);
41
42 quad[0].set(fLeft, fTop);
43 quad[1].set(fRight, fTop);
44 quad[2].set(fRight, fBottom);
45 quad[3].set(fLeft, fBottom);
46 }
47
48 #include "SkNx.h"
49
is_finite(const Sk4s & value)50 static inline bool is_finite(const Sk4s& value) {
51 auto finite = value * Sk4s(0) == Sk4s(0);
52 return finite.allTrue();
53 }
54
setBoundsCheck(const SkPoint pts[],int count)55 bool SkRect::setBoundsCheck(const SkPoint pts[], int count) {
56 SkASSERT((pts && count > 0) || count == 0);
57
58 bool isFinite = true;
59
60 if (count <= 0) {
61 sk_bzero(this, sizeof(SkRect));
62 } else {
63 Sk4s min, max, accum;
64
65 if (count & 1) {
66 min = Sk4s(pts[0].fX, pts[0].fY, pts[0].fX, pts[0].fY);
67 pts += 1;
68 count -= 1;
69 } else {
70 min = Sk4s::Load(&pts[0].fX);
71 pts += 2;
72 count -= 2;
73 }
74 accum = max = min;
75 accum *= Sk4s(0);
76
77 count >>= 1;
78 for (int i = 0; i < count; ++i) {
79 Sk4s xy = Sk4s::Load(&pts->fX);
80 accum *= xy;
81 min = Sk4s::Min(min, xy);
82 max = Sk4s::Max(max, xy);
83 pts += 2;
84 }
85
86 /**
87 * With some trickery, we may be able to use Min/Max to also propogate non-finites,
88 * in which case we could eliminate accum entirely, and just check min and max for
89 * "is_finite".
90 */
91 if (is_finite(accum)) {
92 float minArray[4], maxArray[4];
93 min.store(minArray);
94 max.store(maxArray);
95 this->set(SkTMin(minArray[0], minArray[2]), SkTMin(minArray[1], minArray[3]),
96 SkTMax(maxArray[0], maxArray[2]), SkTMax(maxArray[1], maxArray[3]));
97 } else {
98 // we hit a non-finite value, so zero everything and return false
99 this->setEmpty();
100 isFinite = false;
101 }
102 }
103 return isFinite;
104 }
105
106 #define CHECK_INTERSECT(al, at, ar, ab, bl, bt, br, bb) \
107 SkScalar L = SkMaxScalar(al, bl); \
108 SkScalar R = SkMinScalar(ar, br); \
109 SkScalar T = SkMaxScalar(at, bt); \
110 SkScalar B = SkMinScalar(ab, bb); \
111 do { if (L >= R || T >= B) return false; } while (0)
112
intersect(SkScalar left,SkScalar top,SkScalar right,SkScalar bottom)113 bool SkRect::intersect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
114 CHECK_INTERSECT(left, top, right, bottom, fLeft, fTop, fRight, fBottom);
115 this->setLTRB(L, T, R, B);
116 return true;
117 }
118
intersect(const SkRect & r)119 bool SkRect::intersect(const SkRect& r) {
120 return this->intersect(r.fLeft, r.fTop, r.fRight, r.fBottom);
121 }
122
intersect(const SkRect & a,const SkRect & b)123 bool SkRect::intersect(const SkRect& a, const SkRect& b) {
124 CHECK_INTERSECT(a.fLeft, a.fTop, a.fRight, a.fBottom, b.fLeft, b.fTop, b.fRight, b.fBottom);
125 this->setLTRB(L, T, R, B);
126 return true;
127 }
128
join(SkScalar left,SkScalar top,SkScalar right,SkScalar bottom)129 void SkRect::join(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
130 // do nothing if the params are empty
131 if (left >= right || top >= bottom) {
132 return;
133 }
134
135 // if we are empty, just assign
136 if (fLeft >= fRight || fTop >= fBottom) {
137 this->set(left, top, right, bottom);
138 } else {
139 fLeft = SkMinScalar(fLeft, left);
140 fTop = SkMinScalar(fTop, top);
141 fRight = SkMaxScalar(fRight, right);
142 fBottom = SkMaxScalar(fBottom, bottom);
143 }
144 }
145
146 ////////////////////////////////////////////////////////////////////////////////////////////////
147
148 #include "SkString.h"
149 #include "SkStringUtils.h"
150
set_scalar(SkString * storage,SkScalar value,SkScalarAsStringType asType)151 static const char* set_scalar(SkString* storage, SkScalar value, SkScalarAsStringType asType) {
152 storage->reset();
153 SkAppendScalar(storage, value, asType);
154 return storage->c_str();
155 }
156
dump(bool asHex) const157 void SkRect::dump(bool asHex) const {
158 SkScalarAsStringType asType = asHex ? kHex_SkScalarAsStringType : kDec_SkScalarAsStringType;
159
160 SkString line;
161 if (asHex) {
162 SkString tmp;
163 line.printf( "SkRect::MakeLTRB(%s, /* %f */\n", set_scalar(&tmp, fLeft, asType), fLeft);
164 line.appendf(" %s, /* %f */\n", set_scalar(&tmp, fTop, asType), fTop);
165 line.appendf(" %s, /* %f */\n", set_scalar(&tmp, fRight, asType), fRight);
166 line.appendf(" %s /* %f */);", set_scalar(&tmp, fBottom, asType), fBottom);
167 } else {
168 SkString strL, strT, strR, strB;
169 SkAppendScalarDec(&strL, fLeft);
170 SkAppendScalarDec(&strT, fTop);
171 SkAppendScalarDec(&strR, fRight);
172 SkAppendScalarDec(&strB, fBottom);
173 line.printf("SkRect::MakeLTRB(%s, %s, %s, %s);",
174 strL.c_str(), strT.c_str(), strR.c_str(), strB.c_str());
175 }
176 SkDebugf("%s\n", line.c_str());
177 }
178