Skip to content

Commit 9d5e995

Browse files
Remove some allocations from SVG
1 parent 360bc07 commit 9d5e995

1 file changed

Lines changed: 62 additions & 76 deletions

File tree

src/SixLabors.Fonts/Tables/General/Svg/SvgGlyphSource.cs

Lines changed: 62 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -821,21 +821,23 @@ private static GradientStop[] BuildStopsArray(List<(float Offset, GlyphColor Col
821821
return null;
822822
}
823823

824-
// TODO: Rewrite this using Span.Split to avoid allocations.
825-
string[] parts = style.Split(';', StringSplitOptions.RemoveEmptyEntries);
826-
for (int i = 0; i < parts.Length; i++)
824+
ReadOnlySpan<char> span = style.AsSpan();
825+
while (span.Length > 0)
827826
{
828-
string part = parts[i];
829-
int c = part.IndexOf(':');
830-
if (c <= 0)
827+
int semi = span.IndexOf(';');
828+
ReadOnlySpan<char> part = semi >= 0 ? span[..semi] : span;
829+
span = semi >= 0 ? span[(semi + 1)..] : [];
830+
831+
int colon = part.IndexOf(':');
832+
if (colon <= 0)
831833
{
832834
continue;
833835
}
834836

835-
string name = part.AsSpan(0, c).Trim().ToString();
836-
if (name.Equals(prop, StringComparison.OrdinalIgnoreCase))
837+
ReadOnlySpan<char> name = part[..colon].Trim();
838+
if (name.Equals(prop.AsSpan(), StringComparison.OrdinalIgnoreCase))
837839
{
838-
return part.AsSpan(c + 1).Trim().ToString();
840+
return part[(colon + 1)..].Trim().ToString();
839841
}
840842
}
841843

@@ -861,15 +863,16 @@ private static bool TryParseColor(string s, out GlyphColor color)
861863
int r = s.IndexOf(')');
862864
if (l >= 0 && r > l)
863865
{
864-
// TODO: Rewrite this using Span.Split to avoid allocations.
865-
string[] comps = s.Substring(l + 1, r - l - 1).Split(',');
866-
if (comps.Length >= 3)
866+
ReadOnlySpan<char> inner = s.AsSpan(l + 1, r - l - 1);
867+
Span<Range> ranges = stackalloc Range[5];
868+
int count = inner.Split(ranges, ',');
869+
if (count >= 3)
867870
{
868-
byte rr = ParseByte(comps[0]);
869-
byte gg = ParseByte(comps[1]);
870-
byte bb = ParseByte(comps[2]);
871+
byte rr = ParseByte(inner[ranges[0]]);
872+
byte gg = ParseByte(inner[ranges[1]]);
873+
byte bb = ParseByte(inner[ranges[2]]);
871874
byte aa = 255;
872-
if (comps.Length >= 4 && float.TryParse(comps[3], NumberStyles.Float, CultureInfo.InvariantCulture, out float af))
875+
if (count >= 4 && float.TryParse(inner[ranges[3]].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out float af))
873876
{
874877
aa = (byte)Math.Clamp((int)Math.Round(255f * af), 0, 255);
875878
}
@@ -1429,7 +1432,7 @@ private static Matrix3x2 ParseTransform(string? s)
14291432
i++;
14301433
}
14311434

1432-
string op = s[start..i];
1435+
ReadOnlySpan<char> op = s.AsSpan(start, i - start);
14331436

14341437
SkipSep(s, ref i);
14351438
if (i >= n || s[i] != '(')
@@ -1455,78 +1458,58 @@ private static Matrix3x2 ParseTransform(string? s)
14551458
i++;
14561459
}
14571460

1458-
string args = s.Substring(argsStart, (i - argsStart) - 1);
1461+
ReadOnlySpan<char> args = s.AsSpan(argsStart, (i - argsStart) - 1);
14591462
float[] a = ParseFloatList(args);
14601463

14611464
Matrix3x2 t = Matrix3x2.Identity;
1462-
switch (op)
1465+
if (op.SequenceEqual("matrix"))
14631466
{
1464-
case "matrix":
1467+
if (a.Length >= 6)
14651468
{
1466-
if (a.Length >= 6)
1467-
{
1468-
t = new Matrix3x2(a[0], a[1], a[2], a[3], a[4], a[5]);
1469-
}
1470-
1471-
break;
1469+
t = new Matrix3x2(a[0], a[1], a[2], a[3], a[4], a[5]);
14721470
}
1473-
1474-
case "translate":
1471+
}
1472+
else if (op.SequenceEqual("translate"))
1473+
{
1474+
if (a.Length == 1)
14751475
{
1476-
if (a.Length == 1)
1477-
{
1478-
t = Matrix3x2.CreateTranslation(a[0], 0f);
1479-
}
1480-
else if (a.Length >= 2)
1481-
{
1482-
t = Matrix3x2.CreateTranslation(a[0], a[1]);
1483-
}
1484-
1485-
break;
1476+
t = Matrix3x2.CreateTranslation(a[0], 0f);
14861477
}
1487-
1488-
case "scale":
1478+
else if (a.Length >= 2)
14891479
{
1490-
if (a.Length == 1)
1491-
{
1492-
t = Matrix3x2.CreateScale(a[0], a[0]);
1493-
}
1494-
else if (a.Length >= 2)
1495-
{
1496-
t = Matrix3x2.CreateScale(a[0], a[1]);
1497-
}
1498-
1499-
break;
1480+
t = Matrix3x2.CreateTranslation(a[0], a[1]);
15001481
}
1501-
1502-
case "rotate":
1482+
}
1483+
else if (op.SequenceEqual("scale"))
1484+
{
1485+
if (a.Length == 1)
15031486
{
1504-
if (a.Length >= 1)
1505-
{
1506-
t = Matrix3x2.CreateRotation(a[0] * (float)(Math.PI / 180.0));
1507-
}
1508-
1509-
break;
1487+
t = Matrix3x2.CreateScale(a[0], a[0]);
15101488
}
1511-
1512-
case "skewX":
1489+
else if (a.Length >= 2)
15131490
{
1514-
if (a.Length >= 1)
1515-
{
1516-
t = new Matrix3x2(1f, 0f, MathF.Tan(a[0] * (float)(Math.PI / 180.0)), 1f, 0f, 0f);
1517-
}
1518-
1519-
break;
1491+
t = Matrix3x2.CreateScale(a[0], a[1]);
15201492
}
1521-
1522-
case "skewY":
1493+
}
1494+
else if (op.SequenceEqual("rotate"))
1495+
{
1496+
if (a.Length >= 1)
15231497
{
1524-
if (a.Length >= 1)
1525-
{
1526-
t = new Matrix3x2(1f, MathF.Tan(a[0] * (float)(Math.PI / 180.0)), 0f, 1f, 0f, 0f);
1527-
}
1528-
1529-
break;
1498+
t = Matrix3x2.CreateRotation(a[0] * (float)(Math.PI / 180.0));
1499+
}
1500+
}
1501+
else if (op.SequenceEqual("skewX"))
1502+
{
1503+
if (a.Length >= 1)
1504+
{
1505+
t = new Matrix3x2(1f, 0f, MathF.Tan(a[0] * (float)(Math.PI / 180.0)), 1f, 0f, 0f);
1506+
}
1507+
}
1508+
else if (op.SequenceEqual("skewY"))
1509+
{
1510+
if (a.Length >= 1)
1511+
{
1512+
t = new Matrix3x2(1f, MathF.Tan(a[0] * (float)(Math.PI / 180.0)), 0f, 1f, 0f, 0f);
15301513
}
15311514
}
15321515

@@ -1652,8 +1635,11 @@ private static float ParseFloat(ReadOnlySpan<char> str)
16521635
=> str.IsEmpty ? 0 : float.Parse(str, CultureInfo.InvariantCulture);
16531636

16541637
private static float[] ParseFloatList(string s)
1638+
=> string.IsNullOrEmpty(s) ? [] : ParseFloatList(s.AsSpan());
1639+
1640+
private static float[] ParseFloatList(ReadOnlySpan<char> s)
16551641
{
1656-
if (string.IsNullOrEmpty(s))
1642+
if (s.IsEmpty)
16571643
{
16581644
return [];
16591645
}
@@ -1715,7 +1701,7 @@ private static float[] ParseFloatList(string s)
17151701
}
17161702
}
17171703

1718-
if (float.TryParse(s.AsSpan(start, i - start), NumberStyles.Float, CultureInfo.InvariantCulture, out float v))
1704+
if (float.TryParse(s[start..i], NumberStyles.Float, CultureInfo.InvariantCulture, out float v))
17191705
{
17201706
vals.Add(v);
17211707
}

0 commit comments

Comments
 (0)