math under/overline now draws simple lines based on parameters in math font table (#1568)

This commit is contained in:
damaxwell 2023-06-26 03:42:38 -08:00 committed by GitHub
parent 5ee41e57e8
commit 1861ceb179
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 76 additions and 9 deletions

View File

@ -1,9 +1,14 @@
use super::*; use super::*;
const LINE_GAP: Em = Em::new(0.15);
const BRACE_GAP: Em = Em::new(0.25); const BRACE_GAP: Em = Em::new(0.25);
const BRACKET_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. /// A horizontal line under content.
/// ///
/// ## Example { #example } /// ## Example { #example }
@ -23,7 +28,7 @@ pub struct UnderlineElem {
impl LayoutMath for UnderlineElem { impl LayoutMath for UnderlineElem {
#[tracing::instrument(skip(ctx))] #[tracing::instrument(skip(ctx))]
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> { fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
layout(ctx, &self.body(), &None, '\u{305}', LINE_GAP, false, self.span()) layout_underoverline(ctx, &self.body(), self.span(), LineKind::Under)
} }
} }
@ -46,10 +51,72 @@ pub struct OverlineElem {
impl LayoutMath for OverlineElem { impl LayoutMath for OverlineElem {
#[tracing::instrument(skip(ctx))] #[tracing::instrument(skip(ctx))]
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> { fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
layout(ctx, &self.body(), &None, '\u{332}', LINE_GAP, true, self.span()) 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. /// A horizontal brace under content, with an optional annotation below.
/// ///
/// ## Example { #example } /// ## Example { #example }
@ -73,7 +140,7 @@ pub struct UnderbraceElem {
impl LayoutMath for UnderbraceElem { impl LayoutMath for UnderbraceElem {
#[tracing::instrument(skip(ctx))] #[tracing::instrument(skip(ctx))]
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> { fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
layout( layout_underoverspreader(
ctx, ctx,
&self.body(), &self.body(),
&self.annotation(ctx.styles()), &self.annotation(ctx.styles()),
@ -108,7 +175,7 @@ pub struct OverbraceElem {
impl LayoutMath for OverbraceElem { impl LayoutMath for OverbraceElem {
#[tracing::instrument(skip(ctx))] #[tracing::instrument(skip(ctx))]
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> { fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
layout( layout_underoverspreader(
ctx, ctx,
&self.body(), &self.body(),
&self.annotation(ctx.styles()), &self.annotation(ctx.styles()),
@ -143,7 +210,7 @@ pub struct UnderbracketElem {
impl LayoutMath for UnderbracketElem { impl LayoutMath for UnderbracketElem {
#[tracing::instrument(skip(ctx))] #[tracing::instrument(skip(ctx))]
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> { fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
layout( layout_underoverspreader(
ctx, ctx,
&self.body(), &self.body(),
&self.annotation(ctx.styles()), &self.annotation(ctx.styles()),
@ -178,7 +245,7 @@ pub struct OverbracketElem {
impl LayoutMath for OverbracketElem { impl LayoutMath for OverbracketElem {
#[tracing::instrument(skip(ctx))] #[tracing::instrument(skip(ctx))]
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> { fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
layout( layout_underoverspreader(
ctx, ctx,
&self.body(), &self.body(),
&self.annotation(ctx.styles()), &self.annotation(ctx.styles()),
@ -190,8 +257,8 @@ impl LayoutMath for OverbracketElem {
} }
} }
/// Layout an over- or underthing. /// Layout an over- or underbrace-like object.
fn layout( fn layout_underoverspreader(
ctx: &mut MathContext, ctx: &mut MathContext,
body: &Content, body: &Content,
annotation: &Option<Content>, annotation: &Option<Content>,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB