Class: Logrithm::Utils::Color

Inherits:
Object
  • Object
show all
Defined in:
lib/logrithm/utils/color.rb

Overview

Dealing with colors

Constant Summary collapse

HEXVAL =

Table for conversion to hex

('0'..'9').to_a.concat(('A'..'F').to_a).freeze
BRIGHTNESS_DEFAULT =

Default value for #darken, #lighten etc.

0.2
CLEAR_TERM =
"\e[0m".freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ Color

Constructor. Inits to white (#FFFFFF) by default, or accepts any params supported by #parse.



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/logrithm/utils/color.rb', line 38

def initialize(*args)
  @r = 255
  @g = 255
  @b = 255
  @a = 255

  if args.size.between?(3, 4)
    self.r = args[0]
    self.g = args[1]
    self.b = args[2]
    self.a = args[3] if args[3]
  else
    set(*args)
  end
end

Instance Attribute Details

#aObject (readonly)

Implements a color (r,g,b + a) with conversion to/from web format (eg #aabbcc), and with a number of utilities to lighten, darken and blend values.



28
29
30
# File 'lib/logrithm/utils/color.rb', line 28

def a
  @a
end

#bObject (readonly)

Implements a color (r,g,b + a) with conversion to/from web format (eg #aabbcc), and with a number of utilities to lighten, darken and blend values.



28
29
30
# File 'lib/logrithm/utils/color.rb', line 28

def b
  @b
end

#gObject (readonly)

Implements a color (r,g,b + a) with conversion to/from web format (eg #aabbcc), and with a number of utilities to lighten, darken and blend values.



28
29
30
# File 'lib/logrithm/utils/color.rb', line 28

def g
  @g
end

#rObject (readonly)

Implements a color (r,g,b + a) with conversion to/from web format (eg #aabbcc), and with a number of utilities to lighten, darken and blend values.



28
29
30
# File 'lib/logrithm/utils/color.rb', line 28

def r
  @r
end

Class Method Details

.blend(col1, col2, amt) ⇒ Object

Class-level version for explicit blends of two values, useful with constants



238
239
240
241
# File 'lib/logrithm/utils/color.rb', line 238

def self.blend(col1, col2, amt)
  col1, col2 = [col1, col2].map { |c| Color.parse c }
  col1.blend(col2, amt)
end

.parse(*args) ⇒ Object

Attempt to read in a string and parse it into values



81
82
83
84
85
86
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
# File 'lib/logrithm/utils/color.rb', line 81

def self.parse(*args)
  case args.size
  when 0 then return nil
  when 1
    case val = args.first
    when Color then val
    when Fixnum then Color.new(val, val, val) # Single value, assume grayscale
    when /\A(\d{,3};){1,3}\d{,3}\z/ # console
      # FIXME: implememnt this
      # 16 + 36 * r + 6 * g + b
      case cl = val.split(';').last.to_i
      when 0..15 then '#000000' # FIXME: make it working
      when 232..255
        Color.new(*([cl - 232] * 3).map { |c| c * 10 + 16 })
      else # FIXME: the line below fails for 231, it becomes 255
        r, gb = (cl - 16).divmod(36)
        g, b = gb.divmod(6)
        Color.new(*[r, g, b].map { |e| (51.0 * e).floor })
      end
    when String # assume rgb and try to guess
      str = val.to_s.upcase[/[0-9A-F]{3,8}/] || ''
      Color.new(*case str.length
                 when 3, 4 then str.scan(/[0-9A-F]/).map { |d| d * 2 }
                 when 6, 8 then str.scan(/[0-9A-F]{2}/)
                 else 'FF'
                 end.map { |c| Integer("0x#{c}") })
    end
  when 2 # assume gray + alpha
    val, alpha = args
    Color.new(val, val, val, alpha)
  when 3, 4 then Color.new(*args)
  end
end

.preset(type) ⇒ Object

rubocop:enable Metrics/ParameterLists



254
255
256
257
258
259
260
261
262
263
264
265
266
# File 'lib/logrithm/utils/color.rb', line 254

def self.preset(type)
  Color.parse case type
              when :label then '#999999'
              when :success then '#468847'
              when :warning then '#F89406'
              when :important then '#B94A48'
              when :fatal then '#B94A48'
              when :error then '#FF0000'
              when :info then '#3A87AD'
              when :inverse then '#333333'
              else type
              end
end

.to_xterm256(text, color, bold: true, italic: false, underline: false, reverse: false, foreground: true) ⇒ Object

rubocop:disable Metrics/ParameterLists



244
245
246
247
248
249
250
251
# File 'lib/logrithm/utils/color.rb', line 244

def self.to_xterm256(text, color, bold: true, italic: false, underline: false, reverse: false, foreground: true)
  color = Color.preset(color) unless color.is_a?(Color)
  [
    color.to_esc(true, bold: bold, italic: italic, underline: underline, reverse: reverse, foreground: foreground),
    text,
    CLEAR_TERM
  ].join
end

Instance Method Details

#==(other) ⇒ Object

Test for equality, accepts string vals as well, eg Color.new(‘aaa’) == ‘#AAAAAA’ => true



67
68
69
70
71
# File 'lib/logrithm/utils/color.rb', line 67

def ==(other)
  val = Color.parse(other)
  return false if val.nil?
  r == val.r && g == val.g && b == val.b && a == val.a
end

#blend(other, amt) ⇒ Object

Blend to a color amt % towards another color value, eg red.blend(blue, 0.5) will be purple, white.blend(black, 0.5) will be gray, etc.



220
221
222
223
224
225
226
227
228
229
# File 'lib/logrithm/utils/color.rb', line 220

def blend(other, amt)
  other = Color.parse(other)
  return Color.new(self) if amt <= 0 || other.nil?
  return Color.new(other) if amt >= 1.0
  Color.new(self).tap do |val|
    val.r += ((other.r - val.r) * amt).to_i
    val.g += ((other.g - val.g) * amt).to_i
    val.b += ((other.b - val.b) * amt).to_i
  end
end

#blend!(other, amt) ⇒ Object

In place version of #blend



232
233
234
235
# File 'lib/logrithm/utils/color.rb', line 232

def blend!(other, amt)
  set(blend(other, amt))
  self
end

#colorize(*str, concatenator: '') ⇒ Object



127
128
129
# File 'lib/logrithm/utils/color.rb', line 127

def colorize(*str, concatenator: '')
  "#{to_esc(true)}#{str.map(&:to_s).join(concatenator)}#{CLEAR_TERM}"
end

#darken(amt = BRIGHTNESS_DEFAULT) ⇒ Object

Darken a color towards full black. 0.0 is a no-op, 1.0 will return #000000



191
192
193
194
195
196
197
198
199
# File 'lib/logrithm/utils/color.rb', line 191

def darken(amt = BRIGHTNESS_DEFAULT)
  return self if amt <= 0
  return BLACK if amt >= 1.0
  Color.new(self).tap do |val|
    val.r -= (val.r * amt).to_i
    val.g -= (val.g * amt).to_i
    val.b -= (val.b * amt).to_i
  end
end

#darken!(amt = BRIGHTNESS_DEFAULT) ⇒ Object

In place version of #darken



202
203
204
# File 'lib/logrithm/utils/color.rb', line 202

def darken!(amt = BRIGHTNESS_DEFAULT)
  set(darken(amt))
end

#grayscaleObject

Convert to grayscale, using perception-based weighting



207
208
209
210
211
# File 'lib/logrithm/utils/color.rb', line 207

def grayscale
  Color.new(self).tap do |val|
    val.r = val.g = val.b = (0.2126 * val.r + 0.7152 * val.g + 0.0722 * val.b)
  end
end

#grayscale!Object

In place version of #grayscale



214
215
216
# File 'lib/logrithm/utils/color.rb', line 214

def grayscale!
  set(grayscale)
end

#grayscale?Boolean

Returns:

  • (Boolean)


170
171
172
# File 'lib/logrithm/utils/color.rb', line 170

def grayscale?
  @r == @g && @g == @b
end

#inspectObject

rubocop:enable Metrics/MethodLength rubocop:enable Metrics/CyclomaticComplexity



117
118
119
120
# File 'lib/logrithm/utils/color.rb', line 117

def inspect
  id = format('%x', object_id << 1)
  "#<#{self.class.name}:0x#{id.rjust(14, '0')} 💻=“#{to_esc(true)}███#{CLEAR_TERM}” ✎=“\\e[#{to_esc(false)}m” 🗔=“#{to_html}”>"
end

#lighten(amt = BRIGHTNESS_DEFAULT) ⇒ Object

Lighten color towards white. 0.0 is a no-op, 1.0 will return #FFFFFF



175
176
177
178
179
180
181
182
183
# File 'lib/logrithm/utils/color.rb', line 175

def lighten(amt = BRIGHTNESS_DEFAULT)
  return self if amt <= 0
  return WHITE if amt >= 1.0
  Color.new(self).tap do |val|
    val.r += ((255 - val.r) * amt).to_i
    val.g += ((255 - val.g) * amt).to_i
    val.b += ((255 - val.b) * amt).to_i
  end
end

#lighten!(amt = BRIGHTNESS_DEFAULT) ⇒ Object

In place version of #lighten



186
187
188
# File 'lib/logrithm/utils/color.rb', line 186

def lighten!(amt = BRIGHTNESS_DEFAULT)
  set(lighten(amt))
end

#opaque?Boolean

Returns:

  • (Boolean)


162
163
164
# File 'lib/logrithm/utils/color.rb', line 162

def opaque?
  @a == 255
end

#set(*args) ⇒ Object

All-purpose setter - pass in another Color, ‘#000000’, rgb vals… whatever



55
56
57
58
59
60
61
62
63
64
# File 'lib/logrithm/utils/color.rb', line 55

def set(*args)
  val = Color.parse(*args)
  unless val.nil?
    self.r = val.r
    self.g = val.g
    self.b = val.b
    self.a = val.a
  end
  self
end

#to_esc(surround = true, bold: true, italic: false, underline: false, reverse: false, foreground: true) ⇒ Object

rubocop:disable Metrics/ParameterLists Color as used in 256-color terminal escape sequences



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/logrithm/utils/color.rb', line 133

def to_esc(surround = true, bold: true, italic: false, underline: false, reverse: false, foreground: true)
  result = if grayscale?
             r < 16 ? 0 : ((r - 16) / 10).floor + 232
           else
             16 + 36 * (r / 51).floor + 6 * (g / 51).floor + (b / 51).floor
           end

  esc = [
    bold ? '01' : nil,
    italic ? '03' : nil,
    underline ? '04' : nil,
    reverse ? '07' : nil,
    foreground ? '38' : '48',
    '05',
    result
  ].compact.join(';')

  surround ? "\e[#{esc}m" : esc
end

#to_rgb(add_hash = true) ⇒ Object

rubocop:enable Metrics/ParameterLists



154
155
156
# File 'lib/logrithm/utils/color.rb', line 154

def to_rgb(add_hash = true)
  (add_hash ? '#' : '') + to_hex(r) + to_hex(g) + to_hex(b)
end

#to_rgba(add_hash = true) ⇒ Object



158
159
160
# File 'lib/logrithm/utils/color.rb', line 158

def to_rgba(add_hash = true)
  to_rgb(add_hash) + to_hex(a)
end

#to_s(as_esc = true) ⇒ Object

FIXME: what we really want here?



123
124
125
# File 'lib/logrithm/utils/color.rb', line 123

def to_s(as_esc = true)
  to_esc(as_esc)
end

#trans?Boolean

Returns:

  • (Boolean)


166
167
168
# File 'lib/logrithm/utils/color.rb', line 166

def trans?
  !opaque?
end