MoonWorks/src/Graphics/Font/Font.cs

132 lines
3.4 KiB
C#
Raw Normal View History

2022-04-13 22:10:23 +00:00
using System;
using System.IO;
using System.Runtime.InteropServices;
2022-04-13 22:10:23 +00:00
using WellspringCS;
namespace MoonWorks.Graphics.Font
{
2023-12-07 01:33:17 +00:00
public unsafe class Font : IDisposable
{
public Texture Texture { get; }
2023-12-08 06:54:58 +00:00
public float PixelsPerEm { get; }
2023-12-08 07:50:34 +00:00
public float DistanceRange { get; }
2023-12-07 01:33:17 +00:00
internal IntPtr Handle { get; }
private byte* StringBytes;
private int StringBytesLength;
2022-04-13 22:10:23 +00:00
private bool IsDisposed;
2023-12-07 01:33:17 +00:00
public unsafe static Font Load(
GraphicsDevice graphicsDevice,
CommandBuffer commandBuffer,
string fontPath
) {
var fontFileStream = new FileStream(fontPath, FileMode.Open, FileAccess.Read);
var fontFileByteBuffer = NativeMemory.Alloc((nuint) fontFileStream.Length);
var fontFileByteSpan = new Span<byte>(fontFileByteBuffer, (int) fontFileStream.Length);
fontFileStream.ReadExactly(fontFileByteSpan);
fontFileStream.Close();
var atlasFileStream = new FileStream(Path.ChangeExtension(fontPath, ".json"), FileMode.Open, FileAccess.Read);
var atlasFileByteBuffer = NativeMemory.Alloc((nuint) atlasFileStream.Length);
var atlasFileByteSpan = new Span<byte>(atlasFileByteBuffer, (int) atlasFileStream.Length);
atlasFileStream.ReadExactly(atlasFileByteSpan);
atlasFileStream.Close();
var handle = Wellspring.Wellspring_CreateFont(
(IntPtr) fontFileByteBuffer,
(uint) fontFileByteSpan.Length,
(IntPtr) atlasFileByteBuffer,
2023-12-08 06:54:58 +00:00
(uint) atlasFileByteSpan.Length,
2023-12-08 07:50:34 +00:00
out float pixelsPerEm,
out float distanceRange
2023-12-07 01:33:17 +00:00
);
var texture = Texture.FromImageFile(graphicsDevice, commandBuffer, Path.ChangeExtension(fontPath, ".png"));
NativeMemory.Free(fontFileByteBuffer);
NativeMemory.Free(atlasFileByteBuffer);
2023-12-08 07:50:34 +00:00
return new Font(handle, texture, pixelsPerEm, distanceRange);
2023-12-07 01:33:17 +00:00
}
2023-12-08 07:50:34 +00:00
private Font(IntPtr handle, Texture texture, float pixelsPerEm, float distanceRange)
2023-12-07 01:33:17 +00:00
{
Handle = handle;
Texture = texture;
2023-12-08 06:54:58 +00:00
PixelsPerEm = pixelsPerEm;
2023-12-08 07:50:34 +00:00
DistanceRange = distanceRange;
2023-12-07 01:33:17 +00:00
StringBytesLength = 32;
StringBytes = (byte*) NativeMemory.Alloc((nuint) StringBytesLength);
}
public unsafe bool TextBounds(
string text,
2023-12-08 06:54:58 +00:00
int pixelSize,
2023-12-07 01:33:17 +00:00
HorizontalAlignment horizontalAlignment,
VerticalAlignment verticalAlignment,
out Wellspring.Rectangle rectangle
) {
var byteCount = System.Text.Encoding.UTF8.GetByteCount(text);
if (StringBytesLength < byteCount)
{
StringBytes = (byte*) NativeMemory.Realloc(StringBytes, (nuint) byteCount);
}
fixed (char* chars = text)
{
System.Text.Encoding.UTF8.GetBytes(chars, text.Length, StringBytes, byteCount);
var result = Wellspring.Wellspring_TextBounds(
Handle,
2023-12-08 06:54:58 +00:00
pixelSize,
2023-12-07 01:33:17 +00:00
(Wellspring.HorizontalAlignment) horizontalAlignment,
(Wellspring.VerticalAlignment) verticalAlignment,
(IntPtr) StringBytes,
(uint) byteCount,
out rectangle
);
if (result == 0)
{
Logger.LogWarn("Could not decode string: " + text);
return false;
}
}
return true;
}
2022-04-13 22:10:23 +00:00
protected virtual void Dispose(bool disposing)
{
if (!IsDisposed)
{
2023-12-07 01:33:17 +00:00
if (disposing)
{
Texture.Dispose();
}
2022-04-13 22:10:23 +00:00
Wellspring.Wellspring_DestroyFont(Handle);
IsDisposed = true;
}
}
~Font()
{
2023-12-07 01:33:17 +00:00
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: false);
2022-04-13 22:10:23 +00:00
}
public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}