Add background parameter to overline, underline and strike (#2219)

This commit is contained in:
tingerrr 2023-09-25 16:19:48 +02:00 committed by GitHub
parent 063e9afccf
commit 0710d1c118
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 68 additions and 14 deletions

View File

@ -60,6 +60,16 @@ pub struct UnderlineElem {
#[default(true)] #[default(true)]
pub evade: bool, pub evade: bool,
/// Whether the line is placed behind the content it underlines.
///
/// ```example
/// #set underline(stroke: (thickness: 1em, paint: maroon, cap: "round"))
/// #underline(background: true)[This is stylized.] \
/// #underline(background: false)[This is partially hidden.]
/// ```
#[default(false)]
pub background: bool,
/// The content to underline. /// The content to underline.
#[required] #[required]
pub body: Content, pub body: Content,
@ -73,6 +83,7 @@ impl Show for UnderlineElem {
stroke: self.stroke(styles).unwrap_or_default(), stroke: self.stroke(styles).unwrap_or_default(),
offset: self.offset(styles), offset: self.offset(styles),
evade: self.evade(styles), evade: self.evade(styles),
background: self.background(styles),
}, },
extent: self.extent(styles), extent: self.extent(styles),
}))) })))
@ -141,6 +152,16 @@ pub struct OverlineElem {
#[default(true)] #[default(true)]
pub evade: bool, pub evade: bool,
/// Whether the line is placed behind the content it overlines.
///
/// ```example
/// #set overline(stroke: (thickness: 1em, paint: maroon, cap: "round"))
/// #overline(background: true)[This is stylized.] \
/// #overline(background: false)[This is partially hidden.]
/// ```
#[default(false)]
pub background: bool,
/// The content to add a line over. /// The content to add a line over.
#[required] #[required]
pub body: Content, pub body: Content,
@ -154,6 +175,7 @@ impl Show for OverlineElem {
stroke: self.stroke(styles).unwrap_or_default(), stroke: self.stroke(styles).unwrap_or_default(),
offset: self.offset(styles), offset: self.offset(styles),
evade: self.evade(styles), evade: self.evade(styles),
background: self.background(styles),
}, },
extent: self.extent(styles), extent: self.extent(styles),
}))) })))
@ -207,6 +229,16 @@ pub struct StrikeElem {
#[resolve] #[resolve]
pub extent: Length, pub extent: Length,
/// Whether the line is placed behind the content.
///
/// ```example
/// #set strike(stroke: red)
/// #strike(background: true)[This is behind.] \
/// #strike(background: false)[This is in front.]
/// ```
#[default(false)]
pub background: bool,
/// The content to strike through. /// The content to strike through.
#[required] #[required]
pub body: Content, pub body: Content,
@ -220,6 +252,7 @@ impl Show for StrikeElem {
line: DecoLine::Strikethrough { line: DecoLine::Strikethrough {
stroke: self.stroke(styles).unwrap_or_default(), stroke: self.stroke(styles).unwrap_or_default(),
offset: self.offset(styles), offset: self.offset(styles),
background: self.background(styles),
}, },
extent: self.extent(styles), extent: self.extent(styles),
}))) })))
@ -320,9 +353,9 @@ cast! {
/// A kind of decorative line. /// A kind of decorative line.
#[derive(Debug, Clone, Eq, PartialEq, Hash)] #[derive(Debug, Clone, Eq, PartialEq, Hash)]
enum DecoLine { enum DecoLine {
Underline { stroke: Stroke<Abs>, offset: Smart<Abs>, evade: bool }, Underline { stroke: Stroke<Abs>, offset: Smart<Abs>, evade: bool, background: bool },
Strikethrough { stroke: Stroke<Abs>, offset: Smart<Abs> }, Strikethrough { stroke: Stroke<Abs>, offset: Smart<Abs>, background: bool },
Overline { stroke: Stroke<Abs>, offset: Smart<Abs>, evade: bool }, Overline { stroke: Stroke<Abs>, offset: Smart<Abs>, evade: bool, background: bool },
Highlight { fill: Paint, top_edge: TopEdge, bottom_edge: BottomEdge }, Highlight { fill: Paint, top_edge: TopEdge, bottom_edge: BottomEdge },
} }
@ -346,15 +379,15 @@ pub(super) fn decorate(
return; return;
} }
let (stroke, metrics, offset, evade) = match &deco.line { let (stroke, metrics, offset, evade, background) = match &deco.line {
DecoLine::Strikethrough { stroke, offset } => { DecoLine::Strikethrough { stroke, offset, background } => {
(stroke, font_metrics.strikethrough, offset, false) (stroke, font_metrics.strikethrough, offset, false, *background)
} }
DecoLine::Overline { stroke, offset, evade } => { DecoLine::Overline { stroke, offset, evade, background } => {
(stroke, font_metrics.overline, offset, *evade) (stroke, font_metrics.overline, offset, *evade, *background)
} }
DecoLine::Underline { stroke, offset, evade } => { DecoLine::Underline { stroke, offset, evade, background } => {
(stroke, font_metrics.underline, offset, *evade) (stroke, font_metrics.underline, offset, *evade, *background)
} }
_ => return, _ => return,
}; };
@ -372,18 +405,23 @@ pub(super) fn decorate(
let start = pos.x - deco.extent; let start = pos.x - deco.extent;
let end = pos.x + (width + 2.0 * deco.extent); let end = pos.x + (width + 2.0 * deco.extent);
let mut push_segment = |from: Abs, to: Abs| { let mut push_segment = |from: Abs, to: Abs, prepend: bool| {
let origin = Point::new(from, pos.y + offset); let origin = Point::new(from, pos.y + offset);
let target = Point::new(to - from, Abs::zero()); let target = Point::new(to - from, Abs::zero());
if target.x >= min_width || !evade { if target.x >= min_width || !evade {
let shape = Geometry::Line(target).stroked(stroke.clone()); let shape = Geometry::Line(target).stroked(stroke.clone());
frame.push(origin, FrameItem::Shape(shape, Span::detached()));
if prepend {
frame.prepend(origin, FrameItem::Shape(shape, Span::detached()));
} else {
frame.push(origin, FrameItem::Shape(shape, Span::detached()));
}
} }
}; };
if !evade { if !evade {
push_segment(start, end); push_segment(start, end, background);
return; return;
} }
@ -438,7 +476,7 @@ pub(super) fn decorate(
if r - l < gap_padding { if r - l < gap_padding {
continue; continue;
} else { } else {
push_segment(l + gap_padding, r - gap_padding); push_segment(l + gap_padding, r - gap_padding, background);
} }
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 54 KiB

View File

@ -57,3 +57,19 @@ We can also specify a customized value
#set highlight(top-edge: "bounds", bottom-edge: "bounds") #set highlight(top-edge: "bounds", bottom-edge: "bounds")
#highlight[abc] #highlight[abc]
#highlight[abc #sym.integral] #highlight[abc #sym.integral]
---
// Test underline background
#set underline(background: true, stroke: (thickness: 0.5em, paint: red, cap: "round"))
#underline[This is in the background]
---
// Test overline background
#set overline(background: true, stroke: (thickness: 0.5em, paint: red, cap: "round"))
#overline[This is in the background]
---
// Test strike background
#set strike(background: true, stroke: 5pt + red)
#strike[This is in the background]