public void CloseContour() { cntBuilder.CloseFigure(); GlyphContour cntContour = cntBuilder.CurrentContour; cntContour.allPoints = cntBuilder.GetAllPoints(); cntBuilder.Reset(); contours.Add(cntContour); }
static Msdfgen.Shape CreateMsdfShape(List <GlyphContour> contours) { var shape = new Msdfgen.Shape(); int j = contours.Count; for (int i = 0; i < j; ++i) { var cnt = new Msdfgen.Contour(); shape.contours.Add(cnt); GlyphContour contour = contours[i]; List <GlyphPart> parts = contour.parts; int m = parts.Count; for (int n = 0; n < m; ++n) { GlyphPart p = parts[n]; switch (p.Kind) { default: throw new NotSupportedException(); case GlyphPartKind.Curve3: { GlyphCurve3 curve3 = (GlyphCurve3)p; cnt.AddQuadraticSegment( curve3.FirstPoint.X, curve3.FirstPoint.Y, curve3.x1, curve3.y1, curve3.x2, curve3.y2 ); } break; case GlyphPartKind.Curve4: { GlyphCurve4 curve4 = (GlyphCurve4)p; cnt.AddCubicSegment( curve4.FirstPoint.X, curve4.FirstPoint.Y, curve4.x1, curve4.y1, curve4.x2, curve4.y2, curve4.x3, curve4.y3); } break; case GlyphPartKind.Line: { GlyphLine line = (GlyphLine)p; cnt.AddLine( line.FirstPoint.X, line.FirstPoint.Y, line.x1, line.y1); } break; } } } return(shape); }
static GlyphFitOutline TessWithPolyTri(List <GlyphContour> contours) { List <Poly2Tri.TriangulationPoint> points = new List <Poly2Tri.TriangulationPoint>(); int cntCount = contours.Count; GlyphContour cnt = contours[0]; Poly2Tri.Polygon polygon = CreatePolygon2(contours[0]);//first contour bool isHoleIf = !cnt.IsClockwise; //if (cntCount > 0) //{ // //debug only for (int n = 1; n < cntCount; ++n) { cnt = contours[n]; //IsHole is correct after we Analyze() the glyph contour polygon.AddHole(CreatePolygon2(cnt)); //if (cnt.IsClockwise == isHoleIf) //{ // polygon.AddHole(CreatePolygon2(cnt)); //} //else //{ // //eg i // //the is a complete separate dot (i head) over i body //} } //} //------------------------------------------ Poly2Tri.P2T.Triangulate(polygon); //that poly is triangulated GlyphFitOutline glyphFitOutline = new GlyphFitOutline(polygon, contours); glyphFitOutline.Analyze(); //------------------------------------------ #if DEBUG List <GlyphTriangle> triAngles = glyphFitOutline.dbugGetTriangles(); int triangleCount = triAngles.Count; for (int i = 0; i < triangleCount; ++i) { //--------------- GlyphTriangle tri = triAngles[i]; AssignPointEdgeInvolvement(tri.e0); AssignPointEdgeInvolvement(tri.e1); AssignPointEdgeInvolvement(tri.e2); } #endif return(glyphFitOutline); }
static GlyphContour CreateFitContour(GlyphContour contour, float pixelScale, bool x_axis, bool y_axis) { GlyphContour newc = new GlyphContour(); List <GlyphPart> parts = contour.parts; int m = parts.Count; for (int n = 0; n < m; ++n) { GlyphPart p = parts[n]; switch (p.Kind) { default: throw new NotSupportedException(); case GlyphPartKind.Curve3: { GlyphCurve3 curve3 = (GlyphCurve3)p; newc.AddPart(new GlyphCurve3( curve3.FirstPoint.X * pixelScale, curve3.FirstPoint.Y * pixelScale, curve3.x1 * pixelScale, curve3.y1 * pixelScale, curve3.x2 * pixelScale, curve3.y2 * pixelScale)); } break; case GlyphPartKind.Curve4: { GlyphCurve4 curve4 = (GlyphCurve4)p; newc.AddPart(new GlyphCurve4( curve4.FirstPoint.X * pixelScale, curve4.FirstPoint.Y * pixelScale, curve4.x1 * pixelScale, curve4.y1 * pixelScale, curve4.x2 * pixelScale, curve4.y2 * pixelScale, curve4.x3 * pixelScale, curve4.y3 * pixelScale )); } break; case GlyphPartKind.Line: { GlyphLine line = (GlyphLine)p; newc.AddPart(new GlyphLine( line.FirstPoint.X * pixelScale, line.FirstPoint.Y * pixelScale, line.x1 * pixelScale, line.y1 * pixelScale )); } break; } } return(newc); }
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); }
/// <summary> /// create polygon from flatten curve outline point /// </summary> /// <param name="cnt"></param> /// <returns></returns> static Poly2Tri.Polygon CreatePolygon2(GlyphContour cnt) { List <Poly2Tri.TriangulationPoint> points = new List <Poly2Tri.TriangulationPoint>(); List <GlyphPart> allParts = cnt.parts; //--------------------------------------- //merge all generated points //also remove duplicated point too! List <GlyphPoint2D> mergedPoints = new List <GlyphPoint2D>(); cnt.mergedPoints = mergedPoints; //--------------------------------------- { int tt = 0; int j = allParts.Count; for (int i = 0; i < j; ++i) { GlyphPart p = allParts[i]; List <GlyphPoint2D> fpoints = p.GetFlattenPoints(); if (tt == 0) { int n = fpoints.Count; for (int m = 0; m < n; ++m) { //GlyphPoint2D fp = fpoints[m]; mergedPoints.Add(fpoints[m]); //allPoints.Add((float)fp.x); //allPoints.Add((float)fp.y); } tt++; } else { //except first point int n = fpoints.Count; for (int m = 1; m < n; ++m) { //GlyphPoint2D fp = fpoints[m]; mergedPoints.Add(fpoints[m]); //allPoints.Add((float)fp.x); //allPoints.Add((float)fp.y); } } } } //--------------------------------------- { //check last (x,y) and first (x,y) int lim = mergedPoints.Count - 1; { if (mergedPoints[lim].IsEqualValues(mergedPoints[0])) { //remove last (x,y) mergedPoints.RemoveAt(lim); lim -= 1; } } //limitation: poly tri not accept duplicated points! double prevX = 0; double prevY = 0; Dictionary <TmpPoint, bool> tmpPoints = new Dictionary <TmpPoint, bool>(); lim = mergedPoints.Count; for (int i = 0; i < lim; ++i) { GlyphPoint2D p = mergedPoints[i]; double x = p.x; double y = p.y; if (x == prevX && y == prevY) { if (i > 0) { throw new NotSupportedException(); } } else { TmpPoint tmp_point = new TmpPoint(x, y); if (!tmpPoints.ContainsKey(tmp_point)) { //ensure no duplicated point tmpPoints.Add(tmp_point, true); var userTriangulationPoint = new Poly2Tri.TriangulationPoint(x, y) { userData = p }; p.triangulationPoint = userTriangulationPoint; points.Add(userTriangulationPoint); } else { throw new NotSupportedException(); } prevX = x; prevY = y; } } Poly2Tri.Polygon polygon = new Poly2Tri.Polygon(points.ToArray()); return(polygon); } }
public void Reset() { currentCnt = new GlyphContour(); this.latestMoveToX = this.curX = this.latestMoveToY = this.curY = 0; allPoints = new List <float>(); }