ratio.rs (2231B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ 4 5 //! Generic types for CSS values related to <ratio>. 6 //! https://drafts.csswg.org/css-values/#ratios 7 8 use crate::derives::*; 9 use crate::{One, Zero}; 10 use std::fmt::{self, Write}; 11 use style_traits::{CssWriter, ToCss}; 12 13 /// A generic value for the `<ratio>` value. 14 #[derive( 15 Clone, 16 Copy, 17 Debug, 18 MallocSizeOf, 19 PartialEq, 20 SpecifiedValueInfo, 21 ToAnimatedValue, 22 ToComputedValue, 23 ToResolvedValue, 24 ToShmem, 25 )] 26 #[repr(C)] 27 pub struct Ratio<N>(pub N, pub N); 28 29 impl<N> ToCss for Ratio<N> 30 where 31 N: ToCss, 32 { 33 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result 34 where 35 W: Write, 36 { 37 self.0.to_css(dest)?; 38 // Even though 1 could be omitted, we don't per 39 // https://drafts.csswg.org/css-values-4/#ratio-value: 40 // 41 // The second <number> is optional, defaulting to 1. However, 42 // <ratio> is always serialized with both components. 43 // 44 // And for compat reasons, see bug 1669742. 45 // 46 // We serialize with spaces for consistency with all other 47 // slash-delimited things, see 48 // https://github.com/w3c/csswg-drafts/issues/4282 49 dest.write_str(" / ")?; 50 self.1.to_css(dest)?; 51 Ok(()) 52 } 53 } 54 55 impl<N> Ratio<N> 56 where 57 N: Zero + One, 58 { 59 /// Returns true if this is a degenerate ratio. 60 /// https://drafts.csswg.org/css-values/#degenerate-ratio 61 #[inline] 62 pub fn is_degenerate(&self) -> bool { 63 self.0.is_zero() || self.1.is_zero() 64 } 65 66 /// Returns the used value. A ratio of 0/0 behaves as the ratio 1/0. 67 /// https://drafts.csswg.org/css-values-4/#ratios 68 pub fn used_value(self) -> Self { 69 if self.0.is_zero() && self.1.is_zero() { 70 Self(One::one(), Zero::zero()) 71 } else { 72 self 73 } 74 } 75 } 76 77 impl<N> Zero for Ratio<N> 78 where 79 N: Zero + One, 80 { 81 fn zero() -> Self { 82 Self(Zero::zero(), One::one()) 83 } 84 85 fn is_zero(&self) -> bool { 86 self.0.is_zero() 87 } 88 }