diff --git a/crates/typst-layout/src/math/accent.rs b/crates/typst-layout/src/math/accent.rs index 4e26502e3..0ebe785f1 100644 --- a/crates/typst-layout/src/math/accent.rs +++ b/crates/typst-layout/src/math/accent.rs @@ -1,12 +1,9 @@ use typst_library::diag::SourceResult; use typst_library::foundations::{Packed, StyleChain}; -use typst_library::layout::{Em, Frame, Point, Rel, Size}; +use typst_library::layout::{Em, Frame, Point, Size}; use typst_library::math::{Accent, AccentElem}; -use super::{ - scaled_font_size, style_cramped, FrameFragment, GlyphFragment, MathContext, - MathFragment, -}; +use super::{style_cramped, FrameFragment, GlyphFragment, MathContext, MathFragment}; /// How much the accent can be shorter than the base. const ACCENT_SHORT_FALL: Em = Em::new(0.5); @@ -30,11 +27,7 @@ pub fn layout_accent( let base_class = base.class(); let base_attach = base.accent_attach(); - let width = elem - .size(styles) - .unwrap_or(Rel::one()) - .at(scaled_font_size(ctx, styles)) - .relative_to(base.width()); + let width = elem.size(styles).relative_to(base.width()); let Accent(c) = elem.accent(); let mut glyph = GlyphFragment::new(ctx, styles, *c, elem.span()); @@ -75,7 +68,7 @@ pub fn layout_accent( frame.push_frame(accent_pos, accent); frame.push_frame(base_pos, base.into_frame()); ctx.push( - FrameFragment::new(ctx, styles, frame) + FrameFragment::new(styles, frame) .with_class(base_class) .with_base_ascent(base_ascent) .with_italics_correction(base_italics_correction) diff --git a/crates/typst-layout/src/math/attach.rs b/crates/typst-layout/src/math/attach.rs index cda033159..263fc5c6d 100644 --- a/crates/typst-layout/src/math/attach.rs +++ b/crates/typst-layout/src/math/attach.rs @@ -1,6 +1,6 @@ use typst_library::diag::SourceResult; -use typst_library::foundations::{Packed, Smart, StyleChain}; -use typst_library::layout::{Abs, Axis, Corner, Frame, Length, Point, Rel, Size}; +use typst_library::foundations::{Packed, StyleChain}; +use typst_library::layout::{Abs, Axis, Corner, Frame, Point, Rel, Size}; use typst_library::math::{ AttachElem, EquationElem, LimitsElem, PrimesElem, ScriptsElem, StretchElem, }; @@ -121,7 +121,7 @@ pub fn layout_primes( prime.clone(), ) } - ctx.push(FrameFragment::new(ctx, styles, frame).with_text_like(true)); + ctx.push(FrameFragment::new(styles, frame).with_text_like(true)); } } Ok(()) @@ -154,11 +154,8 @@ pub fn layout_limits( Ok(()) } -/// Get the size to stretch the base to, if the attach argument is true. -fn stretch_size( - styles: StyleChain, - elem: &Packed, -) -> Option>> { +/// Get the size to stretch the base to. +fn stretch_size(styles: StyleChain, elem: &Packed) -> Option> { // Extract from an EquationElem. let mut base = elem.base(); while let Some(equation) = base.to_packed::() { @@ -277,7 +274,7 @@ fn layout_attachments( layout!(b, b_x, b_y); // lower-limit // Done! Note that we retain the class of the base. - ctx.push(FrameFragment::new(ctx, styles, frame).with_class(base_class)); + ctx.push(FrameFragment::new(styles, frame).with_class(base_class)); Ok(()) } diff --git a/crates/typst-layout/src/math/cancel.rs b/crates/typst-layout/src/math/cancel.rs index 994e0e2f7..716832fbf 100644 --- a/crates/typst-layout/src/math/cancel.rs +++ b/crates/typst-layout/src/math/cancel.rs @@ -7,7 +7,7 @@ use typst_library::text::TextElem; use typst_library::visualize::{FixedStroke, Geometry}; use typst_syntax::Span; -use super::{scaled_font_size, FrameFragment, MathContext}; +use super::{FrameFragment, MathContext}; /// Lays out a [`CancelElem`]. #[typst_macros::time(name = "math.cancel", span = elem.span())] @@ -27,7 +27,7 @@ pub fn layout_cancel( let mut body = body.into_frame(); let body_size = body.size(); let span = elem.span(); - let length = elem.length(styles).at(scaled_font_size(ctx, styles)); + let length = elem.length(styles); let stroke = elem.stroke(styles).unwrap_or(FixedStroke { paint: TextElem::fill_in(styles).as_decoration(), @@ -63,7 +63,7 @@ pub fn layout_cancel( } ctx.push( - FrameFragment::new(ctx, styles, body) + FrameFragment::new(styles, body) .with_class(body_class) .with_italics_correction(body_italics) .with_accent_attach(body_attach) diff --git a/crates/typst-layout/src/math/frac.rs b/crates/typst-layout/src/math/frac.rs index 50686333f..fdc3be172 100644 --- a/crates/typst-layout/src/math/frac.rs +++ b/crates/typst-layout/src/math/frac.rs @@ -1,5 +1,5 @@ use typst_library::diag::SourceResult; -use typst_library::foundations::{Content, Packed, StyleChain}; +use typst_library::foundations::{Content, Packed, Resolve, StyleChain}; use typst_library::layout::{Em, Frame, FrameItem, Point, Size}; use typst_library::math::{BinomElem, FracElem}; use typst_library::text::TextElem; @@ -7,8 +7,8 @@ use typst_library::visualize::{FixedStroke, Geometry}; use typst_syntax::Span; use super::{ - scaled_font_size, style_for_denominator, style_for_numerator, FrameFragment, - GlyphFragment, MathContext, DELIM_SHORT_FALL, + style_for_denominator, style_for_numerator, FrameFragment, GlyphFragment, + MathContext, DELIM_SHORT_FALL, }; const FRAC_AROUND: Em = Em::new(0.1); @@ -49,8 +49,7 @@ fn layout_frac_like( binom: bool, span: Span, ) -> SourceResult<()> { - let font_size = scaled_font_size(ctx, styles); - let short_fall = DELIM_SHORT_FALL.at(font_size); + let short_fall = DELIM_SHORT_FALL.resolve(styles); let axis = scaled!(ctx, styles, axis_height); let thickness = scaled!(ctx, styles, fraction_rule_thickness); let shift_up = scaled!( @@ -86,7 +85,7 @@ fn layout_frac_like( styles.chain(&denom_style), )?; - let around = FRAC_AROUND.at(font_size); + let around = FRAC_AROUND.resolve(styles); let num_gap = (shift_up - (axis + thickness / 2.0) - num.descent()).max(num_min); let denom_gap = (shift_down + (axis - thickness / 2.0) - denom.ascent()).max(denom_min); @@ -111,7 +110,7 @@ fn layout_frac_like( .stretch_vertical(ctx, height, short_fall); left.center_on_axis(ctx); ctx.push(left); - ctx.push(FrameFragment::new(ctx, styles, frame)); + ctx.push(FrameFragment::new(styles, frame)); let mut right = GlyphFragment::new(ctx, styles, ')', span) .stretch_vertical(ctx, height, short_fall); right.center_on_axis(ctx); @@ -129,7 +128,7 @@ fn layout_frac_like( span, ), ); - ctx.push(FrameFragment::new(ctx, styles, frame)); + ctx.push(FrameFragment::new(styles, frame)); } Ok(()) diff --git a/crates/typst-layout/src/math/fragment.rs b/crates/typst-layout/src/math/fragment.rs index ac8946681..a0453c14f 100644 --- a/crates/typst-layout/src/math/fragment.rs +++ b/crates/typst-layout/src/math/fragment.rs @@ -17,7 +17,7 @@ use typst_library::visualize::Paint; use typst_syntax::Span; use unicode_math_class::MathClass; -use super::{scaled_font_size, stretch_glyph, MathContext, Scaled}; +use super::{stretch_glyph, MathContext, Scaled}; #[derive(Debug, Clone)] pub enum MathFragment { @@ -292,7 +292,7 @@ impl GlyphFragment { region: TextElem::region_in(styles), fill: TextElem::fill_in(styles).as_decoration(), shift: TextElem::baseline_in(styles), - font_size: scaled_font_size(ctx, styles), + font_size: TextElem::size_in(styles), math_size: EquationElem::size_in(styles), width: Abs::zero(), ascent: Abs::zero(), @@ -512,12 +512,12 @@ pub struct FrameFragment { } impl FrameFragment { - pub fn new(ctx: &MathContext, styles: StyleChain, frame: Frame) -> Self { + pub fn new(styles: StyleChain, frame: Frame) -> Self { let base_ascent = frame.ascent(); let accent_attach = frame.width() / 2.0; Self { frame: frame.post_processed(styles), - font_size: scaled_font_size(ctx, styles), + font_size: TextElem::size_in(styles), class: EquationElem::class_in(styles).unwrap_or(MathClass::Normal), math_size: EquationElem::size_in(styles), limits: Limits::Never, diff --git a/crates/typst-layout/src/math/lr.rs b/crates/typst-layout/src/math/lr.rs index 01a7f4ccd..2f4556fe5 100644 --- a/crates/typst-layout/src/math/lr.rs +++ b/crates/typst-layout/src/math/lr.rs @@ -1,6 +1,6 @@ use typst_library::diag::SourceResult; -use typst_library::foundations::{Packed, Smart, StyleChain}; -use typst_library::layout::{Abs, Axis, Length, Rel}; +use typst_library::foundations::{Packed, StyleChain}; +use typst_library::layout::{Abs, Axis, Rel}; use typst_library::math::{EquationElem, LrElem, MidElem}; use unicode_math_class::MathClass; @@ -22,7 +22,7 @@ pub fn layout_lr( // Extract implicit LrElem. if let Some(lr) = body.to_packed::() { - if lr.size(styles).is_auto() { + if lr.size(styles).is_one() { body = lr.body(); } } @@ -128,7 +128,7 @@ fn scale( styles: StyleChain, fragment: &mut MathFragment, relative_to: Abs, - height: Smart>, + height: Rel, apply: Option, ) { if matches!( diff --git a/crates/typst-layout/src/math/mat.rs b/crates/typst-layout/src/math/mat.rs index 24104f4ee..d28bb037d 100644 --- a/crates/typst-layout/src/math/mat.rs +++ b/crates/typst-layout/src/math/mat.rs @@ -1,5 +1,5 @@ use typst_library::diag::{bail, SourceResult}; -use typst_library::foundations::{Content, Packed, StyleChain}; +use typst_library::foundations::{Content, Packed, Resolve, StyleChain}; use typst_library::layout::{ Abs, Axes, Em, FixedAlignment, Frame, FrameItem, Point, Ratio, Rel, Size, }; @@ -9,9 +9,8 @@ use typst_library::visualize::{FillRule, FixedStroke, Geometry, LineCap, Shape}; use typst_syntax::Span; use super::{ - alignments, delimiter_alignment, scaled_font_size, stack, style_for_denominator, - AlignmentResult, FrameFragment, GlyphFragment, LeftRightAlternator, MathContext, - Scaled, DELIM_SHORT_FALL, + alignments, delimiter_alignment, stack, style_for_denominator, AlignmentResult, + FrameFragment, GlyphFragment, LeftRightAlternator, MathContext, DELIM_SHORT_FALL, }; const VERTICAL_PADDING: Ratio = Ratio::new(0.1); @@ -30,7 +29,7 @@ pub fn layout_vec( styles, elem.children(), elem.align(styles), - elem.gap(styles).at(scaled_font_size(ctx, styles)), + elem.gap(styles), LeftRightAlternator::Right, )?; @@ -73,9 +72,6 @@ pub fn layout_mat( } } - let font_size = scaled_font_size(ctx, styles); - let column_gap = elem.column_gap(styles).at(font_size); - let row_gap = elem.row_gap(styles).at(font_size); let delim = elem.delim(styles); let frame = layout_mat_body( ctx, @@ -83,7 +79,7 @@ pub fn layout_mat( rows, elem.align(styles), augment, - Axes::new(column_gap, row_gap), + Axes::new(elem.column_gap(styles), elem.row_gap(styles)), elem.span(), )?; @@ -103,7 +99,7 @@ pub fn layout_cases( styles, elem.children(), FixedAlignment::Start, - elem.gap(styles).at(scaled_font_size(ctx, styles)), + elem.gap(styles), LeftRightAlternator::None, )?; @@ -162,8 +158,7 @@ fn layout_mat_body( // with font size to ensure that augmentation lines // look correct by default at all matrix sizes. // The line cap is also set to square because it looks more "correct". - let font_size = scaled_font_size(ctx, styles); - let default_stroke_thickness = DEFAULT_STROKE_THICKNESS.at(font_size); + let default_stroke_thickness = DEFAULT_STROKE_THICKNESS.resolve(styles); let default_stroke = FixedStroke { thickness: default_stroke_thickness, paint: TextElem::fill_in(styles).as_decoration(), @@ -308,9 +303,8 @@ fn layout_delimiters( right: Option, span: Span, ) -> SourceResult<()> { - let font_size = scaled_font_size(ctx, styles); - let short_fall = DELIM_SHORT_FALL.at(font_size); - let axis = ctx.constants.axis_height().scaled(ctx, font_size); + let short_fall = DELIM_SHORT_FALL.resolve(styles); + let axis = scaled!(ctx, styles, axis_height); let height = frame.height(); let target = height + VERTICAL_PADDING.of(height); frame.set_baseline(height / 2.0 + axis); @@ -322,7 +316,7 @@ fn layout_delimiters( ctx.push(left); } - ctx.push(FrameFragment::new(ctx, styles, frame)); + ctx.push(FrameFragment::new(styles, frame)); if let Some(right) = right { let mut right = GlyphFragment::new(ctx, styles, right, span) diff --git a/crates/typst-layout/src/math/mod.rs b/crates/typst-layout/src/math/mod.rs index e642f6338..62ecd1725 100644 --- a/crates/typst-layout/src/math/mod.rs +++ b/crates/typst-layout/src/math/mod.rs @@ -28,8 +28,7 @@ use typst_library::math::*; use typst_library::model::ParElem; use typst_library::routines::{Arenas, RealizationKind}; use typst_library::text::{ - families, features, variant, Font, LinebreakElem, SpaceElem, TextEdgeBounds, - TextElem, TextSize, + families, features, variant, Font, LinebreakElem, SpaceElem, TextEdgeBounds, TextElem, }; use typst_library::World; use typst_syntax::Span; @@ -58,12 +57,16 @@ pub fn layout_equation_inline( let mut locator = locator.split(); let mut ctx = MathContext::new(engine, &mut locator, styles, region, &font); + + let scale_style = style_for_script_scale(&ctx); + let styles = styles.chain(&scale_style); + let run = ctx.layout_into_run(&elem.body, styles)?; let mut items = if run.row_count() == 1 { run.into_par_items() } else { - vec![InlineItem::Frame(run.into_fragment(&ctx, styles).into_frame())] + vec![InlineItem::Frame(run.into_fragment(styles).into_frame())] }; // An empty equation should have a height, so we still create a frame @@ -75,13 +78,12 @@ pub fn layout_equation_inline( for item in &mut items { let InlineItem::Frame(frame) = item else { continue }; - let font_size = scaled_font_size(&ctx, styles); let slack = ParElem::leading_in(styles) * 0.7; let (t, b) = font.edges( TextElem::top_edge_in(styles), TextElem::bottom_edge_in(styles), - font_size, + TextElem::size_in(styles), TextEdgeBounds::Frame(frame), ); @@ -110,9 +112,13 @@ pub fn layout_equation_block( let mut locator = locator.split(); let mut ctx = MathContext::new(engine, &mut locator, styles, regions.base(), &font); + + let scale_style = style_for_script_scale(&ctx); + let styles = styles.chain(&scale_style); + let full_equation_builder = ctx .layout_into_run(&elem.body, styles)? - .multiline_frame_builder(&ctx, styles); + .multiline_frame_builder(styles); let width = full_equation_builder.size.x; let equation_builders = if BlockElem::breakable_in(styles) { @@ -469,7 +475,7 @@ impl<'a, 'v, 'e> MathContext<'a, 'v, 'e> { elem: &Content, styles: StyleChain, ) -> SourceResult { - Ok(self.layout_into_run(elem, styles)?.into_fragment(self, styles)) + Ok(self.layout_into_run(elem, styles)?.into_fragment(styles)) } /// Layout the given element and return the result as a [`Frame`]. @@ -502,7 +508,7 @@ impl<'a, 'v, 'e> MathContext<'a, 'v, 'e> { // Hack because the font is fixed in math. if styles != outer && TextElem::font_in(styles) != TextElem::font_in(outer) { let frame = layout_external(elem, self, styles)?; - self.push(FrameFragment::new(self, styles, frame).with_spaced(true)); + self.push(FrameFragment::new(styles, frame).with_spaced(true)); continue; } @@ -522,8 +528,7 @@ fn layout_realized( if let Some(elem) = elem.to_packed::() { ctx.push(MathFragment::Tag(elem.tag.clone())); } else if elem.is::() { - let font_size = scaled_font_size(ctx, styles); - ctx.push(MathFragment::Space(ctx.space_width.at(font_size))); + ctx.push(MathFragment::Space(ctx.space_width.resolve(styles))); } else if elem.is::() { ctx.push(MathFragment::Linebreak); } else if let Some(elem) = elem.to_packed::() { @@ -595,7 +600,7 @@ fn layout_realized( frame.set_baseline(frame.height() / 2.0 + axis); } ctx.push( - FrameFragment::new(ctx, styles, frame) + FrameFragment::new(styles, frame) .with_spaced(true) .with_ignorant(elem.is::()), ); @@ -610,15 +615,14 @@ fn layout_box( ctx: &mut MathContext, styles: StyleChain, ) -> SourceResult<()> { - let local = TextElem::set_size(TextSize(scaled_font_size(ctx, styles).into())).wrap(); let frame = (ctx.engine.routines.layout_box)( elem, ctx.engine, ctx.locator.next(&elem.span()), - styles.chain(&local), + styles, ctx.region.size, )?; - ctx.push(FrameFragment::new(ctx, styles, frame).with_spaced(true)); + ctx.push(FrameFragment::new(styles, frame).with_spaced(true)); Ok(()) } @@ -630,10 +634,7 @@ fn layout_h( ) -> SourceResult<()> { if let Spacing::Rel(rel) = elem.amount() { if rel.rel.is_zero() { - ctx.push(MathFragment::Spacing( - rel.abs.at(scaled_font_size(ctx, styles)), - elem.weak(styles), - )); + ctx.push(MathFragment::Spacing(rel.abs.resolve(styles), elem.weak(styles))); } } Ok(()) @@ -668,7 +669,7 @@ fn layout_op( let text_like = fragment.is_text_like(); ctx.push( - FrameFragment::new(ctx, styles, fragment.into_frame()) + FrameFragment::new(styles, fragment.into_frame()) .with_class(MathClass::Large) .with_italics_correction(italics) .with_accent_attach(accent_attach) @@ -688,12 +689,11 @@ fn layout_external( ctx: &mut MathContext, styles: StyleChain, ) -> SourceResult { - let local = TextElem::set_size(TextSize(scaled_font_size(ctx, styles).into())).wrap(); (ctx.engine.routines.layout_frame)( ctx.engine, content, ctx.locator.next(&content.span()), - styles.chain(&local), + styles, ctx.region, ) } diff --git a/crates/typst-layout/src/math/root.rs b/crates/typst-layout/src/math/root.rs index 0bb2f5393..4e5d844f2 100644 --- a/crates/typst-layout/src/math/root.rs +++ b/crates/typst-layout/src/math/root.rs @@ -38,7 +38,7 @@ pub fn layout_root( let styles = styles.chain(&cramped); let run = ctx.layout_into_run(radicand, styles)?; let multiline = run.is_multiline(); - let mut radicand = run.into_fragment(ctx, styles).into_frame(); + let mut radicand = run.into_fragment(styles).into_frame(); if multiline { // Align the frame center line with the math axis. radicand.set_baseline( @@ -120,7 +120,7 @@ pub fn layout_root( ); frame.push_frame(radicand_pos, radicand); - ctx.push(FrameFragment::new(ctx, styles, frame)); + ctx.push(FrameFragment::new(styles, frame)); Ok(()) } diff --git a/crates/typst-layout/src/math/run.rs b/crates/typst-layout/src/math/run.rs index b07f5893a..ae64368d6 100644 --- a/crates/typst-layout/src/math/run.rs +++ b/crates/typst-layout/src/math/run.rs @@ -6,7 +6,7 @@ use typst_library::math::{EquationElem, MathSize, MEDIUM, THICK, THIN}; use typst_library::model::ParElem; use unicode_math_class::MathClass; -use super::{alignments, scaled_font_size, FrameFragment, MathContext, MathFragment}; +use super::{alignments, FrameFragment, MathFragment}; const TIGHT_LEADING: Em = Em::new(0.25); @@ -161,15 +161,15 @@ impl MathRun { } } - pub fn into_frame(self, ctx: &MathContext, styles: StyleChain) -> Frame { + pub fn into_frame(self, styles: StyleChain) -> Frame { if !self.is_multiline() { self.into_line_frame(&[], LeftRightAlternator::Right) } else { - self.multiline_frame_builder(ctx, styles).build() + self.multiline_frame_builder(styles).build() } } - pub fn into_fragment(self, ctx: &MathContext, styles: StyleChain) -> MathFragment { + pub fn into_fragment(self, styles: StyleChain) -> MathFragment { if self.0.len() == 1 { return self.0.into_iter().next().unwrap(); } @@ -181,7 +181,7 @@ impl MathRun { .filter(|e| e.math_size().is_some()) .all(|e| e.is_text_like()); - FrameFragment::new(ctx, styles, self.into_frame(ctx, styles)) + FrameFragment::new(styles, self.into_frame(styles)) .with_text_like(text_like) .into() } @@ -189,11 +189,7 @@ impl MathRun { /// Returns a builder that lays out the [`MathFragment`]s into a possibly /// multi-row [`Frame`]. The rows are aligned using the same set of alignment /// points computed from them as a whole. - pub fn multiline_frame_builder( - self, - ctx: &MathContext, - styles: StyleChain, - ) -> MathRunFrameBuilder { + pub fn multiline_frame_builder(self, styles: StyleChain) -> MathRunFrameBuilder { let rows: Vec<_> = self.rows(); let row_count = rows.len(); let alignments = alignments(&rows); @@ -201,8 +197,7 @@ impl MathRun { let leading = if EquationElem::size_in(styles) >= MathSize::Text { ParElem::leading_in(styles) } else { - let font_size = scaled_font_size(ctx, styles); - TIGHT_LEADING.at(font_size) + TIGHT_LEADING.resolve(styles) }; let align = AlignElem::alignment_in(styles).resolve(styles).x; diff --git a/crates/typst-layout/src/math/shared.rs b/crates/typst-layout/src/math/shared.rs index 74e62e8f0..5aebdacac 100644 --- a/crates/typst-layout/src/math/shared.rs +++ b/crates/typst-layout/src/math/shared.rs @@ -2,7 +2,6 @@ use ttf_parser::math::MathValue; use typst_library::foundations::{Style, StyleChain}; use typst_library::layout::{Abs, Em, FixedAlignment, Frame, Point, Size, VAlignment}; use typst_library::math::{EquationElem, MathSize}; -use typst_library::text::TextElem; use typst_utils::LazyHash; use super::{LeftRightAlternator, MathContext, MathFragment, MathRun}; @@ -18,7 +17,7 @@ macro_rules! scaled { $crate::math::Scaled::scaled( $ctx.constants.$name(), $ctx, - $crate::math::scaled_font_size($ctx, $styles), + typst_library::text::TextElem::size_in($styles), ) }; } @@ -55,16 +54,6 @@ impl Scaled for MathValue<'_> { } } -/// Get the font size scaled with the `MathSize`. -pub fn scaled_font_size(ctx: &MathContext, styles: StyleChain) -> Abs { - let factor = match EquationElem::size_in(styles) { - MathSize::Display | MathSize::Text => 1.0, - MathSize::Script => percent!(ctx, script_percent_scale_down), - MathSize::ScriptScript => percent!(ctx, script_script_percent_scale_down), - }; - factor * TextElem::size_in(styles) -} - /// Styles something as cramped. pub fn style_cramped() -> LazyHash