From 30f2923500bc252841f5e69136dbed391e5948eb Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 10 Sep 2025 20:02:37 +1000 Subject: [PATCH] Update to latest refs and target frameworks --- .editorconfig | 20 ++-- .gitattributes | 10 ++ .github/workflows/build-and-test.yml | 91 ++++++++++++++----- .../DrawWithImageSharp.csproj | 4 +- samples/ListFonts/ListFonts.csproj | 4 +- shared-infrastructure | 2 +- src/SixLabors.Fonts/BigEndianBinaryReader.cs | 1 + src/SixLabors.Fonts/FontCollection.cs | 19 ++-- src/SixLabors.Fonts/IO/ZlibInflateStream.cs | 7 +- src/SixLabors.Fonts/SixLabors.Fonts.csproj | 16 +--- src/SixLabors.Fonts/StreamFontMetrics.Cff.cs | 2 +- .../StreamFontMetrics.TrueType.cs | 2 +- .../Shapers/IndicShaper.cs | 4 +- .../Shapers/UniversalShaper.cs | 2 +- .../Tables/Cff/CffDataDicEntry.cs | 8 +- src/SixLabors.Fonts/Tables/Cff/CffOperand.cs | 8 +- src/SixLabors.Fonts/TextLayout.cs | 32 +++---- .../Generator.IndicShapingEngine.cs | 5 +- .../Generator.UniversalShapingEngine.cs | 11 ++- src/UnicodeTrieGenerator/Generator.cs | 7 +- .../UnicodeTrieGenerator.csproj | 5 +- .../SixLabors.Fonts.Benchmarks.csproj | 4 +- .../SixLabors.Fonts.Tests.csproj | 4 +- 23 files changed, 163 insertions(+), 105 deletions(-) diff --git a/.editorconfig b/.editorconfig index 2e3045fb1..f579ff5d3 100644 --- a/.editorconfig +++ b/.editorconfig @@ -104,8 +104,8 @@ dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:war dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning dotnet_style_parentheses_in_other_operators = always_for_clarity:suggestion # Expression-level preferences -dotnet_style_object_initializer = true:warning -dotnet_style_collection_initializer = true:warning +dotnet_style_object_initializer = true:error +dotnet_style_collection_initializer = true:error dotnet_style_explicit_tuple_names = true:warning dotnet_style_prefer_inferred_tuple_names = true:warning dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning @@ -135,9 +135,9 @@ csharp_style_prefer_null_check_over_type_check = true:warning # https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/language-rules#c-style-rules [*.{cs,csx,cake}] # 'var' preferences -csharp_style_var_for_built_in_types = false:warning -csharp_style_var_when_type_is_apparent = false:warning -csharp_style_var_elsewhere = false:warning +csharp_style_var_for_built_in_types = false:error +csharp_style_var_when_type_is_apparent = false:error +csharp_style_var_elsewhere = false:error # Expression-bodied members csharp_style_expression_bodied_methods = true:warning csharp_style_expression_bodied_constructors = true:warning @@ -160,7 +160,10 @@ csharp_style_pattern_local_over_anonymous_function = true:warning csharp_style_deconstructed_variable_declaration = true:warning csharp_style_prefer_index_operator = true:warning csharp_style_prefer_range_operator = true:warning -csharp_style_implicit_object_creation_when_type_is_apparent = true:warning +csharp_style_implicit_object_creation_when_type_is_apparent = true:error +# ReSharper inspection severities +resharper_arrange_object_creation_when_type_evident_highlighting = error +resharper_arrange_object_creation_when_type_not_evident_highlighting = error # "Null" checking preferences csharp_style_throw_expression = true:warning csharp_style_conditional_delegate_call = true:warning @@ -172,6 +175,11 @@ dotnet_diagnostic.IDE0063.severity = suggestion csharp_using_directive_placement = outside_namespace:warning # Modifier preferences csharp_prefer_static_local_function = true:warning +# Primary constructor preferences +csharp_style_prefer_primary_constructors = false:none +# Collection preferences +dotnet_style_prefer_collection_expression = true:error +resharper_use_collection_expression_highlighting =true:error ########################################## # Unnecessary Code Rules diff --git a/.gitattributes b/.gitattributes index 3647a7063..f7bd4d061 100644 --- a/.gitattributes +++ b/.gitattributes @@ -133,3 +133,13 @@ *.pnm filter=lfs diff=lfs merge=lfs -text *.wbmp filter=lfs diff=lfs merge=lfs -text *.exr filter=lfs diff=lfs merge=lfs -text +*.ico filter=lfs diff=lfs merge=lfs -text +*.cur filter=lfs diff=lfs merge=lfs -text +*.ani filter=lfs diff=lfs merge=lfs -text +*.heic filter=lfs diff=lfs merge=lfs -text +*.hif filter=lfs diff=lfs merge=lfs -text +*.avif filter=lfs diff=lfs merge=lfs -text +############################################################################### +# Handle ICC files by git lfs +############################################################################### +*.icc filter=lfs diff=lfs merge=lfs -text diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 27f189f00..02977b444 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -12,49 +12,94 @@ on: - release/* types: [ labeled, opened, synchronize, reopened ] jobs: + # Prime a single LFS cache and expose the exact key for the matrix + WarmLFS: + runs-on: ubuntu-latest + outputs: + lfs_key: ${{ steps.expose-key.outputs.lfs_key }} + steps: + - name: Git Config + shell: bash + run: | + git config --global core.autocrlf false + git config --global core.longpaths true + + - name: Git Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + submodules: recursive + + # Deterministic list of LFS object IDs, then compute a portable key: + # - `git lfs ls-files -l` lists all tracked LFS objects with their SHA-256 + # - `awk '{print $1}'` extracts just the SHA field + # - `sort` sorts in byte order (hex hashes sort the same everywhere) + # This ensures the file content is identical regardless of OS or locale + - name: Git Create LFS id list + shell: bash + run: git lfs ls-files -l | awk '{print $1}' | sort > .lfs-assets-id + + - name: Git Expose LFS cache key + id: expose-key + shell: bash + env: + LFS_KEY: lfs-${{ hashFiles('.lfs-assets-id') }}-v1 + run: echo "lfs_key=$LFS_KEY" >> "$GITHUB_OUTPUT" + + - name: Git Setup LFS Cache + uses: actions/cache@v4 + with: + path: .git/lfs + key: ${{ steps.expose-key.outputs.lfs_key }} + + - name: Git Pull LFS + shell: bash + run: git lfs pull + Build: + needs: WarmLFS strategy: matrix: isARM: - ${{ contains(github.event.pull_request.labels.*.name, 'arch:arm32') || contains(github.event.pull_request.labels.*.name, 'arch:arm64') }} options: - os: ubuntu-latest - framework: net7.0 - sdk: 7.0.x + framework: net9.0 + sdk: 9.0.x sdk-preview: true runtime: -x64 codecov: false - os: macos-latest - framework: net7.0 - sdk: 7.0.x + framework: net9.0 + sdk: 9.0.x sdk-preview: true runtime: -x64 codecov: false - os: windows-latest - framework: net7.0 - sdk: 7.0.x + framework: net9.0 + sdk: 9.0.x sdk-preview: true runtime: -x64 codecov: false - os: buildjet-4vcpu-ubuntu-2204-arm - framework: net7.0 - sdk: 7.0.x + framework: net9.0 + sdk: 9.0.x sdk-preview: true runtime: -x64 codecov: false - os: ubuntu-latest - framework: net6.0 - sdk: 6.0.x + framework: net8.0 + sdk: 8.0.x runtime: -x64 codecov: false - os: macos-latest - framework: net6.0 - sdk: 6.0.x + framework: net8.0 + sdk: 8.0.x runtime: -x64 codecov: false - os: windows-latest - framework: net6.0 - sdk: 6.0.x + framework: net8.0 + sdk: 8.0.x runtime: -x64 codecov: true exclude: @@ -66,8 +111,10 @@ jobs: steps: - name: Install libgdi+, which is required for tests running on ubuntu - if: ${{ matrix.options.os == 'buildjet-4vcpu-ubuntu-2204-arm' }} - run: sudo apt-get -y install libgdiplus libgif-dev libglib2.0-dev libcairo2-dev libtiff-dev libexif-dev + if: ${{ contains(matrix.options.os, 'ubuntu') }} + run: | + sudo apt-get update + sudo apt-get -y install libgdiplus libgif-dev libglib2.0-dev libcairo2-dev libtiff-dev libexif-dev - name: Git Config shell: bash @@ -81,16 +128,12 @@ jobs: fetch-depth: 0 submodules: recursive - # See https://github.com/actions/checkout/issues/165#issuecomment-657673315 - - name: Git Create LFS FileList - run: git lfs ls-files -l | cut -d' ' -f1 | sort > .lfs-assets-id - + # Use the warmed key from WarmLFS. Do not recompute or recreate .lfs-assets-id here. - name: Git Setup LFS Cache uses: actions/cache@v4 - id: lfs-cache with: path: .git/lfs - key: ${{ runner.os }}-lfs-${{ hashFiles('.lfs-assets-id') }}-v1 + key: ${{ needs.WarmLFS.outputs.lfs_key }} - name: Git Pull LFS run: git lfs pull @@ -111,14 +154,14 @@ jobs: uses: actions/setup-dotnet@v4 with: dotnet-version: | - 6.0.x + 8.0.x - name: DotNet Setup Preview if: ${{ matrix.options.sdk-preview == true }} uses: actions/setup-dotnet@v4 with: dotnet-version: | - 7.0.x + 9.0.x - name: DotNet Build if: ${{ matrix.options.sdk-preview != true }} diff --git a/samples/DrawWithImageSharp/DrawWithImageSharp.csproj b/samples/DrawWithImageSharp/DrawWithImageSharp.csproj index 58f71516a..89666fa2c 100644 --- a/samples/DrawWithImageSharp/DrawWithImageSharp.csproj +++ b/samples/DrawWithImageSharp/DrawWithImageSharp.csproj @@ -13,12 +13,12 @@ - net7.0;net6.0 + net8.0;net9.0 - net6.0 + net8.0 diff --git a/samples/ListFonts/ListFonts.csproj b/samples/ListFonts/ListFonts.csproj index 425e759c6..24fb7b7f0 100644 --- a/samples/ListFonts/ListFonts.csproj +++ b/samples/ListFonts/ListFonts.csproj @@ -7,12 +7,12 @@ - net7.0;net6.0 + net8.0;net9.0 - net6.0 + net8.0 diff --git a/shared-infrastructure b/shared-infrastructure index 353b9afe3..57699ffb7 160000 --- a/shared-infrastructure +++ b/shared-infrastructure @@ -1 +1 @@ -Subproject commit 353b9afe32a8000410312d17263407cd7bb82d19 +Subproject commit 57699ffb797bc2389c5d6cbb3b1800f2eb5fb947 diff --git a/src/SixLabors.Fonts/BigEndianBinaryReader.cs b/src/SixLabors.Fonts/BigEndianBinaryReader.cs index e164093bb..5f9c6aab7 100644 --- a/src/SixLabors.Fonts/BigEndianBinaryReader.cs +++ b/src/SixLabors.Fonts/BigEndianBinaryReader.cs @@ -377,6 +377,7 @@ public int ReadOffset(int size) /// /// Buffer to read into. /// Number of bytes to read. + /// The end of the stream was reached before reading could complete. private void ReadInternal(byte[] data, int size) { int index = 0; diff --git a/src/SixLabors.Fonts/FontCollection.cs b/src/SixLabors.Fonts/FontCollection.cs index 437d430da..17f6f29c6 100644 --- a/src/SixLabors.Fonts/FontCollection.cs +++ b/src/SixLabors.Fonts/FontCollection.cs @@ -12,8 +12,8 @@ namespace SixLabors.Fonts; /// public sealed class FontCollection : IFontCollection, IFontMetricsCollection { - private readonly HashSet searchDirectories = new(); - private readonly HashSet metricsCollection = new(); + private readonly HashSet searchDirectories = []; + private readonly HashSet metricsCollection = []; /// /// Initializes a new instance of the class. @@ -208,7 +208,7 @@ private FontFamily AddImpl(Stream stream, CultureInfo culture, out FontDescripti return ((IFontMetricsCollection)this).AddMetrics(metrics, culture); } - private IEnumerable AddCollectionImpl( + private HashSet AddCollectionImpl( string path, CultureInfo culture, out IEnumerable descriptions) @@ -216,7 +216,7 @@ private IEnumerable AddCollectionImpl( FileFontMetrics[] fonts = FileFontMetrics.LoadFontCollection(path); FontDescription[] description = new FontDescription[fonts.Length]; - HashSet families = new(); + HashSet families = []; for (int i = 0; i < fonts.Length; i++) { description[i] = fonts[i].Description; @@ -228,7 +228,7 @@ private IEnumerable AddCollectionImpl( return families; } - private IEnumerable AddCollectionImpl( + private HashSet AddCollectionImpl( Stream stream, CultureInfo culture, out IEnumerable descriptions) @@ -237,7 +237,7 @@ private IEnumerable AddCollectionImpl( using BigEndianBinaryReader reader = new(stream, true); TtcHeader ttcHeader = TtcHeader.Read(reader); List result = new((int)ttcHeader.NumFonts); - HashSet installedFamilies = new(); + HashSet installedFamilies = []; for (int i = 0; i < ttcHeader.NumFonts; ++i) { stream.Position = startPos + ttcHeader.OffsetTable[i]; @@ -251,12 +251,11 @@ private IEnumerable AddCollectionImpl( return installedFamilies; } - private IEnumerable FamiliesByCultureImpl(CultureInfo culture) - => this.metricsCollection + private FontFamily[] FamiliesByCultureImpl(CultureInfo culture) + => [.. this.metricsCollection .Select(x => x.Description.FontFamily(culture)) .Distinct() - .Select(x => new FontFamily(x, this, culture)) - .ToArray(); + .Select(x => new FontFamily(x, this, culture))]; private bool TryGetImpl(string name, CultureInfo culture, out FontFamily family) { diff --git a/src/SixLabors.Fonts/IO/ZlibInflateStream.cs b/src/SixLabors.Fonts/IO/ZlibInflateStream.cs index 0157cea05..f28d68132 100644 --- a/src/SixLabors.Fonts/IO/ZlibInflateStream.cs +++ b/src/SixLabors.Fonts/IO/ZlibInflateStream.cs @@ -122,10 +122,7 @@ public override void Flush() /// public override int Read(byte[] buffer, int offset, int count) { - if (this.deflateStream is null) - { - throw new ObjectDisposedException("inner stream"); - } + ObjectDisposedException.ThrowIf(this.deflateStream is null, this.GetType()); // We don't check CRC on reading int read = this.deflateStream.Read(buffer, offset, count); @@ -135,7 +132,7 @@ public override int Read(byte[] buffer, int offset, int count) this.crcRead = new byte[4]; for (int i = 0; i < 4; i++) { - // we dont really check/use this + // we don't really check/use this this.crcRead[i] = (byte)this.rawStream.ReadByte(); } } diff --git a/src/SixLabors.Fonts/SixLabors.Fonts.csproj b/src/SixLabors.Fonts/SixLabors.Fonts.csproj index b90f8cfda..e3d65840c 100644 --- a/src/SixLabors.Fonts/SixLabors.Fonts.csproj +++ b/src/SixLabors.Fonts/SixLabors.Fonts.csproj @@ -26,19 +26,19 @@ - 2.0 + 3.0 - net7.0;net6.0 + net8.0;net9.0 true - net6.0 + net8.0 true @@ -55,15 +55,5 @@ - - - - - - - - - - diff --git a/src/SixLabors.Fonts/StreamFontMetrics.Cff.cs b/src/SixLabors.Fonts/StreamFontMetrics.Cff.cs index 42dfc9b0d..29ed9c062 100644 --- a/src/SixLabors.Fonts/StreamFontMetrics.Cff.cs +++ b/src/SixLabors.Fonts/StreamFontMetrics.Cff.cs @@ -65,7 +65,7 @@ private static StreamFontMetrics LoadCompactFont(FontReader reader) return new StreamFontMetrics(tables); } - private GlyphMetrics CreateCffGlyphMetrics( + private CffGlyphMetrics CreateCffGlyphMetrics( in CodePoint codePoint, ushort glyphId, GlyphType glyphType, diff --git a/src/SixLabors.Fonts/StreamFontMetrics.TrueType.cs b/src/SixLabors.Fonts/StreamFontMetrics.TrueType.cs index 416e5af6b..e33738ef6 100644 --- a/src/SixLabors.Fonts/StreamFontMetrics.TrueType.cs +++ b/src/SixLabors.Fonts/StreamFontMetrics.TrueType.cs @@ -114,7 +114,7 @@ private static StreamFontMetrics LoadTrueTypeFont(FontReader reader) return new StreamFontMetrics(tables); } - private GlyphMetrics CreateTrueTypeGlyphMetrics( + private TrueTypeGlyphMetrics CreateTrueTypeGlyphMetrics( in CodePoint codePoint, ushort glyphId, GlyphType glyphType, diff --git a/src/SixLabors.Fonts/Tables/AdvancedTypographic/Shapers/IndicShaper.cs b/src/SixLabors.Fonts/Tables/AdvancedTypographic/Shapers/IndicShaper.cs index 6fe5900e9..b28e802c7 100644 --- a/src/SixLabors.Fonts/Tables/AdvancedTypographic/Shapers/IndicShaper.cs +++ b/src/SixLabors.Fonts/Tables/AdvancedTypographic/Shapers/IndicShaper.cs @@ -690,7 +690,7 @@ private void InitialReorder(IGlyphShapingCollection collection, int index, int c } } - int prefLen = 2; + const int prefLen = 2; if (basePosition + prefLen < end && gSubTable.TryGetFeatureLookups(in PrefTag, this.ScriptClass, out _)) { @@ -836,7 +836,7 @@ private static bool IsJoiner(GlyphShapingData data) private static bool IsHalantOrCoeng(GlyphShapingData data) => data.IndicShapingEngineInfo != null && (data.IndicShapingEngineInfo.Category & HalantOrCoengFlags) != 0; - private static int NextSyllable(IGlyphShapingCollection collection, int index, int count) + private static int NextSyllable(GlyphSubstitutionCollection collection, int index, int count) { if (index >= count) { diff --git a/src/SixLabors.Fonts/Tables/AdvancedTypographic/Shapers/UniversalShaper.cs b/src/SixLabors.Fonts/Tables/AdvancedTypographic/Shapers/UniversalShaper.cs index 05ee92f86..b5edbb1c9 100644 --- a/src/SixLabors.Fonts/Tables/AdvancedTypographic/Shapers/UniversalShaper.cs +++ b/src/SixLabors.Fonts/Tables/AdvancedTypographic/Shapers/UniversalShaper.cs @@ -317,7 +317,7 @@ private static void Reorder(IGlyphShapingCollection collection, int index, int c } } - private static int NextSyllable(IGlyphShapingCollection collection, int index, int count) + private static int NextSyllable(GlyphSubstitutionCollection collection, int index, int count) { if (index >= count) { diff --git a/src/SixLabors.Fonts/Tables/Cff/CffDataDicEntry.cs b/src/SixLabors.Fonts/Tables/Cff/CffDataDicEntry.cs index a4d7e4fa5..bad5b79b1 100644 --- a/src/SixLabors.Fonts/Tables/Cff/CffDataDicEntry.cs +++ b/src/SixLabors.Fonts/Tables/Cff/CffDataDicEntry.cs @@ -1,7 +1,9 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +#if DEBUG using System.Text; +#endif namespace SixLabors.Fonts.Tables.Cff; @@ -26,14 +28,14 @@ public override string ToString() { if (i > 0) { - builder.Append(" "); + builder.Append(' '); } builder.Append(this.Operands[i].ToString()); } - builder.Append(" "); - builder.Append(this.Operator?.ToString() ?? string.Empty); + builder.Append(' ') + .Append(this.Operator?.ToString() ?? string.Empty); return builder.ToString(); } #endif diff --git a/src/SixLabors.Fonts/Tables/Cff/CffOperand.cs b/src/SixLabors.Fonts/Tables/Cff/CffOperand.cs index 759a86652..acfa8a6d6 100644 --- a/src/SixLabors.Fonts/Tables/Cff/CffOperand.cs +++ b/src/SixLabors.Fonts/Tables/Cff/CffOperand.cs @@ -1,6 +1,10 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +#if DEBUG +using System.Globalization; +#endif + namespace SixLabors.Fonts.Tables.Cff; internal readonly struct CffOperand @@ -19,8 +23,8 @@ public CffOperand(double number, OperandKind kind) public override string ToString() => this.Kind switch { - OperandKind.IntNumber => ((int)this.RealNumValue).ToString(), - _ => this.RealNumValue.ToString(), + OperandKind.IntNumber => ((int)this.RealNumValue).ToString(CultureInfo.InvariantCulture), + _ => this.RealNumValue.ToString(CultureInfo.InvariantCulture), }; #endif diff --git a/src/SixLabors.Fonts/TextLayout.cs b/src/SixLabors.Fonts/TextLayout.cs index 526c5d691..9dc6d9c24 100644 --- a/src/SixLabors.Fonts/TextLayout.cs +++ b/src/SixLabors.Fonts/TextLayout.cs @@ -42,7 +42,7 @@ public static IReadOnlyList BuildTextRuns(ReadOnlySpan text, Text int start = 0; int end = text.GetGraphemeCount(); - List textRuns = new(); + List textRuns = []; foreach (TextRun textRun in options.TextRuns!.OrderBy(x => x.Start)) { // Fill gaps within runs. @@ -89,8 +89,8 @@ private static TextBox ProcessText(ReadOnlySpan text, TextOptions options) { // Gather the font and fallbacks. Font[] fallbackFonts = (options.FallbackFontFamilies?.Count > 0) - ? options.FallbackFontFamilies.Select(x => new Font(x, options.Font.Size, options.Font.RequestedStyle)).ToArray() - : Array.Empty(); + ? [.. options.FallbackFontFamilies.Select(x => new Font(x, options.Font.Size, options.Font.RequestedStyle))] + : []; LayoutMode layoutMode = options.LayoutMode; GlyphSubstitutionCollection substitutions = new(options); @@ -113,8 +113,8 @@ private static TextBox ProcessText(ReadOnlySpan text, TextOptions options) bidi.Process(bidiData); // Get the list of directional runs - BidiRun[] bidiRuns = BidiRun.CoalesceLevels(bidi.ResolvedLevels).ToArray(); - Dictionary bidiMap = new(); + BidiRun[] bidiRuns = [.. BidiRun.CoalesceLevels(bidi.ResolvedLevels)]; + Dictionary bidiMap = []; // Incrementally build out collection of glyphs. IReadOnlyList textRuns = BuildTextRuns(text, options); @@ -188,10 +188,10 @@ private static TextBox ProcessText(ReadOnlySpan text, TextOptions options) return BreakLines(text, options, bidiRuns, bidiMap, positionings, layoutMode); } - private static IReadOnlyList LayoutText(TextBox textBox, TextOptions options) + private static List LayoutText(TextBox textBox, TextOptions options) { LayoutMode layoutMode = options.LayoutMode; - List glyphs = new(); + List glyphs = []; Vector2 boxLocation = options.Origin / options.Dpi; Vector2 penLocation = boxLocation; @@ -303,7 +303,7 @@ private static IReadOnlyList LayoutText(TextBox textBox, TextOption return glyphs; } - private static IEnumerable LayoutLineHorizontal( + private static List LayoutLineHorizontal( TextBox textBox, TextLine textLine, TextDirection direction, @@ -386,7 +386,7 @@ private static IEnumerable LayoutLineHorizontal( penLocation.X += offsetX; - List glyphs = new(); + List glyphs = []; for (int i = 0; i < textLine.Count; i++) { TextLine.GlyphLayoutData data = textLine[i]; @@ -444,7 +444,7 @@ private static IEnumerable LayoutLineHorizontal( return glyphs; } - private static IEnumerable LayoutLineVertical( + private static List LayoutLineVertical( TextBox textBox, TextLine textLine, TextDirection direction, @@ -530,7 +530,7 @@ private static IEnumerable LayoutLineVertical( penLocation.X += offsetX; - List glyphs = new(); + List glyphs = []; for (int i = 0; i < textLine.Count; i++) { TextLine.GlyphLayoutData data = textLine[i]; @@ -602,7 +602,7 @@ private static IEnumerable LayoutLineVertical( return glyphs; } - private static IEnumerable LayoutLineVerticalMixed( + private static List LayoutLineVerticalMixed( TextBox textBox, TextLine textLine, TextDirection direction, @@ -688,7 +688,7 @@ private static IEnumerable LayoutLineVerticalMixed( penLocation.X += offsetX; - List glyphs = new(); + List glyphs = []; for (int i = 0; i < textLine.Count; i++) { TextLine.GlyphLayoutData data = textLine[i]; @@ -940,7 +940,7 @@ private static TextBox BreakLines( int graphemeIndex; int codePointIndex = 0; - List textLines = new(); + List textLines = []; TextLine textLine = new(); int stringIndex = 0; @@ -1176,7 +1176,7 @@ VerticalOrientationType.Rotate or // Now we need to loop through our line and split it at any line breaks. // First calculate the position of potential line breaks. LineBreakEnumerator lineBreakEnumerator = new(text); - List lineBreaks = new(); + List lineBreaks = []; while (lineBreakEnumerator.MoveNext()) { // URLs are now so common in regular plain text that they need to be taken into account when @@ -1340,7 +1340,7 @@ public float ScaledMaxAdvance() internal sealed class TextLine { private readonly List data; - private readonly Dictionary advances = new(); + private readonly Dictionary advances = []; public TextLine() => this.data = new(16); diff --git a/src/UnicodeTrieGenerator/Generator.IndicShapingEngine.cs b/src/UnicodeTrieGenerator/Generator.IndicShapingEngine.cs index abe1309d3..695cc7193 100644 --- a/src/UnicodeTrieGenerator/Generator.IndicShapingEngine.cs +++ b/src/UnicodeTrieGenerator/Generator.IndicShapingEngine.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +#pragma warning disable SYSLIB1045 // Convert to 'GeneratedRegexAttribute'. using System.Text.RegularExpressions; using SixLabors.Fonts.Unicode; using SixLabors.Fonts.Unicode.Resources; @@ -202,7 +203,7 @@ private static void GenerateIndicShapingDataTrie(Codepoint[] codePoints) { SetBlocks(codePoints); - var symbols = ((Categories[])Enum.GetValues(typeof(Categories))).ToDictionary(c => c.ToString(), c => (int)Math.Log((int)c, 2)); + Dictionary symbols = Enum.GetValues().ToDictionary(c => c.ToString(), c => (int)Math.Log((int)c, 2)); UnicodeTrieBuilder builder = new(); for (int i = 0; i < codePoints.Length; i++) @@ -224,7 +225,7 @@ private static void GenerateIndicShapingDataTrie(Codepoint[] codePoints) private static void SetBlocks(Codepoint[] codePoints) { - var regex = new Regex(@"^([0-9A-F]+)(?:\.\.([0-9A-F]+))?\s*;\s*([\w\s-]+)"); + Regex regex = new(@"^([0-9A-F]+)(?:\.\.([0-9A-F]+))?\s*;\s*([\w\s-]+)"); using StreamReader sr = GetStreamReader("Blocks.txt"); string? line; diff --git a/src/UnicodeTrieGenerator/Generator.UniversalShapingEngine.cs b/src/UnicodeTrieGenerator/Generator.UniversalShapingEngine.cs index 18f19e389..b5c389c95 100644 --- a/src/UnicodeTrieGenerator/Generator.UniversalShapingEngine.cs +++ b/src/UnicodeTrieGenerator/Generator.UniversalShapingEngine.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +#pragma warning disable SYSLIB1045 // Convert to 'GeneratedRegexAttribute'. using System.Globalization; using System.Text.RegularExpressions; using SixLabors.Fonts.Unicode; @@ -483,7 +484,7 @@ or 0x2068 return type; } - List codePoints = new(); + List codePoints = []; using StreamReader sr = GetStreamReader("UnicodeData.txt"); string? line; while ((line = sr.ReadLine()) != null) @@ -518,9 +519,9 @@ or 0x2068 // OverrideIndicSyllabicCategory(codePoints); // OverrideIndicPositionalCategory(codePoints); UnicodeTrieBuilder builder = new(); - Dictionary symbols = new(); + Dictionary symbols = []; int numSymbols = 0; - Dictionary> decompositions = new(); + Dictionary> decompositions = []; for (int i = 0; i < codePoints.Count; i++) { Codepoint codePoint = codePoints[i]; @@ -631,12 +632,12 @@ private static void OverrideIndicPositionalCategory(List codePoints) private static List Decompose(int code, List codepoints) { - List decomposition = new(); + List decomposition = []; Codepoint codePoint = codepoints.First(x => x.Code == code); foreach (int c in codePoint.Decomposition) { List codes = Decompose(c, codepoints); - codes = codes.Count > 0 ? codes : new List { c }; + codes = codes.Count > 0 ? codes : [c]; decomposition.AddRange(codes); } diff --git a/src/UnicodeTrieGenerator/Generator.cs b/src/UnicodeTrieGenerator/Generator.cs index fb7dfcba0..3cdab23e4 100644 --- a/src/UnicodeTrieGenerator/Generator.cs +++ b/src/UnicodeTrieGenerator/Generator.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +#pragma warning disable SYSLIB1045 // Convert to 'GeneratedRegexAttribute'. using System.Globalization; using System.Text.RegularExpressions; using SixLabors.Fonts.Tests.Unicode; @@ -444,7 +445,7 @@ private static readonly Dictionary VerticalOrie private const string OutputResourcesRelativePath = @"src\SixLabors.Fonts\Unicode\Resources"; private static readonly Lazy SolutionDirectoryFullPathLazy = new(GetSolutionDirectoryFullPathImpl); - private static readonly Dictionary Bidi = new(); + private static readonly Dictionary Bidi = []; private static string SolutionDirectoryFullPath => SolutionDirectoryFullPathLazy.Value; @@ -466,7 +467,7 @@ public static void GenerateUnicodeTries() GenerateVerticalOrientationTrie(); List codePoints = GenerateUniversalShapingDataTrie(ugc, uisc, uipc, uajt); - GenerateIndicShapingDataTrie(codePoints.ToArray()); + GenerateIndicShapingDataTrie([.. codePoints]); } private static void ProcessUnicodeData() @@ -945,7 +946,7 @@ private static FileStream GetStreamWriter(string path) private static string GetSolutionDirectoryFullPathImpl() { - string assemblyLocation = typeof(Generator).Assembly.Location; + string assemblyLocation = AppContext.BaseDirectory; FileInfo assemblyFile = new(assemblyLocation); diff --git a/src/UnicodeTrieGenerator/UnicodeTrieGenerator.csproj b/src/UnicodeTrieGenerator/UnicodeTrieGenerator.csproj index 5634e043f..d8a5ed612 100644 --- a/src/UnicodeTrieGenerator/UnicodeTrieGenerator.csproj +++ b/src/UnicodeTrieGenerator/UnicodeTrieGenerator.csproj @@ -4,17 +4,18 @@ Exe false enable + false - net7.0;net6.0 + net8.0;net9.0 - net6.0 + net8.0 diff --git a/tests/SixLabors.Fonts.Benchmarks/SixLabors.Fonts.Benchmarks/SixLabors.Fonts.Benchmarks.csproj b/tests/SixLabors.Fonts.Benchmarks/SixLabors.Fonts.Benchmarks/SixLabors.Fonts.Benchmarks.csproj index e33b5b2a2..5300318fb 100644 --- a/tests/SixLabors.Fonts.Benchmarks/SixLabors.Fonts.Benchmarks/SixLabors.Fonts.Benchmarks.csproj +++ b/tests/SixLabors.Fonts.Benchmarks/SixLabors.Fonts.Benchmarks/SixLabors.Fonts.Benchmarks.csproj @@ -19,12 +19,12 @@ - net7.0;net6.0 + net8.0;net9.0 - net6.0 + net8.0 diff --git a/tests/SixLabors.Fonts.Tests/SixLabors.Fonts.Tests.csproj b/tests/SixLabors.Fonts.Tests/SixLabors.Fonts.Tests.csproj index 686eaa70e..c88bf9e20 100644 --- a/tests/SixLabors.Fonts.Tests/SixLabors.Fonts.Tests.csproj +++ b/tests/SixLabors.Fonts.Tests/SixLabors.Fonts.Tests.csproj @@ -14,12 +14,12 @@ - net7.0;net6.0 + net8.0;net9.0 - net6.0 + net8.0