content: // Copyright 2022 Google Inc. Use of this source code is governed by an
  // MIT-style license that can be found in the LICENSE file or at
  // https://opensource.org/licenses/MIT.
  
  import 'dart:math' as math;
  
  import '../../../util/number.dart';
  import '../../color.dart';
  
  /// A constant used to convert Lab to/from XYZ.
  const labKappa = 24389 / 27; // 29^3/3^3;
  
  /// A constant used to convert Lab to/from XYZ.
  const labEpsilon = 216 / 24389; // 6^3/29^3;
  
  /// The hue channel shared across all polar color spaces.
  const hueChannel = ColorChannel(
    'hue',
    isPolarAngle: true,
    associatedUnit: 'deg',
  );
  
  /// The color channels shared across all RGB color spaces (except the legacy RGB space).
  const rgbChannels = [
    LinearChannel('red', 0, 1),
    LinearChannel('green', 0, 1),
    LinearChannel('blue', 0, 1),
  ];
  
  /// The color channels shared across both XYZ color spaces.
  const xyzChannels = [
    LinearChannel('x', 0, 1),
    LinearChannel('y', 0, 1),
    LinearChannel('z', 0, 1),
  ];
  
  /// Converts a legacy HSL/HWB hue to an RGB channel.
  ///
  /// The algorithm comes from from the CSS3 spec:
  /// http://www.w3.org/TR/css3-color/#hsl-color.
  double hueToRgb(double m1, double m2, double hue) {
    if (hue < 0) hue += 1;
    if (hue > 1) hue -= 1;
  
    return switch (hue) {
      < 1 / 6 => m1 + (m2 - m1) * hue * 6,
      < 1 / 2 => m2,
      < 2 / 3 => m1 + (m2 - m1) * (2 / 3 - hue) * 6,
      _ => m1,
    };
  }
  
  /// The algorithm for converting a single `srgb` or `display-p3` channel to
  /// linear-light form.
  double srgbAndDisplayP3ToLinear(double channel) {
    // Algorithm from https://www.w3.org/TR/css-color-4/#color-conversion-code
    var abs = channel.abs();
    return abs <= 0.04045
        ? channel / 12.92
        : channel.sign * math.pow((abs + 0.055) / 1.055, 2.4);
  }
  
  /// The algorithm for converting a single `srgb` or `display-p3` channel to
  /// gamma-corrected form.
  double srgbAndDisplayP3FromLinear(double channel) {
    // Algorithm from https://www.w3.org/TR/css-color-4/#color-conversion-code
    var abs = channel.abs();
    return abs <= 0.0031308
        ? channel * 12.92
        : channel.sign * (1.055 * math.pow(abs, 1 / 2.4) - 0.055);
  }
  
  /// Converts a Lab or OKLab color to LCH or OKLCH, respectively.
  ///
  /// The [missingChroma] and [missingHue] arguments indicate whether this came
  /// from a color that was missing its chroma or hue channels, respectively.
  SassColor labToLch(
    ColorSpace dest,
    double? lightness,
    double? a,
    double? b,
    double? alpha, {
    bool missingChroma = false,
    bool missingHue = false,
  }) {
    // Algorithm from https://www.w3.org/TR/css-color-4/#color-conversion-code
    var chroma = math.sqrt(math.pow(a ?? 0, 2) + math.pow(b ?? 0, 2));
    var hue = missingHue || fuzzyEquals(chroma, 0)
        ? null
        : math.atan2(b ?? 0, a ?? 0) * 180 / math.pi;
  
    return SassColor.forSpaceInternal(
      dest,
      lightness,
      missingChroma ? null : chroma,
      hue == null || hue >= 0 ? hue : hue + 360,
      alpha,
    );
  }
  