1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-24 05:42:03 +03:00

background: use Dimension for background size

This commit is contained in:
Wez Furlong 2022-05-31 12:36:47 -07:00
parent 040cd19f88
commit 1360e13f24
3 changed files with 77 additions and 30 deletions

View File

@ -1,4 +1,4 @@
use crate::{default_one_point_oh, Config, Dimension, HsbTransform, RgbaColor};
use crate::{default_one_point_oh, Config, Dimension, HsbTransform, PixelUnit, RgbaColor};
use luahelper::impl_lua_conversion_dynamic;
use wezterm_dynamic::{FromDynamic, FromDynamicOptions, ToDynamic, Value};
@ -119,14 +119,14 @@ impl BackgroundLayer {
repeat_y_size: None,
vertical_align: Default::default(),
horizontal_align: Default::default(),
width: BackgroundSize::Percent(100),
height: BackgroundSize::Percent(100),
width: BackgroundSize::Dimension(Dimension::Percent(1.)),
height: BackgroundSize::Dimension(Dimension::Percent(1.)),
})
}
}
/// <https://developer.mozilla.org/en-US/docs/Web/CSS/background-size>
#[derive(Debug, Copy, Clone, FromDynamic, ToDynamic)]
#[derive(Debug, Copy, Clone)]
pub enum BackgroundSize {
/// Scales image as large as possible without cropping or stretching.
/// If the container is larger than the image, tiles the image unless
@ -138,11 +138,45 @@ pub enum BackgroundSize {
/// cropped.
Cover,
/// Stretches the image to the specified length in pixels
Length(u32),
/// Stretches the image to a percentage of the background size
/// as determined by the `origin` property.
Percent(u8),
// FIXME: Dimension
Dimension(Dimension),
}
impl FromDynamic for BackgroundSize {
fn from_dynamic(
value: &Value,
options: FromDynamicOptions,
) -> Result<Self, wezterm_dynamic::Error> {
match value {
Value::String(label) => match label.as_str() {
"Contain" => return Ok(Self::Contain),
"Cover" => return Ok(Self::Cover),
_ => {}
},
_ => {}
}
match PixelUnit::from_dynamic(value, options) {
Ok(pix) => Ok(Self::Dimension(pix.into())),
Err(_) => Err(wezterm_dynamic::Error::Message(format!(
"expected either 'Contain', 'Cover', \
a number, or a string of \
the form '123px' where 'px' is a unit and \
can be one of 'px', '%', 'pt' or 'cell', \
but got {}",
value.variant_name()
))),
}
}
}
impl ToDynamic for BackgroundSize {
fn to_dynamic(&self) -> Value {
let s = match self {
Self::Cover => "Cover".to_string(),
Self::Contain => "Contain".to_string(),
Self::Dimension(d) => return d.to_dynamic(),
};
Value::String(s)
}
}
impl Default for BackgroundSize {

View File

@ -1,5 +1,6 @@
use crate::color::LinearRgba;
use crate::termwindow::RenderState;
use crate::utilsprites::RenderMetrics;
use crate::Dimensions;
use anyhow::Context;
use config::{
@ -82,7 +83,19 @@ pub struct LoadedBackgroundLayer {
fn load_background_layer(
layer: &BackgroundLayer,
dimensions: &Dimensions,
render_metrics: &RenderMetrics,
) -> anyhow::Result<LoadedBackgroundLayer> {
let h_context = DimensionContext {
dpi: dimensions.dpi as f32,
pixel_max: dimensions.pixel_width as f32,
pixel_cell: render_metrics.cell_size.width as f32,
};
let v_context = DimensionContext {
dpi: dimensions.dpi as f32,
pixel_max: dimensions.pixel_height as f32,
pixel_cell: render_metrics.cell_size.height as f32,
};
let data = match &layer.source {
BackgroundSource::Gradient(g) => {
let grad = g
@ -90,15 +103,13 @@ fn load_background_layer(
.with_context(|| format!("building gradient {:?}", g))?;
let mut width = match layer.width {
BackgroundSize::Percent(p) => (p as u32 * dimensions.pixel_width as u32) / 100,
BackgroundSize::Length(u) => u as u32,
BackgroundSize::Dimension(d) => d.evaluate_as_pixels(h_context),
unsup => anyhow::bail!("{:?} not yet implemented", unsup),
};
} as u32;
let mut height = match layer.height {
BackgroundSize::Percent(p) => (p as u32 * dimensions.pixel_height as u32) / 100,
BackgroundSize::Length(u) => u as u32,
BackgroundSize::Dimension(d) => d.evaluate_as_pixels(v_context),
unsup => anyhow::bail!("{:?} not yet implemented", unsup),
};
} as u32;
if matches!(g.orientation, GradientOrientation::Radial { .. }) {
// To simplify the math, we compute a perfect circle
@ -215,15 +226,13 @@ fn load_background_layer(
// surface.
// It's not ideal.
let width = match layer.width {
BackgroundSize::Percent(p) => (p as u32 * dimensions.pixel_width as u32) / 100,
BackgroundSize::Length(u) => u as u32,
BackgroundSize::Dimension(d) => d.evaluate_as_pixels(h_context),
unsup => anyhow::bail!("{:?} not yet implemented", unsup),
};
} as u32;
let height = match layer.height {
BackgroundSize::Percent(p) => (p as u32 * dimensions.pixel_height as u32) / 100,
BackgroundSize::Length(u) => u as u32,
BackgroundSize::Dimension(d) => d.evaluate_as_pixels(v_context),
unsup => anyhow::bail!("{:?} not yet implemented", unsup),
};
} as u32;
let size = width.min(height);
@ -252,11 +261,12 @@ fn load_background_layer(
pub fn load_background_image(
config: &ConfigHandle,
dimensions: &Dimensions,
render_metrics: &RenderMetrics,
) -> Vec<LoadedBackgroundLayer> {
let mut layers = vec![];
for layer in &config.background {
let load_start = std::time::Instant::now();
match load_background_layer(layer, dimensions) {
match load_background_layer(layer, dimensions, render_metrics) {
Ok(layer) => {
log::trace!("loaded layer in {:?}", load_start.elapsed());
layers.push(layer);
@ -273,6 +283,7 @@ pub fn reload_background_image(
config: &ConfigHandle,
existing: &[LoadedBackgroundLayer],
dimensions: &Dimensions,
render_metrics: &RenderMetrics,
) -> Vec<LoadedBackgroundLayer> {
// We want to reuse the existing version of the image where possible
// so that the textures we may have cached can be re-used and so that
@ -284,7 +295,7 @@ pub fn reload_background_image(
CachedImage::mark();
let result = load_background_image(config, dimensions)
let result = load_background_image(config, dimensions, render_metrics)
.into_iter()
.map(|mut layer| {
let hash = layer.source.hash();
@ -395,15 +406,13 @@ impl crate::TermWindow {
let width = match layer.def.width {
BackgroundSize::Contain => max_aspect_width as f32,
BackgroundSize::Cover => min_aspect_width as f32,
BackgroundSize::Length(n) => n as f32,
BackgroundSize::Percent(p) => (pixel_width * p as f32) / 100.,
BackgroundSize::Dimension(n) => n.evaluate_as_pixels(h_context),
};
let height = match layer.def.height {
BackgroundSize::Contain => max_aspect_height as f32,
BackgroundSize::Cover => min_aspect_height as f32,
BackgroundSize::Length(n) => n as f32,
BackgroundSize::Percent(p) => (pixel_height * p as f32) / 100.,
BackgroundSize::Dimension(n) => n.evaluate_as_pixels(v_context),
};
let origin_x = pixel_width / -2.;
let top_pixel = pixel_height / -2.;

View File

@ -597,7 +597,7 @@ impl TermWindow {
dpi,
};
let window_background = load_background_image(&config, &dimensions);
let window_background = load_background_image(&config, &dimensions, &render_metrics);
log::trace!(
"TermWindow::new_window called with mux_window_id {} {:?} {:?}",
@ -1332,8 +1332,12 @@ impl TermWindow {
self.config = config.clone();
self.palette.take();
self.window_background =
reload_background_image(&config, &self.window_background, &self.dimensions);
self.window_background = reload_background_image(
&config,
&self.window_background,
&self.dimensions,
&self.render_metrics,
);
let mux = Mux::get().unwrap();
let window = match mux.get_window(self.mux_window_id) {