Skip to content

Commit ac45c72

Browse files
Adds two new layout modes for FigletText
Now supports fitting (kerning) as well as smushing (both universal and from font rules). Closes #1448
1 parent 9e11f2c commit ac45c72

15 files changed

Lines changed: 2846 additions & 41 deletions

src/Spectre.Console.Tests/Data/banner.flf

Lines changed: 2204 additions & 0 deletions
Large diffs are not rendered by default.

src/Spectre.Console.Tests/Expectations/Public_API.Output.verified.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1944,25 +1944,38 @@
19441944
{
19451945
public int Baseline { get; }
19461946
public int Count { get; }
1947+
public char Hardblank { get; }
19471948
public int Height { get; }
19481949
public int MaxWidth { get; }
1950+
public int SmushingRules { get; }
19491951
public static Spectre.Console.FigletFont Default { get; }
19501952
public static Spectre.Console.FigletFont Load(System.IO.Stream stream) { }
19511953
public static Spectre.Console.FigletFont Load(string path) { }
19521954
public static Spectre.Console.FigletFont Parse(string source) { }
19531955
}
1956+
public enum FigletLayoutMode
1957+
{
1958+
FullSize = 0,
1959+
Fitted = 1,
1960+
Smushed = 2,
1961+
}
19541962
public sealed class FigletText : Spectre.Console.Rendering.Renderable, Spectre.Console.IHasJustification
19551963
{
19561964
public FigletText(string text) { }
19571965
public FigletText(Spectre.Console.FigletFont font, string text) { }
19581966
public Spectre.Console.Color? Color { get; set; }
19591967
public Spectre.Console.Justify? Justification { get; set; }
1968+
public Spectre.Console.FigletLayoutMode LayoutMode { get; set; }
19601969
public bool Pad { get; set; }
19611970
protected override System.Collections.Generic.IEnumerable<Spectre.Console.Rendering.Segment> Render(Spectre.Console.Rendering.RenderOptions options, int maxWidth) { }
19621971
}
19631972
public static class FigletTextExtensions
19641973
{
19651974
public static Spectre.Console.FigletText Color(this Spectre.Console.FigletText text, Spectre.Console.Color? color) { }
1975+
public static Spectre.Console.FigletText Fitted(this Spectre.Console.FigletText text) { }
1976+
public static Spectre.Console.FigletText FullSize(this Spectre.Console.FigletText text) { }
1977+
public static Spectre.Console.FigletText LayoutMode(this Spectre.Console.FigletText text, Spectre.Console.FigletLayoutMode mode) { }
1978+
public static Spectre.Console.FigletText Smushed(this Spectre.Console.FigletText text) { }
19661979
}
19671980
public enum FileSizeBase
19681981
{
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
 ____ _ ____ _
2+
/ ___| _ __ ___ ___ | |_ _ __ ___ / ___| ___ _ __ ___ ___ | | ___
3+
\___ \ | '_ \ / _ \ / __|| __|| '__|/ _ \ | | / _ \ | '_ \ / __| / _ \ | | / _ \
4+
___) || |_) || __/| (__ | |_ | | | __/ _| |___| (_) || | | |\__ \| (_) || || __/
5+
|____/ | .__/ \___| \___| \__||_| \___|(_)\____|\___/ |_| |_||___/ \___/ |_| \___|
6+
|_|
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
 _____
2+
| __ \
3+
| |__) |
4+
| ___/
5+
| |
6+
|_|
7+
8+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
 _____ _ _____ _
2+
/ ____| | | / ____| | |
3+
| (___ _ __ ___ ___| |_ _ __ ___ | | ___ _ __ ___ ___ | | ___
4+
\___ \| '_ \ / _ \/ __| __| '__/ _ | | / _ \| '_ \/ __|/ _ \| |/ _ \
5+
____) | |_) | __/ (__| |_| | | __/| |___| (_) | | | \__ \ (_) | | __/
6+
|_____/| .__/ \___|\___|\__|_| \___(_)_____\___/|_| |_|___/\___/|_|\___|
7+
| |
8+
|_|
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+

2+
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@ @@@@@@@@@
3+
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@ @@@@@@@@@
4+
!@@ @@! @@@@! !@@ @@! @@! @@@@! !@@ @@! @@@@!@!@@!@@
5+
!@! !@! @!!@! !@! !@! !@! @!!@! !@! !@! @!!@!!@!@!@!
6+
!!@@!! @!@@!@!@!!!:! !@! @!! @!@!!@!@!!!:! !@! @!@ !@@!@ !!@!!@@!!
7+
!!@!!!!!@!!! !!!!!: !!! !!! !!@!@! !!!!!: !!! !@! !!!@! !!!!!@!!!
8+
!:!!: !!: :!! !!: !!: :!!!!: :!! !!: !!!!: !!! !:!
9+
!:!:!: :!: :!: :!: :!: !::!: :!:!: :!: !::!: !:! !:!
10+
:::: :: :: :: ::::::: ::: :: :: ::::: ::::::::: ::::::: :::: ::::: ::
11+
:: : : : : :: :: :: :: : : : : : :: ::::::: :: :: : ::: ::: : :
12+
13+
14+
@@@@@@@@@ @@@@@@@@
15+
@@@@@@@@@@ @@@@@@@@
16+
@@! @@@@! @@!
17+
!@! @!!@! !@!
18+
@!@ !@@!! @!!!:!
19+
!@! !!!!! !!!!!:
20+
!!: !!!!: !!:
21+
:!: !:!:!: :!:
22+
::::: :::: :::::: ::::
23+
: : :: :: : : :: ::
24+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
 _______..______ _______ ______ .___________..______ _______ ______ ______ .__ __.
2+
/ || _ \| ____/ || || _ \ | ____| / | / __ \| \ | |
3+
| (----`| |_) | |__ | ,----'`---| |----`| |_) | | |__ | ,----'| | | | \| |
4+
\ \ | ___/| __|| | | | | / | __| | | | | | | . ` |
5+
.----) | | | | |___| `----. | | | |\ \----.| |____ _| `----.| `--' | |\ |
6+
|_______/ | _| |_______\______| |__| | _| `._____||_______(__)______| \______/|__| \__|
7+
8+
_______. ______ __ _______
9+
/ | / __ \| | | ____|
10+
| (----`| | | | | | |__
11+
\ \ | | | | | | __|
12+
.----) | | `--' | `----.| |____
13+
|_______/ \______/|_______||_______|
14+

src/Spectre.Console.Tests/Spectre.Console.Tests.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
<None Remove="Data\example.json" />
1313
<None Remove="Data\starwars.flf" />
1414
<None Remove="Data\poison.flf" />
15+
<None Remove="Data\banner.flf" />
16+
<EmbeddedResource Include="Data\banner.flf" />
1517
</ItemGroup>
1618

1719
<ItemGroup>

src/Spectre.Console.Tests/Unit/Widgets/FigletTests.cs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,22 @@ public async Task Should_Render_Text_Correctly()
3737
await Verifier.Verify(console.Output);
3838
}
3939

40+
[Fact]
41+
[Expectation("Render_Single")]
42+
public async Task Should_Render_Single_Character()
43+
{
44+
// Given
45+
var console = new TestConsole().Width(120);
46+
var font = FigletFont.Load(EmbeddedResourceReader.LoadResourceStream("Spectre.Console.Tests/Data/banner.flf"));
47+
var text = new FigletText(font, "P");
48+
49+
// When
50+
console.Write(text);
51+
52+
// Then
53+
await Verifier.Verify(console.Output);
54+
}
55+
4056
[Fact]
4157
[Expectation("Render_Wrapped")]
4258
public async Task Should_Render_Wrapped_Text_Correctly()
@@ -99,4 +115,105 @@ public async Task Should_Render_Right_Aligned_Text_Correctly()
99115
// Then
100116
await Verifier.Verify(console.Output);
101117
}
118+
119+
[Fact]
120+
[Expectation("Render_Fitted")]
121+
public async Task Should_Render_Fitted_Text_Correctly()
122+
{
123+
// Given
124+
var console = new TestConsole().Width(120);
125+
var text = new FigletText(FigletFont.Default, "Spectre.Console")
126+
{
127+
LayoutMode = FigletLayoutMode.Fitted,
128+
};
129+
130+
// When
131+
console.Write(text);
132+
133+
// Then
134+
await Verifier.Verify(console.Output);
135+
}
136+
137+
[Theory]
138+
[InlineData("starwars.flf")]
139+
[InlineData("poison.flf")]
140+
[Expectation("Render_Smushed_Universal")]
141+
public async Task Should_Render_Smushed_Text_Correctly_Using_Universal_Smushing_Rules(string fontfile)
142+
{
143+
// Given
144+
var console = new TestConsole().Width(120);
145+
var font = FigletFont.Load(EmbeddedResourceReader.LoadResourceStream($"Spectre.Console.Tests/Data/{fontfile}"));
146+
var text = new FigletText(font, "Spectre.Console")
147+
{
148+
LayoutMode = FigletLayoutMode.Smushed,
149+
};
150+
151+
// When
152+
console.Write(text);
153+
154+
// Then
155+
await Verifier.Verify(console.Output)
156+
.UseParameters(fontfile);
157+
}
158+
159+
[Fact]
160+
[Expectation("Render_Smushed")]
161+
public async Task Should_Render_Smushed_Text_Correctly_Using_Font_Smushing_Rules()
162+
{
163+
// Given
164+
var console = new TestConsole().Width(120);
165+
var font = FigletFont.Load(EmbeddedResourceReader.LoadResourceStream("Spectre.Console.Tests/Data/banner.flf"));
166+
var text = new FigletText(font, "Spectre.Console")
167+
{
168+
LayoutMode = FigletLayoutMode.Smushed,
169+
};
170+
171+
// When
172+
console.Write(text);
173+
174+
// Then
175+
await Verifier.Verify(console.Output);
176+
}
177+
178+
[Theory]
179+
[InlineData(FigletLayoutMode.FullSize)]
180+
[InlineData(FigletLayoutMode.Fitted)]
181+
[InlineData(FigletLayoutMode.Smushed)]
182+
public void Should_Render_Empty_String(FigletLayoutMode mode)
183+
{
184+
// Given
185+
var console = new TestConsole().Width(120);
186+
var font = FigletFont.Load(EmbeddedResourceReader.LoadResourceStream("Spectre.Console.Tests/Data/banner.flf"));
187+
var text = new FigletText(font, string.Empty)
188+
{
189+
LayoutMode = mode,
190+
};
191+
192+
// When
193+
console.Write(text);
194+
195+
// Then
196+
console.Output.ShouldBeEmpty();
197+
}
198+
199+
[Theory]
200+
[InlineData(FigletLayoutMode.FullSize)]
201+
[InlineData(FigletLayoutMode.Fitted)]
202+
[InlineData(FigletLayoutMode.Smushed)]
203+
public void Should_Not_Render_Non_Existent_Glyph(FigletLayoutMode mode)
204+
{
205+
// Given
206+
var console = new TestConsole().Width(120);
207+
var font = FigletFont.Load(EmbeddedResourceReader.LoadResourceStream("Spectre.Console.Tests/Data/banner.flf"));
208+
var text = new FigletText(font, "😄")
209+
{
210+
LayoutMode = mode,
211+
};
212+
213+
// When
214+
console.Write(text);
215+
216+
// Then
217+
console.Output.ShouldBeEmpty();
218+
}
102219
}

src/Spectre.Console/Extensions/Bcl/StringBuilderExtensions.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ public static StringBuilder AppendWithStyle(this StringBuilder builder, Style? s
1414
if (style != null)
1515
{
1616
return builder.Append('[')
17-
.Append(style.Value.ToMarkup())
18-
.Append(']')
19-
.Append(value.EscapeMarkup())
20-
.Append("[/]");
17+
.Append(style.Value.ToMarkup())
18+
.Append(']')
19+
.Append(value.EscapeMarkup())
20+
.Append("[/]");
2121
}
2222

2323
return builder.Append(value);
@@ -33,4 +33,17 @@ public static void AppendSpan(this StringBuilder builder, ReadOnlySpan<char> spa
3333
builder.Append(span);
3434
#endif
3535
}
36+
37+
public static int CountTrailing(this StringBuilder current, char[] characters)
38+
{
39+
var trailing = 0;
40+
for (var index = current.Length - 1;
41+
index >= 0 && characters.Any(c => current[index] == c);
42+
index--)
43+
{
44+
trailing++;
45+
}
46+
47+
return trailing;
48+
}
3649
}

0 commit comments

Comments
 (0)