text rendering: support strikethroughs (#7363)
<img width="1269" alt="image" src="https://github.com/zed-industries/zed/assets/18583882/d4c93033-b2ac-4ae0-8e12-457f256ee869"> Release Notes: - Added support for styling text with strikethrough. Related: - https://github.com/zed-industries/zed/issues/5364 - https://github.com/zed-industries/zed/pull/7345
This commit is contained in:
parent
55129d4d6c
commit
ad3940c66f
14 changed files with 145 additions and 4 deletions
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
black, fill, point, px, size, Bounds, ElementContext, Hsla, LineLayout, Pixels, Point, Result,
|
||||
SharedString, UnderlineStyle, WrapBoundary, WrappedLineLayout,
|
||||
SharedString, StrikethroughStyle, UnderlineStyle, WrapBoundary, WrappedLineLayout,
|
||||
};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use smallvec::SmallVec;
|
||||
|
@ -20,6 +20,9 @@ pub struct DecorationRun {
|
|||
|
||||
/// The underline style for this run
|
||||
pub underline: Option<UnderlineStyle>,
|
||||
|
||||
/// The strikethrough style for this run
|
||||
pub strikethrough: Option<StrikethroughStyle>,
|
||||
}
|
||||
|
||||
/// A line of text that has been shaped and decorated.
|
||||
|
@ -113,6 +116,7 @@ fn paint_line(
|
|||
let mut run_end = 0;
|
||||
let mut color = black();
|
||||
let mut current_underline: Option<(Point<Pixels>, UnderlineStyle)> = None;
|
||||
let mut current_strikethrough: Option<(Point<Pixels>, StrikethroughStyle)> = None;
|
||||
let mut current_background: Option<(Point<Pixels>, Hsla)> = None;
|
||||
let text_system = cx.text_system().clone();
|
||||
let mut glyph_origin = origin;
|
||||
|
@ -145,6 +149,17 @@ fn paint_line(
|
|||
underline_origin.x = origin.x;
|
||||
underline_origin.y += line_height;
|
||||
}
|
||||
if let Some((strikethrough_origin, strikethrough_style)) =
|
||||
current_strikethrough.as_mut()
|
||||
{
|
||||
cx.paint_strikethrough(
|
||||
*strikethrough_origin,
|
||||
glyph_origin.x - strikethrough_origin.x,
|
||||
strikethrough_style,
|
||||
);
|
||||
strikethrough_origin.x = origin.x;
|
||||
strikethrough_origin.y += line_height;
|
||||
}
|
||||
|
||||
glyph_origin.x = origin.x;
|
||||
glyph_origin.y += line_height;
|
||||
|
@ -153,6 +168,7 @@ fn paint_line(
|
|||
|
||||
let mut finished_background: Option<(Point<Pixels>, Hsla)> = None;
|
||||
let mut finished_underline: Option<(Point<Pixels>, UnderlineStyle)> = None;
|
||||
let mut finished_strikethrough: Option<(Point<Pixels>, StrikethroughStyle)> = None;
|
||||
if glyph.index >= run_end {
|
||||
if let Some(style_run) = decoration_runs.next() {
|
||||
if let Some((_, background_color)) = &mut current_background {
|
||||
|
@ -183,6 +199,24 @@ fn paint_line(
|
|||
},
|
||||
));
|
||||
}
|
||||
if let Some((_, strikethrough_style)) = &mut current_strikethrough {
|
||||
if style_run.strikethrough.as_ref() != Some(strikethrough_style) {
|
||||
finished_strikethrough = current_strikethrough.take();
|
||||
}
|
||||
}
|
||||
if let Some(run_strikethrough) = style_run.strikethrough.as_ref() {
|
||||
current_strikethrough.get_or_insert((
|
||||
point(
|
||||
glyph_origin.x,
|
||||
glyph_origin.y
|
||||
+ (((layout.ascent * 0.5) + baseline_offset.y) * 0.5),
|
||||
),
|
||||
StrikethroughStyle {
|
||||
color: Some(run_strikethrough.color.unwrap_or(style_run.color)),
|
||||
thickness: run_strikethrough.thickness,
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
run_end += style_run.len as usize;
|
||||
color = style_run.color;
|
||||
|
@ -190,6 +224,7 @@ fn paint_line(
|
|||
run_end = layout.len;
|
||||
finished_background = current_background.take();
|
||||
finished_underline = current_underline.take();
|
||||
finished_strikethrough = current_strikethrough.take();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -211,6 +246,14 @@ fn paint_line(
|
|||
);
|
||||
}
|
||||
|
||||
if let Some((strikethrough_origin, strikethrough_style)) = finished_strikethrough {
|
||||
cx.paint_strikethrough(
|
||||
strikethrough_origin,
|
||||
glyph_origin.x - strikethrough_origin.x,
|
||||
&strikethrough_style,
|
||||
);
|
||||
}
|
||||
|
||||
let max_glyph_bounds = Bounds {
|
||||
origin: glyph_origin,
|
||||
size: max_glyph_size,
|
||||
|
@ -263,5 +306,13 @@ fn paint_line(
|
|||
);
|
||||
}
|
||||
|
||||
if let Some((strikethrough_start, strikethrough_style)) = current_strikethrough.take() {
|
||||
cx.paint_strikethrough(
|
||||
strikethrough_start,
|
||||
last_line_end_x - strikethrough_start.x,
|
||||
&strikethrough_style,
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -225,6 +225,7 @@ mod tests {
|
|||
font: font("Helvetica"),
|
||||
color: Default::default(),
|
||||
underline: Default::default(),
|
||||
strikethrough: None,
|
||||
background_color: None,
|
||||
};
|
||||
let bold = TextRun {
|
||||
|
@ -232,6 +233,7 @@ mod tests {
|
|||
font: font("Helvetica").bold(),
|
||||
color: Default::default(),
|
||||
underline: Default::default(),
|
||||
strikethrough: None,
|
||||
background_color: None,
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue