Browse Source

Merge branch 'master' into feature/moveThemeFontAssets

pull/10293/head
Max Katz 3 years ago
committed by GitHub
parent
commit
5f38f34862
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      samples/ControlCatalog/Pages/CustomDrawingExampleControl.cs
  2. 6
      samples/ControlCatalog/Pages/PointerCanvas.cs
  3. 6
      src/Avalonia.Base/Media/TextFormatting/InterWordJustification.cs
  4. 98
      src/Avalonia.Base/Media/TextFormatting/ShapedBuffer.cs
  5. 6
      src/Avalonia.Base/Media/TextFormatting/ShapedTextRun.cs
  6. 2
      src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs
  7. 2
      src/Avalonia.Controls.DataGrid/Themes/Simple.xaml
  8. 6
      src/Avalonia.Controls/PullToRefresh/RefreshInfoProvider.cs
  9. 2
      src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs
  10. 2
      src/Avalonia.Controls/Utils/CollectionChangedEventManager.cs
  11. 4
      src/Avalonia.Diagnostics/Diagnostics/Views/EventsPageView.xaml
  12. 5
      src/Avalonia.Themes.Simple/Accents/Base.xaml
  13. 1
      src/Avalonia.Themes.Simple/Controls/ComboBox.xaml
  14. 1
      src/Avalonia.Themes.Simple/Controls/DataValidationErrors.xaml
  15. 4
      src/Skia/Avalonia.Skia/TextShaperImpl.cs
  16. 4
      src/Windows/Avalonia.Direct2D1/Media/TextShaperImpl.cs
  17. 1
      src/tools/DevAnalyzers/DevAnalyzers.csproj
  18. 1
      src/tools/DevGenerators/DevGenerators.csproj
  19. 4
      tests/Avalonia.Skia.UnitTests/Media/GlyphRunTests.cs
  20. 18
      tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs
  21. 14
      tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLineTests.cs
  22. 10
      tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextShaperTests.cs
  23. 4
      tests/Avalonia.UnitTests/HarfBuzzTextShaperImpl.cs
  24. 3
      tests/Avalonia.UnitTests/MockTextShaperImpl.cs

8
samples/ControlCatalog/Pages/CustomDrawingExampleControl.cs

@ -16,10 +16,10 @@ namespace ControlCatalog.Pages
private Point _cursorPoint;
public StyledProperty<double> ScaleProperty = AvaloniaProperty.Register<CustomDrawingExampleControl, double>(nameof(Scale), 1.0d);
public static readonly StyledProperty<double> ScaleProperty = AvaloniaProperty.Register<CustomDrawingExampleControl, double>(nameof(Scale), 1.0d);
public double Scale { get => GetValue(ScaleProperty); set => SetValue(ScaleProperty, value); }
public StyledProperty<double> RotationProperty = AvaloniaProperty.Register<CustomDrawingExampleControl, double>(nameof(Rotation));
public static readonly StyledProperty<double> RotationProperty = AvaloniaProperty.Register<CustomDrawingExampleControl, double>(nameof(Rotation));
/// <summary>
/// Rotation, measured in Radians!
/// </summary>
@ -33,10 +33,10 @@ namespace ControlCatalog.Pages
}
}
public StyledProperty<double> ViewportCenterYProperty = AvaloniaProperty.Register<CustomDrawingExampleControl, double>(nameof(ViewportCenterY), 0.0d);
public static readonly StyledProperty<double> ViewportCenterYProperty = AvaloniaProperty.Register<CustomDrawingExampleControl, double>(nameof(ViewportCenterY), 0.0d);
public double ViewportCenterY { get => GetValue(ViewportCenterYProperty); set => SetValue(ViewportCenterYProperty, value); }
public StyledProperty<double> ViewportCenterXProperty = AvaloniaProperty.Register<CustomDrawingExampleControl, double>(nameof(ViewportCenterX), 0.0d);
public static readonly StyledProperty<double> ViewportCenterXProperty = AvaloniaProperty.Register<CustomDrawingExampleControl, double>(nameof(ViewportCenterX), 0.0d);
public double ViewportCenterX { get => GetValue(ViewportCenterXProperty); set => SetValue(ViewportCenterXProperty, value); }
private IPen _pen;

6
samples/ControlCatalog/Pages/PointerCanvas.cs

@ -93,7 +93,7 @@ public class PointerCanvas : Control
}
private int _threadSleep;
public static DirectProperty<PointerCanvas, int> ThreadSleepProperty =
public static readonly DirectProperty<PointerCanvas, int> ThreadSleepProperty =
AvaloniaProperty.RegisterDirect<PointerCanvas, int>(nameof(ThreadSleep), c => c.ThreadSleep, (c, v) => c.ThreadSleep = v);
public int ThreadSleep
@ -103,7 +103,7 @@ public class PointerCanvas : Control
}
private bool _drawOnlyPoints;
public static DirectProperty<PointerCanvas, bool> DrawOnlyPointsProperty =
public static readonly DirectProperty<PointerCanvas, bool> DrawOnlyPointsProperty =
AvaloniaProperty.RegisterDirect<PointerCanvas, bool>(nameof(DrawOnlyPoints), c => c.DrawOnlyPoints, (c, v) => c.DrawOnlyPoints = v);
public bool DrawOnlyPoints
@ -113,7 +113,7 @@ public class PointerCanvas : Control
}
private string? _status;
public static DirectProperty<PointerCanvas, string?> StatusProperty =
public static readonly DirectProperty<PointerCanvas, string?> StatusProperty =
AvaloniaProperty.RegisterDirect<PointerCanvas, string?>(nameof(DrawOnlyPoints), c => c.Status, (c, v) => c.Status = v,
defaultBindingMode: Avalonia.Data.BindingMode.TwoWay);

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

@ -89,13 +89,13 @@ namespace Avalonia.Media.TextFormatting
var offset = Math.Max(0, currentPosition - glyphRun.Metrics.FirstCluster);
var glyphIndex = glyphRun.FindGlyphIndex(characterIndex - offset);
var glyphInfo = shapedBuffer.GlyphInfos[glyphIndex];
var glyphInfo = shapedBuffer[glyphIndex];
shapedBuffer.GlyphInfos[glyphIndex] = new GlyphInfo(glyphInfo.GlyphIndex,
shapedBuffer[glyphIndex] = new GlyphInfo(glyphInfo.GlyphIndex,
glyphInfo.GlyphCluster, glyphInfo.GlyphAdvance + spacing);
}
glyphRun.GlyphInfos = shapedBuffer.GlyphInfos;
glyphRun.GlyphInfos = shapedBuffer;
}
currentPosition += textRun.Length;

98
src/Avalonia.Base/Media/TextFormatting/ShapedBuffer.cs

@ -2,6 +2,7 @@
using System.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Avalonia.Utilities;
namespace Avalonia.Media.TextFormatting
@ -9,12 +10,13 @@ namespace Avalonia.Media.TextFormatting
public sealed class ShapedBuffer : IReadOnlyList<GlyphInfo>, IDisposable
{
private GlyphInfo[]? _rentedBuffer;
private ArraySlice<GlyphInfo> _glyphInfos;
public ShapedBuffer(ReadOnlyMemory<char> text, int bufferLength, IGlyphTypeface glyphTypeface, double fontRenderingEmSize, sbyte bidiLevel)
{
_rentedBuffer = ArrayPool<GlyphInfo>.Shared.Rent(bufferLength);
Text = text;
GlyphInfos = new ArraySlice<GlyphInfo>(_rentedBuffer, 0, bufferLength);
_rentedBuffer = ArrayPool<GlyphInfo>.Shared.Rent(bufferLength);
_glyphInfos = new ArraySlice<GlyphInfo>(_rentedBuffer, 0, bufferLength);
GlyphTypeface = glyphTypeface;
FontRenderingEmSize = fontRenderingEmSize;
BidiLevel = bidiLevel;
@ -23,27 +25,70 @@ namespace Avalonia.Media.TextFormatting
internal ShapedBuffer(ReadOnlyMemory<char> text, ArraySlice<GlyphInfo> glyphInfos, IGlyphTypeface glyphTypeface, double fontRenderingEmSize, sbyte bidiLevel)
{
Text = text;
GlyphInfos = glyphInfos;
_glyphInfos = glyphInfos;
GlyphTypeface = glyphTypeface;
FontRenderingEmSize = fontRenderingEmSize;
BidiLevel = bidiLevel;
}
internal ArraySlice<GlyphInfo> GlyphInfos { get; private set; }
public int Length
=> GlyphInfos.Length;
/// <summary>
/// The buffer's length.
/// </summary>
public int Length => _glyphInfos.Length;
/// <summary>
/// The buffer's glyph typeface.
/// </summary>
public IGlyphTypeface GlyphTypeface { get; }
/// <summary>
/// The buffers font rendering em size.
/// </summary>
public double FontRenderingEmSize { get; }
/// <summary>
/// The buffer's bidi level.
/// </summary>
public sbyte BidiLevel { get; }
/// <summary>
/// The buffer's reading direction.
/// </summary>
public bool IsLeftToRight => (BidiLevel & 1) == 0;
/// <summary>
/// The text that is represended by this buffer.
/// </summary>
public ReadOnlyMemory<char> Text { get; }
/// <summary>
/// Reverses the buffer.
/// </summary>
public void Reverse()
{
_glyphInfos.Span.Reverse();
}
public void Dispose()
{
if (_rentedBuffer is not null)
{
ArrayPool<GlyphInfo>.Shared.Return(_rentedBuffer);
_rentedBuffer = null;
_glyphInfos = ArraySlice<GlyphInfo>.Empty; // ensure we don't misuse the returned array
}
}
public GlyphInfo this[int index]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _glyphInfos[index];
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set => _glyphInfos[index] = value;
}
public IEnumerator<GlyphInfo> GetEnumerator() => _glyphInfos.GetEnumerator();
/// <summary>
/// Finds a glyph index for given character index.
/// </summary>
@ -53,20 +98,19 @@ namespace Avalonia.Media.TextFormatting
/// </returns>
private int FindGlyphIndex(int characterIndex)
{
if (characterIndex < GlyphInfos[0].GlyphCluster)
if (characterIndex < _glyphInfos[0].GlyphCluster)
{
return 0;
}
if (characterIndex > GlyphInfos[GlyphInfos.Length - 1].GlyphCluster)
if (characterIndex > _glyphInfos[_glyphInfos.Length - 1].GlyphCluster)
{
return GlyphInfos.Length - 1;
return _glyphInfos.Length - 1;
}
var comparer = GlyphInfo.ClusterAscendingComparer;
var glyphInfos = GlyphInfos.Span;
var glyphInfos = _glyphInfos.Span;
var searchValue = new GlyphInfo(default, characterIndex, default);
@ -109,42 +153,24 @@ namespace Avalonia.Media.TextFormatting
return new SplitResult<ShapedBuffer>(this, null);
}
var firstCluster = GlyphInfos[0].GlyphCluster;
var lastCluster = GlyphInfos[GlyphInfos.Length - 1].GlyphCluster;
var firstCluster = _glyphInfos[0].GlyphCluster;
var lastCluster = _glyphInfos[_glyphInfos.Length - 1].GlyphCluster;
var start = firstCluster < lastCluster ? firstCluster : lastCluster;
var glyphCount = FindGlyphIndex(start + length);
var first = new ShapedBuffer(Text.Slice(0, length),
GlyphInfos.Take(glyphCount), GlyphTypeface, FontRenderingEmSize, BidiLevel);
_glyphInfos.Take(glyphCount), GlyphTypeface, FontRenderingEmSize, BidiLevel);
var second = new ShapedBuffer(Text.Slice(length),
GlyphInfos.Skip(glyphCount), GlyphTypeface, FontRenderingEmSize, BidiLevel);
_glyphInfos.Skip(glyphCount), GlyphTypeface, FontRenderingEmSize, BidiLevel);
return new SplitResult<ShapedBuffer>(first, second);
}
int IReadOnlyCollection<GlyphInfo>.Count => GlyphInfos.Length;
public GlyphInfo this[int index]
{
get => GlyphInfos[index];
set => GlyphInfos[index] = value;
}
public IEnumerator<GlyphInfo> GetEnumerator() => GlyphInfos.GetEnumerator();
int IReadOnlyCollection<GlyphInfo>.Count => _glyphInfos.Length;
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public void Dispose()
{
if (_rentedBuffer is not null)
{
ArrayPool<GlyphInfo>.Shared.Return(_rentedBuffer);
_rentedBuffer = null;
GlyphInfos = ArraySlice<GlyphInfo>.Empty; // ensure we don't misuse the returned array
}
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}

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

@ -85,7 +85,7 @@ namespace Avalonia.Media.TextFormatting
{
_glyphRun = null;
ShapedBuffer.GlyphInfos.Span.Reverse();
ShapedBuffer.Reverse();
IsReversed = !IsReversed;
}
@ -106,7 +106,7 @@ namespace Avalonia.Media.TextFormatting
for (var i = 0; i < ShapedBuffer.Length; i++)
{
var advance = ShapedBuffer.GlyphInfos[i].GlyphAdvance;
var advance = ShapedBuffer[i].GlyphAdvance;
if (currentWidth + advance > availableWidth)
{
@ -130,7 +130,7 @@ namespace Avalonia.Media.TextFormatting
for (var i = ShapedBuffer.Length - 1; i >= 0; i--)
{
var advance = ShapedBuffer.GlyphInfos[i].GlyphAdvance;
var advance = ShapedBuffer[i].GlyphAdvance;
if (width + advance > availableWidth)
{

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

@ -583,7 +583,7 @@ namespace Avalonia.Media.TextFormatting
{
if (shapedTextCharacters.ShapedBuffer.Length > 0)
{
var firstCluster = shapedTextCharacters.ShapedBuffer.GlyphInfos[0].GlyphCluster;
var firstCluster = shapedTextCharacters.ShapedBuffer[0].GlyphCluster;
var lastCluster = firstCluster;
for (var j = 0; j < shapedTextCharacters.ShapedBuffer.Length; j++)

2
src/Avalonia.Controls.DataGrid/Themes/Simple.xaml

@ -202,7 +202,7 @@
<Style Selector="^ /template/ Rectangle#BackgroundRectangle">
<Setter Property="IsVisible" Value="False" />
<Setter Property="Fill" Value="{DynamicResource HighlightBrush}" />
<Setter Property="Fill" Value="{DynamicResource HighlightBrush2}" />
</Style>
<Style Selector="^:pointerover /template/ Rectangle#BackgroundRectangle">

6
src/Avalonia.Controls/PullToRefresh/RefreshInfoProvider.cs

@ -17,16 +17,16 @@ namespace Avalonia.Controls.PullToRefresh
private double _interactionRatio;
private bool _entered;
public DirectProperty<RefreshInfoProvider, bool> IsInteractingForRefreshProperty =
public static readonly DirectProperty<RefreshInfoProvider, bool> IsInteractingForRefreshProperty =
AvaloniaProperty.RegisterDirect<RefreshInfoProvider, bool>(nameof(IsInteractingForRefresh),
s => s.IsInteractingForRefresh, (s, o) => s.IsInteractingForRefresh = o);
public DirectProperty<RefreshInfoProvider, double> ExecutionRatioProperty =
public static readonly DirectProperty<RefreshInfoProvider, double> ExecutionRatioProperty =
AvaloniaProperty.RegisterDirect<RefreshInfoProvider, double>(nameof(ExecutionRatio),
s => s.ExecutionRatio);
public DirectProperty<RefreshInfoProvider, double> InteractionRatioProperty =
public static readonly DirectProperty<RefreshInfoProvider, double> InteractionRatioProperty =
AvaloniaProperty.RegisterDirect<RefreshInfoProvider, double>(nameof(InteractionRatio),
s => s.InteractionRatio, (s, o) => s.InteractionRatio = o);

2
src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs

@ -64,7 +64,7 @@ namespace Avalonia.Controls
/// <summary>
/// Defines the <see cref="RefreshInfoProvider"/> property.
/// </summary>
internal DirectProperty<RefreshVisualizer, RefreshInfoProvider?> RefreshInfoProviderProperty =
internal static readonly DirectProperty<RefreshVisualizer, RefreshInfoProvider?> RefreshInfoProviderProperty =
AvaloniaProperty.RegisterDirect<RefreshVisualizer, RefreshInfoProvider?>(nameof(RefreshInfoProvider),
s => s.RefreshInfoProvider, (s, o) => s.RefreshInfoProvider = o);

2
src/Avalonia.Controls/Utils/CollectionChangedEventManager.cs

@ -141,7 +141,7 @@ namespace Avalonia.Controls.Utils
else
{
var eCapture = e;
Dispatcher.UIThread.Post(() => Notify(_collection, eCapture, l));
Dispatcher.UIThread.Post(() => Notify(_collection, eCapture, l), DispatcherPriority.Send);
}
}
}

4
src/Avalonia.Diagnostics/Diagnostics/Views/EventsPageView.xaml

@ -28,7 +28,7 @@
</Style>
<Style Selector="ListBoxItem.handled" >
<Setter Property="Background" Value="#d9ffdc" />
<Setter Property="Background" Value="#34c940" />
<Setter Property="Foreground" Value="Black" />
</Style>
</UserControl.Styles>
@ -129,7 +129,7 @@
</DockPanel>
<StackPanel Orientation="Horizontal" Grid.Row="3" Spacing="2" Margin="0,2">
<StackPanel Orientation="Horizontal" Grid.Row="3" Spacing="2" Margin="2">
<Button Content="Clear" Command="{Binding Clear}" />
</StackPanel>

5
src/Avalonia.Themes.Simple/Accents/Base.xaml

@ -17,6 +17,7 @@
<Color x:Key="ThemeControlHighlightHighColor">#FF808080</Color>
<Color x:Key="ThemeForegroundColor">#FF000000</Color>
<Color x:Key="HighlightColor">#FF086F9E</Color>
<Color x:Key="HighlightColor2">#FF096085</Color>
<SolidColorBrush x:Key="ThemeBackgroundBrush" Color="{StaticResource ThemeBackgroundColor}" />
<SolidColorBrush x:Key="ThemeBorderLowBrush" Color="{StaticResource ThemeBorderLowColor}" />
@ -33,6 +34,8 @@
<SolidColorBrush x:Key="ThemeForegroundBrush" Color="{StaticResource ThemeForegroundColor}" />
<SolidColorBrush x:Key="HighlightBrush" Color="{StaticResource HighlightColor}" />
<SolidColorBrush x:Key="HighlightBrush2" Color="{StaticResource HighlightColor2}" />
<SolidColorBrush x:Key="RefreshVisualizerForeground" Color="Black" />
<SolidColorBrush x:Key="RefreshVisualizerBackground" Color="Transparent" />
</ResourceDictionary>
@ -51,6 +54,7 @@
<Color x:Key="ThemeControlHighlightHighColor">#FF505050</Color>
<Color x:Key="ThemeForegroundColor">#FFDEDEDE</Color>
<Color x:Key="HighlightColor">#FF119EDA</Color>
<Color x:Key="HighlightColor2">#FF096085</Color>
<SolidColorBrush x:Key="ThemeBackgroundBrush" Color="{StaticResource ThemeBackgroundColor}" />
<SolidColorBrush x:Key="ThemeBorderLowBrush" Color="{StaticResource ThemeBorderLowColor}" />
@ -66,6 +70,7 @@
<SolidColorBrush x:Key="ThemeControlHighlightHighBrush" Color="{StaticResource ThemeControlHighlightHighColor}" />
<SolidColorBrush x:Key="ThemeForegroundBrush" Color="{StaticResource ThemeForegroundColor}" />
<SolidColorBrush x:Key="HighlightBrush" Color="{StaticResource HighlightColor}" />
<SolidColorBrush x:Key="HighlightBrush2" Color="{StaticResource HighlightColor2}" />
<SolidColorBrush x:Key="RefreshVisualizerForeground" Color="White" />
<SolidColorBrush x:Key="RefreshVisualizerBackground" Color="Transparent" />

1
src/Avalonia.Themes.Simple/Controls/ComboBox.xaml

@ -3,6 +3,7 @@
<ControlTheme x:Key="{x:Type ComboBox}"
TargetType="ComboBox">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="{DynamicResource ThemeForegroundBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource ThemeBorderMidBrush}" />
<Setter Property="BorderThickness" Value="{DynamicResource ThemeBorderThickness}" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />

1
src/Avalonia.Themes.Simple/Controls/DataValidationErrors.xaml

@ -30,7 +30,6 @@
Background="Transparent">
<Canvas.Styles>
<Style Selector="ToolTip">
<Setter Property="Background" Value="{DynamicResource ErrorLowBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource ErrorBrush}" />
</Style>
</Canvas.Styles>

4
src/Skia/Avalonia.Skia/TextShaperImpl.cs

@ -56,8 +56,6 @@ namespace Avalonia.Skia
var shapedBuffer = new ShapedBuffer(text, bufferLength, typeface, fontRenderingEmSize, bidiLevel);
var targetInfos = shapedBuffer.GlyphInfos;
var glyphInfos = buffer.GetGlyphInfoSpan();
var glyphPositions = buffer.GetGlyphPositionSpan();
@ -83,7 +81,7 @@ namespace Avalonia.Skia
4 * typeface.GetGlyphAdvance(glyphIndex) * textScale;
}
targetInfos[i] = new Media.TextFormatting.GlyphInfo(glyphIndex, glyphCluster, glyphAdvance, glyphOffset);
shapedBuffer[i] = new Media.TextFormatting.GlyphInfo(glyphIndex, glyphCluster, glyphAdvance, glyphOffset);
}
return shapedBuffer;

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

@ -52,8 +52,6 @@ namespace Avalonia.Direct2D1.Media
var shapedBuffer = new ShapedBuffer(text, bufferLength, typeface, fontRenderingEmSize, bidiLevel);
var targetInfos = shapedBuffer.GlyphInfos;
var glyphInfos = buffer.GetGlyphInfoSpan();
var glyphPositions = buffer.GetGlyphPositionSpan();
@ -79,7 +77,7 @@ namespace Avalonia.Direct2D1.Media
4 * typeface.GetGlyphAdvance(glyphIndex) * textScale;
}
targetInfos[i] = new Avalonia.Media.TextFormatting.GlyphInfo(glyphIndex, glyphCluster, glyphAdvance, glyphOffset);
shapedBuffer[i] = new Avalonia.Media.TextFormatting.GlyphInfo(glyphIndex, glyphCluster, glyphAdvance, glyphOffset);
}
return shapedBuffer;

1
src/tools/DevAnalyzers/DevAnalyzers.csproj

@ -3,6 +3,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Nullable>enable</Nullable>
<EnforceExtendedAnalyzerRules>True</EnforceExtendedAnalyzerRules>
</PropertyGroup>
<ItemGroup>

1
src/tools/DevGenerators/DevGenerators.csproj

@ -4,6 +4,7 @@
<TargetFramework>netstandard2.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<EnforceExtendedAnalyzerRules>True</EnforceExtendedAnalyzerRules>
</PropertyGroup>
<ItemGroup>

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

@ -216,12 +216,12 @@ namespace Avalonia.Skia.UnitTests.Media
shapedBuffer.GlyphTypeface,
shapedBuffer.FontRenderingEmSize,
shapedBuffer.Text,
shapedBuffer.GlyphInfos,
shapedBuffer,
biDiLevel: shapedBuffer.BidiLevel);
if(shapedBuffer.BidiLevel == 1)
{
shapedBuffer.GlyphInfos.Span.Reverse();
shapedBuffer.Reverse();
}
return glyphRun;

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

@ -199,7 +199,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
=> textLayout.TextLines
.Select(line => string.Join('|', line.TextRuns
.Cast<ShapedTextRun>()
.SelectMany(run => run.ShapedBuffer.GlyphInfos, (_, glyph) => glyph.GlyphIndex)))
.SelectMany(run => run.ShapedBuffer, (_, glyph) => glyph.GlyphIndex)))
.ToList();
}
@ -489,7 +489,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
{
var shapedRun = (ShapedTextRun)textRun;
var glyphClusters = shapedRun.ShapedBuffer.GlyphInfos.Select(glyph => glyph.GlyphCluster).ToArray();
var glyphClusters = shapedRun.ShapedBuffer.Select(glyph => glyph.GlyphCluster).ToArray();
var expected = clusters.Skip(index).Take(glyphClusters.Length).ToArray();
@ -522,11 +522,11 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
Assert.Equal(expectedLength, ((ShapedTextRun)layout.TextLines[0].TextRuns[0]).GlyphRun.GlyphInfos.Count);
Assert.Equal(5, ((ShapedTextRun)layout.TextLines[0].TextRuns[0]).ShapedBuffer.GlyphInfos[5].GlyphCluster);
Assert.Equal(5, ((ShapedTextRun)layout.TextLines[0].TextRuns[0]).ShapedBuffer[5].GlyphCluster);
if (expectedLength == 7)
{
Assert.Equal(5, ((ShapedTextRun)layout.TextLines[0].TextRuns[0]).ShapedBuffer.GlyphInfos[6].GlyphCluster);
Assert.Equal(5, ((ShapedTextRun)layout.TextLines[0].TextRuns[0]).ShapedBuffer[6].GlyphCluster);
}
}
}
@ -783,7 +783,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
var rects = layout.TextLines
.SelectMany(x => x.TextRuns.Cast<ShapedTextRun>())
.SelectMany(x => x.ShapedBuffer.GlyphInfos, (_, glyph) => glyph.GlyphAdvance)
.SelectMany(x => x.ShapedBuffer, (_, glyph) => glyph.GlyphAdvance)
.ToArray();
for (var i = 0; i < SingleLineText.Length; i++)
@ -939,7 +939,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
var firstRun = (ShapedTextRun)textLine.TextRuns[0];
var firstCluster = firstRun.ShapedBuffer.GlyphInfos[0].GlyphCluster;
var firstCluster = firstRun.ShapedBuffer[0].GlyphCluster;
var characterHit = textLine.GetCharacterHitFromDistance(0);
@ -953,7 +953,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
distance = textLine.GetDistanceFromCharacterHit(new CharacterHit(characterHit.FirstCharacterIndex));
var firstAdvance = firstRun.ShapedBuffer.GlyphInfos[0].GlyphAdvance;
var firstAdvance = firstRun.ShapedBuffer[0].GlyphAdvance;
Assert.Equal(firstAdvance, distance, 5);
@ -996,9 +996,9 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
var shapedRuns = textLine.TextRuns.Cast<ShapedTextRun>().ToList();
var clusters = shapedRuns.SelectMany(x => x.ShapedBuffer.GlyphInfos, (_, glyph) => glyph.GlyphCluster).ToList();
var clusters = shapedRuns.SelectMany(x => x.ShapedBuffer, (_, glyph) => glyph.GlyphCluster).ToList();
var glyphAdvances = shapedRuns.SelectMany(x => x.ShapedBuffer.GlyphInfos, (_, glyph) => glyph.GlyphAdvance).ToList();
var glyphAdvances = shapedRuns.SelectMany(x => x.ShapedBuffer, (_, glyph) => glyph.GlyphAdvance).ToList();
var currentX = 0.0;

14
tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLineTests.cs

@ -95,7 +95,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
{
var shapedRun = (ShapedTextRun)textRun;
var runClusters = shapedRun.ShapedBuffer.GlyphInfos.Select(glyph => glyph.GlyphCluster);
var runClusters = shapedRun.ShapedBuffer.Select(glyph => glyph.GlyphCluster);
clusters.AddRange(shapedRun.IsReversed ? runClusters.Reverse() : runClusters);
}
@ -142,7 +142,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
{
var shapedRun = (ShapedTextRun)textRun;
var runClusters = shapedRun.ShapedBuffer.GlyphInfos.Select(glyph => glyph.GlyphCluster);
var runClusters = shapedRun.ShapedBuffer.Select(glyph => glyph.GlyphCluster);
clusters.AddRange(shapedRun.IsReversed ? runClusters.Reverse() : runClusters);
}
@ -249,7 +249,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
var clusters = textLine.TextRuns
.Cast<ShapedTextRun>()
.SelectMany(x => x.ShapedBuffer.GlyphInfos, (_, glyph) => glyph.GlyphCluster)
.SelectMany(x => x.ShapedBuffer, (_, glyph) => glyph.GlyphCluster)
.ToArray();
var previousCharacterHit = new CharacterHit(text.Length);
@ -752,7 +752,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
{
var shapedBuffer = textRun.ShapedBuffer;
var currentClusters = shapedBuffer.GlyphInfos.Select(glyph => glyph.GlyphCluster).ToList();
var currentClusters = shapedBuffer.Select(glyph => glyph.GlyphCluster).ToList();
foreach (var currentCluster in currentClusters)
{
@ -785,11 +785,11 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
{
var shapedBuffer = textRun.ShapedBuffer;
for (var index = 0; index < shapedBuffer.GlyphInfos.Length; index++)
for (var index = 0; index < shapedBuffer.Length; index++)
{
var currentCluster = shapedBuffer.GlyphInfos[index].GlyphCluster;
var currentCluster = shapedBuffer[index].GlyphCluster;
var advance = shapedBuffer.GlyphInfos[index].GlyphAdvance;
var advance = shapedBuffer[index].GlyphAdvance;
if (lastCluster != currentCluster)
{

10
tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextShaperTests.cs

@ -19,10 +19,10 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
var shapedBuffer = TextShaper.Current.ShapeText(text, options);
Assert.Equal(shapedBuffer.Length, text.Length);
Assert.Equal(shapedBuffer.GlyphInfos.Length, text.Length);
Assert.Equal(0, shapedBuffer.GlyphInfos[0].GlyphCluster);
Assert.Equal(1, shapedBuffer.GlyphInfos[1].GlyphCluster);
Assert.Equal(1, shapedBuffer.GlyphInfos[2].GlyphCluster);
Assert.Equal(shapedBuffer.Length, text.Length);
Assert.Equal(0, shapedBuffer[0].GlyphCluster);
Assert.Equal(1, shapedBuffer[1].GlyphCluster);
Assert.Equal(1, shapedBuffer[2].GlyphCluster);
}
}
@ -36,7 +36,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
var shapedBuffer = TextShaper.Current.ShapeText(text, options);
Assert.Equal(shapedBuffer.Length, text.Length);
Assert.Equal(100, shapedBuffer.GlyphInfos[0].GlyphAdvance);
Assert.Equal(100, shapedBuffer[0].GlyphAdvance);
}
}

4
tests/Avalonia.UnitTests/HarfBuzzTextShaperImpl.cs

@ -52,8 +52,6 @@ namespace Avalonia.UnitTests
var shapedBuffer = new ShapedBuffer(text, bufferLength, typeface, fontRenderingEmSize, bidiLevel);
var targetInfos = shapedBuffer.GlyphInfos;
var glyphInfos = buffer.GetGlyphInfoSpan();
var glyphPositions = buffer.GetGlyphPositionSpan();
@ -79,7 +77,7 @@ namespace Avalonia.UnitTests
4 * typeface.GetGlyphAdvance(glyphIndex) * textScale;
}
targetInfos[i] = new Media.TextFormatting.GlyphInfo(glyphIndex, glyphCluster, glyphAdvance, glyphOffset);
shapedBuffer[i] = new Media.TextFormatting.GlyphInfo(glyphIndex, glyphCluster, glyphAdvance, glyphOffset);
}
return shapedBuffer;

3
tests/Avalonia.UnitTests/MockTextShaperImpl.cs

@ -13,7 +13,6 @@ namespace Avalonia.UnitTests
var fontRenderingEmSize = options.FontRenderingEmSize;
var bidiLevel = options.BidiLevel;
var shapedBuffer = new ShapedBuffer(text, text.Length, typeface, fontRenderingEmSize, bidiLevel);
var targetInfos = shapedBuffer.GlyphInfos;
var textSpan = text.Span;
var textStartIndex = TextTestHelper.GetStartCharIndex(text);
@ -27,7 +26,7 @@ namespace Avalonia.UnitTests
for (var j = 0; j < count; ++j)
{
targetInfos[i + j] = new GlyphInfo(glyphIndex, glyphCluster, 10);
shapedBuffer[i + j] = new GlyphInfo(glyphIndex, glyphCluster, 10);
}
i += count;

Loading…
Cancel
Save