Dashboard/Quik.Media.Defaults/QFontFreeType.cs

83 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;
2023-09-22 18:30:17 +02:00
using Quik.Media.Color;
2024-05-15 22:17:01 +02:00
using Quik.Media.Font;
2023-09-22 18:30:17 +02:00
namespace Quik.Media.Defaults
{
public class QFontFreeType : QFont
{
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
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;
}
2024-05-15 22:17:01 +02:00
protected override QImage Render(out QGlyphMetrics 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;
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)
);
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-05-16 21:58:22 +02:00
QImageBuffer image = new QImageBuffer(QImageFormat.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;
}
}