diff options
| author | 2020-05-21 00:37:47 +0200 | |
|---|---|---|
| committer | 2020-05-21 00:44:35 +0200 | |
| commit | e0e4ee73feead3f05730625c7e1917b63f0b384e (patch) | |
| tree | 5cd934cc474a5aacc60359f6fe69a5b9d31fe45b /glow/src | |
| parent | a1a5fcfd46622d5b18d1716aa2adb4659835ccf3 (diff) | |
| download | iced-e0e4ee73feead3f05730625c7e1917b63f0b384e.tar.gz iced-e0e4ee73feead3f05730625c7e1917b63f0b384e.tar.bz2 iced-e0e4ee73feead3f05730625c7e1917b63f0b384e.zip | |
Implement `iced_glutin` :tada:
Diffstat (limited to '')
| -rw-r--r-- | glow/src/backend.rs | 29 | ||||
| -rw-r--r-- | glow/src/widget.rs | 11 | ||||
| -rw-r--r-- | glow/src/widget/canvas.rs | 194 | ||||
| -rw-r--r-- | glow/src/window/compositor.rs | 170 | 
4 files changed, 59 insertions, 345 deletions
| diff --git a/glow/src/backend.rs b/glow/src/backend.rs index 5e2aa837..8c578d5e 100644 --- a/glow/src/backend.rs +++ b/glow/src/backend.rs @@ -36,12 +36,6 @@ impl Backend {          }      } -    /// 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,          gl: &glow::Context, @@ -50,6 +44,7 @@ impl Backend {          overlay_text: &[T],      ) -> mouse::Interaction {          let viewport_size = viewport.physical_size(); +        let scale_factor = viewport.scale_factor() as f32;          let projection = viewport.projection();          let mut layers = Layer::generate(primitive, viewport); @@ -58,7 +53,7 @@ impl Backend {          for layer in layers {              self.flush(                  gl, -                viewport.scale_factor() as f32, +                scale_factor,                  projection,                  &layer,                  viewport_size.width, @@ -78,7 +73,8 @@ impl Backend {          target_width: u32,          target_height: u32,      ) { -        let bounds = (layer.bounds * scale_factor).round(); +        let mut bounds = (layer.bounds * scale_factor).round(); +        bounds.height = bounds.height.min(target_height);          if !layer.quads.is_empty() {              self.quad_pipeline.draw( @@ -204,3 +200,20 @@ impl backend::Text for Backend {          self.text_pipeline.space_width(size)      }  } + +#[cfg(feature = "image")] +impl backend::Image for Backend { +    fn dimensions(&self, _handle: &iced_native::image::Handle) -> (u32, u32) { +        (50, 50) +    } +} + +#[cfg(feature = "svg")] +impl backend::Svg for Backend { +    fn viewport_dimensions( +        &self, +        _handle: &iced_native::svg::Handle, +    ) -> (u32, u32) { +        (50, 50) +    } +} diff --git a/glow/src/widget.rs b/glow/src/widget.rs index 16e7ca88..362465f4 100644 --- a/glow/src/widget.rs +++ b/glow/src/widget.rs @@ -38,7 +38,16 @@ pub use slider::Slider;  #[doc(no_inline)]  pub use text_input::TextInput; -pub use iced_native::{Image, Space, Text}; +#[cfg(feature = "canvas")] +#[cfg_attr(docsrs, doc(cfg(feature = "canvas")))] +pub mod canvas; + +#[cfg(feature = "canvas")] +#[doc(no_inline)] +pub use canvas::Canvas; + +pub use iced_native::{Image, Space};  pub type Column<'a, Message> = iced_native::Column<'a, Message, Renderer>;  pub type Row<'a, Message> = iced_native::Row<'a, Message, Renderer>; +pub type Text = iced_native::Text<Renderer>; diff --git a/glow/src/widget/canvas.rs b/glow/src/widget/canvas.rs index 325f90ce..bef34857 100644 --- a/glow/src/widget/canvas.rs +++ b/glow/src/widget/canvas.rs @@ -6,196 +6,4 @@  //!  //! [`Canvas`]: struct.Canvas.html  //! [`Frame`]: struct.Frame.html -use crate::{Defaults, Primitive, Renderer}; - -use iced_native::{ -    layout, Element, Hasher, Layout, Length, MouseCursor, Point, Size, Widget, -}; -use std::hash::Hash; - -pub mod layer; -pub mod path; - -mod drawable; -mod fill; -mod frame; -mod stroke; -mod text; - -pub use drawable::Drawable; -pub use fill::Fill; -pub use frame::Frame; -pub use layer::Layer; -pub use path::Path; -pub use stroke::{LineCap, LineJoin, Stroke}; -pub use text::Text; - -/// A widget capable of drawing 2D graphics. -/// -/// A [`Canvas`] may contain multiple layers. A [`Layer`] is drawn using the -/// painter's algorithm. In other words, layers will be drawn on top of each -/// other in the same order they are pushed into the [`Canvas`]. -/// -/// [`Canvas`]: struct.Canvas.html -/// [`Layer`]: layer/trait.Layer.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. -/// - [`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/0.1/examples -/// [`clock`]: https://github.com/hecrj/iced/tree/0.1/examples/clock -/// [`solar_system`]: https://github.com/hecrj/iced/tree/0.1/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; -/// # } -/// use iced::canvas::{self, layer, Canvas, Drawable, Fill, Frame, Path}; -/// use iced::Color; -/// -/// // First, we define the data we need for drawing -/// #[derive(Debug)] -/// struct Circle { -///     radius: f32, -/// } -/// -/// // Then, we implement the `Drawable` trait -/// impl Drawable for Circle { -///     fn draw(&self, frame: &mut Frame) { -///         // We create a `Path` representing a simple circle -///         let circle = Path::new(|p| p.circle(frame.center(), self.radius)); -/// -///         // And fill it with some color -///         frame.fill(&circle, Fill::Color(Color::BLACK)); -///     } -/// } -/// -/// // We can use a `Cache` to avoid unnecessary re-tessellation -/// let cache: layer::Cache<Circle> = layer::Cache::new(); -/// -/// // Finally, we simply provide the data to our `Cache` and push the resulting -/// // layer into a `Canvas` -/// let canvas = Canvas::new() -///     .push(cache.with(&Circle { radius: 50.0 })); -/// ``` -#[derive(Debug)] -pub struct Canvas<'a> { -    width: Length, -    height: Length, -    layers: Vec<Box<dyn Layer + 'a>>, -} - -impl<'a> Canvas<'a> { -    const DEFAULT_SIZE: u16 = 100; - -    /// Creates a new [`Canvas`] with no layers. -    /// -    /// [`Canvas`]: struct.Canvas.html -    pub fn new() -> Self { -        Canvas { -            width: Length::Units(Self::DEFAULT_SIZE), -            height: Length::Units(Self::DEFAULT_SIZE), -            layers: Vec::new(), -        } -    } - -    /// 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 -    } - -    /// Adds a [`Layer`] to the [`Canvas`]. -    /// -    /// It will be drawn on top of previous layers. -    /// -    /// [`Layer`]: layer/trait.Layer.html -    /// [`Canvas`]: struct.Canvas.html -    pub fn push(mut self, layer: impl Layer + 'a) -> Self { -        self.layers.push(Box::new(layer)); -        self -    } -} - -impl<'a, Message> Widget<Message, Renderer> for Canvas<'a> { -    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 draw( -        &self, -        _renderer: &mut Renderer, -        _defaults: &Defaults, -        layout: Layout<'_>, -        _cursor_position: Point, -    ) -> (Primitive, MouseCursor) { -        let bounds = layout.bounds(); -        let origin = Point::new(bounds.x, bounds.y); -        let size = Size::new(bounds.width, bounds.height); - -        ( -            Primitive::Group { -                primitives: self -                    .layers -                    .iter() -                    .map(|layer| Primitive::Cached { -                        origin, -                        cache: layer.draw(size), -                    }) -                    .collect(), -            }, -            MouseCursor::Idle, -        ) -    } - -    fn hash_layout(&self, state: &mut Hasher) { -        std::any::TypeId::of::<Canvas<'static>>().hash(state); - -        self.width.hash(state); -        self.height.hash(state); -    } -} - -impl<'a, Message> From<Canvas<'a>> for Element<'a, Message, Renderer> -where -    Message: 'static, -{ -    fn from(canvas: Canvas<'a>) -> Element<'a, Message, Renderer> { -        Element::new(canvas) -    } -} +pub use iced_graphics::canvas::*; diff --git a/glow/src/window/compositor.rs b/glow/src/window/compositor.rs index 514904a8..1117166f 100644 --- a/glow/src/window/compositor.rs +++ b/glow/src/window/compositor.rs @@ -1,180 +1,64 @@ -use crate::{Renderer, Settings, Viewport}; +use crate::{Backend, Renderer, Settings, Viewport}; +use core::ffi::c_void;  use glow::HasContext; +use iced_graphics::Size;  use iced_native::mouse; -use raw_window_handle::HasRawWindowHandle;  /// A window graphics backend for iced powered by `glow`.  #[allow(missing_debug_implementations)]  pub struct Compositor { -    connection: surfman::Connection, -    device: surfman::Device, -    gl_context: surfman::Context, -    gl: Option<glow::Context>, +    gl: glow::Context,  } -impl iced_graphics::window::Compositor for Compositor { +impl iced_graphics::window::GLCompositor for Compositor {      type Settings = Settings;      type Renderer = Renderer; -    type Surface = (); -    type SwapChain = (); -    fn new(_settings: Self::Settings) -> Self { -        let connection = surfman::Connection::new().expect("Create connection"); +    unsafe fn new( +        settings: Self::Settings, +        loader_function: impl FnMut(&str) -> *const c_void, +    ) -> (Self, Self::Renderer) { +        let gl = glow::Context::from_loader_function(loader_function); -        let adapter = connection -            .create_hardware_adapter() -            .expect("Create adapter"); +        gl.clear_color(1.0, 1.0, 1.0, 1.0); -        let mut device = -            connection.create_device(&adapter).expect("Create device"); +        // Enable auto-conversion from/to sRGB +        gl.enable(glow::FRAMEBUFFER_SRGB); -        let context_descriptor = device -            .create_context_descriptor(&surfman::ContextAttributes { -                version: surfman::GLVersion::new(3, 0), -                flags: surfman::ContextAttributeFlags::empty(), -            }) -            .expect("Create context descriptor"); +        // Enable alpha blending +        gl.enable(glow::BLEND); +        gl.blend_func(glow::SRC_ALPHA, glow::ONE_MINUS_SRC_ALPHA); -        let gl_context = device -            .create_context(&context_descriptor) -            .expect("Create context"); +        let renderer = Renderer::new(Backend::new(&gl, settings)); -        Self { -            connection, -            device, -            gl_context, -            gl: None, -        } -    } - -    fn create_renderer(&mut self, settings: Settings) -> Renderer { -        self.device -            .make_context_current(&self.gl_context) -            .expect("Make context current"); - -        Renderer::new(crate::Backend::new(self.gl.as_ref().unwrap(), settings)) -    } - -    fn create_surface<W: HasRawWindowHandle>( -        &mut self, -        window: &W, -    ) -> Self::Surface { -        let native_widget = self -            .connection -            .create_native_widget_from_rwh(window.raw_window_handle()) -            .expect("Create widget"); - -        let surface = self -            .device -            .create_surface( -                &self.gl_context, -                surfman::SurfaceAccess::GPUOnly, -                surfman::SurfaceType::Widget { native_widget }, -            ) -            .expect("Create surface"); - -        let surfman::SurfaceInfo { .. } = self.device.surface_info(&surface); - -        self.device -            .bind_surface_to_context(&mut self.gl_context, surface) -            .expect("Bind surface to context"); - -        self.device -            .make_context_current(&self.gl_context) -            .expect("Make context current"); - -        self.gl = Some(glow::Context::from_loader_function(|s| { -            self.device.get_proc_address(&self.gl_context, s) -        })); - -        //let mut framebuffer = -        //    skia_safe::gpu::gl::FramebufferInfo::from_fboid(framebuffer_object); - -        //framebuffer.format = gl::RGBA8; - -        //framebuffer +        (Self { gl }, renderer)      } -    fn create_swap_chain( -        &mut self, -        _surface: &Self::Surface, -        width: u32, -        height: u32, -    ) -> Self::SwapChain { -        let mut surface = self -            .device -            .unbind_surface_from_context(&mut self.gl_context) -            .expect("Unbind surface") -            .expect("Active surface"); - -        self.device -            .resize_surface( -                &self.gl_context, -                &mut surface, -                euclid::Size2D::new(width as i32, height as i32), -            ) -            .expect("Resize surface"); - -        self.device -            .bind_surface_to_context(&mut self.gl_context, surface) -            .expect("Bind surface to context"); - -        let gl = self.gl.as_ref().unwrap(); - +    fn resize_viewport(&mut self, physical_size: Size<u32>) {          unsafe { -            gl.viewport(0, 0, width as i32, height as i32); -            gl.clear_color(1.0, 1.0, 1.0, 1.0); - -            // Enable auto-conversion from/to sRGB -            gl.enable(glow::FRAMEBUFFER_SRGB); - -            // Enable alpha blending -            gl.enable(glow::BLEND); -            gl.blend_func(glow::SRC_ALPHA, glow::ONE_MINUS_SRC_ALPHA); +            self.gl.viewport( +                0, +                0, +                physical_size.width as i32, +                physical_size.height as i32, +            );          }      }      fn draw<T: AsRef<str>>(          &mut self,          renderer: &mut Self::Renderer, -        swap_chain: &mut Self::SwapChain,          viewport: &Viewport,          output: &<Self::Renderer as iced_native::Renderer>::Output,          overlay: &[T],      ) -> mouse::Interaction { -        let gl = self.gl.as_ref().unwrap(); +        let gl = &self.gl;          unsafe {              gl.clear(glow::COLOR_BUFFER_BIT);          } -        let mouse = renderer.backend_mut().draw(gl, viewport, output, overlay); - -        { -            let mut surface = self -                .device -                .unbind_surface_from_context(&mut self.gl_context) -                .expect("Unbind surface") -                .expect("Active surface"); - -            self.device -                .present_surface(&self.gl_context, &mut surface) -                .expect("Present surface"); - -            self.device -                .bind_surface_to_context(&mut self.gl_context, surface) -                .expect("Bind surface to context"); -        } - -        mouse -    } -} - -impl Drop for Compositor { -    fn drop(&mut self) { -        self.device -            .destroy_context(&mut self.gl_context) -            .expect("Destroy context"); +        renderer.backend_mut().draw(gl, viewport, output, overlay)      }  } | 
