diff options
Diffstat (limited to 'library/src/text/shift.rs')
| -rw-r--r-- | library/src/text/shift.rs | 229 |
1 files changed, 0 insertions, 229 deletions
diff --git a/library/src/text/shift.rs b/library/src/text/shift.rs deleted file mode 100644 index 65e309e1..00000000 --- a/library/src/text/shift.rs +++ /dev/null @@ -1,229 +0,0 @@ -use super::{variant, SpaceElem, TextElem, TextSize}; -use crate::prelude::*; - -/// Renders text in subscript. -/// -/// The text is rendered smaller and its baseline is lowered. -/// -/// ## Example { #example } -/// ```example -/// Revenue#sub[yearly] -/// ``` -/// -/// Display: Subscript -/// Category: text -#[element(Show)] -pub struct SubElem { - /// Whether to prefer the dedicated subscript characters of the font. - /// - /// If this is enabled, Typst first tries to transform the text to subscript - /// codepoints. If that fails, it falls back to rendering lowered and shrunk - /// normal letters. - /// - /// ```example - /// N#sub(typographic: true)[1] - /// N#sub(typographic: false)[1] - /// ``` - #[default(true)] - pub typographic: bool, - - /// The baseline shift for synthetic subscripts. Does not apply if - /// `typographic` is true and the font has subscript codepoints for the - /// given `body`. - #[default(Em::new(0.2).into())] - pub baseline: Length, - - /// The font size for synthetic subscripts. Does not apply if - /// `typographic` is true and the font has subscript codepoints for the - /// given `body`. - #[default(TextSize(Em::new(0.6).into()))] - pub size: TextSize, - - /// The text to display in subscript. - #[required] - pub body: Content, -} - -impl Show for SubElem { - #[tracing::instrument(name = "SubElem::show", skip_all)] - fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> { - let body = self.body(); - let mut transformed = None; - if self.typographic(styles) { - if let Some(text) = search_text(&body, true) { - if is_shapable(vt, &text, styles) { - transformed = Some(TextElem::packed(text)); - } - } - }; - - Ok(transformed.unwrap_or_else(|| { - body.styled(TextElem::set_baseline(self.baseline(styles))) - .styled(TextElem::set_size(self.size(styles))) - })) - } -} - -/// Renders text in superscript. -/// -/// The text is rendered smaller and its baseline is raised. -/// -/// ## Example { #example } -/// ```example -/// 1#super[st] try! -/// ``` -/// -/// Display: Superscript -/// Category: text -#[element(Show)] -pub struct SuperElem { - /// Whether to prefer the dedicated superscript characters of the font. - /// - /// If this is enabled, Typst first tries to transform the text to - /// superscript codepoints. If that fails, it falls back to rendering - /// raised and shrunk normal letters. - /// - /// ```example - /// N#super(typographic: true)[1] - /// N#super(typographic: false)[1] - /// ``` - #[default(true)] - pub typographic: bool, - - /// The baseline shift for synthetic superscripts. Does not apply if - /// `typographic` is true and the font has superscript codepoints for the - /// given `body`. - #[default(Em::new(-0.5).into())] - pub baseline: Length, - - /// The font size for synthetic superscripts. Does not apply if - /// `typographic` is true and the font has superscript codepoints for the - /// given `body`. - #[default(TextSize(Em::new(0.6).into()))] - pub size: TextSize, - - /// The text to display in superscript. - #[required] - pub body: Content, -} - -impl Show for SuperElem { - #[tracing::instrument(name = "SuperElem::show", skip_all)] - fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> { - let body = self.body(); - let mut transformed = None; - if self.typographic(styles) { - if let Some(text) = search_text(&body, false) { - if is_shapable(vt, &text, styles) { - transformed = Some(TextElem::packed(text)); - } - } - }; - - Ok(transformed.unwrap_or_else(|| { - body.styled(TextElem::set_baseline(self.baseline(styles))) - .styled(TextElem::set_size(self.size(styles))) - })) - } -} - -/// Find and transform the text contained in `content` to the given script kind -/// if and only if it only consists of `Text`, `Space`, and `Empty` leafs. -fn search_text(content: &Content, sub: bool) -> Option<EcoString> { - if content.is::<SpaceElem>() { - Some(' '.into()) - } else if let Some(elem) = content.to::<TextElem>() { - convert_script(&elem.text(), sub) - } else if let Some(children) = content.to_sequence() { - let mut full = EcoString::new(); - for item in children { - match search_text(item, sub) { - Some(text) => full.push_str(&text), - None => return None, - } - } - Some(full) - } else { - None - } -} - -/// Checks whether the first retrievable family contains all code points of the -/// given string. -fn is_shapable(vt: &Vt, text: &str, styles: StyleChain) -> bool { - let world = vt.world; - for family in TextElem::font_in(styles) { - if let Some(font) = world - .book() - .select(family.as_str(), variant(styles)) - .and_then(|id| world.font(id)) - { - return text.chars().all(|c| font.ttf().glyph_index(c).is_some()); - } - } - - false -} - -/// Convert a string to sub- or superscript codepoints if all characters -/// can be mapped to such a codepoint. -fn convert_script(text: &str, sub: bool) -> Option<EcoString> { - let mut result = EcoString::with_capacity(text.len()); - let converter = if sub { to_subscript_codepoint } else { to_superscript_codepoint }; - - for c in text.chars() { - match converter(c) { - Some(c) => result.push(c), - None => return None, - } - } - - Some(result) -} - -/// Convert a character to its corresponding Unicode superscript. -fn to_superscript_codepoint(c: char) -> Option<char> { - char::from_u32(match c { - '0' => 0x2070, - '1' => 0x00B9, - '2' => 0x00B2, - '3' => 0x00B3, - '4'..='9' => 0x2070 + (c as u32 + 4 - '4' as u32), - '+' => 0x207A, - '-' => 0x207B, - '=' => 0x207C, - '(' => 0x207D, - ')' => 0x207E, - 'n' => 0x207F, - 'i' => 0x2071, - ' ' => 0x0020, - _ => return None, - }) -} - -/// Convert a character to its corresponding Unicode subscript. -fn to_subscript_codepoint(c: char) -> Option<char> { - char::from_u32(match c { - '0' => 0x2080, - '1'..='9' => 0x2080 + (c as u32 - '0' as u32), - '+' => 0x208A, - '-' => 0x208B, - '=' => 0x208C, - '(' => 0x208D, - ')' => 0x208E, - 'a' => 0x2090, - 'e' => 0x2091, - 'o' => 0x2092, - 'x' => 0x2093, - 'h' => 0x2095, - 'k' => 0x2096, - 'l' => 0x2097, - 'm' => 0x2098, - 'n' => 0x2099, - 'p' => 0x209A, - 's' => 0x209B, - 't' => 0x209C, - ' ' => 0x0020, - _ => return None, - }) -} |
