Skip to content

Commit

Permalink
Add support for dashed lines with offset (#3720)
Browse files Browse the repository at this point in the history
<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/master/CONTRIBUTING.md)
before opening a Pull Request!

* Keep your PR:s small and focused.
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to add commits to your PR.
* Remember to run `cargo fmt` and `cargo cranky`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.

Please be patient! I will review your PR, but my time is limited!
-->

Closes <#3677>.

This can naturally be obtained by starting the drawing a bit "later",
but providing support for this directly will simplify interleaved
drawing of dashed lines.

An even more general approach would be to allow passing an even-length
vector of lengths and gaps, in addition to offset. Primarily thinking if
it is better to go even further if a new dashed-line-method is
introduced. The second commit introduce this (I can naturally squash
these!).
  • Loading branch information
oscargus authored Dec 23, 2023
1 parent 76025f2 commit fc18d6f
Showing 1 changed file with 71 additions and 8 deletions.
79 changes: 71 additions & 8 deletions crates/epaint/src/shape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,20 +144,74 @@ impl Shape {
gap_length: f32,
) -> Vec<Self> {
let mut shapes = Vec::new();
dashes_from_line(path, stroke.into(), dash_length, gap_length, &mut shapes);
dashes_from_line(
path,
stroke.into(),
&[dash_length],
&[gap_length],
&mut shapes,
0.,
);
shapes
}

/// Turn a line into dashes with different dash/gap lengths and a start offset.
pub fn dashed_line_with_offset(
path: &[Pos2],
stroke: impl Into<Stroke>,
dash_lengths: &[f32],
gap_lengths: &[f32],
dash_offset: f32,
) -> Vec<Self> {
let mut shapes = Vec::new();
dashes_from_line(
path,
stroke.into(),
dash_lengths,
gap_lengths,
&mut shapes,
dash_offset,
);
shapes
}

/// Turn a line into dashes. If you need to create many dashed lines use this instead of
/// [`Self::dashed_line`]
/// [`Self::dashed_line`].
pub fn dashed_line_many(
points: &[Pos2],
stroke: impl Into<Stroke>,
dash_length: f32,
gap_length: f32,
shapes: &mut Vec<Shape>,
) {
dashes_from_line(points, stroke.into(), dash_length, gap_length, shapes);
dashes_from_line(
points,
stroke.into(),
&[dash_length],
&[gap_length],
shapes,
0.,
);
}

/// Turn a line into dashes with different dash/gap lengths and a start offset. If you need to
/// create many dashed lines use this instead of [`Self::dashed_line_with_offset`].
pub fn dashed_line_many_with_offset(
points: &[Pos2],
stroke: impl Into<Stroke>,
dash_lengths: &[f32],
gap_lengths: &[f32],
dash_offset: f32,
shapes: &mut Vec<Shape>,
) {
dashes_from_line(
points,
stroke.into(),
dash_lengths,
gap_lengths,
shapes,
dash_offset,
);
}

/// A convex polygon with a fill and optional stroke.
Expand Down Expand Up @@ -775,12 +829,16 @@ fn points_from_line(
fn dashes_from_line(
path: &[Pos2],
stroke: Stroke,
dash_length: f32,
gap_length: f32,
dash_lengths: &[f32],
gap_lengths: &[f32],
shapes: &mut Vec<Shape>,
dash_offset: f32,
) {
let mut position_on_segment = 0.0;
assert_eq!(dash_lengths.len(), gap_lengths.len());
let mut position_on_segment = dash_offset;
let mut drawing_dash = false;
let mut step = 0;
let steps = dash_lengths.len();
path.windows(2).for_each(|window| {
let (start, end) = (window[0], window[1]);
let vector = end - start;
Expand All @@ -792,11 +850,16 @@ fn dashes_from_line(
if drawing_dash {
// This is the end point.
shapes.push(Shape::line_segment([start_point, new_point], stroke));
position_on_segment += gap_length;
position_on_segment += gap_lengths[step];
// Increment step counter
step += 1;
if step >= steps {
step = 0;
}
} else {
// Start a new dash.
start_point = new_point;
position_on_segment += dash_length;
position_on_segment += dash_lengths[step];
}
drawing_dash = !drawing_dash;
}
Expand Down

0 comments on commit fc18d6f

Please sign in to comment.