summaryrefslogtreecommitdiff
path: root/library/src/math/underover.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/src/math/underover.rs')
-rw-r--r--library/src/math/underover.rs339
1 files changed, 0 insertions, 339 deletions
diff --git a/library/src/math/underover.rs b/library/src/math/underover.rs
deleted file mode 100644
index 796c9ebc..00000000
--- a/library/src/math/underover.rs
+++ /dev/null
@@ -1,339 +0,0 @@
-use super::*;
-
-const BRACE_GAP: Em = Em::new(0.25);
-const BRACKET_GAP: Em = Em::new(0.25);
-
-/// A marker to distinguish under- vs. overlines.
-enum LineKind {
- Over,
- Under,
-}
-
-/// A horizontal line under content.
-///
-/// ## Example { #example }
-/// ```example
-/// $ underline(1 + 2 + ... + 5) $
-/// ```
-///
-/// Display: Underline
-/// Category: math
-#[element(LayoutMath)]
-pub struct UnderlineElem {
- /// The content above the line.
- #[required]
- pub body: Content,
-}
-
-impl LayoutMath for UnderlineElem {
- #[tracing::instrument(skip(ctx))]
- fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- layout_underoverline(ctx, &self.body(), self.span(), LineKind::Under)
- }
-}
-
-/// A horizontal line over content.
-///
-/// ## Example { #example }
-/// ```example
-/// $ overline(1 + 2 + ... + 5) $
-/// ```
-///
-/// Display: Overline
-/// Category: math
-#[element(LayoutMath)]
-pub struct OverlineElem {
- /// The content below the line.
- #[required]
- pub body: Content,
-}
-
-impl LayoutMath for OverlineElem {
- #[tracing::instrument(skip(ctx))]
- fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- layout_underoverline(ctx, &self.body(), self.span(), LineKind::Over)
- }
-}
-
-/// layout under- or overlined content
-fn layout_underoverline(
- ctx: &mut MathContext,
- body: &Content,
- span: Span,
- line: LineKind,
-) -> SourceResult<()> {
- let (extra_height, content, line_pos, content_pos, baseline, bar_height);
- match line {
- LineKind::Under => {
- let sep = scaled!(ctx, underbar_extra_descender);
- bar_height = scaled!(ctx, underbar_rule_thickness);
- let gap = scaled!(ctx, underbar_vertical_gap);
- extra_height = sep + bar_height + gap;
-
- content = ctx.layout_fragment(body)?;
-
- line_pos = Point::with_y(content.height() + gap + bar_height / 2.0);
- content_pos = Point::zero();
- baseline = content.ascent()
- }
- LineKind::Over => {
- let sep = scaled!(ctx, overbar_extra_ascender);
- bar_height = scaled!(ctx, overbar_rule_thickness);
- let gap = scaled!(ctx, overbar_vertical_gap);
- extra_height = sep + bar_height + gap;
-
- ctx.style(ctx.style.with_cramped(true));
- content = ctx.layout_fragment(body)?;
- ctx.unstyle();
-
- line_pos = Point::with_y(sep + bar_height / 2.0);
- content_pos = Point::with_y(extra_height);
- baseline = content.ascent() + extra_height;
- }
- }
-
- let width = content.width();
- let height = content.height() + extra_height;
- let size = Size::new(width, height);
-
- let content_class = content.class().unwrap_or(MathClass::Normal);
- let mut frame = Frame::new(size);
- frame.set_baseline(baseline);
- frame.push_frame(content_pos, content.into_frame());
- frame.push(
- line_pos,
- FrameItem::Shape(
- Geometry::Line(Point::with_x(width)).stroked(Stroke {
- paint: TextElem::fill_in(ctx.styles()),
- thickness: bar_height,
- ..Stroke::default()
- }),
- span,
- ),
- );
-
- ctx.push(FrameFragment::new(ctx, frame).with_class(content_class));
-
- Ok(())
-}
-
-/// A horizontal brace under content, with an optional annotation below.
-///
-/// ## Example { #example }
-/// ```example
-/// $ underbrace(1 + 2 + ... + 5, "numbers") $
-/// ```
-///
-/// Display: Underbrace
-/// Category: math
-#[element(LayoutMath)]
-pub struct UnderbraceElem {
- /// The content above the brace.
- #[required]
- pub body: Content,
-
- /// The optional content below the brace.
- #[positional]
- pub annotation: Option<Content>,
-}
-
-impl LayoutMath for UnderbraceElem {
- #[tracing::instrument(skip(ctx))]
- fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- layout_underoverspreader(
- ctx,
- &self.body(),
- &self.annotation(ctx.styles()),
- '⏟',
- BRACE_GAP,
- false,
- self.span(),
- )
- }
-}
-
-/// A horizontal brace over content, with an optional annotation above.
-///
-/// ## Example { #example }
-/// ```example
-/// $ overbrace(1 + 2 + ... + 5, "numbers") $
-/// ```
-///
-/// Display: Overbrace
-/// Category: math
-#[element(LayoutMath)]
-pub struct OverbraceElem {
- /// The content below the brace.
- #[required]
- pub body: Content,
-
- /// The optional content above the brace.
- #[positional]
- pub annotation: Option<Content>,
-}
-
-impl LayoutMath for OverbraceElem {
- #[tracing::instrument(skip(ctx))]
- fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- layout_underoverspreader(
- ctx,
- &self.body(),
- &self.annotation(ctx.styles()),
- '⏞',
- BRACE_GAP,
- true,
- self.span(),
- )
- }
-}
-
-/// A horizontal bracket under content, with an optional annotation below.
-///
-/// ## Example { #example }
-/// ```example
-/// $ underbracket(1 + 2 + ... + 5, "numbers") $
-/// ```
-///
-/// Display: Underbracket
-/// Category: math
-#[element(LayoutMath)]
-pub struct UnderbracketElem {
- /// The content above the bracket.
- #[required]
- pub body: Content,
-
- /// The optional content below the bracket.
- #[positional]
- pub annotation: Option<Content>,
-}
-
-impl LayoutMath for UnderbracketElem {
- #[tracing::instrument(skip(ctx))]
- fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- layout_underoverspreader(
- ctx,
- &self.body(),
- &self.annotation(ctx.styles()),
- '⎵',
- BRACKET_GAP,
- false,
- self.span(),
- )
- }
-}
-
-/// A horizontal bracket over content, with an optional annotation above.
-///
-/// ## Example { #example }
-/// ```example
-/// $ overbracket(1 + 2 + ... + 5, "numbers") $
-/// ```
-///
-/// Display: Overbracket
-/// Category: math
-#[element(LayoutMath)]
-pub struct OverbracketElem {
- /// The content below the bracket.
- #[required]
- pub body: Content,
-
- /// The optional content above the bracket.
- #[positional]
- pub annotation: Option<Content>,
-}
-
-impl LayoutMath for OverbracketElem {
- #[tracing::instrument(skip(ctx))]
- fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- layout_underoverspreader(
- ctx,
- &self.body(),
- &self.annotation(ctx.styles()),
- '⎴',
- BRACKET_GAP,
- true,
- self.span(),
- )
- }
-}
-
-/// Layout an over- or underbrace-like object.
-fn layout_underoverspreader(
- ctx: &mut MathContext,
- body: &Content,
- annotation: &Option<Content>,
- c: char,
- gap: Em,
- reverse: bool,
- span: Span,
-) -> SourceResult<()> {
- let gap = gap.scaled(ctx);
- let body = ctx.layout_row(body)?;
- let body_class = body.class();
- let body = body.into_fragment(ctx);
- let glyph = GlyphFragment::new(ctx, c, span);
- let stretched = glyph.stretch_horizontal(ctx, body.width(), Abs::zero());
-
- let mut rows = vec![MathRow::new(vec![body]), stretched.into()];
- ctx.style(if reverse {
- ctx.style.for_subscript()
- } else {
- ctx.style.for_superscript()
- });
- rows.extend(
- annotation
- .as_ref()
- .map(|annotation| ctx.layout_row(annotation))
- .transpose()?,
- );
- ctx.unstyle();
-
- let mut baseline = 0;
- if reverse {
- rows.reverse();
- baseline = rows.len() - 1;
- }
-
- let frame = stack(ctx, rows, Align::Center, gap, baseline);
- ctx.push(FrameFragment::new(ctx, frame).with_class(body_class));
-
- Ok(())
-}
-
-/// Stack rows on top of each other.
-///
-/// Add a `gap` between each row and uses the baseline of the `baseline`th
-/// row for the whole frame.
-pub(super) fn stack(
- ctx: &MathContext,
- rows: Vec<MathRow>,
- align: Align,
- gap: Abs,
- baseline: usize,
-) -> Frame {
- let rows: Vec<_> = rows.into_iter().flat_map(|r| r.rows()).collect();
- let AlignmentResult { points, width } = alignments(&rows);
- let rows: Vec<_> = rows
- .into_iter()
- .map(|row| row.into_aligned_frame(ctx, &points, align))
- .collect();
-
- let mut y = Abs::zero();
- let mut frame = Frame::new(Size::new(
- width,
- rows.iter().map(|row| row.height()).sum::<Abs>()
- + rows.len().saturating_sub(1) as f64 * gap,
- ));
-
- for (i, row) in rows.into_iter().enumerate() {
- let x = align.position(width - row.width());
- let pos = Point::new(x, y);
- if i == baseline {
- frame.set_baseline(y + row.baseline());
- }
- y += row.height() + gap;
- frame.push_frame(pos, row);
- }
-
- frame
-}