getCaretY method

double? getCaretY(
  1. String fragmentId,
  2. int localOffset
)

Implementation

double? getCaretY(String fragmentId, int localOffset) {
  final globalOffset = _localToGlobal(fragmentId, localOffset);
  if (globalOffset == null) return null;

  // 1. Find the character box at the caret to identify the line.
  TextBox? charBox;
  final textLength = _painter.text?.toPlainText().length ?? 0;
  if (globalOffset > 0 && globalOffset <= textLength) {
    final boxes = _painter.getBoxesForSelection(
      TextSelection(baseOffset: globalOffset - 1, extentOffset: globalOffset),
    );
    if (boxes.isNotEmpty) charBox = boxes.first;
  } else if (globalOffset == 0 && textLength > 0) {
    final boxes = _painter.getBoxesForSelection(
      TextSelection(baseOffset: 0, extentOffset: 1),
    );
    if (boxes.isNotEmpty) charBox = boxes.first;
  }

  if (charBox != null) {
    // 2. The baseline of the line is identical for ALL characters on the same
    // visual line, regardless of font size. Find it with
    // computeLineMetrics looking for the line whose baseline falls within
    // the vertical range of the character box.
    if (_lineMetricsDirty || _cachedLineMetrics == null) {
      _cachedLineMetrics = _painter.computeLineMetrics();
      _lineMetricsDirty = false;
    }
    final lineMetrics = _cachedLineMetrics!;
    for (final lm in lineMetrics) {
      if (lm.baseline >= charBox.top && lm.baseline <= charBox.bottom) {
        return localToGlobal(Offset(0, lm.baseline)).dy;
      }
    }
    // If not found (fallback), use the center of the box
    return localToGlobal(Offset(0, (charBox.top + charBox.bottom) / 2)).dy;
  }

  // Fallback for empty document
  final caretOffset = _painter.getOffsetForCaret(
    TextPosition(offset: globalOffset),
    Rect.zero,
  );
  return localToGlobal(caretOffset).dy;
}