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 //! This module contains shared types and messages for use by devtools/script. 6 //! The traits are here instead of in script so that the devtools crate can be 7 //! modified independently of the rest of Servo. 8 9 #![crate_name = "style_traits"] 10 #![crate_type = "rlib"] 11 #![deny(unsafe_code, missing_docs)] 12 13 extern crate app_units; 14 #[macro_use] 15 extern crate bitflags; 16 #[macro_use] 17 extern crate cssparser; 18 extern crate euclid; 19 #[macro_use] 20 extern crate lazy_static; 21 extern crate malloc_size_of; 22 #[macro_use] 23 extern crate malloc_size_of_derive; 24 extern crate selectors; 25 #[macro_use] 26 extern crate serde; 27 extern crate servo_arc; 28 #[cfg(feature = "servo")] 29 extern crate servo_atoms; 30 #[cfg(feature = "servo")] 31 extern crate servo_url; 32 extern crate to_shmem; 33 #[macro_use] 34 extern crate to_shmem_derive; 35 #[cfg(feature = "servo")] 36 extern crate webrender_api; 37 #[cfg(feature = "servo")] 38 pub use webrender_api::units::DevicePixel; 39 40 use cssparser::{CowRcStr, Token}; 41 use selectors::parser::SelectorParseErrorKind; 42 #[cfg(feature = "servo")] 43 use servo_atoms::Atom; 44 45 /// One hardware pixel. 46 /// 47 /// This unit corresponds to the smallest addressable element of the display hardware. 48 #[cfg(not(feature = "servo"))] 49 #[derive(Clone, Copy, Debug)] 50 pub enum DevicePixel {} 51 52 /// Represents a mobile style pinch zoom factor. 53 /// TODO(gw): Once WR supports pinch zoom, use a type directly from webrender_api. 54 #[derive(Clone, Copy, Debug, PartialEq)] 55 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize, MallocSizeOf))] 56 pub struct PinchZoomFactor(f32); 57 58 impl PinchZoomFactor { 59 /// Construct a new pinch zoom factor. new(scale: f32) -> PinchZoomFactor60 pub fn new(scale: f32) -> PinchZoomFactor { 61 PinchZoomFactor(scale) 62 } 63 64 /// Get the pinch zoom factor as an untyped float. get(&self) -> f3265 pub fn get(&self) -> f32 { 66 self.0 67 } 68 } 69 70 /// One CSS "px" in the coordinate system of the "initial viewport": 71 /// <http://www.w3.org/TR/css-device-adapt/#initial-viewport> 72 /// 73 /// `CSSPixel` is equal to `DeviceIndependentPixel` times a "page zoom" factor controlled by the user. This is 74 /// the desktop-style "full page" zoom that enlarges content but then reflows the layout viewport 75 /// so it still exactly fits the visible area. 76 /// 77 /// At the default zoom level of 100%, one `CSSPixel` is equal to one `DeviceIndependentPixel`. However, if the 78 /// document is zoomed in or out then this scale may be larger or smaller. 79 #[derive(Clone, Copy, Debug)] 80 pub enum CSSPixel {} 81 82 // In summary, the hierarchy of pixel units and the factors to convert from one to the next: 83 // 84 // DevicePixel 85 // / hidpi_ratio => DeviceIndependentPixel 86 // / desktop_zoom => CSSPixel 87 88 pub mod arc_slice; 89 pub mod dom; 90 pub mod specified_value_info; 91 #[macro_use] 92 pub mod values; 93 #[macro_use] 94 pub mod viewport; 95 pub mod owned_slice; 96 pub mod owned_str; 97 98 pub use crate::specified_value_info::{CssType, KeywordsCollectFn, SpecifiedValueInfo}; 99 pub use crate::values::{ 100 Comma, CommaWithSpace, CssWriter, OneOrMoreSeparated, Separator, Space, ToCss, 101 }; 102 103 /// The error type for all CSS parsing routines. 104 pub type ParseError<'i> = cssparser::ParseError<'i, StyleParseErrorKind<'i>>; 105 106 /// Error in property value parsing 107 pub type ValueParseError<'i> = cssparser::ParseError<'i, ValueParseErrorKind<'i>>; 108 109 #[derive(Clone, Debug, PartialEq)] 110 /// Errors that can be encountered while parsing CSS values. 111 pub enum StyleParseErrorKind<'i> { 112 /// A bad URL token in a DVB. 113 BadUrlInDeclarationValueBlock(CowRcStr<'i>), 114 /// A bad string token in a DVB. 115 BadStringInDeclarationValueBlock(CowRcStr<'i>), 116 /// Unexpected closing parenthesis in a DVB. 117 UnbalancedCloseParenthesisInDeclarationValueBlock, 118 /// Unexpected closing bracket in a DVB. 119 UnbalancedCloseSquareBracketInDeclarationValueBlock, 120 /// Unexpected closing curly bracket in a DVB. 121 UnbalancedCloseCurlyBracketInDeclarationValueBlock, 122 /// A property declaration value had input remaining after successfully parsing. 123 PropertyDeclarationValueNotExhausted, 124 /// An unexpected dimension token was encountered. 125 UnexpectedDimension(CowRcStr<'i>), 126 /// Missing or invalid media feature name. 127 MediaQueryExpectedFeatureName(CowRcStr<'i>), 128 /// Missing or invalid media feature value. 129 MediaQueryExpectedFeatureValue, 130 /// A media feature range operator was not expected. 131 MediaQueryUnexpectedOperator, 132 /// min- or max- properties must have a value. 133 RangedExpressionWithNoValue, 134 /// A function was encountered that was not expected. 135 UnexpectedFunction(CowRcStr<'i>), 136 /// @namespace must be before any rule but @charset and @import 137 UnexpectedNamespaceRule, 138 /// @import must be before any rule but @charset 139 UnexpectedImportRule, 140 /// @import rules are disallowed in the parser. 141 DisallowedImportRule, 142 /// Unexpected @charset rule encountered. 143 UnexpectedCharsetRule, 144 /// Unsupported @ rule 145 UnsupportedAtRule(CowRcStr<'i>), 146 /// A placeholder for many sources of errors that require more specific variants. 147 UnspecifiedError, 148 /// An unexpected token was found within a namespace rule. 149 UnexpectedTokenWithinNamespace(Token<'i>), 150 /// An error was encountered while parsing a property value. 151 ValueError(ValueParseErrorKind<'i>), 152 /// An error was encountered while parsing a selector 153 SelectorError(SelectorParseErrorKind<'i>), 154 /// The property declaration was for an unknown property. 155 UnknownProperty(CowRcStr<'i>), 156 /// The property declaration was for a disabled experimental property. 157 ExperimentalProperty, 158 /// The property declaration contained an invalid color value. 159 InvalidColor(CowRcStr<'i>, Token<'i>), 160 /// The property declaration contained an invalid filter value. 161 InvalidFilter(CowRcStr<'i>, Token<'i>), 162 /// The property declaration contained an invalid value. 163 OtherInvalidValue(CowRcStr<'i>), 164 /// The declaration contained an animation property, and we were parsing 165 /// this as a keyframe block (so that property should be ignored). 166 /// 167 /// See: https://drafts.csswg.org/css-animations/#keyframes 168 AnimationPropertyInKeyframeBlock, 169 /// The property is not allowed within a page rule. 170 NotAllowedInPageRule, 171 } 172 173 impl<'i> From<ValueParseErrorKind<'i>> for StyleParseErrorKind<'i> { from(this: ValueParseErrorKind<'i>) -> Self174 fn from(this: ValueParseErrorKind<'i>) -> Self { 175 StyleParseErrorKind::ValueError(this) 176 } 177 } 178 179 impl<'i> From<SelectorParseErrorKind<'i>> for StyleParseErrorKind<'i> { from(this: SelectorParseErrorKind<'i>) -> Self180 fn from(this: SelectorParseErrorKind<'i>) -> Self { 181 StyleParseErrorKind::SelectorError(this) 182 } 183 } 184 185 /// Specific errors that can be encountered while parsing property values. 186 #[derive(Clone, Debug, PartialEq)] 187 pub enum ValueParseErrorKind<'i> { 188 /// An invalid token was encountered while parsing a color value. 189 InvalidColor(Token<'i>), 190 /// An invalid filter value was encountered. 191 InvalidFilter(Token<'i>), 192 } 193 194 impl<'i> StyleParseErrorKind<'i> { 195 /// Create an InvalidValue parse error new_invalid<S>(name: S, value_error: ParseError<'i>) -> ParseError<'i> where S: Into<CowRcStr<'i>>,196 pub fn new_invalid<S>(name: S, value_error: ParseError<'i>) -> ParseError<'i> 197 where 198 S: Into<CowRcStr<'i>>, 199 { 200 let name = name.into(); 201 let variant = match value_error.kind { 202 cssparser::ParseErrorKind::Custom(StyleParseErrorKind::ValueError(e)) => match e { 203 ValueParseErrorKind::InvalidColor(token) => { 204 StyleParseErrorKind::InvalidColor(name, token) 205 }, 206 ValueParseErrorKind::InvalidFilter(token) => { 207 StyleParseErrorKind::InvalidFilter(name, token) 208 }, 209 }, 210 _ => StyleParseErrorKind::OtherInvalidValue(name), 211 }; 212 cssparser::ParseError { 213 kind: cssparser::ParseErrorKind::Custom(variant), 214 location: value_error.location, 215 } 216 } 217 } 218 219 bitflags! { 220 /// The mode to use when parsing values. 221 pub struct ParsingMode: u8 { 222 /// In CSS; lengths must have units, except for zero values, where the unit can be omitted. 223 /// <https://www.w3.org/TR/css3-values/#lengths> 224 const DEFAULT = 0x00; 225 /// In SVG; a coordinate or length value without a unit identifier (e.g., "25") is assumed 226 /// to be in user units (px). 227 /// <https://www.w3.org/TR/SVG/coords.html#Units> 228 const ALLOW_UNITLESS_LENGTH = 0x01; 229 /// In SVG; out-of-range values are not treated as an error in parsing. 230 /// <https://www.w3.org/TR/SVG/implnote.html#RangeClamping> 231 const ALLOW_ALL_NUMERIC_VALUES = 0x02; 232 } 233 } 234 235 impl ParsingMode { 236 /// Whether the parsing mode allows unitless lengths for non-zero values to be intpreted as px. 237 #[inline] allows_unitless_lengths(&self) -> bool238 pub fn allows_unitless_lengths(&self) -> bool { 239 self.intersects(ParsingMode::ALLOW_UNITLESS_LENGTH) 240 } 241 242 /// Whether the parsing mode allows all numeric values. 243 #[inline] allows_all_numeric_values(&self) -> bool244 pub fn allows_all_numeric_values(&self) -> bool { 245 self.intersects(ParsingMode::ALLOW_ALL_NUMERIC_VALUES) 246 } 247 } 248 249 #[cfg(feature = "servo")] 250 /// Speculatively execute paint code in the worklet thread pool. 251 pub trait SpeculativePainter: Send + Sync { 252 /// <https://drafts.css-houdini.org/css-paint-api/#draw-a-paint-image> speculatively_draw_a_paint_image( &self, properties: Vec<(Atom, String)>, arguments: Vec<String>, )253 fn speculatively_draw_a_paint_image( 254 &self, 255 properties: Vec<(Atom, String)>, 256 arguments: Vec<String>, 257 ); 258 } 259