mirror of https://github.com/icsharpcode/ILSpy.git
Browse Source
Single .NET classlib that embeds one resource of every type the Avalonia port recognises — .xml / .xsd / .xslt / .xaml / .png / .bmp / .jpg / .gif / .ico / .cur / .resources / .bin (unknown-extension fall-through). The image fixtures render a 64×64 cream square with a blue circle and red diagonal stripe so the inline preview is obviously decoded rather than blank; the .ico is multi-frame (16/32/48) so future per-frame work has something to chew on. Assisted-by: Claude:claude-opus-4-7:Claude Codepull/3755/head
15 changed files with 269 additions and 0 deletions
@ -0,0 +1,130 @@
@@ -0,0 +1,130 @@
|
||||
// Tiny helper that produces all the binary fixture files (PNG / BMP / JPG / GIF / ICO / CUR /
|
||||
// .resources / .bin) into the fixtures/ directory. Text fixtures (XML / XSD / XSLT / XAML) are
|
||||
// checked in as-is. Run with `dotnet run --project Generate.csproj` from this directory.
|
||||
//
|
||||
// Each image format renders an obvious recognizable shape (coloured square with a circle and a
|
||||
// diagonal stripe) at 64×64 so manual ILSpy testing can eyeball that the rendering pipeline
|
||||
// is decoding the bytes — not just rendering a blank tile.
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.IO; |
||||
using System.Resources; |
||||
|
||||
using SixLabors.ImageSharp; |
||||
using SixLabors.ImageSharp.Drawing.Processing; |
||||
using SixLabors.ImageSharp.Formats; |
||||
using SixLabors.ImageSharp.Formats.Bmp; |
||||
using SixLabors.ImageSharp.Formats.Gif; |
||||
using SixLabors.ImageSharp.Formats.Jpeg; |
||||
using SixLabors.ImageSharp.Formats.Png; |
||||
using SixLabors.ImageSharp.PixelFormats; |
||||
using SixLabors.ImageSharp.Processing; |
||||
|
||||
var dir = Path.Combine(AppContext.BaseDirectory, "..", "..", "..", "fixtures"); |
||||
dir = Path.GetFullPath(dir); |
||||
Directory.CreateDirectory(dir); |
||||
|
||||
WriteImage(Path.Combine(dir, "logo.png"), new PngEncoder()); |
||||
WriteImage(Path.Combine(dir, "logo.bmp"), new BmpEncoder()); |
||||
WriteImage(Path.Combine(dir, "logo.jpg"), new JpegEncoder { Quality = 92 }); |
||||
WriteImage(Path.Combine(dir, "logo.gif"), new GifEncoder()); |
||||
|
||||
// Multi-frame .ico: 16x16, 32x32, 48x48, each PNG-encoded inside the ICO container so Avalonia
|
||||
// can decode the largest frame for preview while a savvy viewer can pick any.
|
||||
File.WriteAllBytes(Path.Combine(dir, "favicon.ico"), BuildIcoOrCur(isCursor: false, sizes: new[] { 16, 32, 48 })); |
||||
File.WriteAllBytes(Path.Combine(dir, "pointer.cur"), BuildIcoOrCur(isCursor: true, sizes: new[] { 32 })); |
||||
|
||||
// .resources file with a mix of strings and other-typed entries — the .resources DataGrid view
|
||||
// splits these into two tables.
|
||||
var ms = new MemoryStream(); |
||||
using (var rw = new ResourceWriter(ms)) |
||||
{ |
||||
rw.AddResource("greeting", "Hello, world"); |
||||
rw.AddResource("city", "Linz"); |
||||
rw.AddResource("year", 2026); |
||||
rw.AddResource("ratio", 1.61803); |
||||
rw.AddResource("flag", true); |
||||
} |
||||
File.WriteAllBytes(Path.Combine(dir, "Strings.resources"), ms.ToArray()); |
||||
|
||||
// Unknown extension — should fall through to the generic ResourceTreeNode.
|
||||
File.WriteAllBytes(Path.Combine(dir, "blob.bin"), new byte[] { 0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xBA, 0xBE }); |
||||
|
||||
Console.WriteLine($"Wrote fixtures into {dir}"); |
||||
|
||||
// --- helpers ---
|
||||
|
||||
static void WriteImage(string path, IImageEncoder encoder, int size = 64) |
||||
{ |
||||
using var img = RenderShape(size); |
||||
using var fs = File.Create(path); |
||||
img.Save(fs, encoder); |
||||
} |
||||
|
||||
static Image<Rgba32> RenderShape(int size) |
||||
{ |
||||
var img = new Image<Rgba32>(size, size, new Rgba32(0xFF, 0xF6, 0xE5)); |
||||
img.Mutate(ctx => { |
||||
// Filled blue circle in the centre.
|
||||
ctx.Fill(new Rgba32(0x33, 0x99, 0xCC), |
||||
new SixLabors.ImageSharp.Drawing.EllipsePolygon(size / 2f, size / 2f, size * 0.35f)); |
||||
// Red diagonal stripe.
|
||||
ctx.DrawLine(new Rgba32(0xCC, 0x33, 0x33), |
||||
Math.Max(2, size / 16f), |
||||
new PointF(0, size), |
||||
new PointF(size, 0)); |
||||
// 1px dark border so the bounds are obvious against any background.
|
||||
ctx.Draw(new Rgba32(0x33, 0x33, 0x33), 1, |
||||
new RectangleF(0, 0, size - 1, size - 1)); |
||||
}); |
||||
return img; |
||||
} |
||||
|
||||
// Builds an ICO/CUR file containing one PNG-encoded entry per requested size. The on-disk
|
||||
// layout: ICONDIR + ICONDIRENTRY[*] + concatenated frame bytes; only byte 2 (image type)
|
||||
// distinguishes ICO (1) from CUR (2). Hotspot for cursors is centred at (size/2, size/2).
|
||||
static byte[] BuildIcoOrCur(bool isCursor, int[] sizes) |
||||
{ |
||||
var frames = new List<byte[]>(sizes.Length); |
||||
var pngEncoder = new PngEncoder(); |
||||
foreach (var sz in sizes) |
||||
{ |
||||
using var img = RenderShape(sz); |
||||
using var ms = new MemoryStream(); |
||||
img.Save(ms, pngEncoder); |
||||
frames.Add(ms.ToArray()); |
||||
} |
||||
var fileMs = new MemoryStream(); |
||||
var w = new BinaryWriter(fileMs); |
||||
w.Write((ushort)0); // reserved
|
||||
w.Write((ushort)(isCursor ? 2 : 1)); // type: 1=ICO, 2=CUR
|
||||
w.Write((ushort)sizes.Length); // image count
|
||||
int dirSize = 6 + 16 * sizes.Length; |
||||
int offset = dirSize; |
||||
for (int i = 0; i < sizes.Length; i++) |
||||
{ |
||||
var sz = sizes[i]; |
||||
var dim = (byte)(sz >= 256 ? 0 : sz); |
||||
w.Write(dim); // width
|
||||
w.Write(dim); // height
|
||||
w.Write((byte)0); // palette count
|
||||
w.Write((byte)0); // reserved
|
||||
if (isCursor) |
||||
{ |
||||
w.Write((ushort)(sz / 2)); // hotspot X
|
||||
w.Write((ushort)(sz / 2)); // hotspot Y
|
||||
} |
||||
else |
||||
{ |
||||
w.Write((ushort)1); // colour planes
|
||||
w.Write((ushort)32); // bits per pixel
|
||||
} |
||||
w.Write((uint)frames[i].Length); // bytes in frame
|
||||
w.Write((uint)offset); // offset to frame
|
||||
offset += frames[i].Length; |
||||
} |
||||
foreach (var frame in frames) |
||||
w.Write(frame); |
||||
return fileMs.ToArray(); |
||||
} |
||||
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk"> |
||||
<PropertyGroup> |
||||
<OutputType>Exe</OutputType> |
||||
<TargetFramework>net10.0</TargetFramework> |
||||
<RootNamespace>TestFixtures.Generate</RootNamespace> |
||||
<Nullable>enable</Nullable> |
||||
<!-- This generator runs once to (re)build the binary fixtures and isn't part of the |
||||
solution's CPM scope; pin SkiaSharp inline so the parent Directory.Packages.props |
||||
doesn't need to learn about a one-shot tool. --> |
||||
<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally> |
||||
</PropertyGroup> |
||||
<ItemGroup> |
||||
<!-- ImageSharp covers every encoder we need (PNG/JPG/BMP/GIF) cross-platform; SkiaSharp's |
||||
encoder list doesn't include BMP/GIF. --> |
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.11" /> |
||||
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.4" /> |
||||
</ItemGroup> |
||||
</Project> |
||||
@ -0,0 +1,34 @@
@@ -0,0 +1,34 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk"> |
||||
<PropertyGroup> |
||||
<TargetFramework>net10.0</TargetFramework> |
||||
<AssemblyName>TestFixtures.Resources</AssemblyName> |
||||
<RootNamespace>TestFixtures.Resources</RootNamespace> |
||||
<Nullable>enable</Nullable> |
||||
<!-- Standalone fixture for manual ILSpy testing — keep build artifacts entirely |
||||
under this directory so the parent solution doesn't try to compile it. --> |
||||
<BaseOutputPath>$(MSBuildThisFileDirectory)bin\</BaseOutputPath> |
||||
</PropertyGroup> |
||||
|
||||
<ItemGroup> |
||||
<!-- Each resource keeps its file name as the manifest name so it ends up routed to the |
||||
right specialised resource node by extension. --> |
||||
<EmbeddedResource Include="fixtures\sample.xml" LogicalName="sample.xml" /> |
||||
<EmbeddedResource Include="fixtures\schema.xsd" LogicalName="schema.xsd" /> |
||||
<EmbeddedResource Include="fixtures\transform.xslt" LogicalName="transform.xslt" /> |
||||
<EmbeddedResource Include="fixtures\Window.xaml" LogicalName="Window.xaml" /> |
||||
<EmbeddedResource Include="fixtures\logo.png" LogicalName="logo.png" /> |
||||
<EmbeddedResource Include="fixtures\logo.bmp" LogicalName="logo.bmp" /> |
||||
<EmbeddedResource Include="fixtures\logo.jpg" LogicalName="logo.jpg" /> |
||||
<EmbeddedResource Include="fixtures\logo.gif" LogicalName="logo.gif" /> |
||||
<EmbeddedResource Include="fixtures\favicon.ico" LogicalName="favicon.ico" /> |
||||
<EmbeddedResource Include="fixtures\pointer.cur" LogicalName="pointer.cur" /> |
||||
<EmbeddedResource Include="fixtures\Strings.resources" LogicalName="Strings.resources" /> |
||||
<EmbeddedResource Include="fixtures\blob.bin" LogicalName="blob.bin" /> |
||||
</ItemGroup> |
||||
|
||||
<!-- Generate.cs is for the Generate.csproj only; exclude from compilation here. --> |
||||
<ItemGroup> |
||||
<Compile Remove="Generate.cs" /> |
||||
<None Remove="Generate.cs" /> |
||||
</ItemGroup> |
||||
</Project> |
||||
Binary file not shown.
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
<Window xmlns="https://github.com/avaloniaui" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
Title="Demo Window" |
||||
Width="640" |
||||
Height="480"> |
||||
<DockPanel> |
||||
<TextBlock DockPanel.Dock="Top" |
||||
Text="Hello, world" |
||||
FontSize="20" |
||||
Margin="12" /> |
||||
<Border BorderBrush="Gray" |
||||
BorderThickness="1" |
||||
Margin="12"> |
||||
<StackPanel> |
||||
<Button Content="Click me" /> |
||||
<TextBox Text="Some text" /> |
||||
</StackPanel> |
||||
</Border> |
||||
</DockPanel> |
||||
</Window> |
||||
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 796 B |
@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<configuration> |
||||
<appSettings> |
||||
<add key="environment" value="staging" /> |
||||
<add key="timeoutSeconds" value="30" /> |
||||
</appSettings> |
||||
<connectionStrings> |
||||
<add name="default" |
||||
connectionString="Data Source=.;Initial Catalog=Demo;Integrated Security=True" |
||||
providerName="System.Data.SqlClient" /> |
||||
</connectionStrings> |
||||
<runtime> |
||||
<gcServer enabled="true" /> |
||||
</runtime> |
||||
</configuration> |
||||
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" |
||||
targetNamespace="http://example.com/order" |
||||
xmlns="http://example.com/order" |
||||
elementFormDefault="qualified"> |
||||
<xs:element name="order"> |
||||
<xs:complexType> |
||||
<xs:sequence> |
||||
<xs:element name="customer" type="xs:string" /> |
||||
<xs:element name="items"> |
||||
<xs:complexType> |
||||
<xs:sequence> |
||||
<xs:element name="item" maxOccurs="unbounded"> |
||||
<xs:complexType> |
||||
<xs:attribute name="sku" type="xs:string" use="required" /> |
||||
<xs:attribute name="qty" type="xs:positiveInteger" use="required" /> |
||||
</xs:complexType> |
||||
</xs:element> |
||||
</xs:sequence> |
||||
</xs:complexType> |
||||
</xs:element> |
||||
</xs:sequence> |
||||
<xs:attribute name="id" type="xs:string" use="required" /> |
||||
</xs:complexType> |
||||
</xs:element> |
||||
</xs:schema> |
||||
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<xsl:stylesheet version="1.0" |
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> |
||||
<xsl:output method="html" indent="yes" /> |
||||
|
||||
<xsl:template match="/orders"> |
||||
<html> |
||||
<body> |
||||
<h1>Orders</h1> |
||||
<table border="1"> |
||||
<tr> |
||||
<th>ID</th> |
||||
<th>Customer</th> |
||||
</tr> |
||||
<xsl:for-each select="order"> |
||||
<tr> |
||||
<td><xsl:value-of select="@id" /></td> |
||||
<td><xsl:value-of select="customer" /></td> |
||||
</tr> |
||||
</xsl:for-each> |
||||
</table> |
||||
</body> |
||||
</html> |
||||
</xsl:template> |
||||
</xsl:stylesheet> |
||||
Loading…
Reference in new issue