Browse Source

Reintroduce customizable GlyphRun.BaselineOrigin

Reintroduce Brush IBrush inheritance
pull/10063/head
Benedikt Stebner 3 years ago
parent
commit
cb884c6e9e
  1. 2
      src/Avalonia.Base/Media/Brush.cs
  2. 37
      src/Avalonia.Base/Media/GlyphRun.cs
  3. 2
      src/Avalonia.Base/Media/TextFormatting/ShapedTextRun.cs
  4. 3
      src/Avalonia.Base/Platform/IPlatformRenderInterface.cs
  5. 6
      src/Avalonia.Headless/HeadlessPlatformRenderInterface.cs
  6. 7
      src/Skia/Avalonia.Skia/PlatformRenderInterface.cs
  7. 6
      src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs
  8. 2
      tests/Avalonia.Base.UnitTests/Media/GlyphRunTests.cs
  9. 3
      tests/Avalonia.Base.UnitTests/VisualTree/MockRenderInterface.cs
  10. 3
      tests/Avalonia.Benchmarks/NullRenderingPlatform.cs
  11. 2
      tests/Avalonia.Skia.UnitTests/Media/GlyphRunTests.cs
  12. 3
      tests/Avalonia.UnitTests/MockPlatformRenderInterface.cs

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

@ -11,7 +11,7 @@ namespace Avalonia.Media
/// Describes how an area is painted.
/// </summary>
[TypeConverter(typeof(BrushConverter))]
public abstract class Brush : Animatable
public abstract class Brush : Animatable, IBrush
{
/// <summary>
/// Defines the <see cref="Opacity"/> property.

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

@ -13,14 +13,22 @@ namespace Avalonia.Media
/// </summary>
public sealed class GlyphRun : IDisposable
{
private readonly static IPlatformRenderInterface s_renderInterface;
private IRef<IGlyphRunImpl>? _platformImpl;
private double _fontRenderingEmSize;
private int _biDiLevel;
private GlyphRunMetrics? _glyphRunMetrics;
private ReadOnlyMemory<char> _characters;
private IReadOnlyList<GlyphInfo> _glyphInfos;
private Point? _baselineOrigin;
private bool _hasOneCharPerCluster; // if true, character index and cluster are similar
static GlyphRun()
{
s_renderInterface = AvaloniaLocator.Current.GetRequiredService<IPlatformRenderInterface>();
}
/// <summary>
/// Initializes a new instance of the <see cref="GlyphRun"/> class by specifying properties of the class.
/// </summary>
@ -28,15 +36,17 @@ namespace Avalonia.Media
/// <param name="fontRenderingEmSize">The rendering em size.</param>
/// <param name="characters">The characters.</param>
/// <param name="glyphIndices">The glyph indices.</param>
/// <param name="baselineOrigin">The baseline origin of the run.</param>
/// <param name="biDiLevel">The bidi level.</param>
public GlyphRun(
IGlyphTypeface glyphTypeface,
double fontRenderingEmSize,
ReadOnlyMemory<char> characters,
IReadOnlyList<ushort> glyphIndices,
Point? baselineOrigin = null,
int biDiLevel = 0)
: this(glyphTypeface, fontRenderingEmSize, characters,
CreateGlyphInfos(glyphIndices, fontRenderingEmSize, glyphTypeface), biDiLevel)
CreateGlyphInfos(glyphIndices, fontRenderingEmSize, glyphTypeface), baselineOrigin, biDiLevel)
{
_hasOneCharPerCluster = true;
}
@ -48,12 +58,14 @@ namespace Avalonia.Media
/// <param name="fontRenderingEmSize">The rendering em size.</param>
/// <param name="characters">The characters.</param>
/// <param name="glyphInfos">The list of glyphs used.</param>
/// <param name="baselineOrigin">The baseline origin of the run.</param>
/// <param name="biDiLevel">The bidi level.</param>
public GlyphRun(
IGlyphTypeface glyphTypeface,
double fontRenderingEmSize,
ReadOnlyMemory<char> characters,
IReadOnlyList<GlyphInfo> glyphInfos,
Point? baselineOrigin = null,
int biDiLevel = 0)
{
GlyphTypeface = glyphTypeface;
@ -64,6 +76,8 @@ namespace Avalonia.Media
_glyphInfos = glyphInfos;
_baselineOrigin = baselineOrigin;
_biDiLevel = biDiLevel;
}
@ -72,6 +86,7 @@ namespace Avalonia.Media
_glyphInfos = Array.Empty<GlyphInfo>();
GlyphTypeface = Typeface.Default.GlyphTypeface;
_platformImpl = platformImpl;
_baselineOrigin = platformImpl.Item.BaselineOrigin;
}
private static IReadOnlyList<GlyphInfo> CreateGlyphInfos(IReadOnlyList<ushort> glyphIndices,
@ -147,9 +162,13 @@ namespace Avalonia.Media
=> _glyphRunMetrics ??= CreateGlyphRunMetrics();
/// <summary>
/// Gets the baseline origin of the<see cref="GlyphRun"/>.
/// Gets or sets the baseline origin of the<see cref="GlyphRun"/>.
/// </summary>
public Point BaselineOrigin => PlatformImpl.Item.BaselineOrigin;
public Point BaselineOrigin
{
get => _baselineOrigin ?? default;
set => Set(ref _baselineOrigin, value);
}
/// <summary>
/// Gets or sets the list of UTF16 code points that represent the Unicode content of the <see cref="GlyphRun"/>.
@ -204,9 +223,7 @@ namespace Avalonia.Media
/// <returns>The geometry returned contains the combined geometry of all glyphs in the glyph run.</returns>
public Geometry BuildGeometry()
{
var platformRenderInterface = AvaloniaLocator.Current.GetRequiredService<IPlatformRenderInterface>();
var geometryImpl = platformRenderInterface.BuildGlyphRunGeometry(this);
var geometryImpl = s_renderInterface.BuildGlyphRunGeometry(this);
return new PlatformGeometry(geometryImpl);
}
@ -802,9 +819,11 @@ namespace Avalonia.Media
private IRef<IGlyphRunImpl> CreateGlyphRunImpl()
{
var platformRenderInterface = AvaloniaLocator.Current.GetRequiredService<IPlatformRenderInterface>();
var platformImpl = platformRenderInterface.CreateGlyphRun(GlyphTypeface, FontRenderingEmSize, GlyphInfos);
var platformImpl = s_renderInterface.CreateGlyphRun(
GlyphTypeface,
FontRenderingEmSize,
GlyphInfos,
_baselineOrigin ?? new Point(0, -GlyphTypeface.Metrics.Ascent * Scale));
_platformImpl = RefCountable.Create(platformImpl);

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

@ -185,7 +185,7 @@ namespace Avalonia.Media.TextFormatting
ShapedBuffer.FontRenderingEmSize,
Text,
ShapedBuffer,
BidiLevel);
biDiLevel: BidiLevel);
}
public void Dispose()

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

@ -168,8 +168,9 @@ namespace Avalonia.Platform
/// <param name="glyphTypeface">The glyph typeface.</param>
/// <param name="fontRenderingEmSize">The font rendering em size.</param>
/// <param name="glyphInfos">The list of glyphs.</param>
/// <param name="baselineOrigin">The baseline origin of the run. Can be null.</param>
/// <returns>An <see cref="IGlyphRunImpl"/>.</returns>
IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize, IReadOnlyList<GlyphInfo> glyphInfos);
IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize, IReadOnlyList<GlyphInfo> glyphInfos, Point baselineOrigin);
/// <summary>
/// Creates a backend-specific object using a low-level API graphics context

6
src/Avalonia.Headless/HeadlessPlatformRenderInterface.cs

@ -120,7 +120,11 @@ namespace Avalonia.Headless
return new HeadlessGeometryStub(new Rect(glyphRun.Size));
}
public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize, IReadOnlyList<GlyphInfo> glyphInfos)
public IGlyphRunImpl CreateGlyphRun(
IGlyphTypeface glyphTypeface,
double fontRenderingEmSize,
IReadOnlyList<GlyphInfo> glyphInfos,
Point baselineOrigin)
{
return new HeadlessGlyphRunStub();
}

7
src/Skia/Avalonia.Skia/PlatformRenderInterface.cs

@ -201,7 +201,11 @@ namespace Avalonia.Skia
return new WriteableBitmapImpl(size, dpi, format, alphaFormat);
}
public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize, IReadOnlyList<GlyphInfo> glyphInfos)
public IGlyphRunImpl CreateGlyphRun(
IGlyphTypeface glyphTypeface,
double fontRenderingEmSize,
IReadOnlyList<GlyphInfo> glyphInfos,
Point baselineOrigin)
{
if (glyphTypeface == null)
{
@ -252,7 +256,6 @@ namespace Avalonia.Skia
var scale = fontRenderingEmSize / glyphTypeface.Metrics.DesignEmHeight;
var height = glyphTypeface.Metrics.LineSpacing * scale;
var baselineOrigin = new Point(0, -glyphTypeface.Metrics.Ascent * scale);
return new GlyphRunImpl(builder.Build(), new Size(width, height), baselineOrigin);
}

6
src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs

@ -158,7 +158,8 @@ namespace Avalonia.Direct2D1
public IGeometryImpl CreateGeometryGroup(FillRule fillRule, IReadOnlyList<Geometry> children) => new GeometryGroupImpl(fillRule, children);
public IGeometryImpl CreateCombinedGeometry(GeometryCombineMode combineMode, Geometry g1, Geometry g2) => new CombinedGeometryImpl(combineMode, g1, g2);
public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize, IReadOnlyList<GlyphInfo> glyphInfos)
public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize,
IReadOnlyList<GlyphInfo> glyphInfos, Point baselineOrigin)
{
var glyphTypefaceImpl = (GlyphTypefaceImpl)glyphTypeface;
@ -207,7 +208,6 @@ namespace Avalonia.Direct2D1
var scale = fontRenderingEmSize / glyphTypeface.Metrics.DesignEmHeight;
var height = glyphTypeface.Metrics.LineSpacing * scale;
var baselineOrigin = new Point(0, -glyphTypeface.Metrics.Ascent * scale);
return new GlyphRunImpl(run, new Size(width, height), baselineOrigin);
}
@ -257,7 +257,7 @@ namespace Avalonia.Direct2D1
sink.Close();
}
var (baselineOriginX, baselineOriginY) = glyphRun.BaselineOrigin;
var (baselineOriginX, baselineOriginY) = glyphRun.PlatformImpl.Item.BaselineOrigin;
var transformedGeometry = new SharpDX.Direct2D1.TransformedGeometry(
Direct2D1Factory,

2
tests/Avalonia.Base.UnitTests/Media/GlyphRunTests.cs

@ -188,7 +188,7 @@ namespace Avalonia.Base.UnitTests.Media
glyphInfos[i] = new GlyphInfo(0, glyphClusters[i], glyphAdvances[i]);
}
return new GlyphRun(new MockGlyphTypeface(), 10, new string('a', count).AsMemory(), glyphInfos, bidiLevel);
return new GlyphRun(new MockGlyphTypeface(), 10, new string('a', count).AsMemory(), glyphInfos, biDiLevel: bidiLevel);
}
}
}

3
tests/Avalonia.Base.UnitTests/VisualTree/MockRenderInterface.cs

@ -77,7 +77,8 @@ namespace Avalonia.Base.UnitTests.VisualTree
throw new NotImplementedException();
}
public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize, IReadOnlyList<GlyphInfo> glyphInfos)
public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize,
IReadOnlyList<GlyphInfo> glyphInfos, Point baselineOrigin)
{
throw new NotImplementedException();
}

3
tests/Avalonia.Benchmarks/NullRenderingPlatform.cs

@ -123,7 +123,8 @@ namespace Avalonia.Benchmarks
return new MockStreamGeometryImpl();
}
public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize, IReadOnlyList<GlyphInfo> glyphInfos)
public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize,
IReadOnlyList<GlyphInfo> glyphInfos, Point baselineOrigin)
{
return new MockGlyphRun(glyphInfos);
}

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

@ -217,7 +217,7 @@ namespace Avalonia.Skia.UnitTests.Media
shapedBuffer.FontRenderingEmSize,
shapedBuffer.Text,
shapedBuffer.GlyphInfos,
shapedBuffer.BidiLevel);
biDiLevel: shapedBuffer.BidiLevel);
if(shapedBuffer.BidiLevel == 1)
{

3
tests/Avalonia.UnitTests/MockPlatformRenderInterface.cs

@ -149,7 +149,8 @@ namespace Avalonia.UnitTests
throw new NotImplementedException();
}
public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize, IReadOnlyList<GlyphInfo> glyphInfos)
public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize,
IReadOnlyList<GlyphInfo> glyphInfos, Point baselineOrigin)
{
return new MockGlyphRun(glyphInfos);
}

Loading…
Cancel
Save