diff --git a/src/Avalonia.Base/Media/TextFormatting/ShapedTextRun.cs b/src/Avalonia.Base/Media/TextFormatting/ShapedTextRun.cs
index 5bb8ad5b958..f01de9cc9ef 100644
--- a/src/Avalonia.Base/Media/TextFormatting/ShapedTextRun.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/ShapedTextRun.cs
@@ -98,7 +98,7 @@ internal void Reverse()
///
/// true if characters fit into the available width; otherwise, false.
///
- internal bool TryMeasureCharacters(double availableWidth, out int length)
+ public bool TryMeasureCharacters(double availableWidth, out int length)
{
length = 0;
var currentWidth = 0.0;
diff --git a/src/Avalonia.Base/Media/TextFormatting/TextCollapsingProperties.cs b/src/Avalonia.Base/Media/TextFormatting/TextCollapsingProperties.cs
index 7cdf81ecc9a..e1d92534157 100644
--- a/src/Avalonia.Base/Media/TextFormatting/TextCollapsingProperties.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/TextCollapsingProperties.cs
@@ -27,5 +27,56 @@ public abstract class TextCollapsingProperties
///
/// Text line to collapse.
public abstract TextRun[]? Collapse(TextLine textLine);
+
+ ///
+ /// Creates a list of runs for given collapsed length which includes specified symbol at the end.
+ ///
+ /// The text line.
+ /// The collapsed length.
+ /// The flow direction.
+ /// The symbol.
+ /// List of remaining runs.
+ public static TextRun[] CreateCollapsedRuns(TextLine textLine, int collapsedLength,
+ FlowDirection flowDirection, TextRun shapedSymbol)
+ {
+ var textRuns = textLine.TextRuns;
+
+ if (collapsedLength <= 0)
+ {
+ return new[] { shapedSymbol };
+ }
+
+ if (flowDirection == FlowDirection.RightToLeft)
+ {
+ collapsedLength = textLine.Length - collapsedLength;
+ }
+
+ var objectPool = FormattingObjectPool.Instance;
+
+ var (preSplitRuns, postSplitRuns) = TextFormatterImpl.SplitTextRuns(textRuns, collapsedLength, objectPool);
+
+ try
+ {
+ if (flowDirection == FlowDirection.RightToLeft)
+ {
+ var collapsedRuns = new TextRun[postSplitRuns!.Count + 1];
+ postSplitRuns.CopyTo(collapsedRuns, 1);
+ collapsedRuns[0] = shapedSymbol;
+ return collapsedRuns;
+ }
+ else
+ {
+ var collapsedRuns = new TextRun[preSplitRuns!.Count + 1];
+ preSplitRuns.CopyTo(collapsedRuns);
+ collapsedRuns[collapsedRuns.Length - 1] = shapedSymbol;
+ return collapsedRuns;
+ }
+ }
+ finally
+ {
+ objectPool.TextRunLists.Return(ref preSplitRuns);
+ objectPool.TextRunLists.Return(ref postSplitRuns);
+ }
+ }
}
}
diff --git a/src/Avalonia.Base/Media/TextFormatting/TextEllipsisHelper.cs b/src/Avalonia.Base/Media/TextFormatting/TextEllipsisHelper.cs
index 8b6d576c6ec..fb01afa33d0 100644
--- a/src/Avalonia.Base/Media/TextFormatting/TextEllipsisHelper.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/TextEllipsisHelper.cs
@@ -1,5 +1,4 @@
-using System;
-using Avalonia.Media.TextFormatting.Unicode;
+using Avalonia.Media.TextFormatting.Unicode;
namespace Avalonia.Media.TextFormatting
{
@@ -17,12 +16,12 @@ internal static class TextEllipsisHelper
var runIndex = 0;
var currentWidth = 0.0;
var collapsedLength = 0;
- var shapedSymbol = TextFormatterImpl.CreateSymbol(properties.Symbol, FlowDirection.LeftToRight);
+ var shapedSymbol = TextFormatter.CreateSymbol(properties.Symbol, FlowDirection.LeftToRight);
if (properties.Width < shapedSymbol.GlyphRun.Bounds.Width)
{
//Not enough space to fit in the symbol
- return Array.Empty();
+ return [];
}
var availableWidth = properties.Width - shapedSymbol.Size.Width;
@@ -72,7 +71,7 @@ internal static class TextEllipsisHelper
collapsedLength += measuredLength;
- return CreateCollapsedRuns(textLine, collapsedLength, FlowDirection.LeftToRight, shapedSymbol);
+ return TextCollapsingProperties.CreateCollapsedRuns(textLine, collapsedLength, FlowDirection.LeftToRight, shapedSymbol);
}
availableWidth -= shapedRun.Size.Width;
@@ -85,7 +84,7 @@ internal static class TextEllipsisHelper
//The whole run needs to fit into available space
if (currentWidth + drawableRun.Size.Width > availableWidth)
{
- return CreateCollapsedRuns(textLine, collapsedLength, FlowDirection.LeftToRight, shapedSymbol);
+ return TextCollapsingProperties.CreateCollapsedRuns(textLine, collapsedLength, FlowDirection.LeftToRight, shapedSymbol);
}
availableWidth -= drawableRun.Size.Width;
@@ -146,7 +145,7 @@ internal static class TextEllipsisHelper
collapsedLength += measuredLength;
- return CreateCollapsedRuns(textLine, collapsedLength, FlowDirection.RightToLeft, shapedSymbol);
+ return TextCollapsingProperties.CreateCollapsedRuns(textLine, collapsedLength, FlowDirection.RightToLeft, shapedSymbol);
}
availableWidth -= shapedRun.Size.Width;
@@ -159,7 +158,7 @@ internal static class TextEllipsisHelper
//The whole run needs to fit into available space
if (currentWidth + drawableRun.Size.Width > availableWidth)
{
- return CreateCollapsedRuns(textLine, collapsedLength, FlowDirection.RightToLeft, shapedSymbol);
+ return TextCollapsingProperties.CreateCollapsedRuns(textLine, collapsedLength, FlowDirection.RightToLeft, shapedSymbol);
}
availableWidth -= drawableRun.Size.Width;
@@ -176,48 +175,5 @@ internal static class TextEllipsisHelper
return null;
}
-
- private static TextRun[] CreateCollapsedRuns(TextLine textLine, int collapsedLength,
- FlowDirection flowDirection, TextRun shapedSymbol)
- {
- var textRuns = textLine.TextRuns;
-
- if (collapsedLength <= 0)
- {
- return new[] { shapedSymbol };
- }
-
- if(flowDirection == FlowDirection.RightToLeft)
- {
- collapsedLength = textLine.Length - collapsedLength;
- }
-
- var objectPool = FormattingObjectPool.Instance;
-
- var (preSplitRuns, postSplitRuns) = TextFormatterImpl.SplitTextRuns(textRuns, collapsedLength, objectPool);
-
- try
- {
- if (flowDirection == FlowDirection.RightToLeft)
- {
- var collapsedRuns = new TextRun[postSplitRuns!.Count + 1];
- postSplitRuns.CopyTo(collapsedRuns, 1);
- collapsedRuns[0] = shapedSymbol;
- return collapsedRuns;
- }
- else
- {
- var collapsedRuns = new TextRun[preSplitRuns!.Count + 1];
- preSplitRuns.CopyTo(collapsedRuns);
- collapsedRuns[collapsedRuns.Length - 1] = shapedSymbol;
- return collapsedRuns;
- }
- }
- finally
- {
- objectPool.TextRunLists.Return(ref preSplitRuns);
- objectPool.TextRunLists.Return(ref postSplitRuns);
- }
- }
}
}
diff --git a/src/Avalonia.Base/Media/TextFormatting/TextFormatter.cs b/src/Avalonia.Base/Media/TextFormatting/TextFormatter.cs
index ff8c1c48609..1dbf55fb97a 100644
--- a/src/Avalonia.Base/Media/TextFormatting/TextFormatter.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/TextFormatter.cs
@@ -40,5 +40,31 @@ public static TextFormatter Current
/// The formatted line.
public abstract TextLine? FormatLine(ITextSource textSource, int firstTextSourceIndex, double paragraphWidth,
TextParagraphProperties paragraphProperties, TextLineBreak? previousLineBreak = null);
+
+ ///
+ /// Creates a shaped symbol.
+ ///
+ /// The symbol run to shape.
+ /// The flow direction.
+ ///
+ /// The shaped symbol.
+ ///
+ public static ShapedTextRun CreateSymbol(TextRun textRun, FlowDirection flowDirection)
+ {
+ var textShaper = TextShaper.Current;
+
+ var glyphTypeface = textRun.Properties!.CachedGlyphTypeface;
+
+ var fontRenderingEmSize = textRun.Properties.FontRenderingEmSize;
+
+ var cultureInfo = textRun.Properties.CultureInfo;
+
+ var shaperOptions = new TextShaperOptions(glyphTypeface, textRun.Properties.FontFeatures,
+ fontRenderingEmSize, (sbyte)flowDirection, cultureInfo);
+
+ var shapedBuffer = textShaper.ShapeText(textRun.Text, shaperOptions);
+
+ return new ShapedTextRun(shapedBuffer, textRun.Properties);
+ }
}
}
diff --git a/src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs b/src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs
index 5aeff0fba24..8e2325fb145 100644
--- a/src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs
@@ -957,31 +957,5 @@ public bool MoveNext()
return true;
}
}
-
- ///
- /// Creates a shaped symbol.
- ///
- /// The symbol run to shape.
- /// The flow direction.
- ///
- /// The shaped symbol.
- ///
- internal static ShapedTextRun CreateSymbol(TextRun textRun, FlowDirection flowDirection)
- {
- var textShaper = TextShaper.Current;
-
- var glyphTypeface = textRun.Properties!.CachedGlyphTypeface;
-
- var fontRenderingEmSize = textRun.Properties.FontRenderingEmSize;
-
- var cultureInfo = textRun.Properties.CultureInfo;
-
- var shaperOptions = new TextShaperOptions(glyphTypeface, textRun.Properties.FontFeatures,
- fontRenderingEmSize, (sbyte)flowDirection, cultureInfo);
-
- var shapedBuffer = textShaper.ShapeText(textRun.Text, shaperOptions);
-
- return new ShapedTextRun(shapedBuffer, textRun.Properties);
- }
}
}