summaryrefslogtreecommitdiffstats
path: root/wgpu
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2020-05-19 17:15:44 +0200
committerLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2020-05-19 17:15:44 +0200
commit05af8d00d4c0f7b8e0ece85224fd90a92da86da8 (patch)
tree98e4774a2c0d4a2a0a01aff1d772f89c4cb0aa5e /wgpu
parentd4743183d40c6044ce6fa39e2a52919a32912cda (diff)
downloadiced-05af8d00d4c0f7b8e0ece85224fd90a92da86da8.tar.gz
iced-05af8d00d4c0f7b8e0ece85224fd90a92da86da8.tar.bz2
iced-05af8d00d4c0f7b8e0ece85224fd90a92da86da8.zip
Draft new `iced_graphics` crate :tada:
Diffstat (limited to 'wgpu')
-rw-r--r--wgpu/Cargo.toml11
-rw-r--r--wgpu/src/backend.rs (renamed from wgpu/src/renderer.rs)97
-rw-r--r--wgpu/src/defaults.rs32
-rw-r--r--wgpu/src/lib.rs13
-rw-r--r--wgpu/src/primitive.rs107
-rw-r--r--wgpu/src/renderer/widget.rs19
-rw-r--r--wgpu/src/renderer/widget/button.rs93
-rw-r--r--wgpu/src/renderer/widget/checkbox.rs63
-rw-r--r--wgpu/src/renderer/widget/column.rs34
-rw-r--r--wgpu/src/renderer/widget/container.rs48
-rw-r--r--wgpu/src/renderer/widget/image.rs22
-rw-r--r--wgpu/src/renderer/widget/pane_grid.rs93
-rw-r--r--wgpu/src/renderer/widget/progress_bar.rs54
-rw-r--r--wgpu/src/renderer/widget/radio.rs63
-rw-r--r--wgpu/src/renderer/widget/row.rs34
-rw-r--r--wgpu/src/renderer/widget/scrollable.rs125
-rw-r--r--wgpu/src/renderer/widget/slider.rs106
-rw-r--r--wgpu/src/renderer/widget/space.rs8
-rw-r--r--wgpu/src/renderer/widget/svg.rs22
-rw-r--r--wgpu/src/renderer/widget/text.rs61
-rw-r--r--wgpu/src/renderer/widget/text_input.rs261
-rw-r--r--wgpu/src/text.rs2
-rw-r--r--wgpu/src/triangle.rs27
-rw-r--r--wgpu/src/widget/button.rs2
-rw-r--r--wgpu/src/widget/canvas.rs226
-rw-r--r--wgpu/src/widget/canvas/cache.rs108
-rw-r--r--wgpu/src/widget/canvas/cursor.rs72
-rw-r--r--wgpu/src/widget/canvas/event.rs10
-rw-r--r--wgpu/src/widget/canvas/fill.rs20
-rw-r--r--wgpu/src/widget/canvas/frame.rs367
-rw-r--r--wgpu/src/widget/canvas/geometry.rs34
-rw-r--r--wgpu/src/widget/canvas/path.rs79
-rw-r--r--wgpu/src/widget/canvas/path/arc.rs44
-rw-r--r--wgpu/src/widget/canvas/path/builder.rs180
-rw-r--r--wgpu/src/widget/canvas/program.rs85
-rw-r--r--wgpu/src/widget/canvas/stroke.rs115
-rw-r--r--wgpu/src/widget/canvas/text.rs49
-rw-r--r--wgpu/src/widget/checkbox.rs2
-rw-r--r--wgpu/src/widget/container.rs2
-rw-r--r--wgpu/src/widget/progress_bar.rs2
-rw-r--r--wgpu/src/widget/radio.rs2
-rw-r--r--wgpu/src/widget/scrollable.rs2
-rw-r--r--wgpu/src/widget/slider.rs2
-rw-r--r--wgpu/src/widget/text_input.rs2
-rw-r--r--wgpu/src/window/backend.rs4
45 files changed, 66 insertions, 2738 deletions
diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml
index 612af1ed..88290576 100644
--- a/wgpu/Cargo.toml
+++ b/wgpu/Cargo.toml
@@ -9,12 +9,13 @@ repository = "https://github.com/hecrj/iced"
[features]
svg = ["resvg"]
-canvas = ["lyon"]
+canvas = ["iced_graphics/canvas"]
[dependencies]
wgpu = "0.5"
wgpu_glyph = "0.8"
zerocopy = "0.3"
+bytemuck = "1.2"
glyph_brush = "0.6"
raw-window-handle = "0.3"
glam = "0.8"
@@ -29,9 +30,9 @@ gfx-memory = "=0.1.1"
version = "0.2"
path = "../native"
-[dependencies.iced_style]
+[dependencies.iced_graphics]
version = "0.1"
-path = "../style"
+path = "../graphics"
[dependencies.image]
version = "0.23"
@@ -42,10 +43,6 @@ version = "0.9"
features = ["raqote-backend"]
optional = true
-[dependencies.lyon]
-version = "0.15"
-optional = true
-
[package.metadata.docs.rs]
rustdoc-args = ["--cfg", "docsrs"]
all-features = true
diff --git a/wgpu/src/renderer.rs b/wgpu/src/backend.rs
index 71b4af38..ba1a57a5 100644
--- a/wgpu/src/renderer.rs
+++ b/wgpu/src/backend.rs
@@ -1,22 +1,20 @@
-use crate::{
- quad, text, triangle, Defaults, Primitive, Quad, Settings, Target,
- Transformation,
-};
+use crate::quad;
+use crate::text;
+use crate::triangle;
+use crate::{Quad, Settings, Target, Transformation};
+use iced_graphics::backend;
+use iced_graphics::Primitive;
+use iced_native::mouse;
+use iced_native::{Background, Font, Point, Rectangle, Size, Vector};
#[cfg(any(feature = "image", feature = "svg"))]
use crate::image::{self, Image};
-use iced_native::{
- layout, mouse, Background, Color, Layout, Point, Rectangle, Vector, Widget,
-};
-
-mod widget;
-
/// A [`wgpu`] renderer.
///
/// [`wgpu`]: https://github.com/gfx-rs/wgpu-rs
#[derive(Debug)]
-pub struct Renderer {
+pub struct Backend {
quad_pipeline: quad::Pipeline,
text_pipeline: text::Pipeline,
triangle_pipeline: triangle::Pipeline,
@@ -55,7 +53,7 @@ impl<'a> Layer<'a> {
}
}
-impl Renderer {
+impl Backend {
/// Creates a new [`Renderer`].
///
/// [`Renderer`]: struct.Renderer.html
@@ -451,57 +449,44 @@ impl Renderer {
}
}
-impl iced_native::Renderer for Renderer {
- type Output = (Primitive, mouse::Interaction);
- type Defaults = Defaults;
-
- fn layout<'a, Message>(
- &mut self,
- element: &iced_native::Element<'a, Message, Self>,
- limits: &iced_native::layout::Limits,
- ) -> iced_native::layout::Node {
- let node = element.layout(self, limits);
+impl iced_graphics::Backend for Backend {
+ fn trim_measurements(&mut self) {
+ self.text_pipeline.trim_measurement_cache()
+ }
+}
- self.text_pipeline.clear_measurement_cache();
+impl backend::Text for Backend {
+ const ICON_FONT: Font = text::BUILTIN_ICONS;
+ const CHECKMARK_ICON: char = text::CHECKMARK_ICON;
+
+ fn measure(
+ &self,
+ contents: &str,
+ size: f32,
+ font: Font,
+ bounds: Size,
+ ) -> (f32, f32) {
+ self.text_pipeline.measure(contents, size, font, bounds)
+ }
- node
+ fn space_width(&self, size: f32) -> f32 {
+ self.text_pipeline.space_width(size)
}
}
-impl layout::Debugger for Renderer {
- fn explain<Message>(
- &mut self,
- defaults: &Defaults,
- widget: &dyn Widget<Message, Self>,
- layout: Layout<'_>,
- cursor_position: Point,
- color: Color,
- ) -> Self::Output {
- let mut primitives = Vec::new();
- let (primitive, cursor) =
- widget.draw(self, defaults, layout, cursor_position);
-
- explain_layout(layout, color, &mut primitives);
- primitives.push(primitive);
-
- (Primitive::Group { primitives }, cursor)
+#[cfg(feature = "image")]
+impl backend::Image for Backend {
+ fn dimensions(&self, handle: &iced_native::image::Handle) -> (u32, u32) {
+ self.image_pipeline.dimensions(handle)
}
}
-fn explain_layout(
- layout: Layout<'_>,
- color: Color,
- primitives: &mut Vec<Primitive>,
-) {
- primitives.push(Primitive::Quad {
- bounds: layout.bounds(),
- background: Background::Color(Color::TRANSPARENT),
- border_radius: 0,
- border_width: 1,
- border_color: [0.6, 0.6, 0.6, 0.5].into(),
- });
-
- for child in layout.children() {
- explain_layout(child, color, primitives);
+#[cfg(feature = "svg")]
+impl backend::Svg for Backend {
+ fn viewport_dimensions(
+ &self,
+ handle: &iced_native::svg::Handle,
+ ) -> (u32, u32) {
+ self.image_pipeline.viewport_dimensions(handle)
}
}
diff --git a/wgpu/src/defaults.rs b/wgpu/src/defaults.rs
deleted file mode 100644
index 11718a87..00000000
--- a/wgpu/src/defaults.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-//! Use default styling attributes to inherit styles.
-use iced_native::Color;
-
-/// Some default styling attributes.
-#[derive(Debug, Clone, Copy)]
-pub struct Defaults {
- /// Text styling
- pub text: Text,
-}
-
-impl Default for Defaults {
- fn default() -> Defaults {
- Defaults {
- text: Text::default(),
- }
- }
-}
-
-/// Some default text styling attributes.
-#[derive(Debug, Clone, Copy)]
-pub struct Text {
- /// The default color of text
- pub color: Color,
-}
-
-impl Default for Text {
- fn default() -> Text {
- Text {
- color: Color::BLACK,
- }
- }
-}
diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs
index 799c1f34..86827502 100644
--- a/wgpu/src/lib.rs
+++ b/wgpu/src/lib.rs
@@ -20,32 +20,29 @@
//! [`wgpu`]: https://github.com/gfx-rs/wgpu-rs
//! [WebGPU API]: https://gpuweb.github.io/gpuweb/
//! [`wgpu_glyph`]: https://github.com/hecrj/wgpu_glyph
-#![deny(missing_docs)]
+//#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![deny(unused_results)]
#![forbid(unsafe_code)]
#![forbid(rust_2018_idioms)]
#![cfg_attr(docsrs, feature(doc_cfg))]
-pub mod defaults;
pub mod settings;
pub mod triangle;
pub mod widget;
pub mod window;
-mod primitive;
+mod backend;
mod quad;
-mod renderer;
mod target;
mod text;
mod transformation;
mod viewport;
+pub use iced_graphics::{Defaults, Primitive};
pub use wgpu;
-pub use defaults::Defaults;
-pub use primitive::Primitive;
-pub use renderer::Renderer;
+pub use backend::Backend;
pub use settings::Settings;
pub use target::Target;
pub use viewport::Viewport;
@@ -56,5 +53,7 @@ pub use widget::*;
pub(crate) use quad::Quad;
pub(crate) use transformation::Transformation;
+pub type Renderer = iced_graphics::Renderer<Backend>;
+
#[cfg(any(feature = "image", feature = "svg"))]
mod image;
diff --git a/wgpu/src/primitive.rs b/wgpu/src/primitive.rs
deleted file mode 100644
index e73227ef..00000000
--- a/wgpu/src/primitive.rs
+++ /dev/null
@@ -1,107 +0,0 @@
-use iced_native::{
- image, svg, Background, Color, Font, HorizontalAlignment, Rectangle, Size,
- Vector, VerticalAlignment,
-};
-
-use crate::triangle;
-use std::sync::Arc;
-
-/// A rendering primitive.
-#[derive(Debug, Clone)]
-pub enum Primitive {
- /// An empty primitive
- None,
- /// A group of primitives
- Group {
- /// The primitives of the group
- primitives: Vec<Primitive>,
- },
- /// A text primitive
- Text {
- /// The contents of the text
- content: String,
- /// The bounds of the text
- bounds: Rectangle,
- /// The color of the text
- color: Color,
- /// The size of the text
- size: f32,
- /// The font of the text
- font: Font,
- /// The horizontal alignment of the text
- horizontal_alignment: HorizontalAlignment,
- /// The vertical alignment of the text
- vertical_alignment: VerticalAlignment,
- },
- /// A quad primitive
- Quad {
- /// The bounds of the quad
- bounds: Rectangle,
- /// The background of the quad
- background: Background,
- /// The border radius of the quad
- border_radius: u16,
- /// The border width of the quad
- border_width: u16,
- /// The border color of the quad
- border_color: Color,
- },
- /// An image primitive
- Image {
- /// The handle of the image
- handle: image::Handle,
- /// The bounds of the image
- bounds: Rectangle,
- },
- /// An SVG primitive
- Svg {
- /// The path of the SVG file
- handle: svg::Handle,
-
- /// The bounds of the viewport
- bounds: Rectangle,
- },
- /// A clip primitive
- Clip {
- /// The bounds of the clip
- bounds: Rectangle,
- /// The offset transformation of the clip
- offset: Vector<u32>,
- /// The content of the clip
- content: Box<Primitive>,
- },
- /// A primitive that applies a translation
- Translate {
- /// The translation vector
- translation: Vector,
-
- /// The primitive to translate
- content: Box<Primitive>,
- },
- /// A low-level primitive to render a mesh of triangles.
- ///
- /// It can be used to render many kinds of geometry freely.
- Mesh2D {
- /// The size of the drawable region of the mesh.
- ///
- /// Any geometry that falls out of this region will be clipped.
- size: Size,
-
- /// The vertex and index buffers of the mesh
- buffers: triangle::Mesh2D,
- },
- /// A cached primitive.
- ///
- /// This can be useful if you are implementing a widget where primitive
- /// generation is expensive.
- Cached {
- /// The cached primitive
- cache: Arc<Primitive>,
- },
-}
-
-impl Default for Primitive {
- fn default() -> Primitive {
- Primitive::None
- }
-}
diff --git a/wgpu/src/renderer/widget.rs b/wgpu/src/renderer/widget.rs
deleted file mode 100644
index 37421fbe..00000000
--- a/wgpu/src/renderer/widget.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-mod button;
-mod checkbox;
-mod column;
-mod container;
-mod pane_grid;
-mod progress_bar;
-mod radio;
-mod row;
-mod scrollable;
-mod slider;
-mod space;
-mod text;
-mod text_input;
-
-#[cfg(feature = "svg")]
-mod svg;
-
-#[cfg(feature = "image")]
-mod image;
diff --git a/wgpu/src/renderer/widget/button.rs b/wgpu/src/renderer/widget/button.rs
deleted file mode 100644
index eb225038..00000000
--- a/wgpu/src/renderer/widget/button.rs
+++ /dev/null
@@ -1,93 +0,0 @@
-use crate::{button::StyleSheet, defaults, Defaults, Primitive, Renderer};
-use iced_native::{
- mouse, Background, Color, Element, Layout, Point, Rectangle, Vector,
-};
-
-impl iced_native::button::Renderer for Renderer {
- const DEFAULT_PADDING: u16 = 5;
-
- type Style = Box<dyn StyleSheet>;
-
- fn draw<Message>(
- &mut self,
- _defaults: &Defaults,
- bounds: Rectangle,
- cursor_position: Point,
- is_disabled: bool,
- is_pressed: bool,
- style: &Box<dyn StyleSheet>,
- content: &Element<'_, Message, Self>,
- content_layout: Layout<'_>,
- ) -> Self::Output {
- let is_mouse_over = bounds.contains(cursor_position);
-
- let styling = if is_disabled {
- style.disabled()
- } else if is_mouse_over {
- if is_pressed {
- style.pressed()
- } else {
- style.hovered()
- }
- } else {
- style.active()
- };
-
- let (content, _) = content.draw(
- self,
- &Defaults {
- text: defaults::Text {
- color: styling.text_color,
- },
- },
- content_layout,
- cursor_position,
- );
-
- (
- if styling.background.is_some() || styling.border_width > 0 {
- let background = Primitive::Quad {
- bounds,
- background: styling
- .background
- .unwrap_or(Background::Color(Color::TRANSPARENT)),
- border_radius: styling.border_radius,
- border_width: styling.border_width,
- border_color: styling.border_color,
- };
-
- if styling.shadow_offset == Vector::default() {
- Primitive::Group {
- primitives: vec![background, content],
- }
- } else {
- // TODO: Implement proper shadow support
- let shadow = Primitive::Quad {
- bounds: Rectangle {
- x: bounds.x + styling.shadow_offset.x,
- y: bounds.y + styling.shadow_offset.y,
- ..bounds
- },
- background: Background::Color(
- [0.0, 0.0, 0.0, 0.5].into(),
- ),
- border_radius: styling.border_radius,
- border_width: 0,
- border_color: Color::TRANSPARENT,
- };
-
- Primitive::Group {
- primitives: vec![shadow, background, content],
- }
- }
- } else {
- content
- },
- if is_mouse_over {
- mouse::Interaction::Pointer
- } else {
- mouse::Interaction::default()
- },
- )
- }
-}
diff --git a/wgpu/src/renderer/widget/checkbox.rs b/wgpu/src/renderer/widget/checkbox.rs
deleted file mode 100644
index 0340bf62..00000000
--- a/wgpu/src/renderer/widget/checkbox.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-use crate::{checkbox::StyleSheet, Primitive, Renderer};
-use iced_native::{
- checkbox, mouse, HorizontalAlignment, Rectangle, VerticalAlignment,
-};
-
-impl checkbox::Renderer for Renderer {
- type Style = Box<dyn StyleSheet>;
-
- const DEFAULT_SIZE: u16 = 20;
- const DEFAULT_SPACING: u16 = 15;
-
- fn draw(
- &mut self,
- bounds: Rectangle,
- is_checked: bool,
- is_mouse_over: bool,
- (label, _): Self::Output,
- style_sheet: &Self::Style,
- ) -> Self::Output {
- let style = if is_mouse_over {
- style_sheet.hovered(is_checked)
- } else {
- style_sheet.active(is_checked)
- };
-
- let checkbox = Primitive::Quad {
- bounds,
- background: style.background,
- border_radius: style.border_radius,
- border_width: style.border_width,
- border_color: style.border_color,
- };
-
- (
- Primitive::Group {
- primitives: if is_checked {
- let check = Primitive::Text {
- content: crate::text::CHECKMARK_ICON.to_string(),
- font: crate::text::BUILTIN_ICONS,
- size: bounds.height * 0.7,
- bounds: Rectangle {
- x: bounds.center_x(),
- y: bounds.center_y(),
- ..bounds
- },
- color: style.checkmark_color,
- horizontal_alignment: HorizontalAlignment::Center,
- vertical_alignment: VerticalAlignment::Center,
- };
-
- vec![checkbox, check, label]
- } else {
- vec![checkbox, label]
- },
- },
- if is_mouse_over {
- mouse::Interaction::Pointer
- } else {
- mouse::Interaction::default()
- },
- )
- }
-}
diff --git a/wgpu/src/renderer/widget/column.rs b/wgpu/src/renderer/widget/column.rs
deleted file mode 100644
index b853276d..00000000
--- a/wgpu/src/renderer/widget/column.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-use crate::{Primitive, Renderer};
-use iced_native::{column, mouse, Element, Layout, Point};
-
-impl column::Renderer for Renderer {
- fn draw<Message>(
- &mut self,
- defaults: &Self::Defaults,
- content: &[Element<'_, Message, Self>],
- layout: Layout<'_>,
- cursor_position: Point,
- ) -> Self::Output {
- let mut mouse_interaction = mouse::Interaction::default();
-
- (
- Primitive::Group {
- primitives: content
- .iter()
- .zip(layout.children())
- .map(|(child, layout)| {
- let (primitive, new_mouse_interaction) =
- child.draw(self, defaults, layout, cursor_position);
-
- if new_mouse_interaction > mouse_interaction {
- mouse_interaction = new_mouse_interaction;
- }
-
- primitive
- })
- .collect(),
- },
- mouse_interaction,
- )
- }
-}
diff --git a/wgpu/src/renderer/widget/container.rs b/wgpu/src/renderer/widget/container.rs
deleted file mode 100644
index 30cc3f07..00000000
--- a/wgpu/src/renderer/widget/container.rs
+++ /dev/null
@@ -1,48 +0,0 @@
-use crate::{container, defaults, Defaults, Primitive, Renderer};
-use iced_native::{Background, Color, Element, Layout, Point, Rectangle};
-
-impl iced_native::container::Renderer for Renderer {
- type Style = Box<dyn container::StyleSheet>;
-
- fn draw<Message>(
- &mut self,
- defaults: &Defaults,
- bounds: Rectangle,
- cursor_position: Point,
- style_sheet: &Self::Style,
- content: &Element<'_, Message, Self>,
- content_layout: Layout<'_>,
- ) -> Self::Output {
- let style = style_sheet.style();
-
- let defaults = Defaults {
- text: defaults::Text {
- color: style.text_color.unwrap_or(defaults.text.color),
- },
- };
-
- let (content, mouse_interaction) =
- content.draw(self, &defaults, content_layout, cursor_position);
-
- if style.background.is_some() || style.border_width > 0 {
- let quad = Primitive::Quad {
- bounds,
- background: style
- .background
- .unwrap_or(Background::Color(Color::TRANSPARENT)),
- border_radius: style.border_radius,
- border_width: style.border_width,
- border_color: style.border_color,
- };
-
- (
- Primitive::Group {
- primitives: vec![quad, content],
- },
- mouse_interaction,
- )
- } else {
- (content, mouse_interaction)
- }
- }
-}
diff --git a/wgpu/src/renderer/widget/image.rs b/wgpu/src/renderer/widget/image.rs
deleted file mode 100644
index c4c04984..00000000
--- a/wgpu/src/renderer/widget/image.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-use crate::{Primitive, Renderer};
-use iced_native::{image, mouse, Layout};
-
-impl image::Renderer for Renderer {
- fn dimensions(&self, handle: &image::Handle) -> (u32, u32) {
- self.image_pipeline.dimensions(handle)
- }
-
- fn draw(
- &mut self,
- handle: image::Handle,
- layout: Layout<'_>,
- ) -> Self::Output {
- (
- Primitive::Image {
- handle,
- bounds: layout.bounds(),
- },
- mouse::Interaction::default(),
- )
- }
-}
diff --git a/wgpu/src/renderer/widget/pane_grid.rs b/wgpu/src/renderer/widget/pane_grid.rs
deleted file mode 100644
index 2253e4af..00000000
--- a/wgpu/src/renderer/widget/pane_grid.rs
+++ /dev/null
@@ -1,93 +0,0 @@
-use crate::{Primitive, Renderer};
-use iced_native::{
- mouse,
- pane_grid::{self, Axis, Pane},
- Element, Layout, Point, Rectangle, Vector,
-};
-
-impl pane_grid::Renderer for Renderer {
- fn draw<Message>(
- &mut self,
- defaults: &Self::Defaults,
- content: &[(Pane, Element<'_, Message, Self>)],
- dragging: Option<Pane>,
- resizing: Option<Axis>,
- layout: Layout<'_>,
- cursor_position: Point,
- ) -> Self::Output {
- let pane_cursor_position = if dragging.is_some() {
- // TODO: Remove once cursor availability is encoded in the type
- // system
- Point::new(-1.0, -1.0)
- } else {
- cursor_position
- };
-
- let mut mouse_interaction = mouse::Interaction::default();
- let mut dragged_pane = None;
-
- let mut panes: Vec<_> = content
- .iter()
- .zip(layout.children())
- .enumerate()
- .map(|(i, ((id, pane), layout))| {
- let (primitive, new_mouse_interaction) =
- pane.draw(self, defaults, layout, pane_cursor_position);
-
- if new_mouse_interaction > mouse_interaction {
- mouse_interaction = new_mouse_interaction;
- }
-
- if Some(*id) == dragging {
- dragged_pane = Some((i, layout));
- }
-
- primitive
- })
- .collect();
-
- let primitives = if let Some((index, layout)) = dragged_pane {
- let pane = panes.remove(index);
- let bounds = layout.bounds();
-
- // TODO: Fix once proper layering is implemented.
- // This is a pretty hacky way to achieve layering.
- let clip = Primitive::Clip {
- bounds: Rectangle {
- x: cursor_position.x - bounds.width / 2.0,
- y: cursor_position.y - bounds.height / 2.0,
- width: bounds.width + 0.5,
- height: bounds.height + 0.5,
- },
- offset: Vector::new(0, 0),
- content: Box::new(Primitive::Translate {
- translation: Vector::new(
- cursor_position.x - bounds.x - bounds.width / 2.0,
- cursor_position.y - bounds.y - bounds.height / 2.0,
- ),
- content: Box::new(pane),
- }),
- };
-
- panes.push(clip);
-
- panes
- } else {
- panes
- };
-
- (
- Primitive::Group { primitives },
- if dragging.is_some() {
- mouse::Interaction::Grabbing
- } else if let Some(axis) = resizing {
- match axis {
- Axis::Horizontal => mouse::Interaction::ResizingVertically,
- Axis::Vertical => mouse::Interaction::ResizingHorizontally,
- }
- } else {
- mouse_interaction
- },
- )
- }
-}
diff --git a/wgpu/src/renderer/widget/progress_bar.rs b/wgpu/src/renderer/widget/progress_bar.rs
deleted file mode 100644
index 2baeeb14..00000000
--- a/wgpu/src/renderer/widget/progress_bar.rs
+++ /dev/null
@@ -1,54 +0,0 @@
-use crate::{progress_bar::StyleSheet, Primitive, Renderer};
-use iced_native::{mouse, progress_bar, Color, Rectangle};
-
-impl progress_bar::Renderer for Renderer {
- type Style = Box<dyn StyleSheet>;
-
- const DEFAULT_HEIGHT: u16 = 30;
-
- fn draw(
- &self,
- bounds: Rectangle,
- range: std::ops::RangeInclusive<f32>,
- value: f32,
- style_sheet: &Self::Style,
- ) -> Self::Output {
- let style = style_sheet.style();
-
- let (range_start, range_end) = range.into_inner();
- let active_progress_width = bounds.width
- * ((value - range_start) / (range_end - range_start).max(1.0));
-
- let background = Primitive::Group {
- primitives: vec![Primitive::Quad {
- bounds: Rectangle { ..bounds },
- background: style.background,
- border_radius: style.border_radius,
- border_width: 0,
- border_color: Color::TRANSPARENT,
- }],
- };
-
- (
- if active_progress_width > 0.0 {
- let bar = Primitive::Quad {
- bounds: Rectangle {
- width: active_progress_width,
- ..bounds
- },
- background: style.bar,
- border_radius: style.border_radius,
- border_width: 0,
- border_color: Color::TRANSPARENT,
- };
-
- Primitive::Group {
- primitives: vec![background, bar],
- }
- } else {
- background
- },
- mouse::Interaction::default(),
- )
- }
-}
diff --git a/wgpu/src/renderer/widget/radio.rs b/wgpu/src/renderer/widget/radio.rs
deleted file mode 100644
index cee0deb6..00000000
--- a/wgpu/src/renderer/widget/radio.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-use crate::{radio::StyleSheet, Primitive, Renderer};
-use iced_native::{mouse, radio, Background, Color, Rectangle};
-
-const SIZE: f32 = 28.0;
-const DOT_SIZE: f32 = SIZE / 2.0;
-
-impl radio::Renderer for Renderer {
- type Style = Box<dyn StyleSheet>;
-
- const DEFAULT_SIZE: u16 = SIZE as u16;
- const DEFAULT_SPACING: u16 = 15;
-
- fn draw(
- &mut self,
- bounds: Rectangle,
- is_selected: bool,
- is_mouse_over: bool,
- (label, _): Self::Output,
- style_sheet: &Self::Style,
- ) -> Self::Output {
- let style = if is_mouse_over {
- style_sheet.hovered()
- } else {
- style_sheet.active()
- };
-
- let radio = Primitive::Quad {
- bounds,
- background: style.background,
- border_radius: (SIZE / 2.0) as u16,
- border_width: style.border_width,
- border_color: style.border_color,
- };
-
- (
- Primitive::Group {
- primitives: if is_selected {
- let radio_circle = Primitive::Quad {
- bounds: Rectangle {
- x: bounds.x + DOT_SIZE / 2.0,
- y: bounds.y + DOT_SIZE / 2.0,
- width: bounds.width - DOT_SIZE,
- height: bounds.height - DOT_SIZE,
- },
- background: Background::Color(style.dot_color),
- border_radius: (DOT_SIZE / 2.0) as u16,
- border_width: 0,
- border_color: Color::TRANSPARENT,
- };
-
- vec![radio, radio_circle, label]
- } else {
- vec![radio, label]
- },
- },
- if is_mouse_over {
- mouse::Interaction::Pointer
- } else {
- mouse::Interaction::default()
- },
- )
- }
-}
diff --git a/wgpu/src/renderer/widget/row.rs b/wgpu/src/renderer/widget/row.rs
deleted file mode 100644
index d0b7ef09..00000000
--- a/wgpu/src/renderer/widget/row.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-use crate::{Primitive, Renderer};
-use iced_native::{mouse, row, Element, Layout, Point};
-
-impl row::Renderer for Renderer {
- fn draw<Message>(
- &mut self,
- defaults: &Self::Defaults,
- children: &[Element<'_, Message, Self>],
- layout: Layout<'_>,
- cursor_position: Point,
- ) -> Self::Output {
- let mut mouse_interaction = mouse::Interaction::default();
-
- (
- Primitive::Group {
- primitives: children
- .iter()
- .zip(layout.children())
- .map(|(child, layout)| {
- let (primitive, new_mouse_interaction) =
- child.draw(self, defaults, layout, cursor_position);
-
- if new_mouse_interaction > mouse_interaction {
- mouse_interaction = new_mouse_interaction;
- }
-
- primitive
- })
- .collect(),
- },
- mouse_interaction,
- )
- }
-}
diff --git a/wgpu/src/renderer/widget/scrollable.rs b/wgpu/src/renderer/widget/scrollable.rs
deleted file mode 100644
index 8a400b82..00000000
--- a/wgpu/src/renderer/widget/scrollable.rs
+++ /dev/null
@@ -1,125 +0,0 @@
-use crate::{Primitive, Renderer};
-use iced_native::{mouse, scrollable, Background, Color, Rectangle, Vector};
-
-const SCROLLBAR_WIDTH: u16 = 10;
-const SCROLLBAR_MARGIN: u16 = 2;
-
-impl scrollable::Renderer for Renderer {
- type Style = Box<dyn iced_style::scrollable::StyleSheet>;
-
- fn scrollbar(
- &self,
- bounds: Rectangle,
- content_bounds: Rectangle,
- offset: u32,
- ) -> Option<scrollable::Scrollbar> {
- if content_bounds.height > bounds.height {
- let scrollbar_bounds = Rectangle {
- x: bounds.x + bounds.width
- - f32::from(SCROLLBAR_WIDTH + 2 * SCROLLBAR_MARGIN),
- y: bounds.y,
- width: f32::from(SCROLLBAR_WIDTH + 2 * SCROLLBAR_MARGIN),
- height: bounds.height,
- };
-
- let ratio = bounds.height / content_bounds.height;
- let scrollbar_height = bounds.height * ratio;
- let y_offset = offset as f32 * ratio;
-
- let scroller_bounds = Rectangle {
- x: scrollbar_bounds.x + f32::from(SCROLLBAR_MARGIN),
- y: scrollbar_bounds.y + y_offset,
- width: scrollbar_bounds.width - f32::from(2 * SCROLLBAR_MARGIN),
- height: scrollbar_height,
- };
-
- Some(scrollable::Scrollbar {
- bounds: scrollbar_bounds,
- scroller: scrollable::Scroller {
- bounds: scroller_bounds,
- },
- })
- } else {
- None
- }
- }
-
- fn draw(
- &mut self,
- state: &scrollable::State,
- bounds: Rectangle,
- _content_bounds: Rectangle,
- is_mouse_over: bool,
- is_mouse_over_scrollbar: bool,
- scrollbar: Option<scrollable::Scrollbar>,
- offset: u32,
- style_sheet: &Self::Style,
- (content, mouse_interaction): Self::Output,
- ) -> Self::Output {
- (
- if let Some(scrollbar) = scrollbar {
- let clip = Primitive::Clip {
- bounds,
- offset: Vector::new(0, offset),
- content: Box::new(content),
- };
-
- let style = if state.is_scroller_grabbed() {
- style_sheet.dragging()
- } else if is_mouse_over_scrollbar {
- style_sheet.hovered()
- } else {
- style_sheet.active()
- };
-
- let is_scrollbar_visible =
- style.background.is_some() || style.border_width > 0;
-
- let scroller = if is_mouse_over
- || state.is_scroller_grabbed()
- || is_scrollbar_visible
- {
- Primitive::Quad {
- bounds: scrollbar.scroller.bounds,
- background: Background::Color(style.scroller.color),
- border_radius: style.scroller.border_radius,
- border_width: style.scroller.border_width,
- border_color: style.scroller.border_color,
- }
- } else {
- Primitive::None
- };
-
- let scrollbar = if is_scrollbar_visible {
- Primitive::Quad {
- bounds: Rectangle {
- x: scrollbar.bounds.x + f32::from(SCROLLBAR_MARGIN),
- width: scrollbar.bounds.width
- - f32::from(2 * SCROLLBAR_MARGIN),
- ..scrollbar.bounds
- },
- background: style
- .background
- .unwrap_or(Background::Color(Color::TRANSPARENT)),
- border_radius: style.border_radius,
- border_width: style.border_width,
- border_color: style.border_color,
- }
- } else {
- Primitive::None
- };
-
- Primitive::Group {
- primitives: vec![clip, scrollbar, scroller],
- }
- } else {
- content
- },
- if is_mouse_over_scrollbar || state.is_scroller_grabbed() {
- mouse::Interaction::Idle
- } else {
- mouse_interaction
- },
- )
- }
-}
diff --git a/wgpu/src/renderer/widget/slider.rs b/wgpu/src/renderer/widget/slider.rs
deleted file mode 100644
index 220feace..00000000
--- a/wgpu/src/renderer/widget/slider.rs
+++ /dev/null
@@ -1,106 +0,0 @@
-use crate::{
- slider::{HandleShape, StyleSheet},
- Primitive, Renderer,
-};
-use iced_native::{mouse, slider, Background, Color, Point, Rectangle};
-
-const HANDLE_HEIGHT: f32 = 22.0;
-
-impl slider::Renderer for Renderer {
- type Style = Box<dyn StyleSheet>;
-
- fn height(&self) -> u32 {
- 30
- }
-
- fn draw(
- &mut self,
- bounds: Rectangle,
- cursor_position: Point,
- range: std::ops::RangeInclusive<f32>,
- value: f32,
- is_dragging: bool,
- style_sheet: &Self::Style,
- ) -> Self::Output {
- let is_mouse_over = bounds.contains(cursor_position);
-
- let style = if is_dragging {
- style_sheet.dragging()
- } else if is_mouse_over {
- style_sheet.hovered()
- } else {
- style_sheet.active()
- };
-
- let rail_y = bounds.y + (bounds.height / 2.0).round();
-
- let (rail_top, rail_bottom) = (
- Primitive::Quad {
- bounds: Rectangle {
- x: bounds.x,
- y: rail_y,
- width: bounds.width,
- height: 2.0,
- },
- background: Background::Color(style.rail_colors.0),
- border_radius: 0,
- border_width: 0,
- border_color: Color::TRANSPARENT,
- },
- Primitive::Quad {
- bounds: Rectangle {
- x: bounds.x,
- y: rail_y + 2.0,
- width: bounds.width,
- height: 2.0,
- },
- background: Background::Color(style.rail_colors.1),
- border_radius: 0,
- border_width: 0,
- border_color: Color::TRANSPARENT,
- },
- );
-
- let (range_start, range_end) = range.into_inner();
-
- let (handle_width, handle_height, handle_border_radius) =
- match style.handle.shape {
- HandleShape::Circle { radius } => {
- (f32::from(radius * 2), f32::from(radius * 2), radius)
- }
- HandleShape::Rectangle {
- width,
- border_radius,
- } => (f32::from(width), HANDLE_HEIGHT, border_radius),
- };
-
- let handle_offset = (bounds.width - handle_width)
- * ((value - range_start) / (range_end - range_start).max(1.0));
-
- let handle = Primitive::Quad {
- bounds: Rectangle {
- x: bounds.x + handle_offset.round(),
- y: rail_y - handle_height / 2.0,
- width: handle_width,
- height: handle_height,
- },
- background: Background::Color(style.handle.color),
- border_radius: handle_border_radius,
- border_width: style.handle.border_width,
- border_color: style.handle.border_color,
- };
-
- (
- Primitive::Group {
- primitives: vec![rail_top, rail_bottom, handle],
- },
- if is_dragging {
- mouse::Interaction::Grabbing
- } else if is_mouse_over {
- mouse::Interaction::Grab
- } else {
- mouse::Interaction::default()
- },
- )
- }
-}
diff --git a/wgpu/src/renderer/widget/space.rs b/wgpu/src/renderer/widget/space.rs
deleted file mode 100644
index 225f7e6c..00000000
--- a/wgpu/src/renderer/widget/space.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-use crate::{Primitive, Renderer};
-use iced_native::{mouse, space, Rectangle};
-
-impl space::Renderer for Renderer {
- fn draw(&mut self, _bounds: Rectangle) -> Self::Output {
- (Primitive::None, mouse::Interaction::default())
- }
-}
diff --git a/wgpu/src/renderer/widget/svg.rs b/wgpu/src/renderer/widget/svg.rs
deleted file mode 100644
index f6d6d0ba..00000000
--- a/wgpu/src/renderer/widget/svg.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-use crate::{Primitive, Renderer};
-use iced_native::{mouse, svg, Layout};
-
-impl svg::Renderer for Renderer {
- fn dimensions(&self, handle: &svg::Handle) -> (u32, u32) {
- self.image_pipeline.viewport_dimensions(handle)
- }
-
- fn draw(
- &mut self,
- handle: svg::Handle,
- layout: Layout<'_>,
- ) -> Self::Output {
- (
- Primitive::Svg {
- handle,
- bounds: layout.bounds(),
- },
- mouse::Interaction::default(),
- )
- }
-}
diff --git a/wgpu/src/renderer/widget/text.rs b/wgpu/src/renderer/widget/text.rs
deleted file mode 100644
index 4605ed06..00000000
--- a/wgpu/src/renderer/widget/text.rs
+++ /dev/null
@@ -1,61 +0,0 @@
-use crate::{Primitive, Renderer};
-use iced_native::{
- mouse, text, Color, Font, HorizontalAlignment, Rectangle, Size,
- VerticalAlignment,
-};
-
-use std::f32;
-
-impl text::Renderer for Renderer {
- type Font = Font;
-
- const DEFAULT_SIZE: u16 = 20;
-
- fn measure(
- &self,
- content: &str,
- size: u16,
- font: Font,
- bounds: Size,
- ) -> (f32, f32) {
- self.text_pipeline
- .measure(content, f32::from(size), font, bounds)
- }
-
- fn draw(
- &mut self,
- defaults: &Self::Defaults,
- bounds: Rectangle,
- content: &str,
- size: u16,
- font: Font,
- color: Option<Color>,
- horizontal_alignment: HorizontalAlignment,
- vertical_alignment: VerticalAlignment,
- ) -> Self::Output {
- let x = match horizontal_alignment {
- iced_native::HorizontalAlignment::Left => bounds.x,
- iced_native::HorizontalAlignment::Center => bounds.center_x(),
- iced_native::HorizontalAlignment::Right => bounds.x + bounds.width,
- };
-
- let y = match vertical_alignment {
- iced_native::VerticalAlignment::Top => bounds.y,
- iced_native::VerticalAlignment::Center => bounds.center_y(),
- iced_native::VerticalAlignment::Bottom => bounds.y + bounds.height,
- };
-
- (
- Primitive::Text {
- content: content.to_string(),
- size: f32::from(size),
- bounds: Rectangle { x, y, ..bounds },
- color: color.unwrap_or(defaults.text.color),
- font,
- horizontal_alignment,
- vertical_alignment,
- },
- mouse::Interaction::default(),
- )
- }
-}
diff --git a/wgpu/src/renderer/widget/text_input.rs b/wgpu/src/renderer/widget/text_input.rs
deleted file mode 100644
index 57be6692..00000000
--- a/wgpu/src/renderer/widget/text_input.rs
+++ /dev/null
@@ -1,261 +0,0 @@
-use crate::{text_input::StyleSheet, Primitive, Renderer};
-
-use iced_native::{
- mouse,
- text_input::{self, cursor},
- Background, Color, Font, HorizontalAlignment, Point, Rectangle, Size,
- Vector, VerticalAlignment,
-};
-use std::f32;
-
-impl text_input::Renderer for Renderer {
- type Style = Box<dyn StyleSheet>;
-
- fn default_size(&self) -> u16 {
- // TODO: Make this configurable
- 20
- }
-
- fn measure_value(&self, value: &str, size: u16, font: Font) -> f32 {
- let (mut width, _) = self.text_pipeline.measure(
- value,
- f32::from(size),
- font,
- Size::INFINITY,
- );
-
- let spaces_around = value.len() - value.trim().len();
-
- if spaces_around > 0 {
- let space_width = self.text_pipeline.space_width(size as f32);
- width += spaces_around as f32 * space_width;
- }
-
- width
- }
-
- fn offset(
- &self,
- text_bounds: Rectangle,
- font: Font,
- size: u16,
- value: &text_input::Value,
- state: &text_input::State,
- ) -> f32 {
- if state.is_focused() {
- let cursor = state.cursor();
-
- let focus_position = match cursor.state(value) {
- cursor::State::Index(i) => i,
- cursor::State::Selection { end, .. } => end,
- };
-
- let (_, offset) = measure_cursor_and_scroll_offset(
- self,
- text_bounds,
- value,
- size,
- focus_position,
- font,
- );
-
- offset
- } else {
- 0.0
- }
- }
-
- fn draw(
- &mut self,
- bounds: Rectangle,
- text_bounds: Rectangle,
- cursor_position: Point,
- font: Font,
- size: u16,
- placeholder: &str,
- value: &text_input::Value,
- state: &text_input::State,
- style_sheet: &Self::Style,
- ) -> Self::Output {
- let is_mouse_over = bounds.contains(cursor_position);
-
- let style = if state.is_focused() {
- style_sheet.focused()
- } else if is_mouse_over {
- style_sheet.hovered()
- } else {
- style_sheet.active()
- };
-
- let input = Primitive::Quad {
- bounds,
- background: style.background,
- border_radius: style.border_radius,
- border_width: style.border_width,
- border_color: style.border_color,
- };
-
- let text = value.to_string();
-
- let text_value = Primitive::Text {
- content: if text.is_empty() {
- placeholder.to_string()
- } else {
- text.clone()
- },
- color: if text.is_empty() {
- style_sheet.placeholder_color()
- } else {
- style_sheet.value_color()
- },
- font,
- bounds: Rectangle {
- y: text_bounds.center_y(),
- width: f32::INFINITY,
- ..text_bounds
- },
- size: f32::from(size),
- horizontal_alignment: HorizontalAlignment::Left,
- vertical_alignment: VerticalAlignment::Center,
- };
-
- let (contents_primitive, offset) = if state.is_focused() {
- let cursor = state.cursor();
-
- let (cursor_primitive, offset) = match cursor.state(value) {
- cursor::State::Index(position) => {
- let (text_value_width, offset) =
- measure_cursor_and_scroll_offset(
- self,
- text_bounds,
- value,
- size,
- position,
- font,
- );
-
- (
- Primitive::Quad {
- bounds: Rectangle {
- x: text_bounds.x + text_value_width,
- y: text_bounds.y,
- width: 1.0,
- height: text_bounds.height,
- },
- background: Background::Color(
- style_sheet.value_color(),
- ),
- border_radius: 0,
- border_width: 0,
- border_color: Color::TRANSPARENT,
- },
- offset,
- )
- }
- cursor::State::Selection { start, end } => {
- let left = start.min(end);
- let right = end.max(start);
-
- let (left_position, left_offset) =
- measure_cursor_and_scroll_offset(
- self,
- text_bounds,
- value,
- size,
- left,
- font,
- );
-
- let (right_position, right_offset) =
- measure_cursor_and_scroll_offset(
- self,
- text_bounds,
- value,
- size,
- right,
- font,
- );
-
- let width = right_position - left_position;
-
- (
- Primitive::Quad {
- bounds: Rectangle {
- x: text_bounds.x + left_position,
- y: text_bounds.y,
- width,
- height: text_bounds.height,
- },
- background: Background::Color(
- style_sheet.selection_color(),
- ),
- border_radius: 0,
- border_width: 0,
- border_color: Color::TRANSPARENT,
- },
- if end == right {
- right_offset
- } else {
- left_offset
- },
- )
- }
- };
-
- (
- Primitive::Group {
- primitives: vec![cursor_primitive, text_value],
- },
- Vector::new(offset as u32, 0),
- )
- } else {
- (text_value, Vector::new(0, 0))
- };
-
- let text_width = self.measure_value(
- if text.is_empty() { placeholder } else { &text },
- size,
- font,
- );
-
- let contents = if text_width > text_bounds.width {
- Primitive::Clip {
- bounds: text_bounds,
- offset,
- content: Box::new(contents_primitive),
- }
- } else {
- contents_primitive
- };
-
- (
- Primitive::Group {
- primitives: vec![input, contents],
- },
- if is_mouse_over {
- mouse::Interaction::Text
- } else {
- mouse::Interaction::default()
- },
- )
- }
-}
-
-fn measure_cursor_and_scroll_offset(
- renderer: &Renderer,
- text_bounds: Rectangle,
- value: &text_input::Value,
- size: u16,
- cursor_index: usize,
- font: Font,
-) -> (f32, f32) {
- use iced_native::text_input::Renderer;
-
- let text_before_cursor = value.until(cursor_index).to_string();
-
- let text_value_width =
- renderer.measure_value(&text_before_cursor, size, font);
- let offset = ((text_value_width + 5.0) - text_bounds.width).max(0.0);
-
- (text_value_width, offset)
-}
diff --git a/wgpu/src/text.rs b/wgpu/src/text.rs
index f4521e72..8bcd6d83 100644
--- a/wgpu/src/text.rs
+++ b/wgpu/src/text.rs
@@ -138,7 +138,7 @@ impl Pipeline {
.advance_width
}
- pub fn clear_measurement_cache(&mut self) {
+ pub fn trim_measurement_cache(&mut self) {
// TODO: We should probably use a `GlyphCalculator` for this. However,
// it uses a lifetimed `GlyphCalculatorGuard` with side-effects on drop.
// This makes stuff quite inconvenient. A manual method for trimming the
diff --git a/wgpu/src/triangle.rs b/wgpu/src/triangle.rs
index 3e68a269..a71bcedc 100644
--- a/wgpu/src/triangle.rs
+++ b/wgpu/src/triangle.rs
@@ -4,6 +4,8 @@ use iced_native::{Rectangle, Vector};
use std::mem;
use zerocopy::AsBytes;
+pub use iced_graphics::triangle::{Mesh2D, Vertex2D};
+
mod msaa;
const UNIFORM_BUFFER_SIZE: usize = 100;
@@ -236,7 +238,7 @@ impl Pipeline {
.into();
let vertex_buffer = device.create_buffer_with_data(
- mesh.vertices.as_bytes(),
+ bytemuck::cast_slice(&mesh.vertices),
wgpu::BufferUsage::COPY_SRC,
);
@@ -387,26 +389,3 @@ impl From<Transformation> for Uniforms {
}
}
}
-
-/// A two-dimensional vertex with some color in __linear__ RGBA.
-#[repr(C)]
-#[derive(Copy, Clone, Debug, AsBytes)]
-pub struct Vertex2D {
- /// The vertex position
- pub position: [f32; 2],
- /// The vertex color in __linear__ RGBA.
- pub color: [f32; 4],
-}
-
-/// A set of [`Vertex2D`] and indices representing a list of triangles.
-///
-/// [`Vertex2D`]: struct.Vertex2D.html
-#[derive(Clone, Debug)]
-pub struct Mesh2D {
- /// The vertices of the mesh
- pub vertices: Vec<Vertex2D>,
- /// The list of vertex indices that defines the triangles of the mesh.
- ///
- /// Therefore, this list should always have a length that is a multiple of 3.
- pub indices: Vec<u32>,
-}
diff --git a/wgpu/src/widget/button.rs b/wgpu/src/widget/button.rs
index b738c55e..fee7a7f8 100644
--- a/wgpu/src/widget/button.rs
+++ b/wgpu/src/widget/button.rs
@@ -6,8 +6,8 @@
//! [`State`]: struct.State.html
use crate::Renderer;
+pub use iced_graphics::button::{Style, StyleSheet};
pub use iced_native::button::State;
-pub use iced_style::button::{Style, StyleSheet};
/// A widget that produces a message when clicked.
///
diff --git a/wgpu/src/widget/canvas.rs b/wgpu/src/widget/canvas.rs
index 2fc10ea0..bef34857 100644
--- a/wgpu/src/widget/canvas.rs
+++ b/wgpu/src/widget/canvas.rs
@@ -6,228 +6,4 @@
//!
//! [`Canvas`]: struct.Canvas.html
//! [`Frame`]: struct.Frame.html
-use crate::{Defaults, Primitive, Renderer};
-
-use iced_native::{
- layout, mouse, Clipboard, Element, Hasher, Layout, Length, Point, Size,
- Vector, Widget,
-};
-use std::hash::Hash;
-use std::marker::PhantomData;
-
-pub mod path;
-
-mod cache;
-mod cursor;
-mod event;
-mod fill;
-mod frame;
-mod geometry;
-mod program;
-mod stroke;
-mod text;
-
-pub use cache::Cache;
-pub use cursor::Cursor;
-pub use event::Event;
-pub use fill::Fill;
-pub use frame::Frame;
-pub use geometry::Geometry;
-pub use path::Path;
-pub use program::Program;
-pub use stroke::{LineCap, LineJoin, Stroke};
-pub use text::Text;
-
-/// A widget capable of drawing 2D graphics.
-///
-/// [`Canvas`]: struct.Canvas.html
-///
-/// # Examples
-/// The repository has a couple of [examples] showcasing how to use a
-/// [`Canvas`]:
-///
-/// - [`clock`], an application that uses the [`Canvas`] widget to draw a clock
-/// and its hands to display the current time.
-/// - [`game_of_life`], an interactive version of the Game of Life, invented by
-/// John Conway.
-/// - [`solar_system`], an animated solar system drawn using the [`Canvas`] widget
-/// and showcasing how to compose different transforms.
-///
-/// [examples]: https://github.com/hecrj/iced/tree/master/examples
-/// [`clock`]: https://github.com/hecrj/iced/tree/master/examples/clock
-/// [`game_of_life`]: https://github.com/hecrj/iced/tree/master/examples/game_of_life
-/// [`solar_system`]: https://github.com/hecrj/iced/tree/master/examples/solar_system
-///
-/// ## Drawing a simple circle
-/// If you want to get a quick overview, here's how we can draw a simple circle:
-///
-/// ```no_run
-/// # mod iced {
-/// # pub use iced_wgpu::canvas;
-/// # pub use iced_native::{Color, Rectangle};
-/// # }
-/// use iced::canvas::{self, Canvas, Cursor, Fill, Frame, Geometry, Path, Program};
-/// use iced::{Color, Rectangle};
-///
-/// // First, we define the data we need for drawing
-/// #[derive(Debug)]
-/// struct Circle {
-/// radius: f32,
-/// }
-///
-/// // Then, we implement the `Program` trait
-/// impl Program<()> for Circle {
-/// fn draw(&self, bounds: Rectangle, _cursor: Cursor) -> Vec<Geometry>{
-/// // We prepare a new `Frame`
-/// let mut frame = Frame::new(bounds.size());
-///
-/// // We create a `Path` representing a simple circle
-/// let circle = Path::circle(frame.center(), self.radius);
-///
-/// // And fill it with some color
-/// frame.fill(&circle, Fill::Color(Color::BLACK));
-///
-/// // Finally, we produce the geometry
-/// vec![frame.into_geometry()]
-/// }
-/// }
-///
-/// // Finally, we simply use our `Circle` to create the `Canvas`!
-/// let canvas = Canvas::new(Circle { radius: 50.0 });
-/// ```
-#[derive(Debug)]
-pub struct Canvas<Message, P: Program<Message>> {
- width: Length,
- height: Length,
- program: P,
- phantom: PhantomData<Message>,
-}
-
-impl<Message, P: Program<Message>> Canvas<Message, P> {
- const DEFAULT_SIZE: u16 = 100;
-
- /// Creates a new [`Canvas`].
- ///
- /// [`Canvas`]: struct.Canvas.html
- pub fn new(program: P) -> Self {
- Canvas {
- width: Length::Units(Self::DEFAULT_SIZE),
- height: Length::Units(Self::DEFAULT_SIZE),
- program,
- phantom: PhantomData,
- }
- }
-
- /// Sets the width of the [`Canvas`].
- ///
- /// [`Canvas`]: struct.Canvas.html
- pub fn width(mut self, width: Length) -> Self {
- self.width = width;
- self
- }
-
- /// Sets the height of the [`Canvas`].
- ///
- /// [`Canvas`]: struct.Canvas.html
- pub fn height(mut self, height: Length) -> Self {
- self.height = height;
- self
- }
-}
-
-impl<Message, P: Program<Message>> Widget<Message, Renderer>
- for Canvas<Message, P>
-{
- fn width(&self) -> Length {
- self.width
- }
-
- fn height(&self) -> Length {
- self.height
- }
-
- fn layout(
- &self,
- _renderer: &Renderer,
- limits: &layout::Limits,
- ) -> layout::Node {
- let limits = limits.width(self.width).height(self.height);
- let size = limits.resolve(Size::ZERO);
-
- layout::Node::new(size)
- }
-
- fn on_event(
- &mut self,
- event: iced_native::Event,
- layout: Layout<'_>,
- cursor_position: Point,
- messages: &mut Vec<Message>,
- _renderer: &Renderer,
- _clipboard: Option<&dyn Clipboard>,
- ) {
- let bounds = layout.bounds();
-
- let canvas_event = match event {
- iced_native::Event::Mouse(mouse_event) => {
- Some(Event::Mouse(mouse_event))
- }
- _ => None,
- };
-
- let cursor = Cursor::from_window_position(cursor_position);
-
- if let Some(canvas_event) = canvas_event {
- if let Some(message) =
- self.program.update(canvas_event, bounds, cursor)
- {
- messages.push(message);
- }
- }
- }
-
- fn draw(
- &self,
- _renderer: &mut Renderer,
- _defaults: &Defaults,
- layout: Layout<'_>,
- cursor_position: Point,
- ) -> (Primitive, mouse::Interaction) {
- let bounds = layout.bounds();
- let translation = Vector::new(bounds.x, bounds.y);
- let cursor = Cursor::from_window_position(cursor_position);
-
- (
- Primitive::Translate {
- translation,
- content: Box::new(Primitive::Group {
- primitives: self
- .program
- .draw(bounds, cursor)
- .into_iter()
- .map(Geometry::into_primitive)
- .collect(),
- }),
- },
- self.program.mouse_interaction(bounds, cursor),
- )
- }
-
- fn hash_layout(&self, state: &mut Hasher) {
- struct Marker;
- std::any::TypeId::of::<Marker>().hash(state);
-
- self.width.hash(state);
- self.height.hash(state);
- }
-}
-
-impl<'a, Message, P: Program<Message> + 'a> From<Canvas<Message, P>>
- for Element<'a, Message, Renderer>
-where
- Message: 'static,
-{
- fn from(canvas: Canvas<Message, P>) -> Element<'a, Message, Renderer> {
- Element::new(canvas)
- }
-}
+pub use iced_graphics::canvas::*;
diff --git a/wgpu/src/widget/canvas/cache.rs b/wgpu/src/widget/canvas/cache.rs
deleted file mode 100644
index 4b28d164..00000000
--- a/wgpu/src/widget/canvas/cache.rs
+++ /dev/null
@@ -1,108 +0,0 @@
-use crate::{
- canvas::{Frame, Geometry},
- Primitive,
-};
-
-use iced_native::Size;
-use std::{cell::RefCell, sync::Arc};
-
-enum State {
- Empty,
- Filled {
- bounds: Size,
- primitive: Arc<Primitive>,
- },
-}
-
-impl Default for State {
- fn default() -> Self {
- State::Empty
- }
-}
-/// A simple cache that stores generated [`Geometry`] to avoid recomputation.
-///
-/// A [`Cache`] will not redraw its geometry unless the dimensions of its layer
-/// change or it is explicitly cleared.
-///
-/// [`Layer`]: ../trait.Layer.html
-/// [`Cache`]: struct.Cache.html
-/// [`Geometry`]: struct.Geometry.html
-#[derive(Debug, Default)]
-pub struct Cache {
- state: RefCell<State>,
-}
-
-impl Cache {
- /// Creates a new empty [`Cache`].
- ///
- /// [`Cache`]: struct.Cache.html
- pub fn new() -> Self {
- Cache {
- state: Default::default(),
- }
- }
-
- /// Clears the [`Cache`], forcing a redraw the next time it is used.
- ///
- /// [`Cache`]: struct.Cache.html
- pub fn clear(&mut self) {
- *self.state.borrow_mut() = State::Empty;
- }
-
- /// Draws [`Geometry`] using the provided closure and stores it in the
- /// [`Cache`].
- ///
- /// The closure will only be called when
- /// - the bounds have changed since the previous draw call.
- /// - the [`Cache`] is empty or has been explicitly cleared.
- ///
- /// Otherwise, the previously stored [`Geometry`] will be returned. The
- /// [`Cache`] is not cleared in this case. In other words, it will keep
- /// returning the stored [`Geometry`] if needed.
- ///
- /// [`Cache`]: struct.Cache.html
- pub fn draw(&self, bounds: Size, draw_fn: impl Fn(&mut Frame)) -> Geometry {
- use std::ops::Deref;
-
- if let State::Filled {
- bounds: cached_bounds,
- primitive,
- } = self.state.borrow().deref()
- {
- if *cached_bounds == bounds {
- return Geometry::from_primitive(Primitive::Cached {
- cache: primitive.clone(),
- });
- }
- }
-
- let mut frame = Frame::new(bounds);
- draw_fn(&mut frame);
-
- let primitive = {
- let geometry = frame.into_geometry();
-
- Arc::new(geometry.into_primitive())
- };
-
- *self.state.borrow_mut() = State::Filled {
- bounds,
- primitive: primitive.clone(),
- };
-
- Geometry::from_primitive(Primitive::Cached { cache: primitive })
- }
-}
-
-impl std::fmt::Debug for State {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match self {
- State::Empty => write!(f, "Empty"),
- State::Filled { primitive, bounds } => f
- .debug_struct("Filled")
- .field("primitive", primitive)
- .field("bounds", bounds)
- .finish(),
- }
- }
-}
diff --git a/wgpu/src/widget/canvas/cursor.rs b/wgpu/src/widget/canvas/cursor.rs
deleted file mode 100644
index 456760ea..00000000
--- a/wgpu/src/widget/canvas/cursor.rs
+++ /dev/null
@@ -1,72 +0,0 @@
-use iced_native::{Point, Rectangle};
-
-/// The mouse cursor state.
-#[derive(Debug, Clone, Copy, PartialEq)]
-pub enum Cursor {
- /// The cursor has a defined position.
- Available(Point),
-
- /// The cursor is currently unavailable (i.e. out of bounds or busy).
- Unavailable,
-}
-
-impl Cursor {
- // TODO: Remove this once this type is used in `iced_native` to encode
- // proper cursor availability
- pub(crate) fn from_window_position(position: Point) -> Self {
- if position.x < 0.0 || position.y < 0.0 {
- Cursor::Unavailable
- } else {
- Cursor::Available(position)
- }
- }
-
- /// Returns the absolute position of the [`Cursor`], if available.
- ///
- /// [`Cursor`]: enum.Cursor.html
- pub fn position(&self) -> Option<Point> {
- match self {
- Cursor::Available(position) => Some(*position),
- Cursor::Unavailable => None,
- }
- }
-
- /// Returns the relative position of the [`Cursor`] inside the given bounds,
- /// if available.
- ///
- /// If the [`Cursor`] is not over the provided bounds, this method will
- /// return `None`.
- ///
- /// [`Cursor`]: enum.Cursor.html
- pub fn position_in(&self, bounds: &Rectangle) -> Option<Point> {
- if self.is_over(bounds) {
- self.position_from(bounds.position())
- } else {
- None
- }
- }
-
- /// Returns the relative position of the [`Cursor`] from the given origin,
- /// if available.
- ///
- /// [`Cursor`]: enum.Cursor.html
- pub fn position_from(&self, origin: Point) -> Option<Point> {
- match self {
- Cursor::Available(position) => {
- Some(Point::new(position.x - origin.x, position.y - origin.y))
- }
- Cursor::Unavailable => None,
- }
- }
-
- /// Returns whether the [`Cursor`] is currently over the provided bounds
- /// or not.
- ///
- /// [`Cursor`]: enum.Cursor.html
- pub fn is_over(&self, bounds: &Rectangle) -> bool {
- match self {
- Cursor::Available(position) => bounds.contains(*position),
- Cursor::Unavailable => false,
- }
- }
-}
diff --git a/wgpu/src/widget/canvas/event.rs b/wgpu/src/widget/canvas/event.rs
deleted file mode 100644
index ad11f51e..00000000
--- a/wgpu/src/widget/canvas/event.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-use iced_native::mouse;
-
-/// A [`Canvas`] event.
-///
-/// [`Canvas`]: struct.Event.html
-#[derive(Debug, Clone, Copy, PartialEq)]
-pub enum Event {
- /// A mouse event.
- Mouse(mouse::Event),
-}
diff --git a/wgpu/src/widget/canvas/fill.rs b/wgpu/src/widget/canvas/fill.rs
deleted file mode 100644
index a2010e45..00000000
--- a/wgpu/src/widget/canvas/fill.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-use iced_native::Color;
-
-/// The style used to fill geometry.
-#[derive(Debug, Clone, Copy)]
-pub enum Fill {
- /// Fill with a color.
- Color(Color),
-}
-
-impl Default for Fill {
- fn default() -> Fill {
- Fill::Color(Color::BLACK)
- }
-}
-
-impl From<Color> for Fill {
- fn from(color: Color) -> Fill {
- Fill::Color(color)
- }
-}
diff --git a/wgpu/src/widget/canvas/frame.rs b/wgpu/src/widget/canvas/frame.rs
deleted file mode 100644
index 5262ab4e..00000000
--- a/wgpu/src/widget/canvas/frame.rs
+++ /dev/null
@@ -1,367 +0,0 @@
-use iced_native::{Point, Rectangle, Size, Vector};
-
-use crate::{
- canvas::{Fill, Geometry, Path, Stroke, Text},
- triangle, Primitive,
-};
-
-/// The frame of a [`Canvas`].
-///
-/// [`Canvas`]: struct.Canvas.html
-#[derive(Debug)]
-pub struct Frame {
- size: Size,
- buffers: lyon::tessellation::VertexBuffers<triangle::Vertex2D, u32>,
- primitives: Vec<Primitive>,
- transforms: Transforms,
-}
-
-#[derive(Debug)]
-struct Transforms {
- previous: Vec<Transform>,
- current: Transform,
-}
-
-#[derive(Debug, Clone, Copy)]
-struct Transform {
- raw: lyon::math::Transform,
- is_identity: bool,
-}
-
-impl Frame {
- /// Creates a new empty [`Frame`] with the given dimensions.
- ///
- /// The default coordinate system of a [`Frame`] has its origin at the
- /// top-left corner of its bounds.
- ///
- /// [`Frame`]: struct.Frame.html
- pub fn new(size: Size) -> Frame {
- Frame {
- size,
- buffers: lyon::tessellation::VertexBuffers::new(),
- primitives: Vec::new(),
- transforms: Transforms {
- previous: Vec::new(),
- current: Transform {
- raw: lyon::math::Transform::identity(),
- is_identity: true,
- },
- },
- }
- }
-
- /// Returns the width of the [`Frame`].
- ///
- /// [`Frame`]: struct.Frame.html
- #[inline]
- pub fn width(&self) -> f32 {
- self.size.width
- }
-
- /// Returns the width of the [`Frame`].
- ///
- /// [`Frame`]: struct.Frame.html
- #[inline]
- pub fn height(&self) -> f32 {
- self.size.height
- }
-
- /// Returns the dimensions of the [`Frame`].
- ///
- /// [`Frame`]: struct.Frame.html
- #[inline]
- pub fn size(&self) -> Size {
- self.size
- }
-
- /// Returns the coordinate of the center of the [`Frame`].
- ///
- /// [`Frame`]: struct.Frame.html
- #[inline]
- pub fn center(&self) -> Point {
- Point::new(self.size.width / 2.0, self.size.height / 2.0)
- }
-
- /// Draws the given [`Path`] on the [`Frame`] by filling it with the
- /// provided style.
- ///
- /// [`Path`]: path/struct.Path.html
- /// [`Frame`]: struct.Frame.html
- pub fn fill(&mut self, path: &Path, fill: impl Into<Fill>) {
- use lyon::tessellation::{
- BuffersBuilder, FillOptions, FillTessellator,
- };
-
- let mut buffers = BuffersBuilder::new(
- &mut self.buffers,
- FillVertex(match fill.into() {
- Fill::Color(color) => color.into_linear(),
- }),
- );
-
- let mut tessellator = FillTessellator::new();
-
- let result = if self.transforms.current.is_identity {
- tessellator.tessellate_path(
- path.raw(),
- &FillOptions::default(),
- &mut buffers,
- )
- } else {
- let path = path.transformed(&self.transforms.current.raw);
-
- tessellator.tessellate_path(
- path.raw(),
- &FillOptions::default(),
- &mut buffers,
- )
- };
-
- let _ = result.expect("Tessellate path");
- }
-
- /// Draws an axis-aligned rectangle given its top-left corner coordinate and
- /// its `Size` on the [`Frame`] by filling it with the provided style.
- ///
- /// [`Frame`]: struct.Frame.html
- pub fn fill_rectangle(
- &mut self,
- top_left: Point,
- size: Size,
- fill: impl Into<Fill>,
- ) {
- use lyon::tessellation::{BuffersBuilder, FillOptions};
-
- let mut buffers = BuffersBuilder::new(
- &mut self.buffers,
- FillVertex(match fill.into() {
- Fill::Color(color) => color.into_linear(),
- }),
- );
-
- let top_left =
- self.transforms.current.raw.transform_point(
- lyon::math::Point::new(top_left.x, top_left.y),
- );
-
- let size =
- self.transforms.current.raw.transform_vector(
- lyon::math::Vector::new(size.width, size.height),
- );
-
- let _ = lyon::tessellation::basic_shapes::fill_rectangle(
- &lyon::math::Rect::new(top_left, size.into()),
- &FillOptions::default(),
- &mut buffers,
- )
- .expect("Fill rectangle");
- }
-
- /// Draws the stroke of the given [`Path`] on the [`Frame`] with the
- /// provided style.
- ///
- /// [`Path`]: path/struct.Path.html
- /// [`Frame`]: struct.Frame.html
- pub fn stroke(&mut self, path: &Path, stroke: impl Into<Stroke>) {
- use lyon::tessellation::{
- BuffersBuilder, StrokeOptions, StrokeTessellator,
- };
-
- let stroke = stroke.into();
-
- let mut buffers = BuffersBuilder::new(
- &mut self.buffers,
- StrokeVertex(stroke.color.into_linear()),
- );
-
- let mut tessellator = StrokeTessellator::new();
-
- let mut options = StrokeOptions::default();
- options.line_width = stroke.width;
- options.start_cap = stroke.line_cap.into();
- options.end_cap = stroke.line_cap.into();
- options.line_join = stroke.line_join.into();
-
- let result = if self.transforms.current.is_identity {
- tessellator.tessellate_path(path.raw(), &options, &mut buffers)
- } else {
- let path = path.transformed(&self.transforms.current.raw);
-
- tessellator.tessellate_path(path.raw(), &options, &mut buffers)
- };
-
- let _ = result.expect("Stroke path");
- }
-
- /// Draws the characters of the given [`Text`] on the [`Frame`], filling
- /// them with the given color.
- ///
- /// __Warning:__ Text currently does not work well with rotations and scale
- /// transforms! The position will be correctly transformed, but the
- /// resulting glyphs will not be rotated or scaled properly.
- ///
- /// Additionally, all text will be rendered on top of all the layers of
- /// a [`Canvas`]. Therefore, it is currently only meant to be used for
- /// overlays, which is the most common use case.
- ///
- /// Support for vectorial text is planned, and should address all these
- /// limitations.
- ///
- /// [`Text`]: struct.Text.html
- /// [`Frame`]: struct.Frame.html
- /// [`Canvas`]: struct.Canvas.html
- pub fn fill_text(&mut self, text: impl Into<Text>) {
- use std::f32;
-
- let text = text.into();
-
- let position = if self.transforms.current.is_identity {
- text.position
- } else {
- let transformed = self.transforms.current.raw.transform_point(
- lyon::math::Point::new(text.position.x, text.position.y),
- );
-
- Point::new(transformed.x, transformed.y)
- };
-
- // TODO: Use vectorial text instead of primitive
- self.primitives.push(Primitive::Text {
- content: text.content,
- bounds: Rectangle {
- x: position.x,
- y: position.y,
- width: f32::INFINITY,
- height: f32::INFINITY,
- },
- color: text.color,
- size: text.size,
- font: text.font,
- horizontal_alignment: text.horizontal_alignment,
- vertical_alignment: text.vertical_alignment,
- });
- }
-
- /// Stores the current transform of the [`Frame`] and executes the given
- /// drawing operations, restoring the transform afterwards.
- ///
- /// This method is useful to compose transforms and perform drawing
- /// operations in different coordinate systems.
- ///
- /// [`Frame`]: struct.Frame.html
- #[inline]
- pub fn with_save(&mut self, f: impl FnOnce(&mut Frame)) {
- self.transforms.previous.push(self.transforms.current);
-
- f(self);
-
- self.transforms.current = self.transforms.previous.pop().unwrap();
- }
-
- /// Applies a translation to the current transform of the [`Frame`].
- ///
- /// [`Frame`]: struct.Frame.html
- #[inline]
- pub fn translate(&mut self, translation: Vector) {
- self.transforms.current.raw = self
- .transforms
- .current
- .raw
- .pre_translate(lyon::math::Vector::new(
- translation.x,
- translation.y,
- ));
- self.transforms.current.is_identity = false;
- }
-
- /// Applies a rotation to the current transform of the [`Frame`].
- ///
- /// [`Frame`]: struct.Frame.html
- #[inline]
- pub fn rotate(&mut self, angle: f32) {
- self.transforms.current.raw = self
- .transforms
- .current
- .raw
- .pre_rotate(lyon::math::Angle::radians(-angle));
- self.transforms.current.is_identity = false;
- }
-
- /// Applies a scaling to the current transform of the [`Frame`].
- ///
- /// [`Frame`]: struct.Frame.html
- #[inline]
- pub fn scale(&mut self, scale: f32) {
- self.transforms.current.raw =
- self.transforms.current.raw.pre_scale(scale, scale);
- self.transforms.current.is_identity = false;
- }
-
- /// Produces the [`Geometry`] representing everything drawn on the [`Frame`].
- ///
- /// [`Frame`]: struct.Frame.html
- /// [`Geometry`]: struct.Geometry.html
- pub fn into_geometry(mut self) -> Geometry {
- if !self.buffers.indices.is_empty() {
- self.primitives.push(Primitive::Mesh2D {
- size: self.size,
- buffers: triangle::Mesh2D {
- vertices: self.buffers.vertices,
- indices: self.buffers.indices,
- },
- });
- }
-
- Geometry::from_primitive(Primitive::Group {
- primitives: self.primitives,
- })
- }
-}
-
-struct FillVertex([f32; 4]);
-
-impl lyon::tessellation::BasicVertexConstructor<triangle::Vertex2D>
- for FillVertex
-{
- fn new_vertex(
- &mut self,
- position: lyon::math::Point,
- ) -> triangle::Vertex2D {
- triangle::Vertex2D {
- position: [position.x, position.y],
- color: self.0,
- }
- }
-}
-
-impl lyon::tessellation::FillVertexConstructor<triangle::Vertex2D>
- for FillVertex
-{
- fn new_vertex(
- &mut self,
- position: lyon::math::Point,
- _attributes: lyon::tessellation::FillAttributes<'_>,
- ) -> triangle::Vertex2D {
- triangle::Vertex2D {
- position: [position.x, position.y],
- color: self.0,
- }
- }
-}
-
-struct StrokeVertex([f32; 4]);
-
-impl lyon::tessellation::StrokeVertexConstructor<triangle::Vertex2D>
- for StrokeVertex
-{
- fn new_vertex(
- &mut self,
- position: lyon::math::Point,
- _attributes: lyon::tessellation::StrokeAttributes<'_, '_>,
- ) -> triangle::Vertex2D {
- triangle::Vertex2D {
- position: [position.x, position.y],
- color: self.0,
- }
- }
-}
diff --git a/wgpu/src/widget/canvas/geometry.rs b/wgpu/src/widget/canvas/geometry.rs
deleted file mode 100644
index 4cadee39..00000000
--- a/wgpu/src/widget/canvas/geometry.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-use crate::Primitive;
-
-/// A bunch of shapes that can be drawn.
-///
-/// [`Geometry`] can be easily generated with a [`Frame`] or stored in a
-/// [`Cache`].
-///
-/// [`Geometry`]: struct.Geometry.html
-/// [`Frame`]: struct.Frame.html
-/// [`Cache`]: struct.Cache.html
-#[derive(Debug, Clone)]
-pub struct Geometry(Primitive);
-
-impl Geometry {
- pub(crate) fn from_primitive(primitive: Primitive) -> Self {
- Self(primitive)
- }
-
- /// Turns the [`Geometry`] into a [`Primitive`].
- ///
- /// This can be useful if you are building a custom widget.
- ///
- /// [`Geometry`]: struct.Geometry.html
- /// [`Primitive`]: ../enum.Primitive.html
- pub fn into_primitive(self) -> Primitive {
- self.0
- }
-}
-
-impl From<Geometry> for Primitive {
- fn from(geometry: Geometry) -> Primitive {
- geometry.0
- }
-}
diff --git a/wgpu/src/widget/canvas/path.rs b/wgpu/src/widget/canvas/path.rs
deleted file mode 100644
index c26bf187..00000000
--- a/wgpu/src/widget/canvas/path.rs
+++ /dev/null
@@ -1,79 +0,0 @@
-//! Build different kinds of 2D shapes.
-pub mod arc;
-
-mod builder;
-
-#[doc(no_inline)]
-pub use arc::Arc;
-pub use builder::Builder;
-
-use iced_native::{Point, Size};
-
-/// An immutable set of points that may or may not be connected.
-///
-/// A single [`Path`] can represent different kinds of 2D shapes!
-///
-/// [`Path`]: struct.Path.html
-#[derive(Debug, Clone)]
-pub struct Path {
- raw: lyon::path::Path,
-}
-
-impl Path {
- /// Creates a new [`Path`] with the provided closure.
- ///
- /// Use the [`Builder`] to configure your [`Path`].
- ///
- /// [`Path`]: struct.Path.html
- /// [`Builder`]: struct.Builder.html
- pub fn new(f: impl FnOnce(&mut Builder)) -> Self {
- let mut builder = Builder::new();
-
- // TODO: Make it pure instead of side-effect-based (?)
- f(&mut builder);
-
- builder.build()
- }
-
- /// Creates a new [`Path`] representing a line segment given its starting
- /// and end points.
- ///
- /// [`Path`]: struct.Path.html
- pub fn line(from: Point, to: Point) -> Self {
- Self::new(|p| {
- p.move_to(from);
- p.line_to(to);
- })
- }
-
- /// Creates a new [`Path`] representing a rectangle given its top-left
- /// corner coordinate and its `Size`.
- ///
- /// [`Path`]: struct.Path.html
- pub fn rectangle(top_left: Point, size: Size) -> Self {
- Self::new(|p| p.rectangle(top_left, size))
- }
-
- /// Creates a new [`Path`] representing a circle given its center
- /// coordinate and its radius.
- ///
- /// [`Path`]: struct.Path.html
- pub fn circle(center: Point, radius: f32) -> Self {
- Self::new(|p| p.circle(center, radius))
- }
-
- #[inline]
- pub(crate) fn raw(&self) -> &lyon::path::Path {
- &self.raw
- }
-
- #[inline]
- pub(crate) fn transformed(
- &self,
- transform: &lyon::math::Transform,
- ) -> Path {
- Path {
- raw: self.raw.transformed(transform),
- }
- }
-}
diff --git a/wgpu/src/widget/canvas/path/arc.rs b/wgpu/src/widget/canvas/path/arc.rs
deleted file mode 100644
index 343191f1..00000000
--- a/wgpu/src/widget/canvas/path/arc.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-//! Build and draw curves.
-use iced_native::{Point, Vector};
-
-/// A segment of a differentiable curve.
-#[derive(Debug, Clone, Copy)]
-pub struct Arc {
- /// The center of the arc.
- pub center: Point,
- /// The radius of the arc.
- pub radius: f32,
- /// The start of the segment's angle, clockwise rotation.
- pub start_angle: f32,
- /// The end of the segment's angle, clockwise rotation.
- pub end_angle: f32,
-}
-
-/// An elliptical [`Arc`].
-///
-/// [`Arc`]: struct.Arc.html
-#[derive(Debug, Clone, Copy)]
-pub struct Elliptical {
- /// The center of the arc.
- pub center: Point,
- /// The radii of the arc's ellipse, defining its axes.
- pub radii: Vector,
- /// The rotation of the arc's ellipse.
- pub rotation: f32,
- /// The start of the segment's angle, clockwise rotation.
- pub start_angle: f32,
- /// The end of the segment's angle, clockwise rotation.
- pub end_angle: f32,
-}
-
-impl From<Arc> for Elliptical {
- fn from(arc: Arc) -> Elliptical {
- Elliptical {
- center: arc.center,
- radii: Vector::new(arc.radius, arc.radius),
- rotation: 0.0,
- start_angle: arc.start_angle,
- end_angle: arc.end_angle,
- }
- }
-}
diff --git a/wgpu/src/widget/canvas/path/builder.rs b/wgpu/src/widget/canvas/path/builder.rs
deleted file mode 100644
index 6511fa52..00000000
--- a/wgpu/src/widget/canvas/path/builder.rs
+++ /dev/null
@@ -1,180 +0,0 @@
-use crate::canvas::path::{arc, Arc, Path};
-
-use iced_native::{Point, Size};
-use lyon::path::builder::{Build, FlatPathBuilder, PathBuilder, SvgBuilder};
-
-/// A [`Path`] builder.
-///
-/// Once a [`Path`] is built, it can no longer be mutated.
-///
-/// [`Path`]: struct.Path.html
-#[allow(missing_debug_implementations)]
-pub struct Builder {
- raw: lyon::path::builder::SvgPathBuilder<lyon::path::Builder>,
-}
-
-impl Builder {
- /// Creates a new [`Builder`].
- ///
- /// [`Builder`]: struct.Builder.html
- pub fn new() -> Builder {
- Builder {
- raw: lyon::path::Path::builder().with_svg(),
- }
- }
-
- /// Moves the starting point of a new sub-path to the given `Point`.
- #[inline]
- pub fn move_to(&mut self, point: Point) {
- let _ = self.raw.move_to(lyon::math::Point::new(point.x, point.y));
- }
-
- /// Connects the last point in the [`Path`] to the given `Point` with a
- /// straight line.
- ///
- /// [`Path`]: struct.Path.html
- #[inline]
- pub fn line_to(&mut self, point: Point) {
- let _ = self.raw.line_to(lyon::math::Point::new(point.x, point.y));
- }
-
- /// Adds an [`Arc`] to the [`Path`] from `start_angle` to `end_angle` in
- /// a clockwise direction.
- ///
- /// [`Arc`]: struct.Arc.html
- /// [`Path`]: struct.Path.html
- #[inline]
- pub fn arc(&mut self, arc: Arc) {
- self.ellipse(arc.into());
- }
-
- /// Adds a circular arc to the [`Path`] with the given control points and
- /// radius.
- ///
- /// The arc is connected to the previous point by a straight line, if
- /// necessary.
- ///
- /// [`Path`]: struct.Path.html
- pub fn arc_to(&mut self, a: Point, b: Point, radius: f32) {
- use lyon::{math, path};
-
- let a = math::Point::new(a.x, a.y);
-
- if self.raw.current_position() != a {
- let _ = self.raw.line_to(a);
- }
-
- let _ = self.raw.arc_to(
- math::Vector::new(radius, radius),
- math::Angle::radians(0.0),
- path::ArcFlags::default(),
- math::Point::new(b.x, b.y),
- );
- }
-
- /// Adds an [`Ellipse`] to the [`Path`] using a clockwise direction.
- ///
- /// [`Ellipse`]: struct.Arc.html
- /// [`Path`]: struct.Path.html
- pub fn ellipse(&mut self, arc: arc::Elliptical) {
- use lyon::{geom, math};
-
- let arc = geom::Arc {
- center: math::Point::new(arc.center.x, arc.center.y),
- radii: math::Vector::new(arc.radii.x, arc.radii.y),
- x_rotation: math::Angle::radians(arc.rotation),
- start_angle: math::Angle::radians(arc.start_angle),
- sweep_angle: math::Angle::radians(arc.end_angle),
- };
-
- let _ = self.raw.move_to(arc.sample(0.0));
-
- arc.for_each_quadratic_bezier(&mut |curve| {
- let _ = self.raw.quadratic_bezier_to(curve.ctrl, curve.to);
- });
- }
-
- /// Adds a cubic Bézier curve to the [`Path`] given its two control points
- /// and its end point.
- ///
- /// [`Path`]: struct.Path.html
- #[inline]
- pub fn bezier_curve_to(
- &mut self,
- control_a: Point,
- control_b: Point,
- to: Point,
- ) {
- use lyon::math;
-
- let _ = self.raw.cubic_bezier_to(
- math::Point::new(control_a.x, control_a.y),
- math::Point::new(control_b.x, control_b.y),
- math::Point::new(to.x, to.y),
- );
- }
-
- /// Adds a quadratic Bézier curve to the [`Path`] given its control point
- /// and its end point.
- ///
- /// [`Path`]: struct.Path.html
- #[inline]
- pub fn quadratic_curve_to(&mut self, control: Point, to: Point) {
- use lyon::math;
-
- let _ = self.raw.quadratic_bezier_to(
- math::Point::new(control.x, control.y),
- math::Point::new(to.x, to.y),
- );
- }
-
- /// Adds a rectangle to the [`Path`] given its top-left corner coordinate
- /// and its `Size`.
- ///
- /// [`Path`]: struct.Path.html
- #[inline]
- pub fn rectangle(&mut self, top_left: Point, size: Size) {
- self.move_to(top_left);
- self.line_to(Point::new(top_left.x + size.width, top_left.y));
- self.line_to(Point::new(
- top_left.x + size.width,
- top_left.y + size.height,
- ));
- self.line_to(Point::new(top_left.x, top_left.y + size.height));
- self.close();
- }
-
- /// Adds a circle to the [`Path`] given its center coordinate and its
- /// radius.
- ///
- /// [`Path`]: struct.Path.html
- #[inline]
- pub fn circle(&mut self, center: Point, radius: f32) {
- self.arc(Arc {
- center,
- radius,
- start_angle: 0.0,
- end_angle: 2.0 * std::f32::consts::PI,
- });
- }
-
- /// Closes the current sub-path in the [`Path`] with a straight line to
- /// the starting point.
- ///
- /// [`Path`]: struct.Path.html
- #[inline]
- pub fn close(&mut self) {
- self.raw.close()
- }
-
- /// Builds the [`Path`] of this [`Builder`].
- ///
- /// [`Path`]: struct.Path.html
- /// [`Builder`]: struct.Builder.html
- #[inline]
- pub fn build(self) -> Path {
- Path {
- raw: self.raw.build(),
- }
- }
-}
diff --git a/wgpu/src/widget/canvas/program.rs b/wgpu/src/widget/canvas/program.rs
deleted file mode 100644
index 725d9d72..00000000
--- a/wgpu/src/widget/canvas/program.rs
+++ /dev/null
@@ -1,85 +0,0 @@
-use crate::canvas::{Cursor, Event, Geometry};
-use iced_native::{mouse, Rectangle};
-
-/// The state and logic of a [`Canvas`].
-///
-/// A [`Program`] can mutate internal state and produce messages for an
-/// application.
-///
-/// [`Canvas`]: struct.Canvas.html
-/// [`Program`]: trait.Program.html
-pub trait Program<Message> {
- /// Updates the state of the [`Program`].
- ///
- /// When a [`Program`] is used in a [`Canvas`], the runtime will call this
- /// method for each [`Event`].
- ///
- /// This method can optionally return a `Message` to notify an application
- /// of any meaningful interactions.
- ///
- /// By default, this method does and returns nothing.
- ///
- /// [`Program`]: trait.Program.html
- /// [`Canvas`]: struct.Canvas.html
- /// [`Event`]: enum.Event.html
- fn update(
- &mut self,
- _event: Event,
- _bounds: Rectangle,
- _cursor: Cursor,
- ) -> Option<Message> {
- None
- }
-
- /// Draws the state of the [`Program`], producing a bunch of [`Geometry`].
- ///
- /// [`Geometry`] can be easily generated with a [`Frame`] or stored in a
- /// [`Cache`].
- ///
- /// [`Program`]: trait.Program.html
- /// [`Geometry`]: struct.Geometry.html
- /// [`Frame`]: struct.Frame.html
- /// [`Cache`]: struct.Cache.html
- fn draw(&self, bounds: Rectangle, cursor: Cursor) -> Vec<Geometry>;
-
- /// Returns the current mouse interaction of the [`Program`].
- ///
- /// The interaction returned will be in effect even if the cursor position
- /// is out of bounds of the program's [`Canvas`].
- ///
- /// [`Program`]: trait.Program.html
- /// [`Canvas`]: struct.Canvas.html
- fn mouse_interaction(
- &self,
- _bounds: Rectangle,
- _cursor: Cursor,
- ) -> mouse::Interaction {
- mouse::Interaction::default()
- }
-}
-
-impl<T, Message> Program<Message> for &mut T
-where
- T: Program<Message>,
-{
- fn update(
- &mut self,
- event: Event,
- bounds: Rectangle,
- cursor: Cursor,
- ) -> Option<Message> {
- T::update(self, event, bounds, cursor)
- }
-
- fn draw(&self, bounds: Rectangle, cursor: Cursor) -> Vec<Geometry> {
- T::draw(self, bounds, cursor)
- }
-
- fn mouse_interaction(
- &self,
- bounds: Rectangle,
- cursor: Cursor,
- ) -> mouse::Interaction {
- T::mouse_interaction(self, bounds, cursor)
- }
-}
diff --git a/wgpu/src/widget/canvas/stroke.rs b/wgpu/src/widget/canvas/stroke.rs
deleted file mode 100644
index 5b6fc56a..00000000
--- a/wgpu/src/widget/canvas/stroke.rs
+++ /dev/null
@@ -1,115 +0,0 @@
-use iced_native::Color;
-
-/// The style of a stroke.
-#[derive(Debug, Clone, Copy)]
-pub struct Stroke {
- /// The color of the stroke.
- pub color: Color,
- /// The distance between the two edges of the stroke.
- pub width: f32,
- /// The shape to be used at the end of open subpaths when they are stroked.
- pub line_cap: LineCap,
- /// The shape to be used at the corners of paths or basic shapes when they
- /// are stroked.
- pub line_join: LineJoin,
-}
-
-impl Stroke {
- /// Sets the color of the [`Stroke`].
- ///
- /// [`Stroke`]: struct.Stroke.html
- pub fn with_color(self, color: Color) -> Stroke {
- Stroke { color, ..self }
- }
-
- /// Sets the width of the [`Stroke`].
- ///
- /// [`Stroke`]: struct.Stroke.html
- pub fn with_width(self, width: f32) -> Stroke {
- Stroke { width, ..self }
- }
-
- /// Sets the [`LineCap`] of the [`Stroke`].
- ///
- /// [`LineCap`]: enum.LineCap.html
- /// [`Stroke`]: struct.Stroke.html
- pub fn with_line_cap(self, line_cap: LineCap) -> Stroke {
- Stroke { line_cap, ..self }
- }
-
- /// Sets the [`LineJoin`] of the [`Stroke`].
- ///
- /// [`LineJoin`]: enum.LineJoin.html
- /// [`Stroke`]: struct.Stroke.html
- pub fn with_line_join(self, line_join: LineJoin) -> Stroke {
- Stroke { line_join, ..self }
- }
-}
-
-impl Default for Stroke {
- fn default() -> Stroke {
- Stroke {
- color: Color::BLACK,
- width: 1.0,
- line_cap: LineCap::default(),
- line_join: LineJoin::default(),
- }
- }
-}
-
-/// The shape used at the end of open subpaths when they are stroked.
-#[derive(Debug, Clone, Copy)]
-pub enum LineCap {
- /// The stroke for each sub-path does not extend beyond its two endpoints.
- Butt,
- /// At the end of each sub-path, the shape representing the stroke will be
- /// extended by a square.
- Square,
- /// At the end of each sub-path, the shape representing the stroke will be
- /// extended by a semicircle.
- Round,
-}
-
-impl Default for LineCap {
- fn default() -> LineCap {
- LineCap::Butt
- }
-}
-
-impl From<LineCap> for lyon::tessellation::LineCap {
- fn from(line_cap: LineCap) -> lyon::tessellation::LineCap {
- match line_cap {
- LineCap::Butt => lyon::tessellation::LineCap::Butt,
- LineCap::Square => lyon::tessellation::LineCap::Square,
- LineCap::Round => lyon::tessellation::LineCap::Round,
- }
- }
-}
-
-/// The shape used at the corners of paths or basic shapes when they are
-/// stroked.
-#[derive(Debug, Clone, Copy)]
-pub enum LineJoin {
- /// A sharp corner.
- Miter,
- /// A round corner.
- Round,
- /// A bevelled corner.
- Bevel,
-}
-
-impl Default for LineJoin {
- fn default() -> LineJoin {
- LineJoin::Miter
- }
-}
-
-impl From<LineJoin> for lyon::tessellation::LineJoin {
- fn from(line_join: LineJoin) -> lyon::tessellation::LineJoin {
- match line_join {
- LineJoin::Miter => lyon::tessellation::LineJoin::Miter,
- LineJoin::Round => lyon::tessellation::LineJoin::Round,
- LineJoin::Bevel => lyon::tessellation::LineJoin::Bevel,
- }
- }
-}
diff --git a/wgpu/src/widget/canvas/text.rs b/wgpu/src/widget/canvas/text.rs
deleted file mode 100644
index c4cae30e..00000000
--- a/wgpu/src/widget/canvas/text.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-use iced_native::{Color, Font, HorizontalAlignment, Point, VerticalAlignment};
-
-/// A bunch of text that can be drawn to a canvas
-#[derive(Debug, Clone)]
-pub struct Text {
- /// The contents of the text
- pub content: String,
- /// The position where to begin drawing the text (top-left corner coordinates)
- pub position: Point,
- /// The color of the text
- pub color: Color,
- /// The size of the text
- pub size: f32,
- /// The font of the text
- pub font: Font,
- /// The horizontal alignment of the text
- pub horizontal_alignment: HorizontalAlignment,
- /// The vertical alignment of the text
- pub vertical_alignment: VerticalAlignment,
-}
-
-impl Default for Text {
- fn default() -> Text {
- Text {
- content: String::new(),
- position: Point::ORIGIN,
- color: Color::BLACK,
- size: 16.0,
- font: Font::Default,
- horizontal_alignment: HorizontalAlignment::Left,
- vertical_alignment: VerticalAlignment::Top,
- }
- }
-}
-
-impl From<String> for Text {
- fn from(content: String) -> Text {
- Text {
- content,
- ..Default::default()
- }
- }
-}
-
-impl From<&str> for Text {
- fn from(content: &str) -> Text {
- String::from(content).into()
- }
-}
diff --git a/wgpu/src/widget/checkbox.rs b/wgpu/src/widget/checkbox.rs
index da0d7a84..d27d77cc 100644
--- a/wgpu/src/widget/checkbox.rs
+++ b/wgpu/src/widget/checkbox.rs
@@ -1,7 +1,7 @@
//! Show toggle controls using checkboxes.
use crate::Renderer;
-pub use iced_style::checkbox::{Style, StyleSheet};
+pub use iced_graphics::checkbox::{Style, StyleSheet};
/// A box that can be checked.
///
diff --git a/wgpu/src/widget/container.rs b/wgpu/src/widget/container.rs
index 9a93a246..bc26cef2 100644
--- a/wgpu/src/widget/container.rs
+++ b/wgpu/src/widget/container.rs
@@ -1,7 +1,7 @@
//! Decorate content and apply alignment.
use crate::Renderer;
-pub use iced_style::container::{Style, StyleSheet};
+pub use iced_graphics::container::{Style, StyleSheet};
/// An element decorating some content.
///
diff --git a/wgpu/src/widget/progress_bar.rs b/wgpu/src/widget/progress_bar.rs
index 770bcea8..a636a3a6 100644
--- a/wgpu/src/widget/progress_bar.rs
+++ b/wgpu/src/widget/progress_bar.rs
@@ -6,7 +6,7 @@
//! [`ProgressBar`]: type.ProgressBar.html
use crate::Renderer;
-pub use iced_style::progress_bar::{Style, StyleSheet};
+pub use iced_graphics::progress_bar::{Style, StyleSheet};
/// A bar that displays progress.
///
diff --git a/wgpu/src/widget/radio.rs b/wgpu/src/widget/radio.rs
index 6e5cf042..0b843d1f 100644
--- a/wgpu/src/widget/radio.rs
+++ b/wgpu/src/widget/radio.rs
@@ -1,7 +1,7 @@
//! Create choices using radio buttons.
use crate::Renderer;
-pub use iced_style::radio::{Style, StyleSheet};
+pub use iced_graphics::radio::{Style, StyleSheet};
/// A circular button representing a choice.
///
diff --git a/wgpu/src/widget/scrollable.rs b/wgpu/src/widget/scrollable.rs
index 1d236105..fabb4318 100644
--- a/wgpu/src/widget/scrollable.rs
+++ b/wgpu/src/widget/scrollable.rs
@@ -1,8 +1,8 @@
//! Navigate an endless amount of content with a scrollbar.
use crate::Renderer;
+pub use iced_graphics::scrollable::{Scrollbar, Scroller, StyleSheet};
pub use iced_native::scrollable::State;
-pub use iced_style::scrollable::{Scrollbar, Scroller, StyleSheet};
/// A widget that can vertically display an infinite amount of content
/// with a scrollbar.
diff --git a/wgpu/src/widget/slider.rs b/wgpu/src/widget/slider.rs
index 4e47978f..cf036829 100644
--- a/wgpu/src/widget/slider.rs
+++ b/wgpu/src/widget/slider.rs
@@ -6,8 +6,8 @@
//! [`State`]: struct.State.html
use crate::Renderer;
+pub use iced_graphics::slider::{Handle, HandleShape, Style, StyleSheet};
pub use iced_native::slider::State;
-pub use iced_style::slider::{Handle, HandleShape, Style, StyleSheet};
/// An horizontal bar and a handle that selects a single value from a range of
/// values.
diff --git a/wgpu/src/widget/text_input.rs b/wgpu/src/widget/text_input.rs
index 260fe3a6..1da3fbe6 100644
--- a/wgpu/src/widget/text_input.rs
+++ b/wgpu/src/widget/text_input.rs
@@ -6,8 +6,8 @@
//! [`State`]: struct.State.html
use crate::Renderer;
+pub use iced_graphics::text_input::{Style, StyleSheet};
pub use iced_native::text_input::State;
-pub use iced_style::text_input::{Style, StyleSheet};
/// A field that can be filled with text.
///
diff --git a/wgpu/src/window/backend.rs b/wgpu/src/window/backend.rs
index b467486c..92e81cd9 100644
--- a/wgpu/src/window/backend.rs
+++ b/wgpu/src/window/backend.rs
@@ -51,7 +51,7 @@ impl iced_native::window::Backend for Backend {
}
fn create_renderer(&mut self, settings: Settings) -> Renderer {
- Renderer::new(&mut self.device, settings)
+ Renderer::new(crate::Backend::new(&mut self.device, settings))
}
fn create_surface<W: HasRawWindowHandle>(
@@ -100,7 +100,7 @@ impl iced_native::window::Backend for Backend {
depth_stencil_attachment: None,
});
- let mouse_interaction = renderer.draw(
+ let mouse_interaction = renderer.backend_mut().draw(
&mut self.device,
&mut encoder,
Target {