lib.rs (11601B)
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 #[macro_use] 14 extern crate malloc_size_of_derive; 15 #[macro_use] 16 extern crate serde; 17 #[macro_use] 18 extern crate to_shmem_derive; 19 #[cfg(feature = "servo")] 20 extern crate url; 21 22 use bitflags::bitflags; 23 use cssparser::{CowRcStr, Token}; 24 use selectors::parser::SelectorParseErrorKind; 25 #[cfg(feature = "servo")] 26 use stylo_atoms::Atom; 27 28 /// One hardware pixel. 29 /// 30 /// This unit corresponds to the smallest addressable element of the display hardware. 31 #[derive(Clone, Copy, Debug)] 32 pub enum DevicePixel {} 33 34 /// Represents a mobile style pinch zoom factor. 35 #[derive(Clone, Copy, Debug, PartialEq)] 36 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize, MallocSizeOf))] 37 pub struct PinchZoomFactor(f32); 38 39 impl PinchZoomFactor { 40 /// Construct a new pinch zoom factor. 41 pub fn new(scale: f32) -> PinchZoomFactor { 42 PinchZoomFactor(scale) 43 } 44 45 /// Get the pinch zoom factor as an untyped float. 46 pub fn get(&self) -> f32 { 47 self.0 48 } 49 } 50 51 /// One CSS "px" in the coordinate system of the "initial viewport": 52 /// <http://www.w3.org/TR/css-device-adapt/#initial-viewport> 53 /// 54 /// `CSSPixel` is equal to `DeviceIndependentPixel` times a "page zoom" factor controlled by the user. This is 55 /// the desktop-style "full page" zoom that enlarges content but then reflows the layout viewport 56 /// so it still exactly fits the visible area. 57 /// 58 /// At the default zoom level of 100%, one `CSSPixel` is equal to one `DeviceIndependentPixel`. However, if the 59 /// document is zoomed in or out then this scale may be larger or smaller. 60 #[derive(Clone, Copy, Debug)] 61 pub enum CSSPixel {} 62 63 // In summary, the hierarchy of pixel units and the factors to convert from one to the next: 64 // 65 // DevicePixel 66 // / hidpi_ratio => DeviceIndependentPixel 67 // / desktop_zoom => CSSPixel 68 69 pub mod arc_slice; 70 pub mod dom; 71 pub mod specified_value_info; 72 #[macro_use] 73 pub mod values; 74 pub mod owned_slice; 75 pub mod owned_str; 76 77 pub use crate::specified_value_info::{CssType, KeywordsCollectFn, SpecifiedValueInfo}; 78 pub use crate::values::{ 79 Comma, CommaWithSpace, CssString, CssStringWriter, CssWriter, NumericValue, OneOrMoreSeparated, 80 Separator, Space, ToCss, ToTyped, TypedValue, 81 }; 82 83 /// The error type for all CSS parsing routines. 84 pub type ParseError<'i> = cssparser::ParseError<'i, StyleParseErrorKind<'i>>; 85 86 /// Error in property value parsing 87 pub type ValueParseError<'i> = cssparser::ParseError<'i, ValueParseErrorKind<'i>>; 88 89 #[derive(Clone, Debug, PartialEq)] 90 /// Errors that can be encountered while parsing CSS values. 91 pub enum StyleParseErrorKind<'i> { 92 /// A bad URL token in a DVB. 93 BadUrlInDeclarationValueBlock(CowRcStr<'i>), 94 /// A bad string token in a DVB. 95 BadStringInDeclarationValueBlock(CowRcStr<'i>), 96 /// Unexpected closing parenthesis in a DVB. 97 UnbalancedCloseParenthesisInDeclarationValueBlock, 98 /// Unexpected closing bracket in a DVB. 99 UnbalancedCloseSquareBracketInDeclarationValueBlock, 100 /// Unexpected closing curly bracket in a DVB. 101 UnbalancedCloseCurlyBracketInDeclarationValueBlock, 102 /// A property declaration value had input remaining after successfully parsing. 103 PropertyDeclarationValueNotExhausted, 104 /// An unexpected dimension token was encountered. 105 UnexpectedDimension(CowRcStr<'i>), 106 /// Missing or invalid media feature name. 107 MediaQueryExpectedFeatureName(CowRcStr<'i>), 108 /// Missing or invalid media feature value. 109 MediaQueryExpectedFeatureValue, 110 /// A media feature range operator was not expected. 111 MediaQueryUnexpectedOperator, 112 /// min- or max- properties must have a value. 113 RangedExpressionWithNoValue, 114 /// A function was encountered that was not expected. 115 UnexpectedFunction(CowRcStr<'i>), 116 /// Error encountered parsing a @property's `syntax` descriptor 117 PropertySyntaxField(PropertySyntaxParseError), 118 /// Error encountered parsing a @property's `inherits` descriptor. 119 /// 120 /// TODO(zrhoffman, bug 1920365): Include the custom property name in error messages. 121 PropertyInheritsField(PropertyInheritsParseError), 122 /// @namespace must be before any rule but @charset and @import 123 UnexpectedNamespaceRule, 124 /// @import must be before any rule but @charset 125 UnexpectedImportRule, 126 /// @import rules are disallowed in the parser. 127 DisallowedImportRule, 128 /// Unexpected @charset rule encountered. 129 UnexpectedCharsetRule, 130 /// The @property `<custom-property-name>` must start with `--` 131 UnexpectedIdent(CowRcStr<'i>), 132 /// A placeholder for many sources of errors that require more specific variants. 133 UnspecifiedError, 134 /// An unexpected token was found within a namespace rule. 135 UnexpectedTokenWithinNamespace(Token<'i>), 136 /// An error was encountered while parsing a property value. 137 ValueError(ValueParseErrorKind<'i>), 138 /// An error was encountered while parsing a selector 139 SelectorError(SelectorParseErrorKind<'i>), 140 /// The property declaration was for an unknown property. 141 UnknownProperty(CowRcStr<'i>), 142 /// The property declaration was for a disabled experimental property. 143 ExperimentalProperty, 144 /// The property declaration contained an invalid color value. 145 InvalidColor(CowRcStr<'i>, Token<'i>), 146 /// The property declaration contained an invalid filter value. 147 InvalidFilter(CowRcStr<'i>, Token<'i>), 148 /// The property declaration contained an invalid value. 149 OtherInvalidValue(CowRcStr<'i>), 150 /// `!important` declarations are disallowed in `@position-try` or keyframes. 151 UnexpectedImportantDeclaration, 152 } 153 154 impl<'i> From<ValueParseErrorKind<'i>> for StyleParseErrorKind<'i> { 155 fn from(this: ValueParseErrorKind<'i>) -> Self { 156 StyleParseErrorKind::ValueError(this) 157 } 158 } 159 160 impl<'i> From<SelectorParseErrorKind<'i>> for StyleParseErrorKind<'i> { 161 fn from(this: SelectorParseErrorKind<'i>) -> Self { 162 StyleParseErrorKind::SelectorError(this) 163 } 164 } 165 166 /// Specific errors that can be encountered while parsing property values. 167 #[derive(Clone, Debug, PartialEq)] 168 pub enum ValueParseErrorKind<'i> { 169 /// An invalid token was encountered while parsing a color value. 170 InvalidColor(Token<'i>), 171 /// An invalid filter value was encountered. 172 InvalidFilter(Token<'i>), 173 } 174 175 impl<'i> StyleParseErrorKind<'i> { 176 /// Create an InvalidValue parse error 177 pub fn new_invalid<S>(name: S, value_error: ParseError<'i>) -> ParseError<'i> 178 where 179 S: Into<CowRcStr<'i>>, 180 { 181 let name = name.into(); 182 let variant = match value_error.kind { 183 cssparser::ParseErrorKind::Custom(StyleParseErrorKind::ValueError(e)) => match e { 184 ValueParseErrorKind::InvalidColor(token) => { 185 StyleParseErrorKind::InvalidColor(name, token) 186 }, 187 ValueParseErrorKind::InvalidFilter(token) => { 188 StyleParseErrorKind::InvalidFilter(name, token) 189 }, 190 }, 191 _ => StyleParseErrorKind::OtherInvalidValue(name), 192 }; 193 cssparser::ParseError { 194 kind: cssparser::ParseErrorKind::Custom(variant), 195 location: value_error.location, 196 } 197 } 198 } 199 200 /// Errors that can be encountered while parsing the @property rule's syntax descriptor. 201 #[derive(Clone, Debug, PartialEq)] 202 pub enum PropertySyntaxParseError { 203 /// The syntax descriptor is required for the @property rule to be valid; if it’s missing, the 204 /// @property rule is invalid. 205 /// 206 /// <https://drafts.css-houdini.org/css-properties-values-api-1/#ref-for-descdef-property-syntax②> 207 NoSyntax, 208 /// The string's length was 0. 209 EmptyInput, 210 /// A non-whitespace, non-pipe character was fount after parsing a component. 211 ExpectedPipeBetweenComponents, 212 /// The start of an identifier was expected but not found. 213 /// 214 /// <https://drafts.csswg.org/css-syntax-3/#name-start-code-point> 215 InvalidNameStart, 216 /// The name is not a valid `<ident>`. 217 InvalidName, 218 /// The data type name was not closed. 219 /// 220 /// <https://drafts.css-houdini.org/css-properties-values-api-1/#consume-data-type-name> 221 UnclosedDataTypeName, 222 /// The next byte was expected while parsing, but EOF was found instead. 223 UnexpectedEOF, 224 /// The data type is not a supported syntax component name. 225 /// 226 /// <https://drafts.css-houdini.org/css-properties-values-api-1/#supported-names> 227 UnknownDataTypeName, 228 } 229 230 /// Errors that can be encountered while parsing the @property rule's inherits descriptor. 231 #[derive(Clone, Debug, PartialEq)] 232 pub enum PropertyInheritsParseError { 233 /// The inherits descriptor is required for the @property rule to be valid; if it’s missing, 234 /// the @property rule is invalid. 235 /// 236 /// <https://drafts.css-houdini.org/css-properties-values-api-1/#ref-for-descdef-property-inherits②> 237 NoInherits, 238 239 /// The inherits descriptor must successfully parse as `true` or `false`. 240 InvalidInherits, 241 } 242 243 bitflags! { 244 /// The mode to use when parsing values. 245 #[derive(Clone, Copy, Eq, PartialEq)] 246 #[repr(C)] 247 pub struct ParsingMode: u8 { 248 /// In CSS; lengths must have units, except for zero values, where the unit can be omitted. 249 /// <https://www.w3.org/TR/css3-values/#lengths> 250 const DEFAULT = 0; 251 /// In SVG; a coordinate or length value without a unit identifier (e.g., "25") is assumed 252 /// to be in user units (px). 253 /// <https://www.w3.org/TR/SVG/coords.html#Units> 254 const ALLOW_UNITLESS_LENGTH = 1; 255 /// In SVG; out-of-range values are not treated as an error in parsing. 256 /// <https://www.w3.org/TR/SVG/implnote.html#RangeClamping> 257 const ALLOW_ALL_NUMERIC_VALUES = 1 << 1; 258 /// In CSS Properties and Values, the initial value must be computationally 259 /// independent. 260 /// <https://drafts.css-houdini.org/css-properties-values-api-1/#ref-for-computationally-independent%E2%91%A0> 261 const DISALLOW_COMPUTATIONALLY_DEPENDENT = 1 << 2; 262 } 263 } 264 265 impl ParsingMode { 266 /// Whether the parsing mode allows unitless lengths for non-zero values to be intpreted as px. 267 #[inline] 268 pub fn allows_unitless_lengths(&self) -> bool { 269 self.intersects(ParsingMode::ALLOW_UNITLESS_LENGTH) 270 } 271 272 /// Whether the parsing mode allows all numeric values. 273 #[inline] 274 pub fn allows_all_numeric_values(&self) -> bool { 275 self.intersects(ParsingMode::ALLOW_ALL_NUMERIC_VALUES) 276 } 277 278 /// Whether the parsing mode allows units or functions that are not computationally independent. 279 #[inline] 280 pub fn allows_computational_dependence(&self) -> bool { 281 !self.intersects(ParsingMode::DISALLOW_COMPUTATIONALLY_DEPENDENT) 282 } 283 } 284 285 #[cfg(feature = "servo")] 286 /// Speculatively execute paint code in the worklet thread pool. 287 pub trait SpeculativePainter: Send + Sync { 288 /// <https://drafts.css-houdini.org/css-paint-api/#draw-a-paint-image> 289 fn speculatively_draw_a_paint_image( 290 &self, 291 properties: Vec<(Atom, String)>, 292 arguments: Vec<String>, 293 ); 294 }