static ofTTFCharacter makeContoursForCharacter(FT_Face &face){ //int num = face->glyph->outline.n_points; int nContours = face->glyph->outline.n_contours; int startPos = 0; char * tags = face->glyph->outline.tags; FT_Vector * vec = face->glyph->outline.points; ofTTFCharacter charOutlines; for(int k = 0; k < nContours; k++){ if( k > 0 ){ startPos = face->glyph->outline.contours[k-1]+1; } int endPos = face->glyph->outline.contours[k]+1; if( printVectorInfo )printf("--NEW CONTOUR\n\n"); vector <ofPoint> testOutline; ofPoint lastPoint; for(int j = startPos; j < endPos; j++){ if( FT_CURVE_TAG(tags[j]) == FT_CURVE_TAG_ON ){ lastPoint.set((float)vec[j].x, (float)-vec[j].y, 0); if( printVectorInfo )printf("flag[%i] is set to 1 - regular point - %f %f \n", j, lastPoint.x, lastPoint.y); testOutline.push_back(lastPoint); }else{ if( printVectorInfo )printf("flag[%i] is set to 0 - control point \n", j); if( FT_CURVE_TAG(tags[j]) == FT_CURVE_TAG_CUBIC ){ if( printVectorInfo )printf("- bit 2 is set to 2 - CUBIC\n"); int prevPoint = j-1; if( j == 0){ prevPoint = endPos-1; } int nextIndex = j+1; if( nextIndex >= endPos){ nextIndex = startPos; } ofPoint nextPoint( (float)vec[nextIndex].x, -(float)vec[nextIndex].y ); //we need two control points to draw a cubic bezier bool lastPointCubic = ( FT_CURVE_TAG(tags[prevPoint]) != FT_CURVE_TAG_ON ) && ( FT_CURVE_TAG(tags[prevPoint]) == FT_CURVE_TAG_CUBIC); if( lastPointCubic ){ ofPoint controlPoint1((float)vec[prevPoint].x, (float)-vec[prevPoint].y); ofPoint controlPoint2((float)vec[j].x, (float)-vec[j].y); ofPoint nextPoint((float) vec[nextIndex].x, -(float) vec[nextIndex].y); cubic_bezier(testOutline, lastPoint.x, lastPoint.y, controlPoint1.x, controlPoint1.y, controlPoint2.x, controlPoint2.y, nextPoint.x, nextPoint.y, 8); } }else{ ofPoint conicPoint( (float)vec[j].x, -(float)vec[j].y ); if( printVectorInfo )printf("- bit 2 is set to 0 - conic- \n"); if( printVectorInfo )printf("--- conicPoint point is %f %f \n", conicPoint.x, conicPoint.y); //If the first point is connic and the last point is connic then we need to create a virutal point which acts as a wrap around if( j == startPos ){ bool prevIsConnic = ( FT_CURVE_TAG( tags[endPos-1] ) != FT_CURVE_TAG_ON ) && ( FT_CURVE_TAG( tags[endPos-1]) != FT_CURVE_TAG_CUBIC ); if( prevIsConnic ){ ofPoint lastConnic((float)vec[endPos - 1].x, (float)-vec[endPos - 1].y); lastPoint = (conicPoint + lastConnic) / 2; if( printVectorInfo ) printf("NEED TO MIX WITH LAST\n"); if( printVectorInfo )printf("last is %f %f \n", lastPoint.x, lastPoint.y); } } //bool doubleConic = false; int nextIndex = j+1; if( nextIndex >= endPos){ nextIndex = startPos; } ofPoint nextPoint( (float)vec[nextIndex].x, -(float)vec[nextIndex].y ); if( printVectorInfo )printf("--- last point is %f %f \n", lastPoint.x, lastPoint.y); bool nextIsConnic = ( FT_CURVE_TAG( tags[nextIndex] ) != FT_CURVE_TAG_ON ) && ( FT_CURVE_TAG( tags[nextIndex]) != FT_CURVE_TAG_CUBIC ); //create a 'virtual on point' if we have two connic points if( nextIsConnic ){ nextPoint = (conicPoint + nextPoint) / 2; if( printVectorInfo )printf("|_______ double connic!\n"); } if( printVectorInfo )printf("--- next point is %f %f \n", nextPoint.x, nextPoint.y); quad_bezier(testOutline, lastPoint.x, lastPoint.y, conicPoint.x, conicPoint.y, nextPoint.x, nextPoint.y, 8); if( nextIsConnic ){ lastPoint = nextPoint; } } } //end for } for(int g =0; g < (int)testOutline.size(); g++){ testOutline[g] /= 64.0f; } charOutlines.contours.push_back(ofTTFContour()); if( testOutline.size() ){ charOutlines.contours.back().pts = ofSimplifyContour(testOutline, (float)TTF_SHAPE_SIMPLIFICATION_AMNT); }else{ charOutlines.contours.back().pts = testOutline; } } return charOutlines; }
static int intersect_curve_segment(TTF_Segment *segment, TTF_Scan_Line *scanline) { if (!segment || !scanline) { return 0; } float t; float y = scanline->y; float y0 = segment->y[0], y1 = segment->y[1], y2 = segment->y[2]; float x0 = segment->x[0], x1 = segment->x[1], x2 = segment->x[2]; float a = y0 - 2*y1 + y2; float b = 2*y1 - 2*y0; float c = y0 - y; /* Handle degenerate cases first. */ if (a == 0) { /* Curve is a straight line. */ if (b == 0) { /* Curve is a horizontal line. */ if (c == 0) { /* There are two intersections, x0 and x2. */ add_intersection(scanline, x0); add_intersection(scanline, x2); return 2; } else { /* No intersections. */ return 0; } } else { t = -c / b; if (IN(t, 0.0, 1.0)) { /* One intersection. */ add_intersection(scanline, quad_bezier(t, x0, x1, x2)); return 1; } else { /* No intersections. */ return 0; } } } /* Test discriminant for number of roots. */ float D = b*b - 4*a*c; if (D < 0) { /* No roots. */ return 0; } else if (D == 0) { /* One distinct root. */ t = -b / (2*a); if (IN(t, 0.0, 1.0)) { /* One intersection. */ add_intersection(scanline, quad_bezier(t, x0, x1, x2)); return 1; } else { /* No intersections. */ return 0; } } else { /* Two distinct roots. */ int num_intersections = 0; t = (-b + sqrt(D)) / (2*a); if (IN(t, 0.0, 1.0)) { /* Intersection point is within curve endpoints. */ add_intersection(scanline, quad_bezier(t, x0, x1, x2)); num_intersections++; } t = (-b - sqrt(D)) / (2*a); if (IN(t, 0.0, 1.0)) { /* Intersection point is within curve endpoints. */ add_intersection(scanline, quad_bezier(t, x0, x1, x2)); num_intersections++; } return num_intersections; } }