diff options
Diffstat (limited to 'servo/components/style_traits/lib.rs')
-rw-r--r-- | servo/components/style_traits/lib.rs | 295 |
1 files changed, 295 insertions, 0 deletions
diff --git a/servo/components/style_traits/lib.rs b/servo/components/style_traits/lib.rs new file mode 100644 index 0000000000..9bb2b3c655 --- /dev/null +++ b/servo/components/style_traits/lib.rs @@ -0,0 +1,295 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +//! This module contains shared types and messages for use by devtools/script. +//! The traits are here instead of in script so that the devtools crate can be +//! modified independently of the rest of Servo. + +#![crate_name = "style_traits"] +#![crate_type = "rlib"] +#![deny(unsafe_code, missing_docs)] + +extern crate app_units; +#[macro_use] +extern crate bitflags; +extern crate cssparser; +extern crate euclid; +#[macro_use] +extern crate lazy_static; +extern crate malloc_size_of; +#[macro_use] +extern crate malloc_size_of_derive; +extern crate nsstring; +extern crate selectors; +#[macro_use] +extern crate serde; +extern crate servo_arc; +#[cfg(feature = "servo")] +extern crate servo_atoms; +#[cfg(feature = "servo")] +extern crate servo_url; +extern crate to_shmem; +#[macro_use] +extern crate to_shmem_derive; +#[cfg(feature = "servo")] +extern crate webrender_api; +#[cfg(feature = "servo")] +pub use webrender_api::units::DevicePixel; + +use cssparser::{CowRcStr, Token}; +use selectors::parser::SelectorParseErrorKind; +#[cfg(feature = "servo")] +use servo_atoms::Atom; + +/// One hardware pixel. +/// +/// This unit corresponds to the smallest addressable element of the display hardware. +#[cfg(not(feature = "servo"))] +#[derive(Clone, Copy, Debug)] +pub enum DevicePixel {} + +/// Represents a mobile style pinch zoom factor. +/// TODO(gw): Once WR supports pinch zoom, use a type directly from webrender_api. +#[derive(Clone, Copy, Debug, PartialEq)] +#[cfg_attr(feature = "servo", derive(Deserialize, Serialize, MallocSizeOf))] +pub struct PinchZoomFactor(f32); + +impl PinchZoomFactor { + /// Construct a new pinch zoom factor. + pub fn new(scale: f32) -> PinchZoomFactor { + PinchZoomFactor(scale) + } + + /// Get the pinch zoom factor as an untyped float. + pub fn get(&self) -> f32 { + self.0 + } +} + +/// One CSS "px" in the coordinate system of the "initial viewport": +/// <http://www.w3.org/TR/css-device-adapt/#initial-viewport> +/// +/// `CSSPixel` is equal to `DeviceIndependentPixel` times a "page zoom" factor controlled by the user. This is +/// the desktop-style "full page" zoom that enlarges content but then reflows the layout viewport +/// so it still exactly fits the visible area. +/// +/// At the default zoom level of 100%, one `CSSPixel` is equal to one `DeviceIndependentPixel`. However, if the +/// document is zoomed in or out then this scale may be larger or smaller. +#[derive(Clone, Copy, Debug)] +pub enum CSSPixel {} + +// In summary, the hierarchy of pixel units and the factors to convert from one to the next: +// +// DevicePixel +// / hidpi_ratio => DeviceIndependentPixel +// / desktop_zoom => CSSPixel + +pub mod arc_slice; +pub mod dom; +pub mod specified_value_info; +#[macro_use] +pub mod values; +pub mod owned_slice; +pub mod owned_str; + +pub use crate::specified_value_info::{CssType, KeywordsCollectFn, SpecifiedValueInfo}; +pub use crate::values::{ + Comma, CommaWithSpace, CssWriter, OneOrMoreSeparated, Separator, Space, ToCss, +}; + +/// The error type for all CSS parsing routines. +pub type ParseError<'i> = cssparser::ParseError<'i, StyleParseErrorKind<'i>>; + +/// Error in property value parsing +pub type ValueParseError<'i> = cssparser::ParseError<'i, ValueParseErrorKind<'i>>; + +#[derive(Clone, Debug, PartialEq)] +/// Errors that can be encountered while parsing CSS values. +pub enum StyleParseErrorKind<'i> { + /// A bad URL token in a DVB. + BadUrlInDeclarationValueBlock(CowRcStr<'i>), + /// A bad string token in a DVB. + BadStringInDeclarationValueBlock(CowRcStr<'i>), + /// Unexpected closing parenthesis in a DVB. + UnbalancedCloseParenthesisInDeclarationValueBlock, + /// Unexpected closing bracket in a DVB. + UnbalancedCloseSquareBracketInDeclarationValueBlock, + /// Unexpected closing curly bracket in a DVB. + UnbalancedCloseCurlyBracketInDeclarationValueBlock, + /// A property declaration value had input remaining after successfully parsing. + PropertyDeclarationValueNotExhausted, + /// An unexpected dimension token was encountered. + UnexpectedDimension(CowRcStr<'i>), + /// Missing or invalid media feature name. + MediaQueryExpectedFeatureName(CowRcStr<'i>), + /// Missing or invalid media feature value. + MediaQueryExpectedFeatureValue, + /// A media feature range operator was not expected. + MediaQueryUnexpectedOperator, + /// min- or max- properties must have a value. + RangedExpressionWithNoValue, + /// A function was encountered that was not expected. + UnexpectedFunction(CowRcStr<'i>), + /// Error encountered parsing a @property's `syntax` descriptor + PropertySyntaxField(PropertySyntaxParseError), + /// @namespace must be before any rule but @charset and @import + UnexpectedNamespaceRule, + /// @import must be before any rule but @charset + UnexpectedImportRule, + /// @import rules are disallowed in the parser. + DisallowedImportRule, + /// Unexpected @charset rule encountered. + UnexpectedCharsetRule, + /// The @property `<custom-property-name>` must start with `--` + UnexpectedIdent(CowRcStr<'i>), + /// A placeholder for many sources of errors that require more specific variants. + UnspecifiedError, + /// An unexpected token was found within a namespace rule. + UnexpectedTokenWithinNamespace(Token<'i>), + /// An error was encountered while parsing a property value. + ValueError(ValueParseErrorKind<'i>), + /// An error was encountered while parsing a selector + SelectorError(SelectorParseErrorKind<'i>), + /// The property declaration was for an unknown property. + UnknownProperty(CowRcStr<'i>), + /// The property declaration was for a disabled experimental property. + ExperimentalProperty, + /// The property declaration contained an invalid color value. + InvalidColor(CowRcStr<'i>, Token<'i>), + /// The property declaration contained an invalid filter value. + InvalidFilter(CowRcStr<'i>, Token<'i>), + /// The property declaration contained an invalid value. + OtherInvalidValue(CowRcStr<'i>), + /// The declaration contained an animation property, and we were parsing + /// this as a keyframe block (so that property should be ignored). + /// + /// See: https://drafts.csswg.org/css-animations/#keyframes + AnimationPropertyInKeyframeBlock, + /// The property is not allowed within a page rule. + NotAllowedInPageRule, +} + +impl<'i> From<ValueParseErrorKind<'i>> for StyleParseErrorKind<'i> { + fn from(this: ValueParseErrorKind<'i>) -> Self { + StyleParseErrorKind::ValueError(this) + } +} + +impl<'i> From<SelectorParseErrorKind<'i>> for StyleParseErrorKind<'i> { + fn from(this: SelectorParseErrorKind<'i>) -> Self { + StyleParseErrorKind::SelectorError(this) + } +} + +/// Specific errors that can be encountered while parsing property values. +#[derive(Clone, Debug, PartialEq)] +pub enum ValueParseErrorKind<'i> { + /// An invalid token was encountered while parsing a color value. + InvalidColor(Token<'i>), + /// An invalid filter value was encountered. + InvalidFilter(Token<'i>), +} + +impl<'i> StyleParseErrorKind<'i> { + /// Create an InvalidValue parse error + pub fn new_invalid<S>(name: S, value_error: ParseError<'i>) -> ParseError<'i> + where + S: Into<CowRcStr<'i>>, + { + let name = name.into(); + let variant = match value_error.kind { + cssparser::ParseErrorKind::Custom(StyleParseErrorKind::ValueError(e)) => match e { + ValueParseErrorKind::InvalidColor(token) => { + StyleParseErrorKind::InvalidColor(name, token) + }, + ValueParseErrorKind::InvalidFilter(token) => { + StyleParseErrorKind::InvalidFilter(name, token) + }, + }, + _ => StyleParseErrorKind::OtherInvalidValue(name), + }; + cssparser::ParseError { + kind: cssparser::ParseErrorKind::Custom(variant), + location: value_error.location, + } + } +} + +/// Errors that can be encountered while parsing the @property rule's syntax descriptor. +#[derive(Clone, Debug, PartialEq)] +pub enum PropertySyntaxParseError { + /// The string's length was 0. + EmptyInput, + /// A non-whitespace, non-pipe character was fount after parsing a component. + ExpectedPipeBetweenComponents, + /// The start of an identifier was expected but not found. + /// + /// <https://drafts.csswg.org/css-syntax-3/#name-start-code-point> + InvalidNameStart, + /// The name is not a valid `<ident>`. + InvalidName, + /// The data type name was not closed. + /// + /// <https://drafts.css-houdini.org/css-properties-values-api-1/#consume-data-type-name> + UnclosedDataTypeName, + /// The next byte was expected while parsing, but EOF was found instead. + UnexpectedEOF, + /// The data type is not a supported syntax component name. + /// + /// <https://drafts.css-houdini.org/css-properties-values-api-1/#supported-names> + UnknownDataTypeName, +} + +bitflags! { + /// The mode to use when parsing values. + #[derive(Clone, Copy, Eq, PartialEq)] + #[repr(C)] + pub struct ParsingMode: u8 { + /// In CSS; lengths must have units, except for zero values, where the unit can be omitted. + /// <https://www.w3.org/TR/css3-values/#lengths> + const DEFAULT = 0; + /// In SVG; a coordinate or length value without a unit identifier (e.g., "25") is assumed + /// to be in user units (px). + /// <https://www.w3.org/TR/SVG/coords.html#Units> + const ALLOW_UNITLESS_LENGTH = 1; + /// In SVG; out-of-range values are not treated as an error in parsing. + /// <https://www.w3.org/TR/SVG/implnote.html#RangeClamping> + const ALLOW_ALL_NUMERIC_VALUES = 1 << 1; + /// In CSS Properties and Values, the initial value must be computationally + /// independent. + /// <https://drafts.css-houdini.org/css-properties-values-api-1/#ref-for-computationally-independent%E2%91%A0> + const DISALLOW_FONT_RELATIVE = 1 << 2; + } +} + +impl ParsingMode { + /// Whether the parsing mode allows unitless lengths for non-zero values to be intpreted as px. + #[inline] + pub fn allows_unitless_lengths(&self) -> bool { + self.intersects(ParsingMode::ALLOW_UNITLESS_LENGTH) + } + + /// Whether the parsing mode allows all numeric values. + #[inline] + pub fn allows_all_numeric_values(&self) -> bool { + self.intersects(ParsingMode::ALLOW_ALL_NUMERIC_VALUES) + } + + /// Whether the parsing mode allows font-relative units. + #[inline] + pub fn allows_font_relative_lengths(&self) -> bool { + !self.intersects(ParsingMode::DISALLOW_FONT_RELATIVE) + } +} + +#[cfg(feature = "servo")] +/// Speculatively execute paint code in the worklet thread pool. +pub trait SpeculativePainter: Send + Sync { + /// <https://drafts.css-houdini.org/css-paint-api/#draw-a-paint-image> + fn speculatively_draw_a_paint_image( + &self, + properties: Vec<(Atom, String)>, + arguments: Vec<String>, + ); +} |