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