From 682c09133efddfbccc24cc1c9382159c0f670353 Mon Sep 17 00:00:00 2001 From: Benedikt Stebner Date: Thu, 2 Oct 2025 12:25:29 +0200 Subject: [PATCH] Make sure inlines properly inherit text run properties from their parent (#19750) * Make sure inlines properly inherit text run properties from their parent * Adjust comment --- src/Avalonia.Controls/Documents/Bold.cs | 5 ++ src/Avalonia.Controls/Documents/Inline.cs | 61 +++++++------- src/Avalonia.Controls/Documents/Italic.cs | 5 ++ src/Avalonia.Controls/Documents/Underline.cs | 5 ++ .../InlineTests.cs | 80 +++++++++++++++++++ 5 files changed, 125 insertions(+), 31 deletions(-) create mode 100644 tests/Avalonia.Controls.UnitTests/InlineTests.cs diff --git a/src/Avalonia.Controls/Documents/Bold.cs b/src/Avalonia.Controls/Documents/Bold.cs index 7d0a9130ae..fefe3b6d8a 100644 --- a/src/Avalonia.Controls/Documents/Bold.cs +++ b/src/Avalonia.Controls/Documents/Bold.cs @@ -13,5 +13,10 @@ namespace Avalonia.Controls.Documents { FontWeightProperty.OverrideDefaultValue(FontWeight.Bold); } + + public Bold() + { + SetCurrentValue(FontWeightProperty, FontWeight.Bold); + } } } diff --git a/src/Avalonia.Controls/Documents/Inline.cs b/src/Avalonia.Controls/Documents/Inline.cs index 4e14178805..1ededcf81c 100644 --- a/src/Avalonia.Controls/Documents/Inline.cs +++ b/src/Avalonia.Controls/Documents/Inline.cs @@ -72,44 +72,43 @@ namespace Avalonia.Controls.Documents protected TextRunProperties CreateTextRunProperties() { - var textDecorations = TextDecorations; - var background = Background; + var parentOrSelfBackground = Background ?? FindParentBackground(); - if(Parent is Inline inline) - { - if(textDecorations == null) - { - textDecorations = inline.TextDecorations; - } - - if(background == null) - { - background = inline.Background; - } - } - - var fontStyle = FontStyle; + var typeface = new Typeface( + FontFamily, + FontStyle, + FontWeight, + FontStretch); - if(Parent is Italic) - { - fontStyle = FontStyle.Italic; - } + return new GenericTextRunProperties( + typeface, + FontFeatures, + FontSize, + TextDecorations, + Foreground, + parentOrSelfBackground, + BaselineAlignment); + } - var fontWeight = FontWeight; + /// + /// Searches for the next parent inline element with a non-null Background and returns its Background brush. + /// + /// The first non-null Background brush found in parent inline elements, or null if none is found. + private IBrush? FindParentBackground() + { + var parent = Parent; - if(Parent is Bold) + while (parent is Inline inline) { - fontWeight = FontWeight.Bold; + if (inline.Background != null) + { + return inline.Background; + } + + parent = inline.Parent; } - return new GenericTextRunProperties( - new Typeface(FontFamily, fontStyle, fontWeight), - FontFeatures, - FontSize, - textDecorations, - Foreground, - background, - BaselineAlignment); + return null; } /// diff --git a/src/Avalonia.Controls/Documents/Italic.cs b/src/Avalonia.Controls/Documents/Italic.cs index e9f4698fc4..9c7e510759 100644 --- a/src/Avalonia.Controls/Documents/Italic.cs +++ b/src/Avalonia.Controls/Documents/Italic.cs @@ -13,5 +13,10 @@ namespace Avalonia.Controls.Documents { FontStyleProperty.OverrideDefaultValue(FontStyle.Italic); } + + public Italic() + { + SetCurrentValue(FontStyleProperty, FontStyle.Italic); + } } } diff --git a/src/Avalonia.Controls/Documents/Underline.cs b/src/Avalonia.Controls/Documents/Underline.cs index fcd46c8439..65689a91e0 100644 --- a/src/Avalonia.Controls/Documents/Underline.cs +++ b/src/Avalonia.Controls/Documents/Underline.cs @@ -11,5 +11,10 @@ { TextDecorationsProperty.OverrideDefaultValue(Media.TextDecorations.Underline); } + + public Underline() + { + SetCurrentValue(TextDecorationsProperty, Media.TextDecorations.Underline); + } } } diff --git a/tests/Avalonia.Controls.UnitTests/InlineTests.cs b/tests/Avalonia.Controls.UnitTests/InlineTests.cs new file mode 100644 index 0000000000..ddf7f86bfe --- /dev/null +++ b/tests/Avalonia.Controls.UnitTests/InlineTests.cs @@ -0,0 +1,80 @@ +using Avalonia.Media; +using Avalonia.UnitTests; +using Avalonia.Media.TextFormatting; +using Avalonia.Controls.Documents; +using Xunit; +using System.Collections.Generic; + +namespace Avalonia.Controls.UnitTests +{ + public class InlineTests : ScopedTestBase + { + [Fact] + public void Should_Inherit_FontWeight_In_Nested_Inlines() + { + var bold = new Bold(); + var span = new Span(); + var run = new Run("Test"); + span.Inlines.Add(run); + bold.Inlines.Add(span); + + var textRuns = new List(); + bold.BuildTextRun(textRuns, default); + + var runProperties = textRuns[0].Properties; + Assert.Equal(FontWeight.Bold, runProperties.Typeface.Weight); + } + + [Fact] + public void Should_Inherit_FontStyle_In_Nested_Inlines() + { + var italic = new Italic(); + var span = new Span(); + var run = new Run("Test"); + span.Inlines.Add(run); + italic.Inlines.Add(span); + + var textRuns = new List(); + italic.BuildTextRun(textRuns, default); + + var runProperties = textRuns[0].Properties; + Assert.Equal(FontStyle.Italic, runProperties.Typeface.Style); + } + + [Fact] + public void Should_Inherit_FontStretch_In_Nested_Inlines() + { + var span = new Span(); + var innerSpan = new Span(); + var run = new Run("Test"); + span.FontStretch = FontStretch.Condensed; + innerSpan.Inlines.Add(run); + span.Inlines.Add(innerSpan); + + var textRuns = new List(); + span.BuildTextRun(textRuns, default); + + var runProperties = textRuns[0].Properties; + Assert.Equal(FontStretch.Condensed, runProperties.Typeface.Stretch); + } + + [Fact] + public void Should_Inherit_Background_In_Nested_Inlines() + { + var backgroundBrush = Brushes.Red; + var span = new Span(); + var innerSpan = new Span(); + var run = new Run("Test"); + + span.Background = backgroundBrush; + innerSpan.Inlines.Add(run); + span.Inlines.Add(innerSpan); + + var textRuns = new List(); + span.BuildTextRun(textRuns, default); + + var runProperties = textRuns[0].Properties; + Assert.Equal(backgroundBrush, runProperties.BackgroundBrush); + } + } +}