public static Shape LoadGlyph(Face face, int unicode) { if (face == null) { throw new ArgumentNullException(nameof(face)); } face.LoadChar((uint)unicode, LoadFlags.NoScale, LoadTarget.Normal); Shape output = new Shape(); Context context = new Context { shape = output }; OutlineFuncs funcs = new OutlineFuncs(); funcs.MoveFunction = MoveTo; funcs.LineFunction = LineTo; funcs.ConicFunction = ConicTo; funcs.CubicFunction = CubicTo; unsafe { face.Glyph.Outline.Decompose(funcs, (IntPtr)Unsafe.AsPointer(ref context)); } return(output); }
public static Shape LoadGlyph(Face font, uint unicode, ref double advance) { var result = new Shape(); font.LoadChar(unicode, LoadFlags.NoScale, LoadTarget.Normal); result.InverseYAxis = false; advance = font.Glyph.Advance.X.Value / 64.0; var context = new FtContext(result); var ftFunctions = new OutlineFuncs { MoveFunction = context.FtMoveTo, LineFunction = context.FtLineTo, ConicFunction = context.FtConicTo, CubicFunction = context.FtCubicTo, Shift = 0 }; font.Glyph.Outline.Decompose(ftFunctions, IntPtr.Zero); return(result); }
public static void CreateFromString([NotNull] Font font, [CanBeNull] string str, [NotNull] GeometrySink sink) { if (string.IsNullOrEmpty(str)) { return; } Guard.ArgumentNotNull(font, nameof(font)); var fontFace = font.FontFace; const int noError = 0; const int factorX = 1 << 10; const int factorY = -factorX; var currentOrigin = Vector2.Zero; var outlineFuncs = new OutlineFuncs(MoveTo, LineTo, QuadraticBezierTo, CubicBezierTo, factorX, 0); foreach (var ch in str) { if (ch == '\r') { continue; } if (ch == ' ') { // TODO: hack! currentOrigin.X += FontHelper.PointsToPixels(font.Size) / 2; continue; } if (ch == '\n') { currentOrigin.Y += FontHelper.PointsToPixels(font.Size); continue; } var glyphIndex = fontFace.GetCharIndex(ch); fontFace.LoadGlyph(glyphIndex, LoadFlags.Render, LoadTarget.Normal); var outline = fontFace.Glyph.Outline; sink.BeginFigure(currentOrigin); outline.Decompose(outlineFuncs, IntPtr.Zero); sink.EndFigure(FigureEnd.Closed); var metrics = fontFace.Glyph.Metrics; var charSize = fontFace.GetCharSize(glyphIndex, metrics, null, 1, 1); currentOrigin.X += charSize.X; } int MoveTo(ref FTVector p2, IntPtr user) { sink.EndFigure(FigureEnd.Closed); sink.BeginFigure(currentOrigin + new Vector2(factorX * p2.X.ToSingle(), factorY * p2.Y.ToSingle())); return(noError); } int LineTo(ref FTVector p2, IntPtr user) { sink.AddLine(currentOrigin + new Vector2(factorX * p2.X.ToSingle(), factorY * p2.Y.ToSingle())); return(noError); } int QuadraticBezierTo(ref FTVector cp, ref FTVector p2, IntPtr user) { var bezier = new QuadraticBezierSegment { Point1 = currentOrigin + new Vector2(factorX * cp.X.ToSingle(), factorY * cp.Y.ToSingle()), Point2 = currentOrigin + new Vector2(factorX * p2.X.ToSingle(), factorY * p2.Y.ToSingle()) }; sink.AddQuadraticBezier(bezier); return(noError); } int CubicBezierTo(ref FTVector cp1, ref FTVector cp2, ref FTVector p2, IntPtr user) { var bezier = new BezierSegment { Point1 = currentOrigin + new Vector2(factorX * cp1.X.ToSingle(), factorY * cp1.Y.ToSingle()), Point2 = currentOrigin + new Vector2(factorX * cp2.X.ToSingle(), factorY * cp2.Y.ToSingle()), Point3 = currentOrigin + new Vector2(factorX * p2.X.ToSingle(), factorY * p2.Y.ToSingle()) }; sink.AddBezier(bezier); return(noError); } }