interpolate method

SassColor interpolate(
  1. SassColor other,
  2. InterpolationMethod method, {
  3. double? weight,
  4. bool legacyMissing = true,
})

Returns a color partway between this and other according to method, as defined by the CSS Color 4 color interpolation procedure.

The weight is a number between 0 and 1 that indicates how much of this should be in the resulting color. It defaults to 0.5.

If legacyMissing is false, this will convert missing channels in legacy color spaces to zero if a conversion occurs.

Implementation

SassColor interpolate(SassColor other, InterpolationMethod method,
    {double? weight, bool legacyMissing = true}) {
  weight ??= 0.5;

  if (fuzzyEquals(weight, 0)) return other;
  if (fuzzyEquals(weight, 1)) return this;

  var color1 = toSpace(method.space);
  var color2 = other.toSpace(method.space);

  if (weight < 0 || weight > 1) {
    throw RangeError.range(weight, 0, 1, 'weight');
  }

  // If either color is missing a channel _and_ that channel is analogous with
  // one in the output space, then the output channel should take on the other
  // color's value.
  var missing1_0 = _isAnalogousChannelMissing(this, color1, 0);
  var missing1_1 = _isAnalogousChannelMissing(this, color1, 1);
  var missing1_2 = _isAnalogousChannelMissing(this, color1, 2);
  var missing2_0 = _isAnalogousChannelMissing(other, color2, 0);
  var missing2_1 = _isAnalogousChannelMissing(other, color2, 1);
  var missing2_2 = _isAnalogousChannelMissing(other, color2, 2);
  var channel1_0 = (missing1_0 ? color2 : color1).channel0;
  var channel1_1 = (missing1_1 ? color2 : color1).channel1;
  var channel1_2 = (missing1_2 ? color2 : color1).channel2;
  var channel2_0 = (missing2_0 ? color1 : color2).channel0;
  var channel2_1 = (missing2_1 ? color1 : color2).channel1;
  var channel2_2 = (missing2_2 ? color1 : color2).channel2;
  var alpha1 = alphaOrNull ?? other.alpha;
  var alpha2 = other.alphaOrNull ?? alpha;

  var thisMultiplier = (alphaOrNull ?? 1) * weight;
  var otherMultiplier = (other.alphaOrNull ?? 1) * (1 - weight);
  var mixedAlpha = isAlphaMissing && other.isAlphaMissing
      ? null
      : alpha1 * weight + alpha2 * (1 - weight);
  var mixed0 = missing1_0 && missing2_0
      ? null
      : (channel1_0 * thisMultiplier + channel2_0 * otherMultiplier) /
          (mixedAlpha ?? 1);
  var mixed1 = missing1_1 && missing2_1
      ? null
      : (channel1_1 * thisMultiplier + channel2_1 * otherMultiplier) /
          (mixedAlpha ?? 1);
  var mixed2 = missing1_2 && missing2_2
      ? null
      : (channel1_2 * thisMultiplier + channel2_2 * otherMultiplier) /
          (mixedAlpha ?? 1);

  return switch (method.space) {
    ColorSpace.hsl || ColorSpace.hwb => SassColor.forSpaceInternal(
        method.space,
        missing1_0 && missing2_0
            ? null
            : _interpolateHues(channel1_0, channel2_0, method.hue!, weight),
        mixed1,
        mixed2,
        mixedAlpha),
    ColorSpace.lch || ColorSpace.oklch => SassColor.forSpaceInternal(
        method.space,
        mixed0,
        mixed1,
        missing1_2 && missing2_2
            ? null
            : _interpolateHues(channel1_2, channel2_2, method.hue!, weight),
        mixedAlpha),
    _ => SassColor.forSpaceInternal(
        method.space, mixed0, mixed1, mixed2, mixedAlpha)
  }
      .toSpace(space, legacyMissing: legacyMissing);
}