Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/msdfgen/core/contour-combiners.cpp
9902 views
1
2
#include "contour-combiners.h"
3
4
#include <cfloat>
5
#include "arithmetics.hpp"
6
7
namespace msdfgen {
8
9
static void initDistance(double &distance) {
10
distance = -DBL_MAX;
11
}
12
13
static void initDistance(MultiDistance &distance) {
14
distance.r = -DBL_MAX;
15
distance.g = -DBL_MAX;
16
distance.b = -DBL_MAX;
17
}
18
19
static void initDistance(MultiAndTrueDistance &distance) {
20
distance.r = -DBL_MAX;
21
distance.g = -DBL_MAX;
22
distance.b = -DBL_MAX;
23
distance.a = -DBL_MAX;
24
}
25
26
static double resolveDistance(double distance) {
27
return distance;
28
}
29
30
static double resolveDistance(const MultiDistance &distance) {
31
return median(distance.r, distance.g, distance.b);
32
}
33
34
template <class EdgeSelector>
35
SimpleContourCombiner<EdgeSelector>::SimpleContourCombiner(const Shape &shape) { }
36
37
template <class EdgeSelector>
38
void SimpleContourCombiner<EdgeSelector>::reset(const Point2 &p) {
39
shapeEdgeSelector.reset(p);
40
}
41
42
template <class EdgeSelector>
43
EdgeSelector &SimpleContourCombiner<EdgeSelector>::edgeSelector(int) {
44
return shapeEdgeSelector;
45
}
46
47
template <class EdgeSelector>
48
typename SimpleContourCombiner<EdgeSelector>::DistanceType SimpleContourCombiner<EdgeSelector>::distance() const {
49
return shapeEdgeSelector.distance();
50
}
51
52
template class SimpleContourCombiner<TrueDistanceSelector>;
53
template class SimpleContourCombiner<PerpendicularDistanceSelector>;
54
template class SimpleContourCombiner<MultiDistanceSelector>;
55
template class SimpleContourCombiner<MultiAndTrueDistanceSelector>;
56
57
template <class EdgeSelector>
58
OverlappingContourCombiner<EdgeSelector>::OverlappingContourCombiner(const Shape &shape) {
59
windings.reserve(shape.contours.size());
60
for (std::vector<Contour>::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour)
61
windings.push_back(contour->winding());
62
edgeSelectors.resize(shape.contours.size());
63
}
64
65
template <class EdgeSelector>
66
void OverlappingContourCombiner<EdgeSelector>::reset(const Point2 &p) {
67
this->p = p;
68
for (typename std::vector<EdgeSelector>::iterator contourEdgeSelector = edgeSelectors.begin(); contourEdgeSelector != edgeSelectors.end(); ++contourEdgeSelector)
69
contourEdgeSelector->reset(p);
70
}
71
72
template <class EdgeSelector>
73
EdgeSelector &OverlappingContourCombiner<EdgeSelector>::edgeSelector(int i) {
74
return edgeSelectors[i];
75
}
76
77
template <class EdgeSelector>
78
typename OverlappingContourCombiner<EdgeSelector>::DistanceType OverlappingContourCombiner<EdgeSelector>::distance() const {
79
int contourCount = (int) edgeSelectors.size();
80
EdgeSelector shapeEdgeSelector;
81
EdgeSelector innerEdgeSelector;
82
EdgeSelector outerEdgeSelector;
83
shapeEdgeSelector.reset(p);
84
innerEdgeSelector.reset(p);
85
outerEdgeSelector.reset(p);
86
for (int i = 0; i < contourCount; ++i) {
87
DistanceType edgeDistance = edgeSelectors[i].distance();
88
shapeEdgeSelector.merge(edgeSelectors[i]);
89
if (windings[i] > 0 && resolveDistance(edgeDistance) >= 0)
90
innerEdgeSelector.merge(edgeSelectors[i]);
91
if (windings[i] < 0 && resolveDistance(edgeDistance) <= 0)
92
outerEdgeSelector.merge(edgeSelectors[i]);
93
}
94
95
DistanceType shapeDistance = shapeEdgeSelector.distance();
96
DistanceType innerDistance = innerEdgeSelector.distance();
97
DistanceType outerDistance = outerEdgeSelector.distance();
98
double innerScalarDistance = resolveDistance(innerDistance);
99
double outerScalarDistance = resolveDistance(outerDistance);
100
DistanceType distance;
101
initDistance(distance);
102
103
int winding = 0;
104
if (innerScalarDistance >= 0 && fabs(innerScalarDistance) <= fabs(outerScalarDistance)) {
105
distance = innerDistance;
106
winding = 1;
107
for (int i = 0; i < contourCount; ++i)
108
if (windings[i] > 0) {
109
DistanceType contourDistance = edgeSelectors[i].distance();
110
if (fabs(resolveDistance(contourDistance)) < fabs(outerScalarDistance) && resolveDistance(contourDistance) > resolveDistance(distance))
111
distance = contourDistance;
112
}
113
} else if (outerScalarDistance <= 0 && fabs(outerScalarDistance) < fabs(innerScalarDistance)) {
114
distance = outerDistance;
115
winding = -1;
116
for (int i = 0; i < contourCount; ++i)
117
if (windings[i] < 0) {
118
DistanceType contourDistance = edgeSelectors[i].distance();
119
if (fabs(resolveDistance(contourDistance)) < fabs(innerScalarDistance) && resolveDistance(contourDistance) < resolveDistance(distance))
120
distance = contourDistance;
121
}
122
} else
123
return shapeDistance;
124
125
for (int i = 0; i < contourCount; ++i)
126
if (windings[i] != winding) {
127
DistanceType contourDistance = edgeSelectors[i].distance();
128
if (resolveDistance(contourDistance)*resolveDistance(distance) >= 0 && fabs(resolveDistance(contourDistance)) < fabs(resolveDistance(distance)))
129
distance = contourDistance;
130
}
131
if (resolveDistance(distance) == resolveDistance(shapeDistance))
132
distance = shapeDistance;
133
return distance;
134
}
135
136
template class OverlappingContourCombiner<TrueDistanceSelector>;
137
template class OverlappingContourCombiner<PerpendicularDistanceSelector>;
138
template class OverlappingContourCombiner<MultiDistanceSelector>;
139
template class OverlappingContourCombiner<MultiAndTrueDistanceSelector>;
140
141
}
142
143