mirror of
https://github.com/typst/typst
synced 2025-05-18 11:05:28 +08:00
math under/overline now draws simple lines based on parameters in math font table (#1568)
This commit is contained in:
parent
5ee41e57e8
commit
1861ceb179
@ -1,9 +1,14 @@
|
||||
use super::*;
|
||||
|
||||
const LINE_GAP: Em = Em::new(0.15);
|
||||
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 }
|
||||
@ -23,7 +28,7 @@ pub struct UnderlineElem {
|
||||
impl LayoutMath for UnderlineElem {
|
||||
#[tracing::instrument(skip(ctx))]
|
||||
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 {
|
||||
#[tracing::instrument(skip(ctx))]
|
||||
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.
|
||||
///
|
||||
/// ## Example { #example }
|
||||
@ -73,7 +140,7 @@ pub struct UnderbraceElem {
|
||||
impl LayoutMath for UnderbraceElem {
|
||||
#[tracing::instrument(skip(ctx))]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
layout(
|
||||
layout_underoverspreader(
|
||||
ctx,
|
||||
&self.body(),
|
||||
&self.annotation(ctx.styles()),
|
||||
@ -108,7 +175,7 @@ pub struct OverbraceElem {
|
||||
impl LayoutMath for OverbraceElem {
|
||||
#[tracing::instrument(skip(ctx))]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
layout(
|
||||
layout_underoverspreader(
|
||||
ctx,
|
||||
&self.body(),
|
||||
&self.annotation(ctx.styles()),
|
||||
@ -143,7 +210,7 @@ pub struct UnderbracketElem {
|
||||
impl LayoutMath for UnderbracketElem {
|
||||
#[tracing::instrument(skip(ctx))]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
layout(
|
||||
layout_underoverspreader(
|
||||
ctx,
|
||||
&self.body(),
|
||||
&self.annotation(ctx.styles()),
|
||||
@ -178,7 +245,7 @@ pub struct OverbracketElem {
|
||||
impl LayoutMath for OverbracketElem {
|
||||
#[tracing::instrument(skip(ctx))]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
layout(
|
||||
layout_underoverspreader(
|
||||
ctx,
|
||||
&self.body(),
|
||||
&self.annotation(ctx.styles()),
|
||||
@ -190,8 +257,8 @@ impl LayoutMath for OverbracketElem {
|
||||
}
|
||||
}
|
||||
|
||||
/// Layout an over- or underthing.
|
||||
fn layout(
|
||||
/// Layout an over- or underbrace-like object.
|
||||
fn layout_underoverspreader(
|
||||
ctx: &mut MathContext,
|
||||
body: &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 |
Loading…
x
Reference in New Issue
Block a user