Draw borders with the same color in single bezpath.#366
Draw borders with the same color in single bezpath.#366nicoburns merged 5 commits intoDioxusLabs:mainfrom
Conversation
| let has_multiple_edges = | ||
| next_border_index < count && borders[next_border_index].0 == color; | ||
| if has_multiple_edges { | ||
| let mut border_path = borders[start_border_index].1.take().unwrap(); | ||
| while next_border_index < count && borders[next_border_index].0 == color { | ||
| border_path.extend(&borders[next_border_index].1.take().unwrap()); | ||
| next_border_index += 1; | ||
| } | ||
| scene.fill(Fill::NonZero, self.transform, color, None, &border_path); | ||
| } else { | ||
| scene.fill( | ||
| Fill::NonZero, | ||
| self.transform, | ||
| color, | ||
| None, | ||
| borders[start_border_index].1.as_ref().unwrap(), | ||
| ); | ||
| } |
There was a problem hiding this comment.
This can be simplified:
let mut next_border_index = start_border_index + 1;
let mut border_path = borders[start_border_index].1.take().unwrap();
while next_border_index < count && borders[next_border_index].0 == color {
border_path.extend(&borders[next_border_index].1.take().unwrap());
next_border_index += 1;
}
scene.fill(Fill::NonZero, self.transform, color, None, &border_path);The key insight here being that the has_multiple_edges "if" is using the same condition as the while loop in the first branch of the if. So we simplify to only using a while loop that just does zero iterations in the "else" case.
| if has_multiple_edges { | ||
| let mut border_path = borders[start_border_index].1.take().unwrap(); | ||
| while next_border_index < count && borders[next_border_index].0 == color { | ||
| border_path.extend(&borders[next_border_index].1.take().unwrap()); |
There was a problem hiding this comment.
The docs on BezPath::extend (https://docs.rs/kurbo/latest/kurbo/struct.BezPath.html#method.extend) say:
Note that if you’re attempting to make a continuous path, you will generally want to ensure that the iterator does not contain any MoveTo or ClosePath elements. Note especially that many (open) shapes will start with a MoveTo if you use their path_elements function. Some shapes have alternatives for this use case, such as Arc::append_iter.
Which I think we are doing here?
I guess if it works this is fine. But it would be nice to understand if/why this is ok.
| let current_color = style.clone_color(); | ||
|
|
||
| let mut borders: [(Color, Option<BezPath>); 4] = [ | ||
| (Color::TRANSPARENT, None), |
There was a problem hiding this comment.
Nit: It might be nice for readability to use a struct for this? So we have .color and .path rather than .0 and .1...
I appreciate the disclosure! |
|
Does this have any performance implications? In hb-raster, Claude prototyped a fix for this issue, but the performance degradation was too high (~50%). |
This is a small fix to ensure adjacent borders with the same color are drawn in a single bezpath to avoid artifacts.
Gemini was used to assist with the code.
Fixes #359
prior:
Of tests run:
201 tests CRASHED (0.77% of run; 0.31% of found)
12020 tests PASSED (45.93% of run; 18.48% of found)
13950 tests FAILED (53.30% of run; 21.45% of found)
with border change:
Of tests run:
201 tests CRASHED (0.77% of run; 0.31% of found)
12130 tests PASSED (46.35% of run; 18.65% of found)
13840 tests FAILED (52.88% of run; 21.28% of found)
Prior:

With border Fix: