Dashboard/Dashboard.Media.Defaults/FontFreeType.cs

84 lines
2.7 KiB
C#
Raw Normal View History

2023-09-22 18:30:17 +02:00
using System;
2024-05-15 22:17:01 +02:00
using System.Buffers;
2023-09-22 18:30:17 +02:00
using System.IO;
using ReFuel.FreeType;
2024-07-17 22:18:20 +02:00
using Dashboard.Media.Color;
2024-07-28 13:19:13 +02:00
using Dashboard.Media.Fonts;
using OpenTK.Mathematics;
2023-09-22 18:30:17 +02:00
2024-07-17 22:18:20 +02:00
namespace Dashboard.Media.Defaults
2023-09-22 18:30:17 +02:00
{
2024-07-28 13:19:13 +02:00
public class FontFreeType : Font
2023-09-22 18:30:17 +02:00
{
private MemoryStream ms;
private FTFace face;
2024-05-15 22:17:01 +02:00
public override FontFace Face => throw new NotImplementedException();
2023-09-22 18:30:17 +02:00
2024-07-28 13:19:13 +02:00
public FontFreeType(Stream stream)
2023-09-22 18:30:17 +02:00
{
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;
}
2024-07-28 13:19:13 +02:00
protected override Image Render(out GlyphMetrics metrics, int codepoint, float size, in FontRasterizerOptions options)
2023-09-22 18:30:17 +02:00
{
FT.SetCharSize(face, 0, (long)Math.Round(64*size), 0, (uint)Math.Round(options.Resolution));
2024-05-15 22:17:01 +02:00
uint index = FT.GetCharIndex(face, (ulong)codepoint);
FT.LoadGlyph(face, index, FTLoadFlags.Default);
ref readonly FTGlyphMetrics ftmetrics = ref face.Glyph.Metrics;
2024-07-28 13:19:13 +02:00
metrics = new GlyphMetrics(codepoint,
new Vector2(ftmetrics.Width/64f, ftmetrics.Height/64f),
new Vector2(ftmetrics.HorizontalBearingX/64f, ftmetrics.HorizontalBearingY/64f),
new Vector2(ftmetrics.VerticalBearingX/64f, ftmetrics.VerticalBearingY/64f),
new Vector2(ftmetrics.HorizontalAdvance/64f, ftmetrics.VerticalAdvance/64f)
2024-05-15 22:17:01 +02:00
);
2023-09-22 18:30:17 +02:00
2024-05-15 22:17:01 +02:00
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)
2023-09-22 18:30:17 +02:00
{
2024-05-15 22:17:01 +02:00
return null;
2023-09-22 18:30:17 +02:00
}
2024-07-28 13:19:13 +02:00
QImageBuffer image = new QImageBuffer(ImageFormat.AlphaU8, (int)bitmap.Width, (int)bitmap.Rows);
2024-05-15 22:17:01 +02:00
image.LockBits2d(out QImageLock lk, QImageLockOptions.Default);
2023-09-22 18:30:17 +02:00
2024-05-15 22:17:01 +02:00
unsafe
2023-09-22 18:30:17 +02:00
{
2024-05-15 22:17:01 +02:00
Buffer.MemoryCopy((void*)bitmap.Buffer, (void*)lk.ImagePtr, lk.Width * lk.Height, bitmap.Width * bitmap.Rows);
2023-09-22 18:30:17 +02:00
}
2024-05-15 22:17:01 +02:00
image.UnlockBits();
return image;
2023-09-22 18:30:17 +02:00
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
ms.Dispose();
}
FT.DoneFace(face);
}
private static FTLibrary Ft => FTProvider.Ft;
}
}