Sfoglia il codice sorgente

[Text] Optimize grapheme and add performance benchmark

Sergey Mikolaitis 2 anni fa
parent
commit
84206e93dd

+ 1 - 1
src/Avalonia.Base/Media/TextFormatting/FormattedTextSource.cs

@@ -132,7 +132,7 @@ namespace Avalonia.Media.TextFormatting
             {
                 var grapheme = graphemeEnumerator.Current;
 
-                finalLength += grapheme.Text.Length;
+                finalLength += grapheme.Length;
 
                 if (finalLength >= length)
                 {

+ 2 - 2
src/Avalonia.Base/Media/TextFormatting/TextCharacters.cs

@@ -196,7 +196,7 @@ namespace Avalonia.Media.TextFormatting
                     break;
                 }
 
-                count += grapheme.Text.Length;
+                count += grapheme.Length;
             }
 
             return new UnshapedTextRun(characterBufferRange.CharacterBufferReference, count, defaultProperties, biDiLevel);
@@ -264,7 +264,7 @@ namespace Avalonia.Media.TextFormatting
                     }
                 }
 
-                length += currentGrapheme.Text.Length;
+                length += currentGrapheme.Length;
             }
 
             return length > 0;

+ 10 - 4
src/Avalonia.Base/Media/TextFormatting/Unicode/Grapheme.cs

@@ -7,10 +7,11 @@ namespace Avalonia.Media.TextFormatting.Unicode
     /// </summary>
     public readonly ref struct Grapheme
     {
-        public Grapheme(Codepoint firstCodepoint, ReadOnlySpan<char> text)
+        public Grapheme(Codepoint firstCodepoint, int offset, int length)
         {
             FirstCodepoint = firstCodepoint;
-            Text = text;
+            Offset = offset;
+            Length = length;
         }
 
         /// <summary>
@@ -19,8 +20,13 @@ namespace Avalonia.Media.TextFormatting.Unicode
         public Codepoint FirstCodepoint { get; }
 
         /// <summary>
-        /// The text that is representing the <see cref="Grapheme"/>.
+        /// The Offset to the FirstCodepoint
         /// </summary>
-        public ReadOnlySpan<char> Text { get; }
+        public int Offset { get; }
+
+        /// <summary>
+        /// The length of the grapheme cluster
+        /// </summary>
+        public int Length { get; }
     }
 }

+ 1 - 3
src/Avalonia.Base/Media/TextFormatting/Unicode/GraphemeEnumerator.cs

@@ -185,9 +185,7 @@ namespace Avalonia.Media.TextFormatting.Unicode
 
             Return:
 
-            var text = _text.Take(processor.CurrentCodeUnitOffset);
-
-            Current = new Grapheme(firstCodepoint, text.Span);
+            Current = new Grapheme(firstCodepoint, _text.OffsetToFirstChar, processor.CurrentCodeUnitOffset);
 
             _text = _text.Skip(processor.CurrentCodeUnitOffset);
 

+ 1 - 1
src/Avalonia.Controls/TextBox.cs

@@ -981,7 +981,7 @@ namespace Avalonia.Controls
                         }
                     }
 
-                    length += grapheme.Text.Length;
+                    length += grapheme.Length;
                 }
 
                 if (length < input.Length)

+ 2 - 2
tests/Avalonia.Base.UnitTests/Media/TextFormatting/GraphemeBreakClassTrieGeneratorTests.cs

@@ -42,7 +42,7 @@ namespace Avalonia.Base.UnitTests.Media.TextFormatting
 
             enumerator.MoveNext();
 
-            var actual = enumerator.Current.Text;
+            var actual = text.AsSpan(enumerator.Current.Offset, enumerator.Current.Length);
 
             var pass = true;
 
@@ -93,7 +93,7 @@ namespace Avalonia.Base.UnitTests.Media.TextFormatting
 
             while (enumerator.MoveNext())
             {
-                Assert.Equal(1, enumerator.Current.Text.Length);
+                Assert.Equal(1, enumerator.Current.Length);
 
                 count++;
             }

File diff suppressed because it is too large
+ 38 - 0
tests/Avalonia.Benchmarks/Text/HugeTextLayout.cs


+ 4 - 4
tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs

@@ -153,7 +153,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
                 {
                     while (inner.MoveNext())
                     {
-                        j += inner.Current.Text.Length;
+                        j += inner.Current.Length;
 
                         if (j + i > text.Length)
                         {
@@ -192,7 +192,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
 
                     inner = new GraphemeEnumerator(new CharacterBufferRange(text));
 
-                    i += outer.Current.Text.Length;
+                    i += outer.Current.Length;
                 }
             }
         }
@@ -974,9 +974,9 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
                 {
                     var grapheme = graphemeEnumerator.Current;
 
-                    var textStyleOverrides = new[] { new ValueSpan<TextRunProperties>(i, grapheme.Text.Length, new GenericTextRunProperties(Typeface.Default, 12, foregroundBrush: Brushes.Red)) };
+                    var textStyleOverrides = new[] { new ValueSpan<TextRunProperties>(i, grapheme.Length, new GenericTextRunProperties(Typeface.Default, 12, foregroundBrush: Brushes.Red)) };
 
-                    i += grapheme.Text.Length;
+                    i += grapheme.Length;
 
                     var layout = new TextLayout(
                         text,

Some files were not shown because too many files changed in this diff