/// <summary> /// read fitting output /// </summary> /// <param name="tx">glyph translator</param> public static void ReadOutput(this GlyphFitOutline glyphOutline, IGlyphTranslator tx, float pxScale) { if (glyphOutline == null) { return; } // //----------------------------------------------------------- //create fit contour //this version use only Agg's vertical hint only **** //(ONLY vertical fitting , NOT apply horizontal fit) //----------------------------------------------------------- //create outline //then create List <GlyphContour> contours = glyphOutline.Contours; int j = contours.Count; tx.BeginRead(j); for (int i = 0; i < j; ++i) { //new contour CreateFitShape(tx, contours[i], pxScale, false, true, false); tx.CloseContour(); } tx.EndRead(); }
void GenerateContourOutput(IGlyphTranslator tx, GlyphContour contour) { List <GlyphPoint> points = contour.flattenPoints; int j = points.Count; if (j == 0) { return; } //------------------------------------------------- Bounds controlBounds = this.OriginalGlyphControlBounds; //walk along the edge in the contour to generate new edge output float pxscale = this._pxScale; #if DEBUG // dbugWriteLine("===begin===" + fit_x_offset); // if (!dbugUseHorizontalFitValue) // { // fit_x_offset = 0; // } #endif //------------------------------------------------- //fineSubPixelRenderingOffset = 0.33f; //------------------------------------------------- //TODO: review here float fit_x, fit_y; points[0].GetFitXY(pxscale, out fit_x, out fit_y); // tx.MoveTo(fit_x, fit_y); #if DEBUG // dbugWriteOutput("M", fit_x, fit_x + fit_x_offset, fit_y); #endif //2. others for (int i = 1; i < j; ++i) { //try to fit to grid points[i].GetFitXY(pxscale, out fit_x, out fit_y); tx.LineTo(fit_x, fit_y); #if DEBUG //for debug //dbugWriteOutput("L", fit_x, fit_x + fit_x_offset, fit_y); #endif } //close tx.CloseContour(); #if DEBUG //dbugWriteLine("===end==="); #endif }
//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); // curveControlPointCount--; 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(); }
public void CloseContour() { _is_contour_opened = false; _tx.CloseContour(); }
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) { //foreach contour... //next contour will begin at... int nextCntBeginAtIndex = contourEndPoints[startContour] + 1; //reset ... Vector2 c1 = new Vector2(); Vector2 c2 = new Vector2(); bool curveMode = false; bool isFirstPoint = true; //first point of this contour ///for each point in this contour for (; cpoint_index < nextCntBeginAtIndex; ++cpoint_index) { GlyphPointF p = glyphPoints[cpoint_index]; 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) { //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. if (curveMode) { switch (curveControlPointCount) { case 1: { tx.Curve3( c1.X, c1.Y, p_x, p_y); } break; case 2: { //for TrueType font //we should not be here? tx.Curve4( c1.X, c1.Y, c2.X, c2.Y, p_x, p_y); } break; default: { throw new NotSupportedException(); } } //reset curve control point count curveControlPointCount = 0; //exist from curve mode curveMode = false; } else { //as describe above,... if (isFirstPoint) { isFirstPoint = false; tx.MoveTo(latest_moveto_x = (p_x), latest_moveto_y = (p_y)); } 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 { //this point is curve control point*** //so set curve mode = true curveMode = true; //check number if existing curve control switch (curveControlPointCount) { case 0: c1 = new Vector2(p_x, p_y); //this point may be part 1st control point of a curve, //store it and wait for next point before make decision *** break; case 1: //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 = GetMid(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); // //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 (curveMode) { switch (curveControlPointCount) { case 0: break; case 1: { tx.Curve3(c1.X, c1.Y, latest_moveto_x, latest_moveto_y); } break; case 2: { //for TrueType font //we should not be here? tx.Curve4(c1.X, c1.Y, c2.X, c2.Y, latest_moveto_x, latest_moveto_y); } break; default: { throw new NotSupportedException(); } } //reset curveMode = false; curveControlPointCount = 0; } //-------- tx.CloseContour(); //*** startContour++; todoContourCount--; //-------- } //finish tx.EndRead(); }
public static void Read(this IGlyphTranslator tx, GlyphPointF[] glyphPoints, ushort[] contourEndPoints, float scale = 1, float offsetX = 0, float offsetY = 0) { 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) { //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 isFirstOnCurvePoint = true; //first point of this contour //------------------------------------------------------------------- //[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' //------------------------------------------------------------------- for (; cpoint_index < nextCntBeginAtIndex; ++cpoint_index) { //for each point in this contour GlyphPointF p = glyphPoints[cpoint_index]; float p_x = p.X * scale; float p_y = p.Y * -scale; p_x += offsetX; p_y += offsetY; 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: 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 (isFirstOnCurvePoint) { //special treament for first point isFirstOnCurvePoint = false; 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 = c1.X, latest_moveto_y = c1.Y); //tx.LineTo(p_x, p_y); 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); } } } else { //p is OFF-CURVE point (this is curve control point) switch (curveControlPointCount) { case 0: c1 = new Vector2(p_x, p_y); if (!isFirstOnCurvePoint) { //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: { //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; } 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: { throw new NotSupportedException(); } } //reset offCurveMode = false; curveControlPointCount = 0; } tx.CloseContour(); startContour++; todoContourCount--; } //finish tx.EndRead(); }