using System; using System.Buffers; using System.IO; using ReFuel.FreeType; using Dashboard.Media.Color; using Dashboard.Media.Font; namespace Dashboard.Media.Defaults { public class QFontFreeType : QFont { private MemoryStream ms; private FTFace face; public override FontFace Face => throw new NotImplementedException(); public QFontFreeType(Stream stream) { ms = new MemoryStream(); stream.CopyTo(ms); FTError e = FT.NewMemoryFace(Ft, ms.GetBuffer(), ms.Length, 0, out face); if (e != FTError.None) { throw new Exception("Could not load font face from stream."); } } public override bool HasRune(int rune) { return FT.GetCharIndex(face, (ulong)rune) != 0; } protected override QImage Render(out QGlyphMetrics metrics, int codepoint, float size, in FontRasterizerOptions options) { FT.SetCharSize(face, 0, (long)Math.Round(64*size), 0, (uint)Math.Round(options.Resolution)); uint index = FT.GetCharIndex(face, (ulong)codepoint); FT.LoadGlyph(face, index, FTLoadFlags.Default); ref readonly FTGlyphMetrics ftmetrics = ref face.Glyph.Metrics; metrics = new QGlyphMetrics(codepoint, new QVec2(ftmetrics.Width/64f, ftmetrics.Height/64f), new QVec2(ftmetrics.HorizontalBearingX/64f, ftmetrics.HorizontalBearingY/64f), new QVec2(ftmetrics.VerticalBearingX/64f, ftmetrics.VerticalBearingY/64f), new QVec2(ftmetrics.HorizontalAdvance/64f, ftmetrics.VerticalAdvance/64f) ); FT.RenderGlyph(face.Glyph, options.Sdf ? FTRenderMode.Sdf : FTRenderMode.Normal); ref readonly FTBitmap bitmap = ref face.Glyph.Bitmap; if (bitmap.Width == 0 || bitmap.Pitch == 0 || bitmap.Buffer == IntPtr.Zero) { return null; } QImageBuffer image = new QImageBuffer(QImageFormat.AlphaU8, (int)bitmap.Width, (int)bitmap.Rows); image.LockBits2d(out QImageLock lk, QImageLockOptions.Default); unsafe { Buffer.MemoryCopy((void*)bitmap.Buffer, (void*)lk.ImagePtr, lk.Width * lk.Height, bitmap.Width * bitmap.Rows); } image.UnlockBits(); return image; } protected override void Dispose(bool disposing) { base.Dispose(disposing); if (disposing) { ms.Dispose(); } FT.DoneFace(face); } private static FTLibrary Ft => FTProvider.Ft; } }