liquidGlassProfile function
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;
}