Browse Source

Fix some comments

pull/4260/head
Benedikt Schroeder 6 years ago
parent
commit
453222d8de
  1. 302
      src/Avalonia.Visuals/Media/TextFormatting/TextFormatterImpl.cs
  2. 5
      src/Avalonia.Visuals/Media/TextFormatting/TextLayout.cs
  3. 40
      src/Avalonia.Visuals/Media/TextFormatting/TextLine.cs
  4. 3
      src/Avalonia.Visuals/Media/TextFormatting/TextLineImpl.cs
  5. 7
      src/Avalonia.Visuals/Media/TextFormatting/TextRunProperties.cs

302
src/Avalonia.Visuals/Media/TextFormatting/TextFormatterImpl.cs

@ -41,6 +41,156 @@ namespace Avalonia.Media.TextFormatting
return textLine;
}
/// <summary>
/// Measures the number of characters that fits into available width.
/// </summary>
/// <param name="textCharacters">The text run.</param>
/// <param name="availableWidth">The available width.</param>
/// <returns></returns>
internal static int MeasureCharacters(ShapedTextCharacters textCharacters, double availableWidth)
{
var glyphRun = textCharacters.GlyphRun;
if (glyphRun.Bounds.Width < availableWidth)
{
return glyphRun.Characters.Length;
}
var glyphCount = 0;
var currentWidth = 0.0;
if (glyphRun.GlyphAdvances.IsEmpty)
{
var glyphTypeface = glyphRun.GlyphTypeface;
for (var i = 0; i < glyphRun.GlyphClusters.Length; i++)
{
var glyph = glyphRun.GlyphIndices[i];
var advance = glyphTypeface.GetGlyphAdvance(glyph) * glyphRun.Scale;
if (currentWidth + advance > availableWidth)
{
break;
}
currentWidth += advance;
glyphCount++;
}
}
else
{
foreach (var advance in glyphRun.GlyphAdvances)
{
if (currentWidth + advance > availableWidth)
{
break;
}
currentWidth += advance;
glyphCount++;
}
}
if (glyphCount == glyphRun.GlyphIndices.Length)
{
return glyphRun.Characters.Length;
}
if (glyphRun.GlyphClusters.IsEmpty)
{
return glyphCount;
}
var firstCluster = glyphRun.GlyphClusters[0];
var lastCluster = glyphRun.GlyphClusters[glyphCount];
return lastCluster - firstCluster;
}
/// <summary>
/// Split a sequence of runs into two segments at specified length.
/// </summary>
/// <param name="textRuns">The text run's.</param>
/// <param name="length">The length to split at.</param>
/// <returns>The split text runs.</returns>
internal static SplitTextRunsResult SplitTextRuns(IReadOnlyList<ShapedTextCharacters> textRuns, int length)
{
var currentLength = 0;
for (var i = 0; i < textRuns.Count; i++)
{
var currentRun = textRuns[i];
if (currentLength + currentRun.GlyphRun.Characters.Length < length)
{
currentLength += currentRun.GlyphRun.Characters.Length;
continue;
}
var firstCount = currentRun.GlyphRun.Characters.Length >= 1 ? i + 1 : i;
var first = new ShapedTextCharacters[firstCount];
if (firstCount > 1)
{
for (var j = 0; j < i; j++)
{
first[j] = textRuns[j];
}
}
var secondCount = textRuns.Count - firstCount;
if (currentLength + currentRun.GlyphRun.Characters.Length == length)
{
var second = new ShapedTextCharacters[secondCount];
var offset = currentRun.GlyphRun.Characters.Length > 1 ? 1 : 0;
if (secondCount > 0)
{
for (var j = 0; j < secondCount; j++)
{
second[j] = textRuns[i + j + offset];
}
}
first[i] = currentRun;
return new SplitTextRunsResult(first, second);
}
else
{
secondCount++;
var second = new ShapedTextCharacters[secondCount];
if (secondCount > 0)
{
for (var j = 1; j < secondCount; j++)
{
second[j] = textRuns[i + j];
}
}
var split = currentRun.Split(length - currentLength);
first[i] = split.First;
second[0] = split.Second;
return new SplitTextRunsResult(first, second);
}
}
return new SplitTextRunsResult(textRuns, null);
}
/// <summary>
/// Fetches text runs.
/// </summary>
@ -188,7 +338,7 @@ namespace Avalonia.Media.TextFormatting
if (currentWidth + currentRun.GlyphRun.Bounds.Width > availableWidth)
{
var measuredLength = MeasureText(currentRun, paragraphWidth - currentWidth);
var measuredLength = MeasureCharacters(currentRun, paragraphWidth - currentWidth);
var breakFound = false;
@ -256,77 +406,6 @@ namespace Avalonia.Media.TextFormatting
TextLineMetrics.Create(textRuns, textRange, paragraphWidth, paragraphProperties));
}
/// <summary>
/// Measures the number of characters that fits into available width.
/// </summary>
/// <param name="textCharacters">The text run.</param>
/// <param name="availableWidth">The available width.</param>
/// <returns></returns>
internal static int MeasureText(ShapedTextCharacters textCharacters, double availableWidth)
{
var glyphRun = textCharacters.GlyphRun;
if (glyphRun.Bounds.Width < availableWidth)
{
return glyphRun.Characters.Length;
}
var glyphCount = 0;
var currentWidth = 0.0;
if (glyphRun.GlyphAdvances.IsEmpty)
{
var glyphTypeface = glyphRun.GlyphTypeface;
for (var i = 0; i < glyphRun.GlyphClusters.Length; i++)
{
var glyph = glyphRun.GlyphIndices[i];
var advance = glyphTypeface.GetGlyphAdvance(glyph) * glyphRun.Scale;
if (currentWidth + advance > availableWidth)
{
break;
}
currentWidth += advance;
glyphCount++;
}
}
else
{
foreach (var advance in glyphRun.GlyphAdvances)
{
if (currentWidth + advance > availableWidth)
{
break;
}
currentWidth += advance;
glyphCount++;
}
}
if (glyphCount == glyphRun.GlyphIndices.Length)
{
return glyphRun.Characters.Length;
}
if (glyphRun.GlyphClusters.IsEmpty)
{
return glyphCount;
}
var firstCluster = glyphRun.GlyphClusters[0];
var lastCluster = glyphRun.GlyphClusters[glyphCount];
return lastCluster - firstCluster;
}
/// <summary>
/// Gets the text range that is covered by the text runs.
/// </summary>
@ -353,85 +432,6 @@ namespace Avalonia.Media.TextFormatting
return new TextRange(start, end - start);
}
/// <summary>
/// Split a sequence of runs into two segments at specified length.
/// </summary>
/// <param name="textRuns">The text run's.</param>
/// <param name="length">The length to split at.</param>
/// <returns>The split text runs.</returns>
internal static SplitTextRunsResult SplitTextRuns(IReadOnlyList<ShapedTextCharacters> textRuns, int length)
{
var currentLength = 0;
for (var i = 0; i < textRuns.Count; i++)
{
var currentRun = textRuns[i];
if (currentLength + currentRun.GlyphRun.Characters.Length < length)
{
currentLength += currentRun.GlyphRun.Characters.Length;
continue;
}
var firstCount = currentRun.GlyphRun.Characters.Length >= 1 ? i + 1 : i;
var first = new ShapedTextCharacters[firstCount];
if (firstCount > 1)
{
for (var j = 0; j < i; j++)
{
first[j] = textRuns[j];
}
}
var secondCount = textRuns.Count - firstCount;
if (currentLength + currentRun.GlyphRun.Characters.Length == length)
{
var second = new ShapedTextCharacters[secondCount];
var offset = currentRun.GlyphRun.Characters.Length > 1 ? 1 : 0;
if (secondCount > 0)
{
for (var j = 0; j < secondCount; j++)
{
second[j] = textRuns[i + j + offset];
}
}
first[i] = currentRun;
return new SplitTextRunsResult(first, second);
}
else
{
secondCount++;
var second = new ShapedTextCharacters[secondCount];
if (secondCount > 0)
{
for (var j = 1; j < secondCount; j++)
{
second[j] = textRuns[i + j];
}
}
var split = currentRun.Split(length - currentLength);
first[i] = split.First;
second[0] = split.Second;
return new SplitTextRunsResult(first, second);
}
}
return new SplitTextRunsResult(textRuns, null);
}
internal readonly struct SplitTextRunsResult
{
public SplitTextRunsResult(IReadOnlyList<ShapedTextCharacters> first, IReadOnlyList<ShapedTextCharacters> second)

5
src/Avalonia.Visuals/Media/TextFormatting/TextLayout.cs

@ -268,6 +268,11 @@ namespace Avalonia.Media.TextFormatting
}
}
/// <summary>
/// Gets the <see cref="TextCollapsingProperties"/> for current text trimming mode.
/// </summary>
/// <param name="width">The collapsing width.</param>
/// <returns>The <see cref="TextCollapsingProperties"/>.</returns>
private TextCollapsingProperties GetCollapsingProperties(double width)
{
return _textTrimming switch

40
src/Avalonia.Visuals/Media/TextFormatting/TextLine.cs

@ -40,8 +40,11 @@ namespace Avalonia.Media.TextFormatting
public abstract TextLineBreak LineBreak { get; }
/// <summary>
/// Client to get a boolean value indicates whether a line has been collapsed
/// Gets a value that indicates whether the line is collapsed.
/// </summary>
/// <returns>
/// <c>true</c>, if the line is collapsed; otherwise, <c>false</c>.
/// </returns>
public abstract bool HasCollapsed { get; }
/// <summary>
@ -52,46 +55,49 @@ namespace Avalonia.Media.TextFormatting
public abstract void Draw(DrawingContext drawingContext, Point origin);
/// <summary>
/// Client to collapse the line and get a collapsed line that fits for display
/// Create a collapsed line based on collapsed text properties.
/// </summary>
/// <param name="collapsingPropertiesList">a list of collapsing properties</param>
/// <param name="collapsingPropertiesList">A list of <see cref="TextCollapsingProperties"/>
/// objects that represent the collapsed text properties.</param>
/// <returns>
/// A <see cref="TextLine"/> value that represents a collapsed line that can be displayed.
/// </returns>
public abstract TextLine Collapse(params TextCollapsingProperties[] collapsingPropertiesList);
/// <summary>
/// Client to get the character hit corresponding to the specified
/// distance from the beginning of the line.
/// Gets the character hit corresponding to the specified distance from the beginning of the line.
/// </summary>
/// <param name="distance">distance in text flow direction from the beginning of the line</param>
/// <returns>The <see cref="CharacterHit"/></returns>
/// <param name="distance">A <see cref="double"/> value that represents the distance from the beginning of the line.</param>
/// <returns>The <see cref="CharacterHit"/> object at the specified distance from the beginning of the line.</returns>
public abstract CharacterHit GetCharacterHitFromDistance(double distance);
/// <summary>
/// Client to get the distance from the beginning of the line from the specified
/// Gets the distance from the beginning of the line to the specified character hit.
/// <see cref="CharacterHit"/>.
/// </summary>
/// <param name="characterHit"><see cref="CharacterHit"/> of the character to query the distance.</param>
/// <returns>Distance in text flow direction from the beginning of the line.</returns>
/// <param name="characterHit">The <see cref="CharacterHit"/> object whose distance you want to query.</param>
/// <returns>A <see cref="double"/> that represents the distance from the beginning of the line.</returns>
public abstract double GetDistanceFromCharacterHit(CharacterHit characterHit);
/// <summary>
/// Client to get the next <see cref="CharacterHit"/> for caret navigation.
/// Gets the next character hit for caret navigation.
/// </summary>
/// <param name="characterHit">The current <see cref="CharacterHit"/>.</param>
/// <returns>The next <see cref="CharacterHit"/>.</returns>
public abstract CharacterHit GetNextCaretCharacterHit(CharacterHit characterHit);
/// <summary>
/// Client to get the previous character hit for caret navigation
/// Gets the previous character hit for caret navigation.
/// </summary>
/// <param name="characterHit">the current character hit</param>
/// <returns>The previous <see cref="CharacterHit"/></returns>
/// <param name="characterHit">The current <see cref="CharacterHit"/>.</param>
/// <returns>The previous <see cref="CharacterHit"/>.</returns>
public abstract CharacterHit GetPreviousCaretCharacterHit(CharacterHit characterHit);
/// <summary>
/// Client to get the previous character hit after backspacing
/// Gets the previous character hit after backspacing.
/// </summary>
/// <param name="characterHit">the current character hit</param>
/// <returns>The <see cref="CharacterHit"/> after backspacing</returns>
/// <param name="characterHit">The current <see cref="CharacterHit"/>.</param>
/// <returns>The <see cref="CharacterHit"/> after backspacing.</returns>
public abstract CharacterHit GetBackspaceCaretCharacterHit(CharacterHit characterHit);
/// <summary>

3
src/Avalonia.Visuals/Media/TextFormatting/TextLineImpl.cs

@ -47,6 +47,7 @@ namespace Avalonia.Media.TextFormatting
}
}
/// <inheritdoc/>
public override TextLine Collapse(params TextCollapsingProperties[] collapsingPropertiesList)
{
if (collapsingPropertiesList == null || collapsingPropertiesList.Length == 0)
@ -73,7 +74,7 @@ namespace Avalonia.Media.TextFormatting
if (currentWidth > availableWidth)
{
var measuredLength = TextFormatterImpl.MeasureText(currentRun, availableWidth);
var measuredLength = TextFormatterImpl.MeasureCharacters(currentRun, availableWidth);
var currentBreakPosition = 0;

7
src/Avalonia.Visuals/Media/TextFormatting/TextRunProperties.cs

@ -4,12 +4,11 @@ using System.Globalization;
namespace Avalonia.Media.TextFormatting
{
/// <summary>
/// Properties that can change from one run to the next, such as typeface or foreground brush.
/// Provides a set of properties, such as typeface or foreground brush, that can be applied to a TextRun object. This is an abstract class.
/// </summary>
/// <remarks>
/// The client provides a concrete implementation of this abstract run properties class. This
/// allows client to implement their run properties the way that fits with their run formatting
/// store.
/// The text layout client provides a concrete implementation of this abstract class.
/// This enables the client to implement text run properties in a way that corresponds with the associated formatting store.
/// </remarks>
public abstract class TextRunProperties : IEquatable<TextRunProperties>
{

Loading…
Cancel
Save