forked from spectreconsole/spectre.console
-
Notifications
You must be signed in to change notification settings - Fork 1
/
SvgEncoder.cs
90 lines (74 loc) · 3.09 KB
/
SvgEncoder.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
using System.Web;
namespace Spectre.Console.Internal;
internal sealed class SvgEncoder : IAnsiConsoleEncoder
{
private readonly SvgEncoderSettings _settings;
public SvgEncoder(SvgEncoderSettings settings)
{
_settings = settings ?? throw new ArgumentNullException(nameof(settings));
}
public string Encode(IAnsiConsole console, IEnumerable<IRenderable> renderable)
{
var template = GetTemplate();
if (template == null)
{
throw new InvalidOperationException("Template could not be found");
}
var context = new RenderContext(new EncoderCapabilities(ColorSystem.TrueColor));
var segmentLines = Segment.SplitLines(
renderable.SelectMany(r => r.Render(context, console.Profile.Width)));
var lines = new List<string>();
foreach (var segmentLine in segmentLines)
{
var line = new List<string>();
foreach (var segment in segmentLine)
{
if (segment.IsControlCode)
{
continue;
}
var text = HttpUtility.HtmlEncode(segment.Text);
if (segment.Style != Style.Plain)
{
var rule = SvgCssBuilder.BuildCss(_settings.Theme, segment.Style);
text = $"<span style=\"color: #{_settings.Theme.ForegroundColor.ToHex()};{rule}; \">{text}</span>";
}
else
{
text = $"<span style=\"color: #{_settings.Theme.ForegroundColor.ToHex()}; \">{text}</span>";
}
line.Add(text);
}
lines.Add($"<div>{string.Concat(line)}</div>");
}
var terminalPadding = 12;
var requiredCodeHeight = _settings.LineHeight * segmentLines.Count;
var terminalHeight = requiredCodeHeight + 60;
var terminalWidth =
(int)((console.Profile.Width * _settings.FontWidthScale * _settings.FontSize)
+ (2 * terminalPadding)
+ console.Profile.Width);
var totalHeight = terminalHeight + (2 * _settings.Margin);
var totalWidth = terminalWidth + (2 * _settings.Margin);
return template
.Replace("@(total_width)", totalWidth.ToString())
.Replace("@(total_height)", totalHeight.ToString())
.Replace("@(font_size)", _settings.FontSize.ToString())
.Replace("@(theme_background_color)", "#" + _settings.Theme.BackgroundColor.ToHex())
.Replace("@(theme_foreground_color)", "#" + _settings.Theme.ForegroundColor.ToHex())
.Replace("@(line_height)", _settings.LineHeight.ToString())
.Replace("@(code)", string.Concat(lines));
}
private static string? GetTemplate()
{
var stream = typeof(SvgEncoder).Assembly.GetManifestResourceStream("Spectre.Console.Svg.Templates.Simple.svg");
if (stream != null)
{
using (var reader = new StreamReader(stream))
{
return reader.ReadToEnd();
}
}
return null;
}
}