summaryrefslogtreecommitdiffstats
path: root/glow/src/text.rs
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón <hector0193@gmail.com>2020-05-28 21:52:34 +0200
committerLibravatar GitHub <noreply@github.com>2020-05-28 21:52:34 +0200
commitd3db055583f4cbef1441fd66d07da70424bd1200 (patch)
tree9f695bd26f688a5aaf3b8fa687a0e3ff096ffe11 /glow/src/text.rs
parentead4186870d1b46015986f702dd63382498060fc (diff)
parent709ed1f3f7ad8cf67a176763e394aaae4e808e93 (diff)
downloadiced-d3db055583f4cbef1441fd66d07da70424bd1200.tar.gz
iced-d3db055583f4cbef1441fd66d07da70424bd1200.tar.bz2
iced-d3db055583f4cbef1441fd66d07da70424bd1200.zip
Merge pull request #354 from hecrj/feature/glow-renderer
OpenGL renderer and backend-agnostic graphics subcrate
Diffstat (limited to 'glow/src/text.rs')
-rw-r--r--glow/src/text.rs151
1 files changed, 151 insertions, 0 deletions
diff --git a/glow/src/text.rs b/glow/src/text.rs
new file mode 100644
index 00000000..6dc7882c
--- /dev/null
+++ b/glow/src/text.rs
@@ -0,0 +1,151 @@
+use crate::Transformation;
+use glow_glyph::ab_glyph;
+use iced_graphics::font;
+use std::{cell::RefCell, collections::HashMap};
+
+#[derive(Debug)]
+pub struct Pipeline {
+ draw_brush: RefCell<glow_glyph::GlyphBrush>,
+ draw_font_map: RefCell<HashMap<String, glow_glyph::FontId>>,
+ measure_brush: RefCell<glyph_brush::GlyphBrush<()>>,
+}
+
+impl Pipeline {
+ pub fn new(gl: &glow::Context, default_font: Option<&[u8]>) -> Self {
+ // TODO: Font customization
+ let font_source = font::Source::new();
+
+ let default_font =
+ default_font.map(|slice| slice.to_vec()).unwrap_or_else(|| {
+ font_source
+ .load(&[font::Family::SansSerif, font::Family::Serif])
+ .unwrap_or_else(|_| font::FALLBACK.to_vec())
+ });
+
+ let font = ab_glyph::FontArc::try_from_vec(default_font)
+ .unwrap_or_else(|_| {
+ log::warn!(
+ "System font failed to load. Falling back to \
+ embedded font..."
+ );
+
+ ab_glyph::FontArc::try_from_slice(font::FALLBACK)
+ .expect("Load fallback font")
+ });
+
+ 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
+ .build(&gl);
+
+ let measure_brush =
+ glyph_brush::GlyphBrushBuilder::using_font(font).build();
+
+ Pipeline {
+ draw_brush: RefCell::new(draw_brush),
+ draw_font_map: RefCell::new(HashMap::new()),
+ measure_brush: RefCell::new(measure_brush),
+ }
+ }
+
+ pub fn queue(&mut self, section: glow_glyph::Section<'_>) {
+ self.draw_brush.borrow_mut().queue(section);
+ }
+
+ pub fn draw_queued(
+ &mut self,
+ gl: &glow::Context,
+ transformation: Transformation,
+ region: glow_glyph::Region,
+ ) {
+ self.draw_brush
+ .borrow_mut()
+ .draw_queued_with_transform_and_scissoring(
+ gl,
+ transformation.into(),
+ region,
+ )
+ .expect("Draw text");
+ }
+
+ pub fn measure(
+ &self,
+ content: &str,
+ size: f32,
+ font: iced_native::Font,
+ bounds: iced_native::Size,
+ ) -> (f32, f32) {
+ 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()
+ };
+
+ if let Some(bounds) =
+ self.measure_brush.borrow_mut().glyph_bounds(section)
+ {
+ (bounds.width().ceil(), bounds.height().ceil())
+ } else {
+ (0.0, 0.0)
+ }
+ }
+
+ 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.
+ // This makes stuff quite inconvenient. A manual method for trimming the
+ // cache would make our lives easier.
+ loop {
+ let action = self
+ .measure_brush
+ .borrow_mut()
+ .process_queued(|_, _| {}, |_| {});
+
+ match action {
+ Ok(_) => break,
+ Err(glyph_brush::BrushError::TextureTooSmall { suggested }) => {
+ let (width, height) = suggested;
+
+ self.measure_brush
+ .borrow_mut()
+ .resize_texture(width, height);
+ }
+ }
+ }
+ }
+
+ pub fn find_font(&self, font: iced_native::Font) -> glow_glyph::FontId {
+ match font {
+ iced_native::Font::Default => glow_glyph::FontId(0),
+ iced_native::Font::External { name, bytes } => {
+ if let Some(font_id) = self.draw_font_map.borrow().get(name) {
+ return *font_id;
+ }
+
+ let font = ab_glyph::FontArc::try_from_slice(bytes)
+ .expect("Load font");
+
+ let _ = self.measure_brush.borrow_mut().add_font(font.clone());
+
+ let font_id = self.draw_brush.borrow_mut().add_font(font);
+
+ let _ = self
+ .draw_font_map
+ .borrow_mut()
+ .insert(String::from(name), font_id);
+
+ font_id
+ }
+ }
+ }
+}