Open MrJul opened 10 months ago
I struggle with the same error. Unfortunately, it happens at random moments and I checked that all the fonts imported well.
Could not create glyphTypeface.
System.InvalidOperationException: Could not create glyphTypeface.
at Avalonia.Media.Typeface.get_GlyphTypeface()
at Avalonia.Media.TextFormatting.TextRunProperties.get_CachedGlyphTypeface()
at Avalonia.Media.TextFormatting.TextCharacters.CreateShapeableRun(ReadOnlyMemory`1 text, TextRunProperties defaultProperties, SByte biDiLevel, FontManager fontManager, TextRunProperties& previousProperties)
at Avalonia.Media.TextFormatting.TextCharacters.GetShapeableCharacters(ReadOnlyMemory`1 text, SByte biDiLevel, FontManager fontManager, TextRunProperties& previousProperties, RentedList`1 results)
at Avalonia.Media.TextFormatting.TextFormatterImpl.CoalesceLevels(IReadOnlyList`1 textCharacters, ReadOnlySpan`1 levels, FontManager fontManager, RentedList`1 processedRuns)
at Avalonia.Media.TextFormatting.TextFormatterImpl.ShapeTextRuns(IReadOnlyList`1 textRuns, TextParagraphProperties paragraphProperties, FormattingObjectPool objectPool, FontManager fontManager, FlowDirection& resolvedFlowDirection)
at Avalonia.Media.TextFormatting.TextFormatterImpl.FormatLine(ITextSource textSource, Int32 firstTextSourceIndex, Double paragraphWidth, TextParagraphProperties paragraphProperties, TextLineBreak previousLineBreak)
at Avalonia.Media.TextFormatting.TextLayout.CreateTextLines()
at Avalonia.Media.TextFormatting.TextLayout..ctor(String text, Typeface typeface, Double fontSize, IBrush foreground, TextAlignment textAlignment, TextWrapping textWrapping, TextTrimming textTrimming, TextDecorationCollection textDecorations, FlowDirection flowDirection, Double maxWidth, Double maxHeight, Double lineHeight, Double letterSpacing, Int32 maxLines, IReadOnlyList`1 textStyleOverrides)
at Avalonia.Controls.Presenters.TextPresenter.CreateTextLayoutInternal(Size constraint, String text, Typeface typeface, IReadOnlyList`1 textStyleOverrides)
at Avalonia.Controls.Presenters.TextPresenter.CreateTextLayout()
at Avalonia.Controls.Presenters.TextPresenter.get_TextLayout()
at Avalonia.Controls.Presenters.TextPresenter.MeasureOverride(Size availableSize)
at Avalonia.Layout.Layoutable.MeasureCore(Size availableSize)
at Avalonia.Layout.Layoutable.Measure(Size availableSize)
at Avalonia.Layout.LayoutHelper.MeasureChild(Layoutable control, Size availableSize, Thickness padding, Thickness borderThickness)
at Avalonia.Controls.Border.MeasureOverride(Size availableSize)
at Avalonia.Layout.Layoutable.MeasureCore(Size availableSize)
at Avalonia.Layout.Layoutable.Measure(Size availableSize)
at Avalonia.Layout.LayoutManager.Measure(Layoutable control)
at Avalonia.Layout.LayoutManager.ExecuteMeasurePass()
at Avalonia.Layout.LayoutManager.InnerLayoutPass()
at Avalonia.Layout.LayoutManager.ExecuteLayoutPass()
at Avalonia.Media.MediaContext.FireInvokeOnRenderCallbacks()
at Avalonia.Media.MediaContext.RenderCore()
at Avalonia.Media.MediaContext.Render()
at Avalonia.Threading.DispatcherOperation.InvokeCore()
at Avalonia.Threading.DispatcherOperation.Execute()
at Avalonia.Threading.Dispatcher.ExecuteJob(DispatcherOperation job)
at Avalonia.Threading.Dispatcher.ExecuteJobsCore(Boolean fromExplicitBackgroundProcessingCallback)
at Avalonia.Threading.Dispatcher.Signaled()
at Avalonia.Native.Interop.Impl.__MicroComIAvnPlatformThreadingInterfaceEventsVTable.Signaled(Void* this)
--- End of stack trace from previous location ---
at Avalonia.Native.DispatcherImpl.RunLoop(CancellationToken token)
at Avalonia.Threading.DispatcherFrame.Run(IControlledDispatcherImpl impl)
at Avalonia.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
at Avalonia.Threading.Dispatcher.MainLoop(CancellationToken cancellationToken)
at Avalonia.Controls.ApplicationLifetimes.ClassicDesktopStyleApplicationLifetime.Start(String[] args)
at Avalonia.ClassicDesktopStyleApplicationLifetimeExtensions.StartWithClassicDesktopLifetime(AppBuilder builder, String[] args, ShutdownMode shutdownMode)
at a.b.Main(String[] a)
Current exception message is much better after @ArtjomP changes.
But this issues also mentions Avalonia should ideally report the other family names it found in the collection, via logging or through the exception
which wasn't implemented. But also, is harder to implement with current infra, as this part of the logic is hidden somewhere in skia code.
Avalonia iterates the font collection in FontManager
. To get back to the original example, we know that Skia loaded a font named Font Awesome 6 Free
even if we don't have the details to how it got this name. Avalonia skipped that font since its family name didn't match the requested one, and we can report that through trace logging.
That being said, the changes in the exception message should really help! Maybe we won't need that extra logging.
When loading a font file by family name, it would be awesome to have some optional verbose logging to diagnose font issues, or a better exception than Could not create glyphtypeface.
As seen on Telegram, one user was struggling to load Font Awesome 6 Free Regular. Most tools you can find will report a font family name of
Font Awesome 6 Free Regular
for theFont Awesome 6 Free-Regular-400.otf
file, but Skia reportsFont Awesome 6 Free
as the name instead.It turns out that there are two major font names in OTF files:
The Open Font Format standard ISO/IEC 14496-22:2019 specifies that the typographic family name is ID 16 if present, ID 1 otherwise, which Skia respects. It's quite hard for an user to get the real name quickly, since every tool in existence seems to display the name with ID 1.
When searching through a
FontCollection
for a given family name, Avalonia should ideally report the other family names it found in the collection, via logging or through the exception.