diff --git a/samples/DrawWithImageSharp/DrawWithImageSharp.csproj b/samples/DrawWithImageSharp/DrawWithImageSharp.csproj
index b79b67c6..8c6e4621 100644
--- a/samples/DrawWithImageSharp/DrawWithImageSharp.csproj
+++ b/samples/DrawWithImageSharp/DrawWithImageSharp.csproj
@@ -46,7 +46,7 @@
-
+
diff --git a/samples/DrawWithImageSharp/Program.cs b/samples/DrawWithImageSharp/Program.cs
index f24e6384..1488c9eb 100644
--- a/samples/DrawWithImageSharp/Program.cs
+++ b/samples/DrawWithImageSharp/Program.cs
@@ -289,7 +289,7 @@ public static void RenderTextProcessorWithAlignment(
FontRectangle textSize = TextMeasurer.MeasureSize(text, textOptions);
using var img = new Image(((int)textSize.Width * 2) + 20, ((int)textSize.Height * 2) + 20);
- Size size = img.Size();
+ Size size = img.Size;
textOptions.Origin = new PointF(size.Width / 2F, size.Height / 2F);
img.Mutate(x => x.Fill(Color.Black).ApplyProcessor(
diff --git a/src/SixLabors.Fonts/Tables/AdvancedTypographic/AttachmentListTable.cs b/src/SixLabors.Fonts/Tables/AdvancedTypographic/AttachmentListTable.cs
index 896abe57..ea0695a8 100644
--- a/src/SixLabors.Fonts/Tables/AdvancedTypographic/AttachmentListTable.cs
+++ b/src/SixLabors.Fonts/Tables/AdvancedTypographic/AttachmentListTable.cs
@@ -29,7 +29,7 @@ public static AttachmentListTable Load(BigEndianBinaryReader reader, long offset
Span attachPointOffsets = attachPointOffsetsBuffer.GetSpan();
reader.ReadUInt16Array(attachPointOffsets);
- var attachmentListTable = new AttachmentListTable
+ AttachmentListTable attachmentListTable = new()
{
CoverageTable = CoverageTable.Load(reader, offset + coverageOffset),
AttachPoints = new AttachPoint[glyphCount]
diff --git a/src/SixLabors.Fonts/Tables/AdvancedTypographic/ClassDefinitionTable.cs b/src/SixLabors.Fonts/Tables/AdvancedTypographic/ClassDefinitionTable.cs
index 6ccc4485..c6529e1b 100644
--- a/src/SixLabors.Fonts/Tables/AdvancedTypographic/ClassDefinitionTable.cs
+++ b/src/SixLabors.Fonts/Tables/AdvancedTypographic/ClassDefinitionTable.cs
@@ -1,6 +1,8 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
+using System.Diagnostics.CodeAnalysis;
+
namespace SixLabors.Fonts.Tables.AdvancedTypographic;
///
@@ -20,6 +22,26 @@ internal abstract class ClassDefinitionTable
/// The class id.
public abstract int ClassIndexOf(ushort glyphId);
+ public static bool TryLoad(BigEndianBinaryReader reader, long offset, [NotNullWhen(true)] out ClassDefinitionTable? table)
+ {
+ if (offset == 0)
+ {
+ table = null;
+ return false;
+ }
+
+ reader.Seek(offset, SeekOrigin.Begin);
+ ushort classFormat = reader.ReadUInt16();
+ table = classFormat switch
+ {
+ 1 => ClassDefinitionFormat1Table.Load(reader),
+ 2 => ClassDefinitionFormat2Table.Load(reader),
+ _ => null
+ };
+
+ return table is not null;
+ }
+
public static ClassDefinitionTable Load(BigEndianBinaryReader reader, long offset)
{
reader.Seek(offset, SeekOrigin.Begin);
@@ -97,7 +119,7 @@ public static ClassDefinitionFormat2Table Load(BigEndianBinaryReader reader)
// | | | startGlyphID |
// +------------------+------------------------------------+-----------------------------------------+
ushort classRangeCount = reader.ReadUInt16();
- var records = new ClassRangeRecord[classRangeCount];
+ ClassRangeRecord[] records = new ClassRangeRecord[classRangeCount];
for (int i = 0; i < records.Length; ++i)
{
// +--------+--------------+------------------------------------+
diff --git a/src/SixLabors.Fonts/Tables/AdvancedTypographic/GlyphDefinitionTable.cs b/src/SixLabors.Fonts/Tables/AdvancedTypographic/GlyphDefinitionTable.cs
index dfc2ef5b..2fd85c1a 100644
--- a/src/SixLabors.Fonts/Tables/AdvancedTypographic/GlyphDefinitionTable.cs
+++ b/src/SixLabors.Fonts/Tables/AdvancedTypographic/GlyphDefinitionTable.cs
@@ -145,13 +145,14 @@ public static GlyphDefinitionTable Load(BigEndianBinaryReader reader)
throw new InvalidFontFileException($"Invalid value for 'minor version' {minorVersion} of GDEF table. Should be '0', '2' or '3'.");
}
- ClassDefinitionTable? classDefinitionTable = glyphClassDefOffset is 0 ? null : ClassDefinitionTable.Load(reader, glyphClassDefOffset);
+ ClassDefinitionTable.TryLoad(reader, glyphClassDefOffset, out ClassDefinitionTable? classDefinitionTable);
AttachmentListTable? attachmentListTable = attachListOffset is 0 ? null : AttachmentListTable.Load(reader, attachListOffset);
LigatureCaretList? ligatureCaretList = ligatureCaretListOffset is 0 ? null : LigatureCaretList.Load(reader, ligatureCaretListOffset);
- ClassDefinitionTable? markAttachmentClassDef = markAttachClassDefOffset is 0 ? null : ClassDefinitionTable.Load(reader, markAttachClassDefOffset);
+ ClassDefinitionTable.TryLoad(reader, markAttachClassDefOffset, out ClassDefinitionTable? markAttachmentClassDef);
MarkGlyphSetsTable? markGlyphSetsTable = markGlyphSetsDefOffset is 0 ? null : MarkGlyphSetsTable.Load(reader, markGlyphSetsDefOffset);
- var glyphDefinitionTable = new GlyphDefinitionTable()
+ // TODO: read itemVarStore.
+ return new GlyphDefinitionTable()
{
GlyphClassDefinition = classDefinitionTable,
AttachmentListTable = attachmentListTable,
@@ -159,8 +160,5 @@ public static GlyphDefinitionTable Load(BigEndianBinaryReader reader)
MarkAttachmentClassDef = markAttachmentClassDef,
MarkGlyphSetsTable = markGlyphSetsTable
};
-
- // TODO: read itemVarStore.
- return glyphDefinitionTable;
}
}
diff --git a/src/SixLabors.Fonts/Tables/AdvancedTypographic/MarkGlyphSetsTable.cs b/src/SixLabors.Fonts/Tables/AdvancedTypographic/MarkGlyphSetsTable.cs
index 41daf166..19b4e241 100644
--- a/src/SixLabors.Fonts/Tables/AdvancedTypographic/MarkGlyphSetsTable.cs
+++ b/src/SixLabors.Fonts/Tables/AdvancedTypographic/MarkGlyphSetsTable.cs
@@ -13,7 +13,7 @@ public static MarkGlyphSetsTable Load(BigEndianBinaryReader reader, long offset)
{
reader.Seek(offset, SeekOrigin.Begin);
- var markGlyphSetsTable = new MarkGlyphSetsTable
+ MarkGlyphSetsTable markGlyphSetsTable = new()
{
Format = reader.ReadUInt16()
};
diff --git a/tests/SixLabors.Fonts.Tests/FontLoaderTests.cs b/tests/SixLabors.Fonts.Tests/FontLoaderTests.cs
index 9d1aadef..af86164b 100644
--- a/tests/SixLabors.Fonts.Tests/FontLoaderTests.cs
+++ b/tests/SixLabors.Fonts.Tests/FontLoaderTests.cs
@@ -137,4 +137,16 @@ public void LoadFontWoff()
// the test font only has characters .notdef, 'a' & 'b' defined
Assert.Equal(6, r.ControlPoints.Distinct().Count());
}
+
+ [Fact]
+ public void LoadFontWithIncorrectClassDefinitionTableOffset()
+ {
+ // The following font contains a ClassDefinitionTable with an invalid offset.
+ // See https://forum.stimulsoft.com/viewtopic.php?t=60972
+ Font font = new FontCollection().Add(TestFonts.THSarabunFile).CreateFont(12);
+
+ FontRectangle advance = TextMeasurer.MeasureAdvance("เราใช้คุกกี้เพื่อพัฒนาประสิทธิภาพ และประสบการณ์ที่ดีในการใช้เว็บไซต์ของคุณ คุณสามารถศึกษารายละเอียดได้ที่", new(font));
+
+ Assert.NotEqual(default, advance);
+ }
}
diff --git a/tests/SixLabors.Fonts.Tests/Fonts/THSarabun.ttf b/tests/SixLabors.Fonts.Tests/Fonts/THSarabun.ttf
new file mode 100644
index 00000000..23dd82b1
Binary files /dev/null and b/tests/SixLabors.Fonts.Tests/Fonts/THSarabun.ttf differ
diff --git a/tests/SixLabors.Fonts.Tests/TestFonts.cs b/tests/SixLabors.Fonts.Tests/TestFonts.cs
index dd1f1a3c..85ef2fb3 100644
--- a/tests/SixLabors.Fonts.Tests/TestFonts.cs
+++ b/tests/SixLabors.Fonts.Tests/TestFonts.cs
@@ -243,6 +243,8 @@ public static class TestFonts
public static string DFKaiSBFile => GetFullPath("kaiu.ttf");
+ public static string THSarabunFile => GetFullPath("THSarabun.ttf");
+
public static Stream TwemojiMozillaData() => OpenStream(TwemojiMozillaFile);
public static Stream SegoeuiEmojiData() => OpenStream(SegoeuiEmojiFile);