1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
/* 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;
#[cfg(feature = "gecko")]
extern crate nsstring;
extern crate selectors;
#[macro_use]
extern crate serde;
extern crate servo_arc;
#[cfg(feature = "servo")]
extern crate servo_atoms;
extern crate thin_vec;
extern crate to_shmem;
#[macro_use]
extern crate to_shmem_derive;
#[cfg(feature = "servo")]
extern crate url;
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.
#[derive(Clone, Copy, Debug)]
pub enum DevicePixel {}
/// Represents a mobile style pinch zoom factor.
#[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>),
/// `!important` declarations are disallowed in `@position-try` or keyframes.
UnexpectedImportantDeclaration,
}
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>,
);
}