Android: App crashes with japanese text
Describe the bug In android, when the Avalonia fail to find a possible font to render a text throws an exception in the UI thread and crash the application.
To Reproduce
- Create a control with japanese text, for example
<TextBlock Text="の"/> - Start the app in your android phone
- Throws this error:
System.ArgumentException: Specified family is not supported.
at Avalonia.Media.FontFamily.GetFontFamilyIdentifier(String name) in /_/src/Avalonia.Visuals/Media/FontFamily.cs:line 131
at Avalonia.Media.FontFamily..ctor(Uri baseUri, String name) in /_/src/Avalonia.Visuals/Media/FontFamily.cs:line 37
at Avalonia.Media.FontFamily..ctor(String name) in /_/src/Avalonia.Visuals/Media/FontFamily.cs:line 20
at Avalonia.Media.Typeface..ctor(String fontFamilyName, FontStyle style, FontWeight weight, FontStretch stretch) in /_/src/Avalonia.Visuals/Media/Typeface.cs:line 52
at Avalonia.Skia.FontManagerImpl.TryMatchCharacter(Int32 codepoint, FontStyle fontStyle, FontWeight fontWeight, FontStretch fontStretch, FontFamily fontFamily, CultureInfo culture, Typeface& fontKey) in /_/src/Skia/Avalonia.Skia/FontManagerImpl.cs:line 94
at Avalonia.Media.FontManager.TryMatchCharacter(Int32 codepoint, FontStyle fontStyle, FontWeight fontWeight, FontStretch fontStretch, FontFamily fontFamily, CultureInfo culture, Typeface& typeface) in /_/src/Avalonia.Visuals/Media/FontManager.cs:line 146
at Avalonia.Media.TextFormatting.TextCharacters.CreateShapeableRun(ReadOnlySlice`1 text, TextRunProperties defaultProperties, SByte biDiLevel, TextRunProperties& previousProperties) in /_/src/Avalonia.Visuals/Media/TextFormatting/TextCharacters.cs:line 116
at Avalonia.Media.TextFormatting.TextCharacters.GetShapeableCharacters(ReadOnlySlice`1 runText, SByte biDiLevel, TextRunProperties& previousProperties) in /_/src/Avalonia.Visuals/Media/TextFormatting/TextCharacters.cs:line 48
at Avalonia.Media.TextFormatting.TextFormatterImpl.CoalesceLevels(IReadOnlyList`1 textCharacters, ReadOnlySlice`1 levels)+MoveNext() in /_/src/Avalonia.Visuals/Media/TextFormatting/TextFormatterImpl.cs:line 324
at Avalonia.Media.TextFormatting.TextFormatterImpl.ShapeTextRuns(List`1 textRuns, FlowDirection flowDirection, FlowDirection& resolvedFlowDirection) in /_/src/Avalonia.Visuals/Media/TextFormatting/TextFormatterImpl.cs:line 178
at Avalonia.Media.TextFormatting.TextFormatterImpl.FormatLine(ITextSource textSource, Int32 firstTextSourceIndex, Double paragraphWidth, TextParagraphProperties paragraphProperties, TextLineBreak previousLineBreak) in /_/src/Avalonia.Visuals/Media/TextFormatting/TextFormatterImpl.cs:line 33
at Avalonia.Media.TextFormatting.TextLayout.CreateTextLines() in /_/src/Avalonia.Visuals/Media/TextFormatting/TextLayout.cs:line 575
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, Int32 maxLines, IReadOnlyList`1 textStyleOverrides) in /_/src/Avalonia.Visuals/Media/TextFormatting/TextLayout.cs:line 73
at Avalonia.Controls.TextBlock.CreateTextLayout(Size constraint, String text) in /_/src/Avalonia.Controls/TextBlock.cs:line 511
at Avalonia.Controls.TextBlock.get_TextLayout() in /_/src/Avalonia.Controls/TextBlock.cs:line 175
at Avalonia.Controls.TextBlock.MeasureOverride(Size availableSize) in /_/src/Avalonia.Controls/TextBlock.cs:line 553
at Avalonia.Layout.Layoutable.MeasureCore(Size availableSize) in /_/src/Avalonia.Layout/Layoutable.cs:line 559
at Avalonia.Layout.Layoutable.Measure(Size availableSize) in /_/src/Avalonia.Layout/Layoutable.cs:line 364
at Avalonia.Layout.LayoutManager.Measure(ILayoutable control) in /_/src/Avalonia.Layout/LayoutManager.cs:line 291
at Avalonia.Layout.LayoutManager.ExecuteMeasurePass() in /_/src/Avalonia.Layout/LayoutManager.cs:line 251
at Avalonia.Layout.LayoutManager.InnerLayoutPass() in /_/src/Avalonia.Layout/LayoutManager.cs:line 233
at Avalonia.Layout.LayoutManager.ExecuteLayoutPass() in /_/src/Avalonia.Layout/LayoutManager.cs:line 135
at Avalonia.Threading.JobRunner.Job.Avalonia.Threading.JobRunner.IJob.Run() in /_/src/Avalonia.Base/Threading/JobRunner.cs:line 192
at Avalonia.Threading.JobRunner.RunJobs(Nullable`1 priority) in /_/src/Avalonia.Base/Threading/JobRunner.cs:line 37
at Avalonia.Android.AndroidThreadingInterface.<Signal>b__5_0() in /_/src/Android/Avalonia.Android/AndroidThreadingInterface.cs:line 76
at Java.Lang.Thread.RunnableImplementor.Run()
at Java.Lang.IRunnableInvoker.n_Run(IntPtr jnienv, IntPtr native__this)
at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PP_V(_JniMarshal_PP_V callback, IntPtr jnienv, IntPtr klazz)
- OS: Android 10
- Version 0.10.999-cibuild0019213-beta
Additional context My phone doesn't use the Japanese language usually and as such it probably doesn't have a proper font for Japanese, I haven't tested it on a phone with the Japanese system/region.
It also crashes with the same error if you try to display emojis, for example these ➕ ➖ 🔒
Are you using the latest master from nightly build?
I tried just the nuget pre-release build, but it was a long time ago, if it was fixed i'm not sure since I modified my code to remove any special character. I will test again latter.
You should update anyway as android performance is muuuuuch better now.
But there are many breaking changes, so take some time to upgrade
you mean the pre-release or nighty builds?
No I mean the nightly builds. There is no official prerelase yet.
@marcussacana Hey can know more and I want to work on it ?
@marcussacana Hey can know more and I want to work on it ?
You're looking for a workaround? In my case since Japanese characters are that relevant and Is just something that can appears because of the user input, I just forced remove any non alphabet character from the controls in my program. But if that isn't a Option, I didn't tested, but look at this: https://stackoverflow.com/questions/62816456/how-to-include-external-font-in-avalonia-application-without-installing-it
I'd suggest to ship a custom font with your app. You need a font that You need to use a font that has required glyphs in it. https://github.com/anthonyfok/fonts-wqy-microhei is a good one WenQuanYiMicroHei-01.ttf.zip
Place the ttf file it into Assets, add as AvaloniaResource and add something like
<Style Selector="TextBlock">
<Setter Property="FontFamily" Value="avares://YourAssemblyName/Assets/Fonts#WenQuanYi Micro Hei" />
</Style>
to your App.xaml after the theme
You can define your custom font as a fallback via FontManagerOptions: https://github.com/AvaloniaUI/Avalonia/pull/7089
The font manager will automatically use that. This does not rely on the platforms font manager.
@marcussacana can you assign it to me ?
I don't have permission for that.
Adding https://github.com/AvaloniaUI/Avalonia/files/5703016/WenQuanYiMicroHei-01.ttf.zip as AvaloniaResource to the project and using these options during app setup should work for you:
.With(new FontManagerOptions
{
FontFallbacks = new[]
{
new FontFallback
{
FontFamily = new FontFamily("avares://YourAssemblyName/Assets/Fonts#WenQuanYi Micro Hei")
}
}
}
I will try implement that in my program when I can as well, maybe, since Is a problem because of the user input, isn't like I will spend a time including fonts for all languages, lol
Should I close the issue in this case? I still think should be better the avalonia display a ? or square instead crash when had missing charcters in the font.
For me a fallback char is a good idea 💡
@Gillibald do you think it's hard to implement? Maybe there could be a switch in the FontMgr. to throw or not in that case.
Missing glyphs are rendered with a square by default. Are you useing a custom font manager?
This line is failing: https://github.com/AvaloniaUI/Avalonia/blob/master/src/Avalonia.Base/Media/FontFamily.cs#L131
So there is an issue with the font family name.
Nop, I didn't tried change the default theme style or fonts.
The crash can be reproduced with the default xplat templates with the following:
- New xplat project with latest templates
dotnet new avalonia.xplat - Verify Avalonia is on
11.0.0-preview1 - Run in Android Emulator and Desktop, validate app runs with
Welcome to Avalonia!displayed - Edit
public string Greeting => "Welcome to Avalonia!";topublic string Greeting => "Welcome to Avalonia! ☕";inMainViewModel.cs - Run Desktop and validate app runs with
Welcome to Avalonia! ☕displayed - Run Android and app crashes with
FATAL UNHANDLED EXCEPTION: System.ArgumentException: Specified family is not supported.in the Android console logs
Fixed