paint method

void paint(
  1. Buffer buffer
)

Composites the expanding sub-pixel circles onto the given target buffer.

NOTE: Doing rendering directly within a manager violates MVVM boundaries. For production declarative layouts, place a SubpixelRippleWidget in your widget tree.

Implementation

void paint(Buffer buffer) {
  final now = DateTime.now().millisecondsSinceEpoch;
  updateRipples(now);
  if (_ripples.isEmpty) return;

  final canvas = Canvas(buffer.width, buffer.height, onlyDrawOnSpaces: true);
  var hasPainted = false;

  for (final ripple in _ripples) {
    final elapsed = now - ripple.startTime;
    if (elapsed < 0) continue;

    final progress = (elapsed / ripple.durationMs).clamp(0.0, 1.0);
    final radius = (progress * 16).round();

    if (radius > 0) {
      final Color(:r, :g, :b) = ripple.color;
      final fade = (255 * (1.0 - progress)).round().clamp(0, 255);
      final style = Style(
        foreground: Color(
          (r * fade) ~/ 255,
          (g * fade) ~/ 255,
          (b * fade) ~/ 255,
        ),
      );

      // Map 1-based grid coordinates to 2x4 sub-pixel coordinate space
      canvas.drawCircle(
        (ripple.center.x - 1) * 2 + 1,
        (ripple.center.y - 1) * 4 + 2,
        radius,
        cellStyle: style,
      );
      hasPainted = true;
    }
  }

  if (hasPainted) {
    final el = canvas.createElement();
    el.layout(BoxConstraints.tight(Size(buffer.width, buffer.height)));
    el.paint(buffer, Offset.zero);
    el.unmount();
  }
}