From 264a7dedd42e27cd9e604037640cf0594b2ec46b Mon Sep 17 00:00:00 2001 From: Laurenz Date: Fri, 19 Mar 2021 17:57:31 +0100 Subject: =?UTF-8?q?Scheduled=20maintenance=20=F0=9F=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - New naming scheme - TextNode instead of NodeText - CallExpr instead of ExprCall - ... - Less glob imports - Removes Value::Args variant - Removes prelude - Renames Layouted to Fragment - Moves font into env - Moves shaping into layout - Moves frame into separate module --- src/shaping.rs | 198 --------------------------------------------------------- 1 file changed, 198 deletions(-) delete mode 100644 src/shaping.rs (limited to 'src/shaping.rs') diff --git a/src/shaping.rs b/src/shaping.rs deleted file mode 100644 index 41119639..00000000 --- a/src/shaping.rs +++ /dev/null @@ -1,198 +0,0 @@ -//! Super-basic text shaping. -//! -//! This is really only suited for simple Latin text. It picks the most suitable -//! font for each individual character. When the direction is right-to-left, the -//! word is spelled backwards. Vertical shaping is not supported. - -use std::fmt::{self, Debug, Display, Formatter}; - -use fontdock::{FaceId, FaceQuery, FallbackTree, FontVariant}; -use ttf_parser::{Face, GlyphId}; - -use crate::font::FontLoader; -use crate::geom::{Dir, Length, Point, Size}; -use crate::layout::{Element, Frame}; - -/// A shaped run of text. -#[derive(Clone, PartialEq)] -pub struct Shaped { - /// The shaped text. - pub text: String, - /// The font face the text was shaped with. - pub face: FaceId, - /// The shaped glyphs. - pub glyphs: Vec, - /// The horizontal offsets of the glyphs. This is indexed parallel to - /// `glyphs`. Vertical offsets are not yet supported. - pub offsets: Vec, - /// The font size. - pub font_size: Length, -} - -impl Shaped { - /// Create a new shape run with empty `text`, `glyphs` and `offsets`. - pub fn new(face: FaceId, font_size: Length) -> Self { - Self { - text: String::new(), - face, - glyphs: vec![], - offsets: vec![], - font_size, - } - } - - /// Encode the glyph ids into a big-endian byte buffer. - pub fn encode_glyphs_be(&self) -> Vec { - let mut bytes = Vec::with_capacity(2 * self.glyphs.len()); - for &GlyphId(g) in &self.glyphs { - bytes.push((g >> 8) as u8); - bytes.push((g & 0xff) as u8); - } - bytes - } -} - -impl Debug for Shaped { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "Shaped({})", self.text) - } -} - -/// Identifies a vertical metric of a font. -#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] -pub enum VerticalFontMetric { - /// The distance from the baseline to the typographic ascender. - /// - /// Corresponds to the typographic ascender from the `OS/2` table if present - /// and falls back to the ascender from the `hhea` table otherwise. - Ascender, - /// The approximate height of uppercase letters. - CapHeight, - /// The approximate height of non-ascending lowercase letters. - XHeight, - /// The baseline on which the letters rest. - Baseline, - /// The distance from the baseline to the typographic descender. - /// - /// Corresponds to the typographic descender from the `OS/2` table if - /// present and falls back to the descender from the `hhea` table otherwise. - Descender, -} - -impl Display for VerticalFontMetric { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - f.pad(match self { - Self::Ascender => "ascender", - Self::CapHeight => "cap-height", - Self::XHeight => "x-height", - Self::Baseline => "baseline", - Self::Descender => "descender", - }) - } -} - -/// Shape text into a frame containing [`Shaped`] runs. -pub fn shape( - text: &str, - dir: Dir, - fallback: &FallbackTree, - variant: FontVariant, - font_size: Length, - top_edge: VerticalFontMetric, - bottom_edge: VerticalFontMetric, - loader: &mut FontLoader, -) -> Frame { - let mut frame = Frame::new(Size::new(Length::ZERO, Length::ZERO)); - let mut shaped = Shaped::new(FaceId::MAX, font_size); - let mut width = Length::ZERO; - let mut top = Length::ZERO; - let mut bottom = Length::ZERO; - - // Create an iterator with conditional direction. - let mut forwards = text.chars(); - let mut backwards = text.chars().rev(); - let chars: &mut dyn Iterator = if dir.is_positive() { - &mut forwards - } else { - &mut backwards - }; - - for c in chars { - let query = FaceQuery { fallback: fallback.iter(), variant, c }; - if let Some(id) = loader.query(query) { - let face = loader.face(id).get(); - let (glyph, glyph_width) = match lookup_glyph(face, c) { - Some(v) => v, - None => continue, - }; - - let units_per_em = f64::from(face.units_per_em().unwrap_or(1000)); - let convert = |units| units / units_per_em * font_size; - - // Flush the buffer and reset the metrics if we use a new font face. - if shaped.face != id { - place(&mut frame, shaped, width, top, bottom); - - shaped = Shaped::new(id, font_size); - width = Length::ZERO; - top = convert(f64::from(lookup_metric(face, top_edge))); - bottom = convert(f64::from(lookup_metric(face, bottom_edge))); - } - - shaped.text.push(c); - shaped.glyphs.push(glyph); - shaped.offsets.push(width); - width += convert(f64::from(glyph_width)); - } - } - - place(&mut frame, shaped, width, top, bottom); - - frame -} - -/// Place shaped text into a frame. -fn place(frame: &mut Frame, shaped: Shaped, width: Length, top: Length, bottom: Length) { - if !shaped.text.is_empty() { - frame.push(Point::new(frame.size.width, top), Element::Text(shaped)); - frame.size.width += width; - frame.size.height = frame.size.height.max(top - bottom); - } -} - -/// Look up the glyph for `c` and returns its index alongside its advance width. -fn lookup_glyph(face: &Face, c: char) -> Option<(GlyphId, u16)> { - let glyph = face.glyph_index(c)?; - let width = face.glyph_hor_advance(glyph)?; - Some((glyph, width)) -} - -/// Look up a vertical metric. -fn lookup_metric(face: &Face, metric: VerticalFontMetric) -> i16 { - match metric { - VerticalFontMetric::Ascender => lookup_ascender(face), - VerticalFontMetric::CapHeight => face - .capital_height() - .filter(|&h| h > 0) - .unwrap_or_else(|| lookup_ascender(face)), - VerticalFontMetric::XHeight => face - .x_height() - .filter(|&h| h > 0) - .unwrap_or_else(|| lookup_ascender(face)), - VerticalFontMetric::Baseline => 0, - VerticalFontMetric::Descender => lookup_descender(face), - } -} - -/// The ascender of the face. -fn lookup_ascender(face: &Face) -> i16 { - // We prefer the typographic ascender over the Windows ascender because - // it can be overly large if the font has large glyphs. - face.typographic_ascender().unwrap_or_else(|| face.ascender()) -} - -/// The descender of the face. -fn lookup_descender(face: &Face) -> i16 { - // See `lookup_ascender` for reason. - face.typographic_descender().unwrap_or_else(|| face.descender()) -} -- cgit v1.2.3