diff options
Diffstat (limited to '')
-rw-r--r-- | graphics/src/widget/button.rs (renamed from wgpu/src/renderer/widget/button.rs) | 26 | ||||
-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) | 47 | ||||
-rw-r--r-- | wgpu/src/renderer.rs | 524 | ||||
-rw-r--r-- | wgpu/src/renderer/widget.rs | 19 | ||||
-rw-r--r-- | wgpu/src/renderer/widget/space.rs | 8 |
17 files changed, 270 insertions, 615 deletions
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/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 5799dba7..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,12 +35,10 @@ impl text_input::Renderer for Renderer { } fn measure_value(&self, value: &str, size: u16, font: Font) -> f32 { - let (width, _) = self.text_pipeline.measure( - value, - f32::from(size), - font, - Size::INFINITY, - ); + let backend = self.backend(); + + let (width, _) = + backend.measure(value, f32::from(size), font, Size::INFINITY); width } @@ -234,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/src/renderer.rs b/wgpu/src/renderer.rs deleted file mode 100644 index f3a7c288..00000000 --- a/wgpu/src/renderer.rs +++ /dev/null @@ -1,524 +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, Font, HorizontalAlignment, Layout, Point, - Rectangle, Size, Vector, VerticalAlignment, 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<Text<'a>>, - - #[cfg(any(feature = "image", feature = "svg"))] - images: Vec<Image>, -} - -#[derive(Debug, Clone, Copy)] -pub struct Text<'a> { - pub content: &'a str, - pub bounds: Rectangle, - pub color: [f32; 4], - pub size: f32, - pub font: Font, - pub horizontal_alignment: HorizontalAlignment, - pub vertical_alignment: VerticalAlignment, -} - -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(Text { - content, - bounds: *bounds + translation, - size: *size, - color: color.into_linear(), - font: *font, - horizontal_alignment: *horizontal_alignment, - vertical_alignment: *vertical_alignment, - }); - } - 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); - - for (i, line) in lines.iter().enumerate() { - let text = Text { - content: line.as_ref(), - bounds: Rectangle::new( - Point::new(11.0, 11.0 + 25.0 * i as f32), - Size::INFINITY, - ), - color: [0.9, 0.9, 0.9, 1.0], - size: 20.0, - font: Font::Default, - horizontal_alignment: HorizontalAlignment::Left, - vertical_alignment: VerticalAlignment::Top, - }; - - overlay.text.push(text); - - overlay.text.push(Text { - bounds: text.bounds + Vector::new(-1.0, -1.0), - color: [0.0, 0.0, 0.0, 1.0], - ..text - }); - } - - 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.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(), - ), - text: vec![wgpu_glyph::Text { - text: text.content, - scale: wgpu_glyph::ab_glyph::PxScale { - x: text.size * scale_factor, - y: text.size * scale_factor, - }, - font_id: self.text_pipeline.find_font(text.font), - extra: wgpu_glyph::Extra { - color: text.color, - z: 0.0, - }, - }], - 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_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()) - } -} |