diff --git a/crates/gpui/examples/painting.rs b/crates/gpui/examples/painting.rs index 11c3b33371..41cbcb2802 100644 --- a/crates/gpui/examples/painting.rs +++ b/crates/gpui/examples/painting.rs @@ -67,8 +67,7 @@ impl PaintingViewer { builder.line_to(point(px(50.), px(130.))); builder.close(); let path = builder.build().unwrap(); - let mut red = rgb(0xFF0000); - red.a = 0.5; + let red = rgb(0xFF0000).alpha(0.5); lines.push((path, red.into())); // 50% opaque blue path that extends across black quad. @@ -79,8 +78,7 @@ impl PaintingViewer { builder.line_to(point(px(150.), px(130.))); builder.close(); let path = builder.build().unwrap(); - let mut blue = rgb(0x0000FF); - blue.a = 0.5; + let blue = rgb(0x0000FF).alpha(0.5); lines.push((path, blue.into())); // 50% opaque green path that extends across black quad. @@ -91,8 +89,7 @@ impl PaintingViewer { builder.line_to(point(px(250.), px(130.))); builder.close(); let path = builder.build().unwrap(); - let mut green = rgb(0x00FF00); - green.a = 0.5; + let green = rgb(0x00FF00).alpha(0.5); lines.push((path, green.into())); // 50% opaque black path that extends across black quad. @@ -103,8 +100,7 @@ impl PaintingViewer { builder.line_to(point(px(350.), px(130.))); builder.close(); let path = builder.build().unwrap(); - let mut black = rgb(0x000000); - black.a = 0.5; + let black = rgb(0x000000).alpha(0.5); lines.push((path, black.into())); // Two 50% opaque red circles overlapping - center should be darker red @@ -128,8 +124,7 @@ impl PaintingViewer { ); builder.close(); let path = builder.build().unwrap(); - let mut red1 = rgb(0xFF0000); - red1.a = 0.5; + let red1 = rgb(0xFF0000).alpha(0.5); lines.push((path, red1.into())); let mut builder = PathBuilder::fill(); @@ -152,8 +147,7 @@ impl PaintingViewer { ); builder.close(); let path = builder.build().unwrap(); - let mut red2 = rgb(0xFF0000); - red2.a = 0.5; + let red2 = rgb(0xFF0000).alpha(0.5); lines.push((path, red2.into())); // draw a Rust logo diff --git a/crates/gpui/src/color.rs b/crates/gpui/src/color.rs index be8169e81d..8ec816f49d 100644 --- a/crates/gpui/src/color.rs +++ b/crates/gpui/src/color.rs @@ -69,6 +69,68 @@ impl Rgba { } } } + + /// Returns a new RGBA color with the same red, green and blue channels, but + /// with a new alpha value. + /// + /// Example: + /// ``` + /// use gpui::rgba; + /// let color = rgba(0xFF0000FF); + /// let faded = color.alpha(0.25); + /// assert_eq!(faded.a, 0.25); + /// ``` + /// + /// This will return a red color with 25% opacity. + /// + /// Example: + /// ``` + /// use gpui::rgba; + /// let color = rgba(0x3399FFCC); + /// let transparent = color.alpha(0.0); + /// assert_eq!(transparent.a, 0.0); + /// ``` + /// + /// This will return the same blue color, fully transparent. + pub fn alpha(&self, a: f32) -> Self { + Rgba { + r: self.r, + g: self.g, + b: self.b, + a: a.clamp(0., 1.), + } + } + + /// Returns a new RGBA color with the same red, green, and blue channels, + /// but with the alpha channel multiplied by the given factor. + /// + /// Example: + /// ``` + /// use gpui::rgba; + /// let color = rgba(0xFF0000FF); // Fully opaque red + /// let faded = color.opacity(0.5); + /// assert_eq!(faded.a, 0.5); + /// ``` + /// + /// This will return a red color with 50% opacity. + /// + /// Example: + /// ``` + /// use gpui::rgba; + /// let color = rgba(0x3399FFCC); // A light blue with 80% opacity + /// let faded = color.opacity(0.5); + /// assert!((faded.a - 0.4).abs() < 1e-6); + /// ``` + /// + /// This will return the same blue color scaled down to 40% opacity. + pub fn opacity(&self, factor: f32) -> Self { + Rgba { + r: self.r, + g: self.g, + b: self.b, + a: self.a * factor.clamp(0., 1.), + } + } } impl From for u32 { @@ -591,7 +653,7 @@ impl Hsla { /// assert_eq!(red_color.a, 0.25); /// ``` /// - /// This will return a red color with half the opacity. + /// This will return a red color with 25% opacity. /// /// Example: /// ``` @@ -979,4 +1041,29 @@ mod tests { assert!(!background.is_transparent()); assert!(background.opacity(0.0).is_transparent()); } + + #[test] + fn test_rgba_alpha() { + let color = Rgba { + r: 0.2, + g: 0.6, + b: 1.0, + a: 0.8, + }; + + assert_eq!(color.alpha(0.25).a, 0.25); + assert_eq!(color.alpha(1.5).a, 1.0); + } + + #[test] + fn test_rgba_opacity() { + let color = Rgba { + r: 0.2, + g: 0.6, + b: 1.0, + a: 0.8, + }; + assert!((color.opacity(0.5).a - 0.4).abs() < 1e-6); + assert_eq!(color.opacity(2.0).a, 0.8); + } }