/// <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(); }
public override void ReadShapes(IGlyphTranslator tx) { //read output shape from dynamic outline if (this.UseTrueTypeInstructions) { base.ReadShapes(tx); return; } if (!TemporaryDisableCustomFit && this.UseVerticalHinting) { //read from our auto hint fitoutline //need scale from original. float toPixelScale = Typeface.CalculateScaleToPixel(RecentFontSizeInPixels); if (toPixelScale < 0) { toPixelScale = 1; } _latestDynamicOutline.GenerateOutput(tx, toPixelScale); } else { base.ReadShapes(tx); } }
public virtual void ReadShapes(IGlyphTranslator tx) { //read output from glyph points if (_cffGlyphData != null) { _cffEvalEngine.Run(tx, _ownerCff, _cffGlyphData, _recentPixelScale); } else { tx.Read(_outputGlyphPoints, _outputContours, _recentPixelScale); } }
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 }
public void ReadShapes(IGlyphTranslator tx) { if (_useAutoHint) { //read from our auto hint fitoutline //need scale from original. _fitOutline.ReadOutput(tx, _recentPixelScale); } else { //read output from glyph points tx.Read(this._outputGlyphPoints, this._outputContours, _recentPixelScale); } }
internal void Run(IGlyphTranslator tx, Cff1Font cff1Font, Type2GlyphInstructionList instructionList, float scale = 1) { //all fields are set to new values*** _cff1Font = cff1Font; _scale = scale; //------------- //from Technical Note #5176 (CFF spec) //resolve with bias //Card16 bias; //Card16 nSubrs = subrINDEX.count; //if (CharstringType == 1) // bias = 0; //else if (nSubrs < 1240) // bias = 107; //else if (nSubrs < 33900) // bias = 1131; //else // bias = 32768; //find local subroutine int nsubrs = cff1Font._localSubrs.Count; _cffBias = (nsubrs < 1240) ? 107 : (nsubrs < 33900) ? 1131 : 32769; //TODO: review 32769 or 32768 // double currentX = 0, currentY = 0; var scaleTx = new PxScaleGlyphTx(scale, tx); // scaleTx.BeginRead(0);//unknown contour count // Run(scaleTx, instructionList, ref currentX, ref currentY); // // //some cff end without closing the latest contour? if (scaleTx.IsContourOpened) { scaleTx.CloseContour(); } scaleTx.EndRead(); }
/// <summary> /// generate output with specific pixel scale /// </summary> /// <param name="tx"></param> /// <param name="pxScale"></param> public void GenerateOutput(IGlyphTranslator tx, float pxScale) { if (_contours == null) { return; //blank } #if DEBUG this.EnableGridFit = dbugTestNewGridFitting; #endif if (_pxScale != pxScale) { //new scale need to adjust fit value again _needAdjustGridFitValues = true; } // this._pxScale = pxScale; // if (EnableGridFit) { if (_needRefreshBoneGroup) { //change scale not affect the grid fit *** AnalyzeBoneGroups(GridBoxWidth, GridBoxHeight); _needRefreshBoneGroup = false; } // if (_needAdjustGridFitValues) { ReCalculateFittingValues(); _needAdjustGridFitValues = false; } } if (tx != null) { List <GlyphContour> contours = this._contours; int j = contours.Count; tx.BeginRead(j); for (int i = 0; i < j; ++i) { //generate in order of contour GenerateContourOutput(tx, contours[i]); } tx.EndRead(); } }
public override void ReadShapes(IGlyphTranslator tx) { if (this.UseTrueTypeInstructions) { base.ReadShapes(tx); return; } if (this.UseVerticalHinting) { //read from our auto hint fitoutline //need scale from original. float toPixelScale = Typeface.CalculateToPixelScale(this.RecentFontSizeInPixels); if (toPixelScale < 0) { toPixelScale = 1; } _fitOutline.ReadOutput(tx, toPixelScale); } else { base.ReadShapes(tx); } }
public PxScaleGlyphTx(float scale, IGlyphTranslator tx) { _scale = scale; _tx = tx; }
public virtual void ReadShapes(IGlyphTranslator tx) { //read output from glyph points tx.Read(this._outputGlyphPoints, this._outputContours, _recentPixelScale); }
public PxScaleGlyphTx(float scale, IGlyphTranslator tx) { this.scale = scale; this.tx = tx; }
//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 ContourToGlyphTranslator(IGlyphTranslator tx) => _tx = tx;
void Run(IGlyphTranslator tx, Type2GlyphInstructionList instructionList, ref double currentX, ref double currentY) { //recursive *** Type2EvaluationStack evalStack = GetFreeEvalStack(); //** evalStack._currentX = currentX; evalStack._currentY = currentY; List <Type2Instruction> insts = instructionList.Insts; evalStack.GlyphTranslator = tx; int j = insts.Count; for (int i = 0; i < j; ++i) { Type2Instruction inst = insts[i]; //if (inst.Op != OperatorName.LoadInt) //{ //} switch (inst.Op) { default: throw new NotSupportedException(); case OperatorName.GlyphWidth: //TODO: break; case OperatorName.LoadInt: evalStack.Push(inst.Value); break; // case OperatorName.endchar: evalStack.EndChar(); break; case OperatorName.flex: evalStack.Flex(); break; case OperatorName.hflex: evalStack.H_Flex(); break; case OperatorName.hflex1: evalStack.H_Flex1(); break; case OperatorName.flex1: evalStack.Flex1(); break; //------------------------- //4.4: Arithmetic Operators case OperatorName.abs: evalStack.Op_Abs(); break; case OperatorName.add: evalStack.Op_Add(); break; case OperatorName.sub: evalStack.Op_Sub(); break; case OperatorName.div: evalStack.Op_Div(); break; case OperatorName.neg: evalStack.Op_Neg(); break; case OperatorName.random: evalStack.Op_Random(); break; case OperatorName.mul: evalStack.Op_Mul(); break; case OperatorName.sqrt: evalStack.Op_Sqrt(); break; case OperatorName.drop: evalStack.Op_Drop(); break; case OperatorName.exch: evalStack.Op_Exch(); break; case OperatorName.index: evalStack.Op_Index(); break; case OperatorName.roll: evalStack.Op_Roll(); break; case OperatorName.dup: evalStack.Op_Dup(); break; //------------------------- //4.5: Storage Operators case OperatorName.put: evalStack.Put(); break; case OperatorName.get: evalStack.Get(); break; //------------------------- //4.6: Conditional case OperatorName.and: evalStack.Op_And(); break; case OperatorName.or: evalStack.Op_Or(); break; case OperatorName.not: evalStack.Op_Not(); break; case OperatorName.eq: evalStack.Op_Eq(); break; case OperatorName.ifelse: evalStack.Op_IfElse(); break; // case OperatorName.rlineto: evalStack.R_LineTo(); break; case OperatorName.hlineto: evalStack.H_LineTo(); break; case OperatorName.vlineto: evalStack.V_LineTo(); break; case OperatorName.rrcurveto: evalStack.RR_CurveTo(); break; case OperatorName.hhcurveto: evalStack.HH_CurveTo(); break; case OperatorName.hvcurveto: evalStack.HV_CurveTo(); break; case OperatorName.rcurveline: evalStack.R_CurveLine(); break; case OperatorName.rlinecurve: evalStack.R_LineCurve(); break; case OperatorName.vhcurveto: evalStack.VH_CurveTo(); break; case OperatorName.vvcurveto: evalStack.VV_CurveTo(); break; //------------------------------------------------------------------- case OperatorName.rmoveto: evalStack.R_MoveTo(); break; case OperatorName.hmoveto: evalStack.H_MoveTo(); break; case OperatorName.vmoveto: evalStack.V_MoveTo(); break; //------------------------------------------------------------------- //4.3 Hint Operators case OperatorName.hstem: evalStack.H_Stem(); break; case OperatorName.vstem: evalStack.V_Stem(); break; case OperatorName.vstemhm: evalStack.V_StemHM(); break; case OperatorName.hstemhm: evalStack.H_StemHM(); break; //-------------------------- case OperatorName.hintmask1: evalStack.HintMask1(inst.Value); break; case OperatorName.hintmask2: evalStack.HintMask2(inst.Value); break; case OperatorName.hintmask3: evalStack.HintMask3(inst.Value); break; case OperatorName.hintmask4: evalStack.HintMask4(inst.Value); break; case OperatorName.hintmask_bits: evalStack.HintMaskBits(inst.Value); break; //------------------------------ case OperatorName.cntrmask1: evalStack.CounterSpaceMask1(inst.Value); break; case OperatorName.cntrmask2: evalStack.CounterSpaceMask2(inst.Value); break; case OperatorName.cntrmask3: evalStack.CounterSpaceMask3(inst.Value); break; case OperatorName.cntrmask4: evalStack.CounterSpaceMask4(inst.Value); break; case OperatorName.cntrmask_bits: evalStack.CounterSpaceMaskBits(inst.Value); break; //------------------------- //4.7: Subroutine Operators case OperatorName._return: { //*** //don't forget to return _evalStack's currentX, currentY to prev evl context currentX = evalStack._currentX; currentY = evalStack._currentY; evalStack.Ret(); } break; case OperatorName.callsubr: { //resolve local subrountine int rawSubRoutineNum = (int)evalStack.Pop(); Type2GlyphInstructionList resolvedSubroutine = _cff1Font._localSubrs[rawSubRoutineNum + _cffBias]; //then we move to another context //recursive *** Run(tx, resolvedSubroutine, ref evalStack._currentX, ref evalStack._currentY); } break; case OperatorName.callgsubr: throw new NotSupportedException(); } } ReleaseEvalStack(evalStack);//**** }
static void CreateFitShape(IGlyphTranslator tx, GlyphContour contour, float pixelScale, bool x_axis, bool y_axis, bool useHalfPixel) { List <GlyphPoint2D> mergePoints = contour.mergedPoints; int j = mergePoints.Count; //merge 0 = start double prev_px = 0; double prev_py = 0; double p_x = 0; double p_y = 0; double first_px = 0; double first_py = 0; { GlyphPoint2D p = mergePoints[0]; p_x = p.x * pixelScale; p_y = p.y * pixelScale; if (y_axis && p.isPartOfHorizontalEdge && p.isUpperSide && p_y > 3) { //vertical fitting //fit p_y to grid p_y = RoundToNearestVerticalSide((float)p_y, useHalfPixel); } if (x_axis && p.IsPartOfVerticalEdge && p.IsLeftSide) { float new_x = RoundToNearestHorizontalSide((float)p_x); //adjust right-side vertical edge EdgeLine rightside = p.GetMatchingVerticalEdge(); if (rightside != null) { } p_x = new_x; } tx.MoveTo((float)p_x, (float)p_y); //------------- first_px = prev_px = p_x; first_py = prev_py = p_y; } for (int i = 1; i < j; ++i) { //all merge point is polygon point GlyphPoint2D p = mergePoints[i]; p_x = p.x * pixelScale; p_y = p.y * pixelScale; if (y_axis && p.isPartOfHorizontalEdge && p.isUpperSide && p_y > 3) { //vertical fitting //fit p_y to grid p_y = RoundToNearestVerticalSide((float)p_y, useHalfPixel); } if (x_axis && p.IsPartOfVerticalEdge && p.IsLeftSide) { //horizontal fitting //fix p_x to grid float new_x = RoundToNearestHorizontalSide((float)p_x); ////adjust right-side vertical edge //PixelFarm.Agg.Typography.EdgeLine rightside = p.GetMatchingVerticalEdge(); //if (rightside != null && !rightside.IsLeftSide && rightside.IsOutside) //{ // var rightSideP = rightside.p.userData as GlyphPoint2D; // var rightSideQ = rightside.q.userData as GlyphPoint2D; // //find move diff // float movediff = (float)p_x - new_x; // //adjust right side edge // rightSideP.x = rightSideP.x + movediff; // rightSideQ.x = rightSideQ.x + movediff; //} p_x = new_x; } // tx.LineTo((float)p_x, (float)p_y); // prev_px = p_x; prev_py = p_y; } tx.LineTo((float)first_px, (float)first_py); }
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 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(); }
//----------- //for CFF1 public static void Read(this IGlyphTranslator tx, CFF.Cff1Font cff1Font, CFF.Cff1GlyphData glyphData, float scale = 1) { CFF.CffEvaluationEngine evalEngine = new CFF.CffEvaluationEngine(); evalEngine.Run(tx, cff1Font, glyphData.GlyphInstructions, scale); }
public void Reset() { _currentIndex = 0; _currentX = _currentY = 0; _glyphTranslator = null; }
public void Run(IGlyphTranslator tx, Cff1Font cff1Font, Cff1GlyphData glyphData, float scale = 1) { Run(tx, cff1Font, glyphData.GlyphInstructions, scale); }
/// <summary> /// build and translate /// </summary> /// <param name="builder"></param> /// <param name="glyphIndex"></param> /// <param name="sizeInPoints"></param> /// <param name="tx"></param> public static void BuildFromGlyphIndex(this GlyphOutlineBuilderBase builder, ushort glyphIndex, float sizeInPoints, IGlyphTranslator tx) { builder.BuildFromGlyphIndex(glyphIndex, sizeInPoints); builder.ReadShapes(tx); }