render method

  1. @override
void render(
  1. Buffer buf
)

Implementation

@override
void render(Buffer buf) {
  measureFont();

  final w = math.min(buf.width(), _cols);
  final h = math.min(buf.height(), _rows);
  final scale = _devicePixelRatio;
  final canvasW =
      (_viewportWidth > 0 ? _viewportWidth : _cols * _cellWidth) * scale;
  final canvasH =
      (_viewportHeight > 0 ? _viewportHeight : _rows * _cellHeight) * scale;

  context.save();

  context.imageSmoothingEnabled = false;
  context.textAlign = 'left';
  context.textBaseline = 'alphabetic';
  context.fillStyle = '#000'.toJS;
  context.fillRect(0, 0, canvasW, canvasH);

  _paintBackgroundRuns(buf, w, h, scale);

  for (var y = 0; y < h; y++) {
    final line = buf.line(y);
    if (line == null) continue;

    for (var x = 0; x < w; x++) {
      final cell = line.at(x);
      if (cell == null) continue;

      final c = cell.content;
      final style = cell.style;
      if (style.isZero && (c.isEmpty || c == ' ')) continue;

      final bounds = _cellBounds(x, y, scale);
      final px = bounds.left;
      final py = bounds.top;
      final cellWidth = bounds.right - bounds.left;
      final cellHeight = bounds.bottom - bounds.top;
      final baseline = (py + (_baseline * scale)).roundToDouble();

      final bg = style.bg;
      final fg = style.fg ?? const UvRgb(204, 204, 204);
      final attrs = style.attrs;
      final isReversed = (attrs & Attr.reverse) != 0;

      final drawFg = isReversed ? (bg ?? const UvRgb(0, 0, 0)) : fg;

      if (c.isNotEmpty && c != ' ') {
        final isBold = (attrs & Attr.bold) != 0;
        final isItalic = (attrs & Attr.italic) != 0;
        final isFaint = (attrs & Attr.faint) != 0;
        final alpha = isFaint ? 0.7 : 1.0;
        final drawFgCss = _colorToCss(drawFg);

        if (_paintShapeGlyph(
          c,
          px: px,
          py: py,
          cellWidth: cellWidth,
          cellHeight: cellHeight,
          colorCss: drawFgCss,
          alpha: alpha,
        )) {
          continue;
        }

        var fontStr = '${_scaledFontSize(scale)}px $fontFamily';
        if (isItalic) fontStr = 'italic $fontStr';
        if (isBold) fontStr = 'bold $fontStr';
        context.font = fontStr;

        context.fillStyle = drawFgCss.toJS;
        context.globalAlpha = alpha;
        context.fillText(c, px, baseline);
        if (isBold) {
          final boldOffset = math.min(1.0, math.max(0.5, scale * 0.12));
          context.fillText(c, px + boldOffset, baseline);
        }
        context.globalAlpha = 1.0;

        if (style.underline != UnderlineStyle.none) {
          context.lineWidth = math.max(1.0, scale);
          context.strokeStyle =
              (style.underlineColor != null
                      ? _colorToCss(style.underlineColor!)
                      : _colorToCss(drawFg))
                  .toJS;
          context.beginPath();
          context.moveTo(px, py + cellHeight - scale);
          context.lineTo(px + cellWidth, py + cellHeight - scale);
          context.stroke();
        }

        if ((attrs & Attr.strikethrough) != 0) {
          context.lineWidth = math.max(1.0, scale);
          context.beginPath();
          context.moveTo(px, py + cellHeight * 0.45);
          context.lineTo(px + cellWidth, py + cellHeight * 0.45);
          context.stroke();
        }
      }
    }
  }

  context.restore();
}