Auto merge of #20708 - emilio:gecko-sync, r=emilio

style: sync changes from mozilla-central.

<!-- Reviewable:start -->
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/20708)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2018-04-29 01:03:40 -04:00 committed by GitHub
commit 02c75ea2d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
95 changed files with 1940 additions and 1068 deletions

2
Cargo.lock generated
View file

@ -997,7 +997,6 @@ dependencies = [
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)",
"cstr 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"malloc_size_of 0.0.1",
@ -3123,6 +3122,7 @@ dependencies = [
"serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_arc 0.1.1",
"servo_atoms 0.0.1",
"servo_url 0.0.1",
"webrender_api 0.57.2 (git+https://github.com/servo/webrender)",
]

View file

@ -66,9 +66,9 @@ use style::servo::restyle_damage::ServoRestyleDamage;
use style::values::{Either, RGBA};
use style::values::computed::Gradient;
use style::values::computed::effects::SimpleShadow;
use style::values::computed::pointing::Cursor;
use style::values::generics::background::BackgroundSize;
use style::values::generics::image::{GradientKind, Image, PaintWorklet};
use style::values::generics::pointing::Cursor;
use style_traits::CSSPixel;
use style_traits::ToCss;
use style_traits::cursor::CursorKind;
@ -2952,11 +2952,11 @@ impl ComputedValuesCursorUtility for ComputedValues {
fn get_cursor(&self, default_cursor: CursorKind) -> Option<CursorKind> {
match (
self.get_pointing().pointer_events,
self.get_pointing().cursor,
&self.get_pointing().cursor,
) {
(PointerEvents::None, _) => None,
(PointerEvents::Auto, Cursor(CursorKind::Auto)) => Some(default_cursor),
(PointerEvents::Auto, Cursor(cursor)) => Some(cursor),
(PointerEvents::Auto, &Cursor { keyword: CursorKind::Auto, .. }) => Some(default_cursor),
(PointerEvents::Auto, &Cursor { keyword, .. }) => Some(keyword),
}
}
}

View file

@ -39,6 +39,7 @@ use std::convert::From;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::iter::{ExactSizeIterator, Iterator};
use std::marker::PhantomData;
use std::mem;
use std::ops::{Deref, DerefMut};
use std::os::raw::c_void;
@ -924,7 +925,7 @@ impl<T: 'static> Arc<T> {
///
/// ArcBorrow lets us deal with borrows of known-refcounted objects
/// without needing to worry about how they're actually stored.
#[derive(Eq, PartialEq)]
#[derive(Debug, Eq, PartialEq)]
pub struct ArcBorrow<'a, T: 'a>(&'a T);
impl<'a, T> Copy for ArcBorrow<'a, T> {}
@ -951,6 +952,10 @@ impl<'a, T> ArcBorrow<'a, T> {
ArcBorrow(r)
}
pub fn ptr_eq(this: &Self, other: &Self) -> bool {
this.0 as *const T == other.0 as *const T
}
#[inline]
pub fn with_arc<F, U>(&self, f: F) -> U
where
@ -971,6 +976,13 @@ impl<'a, T> ArcBorrow<'a, T> {
// Forward the result.
result
}
/// Similar to deref, but uses the lifetime |a| rather than the lifetime of
/// self, which is incompatible with the signature of the Deref trait.
#[inline]
pub fn get(&self) -> &'a T {
self.0
}
}
impl<'a, T> Deref for ArcBorrow<'a, T> {
@ -978,7 +990,127 @@ impl<'a, T> Deref for ArcBorrow<'a, T> {
#[inline]
fn deref(&self) -> &T {
&*self.0
self.0
}
}
/// A tagged union that can represent Arc<A> or Arc<B> while only consuming a
/// single word. The type is also NonZero, and thus can be stored in an Option
/// without increasing size.
///
/// This could probably be extended to support four types if necessary.
pub struct ArcUnion<A: 'static, B: 'static> {
p: NonZeroPtrMut<()>,
phantom_a: PhantomData<&'static A>,
phantom_b: PhantomData<&'static B>,
}
impl<A: PartialEq + 'static, B: PartialEq + 'static> PartialEq for ArcUnion<A, B> {
fn eq(&self, other: &Self) -> bool {
use ArcUnionBorrow::*;
match (self.borrow(), other.borrow()) {
(First(x), First(y)) => x == y,
(Second(x), Second(y)) => x == y,
(_, _) => false,
}
}
}
#[derive(Debug)]
pub enum ArcUnionBorrow<'a, A: 'static, B: 'static> {
First(ArcBorrow<'a, A>),
Second(ArcBorrow<'a, B>),
}
impl<A: 'static, B: 'static> ArcUnion<A, B> {
fn new(ptr: *mut ()) -> Self {
ArcUnion {
p: NonZeroPtrMut::new(ptr),
phantom_a: PhantomData,
phantom_b: PhantomData,
}
}
/// Returns true if the two values are pointer-equal.
pub fn ptr_eq(this: &Self, other: &Self) -> bool {
this.p == other.p
}
/// Returns an enum representing a borrow of either A or B.
pub fn borrow(&self) -> ArcUnionBorrow<A, B> {
if self.is_first() {
let ptr = self.p.ptr() as *const A;
let borrow = unsafe { ArcBorrow::from_ref(&*ptr) };
ArcUnionBorrow::First(borrow)
} else {
let ptr = ((self.p.ptr() as usize) & !0x1) as *const B;
let borrow = unsafe { ArcBorrow::from_ref(&*ptr) };
ArcUnionBorrow::Second(borrow)
}
}
/// Creates an ArcUnion from an instance of the first type.
pub fn from_first(other: Arc<A>) -> Self {
Self::new(Arc::into_raw(other) as *mut _)
}
/// Creates an ArcUnion from an instance of the second type.
pub fn from_second(other: Arc<B>) -> Self {
Self::new(((Arc::into_raw(other) as usize) | 0x1) as *mut _)
}
/// Returns true if this ArcUnion contains the first type.
pub fn is_first(&self) -> bool {
self.p.ptr() as usize & 0x1 == 0
}
/// Returns true if this ArcUnion contains the second type.
pub fn is_second(&self) -> bool {
!self.is_first()
}
/// Returns a borrow of the first type if applicable, otherwise None.
pub fn as_first(&self) -> Option<ArcBorrow<A>> {
match self.borrow() {
ArcUnionBorrow::First(x) => Some(x),
ArcUnionBorrow::Second(_) => None,
}
}
/// Returns a borrow of the second type if applicable, otherwise None.
pub fn as_second(&self) -> Option<ArcBorrow<B>> {
match self.borrow() {
ArcUnionBorrow::First(_) => None,
ArcUnionBorrow::Second(x) => Some(x),
}
}
}
impl<A: 'static, B: 'static> Clone for ArcUnion<A, B> {
fn clone(&self) -> Self {
match self.borrow() {
ArcUnionBorrow::First(x) => ArcUnion::from_first(x.clone_arc()),
ArcUnionBorrow::Second(x) => ArcUnion::from_second(x.clone_arc()),
}
}
}
impl<A: 'static, B: 'static> Drop for ArcUnion<A, B> {
fn drop(&mut self) {
match self.borrow() {
ArcUnionBorrow::First(x) => unsafe {
let _ = Arc::from_raw(&*x);
},
ArcUnionBorrow::Second(x) => unsafe {
let _ = Arc::from_raw(&*x);
},
}
}
}
impl<A: fmt::Debug, B: fmt::Debug> fmt::Debug for ArcUnion<A, B> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&self.borrow(), f)
}
}

View file

@ -116,7 +116,7 @@ impl ApplicableDeclarationBlock {
level: CascadeLevel,
) -> Self {
ApplicableDeclarationBlock {
source: StyleSource::Declarations(declarations),
source: StyleSource::from_declarations(declarations),
bits: ApplicableDeclarationBits::new(0, level, 0),
specificity: 0,
}

View file

@ -94,15 +94,15 @@ impl StylesheetInDocument for GeckoStyleSheet {
}
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
use gecko_bindings::structs::ServoMediaList;
use gecko_bindings::structs::mozilla::dom::MediaList as DomMediaList;
use std::mem;
unsafe {
let servo_media_list = self.raw()._base.mMedia.mRawPtr as *const ServoMediaList;
if servo_media_list.is_null() {
let dom_media_list = self.raw()._base.mMedia.mRawPtr as *const DomMediaList;
if dom_media_list.is_null() {
return None;
}
let raw_list = &*(*servo_media_list).mRawList.mRawPtr;
let raw_list = &*(*dom_media_list).mRawList.mRawPtr;
let list = Locked::<MediaList>::as_arc(mem::transmute(&raw_list));
Some(list.read_with(guard))
}

View file

@ -19,7 +19,7 @@ use style_traits::ParseError;
/// A CSS url() value for gecko.
#[css(function = "url")]
#[derive(Clone, Debug, PartialEq, ToCss)]
#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss)]
pub struct CssUrl {
/// The URL in unresolved string form.
///
@ -121,7 +121,7 @@ impl MallocSizeOf for CssUrl {
}
/// A specified url() value for general usage.
#[derive(Clone, Debug, ToComputedValue, ToCss)]
#[derive(Clone, Debug, SpecifiedValueInfo, ToComputedValue, ToCss)]
pub struct SpecifiedUrl {
/// The specified url value.
pub url: CssUrl,
@ -179,7 +179,7 @@ impl MallocSizeOf for SpecifiedUrl {
/// A specified url() value for image.
///
/// This exists so that we can construct `ImageValue` and reuse it.
#[derive(Clone, Debug, ToComputedValue, ToCss)]
#[derive(Clone, Debug, SpecifiedValueInfo, ToComputedValue, ToCss)]
pub struct SpecifiedImageUrl {
/// The specified url value.
pub url: CssUrl,

View file

@ -20,6 +20,7 @@ use std::fmt::{self, Write};
use std::hash::{Hash, Hasher};
use std::iter::Cloned;
use std::ops::Deref;
use style_traits::SpecifiedValueInfo;
#[macro_use]
#[allow(improper_ctypes, non_camel_case_types, missing_docs)]
@ -415,3 +416,5 @@ impl From<String> for Atom {
}
malloc_size_of_is_0!(Atom);
impl SpecifiedValueInfo for Atom {}

View file

@ -68,8 +68,9 @@ macro_rules! try_match_ident_ignore_ascii_case {
macro_rules! define_keyword_type {
($name:ident, $css:expr) => {
#[allow(missing_docs)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, MallocSizeOf, PartialEq,
ToAnimatedValue, ToAnimatedZero, ToComputedValue, ToCss)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, MallocSizeOf,
PartialEq, SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero,
ToComputedValue, ToCss)]
pub struct $name;
impl fmt::Debug for $name {

View file

@ -164,7 +164,7 @@
% if separator == "Comma":
#[css(comma)]
% endif
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
pub struct SpecifiedValue(
% if not allow_empty:
#[css(iterable)]
@ -396,8 +396,8 @@
pub mod computed_value {
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse)]
#[derive(PartialEq, ToCss)]
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse,
PartialEq, SpecifiedValueInfo, ToCss)]
pub enum T {
% for value in keyword.values_for(product):
${to_camel_case(value)},
@ -408,9 +408,10 @@
}
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, Copy, Debug, Eq, PartialEq, ToCss)]
#[derive(Clone, Copy, Debug, Eq, PartialEq, SpecifiedValueInfo, ToCss)]
pub enum SpecifiedValue {
Keyword(computed_value::T),
#[css(skip)]
System(SystemFont),
}
@ -558,7 +559,8 @@
</%def>
% if extra_specified:
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss)]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq,
SpecifiedValueInfo, ToCss)]
pub enum SpecifiedValue {
${variants(keyword.values_for(product) + extra_specified.split(), bool(extra_specified))}
}
@ -569,7 +571,7 @@
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToCss)]
% if not extra_specified:
#[derive(Parse, ToComputedValue)]
#[derive(Parse, SpecifiedValueInfo, ToComputedValue)]
% endif
pub enum T {
${variants(data.longhands_by_name[name].keyword.values_for(product), not extra_specified)}
@ -617,9 +619,14 @@
% endif
</%def>
<%def name="shorthand(name, sub_properties, derive_serialize=False, **kwargs)">
<%def name="shorthand(name, sub_properties, derive_serialize=False,
derive_value_info=True, **kwargs)">
<%
shorthand = data.declare_shorthand(name, sub_properties.split(), **kwargs)
# mako doesn't accept non-string value in parameters with <% %> form, so
# we have to workaround it this way.
if not isinstance(derive_value_info, bool):
derive_value_info = eval(derive_value_info)
%>
% if shorthand:
/// ${shorthand.spec}
@ -634,8 +641,11 @@
#[allow(unused_imports)]
use style_traits::{ParseError, StyleParseErrorKind};
#[allow(unused_imports)]
use style_traits::{CssWriter, ToCss};
use style_traits::{CssWriter, KeywordsCollectFn, SpecifiedValueInfo, ToCss};
% if derive_value_info:
#[derive(SpecifiedValueInfo)]
% endif
pub struct Longhands {
% for sub_property in shorthand.sub_properties:
pub ${sub_property.ident}:

View file

@ -27,7 +27,7 @@ use smallvec::SmallVec;
use std::{cmp, ptr};
use std::mem::{self, ManuallyDrop};
#[cfg(feature = "gecko")] use hash::FnvHashMap;
use style_traits::ParseError;
use style_traits::{KeywordsCollectFn, ParseError, SpecifiedValueInfo};
use super::ComputedValues;
use values::{CSSFloat, CustomIdent, Either};
use values::animated::{Animate, Procedure, ToAnimatedValue, ToAnimatedZero};
@ -172,6 +172,15 @@ impl From<nsCSSPropertyID> for TransitionProperty {
}
}
impl SpecifiedValueInfo for TransitionProperty {
fn collect_completion_keywords(f: KeywordsCollectFn) {
// `transition-property` can actually accept all properties and
// arbitrary identifiers, but `all` is a special one we'd like
// to list.
f(&["all"]);
}
}
/// Returns true if this nsCSSPropertyID is one of the transitionable properties.
#[cfg(feature = "gecko")]
pub fn nscsspropertyid_is_transitionable(property: nsCSSPropertyID) -> bool {

View file

@ -660,9 +660,21 @@ ${helpers.predefined_type(
products="gecko",
gecko_pref="layout.css.shape-outside.enabled",
animation_value_type="ComputedValue",
flags="APPLIES_TO_FIRST_LETTER",
spec="https://drafts.csswg.org/css-shapes/#shape-image-threshold-property",
)}
${helpers.predefined_type(
"shape-margin",
"NonNegativeLengthOrPercentage",
"computed::NonNegativeLengthOrPercentage::zero()",
products="gecko",
gecko_pref="layout.css.shape-outside.enabled",
animation_value_type="NonNegativeLengthOrPercentage",
flags="APPLIES_TO_FIRST_LETTER",
spec="https://drafts.csswg.org/css-shapes/#shape-margin-property",
)}
${helpers.predefined_type(
"shape-outside",
"basic_shape::FloatAreaShape",

View file

@ -274,6 +274,11 @@ ${helpers.predefined_type("-x-text-zoom",
//! detects that a value has a system font, it will resolve it, and
//! cache it on the ComputedValues. After this, it can be just fetched
//! whenever a font longhand on the same element needs the system font.
//!
//! When a longhand property is holding a SystemFont, it's serialized
//! to an empty string as if its value comes from a shorthand with
//! variable reference. We may want to improve this behavior at some
//! point. See also https://github.com/w3c/csswg-drafts/issues/1586.
use app_units::Au;
use cssparser::{Parser, ToCss};
@ -296,7 +301,8 @@ ${helpers.predefined_type("-x-text-zoom",
kw_cast = """font_variant_caps font_kerning font_variant_position
font_optical_sizing""".split()
%>
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq,
SpecifiedValueInfo, ToCss)]
pub enum SystemFont {
% for font in system_fonts:
${to_camel_case(font)},
@ -444,7 +450,7 @@ ${helpers.predefined_type("-x-text-zoom",
// a lot of code with `if product == gecko` conditionals, we have a
// dummy system font module that does nothing
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, ToCss)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, SpecifiedValueInfo, ToCss)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
/// void enum for system font, can never exist
pub enum SystemFont {}

View file

@ -292,7 +292,6 @@ ${helpers.single_keyword("ruby-position", "over under",
${helpers.single_keyword("text-combine-upright", "none all",
products="gecko", animation_value_type="discrete",
gecko_pref="layout.css.text-combine-upright.enabled",
spec="https://drafts.csswg.org/css-writing-modes-3/#text-combine-upright")}
// SVG 1.1: Section 11 - Painting: Filling, Stroking and Marker Symbols

View file

@ -42,7 +42,8 @@ use selector_parser::PseudoElement;
use selectors::parser::SelectorParseErrorKind;
#[cfg(feature = "servo")] use servo_config::prefs::PREFS;
use shared_lock::StylesheetGuards;
use style_traits::{CssWriter, ParseError, ParsingMode, StyleParseErrorKind, ToCss};
use style_traits::{CssWriter, KeywordsCollectFn, ParseError, ParsingMode};
use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss};
use stylesheets::{CssRuleType, Origin, UrlExtraData};
#[cfg(feature = "servo")] use values::Either;
use values::generics::text::LineHeight;
@ -541,6 +542,43 @@ impl NonCustomPropertyId {
false
}
/// The supported types of this property. The return value should be
/// style_traits::CssType when it can become a bitflags type.
fn supported_types(&self) -> u8 {
const SUPPORTED_TYPES: [u8; ${len(data.longhands) + len(data.shorthands)}] = [
% for prop in data.longhands:
<${prop.specified_type()} as SpecifiedValueInfo>::SUPPORTED_TYPES,
% endfor
% for prop in data.shorthands:
% if prop.name == "all":
0, // 'all' accepts no value other than CSS-wide keywords
% else:
<shorthands::${prop.ident}::Longhands as SpecifiedValueInfo>::SUPPORTED_TYPES,
% endif
% endfor
];
SUPPORTED_TYPES[self.0]
}
/// See PropertyId::collect_property_completion_keywords.
fn collect_property_completion_keywords(&self, f: KeywordsCollectFn) {
const COLLECT_FUNCTIONS: [&Fn(KeywordsCollectFn);
${len(data.longhands) + len(data.shorthands)}] = [
% for prop in data.longhands:
&<${prop.specified_type()} as SpecifiedValueInfo>::collect_completion_keywords,
% endfor
% for prop in data.shorthands:
% if prop.name == "all":
&|_f| {}, // 'all' accepts no value other than CSS-wide keywords
% else:
&<shorthands::${prop.ident}::Longhands as SpecifiedValueInfo>::
collect_completion_keywords,
% endif
% endfor
];
COLLECT_FUNCTIONS[self.0](f);
}
}
impl From<LonghandId> for NonCustomPropertyId {
@ -724,7 +762,8 @@ impl LonghandIdSet {
}
/// An enum to represent a CSS Wide keyword.
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToCss)]
pub enum CSSWideKeyword {
/// The `initial` keyword.
Initial,
@ -1692,6 +1731,18 @@ impl PropertyId {
})
}
/// Returns non-alias NonCustomPropertyId corresponding to this
/// property id.
fn non_custom_non_alias_id(&self) -> Option<NonCustomPropertyId> {
Some(match *self {
PropertyId::Custom(_) => return None,
PropertyId::Shorthand(id) => id.into(),
PropertyId::Longhand(id) => id.into(),
PropertyId::ShorthandAlias(id, _) => id.into(),
PropertyId::LonghandAlias(id, _) => id.into(),
})
}
/// Whether the property is enabled for all content regardless of the
/// stylesheet it was declared on (that is, in practice only checks prefs).
#[inline]
@ -1713,6 +1764,24 @@ impl PropertyId {
};
id.allowed_in(context)
}
/// Whether the property supports the given CSS type.
/// `ty` should a bitflags of constants in style_traits::CssType.
pub fn supports_type(&self, ty: u8) -> bool {
let id = self.non_custom_non_alias_id();
id.map_or(0, |id| id.supported_types()) & ty != 0
}
/// Collect supported starting word of values of this property.
///
/// See style_traits::SpecifiedValueInfo::collect_completion_keywords for more
/// details.
pub fn collect_property_completion_keywords(&self, f: KeywordsCollectFn) {
if let Some(id) = self.non_custom_non_alias_id() {
id.collect_property_completion_keywords(f);
}
CSSWideKeyword::collect_completion_keywords(f);
}
}
/// A declaration using a CSS-wide keyword.
@ -3424,7 +3493,7 @@ where
let source = node.style_source();
let declarations = if source.is_some() {
source.read(cascade_level.guard(guards)).declaration_importance_iter()
source.as_ref().unwrap().read(cascade_level.guard(guards)).declaration_importance_iter()
} else {
// The root node has no style source.
DeclarationImportanceIterator::new(&[], &empty)

View file

@ -140,6 +140,7 @@ pub fn parse_border<'i, 't>(
for prop in ['color', 'style', 'width'])}
${' '.join('border-image-%s' % name
for name in ['outset', 'repeat', 'slice', 'source', 'width'])}"
derive_value_info="False"
spec="https://drafts.csswg.org/css-backgrounds/#border">
pub fn parse_value<'i, 't>(
@ -202,6 +203,17 @@ pub fn parse_border<'i, 't>(
}
}
// Just use the same as border-left. The border shorthand can't accept
// any value that the sub-shorthand couldn't.
<%
border_left = "<::properties::shorthands::border_left::Longhands as SpecifiedValueInfo>"
%>
impl SpecifiedValueInfo for Longhands {
const SUPPORTED_TYPES: u8 = ${border_left}::SUPPORTED_TYPES;
fn collect_completion_keywords(f: KeywordsCollectFn) {
${border_left}::collect_completion_keywords(f);
}
}
</%helpers:shorthand>
<%helpers:shorthand name="border-radius" sub_properties="${' '.join(

View file

@ -19,6 +19,7 @@
${'font-language-override' if product == 'gecko' else ''}
${'font-feature-settings' if product == 'gecko' else ''}
${'font-variation-settings' if product == 'gecko' else ''}"
derive_value_info="False"
spec="https://drafts.csswg.org/css-fonts-3/#propdef-font">
use parser::Parse;
use properties::longhands::{font_family, font_style, font_weight, font_stretch};
@ -258,6 +259,29 @@
}
% endif
}
<%
subprops_for_value_info = ["font_style", "font_weight", "font_stretch",
"font_variant_caps", "font_size", "font_family"]
subprops_for_value_info = [
"<longhands::{}::SpecifiedValue as SpecifiedValueInfo>".format(p)
for p in subprops_for_value_info
]
%>
impl SpecifiedValueInfo for Longhands {
const SUPPORTED_TYPES: u8 = 0
% for p in subprops_for_value_info:
| ${p}::SUPPORTED_TYPES
% endfor
;
fn collect_completion_keywords(f: KeywordsCollectFn) {
% for p in subprops_for_value_info:
${p}::collect_completion_keywords(f);
% endfor
<longhands::system_font::SystemFont as SpecifiedValueInfo>::collect_completion_keywords(f);
}
}
</%helpers:shorthand>
<%helpers:shorthand name="font-variant"

View file

@ -5,7 +5,7 @@
<%namespace name="helpers" file="/helpers.mako.rs" />
<%helpers:shorthand name="outline"
sub_properties="outline-width outline-style outline-color"
sub_properties="outline-color outline-style outline-width"
derive_serialize="True"
spec="https://drafts.csswg.org/css-ui/#propdef-outline">
use properties::longhands::{outline_color, outline_width, outline_style};

View file

@ -8,7 +8,7 @@
use fnv::FnvHashMap;
use logical_geometry::WritingMode;
use properties::{ComputedValues, StyleBuilder};
use rule_tree::{StrongRuleNode, StyleSource};
use rule_tree::StrongRuleNode;
use selector_parser::PseudoElement;
use servo_arc::Arc;
use shared_lock::StylesheetGuards;
@ -97,16 +97,18 @@ impl RuleCache {
mut rule_node: Option<&'r StrongRuleNode>,
) -> Option<&'r StrongRuleNode> {
while let Some(node) = rule_node {
match *node.style_source() {
StyleSource::Declarations(ref decls) => {
match node.style_source() {
Some(s) => match s.as_declarations() {
Some(decls) => {
let cascade_level = node.cascade_level();
let decls = decls.read_with(cascade_level.guard(guards));
if decls.contains_any_reset() {
break;
}
},
StyleSource::None => {},
StyleSource::Style(_) => break,
None => break,
},
None => {},
}
rule_node = node.parent();
}

View file

@ -12,7 +12,7 @@ use gecko::selector_parser::PseudoElement;
#[cfg(feature = "gecko")]
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use properties::{Importance, LonghandIdSet, PropertyDeclarationBlock};
use servo_arc::{Arc, ArcBorrow, NonZeroPtrMut};
use servo_arc::{Arc, ArcBorrow, ArcUnion, ArcUnionBorrow, NonZeroPtrMut};
use shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards};
use smallvec::SmallVec;
use std::io::{self, Write};
@ -89,40 +89,27 @@ impl MallocSizeOf for RuleTree {
/// more debuggability, and also the ability of show those selectors to
/// devtools.
#[derive(Clone, Debug)]
pub enum StyleSource {
/// A style rule stable pointer.
Style(Arc<Locked<StyleRule>>),
/// A declaration block stable pointer.
Declarations(Arc<Locked<PropertyDeclarationBlock>>),
/// Indicates no style source. Used to save an Option wrapper around the stylesource in
/// RuleNode
None,
}
pub struct StyleSource(ArcUnion<Locked<StyleRule>, Locked<PropertyDeclarationBlock>>);
impl PartialEq for StyleSource {
fn eq(&self, other: &Self) -> bool {
self.ptr_equals(other)
ArcUnion::ptr_eq(&self.0, &other.0)
}
}
impl StyleSource {
#[inline]
fn ptr_equals(&self, other: &Self) -> bool {
use self::StyleSource::*;
match (self, other) {
(&Style(ref one), &Style(ref other)) => Arc::ptr_eq(one, other),
(&Declarations(ref one), &Declarations(ref other)) => Arc::ptr_eq(one, other),
(&None, _) | (_, &None) => {
panic!("Should not check for equality between null StyleSource objects")
},
_ => false,
/// Creates a StyleSource from a StyleRule.
pub fn from_rule(rule: Arc<Locked<StyleRule>>) -> Self {
StyleSource(ArcUnion::from_first(rule))
}
/// Creates a StyleSource from a PropertyDeclarationBlock.
pub fn from_declarations(decls: Arc<Locked<PropertyDeclarationBlock>>) -> Self {
StyleSource(ArcUnion::from_second(decls))
}
fn dump<W: Write>(&self, guard: &SharedRwLockReadGuard, writer: &mut W) {
use self::StyleSource::*;
if let Style(ref rule) = *self {
if let Some(ref rule) = self.0.as_first() {
let rule = rule.read_with(guard);
let _ = write!(writer, "{:?}", rule.selectors);
}
@ -134,20 +121,31 @@ impl StyleSource {
/// underlying property declaration block.
#[inline]
pub fn read<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> &'a PropertyDeclarationBlock {
let block = match *self {
StyleSource::Style(ref rule) => &rule.read_with(guard).block,
StyleSource::Declarations(ref block) => block,
StyleSource::None => panic!("Cannot call read on StyleSource::None"),
let block: &Locked<PropertyDeclarationBlock> = match self.0.borrow() {
ArcUnionBorrow::First(ref rule) => &rule.get().read_with(guard).block,
ArcUnionBorrow::Second(ref block) => block.get(),
};
block.read_with(guard)
}
/// Indicates if this StyleSource has a value
pub fn is_some(&self) -> bool {
match *self {
StyleSource::None => false,
_ => true,
/// Indicates if this StyleSource is a style rule.
pub fn is_rule(&self) -> bool {
self.0.is_first()
}
/// Indicates if this StyleSource is a PropertyDeclarationBlock.
pub fn is_declarations(&self) -> bool {
self.0.is_second()
}
/// Returns the style rule if applicable, otherwise None.
pub fn as_rule(&self) -> Option<ArcBorrow<Locked<StyleRule>>> {
self.0.as_first()
}
/// Returns the declaration block if applicable, otherwise None.
pub fn as_declarations(&self) -> Option<ArcBorrow<Locked<PropertyDeclarationBlock>>> {
self.0.as_second()
}
}
@ -248,11 +246,12 @@ impl RuleTree {
last_cascade_order = shadow_cascade_order;
important_inner_shadow.push(SmallVec::new());
}
important_inner_shadow.last_mut().unwrap().push(source.clone())
}
SameTreeAuthorNormal => {
important_same_tree.push(source.clone())
important_inner_shadow
.last_mut()
.unwrap()
.push(source.clone())
},
SameTreeAuthorNormal => important_same_tree.push(source.clone()),
UANormal => important_ua.push(source.clone()),
UserNormal => important_user.push(source.clone()),
StyleAttributeNormal => {
@ -391,7 +390,10 @@ impl RuleTree {
// First walk up until the first less-or-equally specific rule.
let mut children = SmallVec::<[_; 10]>::new();
while current.get().level > level {
children.push((current.get().source.clone(), current.get().level));
children.push((
current.get().source.as_ref().unwrap().clone(),
current.get().level,
));
current = current.parent().unwrap().clone();
}
@ -418,13 +420,14 @@ impl RuleTree {
// also equally valid. This is less likely, and would require an
// in-place mutation of the source, which is, at best, fiddly,
// so let's skip it for now.
let is_here_already = match current.get().source {
StyleSource::Declarations(ref already_here) => {
pdb.with_arc(|arc| Arc::ptr_eq(arc, already_here))
},
_ => unreachable!("Replacing non-declarations style?"),
};
let current_decls = current
.get()
.source
.as_ref()
.unwrap()
.as_declarations()
.expect("Replacing non-declarations style?");
let is_here_already = ArcBorrow::ptr_eq(&pdb, &current_decls);
if is_here_already {
debug!("Picking the fast path in rule replacement");
return None;
@ -447,7 +450,7 @@ impl RuleTree {
if pdb.read_with(level.guard(guards)).any_important() {
current = current.ensure_child(
self.root.downgrade(),
StyleSource::Declarations(pdb.clone_arc()),
StyleSource::from_declarations(pdb.clone_arc()),
level,
);
}
@ -455,7 +458,7 @@ impl RuleTree {
if pdb.read_with(level.guard(guards)).any_normal() {
current = current.ensure_child(
self.root.downgrade(),
StyleSource::Declarations(pdb.clone_arc()),
StyleSource::from_declarations(pdb.clone_arc()),
level,
);
}
@ -491,7 +494,10 @@ impl RuleTree {
let mut children = SmallVec::<[_; 10]>::new();
for node in iter {
if !node.cascade_level().is_animation() {
children.push((node.get().source.clone(), node.cascade_level()));
children.push((
node.get().source.as_ref().unwrap().clone(),
node.cascade_level(),
));
}
last = node;
}
@ -689,7 +695,9 @@ pub struct RuleNode {
/// The actual style source, either coming from a selector in a StyleRule,
/// or a raw property declaration block (like the style attribute).
source: StyleSource,
///
/// None for the root node.
source: Option<StyleSource>,
/// The cascade level this rule is positioned at.
level: CascadeLevel,
@ -775,7 +783,7 @@ impl RuleNode {
RuleNode {
root: Some(root),
parent: Some(parent),
source: source,
source: Some(source),
level: level,
refcount: AtomicUsize::new(1),
first_child: AtomicPtr::new(ptr::null_mut()),
@ -789,7 +797,7 @@ impl RuleNode {
RuleNode {
root: None,
parent: None,
source: StyleSource::None,
source: None,
level: CascadeLevel::UANormal,
refcount: AtomicUsize::new(1),
first_child: AtomicPtr::new(ptr::null_mut()),
@ -884,7 +892,10 @@ impl RuleNode {
}
if self.source.is_some() {
self.source.dump(self.level.guard(guards), writer);
self.source
.as_ref()
.unwrap()
.dump(self.level.guard(guards), writer);
} else {
if indent != 0 {
warn!("How has this happened?");
@ -986,7 +997,7 @@ impl StrongRuleNode {
// WeakRuleNode, and implementing this on WeakRuleNode itself...
for child in self.get().iter_children() {
let child_node = unsafe { &*child.ptr() };
if child_node.level == level && child_node.source.ptr_equals(&source) {
if child_node.level == level && child_node.source.as_ref().unwrap() == &source {
return child.upgrade();
}
last = Some(child);
@ -1026,7 +1037,7 @@ impl StrongRuleNode {
// we accessed `last`.
next = WeakRuleNode::from_ptr(existing);
if unsafe { &*next.ptr() }.source.ptr_equals(&source) {
if unsafe { &*next.ptr() }.source.as_ref().unwrap() == &source {
// That node happens to be for the same style source, use
// that, and let node fall out of scope.
return next.upgrade();
@ -1054,8 +1065,8 @@ impl StrongRuleNode {
/// Get the style source corresponding to this rule node. May return `None`
/// if it's the root node, which means that the node hasn't matched any
/// rules.
pub fn style_source(&self) -> &StyleSource {
&self.get().source
pub fn style_source(&self) -> Option<&StyleSource> {
self.get().source.as_ref()
}
/// The cascade level for this node
@ -1317,6 +1328,8 @@ impl StrongRuleNode {
let source = node.style_source();
let declarations = if source.is_some() {
source
.as_ref()
.unwrap()
.read(node.cascade_level().guard(guards))
.declaration_importance_iter()
} else {
@ -1444,7 +1457,7 @@ impl StrongRuleNode {
.take_while(|node| node.cascade_level() > CascadeLevel::Animations);
let mut result = (LonghandIdSet::new(), false);
for node in iter {
let style = node.style_source();
let style = node.style_source().unwrap();
for (decl, important) in style
.read(node.cascade_level().guard(guards))
.declaration_importance_iter()
@ -1464,33 +1477,6 @@ impl StrongRuleNode {
}
result
}
/// Returns PropertyDeclarationBlock for this node.
/// This function must be called only for animation level node.
fn get_animation_style(&self) -> &Arc<Locked<PropertyDeclarationBlock>> {
debug_assert!(
self.cascade_level().is_animation(),
"The cascade level should be an animation level"
);
match *self.style_source() {
StyleSource::Declarations(ref block) => block,
StyleSource::Style(_) => unreachable!("animating style should not be a style rule"),
StyleSource::None => unreachable!("animating style should not be none"),
}
}
/// Returns SMIL override declaration block if exists.
pub fn get_smil_animation_rule(&self) -> Option<&Arc<Locked<PropertyDeclarationBlock>>> {
if cfg!(feature = "servo") {
// Servo has no knowledge of a SMIL rule, so just avoid looking for it.
return None;
}
self.self_and_ancestors()
.take_while(|node| node.cascade_level() >= CascadeLevel::SMILOverride)
.find(|node| node.cascade_level() == CascadeLevel::SMILOverride)
.map(|node| node.get_animation_style())
}
}
/// An iterator over a rule node and its ancestors.

View file

@ -23,7 +23,7 @@ use values::computed::{Context, ToComputedValue};
///
/// However, this approach is still not necessarily optimal: See
/// <https://bugzilla.mozilla.org/show_bug.cgi?id=1347435#c6>
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize, SpecifiedValueInfo)]
pub struct CssUrl {
/// The original URI. This might be optional since we may insert computed
/// values of images into the cascade directly, and we don't bother to

View file

@ -1523,7 +1523,7 @@ impl Stylist {
// just avoid allocating it and calling `apply_declarations` directly,
// maybe...
let rule_node = self.rule_tree.insert_ordered_rules(iter::once((
StyleSource::Declarations(declarations),
StyleSource::from_declarations(declarations),
CascadeLevel::StyleAttributeNormal,
)));
@ -2177,7 +2177,7 @@ impl CascadeData {
.expect("Expected precomputed declarations for the UA level")
.get_or_insert_with(&pseudo.canonical(), Vec::new)
.push(ApplicableDeclarationBlock::new(
StyleSource::Style(locked.clone()),
StyleSource::from_rule(locked.clone()),
self.rules_source_order,
CascadeLevel::UANormal,
selector.specificity(),
@ -2480,7 +2480,7 @@ impl Rule {
level: CascadeLevel,
shadow_cascade_order: ShadowCascadeOrder,
) -> ApplicableDeclarationBlock {
let source = StyleSource::Style(self.style_rule.clone());
let source = StyleSource::from_rule(self.style_rule.clone());
ApplicableDeclarationBlock::new(source, self.source_order, level, self.specificity(), shadow_cascade_order)
}

View file

@ -916,7 +916,8 @@ pub type NonNegativeLengthOrPercentageOrNormal = Either<NonNegativeLengthOrPerce
/// block-size, and inline-size.
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss)]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq,
SpecifiedValueInfo, ToCss)]
pub enum ExtremumLength {
MozMaxContent,
MozMinContent,

View file

@ -12,8 +12,9 @@ use values::generics::NonNegative;
/// A computed percentage.
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, Default, MallocSizeOf, PartialEq,
PartialOrd, ToAnimatedZero, ToComputedValue)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, Default,
MallocSizeOf, PartialEq, PartialOrd, SpecifiedValueInfo,
ToAnimatedZero, ToComputedValue)]
pub struct Percentage(pub CSSFloat);
impl Percentage {

View file

@ -6,137 +6,16 @@
//!
//! https://drafts.csswg.org/css-ui/#pointing-keyboard
use cssparser::Parser;
use parser::{Parse, ParserContext};
use selectors::parser::SelectorParseErrorKind;
#[cfg(feature = "gecko")]
use std::fmt::{self, Write};
#[cfg(feature = "gecko")]
use style_traits::{CssWriter, ToCss};
use style_traits::ParseError;
use style_traits::cursor::CursorKind;
use values::computed::Number;
use values::computed::color::Color;
use values::generics::pointing::CaretColor as GenericCaretColor;
#[cfg(feature = "gecko")]
use values::specified::url::SpecifiedImageUrl;
/// The computed value for the `cursor` property.
///
/// https://drafts.csswg.org/css-ui/#cursor
pub use values::specified::pointing::Cursor;
#[cfg(feature = "gecko")]
pub use values::specified::pointing::CursorImage;
impl Cursor {
/// Set `cursor` to `auto`
#[cfg(feature = "servo")]
#[inline]
pub fn auto() -> Self {
Cursor(CursorKind::Auto)
}
/// Set `cursor` to `auto`
#[cfg(feature = "gecko")]
#[inline]
pub fn auto() -> Self {
Self {
images: vec![].into_boxed_slice(),
keyword: CursorKind::Auto,
}
}
}
impl Parse for Cursor {
/// cursor: [auto | default | ...]
#[cfg(feature = "servo")]
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
Ok(Cursor(CursorKind::parse(context, input)?))
}
/// cursor: [<url> [<number> <number>]?]# [auto | default | ...]
#[cfg(feature = "gecko")]
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let mut images = vec![];
loop {
match input.try(|input| CursorImage::parse_image(context, input)) {
Ok(image) => images.push(image),
Err(_) => break,
}
input.expect_comma()?;
}
Ok(Self {
images: images.into_boxed_slice(),
keyword: CursorKind::parse(context, input)?,
})
}
}
#[cfg(feature = "gecko")]
impl ToCss for Cursor {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
for url in &*self.images {
url.to_css(dest)?;
dest.write_str(", ")?;
}
self.keyword.to_css(dest)
}
}
impl Parse for CursorKind {
fn parse<'i, 't>(
_context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let location = input.current_source_location();
let ident = input.expect_ident()?;
CursorKind::from_css_keyword(&ident).map_err(|_| {
location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(ident.clone()))
})
}
}
#[cfg(feature = "gecko")]
impl CursorImage {
fn parse_image<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
Ok(Self {
url: SpecifiedImageUrl::parse(context, input)?,
// FIXME(emilio): Should use Number::parse to handle calc() correctly.
hotspot: match input.try(|input| input.expect_number()) {
Ok(number) => Some((number, input.expect_number()?)),
Err(_) => None,
},
})
}
}
#[cfg(feature = "gecko")]
impl ToCss for CursorImage {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
self.url.to_css(dest)?;
if let Some((x, y)) = self.hotspot {
dest.write_str(" ")?;
x.to_css(dest)?;
dest.write_str(" ")?;
y.to_css(dest)?;
}
Ok(())
}
}
use values::computed::url::ComputedImageUrl;
use values::generics::pointing as generics;
/// A computed value for the `caret-color` property.
pub type CaretColor = GenericCaretColor<Color>;
pub type CaretColor = generics::CaretColor<Color>;
/// A computed value for the `cursor` property.
pub type Cursor = generics::Cursor<CursorImage>;
/// A computed value for item of `image cursors`.
pub type CursorImage = generics::CursorImage<ComputedImageUrl, Number>;

View file

@ -15,8 +15,7 @@ use values::generics::text::InitialLetter as GenericInitialLetter;
use values::generics::text::LineHeight as GenericLineHeight;
use values::generics::text::MozTabSize as GenericMozTabSize;
use values::generics::text::Spacing;
use values::specified::text::{TextDecorationLine, TextEmphasisFillMode};
use values::specified::text::{TextEmphasisShapeKeyword, TextOverflowSide};
use values::specified::text::{TextEmphasisFillMode, TextEmphasisShapeKeyword, TextOverflowSide};
pub use values::specified::TextAlignKeyword as TextAlign;
pub use values::specified::TextEmphasisPosition;
@ -79,36 +78,6 @@ impl ToCss for TextOverflow {
}
}
impl ToCss for TextDecorationLine {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
let mut has_any = false;
macro_rules! write_value {
($line:path => $css:expr) => {
if self.contains($line) {
if has_any {
dest.write_str(" ")?;
}
dest.write_str($css)?;
has_any = true;
}
};
}
write_value!(TextDecorationLine::UNDERLINE => "underline");
write_value!(TextDecorationLine::OVERLINE => "overline");
write_value!(TextDecorationLine::LINE_THROUGH => "line-through");
write_value!(TextDecorationLine::BLINK => "blink");
if !has_any {
dest.write_str("none")?;
}
Ok(())
}
}
/// A struct that represents the _used_ value of the text-decoration property.
///
/// FIXME(emilio): This is done at style resolution time, though probably should

View file

@ -5,8 +5,8 @@
//! Generic types for CSS values related to backgrounds.
/// A generic value for the `background-size` property.
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq,
ToComputedValue, ToCss)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
pub enum BackgroundSize<LengthOrPercentageOrAuto> {
/// `<width> <height>`
Explicit {

View file

@ -18,7 +18,8 @@ pub type ClippingShape<BasicShape, Url> = ShapeSource<BasicShape, GeometryBox, U
/// <https://drafts.fxtf.org/css-masking-1/#typedef-geometry-box>
#[allow(missing_docs)]
#[derive(Animate, Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Animate, Clone, Copy, Debug, MallocSizeOf, PartialEq,
SpecifiedValueInfo, ToComputedValue, ToCss)]
pub enum GeometryBox {
FillBox,
StrokeBox,
@ -32,7 +33,8 @@ pub type FloatAreaShape<BasicShape, Image> = ShapeSource<BasicShape, ShapeBox, I
/// https://drafts.csswg.org/css-shapes-1/#typedef-shape-box
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Animate, Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)]
#[derive(Animate, Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq,
SpecifiedValueInfo, ToComputedValue, ToCss)]
pub enum ShapeBox {
MarginBox,
BorderBox,
@ -43,7 +45,8 @@ pub enum ShapeBox {
/// A shape source, for some reference box.
#[allow(missing_docs)]
#[animation(no_bound(ImageOrUrl))]
#[derive(Animate, Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Animate, Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
pub enum ShapeSource<BasicShape, ReferenceBox, ImageOrUrl> {
#[animation(error)]
ImageOrUrl(ImageOrUrl),
@ -55,8 +58,8 @@ pub enum ShapeSource<BasicShape, ReferenceBox, ImageOrUrl> {
}
#[allow(missing_docs)]
#[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq, ToComputedValue,
ToCss)]
#[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq,
SpecifiedValueInfo, ToComputedValue, ToCss)]
pub enum BasicShape<H, V, LengthOrPercentage> {
Inset(#[css(field_bound)] InsetRect<LengthOrPercentage>),
Circle(#[css(field_bound)] Circle<H, V, LengthOrPercentage>),
@ -66,7 +69,9 @@ pub enum BasicShape<H, V, LengthOrPercentage> {
/// <https://drafts.csswg.org/css-shapes/#funcdef-inset>
#[allow(missing_docs)]
#[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
#[css(function = "inset")]
#[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq,
SpecifiedValueInfo, ToComputedValue)]
pub struct InsetRect<LengthOrPercentage> {
pub rect: Rect<LengthOrPercentage>,
pub round: Option<BorderRadius<LengthOrPercentage>>,
@ -74,8 +79,9 @@ pub struct InsetRect<LengthOrPercentage> {
/// <https://drafts.csswg.org/css-shapes/#funcdef-circle>
#[allow(missing_docs)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq,
ToComputedValue)]
#[css(function)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
PartialEq, SpecifiedValueInfo, ToComputedValue)]
pub struct Circle<H, V, LengthOrPercentage> {
pub position: Position<H, V>,
pub radius: ShapeRadius<LengthOrPercentage>,
@ -83,8 +89,9 @@ pub struct Circle<H, V, LengthOrPercentage> {
/// <https://drafts.csswg.org/css-shapes/#funcdef-ellipse>
#[allow(missing_docs)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq,
ToComputedValue)]
#[css(function)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
PartialEq, SpecifiedValueInfo, ToComputedValue)]
pub struct Ellipse<H, V, LengthOrPercentage> {
pub position: Position<H, V>,
pub semiaxis_x: ShapeRadius<LengthOrPercentage>,
@ -93,8 +100,8 @@ pub struct Ellipse<H, V, LengthOrPercentage> {
/// <https://drafts.csswg.org/css-shapes/#typedef-shape-radius>
#[allow(missing_docs)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq,
ToComputedValue, ToCss)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
pub enum ShapeRadius<LengthOrPercentage> {
Length(LengthOrPercentage),
#[animation(error)]
@ -106,7 +113,9 @@ pub enum ShapeRadius<LengthOrPercentage> {
/// A generic type for representing the `polygon()` function
///
/// <https://drafts.csswg.org/css-shapes/#funcdef-polygon>
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
#[css(function)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue)]
pub struct Polygon<LengthOrPercentage> {
/// The filling rule for a polygon.
pub fill: FillRule,
@ -120,7 +129,8 @@ pub struct Polygon<LengthOrPercentage> {
// says that it can also be `inherit`
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq,
SpecifiedValueInfo, ToComputedValue, ToCss)]
pub enum FillRule {
Nonzero,
Evenodd,

View file

@ -10,7 +10,8 @@ use values::generics::rect::Rect;
use values::generics::size::Size;
/// A generic value for a single side of a `border-image-width` property.
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
pub enum BorderImageSideWidth<LengthOrPercentage, Number> {
/// `<length-or-percentage>`
Length(LengthOrPercentage),
@ -21,17 +22,19 @@ pub enum BorderImageSideWidth<LengthOrPercentage, Number> {
}
/// A generic value for the `border-image-slice` property.
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue)]
pub struct BorderImageSlice<NumberOrPercentage> {
/// The offsets.
pub offsets: Rect<NumberOrPercentage>,
/// Whether to fill the middle part.
#[value_info(represents_keyword)]
pub fill: bool,
}
/// A generic value for the `border-*-radius` longhand properties.
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq,
ToComputedValue, ToCss)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
pub struct BorderCornerRadius<L>(#[css(field_bound)] pub Size<L>);
impl<L> BorderCornerRadius<L> {
@ -42,8 +45,9 @@ impl<L> BorderCornerRadius<L> {
}
/// A generic value for the `border-spacing` property.
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq,
ToAnimatedValue, ToAnimatedZero, ToComputedValue, ToCss)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
PartialEq, SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero,
ToComputedValue, ToCss)]
pub struct BorderSpacing<L>(#[css(field_bound)] pub Size<L>);
impl<L> BorderSpacing<L> {
@ -56,8 +60,8 @@ impl<L> BorderSpacing<L> {
/// A generic value for `border-radius`, `outline-radius` and `inset()`.
///
/// <https://drafts.csswg.org/css-backgrounds-3/#border-radius>
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq,
ToComputedValue)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
PartialEq, SpecifiedValueInfo, ToComputedValue)]
pub struct BorderRadius<LengthOrPercentage> {
/// The top left radius.
pub top_left: BorderCornerRadius<LengthOrPercentage>,

View file

@ -7,8 +7,8 @@
use values::animated::ToAnimatedZero;
/// A generic value for the `vertical-align` property.
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq,
ToComputedValue, ToCss)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
pub enum VerticalAlign<LengthOrPercentage> {
/// `baseline`
Baseline,
@ -48,7 +48,8 @@ impl<L> ToAnimatedZero for VerticalAlign<L> {
}
/// https://drafts.csswg.org/css-animations/#animation-iteration-count
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
pub enum AnimationIterationCount<Number> {
/// A `<number>` value.
Number(Number),
@ -57,8 +58,9 @@ pub enum AnimationIterationCount<Number> {
}
/// A generic value for the `perspective` property.
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq,
ToAnimatedValue, ToAnimatedZero, ToComputedValue, ToCss)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
PartialEq, SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero,
ToComputedValue, ToCss)]
pub enum Perspective<NonNegativeLength> {
/// A non-negative length.
Length(NonNegativeLength),

View file

@ -5,8 +5,9 @@
//! Generic types for the column properties.
/// A generic type for `column-count` values.
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq,
ToAnimatedValue, ToAnimatedZero, ToComputedValue, ToCss)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
PartialEq, SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero,
ToComputedValue, ToCss)]
pub enum ColumnCount<PositiveInteger> {
/// A positive integer.
Integer(PositiveInteger),

View file

@ -11,7 +11,8 @@ use style_traits::{CssWriter, ToCss};
use values::CustomIdent;
/// A generic value for the `counter-increment` property.
#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
pub struct CounterIncrement<I>(Counters<I>);
impl<I> CounterIncrement<I> {
@ -32,7 +33,8 @@ impl<I> Deref for CounterIncrement<I> {
}
/// A generic value for the `counter-reset` property.
#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
pub struct CounterReset<I>(Counters<I>);
impl<I> CounterReset<I> {
@ -55,8 +57,9 @@ impl<I> Deref for CounterReset<I> {
/// A generic value for lists of counters.
///
/// Keyword `none` is represented by an empty vector.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
pub struct Counters<I>(Box<[(CustomIdent, I)]>);
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue)]
pub struct Counters<I>(#[css(if_empty = "none")] Box<[(CustomIdent, I)]>);
impl<I> Default for Counters<I> {
#[inline]

View file

@ -10,7 +10,8 @@ use style_traits::values::{CssWriter, SequenceWriter, ToCss};
use values::specified::url::SpecifiedUrl;
/// A generic value for a single `box-shadow`.
#[derive(Animate, Clone, Debug, MallocSizeOf, PartialEq, ToAnimatedValue, ToAnimatedZero)]
#[derive(Animate, Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToAnimatedValue, ToAnimatedZero)]
pub struct BoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength> {
/// The base shadow.
pub base: SimpleShadow<Color, SizeLength, BlurShapeLength>,
@ -18,13 +19,14 @@ pub struct BoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength> {
pub spread: ShapeLength,
/// Whether this is an inset box shadow.
#[animation(constant)]
#[value_info(represents_keyword)]
pub inset: bool,
}
/// A generic value for a single `filter`.
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq, ToAnimatedValue,
ToComputedValue, ToCss)]
#[derive(Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq,
SpecifiedValueInfo, ToAnimatedValue, ToComputedValue, ToCss)]
pub enum Filter<Angle, Factor, Length, DropShadow> {
/// `blur(<length>)`
#[css(function)]
@ -66,8 +68,8 @@ pub enum Filter<Angle, Factor, Length, DropShadow> {
///
/// Contrary to the canonical order from the spec, the color is serialised
/// first, like in Gecko and Webkit.
#[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq, ToAnimatedValue,
ToAnimatedZero, ToCss)]
#[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq,
SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, ToCss)]
pub struct SimpleShadow<Color, SizeLength, ShapeLength> {
/// Color.
pub color: Color,

View file

@ -6,8 +6,9 @@
/// A generic value for the `flex-basis` property.
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, PartialEq, ToAnimatedValue,
ToAnimatedZero, ToComputedValue, ToCss)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, PartialEq,
SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, ToComputedValue,
ToCss)]
pub enum FlexBasis<Width> {
/// `content`
Content,

View file

@ -11,11 +11,13 @@ use num_traits::One;
use parser::{Parse, ParserContext};
use std::fmt::{self, Write};
use std::io::Cursor;
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
use style_traits::{CssWriter, KeywordsCollectFn, ParseError};
use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss};
use values::distance::{ComputeSquaredDistance, SquaredDistance};
/// https://drafts.csswg.org/css-fonts-4/#feature-tag-value
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue)]
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue)]
pub struct FeatureTagValue<Integer> {
/// A four-character tag, packed into a u32 (one byte per character).
pub tag: FontTag,
@ -45,7 +47,8 @@ where
/// Variation setting for a single feature, see:
///
/// https://drafts.csswg.org/css-fonts-4/#font-variation-settings-def
#[derive(Animate, Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Animate, Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
pub struct VariationValue<Number> {
/// A four-character tag, packed into a u32 (one byte per character).
#[animation(constant)]
@ -69,7 +72,8 @@ where
/// A value both for font-variation-settings and font-feature-settings.
#[css(comma)]
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
pub struct FontSettings<T>(#[css(if_empty = "normal", iterable)] pub Box<[T]>);
impl<T> FontSettings<T> {
@ -105,7 +109,8 @@ impl<T: Parse> Parse for FontSettings<T> {
/// https://drafts.csswg.org/css-fonts-4/#font-variation-settings-def
/// https://drafts.csswg.org/css-fonts-4/#descdef-font-face-font-feature-settings
///
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue)]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue)]
pub struct FontTag(pub u32);
impl ToCss for FontTag {
@ -177,20 +182,30 @@ where
}
}
impl<L> SpecifiedValueInfo for KeywordInfo<L> {
fn collect_completion_keywords(f: KeywordsCollectFn) {
<KeywordSize as SpecifiedValueInfo>::collect_completion_keywords(f);
}
}
/// CSS font keywords
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq,
ToAnimatedValue, ToAnimatedZero)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
Parse, PartialEq, SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero,
ToCss)]
#[allow(missing_docs)]
pub enum KeywordSize {
#[css(keyword = "xx-small")]
XXSmall,
XSmall,
Small,
Medium,
Large,
XLarge,
#[css(keyword = "xx-large")]
XXLarge,
// This is not a real font keyword and will not parse
// HTML font-size 7 corresponds to this value
#[css(skip)]
XXXLarge,
}
@ -208,41 +223,18 @@ impl Default for KeywordSize {
}
}
impl ToCss for KeywordSize {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
dest.write_str(match *self {
KeywordSize::XXSmall => "xx-small",
KeywordSize::XSmall => "x-small",
KeywordSize::Small => "small",
KeywordSize::Medium => "medium",
KeywordSize::Large => "large",
KeywordSize::XLarge => "x-large",
KeywordSize::XXLarge => "xx-large",
KeywordSize::XXXLarge => {
debug_assert!(
false,
"We should never serialize specified values set via HTML presentation attributes"
);
"-servo-xxx-large"
},
})
}
}
/// A generic value for the `font-style` property.
///
/// https://drafts.csswg.org/css-fonts-4/#font-style-prop
#[allow(missing_docs)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
PartialEq, ToAnimatedValue, ToAnimatedZero)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
PartialEq, SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero)]
pub enum FontStyle<Angle> {
#[animation(error)]
Normal,
#[animation(error)]
Italic,
#[value_info(starts_with_keyword)]
Oblique(Angle),
}

View file

@ -7,7 +7,8 @@
/// A generic value for scroll snap points.
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, Copy, Debug, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, PartialEq, SpecifiedValueInfo, ToComputedValue,
ToCss)]
pub enum ScrollSnapPoint<LengthOrPercentage> {
/// `none`
None,

View file

@ -18,7 +18,8 @@ use values::specified::grid::parse_line_names;
/// A `<grid-line>` type.
///
/// <https://drafts.csswg.org/css-grid/#typedef-grid-row-start-grid-line>
#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq, ToComputedValue)]
#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue)]
pub struct GridLine<Integer> {
/// Flag to check whether it's a `span` keyword.
pub is_span: bool,
@ -148,7 +149,8 @@ impl Parse for GridLine<specified::Integer> {
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq,
SpecifiedValueInfo, ToComputedValue, ToCss)]
pub enum TrackKeyword {
Auto,
MaxContent,
@ -159,7 +161,8 @@ pub enum TrackKeyword {
/// avoid re-implementing it for the computed type.
///
/// <https://drafts.csswg.org/css-grid/#typedef-track-breadth>
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
pub enum TrackBreadth<L> {
/// The generic type is almost always a non-negative `<length-percentage>`
Breadth(L),
@ -187,7 +190,7 @@ impl<L> TrackBreadth<L> {
/// generic only to avoid code bloat. It only takes `<length-percentage>`
///
/// <https://drafts.csswg.org/css-grid/#typedef-track-size>
#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo)]
pub enum TrackSize<L> {
/// A flexible `<track-breadth>`
Breadth(TrackBreadth<L>),
@ -195,10 +198,12 @@ pub enum TrackSize<L> {
/// and a flexible `<track-breadth>`
///
/// <https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-minmax>
#[css(function)]
Minmax(TrackBreadth<L>, TrackBreadth<L>),
/// A `fit-content` function.
///
/// <https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-fit-content>
#[css(function)]
FitContent(L),
}
@ -378,7 +383,9 @@ impl Parse for RepeatCount<specified::Integer> {
///
/// It can also hold `repeat()` function parameters, which expands into the respective
/// values in its computed form.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue)]
#[css(function = "repeat")]
pub struct TrackRepeat<L, I> {
/// The number of times for the value to be repeated (could also be `auto-fit` or `auto-fill`)
pub count: RepeatCount<I>,
@ -464,7 +471,8 @@ impl<L: Clone> TrackRepeat<L, specified::Integer> {
}
/// Track list values. Can be <track-size> or <track-repeat>
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
pub enum TrackListValue<LengthOrPercentage, Integer> {
/// A <track-size> value.
TrackSize(TrackSize<LengthOrPercentage>),
@ -497,12 +505,13 @@ pub enum TrackListType {
/// A grid `<track-list>` type.
///
/// <https://drafts.csswg.org/css-grid/#typedef-track-list>
#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo)]
pub struct TrackList<LengthOrPercentage, Integer> {
/// The type of this `<track-list>` (auto, explicit or general).
///
/// In order to avoid parsing the same value multiple times, this does a single traversal
/// and arrives at the type of value it has parsed (or bails out gracefully with an error).
#[css(skip)]
pub list_type: TrackListType,
/// A vector of `<track-size> | <track-repeat>` values.
pub values: Vec<TrackListValue<LengthOrPercentage, Integer>>,
@ -569,7 +578,8 @@ impl<L: ToCss, I: ToCss> ToCss for TrackList<L, I> {
///
/// `subgrid [ <line-names> | repeat(<positive-integer> | auto-fill, <line-names>+) ]+`
/// Old spec: https://www.w3.org/TR/2015/WD-css-grid-1-20150917/#typedef-line-name-list
#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq, ToComputedValue)]
#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue)]
pub struct LineNameList {
/// The optional `<line-name-list>`
pub names: Box<[Box<[CustomIdent]>]>,
@ -672,7 +682,8 @@ impl ToCss for LineNameList {
/// Variants for `<grid-template-rows> | <grid-template-columns>`
/// Subgrid deferred to Level 2 spec due to lack of implementation.
/// But it's implemented in gecko, so we have to as well.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
pub enum GridTemplateComponent<L, I> {
/// `none` value.
None,

View file

@ -16,7 +16,7 @@ use values::serialize_atom_identifier;
/// An [image].
///
/// [image]: https://drafts.csswg.org/css-images/#image-values
#[derive(Clone, MallocSizeOf, PartialEq, ToComputedValue)]
#[derive(Clone, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)]
pub enum Image<Gradient, MozImageRect, ImageUrl> {
/// A `<url()>` image.
Url(ImageUrl),
@ -26,6 +26,7 @@ pub enum Image<Gradient, MozImageRect, ImageUrl> {
/// A `-moz-image-rect` image. Also fairly large and rare.
Rect(Box<MozImageRect>),
/// A `-moz-element(# <element-id>)`
#[css(function = "-moz-element")]
Element(Atom),
/// A paint worklet image.
/// <https://drafts.css-houdini.org/css-paint-api/>
@ -144,6 +145,8 @@ pub struct PaintWorklet {
pub arguments: Vec<Arc<custom_properties::SpecifiedValue>>,
}
impl ::style_traits::SpecifiedValueInfo for PaintWorklet { }
impl ToCss for PaintWorklet {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
@ -164,7 +167,8 @@ impl ToCss for PaintWorklet {
/// `-moz-image-rect(<uri>, top, right, bottom, left);`
#[allow(missing_docs)]
#[css(comma, function)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
pub struct MozImageRect<NumberOrPercentage, MozImageRectUrl> {
pub url: MozImageRectUrl,
pub top: NumberOrPercentage,

View file

@ -8,7 +8,8 @@
use counter_style::{parse_counter_style_name, Symbols};
use cssparser::Parser;
use parser::{Parse, ParserContext};
use style_traits::{ParseError, StyleParseErrorKind};
use style_traits::{KeywordsCollectFn, ParseError};
use style_traits::{SpecifiedValueInfo, StyleParseErrorKind};
use super::CustomIdent;
pub mod background;
@ -137,14 +138,32 @@ impl Parse for CounterStyleOrNone {
}
}
impl SpecifiedValueInfo for CounterStyleOrNone {
fn collect_completion_keywords(f: KeywordsCollectFn) {
// XXX The best approach for implementing this is probably
// having a CounterStyleName type wrapping CustomIdent, and
// put the predefined list for that type in counter_style mod.
// But that's a non-trivial change itself, so we use a simpler
// approach here.
macro_rules! predefined {
($($name:expr,)+) => {
f(&["none", "symbols", $($name,)+]);
}
}
include!("../../counter_style/predefined.rs");
}
}
/// A wrapper of Non-negative values.
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq,
PartialOrd, ToAnimatedZero, ToComputedValue, ToCss)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
PartialEq, PartialOrd, SpecifiedValueInfo, ToAnimatedZero,
ToComputedValue, ToCss)]
pub struct NonNegative<T>(pub T);
/// A wrapper of greater-than-or-equal-to-one values.
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq,
PartialOrd, ToAnimatedZero, ToComputedValue, ToCss)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
PartialEq, PartialOrd, SpecifiedValueInfo, ToAnimatedZero,
ToComputedValue, ToCss)]
pub struct GreaterThanOrEqualToOne<T>(pub T);

View file

@ -4,12 +4,79 @@
//! Generic values for pointing properties.
use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss};
use style_traits::cursor::CursorKind;
/// A generic value for the `caret-color` property.
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq,
ToAnimatedValue, ToAnimatedZero, ToComputedValue, ToCss)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
PartialEq, SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero,
ToComputedValue, ToCss)]
pub enum CaretColor<Color> {
/// An explicit color.
Color(Color),
/// The keyword `auto`.
Auto,
}
/// A generic value for the `cursor` property.
///
/// https://drafts.csswg.org/css-ui/#cursor
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue)]
pub struct Cursor<Image> {
/// The parsed images for the cursor.
pub images: Box<[Image]>,
/// The kind of the cursor [default | help | ...].
pub keyword: CursorKind,
}
impl<Image> Cursor<Image> {
/// Set `cursor` to `auto`
#[inline]
pub fn auto() -> Self {
Self {
images: vec![].into_boxed_slice(),
keyword: CursorKind::Auto,
}
}
}
impl<Image: ToCss> ToCss for Cursor<Image> {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
for image in &*self.images {
image.to_css(dest)?;
dest.write_str(", ")?;
}
self.keyword.to_css(dest)
}
}
/// A generic value for item of `image cursors`.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue)]
pub struct CursorImage<ImageUrl, Number> {
/// The url to parse images from.
pub url: ImageUrl,
/// The <x> and <y> coordinates.
pub hotspot: Option<(Number, Number)>,
}
impl<ImageUrl: ToCss, Number: ToCss> ToCss for CursorImage<ImageUrl, Number> {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
self.url.to_css(dest)?;
if let Some((ref x, ref y)) = self.hotspot {
dest.write_str(" ")?;
x.to_css(dest)?;
dest.write_str(" ")?;
y.to_css(dest)?;
}
Ok(())
}
}

View file

@ -6,8 +6,8 @@
//! [`position`](https://drafts.csswg.org/css-backgrounds-3/#position)
/// A generic type for representing a CSS [position](https://drafts.csswg.org/css-values/#position).
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq,
ToAnimatedZero, ToComputedValue)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
PartialEq, SpecifiedValueInfo, ToAnimatedZero, ToComputedValue)]
pub struct Position<H, V> {
/// The horizontal component of position.
pub horizontal: H,
@ -26,8 +26,8 @@ impl<H, V> Position<H, V> {
}
/// A generic value for the `z-index` property.
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq,
ToAnimatedZero, ToComputedValue, ToCss)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
PartialEq, SpecifiedValueInfo, ToAnimatedZero, ToComputedValue, ToCss)]
pub enum ZIndex<Integer> {
/// An integer value.
Integer(Integer),

View file

@ -11,8 +11,8 @@ use style_traits::{CssWriter, ParseError, ToCss};
/// A CSS value made of four components, where its `ToCss` impl will try to
/// serialize as few components as possible, like for example in `border-width`.
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq,
ToComputedValue)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
PartialEq, SpecifiedValueInfo, ToComputedValue)]
pub struct Rect<T>(pub T, pub T, pub T, pub T);
impl<T> Rect<T> {

View file

@ -8,7 +8,7 @@ use cssparser::Parser;
use euclid::Size2D;
use parser::ParserContext;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, ToCss};
use style_traits::{CssWriter, ParseError, SpecifiedValueInfo, ToCss};
use values::animated::ToAnimatedValue;
/// A generic size, for `border-*-radius` longhand properties, or
@ -93,3 +93,7 @@ where
))
}
}
impl<L: SpecifiedValueInfo> SpecifiedValueInfo for Size<L> {
const SUPPORTED_TYPES: u8 = L::SUPPORTED_TYPES;
}

View file

@ -16,8 +16,8 @@ use values::distance::{ComputeSquaredDistance, SquaredDistance};
///
/// <https://www.w3.org/TR/SVG2/painting.html#SpecifyingPaint>
#[animation(no_bound(UrlPaintServer))]
#[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq, ToAnimatedValue,
ToComputedValue, ToCss)]
#[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq,
SpecifiedValueInfo, ToAnimatedValue, ToComputedValue, ToCss)]
pub struct SVGPaint<ColorType, UrlPaintServer> {
/// The paint source
pub kind: SVGPaintKind<ColorType, UrlPaintServer>,
@ -31,8 +31,9 @@ pub struct SVGPaint<ColorType, UrlPaintServer> {
/// to have a fallback, Gecko lets the context
/// properties have a fallback as well.
#[animation(no_bound(UrlPaintServer))]
#[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq, ToAnimatedValue,
ToAnimatedZero, ToComputedValue, ToCss)]
#[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq,
SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, ToComputedValue,
ToCss)]
pub enum SVGPaintKind<ColorType, UrlPaintServer> {
/// `none`
#[animation(error)]
@ -112,8 +113,8 @@ impl<ColorType: Parse, UrlPaintServer: Parse> Parse for SVGPaint<ColorType, UrlP
/// A value of <length> | <percentage> | <number> for svg which allow unitless length.
/// <https://www.w3.org/TR/SVG11/painting.html#StrokeProperties>
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToAnimatedValue, ToAnimatedZero,
ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToAnimatedValue, ToAnimatedZero, ToComputedValue, ToCss)]
pub enum SvgLengthOrPercentageOrNumber<LengthOrPercentage, Number> {
/// <length> | <percentage>
LengthOrPercentage(LengthOrPercentage),
@ -190,8 +191,9 @@ impl<LengthOrPercentageType: Parse, NumberType: Parse> Parse
}
/// An SVG length value supports `context-value` in addition to length.
#[derive(Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, ToAnimatedValue,
ToAnimatedZero, ToComputedValue, ToCss)]
#[derive(Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq,
SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, ToComputedValue,
ToCss)]
pub enum SVGLength<LengthType> {
/// `<length> | <percentage> | <number>`
Length(LengthType),
@ -200,8 +202,8 @@ pub enum SVGLength<LengthType> {
}
/// Generic value for stroke-dasharray.
#[derive(Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq, ToAnimatedValue,
ToComputedValue, ToCss)]
#[derive(Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq,
SpecifiedValueInfo, ToAnimatedValue, ToComputedValue, ToCss)]
pub enum SVGStrokeDashArray<LengthType> {
/// `[ <length> | <percentage> | <number> ]#`
#[css(comma)]
@ -216,8 +218,8 @@ pub enum SVGStrokeDashArray<LengthType> {
/// An SVG opacity value accepts `context-{fill,stroke}-opacity` in
/// addition to opacity value.
#[derive(Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, ToAnimatedZero,
ToComputedValue, ToCss)]
#[derive(Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq,
SpecifiedValueInfo, ToAnimatedZero, ToComputedValue, ToCss)]
pub enum SVGOpacity<OpacityType> {
/// `<opacity-value>`
Opacity(OpacityType),

View file

@ -12,7 +12,8 @@ use values::animated::{Animate, Procedure, ToAnimatedZero};
use values::distance::{ComputeSquaredDistance, SquaredDistance};
/// A generic value for the `initial-letter` property.
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
pub enum InitialLetter<Number, Integer> {
/// `normal`
Normal,
@ -29,7 +30,8 @@ impl<N, I> InitialLetter<N, I> {
}
/// A generic spacing value for the `letter-spacing` and `word-spacing` properties.
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
pub enum Spacing<Value> {
/// `normal`
Normal,
@ -110,8 +112,8 @@ where
}
/// A generic value for the `line-height` property.
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq,
ToAnimatedValue, ToCss)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
PartialEq, SpecifiedValueInfo, ToAnimatedValue, ToCss)]
pub enum LineHeight<Number, LengthOrPercentage> {
/// `normal`
Normal,
@ -140,8 +142,9 @@ impl<N, L> LineHeight<N, L> {
}
/// A generic value for the `-moz-tab-size` property.
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq,
ToAnimatedValue, ToAnimatedZero, ToComputedValue, ToCss)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
PartialEq, SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero,
ToComputedValue, ToCss)]
pub enum MozTabSize<Number, Length> {
/// A number.
Number(Number),

View file

@ -15,7 +15,8 @@ use values::specified::length::LengthOrPercentage as SpecifiedLengthOrPercentage
/// A generic 2D transformation matrix.
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
#[css(comma, function)]
pub struct Matrix<T> {
pub a: T,
@ -29,7 +30,8 @@ pub struct Matrix<T> {
#[allow(missing_docs)]
#[cfg_attr(rustfmt, rustfmt_skip)]
#[css(comma, function = "matrix3d")]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
pub struct Matrix3D<T> {
pub m11: T, pub m12: T, pub m13: T, pub m14: T,
pub m21: T, pub m22: T, pub m23: T, pub m24: T,
@ -64,8 +66,8 @@ impl<T: Into<f64>> From<Matrix3D<T>> for Transform3D<f64> {
}
/// A generic transform origin.
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq,
ToAnimatedZero, ToComputedValue, ToCss)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
PartialEq, SpecifiedValueInfo, ToAnimatedZero, ToComputedValue, ToCss)]
pub struct TransformOrigin<H, V, Depth> {
/// The horizontal origin.
pub horizontal: H,
@ -78,7 +80,9 @@ pub struct TransformOrigin<H, V, Depth> {
/// A generic timing function.
///
/// <https://drafts.csswg.org/css-timing-1/#single-timing-function-production>
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToCss)]
#[value_info(ty = "TIMING_FUNCTION")]
pub enum TimingFunction<Integer, Number> {
/// `linear | ease | ease-in | ease-out | ease-in-out`
Keyword(TimingKeyword),
@ -93,6 +97,7 @@ pub enum TimingFunction<Integer, Number> {
},
/// `step-start | step-end | steps(<integer>, [ start | end ]?)`
#[css(comma, function)]
#[value_info(other_values = "step-start,step-end")]
Steps(Integer, #[css(skip_if = "is_end")] StepPosition),
/// `frames(<integer>)`
#[css(comma, function)]
@ -101,7 +106,8 @@ pub enum TimingFunction<Integer, Number> {
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq,
SpecifiedValueInfo, ToComputedValue, ToCss)]
pub enum TimingKeyword {
Linear,
Ease,
@ -157,7 +163,8 @@ impl TimingKeyword {
}
}
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
/// A single operation in the list of a `transform` value
pub enum TransformOperation<Angle, Number, Length, Integer, LengthOrPercentage> {
/// Represents a 2D 2x3 matrix.
@ -261,7 +268,8 @@ pub enum TransformOperation<Angle, Number, Length, Integer, LengthOrPercentage>
},
}
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
/// A value of the `transform` property
pub struct Transform<T>(#[css(if_empty = "none", iterable)] pub Vec<T>);
@ -554,8 +562,8 @@ pub fn get_normalized_vector_and_angle<T: Zero>(
}
}
#[derive(Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, ToAnimatedZero,
ToComputedValue, ToCss)]
#[derive(Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq,
SpecifiedValueInfo, ToAnimatedZero, ToComputedValue, ToCss)]
/// A value of the `Rotate` property
///
/// <https://drafts.csswg.org/css-transforms-2/#individual-transforms>
@ -568,8 +576,8 @@ pub enum Rotate<Number, Angle> {
Rotate3D(Number, Number, Number, Angle),
}
#[derive(Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, ToAnimatedZero,
ToComputedValue, ToCss)]
#[derive(Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq,
SpecifiedValueInfo, ToAnimatedZero, ToComputedValue, ToCss)]
/// A value of the `Scale` property
///
/// <https://drafts.csswg.org/css-transforms-2/#individual-transforms>
@ -584,8 +592,8 @@ pub enum Scale<Number> {
Scale3D(Number, Number, Number),
}
#[derive(Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq, ToAnimatedZero,
ToComputedValue, ToCss)]
#[derive(Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq,
SpecifiedValueInfo, ToAnimatedZero, ToComputedValue, ToCss)]
/// A value of the `Translate` property
///
/// <https://drafts.csswg.org/css-transforms-2/#individual-transforms>
@ -601,7 +609,8 @@ pub enum Translate<LengthOrPercentage, Length> {
}
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
pub enum TransformStyle {
#[cfg(feature = "servo")]
Auto,

View file

@ -9,8 +9,9 @@ use parser::{Parse, ParserContext};
use style_traits::ParseError;
/// An image url or none, used for example in list-style-image
#[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq, ToAnimatedValue,
ToAnimatedZero, ToComputedValue, ToCss)]
#[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq,
SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, ToComputedValue,
ToCss)]
pub enum UrlOrNone<Url> {
/// `none`
None,

View file

@ -71,7 +71,7 @@ where
/// Convenience void type to disable some properties and values through types.
#[cfg_attr(feature = "servo", derive(Deserialize, MallocSizeOf, Serialize))]
#[derive(Clone, Copy, Debug, PartialEq, ToAnimatedValue, ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, PartialEq, SpecifiedValueInfo, ToAnimatedValue, ToComputedValue, ToCss)]
pub enum Impossible {}
// FIXME(nox): This should be derived but the derive code cannot cope
@ -93,8 +93,9 @@ impl Parse for Impossible {
}
/// A struct representing one of two kinds of values.
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, MallocSizeOf, PartialEq, ToAnimatedValue,
ToAnimatedZero, ToComputedValue, ToCss)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, MallocSizeOf, PartialEq,
SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, ToComputedValue,
ToCss)]
pub enum Either<A, B> {
/// The first value.
First(A),
@ -125,7 +126,8 @@ impl<A: Parse, B: Parse> Parse for Either<A, B> {
}
/// <https://drafts.csswg.org/css-values-4/#custom-idents>
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue)]
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue)]
pub struct CustomIdent(pub Atom);
impl CustomIdent {
@ -160,7 +162,7 @@ impl ToCss for CustomIdent {
}
/// <https://drafts.csswg.org/css-animations/#typedef-keyframes-name>
#[derive(Clone, Debug, MallocSizeOf, ToComputedValue)]
#[derive(Clone, Debug, MallocSizeOf, SpecifiedValueInfo, ToComputedValue)]
pub enum KeyframesName {
/// <custom-ident>
Ident(CustomIdent),

View file

@ -10,7 +10,7 @@ use cssparser::Parser;
use gecko_bindings::structs;
use parser::{Parse, ParserContext};
use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, ToCss};
use style_traits::{CssWriter, KeywordsCollectFn, ParseError, SpecifiedValueInfo, ToCss};
bitflags! {
/// Constants shared by multiple CSS Box Alignment properties
@ -191,6 +191,9 @@ impl ContentDistribution {
input: &mut Parser<'i, 't>,
axis: AxisDirection,
) -> Result<Self, ParseError<'i>> {
// NOTE Please also update the `list_keywords` function below
// when this function is updated.
// Try to parse normal first
if input.try(|i| i.expect_ident_matching("normal")).is_ok() {
return Ok(ContentDistribution::normal());
@ -227,6 +230,19 @@ impl ContentDistribution {
content_position | overflow_position,
))
}
fn list_keywords(f: KeywordsCollectFn, axis: AxisDirection) {
f(&["normal"]);
if axis == AxisDirection::Block {
list_baseline_keywords(f);
}
list_content_distribution_keywords(f);
list_overflow_position_keywords(f);
f(&["start", "end", "flex-start", "flex-end", "center"]);
if axis == AxisDirection::Inline {
f(&["left", "right"]);
}
}
}
/// Value for the `align-content` property.
@ -240,6 +256,8 @@ impl Parse for AlignContent {
_: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
// NOTE Please also update `impl SpecifiedValueInfo` below when
// this function is updated.
Ok(AlignContent(ContentDistribution::parse(
input,
AxisDirection::Block,
@ -247,6 +265,12 @@ impl Parse for AlignContent {
}
}
impl SpecifiedValueInfo for AlignContent {
fn collect_completion_keywords(f: KeywordsCollectFn) {
ContentDistribution::list_keywords(f, AxisDirection::Block);
}
}
#[cfg(feature = "gecko")]
impl From<u16> for AlignContent {
fn from(bits: u16) -> Self {
@ -272,6 +296,8 @@ impl Parse for JustifyContent {
_: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
// NOTE Please also update `impl SpecifiedValueInfo` below when
// this function is updated.
Ok(JustifyContent(ContentDistribution::parse(
input,
AxisDirection::Inline,
@ -279,6 +305,12 @@ impl Parse for JustifyContent {
}
}
impl SpecifiedValueInfo for JustifyContent {
fn collect_completion_keywords(f: KeywordsCollectFn) {
ContentDistribution::list_keywords(f, AxisDirection::Inline);
}
}
#[cfg(feature = "gecko")]
impl From<u16> for JustifyContent {
fn from(bits: u16) -> Self {
@ -319,6 +351,9 @@ impl SelfAlignment {
input: &mut Parser<'i, 't>,
axis: AxisDirection,
) -> Result<Self, ParseError<'i>> {
// NOTE Please also update the `list_keywords` function below
// when this function is updated.
// <baseline-position>
//
// It's weird that this accepts <baseline-position>, but not
@ -339,6 +374,13 @@ impl SelfAlignment {
let self_position = parse_self_position(input, axis)?;
Ok(SelfAlignment(overflow_position | self_position))
}
fn list_keywords(f: KeywordsCollectFn, axis: AxisDirection) {
list_baseline_keywords(f);
list_auto_normal_stretch(f);
list_overflow_position_keywords(f);
list_self_position_keywords(f, axis);
}
}
/// The specified value of the align-self property.
@ -352,6 +394,8 @@ impl Parse for AlignSelf {
_: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
// NOTE Please also update `impl SpecifiedValueInfo` below when
// this function is updated.
Ok(AlignSelf(SelfAlignment::parse(
input,
AxisDirection::Block,
@ -359,6 +403,12 @@ impl Parse for AlignSelf {
}
}
impl SpecifiedValueInfo for AlignSelf {
fn collect_completion_keywords(f: KeywordsCollectFn) {
SelfAlignment::list_keywords(f, AxisDirection::Block);
}
}
impl From<u8> for AlignSelf {
fn from(bits: u8) -> Self {
AlignSelf(SelfAlignment(AlignFlags::from_bits_truncate(bits)))
@ -382,6 +432,8 @@ impl Parse for JustifySelf {
_: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
// NOTE Please also update `impl SpecifiedValueInfo` below when
// this function is updated.
Ok(JustifySelf(SelfAlignment::parse(
input,
AxisDirection::Inline,
@ -389,6 +441,12 @@ impl Parse for JustifySelf {
}
}
impl SpecifiedValueInfo for JustifySelf {
fn collect_completion_keywords(f: KeywordsCollectFn) {
SelfAlignment::list_keywords(f, AxisDirection::Inline);
}
}
impl From<u8> for JustifySelf {
fn from(bits: u8) -> Self {
JustifySelf(SelfAlignment(AlignFlags::from_bits_truncate(bits)))
@ -422,6 +480,9 @@ impl Parse for AlignItems {
_: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
// NOTE Please also update `impl SpecifiedValueInfo` below when
// this function is updated.
// <baseline-position>
if let Ok(baseline) = input.try(parse_baseline) {
return Ok(AlignItems(baseline));
@ -440,6 +501,15 @@ impl Parse for AlignItems {
}
}
impl SpecifiedValueInfo for AlignItems {
fn collect_completion_keywords(f: KeywordsCollectFn) {
list_baseline_keywords(f);
list_normal_stretch(f);
list_overflow_position_keywords(f);
list_self_position_keywords(f, AxisDirection::Block);
}
}
/// Value of the `justify-items` property
///
/// <https://drafts.csswg.org/css-align/#justify-items-property>
@ -465,6 +535,9 @@ impl Parse for JustifyItems {
_: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
// NOTE Please also update `impl SpecifiedValueInfo` below when
// this function is updated.
// <baseline-position>
//
// It's weird that this accepts <baseline-position>, but not
@ -492,10 +565,22 @@ impl Parse for JustifyItems {
}
}
impl SpecifiedValueInfo for JustifyItems {
fn collect_completion_keywords(f: KeywordsCollectFn) {
list_baseline_keywords(f);
list_normal_stretch(f);
list_legacy_keywords(f);
list_overflow_position_keywords(f);
list_self_position_keywords(f, AxisDirection::Inline);
}
}
// auto | normal | stretch
fn parse_auto_normal_stretch<'i, 't>(
input: &mut Parser<'i, 't>,
) -> Result<AlignFlags, ParseError<'i>> {
// NOTE Please also update the `list_auto_normal_stretch` function
// below when this function is updated.
try_match_ident_ignore_ascii_case! { input,
"auto" => Ok(AlignFlags::AUTO),
"normal" => Ok(AlignFlags::NORMAL),
@ -503,16 +588,28 @@ fn parse_auto_normal_stretch<'i, 't>(
}
}
fn list_auto_normal_stretch(f: KeywordsCollectFn) {
f(&["auto", "normal", "stretch"]);
}
// normal | stretch
fn parse_normal_stretch<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
// NOTE Please also update the `list_normal_stretch` function below
// when this function is updated.
try_match_ident_ignore_ascii_case! { input,
"normal" => Ok(AlignFlags::NORMAL),
"stretch" => Ok(AlignFlags::STRETCH),
}
}
fn list_normal_stretch(f: KeywordsCollectFn) {
f(&["normal", "stretch"]);
}
// <baseline-position>
fn parse_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
// NOTE Please also update the `list_baseline_keywords` function
// below when this function is updated.
try_match_ident_ignore_ascii_case! { input,
"baseline" => Ok(AlignFlags::BASELINE),
"first" => {
@ -526,10 +623,16 @@ fn parse_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, Pars
}
}
fn list_baseline_keywords(f: KeywordsCollectFn) {
f(&["baseline", "first baseline", "last baseline"]);
}
// <content-distribution>
fn parse_content_distribution<'i, 't>(
input: &mut Parser<'i, 't>,
) -> Result<AlignFlags, ParseError<'i>> {
// NOTE Please also update the `list_content_distribution_keywords`
// function below when this function is updated.
try_match_ident_ignore_ascii_case! { input,
"stretch" => Ok(AlignFlags::STRETCH),
"space-between" => Ok(AlignFlags::SPACE_BETWEEN),
@ -538,21 +641,33 @@ fn parse_content_distribution<'i, 't>(
}
}
fn list_content_distribution_keywords(f: KeywordsCollectFn) {
f(&["stretch", "space-between", "space-around", "space-evenly"]);
}
// <overflow-position>
fn parse_overflow_position<'i, 't>(
input: &mut Parser<'i, 't>,
) -> Result<AlignFlags, ParseError<'i>> {
// NOTE Please also update the `list_overflow_position_keywords`
// function below when this function is updated.
try_match_ident_ignore_ascii_case! { input,
"safe" => Ok(AlignFlags::SAFE),
"unsafe" => Ok(AlignFlags::UNSAFE),
}
}
fn list_overflow_position_keywords(f: KeywordsCollectFn) {
f(&["safe", "unsafe"]);
}
// <self-position> | left | right in the inline axis.
fn parse_self_position<'i, 't>(
input: &mut Parser<'i, 't>,
axis: AxisDirection,
) -> Result<AlignFlags, ParseError<'i>> {
// NOTE Please also update the `list_self_position_keywords`
// function below when this function is updated.
Ok(try_match_ident_ignore_ascii_case! { input,
"start" => AlignFlags::START,
"end" => AlignFlags::END,
@ -566,9 +681,21 @@ fn parse_self_position<'i, 't>(
})
}
fn list_self_position_keywords(f: KeywordsCollectFn, axis: AxisDirection) {
f(&[
"start", "end", "flex-start", "flex-end",
"center", "self-start", "self-end",
]);
if axis == AxisDirection::Inline {
f(&["left", "right"]);
}
}
fn parse_left_right_center<'i, 't>(
input: &mut Parser<'i, 't>,
) -> Result<AlignFlags, ParseError<'i>> {
// NOTE Please also update the `list_legacy_keywords` function below
// when this function is updated.
Ok(try_match_ident_ignore_ascii_case! { input,
"left" => AlignFlags::LEFT,
"right" => AlignFlags::RIGHT,
@ -578,6 +705,8 @@ fn parse_left_right_center<'i, 't>(
// legacy | [ legacy && [ left | right | center ] ]
fn parse_legacy<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
// NOTE Please also update the `list_legacy_keywords` function below
// when this function is updated.
let flags = try_match_ident_ignore_ascii_case! { input,
"legacy" => {
let flags = input.try(parse_left_right_center)
@ -593,3 +722,7 @@ fn parse_legacy<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseE
input.expect_ident_matching("legacy")?;
Ok(AlignFlags::LEGACY | flags)
}
fn list_legacy_keywords(f: KeywordsCollectFn) {
f(&["legacy", "left", "right", "center"]);
}

View file

@ -7,7 +7,7 @@
use cssparser::{Parser, Token};
use parser::{Parse, ParserContext};
use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, ToCss};
use style_traits::{CssWriter, ParseError, SpecifiedValueInfo, ToCss};
use values::CSSFloat;
use values::computed::{Context, ToComputedValue};
use values::computed::angle::Angle as ComputedAngle;
@ -203,3 +203,5 @@ impl Angle {
}.map_err(|()| input.new_unexpected_token_error(token.clone()))
}
}
impl SpecifiedValueInfo for Angle {}

View file

@ -48,7 +48,8 @@ impl BackgroundSize {
}
/// One of the keywords for `background-repeat`.
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq,
SpecifiedValueInfo, ToComputedValue, ToCss)]
#[allow(missing_docs)]
pub enum BackgroundRepeatKeyword {
Repeat,
@ -60,7 +61,8 @@ pub enum BackgroundRepeatKeyword {
/// The specified value for the `background-repeat` property.
///
/// https://drafts.csswg.org/css-backgrounds/#the-background-repeat
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToCss)]
pub enum BackgroundRepeat {
/// `repeat-x`
RepeatX,

View file

@ -20,7 +20,7 @@ use values::specified::{AllowQuirks, Number, NumberOrPercentage};
use values::specified::length::{Length, LengthOrPercentage, NonNegativeLength};
/// A specified value for a single side of the `border-width` property.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
pub enum BorderSideWidth {
/// `thin`
Thin,
@ -189,7 +189,8 @@ impl Parse for BorderSpacing {
/// A single border-image-repeat keyword.
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss)]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq,
SpecifiedValueInfo, ToCss)]
pub enum BorderImageRepeatKeyword {
Stretch,
Repeat,
@ -200,7 +201,8 @@ pub enum BorderImageRepeatKeyword {
/// The specified value for the `border-image-repeat` property.
///
/// https://drafts.csswg.org/css-backgrounds/#the-border-image-repeat
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue)]
pub struct BorderImageRepeat(pub BorderImageRepeatKeyword, pub BorderImageRepeatKeyword);
impl ToCss for BorderImageRepeat {

View file

@ -10,8 +10,7 @@ use parser::{Parse, ParserContext};
use selectors::parser::SelectorParseErrorKind;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
use values::CustomIdent;
use values::KeyframesName;
use values::{CustomIdent, KeyframesName};
use values::generics::box_::AnimationIterationCount as GenericAnimationIterationCount;
use values::generics::box_::Perspective as GenericPerspective;
use values::generics::box_::VerticalAlign as GenericVerticalAlign;
@ -19,7 +18,8 @@ use values::specified::{AllowQuirks, Number};
use values::specified::length::{LengthOrPercentage, NonNegativeLength};
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq,
SpecifiedValueInfo, ToComputedValue, ToCss)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
/// Defines an elements display type, which consists of
/// the two basic qualities of how an element generates boxes
@ -296,7 +296,9 @@ impl AnimationIterationCount {
}
/// A value for the `animation-name` property.
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue)]
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue)]
#[value_info(other_values = "none")]
pub struct AnimationName(pub Option<KeyframesName>);
impl AnimationName {
@ -339,7 +341,8 @@ impl Parse for AnimationName {
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq,
SpecifiedValueInfo, ToComputedValue, ToCss)]
pub enum ScrollSnapType {
None,
Mandatory,
@ -348,7 +351,8 @@ pub enum ScrollSnapType {
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq,
SpecifiedValueInfo, ToComputedValue, ToCss)]
pub enum OverscrollBehavior {
Auto,
Contain,
@ -357,13 +361,15 @@ pub enum OverscrollBehavior {
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq,
SpecifiedValueInfo, ToComputedValue, ToCss)]
pub enum OverflowClipBox {
PaddingBox,
ContentBox,
}
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
/// Provides a rendering hint to the user agent,
/// stating what kinds of changes the author expects
/// to perform on the element
@ -415,8 +421,9 @@ impl Parse for WillChange {
bitflags! {
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(ToComputedValue)]
#[derive(SpecifiedValueInfo, ToComputedValue)]
/// These constants match Gecko's `NS_STYLE_TOUCH_ACTION_*` constants.
#[value_info(other_values = "auto,none,manipulation,pan-x,pan-y")]
pub struct TouchAction: u8 {
/// `none` variant
const TOUCH_ACTION_NONE = 1 << 0;
@ -515,7 +522,8 @@ pub fn assert_touch_action_matches() {
}
bitflags! {
#[derive(MallocSizeOf, ToComputedValue)]
#[derive(MallocSizeOf, SpecifiedValueInfo, ToComputedValue)]
#[value_info(other_values = "none,strict,layout,style,paint")]
/// Constants for contain: https://drafts.csswg.org/css-contain/#contain-property
pub struct Contain: u8 {
/// `layout` variant, turns on layout containment

View file

@ -9,7 +9,7 @@
use cssparser::{AngleOrNumber, NumberOrPercentage, Parser, Token};
use parser::ParserContext;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
use style_traits::{CssWriter, ParseError, SpecifiedValueInfo, StyleParseErrorKind, ToCss};
use style_traits::values::specified::AllowedNumericType;
use values::{CSSFloat, CSSInteger};
use values::computed;
@ -150,6 +150,8 @@ impl ToCss for CalcLengthOrPercentage {
}
}
impl SpecifiedValueInfo for CalcLengthOrPercentage {}
impl CalcNode {
/// Tries to parse a single element in the expression, that is, a
/// `<length>`, `<angle>`, `<time>`, `<percentage>`, according to

View file

@ -14,7 +14,8 @@ use parser::{Parse, ParserContext};
use properties::longhands::system_colors::SystemColor;
use std::fmt::{self, Write};
use std::io::Write as IoWrite;
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss, ValueParseErrorKind};
use style_traits::{CssType, CssWriter, KeywordsCollectFn, ParseError, StyleParseErrorKind};
use style_traits::{SpecifiedValueInfo, ToCss, ValueParseErrorKind};
use super::AllowQuirks;
use values::computed::{Color as ComputedColor, Context, ToComputedValue};
use values::specified::calc::CalcNode;
@ -394,7 +395,7 @@ impl ToComputedValue for Color {
/// Specified color value, but resolved to just RGBA for computed value
/// with value from color property at the same context.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
pub struct RGBAColor(pub Color);
impl Parse for RGBAColor {
@ -426,10 +427,23 @@ impl From<Color> for RGBAColor {
}
}
impl SpecifiedValueInfo for Color {
const SUPPORTED_TYPES: u8 = CssType::COLOR;
fn collect_completion_keywords(f: KeywordsCollectFn) {
// We are not going to insert all the color names here. Caller and
// devtools should take care of them. XXX Actually, transparent
// should probably be handled that way as well.
// XXX `currentColor` should really be `currentcolor`. But let's
// keep it consistent with the old system for now.
f(&["rgb", "rgba", "hsl", "hsla", "currentColor", "transparent"]);
}
}
/// Specified value for the "color" property, which resolves the `currentcolor`
/// keyword to the parent color instead of self's color.
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, Debug, PartialEq, ToCss)]
#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss)]
pub struct ColorPropertyValue(pub Color);
impl ToComputedValue for ColorPropertyValue {

View file

@ -99,7 +99,8 @@ fn is_decimal(counter_type: &CounterStyleType) -> bool {
/// The specified value for the `content` property.
///
/// https://drafts.csswg.org/css-content/#propdef-content
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
pub enum Content {
/// `normal` reserved keyword.
Normal,
@ -113,7 +114,8 @@ pub enum Content {
}
/// Items for the `content` property.
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
pub enum ContentItem {
/// Literal string content.
String(Box<str>),

View file

@ -35,7 +35,7 @@ pub type Filter = GenericFilter<Angle, Factor, NonNegativeLength, SimpleShadow>;
pub type Filter = GenericFilter<Angle, Factor, NonNegativeLength, Impossible>;
/// A value for the `<factor>` parts in `Filter`.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
pub struct Factor(NumberOrPercentage);
impl Factor {

View file

@ -15,7 +15,9 @@ use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use parser::{Parse, ParserContext};
use properties::longhands::system_font::SystemFont;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
use style_traits::{CssWriter, KeywordsCollectFn, ParseError};
use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss};
use style_traits::values::SequenceWriter;
use values::CustomIdent;
use values::computed::{Angle as ComputedAngle, Percentage as ComputedPercentage};
use values::computed::{font as computed, Context, Length, NonNegativeLength, ToComputedValue};
@ -77,7 +79,7 @@ pub const MAX_FONT_WEIGHT: f32 = 1000.;
/// A specified font-weight value.
///
/// https://drafts.csswg.org/css-fonts-4/#propdef-font-weight
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
pub enum FontWeight {
/// `<font-weight-absolute>`
Absolute(AbsoluteFontWeight),
@ -86,6 +88,7 @@ pub enum FontWeight {
/// Lighter variant
Lighter,
/// System font variant.
#[css(skip)]
System(SystemFont),
}
@ -154,7 +157,7 @@ impl ToComputedValue for FontWeight {
/// An absolute font-weight value for a @font-face rule.
///
/// https://drafts.csswg.org/css-fonts-4/#font-weight-absolute-values
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
pub enum AbsoluteFontWeight {
/// A `<number>`, with the additional constraints specified in:
///
@ -333,10 +336,12 @@ impl SpecifiedFontStyle {
}
/// The specified value of the `font-style` property.
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToCss)]
#[allow(missing_docs)]
pub enum FontStyle {
Specified(SpecifiedFontStyle),
#[css(skip)]
System(SystemFont),
}
@ -378,15 +383,18 @@ impl Parse for FontStyle {
///
/// https://drafts.csswg.org/css-fonts-4/#font-stretch-prop
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToCss)]
pub enum FontStretch {
Stretch(Percentage),
Keyword(FontStretchKeyword),
#[css(skip)]
System(SystemFont),
}
/// A keyword value for `font-stretch`.
#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, ToCss)]
#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo,
ToCss)]
#[allow(missing_docs)]
pub enum FontStretchKeyword {
Normal,
@ -501,7 +509,7 @@ impl ToComputedValue for FontStretch {
}
}
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
/// A specified font-size value
pub enum FontSize {
/// A length; e.g. 10px.
@ -522,6 +530,7 @@ pub enum FontSize {
/// font-size: larger
Larger,
/// Derived from a specified system font.
#[css(skip)]
System(SystemFont),
}
@ -538,6 +547,7 @@ pub enum FontFamily {
#[css(comma)]
Values(#[css(iterable)] FontFamilyList),
/// System font
#[css(skip)]
System(SystemFont),
}
@ -602,6 +612,8 @@ impl Parse for FontFamily {
}
}
impl SpecifiedValueInfo for FontFamily {}
/// `FamilyName::parse` is based on `SingleFontFamily::parse` and not the other way around
/// because we want the former to exclude generic family keywords.
impl Parse for FamilyName {
@ -619,7 +631,7 @@ impl Parse for FamilyName {
}
}
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
/// Preserve the readability of text when font fallback occurs
pub enum FontSizeAdjust {
/// None variant
@ -627,6 +639,7 @@ pub enum FontSizeAdjust {
/// Number variant
Number(Number),
/// system font
#[css(skip)]
System(SystemFont),
}
@ -704,21 +717,6 @@ impl KeywordInfo {
}
}
impl KeywordSize {
/// Parses a keyword size.
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
try_match_ident_ignore_ascii_case! { input,
"xx-small" => Ok(KeywordSize::XXSmall),
"x-small" => Ok(KeywordSize::XSmall),
"small" => Ok(KeywordSize::Small),
"medium" => Ok(KeywordSize::Medium),
"large" => Ok(KeywordSize::Large),
"x-large" => Ok(KeywordSize::XLarge),
"xx-large" => Ok(KeywordSize::XXLarge),
}
}
}
/// This is the ratio applied for font-size: larger
/// and smaller by both Firefox and Chrome
const LARGER_FONT_SIZE_RATIO: f32 = 1.2;
@ -1079,7 +1077,7 @@ bitflags! {
}
}
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
/// Set of variant alternates
pub enum VariantAlternates {
/// Enables display of stylistic alternates
@ -1104,7 +1102,7 @@ pub enum VariantAlternates {
HistoricalForms,
}
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
/// List of Variant Alternates
pub struct VariantAlternatesList(
#[css(if_empty = "normal", iterable)] pub Box<[VariantAlternates]>,
@ -1125,12 +1123,13 @@ impl VariantAlternatesList {
}
}
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
/// Control over the selection of these alternate glyphs
pub enum FontVariantAlternates {
/// Use alternative glyph from value
Value(VariantAlternatesList),
/// Use system font glyph
#[css(skip)]
System(SystemFont),
}
@ -1263,31 +1262,82 @@ impl Parse for FontVariantAlternates {
}
}
bitflags! {
macro_rules! impl_variant_east_asian {
{
$(
$(#[$($meta:tt)+])*
$ident:ident / $css:expr => $gecko:ident = $value:expr,
)+
} => {
bitflags! {
#[derive(MallocSizeOf)]
/// Vairants for east asian variant
pub struct VariantEastAsian: u16 {
/// None of the features
const NORMAL = 0;
/// Enables rendering of JIS78 forms (OpenType feature: jp78)
const JIS78 = 0x01;
/// Enables rendering of JIS83 forms (OpenType feature: jp83).
const JIS83 = 0x02;
/// Enables rendering of JIS90 forms (OpenType feature: jp90).
const JIS90 = 0x04;
/// Enables rendering of JIS2004 forms (OpenType feature: jp04).
const JIS04 = 0x08;
/// Enables rendering of simplified forms (OpenType feature: smpl).
const SIMPLIFIED = 0x10;
/// Enables rendering of traditional forms (OpenType feature: trad).
const TRADITIONAL = 0x20;
/// Enables rendering of full-width variants (OpenType feature: fwid).
const FULL_WIDTH = 0x40;
/// Enables rendering of proportionally-spaced variants (OpenType feature: pwid).
const PROPORTIONAL_WIDTH = 0x80;
/// Enables display of ruby variant glyphs (OpenType feature: ruby).
const RUBY = 0x100;
$(
$(#[$($meta)+])*
const $ident = $value;
)+
}
}
impl ToCss for VariantEastAsian {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
if self.is_empty() {
return dest.write_str("normal");
}
let mut writer = SequenceWriter::new(dest, " ");
$(
if self.intersects(VariantEastAsian::$ident) {
writer.raw_item($css)?;
}
)+
Ok(())
}
}
/// Asserts that all variant-east-asian matches its NS_FONT_VARIANT_EAST_ASIAN_* value.
#[cfg(feature = "gecko")]
#[inline]
pub fn assert_variant_east_asian_matches() {
use gecko_bindings::structs;
$(
debug_assert_eq!(structs::$gecko as u16, VariantEastAsian::$ident.bits());
)+
}
impl SpecifiedValueInfo for VariantEastAsian {
fn collect_completion_keywords(f: KeywordsCollectFn) {
f(&["normal", $($css,)+]);
}
}
}
}
impl_variant_east_asian! {
/// Enables rendering of JIS78 forms (OpenType feature: jp78)
JIS78 / "jis78" => NS_FONT_VARIANT_EAST_ASIAN_JIS78 = 0x01,
/// Enables rendering of JIS83 forms (OpenType feature: jp83).
JIS83 / "jis83" => NS_FONT_VARIANT_EAST_ASIAN_JIS83 = 0x02,
/// Enables rendering of JIS90 forms (OpenType feature: jp90).
JIS90 / "jis90" => NS_FONT_VARIANT_EAST_ASIAN_JIS90 = 0x04,
/// Enables rendering of JIS2004 forms (OpenType feature: jp04).
JIS04 / "jis04" => NS_FONT_VARIANT_EAST_ASIAN_JIS04 = 0x08,
/// Enables rendering of simplified forms (OpenType feature: smpl).
SIMPLIFIED / "simplified" => NS_FONT_VARIANT_EAST_ASIAN_SIMPLIFIED = 0x10,
/// Enables rendering of traditional forms (OpenType feature: trad).
TRADITIONAL / "traditional" => NS_FONT_VARIANT_EAST_ASIAN_TRADITIONAL = 0x20,
/// Enables rendering of full-width variants (OpenType feature: fwid).
FULL_WIDTH / "full-width" => NS_FONT_VARIANT_EAST_ASIAN_FULL_WIDTH = 0x40,
/// Enables rendering of proportionally-spaced variants (OpenType feature: pwid).
PROPORTIONAL_WIDTH / "proportional-width" => NS_FONT_VARIANT_EAST_ASIAN_PROP_WIDTH = 0x80,
/// Enables display of ruby variant glyphs (OpenType feature: ruby).
RUBY / "ruby" => NS_FONT_VARIANT_EAST_ASIAN_RUBY = 0x100,
}
#[cfg(feature = "gecko")]
@ -1305,83 +1355,17 @@ impl VariantEastAsian {
}
}
impl ToCss for VariantEastAsian {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
if self.is_empty() {
return dest.write_str("normal");
}
let mut has_any = false;
macro_rules! write_value {
($ident:path => $str:expr) => {
if self.intersects($ident) {
if has_any {
dest.write_str(" ")?;
}
has_any = true;
dest.write_str($str)?;
}
};
}
write_value!(VariantEastAsian::JIS78 => "jis78");
write_value!(VariantEastAsian::JIS83 => "jis83");
write_value!(VariantEastAsian::JIS90 => "jis90");
write_value!(VariantEastAsian::JIS04 => "jis04");
write_value!(VariantEastAsian::SIMPLIFIED => "simplified");
write_value!(VariantEastAsian::TRADITIONAL => "traditional");
write_value!(VariantEastAsian::FULL_WIDTH => "full-width");
write_value!(VariantEastAsian::PROPORTIONAL_WIDTH => "proportional-width");
write_value!(VariantEastAsian::RUBY => "ruby");
debug_assert!(has_any);
Ok(())
}
}
#[cfg(feature = "gecko")]
impl_gecko_keyword_conversions!(VariantEastAsian, u16);
/// Asserts that all variant-east-asian matches its NS_FONT_VARIANT_EAST_ASIAN_* value.
#[cfg(feature = "gecko")]
#[inline]
pub fn assert_variant_east_asian_matches() {
use gecko_bindings::structs;
macro_rules! check_variant_east_asian {
( $( $a:ident => $b:path),*, ) => {
if cfg!(debug_assertions) {
$(
assert_eq!(structs::$a as u16, $b.bits());
)*
}
}
}
check_variant_east_asian! {
NS_FONT_VARIANT_EAST_ASIAN_FULL_WIDTH => VariantEastAsian::FULL_WIDTH,
NS_FONT_VARIANT_EAST_ASIAN_JIS04 => VariantEastAsian::JIS04,
NS_FONT_VARIANT_EAST_ASIAN_JIS78 => VariantEastAsian::JIS78,
NS_FONT_VARIANT_EAST_ASIAN_JIS83 => VariantEastAsian::JIS83,
NS_FONT_VARIANT_EAST_ASIAN_JIS90 => VariantEastAsian::JIS90,
NS_FONT_VARIANT_EAST_ASIAN_PROP_WIDTH => VariantEastAsian::PROPORTIONAL_WIDTH,
NS_FONT_VARIANT_EAST_ASIAN_RUBY => VariantEastAsian::RUBY,
NS_FONT_VARIANT_EAST_ASIAN_SIMPLIFIED => VariantEastAsian::SIMPLIFIED,
NS_FONT_VARIANT_EAST_ASIAN_TRADITIONAL => VariantEastAsian::TRADITIONAL,
}
}
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, Debug, PartialEq, ToCss)]
#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss)]
/// Allows control of glyph substitution and sizing in East Asian text.
pub enum FontVariantEastAsian {
/// Value variant with `variant-east-asian`
Value(VariantEastAsian),
/// System font variant
#[css(skip)]
System(SystemFont),
}
@ -1485,32 +1469,86 @@ impl Parse for FontVariantEastAsian {
}
}
bitflags! {
macro_rules! impl_variant_ligatures {
{
$(
$(#[$($meta:tt)+])*
$ident:ident / $css:expr => $gecko:ident = $value:expr,
)+
} => {
bitflags! {
#[derive(MallocSizeOf)]
/// Variants of ligatures
pub struct VariantLigatures: u16 {
/// Specifies that common default features are enabled
const NORMAL = 0;
$(
$(#[$($meta)+])*
const $ident = $value;
)+
}
}
impl ToCss for VariantLigatures {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
if self.is_empty() {
return dest.write_str("normal");
}
if self.contains(VariantLigatures::NONE) {
return dest.write_str("none");
}
let mut writer = SequenceWriter::new(dest, " ");
$(
if self.intersects(VariantLigatures::$ident) {
writer.raw_item($css)?;
}
)+
Ok(())
}
}
/// Asserts that all variant-east-asian matches its NS_FONT_VARIANT_EAST_ASIAN_* value.
#[cfg(feature = "gecko")]
#[inline]
pub fn assert_variant_ligatures_matches() {
use gecko_bindings::structs;
$(
debug_assert_eq!(structs::$gecko as u16, VariantLigatures::$ident.bits());
)+
}
impl SpecifiedValueInfo for VariantLigatures {
fn collect_completion_keywords(f: KeywordsCollectFn) {
f(&["normal", $($css,)+]);
}
}
}
}
impl_variant_ligatures! {
/// Specifies that all types of ligatures and contextual forms
/// covered by this property are explicitly disabled
const NONE = 0x01;
NONE / "none" => NS_FONT_VARIANT_LIGATURES_NONE = 0x01,
/// Enables display of common ligatures
const COMMON_LIGATURES = 0x02;
COMMON_LIGATURES / "common-ligatures" => NS_FONT_VARIANT_LIGATURES_COMMON = 0x02,
/// Disables display of common ligatures
const NO_COMMON_LIGATURES = 0x04;
NO_COMMON_LIGATURES / "no-common-ligatures" => NS_FONT_VARIANT_LIGATURES_NO_COMMON = 0x04,
/// Enables display of discretionary ligatures
const DISCRETIONARY_LIGATURES = 0x08;
DISCRETIONARY_LIGATURES / "discretionary-ligatures" => NS_FONT_VARIANT_LIGATURES_DISCRETIONARY = 0x08,
/// Disables display of discretionary ligatures
const NO_DISCRETIONARY_LIGATURES = 0x10;
NO_DISCRETIONARY_LIGATURES / "no-discretionary-ligatures" => NS_FONT_VARIANT_LIGATURES_NO_DISCRETIONARY = 0x10,
/// Enables display of historical ligatures
const HISTORICAL_LIGATURES = 0x20;
HISTORICAL_LIGATURES / "historical-ligatures" => NS_FONT_VARIANT_LIGATURES_HISTORICAL = 0x20,
/// Disables display of historical ligatures
const NO_HISTORICAL_LIGATURES = 0x40;
NO_HISTORICAL_LIGATURES / "no-historical-ligatures" => NS_FONT_VARIANT_LIGATURES_NO_HISTORICAL = 0x40,
/// Enables display of contextual alternates
const CONTEXTUAL = 0x80;
CONTEXTUAL / "contextual" => NS_FONT_VARIANT_LIGATURES_CONTEXTUAL = 0x80,
/// Disables display of contextual alternates
const NO_CONTEXTUAL = 0x100;
}
NO_CONTEXTUAL / "no-contextual" => NS_FONT_VARIANT_LIGATURES_NO_CONTEXTUAL = 0x100,
}
#[cfg(feature = "gecko")]
@ -1528,86 +1566,18 @@ impl VariantLigatures {
}
}
impl ToCss for VariantLigatures {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
if self.is_empty() {
return dest.write_str("normal");
}
if self.contains(VariantLigatures::NONE) {
return dest.write_str("none");
}
let mut has_any = false;
macro_rules! write_value {
($ident:path => $str:expr) => {
if self.intersects($ident) {
if has_any {
dest.write_str(" ")?;
}
has_any = true;
dest.write_str($str)?;
}
};
}
write_value!(VariantLigatures::COMMON_LIGATURES => "common-ligatures");
write_value!(VariantLigatures::NO_COMMON_LIGATURES => "no-common-ligatures");
write_value!(VariantLigatures::DISCRETIONARY_LIGATURES => "discretionary-ligatures");
write_value!(VariantLigatures::NO_DISCRETIONARY_LIGATURES => "no-discretionary-ligatures");
write_value!(VariantLigatures::HISTORICAL_LIGATURES => "historical-ligatures");
write_value!(VariantLigatures::NO_HISTORICAL_LIGATURES => "no-historical-ligatures");
write_value!(VariantLigatures::CONTEXTUAL => "contextual");
write_value!(VariantLigatures::NO_CONTEXTUAL => "no-contextual");
debug_assert!(has_any);
Ok(())
}
}
#[cfg(feature = "gecko")]
impl_gecko_keyword_conversions!(VariantLigatures, u16);
/// Asserts that all variant-east-asian matches its NS_FONT_VARIANT_EAST_ASIAN_* value.
#[cfg(feature = "gecko")]
#[inline]
pub fn assert_variant_ligatures_matches() {
use gecko_bindings::structs;
macro_rules! check_variant_ligatures {
( $( $a:ident => $b:path),*, ) => {
if cfg!(debug_assertions) {
$(
assert_eq!(structs::$a as u16, $b.bits());
)*
}
}
}
check_variant_ligatures! {
NS_FONT_VARIANT_LIGATURES_NONE => VariantLigatures::NONE,
NS_FONT_VARIANT_LIGATURES_COMMON => VariantLigatures::COMMON_LIGATURES,
NS_FONT_VARIANT_LIGATURES_NO_COMMON => VariantLigatures::NO_COMMON_LIGATURES,
NS_FONT_VARIANT_LIGATURES_DISCRETIONARY => VariantLigatures::DISCRETIONARY_LIGATURES,
NS_FONT_VARIANT_LIGATURES_NO_DISCRETIONARY => VariantLigatures::NO_DISCRETIONARY_LIGATURES,
NS_FONT_VARIANT_LIGATURES_HISTORICAL => VariantLigatures::HISTORICAL_LIGATURES,
NS_FONT_VARIANT_LIGATURES_NO_HISTORICAL => VariantLigatures::NO_HISTORICAL_LIGATURES,
NS_FONT_VARIANT_LIGATURES_CONTEXTUAL => VariantLigatures::CONTEXTUAL,
NS_FONT_VARIANT_LIGATURES_NO_CONTEXTUAL => VariantLigatures::NO_CONTEXTUAL,
}
}
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, Debug, PartialEq, ToCss)]
#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss)]
/// Ligatures and contextual forms are ways of combining glyphs
/// to produce more harmonized forms
pub enum FontVariantLigatures {
/// Value variant with `variant-ligatures`
Value(VariantLigatures),
/// System font variant
#[css(skip)]
System(SystemFont),
}
@ -1721,29 +1691,80 @@ impl Parse for FontVariantLigatures {
}
}
bitflags! {
macro_rules! impl_variant_numeric {
{
$(
$(#[$($meta:tt)+])*
$ident:ident / $css:expr => $gecko:ident = $value:expr,
)+
} => {
bitflags! {
#[derive(MallocSizeOf)]
/// Vairants of numeric values
pub struct VariantNumeric: u8 {
/// None of other variants are enabled.
const NORMAL = 0;
/// Enables display of lining numerals.
const LINING_NUMS = 0x01;
/// Enables display of old-style numerals.
const OLDSTYLE_NUMS = 0x02;
/// Enables display of proportional numerals.
const PROPORTIONAL_NUMS = 0x04;
/// Enables display of tabular numerals.
const TABULAR_NUMS = 0x08;
/// Enables display of lining diagonal fractions.
const DIAGONAL_FRACTIONS = 0x10;
/// Enables display of lining stacked fractions.
const STACKED_FRACTIONS = 0x20;
/// Enables display of letter forms used with ordinal numbers.
const ORDINAL = 0x80;
/// Enables display of slashed zeros.
const SLASHED_ZERO = 0x40;
$(
$(#[$($meta)+])*
const $ident = $value;
)+
}
}
impl ToCss for VariantNumeric {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
if self.is_empty() {
return dest.write_str("normal");
}
let mut writer = SequenceWriter::new(dest, " ");
$(
if self.intersects(VariantNumeric::$ident) {
writer.raw_item($css)?;
}
)+
Ok(())
}
}
/// Asserts that all variant-east-asian matches its NS_FONT_VARIANT_EAST_ASIAN_* value.
#[cfg(feature = "gecko")]
#[inline]
pub fn assert_variant_numeric_matches() {
use gecko_bindings::structs;
$(
debug_assert_eq!(structs::$gecko as u8, VariantNumeric::$ident.bits());
)+
}
impl SpecifiedValueInfo for VariantNumeric {
fn collect_completion_keywords(f: KeywordsCollectFn) {
f(&["normal", $($css,)+]);
}
}
}
}
impl_variant_numeric! {
/// Enables display of lining numerals.
LINING_NUMS / "lining-nums" => NS_FONT_VARIANT_NUMERIC_LINING = 0x01,
/// Enables display of old-style numerals.
OLDSTYLE_NUMS / "oldstyle-nums" => NS_FONT_VARIANT_NUMERIC_OLDSTYLE = 0x02,
/// Enables display of proportional numerals.
PROPORTIONAL_NUMS / "proportional-nums" => NS_FONT_VARIANT_NUMERIC_PROPORTIONAL = 0x04,
/// Enables display of tabular numerals.
TABULAR_NUMS / "tabular-nums" => NS_FONT_VARIANT_NUMERIC_TABULAR = 0x08,
/// Enables display of lining diagonal fractions.
DIAGONAL_FRACTIONS / "diagonal-fractions" => NS_FONT_VARIANT_NUMERIC_DIAGONAL_FRACTIONS = 0x10,
/// Enables display of lining stacked fractions.
STACKED_FRACTIONS / "stacked-fractions" => NS_FONT_VARIANT_NUMERIC_STACKED_FRACTIONS = 0x20,
/// Enables display of letter forms used with ordinal numbers.
ORDINAL / "ordinal" => NS_FONT_VARIANT_NUMERIC_ORDINAL = 0x80,
/// Enables display of slashed zeros.
SLASHED_ZERO / "slashed-zero" => NS_FONT_VARIANT_NUMERIC_SLASHZERO = 0x40,
}
#[cfg(feature = "gecko")]
@ -1761,81 +1782,17 @@ impl VariantNumeric {
}
}
impl ToCss for VariantNumeric {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
if self.is_empty() {
return dest.write_str("normal");
}
let mut has_any = false;
macro_rules! write_value {
($ident:path => $str:expr) => {
if self.intersects($ident) {
if has_any {
dest.write_str(" ")?;
}
has_any = true;
dest.write_str($str)?;
}
};
}
write_value!(VariantNumeric::LINING_NUMS => "lining-nums");
write_value!(VariantNumeric::OLDSTYLE_NUMS => "oldstyle-nums");
write_value!(VariantNumeric::PROPORTIONAL_NUMS => "proportional-nums");
write_value!(VariantNumeric::TABULAR_NUMS => "tabular-nums");
write_value!(VariantNumeric::DIAGONAL_FRACTIONS => "diagonal-fractions");
write_value!(VariantNumeric::STACKED_FRACTIONS => "stacked-fractions");
write_value!(VariantNumeric::SLASHED_ZERO => "slashed-zero");
write_value!(VariantNumeric::ORDINAL => "ordinal");
debug_assert!(has_any);
Ok(())
}
}
#[cfg(feature = "gecko")]
impl_gecko_keyword_conversions!(VariantNumeric, u8);
/// Asserts that all variant-east-asian matches its NS_FONT_VARIANT_EAST_ASIAN_* value.
#[cfg(feature = "gecko")]
#[inline]
pub fn assert_variant_numeric_matches() {
use gecko_bindings::structs;
macro_rules! check_variant_numeric {
( $( $a:ident => $b:path),*, ) => {
if cfg!(debug_assertions) {
$(
assert_eq!(structs::$a as u8, $b.bits());
)*
}
}
}
check_variant_numeric! {
NS_FONT_VARIANT_NUMERIC_LINING => VariantNumeric::LINING_NUMS,
NS_FONT_VARIANT_NUMERIC_OLDSTYLE => VariantNumeric::OLDSTYLE_NUMS,
NS_FONT_VARIANT_NUMERIC_PROPORTIONAL => VariantNumeric::PROPORTIONAL_NUMS,
NS_FONT_VARIANT_NUMERIC_TABULAR => VariantNumeric::TABULAR_NUMS,
NS_FONT_VARIANT_NUMERIC_DIAGONAL_FRACTIONS => VariantNumeric::DIAGONAL_FRACTIONS,
NS_FONT_VARIANT_NUMERIC_STACKED_FRACTIONS => VariantNumeric::STACKED_FRACTIONS,
NS_FONT_VARIANT_NUMERIC_SLASHZERO => VariantNumeric::SLASHED_ZERO,
NS_FONT_VARIANT_NUMERIC_ORDINAL => VariantNumeric::ORDINAL,
}
}
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, Debug, PartialEq, ToCss)]
#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss)]
/// Specifies control over numerical forms.
pub enum FontVariantNumeric {
/// Value variant with `variant-numeric`
Value(VariantNumeric),
/// System font
#[css(skip)]
System(SystemFont),
}
@ -1938,11 +1895,12 @@ pub type SpecifiedFontFeatureSettings = FontSettings<FeatureTagValue<Integer>>;
/// Define initial settings that apply when the font defined by an @font-face
/// rule is rendered.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
pub enum FontFeatureSettings {
/// Value of `FontSettings`
Value(SpecifiedFontFeatureSettings),
/// System font
#[css(skip)]
System(SystemFont),
}
@ -1981,16 +1939,19 @@ impl Parse for FontFeatureSettings {
}
}
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue)]
/// Whether user agents are allowed to synthesize bold or oblique font faces
/// when a font family lacks bold or italic faces
pub struct FontSynthesis {
/// If a `font-weight` is requested that the font family does not contain,
/// the user agent may synthesize the requested weight from the weights
/// that do exist in the font family.
#[value_info(represents_keyword)]
pub weight: bool,
/// If a font-style is requested that the font family does not contain,
/// the user agent may synthesize the requested style from the normal face in the font family.
#[value_info(represents_keyword)]
pub style: bool,
}
@ -2079,7 +2040,7 @@ impl From<FontSynthesis> for u8 {
}
}
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
/// Allows authors to explicitly specify the language system of the font,
/// overriding the language system implied by the content language
pub enum FontLanguageOverride {
@ -2092,6 +2053,7 @@ pub enum FontLanguageOverride {
/// the language system implied by the language of the element
Override(Box<str>),
/// Use system font
#[css(skip)]
System(SystemFont),
}
@ -2169,11 +2131,12 @@ pub type SpecifiedFontVariationSettings = FontSettings<VariationValue<Number>>;
/// Define initial settings that apply when the font defined by an @font-face
/// rule is rendered.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
pub enum FontVariationSettings {
/// Value of `FontSettings`
Value(SpecifiedFontVariationSettings),
/// System font
#[css(skip)]
System(SystemFont),
}
@ -2254,7 +2217,8 @@ impl Parse for VariationValue<Number> {
}
}
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
/// text-zoom. Enable if true, disable if false
pub struct XTextZoom(#[css(skip)] pub bool);
@ -2271,7 +2235,8 @@ impl Parse for XTextZoom {
}
}
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
/// Internal property that reflects the lang attribute
pub struct XLang(#[css(skip)] pub Atom);
@ -2297,7 +2262,7 @@ impl Parse for XLang {
}
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, Copy, Debug, PartialEq, ToCss)]
#[derive(Clone, Copy, Debug, PartialEq, SpecifiedValueInfo, ToCss)]
/// Specifies the minimum font size allowed due to changes in scriptlevel.
/// Ref: https://wiki.mozilla.org/MathML:mstyle
pub struct MozScriptMinSize(pub NoCalcLength);
@ -2324,7 +2289,7 @@ impl Parse for MozScriptMinSize {
}
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, Copy, Debug, PartialEq, ToCss)]
#[derive(Clone, Copy, Debug, PartialEq, SpecifiedValueInfo, ToCss)]
/// Changes the scriptlevel in effect for the children.
/// Ref: https://wiki.mozilla.org/MathML:mstyle
///
@ -2359,7 +2324,8 @@ impl Parse for MozScriptLevel {
}
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, Copy, Debug, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, PartialEq, SpecifiedValueInfo, ToComputedValue,
ToCss)]
/// Specifies the multiplier to be used to adjust font size
/// due to changes in scriptlevel.
///

View file

@ -104,7 +104,7 @@ pub fn parse_line_names<'i, 't>(
/// The type of `repeat` function (only used in parsing).
///
/// <https://drafts.csswg.org/css-grid/#typedef-track-repeat>
#[derive(Clone, Copy, Debug, PartialEq)]
#[derive(Clone, Copy, Debug, PartialEq, SpecifiedValueInfo)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
enum RepeatType {
/// [`<auto-repeat>`](https://drafts.csswg.org/css-grid/#typedef-auto-repeat)

View file

@ -17,7 +17,8 @@ use servo_url::ServoUrl;
use std::cmp::Ordering;
use std::f32::consts::PI;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
use style_traits::{CssType, CssWriter, KeywordsCollectFn, ParseError};
use style_traits::{StyleParseErrorKind, SpecifiedValueInfo, ToCss};
use values::{Either, None_};
#[cfg(feature = "gecko")]
use values::computed::{Context, Position as ComputedPosition, ToComputedValue};
@ -54,6 +55,29 @@ pub type Gradient = generic::Gradient<
Angle,
>;
impl SpecifiedValueInfo for Gradient {
const SUPPORTED_TYPES: u8 = CssType::GRADIENT;
fn collect_completion_keywords(f: KeywordsCollectFn) {
// This list here should keep sync with that in Gradient::parse.
f(&[
"linear-gradient",
"-webkit-linear-gradient",
"-moz-linear-gradient",
"repeating-linear-gradient",
"-webkit-repeating-linear-gradient",
"-moz-repeating-linear-gradient",
"radial-gradient",
"-webkit-radial-gradient",
"-moz-radial-gradient",
"repeating-radial-gradient",
"-webkit-repeating-radial-gradient",
"-moz-repeating-radial-gradient",
"-webkit-gradient",
]);
}
}
/// A specified gradient kind.
#[cfg(not(feature = "gecko"))]
pub type GradientKind =

View file

@ -15,12 +15,13 @@ use values::specified::Angle;
/// The specified value of the `image-orientation` property.
/// https://drafts.csswg.org/css-images/#propdef-image-orientation
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo)]
pub struct ImageOrientation {
/// The angle specified, if any
pub angle: Option<Angle>,
/// Whether or not "flip" was specified
#[value_info(other_values = "flip,from-image")]
pub flipped: bool,
}

View file

@ -13,7 +13,7 @@ use font_metrics::FontMetricsQueryResult;
use parser::{Parse, ParserContext};
use std::cmp;
use std::ops::{Add, Mul};
use style_traits::{ParseError, StyleParseErrorKind};
use style_traits::{ParseError, SpecifiedValueInfo, StyleParseErrorKind};
use style_traits::values::specified::AllowedNumericType;
use super::{AllowQuirks, Number, Percentage, ToComputedValue};
use values::{Auto, CSSFloat, Either, Normal};
@ -494,11 +494,13 @@ impl NoCalcLength {
}
}
impl SpecifiedValueInfo for NoCalcLength {}
/// An extension to `NoCalcLength` to parse `calc` expressions.
/// This is commonly used for the `<length>` values.
///
/// <https://drafts.csswg.org/css-values/#lengths>
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
pub enum Length {
/// The internal length type that cannot parse `calc`
NoCalc(NoCalcLength),
@ -699,7 +701,7 @@ pub type NonNegativeLengthOrAuto = Either<NonNegativeLength, Auto>;
/// A length or a percentage value.
#[allow(missing_docs)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
pub enum LengthOrPercentage {
Length(NoCalcLength),
Percentage(computed::Percentage),
@ -845,7 +847,7 @@ impl LengthOrPercentage {
/// Either a `<length>`, a `<percentage>`, or the `auto` keyword.
#[allow(missing_docs)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
pub enum LengthOrPercentageOrAuto {
Length(NoCalcLength),
Percentage(computed::Percentage),
@ -1015,7 +1017,7 @@ impl Parse for NonNegativeLengthOrPercentageOrAuto {
}
/// Either a `<length>`, a `<percentage>`, or the `none` keyword.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
#[allow(missing_docs)]
pub enum LengthOrPercentageOrNone {
Length(NoCalcLength),
@ -1195,7 +1197,7 @@ impl LengthOrNumber {
///
/// Note that it only accepts non-negative values.
#[allow(missing_docs)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
pub enum MozLength {
LengthOrPercentageOrAuto(LengthOrPercentageOrAuto),
ExtremumLength(ExtremumLength),
@ -1252,7 +1254,7 @@ impl MozLength {
/// A value suitable for a `max-width` or `max-height` property.
#[allow(missing_docs)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
pub enum MaxLength {
LengthOrPercentageOrNone(LengthOrPercentageOrNone),
ExtremumLength(ExtremumLength),

View file

@ -15,7 +15,8 @@ use values::generics::CounterStyleOrNone;
/// Specified and computed `list-style-type` property.
#[cfg(feature = "gecko")]
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
pub enum ListStyleType {
/// <counter-style> | none
CounterStyle(CounterStyleOrNone),
@ -77,8 +78,10 @@ impl Parse for ListStyleType {
///
/// FIXME(emilio): It's a shame that this allocates all the time it's computed,
/// probably should just be refcounted.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
pub struct Quotes(pub Box<[(Box<str>, Box<str>)]>);
/// FIXME This can probably derive ToCss.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue)]
pub struct Quotes(#[css(if_empty = "none")] pub Box<[(Box<str>, Box<str>)]>);
impl ToCss for Quotes {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result

View file

@ -13,7 +13,7 @@ use num_traits::One;
use parser::{Parse, ParserContext};
use std::f32;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
use style_traits::{CssWriter, ParseError, SpecifiedValueInfo, StyleParseErrorKind, ToCss};
use style_traits::values::specified::AllowedNumericType;
use super::{Auto, CSSFloat, CSSInteger, Either};
use super::computed::{Context, ToComputedValue};
@ -149,8 +149,8 @@ fn parse_number_with_clamping_mode<'i, 't>(
// FIXME(emilio): Should move to border.rs
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Ord, Parse, PartialEq, PartialOrd,
ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Ord, Parse, PartialEq,
PartialOrd, SpecifiedValueInfo, ToComputedValue, ToCss)]
pub enum BorderStyle {
None = -1,
Solid = 6,
@ -273,6 +273,8 @@ impl ToCss for Number {
}
}
impl SpecifiedValueInfo for Number {}
impl From<Number> for f32 {
#[inline]
fn from(n: Number) -> Self {
@ -326,7 +328,8 @@ impl Parse for GreaterThanOrEqualToOneNumber {
///
/// FIXME(emilio): Should probably use Either.
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToCss)]
pub enum NumberOrPercentage {
Percentage(Percentage),
Number(Number),
@ -364,7 +367,8 @@ impl Parse for NumberOrPercentage {
}
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, ToCss)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd,
SpecifiedValueInfo, ToCss)]
pub struct Opacity(Number);
impl Parse for Opacity {
@ -533,6 +537,8 @@ impl ToCss for Integer {
}
}
impl SpecifiedValueInfo for Integer {}
/// A wrapper of Integer, with value >= 1.
pub type PositiveInteger = GreaterThanOrEqualToOne<Integer>;
@ -562,8 +568,9 @@ pub type GridLine = GenericGridLine<Integer>;
/// `<grid-template-rows> | <grid-template-columns>`
pub type GridTemplateComponent = GenericGridTemplateComponent<LengthOrPercentage, Integer>;
#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo)]
/// rect(<top>, <left>, <bottom>, <right>) used by clip and image-region
#[css(function = "rect")]
pub struct ClipRect {
/// <top> (<length> | <auto>)
pub top: Option<Length>,
@ -751,7 +758,9 @@ impl AllowQuirks {
/// An attr(...) rule
///
/// `[namespace? `|`]? ident`
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue)]
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue)]
#[css(function)]
pub struct Attr {
/// Optional namespace prefix and URL.
pub namespace: Option<(Prefix, Namespace)>,

View file

@ -10,8 +10,8 @@ use selectors::parser::SelectorParseErrorKind;
use style_traits::ParseError;
use values::specified::BorderStyle;
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Ord, PartialEq, PartialOrd, ToComputedValue,
ToCss)]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Ord, PartialEq, PartialOrd,
SpecifiedValueInfo, ToComputedValue, ToCss)]
/// <https://drafts.csswg.org/css-ui/#propdef-outline-style>
pub enum OutlineStyle {
/// auto

View file

@ -7,7 +7,7 @@
use cssparser::{Parser, Token};
use parser::{Parse, ParserContext};
use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, ToCss};
use style_traits::{CssWriter, ParseError, SpecifiedValueInfo, ToCss};
use style_traits::values::specified::AllowedNumericType;
use values::{serialize_percentage, CSSFloat};
use values::computed::{Context, ToComputedValue};
@ -158,3 +158,5 @@ impl ToComputedValue for Percentage {
Percentage::new(computed.0)
}
}
impl SpecifiedValueInfo for Percentage {}

View file

@ -8,44 +8,15 @@
use cssparser::Parser;
use parser::{Parse, ParserContext};
use style_traits::ParseError;
use style_traits::{ParseError, StyleParseErrorKind};
use style_traits::cursor::CursorKind;
use values::generics::pointing::CaretColor as GenericCaretColor;
use values::generics::pointing as generics;
use values::specified::Number;
use values::specified::color::Color;
#[cfg(feature = "gecko")]
use values::specified::url::SpecifiedImageUrl;
/// The specified value for the `cursor` property.
///
/// https://drafts.csswg.org/css-ui/#cursor
#[cfg(feature = "servo")]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
pub struct Cursor(pub CursorKind);
/// The specified value for the `cursor` property.
///
/// https://drafts.csswg.org/css-ui/#cursor
#[cfg(feature = "gecko")]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
pub struct Cursor {
/// The parsed images for the cursor.
pub images: Box<[CursorImage]>,
/// The kind of the cursor [default | help | ...].
pub keyword: CursorKind,
}
/// The specified value for the `image cursors`.
#[cfg(feature = "gecko")]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
pub struct CursorImage {
/// The url to parse images from.
pub url: SpecifiedImageUrl,
/// The <x> and <y> coordinates.
pub hotspot: Option<(f32, f32)>,
}
/// A specified value for the `caret-color` property.
pub type CaretColor = GenericCaretColor<Color>;
pub type CaretColor = generics::CaretColor<Color>;
impl Parse for CaretColor {
fn parse<'i, 't>(
@ -53,8 +24,63 @@ impl Parse for CaretColor {
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
if input.try(|i| i.expect_ident_matching("auto")).is_ok() {
return Ok(GenericCaretColor::Auto);
return Ok(generics::CaretColor::Auto);
}
Ok(GenericCaretColor::Color(Color::parse(context, input)?))
Ok(generics::CaretColor::Color(Color::parse(context, input)?))
}
}
/// A specified value for the `cursor` property.
pub type Cursor = generics::Cursor<CursorImage>;
/// A specified value for item of `image cursors`.
pub type CursorImage = generics::CursorImage<SpecifiedImageUrl, Number>;
impl Parse for Cursor {
/// cursor: [<url> [<number> <number>]?]# [auto | default | ...]
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let mut images = vec![];
loop {
match input.try(|input| CursorImage::parse(context, input)) {
Ok(image) => images.push(image),
Err(_) => break,
}
input.expect_comma()?;
}
Ok(Self {
images: images.into_boxed_slice(),
keyword: CursorKind::parse(context, input)?,
})
}
}
impl Parse for CursorKind {
fn parse<'i, 't>(
_context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let location = input.current_source_location();
let ident = input.expect_ident()?;
CursorKind::from_css_keyword(&ident).map_err(|_| {
location.new_custom_error(StyleParseErrorKind::UnspecifiedError)
})
}
}
impl Parse for CursorImage {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
Ok(Self {
url: SpecifiedImageUrl::parse(context, input)?,
hotspot: match input.try(|input| Number::parse(context, input)) {
Ok(number) => Some((number, Number::parse(context, input)?)),
Err(_) => None,
},
})
}
}

View file

@ -34,7 +34,7 @@ pub type HorizontalPosition = PositionComponent<X>;
pub type VerticalPosition = PositionComponent<Y>;
/// The specified value of a component of a CSS `<position>`.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
pub enum PositionComponent<S> {
/// `center`
Center,
@ -45,7 +45,8 @@ pub enum PositionComponent<S> {
}
/// A keyword for the X direction.
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq,
SpecifiedValueInfo, ToComputedValue, ToCss)]
#[allow(missing_docs)]
pub enum X {
Left,
@ -53,7 +54,8 @@ pub enum X {
}
/// A keyword for the Y direction.
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq,
SpecifiedValueInfo, ToComputedValue, ToCss)]
#[allow(missing_docs)]
pub enum Y {
Top,
@ -409,7 +411,8 @@ impl ToCss for LegacyPosition {
}
}
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
/// Auto-placement algorithm Option
pub enum AutoFlow {
/// The auto-placement algorithm places items by filling each row in turn,
@ -420,13 +423,15 @@ pub enum AutoFlow {
Column,
}
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue)]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue)]
/// Controls how the auto-placement algorithm works
/// specifying exactly how auto-placed items get flowed into the grid
pub struct GridAutoFlow {
/// Specifiy how auto-placement algorithm fills each `row` or `column` in turn
pub autoflow: AutoFlow,
/// Specify use `dense` packing algorithm or not
#[value_info(represents_keyword)]
pub dense: bool,
}
@ -533,7 +538,7 @@ impl From<GridAutoFlow> for u8 {
}
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, Debug, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
/// https://drafts.csswg.org/css-grid/#named-grid-area
pub struct TemplateAreas {
/// `named area` containing for each template area
@ -639,7 +644,8 @@ impl Parse for TemplateAreas {
}
/// Arc type for `Arc<TemplateAreas>`
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
pub struct TemplateAreasArc(#[ignore_malloc_size_of = "Arc"] pub Arc<TemplateAreas>);
impl Parse for TemplateAreasArc {
@ -654,7 +660,7 @@ impl Parse for TemplateAreasArc {
}
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo)]
/// Not associated with any particular grid item, but can
/// be referenced from the grid-placement properties.
pub struct NamedArea {

View file

@ -173,7 +173,8 @@ const PAINT_ORDER_MASK: u8 = 0b11;
///
/// Higher priority values, i.e. the values specified first,
/// will be painted first (and may be covered by paintings of lower priority)
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue)]
pub struct SVGPaintOrder(pub u8);
impl SVGPaintOrder {
@ -280,7 +281,8 @@ impl ToCss for SVGPaintOrder {
/// Specified MozContextProperties value.
/// Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-context-properties)
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
pub struct MozContextProperties(pub CustomIdent);
impl Parse for MozContextProperties {

View file

@ -8,7 +8,8 @@ use cssparser::Parser;
use parser::{Parse, ParserContext};
use style_traits::{ParseError, StyleParseErrorKind};
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
/// span. for `<col span>` pres attr
pub struct XSpan(#[css(skip)] pub i32);

View file

@ -9,7 +9,9 @@ use parser::{Parse, ParserContext};
use properties::longhands::writing_mode::computed_value::T as SpecifiedWritingMode;
use selectors::parser::SelectorParseErrorKind;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
use style_traits::{CssWriter, KeywordsCollectFn, ParseError};
use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss};
use style_traits::values::SequenceWriter;
use unicode_segmentation::UnicodeSegmentation;
use values::computed::{Context, ToComputedValue};
use values::computed::text::LineHeight as ComputedLineHeight;
@ -158,7 +160,7 @@ impl ToComputedValue for LineHeight {
}
/// A generic value for the `text-overflow` property.
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
pub enum TextOverflowSide {
/// Clip inline content.
Clip,
@ -192,7 +194,7 @@ impl Parse for TextOverflowSide {
}
}
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
/// text-overflow. Specifies rendering when inline content overflows its line box edge.
pub struct TextOverflow {
/// First value. Applies to end line box edge if no second is supplied; line-left edge otherwise.
@ -251,20 +253,23 @@ impl ToComputedValue for TextOverflow {
}
}
bitflags! {
macro_rules! impl_text_decoration_line {
{
$(
$(#[$($meta:tt)+])*
$ident:ident / $css:expr => $value:expr,
)+
} => {
bitflags! {
#[derive(MallocSizeOf, ToComputedValue)]
/// Specified keyword values for the text-decoration-line property.
pub struct TextDecorationLine: u8 {
/// No text decoration line is specified
const NONE = 0;
/// Underline
const UNDERLINE = 0x01;
/// Overline
const OVERLINE = 0x02;
/// Line through
const LINE_THROUGH = 0x04;
/// Blink
const BLINK = 0x08;
$(
$(#[$($meta)+])*
const $ident = $value;
)+
#[cfg(feature = "gecko")]
/// Only set by presentation attributes
///
@ -275,20 +280,9 @@ bitflags! {
/// a red text decoration
const COLOR_OVERRIDE = 0x10;
}
}
#[cfg(feature = "gecko")]
impl_bitflags_conversions!(TextDecorationLine);
impl TextDecorationLine {
#[inline]
/// Returns the initial value of text-decoration-line
pub fn none() -> Self {
TextDecorationLine::NONE
}
}
impl Parse for TextDecorationLine {
impl Parse for TextDecorationLine {
/// none | [ underline || overline || line-through || blink ]
fn parse<'i, 't>(
_context: &ParserContext,
@ -306,38 +300,16 @@ impl Parse for TextDecorationLine {
let result = input.try(|input| {
let ident = input.expect_ident().map_err(|_| ())?;
match_ignore_ascii_case! { ident,
"underline" => {
if result.contains(TextDecorationLine::UNDERLINE) {
$(
$css => {
if result.contains(TextDecorationLine::$ident) {
Err(())
} else {
result.insert(TextDecorationLine::UNDERLINE);
Ok(())
}
}
"overline" => {
if result.contains(TextDecorationLine::OVERLINE) {
Err(())
} else {
result.insert(TextDecorationLine::OVERLINE);
Ok(())
}
}
"line-through" => {
if result.contains(TextDecorationLine::LINE_THROUGH) {
Err(())
} else {
result.insert(TextDecorationLine::LINE_THROUGH);
Ok(())
}
}
"blink" => {
if result.contains(TextDecorationLine::BLINK) {
Err(())
} else {
result.insert(TextDecorationLine::BLINK);
result.insert(TextDecorationLine::$ident);
Ok(())
}
}
)+
_ => Err(()),
}
});
@ -352,15 +324,69 @@ impl Parse for TextDecorationLine {
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
}
}
}
impl ToCss for TextDecorationLine {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
if self.is_empty() {
return dest.write_str("none");
}
let mut writer = SequenceWriter::new(dest, " ");
$(
if self.contains(TextDecorationLine::$ident) {
writer.raw_item($css)?;
}
)+
Ok(())
}
}
impl SpecifiedValueInfo for TextDecorationLine {
fn collect_completion_keywords(f: KeywordsCollectFn) {
f(&["none", $($css,)+]);
}
}
}
}
impl_text_decoration_line! {
/// Underline
UNDERLINE / "underline" => 1 << 0,
/// Overline
OVERLINE / "overline" => 1 << 1,
/// Line through
LINE_THROUGH / "line-through" => 1 << 2,
/// Blink
BLINK / "blink" => 1 << 3,
}
#[cfg(feature = "gecko")]
impl_bitflags_conversions!(TextDecorationLine);
impl TextDecorationLine {
#[inline]
/// Returns the initial value of text-decoration-line
pub fn none() -> Self {
TextDecorationLine::NONE
}
}
macro_rules! define_text_align_keyword {
($($name: ident => $discriminant: expr,)+) => {
($(
$(#[$($meta:tt)+])*
$name: ident => $discriminant: expr,
)+) => {
/// Specified value of text-align keyword value.
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq,
SpecifiedValueInfo, ToComputedValue, ToCss)]
#[allow(missing_docs)]
pub enum TextAlignKeyword {
$(
$(#[$($meta)+])*
$name = $discriminant,
)+
}
@ -391,6 +417,7 @@ define_text_align_keyword! {
MozCenter => 6,
MozLeft => 7,
MozRight => 8,
#[css(skip)]
Char => 10,
}
@ -417,7 +444,7 @@ impl TextAlignKeyword {
/// Specified value of text-align property.
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, SpecifiedValueInfo, ToCss)]
pub enum TextAlign {
/// Keyword value of text-align property.
Keyword(TextAlignKeyword),
@ -429,6 +456,7 @@ pub enum TextAlign {
/// only set directly on the elements and it has a different handling
/// unlike other values.
#[cfg(feature = "gecko")]
#[css(skip)]
MozCenterOrInherit,
}
@ -453,21 +481,6 @@ impl Parse for TextAlign {
}
}
impl ToCss for TextAlign {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
match *self {
TextAlign::Keyword(key) => key.to_css(dest),
#[cfg(feature = "gecko")]
TextAlign::MatchParent => dest.write_str("match-parent"),
#[cfg(feature = "gecko")]
TextAlign::MozCenterOrInherit => Ok(()),
}
}
}
impl TextAlign {
/// Convert an enumerated value coming from Gecko to a `TextAlign`.
#[cfg(feature = "gecko")]
@ -534,7 +547,7 @@ impl ToComputedValue for TextAlign {
}
/// Specified value of text-emphasis-style property.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
pub enum TextEmphasisStyle {
/// <fill> <shape>
Keyword(TextEmphasisKeywordValue),
@ -545,7 +558,7 @@ pub enum TextEmphasisStyle {
}
/// Keyword value for the text-emphasis-style property
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
pub enum TextEmphasisKeywordValue {
/// <fill>
Fill(TextEmphasisFillMode),
@ -574,7 +587,8 @@ impl TextEmphasisKeywordValue {
}
/// Fill mode for the text-emphasis-style property
#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, ToCss)]
#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo,
ToCss)]
pub enum TextEmphasisFillMode {
/// `filled`
Filled,
@ -583,7 +597,8 @@ pub enum TextEmphasisFillMode {
}
/// Shape keyword for the text-emphasis-style property
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss)]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq,
SpecifiedValueInfo, ToCss)]
pub enum TextEmphasisShapeKeyword {
/// `dot`
Dot,
@ -709,7 +724,8 @@ impl Parse for TextEmphasisStyle {
}
/// The allowed horizontal values for the `text-emphasis-position` property.
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq,
SpecifiedValueInfo, ToComputedValue, ToCss)]
pub enum TextEmphasisHorizontalWritingModeValue {
/// Draw marks over the text in horizontal writing mode.
Over,
@ -718,7 +734,8 @@ pub enum TextEmphasisHorizontalWritingModeValue {
}
/// The allowed vertical values for the `text-emphasis-position` property.
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq,
SpecifiedValueInfo, ToComputedValue, ToCss)]
pub enum TextEmphasisVerticalWritingModeValue {
/// Draws marks to the right of the text in vertical writing mode.
Right,
@ -727,7 +744,8 @@ pub enum TextEmphasisVerticalWritingModeValue {
}
/// Specified value of `text-emphasis-position` property.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
pub struct TextEmphasisPosition(
pub TextEmphasisHorizontalWritingModeValue,
pub TextEmphasisVerticalWritingModeValue,

View file

@ -7,7 +7,7 @@
use cssparser::{Parser, Token};
use parser::{Parse, ParserContext};
use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
use style_traits::{CssWriter, ParseError, SpecifiedValueInfo, StyleParseErrorKind, ToCss};
use style_traits::values::specified::AllowedNumericType;
use values::CSSFloat;
use values::computed::{Context, ToComputedValue};
@ -165,3 +165,5 @@ impl ToCss for Time {
Ok(())
}
}
impl SpecifiedValueInfo for Time {}

View file

@ -233,7 +233,7 @@ impl Parse for Transform {
}
/// The specified value of a component of a CSS `<transform-origin>`.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
pub enum OriginComponent<S> {
/// `center`
Center,

View file

@ -10,7 +10,8 @@ use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
/// Specified value of `-moz-force-broken-image-icon`
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue)]
pub struct MozForceBrokenImageIcon(pub bool);
impl MozForceBrokenImageIcon {

View file

@ -68,7 +68,7 @@ pub fn derive(mut input: DeriveInput) -> Tokens {
}
fn derive_variant_arm(variant: &VariantInfo) -> Result<Tokens, ()> {
let variant_attrs = cg::parse_variant_attrs::<AnimationVariantAttrs>(&variant.ast());
let variant_attrs = cg::parse_variant_attrs_from_ast::<AnimationVariantAttrs>(&variant.ast());
if variant_attrs.error {
return Err(());
}

View file

@ -188,7 +188,7 @@ where
}
}
pub fn parse_variant_attrs<A>(variant: &VariantAst) -> A
pub fn parse_variant_attrs_from_ast<A>(variant: &VariantAst) -> A
where
A: FromVariant,
{
@ -198,7 +198,14 @@ where
fields: variant.fields.clone(),
discriminant: variant.discriminant.clone(),
};
match A::from_variant(&v) {
parse_variant_attrs(&v)
}
pub fn parse_variant_attrs<A>(variant: &Variant) -> A
where
A: FromVariant
{
match A::from_variant(variant) {
Ok(attrs) => attrs,
Err(e) => panic!("failed to parse variant attributes: {}", e),
}

View file

@ -26,7 +26,7 @@ pub fn derive(mut input: DeriveInput) -> Tokens {
let mut append_error_clause = s.variants().len() > 1;
let match_body = s.variants().iter().fold(quote!(), |body, variant| {
let attrs = cg::parse_variant_attrs::<AnimationVariantAttrs>(&variant.ast());
let attrs = cg::parse_variant_attrs_from_ast::<AnimationVariantAttrs>(&variant.ast());
if attrs.error {
append_error_clause = true;
return body;

View file

@ -16,6 +16,7 @@ mod animate;
mod cg;
mod compute_squared_distance;
mod parse;
mod specified_value_info;
mod to_animated_value;
mod to_animated_zero;
mod to_computed_value;
@ -62,3 +63,9 @@ pub fn derive_to_css(stream: TokenStream) -> TokenStream {
let input = syn::parse(stream).unwrap();
to_css::derive(input).into()
}
#[proc_macro_derive(SpecifiedValueInfo, attributes(css, value_info))]
pub fn derive_specified_value_info(stream: TokenStream) -> TokenStream {
let input = syn::parse(stream).unwrap();
specified_value_info::derive(input).into()
}

View file

@ -19,7 +19,11 @@ pub fn derive(input: DeriveInput) -> Tokens {
"Parse is only supported for single-variant enums for now"
);
let variant_attrs = cg::parse_variant_attrs::<CssVariantAttrs>(&variant.ast());
let variant_attrs = cg::parse_variant_attrs_from_ast::<CssVariantAttrs>(&variant.ast());
if variant_attrs.skip {
return match_body;
}
let identifier = cg::to_css_identifier(
&variant_attrs.keyword.unwrap_or(variant.ast().ident.as_ref().into()),
);

View file

@ -0,0 +1,181 @@
/* 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 http://mozilla.org/MPL/2.0/. */
use cg;
use quote::Tokens;
use syn::{Data, DeriveInput, Fields, Ident, Type};
use to_css::{CssFieldAttrs, CssInputAttrs, CssVariantAttrs};
pub fn derive(mut input: DeriveInput) -> Tokens {
let css_attrs = cg::parse_input_attrs::<CssInputAttrs>(&input);
let mut types = vec![];
let mut values = vec![];
let input_ident = input.ident;
let input_name = || cg::to_css_identifier(input_ident.as_ref());
if let Some(function) = css_attrs.function {
values.push(function.explicit().unwrap_or_else(input_name));
// If the whole value is wrapped in a function, value types of
// its fields should not be propagated.
} else {
let mut where_clause = input.generics.where_clause.take();
for param in input.generics.type_params() {
cg::add_predicate(
&mut where_clause,
parse_quote!(#param: ::style_traits::SpecifiedValueInfo),
);
}
input.generics.where_clause = where_clause;
match input.data {
Data::Enum(ref e) => {
for v in e.variants.iter() {
let css_attrs = cg::parse_variant_attrs::<CssVariantAttrs>(&v);
let info_attrs = cg::parse_variant_attrs::<ValueInfoVariantAttrs>(&v);
if css_attrs.skip {
continue;
}
if let Some(aliases) = css_attrs.aliases {
for alias in aliases.split(",") {
values.push(alias.to_string());
}
}
if let Some(other_values) = info_attrs.other_values {
for value in other_values.split(",") {
values.push(value.to_string());
}
}
let ident = &v.ident;
let variant_name = || cg::to_css_identifier(ident.as_ref());
if info_attrs.starts_with_keyword {
values.push(variant_name());
continue;
}
if let Some(keyword) = css_attrs.keyword {
values.push(keyword);
continue;
}
if let Some(function) = css_attrs.function {
values.push(function.explicit().unwrap_or_else(variant_name));
} else {
if !derive_struct_fields(&v.fields, &mut types, &mut values) {
values.push(variant_name());
}
}
}
}
Data::Struct(ref s) => {
if !derive_struct_fields(&s.fields, &mut types, &mut values) {
values.push(input_name());
}
}
Data::Union(_) => unreachable!("union is not supported"),
}
}
let info_attrs = cg::parse_input_attrs::<ValueInfoInputAttrs>(&input);
if let Some(other_values) = info_attrs.other_values {
for value in other_values.split(",") {
values.push(value.to_string());
}
}
let mut types_value = quote!(0);
types_value.append_all(types.iter().map(|ty| quote! {
| <#ty as ::style_traits::SpecifiedValueInfo>::SUPPORTED_TYPES
}));
let mut nested_collects = quote!();
nested_collects.append_all(types.iter().map(|ty| quote! {
<#ty as ::style_traits::SpecifiedValueInfo>::collect_completion_keywords(_f);
}));
if let Some(ty) = info_attrs.ty {
types_value.append_all(quote! {
| ::style_traits::CssType::#ty
});
}
let append_values = if values.is_empty() {
quote!()
} else {
let mut value_list = quote!();
value_list.append_separated(values.iter(), quote! { , });
quote! { _f(&[#value_list]); }
};
let name = &input.ident;
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
quote! {
impl #impl_generics ::style_traits::SpecifiedValueInfo for #name #ty_generics
#where_clause
{
const SUPPORTED_TYPES: u8 = #types_value;
fn collect_completion_keywords(_f: &mut FnMut(&[&'static str])) {
#nested_collects
#append_values
}
}
}
}
/// Derive from the given fields. Return false if the fields is a Unit,
/// true otherwise.
fn derive_struct_fields<'a>(
fields: &'a Fields,
types: &mut Vec<&'a Type>,
values: &mut Vec<String>,
) -> bool {
let fields = match *fields {
Fields::Unit => return false,
Fields::Named(ref fields) => fields.named.iter(),
Fields::Unnamed(ref fields) => fields.unnamed.iter(),
};
types.extend(fields.filter_map(|field| {
let info_attrs = cg::parse_field_attrs::<ValueInfoFieldAttrs>(field);
if let Some(other_values) = info_attrs.other_values {
for value in other_values.split(",") {
values.push(value.to_string());
}
}
if info_attrs.represents_keyword {
let ident = field.ident.as_ref()
.expect("only named field should use represents_keyword");
values.push(cg::to_css_identifier(ident.as_ref()));
return None;
}
let css_attrs = cg::parse_field_attrs::<CssFieldAttrs>(field);
if let Some(if_empty) = css_attrs.if_empty {
values.push(if_empty);
}
if !css_attrs.skip {
Some(&field.ty)
} else {
None
}
}));
true
}
#[darling(attributes(value_info), default)]
#[derive(Default, FromDeriveInput)]
struct ValueInfoInputAttrs {
ty: Option<Ident>,
other_values: Option<String>,
}
#[darling(attributes(value_info), default)]
#[derive(Default, FromVariant)]
struct ValueInfoVariantAttrs {
starts_with_keyword: bool,
other_values: Option<String>,
}
#[darling(attributes(value_info), default)]
#[derive(Default, FromField)]
struct ValueInfoFieldAttrs {
represents_keyword: bool,
other_values: Option<String>,
}

View file

@ -22,7 +22,7 @@ pub fn derive(mut input: syn::DeriveInput) -> quote::Tokens {
}
let to_body = synstructure::Structure::new(&input).each_variant(|variant| {
let attrs = cg::parse_variant_attrs::<AnimationVariantAttrs>(&variant.ast());
let attrs = cg::parse_variant_attrs_from_ast::<AnimationVariantAttrs>(&variant.ast());
if attrs.error {
return Some(quote! { Err(()) });
}

View file

@ -75,9 +75,12 @@ fn derive_variant_arm(
let bindings = variant.bindings();
let identifier = cg::to_css_identifier(variant.ast().ident.as_ref());
let ast = variant.ast();
let variant_attrs = cg::parse_variant_attrs::<CssVariantAttrs>(&ast);
let variant_attrs = cg::parse_variant_attrs_from_ast::<CssVariantAttrs>(&ast);
let separator = if variant_attrs.comma { ", " } else { " " };
if variant_attrs.skip {
return quote!(Ok(()));
}
if variant_attrs.dimension {
assert_eq!(bindings.len(), 1);
assert!(
@ -207,12 +210,12 @@ fn derive_single_field_expr(
#[darling(attributes(css), default)]
#[derive(Default, FromDeriveInput)]
struct CssInputAttrs {
derive_debug: bool,
pub struct CssInputAttrs {
pub derive_debug: bool,
// Here because structs variants are also their whole type definition.
function: Option<Override<String>>,
pub function: Option<Override<String>>,
// Here because structs variants are also their whole type definition.
comma: bool,
pub comma: bool,
}
#[darling(attributes(css), default)]
@ -223,14 +226,15 @@ pub struct CssVariantAttrs {
pub dimension: bool,
pub keyword: Option<String>,
pub aliases: Option<String>,
pub skip: bool,
}
#[darling(attributes(css), default)]
#[derive(Default, FromField)]
struct CssFieldAttrs {
if_empty: Option<String>,
field_bound: bool,
iterable: bool,
skip: bool,
skip_if: Option<Path>,
pub struct CssFieldAttrs {
pub if_empty: Option<String>,
pub field_bound: bool,
pub iterable: bool,
pub skip: bool,
pub skip_if: Option<Path>,
}

View file

@ -10,7 +10,7 @@ name = "style_traits"
path = "lib.rs"
[features]
servo = ["serde", "servo_atoms", "cssparser/serde", "webrender_api"]
servo = ["serde", "servo_atoms", "cssparser/serde", "webrender_api", "servo_url"]
gecko = []
[dependencies]
@ -24,4 +24,5 @@ selectors = { path = "../selectors" }
serde = {version = "1.0", optional = true}
webrender_api = {git = "https://github.com/servo/webrender", optional = true}
servo_atoms = {path = "../atoms", optional = true}
servo_arc = {path = "../servo_arc" }
servo_arc = { path = "../servo_arc" }
servo_url = { path = "../url", optional = true }

View file

@ -4,7 +4,7 @@
//! A list of common mouse cursors per CSS3-UI § 8.1.1.
use super::{CssWriter, ToCss};
use super::{CssWriter, KeywordsCollectFn, SpecifiedValueInfo, ToCss};
macro_rules! define_cursor {
(
@ -57,6 +57,15 @@ macro_rules! define_cursor {
}
}
}
impl SpecifiedValueInfo for CursorKind {
fn collect_completion_keywords(f: KeywordsCollectFn) {
f(&[
$($c_css,)+
$($g_css,)+
]);
}
}
}
}

View file

@ -22,6 +22,7 @@ extern crate selectors;
#[cfg(feature = "servo")] extern crate webrender_api;
extern crate servo_arc;
#[cfg(feature = "servo")] extern crate servo_atoms;
#[cfg(feature = "servo")] extern crate servo_url;
#[cfg(feature = "servo")] pub use webrender_api::DevicePixel;
@ -73,11 +74,13 @@ pub enum CSSPixel {}
// / desktop_zoom => CSSPixel
pub mod cursor;
pub mod specified_value_info;
#[macro_use]
pub mod values;
#[macro_use]
pub mod viewport;
pub use specified_value_info::{CssType, KeywordsCollectFn, SpecifiedValueInfo};
pub use values::{Comma, CommaWithSpace, CssWriter, OneOrMoreSeparated, Separator, Space, ToCss};
/// The error type for all CSS parsing routines.

View file

@ -0,0 +1,134 @@
/* 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 http://mozilla.org/MPL/2.0/. */
//! Value information for devtools.
use servo_arc::Arc;
use std::ops::Range;
use std::sync::Arc as StdArc;
/// Type of value that a property supports. This is used by Gecko's
/// devtools to make sense about value it parses, and types listed
/// here should match TYPE_* constants in InspectorUtils.webidl.
///
/// XXX This should really be a bitflags rather than a namespace mod,
/// but currently we cannot use bitflags in const.
#[allow(non_snake_case)]
pub mod CssType {
/// <color>
pub const COLOR: u8 = 1 << 0;
/// <gradient>
pub const GRADIENT: u8 = 1 << 1;
/// <timing-function>
pub const TIMING_FUNCTION: u8 = 1 << 2;
}
/// See SpecifiedValueInfo::collect_completion_keywords.
pub type KeywordsCollectFn<'a> = &'a mut FnMut(&[&'static str]);
/// Information of values of a given specified value type.
///
/// This trait is derivable with `#[derive(SpecifiedValueInfo)]`.
///
/// The algorithm traverses the type definition. For `SUPPORTED_TYPES`,
/// it puts an or'ed value of `SUPPORTED_TYPES` of all types it finds.
/// For `collect_completion_keywords`, it recursively invokes this
/// method on types found, and lists all keyword values and function
/// names following the same rule as `ToCss` in that method.
///
/// Some attributes of `ToCss` can affect the behavior, specifically:
/// * If `#[css(function)]` is found, the content inside the annotated
/// variant (or the whole type) isn't traversed, only the function
/// name is listed in `collect_completion_keywords`.
/// * If `#[css(skip)]` is found, the content inside the variant or
/// field is ignored.
/// * Values listed in `#[css(if_empty)]`, `#[css(aliases)]`, and
/// `#[css(keyword)]` are added into `collect_completion_keywords`.
///
/// In addition to `css` attributes, it also has `value_info` helper
/// attributes, including:
/// * `#[value_info(ty = "TYPE")]` can be used to specify a constant
/// from `CssType` to `SUPPORTED_TYPES`.
/// * `#[value_info(other_values = "value1,value2")]` can be used to
/// add other values related to a field, variant, or the type itself
/// into `collect_completion_keywords`.
/// * `#[value_info(starts_with_keyword)]` can be used on variants to
/// add the name of a non-unit variant (serialized like `ToCss`) into
/// `collect_completion_keywords`.
/// * `#[value_info(represents_keyword)]` can be used on fields into
/// `collect_completion_keywords`.
pub trait SpecifiedValueInfo {
/// Supported CssTypes by the given value type.
///
/// XXX This should be typed CssType when that becomes a bitflags.
/// Currently we cannot do so since bitflags cannot be used in constant.
const SUPPORTED_TYPES: u8 = 0;
/// Collect value starting words for the given specified value type.
/// This includes keyword and function names which can appear at the
/// beginning of a value of this type.
///
/// Caller should pass in a callback function to accept the list of
/// values. The callback function can be called multiple times, and
/// some values passed to the callback may be duplicate.
fn collect_completion_keywords(_f: KeywordsCollectFn) {}
}
impl SpecifiedValueInfo for bool {}
impl SpecifiedValueInfo for f32 {}
impl SpecifiedValueInfo for i8 {}
impl SpecifiedValueInfo for i32 {}
impl SpecifiedValueInfo for u8 {}
impl SpecifiedValueInfo for u16 {}
impl SpecifiedValueInfo for u32 {}
impl SpecifiedValueInfo for str {}
impl SpecifiedValueInfo for String {}
#[cfg(feature = "servo")]
impl SpecifiedValueInfo for ::servo_atoms::Atom {}
#[cfg(feature = "servo")]
impl SpecifiedValueInfo for ::servo_url::ServoUrl {}
impl<T: SpecifiedValueInfo + ?Sized> SpecifiedValueInfo for Box<T> {
const SUPPORTED_TYPES: u8 = T::SUPPORTED_TYPES;
fn collect_completion_keywords(f: KeywordsCollectFn) {
T::collect_completion_keywords(f);
}
}
impl<T: SpecifiedValueInfo> SpecifiedValueInfo for [T] {
const SUPPORTED_TYPES: u8 = T::SUPPORTED_TYPES;
fn collect_completion_keywords(f: KeywordsCollectFn) {
T::collect_completion_keywords(f);
}
}
macro_rules! impl_generic_specified_value_info {
($ty:ident<$param:ident>) => {
impl<$param: SpecifiedValueInfo> SpecifiedValueInfo for $ty<$param> {
const SUPPORTED_TYPES: u8 = $param::SUPPORTED_TYPES;
fn collect_completion_keywords(f: KeywordsCollectFn) {
$param::collect_completion_keywords(f);
}
}
}
}
impl_generic_specified_value_info!(Option<T>);
impl_generic_specified_value_info!(Vec<T>);
impl_generic_specified_value_info!(Arc<T>);
impl_generic_specified_value_info!(StdArc<T>);
impl_generic_specified_value_info!(Range<Idx>);
impl<T1, T2> SpecifiedValueInfo for (T1, T2)
where
T1: SpecifiedValueInfo,
T2: SpecifiedValueInfo,
{
const SUPPORTED_TYPES: u8 = T1::SUPPORTED_TYPES | T2::SUPPORTED_TYPES;
fn collect_completion_keywords(f: KeywordsCollectFn) {
T1::collect_completion_keywords(f);
T2::collect_completion_keywords(f);
}
}

View file

@ -173,16 +173,10 @@ where
Self { inner, separator }
}
/// Serialises a CSS value, writing any separator as necessary.
///
/// The separator is never written before any `item` produces any output,
/// and is written in subsequent calls only if the `item` produces some
/// output on its own again. This lets us handle `Option<T>` fields by
/// just not printing anything on `None`.
#[inline]
pub fn item<T>(&mut self, item: &T) -> fmt::Result
fn write_item<F>(&mut self, f: F) -> fmt::Result
where
T: ToCss,
F: FnOnce(&mut CssWriter<'b, W>) -> fmt::Result
{
let old_prefix = self.inner.prefix;
if old_prefix.is_none() {
@ -191,7 +185,7 @@ where
// to write the separator next time we produce output again.
self.inner.prefix = Some(self.separator);
}
item.to_css(&mut self.inner)?;
f(self.inner)?;
match (old_prefix, self.inner.prefix) {
(_, None) => {
// This call produced output and cleaned up after itself.
@ -213,6 +207,29 @@ where
}
Ok(())
}
/// Serialises a CSS value, writing any separator as necessary.
///
/// The separator is never written before any `item` produces any output,
/// and is written in subsequent calls only if the `item` produces some
/// output on its own again. This lets us handle `Option<T>` fields by
/// just not printing anything on `None`.
#[inline]
pub fn item<T>(&mut self, item: &T) -> fmt::Result
where
T: ToCss,
{
self.write_item(|inner| item.to_css(inner))
}
/// Writes a string as-is (i.e. not escaped or wrapped in quotes)
/// with any separator as necessary.
///
/// See SequenceWriter::item.
#[inline]
pub fn raw_item(&mut self, item: &str) -> fmt::Result {
self.write_item(|inner| inner.write_str(item))
}
}
/// A wrapper type that implements `ToCss` by printing its inner field.

View file

@ -17,7 +17,6 @@ gecko_debug = ["style/gecko_debug"]
atomic_refcell = "0.1"
cssparser = "0.23.0"
cstr = "0.1.2"
env_logger = {version = "0.5", default-features = false} # disable `regex` to reduce code size
libc = "0.2"
log = {version = "0.4", features = ["release_max_level_info"]}
malloc_size_of = {path = "../../components/malloc_size_of"}

View file

@ -4,15 +4,14 @@
use cssparser::{ParseErrorKind, Parser, ParserInput, SourceLocation};
use cssparser::ToCss as ParserToCss;
use env_logger::Builder;
use malloc_size_of::MallocSizeOfOps;
use nsstring::nsCString;
use nsstring::{nsCString, nsStringRepr};
use selectors::{NthIndexCache, SelectorList};
use selectors::matching::{MatchingContext, MatchingMode, matches_selector};
use servo_arc::{Arc, ArcBorrow, RawOffsetArc};
use smallvec::SmallVec;
use std::cell::RefCell;
use std::env;
use std::collections::BTreeSet;
use std::fmt::Write;
use std::iter;
use std::mem;
@ -137,7 +136,7 @@ use style::properties::{parse_one_declaration_into, parse_style_attribute};
use style::properties::animated_properties::AnimationValue;
use style::properties::animated_properties::compare_property_priority;
use style::rule_cache::RuleCacheConditions;
use style::rule_tree::{CascadeLevel, StrongRuleNode, StyleSource};
use style::rule_tree::{CascadeLevel, StrongRuleNode};
use style::selector_parser::{PseudoElementCascadeType, SelectorImpl};
use style::shared_lock::{SharedRwLockReadGuard, StylesheetGuards, ToCssWithGuard, Locked};
use style::string_cache::{Atom, WeakAtom};
@ -164,7 +163,7 @@ use style::values::generics::rect::Rect;
use style::values::specified;
use style::values::specified::gecko::{IntersectionObserverRootMargin, PixelOrPercentage};
use style::values::specified::source_size_list::SourceSizeList;
use style_traits::{CssWriter, ParsingMode, StyleParseErrorKind, ToCss};
use style_traits::{CssType, CssWriter, ParsingMode, StyleParseErrorKind, ToCss};
use super::error_reporter::ErrorReporter;
use super::stylesheet_loader::{AsyncStylesheetParser, StylesheetLoader};
@ -184,14 +183,6 @@ static mut DUMMY_URL_DATA: *mut URLExtraData = 0 as *mut URLExtraData;
pub extern "C" fn Servo_Initialize(dummy_url_data: *mut URLExtraData) {
use style::gecko_bindings::sugar::origin_flags;
// Initialize logging.
let mut builder = Builder::new();
let default_level = if cfg!(debug_assertions) { "warn" } else { "error" };
match env::var("RUST_LOG") {
Ok(v) => builder.parse(&v).init(),
_ => builder.parse(default_level).init(),
};
// Pretend that we're a Servo Layout thread, to make some assertions happy.
thread_state::initialize(thread_state::ThreadState::LAYOUT);
@ -938,20 +929,36 @@ pub extern "C" fn Servo_ComputedValues_ExtractAnimationValue(
}
}
macro_rules! parse_enabled_property_name {
($prop_name:ident, $found:ident, $default:expr) => {{
let prop_name = $prop_name.as_ref().unwrap().as_str_unchecked();
// XXX This can be simplified once Option::filter is stable.
let prop_id = PropertyId::parse(prop_name).ok().and_then(|p| {
if p.enabled_for_all_content() {
Some(p)
} else {
None
}
});
match prop_id {
Some(p) => {
*$found = true;
p
}
None => {
*$found = false;
return $default;
}
}
}}
}
#[no_mangle]
pub unsafe extern "C" fn Servo_Property_IsShorthand(
prop_name: *const nsACString,
found: *mut bool
) -> bool {
let prop_id = PropertyId::parse(prop_name.as_ref().unwrap().as_str_unchecked());
let prop_id = match prop_id {
Ok(ref p) if p.enabled_for_all_content() => p,
_ => {
*found = false;
return false;
}
};
*found = true;
let prop_id = parse_enabled_property_name!(prop_name, found, false);
prop_id.is_shorthand()
}
@ -974,6 +981,53 @@ pub unsafe extern "C" fn Servo_Property_IsInherited(
longhand_id.inherited()
}
#[no_mangle]
pub unsafe extern "C" fn Servo_Property_SupportsType(
prop_name: *const nsACString,
ty: u32,
found: *mut bool,
) -> bool {
let prop_id = parse_enabled_property_name!(prop_name, found, false);
// This should match the constants in InspectorUtils.
// (Let's don't bother importing InspectorUtilsBinding into bindings
// because it is not used anywhere else, and issue here would be
// caught by the property-db test anyway.)
let ty = match ty {
1 => CssType::COLOR,
2 => CssType::GRADIENT,
3 => CssType::TIMING_FUNCTION,
_ => unreachable!("unknown CSS type {}", ty),
};
prop_id.supports_type(ty)
}
#[no_mangle]
pub unsafe extern "C" fn Servo_Property_GetCSSValuesForProperty(
prop_name: *const nsACString,
found: *mut bool,
result: *mut nsTArray<nsStringRepr>,
) {
let prop_id = parse_enabled_property_name!(prop_name, found, ());
// Use B-tree set for unique and sorted result.
let mut values = BTreeSet::<&'static str>::new();
prop_id.collect_property_completion_keywords(&mut |list| values.extend(list.iter()));
let mut extras = vec![];
if values.contains("transparent") {
// This is a special value devtools use to avoid inserting the
// long list of color keywords. We need to prepend it to values.
extras.push("COLOR");
}
let result = result.as_mut().unwrap();
let len = extras.len() + values.len();
bindings::Gecko_ResizeTArrayForStrings(result, len as u32);
for (src, dest) in extras.iter().chain(values.iter()).zip(result.iter_mut()) {
dest.write_str(src).unwrap();
}
}
#[no_mangle]
pub extern "C" fn Servo_Property_IsAnimatable(property: nsCSSPropertyID) -> bool {
use style::properties::animated_properties;
@ -3123,8 +3177,8 @@ pub extern "C" fn Servo_ComputedValues_GetStyleRuleList(
let mut result = SmallVec::<[_; 10]>::new();
for node in rule_node.self_and_ancestors() {
let style_rule = match *node.style_source() {
StyleSource::Style(ref rule) => rule,
let style_rule = match node.style_source().and_then(|x| x.as_rule()) {
Some(rule) => rule,
_ => continue,
};
@ -3141,9 +3195,11 @@ pub extern "C" fn Servo_ComputedValues_GetStyleRuleList(
unsafe { rules.set_len(result.len() as u32) };
for (ref src, ref mut dest) in result.into_iter().zip(rules.iter_mut()) {
src.with_raw_offset_arc(|arc| {
src.with_arc(|a| {
a.with_raw_offset_arc(|arc| {
**dest = *Locked::<StyleRule>::arc_as_borrowed(arc);
})
});
}
}

View file

@ -5,7 +5,6 @@
extern crate cssparser;
#[macro_use] extern crate cstr;
extern crate env_logger;
extern crate libc;
#[macro_use] extern crate log;
extern crate malloc_size_of;

View file

@ -49,7 +49,16 @@ fn main() {
// Which is not a problem, but would cause this to not compile.
//
// Skip this until libclang is updated there.
if &cap[1] == "InvalidateStyleForDocStateChanges" {
//
// Also skip Servo_Element_IsDisplayContents because we
// forward-declare it in Element.h without the type bindgen uses
// to replace it by a reference, and it depends on the include
// order in ServoBindings.h. We have the same problem for
// ComputedStyle_{AddRef / Release}, we just don't hit it
// because they're included later...
if &cap[1] == "InvalidateStyleForDocStateChanges" ||
&cap[1] == "Element_IsDisplayContents"
{
continue;
}
w.write_all(format!(" [ Servo_{0}, bindings::Servo_{0} ];\n", &cap[1]).as_bytes()).unwrap();

View file

@ -14,7 +14,6 @@
extern crate atomic_refcell;
extern crate cssparser;
#[macro_use] extern crate cstr;
extern crate env_logger;
extern crate geckoservo;
#[macro_use] extern crate log;
extern crate malloc_size_of;

View file

@ -35,8 +35,8 @@ size_of_test!(test_size_of_element_data, ElementData, 24);
size_of_test!(test_size_of_property_declaration, style::properties::PropertyDeclaration, 32);
size_of_test!(test_size_of_application_declaration_block, ApplicableDeclarationBlock, 24);
size_of_test!(test_size_of_rule_node, RuleNode, 80);
size_of_test!(test_size_of_application_declaration_block, ApplicableDeclarationBlock, 16);
size_of_test!(test_size_of_rule_node, RuleNode, 72);
// This is huge, but we allocate it on the stack and then never move it,
// we only pass `&mut SourcePropertyDeclaration` references around.

View file

@ -487,42 +487,6 @@ mod shorthand_serialization {
}
}
mod outline {
use style::values::specified::outline::OutlineStyle;
use super::*;
#[test]
fn outline_should_show_all_properties_when_set() {
let mut properties = Vec::new();
let width = BorderSideWidth::Length(Length::from_px(4f32));
let style = OutlineStyle::Other(BorderStyle::Solid);
let color = RGBA::new(255, 0, 0, 255).into();
properties.push(PropertyDeclaration::OutlineWidth(width));
properties.push(PropertyDeclaration::OutlineStyle(style));
properties.push(PropertyDeclaration::OutlineColor(color));
let serialization = shorthand_properties_to_string(properties);
assert_eq!(serialization, "outline: 4px solid rgb(255, 0, 0);");
}
#[test]
fn outline_should_serialize_correctly_when_style_is_auto() {
let mut properties = Vec::new();
let width = BorderSideWidth::Length(Length::from_px(4f32));
let style = OutlineStyle::Auto;
let color = RGBA::new(255, 0, 0, 255).into();
properties.push(PropertyDeclaration::OutlineWidth(width));
properties.push(PropertyDeclaration::OutlineStyle(style));
properties.push(PropertyDeclaration::OutlineColor(color));
let serialization = shorthand_properties_to_string(properties);
assert_eq!(serialization, "outline: 4px auto rgb(255, 0, 0);");
}
}
mod background {
use super::*;

View file

@ -62,11 +62,12 @@ fn parse_rules(css: &str) -> Vec<(StyleSource, CascadeLevel)> {
let rules = s.contents.rules.read_with(&guard);
rules.0.iter().filter_map(|rule| {
match *rule {
CssRule::Style(ref style_rule) => Some(style_rule),
CssRule::Style(ref style_rule) => Some((
StyleSource::from_rule(style_rule.clone()),
CascadeLevel::UserNormal,
)),
_ => None,
}
}).cloned().map(StyleSource::Style).map(|s| {
(s, CascadeLevel::UserNormal)
}).collect()
}
@ -78,7 +79,7 @@ fn test_insertion_style_attribute(rule_tree: &RuleTree, rules: &[(StyleSource, C
shared_lock: &SharedRwLock)
-> StrongRuleNode {
let mut rules = rules.to_vec();
rules.push((StyleSource::Declarations(Arc::new(shared_lock.wrap(PropertyDeclarationBlock::with_one(
rules.push((StyleSource::from_declarations(Arc::new(shared_lock.wrap(PropertyDeclarationBlock::with_one(
PropertyDeclaration::Display(
longhands::display::SpecifiedValue::Block),
Importance::Normal

View file

@ -26,9 +26,6 @@
[The serialization of border: solid; border-style: dotted should be canonical.]
expected: FAIL
[The serialization of outline-width: 2px; outline-style: dotted; outline-color: blue; should be canonical.]
expected: FAIL
[The serialization of list-style-type: circle; list-style-position: inside; list-style-image: initial; should be canonical.]
expected: FAIL