diff options
Diffstat (limited to 'crates')
22 files changed, 138 insertions, 149 deletions
diff --git a/crates/typst-layout/src/math/accent.rs b/crates/typst-layout/src/math/accent.rs index 4e26502e..0ebe785f 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 cda03315..263fc5c6 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<AttachElem>, -) -> Option<Smart<Rel<Length>>> { +/// Get the size to stretch the base to. +fn stretch_size(styles: StyleChain, elem: &Packed<AttachElem>) -> Option<Rel<Abs>> { // Extract from an EquationElem. let mut base = elem.base(); while let Some(equation) = base.to_packed::<EquationElem>() { @@ -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 994e0e2f..716832fb 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 50686333..fdc3be17 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 ac894668..a0453c14 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 01a7f4cc..2f4556fe 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::<LrElem>() { - 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<Rel<Length>>, + height: Rel<Abs>, apply: Option<MathClass>, ) { if matches!( diff --git a/crates/typst-layout/src/math/mat.rs b/crates/typst-layout/src/math/mat.rs index 24104f4e..d28bb037 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<char>, 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 e642f633..62ecd172 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<MathFragment> { - 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::<TagElem>() { ctx.push(MathFragment::Tag(elem.tag.clone())); } else if elem.is::<SpaceElem>() { - 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::<LinebreakElem>() { ctx.push(MathFragment::Linebreak); } else if let Some(elem) = elem.to_packed::<HElem>() { @@ -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::<PlaceElem>()), ); @@ -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<Frame> { - 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 0bb2f539..4e5d844f 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 b07f5893..ae64368d 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 74e62e8f..5aebdaca 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<Style> { EquationElem::set_cramped(true).wrap() @@ -99,6 +88,15 @@ pub fn style_for_denominator(styles: StyleChain) -> [LazyHash<Style>; 2] { [style_for_numerator(styles), EquationElem::set_cramped(true).wrap()] } +/// Styles to add font constants to the style chain. +pub fn style_for_script_scale(ctx: &MathContext) -> LazyHash<Style> { + EquationElem::set_script_scale(( + ctx.constants.script_percent_scale_down(), + ctx.constants.script_script_percent_scale_down(), + )) + .wrap() +} + /// How a delimieter should be aligned when scaling. pub fn delimiter_alignment(delimiter: char) -> VAlignment { match delimiter { diff --git a/crates/typst-layout/src/math/stretch.rs b/crates/typst-layout/src/math/stretch.rs index 3d7c88cf..4bc5a926 100644 --- a/crates/typst-layout/src/math/stretch.rs +++ b/crates/typst-layout/src/math/stretch.rs @@ -1,14 +1,14 @@ use ttf_parser::math::{GlyphAssembly, GlyphConstruction, GlyphPart}; use ttf_parser::LazyArray16; use typst_library::diag::{warning, SourceResult}; -use typst_library::foundations::{Packed, Smart, StyleChain}; -use typst_library::layout::{Abs, Axis, Frame, Length, Point, Rel, Size}; +use typst_library::foundations::{Packed, StyleChain}; +use typst_library::layout::{Abs, Axis, Frame, Point, Rel, Size}; use typst_library::math::StretchElem; use typst_utils::Get; use super::{ - delimiter_alignment, scaled_font_size, GlyphFragment, MathContext, MathFragment, - Scaled, VariantFragment, + delimiter_alignment, GlyphFragment, MathContext, MathFragment, Scaled, + VariantFragment, }; /// Maximum number of times extenders can be repeated. @@ -42,7 +42,7 @@ pub fn stretch_fragment( fragment: &mut MathFragment, axis: Option<Axis>, relative_to: Option<Abs>, - stretch: Smart<Rel<Length>>, + stretch: Rel<Abs>, short_fall: Abs, ) { let glyph = match fragment { @@ -66,10 +66,7 @@ pub fn stretch_fragment( let mut variant = stretch_glyph( ctx, glyph, - stretch - .unwrap_or(Rel::one()) - .at(scaled_font_size(ctx, styles)) - .relative_to(relative_to_size), + stretch.relative_to(relative_to_size), short_fall, axis, ); diff --git a/crates/typst-layout/src/math/text.rs b/crates/typst-layout/src/math/text.rs index 05d22d12..eb30373d 100644 --- a/crates/typst-layout/src/math/text.rs +++ b/crates/typst-layout/src/math/text.rs @@ -6,15 +6,13 @@ use typst_library::foundations::{Packed, StyleChain, StyleVec}; use typst_library::layout::{Abs, Size}; use typst_library::math::{EquationElem, MathSize, MathVariant}; use typst_library::text::{ - BottomEdge, BottomEdgeMetric, TextElem, TextSize, TopEdge, TopEdgeMetric, + BottomEdge, BottomEdgeMetric, TextElem, TopEdge, TopEdgeMetric, }; use typst_syntax::{is_newline, Span}; use unicode_math_class::MathClass; use unicode_segmentation::UnicodeSegmentation; -use super::{ - scaled_font_size, FrameFragment, GlyphFragment, MathContext, MathFragment, MathRun, -}; +use super::{FrameFragment, GlyphFragment, MathContext, MathFragment, MathRun}; /// Lays out a [`TextElem`]. pub fn layout_text( @@ -70,13 +68,12 @@ pub fn layout_text( let c = styled_char(styles, c, false); fragments.push(GlyphFragment::new(ctx, styles, c, span).into()); } - let frame = MathRun::new(fragments).into_frame(ctx, styles); - FrameFragment::new(ctx, styles, frame).with_text_like(true).into() + let frame = MathRun::new(fragments).into_frame(styles); + FrameFragment::new(styles, frame).with_text_like(true).into() } else { let local = [ TextElem::set_top_edge(TopEdge::Metric(TopEdgeMetric::Bounds)), TextElem::set_bottom_edge(BottomEdge::Metric(BottomEdgeMetric::Bounds)), - TextElem::set_size(TextSize(scaled_font_size(ctx, styles).into())), ] .map(|p| p.wrap()); @@ -94,10 +91,10 @@ pub fn layout_text( fragments.push(layout_complex_text(piece, ctx, span, styles)?.into()); } } - let mut frame = MathRun::new(fragments).into_frame(ctx, styles); + let mut frame = MathRun::new(fragments).into_frame(styles); let axis = scaled!(ctx, styles, axis_height); frame.set_baseline(frame.height() / 2.0 + axis); - FrameFragment::new(ctx, styles, frame).into() + FrameFragment::new(styles, frame).into() } else { layout_complex_text(&text, ctx, span, styles)?.into() } @@ -131,7 +128,7 @@ fn layout_complex_text( )? .into_frame(); - Ok(FrameFragment::new(ctx, styles, frame) + Ok(FrameFragment::new(styles, frame) .with_class(MathClass::Alphabetic) .with_text_like(true) .with_spaced(spaced)) diff --git a/crates/typst-layout/src/math/underover.rs b/crates/typst-layout/src/math/underover.rs index 1a2c8db6..e5599638 100644 --- a/crates/typst-layout/src/math/underover.rs +++ b/crates/typst-layout/src/math/underover.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::{Abs, Em, FixedAlignment, Frame, FrameItem, Point, Size}; use typst_library::math::{ OverbraceElem, OverbracketElem, OverlineElem, OverparenElem, OvershellElem, @@ -10,8 +10,8 @@ use typst_library::visualize::{FixedStroke, Geometry}; use typst_syntax::Span; use super::{ - scaled_font_size, stack, style_cramped, style_for_subscript, style_for_superscript, - FrameFragment, GlyphFragment, LeftRightAlternator, MathContext, MathRun, + stack, style_cramped, style_for_subscript, style_for_superscript, FrameFragment, + GlyphFragment, LeftRightAlternator, MathContext, MathRun, }; const BRACE_GAP: Em = Em::new(0.25); @@ -260,7 +260,7 @@ fn layout_underoverline( ); ctx.push( - FrameFragment::new(ctx, styles, frame) + FrameFragment::new(styles, frame) .with_class(content_class) .with_text_like(content_is_text_like) .with_italics_correction(content_italics_correction), @@ -281,11 +281,10 @@ fn layout_underoverspreader( position: Position, span: Span, ) -> SourceResult<()> { - let font_size = scaled_font_size(ctx, styles); - let gap = gap.at(font_size); + let gap = gap.resolve(styles); let body = ctx.layout_into_run(body, styles)?; let body_class = body.class(); - let body = body.into_fragment(ctx, styles); + let body = body.into_fragment(styles); let glyph = GlyphFragment::new(ctx, styles, c, span); let stretched = glyph.stretch_horizontal(ctx, body.width(), Abs::zero()); @@ -321,7 +320,7 @@ fn layout_underoverspreader( LeftRightAlternator::Right, None, ); - ctx.push(FrameFragment::new(ctx, styles, frame).with_class(body_class)); + ctx.push(FrameFragment::new(styles, frame).with_class(body_class)); Ok(()) } diff --git a/crates/typst-library/src/layout/rel.rs b/crates/typst-library/src/layout/rel.rs index 30441a42..76d73678 100644 --- a/crates/typst-library/src/layout/rel.rs +++ b/crates/typst-library/src/layout/rel.rs @@ -86,12 +86,6 @@ impl Rel<Length> { None } } - - /// Convert to a relative length with the absolute part resolved at the - /// given font size. - pub fn at(self, font_size: Abs) -> Rel<Abs> { - self.map(|abs| abs.at(font_size)) - } } impl<T: Numeric + Debug> Debug for Rel<T> { diff --git a/crates/typst-library/src/math/accent.rs b/crates/typst-library/src/math/accent.rs index a1c70b4a..fee705ee 100644 --- a/crates/typst-library/src/math/accent.rs +++ b/crates/typst-library/src/math/accent.rs @@ -1,5 +1,5 @@ use crate::diag::bail; -use crate::foundations::{cast, elem, func, Content, NativeElement, Smart, Value}; +use crate::foundations::{cast, elem, func, Content, NativeElement, Value}; use crate::layout::{Length, Rel}; use crate::math::Mathy; use crate::text::TextElem; @@ -52,7 +52,9 @@ pub struct AccentElem { pub accent: Accent, /// The size of the accent, relative to the width of the base. - pub size: Smart<Rel<Length>>, + #[resolve] + #[default(Rel::one())] + pub size: Rel<Length>, } /// An accent character. @@ -101,7 +103,7 @@ macro_rules! accents { base: Content, /// The size of the accent, relative to the width of the base. #[named] - size: Option<Smart<Rel<Length>>>, + size: Option<Rel<Length>>, ) -> Content { let mut accent = AccentElem::new(base, Accent::new($primary)); if let Some(size) = size { diff --git a/crates/typst-library/src/math/attach.rs b/crates/typst-library/src/math/attach.rs index f3c7ea99..e1f57727 100644 --- a/crates/typst-library/src/math/attach.rs +++ b/crates/typst-library/src/math/attach.rs @@ -1,4 +1,4 @@ -use crate::foundations::{elem, Content, Packed, Smart}; +use crate::foundations::{elem, Content, Packed}; use crate::layout::{Length, Rel}; use crate::math::{EquationElem, Mathy}; @@ -152,5 +152,7 @@ pub struct StretchElem { /// The size to stretch to, relative to the maximum size of the glyph and /// its attachments. - pub size: Smart<Rel<Length>>, + #[resolve] + #[default(Rel::one())] + pub size: Rel<Length>, } diff --git a/crates/typst-library/src/math/cancel.rs b/crates/typst-library/src/math/cancel.rs index a72505c0..17f4dcfb 100644 --- a/crates/typst-library/src/math/cancel.rs +++ b/crates/typst-library/src/math/cancel.rs @@ -29,6 +29,7 @@ pub struct CancelElem { /// $ a + cancel(x, length: #200%) /// - cancel(x, length: #200%) $ /// ``` + #[resolve] #[default(Rel::new(Ratio::one(), Abs::pt(3.0).into()))] pub length: Rel<Length>, diff --git a/crates/typst-library/src/math/equation.rs b/crates/typst-library/src/math/equation.rs index 4edafe5e..a9173c43 100644 --- a/crates/typst-library/src/math/equation.rs +++ b/crates/typst-library/src/math/equation.rs @@ -135,6 +135,13 @@ pub struct EquationElem { #[internal] #[ghost] pub class: Option<MathClass>, + + /// Values of `scriptPercentScaleDown` and `scriptScriptPercentScaleDown` + /// respectively in the current font's MathConstants table. + #[internal] + #[default((70, 50))] + #[ghost] + pub script_scale: (i16, i16), } impl Synthesize for Packed<EquationElem> { diff --git a/crates/typst-library/src/math/lr.rs b/crates/typst-library/src/math/lr.rs index 07ab0dd4..965f5351 100644 --- a/crates/typst-library/src/math/lr.rs +++ b/crates/typst-library/src/math/lr.rs @@ -1,4 +1,4 @@ -use crate::foundations::{elem, func, Content, NativeElement, Smart}; +use crate::foundations::{elem, func, Content, NativeElement}; use crate::layout::{Length, Rel}; use crate::math::Mathy; use crate::text::TextElem; @@ -10,7 +10,9 @@ use crate::text::TextElem; #[elem(title = "Left/Right", Mathy)] pub struct LrElem { /// The size of the brackets, relative to the height of the wrapped content. - pub size: Smart<Rel<Length>>, + #[resolve] + #[default(Rel::one())] + pub size: Rel<Length>, /// The delimited content, including the delimiters. #[required] @@ -44,7 +46,7 @@ pub struct MidElem { pub fn floor( /// The size of the brackets, relative to the height of the wrapped content. #[named] - size: Option<Smart<Rel<Length>>>, + size: Option<Rel<Length>>, /// The expression to floor. body: Content, ) -> Content { @@ -60,7 +62,7 @@ pub fn floor( pub fn ceil( /// The size of the brackets, relative to the height of the wrapped content. #[named] - size: Option<Smart<Rel<Length>>>, + size: Option<Rel<Length>>, /// The expression to ceil. body: Content, ) -> Content { @@ -76,7 +78,7 @@ pub fn ceil( pub fn round( /// The size of the brackets, relative to the height of the wrapped content. #[named] - size: Option<Smart<Rel<Length>>>, + size: Option<Rel<Length>>, /// The expression to round. body: Content, ) -> Content { @@ -92,7 +94,7 @@ pub fn round( pub fn abs( /// The size of the brackets, relative to the height of the wrapped content. #[named] - size: Option<Smart<Rel<Length>>>, + size: Option<Rel<Length>>, /// The expression to take the absolute value of. body: Content, ) -> Content { @@ -108,7 +110,7 @@ pub fn abs( pub fn norm( /// The size of the brackets, relative to the height of the wrapped content. #[named] - size: Option<Smart<Rel<Length>>>, + size: Option<Rel<Length>>, /// The expression to take the norm of. body: Content, ) -> Content { @@ -119,7 +121,7 @@ fn delimited( body: Content, left: char, right: char, - size: Option<Smart<Rel<Length>>>, + size: Option<Rel<Length>>, ) -> Content { let span = body.span(); let mut elem = LrElem::new(Content::sequence([ diff --git a/crates/typst-library/src/math/matrix.rs b/crates/typst-library/src/math/matrix.rs index 1c788995..c74eb8fa 100644 --- a/crates/typst-library/src/math/matrix.rs +++ b/crates/typst-library/src/math/matrix.rs @@ -56,6 +56,7 @@ pub struct VecElem { /// #set math.vec(gap: 1em) /// $ vec(1, 2) $ /// ``` + #[resolve] #[default(DEFAULT_ROW_GAP.into())] pub gap: Rel<Length>, @@ -161,6 +162,7 @@ pub struct MatElem { /// #set math.mat(row-gap: 1em) /// $ mat(1, 2; 3, 4) $ /// ``` + #[resolve] #[parse( let gap = args.named("gap")?; args.named("row-gap")?.or(gap) @@ -174,6 +176,7 @@ pub struct MatElem { /// #set math.mat(column-gap: 1em) /// $ mat(1, 2; 3, 4) $ /// ``` + #[resolve] #[parse(args.named("column-gap")?.or(gap))] #[default(DEFAULT_COL_GAP.into())] pub column_gap: Rel<Length>, @@ -256,6 +259,7 @@ pub struct CasesElem { /// #set math.cases(gap: 1em) /// $ x = cases(1, 2) $ /// ``` + #[resolve] #[default(DEFAULT_ROW_GAP.into())] pub gap: Rel<Length>, diff --git a/crates/typst-library/src/text/mod.rs b/crates/typst-library/src/text/mod.rs index ee81e3f2..25ed009e 100644 --- a/crates/typst-library/src/text/mod.rs +++ b/crates/typst-library/src/text/mod.rs @@ -50,6 +50,7 @@ use crate::foundations::{ Resolve, Scope, Set, Smart, StyleChain, }; use crate::layout::{Abs, Axis, Dir, Em, Length, Ratio, Rel}; +use crate::math::{EquationElem, MathSize}; use crate::model::ParElem; use crate::visualize::{Color, Paint, RelativeTo, Stroke}; use crate::World; @@ -981,7 +982,14 @@ impl Resolve for TextSize { type Output = Abs; fn resolve(self, styles: StyleChain) -> Self::Output { - self.0.resolve(styles) + let factor = match EquationElem::size_in(styles) { + MathSize::Display | MathSize::Text => 1.0, + MathSize::Script => EquationElem::script_scale_in(styles).0 as f64 / 100.0, + MathSize::ScriptScript => { + EquationElem::script_scale_in(styles).1 as f64 / 100.0 + } + }; + factor * self.0.resolve(styles) } } |
