euclid/
side_offsets.rs

1// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution.
3//
4// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7// option. This file may not be copied, modified, or distributed
8// except according to those terms.
9
10//! A group of side offsets, which correspond to top/left/bottom/right for borders, padding,
11//! and margins in CSS.
12
13use super::UnknownUnit;
14use length::Length;
15use num::Zero;
16use core::fmt;
17use core::ops::Add;
18use core::marker::PhantomData;
19
20/// A group of 2D side offsets, which correspond to top/left/bottom/right for borders, padding,
21/// and margins in CSS, optionally tagged with a unit.
22#[derive(EuclidMatrix)]
23#[repr(C)]
24pub struct TypedSideOffsets2D<T, U> {
25    pub top: T,
26    pub right: T,
27    pub bottom: T,
28    pub left: T,
29    #[doc(hidden)]
30    pub _unit: PhantomData<U>,
31}
32
33impl<T: fmt::Debug, U> fmt::Debug for TypedSideOffsets2D<T, U> {
34    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
35        write!(
36            f,
37            "({:?},{:?},{:?},{:?})",
38            self.top, self.right, self.bottom, self.left
39        )
40    }
41}
42
43impl<T: Default, U> Default for TypedSideOffsets2D<T, U> {
44    fn default() -> Self {
45        TypedSideOffsets2D {
46            top: Default::default(),
47            right: Default::default(),
48            bottom: Default::default(),
49            left: Default::default(),
50            _unit: PhantomData,
51        }
52    }
53}
54
55/// The default 2D side offset type with no unit.
56pub type SideOffsets2D<T> = TypedSideOffsets2D<T, UnknownUnit>;
57
58impl<T: Copy, U> TypedSideOffsets2D<T, U> {
59    /// Constructor taking a scalar for each side.
60    pub fn new(top: T, right: T, bottom: T, left: T) -> Self {
61        TypedSideOffsets2D {
62            top,
63            right,
64            bottom,
65            left,
66            _unit: PhantomData,
67        }
68    }
69
70    /// Constructor taking a typed Length for each side.
71    pub fn from_lengths(
72        top: Length<T, U>,
73        right: Length<T, U>,
74        bottom: Length<T, U>,
75        left: Length<T, U>,
76    ) -> Self {
77        TypedSideOffsets2D::new(top.0, right.0, bottom.0, left.0)
78    }
79
80    /// Access self.top as a typed Length instead of a scalar value.
81    pub fn top_typed(&self) -> Length<T, U> {
82        Length::new(self.top)
83    }
84
85    /// Access self.right as a typed Length instead of a scalar value.
86    pub fn right_typed(&self) -> Length<T, U> {
87        Length::new(self.right)
88    }
89
90    /// Access self.bottom as a typed Length instead of a scalar value.
91    pub fn bottom_typed(&self) -> Length<T, U> {
92        Length::new(self.bottom)
93    }
94
95    /// Access self.left as a typed Length instead of a scalar value.
96    pub fn left_typed(&self) -> Length<T, U> {
97        Length::new(self.left)
98    }
99
100    /// Constructor setting the same value to all sides, taking a scalar value directly.
101    pub fn new_all_same(all: T) -> Self {
102        TypedSideOffsets2D::new(all, all, all, all)
103    }
104
105    /// Constructor setting the same value to all sides, taking a typed Length.
106    pub fn from_length_all_same(all: Length<T, U>) -> Self {
107        TypedSideOffsets2D::new_all_same(all.0)
108    }
109}
110
111impl<T, U> TypedSideOffsets2D<T, U>
112where
113    T: Add<T, Output = T> + Copy,
114{
115    pub fn horizontal(&self) -> T {
116        self.left + self.right
117    }
118
119    pub fn vertical(&self) -> T {
120        self.top + self.bottom
121    }
122
123    pub fn horizontal_typed(&self) -> Length<T, U> {
124        Length::new(self.horizontal())
125    }
126
127    pub fn vertical_typed(&self) -> Length<T, U> {
128        Length::new(self.vertical())
129    }
130}
131
132impl<T, U> Add for TypedSideOffsets2D<T, U>
133where
134    T: Copy + Add<T, Output = T>,
135{
136    type Output = Self;
137    fn add(self, other: Self) -> Self {
138        TypedSideOffsets2D::new(
139            self.top + other.top,
140            self.right + other.right,
141            self.bottom + other.bottom,
142            self.left + other.left,
143        )
144    }
145}
146
147impl<T: Copy + Zero, U> TypedSideOffsets2D<T, U> {
148    /// Constructor, setting all sides to zero.
149    pub fn zero() -> Self {
150        TypedSideOffsets2D::new(Zero::zero(), Zero::zero(), Zero::zero(), Zero::zero())
151    }
152}