blend2D function
Blends a series of Color stops into a 2D gradient.
Returns colors in row-major order: index = y * width + x.
This is a minimal-first port of lipgloss v2 Blend2D (but uses RGB
interpolation via blend1D).
Implementation
List<Color> blend2D(
int width,
int height,
double angle,
List<Color> stops, {
required bool hasDarkBackground,
}) {
if (width < 1) width = 1;
if (height < 1) height = 1;
// Normalize angle to 0-360.
angle %= 360;
if (angle < 0) angle += 360;
if (stops.isEmpty) return const [];
if (stops.length == 1) {
return List<Color>.filled(width * height, stops.first, growable: false);
}
final diagonalGradient = blend1D(
math.max(width, height),
stops,
hasDarkBackground: hasDarkBackground,
);
if (diagonalGradient.isEmpty) return const [];
final out = List<Color>.filled(width * height, diagonalGradient.first);
final centerX = (width - 1) / 2.0;
final centerY = (height - 1) / 2.0;
final angleRad = angle * math.pi / 180.0;
final cosAngle = math.cos(angleRad);
final sinAngle = math.sin(angleRad);
final diagonalLength = math.sqrt(width * width + height * height);
final gradLen = diagonalGradient.length - 1;
for (var y = 0; y < height; y++) {
final dy = y - centerY;
for (var x = 0; x < width; x++) {
final dx = x - centerX;
final rotX = dx * cosAngle - dy * sinAngle;
final pos = ((rotX + diagonalLength / 2.0) / diagonalLength).clamp(
0.0,
1.0,
);
var idx = (pos * gradLen).floor();
if (idx < 0) idx = 0;
if (idx > gradLen) idx = gradLen;
out[y * width + x] = diagonalGradient[idx];
}
}
return out;
}