1//! Taffy uses two coordinate systems to refer to grid lines (the gaps/gutters between rows/columns):
2use super::super::types::TrackCounts;
3use crate::geometry::Line;
4use core::cmp::{max, Ordering};
5use core::ops::{Add, AddAssign, Sub};
67/// Represents a grid line position in "CSS Grid Line" coordinates
8///
9/// "CSS Grid Line" coordinates are those used in grid-row/grid-column in the CSS grid spec:
10/// - The line at left hand (or top) edge of the explicit grid is line 1
11/// (and counts up from there)
12/// - The line at the right hand (or bottom) edge of the explicit grid is -1
13/// (and counts down from there)
14/// - 0 is not a valid index
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
17#[repr(transparent)]
18pub struct GridLine(i16);
1920impl From<i16> for GridLine {
21fn from(value: i16) -> Self {
22Self(value)
23 }
24}
2526impl GridLine {
27/// Returns the underlying i16
28pub fn as_i16(self) -> i16 {
29self.0
30}
3132/// Convert into OriginZero coordinates using the specified explicit track count
33pub(crate) fn into_origin_zero_line(self, explicit_track_count: u16) -> OriginZeroLine {
34let explicit_line_count = explicit_track_count + 1;
35let oz_line = match self.0.cmp(&0) {
36 Ordering::Greater => self.0 - 1,
37 Ordering::Less => self.0 + explicit_line_count as i16,
38 Ordering::Equal => panic!("Grid line of zero is invalid"),
39 };
40 OriginZeroLine(oz_line)
41 }
42}
4344/// Represents a grid line position in "OriginZero" coordinates
45///
46/// "OriginZero" coordinates are a normalized form:
47/// - The line at left hand (or top) edge of the explicit grid is line 0
48/// - The next line to the right (or down) is 1, and so on
49/// - The next line to the left (or up) is -1, and so on
50#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
51#[repr(transparent)]
52pub struct OriginZeroLine(pub i16);
5354// Add and Sub with Self
55impl Add<OriginZeroLine> for OriginZeroLine {
56type Output = Self;
57fn add(self, rhs: OriginZeroLine) -> Self::Output {
58 OriginZeroLine(self.0 + rhs.0)
59 }
60}
61impl Sub<OriginZeroLine> for OriginZeroLine {
62type Output = Self;
63fn sub(self, rhs: OriginZeroLine) -> Self::Output {
64 OriginZeroLine(self.0 - rhs.0)
65 }
66}
6768// Add and Sub with u16
69impl Add<u16> for OriginZeroLine {
70type Output = Self;
71fn add(self, rhs: u16) -> Self::Output {
72 OriginZeroLine(self.0 + rhs as i16)
73 }
74}
75impl AddAssign<u16> for OriginZeroLine {
76fn add_assign(&mut self, rhs: u16) {
77self.0 += rhs as i16;
78 }
79}
80impl Sub<u16> for OriginZeroLine {
81type Output = Self;
82fn sub(self, rhs: u16) -> Self::Output {
83 OriginZeroLine(self.0 - rhs as i16)
84 }
85}
8687impl OriginZeroLine {
88/// Converts a grid line in OriginZero coordinates into the index of that same grid line in the GridTrackVec.
89pub(crate) fn into_track_vec_index(self, track_counts: TrackCounts) -> usize {
90assert!(
91self.0 >= -(track_counts.negative_implicit as i16),
92"OriginZero grid line cannot be less than the number of negative grid lines"
93);
94assert!(
95self.0 <= (track_counts.explicit + track_counts.positive_implicit) as i16,
96"OriginZero grid line cannot be more than the number of positive grid lines"
97);
982 * ((self.0 + track_counts.negative_implicit as i16) as usize)
99 }
100101/// The minimum number of negative implicit track there must be if a grid item starts at this line.
102pub(crate) fn implied_negative_implicit_tracks(self) -> u16 {
103if self.0 < 0 {
104self.0.unsigned_abs()
105 } else {
1060
107}
108 }
109110/// The minimum number of positive implicit track there must be if a grid item end at this line.
111pub(crate) fn implied_positive_implicit_tracks(self, explicit_track_count: u16) -> u16 {
112if self.0 > explicit_track_count as i16 {
113self.0 as u16 - explicit_track_count
114 } else {
1150
116}
117 }
118}
119120impl Line<OriginZeroLine> {
121/// The number of tracks between the start and end lines
122pub(crate) fn span(self) -> u16 {
123 max(self.end.0 - self.start.0, 0) as u16
124 }
125}
126127/// A trait for the different coordinates used to define grid lines.
128pub trait GridCoordinate: Copy {}
129impl GridCoordinate for GridLine {}
130impl GridCoordinate for OriginZeroLine {}