diff --git a/src/Avalonia.Base/Media/Brush.cs b/src/Avalonia.Base/Media/Brush.cs
index b9a560ad8f..accabce145 100644
--- a/src/Avalonia.Base/Media/Brush.cs
+++ b/src/Avalonia.Base/Media/Brush.cs
@@ -11,7 +11,7 @@ namespace Avalonia.Media
/// Describes how an area is painted.
///
[TypeConverter(typeof(BrushConverter))]
- public abstract class Brush : Animatable
+ public abstract class Brush : Animatable, IBrush
{
///
/// Defines the property.
diff --git a/src/Avalonia.Base/Media/GlyphRun.cs b/src/Avalonia.Base/Media/GlyphRun.cs
index 65575617d0..0ec7152359 100644
--- a/src/Avalonia.Base/Media/GlyphRun.cs
+++ b/src/Avalonia.Base/Media/GlyphRun.cs
@@ -13,14 +13,22 @@ namespace Avalonia.Media
///
public sealed class GlyphRun : IDisposable
{
+ private readonly static IPlatformRenderInterface s_renderInterface;
+
private IRef? _platformImpl;
private double _fontRenderingEmSize;
private int _biDiLevel;
private GlyphRunMetrics? _glyphRunMetrics;
private ReadOnlyMemory _characters;
private IReadOnlyList _glyphInfos;
+ private Point? _baselineOrigin;
private bool _hasOneCharPerCluster; // if true, character index and cluster are similar
+ static GlyphRun()
+ {
+ s_renderInterface = AvaloniaLocator.Current.GetRequiredService();
+ }
+
///
/// Initializes a new instance of the class by specifying properties of the class.
///
@@ -28,15 +36,17 @@ namespace Avalonia.Media
/// The rendering em size.
/// The characters.
/// The glyph indices.
+ /// The baseline origin of the run.
/// The bidi level.
public GlyphRun(
IGlyphTypeface glyphTypeface,
double fontRenderingEmSize,
ReadOnlyMemory characters,
IReadOnlyList 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
/// The rendering em size.
/// The characters.
/// The list of glyphs used.
+ /// The baseline origin of the run.
/// The bidi level.
public GlyphRun(
IGlyphTypeface glyphTypeface,
double fontRenderingEmSize,
ReadOnlyMemory characters,
IReadOnlyList 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();
GlyphTypeface = Typeface.Default.GlyphTypeface;
_platformImpl = platformImpl;
+ _baselineOrigin = platformImpl.Item.BaselineOrigin;
}
private static IReadOnlyList CreateGlyphInfos(IReadOnlyList glyphIndices,
@@ -147,9 +162,13 @@ namespace Avalonia.Media
=> _glyphRunMetrics ??= CreateGlyphRunMetrics();
///
- /// Gets the baseline origin of the.
+ /// Gets or sets the baseline origin of the.
///
- public Point BaselineOrigin => PlatformImpl.Item.BaselineOrigin;
+ public Point BaselineOrigin
+ {
+ get => _baselineOrigin ?? default;
+ set => Set(ref _baselineOrigin, value);
+ }
///
/// Gets or sets the list of UTF16 code points that represent the Unicode content of the .
@@ -204,9 +223,7 @@ namespace Avalonia.Media
/// The geometry returned contains the combined geometry of all glyphs in the glyph run.
public Geometry BuildGeometry()
{
- var platformRenderInterface = AvaloniaLocator.Current.GetRequiredService();
-
- var geometryImpl = platformRenderInterface.BuildGlyphRunGeometry(this);
+ var geometryImpl = s_renderInterface.BuildGlyphRunGeometry(this);
return new PlatformGeometry(geometryImpl);
}
@@ -802,9 +819,11 @@ namespace Avalonia.Media
private IRef CreateGlyphRunImpl()
{
- var platformRenderInterface = AvaloniaLocator.Current.GetRequiredService();
-
- 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);
diff --git a/src/Avalonia.Base/Media/TextFormatting/ShapedTextRun.cs b/src/Avalonia.Base/Media/TextFormatting/ShapedTextRun.cs
index ac196bf7e0..7f23ac98b4 100644
--- a/src/Avalonia.Base/Media/TextFormatting/ShapedTextRun.cs
+++ b/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()
diff --git a/src/Avalonia.Base/Platform/IPlatformRenderInterface.cs b/src/Avalonia.Base/Platform/IPlatformRenderInterface.cs
index e2160f21d2..41e792d58e 100644
--- a/src/Avalonia.Base/Platform/IPlatformRenderInterface.cs
+++ b/src/Avalonia.Base/Platform/IPlatformRenderInterface.cs
@@ -168,8 +168,9 @@ namespace Avalonia.Platform
/// The glyph typeface.
/// The font rendering em size.
/// The list of glyphs.
+ /// The baseline origin of the run. Can be null.
/// An .
- IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize, IReadOnlyList glyphInfos);
+ IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize, IReadOnlyList glyphInfos, Point baselineOrigin);
///
/// Creates a backend-specific object using a low-level API graphics context
diff --git a/src/Avalonia.Headless/HeadlessPlatformRenderInterface.cs b/src/Avalonia.Headless/HeadlessPlatformRenderInterface.cs
index 572ff1c876..514d3b3e07 100644
--- a/src/Avalonia.Headless/HeadlessPlatformRenderInterface.cs
+++ b/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 glyphInfos)
+ public IGlyphRunImpl CreateGlyphRun(
+ IGlyphTypeface glyphTypeface,
+ double fontRenderingEmSize,
+ IReadOnlyList glyphInfos,
+ Point baselineOrigin)
{
return new HeadlessGlyphRunStub();
}
diff --git a/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs b/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs
index 6630f0707e..b4297a7c33 100644
--- a/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs
+++ b/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 glyphInfos)
+ public IGlyphRunImpl CreateGlyphRun(
+ IGlyphTypeface glyphTypeface,
+ double fontRenderingEmSize,
+ IReadOnlyList 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);
}
diff --git a/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs b/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs
index 461950b728..fbf8097ece 100644
--- a/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs
+++ b/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs
@@ -158,7 +158,8 @@ namespace Avalonia.Direct2D1
public IGeometryImpl CreateGeometryGroup(FillRule fillRule, IReadOnlyList 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 glyphInfos)
+ public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize,
+ IReadOnlyList 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,
diff --git a/tests/Avalonia.Base.UnitTests/Media/GlyphRunTests.cs b/tests/Avalonia.Base.UnitTests/Media/GlyphRunTests.cs
index a05bfbea4c..43feb75c08 100644
--- a/tests/Avalonia.Base.UnitTests/Media/GlyphRunTests.cs
+++ b/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);
}
}
}
diff --git a/tests/Avalonia.Base.UnitTests/VisualTree/MockRenderInterface.cs b/tests/Avalonia.Base.UnitTests/VisualTree/MockRenderInterface.cs
index ee501a86c1..76c7fe97fc 100644
--- a/tests/Avalonia.Base.UnitTests/VisualTree/MockRenderInterface.cs
+++ b/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 glyphInfos)
+ public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize,
+ IReadOnlyList glyphInfos, Point baselineOrigin)
{
throw new NotImplementedException();
}
diff --git a/tests/Avalonia.Benchmarks/NullRenderingPlatform.cs b/tests/Avalonia.Benchmarks/NullRenderingPlatform.cs
index 9b148c798b..37b79855db 100644
--- a/tests/Avalonia.Benchmarks/NullRenderingPlatform.cs
+++ b/tests/Avalonia.Benchmarks/NullRenderingPlatform.cs
@@ -123,7 +123,8 @@ namespace Avalonia.Benchmarks
return new MockStreamGeometryImpl();
}
- public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize, IReadOnlyList glyphInfos)
+ public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize,
+ IReadOnlyList glyphInfos, Point baselineOrigin)
{
return new MockGlyphRun(glyphInfos);
}
diff --git a/tests/Avalonia.Skia.UnitTests/Media/GlyphRunTests.cs b/tests/Avalonia.Skia.UnitTests/Media/GlyphRunTests.cs
index 59c7ac3786..bfe03030c6 100644
--- a/tests/Avalonia.Skia.UnitTests/Media/GlyphRunTests.cs
+++ b/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)
{
diff --git a/tests/Avalonia.UnitTests/MockPlatformRenderInterface.cs b/tests/Avalonia.UnitTests/MockPlatformRenderInterface.cs
index 30f949ccb8..93073faefb 100644
--- a/tests/Avalonia.UnitTests/MockPlatformRenderInterface.cs
+++ b/tests/Avalonia.UnitTests/MockPlatformRenderInterface.cs
@@ -149,7 +149,8 @@ namespace Avalonia.UnitTests
throw new NotImplementedException();
}
- public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize, IReadOnlyList glyphInfos)
+ public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize,
+ IReadOnlyList glyphInfos, Point baselineOrigin)
{
return new MockGlyphRun(glyphInfos);
}