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