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 void Curve4(float x1, float y1, float x2, float y2, float x3, float y3) { _is_contour_opened = true; _tx.Curve4(x1 * _scale, y1 * _scale, x2 * _scale, y2 * _scale, x3 * _scale, y3 * _scale); }
public void RR_CurveTo() { //|- {dxa dya dxb dyb dxc dyc}+ rrcurveto (8) |- //appends a Bézier curve, defined by dy1 to the current point. //With dxa...dyc, to the current point. //For each subsequent set of six arguments, an additional //curve is appended to the current point. //The number of curve segments is determined from //the number of arguments on the number stack and //is limited only by the size of the number stack //All Bézier curve path segments are drawn using six arguments, //dxa, dya, dxb, dyb, dxc, dyc; where dxa and dya are relative to //the current point, and all subsequent arguments are relative to //the previous point.A number of the curve operators take //advantage of the situation where some tangent points are //horizontal or vertical(and hence the value is zero), thus //reducing the number of arguments needed. int i = 0; #if DEBUG if ((_currentIndex % 6) != 0) { // i++; } #endif double curX = _currentX; double curY = _currentY; for (; i < _currentIndex;) { _glyphTranslator.Curve4( (float)(curX += _argStack[i + 0]), (float)(curY += _argStack[i + 1]), //dxa,dya (float)(curX += _argStack[i + 2]), (float)(curY += _argStack[i + 3]), //dxb,dyb (float)(curX += _argStack[i + 4]), (float)(curY += _argStack[i + 5]) //dxc,dyc ); // i += 6; } _currentX = curX; _currentY = curY; _currentIndex = 0; //clear stack }