internal bool dbugIsEqualsWith(GlyphPointF another) { return(this.P == another.P && this.onCurve == another.onCurve); }
//for TrueType Font public static void Read(this IGlyphTranslator tx, GlyphPointF[] glyphPoints, ushort[] contourEndPoints, float scale = 1) { int startContour = 0; int cpoint_index = 0;//current point index int todoContourCount = contourEndPoints.Length; //----------------------------------- //1. start read data from a glyph tx.BeginRead(todoContourCount); //----------------------------------- float latest_moveto_x = 0; float latest_moveto_y = 0; int curveControlPointCount = 0; // 1 curve control point => Quadratic, 2 curve control points => Cubic while (todoContourCount > 0) { //reset curveControlPointCount = 0; //foreach contour... //next contour will begin at... int nextCntBeginAtIndex = contourEndPoints[startContour] + 1; //reset ... bool has_c_begin = false; //see below [A] Vector2 c_begin = new Vector2(); //special point if the glyph starts with 'off-curve' control point Vector2 c1 = new Vector2(); //control point of quadratic curve //------------------------------------------------------------------- bool offCurveMode = false; bool foundFirstOnCurvePoint = false; bool startWithOffCurve = false; int cnt_point_count = 0; //------------------------------------------------------------------- //[A] //first point may start with 'ON CURVE" or 'OFF-CURVE' //1. if first point is 'ON-CURVE' => we just set moveto command to it // //2. if first point is 'OFF-CURVE' => we store it into c_begin and set has_c_begin= true // the c_begin will be use when we close the contour // // //eg. glyph '2' in Century font starts with 'OFF-CURVE' point, and ends with 'OFF-CURVE' //------------------------------------------------------------------- #if DEBUG int dbug_cmdcount = 0; #endif for (; cpoint_index < nextCntBeginAtIndex; ++cpoint_index) { #if DEBUG dbug_cmdcount++; #endif //for each point in this contour //point p is an on-curve point (on outline). (not curve control point) //possible ways.. //1. if we are in curve mode, then p is end point // we must decide which curve to create (Curve3 or Curve4) // easy, ... // if curveControlPointCount == 1 , then create Curve3 // else curveControlPointCount ==2 , then create Curve4 //2. if we are NOT in curve mode, // if p is first point then set this to x0,y0 // else then p is end point of a line. GlyphPointF p = glyphPoints[cpoint_index]; cnt_point_count++; float p_x = p.X * scale; float p_y = p.Y * scale; //int vtag = (int)flags[cpoint_index] & 0x1; //bool has_dropout = (((vtag >> 2) & 0x1) != 0); //int dropoutMode = vtag >> 3; if (p.onCurve) { //------------------------------------------------------------------- //[B] //point p is an 'on-curve' point (on outline). //(not curve control point)*** //the point touch the outline. //possible ways.. //1. if we are in offCurveMode, then p is a curve end point. // we must decide which curve to create (Curve3 or Curve4) // easy, ... // if curveControlPointCount == 1 , then create Curve3 // else curveControlPointCount ==2 , then create Curve4 (BUT SHOULD NOT BE FOUND IN TRUE TYPEFONT'( //2. if we are NOT in offCurveMode, // if p is first point then set this to =>moveto(x0,y0) // else then p is end point of a line => lineto(x1,y1) //------------------------------------------------------------------- if (offCurveMode) { //as describe above [B.1] ,... switch (curveControlPointCount) { case 1: tx.Curve3( c1.X, c1.Y, p_x, p_y); break; default: //for TrueType font //we should not be here? throw new NotSupportedException(); } //reset curve control point count curveControlPointCount = 0; //we touch the curve, set offCurveMode= false offCurveMode = false; } else { // p is ON CURVE, but now we are in OFF-CURVE mode. // //as describe above [B.2] ,... if (!foundFirstOnCurvePoint) { //special treament for first point foundFirstOnCurvePoint = true; switch (curveControlPointCount) { case 0: //describe above, see [A.1] tx.MoveTo(latest_moveto_x = p_x, latest_moveto_y = p_y); break; case 1: //describe above, see [A.2] c_begin = c1; has_c_begin = true; //since c1 is off curve //we skip the c1 for and use it when we close the curve tx.MoveTo(latest_moveto_x = p_x, latest_moveto_y = p_y); curveControlPointCount--; break; default: throw new NotSupportedException(); } } else { tx.LineTo(p_x, p_y); } //if (has_dropout) //{ // //printf("[%d] on,dropoutMode=%d: %d,y:%d \n", mm, dropoutMode, vpoint.x, vpoint.y); //} //else //{ // //printf("[%d] on,x: %d,y:%d \n", mm, vpoint.x, vpoint.y); //} } } else { //p is OFF-CURVE point (this is curve control point) // if (cnt_point_count == 1) { //1st point startWithOffCurve = true; } switch (curveControlPointCount) { case 0: c1 = new Vector2(p_x, p_y); if (foundFirstOnCurvePoint) { //this point is curve control point*** //so set curve mode = true //check number if existing curve control offCurveMode = true; } else { //describe above, see [A.2] } break; case 1: { if (!foundFirstOnCurvePoint) { Vector2 mid2 = GetMidPoint(c1, p_x, p_y); //---------- //2. generate curve3 *** c_begin = c1; has_c_begin = true; tx.MoveTo(latest_moveto_x = mid2.X, latest_moveto_y = mid2.Y); offCurveMode = true; foundFirstOnCurvePoint = true; c1 = new Vector2(p_x, p_y); continue; } //we already have previous 1st control point (c1) //------------------------------------- //please note that TrueType font //compose of Quadractic Bezier Curve (Curve3) *** //------------------------------------- //in this case, this is NOT Cubic, //this is 2 CONNECTED Quadractic Bezier Curves*** // //we must create 'end point' of the first curve //and set it as 'begin point of the second curve. // //this is done by ... //1. calculate mid point between c1 and the latest point (p_x,p_y) Vector2 mid = GetMidPoint(c1, p_x, p_y); //---------- //2. generate curve3 *** tx.Curve3( c1.X, c1.Y, mid.X, mid.Y); //------------------------ //3. so curve control point number is reduce by 1*** curveControlPointCount--; //------------------------ //4. and set (p_x,p_y) as 1st control point for the new curve c1 = new Vector2(p_x, p_y); offCurveMode = true; // //printf("[%d] bzc2nd, x: %d,y:%d \n", mm, vpoint.x, vpoint.y); } break; default: throw new NotSupportedException(); } //count curveControlPointCount++; } } //-------- //when finish, //ensure that the contour is closed. if (offCurveMode) { switch (curveControlPointCount) { case 0: break; case 1: { if (has_c_begin) { Vector2 mid = GetMidPoint(c1, c_begin.X, c_begin.Y); //---------- //2. generate curve3 *** tx.Curve3( c1.X, c1.Y, mid.X, mid.Y); //------------------------ //3. so curve control point number is reduce by 1*** curveControlPointCount--; //------------------------ tx.Curve3( c_begin.X, c_begin.Y, latest_moveto_x, latest_moveto_y); } else { tx.Curve3( c1.X, c1.Y, latest_moveto_x, latest_moveto_y); } } break; default: //for TrueType font //we should not be here? throw new NotSupportedException(); } } else { //end with touch curve //but if this start with off curve //then we must close it properly if (startWithOffCurve) { //start with off-curve and end with touch curve tx.Curve3( c_begin.X, c_begin.Y, latest_moveto_x, latest_moveto_y); } } //-------- tx.CloseContour(); //*** startContour++; //-------- todoContourCount--; //-------- } //finish tx.EndRead(); }