Browse Source

Merge pull request #10530 from Gillibald/fixes/glyphRunNodeBounds

Introduce GlyphRun.Bounds
pull/10370/head
Nikita Tsukanov 4 years ago
committed by GitHub
parent
commit
8b22bf7eb3
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      src/Avalonia.Base/Media/GlyphRun.cs
  2. 2
      src/Avalonia.Base/Media/GlyphRunDrawing.cs
  3. 2
      src/Avalonia.Base/Media/TextDecoration.cs
  4. 4
      src/Avalonia.Base/Media/TextFormatting/ShapedTextRun.cs
  5. 2
      src/Avalonia.Base/Media/TextFormatting/TextEllipsisHelper.cs
  6. 2
      src/Avalonia.Base/Media/TextFormatting/TextLeadingPrefixCharacterEllipsis.cs
  7. 6
      src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs
  8. 3
      src/Avalonia.Base/Platform/IGlyphRunImpl.cs
  9. 8
      src/Avalonia.Base/Rendering/Composition/Server/DiagnosticTextRenderer.cs
  10. 5
      src/Avalonia.Base/Rendering/SceneGraph/GlyphRunNode.cs
  11. 4
      src/Avalonia.Headless/HeadlessPlatformRenderInterface.cs
  12. 2
      src/Skia/Avalonia.Skia/DrawingContextImpl.cs
  13. 4
      src/Skia/Avalonia.Skia/GlyphRunImpl.cs
  14. 2
      src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
  15. 4
      src/Windows/Avalonia.Direct2D1/Media/GlyphRunImpl.cs
  16. 2
      tests/Avalonia.Benchmarks/NullGlyphRun.cs
  17. 6
      tests/Avalonia.Skia.UnitTests/Media/GlyphRunTests.cs
  18. 2
      tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs
  19. 4
      tests/Avalonia.UnitTests/MockGlyphRun.cs

14
src/Avalonia.Base/Media/GlyphRun.cs

@ -151,9 +151,9 @@ namespace Avalonia.Media
} }
/// <summary> /// <summary>
/// Gets or sets the conservative bounding box of the <see cref="GlyphRun"/>. /// Gets the conservative bounding box of the <see cref="GlyphRun"/>.
/// </summary> /// </summary>
public Size Size => PlatformImpl.Item.Size; public Rect Bounds => PlatformImpl.Item.Bounds;
/// <summary> /// <summary>
/// ///
@ -252,7 +252,7 @@ namespace Avalonia.Media
if (characterIndex > Metrics.LastCluster) if (characterIndex > Metrics.LastCluster)
{ {
return Size.Width; return Bounds.Width;
} }
var glyphIndex = FindGlyphIndex(characterIndex); var glyphIndex = FindGlyphIndex(characterIndex);
@ -287,7 +287,7 @@ namespace Avalonia.Media
if (characterIndex <= Metrics.FirstCluster) if (characterIndex <= Metrics.FirstCluster)
{ {
return Size.Width; return Bounds.Width;
} }
for (var i = glyphIndex + 1; i < _glyphInfos.Count; i++) for (var i = glyphIndex + 1; i < _glyphInfos.Count; i++)
@ -295,7 +295,7 @@ namespace Avalonia.Media
distance += _glyphInfos[i].GlyphAdvance; distance += _glyphInfos[i].GlyphAdvance;
} }
return Size.Width - distance; return Bounds.Width - distance;
} }
} }
@ -321,7 +321,7 @@ namespace Avalonia.Media
} }
//After //After
if (distance >= Size.Width) if (distance >= Bounds.Width)
{ {
isInside = false; isInside = false;
@ -354,7 +354,7 @@ namespace Avalonia.Media
} }
else else
{ {
currentX = Size.Width; currentX = Bounds.Width;
for (var index = _glyphInfos.Count - 1; index >= 0; index--) for (var index = _glyphInfos.Count - 1; index >= 0; index--)
{ {

2
src/Avalonia.Base/Media/GlyphRunDrawing.cs

@ -32,7 +32,7 @@
public override Rect GetBounds() public override Rect GetBounds()
{ {
return GlyphRun != null ? new Rect(GlyphRun.Size) : default; return GlyphRun != null ? GlyphRun.Bounds : default;
} }
} }
} }

2
src/Avalonia.Base/Media/TextDecoration.cs

@ -223,7 +223,7 @@ namespace Avalonia.Media
if (intersections.Count > 0) if (intersections.Count > 0)
{ {
var last = baselineOrigin.X; var last = baselineOrigin.X;
var finalPos = last + glyphRun.Size.Width; var finalPos = last + glyphRun.Bounds.Width;
var end = last; var end = last;
var points = new List<double>(); var points = new List<double>();

4
src/Avalonia.Base/Media/TextFormatting/ShapedTextRun.cs

@ -38,14 +38,14 @@ namespace Avalonia.Media.TextFormatting
public override double Baseline => -TextMetrics.Ascent; public override double Baseline => -TextMetrics.Ascent;
public override Size Size => GlyphRun.Size; public override Size Size => GlyphRun.Bounds.Size;
public GlyphRun GlyphRun => _glyphRun ??= CreateGlyphRun(); public GlyphRun GlyphRun => _glyphRun ??= CreateGlyphRun();
/// <inheritdoc/> /// <inheritdoc/>
public override void Draw(DrawingContext drawingContext, Point origin) public override void Draw(DrawingContext drawingContext, Point origin)
{ {
using (drawingContext.PushPreTransform(Matrix.CreateTranslation(origin))) using (drawingContext.PushTransform(Matrix.CreateTranslation(origin)))
{ {
if (GlyphRun.GlyphInfos.Count == 0) if (GlyphRun.GlyphInfos.Count == 0)
{ {

2
src/Avalonia.Base/Media/TextFormatting/TextEllipsisHelper.cs

@ -19,7 +19,7 @@ namespace Avalonia.Media.TextFormatting
var collapsedLength = 0; var collapsedLength = 0;
var shapedSymbol = TextFormatterImpl.CreateSymbol(properties.Symbol, FlowDirection.LeftToRight); var shapedSymbol = TextFormatterImpl.CreateSymbol(properties.Symbol, FlowDirection.LeftToRight);
if (properties.Width < shapedSymbol.GlyphRun.Size.Width) if (properties.Width < shapedSymbol.GlyphRun.Bounds.Width)
{ {
//Not enough space to fit in the symbol //Not enough space to fit in the symbol
return Array.Empty<TextRun>(); return Array.Empty<TextRun>();

2
src/Avalonia.Base/Media/TextFormatting/TextLeadingPrefixCharacterEllipsis.cs

@ -60,7 +60,7 @@ namespace Avalonia.Media.TextFormatting
var currentWidth = 0.0; var currentWidth = 0.0;
var shapedSymbol = TextFormatterImpl.CreateSymbol(Symbol, FlowDirection.LeftToRight); var shapedSymbol = TextFormatterImpl.CreateSymbol(Symbol, FlowDirection.LeftToRight);
if (Width < shapedSymbol.GlyphRun.Size.Width) if (Width < shapedSymbol.GlyphRun.Bounds.Width)
{ {
return Array.Empty<TextRun>(); return Array.Empty<TextRun>();
} }

6
src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs

@ -423,7 +423,7 @@ namespace Avalonia.Media.TextFormatting
{ {
if (currentGlyphRun != null) if (currentGlyphRun != null)
{ {
currentDistance -= currentGlyphRun.Size.Width; currentDistance -= currentGlyphRun.Bounds.Width;
} }
return currentDistance + distance; return currentDistance + distance;
@ -477,7 +477,7 @@ namespace Avalonia.Media.TextFormatting
{ {
if (currentGlyphRun.IsLeftToRight || flowDirection == FlowDirection.RightToLeft) if (currentGlyphRun.IsLeftToRight || flowDirection == FlowDirection.RightToLeft)
{ {
distance = currentGlyphRun.Size.Width; distance = currentGlyphRun.Bounds.Width;
} }
return true; return true;
@ -1483,7 +1483,7 @@ namespace Avalonia.Media.TextFormatting
trailingWhitespaceLength += glyphRunMetrics.TrailingWhitespaceLength; trailingWhitespaceLength += glyphRunMetrics.TrailingWhitespaceLength;
var whitespaceWidth = glyphRun.Size.Width - glyphRunMetrics.Width; var whitespaceWidth = glyphRun.Bounds.Width - glyphRunMetrics.Width;
width -= whitespaceWidth; width -= whitespaceWidth;
} }

3
src/Avalonia.Base/Platform/IGlyphRunImpl.cs

@ -10,11 +10,10 @@ namespace Avalonia.Platform
[Unstable] [Unstable]
public interface IGlyphRunImpl : IDisposable public interface IGlyphRunImpl : IDisposable
{ {
/// <summary> /// <summary>
/// Gets the conservative bounding box of the glyph run./>. /// Gets the conservative bounding box of the glyph run./>.
/// </summary> /// </summary>
Size Size { get; } Rect Bounds { get; }
/// <summary> /// <summary>
/// Gets the baseline origin of the glyph run./>. /// Gets the baseline origin of the glyph run./>.

8
src/Avalonia.Base/Rendering/Composition/Server/DiagnosticTextRenderer.cs

@ -20,7 +20,7 @@ namespace Avalonia.Rendering.Composition.Server
for (var c = FirstChar; c <= LastChar; c++) for (var c = FirstChar; c <= LastChar; c++)
{ {
var height = _runs[c - FirstChar].Size.Height; var height = _runs[c - FirstChar].Bounds.Height;
if (height > maxHeight) if (height > maxHeight)
{ {
maxHeight = height; maxHeight = height;
@ -51,8 +51,8 @@ namespace Avalonia.Rendering.Composition.Server
{ {
var effectiveChar = c is >= FirstChar and <= LastChar ? c : ' '; var effectiveChar = c is >= FirstChar and <= LastChar ? c : ' ';
var run = _runs[effectiveChar - FirstChar]; var run = _runs[effectiveChar - FirstChar];
width += run.Size.Width; width += run.Bounds.Width;
height = Math.Max(height, run.Size.Height); height = Math.Max(height, run.Bounds.Height);
} }
return new Size(width, height); return new Size(width, height);
@ -69,7 +69,7 @@ namespace Avalonia.Rendering.Composition.Server
var run = _runs[effectiveChar - FirstChar]; var run = _runs[effectiveChar - FirstChar];
context.Transform = originalTransform * Matrix.CreateTranslation(offset, 0.0); context.Transform = originalTransform * Matrix.CreateTranslation(offset, 0.0);
context.DrawGlyphRun(foreground, run.PlatformImpl); context.DrawGlyphRun(foreground, run.PlatformImpl);
offset += run.Size.Width; offset += run.Bounds.Width;
} }
context.Transform = originalTransform; context.Transform = originalTransform;

5
src/Avalonia.Base/Rendering/SceneGraph/GlyphRunNode.cs

@ -16,12 +16,11 @@ namespace Avalonia.Rendering.SceneGraph
/// <param name="transform">The transform.</param> /// <param name="transform">The transform.</param>
/// <param name="foreground">The foreground brush.</param> /// <param name="foreground">The foreground brush.</param>
/// <param name="glyphRun">The glyph run to draw.</param> /// <param name="glyphRun">The glyph run to draw.</param>
/// <param name="aux">Auxiliary data required to draw the brush.</param>
public GlyphRunNode( public GlyphRunNode(
Matrix transform, Matrix transform,
IImmutableBrush foreground, IImmutableBrush foreground,
IRef<IGlyphRunImpl> glyphRun) IRef<IGlyphRunImpl> glyphRun)
: base(new Rect(glyphRun.Item.BaselineOrigin, glyphRun.Item.Size), transform, foreground) : base(glyphRun.Item.Bounds, transform, foreground)
{ {
GlyphRun = glyphRun.Clone(); GlyphRun = glyphRun.Clone();
} }
@ -54,7 +53,7 @@ namespace Avalonia.Rendering.SceneGraph
} }
/// <inheritdoc/> /// <inheritdoc/>
public override bool HitTest(Point p) => new Rect(GlyphRun.Item.Size).ContainsExclusive(p); public override bool HitTest(Point p) => GlyphRun.Item.Bounds.ContainsExclusive(p);
public override void Dispose() public override void Dispose()
{ {

4
src/Avalonia.Headless/HeadlessPlatformRenderInterface.cs

@ -118,7 +118,7 @@ namespace Avalonia.Headless
public IGeometryImpl BuildGlyphRunGeometry(GlyphRun glyphRun) public IGeometryImpl BuildGlyphRunGeometry(GlyphRun glyphRun)
{ {
return new HeadlessGeometryStub(new Rect(glyphRun.Size)); return new HeadlessGeometryStub(glyphRun.Bounds);
} }
public IGlyphRunImpl CreateGlyphRun( public IGlyphRunImpl CreateGlyphRun(
@ -132,7 +132,7 @@ namespace Avalonia.Headless
class HeadlessGlyphRunStub : IGlyphRunImpl class HeadlessGlyphRunStub : IGlyphRunImpl
{ {
public Size Size => new Size(8, 12); public Rect Bounds => new Rect(new Size(8, 12));
public Point BaselineOrigin => new Point(0, 8); public Point BaselineOrigin => new Point(0, 8);

2
src/Skia/Avalonia.Skia/DrawingContextImpl.cs

@ -516,7 +516,7 @@ namespace Avalonia.Skia
return; return;
} }
using (var paintWrapper = CreatePaint(_fillPaint, foreground, glyphRun.Item.Size)) using (var paintWrapper = CreatePaint(_fillPaint, foreground, glyphRun.Item.Bounds.Size))
{ {
var glyphRunImpl = (GlyphRunImpl)glyphRun.Item; var glyphRunImpl = (GlyphRunImpl)glyphRun.Item;

4
src/Skia/Avalonia.Skia/GlyphRunImpl.cs

@ -11,7 +11,7 @@ namespace Avalonia.Skia
{ {
TextBlob = textBlob ?? throw new ArgumentNullException(nameof(textBlob)); TextBlob = textBlob ?? throw new ArgumentNullException(nameof(textBlob));
Size = size; Bounds = new Rect(new Point(baselineOrigin.X, 0), size);
BaselineOrigin = baselineOrigin; BaselineOrigin = baselineOrigin;
} }
@ -21,7 +21,7 @@ namespace Avalonia.Skia
/// </summary> /// </summary>
public SKTextBlob TextBlob { get; } public SKTextBlob TextBlob { get; }
public Size Size { get; } public Rect Bounds { get; }
public Point BaselineOrigin { get; } public Point BaselineOrigin { get; }

2
src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs

@ -387,7 +387,7 @@ namespace Avalonia.Direct2D1.Media
/// <param name="glyphRun">The glyph run.</param> /// <param name="glyphRun">The glyph run.</param>
public void DrawGlyphRun(IBrush foreground, IRef<IGlyphRunImpl> glyphRun) public void DrawGlyphRun(IBrush foreground, IRef<IGlyphRunImpl> glyphRun)
{ {
using (var brush = CreateBrush(foreground, glyphRun.Item.Size)) using (var brush = CreateBrush(foreground, glyphRun.Item.Bounds.Size))
{ {
var glyphRunImpl = (GlyphRunImpl)glyphRun.Item; var glyphRunImpl = (GlyphRunImpl)glyphRun.Item;

4
src/Windows/Avalonia.Direct2D1/Media/GlyphRunImpl.cs

@ -9,12 +9,12 @@ namespace Avalonia.Direct2D1.Media
{ {
public GlyphRunImpl(GlyphRun glyphRun, Size size, Point baselineOrigin) public GlyphRunImpl(GlyphRun glyphRun, Size size, Point baselineOrigin)
{ {
Size = size; Bounds = new Rect(new Point(baselineOrigin.X, 0), size);
BaselineOrigin = baselineOrigin; BaselineOrigin = baselineOrigin;
GlyphRun = glyphRun; GlyphRun = glyphRun;
} }
public Size Size { get; } public Rect Bounds{ get; }
public Point BaselineOrigin { get; } public Point BaselineOrigin { get; }

2
tests/Avalonia.Benchmarks/NullGlyphRun.cs

@ -5,7 +5,7 @@ namespace Avalonia.Benchmarks
{ {
internal class NullGlyphRun : IGlyphRunImpl internal class NullGlyphRun : IGlyphRunImpl
{ {
public Size Size => default; public Rect Bounds => default;
public Point BaselineOrigin => default; public Point BaselineOrigin => default;

6
tests/Avalonia.Skia.UnitTests/Media/GlyphRunTests.cs

@ -110,7 +110,7 @@ namespace Avalonia.Skia.UnitTests.Media
if (glyphRun.IsLeftToRight) if (glyphRun.IsLeftToRight)
{ {
var characterHit = var characterHit =
glyphRun.GetCharacterHitFromDistance(glyphRun.Size.Width, out _); glyphRun.GetCharacterHitFromDistance(glyphRun.Bounds.Width, out _);
Assert.Equal(glyphRun.Characters.Length, characterHit.FirstCharacterIndex + characterHit.TrailingLength); Assert.Equal(glyphRun.Characters.Length, characterHit.FirstCharacterIndex + characterHit.TrailingLength);
} }
@ -157,9 +157,9 @@ namespace Avalonia.Skia.UnitTests.Media
private static List<Rect> BuildRects(GlyphRun glyphRun) private static List<Rect> BuildRects(GlyphRun glyphRun)
{ {
var height = glyphRun.Size.Height; var height = glyphRun.Bounds.Height;
var currentX = glyphRun.IsLeftToRight ? 0d : glyphRun.Size.Width; var currentX = glyphRun.IsLeftToRight ? 0d : glyphRun.Bounds.Width;
var rects = new List<Rect>(glyphRun.GlyphInfos!.Count); var rects = new List<Rect>(glyphRun.GlyphInfos!.Count);

2
tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs

@ -457,7 +457,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
var glyphRun = shapedRun.GlyphRun; var glyphRun = shapedRun.GlyphRun;
var width = glyphRun.Size.Width; var width = glyphRun.Bounds.Width;
var characterHit = glyphRun.GetCharacterHitFromDistance(width, out _); var characterHit = glyphRun.GetCharacterHitFromDistance(width, out _);

4
tests/Avalonia.UnitTests/MockGlyphRun.cs

@ -16,10 +16,10 @@ namespace Avalonia.UnitTests
width += glyphInfos[i].GlyphAdvance; width += glyphInfos[i].GlyphAdvance;
} }
Size = new Size(width, 10); Bounds = new Rect(new Size(width, 10));
} }
public Size Size { get; } public Rect Bounds { get; }
public Point BaselineOrigin => new Point(0, 8); public Point BaselineOrigin => new Point(0, 8);

Loading…
Cancel
Save