|
|
|
@ -6,6 +6,7 @@ using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Runtime.CompilerServices; |
|
|
|
using System.Threading; |
|
|
|
using Avalonia.Collections.Pooled; |
|
|
|
using Avalonia.Utilities; |
|
|
|
|
|
|
|
namespace Avalonia.Media.TextFormatting.Unicode |
|
|
|
@ -27,7 +28,7 @@ namespace Avalonia.Media.TextFormatting.Unicode |
|
|
|
/// as much as possible.
|
|
|
|
/// </para>
|
|
|
|
/// </remarks>
|
|
|
|
internal sealed class BidiAlgorithm |
|
|
|
internal struct BidiAlgorithm : IDisposable |
|
|
|
{ |
|
|
|
/// <summary>
|
|
|
|
/// The original BiDiClass classes as provided by the caller
|
|
|
|
@ -66,7 +67,7 @@ namespace Avalonia.Media.TextFormatting.Unicode |
|
|
|
/// The forward mapping maps the start index to the end index.
|
|
|
|
/// The reverse mapping maps the end index to the start index.
|
|
|
|
/// </remarks>
|
|
|
|
private readonly BidiDictionary<int, int> _isolatePairs = new BidiDictionary<int, int>(); |
|
|
|
private BidiDictionary<int, int>? _isolatePairs; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// The working BiDi classes
|
|
|
|
@ -118,7 +119,7 @@ namespace Avalonia.Media.TextFormatting.Unicode |
|
|
|
/// <summary>
|
|
|
|
/// A stack of pending isolate openings used by FindIsolatePairs()
|
|
|
|
/// </summary>
|
|
|
|
private readonly Stack<int> _pendingIsolateOpenings = new Stack<int>(); |
|
|
|
private Stack<int>? _pendingIsolateOpenings; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// The level of the isolating run currently being processed
|
|
|
|
@ -184,7 +185,7 @@ namespace Avalonia.Media.TextFormatting.Unicode |
|
|
|
/// <summary>
|
|
|
|
/// Initializes a new instance of the <see cref="BidiAlgorithm"/> class.
|
|
|
|
/// </summary>
|
|
|
|
internal BidiAlgorithm() |
|
|
|
public BidiAlgorithm() |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
|
@ -227,7 +228,7 @@ namespace Avalonia.Media.TextFormatting.Unicode |
|
|
|
ArraySlice<sbyte>? outLevels) |
|
|
|
{ |
|
|
|
// Reset state
|
|
|
|
_isolatePairs.Clear(); |
|
|
|
_isolatePairs?.Clear(); |
|
|
|
_workingClassesBuffer.Clear(); |
|
|
|
_levelRuns.Clear(); |
|
|
|
_resolvedLevelsBuffer.Clear(); |
|
|
|
@ -323,7 +324,7 @@ namespace Avalonia.Media.TextFormatting.Unicode |
|
|
|
// Skip isolate pairs
|
|
|
|
// (Because we're working with a slice, we need to adjust the indices
|
|
|
|
// we're using for the isolatePairs map)
|
|
|
|
if (_isolatePairs.TryGetValue(data.Start + i, out i)) |
|
|
|
if (_isolatePairs?.TryGetValue(data.Start + i, out i) == true) |
|
|
|
{ |
|
|
|
i -= data.Start; |
|
|
|
} |
|
|
|
@ -358,7 +359,7 @@ namespace Avalonia.Media.TextFormatting.Unicode |
|
|
|
_hasIsolates = false; |
|
|
|
|
|
|
|
// BD9...
|
|
|
|
_pendingIsolateOpenings.Clear(); |
|
|
|
_pendingIsolateOpenings?.Clear(); |
|
|
|
|
|
|
|
for (var i = 0; i < _originalClasses.Length; i++) |
|
|
|
{ |
|
|
|
@ -370,14 +371,16 @@ namespace Avalonia.Media.TextFormatting.Unicode |
|
|
|
case BidiClass.RightToLeftIsolate: |
|
|
|
case BidiClass.FirstStrongIsolate: |
|
|
|
{ |
|
|
|
_pendingIsolateOpenings ??= new Stack<int>(); |
|
|
|
_pendingIsolateOpenings.Push(i); |
|
|
|
_hasIsolates = true; |
|
|
|
break; |
|
|
|
} |
|
|
|
case BidiClass.PopDirectionalIsolate: |
|
|
|
{ |
|
|
|
if (_pendingIsolateOpenings.Count > 0) |
|
|
|
if (_pendingIsolateOpenings?.Count > 0) |
|
|
|
{ |
|
|
|
_isolatePairs ??= new BidiDictionary<int, int>(); |
|
|
|
_isolatePairs.Add(_pendingIsolateOpenings.Pop(), i); |
|
|
|
} |
|
|
|
|
|
|
|
@ -498,7 +501,7 @@ namespace Avalonia.Media.TextFormatting.Unicode |
|
|
|
|
|
|
|
if (resolvedIsolate == BidiClass.FirstStrongIsolate) |
|
|
|
{ |
|
|
|
if (!_isolatePairs.TryGetValue(i, out var endOfIsolate)) |
|
|
|
if (_isolatePairs == null || !_isolatePairs.TryGetValue(i, out var endOfIsolate)) |
|
|
|
{ |
|
|
|
endOfIsolate = _originalClasses.Length; |
|
|
|
} |
|
|
|
@ -829,7 +832,7 @@ namespace Avalonia.Media.TextFormatting.Unicode |
|
|
|
var lastCharacterIndex = _isolatedRunMapping[_isolatedRunMapping.Length - 1]; |
|
|
|
var lastType = _originalClasses[lastCharacterIndex]; |
|
|
|
if ((lastType == BidiClass.LeftToRightIsolate || lastType == BidiClass.RightToLeftIsolate || lastType == BidiClass.FirstStrongIsolate) && |
|
|
|
_isolatePairs.TryGetValue(lastCharacterIndex, out var nextRunIndex)) |
|
|
|
_isolatePairs?.TryGetValue(lastCharacterIndex, out var nextRunIndex) == true) |
|
|
|
{ |
|
|
|
// Find the continuing run index
|
|
|
|
runIndex = FindRunForIndex(nextRunIndex); |
|
|
|
@ -1714,5 +1717,13 @@ namespace Avalonia.Media.TextFormatting.Unicode |
|
|
|
|
|
|
|
public BidiClass Eos { get; } |
|
|
|
} |
|
|
|
|
|
|
|
public void Dispose() |
|
|
|
{ |
|
|
|
_workingClassesBuffer.Dispose(); |
|
|
|
_resolvedLevelsBuffer.Dispose(); |
|
|
|
_x9Map.Dispose(); |
|
|
|
_isolatedRunMapping.Dispose(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|