summaryrefslogtreecommitdiff
path: root/thirdparty/msdfgen/core/Contour.cpp
diff options
context:
space:
mode:
authorK. S. Ernest (iFire) Lee <fire@users.noreply.github.com>2021-08-27 08:51:37 -0700
committerGitHub <noreply@github.com>2021-08-27 08:51:37 -0700
commit90a35dac489bcbe39de35af661367519b411cb98 (patch)
tree8b6b4535556be521f9fbbadaebdea04e5316582c /thirdparty/msdfgen/core/Contour.cpp
parentca4f20529c0b6588464f88fc0b0680a8df0fc77f (diff)
parent4c3f7d1290311456519ca2416590c7e62465b7f2 (diff)
Merge pull request #51908 from bruvzg/msdf_fonts2
Make FontData importable resource. Add multi-channel SDF font rendering.
Diffstat (limited to 'thirdparty/msdfgen/core/Contour.cpp')
-rw-r--r--thirdparty/msdfgen/core/Contour.cpp90
1 files changed, 90 insertions, 0 deletions
diff --git a/thirdparty/msdfgen/core/Contour.cpp b/thirdparty/msdfgen/core/Contour.cpp
new file mode 100644
index 0000000000..ca80d3c55a
--- /dev/null
+++ b/thirdparty/msdfgen/core/Contour.cpp
@@ -0,0 +1,90 @@
+
+#include "Contour.h"
+
+#include "arithmetics.hpp"
+
+namespace msdfgen {
+
+static double shoelace(const Point2 &a, const Point2 &b) {
+ return (b.x-a.x)*(a.y+b.y);
+}
+
+void Contour::addEdge(const EdgeHolder &edge) {
+ edges.push_back(edge);
+}
+
+#ifdef MSDFGEN_USE_CPP11
+void Contour::addEdge(EdgeHolder &&edge) {
+ edges.push_back((EdgeHolder &&) edge);
+}
+#endif
+
+EdgeHolder & Contour::addEdge() {
+ edges.resize(edges.size()+1);
+ return edges.back();
+}
+
+static void boundPoint(double &l, double &b, double &r, double &t, Point2 p) {
+ if (p.x < l) l = p.x;
+ if (p.y < b) b = p.y;
+ if (p.x > r) r = p.x;
+ if (p.y > t) t = p.y;
+}
+
+void Contour::bound(double &l, double &b, double &r, double &t) const {
+ for (std::vector<EdgeHolder>::const_iterator edge = edges.begin(); edge != edges.end(); ++edge)
+ (*edge)->bound(l, b, r, t);
+}
+
+void Contour::boundMiters(double &l, double &b, double &r, double &t, double border, double miterLimit, int polarity) const {
+ if (edges.empty())
+ return;
+ Vector2 prevDir = edges.back()->direction(1).normalize(true);
+ for (std::vector<EdgeHolder>::const_iterator edge = edges.begin(); edge != edges.end(); ++edge) {
+ Vector2 dir = -(*edge)->direction(0).normalize(true);
+ if (polarity*crossProduct(prevDir, dir) >= 0) {
+ double miterLength = miterLimit;
+ double q = .5*(1-dotProduct(prevDir, dir));
+ if (q > 0)
+ miterLength = min(1/sqrt(q), miterLimit);
+ Point2 miter = (*edge)->point(0)+border*miterLength*(prevDir+dir).normalize(true);
+ boundPoint(l, b, r, t, miter);
+ }
+ prevDir = (*edge)->direction(1).normalize(true);
+ }
+}
+
+int Contour::winding() const {
+ if (edges.empty())
+ return 0;
+ double total = 0;
+ if (edges.size() == 1) {
+ Point2 a = edges[0]->point(0), b = edges[0]->point(1/3.), c = edges[0]->point(2/3.);
+ total += shoelace(a, b);
+ total += shoelace(b, c);
+ total += shoelace(c, a);
+ } else if (edges.size() == 2) {
+ Point2 a = edges[0]->point(0), b = edges[0]->point(.5), c = edges[1]->point(0), d = edges[1]->point(.5);
+ total += shoelace(a, b);
+ total += shoelace(b, c);
+ total += shoelace(c, d);
+ total += shoelace(d, a);
+ } else {
+ Point2 prev = edges.back()->point(0);
+ for (std::vector<EdgeHolder>::const_iterator edge = edges.begin(); edge != edges.end(); ++edge) {
+ Point2 cur = (*edge)->point(0);
+ total += shoelace(prev, cur);
+ prev = cur;
+ }
+ }
+ return sign(total);
+}
+
+void Contour::reverse() {
+ for (int i = (int) edges.size()/2; i > 0; --i)
+ EdgeHolder::swap(edges[i-1], edges[edges.size()-i]);
+ for (std::vector<EdgeHolder>::iterator edge = edges.begin(); edge != edges.end(); ++edge)
+ (*edge)->reverse();
+}
+
+}