Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/msdfgen/core/Contour.cpp
9902 views
1
2
#include "Contour.h"
3
4
#include "arithmetics.hpp"
5
6
namespace msdfgen {
7
8
static double shoelace(const Point2 &a, const Point2 &b) {
9
return (b.x-a.x)*(a.y+b.y);
10
}
11
12
void Contour::addEdge(const EdgeHolder &edge) {
13
edges.push_back(edge);
14
}
15
16
#ifdef MSDFGEN_USE_CPP11
17
void Contour::addEdge(EdgeHolder &&edge) {
18
edges.push_back((EdgeHolder &&) edge);
19
}
20
#endif
21
22
EdgeHolder &Contour::addEdge() {
23
edges.resize(edges.size()+1);
24
return edges.back();
25
}
26
27
static void boundPoint(double &l, double &b, double &r, double &t, Point2 p) {
28
if (p.x < l) l = p.x;
29
if (p.y < b) b = p.y;
30
if (p.x > r) r = p.x;
31
if (p.y > t) t = p.y;
32
}
33
34
void Contour::bound(double &l, double &b, double &r, double &t) const {
35
for (std::vector<EdgeHolder>::const_iterator edge = edges.begin(); edge != edges.end(); ++edge)
36
(*edge)->bound(l, b, r, t);
37
}
38
39
void Contour::boundMiters(double &l, double &b, double &r, double &t, double border, double miterLimit, int polarity) const {
40
if (edges.empty())
41
return;
42
Vector2 prevDir = edges.back()->direction(1).normalize(true);
43
for (std::vector<EdgeHolder>::const_iterator edge = edges.begin(); edge != edges.end(); ++edge) {
44
Vector2 dir = -(*edge)->direction(0).normalize(true);
45
if (polarity*crossProduct(prevDir, dir) >= 0) {
46
double miterLength = miterLimit;
47
double q = .5*(1-dotProduct(prevDir, dir));
48
if (q > 0)
49
miterLength = min(1/sqrt(q), miterLimit);
50
Point2 miter = (*edge)->point(0)+border*miterLength*(prevDir+dir).normalize(true);
51
boundPoint(l, b, r, t, miter);
52
}
53
prevDir = (*edge)->direction(1).normalize(true);
54
}
55
}
56
57
int Contour::winding() const {
58
if (edges.empty())
59
return 0;
60
double total = 0;
61
if (edges.size() == 1) {
62
Point2 a = edges[0]->point(0), b = edges[0]->point(1/3.), c = edges[0]->point(2/3.);
63
total += shoelace(a, b);
64
total += shoelace(b, c);
65
total += shoelace(c, a);
66
} else if (edges.size() == 2) {
67
Point2 a = edges[0]->point(0), b = edges[0]->point(.5), c = edges[1]->point(0), d = edges[1]->point(.5);
68
total += shoelace(a, b);
69
total += shoelace(b, c);
70
total += shoelace(c, d);
71
total += shoelace(d, a);
72
} else {
73
Point2 prev = edges.back()->point(0);
74
for (std::vector<EdgeHolder>::const_iterator edge = edges.begin(); edge != edges.end(); ++edge) {
75
Point2 cur = (*edge)->point(0);
76
total += shoelace(prev, cur);
77
prev = cur;
78
}
79
}
80
return sign(total);
81
}
82
83
void Contour::reverse() {
84
for (int i = (int) edges.size()/2; i > 0; --i)
85
EdgeHolder::swap(edges[i-1], edges[edges.size()-i]);
86
for (std::vector<EdgeHolder>::iterator edge = edges.begin(); edge != edges.end(); ++edge)
87
(*edge)->reverse();
88
}
89
90
}
91
92