getOffsetForCaret method

Offset getOffsetForCaret(
  1. TextPosition position,
  2. Rect caretPrototype
)

Returns the offset at which to paint the caret.

Valid only after layout has been called.

Implementation

Offset getOffsetForCaret(TextPosition position, Rect caretPrototype) {
  final _CaretMetrics caretMetrics;
  final _TextPainterLayoutCacheWithOffset layoutCache = _layoutCache!;
  if (position.offset < 0) {
    // TODO(LongCatIsLooong): make this case impossible; see https://github.com/flutter/flutter/issues/79495
    caretMetrics = const _EmptyLineCaretMetrics(lineVerticalOffset: 0);
  } else {
    caretMetrics = _computeCaretMetrics(position);
  }

  final Offset rawOffset;
  switch (caretMetrics) {
    case _EmptyLineCaretMetrics(:final double lineVerticalOffset):
      final double paintOffsetAlignment = _computePaintOffsetFraction(textAlign, textDirection!);
      // The full width is not (width - caretPrototype.width)
      // because RenderEditable reserves cursor width on the right. Ideally this
      // should be handled by RenderEditable instead.
      final double dx = paintOffsetAlignment == 0 ? 0 : paintOffsetAlignment * layoutCache.contentWidth;
      return Offset(dx, lineVerticalOffset);
    case _LineCaretMetrics(writingDirection: TextDirection.ltr, :final Offset offset):
      rawOffset = offset;
    case _LineCaretMetrics(writingDirection: TextDirection.rtl, :final Offset offset):
      rawOffset = Offset(offset.dx - caretPrototype.width, offset.dy);
  }
  // If offset.dx is outside of the advertised content area, then the associated
  // glyph cluster belongs to a trailing newline character. Ideally the behavior
  // should be handled by higher-level implementations (for instance,
  // RenderEditable reserves width for showing the caret, it's best to handle
  // the clamping there).
  final double adjustedDx = clampDouble(rawOffset.dx + layoutCache.paintOffset.dx, 0, layoutCache.contentWidth);
  return Offset(adjustedDx, rawOffset.dy + layoutCache.paintOffset.dy);
}