Current section
Files
Jump to
Current section
Files
vendor/typst/crates/typst-library/src/text/shift.rs
use crate::introspection::Tagged;
use ttf_parser::Tag;
use crate::foundations::{Content, Smart, elem};
use crate::layout::{Em, Length};
use crate::text::{FontMetrics, ScriptMetrics, TextSize};
/// Renders text in subscript.
///
/// The text is rendered smaller and its baseline is lowered.
///
/// # Example
/// ```example
/// Revenue#sub[yearly]
/// ```
#[elem(title = "Subscript", Tagged)]
pub struct SubElem {
/// Whether to use subscript glyphs from the font if available.
///
/// Ideally, subscripts glyphs are provided by the font (using the `subs`
/// OpenType feature). Otherwise, Typst is able to synthesize subscripts by
/// lowering and scaling down regular glyphs.
///
/// When this is set to `{false}`, synthesized glyphs will be used
/// regardless of whether the font provides dedicated subscript glyphs. When
/// `{true}`, synthesized glyphs may still be used in case the font does not
/// provide the necessary subscript glyphs.
///
/// ```example
/// N#sub(typographic: true)[1]
/// N#sub(typographic: false)[1]
/// ```
#[default(true)]
pub typographic: bool,
/// The downward baseline shift for synthesized subscripts.
///
/// This only applies to synthesized subscripts. In other words, this has no
/// effect if `typographic` is `{true}` and the font provides the necessary
/// subscript glyphs.
///
/// If set to `{auto}`, the baseline is shifted according to the metrics
/// provided by the font, with a fallback to `{0.2em}` in case the font does
/// not define the necessary metrics.
///
/// When using multiple fonts, it might be necessary to set `baseline` and
/// [`size`]($sub.size) explicitly. See [`super`]($super.baseline) for an
/// example.
pub baseline: Smart<Length>,
/// The font size for synthesized subscripts.
///
/// This only applies to synthesized subscripts. In other words, this has no
/// effect if `typographic` is `{true}` and the font provides the necessary
/// subscript glyphs.
///
/// If set to `{auto}`, the size is scaled according to the metrics provided
/// by the font, with a fallback to `{0.6em}` in case the font does not
/// define the necessary metrics.
pub size: Smart<TextSize>,
/// The text to display in subscript.
#[required]
pub body: Content,
}
/// Renders text in superscript.
///
/// The text is rendered smaller and its baseline is raised.
///
/// # Example
/// ```example
/// 1#super[st] try!
/// ```
#[elem(title = "Superscript", Tagged)]
pub struct SuperElem {
/// Whether to use superscript glyphs from the font if available.
///
/// Ideally, superscripts glyphs are provided by the font (using the `sups`
/// OpenType feature). Otherwise, Typst is able to synthesize superscripts
/// by raising and scaling down regular glyphs.
///
/// When this is set to `{false}`, synthesized glyphs will be used
/// regardless of whether the font provides dedicated superscript glyphs.
/// When `{true}`, synthesized glyphs may still be used in case the font
/// does not provide the necessary superscript glyphs.
///
/// ```example
/// N#super(typographic: true)[1]
/// N#super(typographic: false)[1]
/// ```
#[default(true)]
pub typographic: bool,
/// The downward baseline shift for synthesized superscripts.
///
/// This only applies to synthesized superscripts. In other words, this has
/// no effect if `typographic` is `{true}` and the font provides the
/// necessary superscript glyphs.
///
/// If set to `{auto}`, the baseline is shifted according to the metrics
/// provided by the font, with a fallback to `{-0.5em}` in case the font
/// does not define the necessary metrics.
///
/// Note that, since the baseline shift is applied downward, you will need
/// to provide a negative value for the content to appear as raised above
/// the normal baseline.
///
/// Sometimes it is necessary to set `baseline` and [`size`]($super.size)
/// explicitly. In the following example, the superscripted text uses
/// multiple fonts with incompatible metrics. To avoid misalignment, we
/// override the metrics for all fonts.
///
/// ```example
/// #let tz(timezone) = text(
/// font: "Roboto",
/// smallcaps(timezone, all: true),
/// )
///
/// / Per-font metrics:
/// 14:00#super[#tz[UTC], not #tz[CET]]
///
/// #set super(
/// baseline: -0.4em,
/// size: 0.6em,
/// typographic: false,
/// )
/// / Unified metrics:
/// 14:00#super[#tz[UTC], not #tz[CET]]
/// ```
pub baseline: Smart<Length>,
/// The font size for synthesized superscripts.
///
/// This only applies to synthesized superscripts. In other words, this has
/// no effect if `typographic` is `{true}` and the font provides the
/// necessary superscript glyphs.
///
/// If set to `{auto}`, the size is scaled according to the metrics provided
/// by the font, with a fallback to `{0.6em}` in case the font does not
/// define the necessary metrics.
pub size: Smart<TextSize>,
/// The text to display in superscript.
#[required]
pub body: Content,
}
/// Configuration values for sub- or superscript text.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub struct ShiftSettings {
/// Whether the OpenType feature should be used if possible.
pub typographic: bool,
/// The baseline shift of the script, relative to the outer text size.
///
/// For superscripts, this is positive. For subscripts, this is negative. A
/// value of [`Smart::Auto`] indicates that the value should be obtained
/// from font metrics.
pub shift: Smart<Em>,
/// The size of the script, relative to the outer text size.
///
/// A value of [`Smart::Auto`] indicates that the value should be obtained
/// from font metrics.
pub size: Smart<Em>,
/// The kind of script (either a subscript, or a superscript).
///
/// This is used to know which OpenType table to use to resolve
/// [`Smart::Auto`] values.
pub kind: ScriptKind,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum ScriptKind {
Sub,
Super,
}
impl ScriptKind {
/// Returns the default metrics for this script kind.
///
/// This can be used as a last resort if neither the user nor the font
/// provided those metrics.
pub fn default_metrics(self) -> &'static ScriptMetrics {
match self {
Self::Sub => &DEFAULT_SUBSCRIPT_METRICS,
Self::Super => &DEFAULT_SUPERSCRIPT_METRICS,
}
}
/// Reads the script metrics from the font table for to this script kind.
pub fn read_metrics(self, font_metrics: &FontMetrics) -> &ScriptMetrics {
match self {
Self::Sub => font_metrics.subscript.as_ref(),
Self::Super => font_metrics.superscript.as_ref(),
}
.unwrap_or(self.default_metrics())
}
/// The corresponding OpenType feature.
pub const fn feature(self) -> Tag {
match self {
Self::Sub => Tag::from_bytes(b"subs"),
Self::Super => Tag::from_bytes(b"sups"),
}
}
}
pub static DEFAULT_SUBSCRIPT_METRICS: ScriptMetrics = ScriptMetrics {
width: Em::new(0.6),
height: Em::new(0.6),
horizontal_offset: Em::zero(),
vertical_offset: Em::new(-0.2),
};
pub static DEFAULT_SUPERSCRIPT_METRICS: ScriptMetrics = ScriptMetrics {
width: Em::new(0.6),
height: Em::new(0.6),
horizontal_offset: Em::zero(),
vertical_offset: Em::new(0.5),
};