Add basic text support.

This commit is contained in:
H. Utku Maden 2024-12-24 23:20:43 +03:00
parent cf7cf9a77a
commit 165801800e
6 changed files with 245 additions and 14 deletions

@ -0,0 +1,14 @@
namespace Dashboard
{
public enum Anchor
{
Auto = 0,
Right = (1 << 0),
Left = (1 << 1),
HCenter = Left | Right,
Top = (1 << 2),
Bottom = (1 << 3),
VCenter = Top | Bottom,
Middle = HCenter | VCenter,
}
}

@ -0,0 +1,40 @@
namespace Dashboard
{
public enum FontWeight
{
_100 = 100,
_200 = 200,
_300 = 300,
_400 = 400,
_500 = 500,
_600 = 600,
_800 = 800,
_900 = 900,
Thin = _100,
Normal = _400,
Bold = _600,
Heavy = _900,
}
public enum FontSlant
{
Normal,
Italic,
Oblique,
}
public enum FontStretch
{
UltraCondensed = 500,
ExtraCondensed = 625,
Condensed = 750,
SemiCondensed = 875,
Normal = 1000,
SemiExpanded = 1125,
Expanded = 1250,
ExtraExpanded = 1500,
UltraExpanded = 2000,
}
}

@ -123,7 +123,7 @@ namespace Dashboard.Drawing
public static readonly int CommandSize = Unsafe.SizeOf<Value>();
}
public enum StrikeKind
public enum BorderKind
{
Inset = -1,
Center = 0,
@ -179,12 +179,12 @@ namespace Dashboard.Drawing
break;
case Mode.Strike:
ref readonly RectS s = ref MemoryMarshal.AsRef<RectS>(param);
args = new RectCommandArgs(s.Start, s.End, (IBrush)queue.Resources[s.StrikeBrushIndex], s.StrikeSize, s.StrikeKind);
args = new RectCommandArgs(s.Start, s.End, (IBrush)queue.Resources[s.StrikeBrushIndex], s.StrikeSize, s.BorderKind);
break;
default:
ref readonly RectFS fs = ref MemoryMarshal.AsRef<RectFS>(param);
args = new RectCommandArgs(fs.Start, fs.End, (IBrush)queue.Resources[fs.FillBrushIndex],
(IBrush)queue.Resources[fs.StrikeBrushIndex], fs.StrikeSize, fs.StrikeKind);
(IBrush)queue.Resources[fs.StrikeBrushIndex], fs.StrikeSize, fs.BorderKind);
break;
}
@ -215,7 +215,7 @@ namespace Dashboard.Drawing
s.End = obj.End;
s.StrikeBrushIndex = queue.RequireResource(obj.StrikeBrush!);
s.StrikeSize = obj.StrikeSize;
s.StrikeKind = obj.StrikeKind;
s.BorderKind = obj.BorderKind;
break;
default:
ref RectFS fs = ref MemoryMarshal.AsRef<RectFS>(param);
@ -224,7 +224,7 @@ namespace Dashboard.Drawing
fs.FillBrushIndex = queue.RequireResource(obj.FillBrush!);
fs.StrikeBrushIndex = queue.RequireResource(obj.StrikeBrush!);
fs.StrikeSize = obj.StrikeSize;
fs.StrikeKind = obj.StrikeKind;
fs.BorderKind = obj.BorderKind;
break;
}
@ -240,15 +240,15 @@ namespace Dashboard.Drawing
}
private record struct RectF(Vector3 Start, Vector3 End, int FillBrushIndex);
private record struct RectS(Vector3 Start, Vector3 End, int StrikeBrushIndex, float StrikeSize, StrikeKind StrikeKind);
private record struct RectFS(Vector3 Start, Vector3 End, int FillBrushIndex, int StrikeBrushIndex, float StrikeSize, StrikeKind StrikeKind);
private record struct RectS(Vector3 Start, Vector3 End, int StrikeBrushIndex, float StrikeSize, BorderKind BorderKind);
private record struct RectFS(Vector3 Start, Vector3 End, int FillBrushIndex, int StrikeBrushIndex, float StrikeSize, BorderKind BorderKind);
}
public struct RectCommandArgs
{
public Vector3 Start { get; private set; }
public Vector3 End { get; private set; }
public StrikeKind StrikeKind { get; private set; } = StrikeKind.Center;
public BorderKind BorderKind { get; private set; } = BorderKind.Center;
public float StrikeSize { get; private set; } = 0f;
public IBrush? FillBrush { get; private set; } = null;
public IBrush? StrikeBrush { get; private set; } = null;
@ -261,24 +261,24 @@ namespace Dashboard.Drawing
FillBrush = fillBrush;
}
public RectCommandArgs(Vector3 start, Vector3 end, IBrush strikeBrush, float strikeSize, StrikeKind strikeKind)
public RectCommandArgs(Vector3 start, Vector3 end, IBrush strikeBrush, float strikeSize, BorderKind borderKind)
{
Start = start;
End = end;
StrikeBrush = strikeBrush;
StrikeSize = strikeSize;
StrikeKind = strikeKind;
BorderKind = borderKind;
}
public RectCommandArgs(Vector3 start, Vector3 end, IBrush fillBrush, IBrush strikeBrush, float strikeSize,
StrikeKind strikeKind)
BorderKind borderKind)
{
Start = start;
End = end;
FillBrush = fillBrush;
StrikeBrush = strikeBrush;
StrikeSize = strikeSize;
StrikeKind = strikeKind;
BorderKind = borderKind;
}
}
}

@ -94,7 +94,7 @@ namespace Dashboard.Drawing
}
public static void Rect(this DrawQueue queue, Vector3 start, Vector3 end, IBrush strikeBrush, float strikeSize,
StrikeKind kind = StrikeKind.Center)
BorderKind kind = BorderKind.Center)
{
IDrawController controller = queue.GetController(DbBaseCommands.Instance);
Vector3 min = Vector3.Min(start, end);
@ -104,7 +104,7 @@ namespace Dashboard.Drawing
}
public static void Rect(this DrawQueue queue, Vector3 start, Vector3 end, IBrush fillBrush, IBrush strikeBrush,
float strikeSize, StrikeKind kind = StrikeKind.Center)
float strikeSize, BorderKind kind = BorderKind.Center)
{
IDrawController controller = queue.GetController(DbBaseCommands.Instance);
Vector3 min = Vector3.Min(start, end);
@ -112,5 +112,26 @@ namespace Dashboard.Drawing
controller.EnsureBounds(new Box3d(min, max));
controller.Write(DbBaseCommands.Instance.DrawRectF, new RectCommandArgs(start, end, fillBrush, strikeBrush, strikeSize, kind));
}
public static void Text(this DrawQueue queue, Vector3 position, IBrush brush, string text, IFont font,
Anchor anchor = Anchor.Left)
{
IDrawController controller = queue.GetController(DbBaseCommands.Instance);
controller.EnsureBounds(new Box3d(position, position));
controller.Write(TextExtension.Instance.TextCommand, new TextCommandArgs(font, brush, anchor, position, text));
}
public static void Text(this DrawQueue queue, Vector3 position, IBrush textBrush, IBrush borderBrush,
float borderRadius, string text, IFont font, Anchor anchor = Anchor.Left, BorderKind borderKind = BorderKind.Outset)
{
IDrawController controller = queue.GetController(DbBaseCommands.Instance);
controller.EnsureBounds(new Box3d(position, position));
controller.Write(TextExtension.Instance.TextCommand, new TextCommandArgs(font, textBrush, anchor, position, text)
{
BorderBrush = borderBrush,
BorderRadius = borderRadius,
BorderKind = borderKind,
});
}
}
}

22
Dashboard.Drawing/Font.cs Normal file

@ -0,0 +1,22 @@
using System.Linq;
namespace Dashboard.Drawing
{
public class FontExtension : DrawExtension
{
private FontExtension() : base("DB_Font", Enumerable.Empty<DrawExtension>())
{
}
public static readonly IDrawExtension Instance = new FontExtension();
}
public interface IFont : IDrawResource
{
public string Family { get; }
public float Size { get; }
public FontWeight Weight { get; }
public FontSlant Slant { get; }
public FontStretch Stretch { get; }
}
}

@ -0,0 +1,134 @@
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;
}
}