mirror of
https://github.com/storytold/figcraft.git
synced 2026-11-13 22:02:38 +00:00
M8: Tidy up keeps the second layer after a narrow first one when the gap is negative
raise_negative_gap raised a negative gap from the interior widths only, so a first layer narrower than the gap's size let the second start before it (widths 10, 100 x5 at X 0, 80, 200, 260, 400, 460: the modal -40 gave X 0, -30, 30, ...). The second must start after the first, g > -w(0), in whole pixels floor(-w(0)) + 1. Figma kept the order in every measured run; a narrow first layer was not measured, so this bound keeps the order rather than follow a reading. Test: tidy_tests::a_narrow_first_layer_still_keeps_the_second_after_it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Model-Effort: Opus 5.5 drove and wrote
This commit is contained in:
1 parent
fc90078333
commit
1a68ded581
2 files changed
+20
-2
No files matched your search
@@ -167,13 +167,18 @@ fn even_gap(gaps: &[f64], spacing: Option<f64>) -> f64 {
|
||||
/// in Figma's web app on 2026-11-13: interior widths of 10, 20 and 30 among 100s gave -4, -9 and
|
||||
/// -14, and widths of 100 left the most common gap, -40, alone. Only those three widths were
|
||||
/// measured; other widths follow the same formula.
|
||||
///
|
||||
/// The first layer has no layer two places before it, but the second must still start after it:
|
||||
/// `g > -w(0)`, in whole pixels `floor(-w(0)) + 1`. Figma kept the order in every run; a narrow
|
||||
/// first layer was not measured, so this bound keeps that order rather than following a reading.
|
||||
fn raise_negative_gap(gap: f64, widths: &[f64]) -> f64 {
|
||||
let interior = widths.get(1..widths.len().saturating_sub(1)).unwrap_or(&[]);
|
||||
let w_min = interior.iter().copied().fold(f64::INFINITY, f64::min);
|
||||
if widths.len() < 3 || !w_min.is_finite() {
|
||||
let Some(first) = widths.first().copied() else { return gap };
|
||||
if widths.len() < 3 || !w_min.is_finite() || !first.is_finite() {
|
||||
return gap;
|
||||
}
|
||||
gap.max((-w_min / 2.0).floor() + 1.0)
|
||||
gap.max((-w_min / 2.0).floor() + 1.0).max((-first).floor() + 1.0)
|
||||
}
|
||||
|
||||
/// A row (`vertical` false) or a column: the first layer stays, each next one follows the last at
|
||||
|
||||
@@ -339,6 +339,19 @@ fn a_negative_gap_is_raised_so_no_layer_reaches_the_one_two_before() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_narrow_first_layer_still_keeps_the_second_after_it() {
|
||||
// Not measured in Figma (it kept the order in every run): the modal gap -40 would start the
|
||||
// second layer at -30, before a 10 wide first layer, so the gap is raised to -9.
|
||||
let mut s = Session::new();
|
||||
let xs = [0., 80., 200., 260., 400., 460.];
|
||||
let widths = [10., 100., 100., 100., 100., 100.];
|
||||
let pairs: Vec<(f64, f64)> = xs.iter().copied().zip(widths).collect();
|
||||
let ids = bars(&mut s, &pairs);
|
||||
tidy(&mut s, &ids);
|
||||
assert_eq!(xs_of(&s, &ids), vec![0., 1., 92., 183., 274., 365.]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_negative_gap_between_equal_widths_is_the_most_common_gap() {
|
||||
let mut s = Session::new();
|
||||
|
||||
Reference in new issue
Block a user