Skip to content

Commit

Permalink
implement Color::mix
Browse files Browse the repository at this point in the history
  • Loading branch information
edwloef committed Feb 7, 2025
1 parent 940a079 commit 55a180d
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 18 deletions.
16 changes: 16 additions & 0 deletions core/src/color.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,22 @@ impl Color {
..self
}
}

/// Mixes the [`Color`] with another [`Color`] by the specified amount
pub fn mix(self, other: Color, amount: f32) -> Color {
let amount = amount.clamp(0.0, 1.0);
let other_amount = 1.0 - amount;

let self_linear = self.into_linear().map(|c| c * amount);
let other_linear = other.into_linear().map(|c| c * other_amount);

Color::from_linear_rgba(
self_linear[0] + other_linear[0],
self_linear[1] + other_linear[1],
self_linear[2] + other_linear[2],
self_linear[3] + other_linear[3],
)
}
}

impl From<[f32; 3]> for Color {
Expand Down
28 changes: 10 additions & 18 deletions core/src/theme/palette.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{color, Color};

use palette::color_difference::Wcag21RelativeContrast;
use palette::rgb::Rgb;
use palette::{FromColor, Hsl, Mix};
use palette::{FromColor, Hsl};

use std::sync::LazyLock;

Expand Down Expand Up @@ -462,8 +462,8 @@ pub struct Background {
impl Background {
/// Generates a set of [`Background`] colors from the base and text colors.
pub fn new(base: Color, text: Color) -> Self {
let weak = mix(base, text, 0.15);
let strong = mix(base, text, 0.40);
let weak = base.mix(text, 0.15);
let strong = base.mix(text, 0.40);

Self {
base: Pair::new(base, text),
Expand All @@ -487,7 +487,7 @@ pub struct Primary {
impl Primary {
/// Generates a set of [`Primary`] colors from the base, background, and text colors.
pub fn generate(base: Color, background: Color, text: Color) -> Self {
let weak = mix(base, background, 0.4);
let weak = base.mix(background, 0.4);
let strong = deviate(base, 0.1);

Self {
Expand All @@ -512,9 +512,9 @@ pub struct Secondary {
impl Secondary {
/// Generates a set of [`Secondary`] colors from the base and text colors.
pub fn generate(base: Color, text: Color) -> Self {
let base = mix(base, text, 0.2);
let weak = mix(base, text, 0.1);
let strong = mix(base, text, 0.3);
let base = base.mix(text, 0.2);
let weak = base.mix(text, 0.1);
let strong = base.mix(text, 0.3);

Self {
base: Pair::new(base, text),
Expand All @@ -538,7 +538,7 @@ pub struct Success {
impl Success {
/// Generates a set of [`Success`] colors from the base, background, and text colors.
pub fn generate(base: Color, background: Color, text: Color) -> Self {
let weak = mix(base, background, 0.4);
let weak = base.mix(background, 0.4);
let strong = deviate(base, 0.1);

Self {
Expand All @@ -563,7 +563,7 @@ pub struct Warning {
impl Warning {
/// Generates a set of [`Warning`] colors from the base, background, and text colors.
pub fn generate(base: Color, background: Color, text: Color) -> Self {
let weak = mix(base, background, 0.4);
let weak = base.mix(background, 0.4);
let strong = deviate(base, 0.1);

Self {
Expand All @@ -588,7 +588,7 @@ pub struct Danger {
impl Danger {
/// Generates a set of [`Danger`] colors from the base, background, and text colors.
pub fn generate(base: Color, background: Color, text: Color) -> Self {
let weak = mix(base, background, 0.4);
let weak = base.mix(background, 0.4);
let strong = deviate(base, 0.1);

Self {
Expand Down Expand Up @@ -631,14 +631,6 @@ fn deviate(color: Color, amount: f32) -> Color {
}
}

fn mix(a: Color, b: Color, factor: f32) -> Color {
let a_lin = Rgb::from(a).into_linear();
let b_lin = Rgb::from(b).into_linear();

let mixed = a_lin.mix(b_lin, factor);
Rgb::from_linear(mixed).into()
}

fn readable(background: Color, text: Color) -> Color {
if is_readable(background, text) {
text
Expand Down

0 comments on commit 55a180d

Please sign in to comment.