From b44dece827fd4f5de820883f39202536e5213c4f Mon Sep 17 00:00:00 2001 From: ThomasGoulet73 Date: Wed, 3 May 2023 23:47:36 -0400 Subject: [PATCH 1/2] Improve font performance in FamilyCollection.LookupFamily --- .../MS/internal/FontCache/FamilyCollection.cs | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/FontCache/FamilyCollection.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/FontCache/FamilyCollection.cs index 17511d0e91c..77fbe42af91 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/FontCache/FamilyCollection.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/FontCache/FamilyCollection.cs @@ -382,7 +382,7 @@ ref FontStretch fontStretch // For example, "Arial Bold" // We will strip off the styling info (one word at a time from the end) and try to find the family name. int indexOfSpace = -1; - System.Text.StringBuilder potentialFaceName = new System.Text.StringBuilder(); + string originalFamilyName = familyName; // Start removing off strings from the end hoping they are // style info so as to get down to the family name. @@ -396,12 +396,11 @@ ref FontStretch fontStretch else { // store the stripped off style names to look for the specific face later. - potentialFaceName.Insert(0, familyName.AsSpan(indexOfSpace)); familyName = familyName.Substring(0, indexOfSpace); } fontFamilyDWrite = _fontCollection[familyName]; -} while (fontFamilyDWrite == null); + } while (fontFamilyDWrite == null); if (fontFamilyDWrite == null) @@ -410,10 +409,12 @@ ref FontStretch fontStretch } // If there was styling information. - if (potentialFaceName.Length > 0) + if (familyName.Length != originalFamilyName.Length) { - // The first character in the potentialFaceName will be a space so we need to strip it off. - Text.TextInterface.Font font = GetFontFromFamily(fontFamilyDWrite, potentialFaceName.ToString(1, potentialFaceName.Length - 1)); + // To obtain the face name, we remove the family name and the next char (A space) from the original family name. + int faceNameIndex = familyName.Length + 1; + ReadOnlySpan faceName = originalFamilyName.AsSpan(faceNameIndex, originalFamilyName.Length - faceNameIndex); + Text.TextInterface.Font font = GetFontFromFamily(fontFamilyDWrite, faceName); if (font != null) { @@ -464,10 +465,8 @@ private CompositeFontFamily LookUpUserCompositeFamily(string familyName) /// The font family to look in. /// The face to look for. /// The font face if found and null if nothing was found. - private static Text.TextInterface.Font GetFontFromFamily(Text.TextInterface.FontFamily fontFamily, string faceName) + private static Text.TextInterface.Font GetFontFromFamily(Text.TextInterface.FontFamily fontFamily, ReadOnlySpan faceName) { - faceName = faceName.ToUpper(CultureInfo.InvariantCulture); - // The search that DWrite supports is a linear search. // Look at every font face. foreach (Text.TextInterface.Font font in fontFamily) @@ -475,8 +474,7 @@ private static Text.TextInterface.Font GetFontFromFamily(Text.TextInterface.Font // and at every locale name this font face has. foreach (KeyValuePair name in font.FaceNames) { - string currentFontName = name.Value.ToUpper(CultureInfo.InvariantCulture); - if (currentFontName == faceName) + if (faceName.Equals(name.Value, StringComparison.OrdinalIgnoreCase)) { return font; } @@ -488,7 +486,7 @@ private static Text.TextInterface.Font GetFontFromFamily(Text.TextInterface.Font // thus we will start again removing words (separated by ' ') from its end and looking // for the resulting faceName in that dictionary. So this dictionary is // used to speed the search. - Dictionary faces = new Dictionary(); + Dictionary faces = new Dictionary(StringComparer.OrdinalIgnoreCase); //We could have merged this loop with the one above. However this will degrade the performance //of the scenario where the user entered a correct face name (which is the common scenario). @@ -498,8 +496,7 @@ private static Text.TextInterface.Font GetFontFromFamily(Text.TextInterface.Font { foreach (KeyValuePair name in font.FaceNames) { - string currentFontName = name.Value.ToUpper(CultureInfo.InvariantCulture); - faces.TryAdd(currentFontName, font); + faces.TryAdd(name.Value, font); } } @@ -509,8 +506,8 @@ private static Text.TextInterface.Font GetFontFromFamily(Text.TextInterface.Font while (indexOfSpace > 0) { - faceName = faceName.Substring(0, indexOfSpace); - if (faces.TryGetValue(faceName, out matchingFont)) + faceName = faceName.Slice(0, indexOfSpace); + if (faces.TryGetValue(faceName.ToString(), out matchingFont)) { return matchingFont; } From 836c83b2d1166e3fd73f630526c67e99c624ac54 Mon Sep 17 00:00:00 2001 From: ThomasGoulet73 <51839772+ThomasGoulet73@users.noreply.github.com> Date: Mon, 8 May 2023 23:30:06 -0400 Subject: [PATCH 2/2] Update src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/FontCache/FamilyCollection.cs Co-authored-by: halgab <24685886+halgab@users.noreply.github.com> --- .../PresentationCore/MS/internal/FontCache/FamilyCollection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/FontCache/FamilyCollection.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/FontCache/FamilyCollection.cs index 77fbe42af91..18f7172b018 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/FontCache/FamilyCollection.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/FontCache/FamilyCollection.cs @@ -413,7 +413,7 @@ ref FontStretch fontStretch { // To obtain the face name, we remove the family name and the next char (A space) from the original family name. int faceNameIndex = familyName.Length + 1; - ReadOnlySpan faceName = originalFamilyName.AsSpan(faceNameIndex, originalFamilyName.Length - faceNameIndex); + ReadOnlySpan faceName = originalFamilyName.AsSpan(faceNameIndex); Text.TextInterface.Font font = GetFontFromFamily(fontFamilyDWrite, faceName); if (font != null)