1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-25 21:07:39 +03:00

gui: support radial gradients

This commit is contained in:
Wez Furlong 2021-08-13 17:38:33 -07:00
parent d9e0340a94
commit 615b5b3966
6 changed files with 89 additions and 6 deletions

View File

@ -31,6 +31,11 @@ impl Default for BlendMode {
pub enum GradientOrientation {
Horizontal,
Vertical,
Radial {
radius: Option<f64>,
cx: Option<f64>,
cy: Option<f64>,
},
}
impl Default for GradientOrientation {

View File

@ -327,6 +327,15 @@ return {
See [Styling Inactive Panes](#style-inactive-panes) for more information
on hue, saturation, brigthness transformations.
## Window Background Gradient
*Since: nightly builds only*
<img src="../../../screenshots/radial-gradient.png">
See [window_background_gradient](lua/config/window_background_gradient.md)
for configuration information on gradients.
## Window Background Opacity
*since: 20201031-154415-9614e117*

View File

@ -13,7 +13,8 @@ return {
window_background_gradient = {
-- Can be "Vertical" or "Horizontal". Specifies the direction
-- in which the color gradient varies. The default is "Horizontal",
-- with the gradient going from left-to-right
-- with the gradient going from left-to-right.
-- Radial gradients are also supported; see the other example below
orientation = "Vertical",
-- Specifies the set of colors that are interpolated in the gradient.
@ -56,7 +57,44 @@ return {
}
```
<img src="../../../screenshots/vertical-gradient.png">
Gradients are implemented using the `colorgrad` crate.
Take a look at <https://github.com/mazznoer/colorgrad-rs#using-web-color-format>
for some usage examples and additional information about gradients.
## Radial gradient:
Radial gradients are implemented using a notional perfect circle that is
subsequently stretched to fill the dimensions of the window.
```lua
return {
color_scheme = "Github",
window_background_gradient = {
colors = {"deeppink", "gold"},
orientation = {
Radial={
-- Specifies the x coordinate of the center of the circle,
-- in the range 0.0 through 1.0. The default is 0.5 which
-- is centered in the X dimension.
cx = 0.75,
-- Specifies the y coordinate of the center of the circle,
-- in the range 0.0 through 1.0. The default is 0.5 which
-- is centered in the Y dimension.
cy = 0.75,
-- Specifies the radius of the notional circle.
-- The default is 0.5, which combined with the default cx
-- and cy values places the circle in the center of the
-- window, with the edges touching the window edges.
-- Values larger than 1 are possible.
radius = 1.25,
}
},
}
}
```
<img src="../../../screenshots/radial-gradient.png">

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

@ -333,11 +333,20 @@ fn load_background_image(config: &ConfigHandle, dimensions: &Dimensions) -> Opti
match &config.window_background_gradient {
Some(g) => match g.build() {
Ok(grad) => {
let width = dimensions.pixel_width as u32;
let height = dimensions.pixel_height as u32;
let mut width = dimensions.pixel_width as u32;
let mut height = dimensions.pixel_height as u32;
if matches!(g.orientation, GradientOrientation::Radial { .. }) {
// To simplify the math, we compute a perfect circle
// for the radial gradient, and let the texture sampler
// perturb it to fill the window
width = width.min(height);
height = height.min(width);
}
let mut imgbuf = image::RgbaImage::new(width, height);
let fw = dimensions.pixel_width as f64;
let fh = dimensions.pixel_height as f64;
let fw = width as f64;
let fh = height as f64;
fn to_pixel(c: colorgrad::Color) -> image::Rgba<u8> {
let (r, g, b, a) = c.rgba_u8();
@ -358,7 +367,14 @@ fn load_background_image(config: &ConfigHandle, dimensions: &Dimensions) -> Opti
// visible color banding. The default 64 was selected
// because it it was the smallest value on my mac where
// the banding wasn't obvious.
let noise_amount = g.noise.unwrap_or(64);
let noise_amount = g.noise.unwrap_or_else(|| {
if matches!(g.orientation, GradientOrientation::Radial { .. }) {
16
} else {
64
}
});
fn noise(rng: &fastrand::Rng, noise_amount: usize) -> f64 {
if noise_amount == 0 {
0.
@ -390,6 +406,21 @@ fn load_background_image(config: &ConfigHandle, dimensions: &Dimensions) -> Opti
)));
}
}
GradientOrientation::Radial { radius, cx, cy } => {
let radius = fw * radius.unwrap_or(0.5);
let cx = fw * cx.unwrap_or(0.5);
let cy = fh * cy.unwrap_or(0.5);
for (x, y, pixel) in imgbuf.enumerate_pixels_mut() {
let nx = noise(&rng, noise_amount);
let ny = noise(&rng, noise_amount);
let t = (nx + (x as f64 - cx).powi(2) + (ny + y as f64 - cy).powi(2))
.sqrt()
/ radius;
*pixel = to_pixel(grad.at(t));
}
}
}
let data = imgbuf.into_vec();