summaryrefslogtreecommitdiffstats
path: root/graphics
diff options
context:
space:
mode:
Diffstat (limited to 'graphics')
-rw-r--r--graphics/src/cache.rs19
-rw-r--r--graphics/src/geometry/frame.rs24
-rw-r--r--graphics/src/geometry/path.rs13
-rw-r--r--graphics/src/geometry/path/builder.rs68
-rw-r--r--graphics/src/text.rs12
-rw-r--r--graphics/src/text/editor.rs29
-rw-r--r--graphics/src/text/paragraph.rs7
7 files changed, 147 insertions, 25 deletions
diff --git a/graphics/src/cache.rs b/graphics/src/cache.rs
index bbba79eb..7db80a01 100644
--- a/graphics/src/cache.rs
+++ b/graphics/src/cache.rs
@@ -1,6 +1,7 @@
//! Cache computations and efficiently reuse them.
use std::cell::RefCell;
use std::fmt;
+use std::mem;
use std::sync::atomic::{self, AtomicU64};
/// A simple cache that stores generated values to avoid recomputation.
@@ -58,18 +59,18 @@ impl<T> Cache<T> {
}
/// Clears the [`Cache`].
- pub fn clear(&self)
- where
- T: Clone,
- {
- use std::ops::Deref;
+ pub fn clear(&self) {
+ let mut state = self.state.borrow_mut();
+
+ let previous =
+ mem::replace(&mut *state, State::Empty { previous: None });
- let previous = match self.state.borrow().deref() {
- State::Empty { previous } => previous.clone(),
- State::Filled { current } => Some(current.clone()),
+ let previous = match previous {
+ State::Empty { previous } => previous,
+ State::Filled { current } => Some(current),
};
- *self.state.borrow_mut() = State::Empty { previous };
+ *state = State::Empty { previous };
}
}
diff --git a/graphics/src/geometry/frame.rs b/graphics/src/geometry/frame.rs
index b5f2f139..3dee7e75 100644
--- a/graphics/src/geometry/frame.rs
+++ b/graphics/src/geometry/frame.rs
@@ -65,6 +65,17 @@ where
self.raw.stroke(path, stroke);
}
+ /// Draws the stroke of an axis-aligned rectangle with the provided style
+ /// given its top-left corner coordinate and its `Size` on the [`Frame`] .
+ pub fn stroke_rectangle<'a>(
+ &mut self,
+ top_left: Point,
+ size: Size,
+ stroke: impl Into<Stroke<'a>>,
+ ) {
+ self.raw.stroke_rectangle(top_left, size, stroke);
+ }
+
/// Draws the characters of the given [`Text`] on the [`Frame`], filling
/// them with the given color.
///
@@ -200,6 +211,12 @@ pub trait Backend: Sized {
fn paste(&mut self, frame: Self);
fn stroke<'a>(&mut self, path: &Path, stroke: impl Into<Stroke<'a>>);
+ fn stroke_rectangle<'a>(
+ &mut self,
+ top_left: Point,
+ size: Size,
+ stroke: impl Into<Stroke<'a>>,
+ );
fn fill(&mut self, path: &Path, fill: impl Into<Fill>);
fn fill_text(&mut self, text: impl Into<Text>);
@@ -248,6 +265,13 @@ impl Backend for () {
fn paste(&mut self, _frame: Self) {}
fn stroke<'a>(&mut self, _path: &Path, _stroke: impl Into<Stroke<'a>>) {}
+ fn stroke_rectangle<'a>(
+ &mut self,
+ _top_left: Point,
+ _size: Size,
+ _stroke: impl Into<Stroke<'a>>,
+ ) {
+ }
fn fill(&mut self, _path: &Path, _fill: impl Into<Fill>) {}
fn fill_text(&mut self, _text: impl Into<Text>) {}
diff --git a/graphics/src/geometry/path.rs b/graphics/src/geometry/path.rs
index 3d8fc6fa..c4f51593 100644
--- a/graphics/src/geometry/path.rs
+++ b/graphics/src/geometry/path.rs
@@ -9,7 +9,8 @@ pub use builder::Builder;
pub use lyon_path;
-use iced_core::{Point, Size};
+use crate::core::border;
+use crate::core::{Point, Size};
/// An immutable set of points that may or may not be connected.
///
@@ -47,6 +48,16 @@ impl Path {
Self::new(|p| p.rectangle(top_left, size))
}
+ /// Creates a new [`Path`] representing a rounded rectangle given its top-left
+ /// corner coordinate, its [`Size`] and [`border::Radius`].
+ pub fn rounded_rectangle(
+ top_left: Point,
+ size: Size,
+ radius: border::Radius,
+ ) -> Self {
+ Self::new(|p| p.rounded_rectangle(top_left, size, radius))
+ }
+
/// Creates a new [`Path`] representing a circle given its center
/// coordinate and its radius.
pub fn circle(center: Point, radius: f32) -> Self {
diff --git a/graphics/src/geometry/path/builder.rs b/graphics/src/geometry/path/builder.rs
index 1ccd83f2..44410f6d 100644
--- a/graphics/src/geometry/path/builder.rs
+++ b/graphics/src/geometry/path/builder.rs
@@ -1,6 +1,7 @@
use crate::geometry::path::{arc, Arc, Path};
-use iced_core::{Point, Radians, Size};
+use crate::core::border;
+use crate::core::{Point, Radians, Size};
use lyon_path::builder::{self, SvgPathBuilder};
use lyon_path::geom;
@@ -160,6 +161,71 @@ impl Builder {
self.close();
}
+ /// Adds a rounded rectangle to the [`Path`] given its top-left
+ /// corner coordinate its [`Size`] and [`border::Radius`].
+ #[inline]
+ pub fn rounded_rectangle(
+ &mut self,
+ top_left: Point,
+ size: Size,
+ radius: border::Radius,
+ ) {
+ let min_size = (size.height / 2.0).min(size.width / 2.0);
+ let [top_left_corner, top_right_corner, bottom_right_corner, bottom_left_corner] =
+ radius.into();
+
+ self.move_to(Point::new(
+ top_left.x + min_size.min(top_left_corner),
+ top_left.y,
+ ));
+ self.line_to(Point::new(
+ top_left.x + size.width - min_size.min(top_right_corner),
+ top_left.y,
+ ));
+ self.arc_to(
+ Point::new(top_left.x + size.width, top_left.y),
+ Point::new(
+ top_left.x + size.width,
+ top_left.y + min_size.min(top_right_corner),
+ ),
+ min_size.min(top_right_corner),
+ );
+ self.line_to(Point::new(
+ top_left.x + size.width,
+ top_left.y + size.height - min_size.min(bottom_right_corner),
+ ));
+ self.arc_to(
+ Point::new(top_left.x + size.width, top_left.y + size.height),
+ Point::new(
+ top_left.x + size.width - min_size.min(bottom_right_corner),
+ top_left.y + size.height,
+ ),
+ min_size.min(bottom_right_corner),
+ );
+ self.line_to(Point::new(
+ top_left.x + min_size.min(bottom_left_corner),
+ top_left.y + size.height,
+ ));
+ self.arc_to(
+ Point::new(top_left.x, top_left.y + size.height),
+ Point::new(
+ top_left.x,
+ top_left.y + size.height - min_size.min(bottom_left_corner),
+ ),
+ min_size.min(bottom_left_corner),
+ );
+ self.line_to(Point::new(
+ top_left.x,
+ top_left.y + min_size.min(top_left_corner),
+ ));
+ self.arc_to(
+ Point::new(top_left.x, top_left.y),
+ Point::new(top_left.x + min_size.min(top_left_corner), top_left.y),
+ min_size.min(top_left_corner),
+ );
+ self.close();
+ }
+
/// Adds a circle to the [`Path`] given its center coordinate and its
/// radius.
#[inline]
diff --git a/graphics/src/text.rs b/graphics/src/text.rs
index 23ec14d4..feb9932a 100644
--- a/graphics/src/text.rs
+++ b/graphics/src/text.rs
@@ -11,7 +11,7 @@ pub use cosmic_text;
use crate::core::alignment;
use crate::core::font::{self, Font};
-use crate::core::text::Shaping;
+use crate::core::text::{Shaping, Wrapping};
use crate::core::{Color, Pixels, Point, Rectangle, Size, Transformation};
use once_cell::sync::OnceCell;
@@ -306,6 +306,16 @@ pub fn to_shaping(shaping: Shaping) -> cosmic_text::Shaping {
}
}
+/// Converts some [`Wrapping`] strategy to a [`cosmic_text::Wrap`] strategy.
+pub fn to_wrap(wrapping: Wrapping) -> cosmic_text::Wrap {
+ match wrapping {
+ Wrapping::None => cosmic_text::Wrap::None,
+ Wrapping::Word => cosmic_text::Wrap::Word,
+ Wrapping::Glyph => cosmic_text::Wrap::Glyph,
+ Wrapping::WordOrGlyph => cosmic_text::Wrap::WordOrGlyph,
+ }
+}
+
/// Converts some [`Color`] to a [`cosmic_text::Color`].
pub fn to_color(color: Color) -> cosmic_text::Color {
let [r, g, b, a] = color.into_rgba8();
diff --git a/graphics/src/text/editor.rs b/graphics/src/text/editor.rs
index 80733bbb..1f1d0050 100644
--- a/graphics/src/text/editor.rs
+++ b/graphics/src/text/editor.rs
@@ -3,7 +3,7 @@ use crate::core::text::editor::{
self, Action, Cursor, Direction, Edit, Motion,
};
use crate::core::text::highlighter::{self, Highlighter};
-use crate::core::text::LineHeight;
+use crate::core::text::{LineHeight, Wrapping};
use crate::core::{Font, Pixels, Point, Rectangle, Size};
use crate::text;
@@ -437,6 +437,7 @@ impl editor::Editor for Editor {
new_font: Font,
new_size: Pixels,
new_line_height: LineHeight,
+ new_wrapping: Wrapping,
new_highlighter: &mut impl Highlighter,
) {
let editor =
@@ -448,13 +449,12 @@ impl editor::Editor for Editor {
let mut font_system =
text::font_system().write().expect("Write font system");
+ let buffer = buffer_mut_from_editor(&mut internal.editor);
+
if font_system.version() != internal.version {
log::trace!("Updating `FontSystem` of `Editor`...");
- for line in buffer_mut_from_editor(&mut internal.editor)
- .lines
- .iter_mut()
- {
+ for line in buffer.lines.iter_mut() {
line.reset();
}
@@ -465,10 +465,7 @@ impl editor::Editor for Editor {
if new_font != internal.font {
log::trace!("Updating font of `Editor`...");
- for line in buffer_mut_from_editor(&mut internal.editor)
- .lines
- .iter_mut()
- {
+ for line in buffer.lines.iter_mut() {
let _ = line.set_attrs_list(cosmic_text::AttrsList::new(
text::to_attributes(new_font),
));
@@ -478,7 +475,7 @@ impl editor::Editor for Editor {
internal.topmost_line_changed = Some(0);
}
- let metrics = buffer_from_editor(&internal.editor).metrics();
+ let metrics = buffer.metrics();
let new_line_height = new_line_height.to_absolute(new_size);
if new_size.0 != metrics.font_size
@@ -486,16 +483,24 @@ impl editor::Editor for Editor {
{
log::trace!("Updating `Metrics` of `Editor`...");
- buffer_mut_from_editor(&mut internal.editor).set_metrics(
+ buffer.set_metrics(
font_system.raw(),
cosmic_text::Metrics::new(new_size.0, new_line_height.0),
);
}
+ let new_wrap = text::to_wrap(new_wrapping);
+
+ if new_wrap != buffer.wrap() {
+ log::trace!("Updating `Wrap` strategy of `Editor`...");
+
+ buffer.set_wrap(font_system.raw(), new_wrap);
+ }
+
if new_bounds != internal.bounds {
log::trace!("Updating size of `Editor`...");
- buffer_mut_from_editor(&mut internal.editor).set_size(
+ buffer.set_size(
font_system.raw(),
Some(new_bounds.width),
Some(new_bounds.height),
diff --git a/graphics/src/text/paragraph.rs b/graphics/src/text/paragraph.rs
index b9f9c833..07ddbb82 100644
--- a/graphics/src/text/paragraph.rs
+++ b/graphics/src/text/paragraph.rs
@@ -1,7 +1,7 @@
//! Draw paragraphs.
use crate::core;
use crate::core::alignment;
-use crate::core::text::{Hit, Shaping, Span, Text};
+use crate::core::text::{Hit, Shaping, Span, Text, Wrapping};
use crate::core::{Font, Point, Rectangle, Size};
use crate::text;
@@ -17,6 +17,7 @@ struct Internal {
buffer: cosmic_text::Buffer,
font: Font,
shaping: Shaping,
+ wrapping: Wrapping,
horizontal_alignment: alignment::Horizontal,
vertical_alignment: alignment::Vertical,
bounds: Size,
@@ -94,6 +95,7 @@ impl core::text::Paragraph for Paragraph {
horizontal_alignment: text.horizontal_alignment,
vertical_alignment: text.vertical_alignment,
shaping: text.shaping,
+ wrapping: text.wrapping,
bounds: text.bounds,
min_bounds,
version: font_system.version(),
@@ -160,6 +162,7 @@ impl core::text::Paragraph for Paragraph {
horizontal_alignment: text.horizontal_alignment,
vertical_alignment: text.vertical_alignment,
shaping: text.shaping,
+ wrapping: text.wrapping,
bounds: text.bounds,
min_bounds,
version: font_system.version(),
@@ -192,6 +195,7 @@ impl core::text::Paragraph for Paragraph {
|| metrics.line_height != text.line_height.to_absolute(text.size).0
|| paragraph.font != text.font
|| paragraph.shaping != text.shaping
+ || paragraph.wrapping != text.wrapping
|| paragraph.horizontal_alignment != text.horizontal_alignment
|| paragraph.vertical_alignment != text.vertical_alignment
{
@@ -387,6 +391,7 @@ impl Default for Internal {
}),
font: Font::default(),
shaping: Shaping::default(),
+ wrapping: Wrapping::default(),
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top,
bounds: Size::ZERO,