|
|
|
@ -1,6 +1,4 @@ |
|
|
|
using System; |
|
|
|
using System.Buffers; |
|
|
|
using System.Runtime.InteropServices; |
|
|
|
|
|
|
|
namespace Avalonia.Media.TextFormatting |
|
|
|
{ |
|
|
|
@ -26,15 +24,6 @@ namespace Avalonia.Media.TextFormatting |
|
|
|
public CharacterBufferReference(string characterString, int offsetToFirstChar = 0) |
|
|
|
: this(characterString.AsMemory(), offsetToFirstChar) |
|
|
|
{ } |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Construct character buffer reference from unsafe character string
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="unsafeCharacterString">pointer to character string</param>
|
|
|
|
/// <param name="characterLength">character length of unsafe string</param>
|
|
|
|
public unsafe CharacterBufferReference(char* unsafeCharacterString, int characterLength) |
|
|
|
: this(new UnmanagedMemoryManager<char>(unsafeCharacterString, characterLength).Memory, 0) |
|
|
|
{ } |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Construct character buffer reference from memory buffer
|
|
|
|
@ -58,6 +47,17 @@ namespace Avalonia.Media.TextFormatting |
|
|
|
OffsetToFirstChar = offsetToFirstChar; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the character memory buffer
|
|
|
|
/// </summary>
|
|
|
|
public ReadOnlyMemory<char> CharacterBuffer { get; } |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the character offset relative to the beginning of buffer to
|
|
|
|
/// the first character of the run
|
|
|
|
/// </summary>
|
|
|
|
public int OffsetToFirstChar { get; } |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Compute hash code
|
|
|
|
/// </summary>
|
|
|
|
@ -110,67 +110,6 @@ namespace Avalonia.Media.TextFormatting |
|
|
|
{ |
|
|
|
return !(left == right); |
|
|
|
} |
|
|
|
|
|
|
|
public ReadOnlyMemory<char> CharacterBuffer { get; } |
|
|
|
|
|
|
|
public int OffsetToFirstChar { get; } |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// A MemoryManager over a raw pointer
|
|
|
|
/// </summary>
|
|
|
|
/// <remarks>The pointer is assumed to be fully unmanaged, or externally pinned - no attempt will be made to pin this data</remarks>
|
|
|
|
public sealed unsafe class UnmanagedMemoryManager<T> : MemoryManager<T> |
|
|
|
where T : unmanaged |
|
|
|
{ |
|
|
|
private readonly T* _pointer; |
|
|
|
private readonly int _length; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Create a new UnmanagedMemoryManager instance at the given pointer and size
|
|
|
|
/// </summary>
|
|
|
|
/// <remarks>It is assumed that the span provided is already unmanaged or externally pinned</remarks>
|
|
|
|
public UnmanagedMemoryManager(Span<T> span) |
|
|
|
{ |
|
|
|
fixed (T* ptr = &MemoryMarshal.GetReference(span)) |
|
|
|
{ |
|
|
|
_pointer = ptr; |
|
|
|
_length = span.Length; |
|
|
|
} |
|
|
|
} |
|
|
|
/// <summary>
|
|
|
|
/// Create a new UnmanagedMemoryManager instance at the given pointer and size
|
|
|
|
/// </summary>
|
|
|
|
public UnmanagedMemoryManager(T* pointer, int length) |
|
|
|
{ |
|
|
|
if (length < 0) |
|
|
|
throw new ArgumentOutOfRangeException(nameof(length)); |
|
|
|
_pointer = pointer; |
|
|
|
_length = length; |
|
|
|
} |
|
|
|
/// <summary>
|
|
|
|
/// Obtains a span that represents the region
|
|
|
|
/// </summary>
|
|
|
|
public override Span<T> GetSpan() => new Span<T>(_pointer, _length); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Provides access to a pointer that represents the data (note: no actual pin occurs)
|
|
|
|
/// </summary>
|
|
|
|
public override MemoryHandle Pin(int elementIndex = 0) |
|
|
|
{ |
|
|
|
if (elementIndex < 0 || elementIndex >= _length) |
|
|
|
throw new ArgumentOutOfRangeException(nameof(elementIndex)); |
|
|
|
return new MemoryHandle(_pointer + elementIndex); |
|
|
|
} |
|
|
|
/// <summary>
|
|
|
|
/// Has no effect
|
|
|
|
/// </summary>
|
|
|
|
public override void Unpin() { } |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Releases all resources associated with this object
|
|
|
|
/// </summary>
|
|
|
|
protected override void Dispose(bool disposing) { } |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|