Skip to content

Commit

Permalink
feat: Add font fallback support on Skia
Browse files Browse the repository at this point in the history
  • Loading branch information
Youssef1313 committed Nov 5, 2023
1 parent 51a4e44 commit 03397f2
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 28 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Page
x:Class="UITests.Windows_UI_Xaml_Controls.TextBlockControl.TextBlock_FontFallback"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UITests.Windows_UI_Xaml_Controls.TextBlockControl"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

<StackPanel>
<TextBlock Text="Sample Text - 示例文本 - اللغة العربية" FontWeight="Bold" FontSize="40" />
</StackPanel>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Uno.UI.Samples.Controls;
using Windows.UI.Xaml.Controls;

namespace UITests.Windows_UI_Xaml_Controls.TextBlockControl;

[Sample("TextBlock", IsManualTest = true)]
public sealed partial class TextBlock_FontFallback : Page
{
public TextBlock_FontFallback()
{
this.InitializeComponent();
}
}
40 changes: 20 additions & 20 deletions src/Uno.UI/UI/Xaml/Documents/Run.skia.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,54 +91,54 @@ private List<Segment> GetSegments()
break;
}

if (char.IsSymbol(text[i]))
if (i + 1 < text.Length
&& char.IsSurrogate(text[i])
&& char.IsSurrogatePair(text[i], text[i + 1]))
{
symbolTypeface = SKFontManager.Default
.MatchCharacter(text[i]);
var fontManager = SKFontManager.Default;
var codepoint = (int)((text[i] - 0xD800) * 0x400 + (text[i + 1] - 0xDC00) + 0x10000);
symbolTypeface = fontManager
.MatchCharacter(codepoint);

if (symbolTypeface is null)
if (symbolTypeface is not null)
{
surrogate = true;
}
else
{
// Under some Linux systems, the symbol may not be found
// in the default font and
// we have to skip the character and continue segments
// evaluation.

if (this.Log().IsEnabled(LogLevel.Trace))
{
this.Log().Trace($"Failed to match symbol in the default system font (0x{(int)text[i]:X4}, {text[i]})");
this.Log().Trace($"Failed to match surrogate in the default system font (0x{codepoint:X4}, {(char)codepoint})");
}

i++;
}

break;
}
else if (i + 1 < text.Length
&& char.IsSurrogate(text[i])
&& char.IsSurrogatePair(text[i], text[i + 1]))
else if (!fontInfo.SKFont.ContainsGlyph(text[i]))
{
var fontManager = SKFontManager.Default;
var codepoint = (int)((text[i] - 0xD800) * 0x400 + (text[i + 1] - 0xDC00) + 0x10000);
symbolTypeface = fontManager
.MatchCharacter(codepoint);
symbolTypeface = SKFontManager.Default
.MatchCharacter(text[i]);

if (symbolTypeface is not null)
{
surrogate = true;
}
else
if (symbolTypeface is null)
{
// Under some Linux systems, the symbol may not be found
// in the default font and
// we have to skip the character and continue segments
// evaluation.

if (this.Log().IsEnabled(LogLevel.Trace))
{
this.Log().Trace($"Failed to match surrogate in the default system font (0x{codepoint:X4}, {(char)codepoint})");
this.Log().Trace($"Failed to match symbol in the default system font (0x{(int)text[i]:X4}, {text[i]})");
}

i++;
}

break;
}
i++;
Expand Down
16 changes: 8 additions & 8 deletions src/Uno.UI/UI/Xaml/Style/mergedstyles.xaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<ResourceDictionary xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:controls="using:Microsoft.UI.Xaml.Controls" xmlns:contract7Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,7)" xmlns:contract7NotPresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractNotPresent(Windows.Foundation.UniversalApiContract,7)" xmlns:primitives="using:Microsoft.UI.Xaml.Controls.Primitives" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d macos wasm android ios netstdref not_netstdref not_win not_wasm skia" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:macos="http://uno.ui/macos" xmlns:not_macos="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:media="using:Microsoft.UI.Xaml.Media" xmlns:animatedvisuals="using:Microsoft.UI.Xaml.Controls.AnimatedVisuals" xmlns:contract4Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,4)" xmlns:contract4NotPresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractNotPresent(Windows.Foundation.UniversalApiContract,4)" xmlns:primitiveContract7Present="using:Microsoft.UI.Xaml.Controls.Primitives?IsApiContractPresent(Windows.Foundation.UniversalApiContract,7)" xmlns:contract5Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,5)" xmlns:contract5NotPresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractNotPresent(Windows.Foundation.UniversalApiContract,5)" xmlns:contract6Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,6)" xmlns:contract8Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,8)" xmlns:wasm="http://uno.ui/wasm" xmlns:animation="clr-namespace:Windows.UI.Xaml.Media.Animation" xmlns:uno="using:Uno.UI.Xaml.Controls" xmlns:android="http://uno.ui/android#using:Uno.UI.Controls.Legacy" xmlns:not_android="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:ios="http://uno.ui/ios#using:Uno.UI.Controls.Legacy" xmlns:win="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:not_mux="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:uBehaviors="using:Uno.UI.Behaviors" xmlns:local="using:Windows.UI.Xaml.Controls" xmlns:automation="clr-namespace:Windows.UI.Xaml.Automation" xmlns:u="using:Uno.UI.Controls" xmlns:not_win="http://uno.ui/not_win" xmlns:not_wasm="http://uno.ui/not_wasm" xmlns:localUIXC="using:Uno.UI.Xaml.Controls" xmlns:navViewLocal="using:Windows.UI.Xaml.Controls" xmlns:wuxPrimitives="using:Windows.UI.Xaml.Controls.Primitives" xmlns:legacy="using:Windows.UI.Xaml.Controls" xmlns:netstdref="http://uno.ui/netstdref" xmlns:skia="http://uno.ui/skia" xmlns:native="using:UIKit" xmlns:not_netstdref="http://uno.ui/not_netstdref" xmlns:native_ios="using:UIKit" xmlns:native_android="using:Android.Widget" xmlns:itemswrapgridpresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsTypePresent(Windows.UI.Xaml.Controls.ItemsWrapGrid)" xmlns:itemswrapgridnotpresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsTypeNotPresent(Windows.UI.Xaml.Controls.ItemsWrapGrid)" xmlns:uwpOnly="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsTypeNotPresent(Microsoft.UI.Xaml.FrameworkElement)" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<ResourceDictionary xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:controls="using:Microsoft.UI.Xaml.Controls" xmlns:primitives="using:Microsoft.UI.Xaml.Controls.Primitives" xmlns:contract7Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,7)" xmlns:contract7NotPresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractNotPresent(Windows.Foundation.UniversalApiContract,7)" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d macos wasm android ios netstdref not_netstdref not_win not_wasm skia" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:macos="http://uno.ui/macos" xmlns:not_macos="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:media="using:Microsoft.UI.Xaml.Media" xmlns:animatedvisuals="using:Microsoft.UI.Xaml.Controls.AnimatedVisuals" xmlns:contract4Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,4)" xmlns:contract4NotPresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractNotPresent(Windows.Foundation.UniversalApiContract,4)" xmlns:primitiveContract7Present="using:Microsoft.UI.Xaml.Controls.Primitives?IsApiContractPresent(Windows.Foundation.UniversalApiContract,7)" xmlns:contract5Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,5)" xmlns:contract5NotPresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractNotPresent(Windows.Foundation.UniversalApiContract,5)" xmlns:contract6Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,6)" xmlns:contract8Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,8)" xmlns:wasm="http://uno.ui/wasm" xmlns:animation="clr-namespace:Windows.UI.Xaml.Media.Animation" xmlns:uno="using:Uno.UI.Xaml.Controls" xmlns:android="http://uno.ui/android#using:Uno.UI.Controls.Legacy" xmlns:not_android="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:ios="http://uno.ui/ios#using:Uno.UI.Controls.Legacy" xmlns:win="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:not_mux="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:uBehaviors="using:Uno.UI.Behaviors" xmlns:local="using:Windows.UI.Xaml.Controls" xmlns:automation="clr-namespace:Windows.UI.Xaml.Automation" xmlns:u="using:Uno.UI.Controls" xmlns:not_win="http://uno.ui/not_win" xmlns:not_wasm="http://uno.ui/not_wasm" xmlns:localUIXC="using:Uno.UI.Xaml.Controls" xmlns:navViewLocal="using:Windows.UI.Xaml.Controls" xmlns:wuxPrimitives="using:Windows.UI.Xaml.Controls.Primitives" xmlns:legacy="using:Windows.UI.Xaml.Controls" xmlns:netstdref="http://uno.ui/netstdref" xmlns:skia="http://uno.ui/skia" xmlns:native="using:UIKit" xmlns:not_netstdref="http://uno.ui/not_netstdref" xmlns:native_ios="using:UIKit" xmlns:native_android="using:Android.Widget" xmlns:itemswrapgridpresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsTypePresent(Windows.UI.Xaml.Controls.ItemsWrapGrid)" xmlns:itemswrapgridnotpresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsTypeNotPresent(Windows.UI.Xaml.Controls.ItemsWrapGrid)" xmlns:uwpOnly="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsTypeNotPresent(Microsoft.UI.Xaml.FrameworkElement)" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<x:String x:Key="BreadcrumbBarChevronLeftToRight">&#xE974;</x:String>
Expand Down Expand Up @@ -2643,11 +2643,11 @@
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<contract7Present:Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:BreadcrumbBarItem">
<Grid x:Name="PART_LayoutRoot" contract7Present:CornerRadius="{TemplateBinding CornerRadius}" contract7NotPresent:CornerRadius="{ThemeResource ControlCornerRadius}">
<Grid x:Name="PART_LayoutRoot" CornerRadius="{TemplateBinding CornerRadius}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ItemTypeStates">
<VisualState x:Name="Inline" />
Expand Down Expand Up @@ -2754,13 +2754,13 @@
<Setter Property="ScrollViewer.ZoomMode" Value="Disabled" />
<Setter Property="MaxWidth" Value="{ThemeResource FlyoutThemeMaxWidth}" />
<Setter Property="MinHeight" Value="40" />
<contract7Present:Setter Property="CornerRadius" Value="{ThemeResource OverlayCornerRadius}" />
<Setter Property="CornerRadius" Value="{ThemeResource OverlayCornerRadius}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="FlyoutPresenter">
<Grid Background="{TemplateBinding Background}" contract7Present:CornerRadius="{TemplateBinding CornerRadius}" contract7NotPresent:CornerRadius="{ThemeResource ControlCornerRadius}" contract7Present:BackgroundSizing="InnerBorderEdge">
<Grid Background="{TemplateBinding Background}" CornerRadius="{TemplateBinding CornerRadius}" BackgroundSizing="InnerBorderEdge">
<ScrollViewer x:Name="FlyoutPresenterScrollViewer" Margin="{TemplateBinding Padding}" HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}" HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}" VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}" VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}" IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}" IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}" Content="{TemplateBinding Content}" ZoomMode="{TemplateBinding ScrollViewer.ZoomMode}" AutomationProperties.AccessibilityView="Raw" />
<Border x:Name="FlyoutPresenterBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" contract7Present:CornerRadius="{TemplateBinding CornerRadius}" contract7NotPresent:CornerRadius="{ThemeResource ControlCornerRadius}" />
<Border x:Name="FlyoutPresenterBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="{TemplateBinding CornerRadius}" />
</Grid>
</ControlTemplate>
</Setter.Value>
Expand All @@ -2773,7 +2773,7 @@
<ColumnDefinition Width="Auto" x:Name="PART_ContentColumn" />
<ColumnDefinition Width="Auto" x:Name="PART_ChevronColumn" />
</Grid.ColumnDefinitions>
<Button x:Name="PART_ItemButton" x:DeferLoadStrategy="Lazy" Grid.Column="0" AutomationProperties.Name="BreadcrumbBarItemButton" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Control.IsTemplateFocusTarget="True" IsTabStop="False" FocusVisualMargin="-3" Padding="1,3" contract7Present:CornerRadius="{TemplateBinding CornerRadius}" AutomationProperties.AccessibilityView="Raw">
<Button x:Name="PART_ItemButton" x:DeferLoadStrategy="Lazy" Grid.Column="0" AutomationProperties.Name="BreadcrumbBarItemButton" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Control.IsTemplateFocusTarget="True" IsTabStop="False" FocusVisualMargin="-3" Padding="1,3" CornerRadius="{TemplateBinding CornerRadius}" AutomationProperties.AccessibilityView="Raw">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Foreground" Value="{ThemeResource BreadcrumbBarNormalForegroundBrush}" />
Expand Down Expand Up @@ -2867,7 +2867,7 @@
</Grid>
</Button>
<!-- ContentPresenter to be shown only when the rendered item is the Current Item -->
<ContentPresenter x:Name="PART_LastItemContentPresenter" Grid.Column="0" Visibility="Collapsed" Content="{TemplateBinding Content}" ContentTransitions="{TemplateBinding ContentTransitions}" ContentTemplate="{TemplateBinding ContentTemplate}" FocusVisualMargin="-3" FontFamily="{TemplateBinding FontFamily}" FontSize="{TemplateBinding FontSize}" FontWeight="{TemplateBinding FontWeight}" Foreground="{ThemeResource BreadcrumbBarCurrentNormalForegroundBrush}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" LineHeight="20" Padding="1,3" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" contract7Present:CornerRadius="{TemplateBinding CornerRadius}" contract7NotPresent:CornerRadius="{ThemeResource ControlCornerRadius}" AutomationProperties.AccessibilityView="Raw" />
<ContentPresenter x:Name="PART_LastItemContentPresenter" Grid.Column="0" Visibility="Collapsed" Content="{TemplateBinding Content}" ContentTransitions="{TemplateBinding ContentTransitions}" ContentTemplate="{TemplateBinding ContentTemplate}" FocusVisualMargin="-3" FontFamily="{TemplateBinding FontFamily}" FontSize="{TemplateBinding FontSize}" FontWeight="{TemplateBinding FontWeight}" Foreground="{ThemeResource BreadcrumbBarCurrentNormalForegroundBrush}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" LineHeight="20" Padding="1,3" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" CornerRadius="{TemplateBinding CornerRadius}" AutomationProperties.AccessibilityView="Raw" />
<!-- ContentPresenter to be shown only when the rendered item is a drop down Item -->
<ContentPresenter x:Name="PART_EllipsisDropDownItemContentPresenter" x:DeferLoadStrategy="Lazy" Grid.Column="0" Visibility="Collapsed" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" ContentTransitions="{TemplateBinding ContentTransitions}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" HorizontalContentAlignment="Stretch" FontWeight="Normal" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" AutomationProperties.AccessibilityView="Raw" />
<!-- TextBlock that contains the chevron icon -->
Expand Down

0 comments on commit 03397f2

Please sign in to comment.