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;
}
Beispiel #2
0
Datei: scan.c Projekt: dluco/ttf
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;
	}
}