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);