apply method

  1. @override
void apply(
  1. TextFrame frame,
  2. UnitSlice slice
)
override

Write this frame's poses, ink passes and decor for slice into frame.

Implementation

@override
void apply(TextFrame frame, UnitSlice slice) {
  if (slice.isEmpty) return;
  final periodS = period.inMicroseconds / 1e6;
  final phase = periodS <= 0 ? 0.0 : (frame.time / periodS) % 1.0;
  final sweep = (1 - rest).clamp(0.15, 1.0);
  final raw = phase / sweep;
  if (raw >= 1) return; // resting — plain text, no layer, no shader
  final b = band.clamp(0.02, 0.49);
  final eased = KineticEase.sweep.transform(raw);
  final rtl = frame.readsRtl(slice);
  final centers = Sweep.centers(origin, eased, b, rtl: rtl);
  final shaped = frame.shaped;
  final bounds = shaped.boundsOf(slice.units);
  if (bounds.width <= 0) return;
  final appear = Sweep.appear(origin, eased);

  if (pop != 0) {
    for (final i in slice.units) {
      final c = (shaped.units[i].rect.center.dx - bounds.left) / bounds.width;
      var bump = 0.0;
      for (final p in centers) {
        final d = (p - c) / b;
        bump = math.max(bump, math.exp(-d * d));
      }
      bump *= appear;
      if (bump < 0.01) continue;
      final pose = frame.pose(i);
      pose.scale *= 1 + pop * bump;
      pose.pivot = UnitPivot.baseline;
    }
  }

  final k = intensity.clamp(0.0, 1.0) * appear;
  final multi = colors;
  for (var n = 0; n < centers.length; n++) {
    final p = centers[n];
    if (p + b <= 0 || p - b >= 1) continue; // off the slice
    final List<Color> stopsColors;
    final List<double> stops;
    if (multi != null && multi.isNotEmpty) {
      // The last colour leads: mirrored when this band runs leftwards.
      final leftward = Sweep.travelsLeft(origin, rtl: rtl) != (n == 1);
      final ordered = leftward ? multi.reversed.toList() : multi;
      stopsColors = [
        ordered.first.withValues(alpha: 0),
        for (final c in ordered) c.withValues(alpha: c.a * k),
        ordered.last.withValues(alpha: 0),
      ];
      final inner = ordered.length;
      stops = [
        (p - b).clamp(0.0, 1.0),
        for (var j = 0; j < inner; j++)
          (p - b + (j + 1) / (inner + 1) * 2 * b).clamp(0.0, 1.0),
        (p + b).clamp(0.0, 1.0),
      ];
    } else {
      stopsColors = [
        for (final w in bandProfile) color.withValues(alpha: color.a * k * w),
      ];
      stops = bandStops(p, b);
    }
    frame.ink.add(InkPass(
      units: slice.units,
      bounds: bounds,
      gradient: LinearGradient(
        begin: Alignment.centerLeft,
        end: Alignment.centerRight,
        colors: stopsColors,
        stops: stops,
      ),
      blendMode: blendMode,
    ));
  }
}