liquidGlassProfile function

  1. @visibleForTesting
List<double> liquidGlassProfile(
  1. Path outline,
  2. Offset center
)

How far outline reaches from center along _profileTurns even turns, the first toward +x and the rest toward +y, as the shader reads it.

Implementation

@visibleForTesting
List<double> liquidGlassProfile(Path outline, Offset center) {
  const step = 2 * math.pi / _profileTurns;
  final profile = List<double>.filled(_profileTurns, 0);
  void cross(Offset from, Offset to) {
    final start = from.direction;
    var span = to.direction - start;
    if (span > math.pi) {
      span -= 2 * math.pi;
    } else if (span <= -math.pi) {
      span += 2 * math.pi;
    }
    final edge = to - from;
    final first = (math.min(start, start + span) / step).ceil();
    final last = (math.max(start, start + span) / step).floor();
    for (var turn = first; turn <= last; turn++) {
      final ray = Offset.fromDirection(turn * step);
      final facing = ray.dx * edge.dy - ray.dy * edge.dx;
      profile[turn % _profileTurns] = facing.abs() < 1e-9
          ? math.max(from.distance, to.distance)
          : (from.dx * edge.dy - from.dy * edge.dx) / facing;
    }
  }

  for (final metric in outline.computeMetrics()) {
    final samples = math.max(_profileTurns * 4, metric.length.ceil());
    Offset pointAt(int index) =>
        metric.getTangentForOffset(metric.length * index / samples)!.position -
        center;
    var previous = pointAt(0);
    for (var index = 1; index <= samples; index++) {
      final next = pointAt(index);
      cross(previous, next);
      previous = next;
    }
  }
  return profile;
}