From 0b96a9418ddec3c573f1a5e8705fe9e4d4324904 Mon Sep 17 00:00:00 2001 From: James Godfrey-Kittle Date: Wed, 25 Nov 2015 12:12:47 -0800 Subject: [fontcrunch] Incorporate some upstream changes These are changes from https://github.com/googlefonts/fontcrunch. Not included is the removal of the main function in quadopt.cc, which we obviously need. --- third_party/fontcrunch/quadopt.cc | 44 +++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'third_party/fontcrunch/quadopt.cc') diff --git a/third_party/fontcrunch/quadopt.cc b/third_party/fontcrunch/quadopt.cc index 59f3523..a76da84 100644 --- a/third_party/fontcrunch/quadopt.cc +++ b/third_party/fontcrunch/quadopt.cc @@ -119,8 +119,8 @@ class ArclenFunctor { public: ArclenFunctor(const Quad& q) : dx0(2 * (q.p[1].x - q.p[0].x)) - , dx1(2 * (q.p[2].x - q.p[1].x)) , dy0(2 * (q.p[1].y - q.p[0].y)) + , dx1(2 * (q.p[2].x - q.p[1].x)) , dy1(2 * (q.p[2].y - q.p[1].y)) { } void operator()(double dydx[1], double t, const double y[1]) { Point p(deriv(t)); @@ -224,7 +224,6 @@ Point Thetas::dir(double s) const { // L1 angle norm, 2, L2 angle norm, 0.05 // L1 distance norm, 200 -double penalty = 1; double dist_factor = .005; double angle_factor = 5; @@ -272,7 +271,9 @@ private: // of angle mismatch double measureQuad(const Thetas& curve, double s0, double s1, const Quad& q) { ArclenFunctor derivs(q); - double ss = (s1 - s0) / q.arclen(); + double ss = 0; + if (q.arclen() != 0) + ss = (s1 - s0) / q.arclen(); MeasureFunctor err(curve, s0, ss, derivs, q); const int n = 10; double dt = 1./n; @@ -293,13 +294,13 @@ struct Break { }; struct Statelet { - void combine(const Statelet* prev, double score, Quad q); + void combine(const Statelet* prev, double score, Quad q, double penalty); const Statelet* prev; double score; Quad q; }; -void Statelet::combine(const Statelet* newprev, double newscore, Quad newq) { +void Statelet::combine(const Statelet* newprev, double newscore, Quad newq, double penalty) { prev = newprev; double pmul = 2; if (newq.isLine()) { @@ -313,18 +314,18 @@ void Statelet::combine(const Statelet* newprev, double newscore, Quad newq) { } struct State { - void combine(const State* prev, double score, Quad q); + void combine(const State* prev, double score, Quad q, double penalty); vector sts; bool init; }; -void State::combine(const State* prev, double score, Quad q) { +void State::combine(const State* prev, double score, Quad q, double penalty) { const Statelet* prevsl = prev->sts.empty() ? 0 : &prev->sts[0]; if (prevsl == 0 && !prev->init) { return; } Statelet sl; - sl.combine(prevsl, score, q); + sl.combine(prevsl, score, q, penalty); if (sts.empty()) { sts.push_back(sl); } else { @@ -379,7 +380,7 @@ void findBreaks(vector* breaks, const Thetas& curve) { bool intersect(Point* result, Point p0, Point dir0, Point p1, Point dir1) { double det = dir0.x * dir1.y - dir0.y * dir1.x; - if (std::abs(det) < 1e-6) return false; + if (std::abs(det) < 1e-6 || std::isnan(det)) return false; det = 1 / det; double a = p0.y * dir0.x - p0.x * dir0.y; double b = p1.y * dir1.x - p1.x * dir1.y; @@ -389,47 +390,47 @@ bool intersect(Point* result, Point p0, Point dir0, Point p1, Point dir1) { } void tryQuad(const State* prev, State* st, const Thetas& curve, - const Break& bk0, const Break& bk1, const Quad& q) { + const Break& bk0, const Break& bk1, const Quad& q, double penalty) { double score = measureQuad(curve, bk0.s, bk1.s, q); - st->combine(prev, score, q); + st->combine(prev, score, q, penalty); } void tryLineQuad(const State* prev, State* st, const Thetas& curve, - const Break& bk0, const Break& bk1) { + const Break& bk0, const Break& bk1, double penalty) { if (isInt(bk0.xy.x) && isInt(bk0.xy.y)) { Quad line(bk0.xy, lerp(0.5, bk0.xy, bk1.xy), bk1.xy); - tryQuad(prev, st, curve, bk0, bk1, line); + tryQuad(prev, st, curve, bk0, bk1, line, penalty); } Point pmid; if (intersect(&pmid, bk0.xy, bk0.dir, bk1.xy, bk1.dir)) { Quad q(bk0.xy, round(pmid), bk1.xy); if (okForHalf(prev, q)) { - tryQuad(prev, st, curve, bk0, bk1, q); + tryQuad(prev, st, curve, bk0, bk1, q, penalty); } } } -vector optimize(const Thetas& curve) { +vector optimize(const Thetas& curve, double penalty=1) { vector breaks; findBreaks(&breaks, curve); int n = breaks.size() - 1; vector states; states.resize(n + 1); states[0].init = true; - tryLineQuad(&states[0], &states[n], curve, breaks[0], breaks[n]); + tryLineQuad(&states[0], &states[n], curve, breaks[0], breaks[n], penalty); if (states[n].sts[0].score <= 3 * penalty) { goto done; } for (int i = 1; i < n; i++) { - tryLineQuad(&states[0], &states[i], curve, breaks[0], breaks[i]); - tryLineQuad(&states[i], &states[n], curve, breaks[i], breaks[n]); + tryLineQuad(&states[0], &states[i], curve, breaks[0], breaks[i], penalty); + tryLineQuad(&states[i], &states[n], curve, breaks[i], breaks[n], penalty); } if (states[n].sts[0].score <= 4 * penalty) { goto done; } for (int i = 1; i <= n; i++) { for (int j = i - 1; j >= 0; j--) { - tryLineQuad(&states[j], &states[i], curve, breaks[j], breaks[i]); + tryLineQuad(&states[j], &states[i], curve, breaks[j], breaks[i], penalty); } } done: @@ -447,9 +448,8 @@ void readBzs(vector* result, std::istream& is) { result->push_back(Quad(Point(x0, y0), Point(x1, y1), Point(x2, y2))); } // Round the endpoints, they must be on integers - (*result)[0].p[0] = round((*result)[0].p[0]); - Quad* lastq = &(*result)[(*result).size()]; - lastq->p[2] = round(lastq->p[2]); + result->front().p[0] = round(result->front().p[0]); + result->back().p[2] = round(result->back().p[2]); } int main(int argc, char** argv) { -- cgit v1.2.3