pub use font::{Direction, Font, FontConfig, Glyphs, Language, Script};
use crate::dependencies::Dependency;
use crate::views::{Bounds, Output, Size, Transform, View};
mod font;
#[doc(hidden)] pub struct Text<'a> {
font: &'a Font<'a>,
glyphs: Glyphs,
width: f32,
scale: f32,
rgba: [u8; 4],
}
impl Text<'_> {
#[inline]
pub fn height(&self) -> f32 {
self.font.height() * self.scale
}
#[inline]
pub fn ascender(&self) -> f32 {
self.font.ascender() * self.scale
}
#[inline]
pub fn descender(&self) -> f32 {
self.font.descender() * self.scale
}
#[inline]
pub fn capital_height(&self) -> f32 {
self.font.capital_height() * self.scale
}
#[inline]
pub fn line_gap(&self) -> f32 {
self.font.line_gap() * self.scale
}
}
impl View for Text<'_> {
#[inline(always)]
fn size(&self) -> Size {
(self.width, self.height()).into()
}
fn draw(&self, bounds: Bounds, output: &mut impl Output) {
struct Builder<'a, T: Output> {
transform: Transform,
output: &'a mut T,
rgba: [u8; 4],
}
impl<'a, F: Output> rustybuzz::ttf_parser::OutlineBuilder for Builder<'a, F> {
fn move_to(&mut self, x: f32, y: f32) {
self.output.begin(x, y, self.rgba, &self.transform);
}
fn line_to(&mut self, x: f32, y: f32) {
self.output.line_to(x, y);
}
fn quad_to(&mut self, x1: f32, y1: f32, x: f32, y: f32) {
self.output.quadratic_bezier_to(x1, y1, x, y);
}
fn curve_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x: f32, y: f32) {
self.output.cubic_bezier_to(x1, y1, x2, y2, x, y);
}
fn close(&mut self) {
self.output.close();
}
}
let transform = Dependency::<Transform>::new();
let mut builder = Builder {
transform: Transform::scale(self.scale, -self.scale) .then_translate((0.0, self.ascender()).into()) .then_translate(bounds.min.to_vector()) .then(&transform.unwrap_or_default()),
rgba: self.rgba,
output,
};
let positions = self.glyphs.glyph_positions().iter();
let glyphs = self.glyphs.glyph_infos().iter();
for (glyph, position) in Iterator::zip(glyphs, positions) {
builder.transform = builder
.transform .pre_translate((position.x_offset as f32, position.y_offset as f32).into());
self.font.outline_glyph(glyph.glyph_id, &mut builder);
builder.transform = builder
.transform .pre_translate((position.x_advance as f32, position.y_advance as f32).into());
}
}
}