diff options
| author | Laurenz <laurmaedje@gmail.com> | 2023-01-28 12:01:05 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2023-01-28 12:14:03 +0100 |
| commit | 28c554ec2185a15e22f0408ce485ed4afe035e03 (patch) | |
| tree | 622d2d281133c4e6b92633e44bfc1e1301250fb4 /library/src/math/script.rs | |
| parent | 23238d4d44881a5b466ab23a32e2a7447f460127 (diff) | |
Rework math attachments and accents
Diffstat (limited to 'library/src/math/script.rs')
| -rw-r--r-- | library/src/math/script.rs | 184 |
1 files changed, 0 insertions, 184 deletions
diff --git a/library/src/math/script.rs b/library/src/math/script.rs deleted file mode 100644 index 2c765fbf..00000000 --- a/library/src/math/script.rs +++ /dev/null @@ -1,184 +0,0 @@ -use super::*; - -/// # Script -/// A mathematical sub- and/or superscript. -/// -/// ## Syntax -/// This function also has dedicated syntax: Use the underscore (`_`) to -/// indicate a subscript and the circumflex (`^`) to indicate a superscript. -/// -/// ## Example -/// ``` -/// $ a_i = 2^(1+i) $ -/// ``` -/// -/// ## Parameters -/// - base: Content (positional, required) -/// The base to which the applies the sub- and/or superscript. -/// -/// - sub: Content (named) -/// The subscript. -/// -/// - sup: Content (named) -/// The superscript. -/// -/// ## Category -/// math -#[func] -#[capable(LayoutMath)] -#[derive(Debug, Hash)] -pub struct ScriptNode { - /// The base. - pub base: Content, - /// The subscript. - pub sub: Option<Content>, - /// The superscript. - pub sup: Option<Content>, -} - -#[node] -impl ScriptNode { - fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> { - let base = args.expect("base")?; - let sub = args.named("sub")?; - let sup = args.named("sup")?; - Ok(Self { base, sub, sup }.pack()) - } -} - -impl LayoutMath for ScriptNode { - fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> { - let base = ctx.layout_fragment(&self.base)?; - - let mut sub = Frame::new(Size::zero()); - if let Some(node) = &self.sub { - ctx.style(ctx.style.for_subscript()); - sub = ctx.layout_frame(node)?; - ctx.unstyle(); - } - - let mut sup = Frame::new(Size::zero()); - if let Some(node) = &self.sup { - ctx.style(ctx.style.for_superscript()); - sup = ctx.layout_frame(node)?; - ctx.unstyle(); - } - - let render_limits = ctx.style.size == MathSize::Display - && base.class() == Some(MathClass::Large) - && match &base { - MathFragment::Variant(variant) => LIMITS.contains(&variant.c), - MathFragment::Frame(fragment) => fragment.limits, - _ => false, - }; - - if render_limits { - limits(ctx, base, sub, sup) - } else { - scripts(ctx, base, sub, sup, self.sub.is_some() && self.sup.is_some()) - } - } -} - -/// Layout normal sub- and superscripts. -fn scripts( - ctx: &mut MathContext, - base: MathFragment, - sub: Frame, - sup: Frame, - both: bool, -) -> SourceResult<()> { - let sup_shift_up = if ctx.style.cramped { - scaled!(ctx, superscript_shift_up_cramped) - } else { - scaled!(ctx, superscript_shift_up) - }; - let sup_bottom_min = scaled!(ctx, superscript_bottom_min); - let sup_bottom_max_with_sub = scaled!(ctx, superscript_bottom_max_with_subscript); - let sup_drop_max = scaled!(ctx, superscript_baseline_drop_max); - let gap_min = scaled!(ctx, sub_superscript_gap_min); - let sub_shift_down = scaled!(ctx, subscript_shift_down); - let sub_top_max = scaled!(ctx, subscript_top_max); - let sub_drop_min = scaled!(ctx, subscript_baseline_drop_min); - let space_after = scaled!(ctx, space_after_script); - - let mut shift_up = sup_shift_up - .max(base.ascent() - sup_drop_max) - .max(sup_bottom_min + sup.descent()); - - let mut shift_down = sub_shift_down - .max(base.descent() + sub_drop_min) - .max(sub.ascent() - sub_top_max); - - if both { - let sup_bottom = shift_up - sup.descent(); - let sub_top = sub.ascent() - shift_down; - let gap = sup_bottom - sub_top; - if gap < gap_min { - let increase = gap_min - gap; - let sup_only = - (sup_bottom_max_with_sub - sup_bottom).clamp(Abs::zero(), increase); - let rest = (increase - sup_only) / 2.0; - shift_up += sup_only + rest; - shift_down += rest; - } - } - - let delta = base.italics_correction(); - let ascent = shift_up + sup.ascent(); - let descent = shift_down + sub.descent(); - let height = ascent + descent; - let width = base.width() + sup.width().max(sub.width() - delta) + space_after; - let base_pos = Point::with_y(ascent - base.ascent()); - let sup_pos = Point::with_x(base.width()); - let sub_pos = Point::new(base.width() - delta, height - sub.height()); - let class = base.class().unwrap_or(MathClass::Normal); - - let mut frame = Frame::new(Size::new(width, height)); - frame.set_baseline(ascent); - frame.push_frame(base_pos, base.to_frame(ctx)); - frame.push_frame(sub_pos, sub); - frame.push_frame(sup_pos, sup); - ctx.push(FrameFragment::new(frame).with_class(class)); - - Ok(()) -} - -/// Layout limits. -fn limits( - ctx: &mut MathContext, - base: MathFragment, - sub: Frame, - sup: Frame, -) -> SourceResult<()> { - let upper_gap_min = scaled!(ctx, upper_limit_gap_min); - let upper_rise_min = scaled!(ctx, upper_limit_baseline_rise_min); - let lower_gap_min = scaled!(ctx, lower_limit_gap_min); - let lower_drop_min = scaled!(ctx, lower_limit_baseline_drop_min); - - let sup_gap = upper_gap_min.max(upper_rise_min - sup.descent()); - let sub_gap = lower_gap_min.max(lower_drop_min - sub.ascent()); - - let delta = base.italics_correction() / 2.0; - let width = base.width().max(sup.width()).max(sub.width()); - let height = sup.height() + sup_gap + base.height() + sub_gap + sub.height(); - let base_pos = Point::new((width - base.width()) / 2.0, sup.height() + sup_gap); - let sup_pos = Point::with_x((width - sup.width()) / 2.0 + delta); - let sub_pos = Point::new((width - sub.width()) / 2.0 - delta, height - sub.height()); - let class = base.class().unwrap_or(MathClass::Normal); - - let mut frame = Frame::new(Size::new(width, height)); - frame.set_baseline(base_pos.y + base.ascent()); - frame.push_frame(base_pos, base.to_frame(ctx)); - frame.push_frame(sub_pos, sub); - frame.push_frame(sup_pos, sup); - ctx.push(FrameFragment::new(frame).with_class(class)); - - Ok(()) -} - -/// Codepoints that should have sub- and superscripts attached as limits. -const LIMITS: &[char] = &[ - '\u{2210}', '\u{22C1}', '\u{22C0}', '\u{2A04}', '\u{22C2}', '\u{22C3}', '\u{220F}', - '\u{2211}', '\u{2A02}', '\u{2A01}', '\u{2A00}', '\u{2A06}', -]; |
