Created
August 25, 2016 03:11
-
-
Save ryanbartley/e089279b81cf5ee59b3750cdf8f2bcb7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
bool loadGlyph(Shape &output, FT_Face face, unsigned int glyphIndex, double *advance) { | |
enum PointType { | |
NONE = 0, | |
PATH_POINT, | |
QUADRATIC_POINT, | |
CUBIC_POINT, | |
CUBIC_POINT2 | |
}; | |
auto pointTypeOutput = []( PointType type ) { | |
switch ( type ) { | |
case NONE: return "NONE"; break; | |
case PATH_POINT: return "PATH_POINT"; break; | |
case QUADRATIC_POINT: return "QUADRATIC_POINT"; break; | |
case CUBIC_POINT: return "CUBIC_POINT"; break; | |
case CUBIC_POINT2: return "CUBIC_POINT2"; break; | |
default: return "unknown"; break; | |
} | |
}; | |
if (nullptr == face) | |
return false; | |
FT_Error error = FT_Load_Glyph(face, glyphIndex, FT_LOAD_NO_SCALE); | |
if (error) | |
return false; | |
output.contours.clear(); | |
output.inverseYAxis = false; | |
if (advance) | |
*advance = face->glyph->advance.x/64.; | |
float glyphScale = 2048.0f / face->units_per_EM; | |
int last = -1; | |
if ( glyphIndex == 83 || glyphIndex == 51 ) { | |
std::cout << "-------------------------------------------" << std::endl; | |
std::cout << "Num contours: " << face->glyph->outline.n_contours << " glyph: " << glyphIndex << std::endl; | |
} | |
// For each contour | |
for (int i = 0; i < face->glyph->outline.n_contours; ++i) { | |
Contour &contour = output.addContour(); | |
int first = last+1; | |
int firstPathPoint = -1; | |
last = face->glyph->outline.contours[i]; | |
PointType state = NONE; | |
Point2 startPoint; | |
Point2 controlPoint[2]; | |
if ( glyphIndex == 83 || glyphIndex == 51 ) | |
std::cout << "Outer For Loop: " << i << std::endl; | |
// For each point on the contour | |
for (int round = 0, index = first; round == 0; ++index) { | |
if ( glyphIndex == 83 || glyphIndex == 51 ) | |
std::cout << "round: " << round << " index: " << index << " first: " << first << " last: " << last << std::endl; | |
if (index > last) { | |
if (!(firstPathPoint >= 0)) | |
return false; | |
index = first; | |
} | |
// Close contour | |
if (index == firstPathPoint) | |
++round; | |
Point2 point( glyphScale * face->glyph->outline.points[index].x/64., glyphScale * face->glyph->outline.points[index].y/64.); | |
PointType pointType = face->glyph->outline.tags[index]&1 ? PATH_POINT : face->glyph->outline.tags[index]&2 ? CUBIC_POINT : QUADRATIC_POINT; | |
switch (state) { | |
case NONE: | |
if (pointType == PATH_POINT) {// || (pointType == QUADRATIC_POINT && index > 2)) { | |
firstPathPoint = index; | |
startPoint = point; | |
state = PATH_POINT; | |
} | |
if ( glyphIndex == 83 || glyphIndex == 51 ) | |
std::cout << "state: " << pointTypeOutput( state ) << " pointType: " << pointTypeOutput( pointType ) << std::endl; | |
break; | |
case PATH_POINT: | |
if (pointType == PATH_POINT) { | |
contour.addEdge(new LinearSegment(startPoint, point)); | |
startPoint = point; | |
} else { | |
controlPoint[0] = point; | |
state = pointType; | |
} | |
if ( glyphIndex == 83 || glyphIndex == 51 ) | |
std::cout << "state: " << pointTypeOutput( state ) << " pointType: " << pointTypeOutput( pointType ) << std::endl; | |
break; | |
case QUADRATIC_POINT: | |
if (!(pointType != CUBIC_POINT)) | |
return false; | |
if (pointType == PATH_POINT) { | |
contour.addEdge(new QuadraticSegment(startPoint, controlPoint[0], point)); | |
startPoint = point; | |
state = PATH_POINT; | |
} else { | |
Point2 midPoint = .5*controlPoint[0]+.5*point; | |
contour.addEdge(new QuadraticSegment(startPoint, controlPoint[0], midPoint)); | |
startPoint = midPoint; | |
controlPoint[0] = point; | |
} | |
if ( glyphIndex == 83 || glyphIndex == 51 ) | |
std::cout << "state: " << pointTypeOutput( state ) << " pointType: " << pointTypeOutput( pointType ) << std::endl; | |
break; | |
case CUBIC_POINT: | |
if (!(pointType == CUBIC_POINT)) | |
return false;; | |
controlPoint[1] = point; | |
state = CUBIC_POINT2; | |
if ( glyphIndex == 83 || glyphIndex == 51 ) | |
std::cout << "state: " << pointTypeOutput( state ) << " pointType: " << pointTypeOutput( pointType ) << std::endl; | |
break; | |
case CUBIC_POINT2: | |
if (!(pointType != QUADRATIC_POINT)) | |
return false; | |
if (pointType == PATH_POINT) { | |
contour.addEdge(new CubicSegment(startPoint, controlPoint[0], controlPoint[1], point)); | |
startPoint = point; | |
} else { | |
Point2 midPoint = .5*controlPoint[1]+.5*point; | |
contour.addEdge(new CubicSegment(startPoint, controlPoint[0], controlPoint[1], midPoint)); | |
startPoint = midPoint; | |
controlPoint[0] = point; | |
} | |
state = pointType; | |
if ( glyphIndex == 83 || glyphIndex == 51 ) | |
std::cout << "state: " << pointTypeOutput( state ) << " pointType: " << pointTypeOutput( pointType ) << std::endl; | |
break; | |
} | |
} | |
} | |
return true;} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment