diff options
Diffstat (limited to 'graphics/src/renderer.rs')
| -rw-r--r-- | graphics/src/renderer.rs | 201 | 
1 files changed, 125 insertions, 76 deletions
diff --git a/graphics/src/renderer.rs b/graphics/src/renderer.rs index 8f234f1f..c32eb471 100644 --- a/graphics/src/renderer.rs +++ b/graphics/src/renderer.rs @@ -1,30 +1,43 @@ -use crate::{Backend, Defaults, Primitive}; -use iced_native::layout::{self, Layout}; -use iced_native::mouse; -use iced_native::{ -    Background, Color, Element, Point, Rectangle, Vector, Widget, -}; +//! Create a renderer from a [`Backend`]. +use crate::backend::{self, Backend}; +use crate::{Primitive, Vector}; +use iced_native::layout; +use iced_native::renderer; +use iced_native::text::{self, Text}; +use iced_native::{Background, Element, Font, Point, Rectangle, Size}; + +pub use iced_native::renderer::Style;  /// A backend-agnostic renderer that supports all the built-in widgets.  #[derive(Debug)]  pub struct Renderer<B: Backend> {      backend: B, +    primitives: Vec<Primitive>,  }  impl<B: Backend> Renderer<B> {      /// Creates a new [`Renderer`] from the given [`Backend`].      pub fn new(backend: B) -> Self { -        Self { backend } +        Self { +            backend, +            primitives: Vec::new(), +        }      } -    /// Returns a reference to the [`Backend`] of the [`Renderer`]. +    /// Returns the [`Backend`] of the [`Renderer`].      pub fn backend(&self) -> &B {          &self.backend      } -    /// Returns a mutable reference to the [`Backend`] of the [`Renderer`]. -    pub fn backend_mut(&mut self) -> &mut B { -        &mut self.backend +    /// Enqueues the given [`Primitive`] in the [`Renderer`] for drawing. +    pub fn draw_primitive(&mut self, primitive: Primitive) { +        self.primitives.push(primitive); +    } + +    /// Runs the given closure with the [`Backend`] and the recorded primitives +    /// of the [`Renderer`]. +    pub fn with_primitives(&mut self, f: impl FnOnce(&mut B, &[Primitive])) { +        f(&mut self.backend, &self.primitives);      }  } @@ -32,9 +45,6 @@ impl<B> iced_native::Renderer for Renderer<B>  where      B: Backend,  { -    type Output = (Primitive, mouse::Interaction); -    type Defaults = Defaults; -      fn layout<'a, Message>(          &mut self,          element: &Element<'a, Message, Self>, @@ -47,75 +57,114 @@ where          layout      } -    fn overlay( +    fn with_layer(&mut self, bounds: Rectangle, f: impl FnOnce(&mut Self)) { +        let current_primitives = std::mem::take(&mut self.primitives); + +        f(self); + +        let layer_primitives = +            std::mem::replace(&mut self.primitives, current_primitives); + +        self.primitives.push(Primitive::Clip { +            bounds, +            content: Box::new(Primitive::Group { +                primitives: layer_primitives, +            }), +        }); +    } + +    fn with_translation(          &mut self, -        (base_primitive, base_cursor): (Primitive, mouse::Interaction), -        (overlay_primitives, overlay_cursor): (Primitive, mouse::Interaction), -        overlay_bounds: Rectangle, -    ) -> (Primitive, mouse::Interaction) { -        ( -            Primitive::Group { -                primitives: vec![ -                    base_primitive, -                    Primitive::Clip { -                        bounds: Rectangle { -                            width: overlay_bounds.width + 0.5, -                            height: overlay_bounds.height + 0.5, -                            ..overlay_bounds -                        }, -                        offset: Vector::new(0, 0), -                        content: Box::new(overlay_primitives), -                    }, -                ], -            }, -            if base_cursor > overlay_cursor { -                base_cursor -            } else { -                overlay_cursor -            }, -        ) +        translation: Vector, +        f: impl FnOnce(&mut Self), +    ) { +        let current_primitives = std::mem::take(&mut self.primitives); + +        f(self); + +        let layer_primitives = +            std::mem::replace(&mut self.primitives, current_primitives); + +        self.primitives.push(Primitive::Translate { +            translation, +            content: Box::new(Primitive::Group { +                primitives: layer_primitives, +            }), +        }); +    } + +    fn fill_quad( +        &mut self, +        quad: renderer::Quad, +        background: impl Into<Background>, +    ) { +        self.primitives.push(Primitive::Quad { +            bounds: quad.bounds, +            background: background.into(), +            border_radius: quad.border_radius, +            border_width: quad.border_width, +            border_color: quad.border_color, +        }); +    } + +    fn clear(&mut self) { +        self.primitives.clear();      }  } -impl<B> layout::Debugger for Renderer<B> +impl<B> text::Renderer for Renderer<B>  where -    B: Backend, +    B: Backend + backend::Text,  { -    fn explain<Message>( -        &mut self, -        defaults: &Defaults, -        widget: &dyn Widget<Message, Self>, -        layout: Layout<'_>, -        cursor_position: Point, -        viewport: &Rectangle, -        color: Color, -    ) -> Self::Output { -        let (primitive, cursor) = -            widget.draw(self, defaults, layout, cursor_position, viewport); - -        let mut primitives = Vec::new(); - -        explain_layout(layout, color, &mut primitives); -        primitives.push(primitive); - -        (Primitive::Group { primitives }, cursor) +    type Font = Font; + +    const ICON_FONT: Font = B::ICON_FONT; +    const CHECKMARK_ICON: char = B::CHECKMARK_ICON; +    const ARROW_DOWN_ICON: char = B::ARROW_DOWN_ICON; + +    fn default_size(&self) -> u16 { +        self.backend().default_size() +    } + +    fn measure( +        &self, +        content: &str, +        size: u16, +        font: Font, +        bounds: Size, +    ) -> (f32, f32) { +        self.backend() +            .measure(content, f32::from(size), font, bounds) +    } + +    fn hit_test( +        &self, +        content: &str, +        size: f32, +        font: Font, +        bounds: Size, +        point: Point, +        nearest_only: bool, +    ) -> Option<text::Hit> { +        self.backend().hit_test( +            content, +            size, +            font, +            bounds, +            point, +            nearest_only, +        )      } -} -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.0, -        border_width: 1.0, -        border_color: color, -    }); - -    for child in layout.children() { -        explain_layout(child, color, primitives); +    fn fill_text(&mut self, text: Text<'_, Self::Font>) { +        self.primitives.push(Primitive::Text { +            content: text.content.to_string(), +            bounds: text.bounds, +            size: text.size, +            color: text.color, +            font: text.font, +            horizontal_alignment: text.horizontal_alignment, +            vertical_alignment: text.vertical_alignment, +        });      }  }  | 
