-
Notifications
You must be signed in to change notification settings - Fork 405
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Shared/Utility: Define new FormattedMessage core types * Shared/Utility: Move MarkupParser to a new namespace, update to new FormattedText * Shared/Serialization: Temporary fix for FormattedMessageSerializer * Scripting/ScriptInstanceShared: Move to new FormattedMessage.Builder * Shared/Utility: Add a FormattedMessage loader to the .Builder * Server/Scripting: Port SciptHost to FormattedMessage.Builder * UserInterface/RichTextEntry: NOP out almost everything not gonna bother fixing it until more groundwork is laid * Shared/Utility: Expand Utility.Extensions a bit strictly for pesonal reasons * Client/UserInterface: Add the base TextLayout engine * Client/Graphics: Add a Font Library manager * Graphics/TextLayout: Finish up implementing the TextLayout engine * Utility/FormattedMessage: Add yet another hack to keep the serializer in service * Commands/Debug: Use FormattedMessage.Builder * Console/Completions: Use FormattedMessage.Builder * Utility/FormattedMessage: Add `AddMessage` methods * Console/ScriptConsole: Use FormattedMessage.Builder * Client/Log: Use FormattedMessage.Builder * CustomControls/DebugConsole: Use FormattedMessage.Builder * Controls/OutputPanel: Use FormattedMessage.Builder, NOP `Draw` pending rewrite * Controls/RichTextLabel: Use FormattedMessage.Builder, NOP `Draw` pending rewrite * UnitTesting: Update FormattedMessage/Markup Tests They will NOT pass yet, but I don't care; it compiles. * Utility/FormattedMessage: Fix some off-by-one Builder bugs * Utility/FormattedMessage: Continue cleanup, test compliance * Utility/FormattedMessage: Work around dotnet/roslyn#57870 * Utility/FormattedMessage: Move ISectionable from TextLayout, implement it for FormattedMessage * UserInterface/TextLayout: Add a `postcreate` function to set up new `TIn`s Apparently Roslyn isn't big-brained enough to understand that a closure of type `Func<T>` means that `var n = new(); return n;` requires `new()` to return a `T`. Ironically, it's significantly less cbt to add this than to convert that big tuple in `Layout` in to a class or struct of some sort (to initialize the `List<>`s). * UserInterface/TextLayout: Throw if `Meta` isn't recognized TODO warning go brrr * Graphics/FontLibrary: Add a `DummyVariant` * UserInterface/UITheme: Move to FontLibraries * UserInterface/TextLayout: Move to an un-nested `ImmutableArray` * UserInterface/RichTextEntry: Go ahead. Draw. * Markup/Basic: Add extension & helpers for FormattedMessage.Builder * Markup/Basic: Add `EscapeText` back in A forgotten casualty of the great Markup separation of 2021 * Graphics/FontLibrary: Clean up bit magic, ensure that at least one font is picked * Graphics/FontLibrary: Add diagnostics to the "no fonts" exception * UserInterface/TextLayout: Scrap `Word`, return to `Offset` * UserInterface/TextLayout: A whole bunch of hard-fought bugfixes * Utility/FormattedMessage: Add a static, empty FormattedMessage * Utility/FormattedMessage: Fix. Bugs. * UserInterface/RichTextEntry: Bug fixin' * UserInterface: CSS teim * Markup/Basic: Add an optional "default" style to use * Utility/FormattedMessage: I'm surprised I only made this mistake once. * Log/DebugConsoleLogHandler: work around lack of a default style
- Loading branch information
Showing
26 changed files
with
1,204 additions
and
562 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Numerics; | ||
using Robust.Shared.Utility; | ||
using Robust.Client.ResourceManagement; | ||
namespace Robust.Client.Graphics; | ||
|
||
/// <summary> | ||
/// Stores a single style (Bold, Italic, Monospace), or any combination thereof. | ||
/// </summary> | ||
public record FontVariant (FontStyle Style, FontResource[] Resource) | ||
{ | ||
public virtual Font ToFont(byte size) | ||
{ | ||
if (Resource.Length == 1) | ||
return new VectorFont(Resource[0], size); | ||
|
||
var fs = new Font[Resource.Length]; | ||
for (var i = 0; i < Resource.Length; i++) | ||
fs[i] = new VectorFont(Resource[i], size); | ||
|
||
return new StackedFont(fs); | ||
} | ||
}; | ||
|
||
internal record DummyVariant(FontStyle fs) : FontVariant(fs, new FontResource[0]) | ||
{ | ||
public override Font ToFont(byte size) => new DummyFont(); | ||
}; | ||
|
||
public record FontClass | ||
( | ||
string Id, | ||
FontStyle Style, | ||
FontSize Size | ||
); | ||
|
||
/// <summary> | ||
/// Manages font-based bookkeeping across a single stylesheet. | ||
/// </summary> | ||
public interface IFontLibrary | ||
{ | ||
FontClass Default { get; } | ||
|
||
/// <summary>Associates a name to a set of font resources.</summary> | ||
void AddFont(string name, params FontVariant[] variants); | ||
|
||
/// <summary>Sets a standard size which can be reused across the Font Library.</summary> | ||
void SetStandardSize(ushort number, byte size); | ||
|
||
/// <summary>Sets a standard style which can be reused across the Font Library.</summary> | ||
void SetStandardStyle(ushort number, string name, FontStyle style); | ||
|
||
/// <summary> | ||
/// Returns a fancy handle in to the library. | ||
/// The handle keeps track of relative changes to <paramref name="fst"/> and <paramref name="fsz"/>. | ||
/// </summary> | ||
IFontLibrarian StartFont(string id, FontStyle fst, FontSize fsz); | ||
|
||
IFontLibrarian StartFont(FontClass? fclass = default) => | ||
StartFont( | ||
(fclass ?? Default).Id, | ||
(fclass ?? Default).Style, | ||
(fclass ?? Default).Size | ||
); | ||
} | ||
|
||
/// <summary> | ||
/// Acts as a handle in to an <seealso cref="IFontLibrary"/>. | ||
/// </summary> | ||
public interface IFontLibrarian | ||
{ | ||
Font Current { get; } | ||
Font Update(FontStyle fst, FontSize fsz); | ||
} | ||
|
||
public class FontLibrary : IFontLibrary | ||
{ | ||
public FontClass Default { get; set; } | ||
|
||
public FontLibrary(FontClass def) | ||
{ | ||
Default = def; | ||
} | ||
|
||
private Dictionary<string, FontVariant[]> _styles = new(); | ||
private Dictionary<FontStyle, (string, FontStyle)> _standardSt = new(); | ||
private Dictionary<FontSize, byte> _standardSz = new(); | ||
|
||
void IFontLibrary.AddFont(string name, params FontVariant[] variants) => | ||
_styles[name] = variants; | ||
|
||
IFontLibrarian IFontLibrary.StartFont(string id, FontStyle fst, FontSize fsz) => | ||
new FontLibrarian(this, id, fst, fsz); | ||
|
||
void IFontLibrary.SetStandardStyle(ushort number, string name, FontStyle style) => | ||
_standardSt[(FontStyle) number | FontStyle.Standard] = (name, style); | ||
|
||
void IFontLibrary.SetStandardSize(ushort number, byte size) => | ||
_standardSz[(FontSize) number | FontSize.Standard] = size; | ||
|
||
private FontVariant lookup(string id, FontStyle fst) | ||
{ | ||
if (fst.HasFlag(FontStyle.Standard)) | ||
(id, fst) = _standardSt[fst]; | ||
|
||
FontVariant? winner = default; | ||
foreach (var vr in _styles[id]) | ||
{ | ||
var winfst = winner?.Style ?? ((FontStyle) 0); | ||
|
||
// Since the "style" flags are a bitfield, we can just see which one has more bits. | ||
// More bits == closer to the desired font style. Free fallback! | ||
|
||
// Variant's bit count | ||
var vc = BitOperations.PopCount((ulong) (vr.Style & fst)); | ||
// Winner's bit count | ||
var wc = BitOperations.PopCount((ulong) (winfst & fst)); | ||
|
||
if (winner is null || vc > wc) | ||
winner = vr; | ||
} | ||
|
||
if (winner is null) | ||
throw new Exception($"no matching font style ({id}, {fst})"); | ||
|
||
return winner; | ||
} | ||
|
||
private byte lookupSz(FontSize sz) | ||
{ | ||
if (sz.HasFlag(FontSize.RelMinus) || sz.HasFlag(FontSize.RelPlus)) | ||
throw new Exception("can't look up a relative font through a library; get a Librarian first"); | ||
|
||
if (sz.HasFlag(FontSize.Standard)) | ||
return _standardSz[sz]; | ||
|
||
return (byte) sz; | ||
} | ||
|
||
class FontLibrarian : IFontLibrarian | ||
{ | ||
public Font Current => _current; | ||
private Font _current; | ||
|
||
private FontLibrary _lib; | ||
private string _id; | ||
private FontStyle _fst; | ||
private FontSize _fsz; | ||
|
||
public FontLibrarian(FontLibrary lib, string id, FontStyle fst, FontSize fsz) | ||
{ | ||
_id = id; | ||
_fst = fst; | ||
_fsz = fsz; | ||
_lib = lib; | ||
|
||
// Actual font entry | ||
var f = lib.lookup(id, fst); | ||
|
||
// Real size | ||
var rsz = (byte) lib.lookupSz(fsz); | ||
_current = f.ToFont(rsz); | ||
} | ||
|
||
Font IFontLibrarian.Update(FontStyle fst, FontSize fsz) | ||
{ | ||
var f = _lib.lookup(_id, fst); | ||
|
||
byte rsz = (byte) _fsz; | ||
var msk = (byte) fsz & 0b0000_1111; | ||
if (fsz.HasFlag(FontSize.Standard)) | ||
rsz = _lib.lookupSz(fsz); | ||
else if (fsz.HasFlag(FontSize.RelPlus)) | ||
rsz = (byte) (((byte) _fsz) + msk); | ||
else if (fsz.HasFlag(FontSize.RelMinus)) | ||
rsz = (byte) (((byte) _fsz) - msk); | ||
|
||
_fsz = (FontSize) rsz; | ||
_fst = fst; | ||
|
||
return _current = f.ToFont((byte) rsz); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.