diff --git a/src/Controls/src/Core/FontExtensions.cs b/src/Controls/src/Core/FontExtensions.cs index 639fcb93cf0d..2ef5d6a833bb 100644 --- a/src/Controls/src/Core/FontExtensions.cs +++ b/src/Controls/src/Core/FontExtensions.cs @@ -34,5 +34,20 @@ public static Font ToFont(this IFontElement element, double? defaultSize = null) return Font.OfSize(element.FontFamily, size, enableScaling: element.FontAutoScalingEnabled).WithAttributes(element.FontAttributes); } + + internal static Font GetEffectiveFont(this Span span, double defaultFontSize, Font? defaultFont) + { + var fontFamily = span.IsSet(Span.FontFamilyProperty) ? span.FontFamily : defaultFont?.Family; + var fontSize = span.IsSet(Span.FontSizeProperty) ? span.FontSize : defaultFontSize; + var fontAttributes = span.IsSet(Span.FontAttributesProperty) + ? span.FontAttributes + : (defaultFont?.GetFontAttributes() ?? FontAttributes.None); + var autoScaling = span.IsSet(Span.FontAutoScalingEnabledProperty) + ? span.FontAutoScalingEnabled + : (defaultFont?.AutoScalingEnabled ?? true); + + return Font.OfSize(fontFamily, fontSize, enableScaling: autoScaling) + .WithAttributes(fontAttributes); + } } } diff --git a/src/Controls/src/Core/Platform/Android/Extensions/FormattedStringExtensions.cs b/src/Controls/src/Core/Platform/Android/Extensions/FormattedStringExtensions.cs index 486c5a05008f..62cf61d1aca0 100644 --- a/src/Controls/src/Core/Platform/Android/Extensions/FormattedStringExtensions.cs +++ b/src/Controls/src/Core/Platform/Android/Extensions/FormattedStringExtensions.cs @@ -90,10 +90,7 @@ public static SpannableString ToSpannableString( if (characterSpacing >= 0) spannable.SetSpan(new PlatformFontSpan(characterSpacing.ToEm()), start, end, SpanTypes.InclusiveInclusive); - // Font - var font = span.ToFont(defaultFontSize); - if (font.IsDefault && defaultFont.HasValue) - font = defaultFont.Value; + var font = span.GetEffectiveFont(defaultFontSize, defaultFont); if (!font.IsDefault) spannable.SetSpan(new PlatformFontSpan(context ?? AAplication.Context, font.ToTypeface(fontManager), font.AutoScalingEnabled, (float)fontManager.GetFontSize(font).Value), start, end, SpanTypes.InclusiveInclusive); diff --git a/src/Controls/src/Core/Platform/Windows/Extensions/FormattedStringExtensions.cs b/src/Controls/src/Core/Platform/Windows/Extensions/FormattedStringExtensions.cs index bd583f0507d5..fa3af73b1ad4 100644 --- a/src/Controls/src/Core/Platform/Windows/Extensions/FormattedStringExtensions.cs +++ b/src/Controls/src/Core/Platform/Windows/Extensions/FormattedStringExtensions.cs @@ -127,9 +127,7 @@ public static Tuple ToRunAndColorsTuple( var run = new Run { Text = text ?? string.Empty }; - var font = span.ToFont(defaultFontSize); - if (font.IsDefault && defaultFont.HasValue) - font = defaultFont.Value; + var font = span.GetEffectiveFont(defaultFontSize, defaultFont); if (!font.IsDefault) { diff --git a/src/Controls/src/Core/Platform/iOS/Extensions/FormattedStringExtensions.cs b/src/Controls/src/Core/Platform/iOS/Extensions/FormattedStringExtensions.cs index d622371f9598..31c75c13dc61 100644 --- a/src/Controls/src/Core/Platform/iOS/Extensions/FormattedStringExtensions.cs +++ b/src/Controls/src/Core/Platform/iOS/Extensions/FormattedStringExtensions.cs @@ -91,10 +91,7 @@ public static NSAttributedString ToNSAttributedString( _ => UITextAlignment.Left }; - var font = span.ToFont(defaultFontSize); - if (font.IsDefault && defaultFont.HasValue) - font = defaultFont.Value; - + var font = span.GetEffectiveFont(defaultFontSize, defaultFont); var hasUnderline = false; var hasStrikethrough = false; if (span.IsSet(Span.TextDecorationsProperty)) diff --git a/src/Controls/tests/TestCases.Android.Tests/snapshots/android/SpanShouldInheritStyleFromLabel.png b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/SpanShouldInheritStyleFromLabel.png new file mode 100644 index 000000000000..1b64e7edc393 Binary files /dev/null and b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/SpanShouldInheritStyleFromLabel.png differ diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue21326.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue21326.cs new file mode 100644 index 000000000000..2a7c54c87b7c --- /dev/null +++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue21326.cs @@ -0,0 +1,100 @@ +namespace Maui.Controls.Sample.Issues; + +[Issue(IssueTracker.Github, 21326, "Span does not inherit text styling from Label if that styling is applied using Style", PlatformAffected.All)] +public partial class Issue21326 : ContentPage +{ + public Issue21326() + { + var Issue21326resourceDictionary = new ResourceDictionary(); + + var headingStyle = new Style(typeof(Label)); + headingStyle.Setters.Add(new Setter { Property = Label.FontFamilyProperty, Value = "MontserratBold" }); + headingStyle.Setters.Add(new Setter { Property = Label.FontSizeProperty, Value = 20.0 }); + Issue21326resourceDictionary.Add("HeadingStyle", headingStyle); + + Resources = Issue21326resourceDictionary; + + // Test 1: FontFamily inheritance (original test) + var Issue21326testLabel = new Label + { + Style = headingStyle, + AutomationId = "Issue21326Label" + }; + + var formattedString = new FormattedString(); + formattedString.Spans.Add(new Span + { + Text = "SHOULD BE MONTSERRATBOLD from Style" + }); + Issue21326testLabel.FormattedText = formattedString; + + // Test 2: Span with explicit Bold attribute (should render as Bold) + var boldSpanLabel = new Label + { + AutomationId = "BoldSpanLabel" + }; + + var boldFormattedString = new FormattedString(); + boldFormattedString.Spans.Add(new Span + { + Text = "This text should be BOLD", + FontAttributes = FontAttributes.Bold + }); + boldSpanLabel.FormattedText = boldFormattedString; + + // Test 3: Span with explicit Italic attribute (should render as Italic) + var italicSpanLabel = new Label + { + AutomationId = "ItalicSpanLabel" + }; + + var italicFormattedString = new FormattedString(); + italicFormattedString.Spans.Add(new Span + { + Text = "This text should be ITALIC", + FontAttributes = FontAttributes.Italic + }); + italicSpanLabel.FormattedText = italicFormattedString; + + // Test 4: Span with Bold+Italic (should render as Bold Italic) + var boldItalicSpanLabel = new Label + { + AutomationId = "BoldItalicSpanLabel" + }; + + var boldItalicFormattedString = new FormattedString(); + boldItalicFormattedString.Spans.Add(new Span + { + Text = "This text should be BOLD + ITALIC", + FontAttributes = FontAttributes.Bold | FontAttributes.Italic + }); + boldItalicSpanLabel.FormattedText = boldItalicFormattedString; + + Content = new VerticalStackLayout + { + Padding = 10, + Spacing = 20, + Children = + { + new Label { Text = "Test 1: FontFamily inheritance from Style", FontAttributes = FontAttributes.Bold }, + Issue21326testLabel, + + new Label { Text = "Test 2: Span with FontAttributes='Bold'", FontAttributes = FontAttributes.Bold }, + boldSpanLabel, + + new Label { Text = "Test 3: Span with FontAttributes='Italic'", FontAttributes = FontAttributes.Bold }, + italicSpanLabel, + + new Label { Text = "Test 4: Span with Bold + Italic", FontAttributes = FontAttributes.Bold }, + boldItalicSpanLabel, + + new Label + { + Text = "If any Span above looks Regular (not Bold/Italic), the FontAttributes are being dropped!", + TextColor = Colors.Green, + FontSize = 12 + } + } + }; + } +} diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue21326.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue21326.cs new file mode 100644 index 000000000000..1a89ae794c5d --- /dev/null +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue21326.cs @@ -0,0 +1,20 @@ +using NUnit.Framework; +using UITest.Appium; +using UITest.Core; + +namespace Microsoft.Maui.TestCases.Tests.Issues; + +public class Issue21326 : _IssuesUITest +{ + public override string Issue => "Span does not inherit text styling from Label if that styling is applied using Style"; + + public Issue21326(TestDevice device) : base(device) { } + + [Test] + [Category(UITestCategories.Label)] + public void SpanShouldInheritStyleFromLabel() + { + App.WaitForElement("Issue21326Label"); + VerifyScreenshot(); + } +} diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/SpanShouldInheritStyleFromLabel.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/SpanShouldInheritStyleFromLabel.png new file mode 100644 index 000000000000..b8ef0880eb8e Binary files /dev/null and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/SpanShouldInheritStyleFromLabel.png differ