mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
style: Distinguish between specified and computed URLs.
This is needed to serialize computed URLs correctly from getComputedStyle. Bug: 1461288 Reviewed-by: xidorn MozReview-Commit-ID: 9wakhqNrszb
This commit is contained in:
parent
a6328ba3ce
commit
1314f47da5
11 changed files with 375 additions and 295 deletions
|
@ -145,11 +145,11 @@ impl nsStyleImage {
|
|||
match image {
|
||||
GenericImage::Gradient(boxed_gradient) => self.set_gradient(*boxed_gradient),
|
||||
GenericImage::Url(ref url) => unsafe {
|
||||
bindings::Gecko_SetLayerImageImageValue(self, url.image_value.get());
|
||||
bindings::Gecko_SetLayerImageImageValue(self, url.0.image_value.get());
|
||||
},
|
||||
GenericImage::Rect(ref image_rect) => {
|
||||
unsafe {
|
||||
bindings::Gecko_SetLayerImageImageValue(self, image_rect.url.image_value.get());
|
||||
bindings::Gecko_SetLayerImageImageValue(self, image_rect.url.0.image_value.get());
|
||||
bindings::Gecko_InitializeImageCropRect(self);
|
||||
|
||||
// Set CropRect
|
||||
|
|
|
@ -12,10 +12,13 @@ use gecko_bindings::structs::root::{RustString, nsStyleImageRequest};
|
|||
use gecko_bindings::structs::root::mozilla::css::{ImageValue, URLValue};
|
||||
use gecko_bindings::sugar::refptr::RefPtr;
|
||||
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
||||
use nsstring::nsCString;
|
||||
use parser::{Parse, ParserContext};
|
||||
use servo_arc::{Arc, RawOffsetArc};
|
||||
use std::mem;
|
||||
use style_traits::ParseError;
|
||||
use std::fmt::{self, Write};
|
||||
use style_traits::{CssWriter, ParseError, ToCss};
|
||||
use values::computed::{Context, ToComputedValue};
|
||||
|
||||
/// A CSS url() value for gecko.
|
||||
#[css(function = "url")]
|
||||
|
@ -70,10 +73,8 @@ impl CssUrl {
|
|||
self.as_str().chars().next().map_or(false, |c| c == '#')
|
||||
}
|
||||
|
||||
/// Return the resolved url as string, or the empty string if it's invalid.
|
||||
///
|
||||
/// FIXME(bholley): This returns the unresolved URL while the servo version
|
||||
/// returns the resolved URL.
|
||||
/// Return the unresolved url as string, or the empty string if it's
|
||||
/// invalid.
|
||||
pub fn as_str(&self) -> &str {
|
||||
&*self.serialization
|
||||
}
|
||||
|
@ -121,7 +122,7 @@ impl MallocSizeOf for CssUrl {
|
|||
}
|
||||
|
||||
/// A specified url() value for general usage.
|
||||
#[derive(Clone, Debug, SpecifiedValueInfo, ToComputedValue, ToCss)]
|
||||
#[derive(Clone, Debug, SpecifiedValueInfo, ToCss)]
|
||||
pub struct SpecifiedUrl {
|
||||
/// The specified url value.
|
||||
pub url: CssUrl,
|
||||
|
@ -139,15 +140,11 @@ impl SpecifiedUrl {
|
|||
debug_assert!(!ptr.is_null());
|
||||
RefPtr::from_addrefed(ptr)
|
||||
};
|
||||
SpecifiedUrl { url, url_value }
|
||||
}
|
||||
|
||||
/// Convert from URLValueData to SpecifiedUrl.
|
||||
pub unsafe fn from_url_value_data(url: &URLValueData) -> Result<Self, ()> {
|
||||
CssUrl::from_url_value_data(url).map(Self::from_css_url)
|
||||
Self { url, url_value }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl PartialEq for SpecifiedUrl {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.url.eq(&other.url)
|
||||
|
@ -179,7 +176,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, SpecifiedValueInfo, ToComputedValue, ToCss)]
|
||||
#[derive(Clone, Debug, SpecifiedValueInfo, ToCss)]
|
||||
pub struct SpecifiedImageUrl {
|
||||
/// The specified url value.
|
||||
pub url: CssUrl,
|
||||
|
@ -190,16 +187,6 @@ pub struct SpecifiedImageUrl {
|
|||
}
|
||||
|
||||
impl SpecifiedImageUrl {
|
||||
fn from_css_url(url: CssUrl) -> Self {
|
||||
let image_value = unsafe {
|
||||
let ptr = bindings::Gecko_ImageValue_Create(url.for_ffi());
|
||||
// We do not expect Gecko_ImageValue_Create returns null.
|
||||
debug_assert!(!ptr.is_null());
|
||||
RefPtr::from_addrefed(ptr)
|
||||
};
|
||||
SpecifiedImageUrl { url, image_value }
|
||||
}
|
||||
|
||||
/// Parse a URL from a string value. See SpecifiedUrl::parse_from_string.
|
||||
pub fn parse_from_string<'a>(
|
||||
url: String,
|
||||
|
@ -208,20 +195,14 @@ impl SpecifiedImageUrl {
|
|||
CssUrl::parse_from_string(url, context).map(Self::from_css_url)
|
||||
}
|
||||
|
||||
/// Convert from URLValueData to SpecifiedUrl.
|
||||
pub unsafe fn from_url_value_data(url: &URLValueData) -> Result<Self, ()> {
|
||||
CssUrl::from_url_value_data(url).map(Self::from_css_url)
|
||||
}
|
||||
|
||||
/// Convert from nsStyleImageRequest to SpecifiedUrl.
|
||||
pub unsafe fn from_image_request(image_request: &nsStyleImageRequest) -> Result<Self, ()> {
|
||||
if image_request.mImageValue.mRawPtr.is_null() {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
let image_value = image_request.mImageValue.mRawPtr.as_ref().unwrap();
|
||||
let url_value_data = &image_value._base;
|
||||
Self::from_url_value_data(url_value_data)
|
||||
fn from_css_url(url: CssUrl) -> Self {
|
||||
let image_value = unsafe {
|
||||
let ptr = bindings::Gecko_ImageValue_Create(url.for_ffi());
|
||||
// We do not expect Gecko_ImageValue_Create returns null.
|
||||
debug_assert!(!ptr.is_null());
|
||||
RefPtr::from_addrefed(ptr)
|
||||
};
|
||||
Self { url, image_value }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,7 +234,104 @@ impl MallocSizeOf for SpecifiedImageUrl {
|
|||
}
|
||||
}
|
||||
|
||||
impl ToComputedValue for SpecifiedUrl {
|
||||
type ComputedValue = ComputedUrl;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, _: &Context) -> Self::ComputedValue {
|
||||
ComputedUrl(self.clone())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||
computed.0.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToComputedValue for SpecifiedImageUrl {
|
||||
type ComputedValue = ComputedImageUrl;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, _: &Context) -> Self::ComputedValue {
|
||||
ComputedImageUrl(self.clone())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||
computed.0.clone()
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_computed_url<W>(
|
||||
url_value_data: &URLValueData,
|
||||
dest: &mut CssWriter<W>,
|
||||
) -> fmt::Result
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
dest.write_str("url(")?;
|
||||
unsafe {
|
||||
let mut string = nsCString::new();
|
||||
bindings::Gecko_GetComputedURLSpec(url_value_data, &mut string);
|
||||
string.as_str_unchecked().to_css(dest)?;
|
||||
}
|
||||
dest.write_char(')')
|
||||
}
|
||||
|
||||
/// The computed value of a CSS `url()`.
|
||||
pub type ComputedUrl = SpecifiedUrl;
|
||||
///
|
||||
/// The only difference between specified and computed URLs is the
|
||||
/// serialization.
|
||||
#[derive(Clone, Debug, Eq, PartialEq, MallocSizeOf)]
|
||||
pub struct ComputedUrl(pub SpecifiedUrl);
|
||||
|
||||
impl ToCss for ComputedUrl {
|
||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||
where
|
||||
W: Write
|
||||
{
|
||||
serialize_computed_url(&self.0.url_value._base, dest)
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputedUrl {
|
||||
/// Convert from URLValueData to ComputedUrl.
|
||||
pub unsafe fn from_url_value_data(url: &URLValueData) -> Result<Self, ()> {
|
||||
Ok(ComputedUrl(
|
||||
SpecifiedUrl::from_css_url(CssUrl::from_url_value_data(url)?)
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// The computed value of a CSS `url()` for image.
|
||||
pub type ComputedImageUrl = SpecifiedImageUrl;
|
||||
#[derive(Clone, Debug, Eq, PartialEq, MallocSizeOf)]
|
||||
pub struct ComputedImageUrl(pub SpecifiedImageUrl);
|
||||
|
||||
impl ToCss for ComputedImageUrl {
|
||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||
where
|
||||
W: Write
|
||||
{
|
||||
serialize_computed_url(&self.0.image_value._base, dest)
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputedImageUrl {
|
||||
/// Convert from URLValueData to SpecifiedUrl.
|
||||
pub unsafe fn from_url_value_data(url: &URLValueData) -> Result<Self, ()> {
|
||||
Ok(ComputedImageUrl(
|
||||
SpecifiedImageUrl::from_css_url(CssUrl::from_url_value_data(url)?)
|
||||
))
|
||||
}
|
||||
|
||||
/// Convert from nsStyleImageReques to ComputedImageUrl.
|
||||
pub unsafe fn from_image_request(image_request: &nsStyleImageRequest) -> Result<Self, ()> {
|
||||
if image_request.mImageValue.mRawPtr.is_null() {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
let image_value = image_request.mImageValue.mRawPtr.as_ref().unwrap();
|
||||
let url_value_data = &image_value._base;
|
||||
Self::from_url_value_data(url_value_data)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -697,7 +697,7 @@ def set_gecko_property(ffi_name, expr):
|
|||
}
|
||||
SVGPaintKind::PaintServer(url) => {
|
||||
unsafe {
|
||||
bindings::Gecko_nsStyleSVGPaint_SetURLValue(paint, url.url_value.get());
|
||||
bindings::Gecko_nsStyleSVGPaint_SetURLValue(paint, url.0.url_value.get());
|
||||
}
|
||||
}
|
||||
SVGPaintKind::Color(color) => {
|
||||
|
@ -737,8 +737,8 @@ def set_gecko_property(ffi_name, expr):
|
|||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
|
||||
use values::computed::url::ComputedUrl;
|
||||
use values::generics::svg::{SVGPaint, SVGPaintKind};
|
||||
use values::specified::url::SpecifiedUrl;
|
||||
use self::structs::nsStyleSVGPaintType;
|
||||
use self::structs::nsStyleSVGFallbackType;
|
||||
let ref paint = ${get_gecko_property(gecko_ffi_name)};
|
||||
|
@ -760,7 +760,7 @@ def set_gecko_property(ffi_name, expr):
|
|||
nsStyleSVGPaintType::eStyleSVGPaintType_Server => {
|
||||
unsafe {
|
||||
SVGPaintKind::PaintServer(
|
||||
SpecifiedUrl::from_url_value_data(
|
||||
ComputedUrl::from_url_value_data(
|
||||
&(**paint.mPaint.mPaintServer.as_ref())._base
|
||||
).unwrap()
|
||||
)
|
||||
|
@ -939,7 +939,7 @@ def set_gecko_property(ffi_name, expr):
|
|||
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
|
||||
match v {
|
||||
UrlOrNone::Url(ref url) => {
|
||||
self.gecko.${gecko_ffi_name}.set_move(url.url_value.clone())
|
||||
self.gecko.${gecko_ffi_name}.set_move(url.0.url_value.clone())
|
||||
}
|
||||
UrlOrNone::None => {
|
||||
unsafe {
|
||||
|
@ -961,16 +961,18 @@ def set_gecko_property(ffi_name, expr):
|
|||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
|
||||
use values::specified::url::SpecifiedUrl;
|
||||
use values::computed::url::ComputedUrl;
|
||||
|
||||
if self.gecko.${gecko_ffi_name}.mRawPtr.is_null() {
|
||||
UrlOrNone::none()
|
||||
} else {
|
||||
unsafe {
|
||||
let ref gecko_url_value = *self.gecko.${gecko_ffi_name}.mRawPtr;
|
||||
UrlOrNone::Url(SpecifiedUrl::from_url_value_data(&gecko_url_value._base)
|
||||
.expect("${gecko_ffi_name} could not convert to SpecifiedUrl"))
|
||||
return UrlOrNone::none()
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let gecko_url_value = &*self.gecko.${gecko_ffi_name}.mRawPtr;
|
||||
UrlOrNone::Url(
|
||||
ComputedUrl::from_url_value_data(&gecko_url_value._base)
|
||||
.expect("${gecko_ffi_name} could not convert to ComputedUrl")
|
||||
)
|
||||
}
|
||||
}
|
||||
</%def>
|
||||
|
@ -4110,7 +4112,7 @@ fn static_assert() {
|
|||
}
|
||||
UrlOrNone::Url(ref url) => {
|
||||
unsafe {
|
||||
Gecko_SetListStyleImageImageValue(&mut self.gecko, url.image_value.get());
|
||||
Gecko_SetListStyleImageImageValue(&mut self.gecko, url.0.image_value.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4125,7 +4127,7 @@ fn static_assert() {
|
|||
}
|
||||
|
||||
pub fn clone_list_style_image(&self) -> longhands::list_style_image::computed_value::T {
|
||||
use values::specified::url::SpecifiedImageUrl;
|
||||
use values::computed::url::ComputedImageUrl;
|
||||
|
||||
if self.gecko.mListStyleImage.mRawPtr.is_null() {
|
||||
return UrlOrNone::None;
|
||||
|
@ -4133,8 +4135,9 @@ fn static_assert() {
|
|||
|
||||
unsafe {
|
||||
let ref gecko_image_request = *self.gecko.mListStyleImage.mRawPtr;
|
||||
UrlOrNone::Url(SpecifiedImageUrl::from_image_request(gecko_image_request)
|
||||
.expect("mListStyleImage could not convert to SpecifiedImageUrl"))
|
||||
UrlOrNone::Url(ComputedImageUrl::from_image_request(
|
||||
gecko_image_request
|
||||
).expect("mListStyleImage could not convert to ComputedImageUrl"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4480,7 +4483,7 @@ fn static_assert() {
|
|||
},
|
||||
Url(ref url) => {
|
||||
unsafe {
|
||||
bindings::Gecko_nsStyleFilter_SetURLValue(gecko_filter, url.url_value.get());
|
||||
bindings::Gecko_nsStyleFilter_SetURLValue(gecko_filter, url.0.url_value.get());
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -4499,7 +4502,7 @@ fn static_assert() {
|
|||
|
||||
pub fn clone_filter(&self) -> longhands::filter::computed_value::T {
|
||||
use values::generics::effects::Filter;
|
||||
use values::specified::url::SpecifiedUrl;
|
||||
use values::computed::url::ComputedUrl;
|
||||
use gecko_bindings::structs::NS_STYLE_FILTER_BLUR;
|
||||
use gecko_bindings::structs::NS_STYLE_FILTER_BRIGHTNESS;
|
||||
use gecko_bindings::structs::NS_STYLE_FILTER_CONTRAST;
|
||||
|
@ -4541,7 +4544,7 @@ fn static_assert() {
|
|||
NS_STYLE_FILTER_URL => {
|
||||
filters.push(unsafe {
|
||||
Filter::Url(
|
||||
SpecifiedUrl::from_url_value_data(&(**filter.__bindgen_anon_1.mURL.as_ref())._base).unwrap()
|
||||
ComputedUrl::from_url_value_data(&(**filter.__bindgen_anon_1.mURL.as_ref())._base).unwrap()
|
||||
)
|
||||
});
|
||||
}
|
||||
|
@ -5007,7 +5010,7 @@ fn static_assert() {
|
|||
% if ident == "clip_path":
|
||||
ShapeSource::ImageOrUrl(ref url) => {
|
||||
unsafe {
|
||||
bindings::Gecko_StyleShapeSource_SetURLValue(${ident}, url.url_value.get())
|
||||
bindings::Gecko_StyleShapeSource_SetURLValue(${ident}, url.0.url_value.get())
|
||||
}
|
||||
}
|
||||
% elif ident == "shape_outside":
|
||||
|
@ -5347,7 +5350,7 @@ clip-path
|
|||
unsafe {
|
||||
Gecko_SetCursorImageValue(
|
||||
&mut self.gecko.mCursorImages[i],
|
||||
v.images[i].url.image_value.get(),
|
||||
v.images[i].url.0.image_value.get(),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -5377,8 +5380,8 @@ clip-path
|
|||
|
||||
pub fn clone_cursor(&self) -> longhands::cursor::computed_value::T {
|
||||
use values::computed::ui::CursorImage;
|
||||
use values::computed::url::ComputedImageUrl;
|
||||
use style_traits::cursor::CursorKind;
|
||||
use values::specified::url::SpecifiedImageUrl;
|
||||
|
||||
let keyword = match self.gecko.mCursor as u32 {
|
||||
structs::NS_STYLE_CURSOR_AUTO => CursorKind::Auto,
|
||||
|
@ -5423,8 +5426,8 @@ clip-path
|
|||
let images = self.gecko.mCursorImages.iter().map(|gecko_cursor_image| {
|
||||
let url = unsafe {
|
||||
let gecko_image_request = gecko_cursor_image.mImage.mRawPtr.as_ref().unwrap();
|
||||
SpecifiedImageUrl::from_image_request(&gecko_image_request)
|
||||
.expect("mCursorImages.mImage could not convert to SpecifiedImageUrl")
|
||||
ComputedImageUrl::from_image_request(&gecko_image_request)
|
||||
.expect("mCursorImages.mImage could not convert to ComputedImageUrl")
|
||||
};
|
||||
|
||||
let hotspot =
|
||||
|
@ -5483,7 +5486,7 @@ clip-path
|
|||
|
||||
pub fn set_content(&mut self, v: longhands::content::computed_value::T, device: &Device) {
|
||||
use values::CustomIdent;
|
||||
use values::computed::counters::{Content, ContentItem};
|
||||
use values::generics::counters::{Content, ContentItem};
|
||||
use values::generics::CounterStyleOrNone;
|
||||
use gecko_bindings::structs::nsStyleContentData;
|
||||
use gecko_bindings::structs::nsStyleContentAttr;
|
||||
|
@ -5610,7 +5613,7 @@ clip-path
|
|||
unsafe {
|
||||
bindings::Gecko_SetContentDataImageValue(
|
||||
&mut self.gecko.mContents[i],
|
||||
url.image_value.get(),
|
||||
url.0.image_value.get(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -5635,10 +5638,10 @@ clip-path
|
|||
use {Atom, Namespace};
|
||||
use gecko::conversions::string_from_chars_pointer;
|
||||
use gecko_bindings::structs::nsStyleContentType::*;
|
||||
use values::computed::counters::{Content, ContentItem};
|
||||
use values::generics::counters::{Content, ContentItem};
|
||||
use values::computed::url::ComputedImageUrl;
|
||||
use values::{CustomIdent, Either};
|
||||
use values::generics::CounterStyleOrNone;
|
||||
use values::specified::url::SpecifiedImageUrl;
|
||||
use values::specified::Attr;
|
||||
|
||||
if self.gecko.mContents.is_empty() {
|
||||
|
@ -5699,8 +5702,8 @@ clip-path
|
|||
let gecko_image_request =
|
||||
&**gecko_content.mContent.mImage.as_ref();
|
||||
ContentItem::Url(
|
||||
SpecifiedImageUrl::from_image_request(gecko_image_request)
|
||||
.expect("mContent could not convert to SpecifiedImageUrl")
|
||||
ComputedImageUrl::from_image_request(gecko_image_request)
|
||||
.expect("mContent could not convert to ComputedImageUrl")
|
||||
)
|
||||
}
|
||||
},
|
||||
|
|
|
@ -14,6 +14,7 @@ use values::animated::{Animate, Procedure, ToAnimatedValue, ToAnimatedZero};
|
|||
use values::animated::color::RGBA;
|
||||
use values::computed::{Angle, Number};
|
||||
use values::computed::length::Length;
|
||||
use values::computed::url::ComputedUrl;
|
||||
use values::distance::{ComputeSquaredDistance, SquaredDistance};
|
||||
use values::generics::effects::BoxShadow as GenericBoxShadow;
|
||||
use values::generics::effects::Filter as GenericFilter;
|
||||
|
@ -42,11 +43,11 @@ pub struct FilterList(pub Vec<Filter>);
|
|||
|
||||
/// An animated value for a single `filter`.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub type Filter = GenericFilter<Angle, Number, Length, SimpleShadow>;
|
||||
pub type Filter = GenericFilter<Angle, Number, Length, SimpleShadow, ComputedUrl>;
|
||||
|
||||
/// An animated value for a single `filter`.
|
||||
#[cfg(not(feature = "gecko"))]
|
||||
pub type Filter = GenericFilter<Angle, Number, Length, Impossible>;
|
||||
pub type Filter = GenericFilter<Angle, Number, Length, Impossible, ComputedUrl>;
|
||||
|
||||
/// An animated value for the `drop-shadow()` filter.
|
||||
pub type SimpleShadow = GenericSimpleShadow<Option<RGBA>, Length, Length>;
|
||||
|
|
|
@ -15,9 +15,7 @@ use values::computed::Angle as ComputedAngle;
|
|||
use values::computed::BorderCornerRadius as ComputedBorderCornerRadius;
|
||||
use values::computed::MaxLength as ComputedMaxLength;
|
||||
use values::computed::MozLength as ComputedMozLength;
|
||||
#[cfg(feature = "servo")]
|
||||
use values::computed::url::ComputedUrl;
|
||||
use values::specified::url::SpecifiedUrl;
|
||||
|
||||
pub mod color;
|
||||
pub mod effects;
|
||||
|
@ -260,8 +258,6 @@ macro_rules! trivial_to_animated_value {
|
|||
|
||||
trivial_to_animated_value!(Au);
|
||||
trivial_to_animated_value!(ComputedAngle);
|
||||
trivial_to_animated_value!(SpecifiedUrl);
|
||||
#[cfg(feature = "servo")]
|
||||
trivial_to_animated_value!(ComputedUrl);
|
||||
trivial_to_animated_value!(bool);
|
||||
trivial_to_animated_value!(f32);
|
||||
|
|
|
@ -4,22 +4,10 @@
|
|||
|
||||
//! Computed values for counter properties
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
use computed_values::list_style_type::T as ListStyleType;
|
||||
use cssparser::{Parser, Token};
|
||||
use parser::{Parse, ParserContext};
|
||||
use selectors::parser::SelectorParseErrorKind;
|
||||
use style_traits::{ParseError, StyleParseErrorKind};
|
||||
use values::CustomIdent;
|
||||
#[cfg(feature = "gecko")]
|
||||
use values::generics::CounterStyleOrNone;
|
||||
use values::computed::url::ComputedImageUrl;
|
||||
use values::generics::counters as generics;
|
||||
use values::generics::counters::CounterIncrement as GenericCounterIncrement;
|
||||
use values::generics::counters::CounterReset as GenericCounterReset;
|
||||
#[cfg(feature = "gecko")]
|
||||
use values::specified::Attr;
|
||||
#[cfg(feature = "gecko")]
|
||||
use values::specified::url::SpecifiedImageUrl;
|
||||
pub use values::specified::{Content, ContentItem};
|
||||
|
||||
/// A computed value for the `counter-increment` property.
|
||||
pub type CounterIncrement = GenericCounterIncrement<i32>;
|
||||
|
@ -27,134 +15,9 @@ pub type CounterIncrement = GenericCounterIncrement<i32>;
|
|||
/// A computed value for the `counter-increment` property.
|
||||
pub type CounterReset = GenericCounterReset<i32>;
|
||||
|
||||
impl Content {
|
||||
/// Set `content` property to `normal`.
|
||||
#[inline]
|
||||
pub fn normal() -> Self {
|
||||
Content::Normal
|
||||
}
|
||||
/// A computed value for the `content` property.
|
||||
pub type Content = generics::Content<ComputedImageUrl>;
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
fn parse_counter_style(input: &mut Parser) -> ListStyleType {
|
||||
input
|
||||
.try(|input| {
|
||||
input.expect_comma()?;
|
||||
ListStyleType::parse(input)
|
||||
})
|
||||
.unwrap_or(ListStyleType::Decimal)
|
||||
}
|
||||
/// A computed content item.
|
||||
pub type ContentItem = generics::ContentItem<ComputedImageUrl>;
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
fn parse_counter_style(context: &ParserContext, input: &mut Parser) -> CounterStyleOrNone {
|
||||
input
|
||||
.try(|input| {
|
||||
input.expect_comma()?;
|
||||
CounterStyleOrNone::parse(context, input)
|
||||
})
|
||||
.unwrap_or(CounterStyleOrNone::decimal())
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for Content {
|
||||
// normal | none | [ <string> | <counter> | open-quote | close-quote | no-open-quote |
|
||||
// no-close-quote ]+
|
||||
// TODO: <uri>, attr(<identifier>)
|
||||
fn parse<'i, 't>(
|
||||
_context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
if input
|
||||
.try(|input| input.expect_ident_matching("normal"))
|
||||
.is_ok()
|
||||
{
|
||||
return Ok(Content::Normal);
|
||||
}
|
||||
if input
|
||||
.try(|input| input.expect_ident_matching("none"))
|
||||
.is_ok()
|
||||
{
|
||||
return Ok(Content::None);
|
||||
}
|
||||
#[cfg(feature = "gecko")]
|
||||
{
|
||||
if input
|
||||
.try(|input| input.expect_ident_matching("-moz-alt-content"))
|
||||
.is_ok()
|
||||
{
|
||||
return Ok(Content::MozAltContent);
|
||||
}
|
||||
}
|
||||
|
||||
let mut content = vec![];
|
||||
loop {
|
||||
#[cfg(feature = "gecko")]
|
||||
{
|
||||
if let Ok(url) = input.try(|i| SpecifiedImageUrl::parse(_context, i)) {
|
||||
content.push(ContentItem::Url(url));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// FIXME: remove clone() when lifetimes are non-lexical
|
||||
match input.next().map(|t| t.clone()) {
|
||||
Ok(Token::QuotedString(ref value)) => {
|
||||
content.push(ContentItem::String(
|
||||
value.as_ref().to_owned().into_boxed_str(),
|
||||
));
|
||||
},
|
||||
Ok(Token::Function(ref name)) => {
|
||||
let result = match_ignore_ascii_case! { &name,
|
||||
"counter" => Some(input.parse_nested_block(|input| {
|
||||
let location = input.current_source_location();
|
||||
let name = CustomIdent::from_ident(location, input.expect_ident()?, &[])?;
|
||||
#[cfg(feature = "servo")]
|
||||
let style = Content::parse_counter_style(input);
|
||||
#[cfg(feature = "gecko")]
|
||||
let style = Content::parse_counter_style(_context, input);
|
||||
Ok(ContentItem::Counter(name, style))
|
||||
})),
|
||||
"counters" => Some(input.parse_nested_block(|input| {
|
||||
let location = input.current_source_location();
|
||||
let name = CustomIdent::from_ident(location, input.expect_ident()?, &[])?;
|
||||
input.expect_comma()?;
|
||||
let separator = input.expect_string()?.as_ref().to_owned().into_boxed_str();
|
||||
#[cfg(feature = "servo")]
|
||||
let style = Content::parse_counter_style(input);
|
||||
#[cfg(feature = "gecko")]
|
||||
let style = Content::parse_counter_style(_context, input);
|
||||
Ok(ContentItem::Counters(name, separator, style))
|
||||
})),
|
||||
#[cfg(feature = "gecko")]
|
||||
"attr" => Some(input.parse_nested_block(|input| {
|
||||
Ok(ContentItem::Attr(Attr::parse_function(_context, input)?))
|
||||
})),
|
||||
_ => None
|
||||
};
|
||||
match result {
|
||||
Some(result) => content.push(result?),
|
||||
None => {
|
||||
return Err(input.new_custom_error(
|
||||
StyleParseErrorKind::UnexpectedFunction(name.clone()),
|
||||
))
|
||||
},
|
||||
}
|
||||
},
|
||||
Ok(Token::Ident(ref ident)) => {
|
||||
content.push(match_ignore_ascii_case! { &ident,
|
||||
"open-quote" => ContentItem::OpenQuote,
|
||||
"close-quote" => ContentItem::CloseQuote,
|
||||
"no-open-quote" => ContentItem::NoOpenQuote,
|
||||
"no-close-quote" => ContentItem::NoCloseQuote,
|
||||
_ => return Err(input.new_custom_error(
|
||||
SelectorParseErrorKind::UnexpectedIdent(ident.clone())))
|
||||
});
|
||||
},
|
||||
Err(_) => break,
|
||||
Ok(t) => return Err(input.new_unexpected_token_error(t)),
|
||||
}
|
||||
}
|
||||
if content.is_empty() {
|
||||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||
}
|
||||
Ok(Content::Items(content.into_boxed_slice()))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ use values::Impossible;
|
|||
use values::computed::{Angle, NonNegativeNumber};
|
||||
use values::computed::color::RGBAColor;
|
||||
use values::computed::length::{Length, NonNegativeLength};
|
||||
use values::computed::url::ComputedUrl;
|
||||
use values::generics::effects::BoxShadow as GenericBoxShadow;
|
||||
use values::generics::effects::Filter as GenericFilter;
|
||||
use values::generics::effects::SimpleShadow as GenericSimpleShadow;
|
||||
|
@ -18,11 +19,11 @@ pub type BoxShadow = GenericBoxShadow<Option<RGBAColor>, Length, NonNegativeLeng
|
|||
|
||||
/// A computed value for a single `filter`.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub type Filter = GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, SimpleShadow>;
|
||||
pub type Filter = GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, SimpleShadow, ComputedUrl>;
|
||||
|
||||
/// A computed value for a single `filter`.
|
||||
#[cfg(not(feature = "gecko"))]
|
||||
pub type Filter = GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, Impossible>;
|
||||
pub type Filter = GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, Impossible, ComputedUrl>;
|
||||
|
||||
/// A computed value for the `drop-shadow()` filter.
|
||||
pub type SimpleShadow = GenericSimpleShadow<Option<RGBAColor>, Length, NonNegativeLength>;
|
||||
|
|
|
@ -4,8 +4,14 @@
|
|||
|
||||
//! Generic types for counters-related CSS values.
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
use computed_values::list_style_type::T as ListStyleType;
|
||||
use std::ops::Deref;
|
||||
use values::CustomIdent;
|
||||
#[cfg(feature = "gecko")]
|
||||
use values::generics::CounterStyleOrNone;
|
||||
#[cfg(feature = "gecko")]
|
||||
use values::specified::Attr;
|
||||
|
||||
/// A name / value pair for counters.
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
||||
|
@ -74,3 +80,78 @@ impl<I> Default for Counters<I> {
|
|||
Counters(vec![].into_boxed_slice())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
type CounterStyleType = ListStyleType;
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
type CounterStyleType = CounterStyleOrNone;
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
#[inline]
|
||||
fn is_decimal(counter_type: &CounterStyleType) -> bool {
|
||||
*counter_type == ListStyleType::Decimal
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
#[inline]
|
||||
fn is_decimal(counter_type: &CounterStyleType) -> bool {
|
||||
*counter_type == CounterStyleOrNone::decimal()
|
||||
}
|
||||
|
||||
/// The specified value for the `content` property.
|
||||
///
|
||||
/// https://drafts.csswg.org/css-content/#propdef-content
|
||||
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
||||
ToComputedValue, ToCss)]
|
||||
pub enum Content<ImageUrl> {
|
||||
/// `normal` reserved keyword.
|
||||
Normal,
|
||||
/// `none` reserved keyword.
|
||||
None,
|
||||
/// `-moz-alt-content`.
|
||||
#[cfg(feature = "gecko")]
|
||||
MozAltContent,
|
||||
/// Content items.
|
||||
Items(#[css(iterable)] Box<[ContentItem<ImageUrl>]>),
|
||||
}
|
||||
|
||||
impl<ImageUrl> Content<ImageUrl> {
|
||||
/// Set `content` property to `normal`.
|
||||
#[inline]
|
||||
pub fn normal() -> Self {
|
||||
Content::Normal
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Items for the `content` property.
|
||||
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
||||
ToComputedValue, ToCss)]
|
||||
pub enum ContentItem<ImageUrl> {
|
||||
/// Literal string content.
|
||||
String(Box<str>),
|
||||
/// `counter(name, style)`.
|
||||
#[css(comma, function)]
|
||||
Counter(CustomIdent, #[css(skip_if = "is_decimal")] CounterStyleType),
|
||||
/// `counters(name, separator, style)`.
|
||||
#[css(comma, function)]
|
||||
Counters(
|
||||
CustomIdent,
|
||||
Box<str>,
|
||||
#[css(skip_if = "is_decimal")] CounterStyleType,
|
||||
),
|
||||
/// `open-quote`.
|
||||
OpenQuote,
|
||||
/// `close-quote`.
|
||||
CloseQuote,
|
||||
/// `no-open-quote`.
|
||||
NoOpenQuote,
|
||||
/// `no-close-quote`.
|
||||
NoCloseQuote,
|
||||
/// `attr([namespace? `|`]? ident)`
|
||||
#[cfg(feature = "gecko")]
|
||||
Attr(Attr),
|
||||
/// `url(url)`
|
||||
Url(ImageUrl),
|
||||
}
|
||||
|
|
|
@ -4,9 +4,6 @@
|
|||
|
||||
//! Generic types for CSS values related to effects.
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
use values::specified::url::SpecifiedUrl;
|
||||
|
||||
/// A generic value for a single `box-shadow`.
|
||||
#[derive(Animate, Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
||||
ToAnimatedValue, ToAnimatedZero, ToCss)]
|
||||
|
@ -23,9 +20,10 @@ pub struct BoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength> {
|
|||
|
||||
/// A generic value for a single `filter`.
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
#[animation(no_bound(Url))]
|
||||
#[derive(Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq,
|
||||
SpecifiedValueInfo, ToAnimatedValue, ToComputedValue, ToCss)]
|
||||
pub enum Filter<Angle, Factor, Length, DropShadow> {
|
||||
pub enum Filter<Angle, Factor, Length, DropShadow, Url> {
|
||||
/// `blur(<length>)`
|
||||
#[css(function)]
|
||||
Blur(Length),
|
||||
|
@ -58,8 +56,7 @@ pub enum Filter<Angle, Factor, Length, DropShadow> {
|
|||
DropShadow(DropShadow),
|
||||
/// `<url>`
|
||||
#[animation(error)]
|
||||
#[cfg(feature = "gecko")]
|
||||
Url(SpecifiedUrl),
|
||||
Url(Url),
|
||||
}
|
||||
|
||||
/// A generic value for the `drop-shadow()` filter and the `text-shadow` property.
|
||||
|
|
|
@ -8,18 +8,19 @@
|
|||
use computed_values::list_style_type::T as ListStyleType;
|
||||
use cssparser::{Parser, Token};
|
||||
use parser::{Parse, ParserContext};
|
||||
use selectors::parser::SelectorParseErrorKind;
|
||||
use style_traits::{ParseError, StyleParseErrorKind};
|
||||
use values::CustomIdent;
|
||||
#[cfg(feature = "gecko")]
|
||||
use values::generics::CounterStyleOrNone;
|
||||
use values::generics::counters as generics;
|
||||
use values::generics::counters::CounterIncrement as GenericCounterIncrement;
|
||||
use values::generics::counters::CounterPair;
|
||||
use values::generics::counters::CounterReset as GenericCounterReset;
|
||||
use values::specified::Integer;
|
||||
use values::specified::url::SpecifiedImageUrl;
|
||||
#[cfg(feature = "gecko")]
|
||||
use values::specified::Attr;
|
||||
use values::specified::Integer;
|
||||
#[cfg(feature = "gecko")]
|
||||
use values::specified::url::SpecifiedImageUrl;
|
||||
|
||||
/// A specified value for the `counter-increment` property.
|
||||
pub type CounterIncrement = GenericCounterIncrement<Integer>;
|
||||
|
@ -79,69 +80,129 @@ fn parse_counters<'i, 't>(
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
type CounterStyleType = ListStyleType;
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
type CounterStyleType = CounterStyleOrNone;
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
#[inline]
|
||||
fn is_decimal(counter_type: &CounterStyleType) -> bool {
|
||||
*counter_type == ListStyleType::Decimal
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
#[inline]
|
||||
fn is_decimal(counter_type: &CounterStyleType) -> bool {
|
||||
*counter_type == CounterStyleOrNone::decimal()
|
||||
}
|
||||
|
||||
/// The specified value for the `content` property.
|
||||
///
|
||||
/// https://drafts.csswg.org/css-content/#propdef-content
|
||||
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
||||
ToComputedValue, ToCss)]
|
||||
pub enum Content {
|
||||
/// `normal` reserved keyword.
|
||||
Normal,
|
||||
/// `none` reserved keyword.
|
||||
None,
|
||||
/// `-moz-alt-content`.
|
||||
pub type Content = generics::Content<SpecifiedImageUrl>;
|
||||
|
||||
/// The specified value for a content item in the `content` property.
|
||||
pub type ContentItem = generics::ContentItem<SpecifiedImageUrl>;
|
||||
|
||||
impl Content {
|
||||
#[cfg(feature = "servo")]
|
||||
fn parse_counter_style(_: &ParserContext, input: &mut Parser) -> ListStyleType {
|
||||
input
|
||||
.try(|input| {
|
||||
input.expect_comma()?;
|
||||
ListStyleType::parse(input)
|
||||
})
|
||||
.unwrap_or(ListStyleType::Decimal)
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
MozAltContent,
|
||||
/// Content items.
|
||||
Items(#[css(iterable)] Box<[ContentItem]>),
|
||||
fn parse_counter_style(context: &ParserContext, input: &mut Parser) -> CounterStyleOrNone {
|
||||
input
|
||||
.try(|input| {
|
||||
input.expect_comma()?;
|
||||
CounterStyleOrNone::parse(context, input)
|
||||
})
|
||||
.unwrap_or(CounterStyleOrNone::decimal())
|
||||
}
|
||||
}
|
||||
|
||||
/// Items for the `content` property.
|
||||
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
||||
ToComputedValue, ToCss)]
|
||||
pub enum ContentItem {
|
||||
/// Literal string content.
|
||||
String(Box<str>),
|
||||
/// `counter(name, style)`.
|
||||
#[css(comma, function)]
|
||||
Counter(CustomIdent, #[css(skip_if = "is_decimal")] CounterStyleType),
|
||||
/// `counters(name, separator, style)`.
|
||||
#[css(comma, function)]
|
||||
Counters(
|
||||
CustomIdent,
|
||||
Box<str>,
|
||||
#[css(skip_if = "is_decimal")] CounterStyleType,
|
||||
),
|
||||
/// `open-quote`.
|
||||
OpenQuote,
|
||||
/// `close-quote`.
|
||||
CloseQuote,
|
||||
/// `no-open-quote`.
|
||||
NoOpenQuote,
|
||||
/// `no-close-quote`.
|
||||
NoCloseQuote,
|
||||
/// `attr([namespace? `|`]? ident)`
|
||||
impl Parse for Content {
|
||||
// normal | none | [ <string> | <counter> | open-quote | close-quote | no-open-quote |
|
||||
// no-close-quote ]+
|
||||
// TODO: <uri>, attr(<identifier>)
|
||||
fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
if input
|
||||
.try(|input| input.expect_ident_matching("normal"))
|
||||
.is_ok()
|
||||
{
|
||||
return Ok(generics::Content::Normal);
|
||||
}
|
||||
if input
|
||||
.try(|input| input.expect_ident_matching("none"))
|
||||
.is_ok()
|
||||
{
|
||||
return Ok(generics::Content::None);
|
||||
}
|
||||
#[cfg(feature = "gecko")]
|
||||
Attr(Attr),
|
||||
/// `url(url)`
|
||||
{
|
||||
if input
|
||||
.try(|input| input.expect_ident_matching("-moz-alt-content"))
|
||||
.is_ok()
|
||||
{
|
||||
return Ok(generics::Content::MozAltContent);
|
||||
}
|
||||
}
|
||||
|
||||
let mut content = vec![];
|
||||
loop {
|
||||
#[cfg(feature = "gecko")]
|
||||
Url(SpecifiedImageUrl),
|
||||
{
|
||||
if let Ok(url) = input.try(|i| SpecifiedImageUrl::parse(context, i)) {
|
||||
content.push(generics::ContentItem::Url(url));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// FIXME: remove clone() when lifetimes are non-lexical
|
||||
match input.next().map(|t| t.clone()) {
|
||||
Ok(Token::QuotedString(ref value)) => {
|
||||
content.push(generics::ContentItem::String(
|
||||
value.as_ref().to_owned().into_boxed_str(),
|
||||
));
|
||||
},
|
||||
Ok(Token::Function(ref name)) => {
|
||||
let result = match_ignore_ascii_case! { &name,
|
||||
"counter" => Some(input.parse_nested_block(|input| {
|
||||
let location = input.current_source_location();
|
||||
let name = CustomIdent::from_ident(location, input.expect_ident()?, &[])?;
|
||||
let style = Content::parse_counter_style(context, input);
|
||||
Ok(generics::ContentItem::Counter(name, style))
|
||||
})),
|
||||
"counters" => Some(input.parse_nested_block(|input| {
|
||||
let location = input.current_source_location();
|
||||
let name = CustomIdent::from_ident(location, input.expect_ident()?, &[])?;
|
||||
input.expect_comma()?;
|
||||
let separator = input.expect_string()?.as_ref().to_owned().into_boxed_str();
|
||||
let style = Content::parse_counter_style(context, input);
|
||||
Ok(generics::ContentItem::Counters(name, separator, style))
|
||||
})),
|
||||
#[cfg(feature = "gecko")]
|
||||
"attr" => Some(input.parse_nested_block(|input| {
|
||||
Ok(generics::ContentItem::Attr(Attr::parse_function(context, input)?))
|
||||
})),
|
||||
_ => None
|
||||
};
|
||||
match result {
|
||||
Some(result) => content.push(result?),
|
||||
None => {
|
||||
return Err(input.new_custom_error(
|
||||
StyleParseErrorKind::UnexpectedFunction(name.clone()),
|
||||
))
|
||||
},
|
||||
}
|
||||
},
|
||||
Ok(Token::Ident(ref ident)) => {
|
||||
content.push(match_ignore_ascii_case! { &ident,
|
||||
"open-quote" => generics::ContentItem::OpenQuote,
|
||||
"close-quote" => generics::ContentItem::CloseQuote,
|
||||
"no-open-quote" => generics::ContentItem::NoOpenQuote,
|
||||
"no-close-quote" => generics::ContentItem::NoCloseQuote,
|
||||
_ => return Err(input.new_custom_error(
|
||||
SelectorParseErrorKind::UnexpectedIdent(ident.clone())
|
||||
))
|
||||
});
|
||||
},
|
||||
Err(_) => break,
|
||||
Ok(t) => return Err(input.new_unexpected_token_error(t)),
|
||||
}
|
||||
}
|
||||
if content.is_empty() {
|
||||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||
}
|
||||
Ok(generics::Content::Items(content.into_boxed_slice()))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ use values::generics::effects::SimpleShadow as GenericSimpleShadow;
|
|||
use values::specified::{Angle, NumberOrPercentage};
|
||||
use values::specified::color::RGBAColor;
|
||||
use values::specified::length::{Length, NonNegativeLength};
|
||||
#[cfg(feature = "gecko")]
|
||||
use values::specified::url::SpecifiedUrl;
|
||||
|
||||
/// A specified value for a single shadow of the `box-shadow` property.
|
||||
|
@ -28,11 +27,11 @@ pub type BoxShadow =
|
|||
|
||||
/// A specified value for a single `filter`.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub type Filter = GenericFilter<Angle, Factor, NonNegativeLength, SimpleShadow>;
|
||||
pub type Filter = GenericFilter<Angle, Factor, NonNegativeLength, SimpleShadow, SpecifiedUrl>;
|
||||
|
||||
/// A specified value for a single `filter`.
|
||||
#[cfg(not(feature = "gecko"))]
|
||||
pub type Filter = GenericFilter<Angle, Factor, NonNegativeLength, Impossible>;
|
||||
pub type Filter = GenericFilter<Angle, Factor, NonNegativeLength, Impossible, SpecifiedUrl>;
|
||||
|
||||
/// A value for the `<factor>` parts in `Filter`.
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue