diff options
| author | Laurenz <laurmaedje@gmail.com> | 2021-03-30 21:43:12 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2021-03-30 21:43:12 +0200 |
| commit | 8245b7b73667dcdd32b32f49729d39083d513817 (patch) | |
| tree | 30f93625d4a3a5fc12434c86ed51dc32a03116a8 /src/layout/shaping.rs | |
| parent | c00cca3677b9b2f010099b969452969d6b47cb3c (diff) | |
Baseline alignment ⏏
Diffstat (limited to 'src/layout/shaping.rs')
| -rw-r--r-- | src/layout/shaping.rs | 39 |
1 files changed, 23 insertions, 16 deletions
diff --git a/src/layout/shaping.rs b/src/layout/shaping.rs index 6e4b2b41..ca30ce3e 100644 --- a/src/layout/shaping.rs +++ b/src/layout/shaping.rs @@ -5,19 +5,34 @@ use ttf_parser::GlyphId; use super::{Element, Frame, ShapedText}; use crate::env::FontLoader; use crate::exec::FontProps; -use crate::geom::{Dir, Point, Size}; +use crate::geom::{Dir, Length, Point, Size}; /// Shape text into a frame containing [`ShapedText`] runs. pub fn shape(text: &str, dir: Dir, loader: &mut FontLoader, props: &FontProps) -> Frame { - let mut frame = Frame::new(Size::ZERO); let iter = props.families.iter(); - shape_segment(&mut frame, text, dir, loader, props, iter, None); + let mut results = vec![]; + shape_segment(&mut results, text, dir, loader, props, iter, None); + + let mut top = Length::ZERO; + let mut bottom = Length::ZERO; + for result in &results { + top = top.max(result.top); + bottom = bottom.max(result.bottom); + } + + let mut frame = Frame::new(Size::new(Length::ZERO, top + bottom), top); + for shaped in results { + let offset = frame.size.width; + frame.size.width += shaped.width; + frame.push(Point::new(offset, top), Element::Text(shaped)); + } + frame } /// Shape text into a frame with font fallback using the `families` iterator. fn shape_segment<'a>( - frame: &mut Frame, + results: &mut Vec<ShapedText>, text: &str, dir: Dir, loader: &mut FontLoader, @@ -53,7 +68,7 @@ fn shape_segment<'a>( let units_per_em = f64::from(ttf.units_per_em().unwrap_or(1000)); let convert = |units| f64::from(units) / units_per_em * props.size; let top = convert(i32::from(props.top_edge.lookup(ttf))); - let bottom = convert(i32::from(props.bottom_edge.lookup(ttf))); + let bottom = convert(i32::from(-props.bottom_edge.lookup(ttf))); let mut shaped = ShapedText::new(id, props.size, top, bottom, props.color); // Fill the buffer with our text. @@ -76,7 +91,7 @@ fn shape_segment<'a>( if info.codepoint == 0 && fallback { // Flush what we have so far. if !shaped.glyphs.is_empty() { - place(frame, shaped); + results.push(shaped); shaped = ShapedText::new(id, props.size, top, bottom, props.color); } @@ -107,7 +122,7 @@ fn shape_segment<'a>( let part = &text[range]; // Recursively shape the tofu sequence with the next family. - shape_segment(frame, part, dir, loader, props, families.clone(), first); + shape_segment(results, part, dir, loader, props, families.clone(), first); } else { // Add the glyph to the shaped output. // TODO: Don't ignore y_advance and y_offset. @@ -119,14 +134,6 @@ fn shape_segment<'a>( } if !shaped.glyphs.is_empty() { - place(frame, shaped) + results.push(shaped); } } - -/// Place shaped text into a frame. -fn place(frame: &mut Frame, shaped: ShapedText) { - let offset = frame.size.width; - frame.size.width += shaped.width; - frame.size.height = frame.size.height.max(shaped.top - shaped.bottom); - frame.push(Point::new(offset, shaped.top), Element::Text(shaped)); -} |
