internal static void TransformNormalWith2x2Matrix(Glyph glyph, float m00, float m01, float m10, float m11) { //http://stackoverflow.com/questions/13188156/whats-the-different-between-vector2-transform-and-vector2-transformnormal-i //http://www.technologicalutopia.com/sourcecode/xnageometry/vector2.cs.htm //change data on current glyph float new_xmin = 0; float new_ymin = 0; float new_xmax = 0; float new_ymax = 0; GlyphPointF[] glyphPoints = glyph.glyphPoints; for (int i = glyphPoints.Length - 1; i >= 0; --i) { GlyphPointF p = glyphPoints[i]; float x = p.P.X; float y = p.P.Y; float newX, newY; //please note that this is transform normal*** glyphPoints[i] = new GlyphPointF( newX = (float)Math.Round((x * m00) + (y * m10)), newY = (float)Math.Round((x * m01) + (y * m11)), p.onCurve); //short newX = xs[i] = (short)Math.Round((x * m00) + (y * m10)); //short newY = ys[i] = (short)Math.Round((x * m01) + (y * m11)); //------ if (newX < new_xmin) { new_xmin = newX; } if (newX > new_xmax) { new_xmax = newX; } //------ if (newY < new_ymin) { new_ymin = newY; } if (newY > new_ymax) { new_ymax = newY; } } //TODO: review here glyph._bounds = new Bounds( (short)new_xmin, (short)new_ymin, (short)new_xmax, (short)new_ymax); }
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); // 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 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(); }
public static void Read(this IGlyphPathBuilder r, GlyphPointF[] glyphPoints, ushort[] contourEndPoints) { //2. start build path int startContour = 0; int cpoint_index = 0; int todoContourCount = contourEndPoints.Length; //----------------------------------- r.BeginRead(todoContourCount); //----------------------------------- float lastMoveX = 0; float lastMoveY = 0; int controlPointCount = 0; while (todoContourCount > 0) { int nextContour = contourEndPoints[startContour] + 1; bool isFirstPoint = true; Vector2 secondControlPoint = new Vector2(); Vector2 thirdControlPoint = new Vector2(); bool justFromCurveMode = false; for (; cpoint_index < nextContour; ++cpoint_index) { GlyphPointF vpoint = glyphPoints[cpoint_index]; float vpoint_x = vpoint.P.X; float vpoint_y = vpoint.P.Y; //int vtag = (int)flags[cpoint_index] & 0x1; //bool has_dropout = (((vtag >> 2) & 0x1) != 0); //int dropoutMode = vtag >> 3; if (vpoint.onCurve) { //on curve if (justFromCurveMode) { switch (controlPointCount) { case 1: { r.Curve3(secondControlPoint.X, secondControlPoint.Y, vpoint_x, vpoint_y); } break; case 2: { r.Curve4(secondControlPoint.X, secondControlPoint.Y, thirdControlPoint.X, thirdControlPoint.Y, vpoint_x, vpoint_y); } break; default: { throw new NotSupportedException(); } } controlPointCount = 0; justFromCurveMode = false; } else { if (isFirstPoint) { isFirstPoint = false; r.MoveTo(lastMoveX = (vpoint_x), lastMoveY = (vpoint_y)); } else { r.LineTo(vpoint_x, vpoint_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 { switch (controlPointCount) { case 0: { secondControlPoint = new Vector2(vpoint_x, vpoint_y); } break; case 1: { //we already have prev second control point //so auto calculate line to //between 2 point Vector2 mid = GetMid(secondControlPoint, vpoint_x, vpoint_y); //---------- //generate curve3 r.Curve3(secondControlPoint.X, secondControlPoint.Y, mid.X, mid.Y); //------------------------ controlPointCount--; //------------------------ //printf("[%d] bzc2nd, x: %d,y:%d \n", mm, vpoint.x, vpoint.y); secondControlPoint = new Vector2(vpoint_x, vpoint_y); } break; default: { throw new NotSupportedException(); } break; } controlPointCount++; justFromCurveMode = true; } } //-------- //close figure //if in curve mode if (justFromCurveMode) { switch (controlPointCount) { case 0: break; case 1: { r.Curve3(secondControlPoint.X, secondControlPoint.Y, lastMoveX, lastMoveY); } break; case 2: { r.Curve4(secondControlPoint.X, secondControlPoint.Y, thirdControlPoint.X, thirdControlPoint.Y, lastMoveX, lastMoveY); } break; default: { throw new NotSupportedException(); } } justFromCurveMode = false; controlPointCount = 0; } r.CloseFigure(); //-------- startContour++; todoContourCount--; } r.EndRead(); }