summaryrefslogtreecommitdiff
path: root/library/src/math/ctx.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2023-07-02 19:59:52 +0200
committerLaurenz <laurmaedje@gmail.com>2023-07-02 20:07:43 +0200
commitebfdb1dafa430786db10dad2ef7d5467c1bdbed1 (patch)
tree2bbc24ddb4124c4bb14dec0e536129d4de37b056 /library/src/math/ctx.rs
parent3ab19185093d7709f824b95b979060ce125389d8 (diff)
Move everything into `crates/` directory
Diffstat (limited to 'library/src/math/ctx.rs')
-rw-r--r--library/src/math/ctx.rs268
1 files changed, 0 insertions, 268 deletions
diff --git a/library/src/math/ctx.rs b/library/src/math/ctx.rs
deleted file mode 100644
index a1dc6cf4..00000000
--- a/library/src/math/ctx.rs
+++ /dev/null
@@ -1,268 +0,0 @@
-use ttf_parser::math::MathValue;
-use typst::font::{FontStyle, FontWeight};
-use typst::model::realize;
-use unicode_segmentation::UnicodeSegmentation;
-
-use super::*;
-
-macro_rules! scaled {
- ($ctx:expr, text: $text:ident, display: $display:ident $(,)?) => {
- match $ctx.style.size {
- MathSize::Display => scaled!($ctx, $display),
- _ => scaled!($ctx, $text),
- }
- };
- ($ctx:expr, $name:ident) => {
- $ctx.constants.$name().scaled($ctx)
- };
-}
-
-macro_rules! percent {
- ($ctx:expr, $name:ident) => {
- $ctx.constants.$name() as f64 / 100.0
- };
-}
-
-/// The context for math layout.
-pub struct MathContext<'a, 'b, 'v> {
- pub vt: &'v mut Vt<'b>,
- pub regions: Regions<'static>,
- pub font: &'a Font,
- pub ttf: &'a ttf_parser::Face<'a>,
- pub table: ttf_parser::math::Table<'a>,
- pub constants: ttf_parser::math::Constants<'a>,
- pub ssty_table: Option<ttf_parser::gsub::AlternateSubstitution<'a>>,
- pub space_width: Em,
- pub fragments: Vec<MathFragment>,
- pub local: Styles,
- pub style: MathStyle,
- pub size: Abs,
- outer: StyleChain<'a>,
- style_stack: Vec<(MathStyle, Abs)>,
-}
-
-impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
- pub fn new(
- vt: &'v mut Vt<'b>,
- styles: StyleChain<'a>,
- regions: Regions,
- font: &'a Font,
- block: bool,
- ) -> Self {
- let table = font.ttf().tables().math.unwrap();
- let constants = table.constants.unwrap();
-
- let ssty_table = font
- .ttf()
- .tables()
- .gsub
- .and_then(|gsub| {
- gsub.features
- .find(ttf_parser::Tag::from_bytes(b"ssty"))
- .and_then(|feature| feature.lookup_indices.get(0))
- .and_then(|index| gsub.lookups.get(index))
- })
- .and_then(|ssty| {
- ssty.subtables.get::<ttf_parser::gsub::SubstitutionSubtable>(0)
- })
- .and_then(|ssty| match ssty {
- ttf_parser::gsub::SubstitutionSubtable::Alternate(alt_glyphs) => {
- Some(alt_glyphs)
- }
- _ => None,
- });
-
- let size = TextElem::size_in(styles);
- let ttf = font.ttf();
- let space_width = ttf
- .glyph_index(' ')
- .and_then(|id| ttf.glyph_hor_advance(id))
- .map(|advance| font.to_em(advance))
- .unwrap_or(THICK);
-
- let variant = variant(styles);
- Self {
- vt,
- regions: Regions::one(regions.base(), Axes::splat(false)),
- font,
- ttf: font.ttf(),
- table,
- constants,
- ssty_table,
- space_width,
- fragments: vec![],
- local: Styles::new(),
- style: MathStyle {
- variant: MathVariant::Serif,
- size: if block { MathSize::Display } else { MathSize::Text },
- cramped: false,
- bold: variant.weight >= FontWeight::BOLD,
- italic: match variant.style {
- FontStyle::Normal => Smart::Auto,
- FontStyle::Italic | FontStyle::Oblique => Smart::Custom(true),
- },
- },
- size,
- outer: styles,
- style_stack: vec![],
- }
- }
-
- pub fn push(&mut self, fragment: impl Into<MathFragment>) {
- self.fragments.push(fragment.into());
- }
-
- pub fn extend(&mut self, fragments: Vec<MathFragment>) {
- self.fragments.extend(fragments);
- }
-
- pub fn layout_fragment(
- &mut self,
- elem: &dyn LayoutMath,
- ) -> SourceResult<MathFragment> {
- let row = self.layout_fragments(elem)?;
- Ok(MathRow::new(row).into_fragment(self))
- }
-
- pub fn layout_fragments(
- &mut self,
- elem: &dyn LayoutMath,
- ) -> SourceResult<Vec<MathFragment>> {
- let prev = std::mem::take(&mut self.fragments);
- elem.layout_math(self)?;
- Ok(std::mem::replace(&mut self.fragments, prev))
- }
-
- pub fn layout_row(&mut self, elem: &dyn LayoutMath) -> SourceResult<MathRow> {
- let fragments = self.layout_fragments(elem)?;
- Ok(MathRow::new(fragments))
- }
-
- pub fn layout_frame(&mut self, elem: &dyn LayoutMath) -> SourceResult<Frame> {
- Ok(self.layout_fragment(elem)?.into_frame())
- }
-
- pub fn layout_content(&mut self, content: &Content) -> SourceResult<Frame> {
- Ok(content
- .layout(self.vt, self.outer.chain(&self.local), self.regions)?
- .into_frame())
- }
-
- pub fn layout_text(&mut self, elem: &TextElem) -> SourceResult<MathFragment> {
- let text = elem.text();
- let span = elem.span();
- let mut chars = text.chars();
- let fragment = if let Some(mut glyph) = chars
- .next()
- .filter(|_| chars.next().is_none())
- .map(|c| self.style.styled_char(c))
- .and_then(|c| GlyphFragment::try_new(self, c, span))
- {
- // A single letter that is available in the math font.
- match self.style.size {
- MathSize::Display => {
- if glyph.class == Some(MathClass::Large) {
- let height = scaled!(self, display_operator_min_height);
- glyph.stretch_vertical(self, height, Abs::zero()).into()
- } else {
- glyph.into()
- }
- }
- MathSize::Script => {
- glyph.make_scriptsize(self);
- glyph.into()
- }
- MathSize::ScriptScript => {
- glyph.make_scriptscriptsize(self);
- glyph.into()
- }
- _ => glyph.into(),
- }
- } else if text.chars().all(|c| c.is_ascii_digit()) {
- // Numbers aren't that difficult.
- let mut fragments = vec![];
- for c in text.chars() {
- let c = self.style.styled_char(c);
- fragments.push(GlyphFragment::new(self, c, span).into());
- }
- let frame = MathRow::new(fragments).into_frame(self);
- FrameFragment::new(self, frame).into()
- } else {
- // Anything else is handled by Typst's standard text layout.
- let spaced = text.graphemes(true).nth(1).is_some();
- let mut style = self.style;
- if self.style.italic == Smart::Auto {
- style = style.with_italic(false);
- }
- let text: EcoString = text.chars().map(|c| style.styled_char(c)).collect();
- let frame = self.layout_content(&TextElem::packed(text).spanned(span))?;
- FrameFragment::new(self, frame)
- .with_class(MathClass::Alphabetic)
- .with_spaced(spaced)
- .into()
- };
- Ok(fragment)
- }
-
- pub fn styles(&self) -> StyleChain {
- self.outer.chain(&self.local)
- }
-
- pub fn realize(&mut self, content: &Content) -> SourceResult<Option<Content>> {
- realize(self.vt, content, self.outer.chain(&self.local))
- }
-
- pub fn style(&mut self, style: MathStyle) {
- self.style_stack.push((self.style, self.size));
- let base_size = TextElem::size_in(self.styles()) / self.style.size.factor(self);
- self.size = base_size * style.size.factor(self);
- self.local.set(TextElem::set_size(TextSize(self.size.into())));
- self.local
- .set(TextElem::set_style(if style.italic == Smart::Custom(true) {
- FontStyle::Italic
- } else {
- FontStyle::Normal
- }));
- self.local.set(TextElem::set_weight(if style.bold {
- FontWeight::BOLD
- } else {
- FontWeight::REGULAR
- }));
- self.style = style;
- }
-
- pub fn unstyle(&mut self) {
- (self.style, self.size) = self.style_stack.pop().unwrap();
- self.local.unset();
- self.local.unset();
- self.local.unset();
- }
-}
-
-pub(super) trait Scaled {
- fn scaled(self, ctx: &MathContext) -> Abs;
-}
-
-impl Scaled for i16 {
- fn scaled(self, ctx: &MathContext) -> Abs {
- ctx.font.to_em(self).scaled(ctx)
- }
-}
-
-impl Scaled for u16 {
- fn scaled(self, ctx: &MathContext) -> Abs {
- ctx.font.to_em(self).scaled(ctx)
- }
-}
-
-impl Scaled for Em {
- fn scaled(self, ctx: &MathContext) -> Abs {
- self.at(ctx.size)
- }
-}
-
-impl Scaled for MathValue<'_> {
- fn scaled(self, ctx: &MathContext) -> Abs {
- self.value.scaled(ctx)
- }
-}