Browse Source

Merge pull request #7693 from Gillibald/fixes/textProcessingBugs

Fixes text processing bugs
pull/7754/head
Benedikt Stebner 5 years ago
committed by GitHub
parent
commit
d0f3fedbb6
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 16
      src/Avalonia.Controls/Presenters/TextPresenter.cs
  2. 4
      src/Avalonia.Controls/TextBlock.cs
  3. 131
      src/Avalonia.Controls/TextBox.cs
  4. 36
      src/Avalonia.Visuals/Media/TextFormatting/ShapeableTextCharacters.cs
  5. 12
      src/Avalonia.Visuals/Media/TextFormatting/TextCharacters.cs
  6. 74
      src/Avalonia.Visuals/Media/TextFormatting/TextFormatterImpl.cs
  7. 2
      src/Avalonia.Visuals/Media/TextFormatting/TextLayout.cs
  8. 2
      src/Avalonia.Visuals/Media/TextFormatting/TextLineImpl.cs
  9. 27
      src/Avalonia.Visuals/Utilities/ReadOnlySlice.cs

16
src/Avalonia.Controls/Presenters/TextPresenter.cs

@ -395,9 +395,13 @@ namespace Avalonia.Controls.Presenters
var y = Math.Floor(_caretBounds.Y) + 0.5; var y = Math.Floor(_caretBounds.Y) + 0.5;
var b = Math.Ceiling(_caretBounds.Bottom) - 0.5; var b = Math.Ceiling(_caretBounds.Bottom) - 0.5;
if (x >= Bounds.Width) var caretIndex = _lastCharacterHit.FirstCharacterIndex + _lastCharacterHit.TrailingLength;
var lineIndex = TextLayout.GetLineIndexFromCharacterIndex(caretIndex, _lastCharacterHit.TrailingLength > 0);
var textLine = TextLayout.TextLines[lineIndex];
if (_caretBounds.X > 0 && _caretBounds.X >= textLine.WidthIncludingTrailingWhitespace)
{ {
x = Math.Floor(_caretBounds.X - 1) + 0.5; x -= 1;
} }
return (new Point(x, y), new Point(x, b)); return (new Point(x, y), new Point(x, b));
@ -468,8 +472,8 @@ namespace Avalonia.Controls.Presenters
var typeface = new Typeface(FontFamily, FontStyle, FontWeight); var typeface = new Typeface(FontFamily, FontStyle, FontWeight);
var selectionStart = SelectionStart; var selectionStart = CoerceCaretIndex(SelectionStart);
var selectionEnd = SelectionEnd; var selectionEnd = CoerceCaretIndex(SelectionEnd);
var start = Math.Min(selectionStart, selectionEnd); var start = Math.Min(selectionStart, selectionEnd);
var length = Math.Max(selectionStart, selectionEnd) - start; var length = Math.Max(selectionStart, selectionEnd) - start;
@ -513,9 +517,7 @@ namespace Avalonia.Controls.Presenters
InvalidateArrange(); InvalidateArrange();
var scale = LayoutHelper.GetLayoutScale(this); var measuredSize = PixelSize.FromSize(TextLayout.Bounds.Size, 1);
var measuredSize = PixelSize.FromSize(TextLayout.Bounds.Size, scale);
return new Size(measuredSize.Width, measuredSize.Height); return new Size(measuredSize.Width, measuredSize.Height);
} }

4
src/Avalonia.Controls/TextBlock.cs

@ -550,9 +550,7 @@ namespace Avalonia.Controls
InvalidateArrange(); InvalidateArrange();
var scale = LayoutHelper.GetLayoutScale(this); var measuredSize = PixelSize.FromSize(TextLayout.Bounds.Size, 1);
var measuredSize = PixelSize.FromSize(TextLayout.Bounds.Size, scale);
return new Size(measuredSize.Width, measuredSize.Height).Inflate(padding); return new Size(measuredSize.Width, measuredSize.Height).Inflate(padding);
} }

131
src/Avalonia.Controls/TextBox.cs

@ -257,6 +257,8 @@ namespace Avalonia.Controls
UndoRedoState state; UndoRedoState state;
if (IsUndoEnabled && _undoRedoHelper.TryGetLastState(out state) && state.Text == Text) if (IsUndoEnabled && _undoRedoHelper.TryGetLastState(out state) && state.Text == Text)
_undoRedoHelper.UpdateLastState(); _undoRedoHelper.UpdateLastState();
SelectionStart = SelectionEnd = value;
} }
} }
@ -301,14 +303,15 @@ namespace Avalonia.Controls
{ {
value = CoerceCaretIndex(value); value = CoerceCaretIndex(value);
var changed = SetAndRaise(SelectionStartProperty, ref _selectionStart, value); var changed = SetAndRaise(SelectionStartProperty, ref _selectionStart, value);
if (changed) if (changed)
{ {
UpdateCommandStates(); UpdateCommandStates();
} }
if (value == SelectionEnd) if (SelectionEnd == value && CaretIndex != value)
{ {
CaretIndex = SelectionStart; CaretIndex = value;
} }
} }
} }
@ -330,7 +333,7 @@ namespace Avalonia.Controls
UpdateCommandStates(); UpdateCommandStates();
} }
if (value == SelectionStart) if (SelectionStart == value && CaretIndex != value)
{ {
CaretIndex = value; CaretIndex = value;
} }
@ -352,10 +355,12 @@ namespace Avalonia.Controls
if (!_ignoreTextChanges) if (!_ignoreTextChanges)
{ {
var caretIndex = CaretIndex; var caretIndex = CaretIndex;
var selectionStart = SelectionStart;
var selectionEnd = SelectionEnd;
SelectionStart = CoerceCaretIndex(SelectionStart, value);
SelectionEnd = CoerceCaretIndex(SelectionEnd, value);
CaretIndex = CoerceCaretIndex(caretIndex, value); CaretIndex = CoerceCaretIndex(caretIndex, value);
SelectionStart = CoerceCaretIndex(selectionStart, value);
SelectionEnd = CoerceCaretIndex(selectionEnd, value);
if (SetAndRaise(TextProperty, ref _text, value) && IsUndoEnabled && !_isUndoingRedoing) if (SetAndRaise(TextProperty, ref _text, value) && IsUndoEnabled && !_isUndoingRedoing)
{ {
@ -458,7 +463,7 @@ namespace Avalonia.Controls
/// </summary> /// </summary>
public void ClearSelection() public void ClearSelection()
{ {
SelectionStart = SelectionEnd = CaretIndex; CaretIndex = SelectionStart;
} }
/// <summary> /// <summary>
@ -856,6 +861,7 @@ namespace Avalonia.Controls
movement = true; movement = true;
selection = false; selection = false;
handled = true; handled = true;
CaretIndex = _presenter.CaretIndex;
} }
else if (Match(keymap.MoveCursorToTheEndOfDocument)) else if (Match(keymap.MoveCursorToTheEndOfDocument))
{ {
@ -863,6 +869,7 @@ namespace Avalonia.Controls
movement = true; movement = true;
selection = false; selection = false;
handled = true; handled = true;
CaretIndex = _presenter.CaretIndex;
} }
else if (Match(keymap.MoveCursorToTheStartOfLine)) else if (Match(keymap.MoveCursorToTheStartOfLine))
{ {
@ -870,7 +877,7 @@ namespace Avalonia.Controls
movement = true; movement = true;
selection = false; selection = false;
handled = true; handled = true;
CaretIndex = _presenter.CaretIndex;
} }
else if (Match(keymap.MoveCursorToTheEndOfLine)) else if (Match(keymap.MoveCursorToTheEndOfLine))
{ {
@ -878,6 +885,7 @@ namespace Avalonia.Controls
movement = true; movement = true;
selection = false; selection = false;
handled = true; handled = true;
CaretIndex = _presenter.CaretIndex;
} }
else if (Match(keymap.MoveCursorToTheStartOfDocumentWithSelection)) else if (Match(keymap.MoveCursorToTheStartOfDocumentWithSelection))
{ {
@ -950,7 +958,7 @@ namespace Avalonia.Controls
} }
else else
{ {
SelectionStart = SelectionEnd = _presenter.CaretIndex; CaretIndex = _presenter.CaretIndex;
} }
break; break;
@ -972,7 +980,7 @@ namespace Avalonia.Controls
} }
else else
{ {
SelectionStart = SelectionEnd = _presenter.CaretIndex; CaretIndex = _presenter.CaretIndex;
} }
break; break;
@ -996,6 +1004,8 @@ namespace Avalonia.Controls
SetTextInternal(text.Substring(0, length) + SetTextInternal(text.Substring(0, length) +
text.Substring(caretIndex)); text.Substring(caretIndex));
CaretIndex = _presenter.CaretIndex;
} }
SnapshotUndoRedo(); SnapshotUndoRedo();
@ -1070,8 +1080,6 @@ namespace Avalonia.Controls
{ {
e.Handled = true; e.Handled = true;
} }
CaretIndex = _presenter.CaretIndex;
} }
protected override void OnPointerPressed(PointerPressedEventArgs e) protected override void OnPointerPressed(PointerPressedEventArgs e)
@ -1240,6 +1248,7 @@ namespace Avalonia.Controls
{ {
var text = Text ?? string.Empty; var text = Text ?? string.Empty;
var selectionStart = SelectionStart; var selectionStart = SelectionStart;
var selectionEnd = SelectionEnd;
if (!wholeWord) if (!wholeWord)
{ {
@ -1248,15 +1257,32 @@ namespace Avalonia.Controls
return; return;
} }
_presenter.MoveCaretHorizontal(direction > 0 ? LogicalDirection.Forward : LogicalDirection.Backward);
if (isSelecting) if (isSelecting)
{ {
_presenter.MoveCaretToTextPosition(selectionEnd);
_presenter.MoveCaretHorizontal(direction > 0 ?
LogicalDirection.Forward :
LogicalDirection.Backward);
SelectionEnd = _presenter.CaretIndex; SelectionEnd = _presenter.CaretIndex;
} }
else else
{ {
SelectionStart = SelectionEnd = _presenter.CaretIndex; if (selectionStart != selectionEnd)
{
_presenter.MoveCaretToTextPosition(direction > 0 ?
Math.Max(selectionStart, selectionEnd) :
Math.Min(selectionStart, selectionEnd));
}
else
{
_presenter.MoveCaretHorizontal(direction > 0 ?
LogicalDirection.Forward :
LogicalDirection.Backward);
}
CaretIndex = _presenter.CaretIndex;
} }
} }
else else
@ -1265,14 +1291,19 @@ namespace Avalonia.Controls
if (direction > 0) if (direction > 0)
{ {
offset = StringUtils.NextWord(text, selectionStart) - selectionStart; offset = StringUtils.NextWord(text, selectionEnd) - selectionEnd;
} }
else else
{ {
offset = StringUtils.PreviousWord(text, selectionStart) - selectionStart; offset = StringUtils.PreviousWord(text, selectionEnd) - selectionEnd;
} }
SelectionEnd = CaretIndex + offset; SelectionEnd += offset;
if (!isSelecting)
{
CaretIndex = SelectionEnd;
}
} }
} }
@ -1316,10 +1347,18 @@ namespace Avalonia.Controls
else else
{ {
var textLines = _presenter.TextLayout.TextLines; var textLines = _presenter.TextLayout.TextLines;
var lineIndex = _presenter.TextLayout.GetLineIndexFromCharacterIndex(caretIndex, false); var lineIndex = _presenter.TextLayout.GetLineIndexFromCharacterIndex(caretIndex, true);
var textLine = textLines[lineIndex]; var textLine = textLines[lineIndex];
_presenter.MoveCaretToTextPosition(textLine.TextRange.Start + textLine.TextRange.Length, true); if (caretIndex == textLine.TextRange.Start + textLine.TextRange.Length - textLine.NewLineLength &&
lineIndex + 1 < textLines.Count)
{
textLine = textLines[++lineIndex];
}
var textPosition = textLine.TextRange.Start + textLine.TextRange.Length - textLine.NewLineLength;
_presenter.MoveCaretToTextPosition(textPosition, true);
} }
} }
@ -1330,50 +1369,56 @@ namespace Avalonia.Controls
{ {
SelectionStart = 0; SelectionStart = 0;
SelectionEnd = Text?.Length ?? 0; SelectionEnd = Text?.Length ?? 0;
CaretIndex = SelectionEnd;
} }
private bool DeleteSelection(bool raiseTextChanged = true) private bool DeleteSelection(bool raiseTextChanged = true)
{ {
if (!IsReadOnly) if (IsReadOnly) return true;
{
var selectionStart = SelectionStart;
var selectionEnd = SelectionEnd;
if (selectionStart != selectionEnd) var selectionStart = SelectionStart;
{ var selectionEnd = SelectionEnd;
var start = Math.Min(selectionStart, selectionEnd);
var end = Math.Max(selectionStart, selectionEnd); if (selectionStart != selectionEnd)
var text = Text!;
SetTextInternal(text.Substring(0, start) + text.Substring(end), raiseTextChanged);
CaretIndex = start;
ClearSelection();
return true;
}
else
{
return false;
}
}
else
{ {
var start = Math.Min(selectionStart, selectionEnd);
var end = Math.Max(selectionStart, selectionEnd);
var text = Text!;
SetTextInternal(text.Substring(0, start) + text.Substring(end), raiseTextChanged);
_presenter?.MoveCaretToTextPosition(start);
CaretIndex= start;
ClearSelection();
return true; return true;
} }
CaretIndex = SelectionStart;
return false;
} }
private string GetSelection() private string GetSelection()
{ {
var text = Text; var text = Text;
if (string.IsNullOrEmpty(text)) if (string.IsNullOrEmpty(text))
{
return ""; return "";
}
var selectionStart = SelectionStart; var selectionStart = SelectionStart;
var selectionEnd = SelectionEnd; var selectionEnd = SelectionEnd;
var start = Math.Min(selectionStart, selectionEnd); var start = Math.Min(selectionStart, selectionEnd);
var end = Math.Max(selectionStart, selectionEnd); var end = Math.Max(selectionStart, selectionEnd);
if (start == end || (Text?.Length ?? 0) < end) if (start == end || (Text?.Length ?? 0) < end)
{ {
return ""; return "";
} }
return text.Substring(start, end - start); return text.Substring(start, end - start);
} }
@ -1399,9 +1444,11 @@ namespace Avalonia.Controls
private void SetSelectionForControlBackspace() private void SetSelectionForControlBackspace()
{ {
SelectionStart = CaretIndex; var selectionStart = CaretIndex;
MoveHorizontal(-1, true, false); MoveHorizontal(-1, true, false);
SelectionStart = selectionStart;
} }
private void SetSelectionForControlDelete() private void SetSelectionForControlDelete()
@ -1413,7 +1460,7 @@ namespace Avalonia.Controls
SelectionStart = CaretIndex; SelectionStart = CaretIndex;
MoveHorizontal(1, true, false); MoveHorizontal(1, true, true);
if (SelectionEnd < _text.Length && _text[SelectionEnd] == ' ') if (SelectionEnd < _text.Length && _text[SelectionEnd] == ' ')
{ {

36
src/Avalonia.Visuals/Media/TextFormatting/ShapeableTextCharacters.cs

@ -22,5 +22,41 @@ namespace Avalonia.Media.TextFormatting
public override TextRunProperties Properties { get; } public override TextRunProperties Properties { get; }
public sbyte BidiLevel { get; } public sbyte BidiLevel { get; }
public bool CanShapeTogether(ShapeableTextCharacters shapeableTextCharacters)
{
if (!Text.Buffer.Equals(shapeableTextCharacters.Text.Buffer))
{
return false;
}
if (Text.Start + Text.Length != shapeableTextCharacters.Text.Start)
{
return false;
}
if (BidiLevel != shapeableTextCharacters.BidiLevel)
{
return false;
}
if (!MathUtilities.AreClose(Properties.FontRenderingEmSize,
shapeableTextCharacters.Properties.FontRenderingEmSize))
{
return false;
}
if (Properties.Typeface != shapeableTextCharacters.Properties.Typeface)
{
return false;
}
if (Properties.BaselineAlignment != shapeableTextCharacters.Properties.BaselineAlignment)
{
return false;
}
return true;
}
} }
} }

12
src/Avalonia.Visuals/Media/TextFormatting/TextCharacters.cs

@ -176,6 +176,12 @@ namespace Avalonia.Media.TextFormatting
var currentScript = currentGrapheme.FirstCodepoint.Script; var currentScript = currentGrapheme.FirstCodepoint.Script;
//Stop at the first missing glyph
if (!currentGrapheme.FirstCodepoint.IsBreakChar && !font.TryGetGlyph(currentGrapheme.FirstCodepoint, out _))
{
break;
}
if (currentScript != script) if (currentScript != script)
{ {
if (script is Script.Unknown || currentScript != Script.Common && if (script is Script.Unknown || currentScript != Script.Common &&
@ -192,12 +198,6 @@ namespace Avalonia.Media.TextFormatting
} }
} }
//Stop at the first missing glyph
if (!currentGrapheme.FirstCodepoint.IsBreakChar && !font.TryGetGlyph(currentGrapheme.FirstCodepoint, out _))
{
break;
}
length += currentGrapheme.Text.Length; length += currentGrapheme.Text.Length;
} }

74
src/Avalonia.Visuals/Media/TextFormatting/TextFormatterImpl.cs

@ -1,6 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices;
using Avalonia.Media.TextFormatting.Unicode; using Avalonia.Media.TextFormatting.Unicode;
using Avalonia.Utilities; using Avalonia.Utilities;
@ -171,25 +173,83 @@ namespace Avalonia.Media.TextFormatting
resolvedFlowDirection = resolvedFlowDirection =
(resolvedEmbeddingLevel & 1) == 0 ? FlowDirection.LeftToRight : FlowDirection.RightToLeft; (resolvedEmbeddingLevel & 1) == 0 ? FlowDirection.LeftToRight : FlowDirection.RightToLeft;
foreach (var shapeableRuns in CoalesceLevels(textRuns, biDi.ResolvedLevels)) var shapeableRuns = new List<ShapeableTextCharacters>(textRuns.Count);
foreach (var coalescedRuns in CoalesceLevels(textRuns, biDi.ResolvedLevels))
{
shapeableRuns.AddRange(coalescedRuns);
}
for (var index = 0; index < shapeableRuns.Count; index++)
{ {
for (var index = 0; index < shapeableRuns.Count; index++) var currentRun = shapeableRuns[index];
var groupedRuns = new List<ShapeableTextCharacters>(2) { currentRun };
var text = currentRun.Text;
var start = currentRun.Text.Start;
var length = currentRun.Text.Length;
var bufferOffset = currentRun.Text.BufferOffset;
while (index + 1 < shapeableRuns.Count)
{ {
var currentRun = shapeableRuns[index]; var nextRun = shapeableRuns[index + 1];
if (currentRun.CanShapeTogether(nextRun))
{
groupedRuns.Add(nextRun);
length += nextRun.Text.Length;
if (start > nextRun.Text.Start)
{
start = nextRun.Text.Start;
}
if (bufferOffset > nextRun.Text.BufferOffset)
{
bufferOffset = nextRun.Text.BufferOffset;
}
text = new ReadOnlySlice<char>(text.Buffer, start, length, bufferOffset);
var shapedBuffer = TextShaper.Current.ShapeText(currentRun.Text, currentRun.Properties.Typeface.GlyphTypeface, index++;
currentRun.Properties.FontRenderingEmSize, currentRun.Properties.CultureInfo, currentRun.BidiLevel);
var shapedCharacters = new ShapedTextCharacters(shapedBuffer, currentRun.Properties); currentRun = nextRun;
continue;
}
shapedTextCharacters.Add(shapedCharacters); break;
} }
shapedTextCharacters.AddRange(ShapeTogether(groupedRuns, text));
} }
return shapedTextCharacters; return shapedTextCharacters;
} }
private static IReadOnlyList<ShapedTextCharacters> ShapeTogether(
IReadOnlyList<ShapeableTextCharacters> textRuns, ReadOnlySlice<char> text)
{
var shapedRuns = new List<ShapedTextCharacters>(textRuns.Count);
var firstRun = textRuns[0];
var shapedBuffer = TextShaper.Current.ShapeText(text, firstRun.Properties.Typeface.GlyphTypeface,
firstRun.Properties.FontRenderingEmSize, firstRun.Properties.CultureInfo, firstRun.BidiLevel);
for (var i = 0; i < textRuns.Count; i++)
{
var currentRun = textRuns[i];
var splitResult = shapedBuffer.Split(currentRun.Text.Length);
shapedRuns.Add(new ShapedTextCharacters(splitResult.First, currentRun.Properties));
shapedBuffer = splitResult.Second!;
}
return shapedRuns;
}
/// <summary> /// <summary>
/// Coalesces ranges of the same bidi level to form <see cref="ShapeableTextCharacters"/> /// Coalesces ranges of the same bidi level to form <see cref="ShapeableTextCharacters"/>
/// </summary> /// </summary>

2
src/Avalonia.Visuals/Media/TextFormatting/TextLayout.cs

@ -607,7 +607,7 @@ namespace Avalonia.Media.TextFormatting
textLines.Add(textLine); textLines.Add(textLine);
UpdateBounds(textLine,ref left, ref width, ref height); UpdateBounds(textLine, ref left, ref width, ref height);
previousLine = textLine; previousLine = textLine;

2
src/Avalonia.Visuals/Media/TextFormatting/TextLineImpl.cs

@ -553,7 +553,7 @@ namespace Avalonia.Media.TextFormatting
out _); out _);
var isAtEnd = foundCharacterHit.FirstCharacterIndex + foundCharacterHit.TrailingLength == var isAtEnd = foundCharacterHit.FirstCharacterIndex + foundCharacterHit.TrailingLength ==
TextRange.Length; TextRange.Start + TextRange.Length;
if (isAtEnd && !run.GlyphRun.IsLeftToRight) if (isAtEnd && !run.GlyphRun.IsLeftToRight)
{ {

27
src/Avalonia.Visuals/Utilities/ReadOnlySlice.cs

@ -13,7 +13,7 @@ namespace Avalonia.Utilities
[DebuggerTypeProxy(typeof(ReadOnlySlice<>.ReadOnlySliceDebugView))] [DebuggerTypeProxy(typeof(ReadOnlySlice<>.ReadOnlySliceDebugView))]
public readonly struct ReadOnlySlice<T> : IReadOnlyList<T> where T : struct public readonly struct ReadOnlySlice<T> : IReadOnlyList<T> where T : struct
{ {
private readonly int _offset; private readonly int _bufferOffset;
/// <summary> /// <summary>
/// Gets an empty <see cref="ReadOnlySlice{T}"/> /// Gets an empty <see cref="ReadOnlySlice{T}"/>
@ -24,7 +24,7 @@ namespace Avalonia.Utilities
public ReadOnlySlice(ReadOnlyMemory<T> buffer) : this(buffer, 0, buffer.Length) { } public ReadOnlySlice(ReadOnlyMemory<T> buffer) : this(buffer, 0, buffer.Length) { }
public ReadOnlySlice(ReadOnlyMemory<T> buffer, int start, int length, int offset = 0) public ReadOnlySlice(ReadOnlyMemory<T> buffer, int start, int length, int bufferOffset = 0)
{ {
#if DEBUG #if DEBUG
if (start.CompareTo(0) < 0) if (start.CompareTo(0) < 0)
@ -41,7 +41,7 @@ namespace Avalonia.Utilities
_buffer = buffer; _buffer = buffer;
Start = start; Start = start;
Length = length; Length = length;
_offset = offset; _bufferOffset = bufferOffset;
} }
/// <summary> /// <summary>
@ -74,12 +74,17 @@ namespace Avalonia.Utilities
public bool IsEmpty => Length == 0; public bool IsEmpty => Length == 0;
/// <summary> /// <summary>
/// The underlying span. /// Get the underlying span.
/// </summary> /// </summary>
public ReadOnlySpan<T> Span => _buffer.Span.Slice(_offset, Length); public ReadOnlySpan<T> Span => _buffer.Span.Slice(_bufferOffset, Length);
/// <summary> /// <summary>
/// The underlying buffer. /// Get the buffer offset.
/// </summary>
public int BufferOffset => _bufferOffset;
/// <summary>
/// Get the underlying buffer.
/// </summary> /// </summary>
public ReadOnlyMemory<T> Buffer => _buffer; public ReadOnlyMemory<T> Buffer => _buffer;
@ -124,17 +129,17 @@ namespace Avalonia.Utilities
return Empty; return Empty;
} }
if (start < 0 || _offset + start > _buffer.Length - 1) if (start < 0 || _bufferOffset + start > _buffer.Length - 1)
{ {
throw new ArgumentOutOfRangeException(nameof(start)); throw new ArgumentOutOfRangeException(nameof(start));
} }
if (_offset + start + length > _buffer.Length) if (_bufferOffset + start + length > _buffer.Length)
{ {
throw new ArgumentOutOfRangeException(nameof(length)); throw new ArgumentOutOfRangeException(nameof(length));
} }
return new ReadOnlySlice<T>(_buffer, start, length, _offset); return new ReadOnlySlice<T>(_buffer, start, length, _bufferOffset);
} }
/// <summary> /// <summary>
@ -154,7 +159,7 @@ namespace Avalonia.Utilities
throw new ArgumentOutOfRangeException(nameof(length)); throw new ArgumentOutOfRangeException(nameof(length));
} }
return new ReadOnlySlice<T>(_buffer, Start, length, _offset); return new ReadOnlySlice<T>(_buffer, Start, length, _bufferOffset);
} }
/// <summary> /// <summary>
@ -174,7 +179,7 @@ namespace Avalonia.Utilities
throw new ArgumentOutOfRangeException(nameof(length)); throw new ArgumentOutOfRangeException(nameof(length));
} }
return new ReadOnlySlice<T>(_buffer, Start + length, Length - length, _offset + length); return new ReadOnlySlice<T>(_buffer, Start + length, Length - length, _bufferOffset + length);
} }
/// <summary> /// <summary>

Loading…
Cancel
Save