summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorLibravatar Gigas002 <24297712+Gigas002@users.noreply.github.com>2024-04-16 00:08:17 +0900
committerLibravatar GitHub <noreply@github.com>2024-04-16 00:08:17 +0900
commit0ebe0629cef37aee5c48b9409fc36618a3a3e60d (patch)
tree909d9ecf28e7c491bae3afc81928c118517fa7a9 /core
parent13bd106fc585034a7aba17b9c17589113274aaf5 (diff)
parent105b8bd5ad6ade1f203a0d8b0b93bd06f61f621a (diff)
downloadiced-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.toml5
-rw-r--r--core/src/hasher.rs2
-rw-r--r--core/src/image.rs5
-rw-r--r--core/src/lib.rs9
-rw-r--r--core/src/rectangle.rs47
-rw-r--r--core/src/renderer.rs16
-rw-r--r--core/src/renderer/null.rs18
-rw-r--r--core/src/size.rs14
-rw-r--r--core/src/svg.rs5
-rw-r--r--core/src/text.rs10
-rw-r--r--core/src/text/paragraph.rs6
-rw-r--r--core/src/theme/palette.rs18
-rw-r--r--core/src/transformation.rs6
-rw-r--r--core/src/widget/text.rs86
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);