mirror of
https://github.com/storytold/deckcraft.git
synced 2026-10-26 03:27:03 -06:00
Merge pull request #1311
This commit is contained in:
@@ -1860,10 +1860,10 @@ fn wedge_rect(w: f64, h: f64, a0: f64, a1: f64, r: f64) -> Geometry {
|
||||
let r = r.min(w / 2.0).min(h / 2.0);
|
||||
// Walk clockwise from the top-left; insert the wedge on the edge facing the tip.
|
||||
let horiz = dx.abs() > dy.abs();
|
||||
let (bx0, bx1) = (w * 5.0 / 12.0, w * 7.0 / 12.0);
|
||||
let (by0, by1) = (h * 5.0 / 12.0, h * 7.0 / 12.0);
|
||||
let (bx0, bx1) = if tip.x < w / 2.0 { (w * 2.0 / 12.0, w * 5.0 / 12.0) } else { (bx0 + w / 12.0 * 2.0 - w / 12.0 * 2.0, bx1 + w * 2.0 / 12.0) };
|
||||
let (by0, by1) = if tip.y < h / 2.0 { (h * 2.0 / 12.0, h * 5.0 / 12.0) } else { (by0, by1 + h * 2.0 / 12.0) };
|
||||
// The wedge's base: 2..5 twelfths of the edge on the tip's side of the centre when it is
|
||||
// before it, 7..10 twelfths when after (presetShapeDefinitions' xg1/xg2, yg1/yg2).
|
||||
let (bx0, bx1) = if tip.x < w / 2.0 { (w * 2.0 / 12.0, w * 5.0 / 12.0) } else { (w * 7.0 / 12.0, w * 10.0 / 12.0) };
|
||||
let (by0, by1) = if tip.y < h / 2.0 { (h * 2.0 / 12.0, h * 5.0 / 12.0) } else { (h * 7.0 / 12.0, h * 10.0 / 12.0) };
|
||||
b.m(r, 0.0);
|
||||
if !inside && !horiz && dy < 0.0 {
|
||||
b.l(bx0, 0.0).l(tip.x, tip.y).l(bx1, 0.0);
|
||||
@@ -2590,4 +2590,46 @@ mod tests {
|
||||
assert!(g.paths.iter().any(|p| p.stroke && p.fill == FillMode::None), "{name}: the curve is outlined");
|
||||
}
|
||||
}
|
||||
|
||||
/// The end points of a path's move/line elements, in order.
|
||||
fn vertices(p: &BezPath) -> Vec<Point> {
|
||||
p.elements()
|
||||
.iter()
|
||||
.filter_map(|e| match e {
|
||||
kurbo::PathEl::MoveTo(q) | kurbo::PathEl::LineTo(q) => Some(*q),
|
||||
_ => None,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wedge_callout_mirrors_with_its_tip() {
|
||||
// A tip below and right of the centre draws the mirror image of the same tip on the left;
|
||||
// the same for a tip right of the centre, above or below it. presetShapeDefinitions puts
|
||||
// the wedge's base at 2..5 twelfths of the edge on the near side of the centre and at
|
||||
// 7..10 twelfths on the far side.
|
||||
let (w, h) = (240.0, 120.0);
|
||||
// Sorted and deduplicated: the outline closes on the corner it starts from, which the
|
||||
// mirror moves to the opposite corner.
|
||||
let sorted = |mut v: Vec<Point>| {
|
||||
v.sort_by(|a, b| a.x.total_cmp(&b.x).then(a.y.total_cmp(&b.y)));
|
||||
v.dedup_by(|a, b| (*a - *b).hypot() < 1e-9);
|
||||
v
|
||||
};
|
||||
for (right, left, flip_x) in [([10000.0, 80000.0], [-10000.0, 80000.0], true), ([80000.0, 10000.0], [80000.0, -10000.0], false)] {
|
||||
let a = vertices(&build("wedgeRectCallout", w, h, &right).unwrap().paths[0].path);
|
||||
let b = vertices(&build("wedgeRectCallout", w, h, &left).unwrap().paths[0].path);
|
||||
let b: Vec<Point> = b.iter().map(|p| if flip_x { Point::new(w - p.x, p.y) } else { Point::new(p.x, h - p.y) }).collect();
|
||||
let (a, b) = (sorted(a), sorted(b));
|
||||
assert_eq!(a.len(), b.len(), "{right:?}: {a:?} vs mirrored {left:?}: {b:?}");
|
||||
for (p, q) in a.iter().zip(&b) {
|
||||
assert!((*p - *q).hypot() < 1e-6, "{right:?}: {a:?}\n is not the mirror of {left:?}: {b:?}");
|
||||
}
|
||||
}
|
||||
// The bottom wedge of a tip right of the centre leaves the edge at 7/12 and 10/12 of the width.
|
||||
let a = vertices(&build("wedgeRectCallout", w, h, &[10000.0, 80000.0]).unwrap().paths[0].path);
|
||||
for x in [w * 7.0 / 12.0, w * 10.0 / 12.0] {
|
||||
assert!(a.iter().any(|p| (p.x - x).abs() < 1e-6 && (p.y - h).abs() < 1e-6), "no wedge corner at ({x}, {h}): {a:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user