Skip to content

Commit 3d51d90

Browse files
SVG: Use cancellation token while reading SVG
1 parent 838844c commit 3d51d90

2 files changed

Lines changed: 23 additions & 12 deletions

File tree

source/FFImageLoading.Svg.Shared/SkSvg.cs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System.Xml;
1010
using System.Xml.Linq;
1111
using SkiaSharp;
12+
using System.Threading;
1213

1314
namespace FFImageLoading.Svg.Platform
1415
{
@@ -18,7 +19,6 @@ public class SKSvg
1819
private const float DefaultPPI = 160f;
1920
private const bool DefaultThrowOnUnsupportedElement = false;
2021

21-
private static readonly Random random = new Random();
2222
private static readonly IFormatProvider icult = CultureInfo.InvariantCulture;
2323
private static readonly XNamespace xlink = "http://www.w3.org/1999/xlink";
2424
private static readonly XNamespace svg = "http://www.w3.org/2000/svg";
@@ -28,6 +28,7 @@ public class SKSvg
2828
private static readonly Regex urlRe = new Regex(@"url\s*\(\s*#([^\)]+)\)");
2929
private static readonly Regex keyValueRe = new Regex(@"\s*([\w-]+)\s*:\s*(.*)");
3030
private static readonly Regex WSRe = new Regex(@"\s{2,}");
31+
3132
private readonly Dictionary<string, string> styles = new Dictionary<string, string>();
3233
private readonly Dictionary<string, XElement> defs = new Dictionary<string, XElement>();
3334
private readonly Dictionary<string, SKSvgMask> masks = new Dictionary<string, SKSvgMask>();
@@ -78,25 +79,25 @@ public SKSvg(float pixelsPerInch, SKSize canvasSize)
7879

7980
public string Version { get; private set; }
8081

81-
public SKPicture Load(string filename)
82+
public SKPicture Load(string filename, CancellationToken token = default)
8283
{
8384
using (var stream = File.OpenRead(filename))
8485
{
8586
return Load(stream);
8687
}
8788
}
8889

89-
public SKPicture Load(Stream stream)
90+
public SKPicture Load(Stream stream, CancellationToken token = default)
9091
{
9192
using (var reader = XmlReader.Create(stream, xmlReaderSettings, CreateSvgXmlContext()))
9293
{
93-
return Load(reader);
94+
return Load(reader, token);
9495
}
9596
}
9697

97-
public SKPicture Load(XmlReader reader)
98+
public SKPicture Load(XmlReader reader, CancellationToken token = default)
9899
{
99-
return Load(XDocument.Load(reader));
100+
return Load(XDocument.Load(reader), token);
100101
}
101102

102103
private static XmlParserContext CreateSvgXmlContext()
@@ -108,7 +109,7 @@ private static XmlParserContext CreateSvgXmlContext()
108109
return new XmlParserContext(null, manager, null, XmlSpace.None);
109110
}
110111

111-
private SKPicture Load(XDocument xdoc)
112+
private SKPicture Load(XDocument xdoc, CancellationToken token = default)
112113
{
113114
var svg = xdoc.Root;
114115
var ns = svg.Name.Namespace;
@@ -165,6 +166,8 @@ private SKPicture Load(XDocument xdoc)
165166
CanvasSize = size;
166167
}
167168

169+
token.ThrowIfCancellationRequested();
170+
168171
// create the picture from the elements
169172
using (var recorder = new SKPictureRecorder())
170173
using (var canvas = recorder.BeginRecording(SKRect.Create(CanvasSize)))
@@ -203,24 +206,26 @@ private SKPicture Load(XDocument xdoc)
203206
var style = ReadPaints(svg, ref stroke, ref fill, true);
204207

205208
// read elements
206-
LoadElements(svg.Elements(), canvas, stroke, fill);
209+
LoadElements(svg.Elements(), canvas, stroke, fill, token);
207210

208211
Picture = recorder.EndRecording();
209212
}
210213

211214
return Picture;
212215
}
213216

214-
private void LoadElements(IEnumerable<XElement> elements, SKCanvas canvas, SKPaint stroke, SKPaint fill)
217+
private void LoadElements(IEnumerable<XElement> elements, SKCanvas canvas, SKPaint stroke, SKPaint fill, CancellationToken token = default)
215218
{
216219
foreach (var e in elements)
217220
{
218221
ReadElement(e, canvas, stroke?.Clone(), fill?.Clone());
219222
}
220223
}
221224

222-
private void ReadElement(XElement e, SKCanvas canvas, SKPaint stroke, SKPaint fill, bool isMask = false)
225+
private void ReadElement(XElement e, SKCanvas canvas, SKPaint stroke, SKPaint fill, bool isMask = false, CancellationToken token = default)
223226
{
227+
token.ThrowIfCancellationRequested();
228+
224229
if (e.Attribute("display")?.Value == "none")
225230
return;
226231

source/FFImageLoading.Svg.Shared/SvgDataResolver.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ public async Task<DataResolverResult> Resolve(string identifier, TaskParameter p
229229
{
230230
using (var svgStream = resolvedData.Stream)
231231
{
232-
picture = svg.Load(svgStream);
232+
picture = svg.Load(svgStream, token);
233233
}
234234
}
235235
else
@@ -253,13 +253,17 @@ public async Task<DataResolverResult> Resolve(string identifier, TaskParameter p
253253
builder.Replace(map.Key, map.Value);
254254
}
255255

256-
using (var svgFinalStream = new MemoryStream(Encoding.UTF8.GetBytes(builder.ToString())))
256+
token.ThrowIfCancellationRequested();
257+
258+
using (var svgFinalStream = new MemoryStream(Encoding.UTF8.GetBytes(builder.ToString())))
257259
{
258260
picture = svg.Load(svgFinalStream);
259261
}
260262
}
261263
}
262264

265+
token.ThrowIfCancellationRequested();
266+
263267
double sizeX = VectorWidth;
264268
double sizeY = VectorHeight;
265269

@@ -303,6 +307,8 @@ public async Task<DataResolverResult> Resolve(string identifier, TaskParameter p
303307
canvas.DrawPicture(picture, ref matrix, paint);
304308
canvas.Flush();
305309

310+
token.ThrowIfCancellationRequested();
311+
306312
return await Decode(picture, bitmap, resolvedData).ConfigureAwait(false);
307313
}
308314
}

0 commit comments

Comments
 (0)