diff options
author | 2024-04-16 00:08:17 +0900 | |
---|---|---|
committer | 2024-04-16 00:08:17 +0900 | |
commit | 0ebe0629cef37aee5c48b9409fc36618a3a3e60d (patch) | |
tree | 909d9ecf28e7c491bae3afc81928c118517fa7a9 /core | |
parent | 13bd106fc585034a7aba17b9c17589113274aaf5 (diff) | |
parent | 105b8bd5ad6ade1f203a0d8b0b93bd06f61f621a (diff) | |
download | iced-0ebe0629cef37aee5c48b9409fc36618a3a3e60d.tar.gz iced-0ebe0629cef37aee5c48b9409fc36618a3a3e60d.tar.bz2 iced-0ebe0629cef37aee5c48b9409fc36618a3a3e60d.zip |
Merge branch 'iced-rs:master' into viewer_content_fit
Diffstat (limited to '')
-rw-r--r-- | core/Cargo.toml | 5 | ||||
-rw-r--r-- | core/src/hasher.rs | 2 | ||||
-rw-r--r-- | core/src/image.rs | 5 | ||||
-rw-r--r-- | core/src/lib.rs | 9 | ||||
-rw-r--r-- | core/src/rectangle.rs | 47 | ||||
-rw-r--r-- | core/src/renderer.rs | 16 | ||||
-rw-r--r-- | core/src/renderer/null.rs | 18 | ||||
-rw-r--r-- | core/src/size.rs | 14 | ||||
-rw-r--r-- | core/src/svg.rs | 5 | ||||
-rw-r--r-- | core/src/text.rs | 10 | ||||
-rw-r--r-- | core/src/text/paragraph.rs | 6 | ||||
-rw-r--r-- | core/src/theme/palette.rs | 18 | ||||
-rw-r--r-- | core/src/transformation.rs | 6 | ||||
-rw-r--r-- | core/src/widget/text.rs | 86 |
14 files changed, 180 insertions, 67 deletions
diff --git a/core/Cargo.toml b/core/Cargo.toml index 32d233ee..7bd37021 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -10,6 +10,9 @@ homepage.workspace = true categories.workspace = true keywords.workspace = true +[lints] +workspace = true + [features] auto-detect-theme = ["dep:dark-light"] advanced = [] @@ -21,10 +24,10 @@ log.workspace = true num-traits.workspace = true once_cell.workspace = true palette.workspace = true +rustc-hash.workspace = true smol_str.workspace = true thiserror.workspace = true web-time.workspace = true -xxhash-rust.workspace = true dark-light.workspace = true dark-light.optional = true diff --git a/core/src/hasher.rs b/core/src/hasher.rs index a13d78af..13180e41 100644 --- a/core/src/hasher.rs +++ b/core/src/hasher.rs @@ -1,7 +1,7 @@ /// The hasher used to compare layouts. #[allow(missing_debug_implementations)] // Doesn't really make sense to have debug on the hasher state anyways. #[derive(Default)] -pub struct Hasher(xxhash_rust::xxh3::Xxh3); +pub struct Hasher(rustc_hash::FxHasher); impl core::hash::Hasher for Hasher { fn write(&mut self, bytes: &[u8]) { diff --git a/core/src/image.rs b/core/src/image.rs index 32b95f03..dc74e5c1 100644 --- a/core/src/image.rs +++ b/core/src/image.rs @@ -1,6 +1,7 @@ //! Load and draw raster graphics. -use crate::{Hasher, Rectangle, Size}; +use crate::{Rectangle, Size}; +use rustc_hash::FxHasher; use std::hash::{Hash, Hasher as _}; use std::path::PathBuf; use std::sync::Arc; @@ -50,7 +51,7 @@ impl Handle { } fn from_data(data: Data) -> Handle { - let mut hasher = Hasher::default(); + let mut hasher = FxHasher::default(); data.hash(&mut hasher); Handle { diff --git a/core/src/lib.rs b/core/src/lib.rs index d076413e..feda4fb4 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -9,13 +9,6 @@ #![doc( html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg" )] -#![forbid(unsafe_code, rust_2018_idioms)] -#![deny( - missing_debug_implementations, - missing_docs, - unused_results, - rustdoc::broken_intra_doc_links -)] pub mod alignment; pub mod border; pub mod clipboard; @@ -41,7 +34,6 @@ mod background; mod color; mod content_fit; mod element; -mod hasher; mod length; mod padding; mod pixels; @@ -64,7 +56,6 @@ pub use element::Element; pub use event::Event; pub use font::Font; pub use gradient::Gradient; -pub use hasher::Hasher; pub use layout::Layout; pub use length::Length; pub use overlay::Overlay; diff --git a/core/src/rectangle.rs b/core/src/rectangle.rs index c1c2eeac..2ab50137 100644 --- a/core/src/rectangle.rs +++ b/core/src/rectangle.rs @@ -16,24 +16,32 @@ pub struct Rectangle<T = f32> { pub height: T, } -impl Rectangle<f32> { - /// Creates a new [`Rectangle`] with its top-left corner in the given - /// [`Point`] and with the provided [`Size`]. - pub fn new(top_left: Point, size: Size) -> Self { +impl<T> Rectangle<T> +where + T: Default, +{ + /// Creates a new [`Rectangle`] with its top-left corner at the origin + /// and with the provided [`Size`]. + pub fn with_size(size: Size<T>) -> Self { Self { - x: top_left.x, - y: top_left.y, + x: T::default(), + y: T::default(), width: size.width, height: size.height, } } +} - /// Creates a new [`Rectangle`] with its top-left corner at the origin - /// and with the provided [`Size`]. - pub fn with_size(size: Size) -> Self { +impl Rectangle<f32> { + /// A rectangle starting at [`Point::ORIGIN`] with infinite width and height. + pub const INFINITE: Self = Self::new(Point::ORIGIN, Size::INFINITY); + + /// Creates a new [`Rectangle`] with its top-left corner in the given + /// [`Point`] and with the provided [`Size`]. + pub const fn new(top_left: Point, size: Size) -> Self { Self { - x: 0.0, - y: 0.0, + x: top_left.x, + y: top_left.y, width: size.width, height: size.height, } @@ -139,13 +147,20 @@ impl Rectangle<f32> { } /// Snaps the [`Rectangle`] to __unsigned__ integer coordinates. - pub fn snap(self) -> Rectangle<u32> { - Rectangle { + pub fn snap(self) -> Option<Rectangle<u32>> { + let width = self.width as u32; + let height = self.height as u32; + + if width < 1 || height < 1 { + return None; + } + + Some(Rectangle { x: self.x as u32, y: self.y as u32, - width: self.width as u32, - height: self.height as u32, - } + width, + height, + }) } /// Expands the [`Rectangle`] a given amount. diff --git a/core/src/renderer.rs b/core/src/renderer.rs index 6712314e..a2785ae8 100644 --- a/core/src/renderer.rs +++ b/core/src/renderer.rs @@ -9,29 +9,29 @@ use crate::{ /// A component that can be used by widgets to draw themselves on a screen. pub trait Renderer { /// Starts recording a new layer. - fn start_layer(&mut self); + fn start_layer(&mut self, bounds: Rectangle); /// Ends recording a new layer. /// /// The new layer will clip its contents to the provided `bounds`. - fn end_layer(&mut self, bounds: Rectangle); + fn end_layer(&mut self); /// Draws the primitives recorded in the given closure in a new layer. /// /// The layer will clip its contents to the provided `bounds`. fn with_layer(&mut self, bounds: Rectangle, f: impl FnOnce(&mut Self)) { - self.start_layer(); + self.start_layer(bounds); f(self); - self.end_layer(bounds); + self.end_layer(); } /// Starts recording with a new [`Transformation`]. - fn start_transformation(&mut self); + fn start_transformation(&mut self, transformation: Transformation); /// Ends recording a new layer. /// /// The new layer will clip its contents to the provided `bounds`. - fn end_transformation(&mut self, transformation: Transformation); + fn end_transformation(&mut self); /// Applies a [`Transformation`] to the primitives recorded in the given closure. fn with_transformation( @@ -39,9 +39,9 @@ pub trait Renderer { transformation: Transformation, f: impl FnOnce(&mut Self), ) { - self.start_transformation(); + self.start_transformation(transformation); f(self); - self.end_transformation(transformation); + self.end_transformation(); } /// Applies a translation to the primitives recorded in the given closure. diff --git a/core/src/renderer/null.rs b/core/src/renderer/null.rs index c26ce1a5..fe38ec87 100644 --- a/core/src/renderer/null.rs +++ b/core/src/renderer/null.rs @@ -7,16 +7,14 @@ use crate::{ Background, Color, Font, Pixels, Point, Rectangle, Size, Transformation, }; -use std::borrow::Cow; - impl Renderer for () { - fn start_layer(&mut self) {} + fn start_layer(&mut self, _bounds: Rectangle) {} - fn end_layer(&mut self, _bounds: Rectangle) {} + fn end_layer(&mut self) {} - fn start_transformation(&mut self) {} + fn start_transformation(&mut self, _transformation: Transformation) {} - fn end_transformation(&mut self, _transformation: Transformation) {} + fn end_transformation(&mut self) {} fn clear(&mut self) {} @@ -45,8 +43,6 @@ impl text::Renderer for () { Pixels(16.0) } - fn load_font(&mut self, _font: Cow<'static, [u8]>) {} - fn fill_paragraph( &mut self, _paragraph: &Self::Paragraph, @@ -67,7 +63,7 @@ impl text::Renderer for () { fn fill_text( &mut self, - _paragraph: Text<'_, Self::Font>, + _paragraph: Text, _position: Point, _color: Color, _clip_bounds: Rectangle, @@ -78,11 +74,11 @@ impl text::Renderer for () { impl text::Paragraph for () { type Font = Font; - fn with_text(_text: Text<'_, Self::Font>) -> Self {} + fn with_text(_text: Text<&str>) -> Self {} fn resize(&mut self, _new_bounds: Size) {} - fn compare(&self, _text: Text<'_, Self::Font>) -> text::Difference { + fn compare(&self, _text: Text<&str>) -> text::Difference { text::Difference::None } diff --git a/core/src/size.rs b/core/src/size.rs index 55db759d..c2b5671a 100644 --- a/core/src/size.rs +++ b/core/src/size.rs @@ -99,3 +99,17 @@ where } } } + +impl<T> std::ops::Mul<T> for Size<T> +where + T: std::ops::Mul<Output = T> + Copy, +{ + type Output = Size<T>; + + fn mul(self, rhs: T) -> Self::Output { + Size { + width: self.width * rhs, + height: self.height * rhs, + } + } +} diff --git a/core/src/svg.rs b/core/src/svg.rs index ab207cca..0106e0c2 100644 --- a/core/src/svg.rs +++ b/core/src/svg.rs @@ -1,6 +1,7 @@ //! Load and draw vector graphics. -use crate::{Color, Hasher, Rectangle, Size}; +use crate::{Color, Rectangle, Size}; +use rustc_hash::FxHasher; use std::borrow::Cow; use std::hash::{Hash, Hasher as _}; use std::path::PathBuf; @@ -30,7 +31,7 @@ impl Handle { } fn from_data(data: Data) -> Handle { - let mut hasher = Hasher::default(); + let mut hasher = FxHasher::default(); data.hash(&mut hasher); Handle { diff --git a/core/src/text.rs b/core/src/text.rs index edef79c2..b30feae0 100644 --- a/core/src/text.rs +++ b/core/src/text.rs @@ -11,14 +11,13 @@ pub use paragraph::Paragraph; use crate::alignment; use crate::{Color, Pixels, Point, Rectangle, Size}; -use std::borrow::Cow; use std::hash::{Hash, Hasher}; /// A paragraph. #[derive(Debug, Clone, Copy)] -pub struct Text<'a, Font> { +pub struct Text<Content = String, Font = crate::Font> { /// The content of the paragraph. - pub content: &'a str, + pub content: Content, /// The bounds of the paragraph. pub bounds: Size, @@ -192,9 +191,6 @@ pub trait Renderer: crate::Renderer { /// Returns the default size of [`Text`]. fn default_size(&self) -> Pixels; - /// Loads a [`Self::Font`] from its bytes. - fn load_font(&mut self, font: Cow<'static, [u8]>); - /// Draws the given [`Paragraph`] at the given position and with the given /// [`Color`]. fn fill_paragraph( @@ -219,7 +215,7 @@ pub trait Renderer: crate::Renderer { /// [`Color`]. fn fill_text( &mut self, - text: Text<'_, Self::Font>, + text: Text<String, Self::Font>, position: Point, color: Color, clip_bounds: Rectangle, diff --git a/core/src/text/paragraph.rs b/core/src/text/paragraph.rs index de1fb74d..8ff04015 100644 --- a/core/src/text/paragraph.rs +++ b/core/src/text/paragraph.rs @@ -8,14 +8,14 @@ pub trait Paragraph: Sized + Default { type Font: Copy + PartialEq; /// Creates a new [`Paragraph`] laid out with the given [`Text`]. - fn with_text(text: Text<'_, Self::Font>) -> Self; + fn with_text(text: Text<&str, Self::Font>) -> Self; /// Lays out the [`Paragraph`] with some new boundaries. fn resize(&mut self, new_bounds: Size); /// Compares the [`Paragraph`] with some desired [`Text`] and returns the /// [`Difference`]. - fn compare(&self, text: Text<'_, Self::Font>) -> Difference; + fn compare(&self, text: Text<&str, Self::Font>) -> Difference; /// Returns the horizontal alignment of the [`Paragraph`]. fn horizontal_alignment(&self) -> alignment::Horizontal; @@ -35,7 +35,7 @@ pub trait Paragraph: Sized + Default { fn grapheme_position(&self, line: usize, index: usize) -> Option<Point>; /// Updates the [`Paragraph`] to match the given [`Text`], if needed. - fn update(&mut self, text: Text<'_, Self::Font>) { + fn update(&mut self, text: Text<&str, Self::Font>) { match self.compare(text) { Difference::None => {} Difference::Bounds => { diff --git a/core/src/theme/palette.rs b/core/src/theme/palette.rs index ca91c248..e0ff397a 100644 --- a/core/src/theme/palette.rs +++ b/core/src/theme/palette.rs @@ -613,10 +613,15 @@ fn mix(a: Color, b: Color, factor: f32) -> Color { fn readable(background: Color, text: Color) -> Color { if is_readable(background, text) { text - } else if is_dark(background) { - Color::WHITE } else { - Color::BLACK + let white_contrast = relative_contrast(background, Color::WHITE); + let black_contrast = relative_contrast(background, Color::BLACK); + + if white_contrast >= black_contrast { + Color::WHITE + } else { + Color::BLACK + } } } @@ -631,6 +636,13 @@ fn is_readable(a: Color, b: Color) -> bool { a_srgb.has_enhanced_contrast_text(b_srgb) } +fn relative_contrast(a: Color, b: Color) -> f32 { + let a_srgb = Rgb::from(a); + let b_srgb = Rgb::from(b); + + a_srgb.relative_contrast(b_srgb) +} + fn to_hsl(color: Color) -> Hsl { Hsl::from_color(Rgb::from(color)) } diff --git a/core/src/transformation.rs b/core/src/transformation.rs index b2c488b0..74183147 100644 --- a/core/src/transformation.rs +++ b/core/src/transformation.rs @@ -42,6 +42,12 @@ impl Transformation { } } +impl Default for Transformation { + fn default() -> Self { + Transformation::IDENTITY + } +} + impl Mul for Transformation { type Output = Self; diff --git a/core/src/widget/text.rs b/core/src/widget/text.rs index 12f6956a..f1f0b345 100644 --- a/core/src/widget/text.rs +++ b/core/src/widget/text.rs @@ -21,7 +21,7 @@ where Theme: Catalog, Renderer: text::Renderer, { - content: Cow<'a, str>, + fragment: Fragment<'a>, size: Option<Pixels>, line_height: LineHeight, width: Length, @@ -39,9 +39,9 @@ where Renderer: text::Renderer, { /// Create a new fragment of [`Text`] with the given contents. - pub fn new(content: impl Into<Cow<'a, str>>) -> Self { + pub fn new(fragment: impl IntoFragment<'a>) -> Self { Text { - content: content.into(), + fragment: fragment.into_fragment(), size: None, line_height: LineHeight::default(), font: None, @@ -184,7 +184,7 @@ where limits, self.width, self.height, - &self.content, + &self.fragment, self.line_height, self.size, self.font, @@ -366,3 +366,81 @@ impl Catalog for Theme { class(self) } } + +/// A fragment of [`Text`]. +/// +/// This is just an alias to a string that may be either +/// borrowed or owned. +pub type Fragment<'a> = Cow<'a, str>; + +/// A trait for converting a value to some text [`Fragment`]. +pub trait IntoFragment<'a> { + /// Converts the value to some text [`Fragment`]. + fn into_fragment(self) -> Fragment<'a>; +} + +impl<'a> IntoFragment<'a> for Fragment<'a> { + fn into_fragment(self) -> Fragment<'a> { + self + } +} + +impl<'a, 'b> IntoFragment<'a> for &'a Fragment<'b> { + fn into_fragment(self) -> Fragment<'a> { + Fragment::Borrowed(self) + } +} + +impl<'a> IntoFragment<'a> for &'a str { + fn into_fragment(self) -> Fragment<'a> { + Fragment::Borrowed(self) + } +} + +impl<'a> IntoFragment<'a> for &'a String { + fn into_fragment(self) -> Fragment<'a> { + Fragment::Borrowed(self.as_str()) + } +} + +impl<'a> IntoFragment<'a> for String { + fn into_fragment(self) -> Fragment<'a> { + Fragment::Owned(self) + } +} + +macro_rules! into_fragment { + ($type:ty) => { + impl<'a> IntoFragment<'a> for $type { + fn into_fragment(self) -> Fragment<'a> { + Fragment::Owned(self.to_string()) + } + } + + impl<'a> IntoFragment<'a> for &$type { + fn into_fragment(self) -> Fragment<'a> { + Fragment::Owned(self.to_string()) + } + } + }; +} + +into_fragment!(char); +into_fragment!(bool); + +into_fragment!(u8); +into_fragment!(u16); +into_fragment!(u32); +into_fragment!(u64); +into_fragment!(u128); +into_fragment!(usize); + +into_fragment!(i8); +into_fragment!(i16); +into_fragment!(i32); +into_fragment!(i64); +into_fragment!(i128); +into_fragment!(isize); + +into_fragment!(f32); +into_fragment!(f64); |