Remove iced_glow, glyph-brush, and wgpu_glyph dependencies

This commit is contained in:
Héctor Ramón Jiménez 2023-01-06 23:29:38 +01:00
parent 573d27eb52
commit b9a9576207
No known key found for this signature in database
GPG key ID: 140CC052C94F138E
47 changed files with 30 additions and 3846 deletions

View file

@ -4,10 +4,8 @@ use crate::triangle;
use crate::{Settings, Transformation};
use iced_graphics::backend;
use iced_graphics::font;
use iced_graphics::layer::Layer;
use iced_graphics::{Primitive, Viewport};
use iced_native::alignment;
use iced_native::{Font, Size};
#[cfg(feature = "tracing")]
@ -173,83 +171,11 @@ impl Backend {
}
if !layer.text.is_empty() {
for text in layer.text.iter() {
// Target physical coordinates directly to avoid blurry text
let text = wgpu_glyph::Section {
// TODO: We `round` here to avoid rerasterizing text when
// its position changes slightly. This can make text feel a
// bit "jumpy". We may be able to do better once we improve
// our text rendering/caching pipeline.
screen_position: (
(text.bounds.x * scale_factor).round(),
(text.bounds.y * scale_factor).round(),
),
// TODO: Fix precision issues with some scale factors.
//
// The `ceil` here can cause some words to render on the
// same line when they should not.
//
// Ideally, `wgpu_glyph` should be able to compute layout
// using logical positions, and then apply the proper
// scaling when rendering. This would ensure that both
// measuring and rendering follow the same layout rules.
bounds: (
(text.bounds.width * scale_factor).ceil(),
(text.bounds.height * scale_factor).ceil(),
),
text: vec![wgpu_glyph::Text {
text: text.content,
scale: wgpu_glyph::ab_glyph::PxScale {
x: text.size * scale_factor,
y: text.size * scale_factor,
},
font_id: self.text_pipeline.find_font(text.font),
extra: wgpu_glyph::Extra {
color: text.color,
z: 0.0,
},
}],
layout: wgpu_glyph::Layout::default()
.h_align(match text.horizontal_alignment {
alignment::Horizontal::Left => {
wgpu_glyph::HorizontalAlign::Left
}
alignment::Horizontal::Center => {
wgpu_glyph::HorizontalAlign::Center
}
alignment::Horizontal::Right => {
wgpu_glyph::HorizontalAlign::Right
}
})
.v_align(match text.vertical_alignment {
alignment::Vertical::Top => {
wgpu_glyph::VerticalAlign::Top
}
alignment::Vertical::Center => {
wgpu_glyph::VerticalAlign::Center
}
alignment::Vertical::Bottom => {
wgpu_glyph::VerticalAlign::Bottom
}
}),
};
self.text_pipeline.queue(text);
for _text in layer.text.iter() {
// TODO: Queue text sections
}
self.text_pipeline.draw_queued(
device,
staging_belt,
encoder,
target,
transformation,
wgpu_glyph::Region {
x: bounds.x,
y: bounds.y,
width: bounds.width,
height: bounds.height,
},
);
// TODO: Draw queued
}
}
}
@ -261,9 +187,9 @@ impl iced_graphics::Backend for Backend {
}
impl backend::Text for Backend {
const ICON_FONT: Font = font::ICONS;
const CHECKMARK_ICON: char = font::CHECKMARK_ICON;
const ARROW_DOWN_ICON: char = font::ARROW_DOWN_ICON;
const ICON_FONT: Font = Font::Default; // TODO
const CHECKMARK_ICON: char = '✓';
const ARROW_DOWN_ICON: char = '▼';
fn default_size(&self) -> f32 {
self.default_text_size

View file

@ -1,265 +1,39 @@
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<()>>,
draw_font_map: RefCell<HashMap<String, wgpu_glyph::FontId>>,
measure_brush: RefCell<glyph_brush::GlyphBrush<()>>,
}
pub struct Pipeline;
impl Pipeline {
pub fn new(
device: &wgpu::Device,
format: wgpu::TextureFormat,
default_font: Option<&[u8]>,
multithreading: bool,
_device: &wgpu::Device,
_format: wgpu::TextureFormat,
_default_font: Option<&[u8]>,
_multithreading: bool,
) -> Self {
let default_font = default_font.map(|slice| slice.to_vec());
// TODO: Font customization
#[cfg(not(target_os = "ios"))]
#[cfg(feature = "default_system_font")]
let default_font = {
default_font.or_else(|| {
font::Source::new()
.load(&[font::Family::SansSerif, font::Family::Serif])
.ok()
})
};
let default_font =
default_font.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_builder =
wgpu_glyph::GlyphBrushBuilder::using_font(font.clone())
.initial_cache_size((2048, 2048))
.draw_cache_multithread(multithreading);
#[cfg(target_arch = "wasm32")]
let draw_brush_builder = draw_brush_builder.draw_cache_align_4x4(true);
let draw_brush = draw_brush_builder.build(device, format);
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: wgpu_glyph::Section<'_>) {
self.draw_brush.borrow_mut().queue(section);
}
pub fn draw_queued(
&mut self,
device: &wgpu::Device,
staging_belt: &mut wgpu::util::StagingBelt,
encoder: &mut wgpu::CommandEncoder,
target: &wgpu::TextureView,
transformation: Transformation,
region: wgpu_glyph::Region,
) {
self.draw_brush
.borrow_mut()
.draw_queued_with_transform_and_scissoring(
device,
staging_belt,
encoder,
target,
transformation.into(),
region,
)
.expect("Draw text");
Pipeline
}
pub fn measure(
&self,
content: &str,
size: f32,
font: iced_native::Font,
bounds: iced_native::Size,
_content: &str,
_size: f32,
_font: iced_native::Font,
_bounds: iced_native::Size,
) -> (f32, f32) {
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()
};
if let Some(bounds) =
self.measure_brush.borrow_mut().glyph_bounds(section)
{
(bounds.width().ceil(), bounds.height().ceil())
} else {
(0.0, 0.0)
}
(0.0, 0.0)
}
pub fn hit_test(
&self,
content: &str,
size: f32,
font: iced_native::Font,
bounds: iced_native::Size,
point: iced_native::Point,
nearest_only: bool,
_content: &str,
_size: f32,
_font: iced_native::Font,
_bounds: iced_native::Size,
_point: iced_native::Point,
_nearest_only: bool,
) -> Option<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;
}
byte_index
};
if !nearest_only {
for (idx, bounds) in bounds.clone() {
if bounds.contains(point) {
return Some(Hit::CharOffset(char_index(idx)));
}
}
}
let nearest = bounds
.map(|(index, bounds)| (index, bounds.center()))
.min_by(|(_, center_a), (_, center_b)| {
center_a
.distance(point)
.partial_cmp(&center_b.distance(point))
.unwrap_or(std::cmp::Ordering::Greater)
});
nearest.map(|(idx, center)| {
Hit::NearestCharOffset(char_index(idx), point - center)
})
None
}
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) -> wgpu_glyph::FontId {
match font {
iced_native::Font::Default => wgpu_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
}
}
}
pub fn trim_measurement_cache(&mut self) {}
}