module Say::XTerm256Colors

Constants

X256_BG_MASK
X256_COLOR_TABLE

XTERM 256 COLOR CONSTANTS ########################

X256_FG_MASK
X256_RX_RGB_HEX_3
X256_RX_RGB_HEX_6

Public Class Methods

xterm256_bg(color) click to toggle source
# File lib/say.rb, line 75
def xterm256_bg(color)
  sprintf(X256_BG_MASK, xterm256_color_index(color))
end
xterm256_color_index(color) click to toggle source
# File lib/say.rb, line 65
def xterm256_color_index(color)
  xterm_256_cache.fetch(color) do
    xterm_256_cache[color] = compute_xterm256_color_index(color)
  end
end
xterm256_fg(color) click to toggle source
# File lib/say.rb, line 71
def xterm256_fg(color)
  sprintf(X256_FG_MASK, xterm256_color_index(color))
end

Private Class Methods

compute_xterm256_color_index(color) click to toggle source
# File lib/say.rb, line 89
def compute_xterm256_color_index(color)
  color_integer = normalize_rgb_integer(color)
  target_rgb    = integer_to_rgb(color_integer)

  best_distance = 0XFFFFFF
  best_index    = -1

  xterm_256_rgb_vectors.each_with_index do |rgb, index|
    metric = rgb_vector_distance_squared(target_rgb, rgb)
    if metric < best_distance
      best_distance = metric
      best_index    = index
    end
  end

  return best_index + 16
end
integer_to_rgb(integer) click to toggle source
# File lib/say.rb, line 137
def integer_to_rgb(integer)
  [
    (integer >> 16) & 0xFF,
    (integer >> 8) & 0xFF,
    integer & 0xFF
  ].freeze
end
normalize_rgb_integer(value) click to toggle source
# File lib/say.rb, line 107
def normalize_rgb_integer(value)
  integer_value =
    case value
    when Array   then rgb_to_integer(*value)
    when String  then parse_rgb_string(value)
    else value.to_i
    end

  integer_value & 0xFFFFFF
end
parse_rgb_string(string) click to toggle source
# File lib/say.rb, line 118
def parse_rgb_string(string)
  if string =~ X256_RX_RGB_HEX_3
    string = "#{ $1 }#{ $1 }#{ $2 }#{ $2 }#{ $3 }#{ $3 }"
  end

  value =
    if string =~ X256_RX_RGB_HEX_6
      rgb_to_integer($1.to_i(16), $2.to_i(16), $3.to_i(16))
    else
      fail ArgumentError, "Invalid RGB color string value: #{ string.inspect }"
    end

  return value
end
rgb_to_integer(r = 0, g = 0, b = 0) click to toggle source
# File lib/say.rb, line 133
def rgb_to_integer(r = 0, g = 0, b = 0)
  ((r.to_i & 0xFF) << 16) | ((g.to_i & 0xFF) << 8) | (b.to_i & 0xFF)
end
rgb_vector_distance_squared(rgb_1, rgb_2) click to toggle source
# File lib/say.rb, line 145
def rgb_vector_distance_squared(rgb_1, rgb_2)
  r1, g1, b1 = rgb_1
  r2, g2, b2 = rgb_2

  return (
    (r1 - r2) ** 2 +
    (b1 - b2) ** 2 +
    (g1 - g2) ** 2
  )
end
xterm_256_cache() click to toggle source
# File lib/say.rb, line 81
def xterm_256_cache
  @xterm_256_cache ||= {}
end
xterm_256_rgb_vectors() click to toggle source
# File lib/say.rb, line 85
def xterm_256_rgb_vectors
  @xterm_256_rgb_vectors ||= X256_COLOR_TABLE.map { |int| integer_to_rgb(int) }.freeze
end