Path: blob/master/thirdparty/msdfgen/core/Contour.cpp
9902 views
1#include "Contour.h"23#include "arithmetics.hpp"45namespace msdfgen {67static double shoelace(const Point2 &a, const Point2 &b) {8return (b.x-a.x)*(a.y+b.y);9}1011void Contour::addEdge(const EdgeHolder &edge) {12edges.push_back(edge);13}1415#ifdef MSDFGEN_USE_CPP1116void Contour::addEdge(EdgeHolder &&edge) {17edges.push_back((EdgeHolder &&) edge);18}19#endif2021EdgeHolder &Contour::addEdge() {22edges.resize(edges.size()+1);23return edges.back();24}2526static void boundPoint(double &l, double &b, double &r, double &t, Point2 p) {27if (p.x < l) l = p.x;28if (p.y < b) b = p.y;29if (p.x > r) r = p.x;30if (p.y > t) t = p.y;31}3233void Contour::bound(double &l, double &b, double &r, double &t) const {34for (std::vector<EdgeHolder>::const_iterator edge = edges.begin(); edge != edges.end(); ++edge)35(*edge)->bound(l, b, r, t);36}3738void Contour::boundMiters(double &l, double &b, double &r, double &t, double border, double miterLimit, int polarity) const {39if (edges.empty())40return;41Vector2 prevDir = edges.back()->direction(1).normalize(true);42for (std::vector<EdgeHolder>::const_iterator edge = edges.begin(); edge != edges.end(); ++edge) {43Vector2 dir = -(*edge)->direction(0).normalize(true);44if (polarity*crossProduct(prevDir, dir) >= 0) {45double miterLength = miterLimit;46double q = .5*(1-dotProduct(prevDir, dir));47if (q > 0)48miterLength = min(1/sqrt(q), miterLimit);49Point2 miter = (*edge)->point(0)+border*miterLength*(prevDir+dir).normalize(true);50boundPoint(l, b, r, t, miter);51}52prevDir = (*edge)->direction(1).normalize(true);53}54}5556int Contour::winding() const {57if (edges.empty())58return 0;59double total = 0;60if (edges.size() == 1) {61Point2 a = edges[0]->point(0), b = edges[0]->point(1/3.), c = edges[0]->point(2/3.);62total += shoelace(a, b);63total += shoelace(b, c);64total += shoelace(c, a);65} else if (edges.size() == 2) {66Point2 a = edges[0]->point(0), b = edges[0]->point(.5), c = edges[1]->point(0), d = edges[1]->point(.5);67total += shoelace(a, b);68total += shoelace(b, c);69total += shoelace(c, d);70total += shoelace(d, a);71} else {72Point2 prev = edges.back()->point(0);73for (std::vector<EdgeHolder>::const_iterator edge = edges.begin(); edge != edges.end(); ++edge) {74Point2 cur = (*edge)->point(0);75total += shoelace(prev, cur);76prev = cur;77}78}79return sign(total);80}8182void Contour::reverse() {83for (int i = (int) edges.size()/2; i > 0; --i)84EdgeHolder::swap(edges[i-1], edges[edges.size()-i]);85for (std::vector<EdgeHolder>::iterator edge = edges.begin(); edge != edges.end(); ++edge)86(*edge)->reverse();87}8889}909192