using System.Text;
namespace XFESystem.Browser.Tests;
public sealed class SvgReferenceTests
{
[Fact]
public void LocalSymbolsUseInheritedColorTranslationAndTheSamePixelsAsFlattenedGeometry()
{
string svg = "<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' color='red'><defs><symbol id='shape'><path fill='currentColor' d='M1 1H9V9H1Z'/></symbol></defs><use href='#shape' x='2' y='3'/></svg>";
string flat = "<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20'><path fill='red' d='M3 4H11V12H3Z'/></svg>";
Assert.Equal(BrowserSvgRasterizer.Decode(Encoding.UTF8.GetBytes(flat), 400).Pixels.ToArray(), BrowserSvgRasterizer.Decode(Encoding.UTF8.GetBytes(svg), 400).Pixels.ToArray());
}
[Theory]
[InlineData("<use href='https://must-not-fetch.test/shape.svg#x'/>", false)]
[InlineData("<defs><g id='x'><use href='#x'/></g></defs><use href='#x'/>", true)]
public void ExternalReferencesAndLocalCyclesFailWithinExplicitBounds(string body, bool cycle)
{
byte[] data = Encoding.UTF8.GetBytes("<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20'>" + body + "</svg>");
if (cycle) Assert.Throws<BrowserLimitException>(() => BrowserSvgRasterizer.Decode(data, 400));
else Assert.Throws<NotSupportedException>(() => BrowserSvgRasterizer.Decode(data, 400));
}
[Fact]
public void InlineUseFreezesASymbolFromAnotherSvgIntoItsOwnImage()
{
var page = new BrowserService();
try
{
page.Navigate("about:Start");
page.ExecuteJavaScript("document.body.innerHTML='<svg style=\"display:none\"><symbol id=shape><path fill=\"currentColor\" d=\"M1 1H9V9H1Z\"/></symbol></svg><svg id=icon width=20 height=20 style=\"color:red\"><use href=\"#shape\"/></svg>'");
var list = page.Layout(new(800, 600));
var image = Assert.Single(list.Commands, command => command.Kind == BrowserDrawKind.Image && command.Node == page.Document!.GetElementById("icon"));
string text = Uri.UnescapeDataString(image.ImageSource[(image.ImageSource.IndexOf(',') + 1)..]);
Assert.Contains("symbol", text, StringComparison.Ordinal);
var pixels = BrowserSvgRasterizer.Decode(Encoding.UTF8.GetBytes(text), 400);
Assert.Equal(0xFFFF0000u, pixels.Pixels.Span[4 * 20 + 4]);
}
finally { page.Release(); }
}
}
using System.Text;
namespace XFESystem.Browser.Tests;
public sealed class SvgReferenceTests
{
[Fact]
public void LocalSymbolsUseInheritedColorTranslationAndTheSamePixelsAsFlattenedGeometry()
{
string svg = "<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' color='red'><defs><symbol id='shape'><path fill='currentColor' d='M1 1H9V9H1Z'/></symbol></defs><use href='#shape' x='2' y='3'/></svg>";
string flat = "<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20'><path fill='red' d='M3 4H11V12H3Z'/></svg>";
Assert.Equal(BrowserSvgRasterizer.Decode(Encoding.UTF8.GetBytes(flat), 400).Pixels.ToArray(), BrowserSvgRasterizer.Decode(Encoding.UTF8.GetBytes(svg), 400).Pixels.ToArray());
}
[Theory]
[InlineData("<use href='https://must-not-fetch.test/shape.svg#x'/>", false)]
[InlineData("<defs><g id='x'><use href='#x'/></g></defs><use href='#x'/>", true)]
public void ExternalReferencesAndLocalCyclesFailWithinExplicitBounds(string body, bool cycle)
{
byte[] data = Encoding.UTF8.GetBytes("<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20'>" + body + "</svg>");
if (cycle) Assert.Throws<BrowserLimitException>(() => BrowserSvgRasterizer.Decode(data, 400));
else Assert.Throws<NotSupportedException>(() => BrowserSvgRasterizer.Decode(data, 400));
}
[Fact]
public void InlineUseFreezesASymbolFromAnotherSvgIntoItsOwnImage()
{
var page = new BrowserService();
try
{
page.Navigate("about:Start");
page.ExecuteJavaScript("document.body.innerHTML='<svg style=\"display:none\"><symbol id=shape><path fill=\"currentColor\" d=\"M1 1H9V9H1Z\"/></symbol></svg><svg id=icon width=20 height=20 style=\"color:red\"><use href=\"#shape\"/></svg>'");
var list = page.Layout(new(800, 600));
var image = Assert.Single(list.Commands, command => command.Kind == BrowserDrawKind.Image && command.Node == page.Document!.GetElementById("icon"));
string text = Uri.UnescapeDataString(image.ImageSource[(image.ImageSource.IndexOf(',') + 1)..]);
Assert.Contains("symbol", text, StringComparison.Ordinal);
var pixels = BrowserSvgRasterizer.Decode(Encoding.UTF8.GetBytes(text), 400);
Assert.Equal(0xFFFF0000u, pixels.Pixels.Span[4 * 20 + 4]);
}
finally { page.Release(); }
}
}