sai 0.3.0 → 0.3.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -1
- data/README.md +11 -3
- data/docs/USAGE.md +57 -9
- data/lib/sai/ansi/color_parser.rb +109 -0
- data/lib/sai/ansi/sequence_processor.rb +15 -126
- data/lib/sai/ansi/style_parser.rb +66 -0
- data/lib/sai/ansi.rb +0 -27
- data/lib/sai/conversion/color_sequence.rb +4 -4
- data/lib/sai/conversion/rgb/color_classifier.rb +209 -0
- data/lib/sai/conversion/rgb/color_indexer.rb +48 -0
- data/lib/sai/conversion/rgb/color_space.rb +192 -0
- data/lib/sai/conversion/rgb/color_transformer.rb +140 -0
- data/lib/sai/conversion/rgb.rb +23 -269
- data/lib/sai/decorator/color_manipulations.rb +157 -0
- data/lib/sai/decorator/delegation.rb +84 -0
- data/lib/sai/decorator/gradients.rb +363 -0
- data/lib/sai/decorator/hex_colors.rb +56 -0
- data/lib/sai/decorator/named_colors.rb +780 -0
- data/lib/sai/decorator/named_styles.rb +276 -0
- data/lib/sai/decorator/rgb_colors.rb +64 -0
- data/lib/sai/decorator.rb +29 -775
- data/lib/sai/named_colors.rb +437 -0
- data/lib/sai.rb +731 -23
- data/sig/sai/ansi/color_parser.rbs +77 -0
- data/sig/sai/ansi/sequence_processor.rbs +0 -75
- data/sig/sai/ansi/style_parser.rbs +59 -0
- data/sig/sai/ansi.rbs +0 -10
- data/sig/sai/conversion/rgb/color_classifier.rbs +165 -0
- data/sig/sai/conversion/rgb/color_indexer.rbs +41 -0
- data/sig/sai/conversion/rgb/color_space.rbs +129 -0
- data/sig/sai/conversion/rgb/color_transformer.rbs +99 -0
- data/sig/sai/conversion/rgb.rbs +15 -198
- data/sig/sai/decorator/color_manipulations.rbs +125 -0
- data/sig/sai/decorator/delegation.rbs +47 -0
- data/sig/sai/decorator/gradients.rbs +267 -0
- data/sig/sai/decorator/hex_colors.rbs +48 -0
- data/sig/sai/decorator/named_colors.rbs +1491 -0
- data/sig/sai/decorator/named_styles.rbs +72 -0
- data/sig/sai/decorator/rgb_colors.rbs +52 -0
- data/sig/sai/decorator.rbs +21 -195
- data/sig/sai/named_colors.rbs +65 -0
- data/sig/sai.rbs +1468 -44
- metadata +32 -4
@@ -0,0 +1,77 @@
|
|
1
|
+
# Generated from lib/sai/ansi/color_parser.rb with RBS::Inline
|
2
|
+
|
3
|
+
module Sai
|
4
|
+
module ANSI
|
5
|
+
# Handles parsing of ANSI color codes
|
6
|
+
#
|
7
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
8
|
+
# @since 0.3.1
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
class ColorParser
|
12
|
+
# The current segment being processed
|
13
|
+
#
|
14
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
15
|
+
# @since 0.3.1
|
16
|
+
#
|
17
|
+
# @api private
|
18
|
+
#
|
19
|
+
# @return [Hash] the current segment being processed
|
20
|
+
attr_reader segment: Hash[Symbol, untyped]
|
21
|
+
|
22
|
+
# Initialize a new instance of ColorParser
|
23
|
+
#
|
24
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
25
|
+
# @since 0.3.1
|
26
|
+
#
|
27
|
+
# @api private
|
28
|
+
#
|
29
|
+
# @param segment [Hash] the segment to update
|
30
|
+
#
|
31
|
+
# @return [ColorParser] the new instance of ColorParser
|
32
|
+
# @rbs (Hash[Symbol, untyped] segment) -> void
|
33
|
+
def initialize: (Hash[Symbol, untyped] segment) -> void
|
34
|
+
|
35
|
+
# Parse a 256-color code
|
36
|
+
#
|
37
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
38
|
+
# @since 0.3.1
|
39
|
+
#
|
40
|
+
# @api private
|
41
|
+
#
|
42
|
+
# @param codes [Array<Integer>] array of color codes
|
43
|
+
# @param index [Integer] current position in array
|
44
|
+
#
|
45
|
+
# @return [Integer] new position in array
|
46
|
+
# @rbs (Array[Integer] codes, Integer index) -> Integer
|
47
|
+
def parse256: (Array[Integer] codes, Integer index) -> Integer
|
48
|
+
|
49
|
+
# Parse a 24-bit color code
|
50
|
+
#
|
51
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
52
|
+
# @since 0.3.1
|
53
|
+
#
|
54
|
+
# @api private
|
55
|
+
#
|
56
|
+
# @param codes [Array<Integer>] array of color codes
|
57
|
+
# @param index [Integer] current position in array
|
58
|
+
#
|
59
|
+
# @return [Integer] new position in array
|
60
|
+
# @rbs (Array[Integer] codes, Integer index) -> Integer
|
61
|
+
def parse_24bit: (Array[Integer] codes, Integer index) -> Integer
|
62
|
+
|
63
|
+
# Parse a basic color code
|
64
|
+
#
|
65
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
66
|
+
# @since 0.3.1
|
67
|
+
#
|
68
|
+
# @api private
|
69
|
+
#
|
70
|
+
# @param code [Integer] the color code
|
71
|
+
#
|
72
|
+
# @return [void]
|
73
|
+
# @rbs (Integer code) -> void
|
74
|
+
def parse_basic: (Integer code) -> void
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -19,16 +19,6 @@ module Sai
|
|
19
19
|
# @return [Regexp] the pattern
|
20
20
|
SEQUENCE_PATTERN: Regexp
|
21
21
|
|
22
|
-
# Matches the code portion of style sequences
|
23
|
-
#
|
24
|
-
# @author {https://aaronmallen.me Aaron Allen}
|
25
|
-
# @since 0.3.0
|
26
|
-
#
|
27
|
-
# @api private
|
28
|
-
#
|
29
|
-
# @return [Regexp] the pattern
|
30
|
-
STYLE_CODE_PATTERN: Regexp
|
31
|
-
|
32
22
|
# Initialize a new instance of SequenceProcessor and parse the provided string
|
33
23
|
#
|
34
24
|
# @author {https://aaronmallen.me Aaron Allen}
|
@@ -68,34 +58,6 @@ module Sai
|
|
68
58
|
|
69
59
|
private
|
70
60
|
|
71
|
-
# Applies 24-bit truecolor (e.g., 38;2;R;G;B or 48;2;R;G;B)
|
72
|
-
#
|
73
|
-
# @author {https://aaronmallen.me Aaron Allen}
|
74
|
-
# @since 0.3.0
|
75
|
-
#
|
76
|
-
# @api private
|
77
|
-
#
|
78
|
-
# @param codes_array [Array<Integer>]
|
79
|
-
# @param index [Integer]
|
80
|
-
#
|
81
|
-
# @return [Integer] the updated index (consumed 5 codes)
|
82
|
-
# @rbs (Array[Integer] codes_array, Integer index) -> Integer
|
83
|
-
def apply_24bit_color: (Array[Integer] codes_array, Integer index) -> Integer
|
84
|
-
|
85
|
-
# Applies 256-color mode (e.g., 38;5;160 or 48;5;21)
|
86
|
-
#
|
87
|
-
# @author {https://aaronmallen.me Aaron Allen}
|
88
|
-
# @since 0.3.0
|
89
|
-
#
|
90
|
-
# @api private
|
91
|
-
#
|
92
|
-
# @param codes_array [Array<Integer>]
|
93
|
-
# @param index [Integer]
|
94
|
-
#
|
95
|
-
# @return [Integer] the updated index (consumed 3 codes)
|
96
|
-
# @rbs (Array[Integer] codes_array, Integer index) -> Integer
|
97
|
-
def apply_256_color: (Array[Integer] codes_array, Integer index) -> Integer
|
98
|
-
|
99
61
|
# Applies the appropriate action for the provided ANSI sequence
|
100
62
|
#
|
101
63
|
# @author {https://aaronmallen.me Aaron Allen}
|
@@ -109,19 +71,6 @@ module Sai
|
|
109
71
|
# @rbs (String sequence) -> void
|
110
72
|
def apply_ansi_sequence: (String sequence) -> void
|
111
73
|
|
112
|
-
# Applies a basic color (FG or BG) in the range 30..37 (FG) or 40..47 (BG)
|
113
|
-
#
|
114
|
-
# @author {https://aaronmallen.me Aaron Allen}
|
115
|
-
# @since 0.3.0
|
116
|
-
#
|
117
|
-
# @api private
|
118
|
-
#
|
119
|
-
# @param code [Integer] the numeric color code
|
120
|
-
#
|
121
|
-
# @return [void]
|
122
|
-
# @rbs (Integer code) -> void
|
123
|
-
def apply_basic_color: (Integer code) -> void
|
124
|
-
|
125
74
|
# Parse all numeric codes in the provided string, applying them in order (just like a real ANSI terminal)
|
126
75
|
#
|
127
76
|
# @author {https://aaronmallen.me Aaron Allen}
|
@@ -154,30 +103,6 @@ module Sai
|
|
154
103
|
# @rbs (Array[Integer] codes_array, Integer index) -> Integer
|
155
104
|
def apply_single_code: (Array[Integer] codes_array, Integer index) -> Integer
|
156
105
|
|
157
|
-
# Applies a single style code (e.g. 1=bold, 2=dim, 4=underline, etc.) if it matches
|
158
|
-
#
|
159
|
-
# @author {https://aaronmallen.me Aaron Allen}
|
160
|
-
# @since 0.3.0
|
161
|
-
#
|
162
|
-
# @api private
|
163
|
-
#
|
164
|
-
# @param code [Integer] the numeric code to check
|
165
|
-
#
|
166
|
-
# @return [void]
|
167
|
-
# @rbs (Integer code) -> void
|
168
|
-
def apply_style_code: (Integer code) -> void
|
169
|
-
|
170
|
-
# Creates and returns a fresh, blank segment
|
171
|
-
#
|
172
|
-
# @author {https://aaronmallen.me Aaron Allen}
|
173
|
-
# @since 0.3.0
|
174
|
-
#
|
175
|
-
# @api private
|
176
|
-
#
|
177
|
-
# @return [Hash{Symbol => Object}] a new, empty segment
|
178
|
-
# @rbs () -> Hash[Symbol, untyped]
|
179
|
-
def blank_segment: () -> Hash[Symbol, untyped]
|
180
|
-
|
181
106
|
# Scans the string for ANSI sequences or individual characters
|
182
107
|
#
|
183
108
|
# @author {https://aaronmallen.me Aaron Allen}
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# Generated from lib/sai/ansi/style_parser.rb with RBS::Inline
|
2
|
+
|
3
|
+
module Sai
|
4
|
+
module ANSI
|
5
|
+
# Handles parsing of ANSI style codes
|
6
|
+
#
|
7
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
8
|
+
# @since 0.3.1
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
class StyleParser
|
12
|
+
# Matches the code portion of style sequences
|
13
|
+
#
|
14
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
15
|
+
# @since 0.3.1
|
16
|
+
#
|
17
|
+
# @api private
|
18
|
+
#
|
19
|
+
# @return [Regexp] the pattern
|
20
|
+
STYLE_CODE_PATTERN: Regexp
|
21
|
+
|
22
|
+
# The current segment being processed
|
23
|
+
#
|
24
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
25
|
+
# @since 0.3.1
|
26
|
+
#
|
27
|
+
# @api private
|
28
|
+
#
|
29
|
+
# @return [Hash] the current segment being processed
|
30
|
+
attr_reader segment: Hash[Symbol, untyped]
|
31
|
+
|
32
|
+
# Initialize a new instance of StyleParser
|
33
|
+
#
|
34
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
35
|
+
# @since 0.3.1
|
36
|
+
#
|
37
|
+
# @api private
|
38
|
+
#
|
39
|
+
# @param segment [Hash] the segment to update
|
40
|
+
#
|
41
|
+
# @return [StyleParser] the new instance of StyleParser
|
42
|
+
# @rbs (Hash[Symbol, untyped] segment) -> void
|
43
|
+
def initialize: (Hash[Symbol, untyped] segment) -> void
|
44
|
+
|
45
|
+
# Parse a style code
|
46
|
+
#
|
47
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
48
|
+
# @since 0.3.1
|
49
|
+
#
|
50
|
+
# @api private
|
51
|
+
#
|
52
|
+
# @param code [Integer] the style code
|
53
|
+
#
|
54
|
+
# @return [void]
|
55
|
+
# @rbs (Integer code) -> void
|
56
|
+
def parse: (Integer code) -> void
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/sig/sai/ansi.rbs
CHANGED
@@ -18,16 +18,6 @@ module Sai
|
|
18
18
|
# @return [Hash{Symbol => Integer}] the color codes
|
19
19
|
COLOR_CODES: untyped
|
20
20
|
|
21
|
-
# Standard ANSI color names and their RGB values
|
22
|
-
#
|
23
|
-
# @author {https://aaronmallen.me Aaron Allen}
|
24
|
-
# @since 0.1.0
|
25
|
-
#
|
26
|
-
# @api private
|
27
|
-
#
|
28
|
-
# @return [Hash{Symbol => Array<Integer>}] the color names and RGB values
|
29
|
-
COLOR_NAMES: untyped
|
30
|
-
|
31
21
|
# ANSI escape sequence for resetting text formatting
|
32
22
|
#
|
33
23
|
# @author {https://aaronmallen.me Aaron Allen}
|
@@ -0,0 +1,165 @@
|
|
1
|
+
# Generated from lib/sai/conversion/rgb/color_classifier.rb with RBS::Inline
|
2
|
+
|
3
|
+
module Sai
|
4
|
+
module Conversion
|
5
|
+
module RGB
|
6
|
+
# Classify color characteristics
|
7
|
+
#
|
8
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
9
|
+
# @since 0.3.1
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
module ColorClassifier
|
13
|
+
# Get closest ANSI color for RGB values
|
14
|
+
#
|
15
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
16
|
+
# @since 0.1.0
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
#
|
20
|
+
# @param red [Float] the red component (0-1)
|
21
|
+
# @param green [Float] the green component (0-1)
|
22
|
+
# @param blue [Float] the blue component (0-1)
|
23
|
+
#
|
24
|
+
# @return [Symbol] the closest ANSI color name
|
25
|
+
# @rbs (Float red, Float green, Float blue) -> Symbol
|
26
|
+
def self.closest_ansi_color: (Float red, Float green, Float blue) -> Symbol
|
27
|
+
|
28
|
+
# Determine if a color is dark
|
29
|
+
#
|
30
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
31
|
+
# @since 0.1.0
|
32
|
+
#
|
33
|
+
# @api private
|
34
|
+
#
|
35
|
+
# @param red [Float] the red component (0-1)
|
36
|
+
# @param green [Float] the green component (0-1)
|
37
|
+
# @param blue [Float] the blue component (0-1)
|
38
|
+
#
|
39
|
+
# @return [Boolean] true if color is dark
|
40
|
+
# @rbs (Float red, Float green, Float blue) -> bool
|
41
|
+
def self.dark?: (Float red, Float green, Float blue) -> bool
|
42
|
+
|
43
|
+
# Determine if a color is grayscale
|
44
|
+
#
|
45
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
46
|
+
# @since 0.1.0
|
47
|
+
#
|
48
|
+
# @api private
|
49
|
+
#
|
50
|
+
# @param red [Float] the red component (0-1)
|
51
|
+
# @param green [Float] the green component (0-1)
|
52
|
+
# @param blue [Float] the blue component (0-1)
|
53
|
+
#
|
54
|
+
# @return [Boolean] true if color is grayscale
|
55
|
+
# @rbs (Float red, Float green, Float blue) -> bool
|
56
|
+
def self.grayscale?: (Float red, Float green, Float blue) -> bool
|
57
|
+
|
58
|
+
# Determine if RGB values represent a primary color
|
59
|
+
#
|
60
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
61
|
+
# @since 0.1.0
|
62
|
+
#
|
63
|
+
# @api private
|
64
|
+
#
|
65
|
+
# @param red [Float] the red component (0-1)
|
66
|
+
# @param green [Float] the green component (0-1)
|
67
|
+
# @param blue [Float] the blue component (0-1)
|
68
|
+
#
|
69
|
+
# @return [Boolean] true if color is primary
|
70
|
+
# @rbs (Float red, Float green, Float blue) -> bool
|
71
|
+
def self.primary?: (Float red, Float green, Float blue) -> bool
|
72
|
+
|
73
|
+
# Get the closest primary color
|
74
|
+
#
|
75
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
76
|
+
# @since 0.1.0
|
77
|
+
#
|
78
|
+
# @api private
|
79
|
+
#
|
80
|
+
# @param red [Float] the red component (0-1)
|
81
|
+
# @param green [Float] the green component (0-1)
|
82
|
+
# @param blue [Float] the blue component (0-1)
|
83
|
+
#
|
84
|
+
# @return [Symbol] the primary color name
|
85
|
+
# @rbs (Float red, Float green, Float blue) -> Symbol
|
86
|
+
def self.primary_color: (Float red, Float green, Float blue) -> Symbol
|
87
|
+
|
88
|
+
# Determine if RGB values represent a secondary color
|
89
|
+
#
|
90
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
91
|
+
# @since 0.1.0
|
92
|
+
#
|
93
|
+
# @api private
|
94
|
+
#
|
95
|
+
# @param red [Float] the red component (0-1)
|
96
|
+
# @param green [Float] the green component (0-1)
|
97
|
+
# @param blue [Float] the blue component (0-1)
|
98
|
+
#
|
99
|
+
# @return [Boolean] true if color is secondary
|
100
|
+
# @rbs (Float red, Float green, Float blue) -> bool
|
101
|
+
def self.secondary?: (Float red, Float green, Float blue) -> bool
|
102
|
+
|
103
|
+
# Get the closest secondary color
|
104
|
+
#
|
105
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
106
|
+
# @since 0.1.0
|
107
|
+
#
|
108
|
+
# @api private
|
109
|
+
#
|
110
|
+
# @param red [Float] the red component (0-1)
|
111
|
+
# @param green [Float] the green component (0-1)
|
112
|
+
# @param blue [Float] the blue component (0-1)
|
113
|
+
#
|
114
|
+
# @return [Symbol] the secondary color name
|
115
|
+
# @rbs (Float red, Float green, Float blue) -> Symbol
|
116
|
+
def self.secondary_color: (Float red, Float green, Float blue) -> Symbol
|
117
|
+
|
118
|
+
# Check if RGB values represent cyan
|
119
|
+
#
|
120
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
121
|
+
# @since 0.1.0
|
122
|
+
#
|
123
|
+
# @api private
|
124
|
+
#
|
125
|
+
# @param red [Float] the red component (0-1)
|
126
|
+
# @param green [Float] the green component (0-1)
|
127
|
+
# @param blue [Float] the blue component (0-1)
|
128
|
+
#
|
129
|
+
# @return [Boolean] true if color is cyan
|
130
|
+
# @rbs (Float red, Float green, Float blue) -> bool
|
131
|
+
private def self.cyan?: (Float red, Float green, Float blue) -> bool
|
132
|
+
|
133
|
+
# Check if RGB values represent magenta
|
134
|
+
#
|
135
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
136
|
+
# @since 0.1.0
|
137
|
+
#
|
138
|
+
# @api private
|
139
|
+
#
|
140
|
+
# @param red [Float] the red component (0-1)
|
141
|
+
# @param green [Float] the green component (0-1)
|
142
|
+
# @param blue [Float] the blue component (0-1)
|
143
|
+
#
|
144
|
+
# @return [Boolean] true if color is magenta
|
145
|
+
# @rbs (Float red, Float green, Float blue) -> bool
|
146
|
+
private def self.magenta?: (Float red, Float green, Float blue) -> bool
|
147
|
+
|
148
|
+
# Check if RGB values represent yellow
|
149
|
+
#
|
150
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
151
|
+
# @since 0.1.0
|
152
|
+
#
|
153
|
+
# @api private
|
154
|
+
#
|
155
|
+
# @param red [Float] the red component (0-1)
|
156
|
+
# @param green [Float] the green component (0-1)
|
157
|
+
# @param blue [Float] the blue component (0-1)
|
158
|
+
#
|
159
|
+
# @return [Boolean] true if color is yellow
|
160
|
+
# @rbs (Float red, Float green, Float blue) -> bool
|
161
|
+
private def self.yellow?: (Float red, Float green, Float blue) -> bool
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# Generated from lib/sai/conversion/rgb/color_indexer.rb with RBS::Inline
|
2
|
+
|
3
|
+
module Sai
|
4
|
+
module Conversion
|
5
|
+
module RGB
|
6
|
+
# Color indexing utilities
|
7
|
+
#
|
8
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
9
|
+
# @since 0.3.1
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
module ColorIndexer
|
13
|
+
# Convert RGB values to 256-color cube index
|
14
|
+
#
|
15
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
16
|
+
# @since 0.1.0
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
#
|
20
|
+
# @param rgb [Array<Integer>] RGB values (0-255)
|
21
|
+
#
|
22
|
+
# @return [Integer] the color cube index
|
23
|
+
# @rbs (Array[Integer] rgb) -> Integer
|
24
|
+
def self.color_cube: (Array[Integer] rgb) -> Integer
|
25
|
+
|
26
|
+
# Convert RGB values to grayscale index
|
27
|
+
#
|
28
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
29
|
+
# @since 0.1.0
|
30
|
+
#
|
31
|
+
# @api private
|
32
|
+
#
|
33
|
+
# @param rgb [Array<Integer>] RGB values
|
34
|
+
#
|
35
|
+
# @return [Integer] the grayscale index
|
36
|
+
# @rbs (Array[Integer] rgb) -> Integer
|
37
|
+
def self.grayscale: (Array[Integer] rgb) -> Integer
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# Generated from lib/sai/conversion/rgb/color_space.rb with RBS::Inline
|
2
|
+
|
3
|
+
module Sai
|
4
|
+
module Conversion
|
5
|
+
module RGB
|
6
|
+
# Convert colors between different color space formats
|
7
|
+
#
|
8
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
9
|
+
# @since 0.3.1
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
module ColorSpace
|
13
|
+
# Convert HSV values to RGB
|
14
|
+
#
|
15
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
16
|
+
# @since 0.3.1
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
#
|
20
|
+
# @param hue [Float] the hue component (0-360)
|
21
|
+
# @param saturation [Float] the saturation component (0-1)
|
22
|
+
# @param value [Float] the value component (0-1)
|
23
|
+
#
|
24
|
+
# @return [Array<Integer>] the RGB values
|
25
|
+
# @rbs (Float hue, Float saturation, Float value) -> Array[Integer]
|
26
|
+
def self.hsv_to_rgb: (Float hue, Float saturation, Float value) -> Array[Integer]
|
27
|
+
|
28
|
+
# Convert a color value to RGB components
|
29
|
+
#
|
30
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
31
|
+
# @since 0.1.0
|
32
|
+
#
|
33
|
+
# @api private
|
34
|
+
#
|
35
|
+
# @param color [String, Array<Integer>] the color to convert
|
36
|
+
#
|
37
|
+
# @raise [ArgumentError] if the color format is invalid
|
38
|
+
# @return [Array<Integer>] the RGB components
|
39
|
+
# @rbs (Array[Integer] | String | Symbol color) -> Array[Integer]
|
40
|
+
def self.resolve: (Array[Integer] | String | Symbol color) -> Array[Integer]
|
41
|
+
|
42
|
+
# Calculate the intermediate HSV components
|
43
|
+
#
|
44
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
45
|
+
# @since 0.3.1
|
46
|
+
#
|
47
|
+
# @api private
|
48
|
+
#
|
49
|
+
# @param value [Float] the value component
|
50
|
+
# @param saturation [Float] the saturation component
|
51
|
+
# @param hue_remainder [Float] the remainder of hue / 60
|
52
|
+
#
|
53
|
+
# @return [Array<Float>] the primary, secondary, and tertiary components
|
54
|
+
# @rbs (Float value, Float saturation, Float hue_remainder) -> [Float, Float, Float]
|
55
|
+
private def self.calculate_hsv_components: (Float value, Float saturation, Float hue_remainder) -> [ Float, Float, Float ]
|
56
|
+
|
57
|
+
# Convert a hex string to RGB values
|
58
|
+
#
|
59
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
60
|
+
# @since 0.1.0
|
61
|
+
#
|
62
|
+
# @api private
|
63
|
+
#
|
64
|
+
# @param hex [String] the hex color code
|
65
|
+
#
|
66
|
+
# @return [Array<Integer>] the RGB components
|
67
|
+
# @rbs (String hex) -> Array[Integer]
|
68
|
+
private def self.hex_to_rgb: (String hex) -> Array[Integer]
|
69
|
+
|
70
|
+
# Convert a named color to RGB values
|
71
|
+
#
|
72
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
73
|
+
# @since 0.1.0
|
74
|
+
#
|
75
|
+
# @api private
|
76
|
+
#
|
77
|
+
# @param color_name [String] the color name
|
78
|
+
#
|
79
|
+
# @raise [ArgumentError] if the color name is unknown
|
80
|
+
# @return [Array<Integer>] the RGB components
|
81
|
+
# @rbs (String color_name) -> Array[Integer]
|
82
|
+
private def self.named_to_rgb: (String color_name) -> Array[Integer]
|
83
|
+
|
84
|
+
# Convert RGB values from 0-1 range to 0-255 range
|
85
|
+
#
|
86
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
87
|
+
# @since 0.3.1
|
88
|
+
#
|
89
|
+
# @api private
|
90
|
+
#
|
91
|
+
# @param rgb [Array<Float>] RGB values in 0-1 range
|
92
|
+
#
|
93
|
+
# @return [Array<Integer>] RGB values in 0-255 range
|
94
|
+
# @rbs (Array[Float] rgb) -> Array[Integer]
|
95
|
+
private def self.normalize_rgb: (Array[Float] rgb) -> Array[Integer]
|
96
|
+
|
97
|
+
# Select RGB values based on the hue sector
|
98
|
+
#
|
99
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
100
|
+
# @since 0.3.1
|
101
|
+
#
|
102
|
+
# @api private
|
103
|
+
#
|
104
|
+
# @param sector [Integer] the hue sector (0-5)
|
105
|
+
# @param value [Float] the value component
|
106
|
+
# @param primary [Float] primary component from HSV calculation
|
107
|
+
# @param secondary [Float] secondary component from HSV calculation
|
108
|
+
# @param tertiary [Float] tertiary component from HSV calculation
|
109
|
+
#
|
110
|
+
# @return [Array<Float>] the RGB values before normalization
|
111
|
+
# @rbs (Integer sector, Float value, Float primary, Float secondary, Float tertiary) -> Array[Float]
|
112
|
+
private def self.select_rgb_values: (Integer sector, Float value, Float primary, Float secondary, Float tertiary) -> Array[Float]
|
113
|
+
|
114
|
+
# Validate RGB values
|
115
|
+
#
|
116
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
117
|
+
# @since 0.1.0
|
118
|
+
#
|
119
|
+
# @api private
|
120
|
+
#
|
121
|
+
# @param color [Array<Integer>] the RGB components to validate
|
122
|
+
# @return [Array<Integer>] the validated RGB components
|
123
|
+
# @raise [ArgumentError] if the RGB values are invalid
|
124
|
+
# @rbs (Array[Integer] color) -> Array[Integer]
|
125
|
+
private def self.validate_rgb: (Array[Integer] color) -> Array[Integer]
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# Generated from lib/sai/conversion/rgb/color_transformer.rb with RBS::Inline
|
2
|
+
|
3
|
+
module Sai
|
4
|
+
module Conversion
|
5
|
+
module RGB
|
6
|
+
# Perform color transformations
|
7
|
+
#
|
8
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
9
|
+
# @since 0.3.1
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
module ColorTransformer
|
13
|
+
# Darken an RGB color by a percentage
|
14
|
+
#
|
15
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
16
|
+
# @since 0.3.1
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
#
|
20
|
+
# @param color [Array<Integer>, String, Symbol] the color to darken
|
21
|
+
# @param amount [Float] amount to darken by (0.0-1.0)
|
22
|
+
#
|
23
|
+
# @raise [ArgumentError] if amount is not between 0.0 and 1.0
|
24
|
+
# @return [Array<Integer>] the darkened RGB values
|
25
|
+
# @rbs ((Array[Integer] | String | Symbol) color, Float amount) -> Array[Integer]
|
26
|
+
def self.darken: (Array[Integer] | String | Symbol color, Float amount) -> Array[Integer]
|
27
|
+
|
28
|
+
# Generate a gradient between two colors with a specified number of steps
|
29
|
+
#
|
30
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
31
|
+
# @since 0.3.1
|
32
|
+
#
|
33
|
+
# @api private
|
34
|
+
#
|
35
|
+
# @param start_color [Array<Integer>, String, Symbol] the starting color
|
36
|
+
# @param end_color [Array<Integer>, String, Symbol] the ending color
|
37
|
+
# @param steps [Integer] the number of colors to generate (minimum 2)
|
38
|
+
#
|
39
|
+
# @raise [ArgumentError] if steps is less than 2
|
40
|
+
# @return [Array<Array<Integer>>] the gradient colors as RGB values
|
41
|
+
# @rbs (
|
42
|
+
# (Array[Integer] | String | Symbol) start_color,
|
43
|
+
# (Array[Integer] | String | Symbol) end_color,
|
44
|
+
# Integer steps
|
45
|
+
# ) -> Array[Array[Integer]]
|
46
|
+
def self.gradient: (Array[Integer] | String | Symbol start_color, Array[Integer] | String | Symbol end_color, Integer steps) -> Array[Array[Integer]]
|
47
|
+
|
48
|
+
# Interpolate between two colors to create a gradient step
|
49
|
+
#
|
50
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
51
|
+
# @since 0.3.1
|
52
|
+
#
|
53
|
+
# @api private
|
54
|
+
#
|
55
|
+
# @param start_color [Array<Integer>, String, Symbol] the starting color
|
56
|
+
# @param end_color [Array<Integer>, String, Symbol] the ending color
|
57
|
+
# @param step [Float] the interpolation step (0.0-1.0)
|
58
|
+
#
|
59
|
+
# @raise [ArgumentError] if step is not between 0.0 and 1.0
|
60
|
+
# @return [Array<Integer>] the interpolated RGB values
|
61
|
+
# @rbs (
|
62
|
+
# (Array[Integer] | String | Symbol) start_color,
|
63
|
+
# (Array[Integer] | String | Symbol) end_color,
|
64
|
+
# Float step
|
65
|
+
# ) -> Array[Integer]
|
66
|
+
def self.interpolate_color: (Array[Integer] | String | Symbol start_color, Array[Integer] | String | Symbol end_color, Float step) -> Array[Integer]
|
67
|
+
|
68
|
+
# Lighten an RGB color by a percentage
|
69
|
+
#
|
70
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
71
|
+
# @since 0.3.1
|
72
|
+
#
|
73
|
+
# @api private
|
74
|
+
#
|
75
|
+
# @param color [Array<Integer>, String, Symbol] the color to lighten
|
76
|
+
# @param amount [Float] amount to lighten by (0.0-1.0)
|
77
|
+
#
|
78
|
+
# @raise [ArgumentError] if amount is not between 0.0 and 1.0
|
79
|
+
# @return [Array<Integer>] the lightened RGB values
|
80
|
+
# @rbs ((Array[Integer] | String | Symbol) color, Float amount) -> Array[Integer]
|
81
|
+
def self.lighten: (Array[Integer] | String | Symbol color, Float amount) -> Array[Integer]
|
82
|
+
|
83
|
+
# Generate a rainbow gradient with a specified number of steps
|
84
|
+
#
|
85
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
86
|
+
# @since 0.3.1
|
87
|
+
#
|
88
|
+
# @api private
|
89
|
+
#
|
90
|
+
# @param steps [Integer] the number of colors to generate (minimum 2)
|
91
|
+
#
|
92
|
+
# @raise [ArgumentError] if steps is less than 2
|
93
|
+
# @return [Array<Array<Integer>>] the rainbow gradient colors as RGB values
|
94
|
+
# @rbs (Integer steps) -> Array[Array[Integer]]
|
95
|
+
def self.rainbow_gradient: (Integer steps) -> Array[Array[Integer]]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|