soui 5.0.0.1
Soui5 Doc
 
Loading...
Searching...
No Matches
SRect.h
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#ifndef _SRect_DEFINED_
10#define _SRect_DEFINED_
11
12#include "SPoint.h"
13
14SNSBEGIN
15
16template <typename T>
17inline void STSwap(T &a, T &b)
18{
19 T c(a);
20 a = b;
21 b = c;
22}
23
24/** \struct SkRect
25 */
26struct SOUI_EXP SRect : public fRect
27{
28 static SRect IMake(const RECT &src)
29 {
30 SRect rc;
31 rc.iset(src);
32 return rc;
33 }
34
35 /**
36 * Return true if the rectangle's width or height are <= 0
37 */
38 bool isEmpty() const
39 {
40 return fLeft >= fRight || fTop >= fBottom;
41 }
42
43 bool isLargest() const
44 {
45 return SK_ScalarMin == fLeft && SK_ScalarMin == fTop && SK_ScalarMax == fRight && SK_ScalarMax == fBottom;
46 }
47
48 /**
49 * Returns true iff all values in the rect are finite. If any are
50 * infinite or NaN (or SK_FixedNaN when float is fixed) then this
51 * returns false.
52 */
53 bool isFinite() const
54 {
55 float accum = 0;
56 accum *= fLeft;
57 accum *= fTop;
58 accum *= fRight;
59 accum *= fBottom;
60
61 // accum is either NaN or it is finite (zero).
62 SASSERT(0 == accum || !(accum == accum));
63
64 // value==value will be true iff value is not NaN
65 // TODO: is it faster to say !accum or accum==accum?
66 return accum == accum;
67 }
68
69 float x() const
70 {
71 return fLeft;
72 }
73 float y() const
74 {
75 return fTop;
76 }
77 float left() const
78 {
79 return fLeft;
80 }
81 float top() const
82 {
83 return fTop;
84 }
85 float right() const
86 {
87 return fRight;
88 }
89 float bottom() const
90 {
91 return fBottom;
92 }
93 float width() const
94 {
95 return fRight - fLeft;
96 }
97 float height() const
98 {
99 return fBottom - fTop;
100 }
101 float centerX() const
102 {
103 return SFloatHalf(fLeft + fRight);
104 }
105 float centerY() const
106 {
107 return SFloatHalf(fTop + fBottom);
108 }
109
110 friend bool operator==(const SRect &a, const SRect &b)
111 {
112 return SFloatsEqual((float *)&a, (float *)&b, 4);
113 }
114
115 friend bool operator!=(const SRect &a, const SRect &b)
116 {
117 return !SFloatsEqual((float *)&a, (float *)&b, 4);
118 }
119
120 /** return the 4 points that enclose the rectangle (top-left, top-right, bottom-right,
121 bottom-left). TODO: Consider adding param to control whether quad is CW or CCW.
122 */
123 void toQuad(SPoint quad[4]) const;
124
125 /** Set this rectangle to the empty rectangle (0,0,0,0)
126 */
127 void setEmpty()
128 {
129 memset(this, 0, sizeof(*this));
130 }
131
132 void iset(const RECT &src)
133 {
134 fLeft = SkIntToScalar(src.left);
135 fTop = SkIntToScalar(src.top);
136 fRight = SkIntToScalar(src.right);
137 fBottom = SkIntToScalar(src.bottom);
138 }
139
140 RECT toRect() const
141 {
142 RECT rc;
143 rc.left = sk_float_floor2int(fLeft);
144 rc.top = sk_float_floor2int(fTop);
145 rc.right = sk_float_ceil2int(fRight);
146 rc.bottom = sk_float_ceil2int(fBottom);
147 return rc;
148 }
149
150 void set(float left, float top, float right, float bottom)
151 {
152 fLeft = left;
153 fTop = top;
154 fRight = right;
155 fBottom = bottom;
156 }
157
158 /** Initialize the rect with the 4 specified integers. The routine handles
159 converting them to scalars (by calling SkIntToScalar)
160 */
161 void iset(int left, int top, int right, int bottom)
162 {
163 fLeft = SkIntToScalar(left);
164 fTop = SkIntToScalar(top);
165 fRight = SkIntToScalar(right);
166 fBottom = SkIntToScalar(bottom);
167 }
168
169 /** Set this rectangle to be the bounds of the array of points.
170 If the array is empty (count == 0), then set this rectangle
171 to the empty rectangle (0,0,0,0)
172 */
173 void set(const SPoint pts[], int count)
174 {
175 // set() had been checking for non-finite values, so keep that behavior
176 // for now. Now that we have setBoundsCheck(), we may decide to make
177 // set() be simpler/faster, and not check for those.
178 (void)this->setBoundsCheck(pts, count);
179 }
180
181 // alias for set(pts, count)
182 void setBounds(const SPoint pts[], int count)
183 {
184 (void)this->setBoundsCheck(pts, count);
185 }
186
187 /**
188 * Compute the bounds of the array of points, and set this rect to that
189 * bounds and return true... unless a non-finite value is encountered,
190 * in which case this rect is set to empty and false is returned.
191 */
192 bool setBoundsCheck(const SPoint pts[], int count);
193
194 void set(const SPoint &p0, const SPoint &p1)
195 {
196 fLeft = SkMinScalar(p0.fX, p1.fX);
197 fRight = SkMaxScalar(p0.fX, p1.fX);
198 fTop = SkMinScalar(p0.fY, p1.fY);
199 fBottom = SkMaxScalar(p0.fY, p1.fY);
200 }
201
202 /** Offset set the rectangle by adding dx to its left and right,
203 and adding dy to its top and bottom.
204 */
205 void offset(float dx, float dy)
206 {
207 fLeft += dx;
208 fTop += dy;
209 fRight += dx;
210 fBottom += dy;
211 }
212
213 void offset(const SPoint &delta)
214 {
215 this->offset(delta.fX, delta.fY);
216 }
217
218 /**
219 * Offset this rect such its new x() and y() will equal newX and newY.
220 */
221 void offsetTo(float newX, float newY)
222 {
223 fRight += newX - fLeft;
224 fBottom += newY - fTop;
225 fLeft = newX;
226 fTop = newY;
227 }
228
229 /** Inset the rectangle by (dx,dy). If dx is positive, then the sides are
230 moved inwards, making the rectangle narrower. If dx is negative, then
231 the sides are moved outwards, making the rectangle wider. The same holds
232 true for dy and the top and bottom.
233 */
234 void inset(float dx, float dy)
235 {
236 fLeft += dx;
237 fTop += dy;
238 fRight -= dx;
239 fBottom -= dy;
240 }
241
242 /** Outset the rectangle by (dx,dy). If dx is positive, then the sides are
243 moved outwards, making the rectangle wider. If dx is negative, then the
244 sides are moved inwards, making the rectangle narrower. The same holds
245 true for dy and the top and bottom.
246 */
247 void outset(float dx, float dy)
248 {
249 this->inset(-dx, -dy);
250 }
251
252 /**
253 * Swap top/bottom or left/right if there are flipped (i.e. if width()
254 * or height() would have returned a negative value.) This should be called
255 * if the edges are computed separately, and may have crossed over each
256 * other. When this returns, left <= right && top <= bottom
257 */
258 void sort();
259
260 /**
261 * cast-safe way to treat the rect as an array of (4) SFloats.
262 */
263 const float *asScalars() const
264 {
265 return &fLeft;
266 }
267};
268
269struct SOUI_EXP STriangle
270{
271 SPoint fPts[3];
272 bool contains(const SPoint &pt) const;
273};
274
275struct SOUI_EXP SQuad
276{
277 SPoint fPts[4];
278 bool contains(const SPoint &pt) const;
279};
280
281SNSEND
282#endif