diff options
Diffstat (limited to '')
| -rw-r--r-- | graphics/fonts/Icons.ttf (renamed from wgpu/src/text/icons.ttf) | bin | 4912 -> 4912 bytes | |||
| -rw-r--r-- | graphics/fonts/Lato-Regular.ttf (renamed from wgpu/fonts/Lato-Regular.ttf) | bin | 75136 -> 75136 bytes | |||
| -rw-r--r-- | graphics/fonts/OFL.txt (renamed from wgpu/fonts/OFL.txt) | 0 | ||||
| -rw-r--r-- | graphics/src/defaults.rs (renamed from wgpu/src/defaults.rs) | 0 | ||||
| -rw-r--r-- | graphics/src/font/source.rs (renamed from wgpu/src/text/font.rs) | 12 | ||||
| -rw-r--r-- | graphics/src/primitive.rs (renamed from wgpu/src/primitive.rs) | 6 | ||||
| -rw-r--r-- | graphics/src/transformation.rs (renamed from wgpu/src/transformation.rs) | 0 | ||||
| -rw-r--r-- | graphics/src/widget/button.rs (renamed from wgpu/src/renderer/widget/button.rs) | 26 | ||||
| -rw-r--r-- | graphics/src/widget/canvas/cache.rs (renamed from wgpu/src/widget/canvas/cache.rs) | 0 | ||||
| -rw-r--r-- | graphics/src/widget/canvas/cursor.rs (renamed from wgpu/src/widget/canvas/cursor.rs) | 0 | ||||
| -rw-r--r-- | graphics/src/widget/canvas/event.rs (renamed from wgpu/src/widget/canvas/event.rs) | 0 | ||||
| -rw-r--r-- | graphics/src/widget/canvas/fill.rs (renamed from wgpu/src/widget/canvas/fill.rs) | 0 | ||||
| -rw-r--r-- | graphics/src/widget/canvas/frame.rs (renamed from wgpu/src/widget/canvas/frame.rs) | 2 | ||||
| -rw-r--r-- | graphics/src/widget/canvas/geometry.rs (renamed from wgpu/src/widget/canvas/geometry.rs) | 0 | ||||
| -rw-r--r-- | graphics/src/widget/canvas/path.rs (renamed from wgpu/src/widget/canvas/path.rs) | 0 | ||||
| -rw-r--r-- | graphics/src/widget/canvas/path/arc.rs (renamed from wgpu/src/widget/canvas/path/arc.rs) | 0 | ||||
| -rw-r--r-- | graphics/src/widget/canvas/path/builder.rs (renamed from wgpu/src/widget/canvas/path/builder.rs) | 0 | ||||
| -rw-r--r-- | graphics/src/widget/canvas/program.rs (renamed from wgpu/src/widget/canvas/program.rs) | 0 | ||||
| -rw-r--r-- | graphics/src/widget/canvas/stroke.rs (renamed from wgpu/src/widget/canvas/stroke.rs) | 0 | ||||
| -rw-r--r-- | graphics/src/widget/canvas/text.rs (renamed from wgpu/src/widget/canvas/text.rs) | 0 | ||||
| -rw-r--r-- | graphics/src/widget/checkbox.rs (renamed from wgpu/src/renderer/widget/checkbox.rs) | 27 | ||||
| -rw-r--r-- | graphics/src/widget/column.rs (renamed from wgpu/src/renderer/widget/row.rs) | 19 | ||||
| -rw-r--r-- | graphics/src/widget/container.rs (renamed from wgpu/src/renderer/widget/container.rs) | 19 | ||||
| -rw-r--r-- | graphics/src/widget/image.rs (renamed from wgpu/src/renderer/widget/image.rs) | 15 | ||||
| -rw-r--r-- | graphics/src/widget/pane_grid.rs (renamed from wgpu/src/renderer/widget/pane_grid.rs) | 37 | ||||
| -rw-r--r-- | graphics/src/widget/progress_bar.rs (renamed from wgpu/src/renderer/widget/progress_bar.rs) | 25 | ||||
| -rw-r--r-- | graphics/src/widget/radio.rs (renamed from wgpu/src/renderer/widget/radio.rs) | 21 | ||||
| -rw-r--r-- | graphics/src/widget/row.rs (renamed from wgpu/src/renderer/widget/column.rs) | 15 | ||||
| -rw-r--r-- | graphics/src/widget/scrollable.rs (renamed from wgpu/src/renderer/widget/scrollable.rs) | 23 | ||||
| -rw-r--r-- | graphics/src/widget/slider.rs (renamed from wgpu/src/renderer/widget/slider.rs) | 30 | ||||
| -rw-r--r-- | graphics/src/widget/svg.rs (renamed from wgpu/src/renderer/widget/svg.rs) | 11 | ||||
| -rw-r--r-- | graphics/src/widget/text.rs (renamed from wgpu/src/renderer/widget/text.rs) | 19 | ||||
| -rw-r--r-- | graphics/src/widget/text_input.rs (renamed from wgpu/src/renderer/widget/text_input.rs) | 52 | ||||
| -rw-r--r-- | wgpu/Cargo.toml | 13 | ||||
| -rw-r--r-- | wgpu/src/backend.rs | 271 | ||||
| -rw-r--r-- | wgpu/src/image.rs | 57 | ||||
| -rw-r--r-- | wgpu/src/lib.rs | 23 | ||||
| -rw-r--r-- | wgpu/src/quad.rs | 30 | ||||
| -rw-r--r-- | wgpu/src/renderer.rs | 507 | ||||
| -rw-r--r-- | wgpu/src/renderer/widget.rs | 19 | ||||
| -rw-r--r-- | wgpu/src/renderer/widget/space.rs | 8 | ||||
| -rw-r--r-- | wgpu/src/settings.rs | 29 | ||||
| -rw-r--r-- | wgpu/src/target.rs | 14 | ||||
| -rw-r--r-- | wgpu/src/text.rs | 39 | ||||
| -rw-r--r-- | wgpu/src/triangle.rs | 70 | ||||
| -rw-r--r-- | wgpu/src/viewport.rs | 29 | ||||
| -rw-r--r-- | wgpu/src/widget.rs | 17 | ||||
| -rw-r--r-- | wgpu/src/widget/button.rs | 2 | ||||
| -rw-r--r-- | wgpu/src/widget/canvas.rs | 226 | ||||
| -rw-r--r-- | wgpu/src/widget/checkbox.rs | 2 | ||||
| -rw-r--r-- | wgpu/src/widget/container.rs | 2 | ||||
| -rw-r--r-- | wgpu/src/widget/progress_bar.rs | 2 | ||||
| -rw-r--r-- | wgpu/src/widget/radio.rs | 2 | ||||
| -rw-r--r-- | wgpu/src/widget/scrollable.rs | 2 | ||||
| -rw-r--r-- | wgpu/src/widget/slider.rs | 2 | ||||
| -rw-r--r-- | wgpu/src/widget/text.rs | 7 | ||||
| -rw-r--r-- | wgpu/src/widget/text_input.rs | 2 | ||||
| -rw-r--r-- | wgpu/src/window.rs | 6 | ||||
| -rw-r--r-- | wgpu/src/window/compositor.rs (renamed from wgpu/src/window/backend.rs) | 44 | ||||
| -rw-r--r-- | wgpu/src/window/swap_chain.rs | 61 | 
60 files changed, 691 insertions, 1154 deletions
| diff --git a/wgpu/src/text/icons.ttf b/graphics/fonts/Icons.ttfBinary files differ index 1c832f86..1c832f86 100644 --- a/wgpu/src/text/icons.ttf +++ b/graphics/fonts/Icons.ttf diff --git a/wgpu/fonts/Lato-Regular.ttf b/graphics/fonts/Lato-Regular.ttfBinary files differ index 33eba8b1..33eba8b1 100644 --- a/wgpu/fonts/Lato-Regular.ttf +++ b/graphics/fonts/Lato-Regular.ttf diff --git a/wgpu/fonts/OFL.txt b/graphics/fonts/OFL.txt index dfca0da4..dfca0da4 100644 --- a/wgpu/fonts/OFL.txt +++ b/graphics/fonts/OFL.txt diff --git a/wgpu/src/defaults.rs b/graphics/src/defaults.rs index 11718a87..11718a87 100644 --- a/wgpu/src/defaults.rs +++ b/graphics/src/defaults.rs diff --git a/wgpu/src/text/font.rs b/graphics/src/font/source.rs index 7346ccdb..917291ff 100644 --- a/wgpu/src/text/font.rs +++ b/graphics/src/font/source.rs @@ -1,18 +1,24 @@ -pub use font_kit::{ -    error::SelectionError as LoadError, family_name::FamilyName as Family, -}; +use crate::font::{Family, LoadError}; +/// A font source that can find and load system fonts. +#[allow(missing_debug_implementations)]  pub struct Source {      raw: font_kit::source::SystemSource,  }  impl Source { +    /// Creates a new [`Source`]. +    /// +    /// [`Source`]: struct.Source.html      pub fn new() -> Self {          Source {              raw: font_kit::source::SystemSource::new(),          }      } +    /// Finds and loads a font matching the set of provided family priorities. +    /// +    /// [`Source`]: struct.Source.html      pub fn load(&self, families: &[Family]) -> Result<Vec<u8>, LoadError> {          let font = self.raw.select_best_match(              families, diff --git a/wgpu/src/primitive.rs b/graphics/src/primitive.rs index e73227ef..95dbf7dd 100644 --- a/wgpu/src/primitive.rs +++ b/graphics/src/primitive.rs @@ -82,13 +82,13 @@ pub enum Primitive {      ///      /// It can be used to render many kinds of geometry freely.      Mesh2D { +        /// The vertex and index buffers of the mesh +        buffers: triangle::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.      /// diff --git a/wgpu/src/transformation.rs b/graphics/src/transformation.rs index ff3b1d00..ff3b1d00 100644 --- a/wgpu/src/transformation.rs +++ b/graphics/src/transformation.rs diff --git a/wgpu/src/renderer/widget/button.rs b/graphics/src/widget/button.rs index eb225038..aeb862d5 100644 --- a/wgpu/src/renderer/widget/button.rs +++ b/graphics/src/widget/button.rs @@ -1,9 +1,29 @@ -use crate::{button::StyleSheet, defaults, Defaults, Primitive, Renderer}; +//! Allow your users to perform actions by pressing a button. +//! +//! A [`Button`] has some local [`State`]. +//! +//! [`Button`]: type.Button.html +//! [`State`]: struct.State.html +use crate::defaults::{self, Defaults}; +use crate::{Backend, Primitive, Renderer}; +use iced_native::mouse;  use iced_native::{ -    mouse, Background, Color, Element, Layout, Point, Rectangle, Vector, +    Background, Color, Element, Layout, Point, Rectangle, Vector,  }; -impl iced_native::button::Renderer for Renderer { +pub use iced_native::button::State; +pub use iced_style::button::{Style, StyleSheet}; + +/// A widget that produces a message when clicked. +/// +/// This is an alias of an `iced_native` button with an `iced_wgpu::Renderer`. +pub type Button<'a, Message, Backend> = +    iced_native::Button<'a, Message, Renderer<Backend>>; + +impl<B> iced_native::button::Renderer for Renderer<B> +where +    B: Backend, +{      const DEFAULT_PADDING: u16 = 5;      type Style = Box<dyn StyleSheet>; diff --git a/wgpu/src/widget/canvas/cache.rs b/graphics/src/widget/canvas/cache.rs index 4b28d164..4b28d164 100644 --- a/wgpu/src/widget/canvas/cache.rs +++ b/graphics/src/widget/canvas/cache.rs diff --git a/wgpu/src/widget/canvas/cursor.rs b/graphics/src/widget/canvas/cursor.rs index 456760ea..456760ea 100644 --- a/wgpu/src/widget/canvas/cursor.rs +++ b/graphics/src/widget/canvas/cursor.rs diff --git a/wgpu/src/widget/canvas/event.rs b/graphics/src/widget/canvas/event.rs index ad11f51e..ad11f51e 100644 --- a/wgpu/src/widget/canvas/event.rs +++ b/graphics/src/widget/canvas/event.rs diff --git a/wgpu/src/widget/canvas/fill.rs b/graphics/src/widget/canvas/fill.rs index a2010e45..a2010e45 100644 --- a/wgpu/src/widget/canvas/fill.rs +++ b/graphics/src/widget/canvas/fill.rs diff --git a/wgpu/src/widget/canvas/frame.rs b/graphics/src/widget/canvas/frame.rs index 5262ab4e..48d28d95 100644 --- a/wgpu/src/widget/canvas/frame.rs +++ b/graphics/src/widget/canvas/frame.rs @@ -304,11 +304,11 @@ impl Frame {      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,                  }, +                size: self.size,              });          } diff --git a/wgpu/src/widget/canvas/geometry.rs b/graphics/src/widget/canvas/geometry.rs index 4cadee39..4cadee39 100644 --- a/wgpu/src/widget/canvas/geometry.rs +++ b/graphics/src/widget/canvas/geometry.rs diff --git a/wgpu/src/widget/canvas/path.rs b/graphics/src/widget/canvas/path.rs index c26bf187..c26bf187 100644 --- a/wgpu/src/widget/canvas/path.rs +++ b/graphics/src/widget/canvas/path.rs diff --git a/wgpu/src/widget/canvas/path/arc.rs b/graphics/src/widget/canvas/path/arc.rs index 343191f1..343191f1 100644 --- a/wgpu/src/widget/canvas/path/arc.rs +++ b/graphics/src/widget/canvas/path/arc.rs diff --git a/wgpu/src/widget/canvas/path/builder.rs b/graphics/src/widget/canvas/path/builder.rs index 6511fa52..6511fa52 100644 --- a/wgpu/src/widget/canvas/path/builder.rs +++ b/graphics/src/widget/canvas/path/builder.rs diff --git a/wgpu/src/widget/canvas/program.rs b/graphics/src/widget/canvas/program.rs index 725d9d72..725d9d72 100644 --- a/wgpu/src/widget/canvas/program.rs +++ b/graphics/src/widget/canvas/program.rs diff --git a/wgpu/src/widget/canvas/stroke.rs b/graphics/src/widget/canvas/stroke.rs index 5b6fc56a..5b6fc56a 100644 --- a/wgpu/src/widget/canvas/stroke.rs +++ b/graphics/src/widget/canvas/stroke.rs diff --git a/wgpu/src/widget/canvas/text.rs b/graphics/src/widget/canvas/text.rs index c4cae30e..c4cae30e 100644 --- a/wgpu/src/widget/canvas/text.rs +++ b/graphics/src/widget/canvas/text.rs diff --git a/wgpu/src/renderer/widget/checkbox.rs b/graphics/src/widget/checkbox.rs index 0340bf62..cb7fd2cf 100644 --- a/wgpu/src/renderer/widget/checkbox.rs +++ b/graphics/src/widget/checkbox.rs @@ -1,9 +1,22 @@ -use crate::{checkbox::StyleSheet, Primitive, Renderer}; -use iced_native::{ -    checkbox, mouse, HorizontalAlignment, Rectangle, VerticalAlignment, -}; +//! Show toggle controls using checkboxes. +use crate::backend::{self, Backend}; +use crate::{Primitive, Renderer}; +use iced_native::checkbox; +use iced_native::mouse; +use iced_native::{HorizontalAlignment, Rectangle, VerticalAlignment}; -impl checkbox::Renderer for Renderer { +pub use iced_style::checkbox::{Style, StyleSheet}; + +/// A box that can be checked. +/// +/// This is an alias of an `iced_native` checkbox with an `iced_wgpu::Renderer`. +pub type Checkbox<Message, Backend> = +    iced_native::Checkbox<Message, Renderer<Backend>>; + +impl<B> checkbox::Renderer for Renderer<B> +where +    B: Backend + backend::Text, +{      type Style = Box<dyn StyleSheet>;      const DEFAULT_SIZE: u16 = 20; @@ -35,8 +48,8 @@ impl checkbox::Renderer for Renderer {              Primitive::Group {                  primitives: if is_checked {                      let check = Primitive::Text { -                        content: crate::text::CHECKMARK_ICON.to_string(), -                        font: crate::text::BUILTIN_ICONS, +                        content: B::CHECKMARK_ICON.to_string(), +                        font: B::ICON_FONT,                          size: bounds.height * 0.7,                          bounds: Rectangle {                              x: bounds.center_x(), diff --git a/wgpu/src/renderer/widget/row.rs b/graphics/src/widget/column.rs index d0b7ef09..6c7235c7 100644 --- a/wgpu/src/renderer/widget/row.rs +++ b/graphics/src/widget/column.rs @@ -1,11 +1,20 @@ -use crate::{Primitive, Renderer}; -use iced_native::{mouse, row, Element, Layout, Point}; +use crate::{Backend, Primitive, Renderer}; +use iced_native::column; +use iced_native::mouse; +use iced_native::{Element, Layout, Point}; -impl row::Renderer for Renderer { +/// A container that distributes its contents vertically. +pub type Column<'a, Message, Backend> = +    iced_native::Column<'a, Message, Renderer<Backend>>; + +impl<B> column::Renderer for Renderer<B> +where +    B: Backend, +{      fn draw<Message>(          &mut self,          defaults: &Self::Defaults, -        children: &[Element<'_, Message, Self>], +        content: &[Element<'_, Message, Self>],          layout: Layout<'_>,          cursor_position: Point,      ) -> Self::Output { @@ -13,7 +22,7 @@ impl row::Renderer for Renderer {          (              Primitive::Group { -                primitives: children +                primitives: content                      .iter()                      .zip(layout.children())                      .map(|(child, layout)| { diff --git a/wgpu/src/renderer/widget/container.rs b/graphics/src/widget/container.rs index 30cc3f07..070cb48b 100644 --- a/wgpu/src/renderer/widget/container.rs +++ b/graphics/src/widget/container.rs @@ -1,7 +1,22 @@ -use crate::{container, defaults, Defaults, Primitive, Renderer}; +//! Decorate content and apply alignment. +use crate::container; +use crate::defaults::{self, Defaults}; +use crate::{Backend, Primitive, Renderer};  use iced_native::{Background, Color, Element, Layout, Point, Rectangle}; -impl iced_native::container::Renderer for Renderer { +pub use iced_style::container::{Style, StyleSheet}; + +/// An element decorating some content. +/// +/// This is an alias of an `iced_native` container with a default +/// `Renderer`. +pub type Container<'a, Message, Backend> = +    iced_native::Container<'a, Message, Renderer<Backend>>; + +impl<B> iced_native::container::Renderer for Renderer<B> +where +    B: Backend, +{      type Style = Box<dyn container::StyleSheet>;      fn draw<Message>( diff --git a/wgpu/src/renderer/widget/image.rs b/graphics/src/widget/image.rs index c4c04984..30f446e8 100644 --- a/wgpu/src/renderer/widget/image.rs +++ b/graphics/src/widget/image.rs @@ -1,9 +1,18 @@ +//! Display images in your user interface. +use crate::backend::{self, Backend};  use crate::{Primitive, Renderer}; -use iced_native::{image, mouse, Layout}; +use iced_native::image; +use iced_native::mouse; +use iced_native::Layout; -impl image::Renderer for Renderer { +pub use iced_native::image::{Handle, Image}; + +impl<B> image::Renderer for Renderer<B> +where +    B: Backend + backend::Image, +{      fn dimensions(&self, handle: &image::Handle) -> (u32, u32) { -        self.image_pipeline.dimensions(handle) +        self.backend().dimensions(handle)      }      fn draw( diff --git a/wgpu/src/renderer/widget/pane_grid.rs b/graphics/src/widget/pane_grid.rs index 2253e4af..56af683d 100644 --- a/wgpu/src/renderer/widget/pane_grid.rs +++ b/graphics/src/widget/pane_grid.rs @@ -1,11 +1,36 @@ -use crate::{Primitive, Renderer}; -use iced_native::{ -    mouse, -    pane_grid::{self, Axis, Pane}, -    Element, Layout, Point, Rectangle, Vector, +//! Let your users split regions of your application and organize layout dynamically. +//! +//! [](https://gfycat.com/mixedflatjellyfish) +//! +//! # Example +//! The [`pane_grid` example] showcases how to use a [`PaneGrid`] with resizing, +//! drag and drop, and hotkey support. +//! +//! [`pane_grid` example]: https://github.com/hecrj/iced/tree/0.1/examples/pane_grid +//! [`PaneGrid`]: type.PaneGrid.html +use crate::{Backend, Primitive, Renderer}; +use iced_native::mouse; +use iced_native::pane_grid; +use iced_native::{Element, Layout, Point, Rectangle, Vector}; + +pub use iced_native::pane_grid::{ +    Axis, Direction, DragEvent, Focus, KeyPressEvent, Pane, ResizeEvent, Split, +    State,  }; -impl pane_grid::Renderer for Renderer { +/// A collection of panes distributed using either vertical or horizontal splits +/// to completely fill the space available. +/// +/// [](https://gfycat.com/mixedflatjellyfish) +/// +/// This is an alias of an `iced_native` pane grid with an `iced_wgpu::Renderer`. +pub type PaneGrid<'a, Message, Backend> = +    iced_native::PaneGrid<'a, Message, Renderer<Backend>>; + +impl<B> pane_grid::Renderer for Renderer<B> +where +    B: Backend, +{      fn draw<Message>(          &mut self,          defaults: &Self::Defaults, diff --git a/wgpu/src/renderer/widget/progress_bar.rs b/graphics/src/widget/progress_bar.rs index 2baeeb14..48acb3c1 100644 --- a/wgpu/src/renderer/widget/progress_bar.rs +++ b/graphics/src/widget/progress_bar.rs @@ -1,7 +1,26 @@ -use crate::{progress_bar::StyleSheet, Primitive, Renderer}; -use iced_native::{mouse, progress_bar, Color, Rectangle}; +//! Allow your users to visually track the progress of a computation. +//! +//! A [`ProgressBar`] has a range of possible values and a current value, +//! as well as a length, height and style. +//! +//! [`ProgressBar`]: type.ProgressBar.html +use crate::{Backend, Primitive, Renderer}; +use iced_native::mouse; +use iced_native::progress_bar; +use iced_native::{Color, Rectangle}; -impl progress_bar::Renderer for Renderer { +pub use iced_style::progress_bar::{Style, StyleSheet}; + +/// A bar that displays progress. +/// +/// This is an alias of an `iced_native` progress bar with an +/// `iced_wgpu::Renderer`. +pub type ProgressBar<Backend> = iced_native::ProgressBar<Renderer<Backend>>; + +impl<B> progress_bar::Renderer for Renderer<B> +where +    B: Backend, +{      type Style = Box<dyn StyleSheet>;      const DEFAULT_HEIGHT: u16 = 30; diff --git a/wgpu/src/renderer/widget/radio.rs b/graphics/src/widget/radio.rs index cee0deb6..dd8b5f17 100644 --- a/wgpu/src/renderer/widget/radio.rs +++ b/graphics/src/widget/radio.rs @@ -1,10 +1,25 @@ -use crate::{radio::StyleSheet, Primitive, Renderer}; -use iced_native::{mouse, radio, Background, Color, Rectangle}; +//! Create choices using radio buttons. +use crate::{Backend, Primitive, Renderer}; +use iced_native::mouse; +use iced_native::radio; +use iced_native::{Background, Color, Rectangle}; + +pub use iced_style::radio::{Style, StyleSheet}; + +/// A circular button representing a choice. +/// +/// This is an alias of an `iced_native` radio button with an +/// `iced_wgpu::Renderer`. +pub type Radio<Message, Backend> = +    iced_native::Radio<Message, Renderer<Backend>>;  const SIZE: f32 = 28.0;  const DOT_SIZE: f32 = SIZE / 2.0; -impl radio::Renderer for Renderer { +impl<B> radio::Renderer for Renderer<B> +where +    B: Backend, +{      type Style = Box<dyn StyleSheet>;      const DEFAULT_SIZE: u16 = SIZE as u16; diff --git a/wgpu/src/renderer/widget/column.rs b/graphics/src/widget/row.rs index b853276d..4c1dbadc 100644 --- a/wgpu/src/renderer/widget/column.rs +++ b/graphics/src/widget/row.rs @@ -1,7 +1,16 @@ -use crate::{Primitive, Renderer}; -use iced_native::{column, mouse, Element, Layout, Point}; +use crate::{Backend, Primitive, Renderer}; +use iced_native::mouse; +use iced_native::row; +use iced_native::{Element, Layout, Point}; -impl column::Renderer for Renderer { +/// A container that distributes its contents horizontally. +pub type Row<'a, Message, Backend> = +    iced_native::Row<'a, Message, Renderer<Backend>>; + +impl<B> row::Renderer for Renderer<B> +where +    B: Backend, +{      fn draw<Message>(          &mut self,          defaults: &Self::Defaults, diff --git a/wgpu/src/renderer/widget/scrollable.rs b/graphics/src/widget/scrollable.rs index 8a400b82..b149db0a 100644 --- a/wgpu/src/renderer/widget/scrollable.rs +++ b/graphics/src/widget/scrollable.rs @@ -1,10 +1,27 @@ -use crate::{Primitive, Renderer}; -use iced_native::{mouse, scrollable, Background, Color, Rectangle, Vector}; +//! Navigate an endless amount of content with a scrollbar. +use crate::{Backend, Primitive, Renderer}; +use iced_native::mouse; +use iced_native::scrollable; +use iced_native::{Background, Color, Rectangle, Vector}; + +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. +/// +/// This is an alias of an `iced_native` scrollable with a default +/// `Renderer`. +pub type Scrollable<'a, Message, Backend> = +    iced_native::Scrollable<'a, Message, Renderer<Backend>>;  const SCROLLBAR_WIDTH: u16 = 10;  const SCROLLBAR_MARGIN: u16 = 2; -impl scrollable::Renderer for Renderer { +impl<B> scrollable::Renderer for Renderer<B> +where +    B: Backend, +{      type Style = Box<dyn iced_style::scrollable::StyleSheet>;      fn scrollbar( diff --git a/wgpu/src/renderer/widget/slider.rs b/graphics/src/widget/slider.rs index 220feace..b00cde9a 100644 --- a/wgpu/src/renderer/widget/slider.rs +++ b/graphics/src/widget/slider.rs @@ -1,12 +1,30 @@ -use crate::{ -    slider::{HandleShape, StyleSheet}, -    Primitive, Renderer, -}; -use iced_native::{mouse, slider, Background, Color, Point, Rectangle}; +//! Display an interactive selector of a single value from a range of values. +//! +//! A [`Slider`] has some local [`State`]. +//! +//! [`Slider`]: struct.Slider.html +//! [`State`]: struct.State.html +use crate::{Backend, Primitive, Renderer}; +use iced_native::mouse; +use iced_native::slider; +use iced_native::{Background, Color, Point, Rectangle}; + +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. +/// +/// This is an alias of an `iced_native` slider with an `iced_wgpu::Renderer`. +pub type Slider<'a, Message, Backend> = +    iced_native::Slider<'a, Message, Renderer<Backend>>;  const HANDLE_HEIGHT: f32 = 22.0; -impl slider::Renderer for Renderer { +impl<B> slider::Renderer for Renderer<B> +where +    B: Backend, +{      type Style = Box<dyn StyleSheet>;      fn height(&self) -> u32 { diff --git a/wgpu/src/renderer/widget/svg.rs b/graphics/src/widget/svg.rs index f6d6d0ba..8b5ed66a 100644 --- a/wgpu/src/renderer/widget/svg.rs +++ b/graphics/src/widget/svg.rs @@ -1,9 +1,16 @@ +//! Display vector graphics in your application. +use crate::backend::{self, Backend};  use crate::{Primitive, Renderer};  use iced_native::{mouse, svg, Layout}; -impl svg::Renderer for Renderer { +pub use iced_native::svg::{Handle, Svg}; + +impl<B> svg::Renderer for Renderer<B> +where +    B: Backend + backend::Svg, +{      fn dimensions(&self, handle: &svg::Handle) -> (u32, u32) { -        self.image_pipeline.viewport_dimensions(handle) +        self.backend().viewport_dimensions(handle)      }      fn draw( diff --git a/wgpu/src/renderer/widget/text.rs b/graphics/src/widget/text.rs index 4605ed06..327f8e29 100644 --- a/wgpu/src/renderer/widget/text.rs +++ b/graphics/src/widget/text.rs @@ -1,12 +1,23 @@ +//! Write some text for your users to read. +use crate::backend::{self, Backend};  use crate::{Primitive, Renderer}; +use iced_native::mouse; +use iced_native::text;  use iced_native::{ -    mouse, text, Color, Font, HorizontalAlignment, Rectangle, Size, -    VerticalAlignment, +    Color, Font, HorizontalAlignment, Rectangle, Size, VerticalAlignment,  }; +/// A paragraph of text. +/// +/// This is an alias of an `iced_native` text with an `iced_wgpu::Renderer`. +pub type Text<Backend> = iced_native::Text<Renderer<Backend>>; +  use std::f32; -impl text::Renderer for Renderer { +impl<B> text::Renderer for Renderer<B> +where +    B: Backend + backend::Text, +{      type Font = Font;      const DEFAULT_SIZE: u16 = 20; @@ -18,7 +29,7 @@ impl text::Renderer for Renderer {          font: Font,          bounds: Size,      ) -> (f32, f32) { -        self.text_pipeline +        self.backend()              .measure(content, f32::from(size), font, bounds)      } diff --git a/wgpu/src/renderer/widget/text_input.rs b/graphics/src/widget/text_input.rs index 57be6692..893197d1 100644 --- a/wgpu/src/renderer/widget/text_input.rs +++ b/graphics/src/widget/text_input.rs @@ -1,14 +1,32 @@ -use crate::{text_input::StyleSheet, Primitive, Renderer}; - +//! Display fields that can be filled with text. +//! +//! A [`TextInput`] has some local [`State`]. +//! +//! [`TextInput`]: struct.TextInput.html +//! [`State`]: struct.State.html +use crate::backend::{self, Backend}; +use crate::{Primitive, Renderer}; +use iced_native::mouse; +use iced_native::text_input::{self, cursor};  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 { +pub use iced_native::text_input::State; +pub use iced_style::text_input::{Style, StyleSheet}; + +/// A field that can be filled with text. +/// +/// This is an alias of an `iced_native` text input with an `iced_wgpu::Renderer`. +pub type TextInput<'a, Message, Backend> = +    iced_native::TextInput<'a, Message, Renderer<Backend>>; + +impl<B> text_input::Renderer for Renderer<B> +where +    B: Backend + backend::Text, +{      type Style = Box<dyn StyleSheet>;      fn default_size(&self) -> u16 { @@ -17,19 +35,10 @@ impl text_input::Renderer for Renderer {      }      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(); +        let backend = self.backend(); -        if spaces_around > 0 { -            let space_width = self.text_pipeline.space_width(size as f32); -            width += spaces_around as f32 * space_width; -        } +        let (width, _) = +            backend.measure(value, f32::from(size), font, Size::INFINITY);          width      } @@ -241,14 +250,17 @@ impl text_input::Renderer for Renderer {      }  } -fn measure_cursor_and_scroll_offset( -    renderer: &Renderer, +fn measure_cursor_and_scroll_offset<B>( +    renderer: &Renderer<B>,      text_bounds: Rectangle,      value: &text_input::Value,      size: u16,      cursor_index: usize,      font: Font, -) -> (f32, f32) { +) -> (f32, f32) +where +    B: Backend + backend::Text, +{      use iced_native::text_input::Renderer;      let text_before_cursor = value.until(cursor_index).to_string(); diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index 612af1ed..35ea9c31 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -9,16 +9,16 @@ 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" -font-kit = "0.6"  log = "0.4"  guillotiere = "0.5"  # Pin `gfx-memory` until https://github.com/gfx-rs/wgpu-rs/issues/261 is @@ -29,9 +29,10 @@ gfx-memory = "=0.1.1"  version = "0.2"  path = "../native" -[dependencies.iced_style] +[dependencies.iced_graphics]  version = "0.1" -path = "../style" +path = "../graphics" +features = ["font-source", "font-fallback", "font-icons"]  [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/backend.rs b/wgpu/src/backend.rs new file mode 100644 index 00000000..88529ddd --- /dev/null +++ b/wgpu/src/backend.rs @@ -0,0 +1,271 @@ +use crate::quad; +use crate::text; +use crate::triangle; +use crate::{Settings, Transformation}; +use iced_graphics::backend; +use iced_graphics::font; +use iced_graphics::layer::Layer; +use iced_graphics::{Primitive, Viewport}; +use iced_native::mouse; +use iced_native::{Font, HorizontalAlignment, Size, VerticalAlignment}; + +#[cfg(any(feature = "image", feature = "svg"))] +use crate::image; + +/// A [`wgpu`] graphics backend for [`iced`]. +/// +/// [`wgpu`]: https://github.com/gfx-rs/wgpu-rs +/// [`iced`]: https://github.com/hecrj/iced +#[derive(Debug)] +pub struct Backend { +    quad_pipeline: quad::Pipeline, +    text_pipeline: text::Pipeline, +    triangle_pipeline: triangle::Pipeline, + +    #[cfg(any(feature = "image", feature = "svg"))] +    image_pipeline: image::Pipeline, +} + +impl Backend { +    /// Creates a new [`Renderer`]. +    /// +    /// [`Renderer`]: struct.Renderer.html +    pub fn new(device: &wgpu::Device, settings: Settings) -> Self { +        let text_pipeline = +            text::Pipeline::new(device, settings.format, settings.default_font); +        let quad_pipeline = quad::Pipeline::new(device, settings.format); +        let triangle_pipeline = triangle::Pipeline::new( +            device, +            settings.format, +            settings.antialiasing, +        ); + +        #[cfg(any(feature = "image", feature = "svg"))] +        let image_pipeline = image::Pipeline::new(device, settings.format); + +        Self { +            quad_pipeline, +            text_pipeline, +            triangle_pipeline, + +            #[cfg(any(feature = "image", feature = "svg"))] +            image_pipeline, +        } +    } + +    /// Draws the provided primitives in the given [`Target`]. +    /// +    /// The text provided as overlay will be renderer on top of the primitives. +    /// This is useful for rendering debug information. +    /// +    /// [`Target`]: struct.Target.html +    pub fn draw<T: AsRef<str>>( +        &mut self, +        device: &wgpu::Device, +        encoder: &mut wgpu::CommandEncoder, +        frame: &wgpu::TextureView, +        viewport: &Viewport, +        (primitive, mouse_interaction): &(Primitive, mouse::Interaction), +        overlay_text: &[T], +    ) -> mouse::Interaction { +        log::debug!("Drawing"); + +        let target_size = viewport.physical_size(); +        let scale_factor = viewport.scale_factor() as f32; +        let transformation = viewport.projection(); + +        let mut layers = Layer::generate(primitive, viewport); +        layers.push(Layer::overlay(overlay_text, viewport)); + +        for layer in layers { +            self.flush( +                device, +                scale_factor, +                transformation, +                &layer, +                encoder, +                &frame, +                target_size.width, +                target_size.height, +            ); +        } + +        #[cfg(any(feature = "image", feature = "svg"))] +        self.image_pipeline.trim_cache(); + +        *mouse_interaction +    } + +    fn flush( +        &mut self, +        device: &wgpu::Device, +        scale_factor: f32, +        transformation: Transformation, +        layer: &Layer<'_>, +        encoder: &mut wgpu::CommandEncoder, +        target: &wgpu::TextureView, +        target_width: u32, +        target_height: u32, +    ) { +        let bounds = (layer.bounds * scale_factor).round(); + +        if !layer.quads.is_empty() { +            self.quad_pipeline.draw( +                device, +                encoder, +                &layer.quads, +                transformation, +                scale_factor, +                bounds, +                target, +            ); +        } + +        if !layer.meshes.is_empty() { +            let scaled = transformation +                * Transformation::scale(scale_factor, scale_factor); + +            self.triangle_pipeline.draw( +                device, +                encoder, +                target, +                target_width, +                target_height, +                scaled, +                scale_factor, +                &layer.meshes, +            ); +        } + +        #[cfg(any(feature = "image", feature = "svg"))] +        { +            if !layer.images.is_empty() { +                let scaled = transformation +                    * Transformation::scale(scale_factor, scale_factor); + +                self.image_pipeline.draw( +                    device, +                    encoder, +                    &layer.images, +                    scaled, +                    bounds, +                    target, +                    scale_factor, +                ); +            } +        } + +        if !layer.text.is_empty() { +            for text in layer.text.iter() { +                // Target physical coordinates directly to avoid blurry text +                let text = wgpu_glyph::Section { +                    text: text.content, +                    // TODO: We `round` here to avoid rerasterizing text when +                    // its position changes slightly. This can make text feel a +                    // bit "jumpy". We may be able to do better once we improve +                    // our text rendering/caching pipeline. +                    screen_position: ( +                        (text.bounds.x * scale_factor).round(), +                        (text.bounds.y * scale_factor).round(), +                    ), +                    // TODO: Fix precision issues with some scale factors. +                    // +                    // The `ceil` here can cause some words to render on the +                    // same line when they should not. +                    // +                    // Ideally, `wgpu_glyph` should be able to compute layout +                    // using logical positions, and then apply the proper +                    // scaling when rendering. This would ensure that both +                    // measuring and rendering follow the same layout rules. +                    bounds: ( +                        (text.bounds.width * scale_factor).ceil(), +                        (text.bounds.height * scale_factor).ceil(), +                    ), +                    scale: wgpu_glyph::Scale { +                        x: text.size * scale_factor, +                        y: text.size * scale_factor, +                    }, +                    color: text.color, +                    font_id: self.text_pipeline.find_font(text.font), +                    layout: wgpu_glyph::Layout::default() +                        .h_align(match text.horizontal_alignment { +                            HorizontalAlignment::Left => { +                                wgpu_glyph::HorizontalAlign::Left +                            } +                            HorizontalAlignment::Center => { +                                wgpu_glyph::HorizontalAlign::Center +                            } +                            HorizontalAlignment::Right => { +                                wgpu_glyph::HorizontalAlign::Right +                            } +                        }) +                        .v_align(match text.vertical_alignment { +                            VerticalAlignment::Top => { +                                wgpu_glyph::VerticalAlign::Top +                            } +                            VerticalAlignment::Center => { +                                wgpu_glyph::VerticalAlign::Center +                            } +                            VerticalAlignment::Bottom => { +                                wgpu_glyph::VerticalAlign::Bottom +                            } +                        }), +                    ..Default::default() +                }; + +                self.text_pipeline.queue(text); +            } + +            self.text_pipeline.draw_queued( +                device, +                encoder, +                target, +                transformation, +                wgpu_glyph::Region { +                    x: bounds.x, +                    y: bounds.y, +                    width: bounds.width, +                    height: bounds.height, +                }, +            ); +        } +    } +} + +impl iced_graphics::Backend for Backend { +    fn trim_measurements(&mut self) { +        self.text_pipeline.trim_measurement_cache() +    } +} + +impl backend::Text for Backend { +    const ICON_FONT: Font = font::ICONS; +    const CHECKMARK_ICON: char = font::CHECKMARK_ICON; + +    fn measure( +        &self, +        contents: &str, +        size: f32, +        font: Font, +        bounds: Size, +    ) -> (f32, f32) { +        self.text_pipeline.measure(contents, size, font, bounds) +    } +} + +#[cfg(feature = "image")] +impl backend::Image for Backend { +    fn dimensions(&self, handle: &iced_native::image::Handle) -> (u32, u32) { +        self.image_pipeline.dimensions(handle) +    } +} + +#[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/image.rs b/wgpu/src/image.rs index ea5dc09d..49f1d29c 100644 --- a/wgpu/src/image.rs +++ b/wgpu/src/image.rs @@ -9,6 +9,7 @@ mod vector;  use crate::Transformation;  use atlas::Atlas; +use iced_graphics::layer;  use iced_native::Rectangle;  use std::cell::RefCell;  use std::mem; @@ -282,7 +283,7 @@ impl Pipeline {          &mut self,          device: &wgpu::Device,          encoder: &mut wgpu::CommandEncoder, -        images: &[Image], +        images: &[layer::Image],          transformation: Transformation,          bounds: Rectangle<u32>,          target: &wgpu::TextureView, @@ -297,31 +298,48 @@ impl Pipeline {          let mut vector_cache = self.vector_cache.borrow_mut();          for image in images { -            match &image.handle { +            match &image {                  #[cfg(feature = "image")] -                Handle::Raster(handle) => { +                layer::Image::Raster { handle, bounds } => {                      if let Some(atlas_entry) = raster_cache.upload(                          handle,                          device,                          encoder,                          &mut self.texture_atlas,                      ) { -                        add_instances(image, atlas_entry, instances); +                        add_instances( +                            [bounds.x, bounds.y], +                            [bounds.width, bounds.height], +                            atlas_entry, +                            instances, +                        );                      }                  } +                #[cfg(not(feature = "image"))] +                layer::Image::Raster { .. } => {} +                  #[cfg(feature = "svg")] -                Handle::Vector(handle) => { +                layer::Image::Vector { handle, bounds } => { +                    let size = [bounds.width, bounds.height]; +                      if let Some(atlas_entry) = vector_cache.upload(                          handle, -                        image.size, +                        size,                          _scale,                          device,                          encoder,                          &mut self.texture_atlas,                      ) { -                        add_instances(image, atlas_entry, instances); +                        add_instances( +                            [bounds.x, bounds.y], +                            size, +                            atlas_entry, +                            instances, +                        );                      }                  } +                #[cfg(not(feature = "svg"))] +                layer::Image::Vector { .. } => {}              }          } @@ -437,20 +455,6 @@ impl Pipeline {      }  } -pub struct Image { -    pub handle: Handle, -    pub position: [f32; 2], -    pub size: [f32; 2], -} - -pub enum Handle { -    #[cfg(feature = "image")] -    Raster(image::Handle), - -    #[cfg(feature = "svg")] -    Vector(svg::Handle), -} -  #[repr(C)]  #[derive(Clone, Copy, AsBytes)]  pub struct Vertex { @@ -495,22 +499,23 @@ struct Uniforms {  }  fn add_instances( -    image: &Image, +    image_position: [f32; 2], +    image_size: [f32; 2],      entry: &atlas::Entry,      instances: &mut Vec<Instance>,  ) {      match entry {          atlas::Entry::Contiguous(allocation) => { -            add_instance(image.position, image.size, allocation, instances); +            add_instance(image_position, image_size, allocation, instances);          }          atlas::Entry::Fragmented { fragments, size } => { -            let scaling_x = image.size[0] / size.0 as f32; -            let scaling_y = image.size[1] / size.1 as f32; +            let scaling_x = image_size[0] / size.0 as f32; +            let scaling_y = image_size[1] / size.1 as f32;              for fragment in fragments {                  let allocation = &fragment.allocation; -                let [x, y] = image.position; +                let [x, y] = image_position;                  let (fragment_x, fragment_y) = fragment.position;                  let (fragment_width, fragment_height) = allocation.size(); diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 799c1f34..0c351eea 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -27,34 +27,31 @@  #![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, Viewport};  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;  #[doc(no_inline)]  pub use widget::*; -pub(crate) use quad::Quad; -pub(crate) use transformation::Transformation; +pub(crate) use iced_graphics::Transformation;  #[cfg(any(feature = "image", feature = "svg"))]  mod image; + +/// A [`wgpu`] graphics renderer for [`iced`]. +/// +/// [`wgpu`]: https://github.com/gfx-rs/wgpu-rs +/// [`iced`]: https://github.com/hecrj/iced +pub type Renderer = iced_graphics::Renderer<Backend>; diff --git a/wgpu/src/quad.rs b/wgpu/src/quad.rs index 0c2d2244..0b62f44f 100644 --- a/wgpu/src/quad.rs +++ b/wgpu/src/quad.rs @@ -1,4 +1,5 @@  use crate::Transformation; +use iced_graphics::layer;  use iced_native::Rectangle;  use std::mem; @@ -107,7 +108,7 @@ impl Pipeline {                              }],                          },                          wgpu::VertexBufferDescriptor { -                            stride: mem::size_of::<Quad>() as u64, +                            stride: mem::size_of::<layer::Quad>() as u64,                              step_mode: wgpu::InputStepMode::Instance,                              attributes: &[                                  wgpu::VertexAttributeDescriptor { @@ -161,7 +162,7 @@ impl Pipeline {          let instances = device.create_buffer(&wgpu::BufferDescriptor {              label: None, -            size: mem::size_of::<Quad>() as u64 * Quad::MAX as u64, +            size: mem::size_of::<layer::Quad>() as u64 * MAX_INSTANCES as u64,              usage: wgpu::BufferUsage::VERTEX | wgpu::BufferUsage::COPY_DST,          }); @@ -179,7 +180,7 @@ impl Pipeline {          &mut self,          device: &wgpu::Device,          encoder: &mut wgpu::CommandEncoder, -        instances: &[Quad], +        instances: &[layer::Quad],          transformation: Transformation,          scale: f32,          bounds: Rectangle<u32>, @@ -204,11 +205,11 @@ impl Pipeline {          let total = instances.len();          while i < total { -            let end = (i + Quad::MAX).min(total); +            let end = (i + MAX_INSTANCES).min(total);              let amount = end - i;              let instance_buffer = device.create_buffer_with_data( -                &instances[i..end].as_bytes(), +                bytemuck::cast_slice(&instances[i..end]),                  wgpu::BufferUsage::COPY_SRC,              ); @@ -217,7 +218,7 @@ impl Pipeline {                  0,                  &self.instances,                  0, -                (mem::size_of::<Quad>() * amount) as u64, +                (mem::size_of::<layer::Quad>() * amount) as u64,              );              { @@ -260,7 +261,7 @@ impl Pipeline {                  );              } -            i += Quad::MAX; +            i += MAX_INSTANCES;          }      }  } @@ -288,20 +289,7 @@ const QUAD_VERTS: [Vertex; 4] = [      },  ]; -#[repr(C)] -#[derive(Debug, Clone, Copy, AsBytes)] -pub struct Quad { -    pub position: [f32; 2], -    pub scale: [f32; 2], -    pub color: [f32; 4], -    pub border_color: [f32; 4], -    pub border_radius: f32, -    pub border_width: f32, -} - -impl Quad { -    const MAX: usize = 100_000; -} +const MAX_INSTANCES: usize = 100_000;  #[repr(C)]  #[derive(Debug, Clone, Copy, AsBytes)] diff --git a/wgpu/src/renderer.rs b/wgpu/src/renderer.rs deleted file mode 100644 index 71b4af38..00000000 --- a/wgpu/src/renderer.rs +++ /dev/null @@ -1,507 +0,0 @@ -use crate::{ -    quad, text, triangle, Defaults, Primitive, Quad, Settings, Target, -    Transformation, -}; - -#[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 { -    quad_pipeline: quad::Pipeline, -    text_pipeline: text::Pipeline, -    triangle_pipeline: triangle::Pipeline, - -    #[cfg(any(feature = "image", feature = "svg"))] -    image_pipeline: image::Pipeline, -} - -struct Layer<'a> { -    bounds: Rectangle<u32>, -    quads: Vec<Quad>, -    meshes: Vec<(Vector, Rectangle<u32>, &'a triangle::Mesh2D)>, -    text: Vec<wgpu_glyph::Section<'a>>, - -    #[cfg(any(feature = "image", feature = "svg"))] -    images: Vec<Image>, -} - -impl<'a> Layer<'a> { -    pub fn new(bounds: Rectangle<u32>) -> Self { -        Self { -            bounds, -            quads: Vec::new(), -            text: Vec::new(), -            meshes: Vec::new(), - -            #[cfg(any(feature = "image", feature = "svg"))] -            images: Vec::new(), -        } -    } - -    pub fn intersection(&self, rectangle: Rectangle) -> Option<Rectangle<u32>> { -        let layer_bounds: Rectangle<f32> = self.bounds.into(); - -        layer_bounds.intersection(&rectangle).map(Into::into) -    } -} - -impl Renderer { -    /// Creates a new [`Renderer`]. -    /// -    /// [`Renderer`]: struct.Renderer.html -    pub fn new(device: &wgpu::Device, settings: Settings) -> Self { -        let text_pipeline = -            text::Pipeline::new(device, settings.format, settings.default_font); -        let quad_pipeline = quad::Pipeline::new(device, settings.format); -        let triangle_pipeline = triangle::Pipeline::new( -            device, -            settings.format, -            settings.antialiasing, -        ); - -        #[cfg(any(feature = "image", feature = "svg"))] -        let image_pipeline = image::Pipeline::new(device, settings.format); - -        Self { -            quad_pipeline, -            text_pipeline, -            triangle_pipeline, - -            #[cfg(any(feature = "image", feature = "svg"))] -            image_pipeline, -        } -    } - -    /// Draws the provided primitives in the given [`Target`]. -    /// -    /// The text provided as overlay will be renderer on top of the primitives. -    /// This is useful for rendering debug information. -    /// -    /// [`Target`]: struct.Target.html -    pub fn draw<T: AsRef<str>>( -        &mut self, -        device: &wgpu::Device, -        encoder: &mut wgpu::CommandEncoder, -        target: Target<'_>, -        (primitive, mouse_interaction): &(Primitive, mouse::Interaction), -        scale_factor: f64, -        overlay: &[T], -    ) -> mouse::Interaction { -        log::debug!("Drawing"); - -        let (width, height) = target.viewport.dimensions(); -        let scale_factor = scale_factor as f32; -        let transformation = target.viewport.transformation(); - -        let mut layers = Vec::new(); - -        layers.push(Layer::new(Rectangle { -            x: 0, -            y: 0, -            width, -            height, -        })); - -        self.draw_primitive(Vector::new(0.0, 0.0), primitive, &mut layers); -        self.draw_overlay(overlay, &mut layers); - -        for layer in layers { -            self.flush( -                device, -                scale_factor, -                transformation, -                &layer, -                encoder, -                target.texture, -                width, -                height, -            ); -        } - -        #[cfg(any(feature = "image", feature = "svg"))] -        self.image_pipeline.trim_cache(); - -        *mouse_interaction -    } - -    fn draw_primitive<'a>( -        &mut self, -        translation: Vector, -        primitive: &'a Primitive, -        layers: &mut Vec<Layer<'a>>, -    ) { -        match primitive { -            Primitive::None => {} -            Primitive::Group { primitives } => { -                // TODO: Inspect a bit and regroup (?) -                for primitive in primitives { -                    self.draw_primitive(translation, primitive, layers) -                } -            } -            Primitive::Text { -                content, -                bounds, -                size, -                color, -                font, -                horizontal_alignment, -                vertical_alignment, -            } => { -                let layer = layers.last_mut().unwrap(); - -                layer.text.push(wgpu_glyph::Section { -                    text: &content, -                    screen_position: ( -                        bounds.x + translation.x, -                        bounds.y + translation.y, -                    ), -                    bounds: (bounds.width, bounds.height), -                    scale: wgpu_glyph::Scale { x: *size, y: *size }, -                    color: color.into_linear(), -                    font_id: self.text_pipeline.find_font(*font), -                    layout: wgpu_glyph::Layout::default() -                        .h_align(match horizontal_alignment { -                            iced_native::HorizontalAlignment::Left => { -                                wgpu_glyph::HorizontalAlign::Left -                            } -                            iced_native::HorizontalAlignment::Center => { -                                wgpu_glyph::HorizontalAlign::Center -                            } -                            iced_native::HorizontalAlignment::Right => { -                                wgpu_glyph::HorizontalAlign::Right -                            } -                        }) -                        .v_align(match vertical_alignment { -                            iced_native::VerticalAlignment::Top => { -                                wgpu_glyph::VerticalAlign::Top -                            } -                            iced_native::VerticalAlignment::Center => { -                                wgpu_glyph::VerticalAlign::Center -                            } -                            iced_native::VerticalAlignment::Bottom => { -                                wgpu_glyph::VerticalAlign::Bottom -                            } -                        }), -                    ..Default::default() -                }) -            } -            Primitive::Quad { -                bounds, -                background, -                border_radius, -                border_width, -                border_color, -            } => { -                let layer = layers.last_mut().unwrap(); - -                // TODO: Move some of these computations to the GPU (?) -                layer.quads.push(Quad { -                    position: [ -                        bounds.x + translation.x, -                        bounds.y + translation.y, -                    ], -                    scale: [bounds.width, bounds.height], -                    color: match background { -                        Background::Color(color) => color.into_linear(), -                    }, -                    border_radius: *border_radius as f32, -                    border_width: *border_width as f32, -                    border_color: border_color.into_linear(), -                }); -            } -            Primitive::Mesh2D { size, buffers } => { -                let layer = layers.last_mut().unwrap(); - -                // Only draw visible content -                if let Some(clip_bounds) = layer.intersection(Rectangle::new( -                    Point::new(translation.x, translation.y), -                    *size, -                )) { -                    layer.meshes.push(( -                        translation, -                        clip_bounds.into(), -                        buffers, -                    )); -                } -            } -            Primitive::Clip { -                bounds, -                offset, -                content, -            } => { -                let layer = layers.last_mut().unwrap(); - -                // Only draw visible content -                if let Some(clip_bounds) = -                    layer.intersection(*bounds + translation) -                { -                    let clip_layer = Layer::new(clip_bounds.into()); -                    let new_layer = Layer::new(layer.bounds); - -                    layers.push(clip_layer); -                    self.draw_primitive( -                        translation -                            - Vector::new(offset.x as f32, offset.y as f32), -                        content, -                        layers, -                    ); -                    layers.push(new_layer); -                } -            } -            Primitive::Translate { -                translation: new_translation, -                content, -            } => { -                self.draw_primitive( -                    translation + *new_translation, -                    &content, -                    layers, -                ); -            } - -            Primitive::Cached { cache } => { -                self.draw_primitive(translation, &cache, layers); -            } - -            #[cfg(feature = "image")] -            Primitive::Image { handle, bounds } => { -                let layer = layers.last_mut().unwrap(); - -                layer.images.push(Image { -                    handle: image::Handle::Raster(handle.clone()), -                    position: [ -                        bounds.x + translation.x, -                        bounds.y + translation.y, -                    ], -                    size: [bounds.width, bounds.height], -                }); -            } -            #[cfg(not(feature = "image"))] -            Primitive::Image { .. } => {} - -            #[cfg(feature = "svg")] -            Primitive::Svg { handle, bounds } => { -                let layer = layers.last_mut().unwrap(); - -                layer.images.push(Image { -                    handle: image::Handle::Vector(handle.clone()), -                    position: [ -                        bounds.x + translation.x, -                        bounds.y + translation.y, -                    ], -                    size: [bounds.width, bounds.height], -                }); -            } -            #[cfg(not(feature = "svg"))] -            Primitive::Svg { .. } => {} -        } -    } - -    fn draw_overlay<'a, T: AsRef<str>>( -        &mut self, -        lines: &'a [T], -        layers: &mut Vec<Layer<'a>>, -    ) { -        let first = layers.first().unwrap(); -        let mut overlay = Layer::new(first.bounds); - -        let font_id = self.text_pipeline.overlay_font(); -        let scale = wgpu_glyph::Scale { x: 20.0, y: 20.0 }; - -        for (i, line) in lines.iter().enumerate() { -            overlay.text.push(wgpu_glyph::Section { -                text: line.as_ref(), -                screen_position: (11.0, 11.0 + 25.0 * i as f32), -                color: [0.9, 0.9, 0.9, 1.0], -                scale, -                font_id, -                ..wgpu_glyph::Section::default() -            }); - -            overlay.text.push(wgpu_glyph::Section { -                text: line.as_ref(), -                screen_position: (10.0, 10.0 + 25.0 * i as f32), -                color: [0.0, 0.0, 0.0, 1.0], -                scale, -                font_id, -                ..wgpu_glyph::Section::default() -            }); -        } - -        layers.push(overlay); -    } - -    fn flush( -        &mut self, -        device: &wgpu::Device, -        scale_factor: f32, -        transformation: Transformation, -        layer: &Layer<'_>, -        encoder: &mut wgpu::CommandEncoder, -        target: &wgpu::TextureView, -        target_width: u32, -        target_height: u32, -    ) { -        let bounds = layer.bounds * scale_factor; - -        if !layer.quads.is_empty() { -            self.quad_pipeline.draw( -                device, -                encoder, -                &layer.quads, -                transformation, -                scale_factor, -                bounds, -                target, -            ); -        } - -        if !layer.meshes.is_empty() { -            let scaled = transformation -                * Transformation::scale(scale_factor, scale_factor); - -            self.triangle_pipeline.draw( -                device, -                encoder, -                target, -                target_width, -                target_height, -                scaled, -                scale_factor, -                &layer.meshes, -            ); -        } - -        #[cfg(any(feature = "image", feature = "svg"))] -        { -            if !layer.images.is_empty() { -                let scaled = transformation -                    * Transformation::scale(scale_factor, scale_factor); - -                self.image_pipeline.draw( -                    device, -                    encoder, -                    &layer.images, -                    scaled, -                    bounds, -                    target, -                    scale_factor, -                ); -            } -        } - -        if !layer.text.is_empty() { -            for text in layer.text.iter() { -                // Target physical coordinates directly to avoid blurry text -                let text = wgpu_glyph::Section { -                    // TODO: We `round` here to avoid rerasterizing text when -                    // its position changes slightly. This can make text feel a -                    // bit "jumpy". We may be able to do better once we improve -                    // our text rendering/caching pipeline. -                    screen_position: ( -                        (text.screen_position.0 * scale_factor).round(), -                        (text.screen_position.1 * scale_factor).round(), -                    ), -                    // TODO: Fix precision issues with some scale factors. -                    // -                    // The `ceil` here can cause some words to render on the -                    // same line when they should not. -                    // -                    // Ideally, `wgpu_glyph` should be able to compute layout -                    // using logical positions, and then apply the proper -                    // scaling when rendering. This would ensure that both -                    // measuring and rendering follow the same layout rules. -                    bounds: ( -                        (text.bounds.0 * scale_factor).ceil(), -                        (text.bounds.1 * scale_factor).ceil(), -                    ), -                    scale: wgpu_glyph::Scale { -                        x: text.scale.x * scale_factor, -                        y: text.scale.y * scale_factor, -                    }, -                    ..*text -                }; - -                self.text_pipeline.queue(text); -            } - -            self.text_pipeline.draw_queued( -                device, -                encoder, -                target, -                transformation, -                wgpu_glyph::Region { -                    x: bounds.x, -                    y: bounds.y, -                    width: bounds.width, -                    height: bounds.height, -                }, -            ); -        } -    } -} - -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); - -        self.text_pipeline.clear_measurement_cache(); - -        node -    } -} - -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) -    } -} - -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); -    } -} 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/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/settings.rs b/wgpu/src/settings.rs index 5ee245b6..8378d734 100644 --- a/wgpu/src/settings.rs +++ b/wgpu/src/settings.rs @@ -1,6 +1,5 @@ -//! Configure a [`Renderer`]. -//! -//! [`Renderer`]: struct.Renderer.html +//! Configure a renderer. +pub use iced_graphics::Antialiasing;  /// The settings of a [`Renderer`].  /// @@ -30,27 +29,3 @@ impl Default for Settings {          }      }  } - -/// An antialiasing strategy. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum Antialiasing { -    /// Multisample AA with 2 samples -    MSAAx2, -    /// Multisample AA with 4 samples -    MSAAx4, -    /// Multisample AA with 8 samples -    MSAAx8, -    /// Multisample AA with 16 samples -    MSAAx16, -} - -impl Antialiasing { -    pub(crate) fn sample_count(self) -> u32 { -        match self { -            Antialiasing::MSAAx2 => 2, -            Antialiasing::MSAAx4 => 4, -            Antialiasing::MSAAx8 => 8, -            Antialiasing::MSAAx16 => 16, -        } -    } -} diff --git a/wgpu/src/target.rs b/wgpu/src/target.rs deleted file mode 100644 index 1e72c0c3..00000000 --- a/wgpu/src/target.rs +++ /dev/null @@ -1,14 +0,0 @@ -use crate::Viewport; - -/// A rendering target. -#[derive(Debug)] -pub struct Target<'a> { -    /// The texture where graphics will be rendered. -    pub texture: &'a wgpu::TextureView, - -    /// The viewport of the target. -    /// -    /// Most of the time, you will want this to match the dimensions of the -    /// texture. -    pub viewport: &'a Viewport, -} diff --git a/wgpu/src/text.rs b/wgpu/src/text.rs index f4521e72..d65c0385 100644 --- a/wgpu/src/text.rs +++ b/wgpu/src/text.rs @@ -1,23 +1,11 @@ -mod font; -  use crate::Transformation; - +use iced_graphics::font;  use std::{cell::RefCell, collections::HashMap}; -pub const BUILTIN_ICONS: iced_native::Font = iced_native::Font::External { -    name: "iced_wgpu icons", -    bytes: include_bytes!("text/icons.ttf"), -}; - -pub const CHECKMARK_ICON: char = '\u{F00C}'; - -const FALLBACK_FONT: &[u8] = include_bytes!("../fonts/Lato-Regular.ttf"); -  #[derive(Debug)]  pub struct Pipeline {      draw_brush: RefCell<wgpu_glyph::GlyphBrush<'static, ()>>,      draw_font_map: RefCell<HashMap<String, wgpu_glyph::FontId>>, -      measure_brush: RefCell<glyph_brush::GlyphBrush<'static, ()>>,  } @@ -34,7 +22,7 @@ impl Pipeline {              default_font.map(|slice| slice.to_vec()).unwrap_or_else(|| {                  font_source                      .load(&[font::Family::SansSerif, font::Family::Serif]) -                    .unwrap_or_else(|_| FALLBACK_FONT.to_vec()) +                    .unwrap_or_else(|_| font::FALLBACK.to_vec())              });          let load_glyph_brush = |font: Vec<u8>| { @@ -53,7 +41,7 @@ impl Pipeline {              .unwrap_or_else(|_: wgpu_glyph::rusttype::Error| {                  log::warn!("System font failed to load. Falling back to embedded font..."); -                load_glyph_brush(FALLBACK_FONT.to_vec()).expect("Load fallback font") +                load_glyph_brush(font::FALLBACK.to_vec()).expect("Load fallback font")              });          let draw_brush = brush_builder @@ -63,15 +51,10 @@ impl Pipeline {          Pipeline {              draw_brush: RefCell::new(draw_brush),              draw_font_map: RefCell::new(HashMap::new()), -              measure_brush: RefCell::new(measure_brush),          }      } -    pub fn overlay_font(&self) -> wgpu_glyph::FontId { -        wgpu_glyph::FontId(0) -    } -      pub fn queue(&mut self, section: wgpu_glyph::Section<'_>) {          self.draw_brush.borrow_mut().queue(section);      } @@ -124,21 +107,7 @@ impl Pipeline {          }      } -    pub fn space_width(&self, size: f32) -> f32 { -        use wgpu_glyph::GlyphCruncher; - -        let glyph_brush = self.measure_brush.borrow(); - -        // TODO: Select appropriate font -        let font = &glyph_brush.fonts()[0]; - -        font.glyph(' ') -            .scaled(wgpu_glyph::Scale { x: size, y: size }) -            .h_metrics() -            .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..22a27143 100644 --- a/wgpu/src/triangle.rs +++ b/wgpu/src/triangle.rs @@ -1,9 +1,11 @@  //! Draw meshes of triangles.  use crate::{settings, Transformation}; -use iced_native::{Rectangle, Vector}; +use iced_graphics::layer;  use std::mem;  use zerocopy::AsBytes; +pub use iced_graphics::triangle::{Mesh2D, Vertex2D}; +  mod msaa;  const UNIFORM_BUFFER_SIZE: usize = 100; @@ -168,9 +170,9 @@ impl Pipeline {                          ],                      }],                  }, -                sample_count: antialiasing -                    .map(|a| a.sample_count()) -                    .unwrap_or(1), +                sample_count: u32::from( +                    antialiasing.map(|a| a.sample_count()).unwrap_or(1), +                ),                  sample_mask: !0,                  alpha_to_coverage_enabled: false,              }); @@ -202,14 +204,16 @@ impl Pipeline {          target_height: u32,          transformation: Transformation,          scale_factor: f32, -        meshes: &[(Vector, Rectangle<u32>, &Mesh2D)], +        meshes: &[layer::Mesh<'_>],      ) {          // This looks a bit crazy, but we are just counting how many vertices          // and indices we will need to handle.          // TODO: Improve readability          let (total_vertices, total_indices) = meshes              .iter() -            .map(|(_, _, mesh)| (mesh.vertices.len(), mesh.indices.len())) +            .map(|layer::Mesh { buffers, .. }| { +                (buffers.vertices.len(), buffers.indices.len()) +            })              .fold((0, 0), |(total_v, total_i), (v, i)| {                  (total_v + v, total_i + i)              }); @@ -230,18 +234,18 @@ impl Pipeline {          let mut last_index = 0;          // We upload everything upfront -        for (origin, _, mesh) in meshes { +        for mesh in meshes {              let transform = (transformation -                * Transformation::translate(origin.x, origin.y)) +                * Transformation::translate(mesh.origin.x, mesh.origin.y))              .into();              let vertex_buffer = device.create_buffer_with_data( -                mesh.vertices.as_bytes(), +                bytemuck::cast_slice(&mesh.buffers.vertices),                  wgpu::BufferUsage::COPY_SRC,              );              let index_buffer = device.create_buffer_with_data( -                mesh.indices.as_bytes(), +                mesh.buffers.indices.as_bytes(),                  wgpu::BufferUsage::COPY_SRC,              ); @@ -250,7 +254,8 @@ impl Pipeline {                  0,                  &self.vertex_buffer.raw,                  (std::mem::size_of::<Vertex2D>() * last_vertex) as u64, -                (std::mem::size_of::<Vertex2D>() * mesh.vertices.len()) as u64, +                (std::mem::size_of::<Vertex2D>() * mesh.buffers.vertices.len()) +                    as u64,              );              encoder.copy_buffer_to_buffer( @@ -258,18 +263,19 @@ impl Pipeline {                  0,                  &self.index_buffer.raw,                  (std::mem::size_of::<u32>() * last_index) as u64, -                (std::mem::size_of::<u32>() * mesh.indices.len()) as u64, +                (std::mem::size_of::<u32>() * mesh.buffers.indices.len()) +                    as u64,              );              uniforms.push(transform);              offsets.push((                  last_vertex as u64,                  last_index as u64, -                mesh.indices.len(), +                mesh.buffers.indices.len(),              )); -            last_vertex += mesh.vertices.len(); -            last_index += mesh.indices.len(); +            last_vertex += mesh.buffers.vertices.len(); +            last_index += mesh.buffers.indices.len();          }          let uniforms_buffer = device.create_buffer_with_data( @@ -320,13 +326,14 @@ impl Pipeline {              for (i, (vertex_offset, index_offset, indices)) in                  offsets.into_iter().enumerate()              { -                let bounds = meshes[i].1 * scale_factor; +                let clip_bounds = +                    (meshes[i].clip_bounds * scale_factor).round();                  render_pass.set_scissor_rect( -                    bounds.x, -                    bounds.y, -                    bounds.width, -                    bounds.height, +                    clip_bounds.x, +                    clip_bounds.y, +                    clip_bounds.width, +                    clip_bounds.height,                  );                  render_pass.set_bind_group( @@ -387,26 +394,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/viewport.rs b/wgpu/src/viewport.rs deleted file mode 100644 index 66242468..00000000 --- a/wgpu/src/viewport.rs +++ /dev/null @@ -1,29 +0,0 @@ -use crate::Transformation; - -/// A viewing region for displaying computer graphics. -#[derive(Debug)] -pub struct Viewport { -    width: u32, -    height: u32, -    transformation: Transformation, -} - -impl Viewport { -    /// Creates a new [`Viewport`] with the given dimensions. -    pub fn new(width: u32, height: u32) -> Viewport { -        Viewport { -            width, -            height, -            transformation: Transformation::orthographic(width, height), -        } -    } - -    /// Returns the dimensions of the [`Viewport`]. -    pub fn dimensions(&self) -> (u32, u32) { -        (self.width, self.height) -    } - -    pub(crate) fn transformation(&self) -> Transformation { -        self.transformation -    } -} diff --git a/wgpu/src/widget.rs b/wgpu/src/widget.rs index 32ccad17..d17b7a5d 100644 --- a/wgpu/src/widget.rs +++ b/wgpu/src/widget.rs @@ -7,6 +7,8 @@  //! ```  //! use iced_wgpu::{button, Button};  //! ``` +use crate::Renderer; +  pub mod button;  pub mod checkbox;  pub mod container; @@ -17,8 +19,6 @@ pub mod scrollable;  pub mod slider;  pub mod text_input; -mod text; -  #[doc(no_inline)]  pub use button::Button;  #[doc(no_inline)] @@ -38,8 +38,6 @@ pub use slider::Slider;  #[doc(no_inline)]  pub use text_input::TextInput; -pub use text::Text; -  #[cfg(feature = "canvas")]  #[cfg_attr(docsrs, doc(cfg(feature = "canvas")))]  pub mod canvas; @@ -47,3 +45,14 @@ pub mod canvas;  #[cfg(feature = "canvas")]  #[doc(no_inline)]  pub use canvas::Canvas; + +pub use iced_native::Space; + +/// A container that distributes its contents vertically. +pub type Column<'a, Message> = iced_native::Column<'a, Message, Renderer>; + +/// A container that distributes its contents horizontally. +pub type Row<'a, Message> = iced_native::Row<'a, Message, Renderer>; + +/// A paragraph of text. +pub type Text = iced_native::Text<Renderer>; 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/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.rs b/wgpu/src/widget/text.rs deleted file mode 100644 index 1053ea97..00000000 --- a/wgpu/src/widget/text.rs +++ /dev/null @@ -1,7 +0,0 @@ -//! Write some text for your users to read. -use crate::Renderer; - -/// A paragraph of text. -/// -/// This is an alias of an `iced_native` text with an `iced_wgpu::Renderer`. -pub type Text = iced_native::Text<Renderer>; 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.rs b/wgpu/src/window.rs index b7adad82..aac5fb9e 100644 --- a/wgpu/src/window.rs +++ b/wgpu/src/window.rs @@ -1,6 +1,4 @@  //! Display rendering results on windows. -mod backend; -mod swap_chain; +mod compositor; -pub use backend::Backend; -pub use swap_chain::SwapChain; +pub use compositor::Compositor; diff --git a/wgpu/src/window/backend.rs b/wgpu/src/window/compositor.rs index 2924ce5d..600bc81c 100644 --- a/wgpu/src/window/backend.rs +++ b/wgpu/src/window/compositor.rs @@ -1,23 +1,24 @@ -use crate::{window::SwapChain, Renderer, Settings, Target}; +use crate::{Renderer, Settings}; +use iced_graphics::Viewport;  use iced_native::{futures, mouse};  use raw_window_handle::HasRawWindowHandle;  /// A window graphics backend for iced powered by `wgpu`.  #[derive(Debug)] -pub struct Backend { +pub struct Compositor {      device: wgpu::Device,      queue: wgpu::Queue,      format: wgpu::TextureFormat,  } -impl iced_native::window::Backend for Backend { +impl iced_graphics::window::Compositor for Compositor {      type Settings = Settings;      type Renderer = Renderer;      type Surface = wgpu::Surface; -    type SwapChain = SwapChain; +    type SwapChain = wgpu::SwapChain; -    fn new(settings: Self::Settings) -> (Backend, Renderer) { +    fn new(settings: Self::Settings) -> (Self, Renderer) {          let (mut device, queue) = futures::executor::block_on(async {              let adapter = wgpu::Adapter::request(                  &wgpu::RequestAdapterOptions { @@ -43,10 +44,11 @@ impl iced_native::window::Backend for Backend {                  .await          }); -        let renderer = Renderer::new(&mut device, settings); +        let renderer = +            Renderer::new(crate::Backend::new(&mut device, settings));          ( -            Backend { +            Self {                  device,                  queue,                  format: settings.format, @@ -67,19 +69,28 @@ impl iced_native::window::Backend for Backend {          surface: &Self::Surface,          width: u32,          height: u32, -    ) -> SwapChain { -        SwapChain::new(&self.device, surface, self.format, width, height) +    ) -> Self::SwapChain { +        self.device.create_swap_chain( +            surface, +            &wgpu::SwapChainDescriptor { +                usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT, +                format: self.format, +                width, +                height, +                present_mode: wgpu::PresentMode::Mailbox, +            }, +        )      }      fn draw<T: AsRef<str>>(          &mut self,          renderer: &mut Self::Renderer, -        swap_chain: &mut SwapChain, +        swap_chain: &mut Self::SwapChain, +        viewport: &Viewport,          output: &<Self::Renderer as iced_native::Renderer>::Output, -        scale_factor: f64,          overlay: &[T],      ) -> mouse::Interaction { -        let (frame, viewport) = swap_chain.next_frame().expect("Next frame"); +        let frame = swap_chain.get_next_texture().expect("Next frame");          let mut encoder = self.device.create_command_encoder(              &wgpu::CommandEncoderDescriptor { label: None }, @@ -101,15 +112,12 @@ 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 { -                texture: &frame.view, -                viewport, -            }, +            &frame.view, +            viewport,              output, -            scale_factor,              overlay,          ); diff --git a/wgpu/src/window/swap_chain.rs b/wgpu/src/window/swap_chain.rs deleted file mode 100644 index 72e58a50..00000000 --- a/wgpu/src/window/swap_chain.rs +++ /dev/null @@ -1,61 +0,0 @@ -use crate::Viewport; - -/// The rendering target of a window. -/// -/// It represents a series of virtual framebuffers with a scale factor. -#[derive(Debug)] -pub struct SwapChain { -    raw: wgpu::SwapChain, -    viewport: Viewport, -} - -impl SwapChain {} - -impl SwapChain { -    /// Creates a new [`SwapChain`] for the given surface. -    /// -    /// [`SwapChain`]: struct.SwapChain.html -    pub fn new( -        device: &wgpu::Device, -        surface: &wgpu::Surface, -        format: wgpu::TextureFormat, -        width: u32, -        height: u32, -    ) -> SwapChain { -        SwapChain { -            raw: new_swap_chain(surface, format, width, height, device), -            viewport: Viewport::new(width, height), -        } -    } - -    /// Returns the next frame of the [`SwapChain`] alongside its [`Viewport`]. -    /// -    /// [`SwapChain`]: struct.SwapChain.html -    /// [`Viewport`]: ../struct.Viewport.html -    pub fn next_frame( -        &mut self, -    ) -> Result<(wgpu::SwapChainOutput, &Viewport), wgpu::TimeOut> { -        let viewport = &self.viewport; - -        self.raw.get_next_texture().map(|output| (output, viewport)) -    } -} - -fn new_swap_chain( -    surface: &wgpu::Surface, -    format: wgpu::TextureFormat, -    width: u32, -    height: u32, -    device: &wgpu::Device, -) -> wgpu::SwapChain { -    device.create_swap_chain( -        &surface, -        &wgpu::SwapChainDescriptor { -            usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT, -            format, -            width, -            height, -            present_mode: wgpu::PresentMode::Mailbox, -        }, -    ) -} | 
