44using System . Collections . Generic ;
55using System . Diagnostics . CodeAnalysis ;
66using System . Globalization ;
7- using System . Text ;
87using Avalonia . Platform ;
9- using Avalonia . Utilities ;
108
119namespace Avalonia . Media . Fonts
1210{
@@ -170,12 +168,38 @@ IEnumerator IEnumerable.GetEnumerator()
170168 {
171169 return GetEnumerator ( ) ;
172170 }
171+
172+ /// <summary>
173+ /// Attempts to retrieve the glyph typeface that most closely matches the specified font family name, style,
174+ /// weight, and stretch.
175+ /// </summary>
176+ /// <remarks>This method searches for a glyph typeface in the font collection cache that matches
177+ /// the specified parameters. If an exact match is not found, fallback mechanisms are applied to find the
178+ /// closest available match based on the specified style, weight, and stretch. If no suitable match is found,
179+ /// the method returns <see langword="false"/> and <paramref name="glyphTypeface"/> is set to <see
180+ /// langword="null"/>.</remarks>
181+ /// <param name="familyName">The name of the font family to search for. This parameter cannot be <see langword="null"/> or empty.</param>
182+ /// <param name="style">The desired font style.</param>
183+ /// <param name="weight">The desired font weight.</param>
184+ /// <param name="stretch">The desired font stretch.</param>
185+ /// <param name="glyphTypeface">When this method returns, contains the <see cref="IGlyphTypeface"/> that most closely matches the specified
186+ /// parameters, if a match is found; otherwise, <see langword="null"/>. This parameter is passed uninitialized.</param>
187+ /// <returns><see langword="true"/> if a matching glyph typeface is found; otherwise, <see langword="false"/>.</returns>
188+ public bool TryGetNearestMatch ( string familyName , FontStyle style , FontWeight weight , FontStretch stretch , [ NotNullWhen ( true ) ] out IGlyphTypeface ? glyphTypeface )
189+ {
190+ if ( ! _glyphTypefaceCache . TryGetValue ( familyName , out var glyphTypefaces ) )
191+ {
192+ glyphTypeface = null ;
173193
174- internal static bool TryGetNearestMatch (
175- ConcurrentDictionary < FontCollectionKey ,
176- IGlyphTypeface ? > glyphTypefaces ,
177- FontCollectionKey key ,
178- [ NotNullWhen ( true ) ] out IGlyphTypeface ? glyphTypeface )
194+ return false ;
195+ }
196+
197+ var key = new FontCollectionKey { Style = style , Weight = weight , Stretch = stretch } ;
198+
199+ return TryGetNearestMatch ( glyphTypefaces , key , out glyphTypeface ) ;
200+ }
201+
202+ protected bool TryGetNearestMatch ( IDictionary < FontCollectionKey , IGlyphTypeface ? > glyphTypefaces , FontCollectionKey key , [ NotNullWhen ( true ) ] out IGlyphTypeface ? glyphTypeface )
179203 {
180204 if ( glyphTypefaces . TryGetValue ( key , out glyphTypeface ) && glyphTypeface != null )
181205 {
@@ -218,7 +242,7 @@ internal static bool TryGetNearestMatch(
218242 //Take the first glyph typeface we can find.
219243 foreach ( var typeface in glyphTypefaces . Values )
220244 {
221- if ( typeface != null )
245+ if ( typeface != null )
222246 {
223247 glyphTypeface = typeface ;
224248
@@ -230,8 +254,7 @@ internal static bool TryGetNearestMatch(
230254 }
231255
232256 internal static bool TryFindStretchFallback (
233- ConcurrentDictionary < FontCollectionKey ,
234- IGlyphTypeface ? > glyphTypefaces ,
257+ IDictionary < FontCollectionKey , IGlyphTypeface ? > glyphTypefaces ,
235258 FontCollectionKey key ,
236259 [ NotNullWhen ( true ) ] out IGlyphTypeface ? glyphTypeface )
237260 {
@@ -264,8 +287,7 @@ internal static bool TryFindStretchFallback(
264287 }
265288
266289 internal static bool TryFindWeightFallback (
267- ConcurrentDictionary < FontCollectionKey ,
268- IGlyphTypeface ? > glyphTypefaces ,
290+ IDictionary < FontCollectionKey , IGlyphTypeface ? > glyphTypefaces ,
269291 FontCollectionKey key ,
270292 [ NotNullWhen ( true ) ] out IGlyphTypeface ? glyphTypeface )
271293 {
@@ -347,69 +369,5 @@ internal static bool TryFindWeightFallback(
347369
348370 return false ;
349371 }
350-
351- internal static Typeface GetImplicitTypeface ( Typeface typeface , out string normalizedFamilyName )
352- {
353- normalizedFamilyName = typeface . FontFamily . FamilyNames . PrimaryFamilyName ;
354-
355- //Return early if no separator is present.
356- if ( ! normalizedFamilyName . Contains ( ' ' ) )
357- {
358- return typeface ;
359- }
360-
361- var style = typeface . Style ;
362- var weight = typeface . Weight ;
363- var stretch = typeface . Stretch ;
364-
365- StringBuilder ? normalizedFamilyNameBuilder = null ;
366- var totalCharsRemoved = 0 ;
367-
368- var tokenizer = new SpanStringTokenizer ( normalizedFamilyName , ' ' ) ;
369-
370- // Skip initial family name.
371- tokenizer . ReadSpan ( ) ;
372-
373- while ( tokenizer . TryReadSpan ( out var token ) )
374- {
375- // Don't try to match numbers.
376- if ( new SpanStringTokenizer ( token ) . TryReadInt32 ( out _ ) )
377- {
378- continue ;
379- }
380-
381- // Try match with font style, weight or stretch and update accordingly.
382- var match = false ;
383- if ( EnumHelper . TryParse < FontStyle > ( token , true , out var newStyle ) )
384- {
385- style = newStyle ;
386- match = true ;
387- }
388- else if ( EnumHelper . TryParse < FontWeight > ( token , true , out var newWeight ) )
389- {
390- weight = newWeight ;
391- match = true ;
392- }
393- else if ( EnumHelper . TryParse < FontStretch > ( token , true , out var newStretch ) )
394- {
395- stretch = newStretch ;
396- match = true ;
397- }
398-
399- if ( match )
400- {
401- // Carve out matched word from the normalized name.
402- normalizedFamilyNameBuilder ??= new StringBuilder ( normalizedFamilyName ) ;
403- normalizedFamilyNameBuilder . Remove ( tokenizer . CurrentTokenIndex - totalCharsRemoved , token . Length ) ;
404- totalCharsRemoved += token . Length ;
405- }
406- }
407-
408- // Get rid of any trailing spaces.
409- normalizedFamilyName = ( normalizedFamilyNameBuilder ? . ToString ( ) ?? normalizedFamilyName ) . TrimEnd ( ) ;
410-
411- //Preserve old font source
412- return new Typeface ( typeface . FontFamily , style , weight , stretch ) ;
413- }
414372 }
415373}
0 commit comments