Browse Source

Cleanup

pull/9896/head
Benedikt Stebner 3 years ago
parent
commit
fc4e549c2e
  1. 57
      src/Avalonia.Base/Media/TextDecoration.cs
  2. 6
      src/Avalonia.Base/Platform/IGlyphRunImpl.cs
  3. 5
      src/Avalonia.Headless/HeadlessPlatformRenderInterface.cs
  4. 4
      src/Skia/Avalonia.Skia/GlyphRunImpl.cs
  5. 8
      src/Windows/Avalonia.Direct2D1/Media/GlyphRunImpl.cs
  6. 8
      tests/Avalonia.UnitTests/MockGlyphRun.cs

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

@ -1,5 +1,9 @@
using Avalonia.Collections; using System.Collections.Generic;
using Avalonia.Collections;
using Avalonia.Collections.Pooled;
using Avalonia.Media.TextFormatting; using Avalonia.Media.TextFormatting;
using Avalonia.Platform;
using Avalonia.Utilities;
namespace Avalonia.Media namespace Avalonia.Media
{ {
@ -196,19 +200,66 @@ namespace Avalonia.Media
break; break;
} }
var strokeOffset = 0.0;
switch (StrokeOffsetUnit) switch (StrokeOffsetUnit)
{ {
case TextDecorationUnit.FontRenderingEmSize: case TextDecorationUnit.FontRenderingEmSize:
origin += new Point(0, StrokeOffset * textMetrics.FontRenderingEmSize); strokeOffset = StrokeOffset * textMetrics.FontRenderingEmSize;
break; break;
case TextDecorationUnit.Pixel: case TextDecorationUnit.Pixel:
origin += new Point(0, StrokeOffset); strokeOffset = StrokeOffset;
break; break;
} }
origin += new Point(0, strokeOffset);
var pen = new Pen(Stroke ?? defaultBrush, thickness, var pen = new Pen(Stroke ?? defaultBrush, thickness,
new DashStyle(StrokeDashArray, StrokeDashOffset), StrokeLineCap); new DashStyle(StrokeDashArray, StrokeDashOffset), StrokeLineCap);
if (Location == TextDecorationLocation.Underline && MathUtilities.IsZero(strokeOffset))
{
var intersections = glyphRun.GlyphRunImpl.GetIntersections((float)(thickness * 0.5d + strokeOffset), (float)(thickness * 1.5d + strokeOffset));
if (intersections != null && intersections.Count > 0)
{
var last = baselineOrigin.X;
var finalPos = last + glyphRun.Size.Width;
var end = last;
var points = new List<double>();
//math is taken from chrome's source code.
for (var i = 0; i < intersections.Count; i += 2)
{
var start = intersections[i] - thickness;
end = intersections[i + 1] + thickness;
if (start > last && last + textMetrics.FontRenderingEmSize / 12 < start)
{
points.Add(last);
points.Add(start);
}
last = end;
}
if (end < finalPos)
{
points.Add(end);
points.Add(finalPos);
}
for (var i = 0; i < points.Count; i += 2)
{
var a = new Point(points[i], origin.Y);
var b = new Point(points[i + 1], origin.Y);
drawingContext.DrawLine(pen, a, b);
}
return;
}
}
drawingContext.DrawLine(pen, origin, origin + new Point(glyphRun.Metrics.Width, 0)); drawingContext.DrawLine(pen, origin, origin + new Point(glyphRun.Metrics.Width, 0));
} }
} }

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

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using Avalonia.Metadata; using Avalonia.Metadata;
namespace Avalonia.Platform namespace Avalonia.Platform
@ -7,5 +8,8 @@ namespace Avalonia.Platform
/// Actual implementation of a glyph run that stores platform dependent resources. /// Actual implementation of a glyph run that stores platform dependent resources.
/// </summary> /// </summary>
[Unstable] [Unstable]
public interface IGlyphRunImpl : IDisposable { } public interface IGlyphRunImpl : IDisposable
{
IReadOnlyList<float> GetIntersections(float lowerBound, float upperBound);
}
} }

5
src/Avalonia.Headless/HeadlessPlatformRenderInterface.cs

@ -128,6 +128,11 @@ namespace Avalonia.Headless
public void Dispose() public void Dispose()
{ {
} }
public IReadOnlyList<float> GetIntersections(float lowerBound, float upperBound)
{
throw new NotImplementedException();
}
} }
class HeadlessGeometryStub : IGeometryImpl class HeadlessGeometryStub : IGeometryImpl

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

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using Avalonia.Metadata; using Avalonia.Metadata;
using Avalonia.Platform; using Avalonia.Platform;
using SkiaSharp; using SkiaSharp;
@ -20,6 +21,9 @@ namespace Avalonia.Skia
/// </summary> /// </summary>
public SKTextBlob TextBlob { get; } public SKTextBlob TextBlob { get; }
public IReadOnlyList<float> GetIntersections(float upperBound, float lowerBound) =>
TextBlob.GetIntercepts(lowerBound, upperBound);
void IDisposable.Dispose() void IDisposable.Dispose()
{ {
TextBlob.Dispose(); TextBlob.Dispose();

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

@ -1,4 +1,5 @@
using Avalonia.Platform; using System.Collections.Generic;
using Avalonia.Platform;
namespace Avalonia.Direct2D1.Media namespace Avalonia.Direct2D1.Media
{ {
@ -15,5 +16,10 @@ namespace Avalonia.Direct2D1.Media
{ {
GlyphRun?.Dispose(); GlyphRun?.Dispose();
} }
public IReadOnlyList<float> GetIntersections(float lowerBound, float upperBound)
{
return null;
}
} }
} }

8
tests/Avalonia.UnitTests/MockGlyphRun.cs

@ -1,4 +1,5 @@
using Avalonia.Platform; using System.Collections.Generic;
using Avalonia.Platform;
namespace Avalonia.UnitTests namespace Avalonia.UnitTests
{ {
@ -8,5 +9,10 @@ namespace Avalonia.UnitTests
{ {
} }
public IReadOnlyList<float> GetIntersections(float lowerBound, float upperBound)
{
return null;
}
} }
} }

Loading…
Cancel
Save