Class: Unmagic::Color::Gradient::Base
- Inherits:
-
Object
- Object
- Unmagic::Color::Gradient::Base
- Defined in:
- lib/unmagic/color/gradient/base.rb
Overview
Base class for gradient implementations.
Provides shared functionality for all gradient types. Subclasses must override ‘color_class` and `validate_color_types` to specify their color space.
## Subclass Requirements
Subclasses must implement:
-
‘.color_class` - Returns the color class (RGB, HSL, or OKLCH)
-
‘#validate_color_types(stops)` - Validates all stops have correct color type
-
‘#rasterize` - Generates a Bitmap from the gradient
## Examples
# Subclasses use this base class
class RGB::Gradient::Linear < Gradient::Base
def self.color_class
Unmagic::Color::RGB
end
def validate_color_types(stops)
# Validation logic...
end
def rasterize
# Rasterization logic...
end
end
Direct Known Subclasses
HSL::Gradient::Linear, OKLCH::Gradient::Linear, RGB::Gradient::Linear
Defined Under Namespace
Classes: Error
Instance Attribute Summary collapse
-
#direction ⇒ Object
readonly
Returns the value of attribute direction.
-
#stops ⇒ Object
readonly
Returns the value of attribute stops.
Class Method Summary collapse
-
.build(colors_or_tuples, direction: nil) ⇒ Base
Build a gradient from colors or color/position tuples.
-
.color_class ⇒ Class
Get the color class for this gradient type.
Instance Method Summary collapse
-
#initialize(stops, direction: nil) ⇒ Base
constructor
Create a new gradient.
Constructor Details
#initialize(stops, direction: nil) ⇒ Base
Create a new gradient.
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 |
# File 'lib/unmagic/color/gradient/base.rb', line 200 def initialize(stops, direction: nil) raise Error, "stops must be an array" unless stops.is_a?(Array) raise Error, "must have at least 2 stops" if stops.length < 2 stops.each_with_index do |stop, i| unless stop.is_a?(Unmagic::Color::Gradient::Stop) raise Error, "stops[#{i}] must be a Stop object" end end validate_color_types(stops) stops.each_cons(2) do |a, b| if a.position > b.position raise Error, "stops must be sorted by position" end end @stops = stops @direction = direction end |
Instance Attribute Details
#direction ⇒ Object (readonly)
Returns the value of attribute direction.
38 39 40 |
# File 'lib/unmagic/color/gradient/base.rb', line 38 def direction @direction end |
#stops ⇒ Object (readonly)
Returns the value of attribute stops.
38 39 40 |
# File 'lib/unmagic/color/gradient/base.rb', line 38 def stops @stops end |
Class Method Details
.build(colors_or_tuples, direction: nil) ⇒ Base
Build a gradient from colors or color/position tuples.
Convenience factory method that converts colors to Stop objects and creates a gradient. Accepts both color objects and strings (strings are parsed using the color class’s parse method).
Works like CSS linear-gradient - you can mix positioned and non-positioned colors. Non-positioned colors auto-balance between their surrounding positioned neighbors.
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/unmagic/color/gradient/base.rb', line 87 def build(colors_or_tuples, direction: nil) # Parse colors and detect which have explicit positions parsed = colors_or_tuples.map do |item| if item.is_a?(::Array) # Explicit position tuple color_or_string, position = item color = if color_or_string.is_a?(::String) # Use universal parser for strings (handles named colors, hex, rgb(), hsl(), etc.) parsed_color = Unmagic::Color[color_or_string] # Convert to the gradient's color space if needed convert_to_color_space(parsed_color) else color_or_string end { color: color, position: position } else # No position, will auto-balance color = if item.is_a?(::String) # Use universal parser for strings parsed_color = Unmagic::Color[item] # Convert to the gradient's color space if needed convert_to_color_space(parsed_color) else item end { color: color, position: nil } end end # Auto-balance positions for items without explicit positions # Pass 1: Set first and last items if they don't have positions unless parsed.first[:position] parsed.first[:position] = 0.0 end unless parsed.last[:position] parsed.last[:position] = 1.0 end # Pass 2: Auto-balance middle items parsed.each_with_index do |item, i| next if item[:position] # Already has position # Find previous positioned stop prev_pos = nil prev_index = nil (i - 1).downto(0) do |j| if parsed[j][:position] prev_pos = parsed[j][:position] prev_index = j break end end # Find next positioned stop next_pos = nil next_index = nil ((i + 1)...parsed.length).each do |j| if parsed[j][:position] next_pos = parsed[j][:position] next_index = j break end end # Count items in this unpositioned group group_size = next_index - prev_index - 1 group_index = i - prev_index - 1 # Evenly distribute within the range item[:position] = prev_pos + (next_pos - prev_pos) * (group_index + 1) / (group_size + 1).to_f end # Create Stop objects stops = parsed.map do |item| Unmagic::Color::Gradient::Stop.new(color: item[:color], position: item[:position]) end new(stops, direction: direction) end |
.color_class ⇒ Class
Get the color class for this gradient type.
Subclasses must override this to return their color class.
47 48 49 |
# File 'lib/unmagic/color/gradient/base.rb', line 47 def color_class raise NotImplementedError, "Subclasses must define color_class" end |