Gondwana Game Engine Development (master) - 2.6.1
Gondwana is a cross-platform 2.5D game and rendering engine written in C#/.NET 8. It provides fine-grained control over rendering, timing, and scene composition, with built-in support for parallax, z-ordering, pixel overhang, collision detection, and particle effects. Gondwana targets desktop and web platforms using SkiaSharp for graphics and pluggable audio backends for desktop and browser targets.
Loading...
Searching...
No Matches
SvgResource.cs
1using System.Drawing;
2using SkiaSharp;
3using Svg.Skia;
4
5namespace Gondwana.Drawing;
6
10public sealed class SvgResource : IDisposable
11{
12 private readonly SKPicture _picture;
13 private readonly object _cacheLock = new();
14 private readonly Dictionary<(int Width, int Height), SKBitmap> _cachedBitmaps = new();
15 private bool _disposed;
16
17 private SvgResource(SKPicture picture, SizeF intrinsicSize)
18 {
19 _picture = picture;
20 IntrinsicSize = intrinsicSize;
21 }
22
28 public static SvgResource Load(string path)
29 {
30 ArgumentException.ThrowIfNullOrWhiteSpace(path);
31 using var stream = File.OpenRead(path);
32 return Load(stream);
33 }
34
35 internal static SvgResource Load(Stream stream)
36 {
37 ArgumentNullException.ThrowIfNull(stream);
38
39 var svg = new SKSvg();
40 svg.Load(stream);
41
42 if (svg.Picture is null)
43 throw new InvalidOperationException("Failed to parse SVG content.");
44
45 var cull = svg.Picture.CullRect;
46 var intrinsic = new SizeF(cull.Width > 0 ? cull.Width : 1f,
47 cull.Height > 0 ? cull.Height : 1f);
48
49 return new SvgResource(svg.Picture, intrinsic);
50 }
51
55 public SizeF IntrinsicSize { get; }
56
67 public SKBitmap Rasterize(int width, int height)
68 {
69 ThrowIfDisposed();
70
71 if (width <= 0)
72 throw new ArgumentOutOfRangeException(nameof(width), "Width must be greater than 0.");
73
74 if (height <= 0)
75 throw new ArgumentOutOfRangeException(nameof(height), "Height must be greater than 0.");
76
77 lock (_cacheLock)
78 {
79 if (_cachedBitmaps.TryGetValue((width, height), out var cachedBitmap))
80 return cachedBitmap;
81
82 var bitmap = new SKBitmap(width, height, SKColorType.Bgra8888, SKAlphaType.Premul);
83 using var canvas = new SKCanvas(bitmap);
84 canvas.Clear(SKColors.Transparent);
85
86 var src = _picture.CullRect;
87 if (src.Width <= 0 || src.Height <= 0)
88 {
89 src = new SKRect(0, 0, Math.Max(1f, IntrinsicSize.Width), Math.Max(1f, IntrinsicSize.Height));
90 }
91
92 canvas.Scale(width / src.Width, height / src.Height);
93 canvas.DrawPicture(_picture);
94 canvas.Flush();
95
96 _cachedBitmaps[(width, height)] = bitmap;
97 return bitmap;
98 }
99 }
100
106 public SKBitmap Rasterize(float scale = 1.0f)
107 {
108 ThrowIfDisposed();
109
110 if (scale <= 0f)
111 throw new ArgumentOutOfRangeException(nameof(scale), "Scale must be greater than 0.");
112
113 int width = Math.Max(1, (int)MathF.Round(IntrinsicSize.Width * scale));
114 int height = Math.Max(1, (int)MathF.Round(IntrinsicSize.Height * scale));
115 return Rasterize(width, height);
116 }
117
119 public void Dispose()
120 {
121 if (_disposed)
122 return;
123
124 lock (_cacheLock)
125 {
126 foreach (var bitmap in _cachedBitmaps.Values)
127 bitmap.Dispose();
128
129 _cachedBitmaps.Clear();
130 _picture.Dispose();
131 _disposed = true;
132 }
133 }
134
135 private void ThrowIfDisposed()
136 {
137 ObjectDisposedException.ThrowIf(_disposed, this);
138 }
139}
Represents a loaded SVG asset that can be rasterized into cached bitmaps at requested sizes.
SKBitmap Rasterize(int width, int height)
Rasterizes this SVG to an explicit pixel size.
SKBitmap Rasterize(float scale=1.0f)
Rasterizes this SVG to its intrinsic size multiplied by a scale factor.
SizeF IntrinsicSize
Gets the intrinsic (unscaled) SVG size in pixels.
static SvgResource Load(string path)
Loads an SVG resource from a file path.