From a2c7f67c418fe93308ba4b4250de3e71a8cd79f9 Mon Sep 17 00:00:00 2001 From: Dmitry Zhelnin Date: Sat, 28 Jan 2023 15:45:08 +0300 Subject: [PATCH 1/5] throw XamlParseException if there are duplicate property setters in style or control theme --- .../AvaloniaXamlIlCompiler.cs | 1 + .../AvaloniaXamlIlDuplicateSettersChecker.cs | 44 +++++++++++++++++++ .../Xaml/XamlIlTests.cs | 41 +++++++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDuplicateSettersChecker.cs diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs index aaaee39b0d..197815f9a0 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs @@ -49,6 +49,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions InsertBefore( new AvaloniaXamlIlControlThemeTransformer(), new AvaloniaXamlIlSelectorTransformer(), + new AvaloniaXamlIlDuplicateSettersChecker(), new AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer(), new AvaloniaXamlIlBindingPathParser(), new AvaloniaXamlIlPropertyPathTransformer(), diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDuplicateSettersChecker.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDuplicateSettersChecker.cs new file mode 100644 index 0000000000..4f92fde3f0 --- /dev/null +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDuplicateSettersChecker.cs @@ -0,0 +1,44 @@ +using System.Collections.Generic; +using System.Linq; +using XamlX; +using XamlX.Ast; +using XamlX.Transform; + +namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers; + +class AvaloniaXamlIlDuplicateSettersChecker : IXamlAstTransformer +{ + public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node) + { + if (node is not XamlAstObjectNode objectNode) + { + return node; + } + + var fullName = objectNode.Type.GetClrType().FullName; + if (fullName is not ("Avalonia.Styling.Style" or "Avalonia.Styling.ControlTheme")) + { + return node; + } + + var properties = objectNode.Children + .OfType() + .Where(n => n.Type.GetClrType().Name == "Setter") + .SelectMany(setter => + setter.Children.OfType() + .Where(c => c.Property.GetClrProperty().Name == "Property")) + .Select(p => p.Values[0]) + .OfType() + .Select(x => x.Text); + var index = new HashSet(); + foreach (var property in properties) + { + if (!index.Add(property)) + { + throw new XamlParseException($"Duplicate setter encountered for property '{property}'", node); + } + } + + return node; + } +} diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs index f42f787117..be2cae8ec4 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs @@ -334,6 +334,47 @@ namespace Avalonia.Markup.Xaml.UnitTests var parsed = (Button)AvaloniaRuntimeXamlLoader.Load(document); Assert.Equal(Colors.Blue, ((ISolidColorBrush)parsed.Background!).Color); } + + [Fact] + public void Style_Parser_Throws_For_Duplicate_Setter() + { + var xaml = @" + + + + + +"; + AssertThrows(() => AvaloniaRuntimeXamlLoader.Load(xaml, typeof(XamlIlTests).Assembly, designMode: true), + e => e.Message.StartsWith("Duplicate setter encountered for property 'Height'")); + } + + [Fact] + public void Control_Theme_Parser_Throws_For_Duplicate_Setter() + { + var xaml = @" + + + + + + + + + + +"; + AssertThrows(() => AvaloniaRuntimeXamlLoader.Load(xaml, typeof(XamlIlTests).Assembly, designMode: true), + e => e.Message.StartsWith("Duplicate setter encountered for property 'Height'")); + } } public class XamlIlBugTestsEventHandlerCodeBehind : Window From 0b726e1eff92cfbf37ed57cda1f42d7951cfce54 Mon Sep 17 00:00:00 2001 From: Dmitry Zhelnin Date: Mon, 30 Jan 2023 11:10:53 +0300 Subject: [PATCH 2/5] add Style and ControlTheme to WellKnownTypes --- .../Transformers/AvaloniaXamlIlControlThemeTransformer.cs | 3 ++- .../Transformers/AvaloniaXamlIlDuplicateSettersChecker.cs | 5 +++-- .../Transformers/AvaloniaXamlIlSelectorTransformer.cs | 3 ++- .../Transformers/AvaloniaXamlIlWellKnownTypes.cs | 4 ++++ 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlControlThemeTransformer.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlControlThemeTransformer.cs index 1338dc7248..51fe58d1c9 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlControlThemeTransformer.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlControlThemeTransformer.cs @@ -11,7 +11,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers { public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node) { - if (!(node is XamlAstObjectNode on && on.Type.GetClrType().FullName == "Avalonia.Styling.ControlTheme")) + if (node is not XamlAstObjectNode on || + !context.GetAvaloniaTypes().ControlTheme.IsAssignableFrom(on.Type.GetClrType())) return node; // Check if we've already transformed this node. diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDuplicateSettersChecker.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDuplicateSettersChecker.cs index 4f92fde3f0..4ab9594cd8 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDuplicateSettersChecker.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDuplicateSettersChecker.cs @@ -15,8 +15,9 @@ class AvaloniaXamlIlDuplicateSettersChecker : IXamlAstTransformer return node; } - var fullName = objectNode.Type.GetClrType().FullName; - if (fullName is not ("Avalonia.Styling.Style" or "Avalonia.Styling.ControlTheme")) + var nodeType = objectNode.Type.GetClrType(); + if (!context.GetAvaloniaTypes().Style.IsAssignableFrom(nodeType) && + !context.GetAvaloniaTypes().ControlTheme.IsAssignableFrom(nodeType)) { return node; } diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs index 078e23bc02..edddc5424a 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs @@ -19,7 +19,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers { public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node) { - if (!(node is XamlAstObjectNode on && on.Type.GetClrType().FullName == "Avalonia.Styling.Style")) + if (node is not XamlAstObjectNode on || + !context.GetAvaloniaTypes().Style.IsAssignableFrom(on.Type.GetClrType())) return node; var pn = on.Children.OfType() diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs index 0aa3dda693..c55e116cb3 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs @@ -111,6 +111,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers public IXamlMethod ResourceDictionaryDeferredAdd { get; } public IXamlType UriKind { get; } public IXamlConstructor UriConstructor { get; } + public IXamlType Style { get; } + public IXamlType ControlTheme { get; } public AvaloniaXamlIlWellKnownTypes(TransformerConfiguration cfg) { @@ -248,6 +250,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers XamlIlTypes.Object)); UriKind = cfg.TypeSystem.GetType("System.UriKind"); UriConstructor = Uri.GetConstructor(new List() { cfg.WellKnownTypes.String, UriKind }); + Style = cfg.TypeSystem.GetType("Avalonia.Styling.Style"); + ControlTheme = cfg.TypeSystem.GetType("Avalonia.Styling.ControlTheme"); } } From 281d30747dfe36de94a0ddec2ebcd2d8455663c8 Mon Sep 17 00:00:00 2001 From: robloo Date: Mon, 30 Jan 2023 22:45:22 -0500 Subject: [PATCH 3/5] Switch TreeViewItem.IsExpanded to a StyledProperty Includes other small fixes and updates --- src/Avalonia.Controls/TreeViewItem.cs | 29 ++++++++++----------------- 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/src/Avalonia.Controls/TreeViewItem.cs b/src/Avalonia.Controls/TreeViewItem.cs index 022e1a74b1..5674874c01 100644 --- a/src/Avalonia.Controls/TreeViewItem.cs +++ b/src/Avalonia.Controls/TreeViewItem.cs @@ -1,11 +1,11 @@ using System; using System.Collections.Generic; using System.Linq; -using Avalonia.Controls.Generators; using Avalonia.Controls.Metadata; using Avalonia.Controls.Mixins; using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; +using Avalonia.Data; using Avalonia.Input; using Avalonia.LogicalTree; using Avalonia.Threading; @@ -22,11 +22,10 @@ namespace Avalonia.Controls /// /// Defines the property. /// - public static readonly DirectProperty IsExpandedProperty = - AvaloniaProperty.RegisterDirect( + public static readonly StyledProperty IsExpandedProperty = + AvaloniaProperty.Register( nameof(IsExpanded), - o => o.IsExpanded, - (o, v) => o.IsExpanded = v); + defaultBindingMode: BindingMode.TwoWay); /// /// Defines the property. @@ -46,7 +45,6 @@ namespace Avalonia.Controls private TreeView? _treeView; private Control? _header; - private bool _isExpanded; private int _level; private bool _templateApplied; private bool _deferredBringIntoViewFlag; @@ -68,8 +66,8 @@ namespace Avalonia.Controls /// public bool IsExpanded { - get { return _isExpanded; } - set { SetAndRaise(IsExpandedProperty, ref _isExpanded, value); } + get => GetValue(IsExpandedProperty); + set => SetValue(IsExpandedProperty, value); } /// @@ -77,8 +75,8 @@ namespace Avalonia.Controls /// public bool IsSelected { - get { return GetValue(IsSelectedProperty); } - set { SetValue(IsSelectedProperty, value); } + get => GetValue(IsSelectedProperty); + set => SetValue(IsSelectedProperty, value); } /// @@ -86,8 +84,8 @@ namespace Avalonia.Controls /// public int Level { - get { return _level; } - private set { SetAndRaise(LevelProperty, ref _level, value); } + get => _level; + private set => SetAndRaise(LevelProperty, ref _level, value); } internal TreeView? TreeViewOwner => _treeView; @@ -115,11 +113,6 @@ namespace Avalonia.Controls } } - protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e) - { - base.OnDetachedFromLogicalTree(e); - } - protected virtual void OnRequestBringIntoView(RequestBringIntoViewEventArgs e) { if (e.TargetObject == this) @@ -266,7 +259,7 @@ namespace Avalonia.Controls } /// - /// Invoked when the event occurs in the header. + /// Invoked when the event occurs in the header. /// protected virtual void OnHeaderDoubleTapped(TappedEventArgs e) { From 3f6cb8224120e3fb6d2940e35b8c2e43b237bd92 Mon Sep 17 00:00:00 2001 From: Benedikt Stebner Date: Tue, 31 Jan 2023 10:45:44 +0100 Subject: [PATCH 4/5] Add failing test --- .../Media/TextFormatting/TextFormatterImpl.cs | 101 +++++++++--------- .../Media/TextFormatting/TextLineImpl.cs | 14 ++- .../TextFormatting/SingleBufferTextSource.cs | 8 +- .../TextFormatting/TextFormatterTests.cs | 11 +- 4 files changed, 79 insertions(+), 55 deletions(-) diff --git a/src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs b/src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs index 7505b9ccdd..c8db70dbfe 100644 --- a/src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs +++ b/src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs @@ -60,25 +60,25 @@ namespace Avalonia.Media.TextFormatting switch (textWrapping) { case TextWrapping.NoWrap: - { - // perf note: if textRuns comes from remainingRuns above, it's very likely coming from this class - // which already uses an array: ToArray() won't ever be called in this case - var textRunArray = textRuns as TextRun[] ?? textRuns.ToArray(); + { + // perf note: if textRuns comes from remainingRuns above, it's very likely coming from this class + // which already uses an array: ToArray() won't ever be called in this case + var textRunArray = textRuns as TextRun[] ?? textRuns.ToArray(); - textLine = new TextLineImpl(textRunArray, firstTextSourceIndex, textSourceLength, - paragraphWidth, paragraphProperties, resolvedFlowDirection, nextLineBreak); + textLine = new TextLineImpl(textRunArray, firstTextSourceIndex, textSourceLength, + paragraphWidth, paragraphProperties, resolvedFlowDirection, nextLineBreak); - textLine.FinalizeLine(); + textLine.FinalizeLine(); - break; - } + break; + } case TextWrapping.WrapWithOverflow: case TextWrapping.Wrap: - { - textLine = PerformTextWrapping(textRuns, firstTextSourceIndex, paragraphWidth, - paragraphProperties, resolvedFlowDirection, nextLineBreak, objectPool, fontManager); - break; - } + { + textLine = PerformTextWrapping(textRuns, firstTextSourceIndex, paragraphWidth, + paragraphProperties, resolvedFlowDirection, nextLineBreak, objectPool, fontManager); + break; + } default: throw new ArgumentOutOfRangeException(nameof(textWrapping)); } @@ -249,49 +249,49 @@ namespace Avalonia.Media.TextFormatting switch (currentRun) { case UnshapedTextRun shapeableRun: - { - groupedRuns.Clear(); - groupedRuns.Add(shapeableRun); + { + groupedRuns.Clear(); + groupedRuns.Add(shapeableRun); - var text = shapeableRun.Text; - var properties = shapeableRun.Properties; + var text = shapeableRun.Text; + var properties = shapeableRun.Properties; - while (index + 1 < processedRuns.Count) - { - if (processedRuns[index + 1] is not UnshapedTextRun nextRun) + while (index + 1 < processedRuns.Count) { + if (processedRuns[index + 1] is not UnshapedTextRun nextRun) + { + break; + } + + if (shapeableRun.BidiLevel == nextRun.BidiLevel + && TryJoinContiguousMemories(text, nextRun.Text, out var joinedText) + && CanShapeTogether(properties, nextRun.Properties)) + { + groupedRuns.Add(nextRun); + index++; + shapeableRun = nextRun; + text = joinedText; + continue; + } + break; } - if (shapeableRun.BidiLevel == nextRun.BidiLevel - && TryJoinContiguousMemories(text, nextRun.Text, out var joinedText) - && CanShapeTogether(properties, nextRun.Properties)) - { - groupedRuns.Add(nextRun); - index++; - shapeableRun = nextRun; - text = joinedText; - continue; - } + var shaperOptions = new TextShaperOptions( + properties.CachedGlyphTypeface, + properties.FontRenderingEmSize, shapeableRun.BidiLevel, properties.CultureInfo, + paragraphProperties.DefaultIncrementalTab, paragraphProperties.LetterSpacing); + + ShapeTogether(groupedRuns, text, shaperOptions, textShaper, shapedRuns); break; } - - var shaperOptions = new TextShaperOptions( - properties.CachedGlyphTypeface, - properties.FontRenderingEmSize, shapeableRun.BidiLevel, properties.CultureInfo, - paragraphProperties.DefaultIncrementalTab, paragraphProperties.LetterSpacing); - - ShapeTogether(groupedRuns, text, shaperOptions, textShaper, shapedRuns); - - break; - } default: - { - shapedRuns.Add(currentRun); + { + shapedRuns.Add(currentRun); - break; - } + break; + } } } } @@ -712,7 +712,7 @@ namespace Avalonia.Media.TextFormatting switch (currentRun) { case ShapedTextRun: - { + { var lineBreaker = new LineBreakEnumerator(currentRun.Text.Span); while (lineBreaker.MoveNext(out var lineBreak)) @@ -754,7 +754,7 @@ namespace Avalonia.Media.TextFormatting break; } - while (lineBreaker.MoveNext(out lineBreak) && index < textRuns.Count) + while (lineBreaker.MoveNext(out lineBreak)) { currentPosition += lineBreak.PositionWrap; @@ -780,6 +780,11 @@ namespace Avalonia.Media.TextFormatting currentPosition = currentLength + lineBreak.PositionWrap; } + //if (currentPosition == 0 && measuredLength > 0) + //{ + // currentPosition = measuredLength; + //} + breakFound = true; break; diff --git a/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs b/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs index ad3244a3a5..e97f431412 100644 --- a/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs +++ b/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs @@ -172,9 +172,21 @@ namespace Avalonia.Media.TextFormatting distance -= Start; + var firstRunIndex = 0; + + if (_textRuns[firstRunIndex] is TextEndOfLine) + { + firstRunIndex++; + } + + if(firstRunIndex >= _textRuns.Length) + { + return new CharacterHit(FirstTextSourceIndex); + } + if (distance <= 0) { - var firstRun = _textRuns[0]; + var firstRun = _textRuns[firstRunIndex]; return GetRunCharacterHit(firstRun, FirstTextSourceIndex, 0); } diff --git a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/SingleBufferTextSource.cs b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/SingleBufferTextSource.cs index f963277397..7837749adf 100644 --- a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/SingleBufferTextSource.cs +++ b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/SingleBufferTextSource.cs @@ -7,25 +7,27 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting { private readonly string _text; private readonly GenericTextRunProperties _defaultGenericPropertiesRunProperties; + private readonly bool _addEndOfParagraph; - public SingleBufferTextSource(string text, GenericTextRunProperties defaultProperties) + public SingleBufferTextSource(string text, GenericTextRunProperties defaultProperties, bool addEndOfParagraph = false) { _text = text; _defaultGenericPropertiesRunProperties = defaultProperties; + _addEndOfParagraph = addEndOfParagraph; } public TextRun GetTextRun(int textSourceIndex) { if (textSourceIndex >= _text.Length) { - return null; + return _addEndOfParagraph ? new TextEndOfParagraph() : null; } var runText = _text.AsMemory(textSourceIndex); if (runText.IsEmpty) { - return null; + return _addEndOfParagraph ? new TextEndOfParagraph() : null; } return new TextCharacters(runText, _defaultGenericPropertiesRunProperties); diff --git a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs index 7822d6624b..dd04d26bb5 100644 --- a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs +++ b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs @@ -242,10 +242,16 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting { var defaultProperties = new GenericTextRunProperties(Typeface.Default); - var textSource = new SingleBufferTextSource(text, defaultProperties); + var paragraphProperties = new GenericTextParagraphProperties(defaultProperties, textWrap: TextWrapping.WrapWithOverflow); + + var textSource = new SingleBufferTextSource("ABCDEFHFFHFJHKHFK", defaultProperties, true); var formatter = new TextFormatterImpl(); + var line = formatter.FormatLine(textSource, 0, 33, paragraphProperties); + + textSource = new SingleBufferTextSource(text, defaultProperties); + var numberOfLines = 0; var currentPosition = 0; @@ -253,8 +259,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting while (currentPosition < text.Length) { var textLine = - formatter.FormatLine(textSource, currentPosition, 1, - new GenericTextParagraphProperties(defaultProperties, textWrap: TextWrapping.WrapWithOverflow)); + formatter.FormatLine(textSource, currentPosition, 1, paragraphProperties); if (text.Length - currentPosition > expectedCharactersPerLine) { From 743e1fa04060a168b7ec779b78f6003c2e908dd3 Mon Sep 17 00:00:00 2001 From: Benedikt Stebner Date: Tue, 31 Jan 2023 10:46:51 +0100 Subject: [PATCH 5/5] Fix WrapWithOverflow handling for textlines that contain TextEndOfParagraph runs --- .../Media/TextFormatting/TextFormatterImpl.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs b/src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs index c8db70dbfe..2e20d6844e 100644 --- a/src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs +++ b/src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs @@ -780,10 +780,10 @@ namespace Avalonia.Media.TextFormatting currentPosition = currentLength + lineBreak.PositionWrap; } - //if (currentPosition == 0 && measuredLength > 0) - //{ - // currentPosition = measuredLength; - //} + if (currentPosition == 0 && measuredLength > 0) + { + currentPosition = measuredLength; + } breakFound = true;