135 lines
4.6 KiB
C#
135 lines
4.6 KiB
C#
using System;
|
|
using System.Numerics;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace Dashboard.Drawing
|
|
{
|
|
public class TextExtension : DrawExtension
|
|
{
|
|
public TextCommand TextCommand { get; } = new TextCommand();
|
|
|
|
private TextExtension() : base("DB_Text", new [] { FontExtension.Instance, BrushExtension.Instance })
|
|
{
|
|
}
|
|
|
|
public static readonly TextExtension Instance = new TextExtension();
|
|
}
|
|
|
|
public class TextCommand : IDrawCommand<TextCommandArgs>
|
|
{
|
|
public string Name { get; } = "Text";
|
|
public IDrawExtension Extension { get; } = TextExtension.Instance;
|
|
public int Length { get; } = -1;
|
|
|
|
public int WriteParams(DrawQueue queue, TextCommandArgs obj, Span<byte> param)
|
|
{
|
|
int size = Unsafe.SizeOf<Header>() + obj.Text.Length + sizeof(char);
|
|
|
|
if (param.Length < size)
|
|
return size;
|
|
|
|
ref Header header = ref MemoryMarshal.Cast<byte, Header>(param[0..Unsafe.SizeOf<Header>()])[0];
|
|
Span<char> text = MemoryMarshal.Cast<byte, char>(param[Unsafe.SizeOf<Header>()..]);
|
|
|
|
header = new Header()
|
|
{
|
|
Font = queue.RequireResource(obj.Font),
|
|
TextBrush = queue.RequireResource(obj.TextBrush),
|
|
BorderBrush = (obj.BorderBrush != null) ? queue.RequireResource(obj.BorderBrush) : -1,
|
|
BorderRadius = (obj.BorderBrush != null) ? obj.BorderRadius : 0f,
|
|
Anchor = obj.Anchor,
|
|
Position = obj.Position,
|
|
BorderKind = obj.BorderKind,
|
|
};
|
|
obj.Text.CopyTo(text);
|
|
|
|
return size;
|
|
}
|
|
|
|
public TextCommandArgs GetParams(DrawQueue queue, ReadOnlySpan<byte> param)
|
|
{
|
|
Header header = MemoryMarshal.Cast<byte, Header>(param[0..Unsafe.SizeOf<Header>()])[0];
|
|
ReadOnlySpan<char> text = MemoryMarshal.Cast<byte, char>(param[Unsafe.SizeOf<Header>()..]);
|
|
|
|
if (header.BorderBrush == -1 || header.BorderRadius == 0)
|
|
{
|
|
return new TextCommandArgs(
|
|
(IFont)queue.Resources[header.Font],
|
|
(IBrush)queue.Resources[header.TextBrush],
|
|
header.Anchor,
|
|
header.Position,
|
|
text.ToString())
|
|
{
|
|
BorderBrush = (IBrush)queue.Resources[header.BorderBrush],
|
|
BorderRadius = header.BorderRadius,
|
|
BorderKind = header.BorderKind,
|
|
};
|
|
}
|
|
else
|
|
{
|
|
return new TextCommandArgs(
|
|
(IFont)queue.Resources[header.Font],
|
|
(IBrush)queue.Resources[header.TextBrush],
|
|
header.Anchor,
|
|
header.Position,
|
|
text.ToString());
|
|
}
|
|
}
|
|
|
|
int IDrawCommand.WriteParams(DrawQueue queue, object? obj, Span<byte> param)
|
|
{
|
|
return WriteParams(queue, (TextCommandArgs)obj!, param);
|
|
}
|
|
|
|
object? IDrawCommand.GetParams(DrawQueue queue, ReadOnlySpan<byte> param)
|
|
{
|
|
return GetParams(queue, param);
|
|
}
|
|
|
|
private struct Header
|
|
{
|
|
private int _flags;
|
|
public int Font;
|
|
public int TextBrush;
|
|
public int BorderBrush;
|
|
public Vector3 Position;
|
|
public float BorderRadius;
|
|
|
|
public Anchor Anchor
|
|
{
|
|
get => (Anchor)(_flags & 0xF);
|
|
set => _flags = (_flags & ~0xF) | (int)value;
|
|
}
|
|
|
|
public BorderKind BorderKind
|
|
{
|
|
get => (_flags & INSET) switch
|
|
{
|
|
OUTSET => BorderKind.Outset,
|
|
INSET => BorderKind.Inset,
|
|
_ => BorderKind.Center,
|
|
};
|
|
set => _flags = value switch
|
|
{
|
|
BorderKind.Outset => (_flags & ~INSET) | OUTSET,
|
|
BorderKind.Inset => (_flags & ~INSET) | INSET,
|
|
_ => (_flags & ~INSET) | CENTER,
|
|
};
|
|
}
|
|
|
|
private const int INSET = 0x30;
|
|
private const int CENTER = 0x00;
|
|
private const int OUTSET = 0x10;
|
|
}
|
|
}
|
|
|
|
public record struct TextCommandArgs(IFont Font, IBrush TextBrush, Anchor Anchor, Vector3 Position, string Text)
|
|
{
|
|
public IBrush? BorderBrush { get; init; } = null;
|
|
public float BorderRadius { get; init; } = 0;
|
|
|
|
public BorderKind BorderKind { get; init; } = BorderKind.Center;
|
|
}
|
|
}
|