@@ -21,14 +21,14 @@ namespace SixLabors.Fonts.Tables.General.Svg;
2121internal sealed class SvgGlyphSource : IPaintedGlyphSource
2222{
2323 private readonly SvgTable svgTable ;
24- private static readonly ConcurrentDictionary < ushort , ParsedDoc > DocCache = [ ] ;
24+ private static readonly Dictionary < ushort , ParsedDoc > DocCache = [ ] ;
2525 private static readonly ConcurrentDictionary < ushort , ( PaintedGlyph Glyph , PaintedCanvas Canvas ) > CachedGlyphs = [ ] ;
2626
2727 private sealed class ParsedDoc
2828 {
2929 public required XDocument Doc { get ; init ; }
3030
31- public required ConcurrentDictionary < string , XElement > IdMap { get ; init ; }
31+ public required Dictionary < string , XElement > IdMap { get ; init ; }
3232 }
3333
3434 /// <summary>
@@ -40,58 +40,50 @@ private sealed class ParsedDoc
4040 /// <inheritdoc/>
4141 public bool TryGetPaintedGlyph ( ushort glyphId , out PaintedGlyph glyph , out PaintedCanvas canvas )
4242 {
43- if ( CachedGlyphs . TryGetValue ( glyphId , out ( PaintedGlyph Glyph , PaintedCanvas Canvas ) cached ) )
43+ ( PaintedGlyph Glyph , PaintedCanvas Canvas ) result = CachedGlyphs . GetOrAdd ( glyphId , gid =>
4444 {
45- glyph = cached . Glyph ;
46- canvas = cached . Canvas ;
47- return true ;
48- }
49-
50- glyph = default ;
51- canvas = default ;
52-
53- if ( ! this . TryGetParsedDoc ( glyphId , out ParsedDoc ? parsed ) )
54- {
55- return false ;
56- }
57-
58- XElement ? root = parsed . Doc . Root ;
59- if ( root is null )
60- {
61- return false ;
62- }
63-
64- FontRectangle viewBox = GetViewBox ( root ) ;
65- Matrix3x2 rootTransform = ParseTransform ( root . Attribute ( "transform" ) ? . Value ) ;
66-
67- // Prefer a dedicated group with id="glyph{gid}", else fall back to the root.
68- string wantedId = "glyph" + glyphId . ToString ( CultureInfo . InvariantCulture ) ;
69- XElement glyphRoot = parsed . IdMap . TryGetValue ( wantedId , out XElement ? ge ) ? ge : root ;
70-
71- List < PaintedLayer > layers = [ ] ;
72- Walk (
73- glyphRoot ,
74- rootTransform ,
75- inheritedPaint : null ,
76- outputLayers : layers ,
77- idMap : parsed . IdMap ) ;
45+ if ( this . TryGetParsedDoc ( gid , out ParsedDoc ? parsed ) )
46+ {
47+ XElement ? root = parsed . Doc . Root ;
48+ if ( root is not null )
49+ {
50+ FontRectangle viewBox = GetViewBox ( root ) ;
51+ Matrix3x2 rootTransform = ParseTransform ( root . Attribute ( "transform" ) ? . Value ) ;
52+
53+ // Prefer a dedicated group with id="glyph{gid}", else fall back to the root.
54+ string wantedId = "glyph" + gid . ToString ( CultureInfo . InvariantCulture ) ;
55+ XElement glyphRoot = parsed . IdMap . TryGetValue ( wantedId , out XElement ? ge ) ? ge : root ;
56+
57+ List < PaintedLayer > layers = [ ] ;
58+ Walk (
59+ glyphRoot ,
60+ rootTransform ,
61+ inheritedPaint : null ,
62+ outputLayers : layers ,
63+ idMap : parsed . IdMap ) ;
64+
65+ if ( layers . Count > 0 )
66+ {
67+ PaintedGlyph glyph = new ( layers ) ;
68+ PaintedCanvas canvas = new ( viewBox , true , rootTransform ) ;
69+ return ( glyph , canvas ) ;
70+ }
71+ }
72+ }
7873
79- if ( layers . Count == 0 )
80- {
81- return false ;
82- }
74+ return ( default , default ) ;
75+ } ) ;
8376
84- glyph = new PaintedGlyph ( layers ) ;
85- canvas = new PaintedCanvas ( viewBox , true , rootTransform ) ;
86- CachedGlyphs [ glyphId ] = ( glyph , canvas ) ;
87- return true ;
77+ glyph = result . Glyph ;
78+ canvas = result . Canvas ;
79+ return result . Glyph . Layers . Count > 0 ;
8880 }
8981
9082 private bool TryGetParsedDoc ( ushort glyphId , [ NotNullWhen ( true ) ] out ParsedDoc ? parsed )
9183 {
9284 parsed = default ;
9385
94- if ( ! this . svgTable . TryGetDocumentSpan ( glyphId , out int start , out int length ) )
86+ if ( ! this . svgTable . TryGetDocumentSpan ( glyphId , out int _ , out int _ ) )
9587 {
9688 return false ;
9789 }
@@ -115,7 +107,7 @@ private bool TryGetParsedDoc(ushort glyphId, [NotNullWhen(true)] out ParsedDoc?
115107 }
116108
117109 // TODO: How large is this likely to get? If large, consider a more memory-efficient structure.
118- ConcurrentDictionary < string , XElement > idMap = new ( Environment . ProcessorCount , capacity : 1024 , comparer : StringComparer . Ordinal ) ;
110+ Dictionary < string , XElement > idMap = new ( 1024 , StringComparer . Ordinal ) ;
119111
120112 foreach ( XElement e in doc . Root . DescendantsAndSelf ( ) )
121113 {
@@ -168,7 +160,7 @@ private static void Walk(
168160 Matrix3x2 parentLocalTransform ,
169161 Paint ? inheritedPaint ,
170162 List < PaintedLayer > outputLayers ,
171- ConcurrentDictionary < string , XElement > idMap )
163+ Dictionary < string , XElement > idMap )
172164 {
173165 Matrix3x2 localTransform = parentLocalTransform * ParseTransform ( node . Attribute ( "transform" ) ? . Value ) ;
174166
@@ -413,7 +405,7 @@ private static FillRule ResolveFillRule(XElement e, FillRule inheritedDefault)
413405 private static Paint ? ResolvePaint (
414406 XElement e ,
415407 Paint ? inherited ,
416- ConcurrentDictionary < string , XElement > idMap ,
408+ Dictionary < string , XElement > idMap ,
417409 out bool fillNone ,
418410 out float opacityMul )
419411 {
@@ -467,7 +459,7 @@ private static FillRule ResolveFillRule(XElement e, FillRule inheritedDefault)
467459 return inherited ;
468460 }
469461
470- private static Paint ? ResolvePaintServer ( string id , ConcurrentDictionary < string , XElement > idMap )
462+ private static Paint ? ResolvePaintServer ( string id , Dictionary < string , XElement > idMap )
471463 {
472464 if ( ! idMap . TryGetValue ( id , out XElement ? server ) )
473465 {
@@ -484,7 +476,7 @@ private static FillRule ResolveFillRule(XElement e, FillRule inheritedDefault)
484476 } ;
485477 }
486478
487- private static LinearGradientPaint ? BuildLinearGradient ( XElement grad , ConcurrentDictionary < string , XElement > idMap )
479+ private static LinearGradientPaint ? BuildLinearGradient ( XElement grad , Dictionary < string , XElement > idMap )
488480 {
489481 GradientUnits units = GradientUnits . ObjectBoundingBox ;
490482 SpreadMethod spread = SpreadMethod . Pad ;
@@ -583,7 +575,7 @@ private static FillRule ResolveFillRule(XElement e, FillRule inheritedDefault)
583575 } ;
584576 }
585577
586- private static RadialGradientPaint ? BuildRadialGradient ( XElement grad , ConcurrentDictionary < string , XElement > idMap )
578+ private static RadialGradientPaint ? BuildRadialGradient ( XElement grad , Dictionary < string , XElement > idMap )
587579 {
588580 GradientUnits units = GradientUnits . ObjectBoundingBox ;
589581 SpreadMethod spread = SpreadMethod . Pad ;
@@ -932,7 +924,7 @@ private static bool TryExtractUrlId(string s, [NotNullWhen(true)] out string? id
932924 return false ;
933925 }
934926
935- private static XElement ? LookupById ( ConcurrentDictionary < string , XElement > idMap , string href )
927+ private static XElement ? LookupById ( Dictionary < string , XElement > idMap , string href )
936928 {
937929 if ( string . IsNullOrEmpty ( href ) || href [ 0 ] != '#' )
938930 {
0 commit comments