From 98655d04ce3804e717e38dc9cf24b6d6afd3f0b5 Mon Sep 17 00:00:00 2001 From: Benedikt Stebner Date: Tue, 20 Sep 2022 08:20:23 +0200 Subject: [PATCH 1/2] Fix bidi mirror handling --- src/Avalonia.Base/Media/TextFormatting/TextCharacters.cs | 2 +- src/Avalonia.Base/Media/TextFormatting/Unicode/BiDiData.cs | 3 --- src/Skia/Avalonia.Skia/TextShaperImpl.cs | 7 ++++++- src/Windows/Avalonia.Direct2D1/Media/TextShaperImpl.cs | 7 ++++++- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/Avalonia.Base/Media/TextFormatting/TextCharacters.cs b/src/Avalonia.Base/Media/TextFormatting/TextCharacters.cs index 42a9e61c36..bcfa35ae30 100644 --- a/src/Avalonia.Base/Media/TextFormatting/TextCharacters.cs +++ b/src/Avalonia.Base/Media/TextFormatting/TextCharacters.cs @@ -76,7 +76,7 @@ namespace Avalonia.Media.TextFormatting { if (script == Script.Common && previousTypeface is not null) { - if (TryGetShapeableLength(text, previousTypeface.Value, defaultTypeface, out var fallbackCount, out _)) + if (TryGetShapeableLength(text, previousTypeface.Value, null, out var fallbackCount, out _)) { return new ShapeableTextCharacters(text.Take(fallbackCount), defaultProperties.WithTypeface(previousTypeface.Value), biDiLevel); diff --git a/src/Avalonia.Base/Media/TextFormatting/Unicode/BiDiData.cs b/src/Avalonia.Base/Media/TextFormatting/Unicode/BiDiData.cs index 65c348e928..72df2815a9 100644 --- a/src/Avalonia.Base/Media/TextFormatting/Unicode/BiDiData.cs +++ b/src/Avalonia.Base/Media/TextFormatting/Unicode/BiDiData.cs @@ -71,9 +71,6 @@ namespace Avalonia.Media.TextFormatting.Unicode // Resolve the BidiCharacterType, paired bracket type and paired // bracket values for all code points - HasBrackets = false; - HasEmbeddings = false; - HasIsolates = false; int i = Length; diff --git a/src/Skia/Avalonia.Skia/TextShaperImpl.cs b/src/Skia/Avalonia.Skia/TextShaperImpl.cs index 6b0b7bccbb..6da8a20f6a 100644 --- a/src/Skia/Avalonia.Skia/TextShaperImpl.cs +++ b/src/Skia/Avalonia.Skia/TextShaperImpl.cs @@ -27,7 +27,7 @@ namespace Avalonia.Skia buffer.GuessSegmentProperties(); - buffer.Direction = Direction.LeftToRight; //Always shape LeftToRight + buffer.Direction = (bidiLevel & 1) == 0 ? Direction.LeftToRight : Direction.RightToLeft; buffer.Language = new Language(culture ?? CultureInfo.CurrentCulture); @@ -35,6 +35,11 @@ namespace Avalonia.Skia font.Shape(buffer); + if(buffer.Direction == Direction.RightToLeft) + { + buffer.Reverse(); + } + font.GetScale(out var scaleX, out _); var textScale = fontRenderingEmSize / scaleX; diff --git a/src/Windows/Avalonia.Direct2D1/Media/TextShaperImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/TextShaperImpl.cs index 435c7cd89a..bda36e6c8c 100644 --- a/src/Windows/Avalonia.Direct2D1/Media/TextShaperImpl.cs +++ b/src/Windows/Avalonia.Direct2D1/Media/TextShaperImpl.cs @@ -27,7 +27,7 @@ namespace Avalonia.Direct2D1.Media buffer.GuessSegmentProperties(); - buffer.Direction = Direction.LeftToRight; //Always shape LeftToRight + buffer.Direction = (bidiLevel & 1) == 0 ? Direction.LeftToRight : Direction.RightToLeft; buffer.Language = new Language(culture ?? CultureInfo.CurrentCulture); @@ -35,6 +35,11 @@ namespace Avalonia.Direct2D1.Media font.Shape(buffer); + if(buffer.Direction == Direction.RightToLeft) + { + buffer.Reverse(); + } + font.GetScale(out var scaleX, out _); var textScale = fontRenderingEmSize / scaleX; From 3e127d70a1450c3c0960c84e6385a7333222dfdd Mon Sep 17 00:00:00 2001 From: Benedikt Stebner Date: Tue, 20 Sep 2022 12:46:00 +0200 Subject: [PATCH 2/2] Fix RTL hit testing after bidi mirror changes --- src/Avalonia.Base/Media/GlyphRun.cs | 7 +++++-- .../Media/TextFormatting/TextLayoutTests.cs | 5 ++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Base/Media/GlyphRun.cs b/src/Avalonia.Base/Media/GlyphRun.cs index cae7a8fe75..58edea95ea 100644 --- a/src/Avalonia.Base/Media/GlyphRun.cs +++ b/src/Avalonia.Base/Media/GlyphRun.cs @@ -361,7 +361,9 @@ namespace Avalonia.Media characterIndex = cluster; - if (currentX - advance < distance) + var offsetX = currentX - advance; + + if (offsetX < distance) { break; } @@ -375,7 +377,8 @@ namespace Avalonia.Media var characterHit = FindNearestCharacterHit(characterIndex, out var width); var delta = width / 2; - var offset = IsLeftToRight ? distance - currentX : currentX - distance; + + var offset = IsLeftToRight ? Math.Round(distance - currentX, 3) : Math.Round(currentX - distance, 3); var isTrailing = offset > delta; diff --git a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs index 43948e9229..e21986d3a2 100644 --- a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs +++ b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs @@ -1009,7 +1009,10 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting currentX += glyphAdvance; - cluster = clusters[j]; + if(glyphAdvance > 0) + { + cluster = clusters[j]; + } } } }