summaryrefslogtreecommitdiffstats
path: root/wgpu
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón <hector0193@gmail.com>2021-08-26 14:53:15 +0700
committerLibravatar GitHub <noreply@github.com>2021-08-26 14:53:15 +0700
commit6821114cae2e41fd2bc69d6fcaee1e8574ac061d (patch)
tree5741859eba63251190eb0a901a72ef4e185349e7 /wgpu
parent2d65621a3b680457e689b93c800e74f726ffc175 (diff)
parent7614127d3641cf3224798c2f0ff07b6ae57d9a53 (diff)
downloadiced-6821114cae2e41fd2bc69d6fcaee1e8574ac061d.tar.gz
iced-6821114cae2e41fd2bc69d6fcaee1e8574ac061d.tar.bz2
iced-6821114cae2e41fd2bc69d6fcaee1e8574ac061d.zip
Merge pull request #670 from twitchyliquid64/text_backend
Refactor textual hit testing into a `renderer::Backend` method
Diffstat (limited to 'wgpu')
-rw-r--r--wgpu/src/backend.rs20
-rw-r--r--wgpu/src/text.rs92
2 files changed, 112 insertions, 0 deletions
diff --git a/wgpu/src/backend.rs b/wgpu/src/backend.rs
index 4f34045b..b31bf92c 100644
--- a/wgpu/src/backend.rs
+++ b/wgpu/src/backend.rs
@@ -2,6 +2,7 @@ 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;
@@ -274,6 +275,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_rs")]
diff --git a/wgpu/src/text.rs b/wgpu/src/text.rs
index 2b5b94c9..ee49ee4b 100644
--- a/wgpu/src/text.rs
+++ b/wgpu/src/text.rs
@@ -1,8 +1,12 @@
use crate::Transformation;
+
use iced_graphics::font;
+
use std::{cell::RefCell, collections::HashMap};
use wgpu_glyph::ab_glyph;
+pub use iced_native::text::Hit;
+
#[derive(Debug)]
pub struct Pipeline {
draw_brush: RefCell<wgpu_glyph::GlyphBrush<()>>,
@@ -117,6 +121,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 wgpu_glyph::GlyphCruncher;
+
+ let wgpu_glyph::FontId(font_id) = self.find_font(font);
+
+ let section = wgpu_glyph::Section {
+ bounds: (bounds.width, bounds.height),
+ text: vec![wgpu_glyph::Text {
+ text: content,
+ scale: size.into(),
+ font_id: wgpu_glyph::FontId(font_id),
+ extra: wgpu_glyph::Extra::default(),
+ }],
+ ..Default::default()
+ };
+
+ let mut mb = self.measure_brush.borrow_mut();
+
+ // The underlying type is FontArc, so clones are cheap.
+ use wgpu_glyph::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(
+ |wgpu_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.