/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
/// Specified values for an image according to CSS-IMAGES. /// <https://drafts.csswg.org/css-images/#image-values> pubtype Image = generic::Image<Gradient, SpecifiedUrl, Color, Percentage, Resolution>;
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", "conic-gradient", "repeating-conic-gradient",
]);
}
}
// Need to manually implement as whether or not cross-fade shows up in // completions & etc is dependent on it being enabled. impl<Image, Color, Percentage> SpecifiedValueInfo for generic::CrossFade<Image, Color, Percentage> { const SUPPORTED_TYPES: u8 = 0;
/// A specified gradient line direction. /// /// FIXME(emilio): This should be generic over Angle. #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)] pubenum LineDirection { /// An angular direction.
Angle(Angle), /// A horizontal direction.
Horizontal(HorizontalPositionKeyword), /// A vertical direction.
Vertical(VerticalPositionKeyword), /// A direction towards a corner of a box.
Corner(HorizontalPositionKeyword, VerticalPositionKeyword),
}
/// A specified ending shape. pubtype EndingShape = generic::EndingShape<NonNegativeLength, NonNegativeLengthPercentage>;
impl Image { /// Creates an already specified image value from an already resolved URL /// for insertion in the cascade. #[cfg(feature = "servo")] pubfn for_cascade(url: ::servo_arc::Arc<::url::Url>) -> Self { usecrate::values::CssUrl;
generic::Image::Url(CssUrl::for_cascade(url))
}
impl CrossFadeElement { fn parse_percentage<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Option<Percentage> { // We clamp our values here as this is the way that Safari and Chrome's // implementation handle out-of-bounds percentages but whether or not // this behavior follows the specification is still being discussed. // See: <https://github.com/w3c/csswg-drafts/issues/5333>
input
.try_parse(|input| Percentage::parse_non_negative(context, input))
.ok()
.map(|p| p.clamp_to_hundred())
}
/// <cf-image> = <percentage>? && [ <image> | <color> ] fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
cors_mode: CorsMode,
flags: ParseImageFlags,
) -> Result<Self, ParseError<'i>> { // Try and parse a leading percent sign. letmut percent = Self::parse_percentage(context, input); // Parse the image let image = CrossFadeImage::parse(context, input, cors_mode, flags)?; // Try and parse a trailing percent sign. if percent.is_none() {
percent = Self::parse_percentage(context, input);
}
Ok(Self {
percent: percent.into(),
image,
})
}
}
// Try to parse resolution after type(). if mime_type.is_some() && resolution.is_none() {
resolution = input
.try_parse(|input| Resolution::parse(context, input))
.ok();
}
let resolution = resolution.unwrap_or_else(|| Resolution::from_x(1.0)); let has_mime_type = mime_type.is_some(); let mime_type = mime_type.unwrap_or_default();
let ident = input.expect_ident_cloned()?;
input.expect_comma()?;
Ok(match_ignore_ascii_case! { &ident, "linear" => { let first = Point::parse(context, input)?;
input.expect_comma()?; let second = Point::parse(context, input)?;
let direction = line_direction_from_points(first, second); let items = Gradient::parse_webkit_gradient_stops(context, input, false)?;
generic::Gradient::Linear {
direction,
color_interpolation_method: ColorInterpolationMethod::srgb(),
items, // Legacy gradients always use srgb as a default.
flags: generic::GradientFlags::HAS_DEFAULT_COLOR_INTERPOLATION_METHOD,
compat_mode: GradientCompatMode::Modern,
}
}, "radial" => { let first_point = Point::parse(context, input)?;
input.expect_comma()?; let first_radius = Number::parse_non_negative(context, input)?;
input.expect_comma()?; let second_point = Point::parse(context, input)?;
input.expect_comma()?; let second_radius = Number::parse_non_negative(context, input)?;
let (reverse_stops, point, radius) = if second_radius.value >= first_radius.value {
(false, second_point, second_radius)
} else {
(true, first_point, first_radius)
};
let rad = Circle::Radius(NonNegative(Length::from_px(radius.value))); let shape = generic::EndingShape::Circle(rad); let position = Position::new(point.horizontal.into(), point.vertical.into()); let items = Gradient::parse_webkit_gradient_stops(context, input, reverse_stops)?;
generic::Gradient::Radial {
shape,
position,
color_interpolation_method: ColorInterpolationMethod::srgb(),
items, // Legacy gradients always use srgb as a default.
flags: generic::GradientFlags::HAS_DEFAULT_COLOR_INTERPOLATION_METHOD,
compat_mode: GradientCompatMode::Modern,
}
},
_ => { let e = SelectorParseErrorKind::UnexpectedIdent(ident.clone()); return Err(input.new_custom_error(e));
},
})
}
fn parse_webkit_gradient_stops<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
reverse_stops: bool,
) -> Result<LengthPercentageItemList, ParseError<'i>> { letmut items = input
.try_parse(|i| {
i.expect_comma()?;
i.parse_comma_separated(|i| { let function = i.expect_function()?.clone(); let (color, mut p) = i.parse_nested_block(|i| { let p = match_ignore_ascii_case! { &function, "color-stop" => { let p = NumberOrPercentage::parse(context, i)?.to_percentage();
i.expect_comma()?;
p
}, "from" => Percentage::zero(), "to" => Percentage::hundred(),
_ => { return Err(i.new_custom_error(
StyleParseErrorKind::UnexpectedFunction(function.clone())
))
},
}; let color = Color::parse(context, i)?; if color == Color::CurrentColor { return Err(i.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
Ok((color.into(), p))
})?; if reverse_stops {
p.reverse();
}
Ok(generic::GradientItem::ComplexColorStop {
color,
position: p.into(),
})
})
})
.unwrap_or(vec![]);
let direction = input
.try_parse(|p| LineDirection::parse(context, p, &mut compat_mode))
.ok();
if direction.is_some() && color_interpolation_method.is_none() {
color_interpolation_method = Self::try_parse_color_interpolation_method(context, input);
}
// If either of the 2 options were specified, we require a comma. if color_interpolation_method.is_some() || direction.is_some() {
input.expect_comma()?;
}
let items = Gradient::parse_stops(context, input)?;
let default = default_color_interpolation_method(&items); let color_interpolation_method = color_interpolation_method.unwrap_or(default);
flags.set(
GradientFlags::HAS_DEFAULT_COLOR_INTERPOLATION_METHOD,
default == color_interpolation_method,
);
let direction = direction.unwrap_or(match compat_mode {
GradientCompatMode::Modern => LineDirection::Vertical(VerticalPositionKeyword::Bottom),
_ => LineDirection::Vertical(VerticalPositionKeyword::Top),
});
input.try_parse(|i| { let to_ident = i.try_parse(|i| i.expect_ident_matching("to")); match *compat_mode { // `to` keyword is mandatory in modern syntax.
GradientCompatMode::Modern => to_ident?, // Fall back to Modern compatibility mode in case there is a `to` keyword. // According to Gecko, `-moz-linear-gradient(to ...)` should serialize like // `linear-gradient(to ...)`.
GradientCompatMode::Moz if to_ident.is_ok() => {
*compat_mode = GradientCompatMode::Modern
}, // There is no `to` keyword in webkit prefixed syntax. If it's consumed, // parsing should throw an error.
GradientCompatMode::WebKit if to_ident.is_ok() => { return Err(
i.new_custom_error(SelectorParseErrorKind::UnexpectedIdent("to".into()))
);
},
_ => {},
}
/// https://drafts.csswg.org/css-images/#propdef-image-rendering #[allow(missing_docs)] #[derive(
Clone,
Copy,
Debug,
Eq,
Hash,
MallocSizeOf,
Parse,
PartialEq,
SpecifiedValueInfo,
ToCss,
ToComputedValue,
ToResolvedValue,
ToShmem,
)] #[repr(u8)] pubenum ImageRendering {
Auto, #[cfg(feature = "gecko")]
Smooth, #[parse(aliases = "-moz-crisp-edges")]
CrispEdges,
Pixelated, // From the spec: // // This property previously accepted the values optimizeSpeed and // optimizeQuality. These are now deprecated; a user agent must accept // them as valid values but must treat them as having the same behavior // as crisp-edges and smooth respectively, and authors must not use // them. // #[cfg(feature = "gecko")]
Optimizespeed, #[cfg(feature = "gecko")]
Optimizequality,
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.22 Sekunden
(vorverarbeitet am 2026-06-19)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.