* Make FTContour:FTContour comply with the FreeType specification and remove duplicate points in the Bézier curves. Fixes weird rendering errors with some fonts.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
diff --git a/src/FTContour.cpp b/src/FTContour.cpp
index 548322a..fee1e78 100644
--- a/src/FTContour.cpp
+++ b/src/FTContour.cpp
@@ -31,7 +31,7 @@
#include <math.h>
-static const float BEZIER_STEP_SIZE = 0.2f;
+static const unsigned int BEZIER_STEPS = 5;
void FTContour::AddPoint(FTPoint point)
@@ -64,9 +64,9 @@ void FTContour::AddBackPoint(FTPoint point)
void FTContour::evaluateQuadraticCurve(FTPoint A, FTPoint B, FTPoint C)
{
- for(unsigned int i = 0; i <= (1.0f / BEZIER_STEP_SIZE); i++)
+ for(unsigned int i = 1; i < BEZIER_STEPS; i++)
{
- float t = static_cast<float>(i) * BEZIER_STEP_SIZE;
+ float t = static_cast<float>(i) / BEZIER_STEPS;
FTPoint U = (1.0f - t) * A + t * B;
FTPoint V = (1.0f - t) * B + t * C;
@@ -75,11 +75,12 @@ void FTContour::evaluateQuadraticCurve(FTPoint A, FTPoint B, FTPoint C)
}
}
+
void FTContour::evaluateCubicCurve(FTPoint A, FTPoint B, FTPoint C, FTPoint D)
{
- for(unsigned int i = 0; i <= (1.0f / BEZIER_STEP_SIZE); i++)
+ for(unsigned int i = 0; i < BEZIER_STEPS; i++)
{
- float t = static_cast<float>(i) * BEZIER_STEP_SIZE;
+ float t = static_cast<float>(i) / BEZIER_STEPS;
FTPoint U = (1.0f - t) * A + t * B;
FTPoint V = (1.0f - t) * B + t * C;
@@ -156,54 +157,48 @@ void FTContour::outsetContour()
}
}
+
FTContour::FTContour(FT_Vector* contour, char* tags, unsigned int n)
{
- for(unsigned int i = 0; i < n; ++ i)
+ // See http://freetype.sourceforge.net/freetype2/docs/glyphs/glyphs-6.html
+ // for a full description of FreeType tags.
+ for(unsigned int i = 0; i < n; i++)
{
- if(tags[i] == FT_Curve_Tag_On || n < 2)
+ FTPoint cur(contour[i]);
+
+ // Only process point tags we know.
+ if(n < 2 || FT_CURVE_TAG(tags[i]) == FT_Curve_Tag_On)
{
- AddPoint(FTPoint(contour[i]));
- continue;
+ AddPoint(cur);
}
-
- FTPoint cur(contour[i]);
- FTPoint prev = (pointList.size() == 0 || i == 0)
- ? FTPoint(contour[n - 1])
- : pointList[pointList.size() - 1];
- FTPoint next = (i == n - 1)
- ? (pointList.size() == 0)
- ? FTPoint(contour[0])
- : pointList[0]
- : FTPoint(contour[i + 1]);
-
- if(tags[i] == FT_Curve_Tag_Conic)
+ else if(FT_CURVE_TAG(tags[i]) == FT_Curve_Tag_Conic)
{
- while(tags[(i == n - 1) ? 0 : i + 1] == FT_Curve_Tag_Conic)
+ // Previous point is either the real previous point (an "on"
+ // point), or the midpoint between the current one and the
+ // previous "conic off" point.
+ FTPoint prev(contour[(i - 1 + n) % n]);
+ if(FT_CURVE_TAG(tags[(i - 1 + n) % n]) == FT_Curve_Tag_Conic)
{
- next = (cur + next) * 0.5f;
-
- evaluateQuadraticCurve(prev, cur, next);
- ++i;
+ prev = (cur + prev) * 0.5;
+ AddPoint(prev);
+ }
- prev = next;
- cur = FTPoint(contour[i]);
- next = (i == n - 1)
- ? pointList[0]
- : FTPoint(contour[i + 1]);
+ // Next point is either the real next point or the midpoint.
+ FTPoint next(contour[(i + 1) % n]);
+ if(FT_CURVE_TAG(tags[(i + 1) % n]) == FT_Curve_Tag_Conic)
+ {
+ next = (cur + next) * 0.5;
}
evaluateQuadraticCurve(prev, cur, next);
- continue;
}
-
- if(tags[i] == FT_Curve_Tag_Cubic)
+ else if(FT_CURVE_TAG(tags[i]) == FT_Curve_Tag_Cubic
+ && FT_CURVE_TAG(tags[(i + 1) % n]) == FT_Curve_Tag_Cubic)
{
- FTPoint next2 = (i == n - 2)
- ? pointList[0]
- : FTPoint(contour[i + 2]);
- evaluateCubicCurve(prev, cur, next, next2);
- ++i;
- continue;
+ evaluateCubicCurve(FTPoint(contour[(i - 1 + n) % n]),
+ cur,
+ FTPoint(contour[(i + 1) % n]),
+ FTPoint(contour[(i + 2) % n]));
}
}
@@ -211,6 +206,7 @@ FTContour::FTContour(FT_Vector* contour, char* tags, unsigned int n)
outsetContour();
}
+
void FTContour::buildFrontOutset(float outset)
{
for(size_t i = 0; i < PointCount(); ++i)