Browse Source

Faster dashed line generation (#1027)

* Faster dashed lines generation

* Add dashed_line benchmark
pull/1049/head
Lampsitter 3 years ago
committed by GitHub
parent
commit
d31f7d6522
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      Cargo.lock
  2. 1
      epaint/CHANGELOG.md
  3. 7
      epaint/Cargo.toml
  4. 43
      epaint/benches/benchmark.rs
  5. 26
      epaint/src/shape.rs

1
Cargo.lock

@ -950,6 +950,7 @@ dependencies = [
"atomic_refcell",
"bytemuck",
"cint",
"criterion",
"emath",
"nohash-hasher",
"parking_lot",

1
epaint/CHANGELOG.md

@ -5,6 +5,7 @@ All notable changes to the epaint crate will be documented in this file.
## Unreleased
* Added `Shape::dashed_line_many` ([#1027](https://github.com/emilk/egui/pull/1027)).
## 0.16.0 - 2021-12-29
* Anti-alias path ends ([#893](https://github.com/emilk/egui/pull/893)).

7
epaint/Cargo.toml

@ -63,3 +63,10 @@ single_threaded = ["atomic_refcell"]
# Only needed if you plan to use the same fonts from multiple threads.
# It comes with a minor performance impact.
multi_threaded = ["parking_lot"]
[dev-dependencies]
criterion = { version = "0.3", default-features = false }
[[bench]]
name = "benchmark"
harness = false

43
epaint/benches/benchmark.rs

@ -0,0 +1,43 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use epaint::{pos2, Color32, Shape, Stroke};
fn single_dashed_lines(c: &mut Criterion) {
c.bench_function("single_dashed_lines", move |b| {
b.iter(|| {
let mut v = Vec::new();
let line = [pos2(0.0, 0.0), pos2(50.0, 0.0), pos2(100.0, 1.0)];
for _ in 0..100 {
v.extend(Shape::dashed_line(
&line,
Stroke::new(1.5, Color32::RED),
10.0,
2.5,
));
}
black_box(v);
});
});
}
fn many_dashed_lines(c: &mut Criterion) {
c.bench_function("many_dashed_lines", move |b| {
b.iter(|| {
let mut v = Vec::new();
let line = [pos2(0.0, 0.0), pos2(50.0, 0.0), pos2(100.0, 1.0)];
for _ in 0..100 {
Shape::dashed_line_many(&line, Stroke::new(1.5, Color32::RED), 10.0, 2.5, &mut v);
}
black_box(v);
});
});
}
criterion_group!(benches, single_dashed_lines, many_dashed_lines);
criterion_main!(benches);

26
epaint/src/shape.rs

@ -75,6 +75,18 @@ impl Shape {
shapes
}
/// Turn a line into dashes. If you need to create many dashed lines use this instead of
/// [`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);
}
/// A convex polygon with a fill and optional stroke.
#[inline]
pub fn convex_polygon(
@ -425,27 +437,27 @@ fn dashes_from_line(
let end = window[1];
let vector = end - start;
let segment_length = vector.length();
let mut start_point = start;
while position_on_segment < segment_length {
let new_point = start + vector * (position_on_segment / segment_length);
if drawing_dash {
// This is the end point.
if let Shape::Path(PathShape { points, .. }) = shapes.last_mut().unwrap() {
points.push(new_point);
}
shapes.push(Shape::line_segment([start_point, new_point], stroke));
position_on_segment += gap_length;
} else {
// Start a new dash.
shapes.push(Shape::line(vec![new_point], stroke));
start_point = new_point;
position_on_segment += dash_length;
}
drawing_dash = !drawing_dash;
}
// If the segment ends and the dash is not finished, add the segment's end point.
if drawing_dash {
if let Shape::Path(PathShape { points, .. }) = shapes.last_mut().unwrap() {
points.push(end);
}
shapes.push(Shape::line_segment([start_point, end], stroke));
}
position_on_segment -= segment_length;
});
}

Loading…
Cancel
Save