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 "include/core/SkRect.h"
9
10 #include "include/private/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
29 /////////////////////////////////////////////////////////////////////////////
30
toQuad(SkPoint quad[4]) const31 void SkRect::toQuad(SkPoint quad[4]) const {
32 SkASSERT(quad);
33
34 quad[0].set(fLeft, fTop);
35 quad[1].set(fRight, fTop);
36 quad[2].set(fRight, fBottom);
37 quad[3].set(fLeft, fBottom);
38 }
39
40 #include "include/private/SkNx.h"
41
setBoundsCheck(const SkPoint pts[],int count)42 bool SkRect::setBoundsCheck(const SkPoint pts[], int count) {
43 SkASSERT((pts && count > 0) || count == 0);
44
45 if (count <= 0) {
46 this->setEmpty();
47 return true;
48 }
49
50 Sk4s min, max;
51 if (count & 1) {
52 min = max = Sk4s(pts->fX, pts->fY,
53 pts->fX, pts->fY);
54 pts += 1;
55 count -= 1;
56 } else {
57 min = max = Sk4s::Load(pts);
58 pts += 2;
59 count -= 2;
60 }
61
62 Sk4s accum = min * 0;
63 while (count) {
64 Sk4s xy = Sk4s::Load(pts);
65 accum = accum * xy;
66 min = Sk4s::Min(min, xy);
67 max = Sk4s::Max(max, xy);
68 pts += 2;
69 count -= 2;
70 }
71
72 bool all_finite = (accum * 0 == 0).allTrue();
73 if (all_finite) {
74 this->set(SkTMin(min[0], min[2]), SkTMin(min[1], min[3]),
75 SkTMax(max[0], max[2]), SkTMax(max[1], max[3]));
76 } else {
77 this->setEmpty();
78 }
79 return all_finite;
80 }
81
setBoundsNoCheck(const SkPoint pts[],int count)82 void SkRect::setBoundsNoCheck(const SkPoint pts[], int count) {
83 if (!this->setBoundsCheck(pts, count)) {
84 this->set(SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN);
85 }
86 }
87
88 #define CHECK_INTERSECT(al, at, ar, ab, bl, bt, br, bb) \
89 SkScalar L = SkMaxScalar(al, bl); \
90 SkScalar R = SkMinScalar(ar, br); \
91 SkScalar T = SkMaxScalar(at, bt); \
92 SkScalar B = SkMinScalar(ab, bb); \
93 do { if (!(L < R && T < B)) return false; } while (0)
94 // do the !(opposite) check so we return false if either arg is NaN
95
intersect(SkScalar left,SkScalar top,SkScalar right,SkScalar bottom)96 bool SkRect::intersect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
97 CHECK_INTERSECT(left, top, right, bottom, fLeft, fTop, fRight, fBottom);
98 this->setLTRB(L, T, R, B);
99 return true;
100 }
101
intersect(const SkRect & r)102 bool SkRect::intersect(const SkRect& r) {
103 return this->intersect(r.fLeft, r.fTop, r.fRight, r.fBottom);
104 }
105
intersect(const SkRect & a,const SkRect & b)106 bool SkRect::intersect(const SkRect& a, const SkRect& b) {
107 CHECK_INTERSECT(a.fLeft, a.fTop, a.fRight, a.fBottom, b.fLeft, b.fTop, b.fRight, b.fBottom);
108 this->setLTRB(L, T, R, B);
109 return true;
110 }
111
join(SkScalar left,SkScalar top,SkScalar right,SkScalar bottom)112 void SkRect::join(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
113 // do nothing if the params are empty
114 if (left >= right || top >= bottom) {
115 return;
116 }
117
118 // if we are empty, just assign
119 if (fLeft >= fRight || fTop >= fBottom) {
120 this->set(left, top, right, bottom);
121 } else {
122 fLeft = SkMinScalar(fLeft, left);
123 fTop = SkMinScalar(fTop, top);
124 fRight = SkMaxScalar(fRight, right);
125 fBottom = SkMaxScalar(fBottom, bottom);
126 }
127 }
128
129 ////////////////////////////////////////////////////////////////////////////////////////////////
130
131 #include "include/core/SkString.h"
132 #include "src/core/SkStringUtils.h"
133
set_scalar(SkString * storage,SkScalar value,SkScalarAsStringType asType)134 static const char* set_scalar(SkString* storage, SkScalar value, SkScalarAsStringType asType) {
135 storage->reset();
136 SkAppendScalar(storage, value, asType);
137 return storage->c_str();
138 }
139
dump(bool asHex) const140 void SkRect::dump(bool asHex) const {
141 SkScalarAsStringType asType = asHex ? kHex_SkScalarAsStringType : kDec_SkScalarAsStringType;
142
143 SkString line;
144 if (asHex) {
145 SkString tmp;
146 line.printf( "SkRect::MakeLTRB(%s, /* %f */\n", set_scalar(&tmp, fLeft, asType), fLeft);
147 line.appendf(" %s, /* %f */\n", set_scalar(&tmp, fTop, asType), fTop);
148 line.appendf(" %s, /* %f */\n", set_scalar(&tmp, fRight, asType), fRight);
149 line.appendf(" %s /* %f */);", set_scalar(&tmp, fBottom, asType), fBottom);
150 } else {
151 SkString strL, strT, strR, strB;
152 SkAppendScalarDec(&strL, fLeft);
153 SkAppendScalarDec(&strT, fTop);
154 SkAppendScalarDec(&strR, fRight);
155 SkAppendScalarDec(&strB, fBottom);
156 line.printf("SkRect::MakeLTRB(%s, %s, %s, %s);",
157 strL.c_str(), strT.c_str(), strR.c_str(), strB.c_str());
158 }
159 SkDebugf("%s\n", line.c_str());
160 }
161