Coverage Report

Created: 2024-05-20 07:14

/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