module Sass::Script::Functions

def mix(color1, color2, weight = Number.new(50))

Raises:
  • (ArgumentError) - if `color1` or `color2` aren't colors,

Returns:
  • (Color) -

Parameters:
  • weight (Number) -- between 0% and 100%
  • color2 (Color) --
  • color1 (Color) --

Overloads:
  • mix(color1, color2, weight = 50%)
def mix(color1, color2, weight = Number.new(50))
  assert_type color1, :Color
  assert_type color2, :Color
  assert_type weight, :Number
  unless (0..100).include?(weight.value)
    raise ArgumentError.new("Weight #{weight} must be between 0% and 100%")
  end
  # This algorithm factors in both the user-provided weight
  # and the difference between the alpha values of the two colors
  # to decide how to perform the weighted average of the two RGB values.
  #
  # It works by first normalizing both parameters to be within [-1, 1],
  # where 1 indicates "only use color1", -1 indicates "only use color 0",
  # and all values in between indicated a proportionately weighted average.
  #
  # Once we have the normalized variables w and a,
  # we apply the formula (w + a)/(1 + w*a)
  # to get the combined weight (in [-1, 1]) of color1.
  # This formula has two especially nice properties:
  #
  #   * When either w or a are -1 or 1, the combined weight is also that number
  #     (cases where w * a == -1 are undefined, and handled as a special case).
  #
  #   * When a is 0, the combined weight is w, and vice versa
  #
  # Finally, the weight of color1 is renormalized to be within [0, 1]
  # and the weight of color2 is given by 1 minus the weight of color1.
  p = weight.value/100.0
  w = p*2 - 1
  a = color1.alpha - color2.alpha
  w1 = (((w * a == -1) ? w : (w + a)/(1 + w*a)) + 1)/2.0
  w2 = 1 - w1
  rgb = color1.rgb.zip(color2.rgb).map {|v1, v2| v1*w1 + v2*w2}
  alpha = color1.alpha*p + color2.alpha*(1-p)
  Color.new(rgb + [alpha])
end