diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d5988be95..9a9e08a9f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -71,7 +71,7 @@ jobs: toolchain: [stable] include: - os: ubuntu-latest - toolchain: "1.75.0" + toolchain: "1.79.0" - os: ubuntu-latest toolchain: beta diff --git a/Cargo.toml b/Cargo.toml index 6282a47e3..608da5a38 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ keywords = ["gui"] categories = ["gui"] repository = "https://github.com/kas-gui/kas" exclude = ["/examples"] -rust-version = "1.75.0" +rust-version = "1.79.0" [package.metadata.docs.rs] features = ["stable"] diff --git a/README.md b/README.md index 8c607fe45..e7c9328ec 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ KAS GUI [![Crates.io](https://img.shields.io/crates/v/kas.svg)](https://crates.io/crates/kas) [![kas-text](https://img.shields.io/badge/GitHub-kas--text-blueviolet)](https://github.com/kas-gui/kas-text/) [![Docs](https://docs.rs/kas/badge.svg)](https://docs.rs/kas) -![Minimum rustc version](https://img.shields.io/badge/rustc-1.75+-lightgray.svg) +![Minimum rustc version](https://img.shields.io/badge/rustc-1.79+-lightgray.svg) KAS is a stateful, pure-Rust GUI toolkit supporting: diff --git a/crates/kas-core/Cargo.toml b/crates/kas-core/Cargo.toml index 34e19c5e2..b1b93f18b 100644 --- a/crates/kas-core/Cargo.toml +++ b/crates/kas-core/Cargo.toml @@ -130,7 +130,7 @@ version = "0.5.0" # used in doc links [dependencies.winit] # Provides translations for several winit types -version = "0.30.0" +version = "0.30.1" optional = true default-features = false features = ["rwh_06"] diff --git a/crates/kas-core/src/app/app.rs b/crates/kas-core/src/app/app.rs index 532a4b7f2..e60bf4d42 100644 --- a/crates/kas-core/src/app/app.rs +++ b/crates/kas-core/src/app/app.rs @@ -237,8 +237,8 @@ impl<'a> PlatformWrapper<'a> { { cfg_if::cfg_if! { if #[cfg(all(feature = "wayland", feature = "x11"))] { - use winit::platform::wayland::ActiveEventLoopExtWayland; - return if true /*FIXME: self.0.is_wayland()*/ { + use winit::platform::wayland::EventLoopExtWayland; + return if self.0.is_wayland() { Platform::Wayland } else { Platform::X11 diff --git a/crates/kas-core/src/draw/color.rs b/crates/kas-core/src/draw/color.rs index 8a919bf85..d577940a8 100644 --- a/crates/kas-core/src/draw/color.rs +++ b/crates/kas-core/src/draw/color.rs @@ -266,7 +266,8 @@ impl Rgba8Srgb { } /// Compile-time parser for sRGB and sRGBA colours - pub const fn try_parse_srgb(s: &[u8]) -> Result { + pub const fn try_parse(s: &str) -> Result { + let s = s.as_bytes(); if s.len() != 6 && s.len() != 8 { return Err(ParseError::Length); } @@ -303,11 +304,11 @@ impl Rgba8Srgb { /// Compile-time parser for sRGB and sRGBA colours /// - /// This method has worse diagnostics on error due to limited const- - pub const fn parse_srgb(s: &[u8]) -> Rgba8Srgb { - match Self::try_parse_srgb(s) { + /// This method has worse diagnostics on error due to limited error handling in `const fn`. + pub const fn parse(s: &str) -> Rgba8Srgb { + match Self::try_parse(s) { Ok(result) => result, - Err(ParseError::Length) => panic!("invalid length (expected 6 or 8 bytes"), + Err(ParseError::Length) => panic!("invalid length (expected 6 or 8 bytes)"), Err(ParseError::InvalidHex) => panic!("invalid hex byte (expected 0-9, a-f or A-F)"), } } @@ -345,12 +346,13 @@ pub enum ParseError { impl std::str::FromStr for Rgba8Srgb { type Err = ParseError; - fn from_str(s: &str) -> Result { - let mut s = s.as_bytes(); - if s[0] == b'#' { - s = &s[1..]; + fn from_str(mut s: &str) -> Result { + if s.starts_with("#") { + let a; + (a, s) = s.split_at(1); + debug_assert_eq!(a, "#"); } - Rgba8Srgb::try_parse_srgb(&s) + Rgba8Srgb::try_parse(s) } } diff --git a/crates/kas-core/src/theme/colors.rs b/crates/kas-core/src/theme/colors.rs index 067ae6ac2..5de90c334 100644 --- a/crates/kas-core/src/theme/colors.rs +++ b/crates/kas-core/src/theme/colors.rs @@ -226,52 +226,52 @@ impl ColorsSrgb { /// Default "light" scheme pub const LIGHT: ColorsSrgb = Colors { is_dark: false, - background: Rgba8Srgb::parse_srgb(b"FAFAFA"), - frame: Rgba8Srgb::parse_srgb(b"BCBCBC"), - accent: Rgba8Srgb::parse_srgb(b"8347f2"), - accent_soft: Rgba8Srgb::parse_srgb(b"B38DF9"), - nav_focus: Rgba8Srgb::parse_srgb(b"7E3FF2"), - edit_bg: Rgba8Srgb::parse_srgb(b"FAFAFA"), - edit_bg_disabled: Rgba8Srgb::parse_srgb(b"DCDCDC"), - edit_bg_error: Rgba8Srgb::parse_srgb(b"FFBCBC"), - text: Rgba8Srgb::parse_srgb(b"000000"), - text_invert: Rgba8Srgb::parse_srgb(b"FFFFFF"), - text_disabled: Rgba8Srgb::parse_srgb(b"AAAAAA"), - text_sel_bg: Rgba8Srgb::parse_srgb(b"A172FA"), + background: Rgba8Srgb::parse("FAFAFA"), + frame: Rgba8Srgb::parse("BCBCBC"), + accent: Rgba8Srgb::parse("8347f2"), + accent_soft: Rgba8Srgb::parse("B38DF9"), + nav_focus: Rgba8Srgb::parse("7E3FF2"), + edit_bg: Rgba8Srgb::parse("FAFAFA"), + edit_bg_disabled: Rgba8Srgb::parse("DCDCDC"), + edit_bg_error: Rgba8Srgb::parse("FFBCBC"), + text: Rgba8Srgb::parse("000000"), + text_invert: Rgba8Srgb::parse("FFFFFF"), + text_disabled: Rgba8Srgb::parse("AAAAAA"), + text_sel_bg: Rgba8Srgb::parse("A172FA"), }; /// Dark scheme pub const DARK: ColorsSrgb = Colors { is_dark: true, - background: Rgba8Srgb::parse_srgb(b"404040"), - frame: Rgba8Srgb::parse_srgb(b"AAAAAA"), - accent: Rgba8Srgb::parse_srgb(b"F74C00"), - accent_soft: Rgba8Srgb::parse_srgb(b"E77346"), - nav_focus: Rgba8Srgb::parse_srgb(b"D03E00"), - edit_bg: Rgba8Srgb::parse_srgb(b"303030"), - edit_bg_disabled: Rgba8Srgb::parse_srgb(b"606060"), - edit_bg_error: Rgba8Srgb::parse_srgb(b"a06868"), - text: Rgba8Srgb::parse_srgb(b"FFFFFF"), - text_invert: Rgba8Srgb::parse_srgb(b"000000"), - text_disabled: Rgba8Srgb::parse_srgb(b"CBCBCB"), - text_sel_bg: Rgba8Srgb::parse_srgb(b"E77346"), + background: Rgba8Srgb::parse("404040"), + frame: Rgba8Srgb::parse("AAAAAA"), + accent: Rgba8Srgb::parse("F74C00"), + accent_soft: Rgba8Srgb::parse("E77346"), + nav_focus: Rgba8Srgb::parse("D03E00"), + edit_bg: Rgba8Srgb::parse("303030"), + edit_bg_disabled: Rgba8Srgb::parse("606060"), + edit_bg_error: Rgba8Srgb::parse("a06868"), + text: Rgba8Srgb::parse("FFFFFF"), + text_invert: Rgba8Srgb::parse("000000"), + text_disabled: Rgba8Srgb::parse("CBCBCB"), + text_sel_bg: Rgba8Srgb::parse("E77346"), }; /// Blue scheme pub const BLUE: ColorsSrgb = Colors { is_dark: false, - background: Rgba8Srgb::parse_srgb(b"FFFFFF"), - frame: Rgba8Srgb::parse_srgb(b"DADADA"), - accent: Rgba8Srgb::parse_srgb(b"3fafd7"), - accent_soft: Rgba8Srgb::parse_srgb(b"7CDAFF"), - nav_focus: Rgba8Srgb::parse_srgb(b"3B697A"), - edit_bg: Rgba8Srgb::parse_srgb(b"FFFFFF"), - edit_bg_disabled: Rgba8Srgb::parse_srgb(b"DCDCDC"), - edit_bg_error: Rgba8Srgb::parse_srgb(b"FFBCBC"), - text: Rgba8Srgb::parse_srgb(b"000000"), - text_invert: Rgba8Srgb::parse_srgb(b"FFFFFF"), - text_disabled: Rgba8Srgb::parse_srgb(b"AAAAAA"), - text_sel_bg: Rgba8Srgb::parse_srgb(b"6CC0E1"), + background: Rgba8Srgb::parse("FFFFFF"), + frame: Rgba8Srgb::parse("DADADA"), + accent: Rgba8Srgb::parse("3fafd7"), + accent_soft: Rgba8Srgb::parse("7CDAFF"), + nav_focus: Rgba8Srgb::parse("3B697A"), + edit_bg: Rgba8Srgb::parse("FFFFFF"), + edit_bg_disabled: Rgba8Srgb::parse("DCDCDC"), + edit_bg_error: Rgba8Srgb::parse("FFBCBC"), + text: Rgba8Srgb::parse("000000"), + text_invert: Rgba8Srgb::parse("FFFFFF"), + text_disabled: Rgba8Srgb::parse("AAAAAA"), + text_sel_bg: Rgba8Srgb::parse("6CC0E1"), }; } diff --git a/crates/kas-core/src/util.rs b/crates/kas-core/src/util.rs index f5c330390..3f43d3560 100644 --- a/crates/kas-core/src/util.rs +++ b/crates/kas-core/src/util.rs @@ -130,7 +130,7 @@ pub fn load_icon_from_path>( ) -> Result> { // TODO(opt): image loading could be de-duplicated with // DrawShared::image_from_path, but this may not be worthwhile. - let im = image::io::Reader::open(path)? + let im = image::ImageReader::open(path)? .with_guessed_format()? .decode()? .into_rgba8(); diff --git a/crates/kas-resvg/Cargo.toml b/crates/kas-resvg/Cargo.toml index f0a5aa95a..73fa39114 100644 --- a/crates/kas-resvg/Cargo.toml +++ b/crates/kas-resvg/Cargo.toml @@ -26,8 +26,8 @@ svg = ["dep:resvg", "dep:usvg"] [dependencies] tiny-skia = { version = "0.11.0" } -resvg = { version = "0.41.0", optional = true } -usvg = { version = "0.41.0", optional = true } +resvg = { version = "0.43.0", optional = true } +usvg = { version = "0.43.0", optional = true } once_cell = "1.17.0" thiserror = "1.0.23" diff --git a/crates/kas-resvg/src/svg.rs b/crates/kas-resvg/src/svg.rs index edc86b3ea..c36b95a77 100644 --- a/crates/kas-resvg/src/svg.rs +++ b/crates/kas-resvg/src/svg.rs @@ -36,6 +36,7 @@ fn load(data: &[u8], resources_dir: Option<&Path>) -> Result // - default_size: affected by screen scale factor later // - dpi: according to css-values-3, 1in = 96px // - font_size: units are (logical) px per em; 16px = 12pt + // - TODO: add option to clone fontdb from kas::text? let opts = usvg::Options { resources_dir: resources_dir.map(|path| path.to_owned()), dpi: 96.0, @@ -47,10 +48,11 @@ fn load(data: &[u8], resources_dir: Option<&Path>) -> Result image_rendering: usvg::ImageRendering::default(), default_size: usvg::Size::from_wh(100.0, 100.0).unwrap(), image_href_resolver: Default::default(), + font_resolver: Default::default(), + fontdb: Default::default(), }; - let fonts_db = kas::text::fonts::library().read_db(); - let tree = Tree::from_data(data, &opts, fonts_db.db())?; + let tree = Tree::from_data(data, &opts)?; Ok(tree) } diff --git a/crates/kas-wgpu/Cargo.toml b/crates/kas-wgpu/Cargo.toml index 052b6993c..4839afbee 100644 --- a/crates/kas-wgpu/Cargo.toml +++ b/crates/kas-wgpu/Cargo.toml @@ -35,7 +35,7 @@ futures-lite = "2.0" log = "0.4" thiserror = "1.0.23" guillotiere = "0.6.0" -rustc-hash = "1.0" +rustc-hash = "2.0" [dependencies.kas] # Rename package purely for convenience: @@ -47,7 +47,7 @@ path = "../kas-core" version = "0.6.0" [dependencies.wgpu] -version = "0.20.0" +version = "22.1.0" default-features = false features = ["spirv"] diff --git a/crates/kas-wgpu/src/draw/atlases.rs b/crates/kas-wgpu/src/draw/atlases.rs index dfba48b58..4f5cf10ad 100644 --- a/crates/kas-wgpu/src/draw/atlases.rs +++ b/crates/kas-wgpu/src/draw/atlases.rs @@ -149,6 +149,7 @@ impl Pipeline { multisample: Default::default(), fragment: Some(fragment), multiview: None, + cache: None, }); let sampler = device.create_sampler(&wgpu::SamplerDescriptor { diff --git a/crates/kas-wgpu/src/draw/flat_round.rs b/crates/kas-wgpu/src/draw/flat_round.rs index 16f9c511d..8b80745f8 100644 --- a/crates/kas-wgpu/src/draw/flat_round.rs +++ b/crates/kas-wgpu/src/draw/flat_round.rs @@ -103,6 +103,7 @@ impl Pipeline { })], }), multiview: None, + cache: None, }); Pipeline { render_pipeline } diff --git a/crates/kas-wgpu/src/draw/round_2col.rs b/crates/kas-wgpu/src/draw/round_2col.rs index f9d5a38ea..54d33851a 100644 --- a/crates/kas-wgpu/src/draw/round_2col.rs +++ b/crates/kas-wgpu/src/draw/round_2col.rs @@ -91,6 +91,7 @@ impl Pipeline { })], }), multiview: None, + cache: None, }); Pipeline { render_pipeline } diff --git a/crates/kas-wgpu/src/draw/shaded_round.rs b/crates/kas-wgpu/src/draw/shaded_round.rs index b76776b1b..1ebcc5f35 100644 --- a/crates/kas-wgpu/src/draw/shaded_round.rs +++ b/crates/kas-wgpu/src/draw/shaded_round.rs @@ -98,6 +98,7 @@ impl Pipeline { })], }), multiview: None, + cache: None, }); Pipeline { render_pipeline } diff --git a/crates/kas-wgpu/src/draw/shaded_square.rs b/crates/kas-wgpu/src/draw/shaded_square.rs index a9bac5c33..1cbd9795a 100644 --- a/crates/kas-wgpu/src/draw/shaded_square.rs +++ b/crates/kas-wgpu/src/draw/shaded_square.rs @@ -83,6 +83,7 @@ impl Pipeline { })], }), multiview: None, + cache: None, }); Pipeline { render_pipeline } diff --git a/crates/kas-widgets/src/image.rs b/crates/kas-widgets/src/image.rs index 6fa580726..5f0e9200b 100644 --- a/crates/kas-widgets/src/image.rs +++ b/crates/kas-widgets/src/image.rs @@ -90,7 +90,7 @@ impl_scope! { path: P, draw: &mut dyn DrawShared, ) -> Result { - let image = image::io::Reader::open(path)? + let image = image::ImageReader::open(path)? .with_guessed_format()? .decode()?; diff --git a/examples/clock.rs b/examples/clock.rs index b8b96a605..e168ca82a 100644 --- a/examples/clock.rs +++ b/examples/clock.rs @@ -69,7 +69,7 @@ impl_scope! { } fn draw(&mut self, mut draw: DrawCx) { - let accent: Rgba = Rgba8Srgb::parse_srgb(b"d7916f").into(); + let accent: Rgba = Rgba8Srgb::parse("d7916f").into(); let col_back = Rgba::ga(0.0, 0.5); let col_face = accent.multiply(0.4); let col_time = Rgba::grey(1.0); diff --git a/examples/gallery.rs b/examples/gallery.rs index e1ecdb3b3..9611a0183 100644 --- a/examples/gallery.rs +++ b/examples/gallery.rs @@ -152,8 +152,7 @@ fn widgets() -> Box> { row!["ScrollLabel", ScrollLabel::new(text).map_any()], row![ "EditBox", - EditBox::string(|data: &Data| data.text.clone()) - .with_msg(|s| Item::Text(s.to_string())), + EditBox::new(Guard).with_text("length must not be a multiple of 8!"), ], row![ "Button (text)", diff --git a/examples/mandlebrot/mandlebrot.rs b/examples/mandlebrot/mandlebrot.rs index eb6eee34c..e1110bc13 100644 --- a/examples/mandlebrot/mandlebrot.rs +++ b/examples/mandlebrot/mandlebrot.rs @@ -107,6 +107,7 @@ impl CustomPipeBuilder for PipeBuilder { max_push_constant_size: size_of::().cast(), ..Default::default() }, + ..Default::default() } } @@ -162,6 +163,7 @@ impl CustomPipeBuilder for PipeBuilder { })], }), multiview: None, + cache: None, }); Pipe { render_pipeline }