Line data Source code
1 : /**
2 : Copyright (c) 2010-2012 cocos2d-x.org
3 : Copyright (c) 2013-2014 Chukong Technologies
4 : Copyright (c) 2016-2022 Roman Katuntsev <sbkarr@stappler.org>
5 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
6 :
7 : Permission is hereby granted, free of charge, to any person obtaining a copy
8 : of this software and associated documentation files (the "Software"), to deal
9 : in the Software without restriction, including without limitation the rights
10 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 : copies of the Software, and to permit persons to whom the Software is
12 : furnished to do so, subject to the following conditions:
13 :
14 : The above copyright notice and this permission notice shall be included in
15 : all copies or substantial portions of the Software.
16 :
17 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 : THE SOFTWARE.
24 : **/
25 :
26 : #include "SPGeometry.h"
27 : #include "SPMat4.h"
28 :
29 : namespace STAPPLER_VERSIONIZED stappler::geom {
30 :
31 1475 : bool Metric::readStyleValue(StringView r, bool resolutionMetric, bool allowEmptyMetric) {
32 1475 : r.skipChars<StringView::CharGroup<CharGroupId::WhiteSpace>>();
33 1475 : if (!resolutionMetric && r.starts_with("auto")) {
34 25 : r += 4;
35 25 : this->metric = Metric::Units::Auto;
36 25 : this->value = 0.0f;
37 25 : return true;
38 : }
39 :
40 1450 : auto fRes = r.readFloat();
41 1450 : if (!fRes.valid()) {
42 0 : return false;
43 : }
44 :
45 1450 : auto fvalue = fRes.get();
46 1450 : if (fvalue == 0.0f) {
47 100 : this->value = fvalue;
48 100 : this->metric = Metric::Units::Px;
49 100 : return true;
50 : }
51 :
52 1350 : r.skipChars<StringView::CharGroup<CharGroupId::WhiteSpace>>();
53 :
54 1350 : auto str = r.readUntil<StringView::CharGroup<CharGroupId::WhiteSpace>>();
55 :
56 1350 : if (!resolutionMetric) {
57 1275 : if (str.is('%')) {
58 75 : ++ str;
59 75 : this->value = fvalue / 100.0f;
60 75 : this->metric = Metric::Units::Percent;
61 75 : return true;
62 1200 : } else if (str == "em") {
63 25 : str += 2;
64 25 : this->value = fvalue;
65 25 : this->metric = Metric::Units::Em;
66 25 : return true;
67 1175 : } else if (str == "rem") {
68 25 : str += 3;
69 25 : this->value = fvalue;
70 25 : this->metric = Metric::Units::Rem;
71 25 : return true;
72 1150 : } else if (str == "px") {
73 50 : str += 2;
74 50 : this->value = fvalue;
75 50 : this->metric = Metric::Units::Px;
76 50 : return true;
77 1100 : } else if (str == "pt") {
78 25 : str += 2;
79 25 : this->value = fvalue * 4.0f / 3.0f;
80 25 : this->metric = Metric::Units::Px;
81 25 : return true;
82 1075 : } else if (str == "pc") {
83 25 : str += 2;
84 25 : this->value = fvalue * 15.0f;
85 25 : this->metric = Metric::Units::Px;
86 25 : return true;
87 1050 : } else if (str == "mm") {
88 25 : str += 2;
89 25 : this->value = fvalue * 3.543307f;
90 25 : this->metric = Metric::Units::Px;
91 25 : return true;
92 1025 : } else if (str == "cm") {
93 25 : str += 2;
94 25 : this->value = fvalue * 35.43307f;
95 25 : this->metric = Metric::Units::Px;
96 25 : return true;
97 1000 : } else if (str == "in") {
98 25 : str += 2;
99 25 : this->value = fvalue * 90.0f;
100 25 : this->metric = Metric::Units::Px;
101 25 : return true;
102 975 : } else if (str == "vw") {
103 25 : str += 2;
104 25 : this->value = fvalue;
105 25 : this->metric = Metric::Units::Vw;
106 25 : return true;
107 950 : } else if (str == "vh") {
108 25 : str += 2;
109 25 : this->value = fvalue;
110 25 : this->metric = Metric::Units::Vh;
111 25 : return true;
112 925 : } else if (str == "vmin") {
113 25 : str += 4;
114 25 : this->value = fvalue;
115 25 : this->metric = Metric::Units::VMin;
116 25 : return true;
117 900 : } else if (str == "vmax") {
118 25 : str += 4;
119 25 : this->value = fvalue;
120 25 : this->metric = Metric::Units::VMax;
121 25 : return true;
122 : }
123 : } else {
124 75 : if (str == "dpi") {
125 25 : str += 3;
126 25 : this->value = fvalue;
127 25 : this->metric = Metric::Units::Dpi;
128 25 : return true;
129 50 : } else if (str == "dpcm") {
130 25 : str += 4;
131 25 : this->value = fvalue / 2.54f;
132 25 : this->metric = Metric::Units::Dpi;
133 25 : return true;
134 25 : } else if (str == "dppx") {
135 25 : str += 4;
136 25 : this->value = fvalue;
137 25 : this->metric = Metric::Units::Dppx;
138 25 : return true;
139 : }
140 : }
141 :
142 875 : if (allowEmptyMetric) {
143 850 : this->value = fvalue;
144 850 : return true;
145 : }
146 :
147 25 : return false;
148 : }
149 :
150 50 : bool Rect::containsPoint(const Vec2& point, float padding) const {
151 50 : bool bRet = false;
152 :
153 50 : if (point.x >= getMinX() - padding && point.x <= getMaxX() + padding && point.y >= getMinY() - padding && point.y <= getMaxY() + padding) {
154 25 : bRet = true;
155 : }
156 :
157 50 : return bRet;
158 : }
159 :
160 25 : bool Rect::intersectsRect(const Rect& rect) const {
161 50 : return !( getMaxX() < rect.getMinX() ||
162 25 : rect.getMaxX() < getMinX() ||
163 25 : getMaxY() < rect.getMinY() ||
164 50 : rect.getMaxY() < getMinY());
165 : }
166 :
167 100 : bool Rect::intersectsCircle(const Vec2 ¢er, float radius) const {
168 100 : Vec2 rectangleCenter((origin.x + size.width / 2),
169 100 : (origin.y + size.height / 2));
170 :
171 100 : float w = size.width / 2;
172 100 : float h = size.height / 2;
173 :
174 100 : float dx = fabs(center.x - rectangleCenter.x);
175 100 : float dy = fabs(center.y - rectangleCenter.y);
176 :
177 100 : if (dx > (radius + w) || dy > (radius + h)) {
178 25 : return false;
179 : }
180 :
181 75 : Vec2 circleDistance(fabs(center.x - origin.x - w),
182 75 : fabs(center.y - origin.y - h));
183 :
184 75 : if (circleDistance.x <= (w)) {
185 25 : return true;
186 : }
187 :
188 50 : if (circleDistance.y <= (h)) {
189 25 : return true;
190 : }
191 :
192 25 : float cornerDistanceSq = powf(circleDistance.x - w, 2) + powf(circleDistance.y - h, 2);
193 :
194 25 : return (cornerDistanceSq <= (powf(radius, 2)));
195 : }
196 :
197 25 : void Rect::merge(const Rect& rect) {
198 25 : float top1 = getMaxY();
199 25 : float left1 = getMinX();
200 25 : float right1 = getMaxX();
201 25 : float bottom1 = getMinY();
202 :
203 25 : float top2 = rect.getMaxY();
204 25 : float left2 = rect.getMinX();
205 25 : float right2 = rect.getMaxX();
206 25 : float bottom2 = rect.getMinY();
207 25 : origin.x = std::min(left1, left2);
208 25 : origin.y = std::min(bottom1, bottom2);
209 25 : size.width = std::max(right1, right2) - origin.x;
210 25 : size.height = std::max(top1, top2) - origin.y;
211 25 : }
212 :
213 50 : Rect Rect::unionWithRect(const Rect & rect) const {
214 50 : float thisLeftX = origin.x;
215 50 : float thisRightX = origin.x + size.width;
216 50 : float thisTopY = origin.y + size.height;
217 50 : float thisBottomY = origin.y;
218 :
219 50 : if (thisRightX < thisLeftX) {
220 0 : std::swap(thisRightX, thisLeftX); // This rect has negative width
221 : }
222 :
223 50 : if (thisTopY < thisBottomY) {
224 0 : std::swap(thisTopY, thisBottomY); // This rect has negative height
225 : }
226 :
227 50 : float otherLeftX = rect.origin.x;
228 50 : float otherRightX = rect.origin.x + rect.size.width;
229 50 : float otherTopY = rect.origin.y + rect.size.height;
230 50 : float otherBottomY = rect.origin.y;
231 :
232 50 : if (otherRightX < otherLeftX) {
233 0 : std::swap(otherRightX, otherLeftX); // Other rect has negative width
234 : }
235 :
236 50 : if (otherTopY < otherBottomY) {
237 0 : std::swap(otherTopY, otherBottomY); // Other rect has negative height
238 : }
239 :
240 50 : float combinedLeftX = std::min(thisLeftX, otherLeftX);
241 50 : float combinedRightX = std::max(thisRightX, otherRightX);
242 50 : float combinedTopY = std::max(thisTopY, otherTopY);
243 50 : float combinedBottomY = std::min(thisBottomY, otherBottomY);
244 :
245 50 : return Rect(combinedLeftX, combinedBottomY, combinedRightX - combinedLeftX, combinedTopY - combinedBottomY);
246 : }
247 :
248 50 : bool URect::containsPoint(const UVec2 &point) const {
249 50 : bool bRet = false;
250 :
251 50 : if (point.x >= getMinX() && point.x <= getMaxX() && point.y >= getMinY() && point.y <= getMaxY()) {
252 25 : bRet = true;
253 : }
254 :
255 50 : return bRet;
256 : }
257 :
258 175 : bool URect::intersectsRect(const URect &rect) const {
259 275 : return !( getMaxX() < rect.getMinX() ||
260 100 : rect.getMaxX() < getMinX() ||
261 25 : getMaxY() < rect.getMinY() ||
262 200 : rect.getMaxY() < getMinY());
263 : }
264 :
265 25 : Rect TransformRect(const Rect& rect, const Mat4& transform) {
266 25 : const float top = rect.getMinY();
267 25 : const float left = rect.getMinX();
268 25 : const float right = rect.getMaxX();
269 25 : const float bottom = rect.getMaxY();
270 :
271 25 : Vec2 topLeft(left, top);
272 25 : Vec2 topRight(right, top);
273 25 : Vec2 bottomLeft(left, bottom);
274 25 : Vec2 bottomRight(right, bottom);
275 :
276 25 : transform.transformPoint(&topLeft);
277 25 : transform.transformPoint(&topRight);
278 25 : transform.transformPoint(&bottomLeft);
279 25 : transform.transformPoint(&bottomRight);
280 :
281 25 : const float minX = min(min(topLeft.x, topRight.x), min(bottomLeft.x, bottomRight.x));
282 25 : const float maxX = max(max(topLeft.x, topRight.x), max(bottomLeft.x, bottomRight.x));
283 25 : const float minY = min(min(topLeft.y, topRight.y), min(bottomLeft.y, bottomRight.y));
284 25 : const float maxY = max(max(topLeft.y, topRight.y), max(bottomLeft.y, bottomRight.y));
285 :
286 25 : return Rect(minX, minY, (maxX - minX), (maxY - minY));
287 : }
288 :
289 : #ifdef __LCC__
290 :
291 : constexpr Size2 Size2::ZERO(0.0f, 0.0f);
292 : constexpr Size3 Size3::ZERO = Size3(0.0f, 0.0f, 0.0f);
293 : constexpr Extent2 Extent2::ZERO = Extent2(0, 0);
294 : constexpr Extent3 Extent3::ZERO = Extent3(0, 0, 0);
295 : constexpr Rect Rect::ZERO = Rect(0.0f, 0.0f, 0.0f, 0.0f);
296 :
297 : #endif
298 :
299 : }
|