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::*;
|
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 |
Loading…
x
Reference in New Issue
Block a user