diff options
Diffstat (limited to 'glow/src')
-rw-r--r-- | glow/src/backend.rs | 27 | ||||
-rw-r--r-- | glow/src/lib.rs | 4 | ||||
-rw-r--r-- | glow/src/settings.rs | 18 | ||||
-rw-r--r-- | glow/src/text.rs | 102 | ||||
-rw-r--r-- | glow/src/widget.rs | 3 | ||||
-rw-r--r-- | glow/src/widget/pane_grid.rs | 2 | ||||
-rw-r--r-- | glow/src/widget/toggler.rs | 9 |
7 files changed, 158 insertions, 7 deletions
diff --git a/glow/src/backend.rs b/glow/src/backend.rs index 92bb993e..37c0ac9d 100644 --- a/glow/src/backend.rs +++ b/glow/src/backend.rs @@ -2,6 +2,7 @@ use crate::quad; use crate::text; use crate::triangle; use crate::{Settings, Transformation, Viewport}; + use iced_graphics::backend; use iced_graphics::font; use iced_graphics::Layer; @@ -24,7 +25,12 @@ pub struct Backend { impl Backend { /// Creates a new [`Backend`]. pub fn new(gl: &glow::Context, settings: Settings) -> Self { - let text_pipeline = text::Pipeline::new(gl, settings.default_font); + let text_pipeline = text::Pipeline::new( + gl, + settings.default_font, + settings.text_multithreading, + ); + let quad_pipeline = quad::Pipeline::new(gl); let triangle_pipeline = triangle::Pipeline::new(gl); @@ -206,6 +212,25 @@ impl backend::Text for Backend { ) -> (f32, f32) { self.text_pipeline.measure(contents, size, font, bounds) } + + fn hit_test( + &self, + contents: &str, + size: f32, + font: Font, + bounds: Size, + point: iced_native::Point, + nearest_only: bool, + ) -> text::Hit { + self.text_pipeline.hit_test( + contents, + size, + font, + bounds, + point, + nearest_only, + ) + } } #[cfg(feature = "image")] diff --git a/glow/src/lib.rs b/glow/src/lib.rs index 98faf24c..888492d8 100644 --- a/glow/src/lib.rs +++ b/glow/src/lib.rs @@ -4,14 +4,14 @@ //! //! [`glow`]: https://github.com/grovesNL/glow //! [`iced_native`]: https://github.com/hecrj/iced/tree/master/native -#![deny(missing_docs)] +//#![deny(missing_docs)] #![deny(missing_debug_implementations)] #![deny(unused_results)] #![forbid(rust_2018_idioms)] #![cfg_attr(docsrs, feature(doc_cfg))] mod backend; -mod program; +pub mod program; mod quad; mod text; mod triangle; diff --git a/glow/src/settings.rs b/glow/src/settings.rs index 524d91a9..f3dddfaf 100644 --- a/glow/src/settings.rs +++ b/glow/src/settings.rs @@ -16,7 +16,15 @@ pub struct Settings { /// By default, it will be set to 20. pub default_text_size: u16, + /// If enabled, spread text workload in multiple threads when multiple cores + /// are available. + /// + /// By default, it is disabled. + pub text_multithreading: bool, + /// The antialiasing strategy that will be used for triangle primitives. + /// + /// By default, it is `None`. pub antialiasing: Option<Antialiasing>, } @@ -25,7 +33,17 @@ impl Default for Settings { Settings { default_font: None, default_text_size: 20, + text_multithreading: false, antialiasing: None, } } } + +impl Settings { + /// Creates new [`Settings`] using environment configuration. + /// + /// Currently, this is equivalent to calling [`Settings::default`]. + pub fn from_env() -> Self { + Self::default() + } +} diff --git a/glow/src/text.rs b/glow/src/text.rs index 925c7287..d6915d92 100644 --- a/glow/src/text.rs +++ b/glow/src/text.rs @@ -1,8 +1,12 @@ use crate::Transformation; -use glow_glyph::ab_glyph; + use iced_graphics::font; + +use glow_glyph::ab_glyph; use std::{cell::RefCell, collections::HashMap}; +pub use iced_native::text::Hit; + #[derive(Debug)] pub struct Pipeline { draw_brush: RefCell<glow_glyph::GlyphBrush>, @@ -11,7 +15,11 @@ pub struct Pipeline { } impl Pipeline { - pub fn new(gl: &glow::Context, default_font: Option<&[u8]>) -> Self { + pub fn new( + gl: &glow::Context, + default_font: Option<&[u8]>, + multithreading: bool, + ) -> Self { let default_font = default_font.map(|slice| slice.to_vec()); // TODO: Font customization @@ -41,7 +49,7 @@ impl Pipeline { let draw_brush = glow_glyph::GlyphBrushBuilder::using_font(font.clone()) .initial_cache_size((2048, 2048)) - .draw_cache_multithread(false) // TODO: Expose as a configuration flag + .draw_cache_multithread(multithreading) .build(&gl); let measure_brush = @@ -105,6 +113,94 @@ impl Pipeline { } } + pub fn hit_test( + &self, + content: &str, + size: f32, + font: iced_native::Font, + bounds: iced_native::Size, + point: iced_native::Point, + nearest_only: bool, + ) -> Hit { + use glow_glyph::GlyphCruncher; + + let glow_glyph::FontId(font_id) = self.find_font(font); + + let section = glow_glyph::Section { + bounds: (bounds.width, bounds.height), + text: vec![glow_glyph::Text { + text: content, + scale: size.into(), + font_id: glow_glyph::FontId(font_id), + extra: glow_glyph::Extra::default(), + }], + ..Default::default() + }; + + let mut mb = self.measure_brush.borrow_mut(); + + // The underlying type is FontArc, so clones are cheap. + use ab_glyph::{Font, ScaleFont}; + let font = mb.fonts()[font_id].clone().into_scaled(size); + + // Implements an iterator over the glyph bounding boxes. + let bounds = mb.glyphs(section).map( + |glow_glyph::SectionGlyph { + byte_index, glyph, .. + }| { + ( + *byte_index, + iced_native::Rectangle::new( + iced_native::Point::new( + glyph.position.x - font.h_side_bearing(glyph.id), + glyph.position.y - font.ascent(), + ), + iced_native::Size::new( + font.h_advance(glyph.id), + font.ascent() - font.descent(), + ), + ), + ) + }, + ); + + // Implements computation of the character index based on the byte index + // within the input string. + let char_index = |byte_index| { + let mut b_count = 0; + for (i, utf8_len) in + content.chars().map(|c| c.len_utf8()).enumerate() + { + if byte_index < (b_count + utf8_len) { + return i; + } + b_count += utf8_len; + } + return byte_index; + }; + + if !nearest_only { + for (idx, bounds) in bounds.clone() { + if bounds.contains(point) { + return Hit::CharOffset(char_index(idx)); + } + } + } + + let (idx, nearest) = bounds.fold( + (0usize, iced_native::Point::ORIGIN), + |acc: (usize, iced_native::Point), (idx, bounds)| { + if bounds.center().distance(point) < acc.1.distance(point) { + (idx, bounds.center()) + } else { + acc + } + }, + ); + + Hit::NearestCharOffset(char_index(idx), (point - nearest).into()) + } + 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. diff --git a/glow/src/widget.rs b/glow/src/widget.rs index 5481216a..a77511e8 100644 --- a/glow/src/widget.rs +++ b/glow/src/widget.rs @@ -20,6 +20,7 @@ pub mod rule; pub mod scrollable; pub mod slider; pub mod text_input; +pub mod toggler; pub mod tooltip; #[doc(no_inline)] @@ -45,6 +46,8 @@ pub use slider::Slider; #[doc(no_inline)] pub use text_input::TextInput; #[doc(no_inline)] +pub use toggler::Toggler; +#[doc(no_inline)] pub use tooltip::Tooltip; #[cfg(feature = "canvas")] diff --git a/glow/src/widget/pane_grid.rs b/glow/src/widget/pane_grid.rs index 44f9201c..fc36862c 100644 --- a/glow/src/widget/pane_grid.rs +++ b/glow/src/widget/pane_grid.rs @@ -6,7 +6,7 @@ //! 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.2/examples/pane_grid +//! [`pane_grid` example]: https://github.com/hecrj/iced/tree/0.3/examples/pane_grid use crate::Renderer; pub use iced_graphics::pane_grid::{ diff --git a/glow/src/widget/toggler.rs b/glow/src/widget/toggler.rs new file mode 100644 index 00000000..1cd8711b --- /dev/null +++ b/glow/src/widget/toggler.rs @@ -0,0 +1,9 @@ +//! Show toggle controls using togglers. +use crate::Renderer; + +pub use iced_graphics::toggler::{Style, StyleSheet}; + +/// A toggler that can be toggled. +/// +/// This is an alias of an `iced_native` checkbox with an `iced_wgpu::Renderer`. +pub type Toggler<Message> = iced_native::Toggler<Message, Renderer>; |