Skip to content

Commit

Permalink
fix border when there is no border radius
Browse files Browse the repository at this point in the history
  • Loading branch information
jrmoulton committed Feb 18, 2025
1 parent c9f9b16 commit 96f3a23
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 48 deletions.
108 changes: 61 additions & 47 deletions src/border_path_iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,8 @@ impl<'a> Iterator for BorderPathIter<'a> {
}
assert!(self.current_iter.is_none());

const EPSILON: f64 = 1e-4;

// end condition: we have reached the target percentage
if (self.current_len / self.total_len - end).abs() <= EPSILON
if (self.current_len / self.total_len - end).abs() <= f64::EPSILON
|| (self.current_len / self.total_len) >= end
{
return if self.emitted_last_stroke {
Expand Down Expand Up @@ -176,10 +174,10 @@ impl<'a> Iterator for BorderPathIter<'a> {

let subseg = path_seg.subsegment(0.0..t);
self.current_len += subseg.arclen(self.tolerance);
self.current_iter = Some(Box::new(std::iter::once(subseg.as_path_el())));
self.current_iter = Some(Box::new(subseg.path_elements(self.tolerance)));
} else {
self.current_len += seg_len;
self.current_iter = Some(Box::new(std::iter::once(path_seg.as_path_el())));
self.current_iter = Some(Box::new(path_seg.path_elements(self.tolerance)));
}
break;
}
Expand Down Expand Up @@ -383,6 +381,7 @@ pub struct RoundedRectPathIter {
rect: RectPathIter,
arcs: [Arc; 8],
}

#[derive(Debug)]
pub enum ArcOrPath {
Arc(Arc),
Expand All @@ -394,48 +393,63 @@ impl Iterator for RoundedRectPathIter {
type Item = ArcOrPath;

fn next(&mut self) -> Option<Self::Item> {
// The total sequence is:
// 0. Arc 1
// 1. LineTo from rect
// 2. Arc 2 (top right)
// 3. Corner
// 4. Arc 3 (right top)
// 5. LineTo from rect
// 6. Arc 4 (right bottom)
// 7. Corner
// 8. Arc 5 (bottom right)
// 9. LineTo from rect
// 10. Arc 6 (bottom left)
// 11. Corner
// 12. Arc 7 (left bottom)
// 13. Final LineTo from rect
// 14. Arc 8 (left top)
// 15. Corner

if self.idx >= 16 {
return None;
}

let result = match self.idx {
// Arc segments (even indices except 2,5,8)
0 => Some(ArcOrPath::Arc(self.arcs[1])),
2 => Some(ArcOrPath::Arc(self.arcs[2])),
4 => Some(ArcOrPath::Arc(self.arcs[3])),
6 => Some(ArcOrPath::Arc(self.arcs[4])),
8 => Some(ArcOrPath::Arc(self.arcs[5])),
10 => Some(ArcOrPath::Arc(self.arcs[6])),
12 => Some(ArcOrPath::Arc(self.arcs[7])),
14 => Some(ArcOrPath::Arc(self.arcs[0])),

// Line segments (odd indices)
1 | 5 | 9 | 13 => Some(ArcOrPath::Path(self.rect.next().unwrap())),

3 | 7 | 11 | 15 => Some(ArcOrPath::Corner),

16.. => None,
};
while self.idx < 16 {
let idx = self.idx;
let mut skip_arc = false;
let mut check_arc = |radius: f64, arc_idx: usize| {
if radius > f64::EPSILON {
Some(ArcOrPath::Arc(self.arcs[arc_idx]))
} else {
skip_arc = true;
None
}
};
let mut line_to = || Some(ArcOrPath::Path(self.rect.next().unwrap()));
let result = match idx {
// Arc 1 (top left)
0 => check_arc(self.rect.radii.top_left, 1),
// LineTo from rect
1 => line_to(),
// Arc 2 (top right)
2 => check_arc(self.rect.radii.top_right, 2),
// Corner
3 => Some(ArcOrPath::Corner),
// Arc 3 (right top)
4 => check_arc(self.rect.radii.top_right, 3),
// LineTo from rect
5 => line_to(),
// Arc 4 (right bottom)
6 => check_arc(self.rect.radii.bottom_right, 4),
// Corner
7 => Some(ArcOrPath::Corner),
// Arc 5 (bottom right)
8 => check_arc(self.rect.radii.bottom_right, 5),
// LineTo from rect
9 => line_to(),
// Arc 6 (bottom left)
10 => check_arc(self.rect.radii.bottom_left, 6),
// Corner
11 => Some(ArcOrPath::Corner),
// Arc 7 (left bottom)
12 => check_arc(self.rect.radii.bottom_left, 7),
// Final LineTo from rect
13 => line_to(),
// Arc 8 (left top)
14 => check_arc(self.rect.radii.top_left, 0),
// Corner
15 => Some(ArcOrPath::Corner),
16.. => None,
};

self.idx += 1;
result
self.idx += 1;
if skip_arc {
continue;
}
if let Some(result) = result {
return Some(result);
}
continue;
}
None
}
}
8 changes: 7 additions & 1 deletion src/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,13 @@ pub(crate) fn paint_border(
let mut current_path = Vec::new();
for event in border_path.path_elements(&borders, 0.1) {
match event {
BorderPathEvent::PathElement(el) => current_path.push(el),
BorderPathEvent::PathElement(el) => {
if !current_path.is_empty() && matches!(el, PathEl::MoveTo(_)) {
// extra move to's will mess up dashed patterns
continue;
}
current_path.push(el)
}
BorderPathEvent::NewStroke(stroke) => {
// Render current path with previous stroke if any
if !current_path.is_empty() {
Expand Down

0 comments on commit 96f3a23

Please sign in to comment.