From 154432a78bad453839d55a452bfda5a37f3e9704 Mon Sep 17 00:00:00 2001 From: ABykiev Date: Thu, 1 Aug 2024 20:38:42 +0300 Subject: [PATCH 1/2] Fix IDisposable usage This PR fixes a memory leak in FontReader with Woff2 fonts. Because of this FontReader class now implements IDisposable interface. This PR also wraps disposable types with using statements to remove warnings. --- src/SixLabors.Fonts/Buffer{T}.cs | 2 +- src/SixLabors.Fonts/FileFontMetrics.cs | 2 +- src/SixLabors.Fonts/FontCollection.cs | 2 +- src/SixLabors.Fonts/FontDescription.cs | 8 +++---- src/SixLabors.Fonts/FontReader.cs | 17 +++++++++---- .../Native/MacSystemFontsEnumerator.cs | 2 +- src/SixLabors.Fonts/StreamFontMetrics.cs | 4 ++-- .../Tables/Cff/CffDataDicEntry.cs | 4 ++-- .../SixLabors.Fonts.Tests/FontReaderTests.cs | 24 +++++++++---------- .../Tables/General/CMapTableTests.cs | 6 ++++- .../Tables/General/ColrTableTests.cs | 11 +++++---- .../General/HorizontalHeadTableTests.cs | 5 ++-- .../Tables/General/IndexLocationTableTests.cs | 23 +++++++++++------- .../Tables/General/KerningTableTests.cs | 7 +++--- .../General/MaximumProfileTableTests.cs | 7 ++++-- .../Tables/General/NameTableTests.cs | 9 ++++--- .../Tables/General/Os2TableTests.cs | 7 +++--- .../Tables/General/VerticalHeadTableTests.cs | 3 ++- 18 files changed, 87 insertions(+), 56 deletions(-) diff --git a/src/SixLabors.Fonts/Buffer{T}.cs b/src/SixLabors.Fonts/Buffer{T}.cs index 5b8ec3f..d3bd043 100644 --- a/src/SixLabors.Fonts/Buffer{T}.cs +++ b/src/SixLabors.Fonts/Buffer{T}.cs @@ -26,7 +26,7 @@ internal ref struct Buffer this.buffer = ArrayPool.Shared.Rent(bufferSizeInBytes); this.length = length; - ByteMemoryManager manager = new(this.buffer); + using ByteMemoryManager manager = new(this.buffer); this.Memory = manager.Memory.Slice(0, this.length); this.span = this.Memory.Span; diff --git a/src/SixLabors.Fonts/FileFontMetrics.cs b/src/SixLabors.Fonts/FileFontMetrics.cs index d316c5e..eadd93c 100644 --- a/src/SixLabors.Fonts/FileFontMetrics.cs +++ b/src/SixLabors.Fonts/FileFontMetrics.cs @@ -164,7 +164,7 @@ internal sealed class FileFontMetrics : FontMetrics { using FileStream fs = File.OpenRead(path); long startPos = fs.Position; - BigEndianBinaryReader reader = new(fs, true); + using BigEndianBinaryReader reader = new(fs, true); TtcHeader ttcHeader = TtcHeader.Read(reader); FileFontMetrics[] fonts = new FileFontMetrics[(int)ttcHeader.NumFonts]; diff --git a/src/SixLabors.Fonts/FontCollection.cs b/src/SixLabors.Fonts/FontCollection.cs index e3815e4..437d430 100644 --- a/src/SixLabors.Fonts/FontCollection.cs +++ b/src/SixLabors.Fonts/FontCollection.cs @@ -234,7 +234,7 @@ public sealed class FontCollection : IFontCollection, IFontMetricsCollection out IEnumerable descriptions) { long startPos = stream.Position; - BigEndianBinaryReader reader = new(stream, true); + using BigEndianBinaryReader reader = new(stream, true); TtcHeader ttcHeader = TtcHeader.Read(reader); List result = new((int)ttcHeader.NumFonts); HashSet installedFamilies = new(); diff --git a/src/SixLabors.Fonts/FontDescription.cs b/src/SixLabors.Fonts/FontDescription.cs index 27d3877..ce20c98 100644 --- a/src/SixLabors.Fonts/FontDescription.cs +++ b/src/SixLabors.Fonts/FontDescription.cs @@ -92,7 +92,7 @@ public class FontDescription Guard.NotNullOrWhiteSpace(path, nameof(path)); using FileStream fs = File.OpenRead(path); - var reader = new FontReader(fs); + using var reader = new FontReader(fs); return LoadDescription(reader); } @@ -106,7 +106,7 @@ public class FontDescription Guard.NotNull(stream, nameof(stream)); // Only read the name tables. - var reader = new FontReader(stream); + using var reader = new FontReader(stream); return LoadDescription(reader); } @@ -152,14 +152,14 @@ public class FontDescription public static FontDescription[] LoadFontCollectionDescriptions(Stream stream) { long startPos = stream.Position; - var reader = new BigEndianBinaryReader(stream, true); + using var reader = new BigEndianBinaryReader(stream, true); var ttcHeader = TtcHeader.Read(reader); var result = new FontDescription[(int)ttcHeader.NumFonts]; for (int i = 0; i < ttcHeader.NumFonts; ++i) { stream.Position = startPos + ttcHeader.OffsetTable[i]; - var fontReader = new FontReader(stream); + using var fontReader = new FontReader(stream); result[i] = LoadDescription(fontReader); } diff --git a/src/SixLabors.Fonts/FontReader.cs b/src/SixLabors.Fonts/FontReader.cs index 37efd0e..cfeae13 100644 --- a/src/SixLabors.Fonts/FontReader.cs +++ b/src/SixLabors.Fonts/FontReader.cs @@ -9,21 +9,21 @@ using SixLabors.Fonts.Tables.Woff; namespace SixLabors.Fonts; -internal sealed class FontReader +internal sealed class FontReader : IDisposable { private readonly Stream stream; private readonly Dictionary loadedTables = new(); private readonly TableLoader loader; + private readonly bool disposable; internal FontReader(Stream stream, TableLoader loader) { this.loader = loader; Func loadHeader = TableHeader.Read; - long startOfFilePosition = stream.Position; this.stream = stream; - var reader = new BigEndianBinaryReader(stream, true); + using var reader = new BigEndianBinaryReader(stream, true); // we should immediately read the table header to learn which tables we have and what order they are in uint version = reader.ReadUInt32(); @@ -85,13 +85,14 @@ internal sealed class FontReader this.CompressedTableData = true; this.Headers = Woff2Utils.ReadWoff2Headers(reader, tableCount); + this.disposable = true; + byte[] compressedBuffer = reader.ReadBytes((int)totalCompressedSize); var decompressedStream = new MemoryStream(); using var input = new MemoryStream(compressedBuffer); using var decompressor = new BrotliStream(input, CompressionMode.Decompress); decompressor.CopyTo(decompressedStream); decompressedStream.Position = 0; - this.stream.Dispose(); this.stream = decompressedStream; return; } @@ -197,4 +198,12 @@ internal sealed class FontReader reader = header?.CreateReader(this.stream); return reader != null; } + + public void Dispose() + { + if (this.disposable) + { + this.stream.Dispose(); + } + } } diff --git a/src/SixLabors.Fonts/Native/MacSystemFontsEnumerator.cs b/src/SixLabors.Fonts/Native/MacSystemFontsEnumerator.cs index c59f956..9f28aff 100644 --- a/src/SixLabors.Fonts/Native/MacSystemFontsEnumerator.cs +++ b/src/SixLabors.Fonts/Native/MacSystemFontsEnumerator.cs @@ -18,7 +18,7 @@ namespace SixLabors.Fonts.Native; /// Internally, it calls the native CoreText's method to retrieve /// the list of fonts so using this class must be guarded by RuntimeInformation.IsOSPlatform(OSPlatform.OSX). /// -internal class MacSystemFontsEnumerator : IEnumerable, IEnumerator +internal sealed class MacSystemFontsEnumerator : IEnumerable, IEnumerator { private static readonly ArrayPool BytePool = ArrayPool.Shared; diff --git a/src/SixLabors.Fonts/StreamFontMetrics.cs b/src/SixLabors.Fonts/StreamFontMetrics.cs index 4b8ca43..afb1b9f 100644 --- a/src/SixLabors.Fonts/StreamFontMetrics.cs +++ b/src/SixLabors.Fonts/StreamFontMetrics.cs @@ -333,7 +333,7 @@ internal partial class StreamFontMetrics : FontMetrics public static StreamFontMetrics LoadFont(string path) { using FileStream fs = File.OpenRead(path); - var reader = new FontReader(fs); + using var reader = new FontReader(fs); return LoadFont(reader); } @@ -357,7 +357,7 @@ internal partial class StreamFontMetrics : FontMetrics /// a . public static StreamFontMetrics LoadFont(Stream stream) { - var reader = new FontReader(stream); + using var reader = new FontReader(stream); return LoadFont(reader); } diff --git a/src/SixLabors.Fonts/Tables/Cff/CffDataDicEntry.cs b/src/SixLabors.Fonts/Tables/Cff/CffDataDicEntry.cs index a4d7e4f..42e6466 100644 --- a/src/SixLabors.Fonts/Tables/Cff/CffDataDicEntry.cs +++ b/src/SixLabors.Fonts/Tables/Cff/CffDataDicEntry.cs @@ -26,13 +26,13 @@ internal class CffDataDicEntry { if (i > 0) { - builder.Append(" "); + builder.Append(' '); } builder.Append(this.Operands[i].ToString()); } - builder.Append(" "); + builder.Append(' '); builder.Append(this.Operator?.ToString() ?? string.Empty); return builder.ToString(); } diff --git a/tests/SixLabors.Fonts.Tests/FontReaderTests.cs b/tests/SixLabors.Fonts.Tests/FontReaderTests.cs index 5f256e7..2c09832 100644 --- a/tests/SixLabors.Fonts.Tests/FontReaderTests.cs +++ b/tests/SixLabors.Fonts.Tests/FontReaderTests.cs @@ -15,7 +15,7 @@ public class FontReaderTests var writer = new BigEndianBinaryWriter(); writer.WriteTrueTypeFileHeader(0, 0, 0, 0); - var reader = new FontReader(writer.GetStream()); + using var reader = new FontReader(writer.GetStream()); Assert.Equal(OutlineType.TrueType, reader.OutlineType); } @@ -25,7 +25,7 @@ public class FontReaderTests var writer = new BigEndianBinaryWriter(); writer.WriteCffFileHeader(0, 0, 0, 0); - var reader = new FontReader(writer.GetStream()); + using var reader = new FontReader(writer.GetStream()); Assert.Equal(OutlineType.CFF, reader.OutlineType); } @@ -37,7 +37,7 @@ public class FontReaderTests writer.WriteTableHeader("name", 0, 10, 0); writer.WriteTableHeader("cmap", 0, 1, 0); - var reader = new FontReader(writer.GetStream()); + using var reader = new FontReader(writer.GetStream()); Assert.Equal(2, reader.Headers.Count); } @@ -59,7 +59,7 @@ public class FontReaderTests new byte[] { 2, 9 }) }); - var reader = new FontReader(writer.GetStream()); + using var reader = new FontReader(writer.GetStream()); CMapTable cmap = reader.GetTable(); Assert.NotNull(cmap); } @@ -67,8 +67,8 @@ public class FontReaderTests [Fact] public void ReadFont_WithWoffFormat_EqualsTtf() { - var fontReaderTtf = new FontReader(TestFonts.OpenSansTtfData()); - var fontReaderWoff = new FontReader(TestFonts.OpensSansWoff1Data()); + using var fontReaderTtf = new FontReader(TestFonts.OpenSansTtfData()); + using var fontReaderWoff = new FontReader(TestFonts.OpensSansWoff1Data()); Assert.Equal(fontReaderTtf.Headers.Count, fontReaderWoff.Headers.Count); foreach (string key in fontReaderTtf.Headers.Keys) @@ -80,9 +80,9 @@ public class FontReaderTests [Fact] public void GlyphsCount_WithWoffFormat_EqualsTtf() { - var fontReaderWoff = new FontReader(TestFonts.OpensSansWoff1Data()); + using var fontReaderWoff = new FontReader(TestFonts.OpensSansWoff1Data()); GlyphTable glyphsWoff = fontReaderWoff.GetTable(); - var fontReaderTtf = new FontReader(TestFonts.OpenSansTtfData()); + using var fontReaderTtf = new FontReader(TestFonts.OpenSansTtfData()); GlyphTable glyphsTtf = fontReaderTtf.GetTable(); Assert.Equal(glyphsTtf.GlyphCount, glyphsWoff.GlyphCount); @@ -91,8 +91,8 @@ public class FontReaderTests [Fact] public void ReadFont_WithWoff2Format_EqualsTtf() { - var fontReaderTtf = new FontReader(TestFonts.OpenSansTtfData()); - var fontReaderWoff = new FontReader(TestFonts.OpensSansWoff2Data()); + using var fontReaderTtf = new FontReader(TestFonts.OpenSansTtfData()); + using var fontReaderWoff = new FontReader(TestFonts.OpensSansWoff2Data()); Assert.Equal(fontReaderTtf.Headers.Count, fontReaderWoff.Headers.Count); foreach (string key in fontReaderTtf.Headers.Keys) @@ -104,9 +104,9 @@ public class FontReaderTests [Fact] public void GlyphsCount_WithWoff2Format_EqualsTtf() { - var fontReaderWoff = new FontReader(TestFonts.OpensSansWoff2Data()); + using var fontReaderWoff = new FontReader(TestFonts.OpensSansWoff2Data()); GlyphTable glyphsWoff = fontReaderWoff.GetTable(); - var fontReaderTtf = new FontReader(TestFonts.OpenSansTtfData()); + using var fontReaderTtf = new FontReader(TestFonts.OpenSansTtfData()); GlyphTable glyphsTtf = fontReaderTtf.GetTable(); Assert.Equal(glyphsTtf.GlyphCount, glyphsWoff.GlyphCount); diff --git a/tests/SixLabors.Fonts.Tests/Tables/General/CMapTableTests.cs b/tests/SixLabors.Fonts.Tests/Tables/General/CMapTableTests.cs index 1d6acc7..b7e351d 100644 --- a/tests/SixLabors.Fonts.Tests/Tables/General/CMapTableTests.cs +++ b/tests/SixLabors.Fonts.Tests/Tables/General/CMapTableTests.cs @@ -35,7 +35,11 @@ public class CMapTableTests using (System.IO.MemoryStream stream = writer.GetStream()) { - InvalidFontTableException exception = Assert.Throws(() => CMapTable.Load(new FontReader(stream))); + InvalidFontTableException exception = Assert.Throws(() => + { + using var reader = new FontReader(stream); + CMapTable.Load(reader); + }); Assert.Equal("cmap", exception.Table); } diff --git a/tests/SixLabors.Fonts.Tests/Tables/General/ColrTableTests.cs b/tests/SixLabors.Fonts.Tests/Tables/General/ColrTableTests.cs index b72299f..7f60b60 100644 --- a/tests/SixLabors.Fonts.Tests/Tables/General/ColrTableTests.cs +++ b/tests/SixLabors.Fonts.Tests/Tables/General/ColrTableTests.cs @@ -14,9 +14,10 @@ public class ColrTableTests var writer = new BigEndianBinaryWriter(); writer.WriteTrueTypeFileHeader(); - using (System.IO.MemoryStream stream = writer.GetStream()) + using (MemoryStream stream = writer.GetStream()) { - Assert.Null(ColrTable.Load(new FontReader(stream))); + using var reader = new FontReader(stream); + Assert.Null(ColrTable.Load(reader)); } } @@ -47,12 +48,12 @@ public class ColrTableTests } }); - using (System.IO.Stream stream = TestFonts.TwemojiMozillaData()) + using (Stream stream = TestFonts.TwemojiMozillaData()) { - var reader = new FontReader(stream); + using var reader = new FontReader(stream); ColrTable tbl = reader.GetTable(); - System.Span layers = tbl.GetLayers(15); + Span layers = tbl.GetLayers(15); Assert.Equal(2, layers.Length); } } diff --git a/tests/SixLabors.Fonts.Tests/Tables/General/HorizontalHeadTableTests.cs b/tests/SixLabors.Fonts.Tests/Tables/General/HorizontalHeadTableTests.cs index 31940af..95d5540 100644 --- a/tests/SixLabors.Fonts.Tests/Tables/General/HorizontalHeadTableTests.cs +++ b/tests/SixLabors.Fonts.Tests/Tables/General/HorizontalHeadTableTests.cs @@ -35,9 +35,10 @@ public class HorizontalHeadTableTests var writer = new BigEndianBinaryWriter(); writer.WriteTrueTypeFileHeader(); - using (System.IO.MemoryStream stream = writer.GetStream()) + using (MemoryStream stream = writer.GetStream()) { - Assert.Null(HorizontalHeadTable.Load(new FontReader(stream))); + using var reader = new FontReader(stream); + Assert.Null(HorizontalHeadTable.Load(reader)); } } } diff --git a/tests/SixLabors.Fonts.Tests/Tables/General/IndexLocationTableTests.cs b/tests/SixLabors.Fonts.Tests/Tables/General/IndexLocationTableTests.cs index ce11426..1052cc0 100644 --- a/tests/SixLabors.Fonts.Tests/Tables/General/IndexLocationTableTests.cs +++ b/tests/SixLabors.Fonts.Tests/Tables/General/IndexLocationTableTests.cs @@ -15,10 +15,13 @@ public class IndexLocationTableTests var writer = new BigEndianBinaryWriter(); writer.WriteTrueTypeFileHeader(); - using (System.IO.MemoryStream stream = writer.GetStream()) + using (MemoryStream stream = writer.GetStream()) { - MissingFontTableException exception = Assert.Throws( - () => IndexLocationTable.Load(new FontReader(stream))); + MissingFontTableException exception = Assert.Throws(() => + { + using var reader = new FontReader(stream); + IndexLocationTable.Load(reader); + }); Assert.Equal("head", exception.Table); } @@ -40,10 +43,13 @@ public class IndexLocationTableTests 0, HeadTable.IndexLocationFormats.Offset16)); - using (System.IO.MemoryStream stream = writer.GetStream()) + using (MemoryStream stream = writer.GetStream()) { - InvalidFontTableException exception = Assert.Throws( - () => IndexLocationTable.Load(new FontReader(stream))); + InvalidFontTableException exception = Assert.Throws(() => + { + using var reader = new FontReader(stream); + IndexLocationTable.Load(reader); + }); Assert.Equal("maxp", exception.Table); } @@ -65,9 +71,10 @@ public class IndexLocationTableTests 0, HeadTable.IndexLocationFormats.Offset16)); - using (System.IO.MemoryStream stream = writer.GetStream()) + using (MemoryStream stream = writer.GetStream()) { - Assert.Null(IndexLocationTable.Load(new FontReader(stream))); + using var reader = new FontReader(stream); + Assert.Null(IndexLocationTable.Load(reader)); } } } diff --git a/tests/SixLabors.Fonts.Tests/Tables/General/KerningTableTests.cs b/tests/SixLabors.Fonts.Tests/Tables/General/KerningTableTests.cs index 8f0eae7..b018359 100644 --- a/tests/SixLabors.Fonts.Tests/Tables/General/KerningTableTests.cs +++ b/tests/SixLabors.Fonts.Tests/Tables/General/KerningTableTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using SixLabors.Fonts.Tables.General.Kern; @@ -13,9 +13,10 @@ public class KerningTableTests var writer = new BigEndianBinaryWriter(); writer.WriteTrueTypeFileHeader(); - using (System.IO.MemoryStream stream = writer.GetStream()) + using (MemoryStream stream = writer.GetStream()) { - var table = KerningTable.Load(new FontReader(stream)); + using var reader = new FontReader(stream); + var table = KerningTable.Load(reader); Assert.NotNull(table); } } diff --git a/tests/SixLabors.Fonts.Tests/Tables/General/MaximumProfileTableTests.cs b/tests/SixLabors.Fonts.Tests/Tables/General/MaximumProfileTableTests.cs index 6e26013..54f123d 100644 --- a/tests/SixLabors.Fonts.Tests/Tables/General/MaximumProfileTableTests.cs +++ b/tests/SixLabors.Fonts.Tests/Tables/General/MaximumProfileTableTests.cs @@ -15,8 +15,11 @@ public class MaximumProfileTableTests using (MemoryStream stream = writer.GetStream()) { - InvalidFontTableException exception = Assert.Throws( - () => MaximumProfileTable.Load(new FontReader(stream))); + InvalidFontTableException exception = Assert.Throws(() => + { + using var reader = new FontReader(stream); + MaximumProfileTable.Load(reader); + }); Assert.Equal("maxp", exception.Table); } diff --git a/tests/SixLabors.Fonts.Tests/Tables/General/NameTableTests.cs b/tests/SixLabors.Fonts.Tests/Tables/General/NameTableTests.cs index 12ae2dc..25cec2c 100644 --- a/tests/SixLabors.Fonts.Tests/Tables/General/NameTableTests.cs +++ b/tests/SixLabors.Fonts.Tests/Tables/General/NameTableTests.cs @@ -76,10 +76,13 @@ public class NameTableTests var writer = new BigEndianBinaryWriter(); writer.WriteTrueTypeFileHeader(); - using (System.IO.MemoryStream stream = writer.GetStream()) + using (MemoryStream stream = writer.GetStream()) { - InvalidFontTableException exception = Assert.Throws( - () => NameTable.Load(new FontReader(stream))); + InvalidFontTableException exception = Assert.Throws(() => + { + using var reader = new FontReader(stream); + NameTable.Load(reader); + }); Assert.Equal("name", exception.Table); } diff --git a/tests/SixLabors.Fonts.Tests/Tables/General/Os2TableTests.cs b/tests/SixLabors.Fonts.Tests/Tables/General/Os2TableTests.cs index ed6dde0..cfa4a2f 100644 --- a/tests/SixLabors.Fonts.Tests/Tables/General/Os2TableTests.cs +++ b/tests/SixLabors.Fonts.Tests/Tables/General/Os2TableTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using SixLabors.Fonts.Tables.General; @@ -13,9 +13,10 @@ public class OS2TableTests var writer = new BigEndianBinaryWriter(); writer.WriteTrueTypeFileHeader(); - using (System.IO.MemoryStream stream = writer.GetStream()) + using (MemoryStream stream = writer.GetStream()) { - Assert.Null(OS2Table.Load(new FontReader(stream))); + using var reader = new FontReader(stream); + Assert.Null(OS2Table.Load(reader)); } } } diff --git a/tests/SixLabors.Fonts.Tests/Tables/General/VerticalHeadTableTests.cs b/tests/SixLabors.Fonts.Tests/Tables/General/VerticalHeadTableTests.cs index b73683c..5ea44e7 100644 --- a/tests/SixLabors.Fonts.Tests/Tables/General/VerticalHeadTableTests.cs +++ b/tests/SixLabors.Fonts.Tests/Tables/General/VerticalHeadTableTests.cs @@ -36,6 +36,7 @@ public class VerticalHeadTableTests writer.WriteTrueTypeFileHeader(); using MemoryStream stream = writer.GetStream(); - Assert.Null(VerticalHeadTable.Load(new FontReader(stream))); + using var reader = new FontReader(stream); + Assert.Null(VerticalHeadTable.Load(reader)); } } From ed4b24edc4f814dba9aa76a286c5fc0102a274a1 Mon Sep 17 00:00:00 2001 From: Andrey Bykiev Date: Fri, 2 Aug 2024 12:00:24 +0300 Subject: [PATCH 2/2] Fix some review issues --- src/SixLabors.Fonts/FontReader.cs | 14 +++++++++++--- src/SixLabors.Fonts/Tables/Cff/CffDataDicEntry.cs | 4 ++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/SixLabors.Fonts/FontReader.cs b/src/SixLabors.Fonts/FontReader.cs index cfeae13..2c27ef4 100644 --- a/src/SixLabors.Fonts/FontReader.cs +++ b/src/SixLabors.Fonts/FontReader.cs @@ -14,7 +14,9 @@ internal sealed class FontReader : IDisposable private readonly Stream stream; private readonly Dictionary loadedTables = new(); private readonly TableLoader loader; - private readonly bool disposable; + + private readonly bool isOwnedStream; + private bool isDisposed; internal FontReader(Stream stream, TableLoader loader) { @@ -85,7 +87,7 @@ internal sealed class FontReader : IDisposable this.CompressedTableData = true; this.Headers = Woff2Utils.ReadWoff2Headers(reader, tableCount); - this.disposable = true; + this.isOwnedStream = true; byte[] compressedBuffer = reader.ReadBytes((int)totalCompressedSize); var decompressedStream = new MemoryStream(); @@ -201,9 +203,15 @@ internal sealed class FontReader : IDisposable public void Dispose() { - if (this.disposable) + if (this.isDisposed) + { + return; + } + + if (this.isOwnedStream) { this.stream.Dispose(); + this.isDisposed = true; } } } diff --git a/src/SixLabors.Fonts/Tables/Cff/CffDataDicEntry.cs b/src/SixLabors.Fonts/Tables/Cff/CffDataDicEntry.cs index 42e6466..a4d7e4f 100644 --- a/src/SixLabors.Fonts/Tables/Cff/CffDataDicEntry.cs +++ b/src/SixLabors.Fonts/Tables/Cff/CffDataDicEntry.cs @@ -26,13 +26,13 @@ internal class CffDataDicEntry { if (i > 0) { - builder.Append(' '); + builder.Append(" "); } builder.Append(this.Operands[i].ToString()); } - builder.Append(' '); + builder.Append(" "); builder.Append(this.Operator?.ToString() ?? string.Empty); return builder.ToString(); }