Browse Source

[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.
James Godfrey-Kittle 9 years ago
parent
commit
0b96a9418d
1 changed files with 22 additions and 22 deletions
  1. 22 22
      third_party/fontcrunch/quadopt.cc

+ 22 - 22
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<Statelet> 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<Break>* 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<Quad> optimize(const Thetas& curve) {
+vector<Quad> optimize(const Thetas& curve, double penalty=1) {
 	vector<Break> breaks;
 	findBreaks(&breaks, curve);
 	int n = breaks.size() - 1;
 	vector<State> 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<Quad>* 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) {