Line data Source code
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 :
12 1771 : void SkIRect::join(int32_t left, int32_t top, int32_t right, int32_t bottom) {
13 : // do nothing if the params are empty
14 1771 : if (left >= right || top >= bottom) {
15 0 : return;
16 : }
17 :
18 : // if we are empty, just assign
19 1771 : if (fLeft >= fRight || fTop >= fBottom) {
20 458 : this->set(left, top, right, bottom);
21 : } else {
22 1313 : if (left < fLeft) fLeft = left;
23 1313 : if (top < fTop) fTop = top;
24 1313 : if (right > fRight) fRight = right;
25 1313 : if (bottom > fBottom) fBottom = bottom;
26 : }
27 : }
28 :
29 0 : void SkIRect::sort() {
30 0 : if (fLeft > fRight) {
31 0 : SkTSwap<int32_t>(fLeft, fRight);
32 : }
33 0 : if (fTop > fBottom) {
34 0 : SkTSwap<int32_t>(fTop, fBottom);
35 : }
36 0 : }
37 :
38 : /////////////////////////////////////////////////////////////////////////////
39 :
40 0 : void SkRect::toQuad(SkPoint quad[4]) const {
41 0 : SkASSERT(quad);
42 :
43 0 : quad[0].set(fLeft, fTop);
44 0 : quad[1].set(fRight, fTop);
45 0 : quad[2].set(fRight, fBottom);
46 0 : quad[3].set(fLeft, fBottom);
47 0 : }
48 :
49 : #include "SkNx.h"
50 :
51 286 : static inline bool is_finite(const Sk4s& value) {
52 572 : auto finite = value * Sk4s(0) == Sk4s(0);
53 286 : return finite.allTrue();
54 : }
55 :
56 287 : bool SkRect::setBoundsCheck(const SkPoint pts[], int count) {
57 287 : SkASSERT((pts && count > 0) || count == 0);
58 :
59 287 : bool isFinite = true;
60 :
61 287 : if (count <= 0) {
62 1 : sk_bzero(this, sizeof(SkRect));
63 : } else {
64 : Sk4s min, max, accum;
65 :
66 286 : if (count & 1) {
67 172 : min = Sk4s(pts[0].fX, pts[0].fY, pts[0].fX, pts[0].fY);
68 86 : pts += 1;
69 86 : count -= 1;
70 : } else {
71 200 : min = Sk4s::Load(pts);
72 200 : pts += 2;
73 200 : count -= 2;
74 : }
75 286 : accum = max = min;
76 286 : accum = accum * Sk4s(0);
77 :
78 286 : count >>= 1;
79 2020 : for (int i = 0; i < count; ++i) {
80 1734 : Sk4s xy = Sk4s::Load(pts);
81 1734 : accum = accum * xy;
82 1734 : min = Sk4s::Min(min, xy);
83 1734 : max = Sk4s::Max(max, xy);
84 1734 : 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 286 : if (is_finite(accum)) {
93 : float minArray[4], maxArray[4];
94 : min.store(minArray);
95 : max.store(maxArray);
96 572 : this->set(SkTMin(minArray[0], minArray[2]), SkTMin(minArray[1], minArray[3]),
97 858 : 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 0 : this->setEmpty();
101 0 : isFinite = false;
102 : }
103 : }
104 287 : 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 :
114 248 : bool SkRect::intersect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
115 248 : CHECK_INTERSECT(left, top, right, bottom, fLeft, fTop, fRight, fBottom);
116 248 : this->setLTRB(L, T, R, B);
117 248 : return true;
118 : }
119 :
120 248 : bool SkRect::intersect(const SkRect& r) {
121 248 : return this->intersect(r.fLeft, r.fTop, r.fRight, r.fBottom);
122 : }
123 :
124 113 : bool SkRect::intersect(const SkRect& a, const SkRect& b) {
125 113 : CHECK_INTERSECT(a.fLeft, a.fTop, a.fRight, a.fBottom, b.fLeft, b.fTop, b.fRight, b.fBottom);
126 113 : this->setLTRB(L, T, R, B);
127 113 : return true;
128 : }
129 :
130 0 : void SkRect::join(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
131 : // do nothing if the params are empty
132 0 : if (left >= right || top >= bottom) {
133 0 : return;
134 : }
135 :
136 : // if we are empty, just assign
137 0 : if (fLeft >= fRight || fTop >= fBottom) {
138 0 : this->set(left, top, right, bottom);
139 : } else {
140 0 : fLeft = SkMinScalar(fLeft, left);
141 0 : fTop = SkMinScalar(fTop, top);
142 0 : fRight = SkMaxScalar(fRight, right);
143 0 : fBottom = SkMaxScalar(fBottom, bottom);
144 : }
145 : }
146 :
147 : ////////////////////////////////////////////////////////////////////////////////////////////////
148 :
149 : #include "SkString.h"
150 : #include "SkStringUtils.h"
151 :
152 0 : static const char* set_scalar(SkString* storage, SkScalar value, SkScalarAsStringType asType) {
153 0 : storage->reset();
154 0 : SkAppendScalar(storage, value, asType);
155 0 : return storage->c_str();
156 : }
157 :
158 0 : void SkRect::dump(bool asHex) const {
159 0 : SkScalarAsStringType asType = asHex ? kHex_SkScalarAsStringType : kDec_SkScalarAsStringType;
160 :
161 0 : SkString line;
162 0 : if (asHex) {
163 0 : SkString tmp;
164 0 : line.printf( "SkRect::MakeLTRB(%s, /* %f */\n", set_scalar(&tmp, fLeft, asType), fLeft);
165 0 : line.appendf(" %s, /* %f */\n", set_scalar(&tmp, fTop, asType), fTop);
166 0 : line.appendf(" %s, /* %f */\n", set_scalar(&tmp, fRight, asType), fRight);
167 0 : line.appendf(" %s /* %f */);", set_scalar(&tmp, fBottom, asType), fBottom);
168 : } else {
169 0 : SkString strL, strT, strR, strB;
170 0 : SkAppendScalarDec(&strL, fLeft);
171 0 : SkAppendScalarDec(&strT, fTop);
172 0 : SkAppendScalarDec(&strR, fRight);
173 0 : SkAppendScalarDec(&strB, fBottom);
174 0 : line.printf("SkRect::MakeLTRB(%s, %s, %s, %s);",
175 0 : strL.c_str(), strT.c_str(), strR.c_str(), strB.c_str());
176 : }
177 0 : SkDebugf("%s\n", line.c_str());
178 0 : }
|