Dashboard/Quik/Media/QFont.cs

129 lines
4.1 KiB
C#
Raw Normal View History

2023-06-29 13:17:32 +02:00
using System;
2024-04-28 12:45:46 +02:00
using System.Collections.Generic;
2024-05-15 22:17:01 +02:00
using System.Runtime.InteropServices;
2024-04-28 12:45:46 +02:00
using Quik.Media;
using Quik.Media.Font;
2023-06-29 13:17:32 +02:00
namespace Quik.Media
{
/// <summary>
/// Abstract class that represents a font.
/// </summary>
public abstract class QFont : IDisposable
{
2024-04-28 12:45:46 +02:00
public abstract FontFace Face { get; }
public string Family => Face.Family;
public FontSlant Slant => Face.Slant;
public FontWeight Weight => Face.Weight;
public FontStretch Stretch => Face.Stretch;
2023-06-29 13:17:32 +02:00
public abstract bool HasRune(int rune);
2024-05-15 22:17:01 +02:00
protected abstract QImage Render(out QGlyphMetrics metrics, int codepoint, float size, in FontRasterizerOptions options);
private readonly Dictionary<float, SizedFontCollection> _atlasses = new Dictionary<float, SizedFontCollection>();
public void Get(int codepoint, float size, out FontGlyph glyph)
{
SizedFontCollection collection;
if (!_atlasses.TryGetValue(size, out collection))
{
collection = new SizedFontCollection(size);
_atlasses.Add(size, collection);
}
collection.Get(codepoint, out glyph, this);
}
2023-06-29 13:17:32 +02:00
// IDisposable
private bool isDisposed = false;
private void DisposePrivate(bool disposing)
{
if (isDisposed) return;
Dispose(disposing);
isDisposed = true;
}
protected virtual void Dispose(bool disposing) { }
public void Dispose() => DisposePrivate(true);
2023-09-22 18:30:17 +02:00
2024-05-15 22:17:01 +02:00
private class SizedFontCollection
2023-09-22 18:30:17 +02:00
{
2024-05-15 22:17:01 +02:00
public float Size { get; }
private readonly Dictionary<int, FontGlyph> glyphs = new Dictionary<int, FontGlyph>();
private readonly FontAtlas atlas;
2023-09-22 18:30:17 +02:00
2024-05-15 22:17:01 +02:00
public SizedFontCollection(float size)
{
Size = size;
2023-09-22 18:30:17 +02:00
2024-05-15 22:17:01 +02:00
QuikApplication.Current.Platform.GetMaximumImage(out int height, out int width);
2023-09-22 18:30:17 +02:00
2024-05-15 22:17:01 +02:00
// Do no allow to create a texture that is greater than 16 square characters at 200 DPI.
width = Math.Min(width, (int)(size * 200 * 16));
height = Math.Min(height, (int)(size * 200 * 16));
// width = height = 256;
2023-09-22 18:30:17 +02:00
2024-05-15 22:17:01 +02:00
atlas = new FontAtlas(width, height, QuikApplication.Current.FontProvider.RasterizerOptions.Sdf);
}
public void Get(int codepoint, out FontGlyph glyph, QFont font)
{
if (glyphs.TryGetValue(codepoint, out glyph))
return;
QImage image = font.Render(
out QGlyphMetrics metrics,
codepoint,
Size,
QuikApplication.Current.FontProvider.RasterizerOptions);
if (image != null)
{
image.LockBits2d(out QImageLock l, QImageLockOptions.Default);
atlas.PutGlyph(codepoint, l, out FontAtlasGlyphInfo glyphInfo);
image.UnlockBits();
image.Dispose();
glyph = new FontGlyph(codepoint, glyphInfo.Image, metrics, glyphInfo.UVs);
}
else
{
glyph = new FontGlyph(codepoint, null, metrics, default);
}
glyphs[codepoint] = glyph;
}
2023-09-22 18:30:17 +02:00
}
2024-05-15 22:17:01 +02:00
}
public readonly struct FontGlyph
{
public readonly int CodePoint;
public readonly QImage Image;
public readonly QGlyphMetrics Metrics;
public readonly QRectangle UVs;
public FontGlyph(int codepoint, QImage image, in QGlyphMetrics metrics, in QRectangle uvs)
2023-09-22 18:30:17 +02:00
{
2024-05-15 22:17:01 +02:00
CodePoint = codepoint;
2023-09-22 18:30:17 +02:00
Image = image;
Metrics = metrics;
2024-05-15 22:17:01 +02:00
UVs = uvs;
2023-09-22 18:30:17 +02:00
}
2024-05-15 22:17:01 +02:00
}
2023-09-22 18:30:17 +02:00
2024-05-15 22:17:01 +02:00
public struct FontRasterizerOptions
{
public float Resolution { get; set; }
public bool Sdf { get; set; }
2023-09-22 18:30:17 +02:00
2024-05-15 22:17:01 +02:00
public static readonly FontRasterizerOptions Default = new FontRasterizerOptions()
2023-09-22 18:30:17 +02:00
{
2024-05-15 22:17:01 +02:00
Resolution = 96.0f,
Sdf = false
};
2023-09-22 18:30:17 +02:00
}
2023-06-29 13:17:32 +02:00
}