blend1D function
Blends a series of Color stops into steps colors (1D gradient).
This is a minimal-first port of lipgloss v2 Blend1D, but uses simple
RGB interpolation (rather than Lab) to avoid pulling in a large dependency.
If fewer than 2 blendable stops are provided, returns a list filled with the single stop (or empty if none are blendable).
Implementation
List<Color> blend1D(
int steps,
List<Color> stops, {
required bool hasDarkBackground,
}) {
if (steps < 0) steps = 0;
if (steps == 0) return const [];
if (stops.isEmpty) return const [];
final rgbStops = <cp.Rgb>[];
for (final c in stops) {
final rgb = c.toRgb(hasDarkBackground: hasDarkBackground);
if (rgb != null) rgbStops.add(rgb);
}
if (rgbStops.isEmpty) return const [];
if (rgbStops.length == 1) {
final single = _colorFromRgb(rgbStops[0]);
return List<Color>.filled(steps, single, growable: false);
}
if (steps == 1) {
return [_colorFromRgb(rgbStops.first)];
}
final out = List<Color>.filled(
steps,
_colorFromRgb(rgbStops.first),
growable: false,
);
final maxPos = rgbStops.length - 1;
for (var i = 0; i < steps; i++) {
final pos = i / (steps - 1);
final target = pos * maxPos;
final leftIndex = target.floor().clamp(0, maxPos).toInt();
final rightIndex = (leftIndex + 1).clamp(0, maxPos).toInt();
final t = target - leftIndex;
if (leftIndex == rightIndex) {
out[i] = _colorFromRgb(rgbStops[leftIndex]);
continue;
}
final from = rgbStops[leftIndex];
final to = rgbStops[rightIndex];
out[i] = BasicColor(
_hexFromRgb(
_lerp(from.r, to.r, t),
_lerp(from.g, to.g, t),
_lerp(from.b, to.b, t),
),
);
}
return out;
}