render method

void render(
  1. Buffer newbuf
)

Implementation

void render(Buffer newbuf) {
  metrics.beginFrame();

  final touchedLines = _touched(newbuf);
  if (!_clear && touchedLines == 0) {
    metrics.endFrame(skipped: true);
    return;
  }

  _curbuf ??= Buffer.create(newbuf.width(), newbuf.height());

  final newWidth = newbuf.width();
  final newHeight = newbuf.height();
  final curWidth = _curbuf!.width();
  final curHeight = _curbuf!.height();
  final sameSize = curWidth == newWidth && curHeight == newHeight;

  if (!sameSize) {
    _oldhash = const [];
    _newhash = const [];
  }

  final partialClear =
      !fullscreen() &&
      _cur.x != -1 &&
      _cur.y != -1 &&
      curWidth == newWidth &&
      curHeight > 0 &&
      curHeight > newHeight;

  if (!_clear && partialClear) {
    _clearBelow(newbuf, _clearBlank(), newHeight - 1);
  }

  if (_clear) {
    _clearUpdate(newbuf);
    _clear = false;
  } else if (touchedLines > 0) {
    if ((_flags & _Flag.scrollOptim) != 0 &&
        fullscreen() &&
        sameSize &&
        !Platform.isWindows) {
      _scrollOptimize(newbuf);
    }

    var nonEmpty = fullscreen()
        ? (curHeight < newHeight ? curHeight : newHeight)
        : newHeight;
    nonEmpty = _clearBottom(newbuf, nonEmpty);
    for (var i = 0; i < nonEmpty && i < newHeight; i++) {
      final ld = (newbuf.touched.isEmpty || i >= newbuf.touched.length)
          ? null
          : newbuf.touched[i];
      final shouldTransform =
          newbuf.touched.isEmpty ||
          i >= newbuf.touched.length ||
          (ld != null && (ld.firstCell != -1 || ld.lastCell != -1));
      if (shouldTransform) {
        _transformLine(newbuf, i);
      }
      if (i < newbuf.touched.length) {
        newbuf.touched[i] = const LineData(firstCell: -1, lastCell: -1);
      }
      if (i < _curbuf!.touched.length) {
        _curbuf!.touched[i] = const LineData(firstCell: -1, lastCell: -1);
      }
    }
  }

  if (!fullscreen() && _scrollHeight < newHeight - 1) {
    _move(newbuf, 0, newHeight - 1);
  }

  // Sync touched markers.
  newbuf.touched = List<LineData?>.generate(
    newHeight,
    (_) => const LineData(firstCell: -1, lastCell: -1),
  );
  _curbuf!.touched = List<LineData?>.generate(
    _curbuf!.height(),
    (_) => const LineData(firstCell: -1, lastCell: -1),
  );

  if (curWidth != newWidth || curHeight != newHeight) {
    _curbuf!.resize(newWidth, newHeight);
    final start = curHeight <= 0 ? 0 : curHeight - 1;
    for (var i = start; i < newHeight; i++) {
      final srcLine = newbuf.line(i);
      final dstLine = _curbuf!.line(i);
      if (srcLine != null && dstLine != null) {
        final src = srcLine.cells;
        final dst = dstLine.cells;
        for (var x = 0; x < dst.length && x < src.length; x++) {
          dst[x] = src[x].clone();
        }
      }
    }
  }

  // Reset pen after rendering to avoid style/link bleed.
  _updatePen(null);

  metrics.endFrame();
}