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 http://mozilla.org/MPL/2.0/. */ 4 5 //! CSS handling for the computed value of 6 //! [`image`][image]s 7 //! 8 //! [image]: https://drafts.csswg.org/css-images/#image-values 9 10 use cssparser::RGBA; 11 use std::f32::consts::PI; 12 use std::fmt::{self, Write}; 13 use style_traits::{CssWriter, ToCss}; 14 use values::{Either, None_}; 15 use values::computed::{Angle, ComputedImageUrl, Context}; 16 use values::computed::{Length, LengthOrPercentage, NumberOrPercentage, ToComputedValue}; 17 #[cfg(feature = "gecko")] 18 use values::computed::Percentage; 19 use values::computed::position::Position; 20 use values::generics::image::{CompatMode, ColorStop as GenericColorStop, EndingShape as GenericEndingShape}; 21 use values::generics::image::{Gradient as GenericGradient, GradientItem as GenericGradientItem}; 22 use values::generics::image::{Image as GenericImage, GradientKind as GenericGradientKind}; 23 use values::generics::image::{LineDirection as GenericLineDirection, MozImageRect as GenericMozImageRect}; 24 use values::specified::image::LineDirection as SpecifiedLineDirection; 25 use values::specified::position::{X, Y}; 26 27 /// A computed image layer. 28 pub type ImageLayer = Either<None_, Image>; 29 30 /// Computed values for an image according to CSS-IMAGES. 31 /// <https://drafts.csswg.org/css-images/#image-values> 32 pub type Image = GenericImage<Gradient, MozImageRect, ComputedImageUrl>; 33 34 /// Computed values for a CSS gradient. 35 /// <https://drafts.csswg.org/css-images/#gradients> 36 pub type Gradient = GenericGradient< 37 LineDirection, 38 Length, 39 LengthOrPercentage, 40 Position, 41 RGBA, 42 Angle, 43 >; 44 45 /// A computed gradient kind. 46 pub type GradientKind = GenericGradientKind< 47 LineDirection, 48 Length, 49 LengthOrPercentage, 50 Position, 51 Angle, 52 >; 53 54 /// A computed gradient line direction. 55 #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq)] 56 pub enum LineDirection { 57 /// An angle. 58 Angle(Angle), 59 /// A horizontal direction. 60 Horizontal(X), 61 /// A vertical direction. 62 Vertical(Y), 63 /// A corner. 64 Corner(X, Y), 65 /// A Position and an Angle for legacy `-moz-` prefixed gradient. 66 #[cfg(feature = "gecko")] 67 MozPosition(Option<Position>, Option<Angle>), 68 } 69 70 /// A computed radial gradient ending shape. 71 pub type EndingShape = GenericEndingShape<Length, LengthOrPercentage>; 72 73 /// A computed gradient item. 74 pub type GradientItem = GenericGradientItem<RGBA, LengthOrPercentage>; 75 76 /// A computed color stop. 77 pub type ColorStop = GenericColorStop<RGBA, LengthOrPercentage>; 78 79 /// Computed values for `-moz-image-rect(...)`. 80 pub type MozImageRect = GenericMozImageRect<NumberOrPercentage, ComputedImageUrl>; 81 82 impl GenericLineDirection for LineDirection { points_downwards(&self, compat_mode: CompatMode) -> bool83 fn points_downwards(&self, compat_mode: CompatMode) -> bool { 84 match *self { 85 LineDirection::Angle(angle) => angle.radians() == PI, 86 LineDirection::Vertical(Y::Bottom) 87 if compat_mode == CompatMode::Modern => true, 88 LineDirection::Vertical(Y::Top) 89 if compat_mode != CompatMode::Modern => true, 90 LineDirection::Corner(..) => false, 91 #[cfg(feature = "gecko")] 92 LineDirection::MozPosition(Some(Position { 93 horizontal: LengthOrPercentage::Percentage(Percentage(x)), 94 vertical: LengthOrPercentage::Percentage(Percentage(y)), 95 }), None) => { 96 // `50% 0%` is the default value for line direction. 97 x == 0.5 && y == 0.0 98 }, 99 _ => false, 100 } 101 } 102 to_css<W>( &self, dest: &mut CssWriter<W>, compat_mode: CompatMode, ) -> fmt::Result where W: Write,103 fn to_css<W>( 104 &self, 105 dest: &mut CssWriter<W>, 106 compat_mode: CompatMode, 107 ) -> fmt::Result 108 where 109 W: Write, 110 { 111 match *self { 112 LineDirection::Angle(ref angle) => angle.to_css(dest), 113 LineDirection::Horizontal(x) => { 114 if compat_mode == CompatMode::Modern { 115 dest.write_str("to ")?; 116 } 117 x.to_css(dest) 118 }, 119 LineDirection::Vertical(y) => { 120 if compat_mode == CompatMode::Modern { 121 dest.write_str("to ")?; 122 } 123 y.to_css(dest) 124 }, 125 LineDirection::Corner(x, y) => { 126 if compat_mode == CompatMode::Modern { 127 dest.write_str("to ")?; 128 } 129 x.to_css(dest)?; 130 dest.write_str(" ")?; 131 y.to_css(dest) 132 }, 133 #[cfg(feature = "gecko")] 134 LineDirection::MozPosition(position, angle) => { 135 let mut need_space = false; 136 if let Some(position) = position { 137 position.to_css(dest)?; 138 need_space = true; 139 } 140 if let Some(angle) = angle { 141 if need_space { 142 dest.write_str(" ")?; 143 } 144 angle.to_css(dest)?; 145 } 146 Ok(()) 147 } 148 } 149 } 150 } 151 152 impl ToComputedValue for SpecifiedLineDirection { 153 type ComputedValue = LineDirection; 154 to_computed_value(&self, context: &Context) -> Self::ComputedValue155 fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { 156 match *self { 157 SpecifiedLineDirection::Angle(ref angle) => { 158 LineDirection::Angle(angle.to_computed_value(context)) 159 }, 160 SpecifiedLineDirection::Horizontal(x) => { 161 LineDirection::Horizontal(x) 162 }, 163 SpecifiedLineDirection::Vertical(y) => { 164 LineDirection::Vertical(y) 165 }, 166 SpecifiedLineDirection::Corner(x, y) => { 167 LineDirection::Corner(x, y) 168 }, 169 #[cfg(feature = "gecko")] 170 SpecifiedLineDirection::MozPosition(ref position, ref angle) => { 171 LineDirection::MozPosition(position.to_computed_value(context), 172 angle.to_computed_value(context)) 173 }, 174 } 175 } 176 from_computed_value(computed: &Self::ComputedValue) -> Self177 fn from_computed_value(computed: &Self::ComputedValue) -> Self { 178 match *computed { 179 LineDirection::Angle(ref angle) => { 180 SpecifiedLineDirection::Angle(ToComputedValue::from_computed_value(angle)) 181 }, 182 LineDirection::Horizontal(x) => { 183 SpecifiedLineDirection::Horizontal(x) 184 }, 185 LineDirection::Vertical(y) => { 186 SpecifiedLineDirection::Vertical(y) 187 }, 188 LineDirection::Corner(x, y) => { 189 SpecifiedLineDirection::Corner(x, y) 190 }, 191 #[cfg(feature = "gecko")] 192 LineDirection::MozPosition(ref position, ref angle) => { 193 SpecifiedLineDirection::MozPosition(ToComputedValue::from_computed_value(position), 194 ToComputedValue::from_computed_value(angle)) 195 }, 196 } 197 } 198 } 199