sass-embedded 1.79.2-x86-mswin32 → 1.79.4-x86-mswin32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/exe/sass +1 -9
  3. data/ext/sass/dart-sass/src/sass.snapshot +0 -0
  4. data/lib/sass/compiler/connection.rb +1 -9
  5. data/lib/sass/compiler/host/protofier.rb +16 -55
  6. data/lib/sass/elf.rb +4 -4
  7. data/lib/sass/embedded/version.rb +1 -1
  8. data/lib/sass/value/color/channel.rb +79 -0
  9. data/lib/sass/value/color/conversions.rb +464 -0
  10. data/lib/sass/value/color/gamut_map_method/clip.rb +45 -0
  11. data/lib/sass/value/color/gamut_map_method/local_minde.rb +94 -0
  12. data/lib/sass/value/color/gamut_map_method.rb +45 -0
  13. data/lib/sass/value/color/interpolation_method.rb +51 -0
  14. data/lib/sass/value/color/space/a98_rgb.rb +57 -0
  15. data/lib/sass/value/color/space/display_p3.rb +57 -0
  16. data/lib/sass/value/color/space/hsl.rb +65 -0
  17. data/lib/sass/value/color/space/hwb.rb +70 -0
  18. data/lib/sass/value/color/space/lab.rb +77 -0
  19. data/lib/sass/value/color/space/lch.rb +53 -0
  20. data/lib/sass/value/color/space/lms.rb +129 -0
  21. data/lib/sass/value/color/space/oklab.rb +66 -0
  22. data/lib/sass/value/color/space/oklch.rb +54 -0
  23. data/lib/sass/value/color/space/prophoto_rgb.rb +59 -0
  24. data/lib/sass/value/color/space/rec2020.rb +69 -0
  25. data/lib/sass/value/color/space/rgb.rb +52 -0
  26. data/lib/sass/value/color/space/srgb.rb +141 -0
  27. data/lib/sass/value/color/space/srgb_linear.rb +72 -0
  28. data/lib/sass/value/color/space/utils.rb +86 -0
  29. data/lib/sass/value/color/space/xyz_d50.rb +100 -0
  30. data/lib/sass/value/color/space/xyz_d65.rb +57 -0
  31. data/lib/sass/value/color/space.rb +198 -0
  32. data/lib/sass/value/color.rb +537 -162
  33. data/lib/sass/value/fuzzy_math.rb +30 -3
  34. data/lib/sass/value/string.rb +1 -1
  35. metadata +29 -5
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ module Value
5
+ class Color
6
+ # @see https://github.com/sass/dart-sass/blob/main/lib/src/value/color/interpolation_method.dart
7
+ class InterpolationMethod
8
+ # @return [Space]
9
+ attr_reader :space
10
+
11
+ # @return [Symbol, nil]
12
+ attr_reader :hue
13
+
14
+ # @param space [Space]
15
+ # @param hue [Symbol]
16
+ def initialize(space, hue = nil)
17
+ @space = space
18
+ @hue = if space.polar?
19
+ hue.nil? ? :shorter : hue
20
+ end
21
+
22
+ return unless !space.polar? && !hue.nil?
23
+
24
+ raise Sass::ScriptError,
25
+ "Hue interpolation method may not be set for rectangular color space #{space.name}."
26
+ end
27
+ end
28
+
29
+ private_constant :InterpolationMethod
30
+
31
+ # @see https://github.com/sass/dart-sass/blob/main/lib/src/value/color/interpolation_method.dart
32
+ module HueInterpolationMethod
33
+ class << self
34
+ # @param name [::String]
35
+ # @param argument_name [::String]
36
+ # @return [Symbol]
37
+ def from_name(name, argument_name = nil)
38
+ case name
39
+ when 'decreasing', 'increasing', 'longer', 'shorter'
40
+ name.to_sym
41
+ else
42
+ raise Sass::ScriptError.new("Unknown hue interpolation method \"#{name}\".", argument_name)
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ private_constant :HueInterpolationMethod
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ module Value
5
+ class Color
6
+ module Space
7
+ # @see https://github.com/sass/dart-sass/blob/main/lib/src/value/color/space/a98_rgb.dart
8
+ class A98Rgb
9
+ include Space
10
+
11
+ def bounded?
12
+ true
13
+ end
14
+
15
+ def initialize
16
+ super('a98-rgb', Utils::RGB_CHANNELS)
17
+ end
18
+
19
+ def to_linear(channel)
20
+ FuzzyMath.sign(channel) * (channel.abs**(563 / 256.0))
21
+ end
22
+
23
+ def from_linear(channel)
24
+ FuzzyMath.sign(channel) * (channel.abs**(256 / 563.0))
25
+ end
26
+
27
+ private
28
+
29
+ def transformation_matrix(dest)
30
+ case dest
31
+ when DISPLAY_P3
32
+ Conversions::LINEAR_A98_RGB_TO_LINEAR_DISPLAY_P3
33
+ when LMS
34
+ Conversions::LINEAR_A98_RGB_TO_LMS
35
+ when PROPHOTO_RGB
36
+ Conversions::LINEAR_A98_RGB_TO_LINEAR_PROPHOTO_RGB
37
+ when REC2020
38
+ Conversions::LINEAR_A98_RGB_TO_LINEAR_REC2020
39
+ when RGB, SRGB, SRGB_LINEAR
40
+ Conversions::LINEAR_A98_RGB_TO_LINEAR_SRGB
41
+ when XYZ_D50
42
+ Conversions::LINEAR_A98_RGB_TO_XYZ_D50
43
+ when XYZ_D65
44
+ Conversions::LINEAR_A98_RGB_TO_XYZ_D65
45
+ else
46
+ super
47
+ end
48
+ end
49
+ end
50
+
51
+ private_constant :A98Rgb
52
+
53
+ A98_RGB = A98Rgb.new
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ module Value
5
+ class Color
6
+ module Space
7
+ # @see https://github.com/sass/dart-sass/blob/main/lib/src/value/color/space/display_p3.dart
8
+ class DisplayP3
9
+ include Space
10
+
11
+ def bounded?
12
+ true
13
+ end
14
+
15
+ def initialize
16
+ super('display-p3', Utils::RGB_CHANNELS)
17
+ end
18
+
19
+ def to_linear(channel)
20
+ Utils.srgb_and_display_p3_to_linear(channel)
21
+ end
22
+
23
+ def from_linear(channel)
24
+ Utils.srgb_and_display_p3_from_linear(channel)
25
+ end
26
+
27
+ private
28
+
29
+ def transformation_matrix(dest)
30
+ case dest
31
+ when A98_RGB
32
+ Conversions::LINEAR_DISPLAY_P3_TO_LINEAR_A98_RGB
33
+ when LMS
34
+ Conversions::LINEAR_DISPLAY_P3_TO_LMS
35
+ when PROPHOTO_RGB
36
+ Conversions::LINEAR_DISPLAY_P3_TO_LINEAR_PROPHOTO_RGB
37
+ when REC2020
38
+ Conversions::LINEAR_DISPLAY_P3_TO_LINEAR_REC2020
39
+ when RGB, SRGB, SRGB_LINEAR
40
+ Conversions::LINEAR_DISPLAY_P3_TO_LINEAR_SRGB
41
+ when XYZ_D50
42
+ Conversions::LINEAR_DISPLAY_P3_TO_XYZ_D50
43
+ when XYZ_D65
44
+ Conversions::LINEAR_DISPLAY_P3_TO_XYZ_D65
45
+ else
46
+ super
47
+ end
48
+ end
49
+ end
50
+
51
+ private_constant :DisplayP3
52
+
53
+ DISPLAY_P3 = DisplayP3.new
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ module Value
5
+ class Color
6
+ module Space
7
+ # @see https://github.com/sass/dart-sass/blob/main/lib/src/value/color/space/hsl.dart
8
+ class Hsl
9
+ include Space
10
+
11
+ def bounded?
12
+ true
13
+ end
14
+
15
+ def legacy?
16
+ true
17
+ end
18
+
19
+ def polar?
20
+ true
21
+ end
22
+
23
+ def initialize
24
+ super('hsl', [
25
+ Utils::HUE_CHANNEL,
26
+ LinearChannel.new('saturation', 0, 100, requires_percent: true, lower_clamped: true).freeze,
27
+ LinearChannel.new('lightness', 0, 100, requires_percent: true).freeze
28
+ ].freeze)
29
+ end
30
+
31
+ def convert(dest, hue, saturation, lightness, alpha)
32
+ missing_lightness = lightness.nil?
33
+ missing_chroma = saturation.nil?
34
+ missing_hue = hue.nil?
35
+
36
+ hue = ((hue.nil? ? 0 : hue) % 360) / 30.0
37
+ saturation = (saturation.nil? ? 0 : saturation) / 100.0
38
+ lightness = (lightness.nil? ? 0 : lightness) / 100.0
39
+
40
+ a = saturation * [lightness, 1 - lightness].min
41
+ f = lambda do |n|
42
+ k = (n + hue) % 12
43
+ lightness - (a * [-1, [k - 3, 9 - k, 1].min].max)
44
+ end
45
+
46
+ SRGB.convert(
47
+ dest,
48
+ f.call(0),
49
+ f.call(8),
50
+ f.call(4),
51
+ alpha,
52
+ missing_lightness:,
53
+ missing_chroma:,
54
+ missing_hue:
55
+ )
56
+ end
57
+ end
58
+
59
+ private_constant :Hsl
60
+
61
+ HSL = Hsl.new
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ module Value
5
+ class Color
6
+ module Space
7
+ # @see https://github.com/sass/dart-sass/blob/main/lib/src/value/color/space/hwb.dart
8
+ class Hwb
9
+ include Space
10
+
11
+ def bounded?
12
+ true
13
+ end
14
+
15
+ def legacy?
16
+ true
17
+ end
18
+
19
+ def polar?
20
+ true
21
+ end
22
+
23
+ def initialize
24
+ super('hwb', [
25
+ Utils::HUE_CHANNEL,
26
+ LinearChannel.new('whiteness', 0, 100, requires_percent: true).freeze,
27
+ LinearChannel.new('blackness', 0, 100, requires_percent: true).freeze
28
+ ].freeze)
29
+ end
30
+
31
+ def convert(dest, hue, whiteness, blackness, alpha)
32
+ missing_hue = hue.nil?
33
+
34
+ hue = ((hue.nil? ? 0 : hue) % 360) / 30.0
35
+ whiteness = (whiteness.nil? ? 0 : whiteness) / 100.0
36
+ blackness = (blackness.nil? ? 0 : blackness) / 100.0
37
+
38
+ sum = whiteness + blackness
39
+ if sum > 1
40
+ gray = whiteness / sum
41
+ SRGB.convert(dest,
42
+ gray,
43
+ gray,
44
+ gray,
45
+ alpha,
46
+ missing_hue:)
47
+ else
48
+ f = lambda do |n|
49
+ k = (n + hue) % 12
50
+ 0.5 - ([-1, [k - 3, 9 - k, 1].min].max / 2.0)
51
+ end
52
+
53
+ factor = 1 - sum
54
+ SRGB.convert(dest,
55
+ (f.call(0) * factor) + whiteness,
56
+ (f.call(8) * factor) + whiteness,
57
+ (f.call(4) * factor) + whiteness,
58
+ alpha,
59
+ missing_hue:)
60
+ end
61
+ end
62
+ end
63
+
64
+ private_constant :Hwb
65
+
66
+ HWB = Hwb.new
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ module Value
5
+ class Color
6
+ module Space
7
+ # @see https://github.com/sass/dart-sass/blob/main/lib/src/value/color/space/lab.dart
8
+ class Lab
9
+ include Space
10
+
11
+ def bounded?
12
+ false
13
+ end
14
+
15
+ def initialize
16
+ super('lab', [
17
+ LinearChannel.new('lightness', 0, 100, lower_clamped: true, upper_clamped: true).freeze,
18
+ LinearChannel.new('a', -125, 125).freeze,
19
+ LinearChannel.new('b', -125, 125).freeze
20
+ ].freeze)
21
+ end
22
+
23
+ def convert(dest, lightness, a, b, alpha, # rubocop:disable Naming/MethodParameterName
24
+ missing_chroma: false, missing_hue: false)
25
+ case dest
26
+ when LAB
27
+ powerless_ab = lightness.nil? || FuzzyMath.equals(lightness, 0)
28
+ Color.send(
29
+ :_for_space,
30
+ dest,
31
+ lightness,
32
+ a.nil? || powerless_ab ? nil : a,
33
+ b.nil? || powerless_ab ? nil : b,
34
+ alpha
35
+ )
36
+ when LCH
37
+ Utils.lab_to_lch(dest, lightness, a, b, alpha)
38
+ else
39
+ missing_lightness = lightness.nil?
40
+ lightness = 0 if missing_lightness
41
+
42
+ f1 = (lightness + 16) / 116.0
43
+
44
+ XYZ_D50.convert(
45
+ dest,
46
+ _convert_f_to_x_or_z(((a.nil? ? 0 : a) / 500.0) + f1) * Conversions::D50[0],
47
+ (if lightness > Utils::LAB_KAPPA * Utils::LAB_EPSILON
48
+ (((lightness + 16) / 116.0)**3)
49
+ else
50
+ lightness / Utils::LAB_KAPPA
51
+ end) * Conversions::D50[1],
52
+ _convert_f_to_x_or_z(f1 - ((b.nil? ? 0 : b) / 200.0)) * Conversions::D50[2],
53
+ alpha,
54
+ missing_lightness:,
55
+ missing_chroma:,
56
+ missing_hue:,
57
+ missing_a: a.nil?,
58
+ missing_b: b.nil?
59
+ )
60
+ end
61
+ end
62
+
63
+ private
64
+
65
+ def _convert_f_to_x_or_z(component)
66
+ cubed = component**3
67
+ cubed > Utils::LAB_EPSILON ? cubed : ((116 * component) - 16) / Utils::LAB_KAPPA
68
+ end
69
+ end
70
+
71
+ private_constant :Lab
72
+
73
+ LAB = Lab.new
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ module Value
5
+ class Color
6
+ module Space
7
+ # @see https://github.com/sass/dart-sass/blob/main/lib/src/value/color/space/lch.dart
8
+ class Lch
9
+ include Space
10
+
11
+ def bounded?
12
+ false
13
+ end
14
+
15
+ def polar?
16
+ true
17
+ end
18
+
19
+ def initialize
20
+ super('lch', [
21
+ LinearChannel.new('lightness', 0, 100, lower_clamped: true, upper_clamped: true).freeze,
22
+ LinearChannel.new('chroma', 0, 150, lower_clamped: true).freeze,
23
+ Utils::HUE_CHANNEL
24
+ ].freeze)
25
+ end
26
+
27
+ def convert(dest, lightness, chroma, hue, alpha)
28
+ missing_chroma = chroma.nil?
29
+ missing_hue = hue.nil?
30
+
31
+ chroma = 0 if missing_chroma
32
+ hue = 0 if missing_hue
33
+
34
+ hue_radians = hue * Math::PI / 180
35
+ LAB.convert(
36
+ dest,
37
+ lightness,
38
+ chroma * Math.cos(hue_radians),
39
+ chroma * Math.sin(hue_radians),
40
+ alpha,
41
+ missing_chroma:,
42
+ missing_hue:
43
+ )
44
+ end
45
+ end
46
+
47
+ private_constant :Lch
48
+
49
+ LCH = Lch.new
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ module Value
5
+ class Color
6
+ module Space
7
+ # @see https://github.com/sass/dart-sass/blob/main/lib/src/value/color/space/lms.dart
8
+ class Lms
9
+ include Space
10
+
11
+ def bounded?
12
+ false
13
+ end
14
+
15
+ def initialize
16
+ super('lms', [
17
+ LinearChannel.new('long', 0, 1).freeze,
18
+ LinearChannel.new('medium', 0, 1).freeze,
19
+ LinearChannel.new('short', 0, 1).freeze
20
+ ].freeze)
21
+ end
22
+
23
+ def convert(dest, long, medium, short, alpha,
24
+ missing_lightness: false,
25
+ missing_chroma: false,
26
+ missing_hue: false,
27
+ missing_a: false,
28
+ missing_b: false)
29
+ case dest
30
+ when OKLAB
31
+ long_scaled = Math.cbrt(long.nil? ? 0 : long)
32
+ medium_scaled = Math.cbrt(medium.nil? ? 0 : medium)
33
+ short_scaled = Math.cbrt(short.nil? ? 0 : short)
34
+
35
+ Color.send(
36
+ :_for_space,
37
+ dest,
38
+ unless missing_lightness
39
+ (Conversions::LMS_TO_OKLAB[0] * long_scaled) +
40
+ (Conversions::LMS_TO_OKLAB[1] * medium_scaled) +
41
+ (Conversions::LMS_TO_OKLAB[2] * short_scaled)
42
+ end,
43
+ unless missing_a
44
+ (Conversions::LMS_TO_OKLAB[3] * long_scaled) +
45
+ (Conversions::LMS_TO_OKLAB[4] * medium_scaled) +
46
+ (Conversions::LMS_TO_OKLAB[5] * short_scaled)
47
+ end,
48
+ unless missing_b
49
+ (Conversions::LMS_TO_OKLAB[6] * long_scaled) +
50
+ (Conversions::LMS_TO_OKLAB[7] * medium_scaled) +
51
+ (Conversions::LMS_TO_OKLAB[8] * short_scaled)
52
+ end,
53
+ alpha
54
+ )
55
+ when OKLCH
56
+ long_scaled = Math.cbrt(long.nil? ? 0 : long)
57
+ medium_scaled = Math.cbrt(medium.nil? ? 0 : medium)
58
+ short_scaled = Math.cbrt(short.nil? ? 0 : short)
59
+
60
+ Utils.lab_to_lch(
61
+ dest,
62
+ unless missing_lightness
63
+ (Conversions::LMS_TO_OKLAB[0] * long_scaled) +
64
+ (Conversions::LMS_TO_OKLAB[1] * medium_scaled) +
65
+ (Conversions::LMS_TO_OKLAB[2] * short_scaled)
66
+ end,
67
+ unless missing_a
68
+ (Conversions::LMS_TO_OKLAB[3] * long_scaled) +
69
+ (Conversions::LMS_TO_OKLAB[4] * medium_scaled) +
70
+ (Conversions::LMS_TO_OKLAB[5] * short_scaled)
71
+ end,
72
+ unless missing_b
73
+ (Conversions::LMS_TO_OKLAB[6] * long_scaled) +
74
+ (Conversions::LMS_TO_OKLAB[7] * medium_scaled) +
75
+ (Conversions::LMS_TO_OKLAB[8] * short_scaled)
76
+ end,
77
+ alpha
78
+ )
79
+ else
80
+ convert_linear(dest, long, medium, short, alpha,
81
+ missing_lightness:,
82
+ missing_chroma:,
83
+ missing_hue:,
84
+ missing_a:,
85
+ missing_b:)
86
+ end
87
+ end
88
+
89
+ def to_linear(channel)
90
+ channel
91
+ end
92
+
93
+ def from_linear(channel)
94
+ channel
95
+ end
96
+
97
+ private
98
+
99
+ def transformation_matrix(dest)
100
+ case dest
101
+ when A98_RGB
102
+ Conversions::LMS_TO_LINEAR_A98_RGB
103
+ when DISPLAY_P3
104
+ Conversions::LMS_TO_LINEAR_DISPLAY_P3
105
+ when PROPHOTO_RGB
106
+ Conversions::LMS_TO_LINEAR_PROPHOTO_RGB
107
+ when REC2020
108
+ Conversions::LMS_TO_LINEAR_REC2020
109
+ when RGB, SRGB, SRGB_LINEAR
110
+ Conversions::LMS_TO_LINEAR_SRGB
111
+ when XYZ_D50
112
+ Conversions::LMS_TO_XYZ_D50
113
+ when XYZ_D65
114
+ Conversions::LMS_TO_XYZ_D65
115
+ else
116
+ super
117
+ end
118
+ end
119
+ end
120
+
121
+ private_constant :Lms
122
+
123
+ LMS = Lms.new
124
+
125
+ private_constant :LMS
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ module Value
5
+ class Color
6
+ module Space
7
+ # @see https://github.com/sass/dart-sass/blob/main/lib/src/value/color/space/oklab.dart
8
+ class Oklab
9
+ include Space
10
+
11
+ def bounded?
12
+ false
13
+ end
14
+
15
+ def initialize
16
+ super('oklab', [
17
+ LinearChannel.new('lightness', 0, 1,
18
+ conventionally_percent: true, lower_clamped: true, upper_clamped: true).freeze,
19
+ LinearChannel.new('a', -0.4, 0.4).freeze,
20
+ LinearChannel.new('b', -0.4, 0.4).freeze
21
+ ].freeze)
22
+ end
23
+
24
+ def convert(dest, lightness, a, b, alpha, # rubocop:disable Naming/MethodParameterName
25
+ missing_chroma: false, missing_hue: false)
26
+ case dest
27
+ when OKLCH
28
+ Utils.lab_to_lch(dest, lightness, a, b, alpha)
29
+ else
30
+ missing_lightness = lightness.nil?
31
+ missing_a = a.nil?
32
+ missing_b = b.nil?
33
+
34
+ lightness = 0 if missing_lightness
35
+ a = 0 if missing_a
36
+ b = 0 if missing_b
37
+
38
+ LMS.convert(
39
+ dest,
40
+ ((Conversions::OKLAB_TO_LMS[0] * lightness) +
41
+ (Conversions::OKLAB_TO_LMS[1] * a) +
42
+ (Conversions::OKLAB_TO_LMS[2] * b))**3,
43
+ ((Conversions::OKLAB_TO_LMS[3] * lightness) +
44
+ (Conversions::OKLAB_TO_LMS[4] * a) +
45
+ (Conversions::OKLAB_TO_LMS[5] * b))**3,
46
+ ((Conversions::OKLAB_TO_LMS[6] * lightness) +
47
+ (Conversions::OKLAB_TO_LMS[7] * a) +
48
+ (Conversions::OKLAB_TO_LMS[8] * b))**3,
49
+ alpha,
50
+ missing_lightness:,
51
+ missing_chroma:,
52
+ missing_hue:,
53
+ missing_a:,
54
+ missing_b:
55
+ )
56
+ end
57
+ end
58
+ end
59
+
60
+ private_constant :Oklab
61
+
62
+ OKLAB = Oklab.new
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ module Value
5
+ class Color
6
+ module Space
7
+ # @see https://github.com/sass/dart-sass/blob/main/lib/src/value/color/space/oklch.dart
8
+ class Oklch
9
+ include Space
10
+
11
+ def bounded?
12
+ false
13
+ end
14
+
15
+ def polar?
16
+ true
17
+ end
18
+
19
+ def initialize
20
+ super('oklch', [
21
+ LinearChannel.new('lightness', 0, 1,
22
+ conventionally_percent: true, lower_clamped: true, upper_clamped: true).freeze,
23
+ LinearChannel.new('chroma', 0, 0.4, lower_clamped: true).freeze,
24
+ Utils::HUE_CHANNEL
25
+ ].freeze)
26
+ end
27
+
28
+ def convert(dest, lightness, chroma, hue, alpha)
29
+ missing_chroma = chroma.nil?
30
+ missing_hue = hue.nil?
31
+
32
+ chroma = 0 if missing_chroma
33
+ hue = 0 if missing_hue
34
+
35
+ hue_radians = hue * Math::PI / 180
36
+ OKLAB.convert(
37
+ dest,
38
+ lightness,
39
+ chroma * Math.cos(hue_radians),
40
+ chroma * Math.sin(hue_radians),
41
+ alpha,
42
+ missing_chroma:,
43
+ missing_hue:
44
+ )
45
+ end
46
+ end
47
+
48
+ private_constant :Oklch
49
+
50
+ OKLCH = Oklch.new
51
+ end
52
+ end
53
+ end
54
+ end