/src/skia/include/core/SkRect.h
Line | Count | Source (jump to first uncovered line) |
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 | | #ifndef SkRect_DEFINED |
9 | | #define SkRect_DEFINED |
10 | | |
11 | | #include "include/core/SkPoint.h" |
12 | | #include "include/core/SkSize.h" |
13 | | #include "include/core/SkTypes.h" |
14 | | #include "include/private/base/SkFloatingPoint.h" |
15 | | #include "include/private/base/SkSafe32.h" |
16 | | #include "include/private/base/SkTFitsIn.h" |
17 | | |
18 | | #include <algorithm> |
19 | | #include <cmath> |
20 | | #include <cstdint> |
21 | | #include <cstring> |
22 | | |
23 | | struct SkRect; |
24 | | |
25 | | /** \struct SkIRect |
26 | | SkIRect holds four 32-bit integer coordinates describing the upper and |
27 | | lower bounds of a rectangle. SkIRect may be created from outer bounds or |
28 | | from position, width, and height. SkIRect describes an area; if its right |
29 | | is less than or equal to its left, or if its bottom is less than or equal to |
30 | | its top, it is considered empty. |
31 | | */ |
32 | | struct SK_API SkIRect { |
33 | | int32_t fLeft = 0; //!< smaller x-axis bounds |
34 | | int32_t fTop = 0; //!< smaller y-axis bounds |
35 | | int32_t fRight = 0; //!< larger x-axis bounds |
36 | | int32_t fBottom = 0; //!< larger y-axis bounds |
37 | | |
38 | | /** Returns constructed SkIRect set to (0, 0, 0, 0). |
39 | | Many other rectangles are empty; if left is equal to or greater than right, |
40 | | or if top is equal to or greater than bottom. Setting all members to zero |
41 | | is a convenience, but does not designate a special empty rectangle. |
42 | | |
43 | | @return bounds (0, 0, 0, 0) |
44 | | */ |
45 | 1.82M | [[nodiscard]] static constexpr SkIRect MakeEmpty() { |
46 | 1.82M | return SkIRect{0, 0, 0, 0}; |
47 | 1.82M | } |
48 | | |
49 | | /** Returns constructed SkIRect set to (0, 0, w, h). Does not validate input; w or h |
50 | | may be negative. |
51 | | |
52 | | @param w width of constructed SkIRect |
53 | | @param h height of constructed SkIRect |
54 | | @return bounds (0, 0, w, h) |
55 | | */ |
56 | 1.35M | [[nodiscard]] static constexpr SkIRect MakeWH(int32_t w, int32_t h) { |
57 | 1.35M | return SkIRect{0, 0, w, h}; |
58 | 1.35M | } |
59 | | |
60 | | /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()). |
61 | | Does not validate input; size.width() or size.height() may be negative. |
62 | | |
63 | | @param size values for SkIRect width and height |
64 | | @return bounds (0, 0, size.width(), size.height()) |
65 | | */ |
66 | 2.19M | [[nodiscard]] static constexpr SkIRect MakeSize(const SkISize& size) { |
67 | 2.19M | return SkIRect{0, 0, size.fWidth, size.fHeight}; |
68 | 2.19M | } |
69 | | |
70 | | /** Returns constructed SkIRect set to (pt.x(), pt.y(), pt.x() + size.width(), |
71 | | pt.y() + size.height()). Does not validate input; size.width() or size.height() may be |
72 | | negative. |
73 | | |
74 | | @param pt values for SkIRect fLeft and fTop |
75 | | @param size values for SkIRect width and height |
76 | | @return bounds at pt with width and height of size |
77 | | */ |
78 | 95.9k | [[nodiscard]] static constexpr SkIRect MakePtSize(SkIPoint pt, SkISize size) { |
79 | 95.9k | return MakeXYWH(pt.x(), pt.y(), size.width(), size.height()); |
80 | 95.9k | } |
81 | | |
82 | | /** Returns constructed SkIRect set to (l, t, r, b). Does not sort input; SkIRect may |
83 | | result in fLeft greater than fRight, or fTop greater than fBottom. |
84 | | |
85 | | @param l integer stored in fLeft |
86 | | @param t integer stored in fTop |
87 | | @param r integer stored in fRight |
88 | | @param b integer stored in fBottom |
89 | | @return bounds (l, t, r, b) |
90 | | */ |
91 | 339k | [[nodiscard]] static constexpr SkIRect MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b) { |
92 | 339k | return SkIRect{l, t, r, b}; |
93 | 339k | } |
94 | | |
95 | | /** Returns constructed SkIRect set to: (x, y, x + w, y + h). |
96 | | Does not validate input; w or h may be negative. |
97 | | |
98 | | @param x stored in fLeft |
99 | | @param y stored in fTop |
100 | | @param w added to x and stored in fRight |
101 | | @param h added to y and stored in fBottom |
102 | | @return bounds at (x, y) with width w and height h |
103 | | */ |
104 | 918k | [[nodiscard]] static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h) { |
105 | 918k | return { x, y, Sk32_sat_add(x, w), Sk32_sat_add(y, h) }; |
106 | 918k | } |
107 | | |
108 | | /** Returns left edge of SkIRect, if sorted. |
109 | | Call sort() to reverse fLeft and fRight if needed. |
110 | | |
111 | | @return fLeft |
112 | | */ |
113 | 12.2M | constexpr int32_t left() const { return fLeft; } |
114 | | |
115 | | /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid, |
116 | | and sort() to reverse fTop and fBottom if needed. |
117 | | |
118 | | @return fTop |
119 | | */ |
120 | 12.1M | constexpr int32_t top() const { return fTop; } |
121 | | |
122 | | /** Returns right edge of SkIRect, if sorted. |
123 | | Call sort() to reverse fLeft and fRight if needed. |
124 | | |
125 | | @return fRight |
126 | | */ |
127 | 171M | constexpr int32_t right() const { return fRight; } |
128 | | |
129 | | /** Returns bottom edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid, |
130 | | and sort() to reverse fTop and fBottom if needed. |
131 | | |
132 | | @return fBottom |
133 | | */ |
134 | 169M | constexpr int32_t bottom() const { return fBottom; } |
135 | | |
136 | | /** Returns left edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid, |
137 | | and sort() to reverse fLeft and fRight if needed. |
138 | | |
139 | | @return fLeft |
140 | | */ |
141 | 2.66M | constexpr int32_t x() const { return fLeft; } |
142 | | |
143 | | /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid, |
144 | | and sort() to reverse fTop and fBottom if needed. |
145 | | |
146 | | @return fTop |
147 | | */ |
148 | 2.92M | constexpr int32_t y() const { return fTop; } |
149 | | |
150 | | // Experimental |
151 | 209k | constexpr SkIPoint topLeft() const { return {fLeft, fTop}; } |
152 | | |
153 | | /** Returns span on the x-axis. This does not check if SkIRect is sorted, or if |
154 | | result fits in 32-bit signed integer; result may be negative. |
155 | | |
156 | | @return fRight minus fLeft |
157 | | */ |
158 | 29.7M | constexpr int32_t width() const { return Sk32_can_overflow_sub(fRight, fLeft); } |
159 | | |
160 | | /** Returns span on the y-axis. This does not check if SkIRect is sorted, or if |
161 | | result fits in 32-bit signed integer; result may be negative. |
162 | | |
163 | | @return fBottom minus fTop |
164 | | */ |
165 | 157M | constexpr int32_t height() const { return Sk32_can_overflow_sub(fBottom, fTop); } |
166 | | |
167 | | /** Returns spans on the x-axis and y-axis. This does not check if SkIRect is sorted, |
168 | | or if result fits in 32-bit signed integer; result may be negative. |
169 | | |
170 | | @return SkISize (width, height) |
171 | | */ |
172 | 1.09M | constexpr SkISize size() const { return SkISize::Make(this->width(), this->height()); } |
173 | | |
174 | | /** Returns span on the x-axis. This does not check if SkIRect is sorted, so the |
175 | | result may be negative. This is safer than calling width() since width() might |
176 | | overflow in its calculation. |
177 | | |
178 | | @return fRight minus fLeft cast to int64_t |
179 | | */ |
180 | 11.1G | constexpr int64_t width64() const { return (int64_t)fRight - (int64_t)fLeft; } |
181 | | |
182 | | /** Returns span on the y-axis. This does not check if SkIRect is sorted, so the |
183 | | result may be negative. This is safer than calling height() since height() might |
184 | | overflow in its calculation. |
185 | | |
186 | | @return fBottom minus fTop cast to int64_t |
187 | | */ |
188 | 11.1G | constexpr int64_t height64() const { return (int64_t)fBottom - (int64_t)fTop; } |
189 | | |
190 | | /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal |
191 | | to or greater than fBottom. Call sort() to reverse rectangles with negative |
192 | | width64() or height64(). |
193 | | |
194 | | @return true if width64() or height64() are zero or negative |
195 | | */ |
196 | 833k | bool isEmpty64() const { return fRight <= fLeft || fBottom <= fTop; } |
197 | | |
198 | | /** Returns true if width() or height() are zero or negative. |
199 | | |
200 | | @return true if width() or height() are zero or negative |
201 | | */ |
202 | 11.1G | bool isEmpty() const { |
203 | 11.1G | int64_t w = this->width64(); |
204 | 11.1G | int64_t h = this->height64(); |
205 | 11.1G | if (w <= 0 || h <= 0) { |
206 | 10.5G | return true; |
207 | 10.5G | } |
208 | | // Return true if either exceeds int32_t |
209 | 509M | return !SkTFitsIn<int32_t>(w | h); |
210 | 11.1G | } |
211 | | |
212 | | /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are |
213 | | identical to corresponding members in b. |
214 | | |
215 | | @param a SkIRect to compare |
216 | | @param b SkIRect to compare |
217 | | @return true if members are equal |
218 | | */ |
219 | 637k | friend bool operator==(const SkIRect& a, const SkIRect& b) { |
220 | 637k | return a.fLeft == b.fLeft && a.fTop == b.fTop && |
221 | 637k | a.fRight == b.fRight && a.fBottom == b.fBottom; |
222 | 637k | } |
223 | | |
224 | | /** Returns true if any member in a: fLeft, fTop, fRight, and fBottom; is not |
225 | | identical to the corresponding member in b. |
226 | | |
227 | | @param a SkIRect to compare |
228 | | @param b SkIRect to compare |
229 | | @return true if members are not equal |
230 | | */ |
231 | 33.5k | friend bool operator!=(const SkIRect& a, const SkIRect& b) { |
232 | 33.5k | return a.fLeft != b.fLeft || a.fTop != b.fTop || |
233 | 33.5k | a.fRight != b.fRight || a.fBottom != b.fBottom; |
234 | 33.5k | } |
235 | | |
236 | | /** Sets SkIRect to (0, 0, 0, 0). |
237 | | |
238 | | Many other rectangles are empty; if left is equal to or greater than right, |
239 | | or if top is equal to or greater than bottom. Setting all members to zero |
240 | | is a convenience, but does not designate a special empty rectangle. |
241 | | */ |
242 | 310M | void setEmpty() { memset(this, 0, sizeof(*this)); } |
243 | | |
244 | | /** Sets SkIRect to (left, top, right, bottom). |
245 | | left and right are not sorted; left is not necessarily less than right. |
246 | | top and bottom are not sorted; top is not necessarily less than bottom. |
247 | | |
248 | | @param left stored in fLeft |
249 | | @param top stored in fTop |
250 | | @param right stored in fRight |
251 | | @param bottom stored in fBottom |
252 | | */ |
253 | 107M | void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom) { |
254 | 107M | fLeft = left; |
255 | 107M | fTop = top; |
256 | 107M | fRight = right; |
257 | 107M | fBottom = bottom; |
258 | 107M | } |
259 | | |
260 | | /** Sets SkIRect to: (x, y, x + width, y + height). |
261 | | Does not validate input; width or height may be negative. |
262 | | |
263 | | @param x stored in fLeft |
264 | | @param y stored in fTop |
265 | | @param width added to x and stored in fRight |
266 | | @param height added to y and stored in fBottom |
267 | | */ |
268 | 55.4k | void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height) { |
269 | 55.4k | fLeft = x; |
270 | 55.4k | fTop = y; |
271 | 55.4k | fRight = Sk32_sat_add(x, width); |
272 | 55.4k | fBottom = Sk32_sat_add(y, height); |
273 | 55.4k | } |
274 | | |
275 | 620k | void setWH(int32_t width, int32_t height) { |
276 | 620k | fLeft = 0; |
277 | 620k | fTop = 0; |
278 | 620k | fRight = width; |
279 | 620k | fBottom = height; |
280 | 620k | } |
281 | | |
282 | 0 | void setSize(SkISize size) { |
283 | 0 | fLeft = 0; |
284 | 0 | fTop = 0; |
285 | 0 | fRight = size.width(); |
286 | 0 | fBottom = size.height(); |
287 | 0 | } |
288 | | |
289 | | /** Returns SkIRect offset by (dx, dy). |
290 | | |
291 | | If dx is negative, SkIRect returned is moved to the left. |
292 | | If dx is positive, SkIRect returned is moved to the right. |
293 | | If dy is negative, SkIRect returned is moved upward. |
294 | | If dy is positive, SkIRect returned is moved downward. |
295 | | |
296 | | @param dx offset added to fLeft and fRight |
297 | | @param dy offset added to fTop and fBottom |
298 | | @return SkIRect offset by dx and dy, with original width and height |
299 | | */ |
300 | 7.34M | constexpr SkIRect makeOffset(int32_t dx, int32_t dy) const { |
301 | 7.34M | return { |
302 | 7.34M | Sk32_sat_add(fLeft, dx), Sk32_sat_add(fTop, dy), |
303 | 7.34M | Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy), |
304 | 7.34M | }; |
305 | 7.34M | } |
306 | | |
307 | | /** Returns SkIRect offset by (offset.x(), offset.y()). |
308 | | |
309 | | If offset.x() is negative, SkIRect returned is moved to the left. |
310 | | If offset.x() is positive, SkIRect returned is moved to the right. |
311 | | If offset.y() is negative, SkIRect returned is moved upward. |
312 | | If offset.y() is positive, SkIRect returned is moved downward. |
313 | | |
314 | | @param offset translation vector |
315 | | @return SkIRect translated by offset, with original width and height |
316 | | */ |
317 | 131k | constexpr SkIRect makeOffset(SkIVector offset) const { |
318 | 131k | return this->makeOffset(offset.x(), offset.y()); |
319 | 131k | } |
320 | | |
321 | | /** Returns SkIRect, inset by (dx, dy). |
322 | | |
323 | | If dx is negative, SkIRect returned is wider. |
324 | | If dx is positive, SkIRect returned is narrower. |
325 | | If dy is negative, SkIRect returned is taller. |
326 | | If dy is positive, SkIRect returned is shorter. |
327 | | |
328 | | @param dx offset added to fLeft and subtracted from fRight |
329 | | @param dy offset added to fTop and subtracted from fBottom |
330 | | @return SkIRect inset symmetrically left and right, top and bottom |
331 | | */ |
332 | 107k | SkIRect makeInset(int32_t dx, int32_t dy) const { |
333 | 107k | return { |
334 | 107k | Sk32_sat_add(fLeft, dx), Sk32_sat_add(fTop, dy), |
335 | 107k | Sk32_sat_sub(fRight, dx), Sk32_sat_sub(fBottom, dy), |
336 | 107k | }; |
337 | 107k | } |
338 | | |
339 | | /** Returns SkIRect, outset by (dx, dy). |
340 | | |
341 | | If dx is negative, SkIRect returned is narrower. |
342 | | If dx is positive, SkIRect returned is wider. |
343 | | If dy is negative, SkIRect returned is shorter. |
344 | | If dy is positive, SkIRect returned is taller. |
345 | | |
346 | | @param dx offset subtracted to fLeft and added from fRight |
347 | | @param dy offset subtracted to fTop and added from fBottom |
348 | | @return SkIRect outset symmetrically left and right, top and bottom |
349 | | */ |
350 | 315k | SkIRect makeOutset(int32_t dx, int32_t dy) const { |
351 | 315k | return { |
352 | 315k | Sk32_sat_sub(fLeft, dx), Sk32_sat_sub(fTop, dy), |
353 | 315k | Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy), |
354 | 315k | }; |
355 | 315k | } |
356 | | |
357 | | /** Offsets SkIRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom. |
358 | | |
359 | | If dx is negative, moves SkIRect returned to the left. |
360 | | If dx is positive, moves SkIRect returned to the right. |
361 | | If dy is negative, moves SkIRect returned upward. |
362 | | If dy is positive, moves SkIRect returned downward. |
363 | | |
364 | | @param dx offset added to fLeft and fRight |
365 | | @param dy offset added to fTop and fBottom |
366 | | */ |
367 | 76.8M | void offset(int32_t dx, int32_t dy) { |
368 | 76.8M | fLeft = Sk32_sat_add(fLeft, dx); |
369 | 76.8M | fTop = Sk32_sat_add(fTop, dy); |
370 | 76.8M | fRight = Sk32_sat_add(fRight, dx); |
371 | 76.8M | fBottom = Sk32_sat_add(fBottom, dy); |
372 | 76.8M | } |
373 | | |
374 | | /** Offsets SkIRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to |
375 | | fTop, fBottom. |
376 | | |
377 | | If delta.fX is negative, moves SkIRect returned to the left. |
378 | | If delta.fX is positive, moves SkIRect returned to the right. |
379 | | If delta.fY is negative, moves SkIRect returned upward. |
380 | | If delta.fY is positive, moves SkIRect returned downward. |
381 | | |
382 | | @param delta offset added to SkIRect |
383 | | */ |
384 | 11.7k | void offset(const SkIPoint& delta) { |
385 | 11.7k | this->offset(delta.fX, delta.fY); |
386 | 11.7k | } |
387 | | |
388 | | /** Offsets SkIRect so that fLeft equals newX, and fTop equals newY. width and height |
389 | | are unchanged. |
390 | | |
391 | | @param newX stored in fLeft, preserving width() |
392 | | @param newY stored in fTop, preserving height() |
393 | | */ |
394 | 49.9k | void offsetTo(int32_t newX, int32_t newY) { |
395 | 49.9k | fRight = Sk64_pin_to_s32((int64_t)fRight + newX - fLeft); |
396 | 49.9k | fBottom = Sk64_pin_to_s32((int64_t)fBottom + newY - fTop); |
397 | 49.9k | fLeft = newX; |
398 | 49.9k | fTop = newY; |
399 | 49.9k | } |
400 | | |
401 | | /** Insets SkIRect by (dx,dy). |
402 | | |
403 | | If dx is positive, makes SkIRect narrower. |
404 | | If dx is negative, makes SkIRect wider. |
405 | | If dy is positive, makes SkIRect shorter. |
406 | | If dy is negative, makes SkIRect taller. |
407 | | |
408 | | @param dx offset added to fLeft and subtracted from fRight |
409 | | @param dy offset added to fTop and subtracted from fBottom |
410 | | */ |
411 | 782k | void inset(int32_t dx, int32_t dy) { |
412 | 782k | fLeft = Sk32_sat_add(fLeft, dx); |
413 | 782k | fTop = Sk32_sat_add(fTop, dy); |
414 | 782k | fRight = Sk32_sat_sub(fRight, dx); |
415 | 782k | fBottom = Sk32_sat_sub(fBottom, dy); |
416 | 782k | } |
417 | | |
418 | | /** Outsets SkIRect by (dx, dy). |
419 | | |
420 | | If dx is positive, makes SkIRect wider. |
421 | | If dx is negative, makes SkIRect narrower. |
422 | | If dy is positive, makes SkIRect taller. |
423 | | If dy is negative, makes SkIRect shorter. |
424 | | |
425 | | @param dx subtracted to fLeft and added from fRight |
426 | | @param dy subtracted to fTop and added from fBottom |
427 | | */ |
428 | 761k | void outset(int32_t dx, int32_t dy) { this->inset(-dx, -dy); } |
429 | | |
430 | | /** Adjusts SkIRect by adding dL to fLeft, dT to fTop, dR to fRight, and dB to fBottom. |
431 | | |
432 | | If dL is positive, narrows SkIRect on the left. If negative, widens it on the left. |
433 | | If dT is positive, shrinks SkIRect on the top. If negative, lengthens it on the top. |
434 | | If dR is positive, narrows SkIRect on the right. If negative, widens it on the right. |
435 | | If dB is positive, shrinks SkIRect on the bottom. If negative, lengthens it on the bottom. |
436 | | |
437 | | The resulting SkIRect is not checked for validity. Thus, if the resulting SkIRect left is |
438 | | greater than right, the SkIRect will be considered empty. Call sort() after this call |
439 | | if that is not the desired behavior. |
440 | | |
441 | | @param dL offset added to fLeft |
442 | | @param dT offset added to fTop |
443 | | @param dR offset added to fRight |
444 | | @param dB offset added to fBottom |
445 | | */ |
446 | 25.5k | void adjust(int32_t dL, int32_t dT, int32_t dR, int32_t dB) { |
447 | 25.5k | fLeft = Sk32_sat_add(fLeft, dL); |
448 | 25.5k | fTop = Sk32_sat_add(fTop, dT); |
449 | 25.5k | fRight = Sk32_sat_add(fRight, dR); |
450 | 25.5k | fBottom = Sk32_sat_add(fBottom, dB); |
451 | 25.5k | } |
452 | | |
453 | | /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom. |
454 | | Returns false if SkIRect is empty. |
455 | | |
456 | | Considers input to describe constructed SkIRect: (x, y, x + 1, y + 1) and |
457 | | returns true if constructed area is completely enclosed by SkIRect area. |
458 | | |
459 | | @param x test SkIPoint x-coordinate |
460 | | @param y test SkIPoint y-coordinate |
461 | | @return true if (x, y) is inside SkIRect |
462 | | */ |
463 | 35.6k | bool contains(int32_t x, int32_t y) const { |
464 | 35.6k | return x >= fLeft && x < fRight && y >= fTop && y < fBottom; |
465 | 35.6k | } |
466 | | |
467 | | /** Returns true if SkIRect contains r. |
468 | | Returns false if SkIRect is empty or r is empty. |
469 | | |
470 | | SkIRect contains r when SkIRect area completely includes r area. |
471 | | |
472 | | @param r SkIRect contained |
473 | | @return true if all sides of SkIRect are outside r |
474 | | */ |
475 | 106M | bool contains(const SkIRect& r) const { |
476 | 106M | return !r.isEmpty() && !this->isEmpty() && // check for empties |
477 | 106M | fLeft <= r.fLeft && fTop <= r.fTop && |
478 | 106M | fRight >= r.fRight && fBottom >= r.fBottom; |
479 | 106M | } |
480 | | |
481 | | /** Returns true if SkIRect contains r. |
482 | | Returns false if SkIRect is empty or r is empty. |
483 | | |
484 | | SkIRect contains r when SkIRect area completely includes r area. |
485 | | |
486 | | @param r SkRect contained |
487 | | @return true if all sides of SkIRect are outside r |
488 | | */ |
489 | | inline bool contains(const SkRect& r) const; |
490 | | |
491 | | /** Returns true if SkIRect contains construction. |
492 | | Asserts if SkIRect is empty or construction is empty, and if SK_DEBUG is defined. |
493 | | |
494 | | Return is undefined if SkIRect is empty or construction is empty. |
495 | | |
496 | | @param r SkIRect contained |
497 | | @return true if all sides of SkIRect are outside r |
498 | | */ |
499 | 88.7k | bool containsNoEmptyCheck(const SkIRect& r) const { |
500 | 88.7k | SkASSERT(fLeft < fRight && fTop < fBottom); |
501 | 88.7k | SkASSERT(r.fLeft < r.fRight && r.fTop < r.fBottom); |
502 | 88.7k | return fLeft <= r.fLeft && fTop <= r.fTop && fRight >= r.fRight && fBottom >= r.fBottom; |
503 | 88.7k | } SkIRect::containsNoEmptyCheck(SkIRect const&) const Line | Count | Source | 499 | 88.7k | bool containsNoEmptyCheck(const SkIRect& r) const { | 500 | 88.7k | SkASSERT(fLeft < fRight && fTop < fBottom); | 501 | 88.7k | SkASSERT(r.fLeft < r.fRight && r.fTop < r.fBottom); | 502 | 88.7k | return fLeft <= r.fLeft && fTop <= r.fTop && fRight >= r.fRight && fBottom >= r.fBottom; | 503 | 88.7k | } |
Unexecuted instantiation: SkIRect::containsNoEmptyCheck(SkIRect const&) const |
504 | | |
505 | | /** Returns true if SkIRect intersects r, and sets SkIRect to intersection. |
506 | | Returns false if SkIRect does not intersect r, and leaves SkIRect unchanged. |
507 | | |
508 | | Returns false if either r or SkIRect is empty, leaving SkIRect unchanged. |
509 | | |
510 | | @param r limit of result |
511 | | @return true if r and SkIRect have area in common |
512 | | */ |
513 | 5.70M | bool intersect(const SkIRect& r) { |
514 | 5.70M | return this->intersect(*this, r); |
515 | 5.70M | } |
516 | | |
517 | | /** Returns true if a intersects b, and sets SkIRect to intersection. |
518 | | Returns false if a does not intersect b, and leaves SkIRect unchanged. |
519 | | |
520 | | Returns false if either a or b is empty, leaving SkIRect unchanged. |
521 | | |
522 | | @param a SkIRect to intersect |
523 | | @param b SkIRect to intersect |
524 | | @return true if a and b have area in common |
525 | | */ |
526 | | [[nodiscard]] bool intersect(const SkIRect& a, const SkIRect& b); |
527 | | |
528 | | /** Returns true if a intersects b. |
529 | | Returns false if either a or b is empty, or do not intersect. |
530 | | |
531 | | @param a SkIRect to intersect |
532 | | @param b SkIRect to intersect |
533 | | @return true if a and b have area in common |
534 | | */ |
535 | 10.6G | static bool Intersects(const SkIRect& a, const SkIRect& b) { |
536 | 10.6G | return SkIRect{}.intersect(a, b); |
537 | 10.6G | } |
538 | | |
539 | | /** Sets SkIRect to the union of itself and r. |
540 | | |
541 | | Has no effect if r is empty. Otherwise, if SkIRect is empty, sets SkIRect to r. |
542 | | |
543 | | @param r expansion SkIRect |
544 | | |
545 | | example: https://fiddle.skia.org/c/@IRect_join_2 |
546 | | */ |
547 | | void join(const SkIRect& r); |
548 | | |
549 | | /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps |
550 | | fTop and fBottom if fTop is greater than fBottom. Result may be empty, |
551 | | and width() and height() will be zero or positive. |
552 | | */ |
553 | 184k | void sort() { |
554 | 184k | using std::swap; |
555 | 184k | if (fLeft > fRight) { |
556 | 40.3k | swap(fLeft, fRight); |
557 | 40.3k | } |
558 | 184k | if (fTop > fBottom) { |
559 | 32.8k | swap(fTop, fBottom); |
560 | 32.8k | } |
561 | 184k | } |
562 | | |
563 | | /** Returns SkIRect with fLeft and fRight swapped if fLeft is greater than fRight; and |
564 | | with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty; |
565 | | and width() and height() will be zero or positive. |
566 | | |
567 | | @return sorted SkIRect |
568 | | */ |
569 | 0 | SkIRect makeSorted() const { |
570 | 0 | return MakeLTRB(std::min(fLeft, fRight), std::min(fTop, fBottom), |
571 | 0 | std::max(fLeft, fRight), std::max(fTop, fBottom)); |
572 | 0 | } |
573 | | }; |
574 | | |
575 | | /** \struct SkRect |
576 | | SkRect holds four float coordinates describing the upper and |
577 | | lower bounds of a rectangle. SkRect may be created from outer bounds or |
578 | | from position, width, and height. SkRect describes an area; if its right |
579 | | is less than or equal to its left, or if its bottom is less than or equal to |
580 | | its top, it is considered empty. |
581 | | */ |
582 | | struct SK_API SkRect { |
583 | | float fLeft = 0; //!< smaller x-axis bounds |
584 | | float fTop = 0; //!< smaller y-axis bounds |
585 | | float fRight = 0; //!< larger x-axis bounds |
586 | | float fBottom = 0; //!< larger y-axis bounds |
587 | | |
588 | | /** Returns constructed SkRect set to (0, 0, 0, 0). |
589 | | Many other rectangles are empty; if left is equal to or greater than right, |
590 | | or if top is equal to or greater than bottom. Setting all members to zero |
591 | | is a convenience, but does not designate a special empty rectangle. |
592 | | |
593 | | @return bounds (0, 0, 0, 0) |
594 | | */ |
595 | 91.4M | [[nodiscard]] static constexpr SkRect MakeEmpty() { |
596 | 91.4M | return SkRect{0, 0, 0, 0}; |
597 | 91.4M | } |
598 | | |
599 | | /** Returns constructed SkRect set to float values (0, 0, w, h). Does not |
600 | | validate input; w or h may be negative. |
601 | | |
602 | | Passing integer values may generate a compiler warning since SkRect cannot |
603 | | represent 32-bit integers exactly. Use SkIRect for an exact integer rectangle. |
604 | | |
605 | | @param w float width of constructed SkRect |
606 | | @param h float height of constructed SkRect |
607 | | @return bounds (0, 0, w, h) |
608 | | */ |
609 | 266k | [[nodiscard]] static constexpr SkRect MakeWH(float w, float h) { |
610 | 266k | return SkRect{0, 0, w, h}; |
611 | 266k | } |
612 | | |
613 | | /** Returns constructed SkRect set to integer values (0, 0, w, h). Does not validate |
614 | | input; w or h may be negative. |
615 | | |
616 | | Use to avoid a compiler warning that input may lose precision when stored. |
617 | | Use SkIRect for an exact integer rectangle. |
618 | | |
619 | | @param w integer width of constructed SkRect |
620 | | @param h integer height of constructed SkRect |
621 | | @return bounds (0, 0, w, h) |
622 | | */ |
623 | 1.01M | [[nodiscard]] static SkRect MakeIWH(int w, int h) { |
624 | 1.01M | return {0, 0, static_cast<float>(w), static_cast<float>(h)}; |
625 | 1.01M | } |
626 | | |
627 | | /** Returns constructed SkRect set to (0, 0, size.width(), size.height()). Does not |
628 | | validate input; size.width() or size.height() may be negative. |
629 | | |
630 | | @param size float values for SkRect width and height |
631 | | @return bounds (0, 0, size.width(), size.height()) |
632 | | */ |
633 | 69.1k | [[nodiscard]] static constexpr SkRect MakeSize(const SkSize& size) { |
634 | 69.1k | return SkRect{0, 0, size.fWidth, size.fHeight}; |
635 | 69.1k | } |
636 | | |
637 | | /** Returns constructed SkRect set to (l, t, r, b). Does not sort input; SkRect may |
638 | | result in fLeft greater than fRight, or fTop greater than fBottom. |
639 | | |
640 | | @param l float stored in fLeft |
641 | | @param t float stored in fTop |
642 | | @param r float stored in fRight |
643 | | @param b float stored in fBottom |
644 | | @return bounds (l, t, r, b) |
645 | | */ |
646 | 15.9M | [[nodiscard]] static constexpr SkRect MakeLTRB(float l, float t, float r, float b) { |
647 | 15.9M | return SkRect {l, t, r, b}; |
648 | 15.9M | } |
649 | | |
650 | | /** Returns constructed SkRect set to (x, y, x + w, y + h). |
651 | | Does not validate input; w or h may be negative. |
652 | | |
653 | | @param x stored in fLeft |
654 | | @param y stored in fTop |
655 | | @param w added to x and stored in fRight |
656 | | @param h added to y and stored in fBottom |
657 | | @return bounds at (x, y) with width w and height h |
658 | | */ |
659 | 599k | [[nodiscard]] static constexpr SkRect MakeXYWH(float x, float y, float w, float h) { |
660 | 599k | return SkRect {x, y, x + w, y + h}; |
661 | 599k | } |
662 | | |
663 | | /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()). |
664 | | Does not validate input; size.width() or size.height() may be negative. |
665 | | |
666 | | @param size integer values for SkRect width and height |
667 | | @return bounds (0, 0, size.width(), size.height()) |
668 | | */ |
669 | 989k | static SkRect Make(const SkISize& size) { |
670 | 989k | return MakeIWH(size.width(), size.height()); |
671 | 989k | } |
672 | | |
673 | | /** Returns constructed SkIRect set to irect, promoting integers to float. |
674 | | Does not validate input; fLeft may be greater than fRight, fTop may be greater |
675 | | than fBottom. |
676 | | |
677 | | @param irect integer unsorted bounds |
678 | | @return irect members converted to float |
679 | | */ |
680 | 3.03M | [[nodiscard]] static SkRect Make(const SkIRect& irect) { |
681 | 3.03M | return { |
682 | 3.03M | static_cast<float>(irect.fLeft), static_cast<float>(irect.fTop), |
683 | 3.03M | static_cast<float>(irect.fRight), static_cast<float>(irect.fBottom) |
684 | 3.03M | }; |
685 | 3.03M | } |
686 | | |
687 | | /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal |
688 | | to or greater than fBottom. Call sort() to reverse rectangles with negative |
689 | | width() or height(). |
690 | | |
691 | | @return true if width() or height() are zero or negative |
692 | | */ |
693 | 66.4M | bool isEmpty() const { |
694 | | // We write it as the NOT of a non-empty rect, so we will return true if any values |
695 | | // are NaN. |
696 | 66.4M | return !(fLeft < fRight && fTop < fBottom); |
697 | 66.4M | } |
698 | | |
699 | | /** Returns true if fLeft is equal to or less than fRight, or if fTop is equal |
700 | | to or less than fBottom. Call sort() to reverse rectangles with negative |
701 | | width() or height(). |
702 | | |
703 | | @return true if width() or height() are zero or positive |
704 | | */ |
705 | 101k | bool isSorted() const { return fLeft <= fRight && fTop <= fBottom; } |
706 | | |
707 | | /** Returns true if all values in the rectangle are finite. |
708 | | |
709 | | @return true if no member is infinite or NaN |
710 | | */ |
711 | 79.2M | bool isFinite() const { |
712 | 79.2M | return SkIsFinite(fLeft, fTop, fRight, fBottom); |
713 | 79.2M | } |
714 | | |
715 | | /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid. |
716 | | Call sort() to reverse fLeft and fRight if needed. |
717 | | |
718 | | @return fLeft |
719 | | */ |
720 | 8.50k | constexpr float x() const { return fLeft; } |
721 | | |
722 | | /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid, |
723 | | and sort() to reverse fTop and fBottom if needed. |
724 | | |
725 | | @return fTop |
726 | | */ |
727 | 8.51k | constexpr float y() const { return fTop; } |
728 | | |
729 | | /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid. |
730 | | Call sort() to reverse fLeft and fRight if needed. |
731 | | |
732 | | @return fLeft |
733 | | */ |
734 | 159k | constexpr float left() const { return fLeft; } |
735 | | |
736 | | /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid, |
737 | | and sort() to reverse fTop and fBottom if needed. |
738 | | |
739 | | @return fTop |
740 | | */ |
741 | 159k | constexpr float top() const { return fTop; } |
742 | | |
743 | | /** Returns right edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid. |
744 | | Call sort() to reverse fLeft and fRight if needed. |
745 | | |
746 | | @return fRight |
747 | | */ |
748 | 159k | constexpr float right() const { return fRight; } |
749 | | |
750 | | /** Returns bottom edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid, |
751 | | and sort() to reverse fTop and fBottom if needed. |
752 | | |
753 | | @return fBottom |
754 | | */ |
755 | 159k | constexpr float bottom() const { return fBottom; } |
756 | | |
757 | | /** Returns span on the x-axis. This does not check if SkRect is sorted, or if |
758 | | result fits in 32-bit float; result may be negative or infinity. |
759 | | |
760 | | @return fRight minus fLeft |
761 | | */ |
762 | 15.1M | constexpr float width() const { return fRight - fLeft; } |
763 | | |
764 | | /** Returns span on the y-axis. This does not check if SkRect is sorted, or if |
765 | | result fits in 32-bit float; result may be negative or infinity. |
766 | | |
767 | | @return fBottom minus fTop |
768 | | */ |
769 | 5.30M | constexpr float height() const { return fBottom - fTop; } |
770 | | |
771 | | /** Returns average of left edge and right edge. Result does not change if SkRect |
772 | | is sorted. Result may overflow to infinity if SkRect is far from the origin. |
773 | | |
774 | | @return midpoint on x-axis |
775 | | */ |
776 | 320k | constexpr float centerX() const { |
777 | 320k | return sk_float_midpoint(fLeft, fRight); |
778 | 320k | } |
779 | | |
780 | | /** Returns average of top edge and bottom edge. Result does not change if SkRect |
781 | | is sorted. |
782 | | |
783 | | @return midpoint on y-axis |
784 | | */ |
785 | 321k | constexpr float centerY() const { |
786 | 321k | return sk_float_midpoint(fTop, fBottom); |
787 | 321k | } |
788 | | |
789 | | /** Returns the point this->centerX(), this->centerY(). |
790 | | @return rectangle center |
791 | | */ |
792 | 3.32k | constexpr SkPoint center() const { return {this->centerX(), this->centerY()}; } |
793 | | |
794 | | /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are |
795 | | equal to the corresponding members in b. |
796 | | |
797 | | a and b are not equal if either contain NaN. a and b are equal if members |
798 | | contain zeroes with different signs. |
799 | | |
800 | | @param a SkRect to compare |
801 | | @param b SkRect to compare |
802 | | @return true if members are equal |
803 | | */ |
804 | 272k | friend bool operator==(const SkRect& a, const SkRect& b) { |
805 | 272k | return a.fLeft == b.fLeft && |
806 | 272k | a.fTop == b.fTop && |
807 | 272k | a.fRight == b.fRight && |
808 | 272k | a.fBottom == b.fBottom; |
809 | 272k | } |
810 | | |
811 | | /** Returns true if any in a: fLeft, fTop, fRight, and fBottom; does not |
812 | | equal the corresponding members in b. |
813 | | |
814 | | a and b are not equal if either contain NaN. a and b are equal if members |
815 | | contain zeroes with different signs. |
816 | | |
817 | | @param a SkRect to compare |
818 | | @param b SkRect to compare |
819 | | @return true if members are not equal |
820 | | */ |
821 | 57.5k | friend bool operator!=(const SkRect& a, const SkRect& b) { |
822 | 57.5k | return !(a == b); |
823 | 57.5k | } |
824 | | |
825 | | /** Returns four points in quad that enclose SkRect ordered as: top-left, top-right, |
826 | | bottom-right, bottom-left. |
827 | | |
828 | | TODO: Consider adding parameter to control whether quad is clockwise or counterclockwise. |
829 | | |
830 | | @param quad storage for corners of SkRect |
831 | | |
832 | | example: https://fiddle.skia.org/c/@Rect_toQuad |
833 | | */ |
834 | | void toQuad(SkPoint quad[4]) const; |
835 | | |
836 | | /** Sets SkRect to (0, 0, 0, 0). |
837 | | |
838 | | Many other rectangles are empty; if left is equal to or greater than right, |
839 | | or if top is equal to or greater than bottom. Setting all members to zero |
840 | | is a convenience, but does not designate a special empty rectangle. |
841 | | */ |
842 | 85.9M | void setEmpty() { *this = MakeEmpty(); } |
843 | | |
844 | | /** Sets SkRect to src, promoting src members from integer to float. |
845 | | Very large values in src may lose precision. |
846 | | |
847 | | @param src integer SkRect |
848 | | */ |
849 | 33.1M | void set(const SkIRect& src) { |
850 | 33.1M | fLeft = src.fLeft; |
851 | 33.1M | fTop = src.fTop; |
852 | 33.1M | fRight = src.fRight; |
853 | 33.1M | fBottom = src.fBottom; |
854 | 33.1M | } |
855 | | |
856 | | /** Sets SkRect to (left, top, right, bottom). |
857 | | left and right are not sorted; left is not necessarily less than right. |
858 | | top and bottom are not sorted; top is not necessarily less than bottom. |
859 | | |
860 | | @param left stored in fLeft |
861 | | @param top stored in fTop |
862 | | @param right stored in fRight |
863 | | @param bottom stored in fBottom |
864 | | */ |
865 | 165M | void setLTRB(float left, float top, float right, float bottom) { |
866 | 165M | fLeft = left; |
867 | 165M | fTop = top; |
868 | 165M | fRight = right; |
869 | 165M | fBottom = bottom; |
870 | 165M | } |
871 | | |
872 | | /** Sets to bounds of SkPoint array with count entries. If count is zero or smaller, |
873 | | or if SkPoint array contains an infinity or NaN, sets to (0, 0, 0, 0). |
874 | | |
875 | | Result is either empty or sorted: fLeft is less than or equal to fRight, and |
876 | | fTop is less than or equal to fBottom. |
877 | | |
878 | | @param pts SkPoint array |
879 | | @param count entries in array |
880 | | */ |
881 | 140M | void setBounds(const SkPoint pts[], int count) { |
882 | 140M | (void)this->setBoundsCheck(pts, count); |
883 | 140M | } |
884 | | |
885 | | /** Sets to bounds of SkPoint array with count entries. Returns false if count is |
886 | | zero or smaller, or if SkPoint array contains an infinity or NaN; in these cases |
887 | | sets SkRect to (0, 0, 0, 0). |
888 | | |
889 | | Result is either empty or sorted: fLeft is less than or equal to fRight, and |
890 | | fTop is less than or equal to fBottom. |
891 | | |
892 | | @param pts SkPoint array |
893 | | @param count entries in array |
894 | | @return true if all SkPoint values are finite |
895 | | |
896 | | example: https://fiddle.skia.org/c/@Rect_setBoundsCheck |
897 | | */ |
898 | | bool setBoundsCheck(const SkPoint pts[], int count); |
899 | | |
900 | | /** Sets to bounds of SkPoint pts array with count entries. If any SkPoint in pts |
901 | | contains infinity or NaN, all SkRect dimensions are set to NaN. |
902 | | |
903 | | @param pts SkPoint array |
904 | | @param count entries in array |
905 | | |
906 | | example: https://fiddle.skia.org/c/@Rect_setBoundsNoCheck |
907 | | */ |
908 | | void setBoundsNoCheck(const SkPoint pts[], int count); |
909 | | |
910 | | /** Sets bounds to the smallest SkRect enclosing SkPoint p0 and p1. The result is |
911 | | sorted and may be empty. Does not check to see if values are finite. |
912 | | |
913 | | @param p0 corner to include |
914 | | @param p1 corner to include |
915 | | */ |
916 | 10.1M | void set(const SkPoint& p0, const SkPoint& p1) { |
917 | 10.1M | fLeft = std::min(p0.fX, p1.fX); |
918 | 10.1M | fRight = std::max(p0.fX, p1.fX); |
919 | 10.1M | fTop = std::min(p0.fY, p1.fY); |
920 | 10.1M | fBottom = std::max(p0.fY, p1.fY); |
921 | 10.1M | } |
922 | | |
923 | | /** Sets SkRect to (x, y, x + width, y + height). |
924 | | Does not validate input; width or height may be negative. |
925 | | |
926 | | @param x stored in fLeft |
927 | | @param y stored in fTop |
928 | | @param width added to x and stored in fRight |
929 | | @param height added to y and stored in fBottom |
930 | | */ |
931 | 0 | void setXYWH(float x, float y, float width, float height) { |
932 | 0 | fLeft = x; |
933 | 0 | fTop = y; |
934 | 0 | fRight = x + width; |
935 | 0 | fBottom = y + height; |
936 | 0 | } |
937 | | |
938 | | /** Sets SkRect to (0, 0, width, height). Does not validate input; |
939 | | width or height may be negative. |
940 | | |
941 | | @param width stored in fRight |
942 | | @param height stored in fBottom |
943 | | */ |
944 | 243k | void setWH(float width, float height) { |
945 | 243k | fLeft = 0; |
946 | 243k | fTop = 0; |
947 | 243k | fRight = width; |
948 | 243k | fBottom = height; |
949 | 243k | } |
950 | 243k | void setIWH(int32_t width, int32_t height) { |
951 | 243k | this->setWH(width, height); |
952 | 243k | } |
953 | | |
954 | | /** Returns SkRect offset by (dx, dy). |
955 | | |
956 | | If dx is negative, SkRect returned is moved to the left. |
957 | | If dx is positive, SkRect returned is moved to the right. |
958 | | If dy is negative, SkRect returned is moved upward. |
959 | | If dy is positive, SkRect returned is moved downward. |
960 | | |
961 | | @param dx added to fLeft and fRight |
962 | | @param dy added to fTop and fBottom |
963 | | @return SkRect offset on axes, with original width and height |
964 | | */ |
965 | 110k | constexpr SkRect makeOffset(float dx, float dy) const { |
966 | 110k | return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy); |
967 | 110k | } |
968 | | |
969 | | /** Returns SkRect offset by v. |
970 | | |
971 | | @param v added to rect |
972 | | @return SkRect offset on axes, with original width and height |
973 | | */ |
974 | 53.3k | constexpr SkRect makeOffset(SkVector v) const { return this->makeOffset(v.x(), v.y()); } |
975 | | |
976 | | /** Returns SkRect, inset by (dx, dy). |
977 | | |
978 | | If dx is negative, SkRect returned is wider. |
979 | | If dx is positive, SkRect returned is narrower. |
980 | | If dy is negative, SkRect returned is taller. |
981 | | If dy is positive, SkRect returned is shorter. |
982 | | |
983 | | @param dx added to fLeft and subtracted from fRight |
984 | | @param dy added to fTop and subtracted from fBottom |
985 | | @return SkRect inset symmetrically left and right, top and bottom |
986 | | */ |
987 | 1.12M | SkRect makeInset(float dx, float dy) const { |
988 | 1.12M | return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, fBottom - dy); |
989 | 1.12M | } |
990 | | |
991 | | /** Returns SkRect, outset by (dx, dy). |
992 | | |
993 | | If dx is negative, SkRect returned is narrower. |
994 | | If dx is positive, SkRect returned is wider. |
995 | | If dy is negative, SkRect returned is shorter. |
996 | | If dy is positive, SkRect returned is taller. |
997 | | |
998 | | @param dx subtracted to fLeft and added from fRight |
999 | | @param dy subtracted to fTop and added from fBottom |
1000 | | @return SkRect outset symmetrically left and right, top and bottom |
1001 | | */ |
1002 | 488k | SkRect makeOutset(float dx, float dy) const { |
1003 | 488k | return MakeLTRB(fLeft - dx, fTop - dy, fRight + dx, fBottom + dy); |
1004 | 488k | } |
1005 | | |
1006 | | /** Offsets SkRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom. |
1007 | | |
1008 | | If dx is negative, moves SkRect to the left. |
1009 | | If dx is positive, moves SkRect to the right. |
1010 | | If dy is negative, moves SkRect upward. |
1011 | | If dy is positive, moves SkRect downward. |
1012 | | |
1013 | | @param dx offset added to fLeft and fRight |
1014 | | @param dy offset added to fTop and fBottom |
1015 | | */ |
1016 | 166k | void offset(float dx, float dy) { |
1017 | 166k | fLeft += dx; |
1018 | 166k | fTop += dy; |
1019 | 166k | fRight += dx; |
1020 | 166k | fBottom += dy; |
1021 | 166k | } |
1022 | | |
1023 | | /** Offsets SkRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to |
1024 | | fTop, fBottom. |
1025 | | |
1026 | | If delta.fX is negative, moves SkRect to the left. |
1027 | | If delta.fX is positive, moves SkRect to the right. |
1028 | | If delta.fY is negative, moves SkRect upward. |
1029 | | If delta.fY is positive, moves SkRect downward. |
1030 | | |
1031 | | @param delta added to SkRect |
1032 | | */ |
1033 | 0 | void offset(const SkPoint& delta) { |
1034 | 0 | this->offset(delta.fX, delta.fY); |
1035 | 0 | } |
1036 | | |
1037 | | /** Offsets SkRect so that fLeft equals newX, and fTop equals newY. width and height |
1038 | | are unchanged. |
1039 | | |
1040 | | @param newX stored in fLeft, preserving width() |
1041 | | @param newY stored in fTop, preserving height() |
1042 | | */ |
1043 | 0 | void offsetTo(float newX, float newY) { |
1044 | 0 | fRight += newX - fLeft; |
1045 | 0 | fBottom += newY - fTop; |
1046 | 0 | fLeft = newX; |
1047 | 0 | fTop = newY; |
1048 | 0 | } |
1049 | | |
1050 | | /** Insets SkRect by (dx, dy). |
1051 | | |
1052 | | If dx is positive, makes SkRect narrower. |
1053 | | If dx is negative, makes SkRect wider. |
1054 | | If dy is positive, makes SkRect shorter. |
1055 | | If dy is negative, makes SkRect taller. |
1056 | | |
1057 | | @param dx added to fLeft and subtracted from fRight |
1058 | | @param dy added to fTop and subtracted from fBottom |
1059 | | */ |
1060 | 2.96M | void inset(float dx, float dy) { |
1061 | 2.96M | fLeft += dx; |
1062 | 2.96M | fTop += dy; |
1063 | 2.96M | fRight -= dx; |
1064 | 2.96M | fBottom -= dy; |
1065 | 2.96M | } |
1066 | | |
1067 | | /** Outsets SkRect by (dx, dy). |
1068 | | |
1069 | | If dx is positive, makes SkRect wider. |
1070 | | If dx is negative, makes SkRect narrower. |
1071 | | If dy is positive, makes SkRect taller. |
1072 | | If dy is negative, makes SkRect shorter. |
1073 | | |
1074 | | @param dx subtracted to fLeft and added from fRight |
1075 | | @param dy subtracted to fTop and added from fBottom |
1076 | | */ |
1077 | 2.79M | void outset(float dx, float dy) { this->inset(-dx, -dy); } |
1078 | | |
1079 | | /** Returns true if SkRect intersects r, and sets SkRect to intersection. |
1080 | | Returns false if SkRect does not intersect r, and leaves SkRect unchanged. |
1081 | | |
1082 | | Returns false if either r or SkRect is empty, leaving SkRect unchanged. |
1083 | | |
1084 | | @param r limit of result |
1085 | | @return true if r and SkRect have area in common |
1086 | | |
1087 | | example: https://fiddle.skia.org/c/@Rect_intersect |
1088 | | */ |
1089 | | bool intersect(const SkRect& r); |
1090 | | |
1091 | | /** Returns true if a intersects b, and sets SkRect to intersection. |
1092 | | Returns false if a does not intersect b, and leaves SkRect unchanged. |
1093 | | |
1094 | | Returns false if either a or b is empty, leaving SkRect unchanged. |
1095 | | |
1096 | | @param a SkRect to intersect |
1097 | | @param b SkRect to intersect |
1098 | | @return true if a and b have area in common |
1099 | | */ |
1100 | | [[nodiscard]] bool intersect(const SkRect& a, const SkRect& b); |
1101 | | |
1102 | | |
1103 | | private: |
1104 | | static bool Intersects(float al, float at, float ar, float ab, |
1105 | 546k | float bl, float bt, float br, float bb) { |
1106 | 546k | float L = std::max(al, bl); |
1107 | 546k | float R = std::min(ar, br); |
1108 | 546k | float T = std::max(at, bt); |
1109 | 546k | float B = std::min(ab, bb); |
1110 | 546k | return L < R && T < B; |
1111 | 546k | } |
1112 | | |
1113 | | public: |
1114 | | |
1115 | | /** Returns true if SkRect intersects r. |
1116 | | Returns false if either r or SkRect is empty, or do not intersect. |
1117 | | |
1118 | | @param r SkRect to intersect |
1119 | | @return true if r and SkRect have area in common |
1120 | | */ |
1121 | 540k | bool intersects(const SkRect& r) const { |
1122 | 540k | return Intersects(fLeft, fTop, fRight, fBottom, |
1123 | 540k | r.fLeft, r.fTop, r.fRight, r.fBottom); |
1124 | 540k | } |
1125 | | |
1126 | | /** Returns true if a intersects b. |
1127 | | Returns false if either a or b is empty, or do not intersect. |
1128 | | |
1129 | | @param a SkRect to intersect |
1130 | | @param b SkRect to intersect |
1131 | | @return true if a and b have area in common |
1132 | | */ |
1133 | 6.20k | static bool Intersects(const SkRect& a, const SkRect& b) { |
1134 | 6.20k | return Intersects(a.fLeft, a.fTop, a.fRight, a.fBottom, |
1135 | 6.20k | b.fLeft, b.fTop, b.fRight, b.fBottom); |
1136 | 6.20k | } |
1137 | | |
1138 | | /** Sets SkRect to the union of itself and r. |
1139 | | |
1140 | | Has no effect if r is empty. Otherwise, if SkRect is empty, sets |
1141 | | SkRect to r. |
1142 | | |
1143 | | @param r expansion SkRect |
1144 | | |
1145 | | example: https://fiddle.skia.org/c/@Rect_join_2 |
1146 | | */ |
1147 | | void join(const SkRect& r); |
1148 | | |
1149 | | /** Sets SkRect to the union of itself and r. |
1150 | | |
1151 | | Asserts if r is empty and SK_DEBUG is defined. |
1152 | | If SkRect is empty, sets SkRect to r. |
1153 | | |
1154 | | May produce incorrect results if r is empty. |
1155 | | |
1156 | | @param r expansion SkRect |
1157 | | */ |
1158 | 0 | void joinNonEmptyArg(const SkRect& r) { |
1159 | 0 | SkASSERT(!r.isEmpty()); |
1160 | | // if we are empty, just assign |
1161 | 0 | if (fLeft >= fRight || fTop >= fBottom) { |
1162 | 0 | *this = r; |
1163 | 0 | } else { |
1164 | 0 | this->joinPossiblyEmptyRect(r); |
1165 | 0 | } |
1166 | 0 | } Unexecuted instantiation: SkRect::joinNonEmptyArg(SkRect const&) Unexecuted instantiation: SkRect::joinNonEmptyArg(SkRect const&) |
1167 | | |
1168 | | /** Sets SkRect to the union of itself and the construction. |
1169 | | |
1170 | | May produce incorrect results if SkRect or r is empty. |
1171 | | |
1172 | | @param r expansion SkRect |
1173 | | */ |
1174 | 107k | void joinPossiblyEmptyRect(const SkRect& r) { |
1175 | 107k | fLeft = std::min(fLeft, r.left()); |
1176 | 107k | fTop = std::min(fTop, r.top()); |
1177 | 107k | fRight = std::max(fRight, r.right()); |
1178 | 107k | fBottom = std::max(fBottom, r.bottom()); |
1179 | 107k | } |
1180 | | |
1181 | | /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom. |
1182 | | Returns false if SkRect is empty. |
1183 | | |
1184 | | @param x test SkPoint x-coordinate |
1185 | | @param y test SkPoint y-coordinate |
1186 | | @return true if (x, y) is inside SkRect |
1187 | | */ |
1188 | 7.65k | bool contains(float x, float y) const { |
1189 | 7.65k | return x >= fLeft && x < fRight && y >= fTop && y < fBottom; |
1190 | 7.65k | } |
1191 | | |
1192 | | /** Returns true if SkRect contains r. |
1193 | | Returns false if SkRect is empty or r is empty. |
1194 | | |
1195 | | SkRect contains r when SkRect area completely includes r area. |
1196 | | |
1197 | | @param r SkRect contained |
1198 | | @return true if all sides of SkRect are outside r |
1199 | | */ |
1200 | 29.5M | bool contains(const SkRect& r) const { |
1201 | | // todo: can we eliminate the this->isEmpty check? |
1202 | 29.5M | return !r.isEmpty() && !this->isEmpty() && |
1203 | 29.5M | fLeft <= r.fLeft && fTop <= r.fTop && |
1204 | 29.5M | fRight >= r.fRight && fBottom >= r.fBottom; |
1205 | 29.5M | } |
1206 | | |
1207 | | /** Returns true if SkRect contains r. |
1208 | | Returns false if SkRect is empty or r is empty. |
1209 | | |
1210 | | SkRect contains r when SkRect area completely includes r area. |
1211 | | |
1212 | | @param r SkIRect contained |
1213 | | @return true if all sides of SkRect are outside r |
1214 | | */ |
1215 | 839 | bool contains(const SkIRect& r) const { |
1216 | | // todo: can we eliminate the this->isEmpty check? |
1217 | 839 | return !r.isEmpty() && !this->isEmpty() && |
1218 | 839 | fLeft <= r.fLeft && fTop <= r.fTop && |
1219 | 839 | fRight >= r.fRight && fBottom >= r.fBottom; |
1220 | 839 | } |
1221 | | |
1222 | | /** Sets SkIRect by adding 0.5 and discarding the fractional portion of SkRect |
1223 | | members, using (sk_float_round2int(fLeft), sk_float_round2int(fTop), |
1224 | | sk_float_round2int(fRight), sk_float_round2int(fBottom)). |
1225 | | |
1226 | | @param dst storage for SkIRect |
1227 | | */ |
1228 | 333k | void round(SkIRect* dst) const { |
1229 | 333k | SkASSERT(dst); |
1230 | 333k | dst->setLTRB(sk_float_round2int(fLeft), sk_float_round2int(fTop), |
1231 | 333k | sk_float_round2int(fRight), sk_float_round2int(fBottom)); |
1232 | 333k | } |
1233 | | |
1234 | | /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding |
1235 | | up fRight and fBottom, using |
1236 | | (sk_float_floor2int(fLeft), sk_float_floor2int(fTop), |
1237 | | sk_float_ceil2int(fRight), sk_float_ceil2int(fBottom)). |
1238 | | |
1239 | | @param dst storage for SkIRect |
1240 | | */ |
1241 | 2.90M | void roundOut(SkIRect* dst) const { |
1242 | 2.90M | SkASSERT(dst); |
1243 | 2.90M | dst->setLTRB(sk_float_floor2int(fLeft), sk_float_floor2int(fTop), |
1244 | 2.90M | sk_float_ceil2int(fRight), sk_float_ceil2int(fBottom)); |
1245 | 2.90M | } |
1246 | | |
1247 | | /** Sets SkRect by discarding the fractional portion of fLeft and fTop; and rounding |
1248 | | up fRight and fBottom, using |
1249 | | (std::floor(fLeft), std::floor(fTop), |
1250 | | std::ceil(fRight), std::ceil(fBottom)). |
1251 | | |
1252 | | @param dst storage for SkRect |
1253 | | */ |
1254 | 111k | void roundOut(SkRect* dst) const { |
1255 | 111k | dst->setLTRB(std::floor(fLeft), std::floor(fTop), |
1256 | 111k | std::ceil(fRight), std::ceil(fBottom)); |
1257 | 111k | } |
1258 | | |
1259 | | /** Sets SkRect by rounding up fLeft and fTop; and discarding the fractional portion |
1260 | | of fRight and fBottom, using |
1261 | | (sk_float_ceil2int(fLeft), sk_float_ceil2int(fTop), |
1262 | | sk_float_floor2int(fRight), sk_float_floor2int(fBottom)). |
1263 | | |
1264 | | @param dst storage for SkIRect |
1265 | | */ |
1266 | 20.6k | void roundIn(SkIRect* dst) const { |
1267 | 20.6k | SkASSERT(dst); |
1268 | 20.6k | dst->setLTRB(sk_float_ceil2int(fLeft), sk_float_ceil2int(fTop), |
1269 | 20.6k | sk_float_floor2int(fRight), sk_float_floor2int(fBottom)); |
1270 | 20.6k | } |
1271 | | |
1272 | | /** Returns SkIRect by adding 0.5 and discarding the fractional portion of SkRect |
1273 | | members, using (sk_float_round2int(fLeft), sk_float_round2int(fTop), |
1274 | | sk_float_round2int(fRight), sk_float_round2int(fBottom)). |
1275 | | |
1276 | | @return rounded SkIRect |
1277 | | */ |
1278 | 211k | SkIRect round() const { |
1279 | 211k | SkIRect ir; |
1280 | 211k | this->round(&ir); |
1281 | 211k | return ir; |
1282 | 211k | } |
1283 | | |
1284 | | /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding |
1285 | | up fRight and fBottom, using |
1286 | | (sk_float_floor2int(fLeft), sk_float_floor2int(fTop), |
1287 | | sk_float_ceil2int(fRight), sk_float_ceil2int(fBottom)). |
1288 | | |
1289 | | @return rounded SkIRect |
1290 | | */ |
1291 | 1.59M | SkIRect roundOut() const { |
1292 | 1.59M | SkIRect ir; |
1293 | 1.59M | this->roundOut(&ir); |
1294 | 1.59M | return ir; |
1295 | 1.59M | } |
1296 | | /** Sets SkIRect by rounding up fLeft and fTop; and discarding the fractional portion |
1297 | | of fRight and fBottom, using |
1298 | | (sk_float_ceil2int(fLeft), sk_float_ceil2int(fTop), |
1299 | | sk_float_floor2int(fRight), sk_float_floor2int(fBottom)). |
1300 | | |
1301 | | @return rounded SkIRect |
1302 | | */ |
1303 | 16.7k | SkIRect roundIn() const { |
1304 | 16.7k | SkIRect ir; |
1305 | 16.7k | this->roundIn(&ir); |
1306 | 16.7k | return ir; |
1307 | 16.7k | } |
1308 | | |
1309 | | /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps |
1310 | | fTop and fBottom if fTop is greater than fBottom. Result may be empty; |
1311 | | and width() and height() will be zero or positive. |
1312 | | */ |
1313 | 334k | void sort() { |
1314 | 334k | using std::swap; |
1315 | 334k | if (fLeft > fRight) { |
1316 | 32.3k | swap(fLeft, fRight); |
1317 | 32.3k | } |
1318 | | |
1319 | 334k | if (fTop > fBottom) { |
1320 | 30.6k | swap(fTop, fBottom); |
1321 | 30.6k | } |
1322 | 334k | } |
1323 | | |
1324 | | /** Returns SkRect with fLeft and fRight swapped if fLeft is greater than fRight; and |
1325 | | with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty; |
1326 | | and width() and height() will be zero or positive. |
1327 | | |
1328 | | @return sorted SkRect |
1329 | | */ |
1330 | 654k | SkRect makeSorted() const { |
1331 | 654k | return MakeLTRB(std::min(fLeft, fRight), std::min(fTop, fBottom), |
1332 | 654k | std::max(fLeft, fRight), std::max(fTop, fBottom)); |
1333 | 654k | } |
1334 | | |
1335 | | /** Returns pointer to first float in SkRect, to treat it as an array with four |
1336 | | entries. |
1337 | | |
1338 | | @return pointer to fLeft |
1339 | | */ |
1340 | 4.11k | const float* asScalars() const { return &fLeft; } |
1341 | | |
1342 | | /** Writes text representation of SkRect to standard output. Set asHex to true to |
1343 | | generate exact binary representations of floating point numbers. |
1344 | | |
1345 | | @param asHex true if SkScalar values are written as hexadecimal |
1346 | | |
1347 | | example: https://fiddle.skia.org/c/@Rect_dump |
1348 | | */ |
1349 | | void dump(bool asHex) const; |
1350 | | |
1351 | | /** Writes text representation of SkRect to standard output. The representation may be |
1352 | | directly compiled as C++ code. Floating point values are written |
1353 | | with limited precision; it may not be possible to reconstruct original SkRect |
1354 | | from output. |
1355 | | */ |
1356 | 0 | void dump() const { this->dump(false); } |
1357 | | |
1358 | | /** Writes text representation of SkRect to standard output. The representation may be |
1359 | | directly compiled as C++ code. Floating point values are written |
1360 | | in hexadecimal to preserve their exact bit pattern. The output reconstructs the |
1361 | | original SkRect. |
1362 | | |
1363 | | Use instead of dump() when submitting |
1364 | | */ |
1365 | 0 | void dumpHex() const { this->dump(true); } |
1366 | | }; |
1367 | | |
1368 | 305 | inline bool SkIRect::contains(const SkRect& r) const { |
1369 | 305 | return !r.isEmpty() && !this->isEmpty() && // check for empties |
1370 | 305 | fLeft <= r.fLeft && fTop <= r.fTop && |
1371 | 305 | fRight >= r.fRight && fBottom >= r.fBottom; |
1372 | 305 | } |
1373 | | |
1374 | | #endif |