// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/// @docImport 'package:flutter/widgets.dart';
///
/// @docImport 'editable.dart';
library;

import 'dart:math' as math;
import 'dart:ui'
    as ui
    show
        BoxHeightStyle,
        BoxWidthStyle,
        Gradient,
        LineMetrics,
        PlaceholderAlignment,
        Shader,
        TextBox,
        TextHeightBehavior;

import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/semantics.dart';
import 'package:flutter/services.dart';

import 'box.dart';
import 'debug.dart';
import 'layer.dart';
import 'layout_helper.dart';
import 'object.dart';
import 'selection.dart';

/// The start and end positions for a text boundary.
typedef _TextBoundaryRecord = ({TextPosition boundaryStart, TextPosition boundaryEnd});

/// Signature for a function that determines the [_TextBoundaryRecord] at the given
/// [TextPosition].
typedef _TextBoundaryAtPosition = _TextBoundaryRecord Function(TextPosition position);

/// Signature for a function that determines the [_TextBoundaryRecord] at the given
/// [TextPosition], for the given [String].
typedef _TextBoundaryAtPositionInText =
    _TextBoundaryRecord Function(TextPosition position, String text);

const String _kEllipsis = '\u2026';

/// Used by the [RenderParagraph] to map its rendering children to their
/// corresponding semantics nodes.
///
/// The [RichText] uses this to tag the relation between its placeholder spans
/// and their semantics nodes.
@immutable
class PlaceholderSpanIndexSemanticsTag extends SemanticsTag {
  /// Creates a semantics tag with the input `index`.
  ///
  /// Different [PlaceholderSpanIndexSemanticsTag]s with the same `index` are
  /// consider the same.
  const PlaceholderSpanIndexSemanticsTag(this.index)
    : super('PlaceholderSpanIndexSemanticsTag($index)');

  /// The index of this tag.
  final int index;

  @override
  bool operator ==(Object other) {
    return other is PlaceholderSpanIndexSemanticsTag && other.index == index;
  }

  @override
  int get hashCode => Object.hash(PlaceholderSpanIndexSemanticsTag, index);
}

/// Parent data used by [RenderParagraph] and [RenderEditable] to annotate
/// inline contents (such as [WidgetSpan]s) with.
class TextParentData extends ParentData with ContainerParentDataMixin<RenderBox> {
  /// The offset at which to paint the child in the parent's coordinate system.
  ///
  /// A `null` value indicates this inline widget is not laid out. For instance,
  /// when the inline widget has never been laid out, or the inline widget is
  /// ellipsized away.
  Offset? get offset => _offset;
  Offset? _offset;

  /// The [PlaceholderSpan] associated with this render child.
  ///
  /// This field is usually set by a [ParentDataWidget], and is typically not
  /// null when `performLayout` is called.
  PlaceholderSpan? span;

  @override
  void detach() {
    span = null;
    _offset = null;
    super.detach();
  }

  @override
  String toString() => 'widget: $span, ${offset == null ? "not laid out" : "offset: $offset"}';
}

/// A mixin that provides useful default behaviors for text [RenderBox]es
/// ([RenderParagraph] and [RenderEditable] for example) with inline content
/// children managed by the [ContainerRenderObjectMixin] mixin.
///
/// This mixin assumes every child managed by the [ContainerRenderObjectMixin]
/// mixin corresponds to a [PlaceholderSpan], and they are organized in logical
/// order of the text (the order each [PlaceholderSpan] is encountered when the
/// user reads the text).
///
/// To use this mixin in a [RenderBox] class:
///
///  * Call [layoutInlineChildren] in the `performLayout` and `computeDryLayout`
///    implementation, and during intrinsic size calculations, to get the size
///    information of the inline widgets as a `List` of `PlaceholderDimensions`.
///    Determine the positioning of the inline widgets (which is usually done by
///    a [TextPainter] using its line break algorithm).
///
///  * Call [positionInlineChildren] with the positioning information of the
///    inline widgets.
///
///  * Implement [RenderBox.applyPaintTransform], optionally with
///    [defaultApplyPaintTransform].
///
///  * Call [paintInlineChildren] in [RenderBox.paint] to paint the inline widgets.
///
///  * Call [hitTestInlineChildren] in [RenderBox.hitTestChildren] to hit test the
///    inline widgets.
///
/// See also:
///
///  * [WidgetSpan.extractFromInlineSpan], a helper function for extracting
///    [WidgetSpan]s from an [InlineSpan] tree.
mixin RenderInlineChildrenContainerDefaults
    on RenderBox, ContainerRenderObjectMixin<RenderBox, TextParentData> {
  @override
  void setupParentData(RenderBox child) {
    if (child.parentData is! TextParentData) {
      child.parentData = TextParentData();
    }
  }

  static PlaceholderDimensions _layoutChild(
    RenderBox child,
    BoxConstraints childConstraints,
    ChildLayouter layoutChild,
    ChildBaselineGetter getBaseline,
  ) {
    final TextParentData parentData = child.parentData! as TextParentData;
    final PlaceholderSpan? span = parentData.span;
    assert(span != null);
    return span == null
        ? PlaceholderDimensions.empty
        : PlaceholderDimensions(
            size: layoutChild(child, childConstraints),
            alignment: span.alignment,
            baseline: span.baseline,
            baselineOffset: switch (span.alignment) {
              ui.PlaceholderAlignment.aboveBaseline ||
              ui.PlaceholderAlignment.belowBaseline ||
              ui.PlaceholderAlignment.bottom ||
              ui.PlaceholderAlignment.middle ||
              ui.PlaceholderAlignment.top => null,
              ui.PlaceholderAlignment.baseline => getBaseline(
                child,
                childConstraints,
                span.baseline!,
              ),
            },
          );
  }

  /// Computes the layout for every inline child using the `maxWidth` constraint.
  ///
  /// Returns a list of [PlaceholderDimensions], representing the layout results
  /// for each child managed by the [ContainerRenderObjectMixin] mixin.
  ///
  /// The `getChildBaseline` parameter and the `layoutChild` parameter must be
  /// consistent: if `layoutChild` computes the size of the child without
  /// modifying the actual layout of that child, then `getChildBaseline` must
  /// also be "dry", and vice versa.
  ///
  /// Since this method does not impose a maximum height constraint on the
  /// inline children, some children may become taller than this [RenderBox].
  ///
  /// See also:
  ///
  ///  * [TextPainter.setPlaceholderDimensions], the method that usually takes
  ///    the layout results from this method as the input.
  @protected
  List<PlaceholderDimensions> layoutInlineChildren(
    double maxWidth,
    ChildLayouter layoutChild,
    ChildBaselineGetter getChildBaseline,
  ) {
    final BoxConstraints constraints = BoxConstraints(maxWidth: maxWidth);
    return <PlaceholderDimensions>[
      for (RenderBox? child = firstChild; child != null; child = childAfter(child))
        _layoutChild(child, constraints, layoutChild, getChildBaseline),
    ];
  }

  /// Positions each inline child according to the coordinates provided in the
  /// `boxes` list.
  ///
  /// The `boxes` list must be in logical order, which is the order each child
  /// is encountered when the user reads the text. Usually the length of the
  /// list equals [childCount], but it can be less than that, when some children
  /// are omitted due to ellipsing. It never exceeds [childCount].
  ///
  /// See also:
  ///
  ///  * [TextPainter.inlinePlaceholderBoxes], the method that can be used to
  ///    get the input `boxes`.
  @protected
  void positionInlineChildren(List<ui.TextBox> boxes) {
    RenderBox? child = firstChild;
    for (final ui.TextBox box in boxes) {
      if (child == null) {
        assert(
          false,
          'The length of boxes (${boxes.length}) should be greater than childCount ($childCount)',
        );
        return;
      }
      final TextParentData textParentData = child.parentData! as TextParentData;
      textParentData._offset = Offset(box.left, box.top);
      child = childAfter(child);
    }
    while (child != null) {
      final TextParentData textParentData = child.parentData! as TextParentData;
      textParentData._offset = null;
      child = childAfter(child);
    }
  }

  /// Applies the transform that would be applied when painting the given child
  /// to the given matrix.
  ///
  /// Render children whose [TextParentData.offset] is null zeros out the
  /// `transform` to indicate they're invisible thus should not be painted.
  @protected
  void defaultApplyPaintTransform(RenderBox child, Matrix4 transform) {
    final TextParentData childParentData = child.parentData! as TextParentData;
    final Offset? offset = childParentData.offset;
    if (offset == null) {
      transform.setZero();
    } else {
      transform.translateByDouble(offset.dx, offset.dy, 0, 1);
    }
  }

  /// Paints each inline child.
  ///
  /// Render children whose [TextParentData.offset] is null will be skipped by
  /// this method.
  @protected
  void paintInlineChildren(PaintingContext context, Offset offset) {
    RenderBox? child = firstChild;
    while (child != null) {
      final TextParentData childParentData = child.parentData! as TextParentData;
      final Offset? childOffset = childParentData.offset;
      if (childOffset == null) {
        return;
      }
      context.paintChild(child, childOffset + offset);
      child = childAfter(child);
    }
  }

  /// Performs a hit test on each inline child.
  ///
  /// Render children whose [TextParentData.offset] is null will be skipped by
  /// this method.
  @protected
  bool hitTestInlineChildren(BoxHitTestResult result, Offset position) {
    RenderBox? child = firstChild;
    while (child != null) {
      final TextParentData childParentData = child.parentData! as TextParentData;
      final Offset? childOffset = childParentData.offset;
      if (childOffset == null) {
        return false;
      }
      final bool isHit = result.addWithPaintOffset(
        offset: childOffset,
        position: position,
        hitTest: (BoxHitTestResult result, Offset transformed) =>
            child!.hitTest(result, position: transformed),
      );
      if (isHit) {
        return true;
      }
      child = childAfter(child);
    }
    return false;
  }
}

class _UnspecifiedTextScaler extends TextScaler {
  const _UnspecifiedTextScaler();
  @override
  Never get textScaleFactor => throw UnimplementedError();

  @override
  Never scale(double fontSize) => throw UnimplementedError();
}

/// A render object that displays a paragraph of text.
class RenderParagraph extends RenderBox
    with
        ContainerRenderObjectMixin<RenderBox, TextParentData>,
        RenderInlineChildrenContainerDefaults,
        RelayoutWhenSystemFontsChangeMixin {
  /// Creates a paragraph render object.
  ///
  /// The [maxLines] property may be null (and indeed defaults to null), but if
  /// it is not null, it must be greater than zero.
  RenderParagraph(
    InlineSpan text, {
    TextAlign textAlign = TextAlign.start,
    required TextDirection textDirection,
    bool softWrap = true,
    TextOverflow overflow = TextOverflow.clip,
    @Deprecated(
      'Use textScaler instead. '
      'Use of textScaleFactor was deprecated in preparation for the upcoming nonlinear text scaling support. '
      'This feature was deprecated after v3.12.0-2.0.pre.',
    )
    double textScaleFactor = 1.0,
    TextScaler textScaler = const _UnspecifiedTextScaler(),
    int? maxLines,
    Locale? locale,
    StrutStyle? strutStyle,
    TextWidthBasis textWidthBasis = TextWidthBasis.parent,
    ui.TextHeightBehavior? textHeightBehavior,
    List<RenderBox>? children,
    Color? selectionColor,
    SelectionRegistrar? registrar,
  }) : assert(text.debugAssertIsValid()),
       assert(maxLines == null || maxLines > 0),
       assert(
         identical(textScaler, const _UnspecifiedTextScaler()) || textScaleFactor == 1.0,
         'textScaleFactor is deprecated and cannot be specified when textScaler is specified.',
       ),
       _softWrap = softWrap,
       _overflow = overflow,
       _selectionColor = selectionColor,
       _textPainter = TextPainter(
         text: text,
         textAlign: textAlign,
         textDirection: textDirection,
         textScaler: textScaler == const _UnspecifiedTextScaler()
             ? TextScaler.linear(textScaleFactor)
             : textScaler,
         maxLines: maxLines,
         ellipsis: overflow == TextOverflow.ellipsis ? _kEllipsis : null,
         locale: locale,
         strutStyle: strutStyle,
         textWidthBasis: textWidthBasis,
         textHeightBehavior: textHeightBehavior,
       ) {
    addAll(children);
    this.registrar = registrar;
  }

  static final String _placeholderCharacter = String.fromCharCode(
    PlaceholderSpan.placeholderCodeUnit,
  );

  final TextPainter _textPainter;

  // Currently, computing min/max intrinsic width/height will destroy state
  // inside the painter. Instead of calling _layout again to get back the correct
  // state, use a separate TextPainter for intrinsics calculation.
  //
  // TODO(abarth): Make computing the min/max intrinsic width/height a
  //  non-destructive operation.
  TextPainter? _textIntrinsicsCache;
  TextPainter get _textIntrinsics {
    return (_textIntrinsicsCache ??= TextPainter())
      ..text = _textPainter.text
      ..textAlign = _textPainter.textAlign
      ..textDirection = _textPainter.textDirection
      ..textScaler = _textPainter.textScaler
      ..maxLines = _textPainter.maxLines
      ..ellipsis = _textPainter.ellipsis
      ..locale = _textPainter.locale
      ..strutStyle = _textPainter.strutStyle
      ..textWidthBasis = _textPainter.textWidthBasis
      ..textHeightBehavior = _textPainter.textHeightBehavior;
  }

  List<AttributedString>? _cachedAttributedLabels;

  List<InlineSpanSemanticsInformation>? _cachedCombinedSemanticsInfos;

  /// The text to display.
  InlineSpan get text => _textPainter.text!;
  set text(InlineSpan value) {
    switch (_textPainter.text!.compareTo(value)) {
      case RenderComparison.identical:
        return;
      case RenderComparison.metadata:
        _textPainter.text = value;
        _cachedCombinedSemanticsInfos = null;
        markNeedsSemanticsUpdate();
      case RenderComparison.paint:
        _textPainter.text = value;
        _cachedAttributedLabels = null;
        _cachedCombinedSemanticsInfos = null;
        markNeedsPaint();
        markNeedsSemanticsUpdate();
      case RenderComparison.layout:
        _textPainter.text = value;
        _overflowShader = null;
        _cachedAttributedLabels = null;
        _cachedCombinedSemanticsInfos = null;
        markNeedsLayout();
        _removeSelectionRegistrarSubscription();
        _disposeSelectableFragments();
        _updateSelectionRegistrarSubscription();
    }
  }

  /// The ongoing selections in this paragraph.
  ///
  /// The selection does not include selections in [PlaceholderSpan] if there
  /// are any.
  @visibleForTesting
  List<TextSelection> get selections {
    if (_lastSelectableFragments == null) {
      return const <TextSelection>[];
    }
    final List<TextSelection> results = <TextSelection>[];
    for (final _SelectableFragment fragment in _lastSelectableFragments!) {
      if (fragment._textSelectionStart != null && fragment._textSelectionEnd != null) {
        results.add(
          TextSelection(
            baseOffset: fragment._textSelectionStart!.offset,
            extentOffset: fragment._textSelectionEnd!.offset,
          ),
        );
      }
    }
    return results;
  }

  // Should be null if selection is not enabled, i.e. _registrar = null. The
  // paragraph splits on [PlaceholderSpan.placeholderCodeUnit], and stores each
  // fragment in this list.
  List<_SelectableFragment>? _lastSelectableFragments;

  /// The [SelectionRegistrar] this paragraph will be, or is, registered to.
  SelectionRegistrar? get registrar => _registrar;
  SelectionRegistrar? _registrar;
  set registrar(SelectionRegistrar? value) {
    if (value == _registrar) {
      return;
    }
    _removeSelectionRegistrarSubscription();
    _disposeSelectableFragments();
    _registrar = value;
    _updateSelectionRegistrarSubscription();
  }

  void _updateSelectionRegistrarSubscription() {
    if (_registrar == null) {
      return;
    }
    _lastSelectableFragments ??= _getSelectableFragments();
    _lastSelectableFragments!.forEach(_registrar!.add);
    if (_lastSelectableFragments!.isNotEmpty) {
      markNeedsCompositingBitsUpdate();
    }
  }

  void _removeSelectionRegistrarSubscription() {
    if (_registrar == null || _lastSelectableFragments == null) {
      return;
    }
    _lastSelectableFragments!.forEach(_registrar!.remove);
  }

  List<_SelectableFragment> _getSelectableFragments() {
    final String plainText = text.toPlainText(includeSemanticsLabels: false);
    final List<_SelectableFragment> result = <_SelectableFragment>[];
    int start = 0;
    while (start < plainText.length) {
      int end = plainText.indexOf(_placeholderCharacter, start);
      if (start != end) {
        if (end == -1) {
          end = plainText.length;
        }
        result.add(
          _SelectableFragment(
            paragraph: this,
            range: TextRange(start: start, end: end),
            fullText: plainText,
          ),
        );
        start = end;
      }
      start += 1;
    }
    return result;
  }

  /// Determines whether the given [Selectable] was created by this
  /// [RenderParagraph].
  ///
  /// The [RenderParagraph] splits its text into multiple [Selectable]s,
  /// delimited by [PlaceholderSpan]s or [WidgetSpan]s.
  bool selectableBelongsToParagraph(Selectable selectable) {
    if (_lastSelectableFragments == null) {
      return false;
    }
    return _lastSelectableFragments!.contains(selectable);
  }

  void _disposeSelectableFragments() {
    if (_lastSelectableFragments == null) {
      return;
    }
    for (final _SelectableFragment fragment in _lastSelectableFragments!) {
      fragment.dispose();
    }
    _lastSelectableFragments = null;
  }

  @override
  bool get alwaysNeedsCompositing => _lastSelectableFragments?.isNotEmpty ?? false;

  @override
  void markNeedsLayout() {
    _lastSelectableFragments?.forEach(
      (_SelectableFragment element) => element.didChangeParagraphLayout(),
    );
    super.markNeedsLayout();
  }

  @override
  void dispose() {
    _removeSelectionRegistrarSubscription();
    _disposeSelectableFragments();
    _textPainter.dispose();
    _textIntrinsicsCache?.dispose();
    super.dispose();
  }

  /// How the text should be aligned horizontally.
  TextAlign get textAlign => _textPainter.textAlign;
  set textAlign(TextAlign value) {
    if (_textPainter.textAlign == value) {
      return;
    }
    _textPainter.textAlign = value;
    markNeedsPaint();
  }

  /// The directionality of the text.
  ///
  /// This decides how the [TextAlign.start], [TextAlign.end], and
  /// [TextAlign.justify] values of [textAlign] are interpreted.
  ///
  /// This is also used to disambiguate how to render bidirectional text. For
  /// example, if the [text] is an English phrase followed by a Hebrew phrase,
  /// in a [TextDirection.ltr] context the English phrase will be on the left
  /// and the Hebrew phrase to its right, while in a [TextDirection.rtl]
  /// context, the English phrase will be on the right and the Hebrew phrase on
  /// its left.
  TextDirection get textDirection => _textPainter.textDirection!;
  set textDirection(TextDirection value) {
    if (_textPainter.textDirection == value) {
      return;
    }
    _textPainter.textDirection = value;
    markNeedsLayout();
  }

  /// Whether the text should break at soft line breaks.
  ///
  /// If false, the glyphs in the text will be positioned as if there was
  /// unlimited horizontal space.
  ///
  /// If [softWrap] is false, [overflow] and [textAlign] may have unexpected
  /// effects.
  bool get softWrap => _softWrap;
  bool _softWrap;
  set softWrap(bool value) {
    if (_softWrap == value) {
      return;
    }
    _softWrap = value;
    markNeedsLayout();
  }

  /// How visual overflow should be handled.
  TextOverflow get overflow => _overflow;
  TextOverflow _overflow;
  set overflow(TextOverflow value) {
    if (_overflow == value) {
      return;
    }
    _overflow = value;
    _textPainter.ellipsis = value == TextOverflow.ellipsis ? _kEllipsis : null;
    markNeedsLayout();
  }

  /// Deprecated. Will be removed in a future version of Flutter. Use
  /// [textScaler] instead.
  ///
  /// The number of font pixels for each logical pixel.
  ///
  /// For example, if the text scale factor is 1.5, text will be 50% larger than
  /// the specified font size.
  @Deprecated(
    'Use textScaler instead. '
    'Use of textScaleFactor was deprecated in preparation for the upcoming nonlinear text scaling support. '
    'This feature was deprecated after v3.12.0-2.0.pre.',
  )
  double get textScaleFactor => _textPainter.textScaleFactor;
  @Deprecated(
    'Use textScaler instead. '
    'Use of textScaleFactor was deprecated in preparation for the upcoming nonlinear text scaling support. '
    'This feature was deprecated after v3.12.0-2.0.pre.',
  )
  set textScaleFactor(double value) {
    textScaler = TextScaler.linear(value);
  }

  /// {@macro flutter.painting.textPainter.textScaler}
  TextScaler get textScaler => _textPainter.textScaler;
  set textScaler(TextScaler value) {
    if (_textPainter.textScaler == value) {
      return;
    }
    _textPainter.textScaler = value;
    _overflowShader = null;
    markNeedsLayout();
  }

  /// An optional maximum number of lines for the text to span, wrapping if
  /// necessary. If the text exceeds the given number of lines, it will be
  /// truncated according to [overflow] and [softWrap].
  int? get maxLines => _textPainter.maxLines;

  /// The value may be null. If it is not null, then it must be greater than
  /// zero.
  set maxLines(int? value) {
    assert(value == null || value > 0);
    if (_textPainter.maxLines == value) {
      return;
    }
    _textPainter.maxLines = value;
    _overflowShader = null;
    markNeedsLayout();
  }

  /// Used by this paragraph's internal [TextPainter] to select a
  /// locale-specific font.
  ///
  /// In some cases, the same Unicode character may be rendered differently
  /// depending on the locale. For example, the '骨' character is rendered
  /// differently in the Chinese and Japanese locales. In these cases, the
  /// [locale] may be used to select a locale-specific font.
  Locale? get locale => _textPainter.locale;

  /// The value may be null.
  set locale(Locale? value) {
    if (_textPainter.locale == value) {
      return;
    }
    _textPainter.locale = value;
    _overflowShader = null;
    markNeedsLayout();
  }

  /// {@macro flutter.painting.textPainter.strutStyle}
  StrutStyle? get strutStyle => _textPainter.strutStyle;

  /// The value may be null.
  set strutStyle(StrutStyle? value) {
    if (_textPainter.strutStyle == value) {
      return;
    }
    _textPainter.strutStyle = value;
    _overflowShader = null;
    markNeedsLayout();
  }

  /// {@macro flutter.painting.textPainter.textWidthBasis}
  TextWidthBasis get textWidthBasis => _textPainter.textWidthBasis;
  set textWidthBasis(TextWidthBasis value) {
    if (_textPainter.textWidthBasis == value) {
      return;
    }
    _textPainter.textWidthBasis = value;
    _overflowShader = null;
    markNeedsLayout();
  }

  /// {@macro dart.ui.textHeightBehavior}
  ui.TextHeightBehavior? get textHeightBehavior => _textPainter.textHeightBehavior;
  set textHeightBehavior(ui.TextHeightBehavior? value) {
    if (_textPainter.textHeightBehavior == value) {
      return;
    }
    _textPainter.textHeightBehavior = value;
    _overflowShader = null;
    markNeedsLayout();
  }

  /// The color to use when painting the selection.
  ///
  /// Ignored if the text is not selectable (e.g. if [registrar] is null).
  Color? get selectionColor => _selectionColor;
  Color? _selectionColor;
  set selectionColor(Color? value) {
    if (_selectionColor == value) {
      return;
    }
    _selectionColor = value;
    if (_lastSelectableFragments?.any(
          (_SelectableFragment fragment) => fragment.value.hasSelection,
        ) ??
        false) {
      markNeedsPaint();
    }
  }

  Offset _getOffsetForPosition(TextPosition position) {
    return getOffsetForCaret(position, Rect.zero) + Offset(0, getFullHeightForCaret(position));
  }

  @override
  double computeMinIntrinsicWidth(double height) {
    final List<PlaceholderDimensions> placeholderDimensions = layoutInlineChildren(
      double.infinity,
      (RenderBox child, BoxConstraints constraints) =>
          Size(child.getMinIntrinsicWidth(double.infinity), 0.0),
      ChildLayoutHelper.getDryBaseline,
    );
    return (_textIntrinsics
          ..setPlaceholderDimensions(placeholderDimensions)
          ..layout())
        .minIntrinsicWidth;
  }

  @override
  double computeMaxIntrinsicWidth(double height) {
    final List<PlaceholderDimensions> placeholderDimensions = layoutInlineChildren(
      double.infinity,
      // Height and baseline is irrelevant as all text will be laid
      // out in a single line. Therefore, using 0.0 as a dummy for the height.
      (RenderBox child, BoxConstraints constraints) =>
          Size(child.getMaxIntrinsicWidth(double.infinity), 0.0),
      ChildLayoutHelper.getDryBaseline,
    );
    return (_textIntrinsics
          ..setPlaceholderDimensions(placeholderDimensions)
          ..layout())
        .maxIntrinsicWidth;
  }

  /// An estimate of the height of a line in the text. See [TextPainter.preferredLineHeight].
  ///
  /// This does not require the layout to be updated.
  @visibleForTesting
  double get preferredLineHeight => _textPainter.preferredLineHeight;

  double _computeIntrinsicHeight(double width) {
    return (_textIntrinsics
          ..setPlaceholderDimensions(
            layoutInlineChildren(
              width,
              ChildLayoutHelper.dryLayoutChild,
              ChildLayoutHelper.getDryBaseline,
            ),
          )
          ..layout(minWidth: width, maxWidth: _adjustMaxWidth(width)))
        .height;
  }

  @override
  double computeMinIntrinsicHeight(double width) {
    return _computeIntrinsicHeight(width);
  }

  @override
  double computeMaxIntrinsicHeight(double width) {
    return _computeIntrinsicHeight(width);
  }

  @override
  bool hitTestSelf(Offset position) => true;

  @override
  @protected
  bool hitTestChildren(BoxHitTestResult result, {required Offset position}) {
    final GlyphInfo? glyph = _textPainter.getClosestGlyphForOffset(position);
    // The hit-test can't fall through the horizontal gaps between visually
    // adjacent characters on the same line, even with a large letter-spacing or
    // text justification, as graphemeClusterLayoutBounds.width is the advance
    // width to the next character, so there's no gap between their
    // graphemeClusterLayoutBounds rects.
    final InlineSpan? spanHit =
        glyph != null && glyph.graphemeClusterLayoutBounds.contains(position)
        ? _textPainter.text!.getSpanForPosition(
            TextPosition(offset: glyph.graphemeClusterCodeUnitRange.start),
          )
        : null;
    switch (spanHit) {
      case final HitTestTarget span:
        result.add(HitTestEntry(span));
        return true;
      case _:
        return hitTestInlineChildren(result, position);
    }
  }

  bool _needsClipping = false;
  ui.Shader? _overflowShader;

  /// Whether this paragraph currently has a [dart:ui.Shader] for its overflow
  /// effect.
  ///
  /// Used to test this object. Not for use in production.
  @visibleForTesting
  bool get debugHasOverflowShader => _overflowShader != null;

  @override
  void systemFontsDidChange() {
    super.systemFontsDidChange();
    _textPainter.markNeedsLayout();
  }

  // Placeholder dimensions representing the sizes of child inline widgets.
  //
  // These need to be cached because the text painter's placeholder dimensions
  // will be overwritten during intrinsic width/height calculations and must be
  // restored to the original values before final layout and painting.
  List<PlaceholderDimensions>? _placeholderDimensions;

  double _adjustMaxWidth(double maxWidth) {
    return softWrap || overflow == TextOverflow.ellipsis ? maxWidth : double.infinity;
  }

  void _layoutTextWithConstraints(BoxConstraints constraints) {
    _textPainter
      ..setPlaceholderDimensions(_placeholderDimensions)
      ..layout(minWidth: constraints.minWidth, maxWidth: _adjustMaxWidth(constraints.maxWidth));
  }

  @override
  @protected
  Size computeDryLayout(covariant BoxConstraints constraints) {
    final Size size =
        (_textIntrinsics
              ..setPlaceholderDimensions(
                layoutInlineChildren(
                  constraints.maxWidth,
                  ChildLayoutHelper.dryLayoutChild,
                  ChildLayoutHelper.getDryBaseline,
                ),
              )
              ..layout(
                minWidth: constraints.minWidth,
                maxWidth: _adjustMaxWidth(constraints.maxWidth),
              ))
            .size;
    return constraints.constrain(size);
  }

  @override
  double computeDistanceToActualBaseline(TextBaseline baseline) {
    assert(!debugNeedsLayout);
    assert(constraints.debugAssertIsValid());
    _layoutTextWithConstraints(constraints);
    // TODO(garyq): Since our metric for ideographic baseline is currently
    // inaccurate and the non-alphabetic baselines are based off of the
    // alphabetic baseline, we use the alphabetic for now to produce correct
    // layouts. We should eventually change this back to pass the `baseline`
    // property when the ideographic baseline is properly implemented
    // (https://github.com/flutter/flutter/issues/22625).
    return _textPainter.computeDistanceToActualBaseline(TextBaseline.alphabetic);
  }

  @override
  double computeDryBaseline(covariant BoxConstraints constraints, TextBaseline baseline) {
    assert(constraints.debugAssertIsValid());
    _textIntrinsics
      ..setPlaceholderDimensions(
        layoutInlineChildren(
          constraints.maxWidth,
          ChildLayoutHelper.dryLayoutChild,
          ChildLayoutHelper.getDryBaseline,
        ),
      )
      ..layout(minWidth: constraints.minWidth, maxWidth: _adjustMaxWidth(constraints.maxWidth));
    return _textIntrinsics.computeDistanceToActualBaseline(TextBaseline.alphabetic);
  }

  @override
  void performLayout() {
    _lastSelectableFragments?.forEach(
      (_SelectableFragment element) => element.didChangeParagraphLayout(),
    );
    final BoxConstraints constraints = this.constraints;
    _placeholderDimensions = layoutInlineChildren(
      constraints.maxWidth,
      ChildLayoutHelper.layoutChild,
      ChildLayoutHelper.getBaseline,
    );
    _layoutTextWithConstraints(constraints);
    positionInlineChildren(_textPainter.inlinePlaceholderBoxes!);

    final Size textSize = _textPainter.size;
    size = constraints.constrain(textSize);

    final bool didOverflowHeight = size.height < textSize.height || _textPainter.didExceedMaxLines;
    final bool didOverflowWidth = size.width < textSize.width;
    // TODO(abarth): We're only measuring the sizes of the line boxes here. If
    // the glyphs draw outside the line boxes, we might think that there isn't
    // visual overflow when there actually is visual overflow. This can become
    // a problem if we start having horizontal overflow and introduce a clip
    // that affects the actual (but undetected) vertical overflow.
    final bool hasVisualOverflow = didOverflowWidth || didOverflowHeight;
    if (hasVisualOverflow) {
      switch (_overflow) {
        case TextOverflow.visible:
          _needsClipping = false;
          _overflowShader = null;
        case TextOverflow.clip:
        case TextOverflow.ellipsis:
          _needsClipping = true;
          _overflowShader = null;
        case TextOverflow.fade:
          _needsClipping = true;
          final TextPainter fadeSizePainter = TextPainter(
            text: TextSpan(style: _textPainter.text!.style, text: '\u2026'),
            textDirection: textDirection,
            textScaler: textScaler,
            locale: locale,
          )..layout();
          if (didOverflowWidth) {
            final (double fadeStart, double fadeEnd) = switch (textDirection) {
              TextDirection.rtl => (fadeSizePainter.width, 0.0),
              TextDirection.ltr => (size.width - fadeSizePainter.width, size.width),
            };
            _overflowShader = ui.Gradient.linear(
              Offset(fadeStart, 0.0),
              Offset(fadeEnd, 0.0),
              <Color>[const Color(0xFFFFFFFF), const Color(0x00FFFFFF)],
            );
          } else {
            final double fadeEnd = size.height;
            final double fadeStart = fadeEnd - fadeSizePainter.height / 2.0;
            _overflowShader = ui.Gradient.linear(
              Offset(0.0, fadeStart),
              Offset(0.0, fadeEnd),
              <Color>[const Color(0xFFFFFFFF), const Color(0x00FFFFFF)],
            );
          }
          fadeSizePainter.dispose();
      }
    } else {
      _needsClipping = false;
      _overflowShader = null;
    }
  }

  @override
  void applyPaintTransform(RenderBox child, Matrix4 transform) {
    defaultApplyPaintTransform(child, transform);
  }

  @override
  void paint(PaintingContext context, Offset offset) {
    // Text alignment only triggers repaint so it's possible the text layout has
    // been invalidated but performLayout wasn't called at this point. Make sure
    // the TextPainter has a valid layout.
    _layoutTextWithConstraints(constraints);
    assert(() {
      if (debugRepaintTextRainbowEnabled) {
        final Paint paint = Paint()..color = debugCurrentRepaintColor.toColor();
        context.canvas.drawRect(offset & size, paint);
      }
      return true;
    }());

    if (_needsClipping) {
      final Rect bounds = offset & size;
      if (_overflowShader != null) {
        // This layer limits what the shader below blends with to be just the
        // text (as opposed to the text and its background).
        context.canvas.saveLayer(bounds, Paint());
      } else {
        context.canvas.save();
      }
      context.canvas.clipRect(bounds);
    }

    if (_lastSelectableFragments != null) {
      for (final _SelectableFragment fragment in _lastSelectableFragments!) {
        fragment.paint(context, offset);
      }
    }

    assert(() {
      _textPainter.debugPaintTextLayoutBoxes = debugPaintTextLayoutBoxes;
      return true;
    }());

    _textPainter.paint(context.canvas, offset);

    paintInlineChildren(context, offset);

    if (_needsClipping) {
      if (_overflowShader != null) {
        context.canvas.translate(offset.dx, offset.dy);
        final Paint paint = Paint()
          ..blendMode = BlendMode.modulate
          ..shader = _overflowShader;
        context.canvas.drawRect(Offset.zero & size, paint);
      }
      context.canvas.restore();
    }
  }

  /// Returns the offset at which to paint the caret.
  ///
  /// Valid only after [layout].
  Offset getOffsetForCaret(TextPosition position, Rect caretPrototype) {
    assert(!debugNeedsLayout);
    _layoutTextWithConstraints(constraints);
    return _textPainter.getOffsetForCaret(position, caretPrototype);
  }

  /// {@macro flutter.painting.textPainter.getFullHeightForCaret}
  ///
  /// Valid only after [layout].
  double getFullHeightForCaret(TextPosition position) {
    assert(!debugNeedsLayout);
    _layoutTextWithConstraints(constraints);
    return _textPainter.getFullHeightForCaret(position, Rect.zero);
  }

  /// Returns a list of rects that bound the given selection.
  ///
  /// The [boxHeightStyle] and [boxWidthStyle] arguments may be used to select
  /// the shape of the [TextBox]es. These properties default to
  /// [ui.BoxHeightStyle.tight] and [ui.BoxWidthStyle.tight] respectively.
  ///
  /// A given selection might have more than one rect if the [RenderParagraph]
  /// contains multiple [InlineSpan]s or bidirectional text, because logically
  /// contiguous text might not be visually contiguous.
  ///
  /// Valid only after [layout].
  ///
  /// See also:
  ///
  ///  * [TextPainter.getBoxesForSelection], the method in TextPainter to get
  ///    the equivalent boxes.
  List<ui.TextBox> getBoxesForSelection(
    TextSelection selection, {
    ui.BoxHeightStyle boxHeightStyle = ui.BoxHeightStyle.tight,
    ui.BoxWidthStyle boxWidthStyle = ui.BoxWidthStyle.tight,
  }) {
    assert(!debugNeedsLayout);
    _layoutTextWithConstraints(constraints);
    return _textPainter.getBoxesForSelection(
      selection,
      boxHeightStyle: boxHeightStyle,
      boxWidthStyle: boxWidthStyle,
    );
  }

  /// Returns the position within the text for the given pixel offset.
  ///
  /// Valid only after [layout].
  TextPosition getPositionForOffset(Offset offset) {
    assert(!debugNeedsLayout);
    _layoutTextWithConstraints(constraints);
    return _textPainter.getPositionForOffset(offset);
  }

  /// Returns the text range of the word at the given offset. Characters not
  /// part of a word, such as spaces, symbols, and punctuation, have word breaks
  /// on both sides. In such cases, this method will return a text range that
  /// contains the given text position.
  ///
  /// Word boundaries are defined more precisely in Unicode Standard Annex #29
  /// <http://www.unicode.org/reports/tr29/#Word_Boundaries>.
  ///
  /// Valid only after [layout].
  TextRange getWordBoundary(TextPosition position) {
    assert(!debugNeedsLayout);
    _layoutTextWithConstraints(constraints);
    return _textPainter.getWordBoundary(position);
  }

  TextRange _getLineAtOffset(TextPosition position) => _textPainter.getLineBoundary(position);

  TextPosition _getTextPositionAbove(TextPosition position) {
    // -0.5 of preferredLineHeight points to the middle of the line above.
    final double preferredLineHeight = _textPainter.preferredLineHeight;
    final double verticalOffset = -0.5 * preferredLineHeight;
    return _getTextPositionVertical(position, verticalOffset);
  }

  TextPosition _getTextPositionBelow(TextPosition position) {
    // 1.5 of preferredLineHeight points to the middle of the line below.
    final double preferredLineHeight = _textPainter.preferredLineHeight;
    final double verticalOffset = 1.5 * preferredLineHeight;
    return _getTextPositionVertical(position, verticalOffset);
  }

  TextPosition _getTextPositionVertical(TextPosition position, double verticalOffset) {
    final Offset caretOffset = _textPainter.getOffsetForCaret(position, Rect.zero);
    final Offset caretOffsetTranslated = caretOffset.translate(0.0, verticalOffset);
    return _textPainter.getPositionForOffset(caretOffsetTranslated);
  }

  /// Returns the size of the text as laid out.
  ///
  /// This can differ from [size] if the text overflowed or if the [constraints]
  /// provided by the parent [RenderObject] forced the layout to be bigger than
  /// necessary for the given [text].
  ///
  /// This returns the [TextPainter.size] of the underlying [TextPainter].
  ///
  /// Valid only after [layout].
  Size get textSize {
    assert(!debugNeedsLayout);
    return _textPainter.size;
  }

  /// Whether the text was truncated or ellipsized as laid out.
  ///
  /// This returns the [TextPainter.didExceedMaxLines] of the underlying [TextPainter].
  ///
  /// Valid only after [layout].
  bool get didExceedMaxLines {
    assert(!debugNeedsLayout);
    return _textPainter.didExceedMaxLines;
  }

  /// Collected during [describeSemanticsConfiguration], used by
  /// [assembleSemanticsNode].
  List<InlineSpanSemanticsInformation>? _semanticsInfo;

  @override
  void describeSemanticsConfiguration(SemanticsConfiguration config) {
    super.describeSemanticsConfiguration(config);
    _semanticsInfo = text.getSemanticsInformation();
    bool needsAssembleSemanticsNode = false;
    bool needsChildConfigurationsDelegate = false;
    for (final InlineSpanSemanticsInformation info in _semanticsInfo!) {
      if (info.recognizer != null || info.semanticsIdentifier != null) {
        needsAssembleSemanticsNode = true;
        break;
      }
      needsChildConfigurationsDelegate = needsChildConfigurationsDelegate || info.isPlaceholder;
    }

    if (needsAssembleSemanticsNode) {
      config.explicitChildNodes = true;
      config.isSemanticBoundary = true;
    } else if (needsChildConfigurationsDelegate) {
      config.childConfigurationsDelegate = _childSemanticsConfigurationsDelegate;
    } else {
      if (_cachedAttributedLabels == null) {
        final StringBuffer buffer = StringBuffer();
        int offset = 0;
        final List<StringAttribute> attributes = <StringAttribute>[];
        for (final InlineSpanSemanticsInformation info in _semanticsInfo!) {
          final String label = info.semanticsLabel ?? info.text;
          for (final StringAttribute infoAttribute in info.stringAttributes) {
            final TextRange originalRange = infoAttribute.range;
            attributes.add(
              infoAttribute.copy(
                range: TextRange(
                  start: offset + originalRange.start,
                  end: offset + originalRange.end,
                ),
              ),
            );
          }
          buffer.write(label);
          offset += label.length;
        }
        _cachedAttributedLabels = <AttributedString>[
          AttributedString(buffer.toString(), attributes: attributes),
        ];
      }
      config.attributedLabel = _cachedAttributedLabels![0];
      config.textDirection = textDirection;
    }
  }

  ChildSemanticsConfigurationsResult _childSemanticsConfigurationsDelegate(
    List<SemanticsConfiguration> childConfigs,
  ) {
    final ChildSemanticsConfigurationsResultBuilder builder =
        ChildSemanticsConfigurationsResultBuilder();
    int placeholderIndex = 0;
    int childConfigsIndex = 0;
    int attributedLabelCacheIndex = 0;
    InlineSpanSemanticsInformation? seenTextInfo;
    _cachedCombinedSemanticsInfos ??= combineSemanticsInfo(_semanticsInfo!);
    for (final InlineSpanSemanticsInformation info in _cachedCombinedSemanticsInfos!) {
      if (info.isPlaceholder) {
        if (seenTextInfo != null) {
          builder.markAsMergeUp(
            _createSemanticsConfigForTextInfo(seenTextInfo, attributedLabelCacheIndex),
          );
          attributedLabelCacheIndex += 1;
        }
        // Mark every childConfig belongs to this placeholder to merge up group.
        while (childConfigsIndex < childConfigs.length &&
            childConfigs[childConfigsIndex].tagsChildrenWith(
              PlaceholderSpanIndexSemanticsTag(placeholderIndex),
            )) {
          builder.markAsMergeUp(childConfigs[childConfigsIndex]);
          childConfigsIndex += 1;
        }
        placeholderIndex += 1;
      } else {
        seenTextInfo = info;
      }
    }

    // Handle plain text info at the end.
    if (seenTextInfo != null) {
      builder.markAsMergeUp(
        _createSemanticsConfigForTextInfo(seenTextInfo, attributedLabelCacheIndex),
      );
    }
    return builder.build();
  }

  SemanticsConfiguration _createSemanticsConfigForTextInfo(
    InlineSpanSemanticsInformation textInfo,
    int cacheIndex,
  ) {
    assert(!textInfo.requiresOwnNode);
    final List<AttributedString> cachedStrings = _cachedAttributedLabels ??= <AttributedString>[];
    assert(cacheIndex <= cachedStrings.length);
    final bool hasCache = cacheIndex < cachedStrings.length;

    late AttributedString attributedLabel;
    if (hasCache) {
      attributedLabel = cachedStrings[cacheIndex];
    } else {
      assert(cachedStrings.length == cacheIndex);
      attributedLabel = AttributedString(
        textInfo.semanticsLabel ?? textInfo.text,
        attributes: textInfo.stringAttributes,
      );
      cachedStrings.add(attributedLabel);
    }
    return SemanticsConfiguration()
      ..textDirection = textDirection
      ..attributedLabel = attributedLabel;
  }

  // Caches [SemanticsNode]s created during [assembleSemanticsNode] so they
  // can be re-used when [assembleSemanticsNode] is called again. This ensures
  // stable ids for the [SemanticsNode]s of [TextSpan]s across
  // [assembleSemanticsNode] invocations.
  Map<Key, SemanticsNode>? _cachedChildNodes;

  @override
  void assembleSemanticsNode(
    SemanticsNode node,
    SemanticsConfiguration config,
    Iterable<SemanticsNode> children,
  ) {
    assert(_semanticsInfo != null && _semanticsInfo!.isNotEmpty);
    final List<SemanticsNode> newChildren = <SemanticsNode>[];
    TextDirection currentDirection = textDirection;
    Rect currentRect;
    double ordinal = 0.0;
    int start = 0;
    int placeholderIndex = 0;
    int childIndex = 0;
    RenderBox? child = firstChild;
    final Map<Key, SemanticsNode> newChildCache = <Key, SemanticsNode>{};
    _cachedCombinedSemanticsInfos ??= combineSemanticsInfo(_semanticsInfo!);
    for (final InlineSpanSemanticsInformation info in _cachedCombinedSemanticsInfos!) {
      final TextSelection selection = TextSelection(
        baseOffset: start,
        extentOffset: start + info.text.length,
      );
      start += info.text.length;

      if (info.isPlaceholder) {
        // A placeholder span may have 0 to multiple semantics nodes, we need
        // to annotate all of the semantics nodes belong to this span.
        while (children.length > childIndex &&
            children
                .elementAt(childIndex)
                .isTagged(PlaceholderSpanIndexSemanticsTag(placeholderIndex))) {
          final SemanticsNode childNode = children.elementAt(childIndex);
          final TextParentData parentData = child!.parentData! as TextParentData;
          // parentData.scale may be null if the render object is truncated.
          if (parentData.offset != null) {
            newChildren.add(childNode);
          }
          childIndex += 1;
        }
        child = childAfter(child!);
        placeholderIndex += 1;
      } else {
        final TextDirection initialDirection = currentDirection;
        final List<ui.TextBox> rects = getBoxesForSelection(selection);
        if (rects.isEmpty) {
          continue;
        }
        Rect rect = rects.first.toRect();
        currentDirection = rects.first.direction;
        for (final ui.TextBox textBox in rects.skip(1)) {
          rect = rect.expandToInclude(textBox.toRect());
          currentDirection = textBox.direction;
        }
        // Any of the text boxes may have had infinite dimensions.
        // We shouldn't pass infinite dimensions up to the bridges.
        rect = Rect.fromLTWH(
          math.max(0.0, rect.left),
          math.max(0.0, rect.top),
          math.min(rect.width, constraints.maxWidth),
          math.min(rect.height, constraints.maxHeight),
        );
        // round the current rectangle to make this API testable and add some
        // padding so that the accessibility rects do not overlap with the text.
        currentRect = Rect.fromLTRB(
          rect.left.floorToDouble() - 4.0,
          rect.top.floorToDouble() - 4.0,
          rect.right.ceilToDouble() + 4.0,
          rect.bottom.ceilToDouble() + 4.0,
        );
        final SemanticsConfiguration configuration = SemanticsConfiguration()
          ..sortKey = OrdinalSortKey(ordinal++)
          ..textDirection = initialDirection
          ..identifier = info.semanticsIdentifier ?? ''
          ..attributedLabel = AttributedString(
            info.semanticsLabel ?? info.text,
            attributes: info.stringAttributes,
          );
        switch (info.recognizer) {
          case TapGestureRecognizer(onTap: final VoidCallback? handler):
          case DoubleTapGestureRecognizer(onDoubleTap: final VoidCallback? handler):
            if (handler != null) {
              configuration.onTap = handler;
              configuration.isLink = true;
            }
          case LongPressGestureRecognizer(onLongPress: final GestureLongPressCallback? onLongPress):
            if (onLongPress != null) {
              configuration.onLongPress = onLongPress;
            }
          case null:
            break;
          default:
            assert(false, '${info.recognizer.runtimeType} is not supported.');
        }
        if (node.parentPaintClipRect != null) {
          final Rect paintRect = node.parentPaintClipRect!.intersect(currentRect);
          configuration.isHidden = paintRect.isEmpty && !currentRect.isEmpty;
        }
        final SemanticsNode newChild;
        if (_cachedChildNodes?.isNotEmpty ?? false) {
          newChild = _cachedChildNodes!.remove(_cachedChildNodes!.keys.first)!;
        } else {
          final UniqueKey key = UniqueKey();
          newChild = SemanticsNode(key: key, showOnScreen: _createShowOnScreenFor(key));
        }
        newChild
          ..updateWith(config: configuration)
          ..rect = currentRect;
        newChildCache[newChild.key!] = newChild;
        newChildren.add(newChild);
      }
    }
    // Makes sure we annotated all of the semantics children.
    assert(childIndex == children.length);
    assert(child == null);

    _cachedChildNodes = newChildCache;
    node.updateWith(config: config, childrenInInversePaintOrder: newChildren);
  }

  VoidCallback? _createShowOnScreenFor(Key key) {
    return () {
      final SemanticsNode node = _cachedChildNodes![key]!;
      showOnScreen(descendant: this, rect: node.rect);
    };
  }

  @override
  void clearSemantics() {
    super.clearSemantics();
    _cachedChildNodes = null;
  }

  @override
  List<DiagnosticsNode> debugDescribeChildren() {
    return <DiagnosticsNode>[
      text.toDiagnosticsNode(name: 'text', style: DiagnosticsTreeStyle.transition),
    ];
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(EnumProperty<TextAlign>('textAlign', textAlign));
    properties.add(EnumProperty<TextDirection>('textDirection', textDirection));
    properties.add(
      FlagProperty(
        'softWrap',
        value: softWrap,
        ifTrue: 'wrapping at box width',
        ifFalse: 'no wrapping except at line break characters',
        showName: true,
      ),
    );
    properties.add(EnumProperty<TextOverflow>('overflow', overflow));
    properties.add(
      DiagnosticsProperty<TextScaler>('textScaler', textScaler, defaultValue: TextScaler.noScaling),
    );
    properties.add(DiagnosticsProperty<Locale>('locale', locale, defaultValue: null));
    properties.add(IntProperty('maxLines', maxLines, ifNull: 'unlimited'));
  }
}

/// A continuous, selectable piece of paragraph.
///
/// Since the selections in [PlaceholderSpan] are handled independently in its
/// subtree, a selection in [RenderParagraph] can't continue across a
/// [PlaceholderSpan]. The [RenderParagraph] splits itself on [PlaceholderSpan]
/// to create multiple `_SelectableFragment`s so that they can be selected
/// separately.
class _SelectableFragment
    with Selectable, Diagnosticable, ChangeNotifier
    implements TextLayoutMetrics {
  _SelectableFragment({required this.paragraph, required this.fullText, required this.range})
    : assert(range.isValid && !range.isCollapsed && range.isNormalized) {
    if (kFlutterMemoryAllocationsEnabled) {
      ChangeNotifier.maybeDispatchObjectCreation(this);
    }
    _selectionGeometry = _getSelectionGeometry();
  }

  final TextRange range;
  final RenderParagraph paragraph;
  final String fullText;

  TextPosition? _textSelectionStart;
  TextPosition? _textSelectionEnd;

  bool _selectableContainsOriginTextBoundary = false;

  LayerLink? _startHandleLayerLink;
  LayerLink? _endHandleLayerLink;

  @override
  SelectionGeometry get value => _selectionGeometry;
  late SelectionGeometry _selectionGeometry;
  void _updateSelectionGeometry() {
    final SelectionGeometry newValue = _getSelectionGeometry();

    if (_selectionGeometry == newValue) {
      return;
    }
    _selectionGeometry = newValue;
    notifyListeners();
  }

  SelectionGeometry _getSelectionGeometry() {
    if (_textSelectionStart == null || _textSelectionEnd == null) {
      return const SelectionGeometry(status: SelectionStatus.none, hasContent: true);
    }

    final int selectionStart = _textSelectionStart!.offset;
    final int selectionEnd = _textSelectionEnd!.offset;
    final bool isReversed = selectionStart > selectionEnd;
    final Offset startOffsetInParagraphCoordinates = paragraph._getOffsetForPosition(
      TextPosition(offset: selectionStart),
    );
    final Offset endOffsetInParagraphCoordinates = selectionStart == selectionEnd
        ? startOffsetInParagraphCoordinates
        : paragraph._getOffsetForPosition(TextPosition(offset: selectionEnd));
    final bool flipHandles = isReversed != (TextDirection.rtl == paragraph.textDirection);
    final TextSelection selection = TextSelection(
      baseOffset: selectionStart,
      extentOffset: selectionEnd,
    );
    final List<Rect> selectionRects = <Rect>[];
    for (final TextBox textBox in paragraph.getBoxesForSelection(selection)) {
      selectionRects.add(textBox.toRect());
    }
    final bool selectionCollapsed = selectionStart == selectionEnd;
    final (
      TextSelectionHandleType startSelectionHandleType,
      TextSelectionHandleType endSelectionHandleType,
    ) = switch ((selectionCollapsed, flipHandles)) {
      // Always prefer collapsed handle when selection is collapsed.
      (true, _) => (TextSelectionHandleType.collapsed, TextSelectionHandleType.collapsed),
      (false, true) => (TextSelectionHandleType.right, TextSelectionHandleType.left),
      (false, false) => (TextSelectionHandleType.left, TextSelectionHandleType.right),
    };
    return SelectionGeometry(
      startSelectionPoint: SelectionPoint(
        localPosition: startOffsetInParagraphCoordinates,
        lineHeight: paragraph._textPainter.preferredLineHeight,
        handleType: startSelectionHandleType,
      ),
      endSelectionPoint: SelectionPoint(
        localPosition: endOffsetInParagraphCoordinates,
        lineHeight: paragraph._textPainter.preferredLineHeight,
        handleType: endSelectionHandleType,
      ),
      selectionRects: selectionRects,
      status: selectionCollapsed ? SelectionStatus.collapsed : SelectionStatus.uncollapsed,
      hasContent: true,
    );
  }

  @override
  SelectionResult dispatchSelectionEvent(SelectionEvent event) {
    late final SelectionResult result;
    final TextPosition? existingSelectionStart = _textSelectionStart;
    final TextPosition? existingSelectionEnd = _textSelectionEnd;
    switch (event.type) {
      case SelectionEventType.startEdgeUpdate:
      case SelectionEventType.endEdgeUpdate:
        final SelectionEdgeUpdateEvent edgeUpdate = event as SelectionEdgeUpdateEvent;
        final TextGranularity granularity = event.granularity;

        switch (granularity) {
          case TextGranularity.character:
            result = _updateSelectionEdge(
              edgeUpdate.globalPosition,
              isEnd: edgeUpdate.type == SelectionEventType.endEdgeUpdate,
            );
          case TextGranularity.word:
            result = _updateSelectionEdgeByTextBoundary(
              edgeUpdate.globalPosition,
              isEnd: edgeUpdate.type == SelectionEventType.endEdgeUpdate,
              getTextBoundary: _getWordBoundaryAtPosition,
            );
          case TextGranularity.paragraph:
            result = _updateSelectionEdgeByMultiSelectableTextBoundary(
              edgeUpdate.globalPosition,
              isEnd: edgeUpdate.type == SelectionEventType.endEdgeUpdate,
              getTextBoundary: _getParagraphBoundaryAtPosition,
              getClampedTextBoundary: _getClampedParagraphBoundaryAtPosition,
            );
          case TextGranularity.document:
          case TextGranularity.line:
            assert(false, 'Moving the selection edge by line or document is not supported.');
        }
      case SelectionEventType.clear:
        result = _handleClearSelection();
      case SelectionEventType.selectAll:
        result = _handleSelectAll();
      case SelectionEventType.selectWord:
        final SelectWordSelectionEvent selectWord = event as SelectWordSelectionEvent;
        result = _handleSelectWord(selectWord.globalPosition);
      case SelectionEventType.selectParagraph:
        final SelectParagraphSelectionEvent selectParagraph =
            event as SelectParagraphSelectionEvent;
        if (selectParagraph.absorb) {
          _handleSelectAll();
          result = SelectionResult.next;
          _selectableContainsOriginTextBoundary = true;
        } else {
          result = _handleSelectParagraph(selectParagraph.globalPosition);
        }
      case SelectionEventType.granularlyExtendSelection:
        final GranularlyExtendSelectionEvent granularlyExtendSelection =
            event as GranularlyExtendSelectionEvent;
        result = _handleGranularlyExtendSelection(
          granularlyExtendSelection.forward,
          granularlyExtendSelection.isEnd,
          granularlyExtendSelection.granularity,
        );
      case SelectionEventType.directionallyExtendSelection:
        final DirectionallyExtendSelectionEvent directionallyExtendSelection =
            event as DirectionallyExtendSelectionEvent;
        result = _handleDirectionallyExtendSelection(
          directionallyExtendSelection.dx,
          directionallyExtendSelection.isEnd,
          directionallyExtendSelection.direction,
        );
    }

    if (existingSelectionStart != _textSelectionStart ||
        existingSelectionEnd != _textSelectionEnd) {
      _didChangeSelection();
    }
    return result;
  }

  @override
  SelectedContent? getSelectedContent() {
    if (_textSelectionStart == null || _textSelectionEnd == null) {
      return null;
    }
    final int start = math.min(_textSelectionStart!.offset, _textSelectionEnd!.offset);
    final int end = math.max(_textSelectionStart!.offset, _textSelectionEnd!.offset);
    return SelectedContent(plainText: fullText.substring(start, end));
  }

  @override
  SelectedContentRange? getSelection() {
    if (_textSelectionStart == null || _textSelectionEnd == null) {
      return null;
    }
    return SelectedContentRange(
      startOffset: _textSelectionStart!.offset,
      endOffset: _textSelectionEnd!.offset,
    );
  }

  void _didChangeSelection() {
    paragraph.markNeedsPaint();
    _updateSelectionGeometry();
  }

  TextPosition _updateSelectionStartEdgeByTextBoundary(
    _TextBoundaryRecord? textBoundary,
    _TextBoundaryAtPosition getTextBoundary,
    TextPosition position,
    TextPosition? existingSelectionStart,
    TextPosition? existingSelectionEnd,
  ) {
    TextPosition? targetPosition;
    if (textBoundary != null) {
      assert(
        textBoundary.boundaryStart.offset >= range.start &&
            textBoundary.boundaryEnd.offset <= range.end,
      );
      if (_selectableContainsOriginTextBoundary &&
          existingSelectionStart != null &&
          existingSelectionEnd != null) {
        final bool isSamePosition = position.offset == existingSelectionEnd.offset;
        final bool isSelectionInverted =
            existingSelectionStart.offset > existingSelectionEnd.offset;
        final bool shouldSwapEdges =
            !isSamePosition &&
            (isSelectionInverted != (position.offset > existingSelectionEnd.offset));
        if (shouldSwapEdges) {
          if (position.offset < existingSelectionEnd.offset) {
            targetPosition = textBoundary.boundaryStart;
          } else {
            targetPosition = textBoundary.boundaryEnd;
          }
          // When the selection is inverted by the new position it is necessary to
          // swap the start edge (moving edge) with the end edge (static edge) to
          // maintain the origin text boundary within the selection.
          final _TextBoundaryRecord localTextBoundary = getTextBoundary(existingSelectionEnd);
          assert(
            localTextBoundary.boundaryStart.offset >= range.start &&
                localTextBoundary.boundaryEnd.offset <= range.end,
          );
          _setSelectionPosition(
            existingSelectionEnd.offset == localTextBoundary.boundaryStart.offset
                ? localTextBoundary.boundaryEnd
                : localTextBoundary.boundaryStart,
            isEnd: true,
          );
        } else {
          if (position.offset < existingSelectionEnd.offset) {
            targetPosition = textBoundary.boundaryStart;
          } else if (position.offset > existingSelectionEnd.offset) {
            targetPosition = textBoundary.boundaryEnd;
          } else {
            // Keep the origin text boundary in bounds when position is at the static edge.
            targetPosition = existingSelectionStart;
          }
        }
      } else {
        if (existingSelectionEnd != null) {
          // If the end edge exists and the start edge is being moved, then the
          // start edge is moved to encompass the entire text boundary at the new position.
          if (position.offset < existingSelectionEnd.offset) {
            targetPosition = textBoundary.boundaryStart;
          } else {
            targetPosition = textBoundary.boundaryEnd;
          }
        } else {
          // Move the start edge to the closest text boundary.
          targetPosition = _closestTextBoundary(textBoundary, position);
        }
      }
    } else {
      // The position is not contained within the current rect. The targetPosition
      // will either be at the end or beginning of the current rect. See [SelectionUtils.adjustDragOffset]
      // for a more in depth explanation on this adjustment.
      if (_selectableContainsOriginTextBoundary &&
          existingSelectionStart != null &&
          existingSelectionEnd != null) {
        // When the selection is inverted by the new position it is necessary to
        // swap the start edge (moving edge) with the end edge (static edge) to
        // maintain the origin text boundary within the selection.
        final bool isSamePosition = position.offset == existingSelectionEnd.offset;
        final bool isSelectionInverted =
            existingSelectionStart.offset > existingSelectionEnd.offset;
        final bool shouldSwapEdges =
            !isSamePosition &&
            (isSelectionInverted != (position.offset > existingSelectionEnd.offset));

        if (shouldSwapEdges) {
          final _TextBoundaryRecord localTextBoundary = getTextBoundary(existingSelectionEnd);
          assert(
            localTextBoundary.boundaryStart.offset >= range.start &&
                localTextBoundary.boundaryEnd.offset <= range.end,
          );
          _setSelectionPosition(
            isSelectionInverted ? localTextBoundary.boundaryEnd : localTextBoundary.boundaryStart,
            isEnd: true,
          );
        }
      }
    }
    return targetPosition ?? position;
  }

  TextPosition _updateSelectionEndEdgeByTextBoundary(
    _TextBoundaryRecord? textBoundary,
    _TextBoundaryAtPosition getTextBoundary,
    TextPosition position,
    TextPosition? existingSelectionStart,
    TextPosition? existingSelectionEnd,
  ) {
    TextPosition? targetPosition;
    if (textBoundary != null) {
      assert(
        textBoundary.boundaryStart.offset >= range.start &&
            textBoundary.boundaryEnd.offset <= range.end,
      );
      if (_selectableContainsOriginTextBoundary &&
          existingSelectionStart != null &&
          existingSelectionEnd != null) {
        final bool isSamePosition = position.offset == existingSelectionStart.offset;
        final bool isSelectionInverted =
            existingSelectionStart.offset > existingSelectionEnd.offset;
        final bool shouldSwapEdges =
            !isSamePosition &&
            (isSelectionInverted != (position.offset < existingSelectionStart.offset));
        if (shouldSwapEdges) {
          if (position.offset < existingSelectionStart.offset) {
            targetPosition = textBoundary.boundaryStart;
          } else {
            targetPosition = textBoundary.boundaryEnd;
          }
          // When the selection is inverted by the new position it is necessary to
          // swap the end edge (moving edge) with the start edge (static edge) to
          // maintain the origin text boundary within the selection.
          final _TextBoundaryRecord localTextBoundary = getTextBoundary(existingSelectionStart);
          assert(
            localTextBoundary.boundaryStart.offset >= range.start &&
                localTextBoundary.boundaryEnd.offset <= range.end,
          );
          _setSelectionPosition(
            existingSelectionStart.offset == localTextBoundary.boundaryStart.offset
                ? localTextBoundary.boundaryEnd
                : localTextBoundary.boundaryStart,
            isEnd: false,
          );
        } else {
          if (position.offset < existingSelectionStart.offset) {
            targetPosition = textBoundary.boundaryStart;
          } else if (position.offset > existingSelectionStart.offset) {
            targetPosition = textBoundary.boundaryEnd;
          } else {
            // Keep the origin text boundary in bounds when position is at the static edge.
            targetPosition = existingSelectionEnd;
          }
        }
      } else {
        if (existingSelectionStart != null) {
          // If the start edge exists and the end edge is being moved, then the
          // end edge is moved to encompass the entire text boundary at the new position.
          if (position.offset < existingSelectionStart.offset) {
            targetPosition = textBoundary.boundaryStart;
          } else {
            targetPosition = textBoundary.boundaryEnd;
          }
        } else {
          // Move the end edge to the closest text boundary.
          targetPosition = _closestTextBoundary(textBoundary, position);
        }
      }
    } else {
      // The position is not contained within the current rect. The targetPosition
      // will either be at the end or beginning of the current rect. See [SelectionUtils.adjustDragOffset]
      // for a more in depth explanation on this adjustment.
      if (_selectableContainsOriginTextBoundary &&
          existingSelectionStart != null &&
          existingSelectionEnd != null) {
        // When the selection is inverted by the new position it is necessary to
        // swap the end edge (moving edge) with the start edge (static edge) to
        // maintain the origin text boundary within the selection.
        final bool isSamePosition = position.offset == existingSelectionStart.offset;
        final bool isSelectionInverted =
            existingSelectionStart.offset > existingSelectionEnd.offset;
        final bool shouldSwapEdges =
            isSelectionInverted != (position.offset < existingSelectionStart.offset) ||
            isSamePosition;
        if (shouldSwapEdges) {
          final _TextBoundaryRecord localTextBoundary = getTextBoundary(existingSelectionStart);
          assert(
            localTextBoundary.boundaryStart.offset >= range.start &&
                localTextBoundary.boundaryEnd.offset <= range.end,
          );
          _setSelectionPosition(
            isSelectionInverted ? localTextBoundary.boundaryStart : localTextBoundary.boundaryEnd,
            isEnd: false,
          );
        }
      }
    }
    return targetPosition ?? position;
  }

  SelectionResult _updateSelectionEdgeByTextBoundary(
    Offset globalPosition, {
    required bool isEnd,
    required _TextBoundaryAtPosition getTextBoundary,
  }) {
    // When the start/end edges are swapped, i.e. the start is after the end, and
    // the scrollable synthesizes an event for the opposite edge, this will potentially
    // move the opposite edge outside of the origin text boundary and we are unable to recover.
    final TextPosition? existingSelectionStart = _textSelectionStart;
    final TextPosition? existingSelectionEnd = _textSelectionEnd;

    _setSelectionPosition(null, isEnd: isEnd);
    final Matrix4 transform = paragraph.getTransformTo(null);
    transform.invert();
    final Offset localPosition = MatrixUtils.transformPoint(transform, globalPosition);
    if (_rect.isEmpty) {
      return SelectionUtils.getResultBasedOnRect(_rect, localPosition);
    }
    final Offset adjustedOffset = SelectionUtils.adjustDragOffset(
      _rect,
      localPosition,
      direction: paragraph.textDirection,
    );

    final TextPosition position = paragraph.getPositionForOffset(adjustedOffset);
    // Check if the original local position is within the rect, if it is not then
    // we do not need to look up the text boundary for that position. This is to
    // maintain a selectables selection collapsed at 0 when the local position is
    // not located inside its rect.
    _TextBoundaryRecord? textBoundary = _rect.contains(localPosition)
        ? getTextBoundary(position)
        : null;
    if (textBoundary != null &&
        (textBoundary.boundaryStart.offset < range.start &&
                textBoundary.boundaryEnd.offset <= range.start ||
            textBoundary.boundaryStart.offset >= range.end &&
                textBoundary.boundaryEnd.offset > range.end)) {
      // When the position is located at a placeholder inside of the text, then we may compute
      // a text boundary that does not belong to the current selectable fragment. In this case
      // we should invalidate the text boundary so that it is not taken into account when
      // computing the target position.
      textBoundary = null;
    }
    final TextPosition targetPosition = _clampTextPosition(
      isEnd
          ? _updateSelectionEndEdgeByTextBoundary(
              textBoundary,
              getTextBoundary,
              position,
              existingSelectionStart,
              existingSelectionEnd,
            )
          : _updateSelectionStartEdgeByTextBoundary(
              textBoundary,
              getTextBoundary,
              position,
              existingSelectionStart,
              existingSelectionEnd,
            ),
    );

    _setSelectionPosition(targetPosition, isEnd: isEnd);
    if (targetPosition.offset == range.end) {
      return SelectionResult.next;
    }

    if (targetPosition.offset == range.start) {
      return SelectionResult.previous;
    }
    // TODO(chunhtai): The geometry information should not be used to determine
    // selection result. This is a workaround to RenderParagraph, where it does
    // not have a way to get accurate text length if its text is truncated due to
    // layout constraint.
    return SelectionUtils.getResultBasedOnRect(_rect, localPosition);
  }

  SelectionResult _updateSelectionEdge(Offset globalPosition, {required bool isEnd}) {
    _setSelectionPosition(null, isEnd: isEnd);
    final Matrix4 transform = paragraph.getTransformTo(null);
    transform.invert();
    final Offset localPosition = MatrixUtils.transformPoint(transform, globalPosition);
    if (_rect.isEmpty) {
      return SelectionUtils.getResultBasedOnRect(_rect, localPosition);
    }
    final Offset adjustedOffset = SelectionUtils.adjustDragOffset(
      _rect,
      localPosition,
      direction: paragraph.textDirection,
    );

    final TextPosition position = _clampTextPosition(
      paragraph.getPositionForOffset(adjustedOffset),
    );
    _setSelectionPosition(position, isEnd: isEnd);
    if (position.offset == range.end) {
      return SelectionResult.next;
    }
    if (position.offset == range.start) {
      return SelectionResult.previous;
    }
    // TODO(chunhtai): The geometry information should not be used to determine
    // selection result. This is a workaround to RenderParagraph, where it does
    // not have a way to get accurate text length if its text is truncated due to
    // layout constraint.
    return SelectionUtils.getResultBasedOnRect(_rect, localPosition);
  }

  // This method handles updating the start edge by a text boundary that may
  // not be contained within this selectable fragment. It is possible
  // that a boundary spans multiple selectable fragments when the text contains
  // [WidgetSpan]s.
  //
  // This method differs from [_updateSelectionStartEdgeByTextBoundary] in that
  // to pivot offset used to swap selection edges and maintain the origin
  // text boundary selected may be located outside of this selectable fragment.
  //
  // See [_updateSelectionEndEdgeByMultiSelectableTextBoundary] for the method
  // that handles updating the end edge.
  SelectionResult? _updateSelectionStartEdgeByMultiSelectableTextBoundary(
    _TextBoundaryAtPositionInText getTextBoundary,
    bool paragraphContainsPosition,
    TextPosition position,
    TextPosition? existingSelectionStart,
    TextPosition? existingSelectionEnd,
  ) {
    const bool isEnd = false;
    if (_selectableContainsOriginTextBoundary &&
        existingSelectionStart != null &&
        existingSelectionEnd != null) {
      // If this selectable contains the origin boundary, maintain the existing
      // selection.
      final bool forwardSelection = existingSelectionEnd.offset >= existingSelectionStart.offset;
      if (paragraphContainsPosition) {
        // When the position is within the root paragraph, swap the start and end
        // edges when the selection is inverted.
        final _TextBoundaryRecord boundaryAtPosition = getTextBoundary(position, fullText);
        // To accurately retrieve the origin text boundary when the selection
        // is forward, use existingSelectionEnd.offset - 1. This is necessary
        // because in a forwards selection, existingSelectionEnd marks the end
        // of the origin text boundary. Using the unmodified offset incorrectly
        // targets the subsequent text boundary.
        final _TextBoundaryRecord originTextBoundary = getTextBoundary(
          forwardSelection
              ? TextPosition(
                  offset: existingSelectionEnd.offset - 1,
                  affinity: existingSelectionEnd.affinity,
                )
              : existingSelectionEnd,
          fullText,
        );
        final TextPosition targetPosition;
        final int pivotOffset = forwardSelection
            ? originTextBoundary.boundaryEnd.offset
            : originTextBoundary.boundaryStart.offset;
        final bool shouldSwapEdges = !forwardSelection != (position.offset > pivotOffset);
        if (position.offset < pivotOffset) {
          targetPosition = boundaryAtPosition.boundaryStart;
        } else if (position.offset > pivotOffset) {
          targetPosition = boundaryAtPosition.boundaryEnd;
        } else {
          // Keep the origin text boundary in bounds when position is at the static edge.
          targetPosition = forwardSelection ? existingSelectionStart : existingSelectionEnd;
        }
        if (shouldSwapEdges) {
          _setSelectionPosition(
            _clampTextPosition(
              forwardSelection ? originTextBoundary.boundaryStart : originTextBoundary.boundaryEnd,
            ),
            isEnd: true,
          );
        }
        _setSelectionPosition(_clampTextPosition(targetPosition), isEnd: isEnd);
        final bool finalSelectionIsForward =
            _textSelectionEnd!.offset >= _textSelectionStart!.offset;
        if (boundaryAtPosition.boundaryStart.offset > range.end &&
            boundaryAtPosition.boundaryEnd.offset > range.end) {
          return SelectionResult.next;
        }
        if (boundaryAtPosition.boundaryStart.offset < range.start &&
            boundaryAtPosition.boundaryEnd.offset < range.start) {
          return SelectionResult.previous;
        }
        if (finalSelectionIsForward) {
          if (boundaryAtPosition.boundaryStart.offset >= originTextBoundary.boundaryStart.offset) {
            return SelectionResult.end;
          }
          if (boundaryAtPosition.boundaryStart.offset < originTextBoundary.boundaryStart.offset) {
            return SelectionResult.previous;
          }
        } else {
          if (boundaryAtPosition.boundaryEnd.offset <= originTextBoundary.boundaryEnd.offset) {
            return SelectionResult.end;
          }
          if (boundaryAtPosition.boundaryEnd.offset > originTextBoundary.boundaryEnd.offset) {
            return SelectionResult.next;
          }
        }
      } else {
        // When the drag position is not contained within the root paragraph,
        // swap the edges when the selection changes direction.
        final TextPosition clampedPosition = _clampTextPosition(position);
        // To accurately retrieve the origin text boundary when the selection
        // is forward, use existingSelectionEnd.offset - 1. This is necessary
        // because in a forwards selection, existingSelectionEnd marks the end
        // of the origin text boundary. Using the unmodified offset incorrectly
        // targets the subsequent text boundary.
        final _TextBoundaryRecord originTextBoundary = getTextBoundary(
          forwardSelection
              ? TextPosition(
                  offset: existingSelectionEnd.offset - 1,
                  affinity: existingSelectionEnd.affinity,
                )
              : existingSelectionEnd,
          fullText,
        );
        if (forwardSelection && clampedPosition.offset == range.start) {
          _setSelectionPosition(clampedPosition, isEnd: isEnd);
          return SelectionResult.previous;
        }
        if (!forwardSelection && clampedPosition.offset == range.end) {
          _setSelectionPosition(clampedPosition, isEnd: isEnd);
          return SelectionResult.next;
        }
        if (forwardSelection && clampedPosition.offset == range.end) {
          _setSelectionPosition(_clampTextPosition(originTextBoundary.boundaryStart), isEnd: true);
          _setSelectionPosition(clampedPosition, isEnd: isEnd);
          return SelectionResult.next;
        }
        if (!forwardSelection && clampedPosition.offset == range.start) {
          _setSelectionPosition(_clampTextPosition(originTextBoundary.boundaryEnd), isEnd: true);
          _setSelectionPosition(clampedPosition, isEnd: isEnd);
          return SelectionResult.previous;
        }
      }
    } else {
      // A paragraph boundary may not be completely contained within this root
      // selectable fragment. Keep searching until we find the end of the
      // boundary. Do not search when the current drag position is on a placeholder
      // to allow traversal to reach that placeholder.
      final bool positionOnPlaceholder =
          paragraph.getWordBoundary(position).textInside(fullText) == _placeholderCharacter;
      if (!paragraphContainsPosition || positionOnPlaceholder) {
        return null;
      }
      if (existingSelectionEnd != null) {
        final _TextBoundaryRecord boundaryAtPosition = getTextBoundary(position, fullText);
        final bool backwardSelection =
            existingSelectionStart == null && existingSelectionEnd.offset == range.start ||
            existingSelectionStart == existingSelectionEnd &&
                existingSelectionEnd.offset == range.start ||
            existingSelectionStart != null &&
                existingSelectionStart.offset > existingSelectionEnd.offset;
        if (boundaryAtPosition.boundaryStart.offset < range.start &&
            boundaryAtPosition.boundaryEnd.offset < range.start) {
          _setSelectionPosition(TextPosition(offset: range.start), isEnd: isEnd);
          return SelectionResult.previous;
        }
        if (boundaryAtPosition.boundaryStart.offset > range.end &&
            boundaryAtPosition.boundaryEnd.offset > range.end) {
          _setSelectionPosition(TextPosition(offset: range.end), isEnd: isEnd);
          return SelectionResult.next;
        }
        if (backwardSelection) {
          if (boundaryAtPosition.boundaryEnd.offset <= range.end) {
            _setSelectionPosition(_clampTextPosition(boundaryAtPosition.boundaryEnd), isEnd: isEnd);
            return SelectionResult.end;
          }
          if (boundaryAtPosition.boundaryEnd.offset > range.end) {
            _setSelectionPosition(TextPosition(offset: range.end), isEnd: isEnd);
            return SelectionResult.next;
          }
        } else {
          _setSelectionPosition(_clampTextPosition(boundaryAtPosition.boundaryStart), isEnd: isEnd);
          if (boundaryAtPosition.boundaryStart.offset < range.start) {
            return SelectionResult.previous;
          }
          if (boundaryAtPosition.boundaryStart.offset >= range.start) {
            return SelectionResult.end;
          }
        }
      }
    }
    return null;
  }

  // This method handles updating the end edge by a text boundary that may
  // not be contained within this selectable fragment. It is possible
  // that a boundary spans multiple selectable fragments when the text contains
  // [WidgetSpan]s.
  //
  // This method differs from [_updateSelectionEndEdgeByTextBoundary] in that
  // to pivot offset used to swap selection edges and maintain the origin
  // text boundary selected may be located outside of this selectable fragment.
  //
  // See [_updateSelectionStartEdgeByMultiSelectableTextBoundary] for the method
  // that handles updating the end edge.
  SelectionResult? _updateSelectionEndEdgeByMultiSelectableTextBoundary(
    _TextBoundaryAtPositionInText getTextBoundary,
    bool paragraphContainsPosition,
    TextPosition position,
    TextPosition? existingSelectionStart,
    TextPosition? existingSelectionEnd,
  ) {
    const bool isEnd = true;
    if (_selectableContainsOriginTextBoundary &&
        existingSelectionStart != null &&
        existingSelectionEnd != null) {
      // If this selectable contains the origin boundary, maintain the existing
      // selection.
      final bool forwardSelection = existingSelectionEnd.offset >= existingSelectionStart.offset;
      if (paragraphContainsPosition) {
        // When the position is within the root paragraph, swap the start and end
        // edges when the selection is inverted.
        final _TextBoundaryRecord boundaryAtPosition = getTextBoundary(position, fullText);
        // To accurately retrieve the origin text boundary when the selection
        // is backwards, use existingSelectionStart.offset - 1. This is necessary
        // because in a backwards selection, existingSelectionStart marks the end
        // of the origin text boundary. Using the unmodified offset incorrectly
        // targets the subsequent text boundary.
        final _TextBoundaryRecord originTextBoundary = getTextBoundary(
          forwardSelection
              ? existingSelectionStart
              : TextPosition(
                  offset: existingSelectionStart.offset - 1,
                  affinity: existingSelectionStart.affinity,
                ),
          fullText,
        );
        final TextPosition targetPosition;
        final int pivotOffset = forwardSelection
            ? originTextBoundary.boundaryStart.offset
            : originTextBoundary.boundaryEnd.offset;
        final bool shouldSwapEdges = !forwardSelection != (position.offset < pivotOffset);
        if (position.offset < pivotOffset) {
          targetPosition = boundaryAtPosition.boundaryStart;
        } else if (position.offset > pivotOffset) {
          targetPosition = boundaryAtPosition.boundaryEnd;
        } else {
          // Keep the origin text boundary in bounds when position is at the static edge.
          targetPosition = forwardSelection ? existingSelectionEnd : existingSelectionStart;
        }
        if (shouldSwapEdges) {
          _setSelectionPosition(
            _clampTextPosition(
              forwardSelection ? originTextBoundary.boundaryEnd : originTextBoundary.boundaryStart,
            ),
            isEnd: false,
          );
        }
        _setSelectionPosition(_clampTextPosition(targetPosition), isEnd: isEnd);
        final bool finalSelectionIsForward =
            _textSelectionEnd!.offset >= _textSelectionStart!.offset;
        if (boundaryAtPosition.boundaryStart.offset > range.end &&
            boundaryAtPosition.boundaryEnd.offset > range.end) {
          return SelectionResult.next;
        }
        if (boundaryAtPosition.boundaryStart.offset < range.start &&
            boundaryAtPosition.boundaryEnd.offset < range.start) {
          return SelectionResult.previous;
        }
        if (finalSelectionIsForward) {
          if (boundaryAtPosition.boundaryEnd.offset <= originTextBoundary.boundaryEnd.offset) {
            return SelectionResult.end;
          }
          if (boundaryAtPosition.boundaryEnd.offset > originTextBoundary.boundaryEnd.offset) {
            return SelectionResult.next;
          }
        } else {
          if (boundaryAtPosition.boundaryStart.offset >= originTextBoundary.boundaryStart.offset) {
            return SelectionResult.end;
          }
          if (boundaryAtPosition.boundaryStart.offset < originTextBoundary.boundaryStart.offset) {
            return SelectionResult.previous;
          }
        }
      } else {
        // When the drag position is not contained within the root paragraph,
        // swap the edges when the selection changes direction.
        final TextPosition clampedPosition = _clampTextPosition(position);
        // To accurately retrieve the origin text boundary when the selection
        // is backwards, use existingSelectionStart.offset - 1. This is necessary
        // because in a backwards selection, existingSelectionStart marks the end
        // of the origin text boundary. Using the unmodified offset incorrectly
        // targets the subsequent text boundary.
        final _TextBoundaryRecord originTextBoundary = getTextBoundary(
          forwardSelection
              ? existingSelectionStart
              : TextPosition(
                  offset: existingSelectionStart.offset - 1,
                  affinity: existingSelectionStart.affinity,
                ),
          fullText,
        );
        if (forwardSelection && clampedPosition.offset == range.start) {
          _setSelectionPosition(_clampTextPosition(originTextBoundary.boundaryEnd), isEnd: false);
          _setSelectionPosition(clampedPosition, isEnd: isEnd);
          return SelectionResult.previous;
        }
        if (!forwardSelection && clampedPosition.offset == range.end) {
          _setSelectionPosition(_clampTextPosition(originTextBoundary.boundaryStart), isEnd: false);
          _setSelectionPosition(clampedPosition, isEnd: isEnd);
          return SelectionResult.next;
        }
        if (forwardSelection && clampedPosition.offset == range.end) {
          _setSelectionPosition(clampedPosition, isEnd: isEnd);
          return SelectionResult.next;
        }
        if (!forwardSelection && clampedPosition.offset == range.start) {
          _setSelectionPosition(clampedPosition, isEnd: isEnd);
          return SelectionResult.previous;
        }
      }
    } else {
      // A paragraph boundary may not be completely contained within this root
      // selectable fragment. Keep searching until we find the end of the
      // boundary. Do not search when the current drag position is on a placeholder
      // to allow traversal to reach that placeholder.
      final bool positionOnPlaceholder =
          paragraph.getWordBoundary(position).textInside(fullText) == _placeholderCharacter;
      if (!paragraphContainsPosition || positionOnPlaceholder) {
        return null;
      }
      if (existingSelectionStart != null) {
        final _TextBoundaryRecord boundaryAtPosition = getTextBoundary(position, fullText);
        final bool backwardSelection =
            existingSelectionEnd == null && existingSelectionStart.offset == range.end ||
            existingSelectionStart == existingSelectionEnd &&
                existingSelectionStart.offset == range.end ||
            existingSelectionEnd != null &&
                existingSelectionStart.offset > existingSelectionEnd.offset;
        if (boundaryAtPosition.boundaryStart.offset < range.start &&
            boundaryAtPosition.boundaryEnd.offset < range.start) {
          _setSelectionPosition(TextPosition(offset: range.start), isEnd: isEnd);
          return SelectionResult.previous;
        }
        if (boundaryAtPosition.boundaryStart.offset > range.end &&
            boundaryAtPosition.boundaryEnd.offset > range.end) {
          _setSelectionPosition(TextPosition(offset: range.end), isEnd: isEnd);
          return SelectionResult.next;
        }
        if (backwardSelection) {
          _setSelectionPosition(_clampTextPosition(boundaryAtPosition.boundaryStart), isEnd: isEnd);
          if (boundaryAtPosition.boundaryStart.offset < range.start) {
            return SelectionResult.previous;
          }
          if (boundaryAtPosition.boundaryStart.offset >= range.start) {
            return SelectionResult.end;
          }
        } else {
          if (boundaryAtPosition.boundaryEnd.offset <= range.end) {
            _setSelectionPosition(_clampTextPosition(boundaryAtPosition.boundaryEnd), isEnd: isEnd);
            return SelectionResult.end;
          }
          if (boundaryAtPosition.boundaryEnd.offset > range.end) {
            _setSelectionPosition(TextPosition(offset: range.end), isEnd: isEnd);
            return SelectionResult.next;
          }
        }
      }
    }
    return null;
  }

  // The placeholder character used by [RenderParagraph].
  static final String _placeholderCharacter = String.fromCharCode(
    PlaceholderSpan.placeholderCodeUnit,
  );
  static final int _placeholderLength = _placeholderCharacter.length;
  // This method handles updating the start edge by a text boundary that may
  // not be contained within this selectable fragment. It is possible
  // that a boundary spans multiple selectable fragments when the text contains
  // [WidgetSpan]s.
  //
  // This method differs from [_updateSelectionStartEdgeByMultiSelectableBoundary]
  // in that to maintain the origin text boundary selected at a placeholder,
  // this selectable fragment must be aware of the [RenderParagraph] that closely
  // encompasses the complete origin text boundary.
  //
  // See [_updateSelectionEndEdgeAtPlaceholderByMultiSelectableTextBoundary] for the method
  // that handles updating the end edge.
  SelectionResult? _updateSelectionStartEdgeAtPlaceholderByMultiSelectableTextBoundary(
    _TextBoundaryAtPositionInText getTextBoundary,
    Offset globalPosition,
    bool paragraphContainsPosition,
    TextPosition position,
    TextPosition? existingSelectionStart,
    TextPosition? existingSelectionEnd,
  ) {
    const bool isEnd = false;
    if (_selectableContainsOriginTextBoundary &&
        existingSelectionStart != null &&
        existingSelectionEnd != null) {
      // If this selectable contains the origin boundary, maintain the existing
      // selection.
      final bool forwardSelection = existingSelectionEnd.offset >= existingSelectionStart.offset;
      final RenderParagraph originParagraph = _getOriginParagraph();
      final bool fragmentBelongsToOriginParagraph = originParagraph == paragraph;
      if (fragmentBelongsToOriginParagraph) {
        return _updateSelectionStartEdgeByMultiSelectableTextBoundary(
          getTextBoundary,
          paragraphContainsPosition,
          position,
          existingSelectionStart,
          existingSelectionEnd,
        );
      }
      final Matrix4 originTransform = originParagraph.getTransformTo(null);
      originTransform.invert();
      final Offset originParagraphLocalPosition = MatrixUtils.transformPoint(
        originTransform,
        globalPosition,
      );
      final bool positionWithinOriginParagraph = originParagraph.paintBounds.contains(
        originParagraphLocalPosition,
      );
      final TextPosition positionRelativeToOriginParagraph = originParagraph.getPositionForOffset(
        originParagraphLocalPosition,
      );
      if (positionWithinOriginParagraph) {
        // When the selection is inverted by the new position it is necessary to
        // swap the start edge (moving edge) with the end edge (static edge) to
        // maintain the origin text boundary within the selection.
        final String originText = originParagraph.text.toPlainText(includeSemanticsLabels: false);
        final _TextBoundaryRecord boundaryAtPosition = getTextBoundary(
          positionRelativeToOriginParagraph,
          originText,
        );
        final _TextBoundaryRecord originTextBoundary = getTextBoundary(
          _getPositionInParagraph(originParagraph),
          originText,
        );
        final TextPosition targetPosition;
        final int pivotOffset = forwardSelection
            ? originTextBoundary.boundaryEnd.offset
            : originTextBoundary.boundaryStart.offset;
        final bool shouldSwapEdges =
            !forwardSelection != (positionRelativeToOriginParagraph.offset > pivotOffset);
        if (positionRelativeToOriginParagraph.offset < pivotOffset) {
          targetPosition = boundaryAtPosition.boundaryStart;
        } else if (positionRelativeToOriginParagraph.offset > pivotOffset) {
          targetPosition = boundaryAtPosition.boundaryEnd;
        } else {
          // Keep the origin text boundary in bounds when position is at the static edge.
          targetPosition = existingSelectionStart;
        }
        if (shouldSwapEdges) {
          _setSelectionPosition(existingSelectionStart, isEnd: true);
        }
        _setSelectionPosition(_clampTextPosition(targetPosition), isEnd: isEnd);
        final bool finalSelectionIsForward =
            _textSelectionEnd!.offset >= _textSelectionStart!.offset;
        final TextPosition originParagraphPlaceholderTextPosition = _getPositionInParagraph(
          originParagraph,
        );
        final TextRange originParagraphPlaceholderRange = TextRange(
          start: originParagraphPlaceholderTextPosition.offset,
          end: originParagraphPlaceholderTextPosition.offset + _placeholderLength,
        );
        if (boundaryAtPosition.boundaryStart.offset > originParagraphPlaceholderRange.end &&
            boundaryAtPosition.boundaryEnd.offset > originParagraphPlaceholderRange.end) {
          return SelectionResult.next;
        }
        if (boundaryAtPosition.boundaryStart.offset < originParagraphPlaceholderRange.start &&
            boundaryAtPosition.boundaryEnd.offset < originParagraphPlaceholderRange.start) {
          return SelectionResult.previous;
        }
        if (finalSelectionIsForward) {
          if (boundaryAtPosition.boundaryEnd.offset <= originTextBoundary.boundaryEnd.offset) {
            return SelectionResult.end;
          }
          if (boundaryAtPosition.boundaryEnd.offset > originTextBoundary.boundaryEnd.offset) {
            return SelectionResult.next;
          }
        } else {
          if (boundaryAtPosition.boundaryStart.offset >= originTextBoundary.boundaryStart.offset) {
            return SelectionResult.end;
          }
          if (boundaryAtPosition.boundaryStart.offset < originTextBoundary.boundaryStart.offset) {
            return SelectionResult.previous;
          }
        }
      } else {
        // When the drag position is not contained within the origin paragraph,
        // swap the edges when the selection changes direction.
        //
        // [SelectionUtils.adjustDragOffset] will adjust the given [Offset] to the
        // beginning or end of the provided [Rect] based on whether the [Offset]
        // is located within the given [Rect].
        final Offset adjustedOffset = SelectionUtils.adjustDragOffset(
          originParagraph.paintBounds,
          originParagraphLocalPosition,
          direction: paragraph.textDirection,
        );
        final TextPosition adjustedPositionRelativeToOriginParagraph = originParagraph
            .getPositionForOffset(adjustedOffset);
        final TextPosition originParagraphPlaceholderTextPosition = _getPositionInParagraph(
          originParagraph,
        );
        final TextRange originParagraphPlaceholderRange = TextRange(
          start: originParagraphPlaceholderTextPosition.offset,
          end: originParagraphPlaceholderTextPosition.offset + _placeholderLength,
        );
        if (forwardSelection &&
            adjustedPositionRelativeToOriginParagraph.offset <=
                originParagraphPlaceholderRange.start) {
          _setSelectionPosition(TextPosition(offset: range.start), isEnd: isEnd);
          return SelectionResult.previous;
        }
        if (!forwardSelection &&
            adjustedPositionRelativeToOriginParagraph.offset >=
                originParagraphPlaceholderRange.end) {
          _setSelectionPosition(TextPosition(offset: range.end), isEnd: isEnd);
          return SelectionResult.next;
        }
        if (forwardSelection &&
            adjustedPositionRelativeToOriginParagraph.offset >=
                originParagraphPlaceholderRange.end) {
          _setSelectionPosition(existingSelectionStart, isEnd: true);
          _setSelectionPosition(TextPosition(offset: range.end), isEnd: isEnd);
          return SelectionResult.next;
        }
        if (!forwardSelection &&
            adjustedPositionRelativeToOriginParagraph.offset <=
                originParagraphPlaceholderRange.start) {
          _setSelectionPosition(existingSelectionStart, isEnd: true);
          _setSelectionPosition(TextPosition(offset: range.start), isEnd: isEnd);
          return SelectionResult.previous;
        }
      }
    } else {
      // When the drag position is somewhere on the root text and not a placeholder,
      // traverse the selectable fragments relative to the [RenderParagraph] that
      // contains the drag position.
      if (paragraphContainsPosition) {
        return _updateSelectionStartEdgeByMultiSelectableTextBoundary(
          getTextBoundary,
          paragraphContainsPosition,
          position,
          existingSelectionStart,
          existingSelectionEnd,
        );
      }
      if (existingSelectionEnd != null) {
        final ({RenderParagraph paragraph, Offset localPosition})? targetDetails =
            _getParagraphContainingPosition(globalPosition);
        if (targetDetails == null) {
          return null;
        }
        final RenderParagraph targetParagraph = targetDetails.paragraph;
        final TextPosition positionRelativeToTargetParagraph = targetParagraph.getPositionForOffset(
          targetDetails.localPosition,
        );
        final String targetText = targetParagraph.text.toPlainText(includeSemanticsLabels: false);
        final bool positionOnPlaceholder =
            targetParagraph
                .getWordBoundary(positionRelativeToTargetParagraph)
                .textInside(targetText) ==
            _placeholderCharacter;
        if (positionOnPlaceholder) {
          return null;
        }
        final bool backwardSelection =
            existingSelectionStart == null && existingSelectionEnd.offset == range.start ||
            existingSelectionStart == existingSelectionEnd &&
                existingSelectionEnd.offset == range.start ||
            existingSelectionStart != null &&
                existingSelectionStart.offset > existingSelectionEnd.offset;
        final _TextBoundaryRecord boundaryAtPositionRelativeToTargetParagraph = getTextBoundary(
          positionRelativeToTargetParagraph,
          targetText,
        );
        final TextPosition targetParagraphPlaceholderTextPosition = _getPositionInParagraph(
          targetParagraph,
        );
        final TextRange targetParagraphPlaceholderRange = TextRange(
          start: targetParagraphPlaceholderTextPosition.offset,
          end: targetParagraphPlaceholderTextPosition.offset + _placeholderLength,
        );
        if (boundaryAtPositionRelativeToTargetParagraph.boundaryStart.offset <
                targetParagraphPlaceholderRange.start &&
            boundaryAtPositionRelativeToTargetParagraph.boundaryEnd.offset <
                targetParagraphPlaceholderRange.start) {
          _setSelectionPosition(TextPosition(offset: range.start), isEnd: isEnd);
          return SelectionResult.previous;
        }
        if (boundaryAtPositionRelativeToTargetParagraph.boundaryStart.offset >
                targetParagraphPlaceholderRange.end &&
            boundaryAtPositionRelativeToTargetParagraph.boundaryEnd.offset >
                targetParagraphPlaceholderRange.end) {
          _setSelectionPosition(TextPosition(offset: range.end), isEnd: isEnd);
          return SelectionResult.next;
        }
        if (backwardSelection) {
          if (boundaryAtPositionRelativeToTargetParagraph.boundaryEnd.offset <=
              targetParagraphPlaceholderRange.end) {
            _setSelectionPosition(TextPosition(offset: range.end), isEnd: isEnd);
            return SelectionResult.end;
          }
          if (boundaryAtPositionRelativeToTargetParagraph.boundaryEnd.offset >
              targetParagraphPlaceholderRange.end) {
            _setSelectionPosition(TextPosition(offset: range.end), isEnd: isEnd);
            return SelectionResult.next;
          }
        } else {
          if (boundaryAtPositionRelativeToTargetParagraph.boundaryStart.offset >=
              targetParagraphPlaceholderRange.start) {
            _setSelectionPosition(TextPosition(offset: range.start), isEnd: isEnd);
            return SelectionResult.end;
          }
          if (boundaryAtPositionRelativeToTargetParagraph.boundaryStart.offset <
              targetParagraphPlaceholderRange.start) {
            _setSelectionPosition(TextPosition(offset: range.start), isEnd: isEnd);
            return SelectionResult.previous;
          }
        }
      }
    }
    return null;
  }

  // This method handles updating the end edge by a text boundary that may
  // not be contained within this selectable fragment. It is possible
  // that a boundary spans multiple selectable fragments when the text contains
  // [WidgetSpan]s.
  //
  // This method differs from [_updateSelectionEndEdgeByMultiSelectableBoundary]
  // in that to maintain the origin text boundary selected at a placeholder, this
  // selectable fragment must be aware of the [RenderParagraph] that closely
  // encompasses the complete origin text boundary.
  //
  // See [_updateSelectionStartEdgeAtPlaceholderByMultiSelectableTextBoundary]
  // for the method that handles updating the start edge.
  SelectionResult? _updateSelectionEndEdgeAtPlaceholderByMultiSelectableTextBoundary(
    _TextBoundaryAtPositionInText getTextBoundary,
    Offset globalPosition,
    bool paragraphContainsPosition,
    TextPosition position,
    TextPosition? existingSelectionStart,
    TextPosition? existingSelectionEnd,
  ) {
    const bool isEnd = true;
    if (_selectableContainsOriginTextBoundary &&
        existingSelectionStart != null &&
        existingSelectionEnd != null) {
      // If this selectable contains the origin boundary, maintain the existing
      // selection.
      final bool forwardSelection = existingSelectionEnd.offset >= existingSelectionStart.offset;
      final RenderParagraph originParagraph = _getOriginParagraph();
      final bool fragmentBelongsToOriginParagraph = originParagraph == paragraph;
      if (fragmentBelongsToOriginParagraph) {
        return _updateSelectionEndEdgeByMultiSelectableTextBoundary(
          getTextBoundary,
          paragraphContainsPosition,
          position,
          existingSelectionStart,
          existingSelectionEnd,
        );
      }
      final Matrix4 originTransform = originParagraph.getTransformTo(null);
      originTransform.invert();
      final Offset originParagraphLocalPosition = MatrixUtils.transformPoint(
        originTransform,
        globalPosition,
      );
      final bool positionWithinOriginParagraph = originParagraph.paintBounds.contains(
        originParagraphLocalPosition,
      );
      final TextPosition positionRelativeToOriginParagraph = originParagraph.getPositionForOffset(
        originParagraphLocalPosition,
      );
      if (positionWithinOriginParagraph) {
        // When the selection is inverted by the new position it is necessary to
        // swap the end edge (moving edge) with the start edge (static edge) to
        // maintain the origin text boundary within the selection.
        final String originText = originParagraph.text.toPlainText(includeSemanticsLabels: false);
        final _TextBoundaryRecord boundaryAtPosition = getTextBoundary(
          positionRelativeToOriginParagraph,
          originText,
        );
        final _TextBoundaryRecord originTextBoundary = getTextBoundary(
          _getPositionInParagraph(originParagraph),
          originText,
        );
        final TextPosition targetPosition;
        final int pivotOffset = forwardSelection
            ? originTextBoundary.boundaryStart.offset
            : originTextBoundary.boundaryEnd.offset;
        final bool shouldSwapEdges =
            !forwardSelection != (positionRelativeToOriginParagraph.offset < pivotOffset);
        if (positionRelativeToOriginParagraph.offset < pivotOffset) {
          targetPosition = boundaryAtPosition.boundaryStart;
        } else if (positionRelativeToOriginParagraph.offset > pivotOffset) {
          targetPosition = boundaryAtPosition.boundaryEnd;
        } else {
          // Keep the origin text boundary in bounds when position is at the static edge.
          targetPosition = existingSelectionEnd;
        }
        if (shouldSwapEdges) {
          _setSelectionPosition(existingSelectionEnd, isEnd: false);
        }
        _setSelectionPosition(_clampTextPosition(targetPosition), isEnd: isEnd);
        final bool finalSelectionIsForward =
            _textSelectionEnd!.offset >= _textSelectionStart!.offset;
        final TextPosition originParagraphPlaceholderTextPosition = _getPositionInParagraph(
          originParagraph,
        );
        final TextRange originParagraphPlaceholderRange = TextRange(
          start: originParagraphPlaceholderTextPosition.offset,
          end: originParagraphPlaceholderTextPosition.offset + _placeholderLength,
        );
        if (boundaryAtPosition.boundaryStart.offset > originParagraphPlaceholderRange.end &&
            boundaryAtPosition.boundaryEnd.offset > originParagraphPlaceholderRange.end) {
          return SelectionResult.next;
        }
        if (boundaryAtPosition.boundaryStart.offset < originParagraphPlaceholderRange.start &&
            boundaryAtPosition.boundaryEnd.offset < originParagraphPlaceholderRange.start) {
          return SelectionResult.previous;
        }
        if (finalSelectionIsForward) {
          if (boundaryAtPosition.boundaryEnd.offset <= originTextBoundary.boundaryEnd.offset) {
            return SelectionResult.end;
          }
          if (boundaryAtPosition.boundaryEnd.offset > originTextBoundary.boundaryEnd.offset) {
            return SelectionResult.next;
          }
        } else {
          if (boundaryAtPosition.boundaryStart.offset >= originTextBoundary.boundaryStart.offset) {
            return SelectionResult.end;
          }
          if (boundaryAtPosition.boundaryStart.offset < originTextBoundary.boundaryStart.offset) {
            return SelectionResult.previous;
          }
        }
      } else {
        // When the drag position is not contained within the origin paragraph,
        // swap the edges when the selection changes direction.
        //
        // [SelectionUtils.adjustDragOffset] will adjust the given [Offset] to the
        // beginning or end of the provided [Rect] based on whether the [Offset]
        // is located within the given [Rect].
        final Offset adjustedOffset = SelectionUtils.adjustDragOffset(
          originParagraph.paintBounds,
          originParagraphLocalPosition,
          direction: paragraph.textDirection,
        );
        final TextPosition adjustedPositionRelativeToOriginParagraph = originParagraph
            .getPositionForOffset(adjustedOffset);
        final TextPosition originParagraphPlaceholderTextPosition = _getPositionInParagraph(
          originParagraph,
        );
        final TextRange originParagraphPlaceholderRange = TextRange(
          start: originParagraphPlaceholderTextPosition.offset,
          end: originParagraphPlaceholderTextPosition.offset + _placeholderLength,
        );
        if (forwardSelection &&
            adjustedPositionRelativeToOriginParagraph.offset <=
                originParagraphPlaceholderRange.start) {
          _setSelectionPosition(existingSelectionEnd, isEnd: false);
          _setSelectionPosition(TextPosition(offset: range.start), isEnd: isEnd);
          return SelectionResult.previous;
        }
        if (!forwardSelection &&
            adjustedPositionRelativeToOriginParagraph.offset >=
                originParagraphPlaceholderRange.end) {
          _setSelectionPosition(existingSelectionEnd, isEnd: false);
          _setSelectionPosition(TextPosition(offset: range.end), isEnd: isEnd);
          return SelectionResult.next;
        }
        if (forwardSelection &&
            adjustedPositionRelativeToOriginParagraph.offset >=
                originParagraphPlaceholderRange.end) {
          _setSelectionPosition(TextPosition(offset: range.end), isEnd: isEnd);
          return SelectionResult.next;
        }
        if (!forwardSelection &&
            adjustedPositionRelativeToOriginParagraph.offset <=
                originParagraphPlaceholderRange.start) {
          _setSelectionPosition(TextPosition(offset: range.start), isEnd: isEnd);
          return SelectionResult.previous;
        }
      }
    } else {
      // When the drag position is somewhere on the root text and not a placeholder,
      // traverse the selectable fragments relative to the [RenderParagraph] that
      // contains the drag position.
      if (paragraphContainsPosition) {
        return _updateSelectionEndEdgeByMultiSelectableTextBoundary(
          getTextBoundary,
          paragraphContainsPosition,
          position,
          existingSelectionStart,
          existingSelectionEnd,
        );
      }
      if (existingSelectionStart != null) {
        final ({RenderParagraph paragraph, Offset localPosition})? targetDetails =
            _getParagraphContainingPosition(globalPosition);
        if (targetDetails == null) {
          return null;
        }
        final RenderParagraph targetParagraph = targetDetails.paragraph;
        final TextPosition positionRelativeToTargetParagraph = targetParagraph.getPositionForOffset(
          targetDetails.localPosition,
        );
        final String targetText = targetParagraph.text.toPlainText(includeSemanticsLabels: false);
        final bool positionOnPlaceholder =
            targetParagraph
                .getWordBoundary(positionRelativeToTargetParagraph)
                .textInside(targetText) ==
            _placeholderCharacter;
        if (positionOnPlaceholder) {
          return null;
        }
        final bool backwardSelection =
            existingSelectionEnd == null && existingSelectionStart.offset == range.end ||
            existingSelectionStart == existingSelectionEnd &&
                existingSelectionStart.offset == range.end ||
            existingSelectionEnd != null &&
                existingSelectionStart.offset > existingSelectionEnd.offset;
        final _TextBoundaryRecord boundaryAtPositionRelativeToTargetParagraph = getTextBoundary(
          positionRelativeToTargetParagraph,
          targetText,
        );
        final TextPosition targetParagraphPlaceholderTextPosition = _getPositionInParagraph(
          targetParagraph,
        );
        final TextRange targetParagraphPlaceholderRange = TextRange(
          start: targetParagraphPlaceholderTextPosition.offset,
          end: targetParagraphPlaceholderTextPosition.offset + _placeholderLength,
        );
        if (boundaryAtPositionRelativeToTargetParagraph.boundaryStart.offset <
                targetParagraphPlaceholderRange.start &&
            boundaryAtPositionRelativeToTargetParagraph.boundaryEnd.offset <
                targetParagraphPlaceholderRange.start) {
          _setSelectionPosition(TextPosition(offset: range.start), isEnd: isEnd);
          return SelectionResult.previous;
        }
        if (boundaryAtPositionRelativeToTargetParagraph.boundaryStart.offset >
                targetParagraphPlaceholderRange.end &&
            boundaryAtPositionRelativeToTargetParagraph.boundaryEnd.offset >
                targetParagraphPlaceholderRange.end) {
          _setSelectionPosition(TextPosition(offset: range.end), isEnd: isEnd);
          return SelectionResult.next;
        }
        if (backwardSelection) {
          if (boundaryAtPositionRelativeToTargetParagraph.boundaryStart.offset >=
              targetParagraphPlaceholderRange.start) {
            _setSelectionPosition(TextPosition(offset: range.start), isEnd: isEnd);
            return SelectionResult.end;
          }
          if (boundaryAtPositionRelativeToTargetParagraph.boundaryStart.offset <
              targetParagraphPlaceholderRange.start) {
            _setSelectionPosition(TextPosition(offset: range.start), isEnd: isEnd);
            return SelectionResult.previous;
          }
        } else {
          if (boundaryAtPositionRelativeToTargetParagraph.boundaryEnd.offset <=
              targetParagraphPlaceholderRange.end) {
            _setSelectionPosition(TextPosition(offset: range.end), isEnd: isEnd);
            return SelectionResult.end;
          }
          if (boundaryAtPositionRelativeToTargetParagraph.boundaryEnd.offset >
              targetParagraphPlaceholderRange.end) {
            _setSelectionPosition(TextPosition(offset: range.end), isEnd: isEnd);
            return SelectionResult.next;
          }
        }
      }
    }
    return null;
  }

  SelectionResult _updateSelectionEdgeByMultiSelectableTextBoundary(
    Offset globalPosition, {
    required bool isEnd,
    required _TextBoundaryAtPositionInText getTextBoundary,
    required _TextBoundaryAtPosition getClampedTextBoundary,
  }) {
    // When the start/end edges are swapped, i.e. the start is after the end, and
    // the scrollable synthesizes an event for the opposite edge, this will potentially
    // move the opposite edge outside of the origin text boundary and we are unable to recover.
    final TextPosition? existingSelectionStart = _textSelectionStart;
    final TextPosition? existingSelectionEnd = _textSelectionEnd;

    _setSelectionPosition(null, isEnd: isEnd);
    final Matrix4 transform = paragraph.getTransformTo(null);
    transform.invert();
    final Offset localPosition = MatrixUtils.transformPoint(transform, globalPosition);
    if (_rect.isEmpty) {
      return SelectionUtils.getResultBasedOnRect(_rect, localPosition);
    }
    final Offset adjustedOffset = SelectionUtils.adjustDragOffset(
      _rect,
      localPosition,
      direction: paragraph.textDirection,
    );
    final Offset adjustedOffsetRelativeToParagraph = SelectionUtils.adjustDragOffset(
      paragraph.paintBounds,
      localPosition,
      direction: paragraph.textDirection,
    );

    final TextPosition position = paragraph.getPositionForOffset(adjustedOffset);
    final TextPosition positionInFullText = paragraph.getPositionForOffset(
      adjustedOffsetRelativeToParagraph,
    );

    final SelectionResult? result;
    if (_isPlaceholder()) {
      result = isEnd
          ? _updateSelectionEndEdgeAtPlaceholderByMultiSelectableTextBoundary(
              getTextBoundary,
              globalPosition,
              paragraph.paintBounds.contains(localPosition),
              positionInFullText,
              existingSelectionStart,
              existingSelectionEnd,
            )
          : _updateSelectionStartEdgeAtPlaceholderByMultiSelectableTextBoundary(
              getTextBoundary,
              globalPosition,
              paragraph.paintBounds.contains(localPosition),
              positionInFullText,
              existingSelectionStart,
              existingSelectionEnd,
            );
    } else {
      result = isEnd
          ? _updateSelectionEndEdgeByMultiSelectableTextBoundary(
              getTextBoundary,
              paragraph.paintBounds.contains(localPosition),
              positionInFullText,
              existingSelectionStart,
              existingSelectionEnd,
            )
          : _updateSelectionStartEdgeByMultiSelectableTextBoundary(
              getTextBoundary,
              paragraph.paintBounds.contains(localPosition),
              positionInFullText,
              existingSelectionStart,
              existingSelectionEnd,
            );
    }
    if (result != null) {
      return result;
    }

    // Check if the original local position is within the rect, if it is not then
    // we do not need to look up the text boundary for that position. This is to
    // maintain a selectables selection collapsed at 0 when the local position is
    // not located inside its rect.
    _TextBoundaryRecord? textBoundary = _boundingBoxesContains(localPosition)
        ? getClampedTextBoundary(position)
        : null;
    if (textBoundary != null &&
        (textBoundary.boundaryStart.offset < range.start &&
                textBoundary.boundaryEnd.offset <= range.start ||
            textBoundary.boundaryStart.offset >= range.end &&
                textBoundary.boundaryEnd.offset > range.end)) {
      // When the position is located at a placeholder inside of the text, then we may compute
      // a text boundary that does not belong to the current selectable fragment. In this case
      // we should invalidate the text boundary so that it is not taken into account when
      // computing the target position.
      textBoundary = null;
    }
    final TextPosition targetPosition = _clampTextPosition(
      isEnd
          ? _updateSelectionEndEdgeByTextBoundary(
              textBoundary,
              getClampedTextBoundary,
              position,
              existingSelectionStart,
              existingSelectionEnd,
            )
          : _updateSelectionStartEdgeByTextBoundary(
              textBoundary,
              getClampedTextBoundary,
              position,
              existingSelectionStart,
              existingSelectionEnd,
            ),
    );

    _setSelectionPosition(targetPosition, isEnd: isEnd);
    if (targetPosition.offset == range.end) {
      return SelectionResult.next;
    }

    if (targetPosition.offset == range.start) {
      return SelectionResult.previous;
    }
    // TODO(chunhtai): The geometry information should not be used to determine
    // selection result. This is a workaround to RenderParagraph, where it does
    // not have a way to get accurate text length if its text is truncated due to
    // layout constraint.
    return SelectionUtils.getResultBasedOnRect(_rect, localPosition);
  }

  TextPosition _closestTextBoundary(_TextBoundaryRecord textBoundary, TextPosition position) {
    final int differenceA = (position.offset - textBoundary.boundaryStart.offset).abs();
    final int differenceB = (position.offset - textBoundary.boundaryEnd.offset).abs();
    return differenceA < differenceB ? textBoundary.boundaryStart : textBoundary.boundaryEnd;
  }

  bool _isPlaceholder() {
    // Determine whether this selectable fragment is a placeholder.
    RenderObject? current = paragraph.parent;
    while (current != null) {
      if (current is RenderParagraph) {
        return true;
      }
      current = current.parent;
    }
    return false;
  }

  RenderParagraph _getOriginParagraph() {
    // This method should only be called from a fragment that contains
    // the origin boundary. By traversing up the RenderTree, determine the
    // highest RenderParagraph that contains the origin text boundary.
    assert(_selectableContainsOriginTextBoundary);
    // Begin at the parent because it is guaranteed the paragraph containing
    // this selectable fragment contains the origin boundary.
    RenderObject? current = paragraph.parent;
    RenderParagraph? originParagraph;
    while (current != null) {
      if (current is RenderParagraph) {
        if (current._lastSelectableFragments != null) {
          bool paragraphContainsOriginTextBoundary = false;
          for (final _SelectableFragment fragment in current._lastSelectableFragments!) {
            if (fragment._selectableContainsOriginTextBoundary) {
              paragraphContainsOriginTextBoundary = true;
              originParagraph = current;
              break;
            }
          }
          if (!paragraphContainsOriginTextBoundary) {
            return originParagraph ?? paragraph;
          }
        }
      }
      current = current.parent;
    }
    return originParagraph ?? paragraph;
  }

  ({RenderParagraph paragraph, Offset localPosition})? _getParagraphContainingPosition(
    Offset globalPosition,
  ) {
    // This method will return the closest [RenderParagraph] whose rect
    // contains the given `globalPosition` and the given `globalPosition`
    // relative to that [RenderParagraph]. If no ancestor [RenderParagraph]
    // contains the given `globalPosition` then this method will return null.
    RenderObject? current = paragraph;
    while (current != null) {
      if (current is RenderParagraph) {
        final Matrix4 currentTransform = current.getTransformTo(null);
        currentTransform.invert();
        final Offset currentParagraphLocalPosition = MatrixUtils.transformPoint(
          currentTransform,
          globalPosition,
        );
        final bool positionWithinCurrentParagraph = current.paintBounds.contains(
          currentParagraphLocalPosition,
        );
        if (positionWithinCurrentParagraph) {
          return (paragraph: current, localPosition: currentParagraphLocalPosition);
        }
      }
      current = current.parent;
    }
    return null;
  }

  bool _boundingBoxesContains(Offset position) {
    for (final Rect rect in boundingBoxes) {
      if (rect.contains(position)) {
        return true;
      }
    }
    return false;
  }

  TextPosition _clampTextPosition(TextPosition position) {
    // Affinity of range.end is upstream.
    if (position.offset > range.end ||
        (position.offset == range.end && position.affinity == TextAffinity.downstream)) {
      return TextPosition(offset: range.end, affinity: TextAffinity.upstream);
    }
    if (position.offset < range.start) {
      return TextPosition(offset: range.start);
    }
    return position;
  }

  void _setSelectionPosition(TextPosition? position, {required bool isEnd}) {
    if (isEnd) {
      _textSelectionEnd = position;
    } else {
      _textSelectionStart = position;
    }
  }

  SelectionResult _handleClearSelection() {
    _textSelectionStart = null;
    _textSelectionEnd = null;
    _selectableContainsOriginTextBoundary = false;
    return SelectionResult.none;
  }

  SelectionResult _handleSelectAll() {
    _textSelectionStart = TextPosition(offset: range.start);
    _textSelectionEnd = TextPosition(offset: range.end, affinity: TextAffinity.upstream);
    return SelectionResult.none;
  }

  SelectionResult _handleSelectTextBoundary(_TextBoundaryRecord textBoundary) {
    // This fragment may not contain the boundary, decide what direction the target
    // fragment is located in. Because fragments are separated by placeholder
    // spans, we also check if the beginning or end of the boundary is touching
    // either edge of this fragment.
    if (textBoundary.boundaryStart.offset < range.start &&
        textBoundary.boundaryEnd.offset <= range.start) {
      return SelectionResult.previous;
    } else if (textBoundary.boundaryStart.offset >= range.end &&
        textBoundary.boundaryEnd.offset > range.end) {
      return SelectionResult.next;
    }
    // Fragments are separated by placeholder span, the text boundary shouldn't
    // expand across fragments.
    assert(
      textBoundary.boundaryStart.offset >= range.start &&
          textBoundary.boundaryEnd.offset <= range.end,
    );
    _textSelectionStart = textBoundary.boundaryStart;
    _textSelectionEnd = textBoundary.boundaryEnd;
    _selectableContainsOriginTextBoundary = true;
    return SelectionResult.end;
  }

  TextRange? _intersect(TextRange a, TextRange b) {
    assert(a.isNormalized);
    assert(b.isNormalized);
    final int startMax = math.max(a.start, b.start);
    final int endMin = math.min(a.end, b.end);
    if (startMax <= endMin) {
      // Intersection.
      return TextRange(start: startMax, end: endMin);
    }
    return null;
  }

  SelectionResult _handleSelectMultiFragmentTextBoundary(_TextBoundaryRecord textBoundary) {
    // This fragment may not contain the boundary, decide what direction the target
    // fragment is located in. Because fragments are separated by placeholder
    // spans, we also check if the beginning or end of the boundary is touching
    // either edge of this fragment.
    if (textBoundary.boundaryStart.offset < range.start &&
        textBoundary.boundaryEnd.offset <= range.start) {
      return SelectionResult.previous;
    } else if (textBoundary.boundaryStart.offset >= range.end &&
        textBoundary.boundaryEnd.offset > range.end) {
      return SelectionResult.next;
    }
    final TextRange boundaryAsRange = TextRange(
      start: textBoundary.boundaryStart.offset,
      end: textBoundary.boundaryEnd.offset,
    );
    final TextRange? intersectRange = _intersect(range, boundaryAsRange);
    if (intersectRange != null) {
      _textSelectionStart = TextPosition(offset: intersectRange.start);
      _textSelectionEnd = TextPosition(offset: intersectRange.end);
      _selectableContainsOriginTextBoundary = true;
      if (range.end < textBoundary.boundaryEnd.offset) {
        return SelectionResult.next;
      }
      return SelectionResult.end;
    }
    return SelectionResult.none;
  }

  _TextBoundaryRecord _adjustTextBoundaryAtPosition(TextRange textBoundary, TextPosition position) {
    late final TextPosition start;
    late final TextPosition end;
    if (position.offset > textBoundary.end) {
      start = end = TextPosition(offset: position.offset);
    } else {
      start = TextPosition(offset: textBoundary.start);
      end = TextPosition(offset: textBoundary.end, affinity: TextAffinity.upstream);
    }
    return (boundaryStart: start, boundaryEnd: end);
  }

  SelectionResult _handleSelectWord(Offset globalPosition) {
    final TextPosition position = paragraph.getPositionForOffset(
      paragraph.globalToLocal(globalPosition),
    );
    if (_positionIsWithinCurrentSelection(position) && _textSelectionStart != _textSelectionEnd) {
      return SelectionResult.end;
    }
    final _TextBoundaryRecord wordBoundary = _getWordBoundaryAtPosition(position);
    return _handleSelectTextBoundary(wordBoundary);
  }

  _TextBoundaryRecord _getWordBoundaryAtPosition(TextPosition position) {
    final TextRange word = paragraph.getWordBoundary(position);
    assert(word.isNormalized);
    return _adjustTextBoundaryAtPosition(word, position);
  }

  SelectionResult _handleSelectParagraph(Offset globalPosition) {
    final Offset localPosition = paragraph.globalToLocal(globalPosition);
    final TextPosition position = paragraph.getPositionForOffset(localPosition);
    final _TextBoundaryRecord paragraphBoundary = _getParagraphBoundaryAtPosition(
      position,
      fullText,
    );
    return _handleSelectMultiFragmentTextBoundary(paragraphBoundary);
  }

  TextPosition _getPositionInParagraph(RenderParagraph targetParagraph) {
    final Matrix4 transform = paragraph.getTransformTo(targetParagraph);
    final Offset localCenter = paragraph.paintBounds.centerLeft;
    final Offset localPos = MatrixUtils.transformPoint(transform, localCenter);
    final TextPosition position = targetParagraph.getPositionForOffset(localPos);
    return position;
  }

  _TextBoundaryRecord _getParagraphBoundaryAtPosition(TextPosition position, String text) {
    final ParagraphBoundary paragraphBoundary = ParagraphBoundary(text);
    // Use position.offset - 1 when `position` is at the end of the selectable to retrieve
    // the previous text boundary's location.
    final int paragraphStart =
        paragraphBoundary.getLeadingTextBoundaryAt(
          position.offset == text.length || position.affinity == TextAffinity.upstream
              ? position.offset - 1
              : position.offset,
        ) ??
        0;
    final int paragraphEnd =
        paragraphBoundary.getTrailingTextBoundaryAt(position.offset) ?? text.length;
    final TextRange paragraphRange = TextRange(start: paragraphStart, end: paragraphEnd);
    assert(paragraphRange.isNormalized);
    return _adjustTextBoundaryAtPosition(paragraphRange, position);
  }

  _TextBoundaryRecord _getClampedParagraphBoundaryAtPosition(TextPosition position) {
    final ParagraphBoundary paragraphBoundary = ParagraphBoundary(fullText);
    // Use position.offset - 1 when `position` is at the end of the selectable to retrieve
    // the previous text boundary's location.
    int paragraphStart =
        paragraphBoundary.getLeadingTextBoundaryAt(
          position.offset == fullText.length || position.affinity == TextAffinity.upstream
              ? position.offset - 1
              : position.offset,
        ) ??
        0;
    int paragraphEnd =
        paragraphBoundary.getTrailingTextBoundaryAt(position.offset) ?? fullText.length;
    paragraphStart = paragraphStart < range.start
        ? range.start
        : paragraphStart > range.end
        ? range.end
        : paragraphStart;
    paragraphEnd = paragraphEnd > range.end
        ? range.end
        : paragraphEnd < range.start
        ? range.start
        : paragraphEnd;
    final TextRange paragraphRange = TextRange(start: paragraphStart, end: paragraphEnd);
    assert(paragraphRange.isNormalized);
    return _adjustTextBoundaryAtPosition(paragraphRange, position);
  }

  SelectionResult _handleDirectionallyExtendSelection(
    double horizontalBaseline,
    bool isExtent,
    SelectionExtendDirection movement,
  ) {
    final Matrix4 transform = paragraph.getTransformTo(null);
    if (transform.invert() == 0.0) {
      switch (movement) {
        case SelectionExtendDirection.previousLine:
        case SelectionExtendDirection.backward:
          return SelectionResult.previous;
        case SelectionExtendDirection.nextLine:
        case SelectionExtendDirection.forward:
          return SelectionResult.next;
      }
    }
    final double baselineInParagraphCoordinates = MatrixUtils.transformPoint(
      transform,
      Offset(horizontalBaseline, 0),
    ).dx;
    assert(!baselineInParagraphCoordinates.isNaN);
    final TextPosition newPosition;
    final SelectionResult result;
    switch (movement) {
      case SelectionExtendDirection.previousLine:
      case SelectionExtendDirection.nextLine:
        assert(_textSelectionEnd != null && _textSelectionStart != null);
        final TextPosition targetedEdge = isExtent ? _textSelectionEnd! : _textSelectionStart!;
        final MapEntry<TextPosition, SelectionResult> moveResult = _handleVerticalMovement(
          targetedEdge,
          horizontalBaselineInParagraphCoordinates: baselineInParagraphCoordinates,
          below: movement == SelectionExtendDirection.nextLine,
        );
        newPosition = moveResult.key;
        result = moveResult.value;
      case SelectionExtendDirection.forward:
      case SelectionExtendDirection.backward:
        _textSelectionEnd ??= movement == SelectionExtendDirection.forward
            ? TextPosition(offset: range.start)
            : TextPosition(offset: range.end, affinity: TextAffinity.upstream);
        _textSelectionStart ??= _textSelectionEnd;
        final TextPosition targetedEdge = isExtent ? _textSelectionEnd! : _textSelectionStart!;
        final Offset edgeOffsetInParagraphCoordinates = paragraph._getOffsetForPosition(
          targetedEdge,
        );
        final Offset baselineOffsetInParagraphCoordinates = Offset(
          baselineInParagraphCoordinates,
          // Use half of line height to point to the middle of the line.
          edgeOffsetInParagraphCoordinates.dy - paragraph._textPainter.preferredLineHeight / 2,
        );
        newPosition = paragraph.getPositionForOffset(baselineOffsetInParagraphCoordinates);
        result = SelectionResult.end;
    }
    if (isExtent) {
      _textSelectionEnd = newPosition;
    } else {
      _textSelectionStart = newPosition;
    }
    return result;
  }

  SelectionResult _handleGranularlyExtendSelection(
    bool forward,
    bool isExtent,
    TextGranularity granularity,
  ) {
    _textSelectionEnd ??= forward
        ? TextPosition(offset: range.start)
        : TextPosition(offset: range.end, affinity: TextAffinity.upstream);
    _textSelectionStart ??= _textSelectionEnd;
    final TextPosition targetedEdge = isExtent ? _textSelectionEnd! : _textSelectionStart!;
    if (forward && (targetedEdge.offset == range.end)) {
      return SelectionResult.next;
    }
    if (!forward && (targetedEdge.offset == range.start)) {
      return SelectionResult.previous;
    }
    final SelectionResult result;
    final TextPosition newPosition;
    switch (granularity) {
      case TextGranularity.character:
        final String text = range.textInside(fullText);
        newPosition = _moveBeyondTextBoundaryAtDirection(
          targetedEdge,
          forward,
          CharacterBoundary(text),
        );
        result = SelectionResult.end;
      case TextGranularity.word:
        final TextBoundary textBoundary = paragraph._textPainter.wordBoundaries.moveByWordBoundary;
        newPosition = _moveBeyondTextBoundaryAtDirection(targetedEdge, forward, textBoundary);
        result = SelectionResult.end;
      case TextGranularity.paragraph:
        final String text = range.textInside(fullText);
        newPosition = _moveBeyondTextBoundaryAtDirection(
          targetedEdge,
          forward,
          ParagraphBoundary(text),
        );
        result = SelectionResult.end;
      case TextGranularity.line:
        newPosition = _moveToTextBoundaryAtDirection(targetedEdge, forward, LineBoundary(this));
        result = SelectionResult.end;
      case TextGranularity.document:
        final String text = range.textInside(fullText);
        newPosition = _moveBeyondTextBoundaryAtDirection(
          targetedEdge,
          forward,
          DocumentBoundary(text),
        );
        if (forward && newPosition.offset == range.end) {
          result = SelectionResult.next;
        } else if (!forward && newPosition.offset == range.start) {
          result = SelectionResult.previous;
        } else {
          result = SelectionResult.end;
        }
    }

    if (isExtent) {
      _textSelectionEnd = newPosition;
    } else {
      _textSelectionStart = newPosition;
    }
    return result;
  }

  // Move **beyond** the local boundary of the given type (unless range.start or
  // range.end is reached). Used for most TextGranularity types except for
  // TextGranularity.line, to ensure the selection movement doesn't get stuck at
  // a local fixed point.
  TextPosition _moveBeyondTextBoundaryAtDirection(
    TextPosition end,
    bool forward,
    TextBoundary textBoundary,
  ) {
    final int newOffset = forward
        ? textBoundary.getTrailingTextBoundaryAt(end.offset) ?? range.end
        : textBoundary.getLeadingTextBoundaryAt(end.offset - 1) ?? range.start;
    return TextPosition(offset: newOffset);
  }

  // Move **to** the local boundary of the given type. Typically used for line
  // boundaries, such that performing "move to line start" more than once never
  // moves the selection to the previous line.
  TextPosition _moveToTextBoundaryAtDirection(
    TextPosition end,
    bool forward,
    TextBoundary textBoundary,
  ) {
    assert(end.offset >= 0);
    final int caretOffset;
    switch (end.affinity) {
      case TextAffinity.upstream:
        if (end.offset < 1 && !forward) {
          assert(end.offset == 0);
          return const TextPosition(offset: 0);
        }
        final CharacterBoundary characterBoundary = CharacterBoundary(fullText);
        caretOffset =
            math.max(
              0,
              characterBoundary.getLeadingTextBoundaryAt(range.start + end.offset) ?? range.start,
            ) -
            1;
      case TextAffinity.downstream:
        caretOffset = end.offset;
    }
    final int offset = forward
        ? textBoundary.getTrailingTextBoundaryAt(caretOffset) ?? range.end
        : textBoundary.getLeadingTextBoundaryAt(caretOffset) ?? range.start;
    return TextPosition(offset: offset);
  }

  MapEntry<TextPosition, SelectionResult> _handleVerticalMovement(
    TextPosition position, {
    required double horizontalBaselineInParagraphCoordinates,
    required bool below,
  }) {
    final List<ui.LineMetrics> lines = paragraph._textPainter.computeLineMetrics();
    final Offset offset = paragraph.getOffsetForCaret(position, Rect.zero);
    int currentLine = lines.length - 1;
    for (final ui.LineMetrics lineMetrics in lines) {
      if (lineMetrics.baseline > offset.dy) {
        currentLine = lineMetrics.lineNumber;
        break;
      }
    }
    final TextPosition newPosition;
    if (below && currentLine == lines.length - 1) {
      newPosition = TextPosition(offset: range.end, affinity: TextAffinity.upstream);
    } else if (!below && currentLine == 0) {
      newPosition = TextPosition(offset: range.start);
    } else {
      final int newLine = below ? currentLine + 1 : currentLine - 1;
      newPosition = _clampTextPosition(
        paragraph.getPositionForOffset(
          Offset(horizontalBaselineInParagraphCoordinates, lines[newLine].baseline),
        ),
      );
    }
    final SelectionResult result;
    if (newPosition.offset == range.start) {
      result = SelectionResult.previous;
    } else if (newPosition.offset == range.end) {
      result = SelectionResult.next;
    } else {
      result = SelectionResult.end;
    }
    assert(result != SelectionResult.next || below);
    assert(result != SelectionResult.previous || !below);
    return MapEntry<TextPosition, SelectionResult>(newPosition, result);
  }

  /// Whether the given text position is contained in current selection
  /// range.
  ///
  /// The parameter `start` must be smaller than `end`.
  bool _positionIsWithinCurrentSelection(TextPosition position) {
    if (_textSelectionStart == null || _textSelectionEnd == null) {
      return false;
    }
    // Normalize current selection.
    late TextPosition currentStart;
    late TextPosition currentEnd;
    if (_compareTextPositions(_textSelectionStart!, _textSelectionEnd!) > 0) {
      currentStart = _textSelectionStart!;
      currentEnd = _textSelectionEnd!;
    } else {
      currentStart = _textSelectionEnd!;
      currentEnd = _textSelectionStart!;
    }
    return _compareTextPositions(currentStart, position) >= 0 &&
        _compareTextPositions(currentEnd, position) <= 0;
  }

  /// Compares two text positions.
  ///
  /// Returns 1 if `position` < `otherPosition`, -1 if `position` > `otherPosition`,
  /// or 0 if they are equal.
  static int _compareTextPositions(TextPosition position, TextPosition otherPosition) {
    if (position.offset < otherPosition.offset) {
      return 1;
    } else if (position.offset > otherPosition.offset) {
      return -1;
    } else if (position.affinity == otherPosition.affinity) {
      return 0;
    } else {
      return position.affinity == TextAffinity.upstream ? 1 : -1;
    }
  }

  @override
  Matrix4 getTransformTo(RenderObject? ancestor) {
    return paragraph.getTransformTo(ancestor);
  }

  @override
  void pushHandleLayers(LayerLink? startHandle, LayerLink? endHandle) {
    if (!paragraph.attached) {
      assert(startHandle == null && endHandle == null, 'Only clean up can be called.');
      return;
    }
    if (_startHandleLayerLink != startHandle) {
      _startHandleLayerLink = startHandle;
      paragraph.markNeedsPaint();
    }
    if (_endHandleLayerLink != endHandle) {
      _endHandleLayerLink = endHandle;
      paragraph.markNeedsPaint();
    }
  }

  List<Rect>? _cachedBoundingBoxes;
  @override
  List<Rect> get boundingBoxes {
    if (_cachedBoundingBoxes == null) {
      final List<TextBox> boxes = paragraph.getBoxesForSelection(
        TextSelection(baseOffset: range.start, extentOffset: range.end),
        boxHeightStyle: ui.BoxHeightStyle.max,
      );
      if (boxes.isNotEmpty) {
        _cachedBoundingBoxes = <Rect>[];
        for (final TextBox textBox in boxes) {
          _cachedBoundingBoxes!.add(textBox.toRect());
        }
      } else {
        final Offset offset = paragraph._getOffsetForPosition(TextPosition(offset: range.start));
        final Rect rect = Rect.fromPoints(
          offset,
          offset.translate(0, -paragraph._textPainter.preferredLineHeight),
        );
        _cachedBoundingBoxes = <Rect>[rect];
      }
    }
    return _cachedBoundingBoxes!;
  }

  Rect? _cachedRect;
  Rect get _rect {
    if (_cachedRect == null) {
      final List<TextBox> boxes = paragraph.getBoxesForSelection(
        TextSelection(baseOffset: range.start, extentOffset: range.end),
      );
      if (boxes.isNotEmpty) {
        Rect result = boxes.first.toRect();
        for (int index = 1; index < boxes.length; index += 1) {
          result = result.expandToInclude(boxes[index].toRect());
        }
        _cachedRect = result;
      } else {
        final Offset offset = paragraph._getOffsetForPosition(TextPosition(offset: range.start));
        _cachedRect = Rect.fromPoints(
          offset,
          offset.translate(0, -paragraph._textPainter.preferredLineHeight),
        );
      }
    }
    return _cachedRect!;
  }

  void didChangeParagraphLayout() {
    _cachedRect = null;
    _cachedBoundingBoxes = null;
  }

  @override
  int get contentLength => range.end - range.start;

  @override
  Size get size {
    return _rect.size;
  }

  void paint(PaintingContext context, Offset offset) {
    if (_textSelectionStart == null || _textSelectionEnd == null) {
      return;
    }
    if (paragraph.selectionColor != null) {
      final TextSelection selection = TextSelection(
        baseOffset: _textSelectionStart!.offset,
        extentOffset: _textSelectionEnd!.offset,
      );
      final Paint selectionPaint = Paint()
        ..style = PaintingStyle.fill
        ..color = paragraph.selectionColor!;
      for (final TextBox textBox in paragraph.getBoxesForSelection(selection)) {
        context.canvas.drawRect(textBox.toRect().shift(offset), selectionPaint);
      }
    }
    if (_startHandleLayerLink != null && value.startSelectionPoint != null) {
      context.pushLayer(
        LeaderLayer(
          link: _startHandleLayerLink!,
          offset: offset + value.startSelectionPoint!.localPosition,
        ),
        (PaintingContext context, Offset offset) {},
        Offset.zero,
      );
    }
    if (_endHandleLayerLink != null && value.endSelectionPoint != null) {
      context.pushLayer(
        LeaderLayer(
          link: _endHandleLayerLink!,
          offset: offset + value.endSelectionPoint!.localPosition,
        ),
        (PaintingContext context, Offset offset) {},
        Offset.zero,
      );
    }
  }

  @override
  TextSelection getLineAtOffset(TextPosition position) {
    final TextRange line = paragraph._getLineAtOffset(position);
    final int start = line.start.clamp(range.start, range.end);
    final int end = line.end.clamp(range.start, range.end);
    return TextSelection(baseOffset: start, extentOffset: end);
  }

  @override
  TextPosition getTextPositionAbove(TextPosition position) {
    return _clampTextPosition(paragraph._getTextPositionAbove(position));
  }

  @override
  TextPosition getTextPositionBelow(TextPosition position) {
    return _clampTextPosition(paragraph._getTextPositionBelow(position));
  }

  @override
  TextRange getWordBoundary(TextPosition position) => paragraph.getWordBoundary(position);

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<String>('textInsideRange', range.textInside(fullText)));
    properties.add(DiagnosticsProperty<TextRange>('range', range));
    properties.add(DiagnosticsProperty<String>('fullText', fullText));
  }
}
