Coverage Report

Created: 2025-06-24 08:20

/src/skia/modules/pathops/src/SkIntersections.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2012 Google Inc.
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 "modules/pathops/src/SkIntersections.h"
9
10
#include <cstring>
11
12
int SkIntersections::closestTo(double rangeStart, double rangeEnd, const SkDPoint& testPt,
13
1.74M
        double* closestDist) const {
14
1.74M
    int closest = -1;
15
1.74M
    *closestDist = SK_ScalarMax;
16
3.34M
    for (int index = 0; index < fUsed; ++index) {
17
1.59M
        if (!between(rangeStart, fT[0][index], rangeEnd)) {
18
606k
            continue;
19
606k
        }
20
989k
        const SkDPoint& iPt = fPt[index];
21
989k
        double dist = testPt.distanceSquared(iPt);
22
989k
        if (*closestDist > dist) {
23
850k
            *closestDist = dist;
24
850k
            closest = index;
25
850k
        }
26
989k
    }
27
1.74M
    return closest;
28
1.74M
}
29
30
4.76M
void SkIntersections::flip() {
31
9.00M
    for (int index = 0; index < fUsed; ++index) {
32
4.24M
        fT[1][index] = 1 - fT[1][index];
33
4.24M
    }
34
4.76M
}
35
36
217M
int SkIntersections::insert(double one, double two, const SkDPoint& pt) {
37
217M
    if (fIsCoincident[0] == 3 && between(fT[0][0], one, fT[0][1])) {
38
        // For now, don't allow a mix of coincident and non-coincident intersections
39
2.75M
        return -1;
40
2.75M
    }
41
214M
    SkASSERT(fUsed <= 1 || fT[0][0] <= fT[0][1]);
42
214M
    int index;
43
237M
    for (index = 0; index < fUsed; ++index) {
44
114M
        double oldOne = fT[0][index];
45
114M
        double oldTwo = fT[1][index];
46
114M
        if (one == oldOne && two == oldTwo) {
47
89.3M
            return -1;
48
89.3M
        }
49
25.3M
        if (more_roughly_equal(oldOne, one) && more_roughly_equal(oldTwo, two)) {
50
2.11M
            if ((!precisely_zero(one) || precisely_zero(oldOne))
51
2.11M
                    && (!precisely_equal(one, 1) || precisely_equal(oldOne, 1))
52
2.11M
                    && (!precisely_zero(two) || precisely_zero(oldTwo))
53
2.11M
                    && (!precisely_equal(two, 1) || precisely_equal(oldTwo, 1))) {
54
938k
                return -1;
55
938k
            }
56
1.18M
            SkASSERT(one >= 0 && one <= 1);
57
1.18M
            SkASSERT(two >= 0 && two <= 1);
58
            // remove this and reinsert below in case replacing would make list unsorted
59
1.18M
            int remaining = fUsed - index - 1;
60
1.18M
            memmove(&fPt[index], &fPt[index + 1], sizeof(fPt[0]) * remaining);
61
1.18M
            memmove(&fT[0][index], &fT[0][index + 1], sizeof(fT[0][0]) * remaining);
62
1.18M
            memmove(&fT[1][index], &fT[1][index + 1], sizeof(fT[1][0]) * remaining);
63
1.18M
            int clearMask = ~((1 << index) - 1);
64
1.18M
            fIsCoincident[0] -= (fIsCoincident[0] >> 1) & clearMask;
65
1.18M
            fIsCoincident[1] -= (fIsCoincident[1] >> 1) & clearMask;
66
1.18M
            --fUsed;
67
1.18M
            break;
68
2.11M
        }
69
    #if ONE_OFF_DEBUG
70
        if (pt.roughlyEqual(fPt[index])) {
71
            SkDebugf("%s t=%1.9g pts roughly equal\n", __FUNCTION__, one);
72
        }
73
    #endif
74
25.3M
    }
75
135M
    for (index = 0; index < fUsed; ++index) {
76
16.8M
        if (fT[0][index] > one) {
77
5.27M
            break;
78
5.27M
        }
79
16.8M
    }
80
124M
    if (fUsed >= fMax) {
81
4.93k
        SkOPASSERT(0);  // FIXME : this error, if it is to be handled at runtime in release, must
82
                      // be propagated all the way back down to the caller, and return failure.
83
4.93k
        fUsed = 0;
84
4.93k
        return 0;
85
4.93k
    }
86
124M
    int remaining = fUsed - index;
87
124M
    if (remaining > 0) {
88
5.26M
        memmove(&fPt[index + 1], &fPt[index], sizeof(fPt[0]) * remaining);
89
5.26M
        memmove(&fT[0][index + 1], &fT[0][index], sizeof(fT[0][0]) * remaining);
90
5.26M
        memmove(&fT[1][index + 1], &fT[1][index], sizeof(fT[1][0]) * remaining);
91
5.26M
        int clearMask = ~((1 << index) - 1);
92
5.26M
        fIsCoincident[0] += fIsCoincident[0] & clearMask;
93
5.26M
        fIsCoincident[1] += fIsCoincident[1] & clearMask;
94
5.26M
    }
95
124M
    fPt[index] = pt;
96
124M
    if (one < 0 || one > 1) {
97
0
        return -1;
98
0
    }
99
124M
    if (two < 0 || two > 1) {
100
0
        return -1;
101
0
    }
102
124M
    fT[0][index] = one;
103
124M
    fT[1][index] = two;
104
124M
    ++fUsed;
105
124M
    SkASSERT(fUsed <= std::size(fPt));
106
124M
    return index;
107
124M
}
SkIntersections::insert(double, double, SkDPoint const&)
Line
Count
Source
36
217M
int SkIntersections::insert(double one, double two, const SkDPoint& pt) {
37
217M
    if (fIsCoincident[0] == 3 && between(fT[0][0], one, fT[0][1])) {
38
        // For now, don't allow a mix of coincident and non-coincident intersections
39
2.75M
        return -1;
40
2.75M
    }
41
214M
    SkASSERT(fUsed <= 1 || fT[0][0] <= fT[0][1]);
42
214M
    int index;
43
237M
    for (index = 0; index < fUsed; ++index) {
44
114M
        double oldOne = fT[0][index];
45
114M
        double oldTwo = fT[1][index];
46
114M
        if (one == oldOne && two == oldTwo) {
47
89.3M
            return -1;
48
89.3M
        }
49
25.3M
        if (more_roughly_equal(oldOne, one) && more_roughly_equal(oldTwo, two)) {
50
2.11M
            if ((!precisely_zero(one) || precisely_zero(oldOne))
51
2.11M
                    && (!precisely_equal(one, 1) || precisely_equal(oldOne, 1))
52
2.11M
                    && (!precisely_zero(two) || precisely_zero(oldTwo))
53
2.11M
                    && (!precisely_equal(two, 1) || precisely_equal(oldTwo, 1))) {
54
938k
                return -1;
55
938k
            }
56
1.18M
            SkASSERT(one >= 0 && one <= 1);
57
1.18M
            SkASSERT(two >= 0 && two <= 1);
58
            // remove this and reinsert below in case replacing would make list unsorted
59
1.18M
            int remaining = fUsed - index - 1;
60
1.18M
            memmove(&fPt[index], &fPt[index + 1], sizeof(fPt[0]) * remaining);
61
1.18M
            memmove(&fT[0][index], &fT[0][index + 1], sizeof(fT[0][0]) * remaining);
62
1.18M
            memmove(&fT[1][index], &fT[1][index + 1], sizeof(fT[1][0]) * remaining);
63
1.18M
            int clearMask = ~((1 << index) - 1);
64
1.18M
            fIsCoincident[0] -= (fIsCoincident[0] >> 1) & clearMask;
65
1.18M
            fIsCoincident[1] -= (fIsCoincident[1] >> 1) & clearMask;
66
1.18M
            --fUsed;
67
1.18M
            break;
68
2.11M
        }
69
    #if ONE_OFF_DEBUG
70
        if (pt.roughlyEqual(fPt[index])) {
71
            SkDebugf("%s t=%1.9g pts roughly equal\n", __FUNCTION__, one);
72
        }
73
    #endif
74
25.3M
    }
75
135M
    for (index = 0; index < fUsed; ++index) {
76
16.8M
        if (fT[0][index] > one) {
77
5.27M
            break;
78
5.27M
        }
79
16.8M
    }
80
124M
    if (fUsed >= fMax) {
81
4.93k
        SkOPASSERT(0);  // FIXME : this error, if it is to be handled at runtime in release, must
82
                      // be propagated all the way back down to the caller, and return failure.
83
4.93k
        fUsed = 0;
84
4.93k
        return 0;
85
4.93k
    }
86
124M
    int remaining = fUsed - index;
87
124M
    if (remaining > 0) {
88
5.26M
        memmove(&fPt[index + 1], &fPt[index], sizeof(fPt[0]) * remaining);
89
5.26M
        memmove(&fT[0][index + 1], &fT[0][index], sizeof(fT[0][0]) * remaining);
90
5.26M
        memmove(&fT[1][index + 1], &fT[1][index], sizeof(fT[1][0]) * remaining);
91
5.26M
        int clearMask = ~((1 << index) - 1);
92
5.26M
        fIsCoincident[0] += fIsCoincident[0] & clearMask;
93
5.26M
        fIsCoincident[1] += fIsCoincident[1] & clearMask;
94
5.26M
    }
95
124M
    fPt[index] = pt;
96
124M
    if (one < 0 || one > 1) {
97
0
        return -1;
98
0
    }
99
124M
    if (two < 0 || two > 1) {
100
0
        return -1;
101
0
    }
102
124M
    fT[0][index] = one;
103
124M
    fT[1][index] = two;
104
124M
    ++fUsed;
105
124M
    SkASSERT(fUsed <= std::size(fPt));
106
124M
    return index;
107
124M
}
Unexecuted instantiation: SkIntersections::insert(double, double, SkDPoint const&)
108
109
441k
void SkIntersections::insertNear(double one, double two, const SkDPoint& pt1, const SkDPoint& pt2) {
110
441k
    SkASSERT(one == 0 || one == 1);
111
441k
    SkASSERT(two == 0 || two == 1);
112
441k
    SkASSERT(pt1 != pt2);
113
441k
    fNearlySame[one ? 1 : 0] = true;
114
441k
    (void) insert(one, two, pt1);
115
441k
    fPt2[one ? 1 : 0] = pt2;
116
441k
}
117
118
4.05M
int SkIntersections::insertCoincident(double one, double two, const SkDPoint& pt) {
119
4.05M
    int index = insertSwap(one, two, pt);
120
4.05M
    if (index >= 0) {
121
3.97M
        setCoincident(index);
122
3.97M
    }
123
4.05M
    return index;
124
4.05M
}
125
126
8.52M
void SkIntersections::setCoincident(int index) {
127
8.52M
    SkASSERT(index >= 0);
128
8.52M
    int bit = 1 << index;
129
8.52M
    fIsCoincident[0] |= bit;
130
8.52M
    fIsCoincident[1] |= bit;
131
8.52M
}
132
133
void SkIntersections::merge(const SkIntersections& a, int aIndex, const SkIntersections& b,
134
3.61M
        int bIndex) {
135
3.61M
    this->reset();
136
3.61M
    fT[0][0] = a.fT[0][aIndex];
137
3.61M
    fT[1][0] = b.fT[0][bIndex];
138
3.61M
    fPt[0] = a.fPt[aIndex];
139
3.61M
    fPt2[0] = b.fPt[bIndex];
140
3.61M
    fUsed = 1;
141
3.61M
}
142
143
8.22M
int SkIntersections::mostOutside(double rangeStart, double rangeEnd, const SkDPoint& origin) const {
144
8.22M
    int result = -1;
145
20.0M
    for (int index = 0; index < fUsed; ++index) {
146
11.7M
        if (!between(rangeStart, fT[0][index], rangeEnd)) {
147
3.04M
            continue;
148
3.04M
        }
149
8.74M
        if (result < 0) {
150
7.44M
            result = index;
151
7.44M
            continue;
152
7.44M
        }
153
1.29M
        SkDVector best = fPt[result] - origin;
154
1.29M
        SkDVector test = fPt[index] - origin;
155
1.29M
        if (test.crossCheck(best) < 0) {
156
49.7k
            result = index;
157
49.7k
        }
158
1.29M
    }
159
8.22M
    return result;
160
8.22M
}
161
162
1.75M
void SkIntersections::removeOne(int index) {
163
1.75M
    int remaining = --fUsed - index;
164
1.75M
    if (remaining <= 0) {
165
726k
        return;
166
726k
    }
167
1.03M
    memmove(&fPt[index], &fPt[index + 1], sizeof(fPt[0]) * remaining);
168
1.03M
    memmove(&fT[0][index], &fT[0][index + 1], sizeof(fT[0][0]) * remaining);
169
1.03M
    memmove(&fT[1][index], &fT[1][index + 1], sizeof(fT[1][0]) * remaining);
170
//    SkASSERT(fIsCoincident[0] == 0);
171
1.03M
    int coBit = fIsCoincident[0] & (1 << index);
172
1.03M
    fIsCoincident[0] -= ((fIsCoincident[0] >> 1) & ~((1 << index) - 1)) + coBit;
173
1.03M
    SkASSERT(!(coBit ^ (fIsCoincident[1] & (1 << index))));
174
1.03M
    fIsCoincident[1] -= ((fIsCoincident[1] >> 1) & ~((1 << index) - 1)) + coBit;
175
1.03M
}