1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
//! Color-stop position normalization.
//!
//! Mirrors culori 4.0.2's `util/normalizePositions.js`, which implements
//! the CSS Images Module 4 stop-fixup algorithm
//! (<https://drafts.csswg.org/css-images-4/#color-stop-fixup>):
//!
//! 1. Set the first position to `0` if missing, the last to `1` if missing.
//! 2. Spread runs of missing positions evenly between their defined
//! neighbours.
//! 3. Clamp every position to be at least as large as the previous one.
//!
//! culors uses `NaN` as the "missing" marker (where culori uses
//! `undefined`). Pass [`f64::NAN`] for stops without an explicit position.
//!
//! culors's `interpolate` family always assigns evenly spaced positions
//! internally, so this helper is exposed for callers building gradient
//! pipelines who need the explicit-position semantics culori's
//! `interpolate(stops, mode)` accepts via `[color, position]` pairs.
/// Normalize a slice of stop positions in place using the CSS Images
/// Module 4 stop-fixup rules. Returns the same slice for chaining.
///
/// `f64::NAN` stands in for "missing" (`undefined` in culori). The slice
/// is mutated directly: defined positions are kept, missing positions are
/// filled, and out-of-order positions are pulled forward to the previous
/// one's value.
///
/// # Examples
///
/// All-missing positions are spread evenly across `[0, 1]`:
///
/// ```rust
/// use culors::normalize_positions;
/// let mut stops = [f64::NAN; 5];
/// normalize_positions(&mut stops);
/// assert_eq!(stops, [0.0, 0.25, 0.5, 0.75, 1.0]);
/// ```
///
/// Defined endpoints anchor the gap fill:
///
/// ```rust
/// use culors::normalize_positions;
/// let mut stops = [0.2, f64::NAN, f64::NAN, 0.8];
/// normalize_positions(&mut stops);
/// assert_eq!(stops, [0.2, 0.4, 0.6000000000000001, 0.8]);
/// ```
///
/// Out-of-order stops clamp forward (rule 3):
///
/// ```rust
/// use culors::normalize_positions;
/// let mut stops = [0.5, 0.3, 0.8];
/// normalize_positions(&mut stops);
/// assert_eq!(stops, [0.5, 0.5, 0.8]);
/// ```