summaryrefslogtreecommitdiff
path: root/library/src/text/shift.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/src/text/shift.rs')
-rw-r--r--library/src/text/shift.rs229
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,
- })
-}