Coverage Report

Created: 2021-08-22 09:07

/src/skia/src/core/SkRect.cpp
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
#include "include/core/SkRect.h"
9
10
#include "include/private/SkMalloc.h"
11
#include "src/core/SkRectPriv.h"
12
13
5.96M
bool SkIRect::intersect(const SkIRect& a, const SkIRect& b) {
14
5.96M
    SkIRect tmp = {
15
5.96M
        std::max(a.fLeft,   b.fLeft),
16
5.96M
        std::max(a.fTop,    b.fTop),
17
5.96M
        std::min(a.fRight,  b.fRight),
18
5.96M
        std::min(a.fBottom, b.fBottom)
19
5.96M
    };
20
5.96M
    if (tmp.isEmpty()) {
21
1.80M
        return false;
22
1.80M
    }
23
4.16M
    *this = tmp;
24
4.16M
    return true;
25
4.16M
}
26
27
372k
void SkIRect::join(const SkIRect& r) {
28
    // do nothing if the params are empty
29
372k
    if (r.fLeft >= r.fRight || r.fTop >= r.fBottom) {
30
39.2k
        return;
31
39.2k
    }
32
33
    // if we are empty, just assign
34
333k
    if (fLeft >= fRight || fTop >= fBottom) {
35
22.5k
        *this = r;
36
310k
    } else {
37
310k
        if (r.fLeft < fLeft)     fLeft = r.fLeft;
38
310k
        if (r.fTop < fTop)       fTop = r.fTop;
39
310k
        if (r.fRight > fRight)   fRight = r.fRight;
40
310k
        if (r.fBottom > fBottom) fBottom = r.fBottom;
41
310k
    }
42
333k
}
43
44
/////////////////////////////////////////////////////////////////////////////
45
46
112k
void SkRect::toQuad(SkPoint quad[4]) const {
47
112k
    SkASSERT(quad);
48
49
112k
    quad[0].set(fLeft, fTop);
50
112k
    quad[1].set(fRight, fTop);
51
112k
    quad[2].set(fRight, fBottom);
52
112k
    quad[3].set(fLeft, fBottom);
53
112k
}
54
55
#include "include/private/SkNx.h"
56
57
223M
bool SkRect::setBoundsCheck(const SkPoint pts[], int count) {
58
223M
    SkASSERT((pts && count > 0) || count == 0);
59
60
223M
    if (count <= 0) {
61
98.5k
        this->setEmpty();
62
98.5k
        return true;
63
98.5k
    }
64
65
223M
    Sk4s min, max;
66
223M
    if (count & 1) {
67
206M
        min = max = Sk4s(pts->fX, pts->fY,
68
206M
                         pts->fX, pts->fY);
69
206M
        pts   += 1;
70
206M
        count -= 1;
71
16.3M
    } else {
72
16.3M
        min = max = Sk4s::Load(pts);
73
16.3M
        pts   += 2;
74
16.3M
        count -= 2;
75
16.3M
    }
76
77
223M
    Sk4s accum = min * 0;
78
1.70G
    while (count) {
79
1.48G
        Sk4s xy = Sk4s::Load(pts);
80
1.48G
        accum = accum * xy;
81
1.48G
        min = Sk4s::Min(min, xy);
82
1.48G
        max = Sk4s::Max(max, xy);
83
1.48G
        pts   += 2;
84
1.48G
        count -= 2;
85
1.48G
    }
86
87
223M
    bool all_finite = (accum * 0 == 0).allTrue();
88
223M
    if (all_finite) {
89
223M
        this->setLTRB(std::min(min[0], min[2]), std::min(min[1], min[3]),
90
223M
                      std::max(max[0], max[2]), std::max(max[1], max[3]));
91
164k
    } else {
92
164k
        this->setEmpty();
93
164k
    }
94
223M
    return all_finite;
95
223M
}
96
97
112k
void SkRect::setBoundsNoCheck(const SkPoint pts[], int count) {
98
112k
    if (!this->setBoundsCheck(pts, count)) {
99
6.84k
        this->setLTRB(SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN);
100
6.84k
    }
101
112k
}
102
103
#define CHECK_INTERSECT(al, at, ar, ab, bl, bt, br, bb) \
104
611k
    SkScalar L = std::max(al, bl);                   \
105
611k
    SkScalar R = std::min(ar, br);                   \
106
611k
    SkScalar T = std::max(at, bt);                   \
107
611k
    SkScalar B = std::min(ab, bb);                   \
108
611k
    do { if (!(L < R && T < B)) return false; } while (0)
109
    // do the !(opposite) check so we return false if either arg is NaN
110
111
607k
bool SkRect::intersect(const SkRect& r) {
112
607k
    CHECK_INTERSECT(r.fLeft, r.fTop, r.fRight, r.fBottom, fLeft, fTop, fRight, fBottom);
113
398k
    this->setLTRB(L, T, R, B);
114
398k
    return true;
115
607k
}
116
117
4.57k
bool SkRect::intersect(const SkRect& a, const SkRect& b) {
118
4.57k
    CHECK_INTERSECT(a.fLeft, a.fTop, a.fRight, a.fBottom, b.fLeft, b.fTop, b.fRight, b.fBottom);
119
4.33k
    this->setLTRB(L, T, R, B);
120
4.33k
    return true;
121
4.57k
}
122
123
6.10M
void SkRect::join(const SkRect& r) {
124
6.10M
    if (r.isEmpty()) {
125
5.54M
        return;
126
5.54M
    }
127
128
558k
    if (this->isEmpty()) {
129
112k
        *this = r;
130
445k
    } else {
131
445k
        fLeft   = std::min(fLeft, r.fLeft);
132
445k
        fTop    = std::min(fTop, r.fTop);
133
445k
        fRight  = std::max(fRight, r.fRight);
134
445k
        fBottom = std::max(fBottom, r.fBottom);
135
445k
    }
136
558k
}
137
138
////////////////////////////////////////////////////////////////////////////////////////////////
139
140
#include "include/core/SkString.h"
141
#include "src/core/SkStringUtils.h"
142
143
0
static const char* set_scalar(SkString* storage, SkScalar value, SkScalarAsStringType asType) {
144
0
    storage->reset();
145
0
    SkAppendScalar(storage, value, asType);
146
0
    return storage->c_str();
147
0
}
148
149
0
void SkRect::dump(bool asHex) const {
150
0
    SkScalarAsStringType asType = asHex ? kHex_SkScalarAsStringType : kDec_SkScalarAsStringType;
151
152
0
    SkString line;
153
0
    if (asHex) {
154
0
        SkString tmp;
155
0
        line.printf( "SkRect::MakeLTRB(%s, /* %f */\n", set_scalar(&tmp, fLeft, asType), fLeft);
156
0
        line.appendf("                 %s, /* %f */\n", set_scalar(&tmp, fTop, asType), fTop);
157
0
        line.appendf("                 %s, /* %f */\n", set_scalar(&tmp, fRight, asType), fRight);
158
0
        line.appendf("                 %s  /* %f */);", set_scalar(&tmp, fBottom, asType), fBottom);
159
0
    } else {
160
0
        SkString strL, strT, strR, strB;
161
0
        SkAppendScalarDec(&strL, fLeft);
162
0
        SkAppendScalarDec(&strT, fTop);
163
0
        SkAppendScalarDec(&strR, fRight);
164
0
        SkAppendScalarDec(&strB, fBottom);
165
0
        line.printf("SkRect::MakeLTRB(%s, %s, %s, %s);",
166
0
                    strL.c_str(), strT.c_str(), strR.c_str(), strB.c_str());
167
0
    }
168
0
    SkDebugf("%s\n", line.c_str());
169
0
}
170
171
////////////////////////////////////////////////////////////////////////////////////////////////
172
173
template<typename R, typename C>
174
24.6k
static bool subtract(const R& a, const R& b, R* out) {
175
24.6k
    static constexpr C kZero = C(0);
176
177
24.6k
    if (!R::Intersects(a, b)) {
178
        // Either already empty, or subtracting the empty rect, or there's no intersection, so
179
        // in all cases the answer is A.
180
18.8k
        *out = a;
181
18.8k
        return true;
182
18.8k
    }
183
184
    // 4 rectangles to consider. If the edge in A is contained in B, the resulting difference can
185
    // be represented exactly as a rectangle. Otherwise the difference is the largest subrectangle
186
    // that is disjoint from B:
187
    // 1. Left part of A:   (A.left,  A.top,    B.left,  A.bottom)
188
    // 2. Right part of A:  (B.right, A.top,    A.right, A.bottom)
189
    // 3. Top part of A:    (A.left,  A.top,    A.right, B.top)
190
    // 4. Bottom part of A: (A.left,  B.bottom, A.right, A.bottom)
191
192
5.73k
    C height = a.height();
193
5.73k
    C width = a.width();
194
195
    // Compute the areas of the 4 rects described above. Depending on how B intersects A, there
196
    // will be 1 to 4 positive areas:
197
    //  - 4 occur when A contains B
198
    //  - 3 occur when B intersects a single edge
199
    //  - 2 occur when B intersects at a corner, or spans two opposing edges
200
    //  - 1 occurs when B spans two opposing edges and contains a 3rd, resulting in an exact rect
201
    //  - 0 occurs when B contains A, resulting in the empty rect
202
5.73k
    C leftArea = kZero, rightArea = kZero, topArea = kZero, bottomArea = kZero;
203
5.73k
    int positiveCount = 0;
204
5.73k
    if (b.fLeft > a.fLeft) {
205
3.72k
        leftArea = (b.fLeft - a.fLeft) * height;
206
3.72k
        positiveCount++;
207
3.72k
    }
208
5.73k
    if (a.fRight > b.fRight) {
209
5.30k
        rightArea = (a.fRight - b.fRight) * height;
210
5.30k
        positiveCount++;
211
5.30k
    }
212
5.73k
    if (b.fTop > a.fTop) {
213
4.52k
        topArea = (b.fTop - a.fTop) * width;
214
4.52k
        positiveCount++;
215
4.52k
    }
216
5.73k
    if (a.fBottom > b.fBottom) {
217
1.72k
        bottomArea = (a.fBottom - b.fBottom) * width;
218
1.72k
        positiveCount++;
219
1.72k
    }
220
221
5.73k
    if (positiveCount == 0) {
222
15
        SkASSERT(b.contains(a));
223
15
        *out = R::MakeEmpty();
224
15
        return true;
225
15
    }
226
227
5.72k
    *out = a;
228
5.72k
    if (leftArea > rightArea && leftArea > topArea && leftArea > bottomArea) {
229
        // Left chunk of A, so the new right edge is B's left edge
230
158
        out->fRight = b.fLeft;
231
5.56k
    } else if (rightArea > topArea && rightArea > bottomArea) {
232
        // Right chunk of A, so the new left edge is B's right edge
233
3.67k
        out->fLeft = b.fRight;
234
1.89k
    } else if (topArea > bottomArea) {
235
        // Top chunk of A, so the new bottom edge is B's top edge
236
317
        out->fBottom = b.fTop;
237
1.57k
    } else {
238
        // Bottom chunk of A, so the new top edge is B's bottom edge
239
1.57k
        SkASSERT(bottomArea > kZero);
240
1.57k
        out->fTop = b.fBottom;
241
1.57k
    }
242
243
    // If we have 1 valid area, the disjoint shape is representable as a rectangle.
244
5.72k
    SkASSERT(!R::Intersects(*out, b));
245
5.72k
    return positiveCount == 1;
246
5.72k
}
Unexecuted instantiation: SkRect.cpp:bool subtract<SkRect, float>(SkRect const&, SkRect const&, SkRect*)
SkRect.cpp:bool subtract<SkIRect, int>(SkIRect const&, SkIRect const&, SkIRect*)
Line
Count
Source
174
24.6k
static bool subtract(const R& a, const R& b, R* out) {
175
24.6k
    static constexpr C kZero = C(0);
176
177
24.6k
    if (!R::Intersects(a, b)) {
178
        // Either already empty, or subtracting the empty rect, or there's no intersection, so
179
        // in all cases the answer is A.
180
18.8k
        *out = a;
181
18.8k
        return true;
182
18.8k
    }
183
184
    // 4 rectangles to consider. If the edge in A is contained in B, the resulting difference can
185
    // be represented exactly as a rectangle. Otherwise the difference is the largest subrectangle
186
    // that is disjoint from B:
187
    // 1. Left part of A:   (A.left,  A.top,    B.left,  A.bottom)
188
    // 2. Right part of A:  (B.right, A.top,    A.right, A.bottom)
189
    // 3. Top part of A:    (A.left,  A.top,    A.right, B.top)
190
    // 4. Bottom part of A: (A.left,  B.bottom, A.right, A.bottom)
191
192
5.73k
    C height = a.height();
193
5.73k
    C width = a.width();
194
195
    // Compute the areas of the 4 rects described above. Depending on how B intersects A, there
196
    // will be 1 to 4 positive areas:
197
    //  - 4 occur when A contains B
198
    //  - 3 occur when B intersects a single edge
199
    //  - 2 occur when B intersects at a corner, or spans two opposing edges
200
    //  - 1 occurs when B spans two opposing edges and contains a 3rd, resulting in an exact rect
201
    //  - 0 occurs when B contains A, resulting in the empty rect
202
5.73k
    C leftArea = kZero, rightArea = kZero, topArea = kZero, bottomArea = kZero;
203
5.73k
    int positiveCount = 0;
204
5.73k
    if (b.fLeft > a.fLeft) {
205
3.72k
        leftArea = (b.fLeft - a.fLeft) * height;
206
3.72k
        positiveCount++;
207
3.72k
    }
208
5.73k
    if (a.fRight > b.fRight) {
209
5.30k
        rightArea = (a.fRight - b.fRight) * height;
210
5.30k
        positiveCount++;
211
5.30k
    }
212
5.73k
    if (b.fTop > a.fTop) {
213
4.52k
        topArea = (b.fTop - a.fTop) * width;
214
4.52k
        positiveCount++;
215
4.52k
    }
216
5.73k
    if (a.fBottom > b.fBottom) {
217
1.72k
        bottomArea = (a.fBottom - b.fBottom) * width;
218
1.72k
        positiveCount++;
219
1.72k
    }
220
221
5.73k
    if (positiveCount == 0) {
222
15
        SkASSERT(b.contains(a));
223
15
        *out = R::MakeEmpty();
224
15
        return true;
225
15
    }
226
227
5.72k
    *out = a;
228
5.72k
    if (leftArea > rightArea && leftArea > topArea && leftArea > bottomArea) {
229
        // Left chunk of A, so the new right edge is B's left edge
230
158
        out->fRight = b.fLeft;
231
5.56k
    } else if (rightArea > topArea && rightArea > bottomArea) {
232
        // Right chunk of A, so the new left edge is B's right edge
233
3.67k
        out->fLeft = b.fRight;
234
1.89k
    } else if (topArea > bottomArea) {
235
        // Top chunk of A, so the new bottom edge is B's top edge
236
317
        out->fBottom = b.fTop;
237
1.57k
    } else {
238
        // Bottom chunk of A, so the new top edge is B's bottom edge
239
1.57k
        SkASSERT(bottomArea > kZero);
240
1.57k
        out->fTop = b.fBottom;
241
1.57k
    }
242
243
    // If we have 1 valid area, the disjoint shape is representable as a rectangle.
244
5.72k
    SkASSERT(!R::Intersects(*out, b));
245
5.72k
    return positiveCount == 1;
246
5.72k
}
Unexecuted instantiation: SkRect.cpp:bool subtract<SkRect, float>(SkRect const&, SkRect const&, SkRect*)
247
248
0
bool SkRectPriv::Subtract(const SkRect& a, const SkRect& b, SkRect* out) {
249
0
    return subtract<SkRect, SkScalar>(a, b, out);
250
0
}
251
252
24.6k
bool SkRectPriv::Subtract(const SkIRect& a, const SkIRect& b, SkIRect* out) {
253
24.6k
    return subtract<SkIRect, int>(a, b, out);
254
24.6k
}