sass-embedded 1.6.2 → 1.83.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +9 -3
  3. data/exe/sass +13 -0
  4. data/ext/sass/Rakefile +352 -76
  5. data/ext/sass/embedded_sass_pb.rb +61 -0
  6. data/ext/sass/expand-archive.ps1 +1 -0
  7. data/ext/sass/package.json +1 -1
  8. data/lib/sass/calculation_value/calculation_operation.rb +49 -0
  9. data/lib/sass/calculation_value.rb +22 -0
  10. data/lib/sass/canonicalize_context.rb +25 -0
  11. data/lib/sass/compile_result.rb +3 -2
  12. data/lib/sass/compiler/channel.rb +68 -0
  13. data/lib/sass/compiler/connection.rb +89 -0
  14. data/lib/sass/compiler/dispatcher.rb +116 -0
  15. data/lib/sass/{embedded → compiler}/host/function_registry.rb +31 -34
  16. data/lib/sass/compiler/host/importer_registry.rb +141 -0
  17. data/lib/sass/compiler/host/logger_registry.rb +80 -0
  18. data/lib/sass/compiler/host/protofier.rb +360 -0
  19. data/lib/sass/compiler/host/structifier.rb +37 -0
  20. data/lib/sass/compiler/host.rb +226 -0
  21. data/lib/sass/{embedded → compiler}/varint.rb +9 -5
  22. data/lib/sass/compiler.rb +212 -0
  23. data/lib/sass/elf.rb +222 -0
  24. data/lib/sass/embedded/version.rb +2 -2
  25. data/lib/sass/embedded.rb +76 -204
  26. data/lib/sass/embedded_protocol.rb +10 -0
  27. data/lib/sass/exception.rb +74 -0
  28. data/lib/sass/fork_tracker.rb +51 -0
  29. data/lib/sass/logger/silent.rb +5 -3
  30. data/lib/sass/logger/source_location.rb +6 -5
  31. data/lib/sass/logger/source_span.rb +8 -7
  32. data/lib/sass/node_package_importer.rb +17 -0
  33. data/lib/sass/serializer.rb +30 -0
  34. data/lib/sass/value/argument_list.rb +13 -6
  35. data/lib/sass/value/boolean.rb +1 -1
  36. data/lib/sass/value/calculation.rb +90 -0
  37. data/lib/sass/value/color/channel.rb +79 -0
  38. data/lib/sass/value/color/conversions.rb +473 -0
  39. data/lib/sass/value/color/gamut_map_method/clip.rb +45 -0
  40. data/lib/sass/value/color/gamut_map_method/local_minde.rb +94 -0
  41. data/lib/sass/value/color/gamut_map_method.rb +45 -0
  42. data/lib/sass/value/color/interpolation_method.rb +51 -0
  43. data/lib/sass/value/color/space/a98_rgb.rb +57 -0
  44. data/lib/sass/value/color/space/display_p3.rb +57 -0
  45. data/lib/sass/value/color/space/hsl.rb +65 -0
  46. data/lib/sass/value/color/space/hwb.rb +70 -0
  47. data/lib/sass/value/color/space/lab.rb +77 -0
  48. data/lib/sass/value/color/space/lch.rb +53 -0
  49. data/lib/sass/value/color/space/lms.rb +129 -0
  50. data/lib/sass/value/color/space/oklab.rb +66 -0
  51. data/lib/sass/value/color/space/oklch.rb +54 -0
  52. data/lib/sass/value/color/space/prophoto_rgb.rb +59 -0
  53. data/lib/sass/value/color/space/rec2020.rb +69 -0
  54. data/lib/sass/value/color/space/rgb.rb +52 -0
  55. data/lib/sass/value/color/space/srgb.rb +140 -0
  56. data/lib/sass/value/color/space/srgb_linear.rb +72 -0
  57. data/lib/sass/value/color/space/utils.rb +86 -0
  58. data/lib/sass/value/color/space/xyz_d50.rb +100 -0
  59. data/lib/sass/value/color/space/xyz_d65.rb +57 -0
  60. data/lib/sass/value/color/space.rb +198 -0
  61. data/lib/sass/value/color.rb +538 -163
  62. data/lib/sass/value/function.rb +11 -16
  63. data/lib/sass/value/fuzzy_math.rb +24 -21
  64. data/lib/sass/value/list.rb +7 -7
  65. data/lib/sass/value/map.rb +6 -6
  66. data/lib/sass/value/mixin.rb +34 -0
  67. data/lib/sass/value/null.rb +1 -1
  68. data/lib/sass/value/number/unit.rb +7 -6
  69. data/lib/sass/value/number.rb +34 -26
  70. data/lib/sass/value/string.rb +9 -3
  71. data/lib/sass/value.rb +20 -16
  72. metadata +67 -103
  73. data/ext/sass/unzip.vbs +0 -13
  74. data/lib/sass/compile_error.rb +0 -28
  75. data/lib/sass/embedded/async.rb +0 -65
  76. data/lib/sass/embedded/channel.rb +0 -61
  77. data/lib/sass/embedded/compiler.rb +0 -60
  78. data/lib/sass/embedded/dispatcher.rb +0 -90
  79. data/lib/sass/embedded/host/importer_registry.rb +0 -107
  80. data/lib/sass/embedded/host/logger_registry.rb +0 -50
  81. data/lib/sass/embedded/host/value_protofier.rb +0 -241
  82. data/lib/sass/embedded/host.rb +0 -139
  83. data/lib/sass/embedded/protofier.rb +0 -78
  84. data/lib/sass/embedded/structifier.rb +0 -36
  85. data/lib/sass/script_error.rb +0 -6
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ module Value
5
+ class Color
6
+ module GamutMapMethod
7
+ # @see https://github.com/sass/dart-sass/blob/main/lib/src/value/color/gamut_map_method/local_minde.dart
8
+ class LocalMinde
9
+ include GamutMapMethod
10
+
11
+ # A constant from the gamut-mapping algorithm.
12
+ JND = 0.02
13
+
14
+ private_constant :JND
15
+
16
+ # A constant from the gamut-mapping algorithm.
17
+ EPSILON = 0.0001
18
+
19
+ private_constant :EPSILON
20
+
21
+ def initialize
22
+ super('local-minde')
23
+ end
24
+
25
+ def map(color)
26
+ original_oklch = color.send(:_to_space, Space::OKLCH)
27
+ lightness = original_oklch.send(:channel0_or_nil)
28
+ hue = original_oklch.send(:channel2_or_nil)
29
+ alpha = original_oklch.send(:alpha_or_nil)
30
+
31
+ if FuzzyMath.greater_than_or_equals(lightness.nil? ? 0 : lightness, 1)
32
+ if color.legacy?
33
+ return Color.send(:_for_space,
34
+ Space::RGB, 255, 255, 255, color.send(:alpha_or_nil))
35
+ .send(:_to_space, color.send(:_space))
36
+ else
37
+ return Color.send(:for_space_internal,
38
+ color.send(:_space), 1, 1, 1, color.send(:alpha_or_nil))
39
+ end
40
+ elsif FuzzyMath.less_than_or_equals(lightness.nil? ? 0 : lightness, 0)
41
+ return Color.send(:_for_space,
42
+ Space::RGB, 0, 0, 0, color.send(:alpha_or_nil))
43
+ .send(:_to_space, color.send(:_space))
44
+ end
45
+
46
+ clipped = color.send(:_to_gamut, CLIP)
47
+ return clipped if _delta_eok(clipped, color) < JND
48
+
49
+ min = 0.0
50
+ max = original_oklch.send(:channel1)
51
+ min_in_gamut = true
52
+ while max - min > EPSILON
53
+ chroma = (min + max) / 2
54
+
55
+ current = Space::OKLCH.convert(color.send(:_space), lightness, chroma, hue, alpha)
56
+
57
+ if min_in_gamut && current.in_gamut?
58
+ min = chroma
59
+ next
60
+ end
61
+
62
+ clipped = current.send(:_to_gamut, CLIP)
63
+ e = _delta_eok(clipped, current)
64
+
65
+ if e < JND
66
+ return clipped if JND - e < EPSILON
67
+
68
+ min_in_gamut = false
69
+ min = chroma
70
+ else
71
+ max = chroma
72
+ end
73
+ end
74
+ clipped
75
+ end
76
+
77
+ private
78
+
79
+ def _delta_eok(color1, color2)
80
+ lab1 = color1.send(:_to_space, Space::OKLAB)
81
+ lab2 = color2.send(:_to_space, Space::OKLAB)
82
+ Math.sqrt(((lab1.send(:channel0) - lab2.send(:channel0))**2) +
83
+ ((lab1.send(:channel1) - lab2.send(:channel1))**2) +
84
+ ((lab1.send(:channel2) - lab2.send(:channel2))**2))
85
+ end
86
+ end
87
+
88
+ private_constant :LocalMinde
89
+
90
+ LOCAL_MINDE = LocalMinde.new
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,45 @@
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/gamut_map_method.dart
7
+ module GamutMapMethod
8
+ # @return [::String]
9
+ attr_reader :name
10
+
11
+ # @param name [::String]
12
+ def initialize(name)
13
+ @name = name
14
+ end
15
+
16
+ class << self
17
+ # @param name [::String]
18
+ # @param argument_name [::String]
19
+ # @return [GamutMapMethod]
20
+ def from_name(name, argument_name = nil)
21
+ case name
22
+ when 'clip'
23
+ CLIP
24
+ when 'local-minde'
25
+ LOCAL_MINDE
26
+ else
27
+ raise Sass::ScriptError.new("Unknown gamut map method \"#{name}\".", argument_name)
28
+ end
29
+ end
30
+ end
31
+
32
+ # @param color [Color]
33
+ # @return [Color]
34
+ def map(color)
35
+ raise NotImplementedError, "[BUG] gamut map method #{name} doesn't implement map."
36
+ end
37
+ end
38
+
39
+ private_constant :GamutMapMethod
40
+ end
41
+ end
42
+ end
43
+
44
+ require_relative 'gamut_map_method/clip'
45
+ require_relative 'gamut_map_method/local_minde'
@@ -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
+ (channel <=> 0) * (channel.abs**(563 / 256.0))
21
+ end
22
+
23
+ def from_linear(channel)
24
+ (channel <=> 0) * (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