mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
Introduce ComputedUrl
Add web platform tests for computed URL styles Mark url with no original or resolved unreachable Update the WPT manifest for new url tests
This commit is contained in:
parent
f6aa17add9
commit
14c5a1b8d3
17 changed files with 197 additions and 46 deletions
|
@ -44,7 +44,7 @@ use values::animated::effects::FilterList as AnimatedFilterList;
|
||||||
use values::animated::effects::TextShadowList as AnimatedTextShadowList;
|
use values::animated::effects::TextShadowList as AnimatedTextShadowList;
|
||||||
use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
|
use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
|
||||||
use values::computed::{BorderCornerRadius, ClipRect};
|
use values::computed::{BorderCornerRadius, ClipRect};
|
||||||
use values::computed::{CalcLengthOrPercentage, Color, Context, ComputedValueAsSpecified};
|
use values::computed::{CalcLengthOrPercentage, Color, Context, ComputedValueAsSpecified, ComputedUrl};
|
||||||
use values::computed::{LengthOrPercentage, MaxLength, MozLength, Percentage, ToComputedValue};
|
use values::computed::{LengthOrPercentage, MaxLength, MozLength, Percentage, ToComputedValue};
|
||||||
use values::computed::{NonNegativeAu, NonNegativeNumber, PositiveIntegerOrAuto};
|
use values::computed::{NonNegativeAu, NonNegativeNumber, PositiveIntegerOrAuto};
|
||||||
use values::computed::length::{NonNegativeLengthOrAuto, NonNegativeLengthOrNormal};
|
use values::computed::length::{NonNegativeLengthOrAuto, NonNegativeLengthOrNormal};
|
||||||
|
@ -2974,10 +2974,10 @@ impl ToAnimatedZero for IntermediateColor {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Animatable SVGPaint
|
/// Animatable SVGPaint
|
||||||
pub type IntermediateSVGPaint = SVGPaint<IntermediateRGBA>;
|
pub type IntermediateSVGPaint = SVGPaint<IntermediateRGBA, ComputedUrl>;
|
||||||
|
|
||||||
/// Animatable SVGPaintKind
|
/// Animatable SVGPaintKind
|
||||||
pub type IntermediateSVGPaintKind = SVGPaintKind<IntermediateRGBA>;
|
pub type IntermediateSVGPaintKind = SVGPaintKind<IntermediateRGBA, ComputedUrl>;
|
||||||
|
|
||||||
impl Animatable for IntermediateSVGPaint {
|
impl Animatable for IntermediateSVGPaint {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -12,6 +12,7 @@ use std::fmt;
|
||||||
// the threshold.
|
// the threshold.
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use style_traits::{ToCss, ParseError};
|
use style_traits::{ToCss, ParseError};
|
||||||
|
use values::computed::{Context, ToComputedValue, ComputedUrl};
|
||||||
|
|
||||||
/// A specified url() value for servo.
|
/// A specified url() value for servo.
|
||||||
///
|
///
|
||||||
|
@ -126,3 +127,35 @@ impl ToCss for SpecifiedUrl {
|
||||||
dest.write_str(")")
|
dest.write_str(")")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToComputedValue for SpecifiedUrl {
|
||||||
|
type ComputedValue = ComputedUrl;
|
||||||
|
|
||||||
|
// If we can't resolve the URL from the specified one, we fall back to the original
|
||||||
|
// but still return it as a ComputedUrl::Invalid
|
||||||
|
fn to_computed_value(&self, _: &Context) -> Self::ComputedValue {
|
||||||
|
match self.resolved {
|
||||||
|
Some(ref url) => ComputedUrl::Valid(url.clone()),
|
||||||
|
None => match self.original {
|
||||||
|
Some(ref url) => ComputedUrl::Invalid(url.clone()),
|
||||||
|
None => {
|
||||||
|
unreachable!("Found specified url with neither resolved or original URI!");
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_computed_value(computed: &ComputedUrl) -> Self {
|
||||||
|
match *computed {
|
||||||
|
ComputedUrl::Valid(ref url) => SpecifiedUrl {
|
||||||
|
original: None,
|
||||||
|
resolved: Some(url.clone()),
|
||||||
|
},
|
||||||
|
ComputedUrl::Invalid(ref url) => SpecifiedUrl {
|
||||||
|
original: Some(url.clone()),
|
||||||
|
resolved: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,8 @@ use smallvec::SmallVec;
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
use values::computed::Angle as ComputedAngle;
|
use values::computed::Angle as ComputedAngle;
|
||||||
use values::computed::BorderCornerRadius as ComputedBorderCornerRadius;
|
use values::computed::BorderCornerRadius as ComputedBorderCornerRadius;
|
||||||
|
#[cfg(feature = "servo")]
|
||||||
|
use values::computed::ComputedUrl;
|
||||||
use values::computed::GreaterThanOrEqualToOneNumber as ComputedGreaterThanOrEqualToOneNumber;
|
use values::computed::GreaterThanOrEqualToOneNumber as ComputedGreaterThanOrEqualToOneNumber;
|
||||||
use values::computed::MaxLength as ComputedMaxLength;
|
use values::computed::MaxLength as ComputedMaxLength;
|
||||||
use values::computed::MozLength as ComputedMozLength;
|
use values::computed::MozLength as ComputedMozLength;
|
||||||
|
@ -95,6 +97,8 @@ pub trait AnimatedValueAsComputed {}
|
||||||
impl AnimatedValueAsComputed for Au {}
|
impl AnimatedValueAsComputed for Au {}
|
||||||
impl AnimatedValueAsComputed for ComputedAngle {}
|
impl AnimatedValueAsComputed for ComputedAngle {}
|
||||||
impl AnimatedValueAsComputed for SpecifiedUrl {}
|
impl AnimatedValueAsComputed for SpecifiedUrl {}
|
||||||
|
#[cfg(feature = "servo")]
|
||||||
|
impl AnimatedValueAsComputed for ComputedUrl {}
|
||||||
impl AnimatedValueAsComputed for bool {}
|
impl AnimatedValueAsComputed for bool {}
|
||||||
impl AnimatedValueAsComputed for f32 {}
|
impl AnimatedValueAsComputed for f32 {}
|
||||||
|
|
||||||
|
|
|
@ -9,17 +9,17 @@
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use values::computed::LengthOrPercentage;
|
use values::computed::{LengthOrPercentage, ComputedUrl};
|
||||||
use values::generics::basic_shape::{BasicShape as GenericBasicShape};
|
use values::generics::basic_shape::{BasicShape as GenericBasicShape};
|
||||||
use values::generics::basic_shape::{Circle as GenericCircle, ClippingShape as GenericClippingShape};
|
use values::generics::basic_shape::{Circle as GenericCircle, ClippingShape as GenericClippingShape};
|
||||||
use values::generics::basic_shape::{Ellipse as GenericEllipse, FloatAreaShape as GenericFloatAreaShape};
|
use values::generics::basic_shape::{Ellipse as GenericEllipse, FloatAreaShape as GenericFloatAreaShape};
|
||||||
use values::generics::basic_shape::{InsetRect as GenericInsetRect, ShapeRadius as GenericShapeRadius};
|
use values::generics::basic_shape::{InsetRect as GenericInsetRect, ShapeRadius as GenericShapeRadius};
|
||||||
|
|
||||||
/// A specified clipping shape.
|
/// A specified clipping shape.
|
||||||
pub type ClippingShape = GenericClippingShape<BasicShape>;
|
pub type ClippingShape = GenericClippingShape<BasicShape, ComputedUrl>;
|
||||||
|
|
||||||
/// A specified float area shape.
|
/// A specified float area shape.
|
||||||
pub type FloatAreaShape = GenericFloatAreaShape<BasicShape>;
|
pub type FloatAreaShape = GenericFloatAreaShape<BasicShape, ComputedUrl>;
|
||||||
|
|
||||||
/// A computed basic shape.
|
/// A computed basic shape.
|
||||||
pub type BasicShape = GenericBasicShape<LengthOrPercentage, LengthOrPercentage, LengthOrPercentage>;
|
pub type BasicShape = GenericBasicShape<LengthOrPercentage, LengthOrPercentage, LengthOrPercentage>;
|
||||||
|
|
|
@ -12,7 +12,7 @@ use std::f32::consts::PI;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use values::{Either, None_};
|
use values::{Either, None_};
|
||||||
use values::computed::{Angle, Context, Length, LengthOrPercentage, NumberOrPercentage, ToComputedValue};
|
use values::computed::{Angle, ComputedUrl, Context, Length, LengthOrPercentage, NumberOrPercentage, ToComputedValue};
|
||||||
use values::computed::position::Position;
|
use values::computed::position::Position;
|
||||||
use values::generics::image::{CompatMode, ColorStop as GenericColorStop, EndingShape as GenericEndingShape};
|
use values::generics::image::{CompatMode, ColorStop as GenericColorStop, EndingShape as GenericEndingShape};
|
||||||
use values::generics::image::{Gradient as GenericGradient, GradientItem as GenericGradientItem};
|
use values::generics::image::{Gradient as GenericGradient, GradientItem as GenericGradientItem};
|
||||||
|
@ -27,7 +27,7 @@ pub type ImageLayer = Either<None_, Image>;
|
||||||
|
|
||||||
/// Computed values for an image according to CSS-IMAGES.
|
/// Computed values for an image according to CSS-IMAGES.
|
||||||
/// https://drafts.csswg.org/css-images/#image-values
|
/// https://drafts.csswg.org/css-images/#image-values
|
||||||
pub type Image = GenericImage<Gradient, MozImageRect>;
|
pub type Image = GenericImage<Gradient, MozImageRect, ComputedUrl>;
|
||||||
|
|
||||||
/// Computed values for a CSS gradient.
|
/// Computed values for a CSS gradient.
|
||||||
/// https://drafts.csswg.org/css-images/#gradients
|
/// https://drafts.csswg.org/css-images/#gradients
|
||||||
|
@ -76,7 +76,7 @@ pub type GradientItem = GenericGradientItem<RGBA, LengthOrPercentage>;
|
||||||
pub type ColorStop = GenericColorStop<RGBA, LengthOrPercentage>;
|
pub type ColorStop = GenericColorStop<RGBA, LengthOrPercentage>;
|
||||||
|
|
||||||
/// Computed values for `-moz-image-rect(...)`.
|
/// Computed values for `-moz-image-rect(...)`.
|
||||||
pub type MozImageRect = GenericMozImageRect<NumberOrPercentage>;
|
pub type MozImageRect = GenericMozImageRect<NumberOrPercentage, ComputedUrl>;
|
||||||
|
|
||||||
impl GenericLineDirection for LineDirection {
|
impl GenericLineDirection for LineDirection {
|
||||||
fn points_downwards(&self) -> bool {
|
fn points_downwards(&self) -> bool {
|
||||||
|
|
|
@ -12,10 +12,14 @@ use media_queries::Device;
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use properties;
|
use properties;
|
||||||
use properties::{ComputedValues, StyleBuilder};
|
use properties::{ComputedValues, StyleBuilder};
|
||||||
|
#[cfg(feature = "servo")]
|
||||||
|
use servo_url::ServoUrl;
|
||||||
use std::f32;
|
use std::f32;
|
||||||
use std::f64;
|
use std::f64;
|
||||||
use std::f64::consts::PI;
|
use std::f64::consts::PI;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
#[cfg(feature = "servo")]
|
||||||
|
use std::sync::Arc;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use super::{CSSFloat, CSSInteger};
|
use super::{CSSFloat, CSSInteger};
|
||||||
use super::generics::{GreaterThanOrEqualToOne, NonNegative};
|
use super::generics::{GreaterThanOrEqualToOne, NonNegative};
|
||||||
|
@ -39,9 +43,8 @@ pub use self::image::{Gradient, GradientItem, Image, ImageLayer, LineDirection,
|
||||||
pub use self::gecko::ScrollSnapPoint;
|
pub use self::gecko::ScrollSnapPoint;
|
||||||
pub use self::rect::LengthOrNumberRect;
|
pub use self::rect::LengthOrNumberRect;
|
||||||
pub use super::{Auto, Either, None_};
|
pub use super::{Auto, Either, None_};
|
||||||
pub use super::specified::{BorderStyle, UrlOrNone};
|
pub use super::specified::BorderStyle;
|
||||||
pub use super::generics::grid::GridLine;
|
pub use super::generics::grid::GridLine;
|
||||||
pub use super::specified::url::SpecifiedUrl;
|
|
||||||
pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNone, LengthOrNumber, LengthOrPercentage};
|
pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNone, LengthOrNumber, LengthOrPercentage};
|
||||||
pub use self::length::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone, MaxLength, MozLength};
|
pub use self::length::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone, MaxLength, MozLength};
|
||||||
pub use self::length::NonNegativeLengthOrPercentage;
|
pub use self::length::NonNegativeLengthOrPercentage;
|
||||||
|
@ -684,3 +687,45 @@ impl ToComputedValue for specified::Percentage {
|
||||||
specified::Percentage::new(computed.0)
|
specified::Percentage::new(computed.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The computed value of a CSS `url()`, resolved relative to the stylesheet URL.
|
||||||
|
#[cfg(feature = "servo")]
|
||||||
|
#[derive(Clone, Debug, HeapSizeOf, Serialize, Deserialize, PartialEq)]
|
||||||
|
pub enum ComputedUrl {
|
||||||
|
/// The `url()` was invalid or it wasn't specified by the user.
|
||||||
|
Invalid(Arc<String>),
|
||||||
|
/// The resolved `url()` relative to the stylesheet URL.
|
||||||
|
Valid(ServoUrl),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// TODO: Properly build ComputedUrl for gecko
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
pub type ComputedUrl = specified::url::SpecifiedUrl;
|
||||||
|
|
||||||
|
#[cfg(feature = "servo")]
|
||||||
|
impl ComputedUrl {
|
||||||
|
/// Returns the resolved url if it was valid.
|
||||||
|
pub fn url(&self) -> Option<&ServoUrl> {
|
||||||
|
match *self {
|
||||||
|
ComputedUrl::Valid(ref url) => Some(url),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "servo")]
|
||||||
|
impl ToCss for ComputedUrl {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
let string = match *self {
|
||||||
|
ComputedUrl::Valid(ref url) => url.as_str(),
|
||||||
|
ComputedUrl::Invalid(ref invalid_string) => invalid_string,
|
||||||
|
};
|
||||||
|
|
||||||
|
dest.write_str("url(")?;
|
||||||
|
string.to_css(dest)?;
|
||||||
|
dest.write_str(")")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <url> | <none>
|
||||||
|
pub type UrlOrNone = Either<ComputedUrl, None_>;
|
||||||
|
|
|
@ -8,12 +8,13 @@ use app_units::Au;
|
||||||
use values::{Either, RGBA};
|
use values::{Either, RGBA};
|
||||||
use values::computed::{LengthOrPercentageOrNumber, Opacity};
|
use values::computed::{LengthOrPercentageOrNumber, Opacity};
|
||||||
use values::computed::{NonNegativeAu, NonNegativeLengthOrPercentageOrNumber};
|
use values::computed::{NonNegativeAu, NonNegativeLengthOrPercentageOrNumber};
|
||||||
|
use values::computed::ComputedUrl;
|
||||||
use values::generics::svg as generic;
|
use values::generics::svg as generic;
|
||||||
|
|
||||||
/// Computed SVG Paint value
|
/// Computed SVG Paint value
|
||||||
pub type SVGPaint = generic::SVGPaint<RGBA>;
|
pub type SVGPaint = generic::SVGPaint<RGBA, ComputedUrl>;
|
||||||
/// Computed SVG Paint Kind value
|
/// Computed SVG Paint Kind value
|
||||||
pub type SVGPaintKind = generic::SVGPaintKind<RGBA>;
|
pub type SVGPaintKind = generic::SVGPaintKind<RGBA, ComputedUrl>;
|
||||||
|
|
||||||
impl Default for SVGPaint {
|
impl Default for SVGPaint {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
|
|
|
@ -11,10 +11,9 @@ use values::computed::ComputedValueAsSpecified;
|
||||||
use values::generics::border::BorderRadius;
|
use values::generics::border::BorderRadius;
|
||||||
use values::generics::position::Position;
|
use values::generics::position::Position;
|
||||||
use values::generics::rect::Rect;
|
use values::generics::rect::Rect;
|
||||||
use values::specified::url::SpecifiedUrl;
|
|
||||||
|
|
||||||
/// A clipping shape, for `clip-path`.
|
/// A clipping shape, for `clip-path`.
|
||||||
pub type ClippingShape<BasicShape> = ShapeSource<BasicShape, GeometryBox>;
|
pub type ClippingShape<BasicShape, UrlShapeSource> = ShapeSource<BasicShape, GeometryBox, UrlShapeSource>;
|
||||||
|
|
||||||
/// https://drafts.fxtf.org/css-masking-1/#typedef-geometry-box
|
/// https://drafts.fxtf.org/css-masking-1/#typedef-geometry-box
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
|
@ -29,7 +28,7 @@ pub enum GeometryBox {
|
||||||
impl ComputedValueAsSpecified for GeometryBox {}
|
impl ComputedValueAsSpecified for GeometryBox {}
|
||||||
|
|
||||||
/// A float area shape, for `shape-outside`.
|
/// A float area shape, for `shape-outside`.
|
||||||
pub type FloatAreaShape<BasicShape> = ShapeSource<BasicShape, ShapeBox>;
|
pub type FloatAreaShape<BasicShape, UrlShapeSource> = ShapeSource<BasicShape, ShapeBox, UrlShapeSource>;
|
||||||
|
|
||||||
// https://drafts.csswg.org/css-shapes-1/#typedef-shape-box
|
// https://drafts.csswg.org/css-shapes-1/#typedef-shape-box
|
||||||
define_css_keyword_enum!(ShapeBox:
|
define_css_keyword_enum!(ShapeBox:
|
||||||
|
@ -44,8 +43,8 @@ add_impls_for_keyword_enum!(ShapeBox);
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
#[derive(Clone, Debug, PartialEq, ToComputedValue, ToCss)]
|
#[derive(Clone, Debug, PartialEq, ToComputedValue, ToCss)]
|
||||||
pub enum ShapeSource<BasicShape, ReferenceBox> {
|
pub enum ShapeSource<BasicShape, ReferenceBox, UrlShapeSource> {
|
||||||
Url(SpecifiedUrl),
|
Url(UrlShapeSource),
|
||||||
Shape(BasicShape, Option<ReferenceBox>),
|
Shape(BasicShape, Option<ReferenceBox>),
|
||||||
Box(ReferenceBox),
|
Box(ReferenceBox),
|
||||||
None,
|
None,
|
||||||
|
@ -121,7 +120,7 @@ define_css_keyword_enum!(FillRule:
|
||||||
);
|
);
|
||||||
add_impls_for_keyword_enum!(FillRule);
|
add_impls_for_keyword_enum!(FillRule);
|
||||||
|
|
||||||
impl<B, T> HasViewportPercentage for ShapeSource<B, T> {
|
impl<B, T, U> HasViewportPercentage for ShapeSource<B, T, U> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn has_viewport_percentage(&self) -> bool { false }
|
fn has_viewport_percentage(&self) -> bool { false }
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,16 +12,15 @@ use custom_properties::SpecifiedValue;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::{HasViewportPercentage, ToCss};
|
use style_traits::{HasViewportPercentage, ToCss};
|
||||||
use values::computed::ComputedValueAsSpecified;
|
use values::computed::ComputedValueAsSpecified;
|
||||||
use values::specified::url::SpecifiedUrl;
|
|
||||||
|
|
||||||
/// An [image].
|
/// An [image].
|
||||||
///
|
///
|
||||||
/// [image]: https://drafts.csswg.org/css-images/#image-values
|
/// [image]: https://drafts.csswg.org/css-images/#image-values
|
||||||
#[derive(Clone, PartialEq, ToComputedValue)]
|
#[derive(Clone, PartialEq, ToComputedValue)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub enum Image<Gradient, MozImageRect> {
|
pub enum Image<Gradient, MozImageRect, ImageUrl> {
|
||||||
/// A `<url()>` image.
|
/// A `<url()>` image.
|
||||||
Url(SpecifiedUrl),
|
Url(ImageUrl),
|
||||||
/// A `<gradient>` image.
|
/// A `<gradient>` image.
|
||||||
Gradient(Gradient),
|
Gradient(Gradient),
|
||||||
/// A `-moz-image-rect` image
|
/// A `-moz-image-rect` image
|
||||||
|
@ -168,16 +167,16 @@ impl ToCss for PaintWorklet {
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
#[css(comma, function)]
|
#[css(comma, function)]
|
||||||
#[derive(Clone, Debug, PartialEq, ToComputedValue, ToCss)]
|
#[derive(Clone, Debug, PartialEq, ToComputedValue, ToCss)]
|
||||||
pub struct MozImageRect<NumberOrPercentage> {
|
pub struct MozImageRect<NumberOrPercentage, MozImageRectUrl> {
|
||||||
pub url: SpecifiedUrl,
|
pub url: MozImageRectUrl,
|
||||||
pub top: NumberOrPercentage,
|
pub top: NumberOrPercentage,
|
||||||
pub right: NumberOrPercentage,
|
pub right: NumberOrPercentage,
|
||||||
pub bottom: NumberOrPercentage,
|
pub bottom: NumberOrPercentage,
|
||||||
pub left: NumberOrPercentage,
|
pub left: NumberOrPercentage,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<G, R> fmt::Debug for Image<G, R>
|
impl<G, R, U> fmt::Debug for Image<G, R, U>
|
||||||
where G: fmt::Debug, R: fmt::Debug,
|
where G: fmt::Debug, R: fmt::Debug, U: fmt::Debug + ToCss
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match *self {
|
match *self {
|
||||||
|
@ -195,8 +194,8 @@ impl<G, R> fmt::Debug for Image<G, R>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<G, R> ToCss for Image<G, R>
|
impl<G, R, U> ToCss for Image<G, R, U>
|
||||||
where G: ToCss, R: ToCss,
|
where G: ToCss, R: ToCss, U: ToCss
|
||||||
{
|
{
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
match *self {
|
match *self {
|
||||||
|
@ -214,7 +213,7 @@ impl<G, R> ToCss for Image<G, R>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<G, R> HasViewportPercentage for Image<G, R>
|
impl<G, R, U> HasViewportPercentage for Image<G, R, U>
|
||||||
where G: HasViewportPercentage
|
where G: HasViewportPercentage
|
||||||
{
|
{
|
||||||
fn has_viewport_percentage(&self) -> bool {
|
fn has_viewport_percentage(&self) -> bool {
|
||||||
|
|
|
@ -8,16 +8,15 @@ use cssparser::Parser;
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::{ParseError, StyleParseError, ToCss};
|
use style_traits::{ParseError, StyleParseError, ToCss};
|
||||||
use values::specified::url::SpecifiedUrl;
|
|
||||||
|
|
||||||
/// An SVG paint value
|
/// An SVG paint value
|
||||||
///
|
///
|
||||||
/// https://www.w3.org/TR/SVG2/painting.html#SpecifyingPaint
|
/// https://www.w3.org/TR/SVG2/painting.html#SpecifyingPaint
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
#[derive(Clone, Debug, PartialEq, ToAnimatedValue, ToComputedValue, ToCss)]
|
#[derive(Clone, Debug, PartialEq, ToAnimatedValue, ToComputedValue, ToCss)]
|
||||||
pub struct SVGPaint<ColorType> {
|
pub struct SVGPaint<ColorType, UrlPaintServer> {
|
||||||
/// The paint source
|
/// The paint source
|
||||||
pub kind: SVGPaintKind<ColorType>,
|
pub kind: SVGPaintKind<ColorType, UrlPaintServer>,
|
||||||
/// The fallback color
|
/// The fallback color
|
||||||
pub fallback: Option<ColorType>,
|
pub fallback: Option<ColorType>,
|
||||||
}
|
}
|
||||||
|
@ -29,20 +28,20 @@ pub struct SVGPaint<ColorType> {
|
||||||
/// properties have a fallback as well.
|
/// properties have a fallback as well.
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
#[derive(Clone, Debug, PartialEq, ToAnimatedValue, ToComputedValue, ToCss)]
|
#[derive(Clone, Debug, PartialEq, ToAnimatedValue, ToComputedValue, ToCss)]
|
||||||
pub enum SVGPaintKind<ColorType> {
|
pub enum SVGPaintKind<ColorType, UrlPaintServer> {
|
||||||
/// `none`
|
/// `none`
|
||||||
None,
|
None,
|
||||||
/// `<color>`
|
/// `<color>`
|
||||||
Color(ColorType),
|
Color(ColorType),
|
||||||
/// `url(...)`
|
/// `url(...)`
|
||||||
PaintServer(SpecifiedUrl),
|
PaintServer(UrlPaintServer),
|
||||||
/// `context-fill`
|
/// `context-fill`
|
||||||
ContextFill,
|
ContextFill,
|
||||||
/// `context-stroke`
|
/// `context-stroke`
|
||||||
ContextStroke,
|
ContextStroke,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ColorType> SVGPaintKind<ColorType> {
|
impl<ColorType, UrlPaintServer> SVGPaintKind<ColorType, UrlPaintServer> {
|
||||||
/// Parse a keyword value only
|
/// Parse a keyword value only
|
||||||
fn parse_ident<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
fn parse_ident<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
try_match_ident_ignore_ascii_case! { input.expect_ident()?,
|
try_match_ident_ignore_ascii_case! { input.expect_ident()?,
|
||||||
|
@ -66,9 +65,9 @@ fn parse_fallback<'i, 't, ColorType: Parse>(context: &ParserContext,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ColorType: Parse> Parse for SVGPaint<ColorType> {
|
impl<ColorType: Parse, UrlPaintServer: Parse> Parse for SVGPaint<ColorType, UrlPaintServer> {
|
||||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(url) = input.try(|i| SpecifiedUrl::parse(context, i)) {
|
if let Ok(url) = input.try(|i| UrlPaintServer::parse(context, i)) {
|
||||||
Ok(SVGPaint {
|
Ok(SVGPaint {
|
||||||
kind: SVGPaintKind::PaintServer(url),
|
kind: SVGPaintKind::PaintServer(url),
|
||||||
fallback: parse_fallback(context, input),
|
fallback: parse_fallback(context, input),
|
||||||
|
|
|
@ -26,10 +26,10 @@ use values::specified::position::{HorizontalPosition, Position, PositionComponen
|
||||||
use values::specified::url::SpecifiedUrl;
|
use values::specified::url::SpecifiedUrl;
|
||||||
|
|
||||||
/// A specified clipping shape.
|
/// A specified clipping shape.
|
||||||
pub type ClippingShape = GenericClippingShape<BasicShape>;
|
pub type ClippingShape = GenericClippingShape<BasicShape, SpecifiedUrl>;
|
||||||
|
|
||||||
/// A specified float area shape.
|
/// A specified float area shape.
|
||||||
pub type FloatAreaShape = GenericFloatAreaShape<BasicShape>;
|
pub type FloatAreaShape = GenericFloatAreaShape<BasicShape, SpecifiedUrl>;
|
||||||
|
|
||||||
/// A specified basic shape.
|
/// A specified basic shape.
|
||||||
pub type BasicShape = GenericBasicShape<HorizontalPosition, VerticalPosition, LengthOrPercentage>;
|
pub type BasicShape = GenericBasicShape<HorizontalPosition, VerticalPosition, LengthOrPercentage>;
|
||||||
|
@ -49,7 +49,7 @@ pub type ShapeRadius = GenericShapeRadius<LengthOrPercentage>;
|
||||||
/// The specified value of `Polygon`
|
/// The specified value of `Polygon`
|
||||||
pub type Polygon = GenericPolygon<LengthOrPercentage>;
|
pub type Polygon = GenericPolygon<LengthOrPercentage>;
|
||||||
|
|
||||||
impl<ReferenceBox: Parse> Parse for ShapeSource<BasicShape, ReferenceBox> {
|
impl<ReferenceBox: Parse> Parse for ShapeSource<BasicShape, ReferenceBox, SpecifiedUrl> {
|
||||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
||||||
return Ok(ShapeSource::None)
|
return Ok(ShapeSource::None)
|
||||||
|
|
|
@ -38,7 +38,7 @@ pub type ImageLayer = Either<None_, Image>;
|
||||||
|
|
||||||
/// Specified values for an image according to CSS-IMAGES.
|
/// Specified values for an image according to CSS-IMAGES.
|
||||||
/// https://drafts.csswg.org/css-images/#image-values
|
/// https://drafts.csswg.org/css-images/#image-values
|
||||||
pub type Image = GenericImage<Gradient, MozImageRect>;
|
pub type Image = GenericImage<Gradient, MozImageRect, SpecifiedUrl>;
|
||||||
|
|
||||||
/// Specified values for a CSS gradient.
|
/// Specified values for a CSS gradient.
|
||||||
/// https://drafts.csswg.org/css-images/#gradients
|
/// https://drafts.csswg.org/css-images/#gradients
|
||||||
|
@ -125,7 +125,7 @@ pub type ColorStop = GenericColorStop<RGBAColor, LengthOrPercentage>;
|
||||||
|
|
||||||
/// Specified values for `moz-image-rect`
|
/// Specified values for `moz-image-rect`
|
||||||
/// -moz-image-rect(<uri>, top, right, bottom, left);
|
/// -moz-image-rect(<uri>, top, right, bottom, left);
|
||||||
pub type MozImageRect = GenericMozImageRect<NumberOrPercentage>;
|
pub type MozImageRect = GenericMozImageRect<NumberOrPercentage, SpecifiedUrl>;
|
||||||
|
|
||||||
impl Parse for Image {
|
impl Parse for Image {
|
||||||
#[cfg_attr(not(feature = "gecko"), allow(unused_mut))]
|
#[cfg_attr(not(feature = "gecko"), allow(unused_mut))]
|
||||||
|
|
|
@ -76,6 +76,7 @@ pub mod url {
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
use style_traits::ParseError;
|
use style_traits::ParseError;
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
use values::computed::ComputedValueAsSpecified;
|
use values::computed::ComputedValueAsSpecified;
|
||||||
|
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
|
@ -92,7 +93,7 @@ impl Parse for SpecifiedUrl {
|
||||||
|
|
||||||
impl Eq for SpecifiedUrl {}
|
impl Eq for SpecifiedUrl {}
|
||||||
|
|
||||||
// TODO(emilio): Maybe consider ComputedUrl to save a word in style structs?
|
#[cfg(feature = "gecko")]
|
||||||
impl ComputedValueAsSpecified for SpecifiedUrl {}
|
impl ComputedValueAsSpecified for SpecifiedUrl {}
|
||||||
|
|
||||||
no_viewport_percentage!(SpecifiedUrl);
|
no_viewport_percentage!(SpecifiedUrl);
|
||||||
|
|
|
@ -8,16 +8,16 @@ use cssparser::Parser;
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
use style_traits::{CommaWithSpace, ParseError, Separator, StyleParseError};
|
use style_traits::{CommaWithSpace, ParseError, Separator, StyleParseError};
|
||||||
use values::generics::svg as generic;
|
use values::generics::svg as generic;
|
||||||
use values::specified::{LengthOrPercentageOrNumber, NonNegativeLengthOrPercentageOrNumber, Opacity};
|
use values::specified::{LengthOrPercentageOrNumber, NonNegativeLengthOrPercentageOrNumber, Opacity, SpecifiedUrl};
|
||||||
use values::specified::color::RGBAColor;
|
use values::specified::color::RGBAColor;
|
||||||
|
|
||||||
/// Specified SVG Paint value
|
/// Specified SVG Paint value
|
||||||
pub type SVGPaint = generic::SVGPaint<RGBAColor>;
|
pub type SVGPaint = generic::SVGPaint<RGBAColor, SpecifiedUrl>;
|
||||||
|
|
||||||
no_viewport_percentage!(SVGPaint);
|
no_viewport_percentage!(SVGPaint);
|
||||||
|
|
||||||
/// Specified SVG Paint Kind value
|
/// Specified SVG Paint Kind value
|
||||||
pub type SVGPaintKind = generic::SVGPaintKind<RGBAColor>;
|
pub type SVGPaintKind = generic::SVGPaintKind<RGBAColor, SpecifiedUrl>;
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
fn is_context_value_enabled() -> bool {
|
fn is_context_value_enabled() -> bool {
|
||||||
|
|
|
@ -13536,6 +13536,12 @@
|
||||||
{}
|
{}
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
"css/get-computed-style-for-url.html": [
|
||||||
|
[
|
||||||
|
"/_mozilla/css/get-computed-style-for-url.html",
|
||||||
|
{}
|
||||||
|
]
|
||||||
|
],
|
||||||
"css/import_serialization.html": [
|
"css/import_serialization.html": [
|
||||||
[
|
[
|
||||||
"/_mozilla/css/import_serialization.html",
|
"/_mozilla/css/import_serialization.html",
|
||||||
|
@ -23357,6 +23363,10 @@
|
||||||
"13a3f8dd23fa28c0b2ad2fe0662d29a27a569e74",
|
"13a3f8dd23fa28c0b2ad2fe0662d29a27a569e74",
|
||||||
"support"
|
"support"
|
||||||
],
|
],
|
||||||
|
"css/get-computed-style-for-url.html": [
|
||||||
|
"2e90c0abd6c83bb11113f39a557a4c1c1c24364b",
|
||||||
|
"testharness"
|
||||||
|
],
|
||||||
"css/green.png": [
|
"css/green.png": [
|
||||||
"15e39f6df8def787cefcfb30e27de5f43da65c9a",
|
"15e39f6df8def787cefcfb30e27de5f43da65c9a",
|
||||||
"support"
|
"support"
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
[get-computed-style-for-url.html]
|
||||||
|
type: testharness
|
||||||
|
|
||||||
|
[getComputedStyle(elem) for url() listStyle uses the resolved URL and elem.style uses the original URL]
|
||||||
|
expected: FAIL
|
||||||
|
bug: https://github.com/servo/servo/issues/18015
|
||||||
|
|
||||||
|
[getComputedStyle(elem) for url() listStyleImage uses the resolved URL and elem.style uses the original URL]
|
||||||
|
expected: FAIL
|
||||||
|
bug: https://github.com/servo/servo/issues/18015
|
||||||
|
|
49
tests/wpt/mozilla/tests/css/get-computed-style-for-url.html
Normal file
49
tests/wpt/mozilla/tests/css/get-computed-style-for-url.html
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
<!doctype html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Computed styles for URLs use the resolved URL and specified styles use the original URL</title>
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<div id="tests"></div>
|
||||||
|
<script>
|
||||||
|
var origin = window.location.origin;
|
||||||
|
var container = document.getElementById("tests");
|
||||||
|
|
||||||
|
// Some shorthands like background and border-image compute to other properties
|
||||||
|
var computedPropertyName = {
|
||||||
|
background: "backgroundImage",
|
||||||
|
borderImage: "borderImageSource",
|
||||||
|
listStyle: "listStyleImage",
|
||||||
|
};
|
||||||
|
|
||||||
|
function makeComputedUrlStyle(path) {
|
||||||
|
return `url("${origin}/${path}")`;
|
||||||
|
}
|
||||||
|
function makeSpecifiedUrlStyle(path) {
|
||||||
|
return `url("${path}")`;
|
||||||
|
}
|
||||||
|
function testUrlsForProperty(property, urlValue, extraShorthand) {
|
||||||
|
test(function() {
|
||||||
|
var extra = extraShorthand ? ` ${extraShorthand}` : "";
|
||||||
|
|
||||||
|
var elem = document.createElement("div");
|
||||||
|
elem.style[property] = `url("${urlValue}")${extra}`;
|
||||||
|
container.appendChild(elem);
|
||||||
|
|
||||||
|
assert_equals(
|
||||||
|
getComputedStyle(elem)[computedPropertyName[property] || property],
|
||||||
|
makeComputedUrlStyle(`_mozilla/css/${urlValue}`)
|
||||||
|
);
|
||||||
|
assert_equals(
|
||||||
|
elem.style[computedPropertyName[property] || property],
|
||||||
|
makeSpecifiedUrlStyle(urlValue)
|
||||||
|
);
|
||||||
|
}, `getComputedStyle(elem) for url() ${property} uses the resolved URL and elem.style uses the original URL`);
|
||||||
|
}
|
||||||
|
|
||||||
|
testUrlsForProperty("backgroundImage", "test.jpg");
|
||||||
|
testUrlsForProperty("background", "test.jpg", "no-repeat");
|
||||||
|
testUrlsForProperty("borderImage", "test.jpg", "30 round");
|
||||||
|
testUrlsForProperty("listStyleImage", "test.jpg");
|
||||||
|
testUrlsForProperty("listStyle", "test.jpg", "square");
|
||||||
|
</script>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue