From d4743183d40c6044ce6fa39e2a52919a32912cda Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 19 May 2020 14:23:28 +0200 Subject: Draft first working version of `iced_glow` :tada: --- glow/src/text.rs | 180 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 glow/src/text.rs (limited to 'glow/src/text.rs') diff --git a/glow/src/text.rs b/glow/src/text.rs new file mode 100644 index 00000000..bda619fc --- /dev/null +++ b/glow/src/text.rs @@ -0,0 +1,180 @@ +mod font; + +use crate::Transformation; + +use std::{cell::RefCell, collections::HashMap}; + +pub const BUILTIN_ICONS: iced_native::Font = iced_native::Font::External { + name: "iced_glow icons", + bytes: include_bytes!("text/icons.ttf"), +}; + +pub const CHECKMARK_ICON: char = '\u{F00C}'; + +const FALLBACK_FONT: &[u8] = + include_bytes!("../../wgpu/fonts/Lato-Regular.ttf"); + +#[derive(Debug)] +pub struct Pipeline { + draw_brush: RefCell>, + draw_font_map: RefCell>, + + measure_brush: RefCell>, +} + +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(|_| FALLBACK_FONT.to_vec()) + }); + + let load_glyph_brush = |font: Vec| { + let builder = + glow_glyph::GlyphBrushBuilder::using_fonts_bytes(vec![ + font.clone() + ])?; + + Ok(( + builder, + glyph_brush::GlyphBrushBuilder::using_font_bytes(font).build(), + )) + }; + + let (brush_builder, measure_brush) = load_glyph_brush(default_font) + .unwrap_or_else(|_: glow_glyph::rusttype::Error| { + log::warn!("System font failed to load. Falling back to embedded font..."); + + load_glyph_brush(FALLBACK_FONT.to_vec()).expect("Load fallback font") + }); + + let draw_brush = + brush_builder.initial_cache_size((2048, 2048)).build(gl); + + Pipeline { + draw_brush: RefCell::new(draw_brush), + draw_font_map: RefCell::new(HashMap::new()), + + measure_brush: RefCell::new(measure_brush), + } + } + + pub fn overlay_font(&self) -> glow_glyph::FontId { + glow_glyph::FontId(0) + } + + 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 { + text: content, + scale: glow_glyph::Scale { x: size, y: size }, + bounds: (bounds.width, bounds.height), + font_id: glow_glyph::FontId(font_id), + ..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 space_width(&self, size: f32) -> f32 { + use glow_glyph::GlyphCruncher; + + let glyph_brush = self.measure_brush.borrow(); + + // TODO: Select appropriate font + let font = &glyph_brush.fonts()[0]; + + font.glyph(' ') + .scaled(glow_glyph::Scale { x: size, y: size }) + .h_metrics() + .advance_width + } + + pub fn clear_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; + } + + // TODO: Find a way to share font data + let _ = self.measure_brush.borrow_mut().add_font_bytes(bytes); + + let font_id = + self.draw_brush.borrow_mut().add_font_bytes(bytes); + + let _ = self + .draw_font_map + .borrow_mut() + .insert(String::from(name), font_id); + + font_id + } + } + } +} -- cgit From 05af8d00d4c0f7b8e0ece85224fd90a92da86da8 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 19 May 2020 17:15:44 +0200 Subject: Draft new `iced_graphics` crate :tada: --- glow/src/text.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'glow/src/text.rs') diff --git a/glow/src/text.rs b/glow/src/text.rs index bda619fc..159c80a6 100644 --- a/glow/src/text.rs +++ b/glow/src/text.rs @@ -130,7 +130,7 @@ impl Pipeline { .advance_width } - pub fn clear_measurement_cache(&mut self) { + 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 -- cgit From e0c4f1a08e756f11c30a99cd739fe78267e5040b Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 19 May 2020 20:20:51 +0200 Subject: Move `font::Source` to `iced_graphics` --- glow/src/text.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'glow/src/text.rs') diff --git a/glow/src/text.rs b/glow/src/text.rs index 159c80a6..be88ceaf 100644 --- a/glow/src/text.rs +++ b/glow/src/text.rs @@ -1,7 +1,5 @@ -mod font; - use crate::Transformation; - +use iced_graphics::font; use std::{cell::RefCell, collections::HashMap}; pub const BUILTIN_ICONS: iced_native::Font = iced_native::Font::External { -- cgit From f0480854a9cd76f443848dbfa14256089b56abfe Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 19 May 2020 20:30:46 +0200 Subject: Move built-in fonts to `iced_graphics` --- glow/src/text.rs | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'glow/src/text.rs') diff --git a/glow/src/text.rs b/glow/src/text.rs index be88ceaf..952fd2cd 100644 --- a/glow/src/text.rs +++ b/glow/src/text.rs @@ -2,16 +2,6 @@ use crate::Transformation; use iced_graphics::font; use std::{cell::RefCell, collections::HashMap}; -pub const BUILTIN_ICONS: iced_native::Font = iced_native::Font::External { - name: "iced_glow icons", - bytes: include_bytes!("text/icons.ttf"), -}; - -pub const CHECKMARK_ICON: char = '\u{F00C}'; - -const FALLBACK_FONT: &[u8] = - include_bytes!("../../wgpu/fonts/Lato-Regular.ttf"); - #[derive(Debug)] pub struct Pipeline { draw_brush: RefCell>, @@ -29,7 +19,7 @@ impl Pipeline { default_font.map(|slice| slice.to_vec()).unwrap_or_else(|| { font_source .load(&[font::Family::SansSerif, font::Family::Serif]) - .unwrap_or_else(|_| FALLBACK_FONT.to_vec()) + .unwrap_or_else(|_| font::FALLBACK.to_vec()) }); let load_glyph_brush = |font: Vec| { @@ -48,7 +38,7 @@ impl Pipeline { .unwrap_or_else(|_: glow_glyph::rusttype::Error| { log::warn!("System font failed to load. Falling back to embedded font..."); - load_glyph_brush(FALLBACK_FONT.to_vec()).expect("Load fallback font") + load_glyph_brush(font::FALLBACK.to_vec()).expect("Load fallback font") }); let draw_brush = -- cgit From 2798d4935e14a2453adc9e85c1037cac3b79a8c9 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 21 May 2020 19:08:04 +0200 Subject: Remove unused `overlay_font` in `iced_glow` --- glow/src/text.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'glow/src/text.rs') diff --git a/glow/src/text.rs b/glow/src/text.rs index 952fd2cd..0a11b64f 100644 --- a/glow/src/text.rs +++ b/glow/src/text.rs @@ -36,9 +36,13 @@ impl Pipeline { let (brush_builder, measure_brush) = load_glyph_brush(default_font) .unwrap_or_else(|_: glow_glyph::rusttype::Error| { - log::warn!("System font failed to load. Falling back to embedded font..."); + log::warn!( + "System font failed to load. \ + Falling back to embedded font..." + ); - load_glyph_brush(font::FALLBACK.to_vec()).expect("Load fallback font") + load_glyph_brush(font::FALLBACK.to_vec()) + .expect("Load fallback font") }); let draw_brush = @@ -52,10 +56,6 @@ impl Pipeline { } } - pub fn overlay_font(&self) -> glow_glyph::FontId { - glow_glyph::FontId(0) - } - pub fn queue(&mut self, section: glow_glyph::Section<'_>) { self.draw_brush.borrow_mut().queue(section); } -- cgit From 823ea1573245b849a0696543838a7ad1d0f914d8 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 27 May 2020 23:09:27 +0200 Subject: Update `glyph_brush` and `glow_glyph` --- glow/src/text.rs | 69 +++++++++++++++++++++----------------------------------- 1 file changed, 26 insertions(+), 43 deletions(-) (limited to 'glow/src/text.rs') diff --git a/glow/src/text.rs b/glow/src/text.rs index 0a11b64f..6dc7882c 100644 --- a/glow/src/text.rs +++ b/glow/src/text.rs @@ -1,13 +1,13 @@ 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>, + draw_brush: RefCell, draw_font_map: RefCell>, - - measure_brush: RefCell>, + measure_brush: RefCell>, } impl Pipeline { @@ -22,36 +22,29 @@ impl Pipeline { .unwrap_or_else(|_| font::FALLBACK.to_vec()) }); - let load_glyph_brush = |font: Vec| { - let builder = - glow_glyph::GlyphBrushBuilder::using_fonts_bytes(vec![ - font.clone() - ])?; - - Ok(( - builder, - glyph_brush::GlyphBrushBuilder::using_font_bytes(font).build(), - )) - }; - - let (brush_builder, measure_brush) = load_glyph_brush(default_font) - .unwrap_or_else(|_: glow_glyph::rusttype::Error| { + 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..." + "System font failed to load. Falling back to \ + embedded font..." ); - load_glyph_brush(font::FALLBACK.to_vec()) + ab_glyph::FontArc::try_from_slice(font::FALLBACK) .expect("Load fallback font") }); let draw_brush = - brush_builder.initial_cache_size((2048, 2048)).build(gl); + 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), } } @@ -88,10 +81,13 @@ impl Pipeline { let glow_glyph::FontId(font_id) = self.find_font(font); let section = glow_glyph::Section { - text: content, - scale: glow_glyph::Scale { x: size, y: size }, bounds: (bounds.width, bounds.height), - font_id: glow_glyph::FontId(font_id), + text: vec![glow_glyph::Text { + text: content, + scale: size.into(), + font_id: glow_glyph::FontId(font_id), + extra: glow_glyph::Extra::default(), + }], ..Default::default() }; @@ -104,20 +100,6 @@ impl Pipeline { } } - pub fn space_width(&self, size: f32) -> f32 { - use glow_glyph::GlyphCruncher; - - let glyph_brush = self.measure_brush.borrow(); - - // TODO: Select appropriate font - let font = &glyph_brush.fonts()[0]; - - font.glyph(' ') - .scaled(glow_glyph::Scale { x: size, y: size }) - .h_metrics() - .advance_width - } - 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. @@ -150,11 +132,12 @@ impl Pipeline { return *font_id; } - // TODO: Find a way to share font data - let _ = self.measure_brush.borrow_mut().add_font_bytes(bytes); + 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_bytes(bytes); + let font_id = self.draw_brush.borrow_mut().add_font(font); let _ = self .draw_font_map -- cgit