mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
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:
commit
02c75ea2d9
95 changed files with 1940 additions and 1068 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -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)",
|
||||
]
|
||||
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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}:
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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 {}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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, ¤t_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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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"]);
|
||||
}
|
||||
|
|
|
@ -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 {}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 element’s 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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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>),
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)>,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {}
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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(());
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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()),
|
||||
);
|
||||
|
|
181
components/style_derive/specified_value_info.rs
Normal file
181
components/style_derive/specified_value_info.rs
Normal 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>,
|
||||
}
|
|
@ -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(()) });
|
||||
}
|
||||
|
|
|
@ -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>,
|
||||
}
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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,)+
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
134
components/style_traits/specified_value_info.rs
Normal file
134
components/style_traits/specified_value_info.rs
Normal 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);
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
|
|
|
@ -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"}
|
||||
|
|
|
@ -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);
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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::*;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue