• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Taffy uses two coordinate systems to refer to grid lines (the gaps/gutters between rows/columns):
2 use super::super::types::TrackCounts;
3 use crate::geometry::Line;
4 use core::cmp::{max, Ordering};
5 use core::ops::{Add, AddAssign, Sub};
6 
7 /// 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)]
18 pub struct GridLine(i16);
19 
20 impl From<i16> for GridLine {
from(value: i16) -> Self21     fn from(value: i16) -> Self {
22         Self(value)
23     }
24 }
25 
26 impl GridLine {
27     /// Returns the underlying i16
as_i16(self) -> i1628     pub fn as_i16(self) -> i16 {
29         self.0
30     }
31 
32     /// Convert into OriginZero coordinates using the specified explicit track count
into_origin_zero_line(self, explicit_track_count: u16) -> OriginZeroLine33     pub(crate) fn into_origin_zero_line(self, explicit_track_count: u16) -> OriginZeroLine {
34         let explicit_line_count = explicit_track_count + 1;
35         let 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 }
43 
44 /// 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)]
52 pub struct OriginZeroLine(pub i16);
53 
54 // Add and Sub with Self
55 impl Add<OriginZeroLine> for OriginZeroLine {
56     type Output = Self;
add(self, rhs: OriginZeroLine) -> Self::Output57     fn add(self, rhs: OriginZeroLine) -> Self::Output {
58         OriginZeroLine(self.0 + rhs.0)
59     }
60 }
61 impl Sub<OriginZeroLine> for OriginZeroLine {
62     type Output = Self;
sub(self, rhs: OriginZeroLine) -> Self::Output63     fn sub(self, rhs: OriginZeroLine) -> Self::Output {
64         OriginZeroLine(self.0 - rhs.0)
65     }
66 }
67 
68 // Add and Sub with u16
69 impl Add<u16> for OriginZeroLine {
70     type Output = Self;
add(self, rhs: u16) -> Self::Output71     fn add(self, rhs: u16) -> Self::Output {
72         OriginZeroLine(self.0 + rhs as i16)
73     }
74 }
75 impl AddAssign<u16> for OriginZeroLine {
add_assign(&mut self, rhs: u16)76     fn add_assign(&mut self, rhs: u16) {
77         self.0 += rhs as i16;
78     }
79 }
80 impl Sub<u16> for OriginZeroLine {
81     type Output = Self;
sub(self, rhs: u16) -> Self::Output82     fn sub(self, rhs: u16) -> Self::Output {
83         OriginZeroLine(self.0 - rhs as i16)
84     }
85 }
86 
87 impl OriginZeroLine {
88     /// Converts a grid line in OriginZero coordinates into the index of that same grid line in the GridTrackVec.
into_track_vec_index(self, track_counts: TrackCounts) -> usize89     pub(crate) fn into_track_vec_index(self, track_counts: TrackCounts) -> usize {
90         assert!(
91             self.0 >= -(track_counts.negative_implicit as i16),
92             "OriginZero grid line cannot be less than the number of negative grid lines"
93         );
94         assert!(
95             self.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         );
98         2 * ((self.0 + track_counts.negative_implicit as i16) as usize)
99     }
100 
101     /// The minimum number of negative implicit track there must be if a grid item starts at this line.
implied_negative_implicit_tracks(self) -> u16102     pub(crate) fn implied_negative_implicit_tracks(self) -> u16 {
103         if self.0 < 0 {
104             self.0.unsigned_abs()
105         } else {
106             0
107         }
108     }
109 
110     /// The minimum number of positive implicit track there must be if a grid item end at this line.
implied_positive_implicit_tracks(self, explicit_track_count: u16) -> u16111     pub(crate) fn implied_positive_implicit_tracks(self, explicit_track_count: u16) -> u16 {
112         if self.0 > explicit_track_count as i16 {
113             self.0 as u16 - explicit_track_count
114         } else {
115             0
116         }
117     }
118 }
119 
120 impl Line<OriginZeroLine> {
121     /// The number of tracks between the start and end lines
span(self) -> u16122     pub(crate) fn span(self) -> u16 {
123         max(self.end.0 - self.start.0, 0) as u16
124     }
125 }
126 
127 /// A trait for the different coordinates used to define grid lines.
128 pub trait GridCoordinate: Copy {}
129 impl GridCoordinate for GridLine {}
130 impl GridCoordinate for OriginZeroLine {}
131