mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
Introduce style::values::generics::image
This commit is contained in:
parent
34d0e59849
commit
1c54758ad6
8 changed files with 429 additions and 460 deletions
|
@ -57,11 +57,12 @@ use style::properties::{self, ServoComputedValues};
|
||||||
use style::properties::longhands::border_image_repeat::computed_value::RepeatKeyword;
|
use style::properties::longhands::border_image_repeat::computed_value::RepeatKeyword;
|
||||||
use style::properties::style_structs;
|
use style::properties::style_structs;
|
||||||
use style::servo::restyle_damage::REPAINT;
|
use style::servo::restyle_damage::REPAINT;
|
||||||
use style::values::{Either, RGBA, computed};
|
use style::values::{Either, RGBA};
|
||||||
use style::values::computed::{AngleOrCorner, Gradient, GradientItem, GradientKind, LengthOrPercentage};
|
use style::values::computed::{AngleOrCorner, Gradient, GradientItem, GradientKind, LengthOrPercentage};
|
||||||
use style::values::computed::{LengthOrPercentageOrAuto, LengthOrKeyword, LengthOrPercentageOrKeyword};
|
use style::values::computed::{LengthOrPercentageOrAuto, LengthOrKeyword, LengthOrPercentageOrKeyword};
|
||||||
use style::values::computed::{NumberOrPercentage, Position};
|
use style::values::computed::{NumberOrPercentage, Position};
|
||||||
use style::values::computed::image::{EndingShape, SizeKeyword};
|
use style::values::computed::image::{EndingShape, SizeKeyword};
|
||||||
|
use style::values::generics::image::{GradientItem as GenericGradientItem, Image};
|
||||||
use style::values::specified::{HorizontalDirection, VerticalDirection};
|
use style::values::specified::{HorizontalDirection, VerticalDirection};
|
||||||
use style_traits::CSSPixel;
|
use style_traits::CSSPixel;
|
||||||
use style_traits::cursor::Cursor;
|
use style_traits::cursor::Cursor;
|
||||||
|
@ -610,7 +611,7 @@ fn convert_gradient_stops(gradient_items: &[GradientItem],
|
||||||
// Only keep the color stops, discard the color interpolation hints.
|
// Only keep the color stops, discard the color interpolation hints.
|
||||||
let mut stop_items = gradient_items.iter().filter_map(|item| {
|
let mut stop_items = gradient_items.iter().filter_map(|item| {
|
||||||
match *item {
|
match *item {
|
||||||
GradientItem::ColorStop(ref stop) => Some(*stop),
|
GenericGradientItem::ColorStop(ref stop) => Some(*stop),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}).collect::<Vec<_>>();
|
}).collect::<Vec<_>>();
|
||||||
|
@ -855,7 +856,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
for (i, background_image) in background.background_image.0.iter().enumerate().rev() {
|
for (i, background_image) in background.background_image.0.iter().enumerate().rev() {
|
||||||
match background_image.0 {
|
match background_image.0 {
|
||||||
None => {}
|
None => {}
|
||||||
Some(computed::Image::Gradient(ref gradient)) => {
|
Some(Image::Gradient(ref gradient)) => {
|
||||||
self.build_display_list_for_background_gradient(state,
|
self.build_display_list_for_background_gradient(state,
|
||||||
display_list_section,
|
display_list_section,
|
||||||
&absolute_bounds,
|
&absolute_bounds,
|
||||||
|
@ -864,7 +865,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
gradient,
|
gradient,
|
||||||
style);
|
style);
|
||||||
}
|
}
|
||||||
Some(computed::Image::Url(ref image_url)) => {
|
Some(Image::Url(ref image_url)) => {
|
||||||
if let Some(url) = image_url.url() {
|
if let Some(url) = image_url.url() {
|
||||||
self.build_display_list_for_background_image(state,
|
self.build_display_list_for_background_image(state,
|
||||||
style,
|
style,
|
||||||
|
@ -875,10 +876,10 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
i);
|
i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(computed::Image::ImageRect(_)) => {
|
Some(Image::Rect(_)) => {
|
||||||
// TODO: Implement `-moz-image-rect`
|
// TODO: Implement `-moz-image-rect`
|
||||||
}
|
}
|
||||||
Some(computed::Image::Element(_)) => {
|
Some(Image::Element(_)) => {
|
||||||
// TODO: Implement `-moz-element`
|
// TODO: Implement `-moz-element`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1221,7 +1222,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
style.get_cursor(Cursor::Default),
|
style.get_cursor(Cursor::Default),
|
||||||
display_list_section);
|
display_list_section);
|
||||||
|
|
||||||
let display_item = match gradient.gradient_kind {
|
let display_item = match gradient.kind {
|
||||||
GradientKind::Linear(ref angle_or_corner) => {
|
GradientKind::Linear(ref angle_or_corner) => {
|
||||||
let gradient = self.convert_linear_gradient(&bounds,
|
let gradient = self.convert_linear_gradient(&bounds,
|
||||||
&gradient.items[..],
|
&gradient.items[..],
|
||||||
|
@ -1357,8 +1358,8 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
}),
|
}),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
Some(computed::Image::Gradient(ref gradient)) => {
|
Some(Image::Gradient(ref gradient)) => {
|
||||||
match gradient.gradient_kind {
|
match gradient.kind {
|
||||||
GradientKind::Linear(angle_or_corner) => {
|
GradientKind::Linear(angle_or_corner) => {
|
||||||
let grad = self.convert_linear_gradient(&bounds,
|
let grad = self.convert_linear_gradient(&bounds,
|
||||||
&gradient.items[..],
|
&gradient.items[..],
|
||||||
|
@ -1398,13 +1399,13 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(computed::Image::ImageRect(..)) => {
|
Some(Image::Rect(..)) => {
|
||||||
// TODO: Handle border-image with `-moz-image-rect`.
|
// TODO: Handle border-image with `-moz-image-rect`.
|
||||||
}
|
}
|
||||||
Some(computed::Image::Element(..)) => {
|
Some(Image::Element(..)) => {
|
||||||
// TODO: Handle border-image with `-moz-element`.
|
// TODO: Handle border-image with `-moz-element`.
|
||||||
}
|
}
|
||||||
Some(computed::Image::Url(ref image_url)) => {
|
Some(Image::Url(ref image_url)) => {
|
||||||
if let Some(url) = image_url.url() {
|
if let Some(url) = image_url.url() {
|
||||||
let webrender_image = state.layout_context
|
let webrender_image = state.layout_context
|
||||||
.get_webrender_image_for_url(self.node,
|
.get_webrender_image_for_url(self.node,
|
||||||
|
|
|
@ -16,8 +16,9 @@ use gecko_bindings::structs::{nsCSSUnit, nsStyleCoord_CalcValue, nsStyleImage};
|
||||||
use gecko_bindings::structs::{nsresult, SheetType};
|
use gecko_bindings::structs::{nsresult, SheetType};
|
||||||
use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordDataMut};
|
use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordDataMut};
|
||||||
use stylesheets::{Origin, RulesMutateError};
|
use stylesheets::{Origin, RulesMutateError};
|
||||||
use values::computed::{Angle, CalcLengthOrPercentage, Gradient, GradientItem, Image};
|
use values::computed::{Angle, CalcLengthOrPercentage, Gradient, Image};
|
||||||
use values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
|
use values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
|
||||||
|
use values::generics::image::{GradientItem, Image as GenericImage};
|
||||||
|
|
||||||
impl From<CalcLengthOrPercentage> for nsStyleCoord_CalcValue {
|
impl From<CalcLengthOrPercentage> for nsStyleCoord_CalcValue {
|
||||||
fn from(other: CalcLengthOrPercentage) -> nsStyleCoord_CalcValue {
|
fn from(other: CalcLengthOrPercentage) -> nsStyleCoord_CalcValue {
|
||||||
|
@ -138,10 +139,10 @@ impl nsStyleImage {
|
||||||
/// Set a given Servo `Image` value into this `nsStyleImage`.
|
/// Set a given Servo `Image` value into this `nsStyleImage`.
|
||||||
pub fn set(&mut self, image: Image, cacheable: &mut bool) {
|
pub fn set(&mut self, image: Image, cacheable: &mut bool) {
|
||||||
match image {
|
match image {
|
||||||
Image::Gradient(gradient) => {
|
GenericImage::Gradient(gradient) => {
|
||||||
self.set_gradient(gradient)
|
self.set_gradient(gradient)
|
||||||
},
|
},
|
||||||
Image::Url(ref url) => {
|
GenericImage::Url(ref url) => {
|
||||||
unsafe {
|
unsafe {
|
||||||
Gecko_SetUrlImageValue(self, url.for_ffi());
|
Gecko_SetUrlImageValue(self, url.for_ffi());
|
||||||
// We unfortunately must make any url() value uncacheable, since
|
// We unfortunately must make any url() value uncacheable, since
|
||||||
|
@ -154,7 +155,7 @@ impl nsStyleImage {
|
||||||
*cacheable = false;
|
*cacheable = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Image::ImageRect(ref image_rect) => {
|
GenericImage::Rect(ref image_rect) => {
|
||||||
unsafe {
|
unsafe {
|
||||||
Gecko_SetUrlImageValue(self, image_rect.url.for_ffi());
|
Gecko_SetUrlImageValue(self, image_rect.url.for_ffi());
|
||||||
Gecko_InitializeImageCropRect(self);
|
Gecko_InitializeImageCropRect(self);
|
||||||
|
@ -176,7 +177,7 @@ impl nsStyleImage {
|
||||||
image_rect.left.to_gecko_style_coord(&mut rect.data_at_mut(3));
|
image_rect.left.to_gecko_style_coord(&mut rect.data_at_mut(3));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Image::Element(ref element) => {
|
GenericImage::Element(ref element) => {
|
||||||
unsafe {
|
unsafe {
|
||||||
Gecko_SetImageElement(self, element.as_ptr());
|
Gecko_SetImageElement(self, element.as_ptr());
|
||||||
}
|
}
|
||||||
|
@ -201,7 +202,7 @@ impl nsStyleImage {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let gecko_gradient = match gradient.gradient_kind {
|
let gecko_gradient = match gradient.kind {
|
||||||
GradientKind::Linear(angle_or_corner) => {
|
GradientKind::Linear(angle_or_corner) => {
|
||||||
let gecko_gradient = unsafe {
|
let gecko_gradient = unsafe {
|
||||||
Gecko_CreateGradient(NS_STYLE_GRADIENT_SHAPE_LINEAR as u8,
|
Gecko_CreateGradient(NS_STYLE_GRADIENT_SHAPE_LINEAR as u8,
|
||||||
|
|
|
@ -7,128 +7,35 @@
|
||||||
//!
|
//!
|
||||||
//! [image]: https://drafts.csswg.org/css-images/#image-values
|
//! [image]: https://drafts.csswg.org/css-images/#image-values
|
||||||
|
|
||||||
use Atom;
|
use cssparser::Color as CSSColor;
|
||||||
use cssparser::{Color as CSSColor, serialize_identifier};
|
|
||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
|
use values::generics::image::{CompatMode, ColorStop as GenericColorStop};
|
||||||
|
use values::generics::image::{Gradient as GenericGradient, GradientItem as GenericGradientItem};
|
||||||
|
use values::generics::image::{Image as GenericImage, ImageRect as GenericImageRect};
|
||||||
use values::computed::{Angle, Context, Length, LengthOrPercentage, NumberOrPercentage, ToComputedValue};
|
use values::computed::{Angle, Context, Length, LengthOrPercentage, NumberOrPercentage, ToComputedValue};
|
||||||
use values::computed::position::Position;
|
use values::computed::position::Position;
|
||||||
use values::specified::{self, HorizontalDirection, VerticalDirection};
|
use values::specified::{self, HorizontalDirection, VerticalDirection};
|
||||||
use values::specified::image::CompatMode;
|
|
||||||
use values::specified::url::SpecifiedUrl;
|
|
||||||
|
|
||||||
pub use values::specified::SizeKeyword;
|
pub use values::specified::SizeKeyword;
|
||||||
|
|
||||||
impl ToComputedValue for specified::Image {
|
|
||||||
type ComputedValue = Image;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn to_computed_value(&self, context: &Context) -> Image {
|
|
||||||
match *self {
|
|
||||||
specified::Image::Url(ref url_value) => {
|
|
||||||
Image::Url(url_value.clone())
|
|
||||||
},
|
|
||||||
specified::Image::Gradient(ref gradient) => {
|
|
||||||
Image::Gradient(gradient.to_computed_value(context))
|
|
||||||
},
|
|
||||||
specified::Image::ImageRect(ref image_rect) => {
|
|
||||||
Image::ImageRect(image_rect.to_computed_value(context))
|
|
||||||
},
|
|
||||||
specified::Image::Element(ref selector) => {
|
|
||||||
Image::Element(selector.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn from_computed_value(computed: &Image) -> Self {
|
|
||||||
match *computed {
|
|
||||||
Image::Url(ref url_value) => {
|
|
||||||
specified::Image::Url(url_value.clone())
|
|
||||||
},
|
|
||||||
Image::Gradient(ref linear_gradient) => {
|
|
||||||
specified::Image::Gradient(
|
|
||||||
ToComputedValue::from_computed_value(linear_gradient)
|
|
||||||
)
|
|
||||||
},
|
|
||||||
Image::ImageRect(ref image_rect) => {
|
|
||||||
specified::Image::ImageRect(
|
|
||||||
ToComputedValue::from_computed_value(image_rect)
|
|
||||||
)
|
|
||||||
},
|
|
||||||
Image::Element(ref selector) => {
|
|
||||||
specified::Image::Element(selector.clone())
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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
|
||||||
#[derive(Clone, PartialEq)]
|
pub type Image = GenericImage<Gradient, NumberOrPercentage>;
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
pub enum Image {
|
|
||||||
Url(SpecifiedUrl),
|
|
||||||
Gradient(Gradient),
|
|
||||||
ImageRect(ImageRect),
|
|
||||||
Element(Atom),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for Image {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
match *self {
|
|
||||||
Image::Url(ref url) => url.to_css(f),
|
|
||||||
Image::Gradient(ref grad) => {
|
|
||||||
if grad.repeating {
|
|
||||||
let _ = write!(f, "repeating-");
|
|
||||||
}
|
|
||||||
match grad.gradient_kind {
|
|
||||||
GradientKind::Linear(_) => write!(f, "linear-gradient({:?})", grad),
|
|
||||||
GradientKind::Radial(_, _) => write!(f, "radial-gradient({:?})", grad),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Image::ImageRect(ref image_rect) => write!(f, "{:?}", image_rect),
|
|
||||||
Image::Element(ref selector) => {
|
|
||||||
f.write_str("-moz-element(#")?;
|
|
||||||
serialize_identifier(&*selector.to_string(), f)?;
|
|
||||||
f.write_str(")")
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToCss for Image {
|
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
|
||||||
match *self {
|
|
||||||
Image::Url(ref url) => url.to_css(dest),
|
|
||||||
Image::Gradient(ref gradient) => gradient.to_css(dest),
|
|
||||||
Image::ImageRect(ref image_rect) => image_rect.to_css(dest),
|
|
||||||
Image::Element(ref selector) => {
|
|
||||||
dest.write_str("-moz-element(#")?;
|
|
||||||
// FIXME: We should get rid of these intermediate strings.
|
|
||||||
serialize_identifier(&*selector.to_string(), dest)?;
|
|
||||||
dest.write_str(")")
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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
|
||||||
#[derive(Clone, PartialEq)]
|
pub type Gradient = GenericGradient<GradientKind, CSSColor, LengthOrPercentage>;
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
|
||||||
pub struct Gradient {
|
/// A computed gradient item.
|
||||||
/// The color stops.
|
pub type GradientItem = GenericGradientItem<CSSColor, LengthOrPercentage>;
|
||||||
pub items: Vec<GradientItem>,
|
|
||||||
/// True if this is a repeating gradient.
|
/// A computed color stop.
|
||||||
pub repeating: bool,
|
pub type ColorStop = GenericColorStop<CSSColor, LengthOrPercentage>;
|
||||||
/// Gradient kind can be linear or radial.
|
|
||||||
pub gradient_kind: GradientKind,
|
/// Computed values for ImageRect.
|
||||||
/// Compatibility mode.
|
pub type ImageRect = GenericImageRect<NumberOrPercentage>;
|
||||||
pub compat_mode: CompatMode,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToCss for Gradient {
|
impl ToCss for Gradient {
|
||||||
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 {
|
||||||
|
@ -138,7 +45,7 @@ impl ToCss for Gradient {
|
||||||
if self.repeating {
|
if self.repeating {
|
||||||
try!(dest.write_str("repeating-"));
|
try!(dest.write_str("repeating-"));
|
||||||
}
|
}
|
||||||
match self.gradient_kind {
|
match self.kind {
|
||||||
GradientKind::Linear(angle_or_corner) => {
|
GradientKind::Linear(angle_or_corner) => {
|
||||||
try!(dest.write_str("linear-gradient("));
|
try!(dest.write_str("linear-gradient("));
|
||||||
try!(angle_or_corner.to_css(dest, self.compat_mode));
|
try!(angle_or_corner.to_css(dest, self.compat_mode));
|
||||||
|
@ -161,7 +68,7 @@ impl ToCss for Gradient {
|
||||||
|
|
||||||
impl fmt::Debug for Gradient {
|
impl fmt::Debug for Gradient {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self.gradient_kind {
|
match self.kind {
|
||||||
GradientKind::Linear(angle_or_corner) => {
|
GradientKind::Linear(angle_or_corner) => {
|
||||||
let _ = write!(f, "{:?}", angle_or_corner);
|
let _ = write!(f, "{:?}", angle_or_corner);
|
||||||
},
|
},
|
||||||
|
@ -177,42 +84,6 @@ impl fmt::Debug for Gradient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToComputedValue for specified::Gradient {
|
|
||||||
type ComputedValue = Gradient;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn to_computed_value(&self, context: &Context) -> Gradient {
|
|
||||||
let specified::Gradient {
|
|
||||||
ref items,
|
|
||||||
repeating,
|
|
||||||
ref gradient_kind,
|
|
||||||
compat_mode,
|
|
||||||
} = *self;
|
|
||||||
Gradient {
|
|
||||||
items: items.iter().map(|s| s.to_computed_value(context)).collect(),
|
|
||||||
repeating: repeating,
|
|
||||||
gradient_kind: gradient_kind.to_computed_value(context),
|
|
||||||
compat_mode: compat_mode,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn from_computed_value(computed: &Gradient) -> Self {
|
|
||||||
let Gradient {
|
|
||||||
ref items,
|
|
||||||
repeating,
|
|
||||||
ref gradient_kind,
|
|
||||||
compat_mode,
|
|
||||||
} = *computed;
|
|
||||||
specified::Gradient {
|
|
||||||
items: items.iter().map(ToComputedValue::from_computed_value).collect(),
|
|
||||||
repeating: repeating,
|
|
||||||
gradient_kind: ToComputedValue::from_computed_value(gradient_kind),
|
|
||||||
compat_mode: compat_mode,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Computed values for CSS linear or radial gradients.
|
/// Computed values for CSS linear or radial gradients.
|
||||||
/// https://drafts.csswg.org/css-images/#gradients
|
/// https://drafts.csswg.org/css-images/#gradients
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
|
@ -252,112 +123,6 @@ impl ToComputedValue for specified::GradientKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specified values for color stops and interpolation hints.
|
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
|
||||||
pub enum GradientItem {
|
|
||||||
/// A color stop.
|
|
||||||
ColorStop(ColorStop),
|
|
||||||
/// An interpolation hint.
|
|
||||||
InterpolationHint(LengthOrPercentage),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToCss for GradientItem {
|
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
|
||||||
match *self {
|
|
||||||
GradientItem::ColorStop(stop) => stop.to_css(dest),
|
|
||||||
GradientItem::InterpolationHint(hint) => hint.to_css(dest),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToComputedValue for specified::GradientItem {
|
|
||||||
type ComputedValue = GradientItem;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn to_computed_value(&self, context: &Context) -> GradientItem {
|
|
||||||
match *self {
|
|
||||||
specified::GradientItem::ColorStop(ref stop) => {
|
|
||||||
GradientItem::ColorStop(stop.to_computed_value(context))
|
|
||||||
},
|
|
||||||
specified::GradientItem::InterpolationHint(ref hint) => {
|
|
||||||
GradientItem::InterpolationHint(hint.to_computed_value(context))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn from_computed_value(computed: &GradientItem) -> Self {
|
|
||||||
match *computed {
|
|
||||||
GradientItem::ColorStop(ref stop) => {
|
|
||||||
specified::GradientItem::ColorStop(ToComputedValue::from_computed_value(stop))
|
|
||||||
},
|
|
||||||
GradientItem::InterpolationHint(ref hint) => {
|
|
||||||
specified::GradientItem::InterpolationHint(ToComputedValue::from_computed_value(hint))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Computed values for one color stop in a linear gradient.
|
|
||||||
/// https://drafts.csswg.org/css-images/#typedef-color-stop-list
|
|
||||||
#[derive(Clone, PartialEq, Copy)]
|
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
|
||||||
pub struct ColorStop {
|
|
||||||
/// The color of this stop.
|
|
||||||
pub color: CSSColor,
|
|
||||||
|
|
||||||
/// The position of this stop. If not specified, this stop is placed halfway between the
|
|
||||||
/// point that precedes it and the point that follows it per CSS-IMAGES § 3.4.
|
|
||||||
pub position: Option<LengthOrPercentage>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToCss for ColorStop {
|
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
|
||||||
try!(self.color.to_css(dest));
|
|
||||||
if let Some(position) = self.position {
|
|
||||||
try!(dest.write_str(" "));
|
|
||||||
try!(position.to_css(dest));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for ColorStop {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
let _ = write!(f, "{:?}", self.color);
|
|
||||||
self.position.map(|pos| {
|
|
||||||
let _ = write!(f, " {:?}", pos);
|
|
||||||
});
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToComputedValue for specified::ColorStop {
|
|
||||||
type ComputedValue = ColorStop;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn to_computed_value(&self, context: &Context) -> ColorStop {
|
|
||||||
ColorStop {
|
|
||||||
color: self.color.to_computed_value(context),
|
|
||||||
position: match self.position {
|
|
||||||
None => None,
|
|
||||||
Some(ref value) => Some(value.to_computed_value(context)),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_computed_value(computed: &ColorStop) -> Self {
|
|
||||||
specified::ColorStop {
|
|
||||||
color: ToComputedValue::from_computed_value(&computed.color),
|
|
||||||
position: match computed.position {
|
|
||||||
None => None,
|
|
||||||
Some(value) => Some(ToComputedValue::from_computed_value(&value)),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Computed values for EndingShape
|
/// Computed values for EndingShape
|
||||||
/// https://drafts.csswg.org/css-images/#valdef-radial-gradient-ending-shape
|
/// https://drafts.csswg.org/css-images/#valdef-radial-gradient-ending-shape
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
|
@ -425,59 +190,6 @@ impl ToComputedValue for specified::GradientEndingShape {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computed values for ImageRect
|
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
pub struct ImageRect {
|
|
||||||
pub url: SpecifiedUrl,
|
|
||||||
pub top: NumberOrPercentage,
|
|
||||||
pub bottom: NumberOrPercentage,
|
|
||||||
pub right: NumberOrPercentage,
|
|
||||||
pub left: NumberOrPercentage,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToCss for ImageRect {
|
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
|
||||||
dest.write_str("-moz-image-rect(")?;
|
|
||||||
self.url.to_css(dest)?;
|
|
||||||
dest.write_str(", ")?;
|
|
||||||
self.top.to_css(dest)?;
|
|
||||||
dest.write_str(", ")?;
|
|
||||||
self.right.to_css(dest)?;
|
|
||||||
dest.write_str(", ")?;
|
|
||||||
self.bottom.to_css(dest)?;
|
|
||||||
dest.write_str(", ")?;
|
|
||||||
self.left.to_css(dest)?;
|
|
||||||
dest.write_str(")")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToComputedValue for specified::ImageRect {
|
|
||||||
type ComputedValue = ImageRect;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn to_computed_value(&self, context: &Context) -> ImageRect {
|
|
||||||
ImageRect {
|
|
||||||
url: self.url.to_computed_value(context),
|
|
||||||
top: self.top.to_computed_value(context),
|
|
||||||
right: self.right.to_computed_value(context),
|
|
||||||
bottom: self.bottom.to_computed_value(context),
|
|
||||||
left: self.left.to_computed_value(context),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_computed_value(computed: &ImageRect) -> Self {
|
|
||||||
specified::ImageRect {
|
|
||||||
url: ToComputedValue::from_computed_value(&computed.url),
|
|
||||||
top: ToComputedValue::from_computed_value(&computed.top),
|
|
||||||
right: ToComputedValue::from_computed_value(&computed.right),
|
|
||||||
bottom: ToComputedValue::from_computed_value(&computed.bottom),
|
|
||||||
left: ToComputedValue::from_computed_value(&computed.left),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// https://drafts.csswg.org/css-images/#valdef-radial-gradient-size
|
/// https://drafts.csswg.org/css-images/#valdef-radial-gradient-size
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
|
362
components/style/values/generics/image.rs
Normal file
362
components/style/values/generics/image.rs
Normal file
|
@ -0,0 +1,362 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
//! Generic types for the handling of [images].
|
||||||
|
//!
|
||||||
|
//! [images]: https://drafts.csswg.org/css-images/#image-values
|
||||||
|
|
||||||
|
use Atom;
|
||||||
|
use cssparser::serialize_identifier;
|
||||||
|
use std::fmt;
|
||||||
|
use style_traits::ToCss;
|
||||||
|
use values::HasViewportPercentage;
|
||||||
|
use values::computed::{Context, ToComputedValue};
|
||||||
|
use values::specified::url::SpecifiedUrl;
|
||||||
|
|
||||||
|
/// An [image].
|
||||||
|
///
|
||||||
|
/// [image]: https://drafts.csswg.org/css-images/#image-values
|
||||||
|
#[derive(Clone, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
pub enum Image<G, N> {
|
||||||
|
/// A `<url()>` image.
|
||||||
|
Url(SpecifiedUrl),
|
||||||
|
/// A `<gradient>` image.
|
||||||
|
Gradient(G),
|
||||||
|
/// A `-moz-image-rect` image
|
||||||
|
Rect(ImageRect<N>),
|
||||||
|
/// A `-moz-element(# <element-id>)`
|
||||||
|
Element(Atom),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A CSS gradient.
|
||||||
|
/// https://drafts.csswg.org/css-images/#gradients
|
||||||
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
pub struct Gradient<K, C, L> {
|
||||||
|
/// Gradients can be linear or radial.
|
||||||
|
pub kind: K,
|
||||||
|
/// The color stops and interpolation hints.
|
||||||
|
pub items: Vec<GradientItem<C, L>>,
|
||||||
|
/// True if this is a repeating gradient.
|
||||||
|
pub repeating: bool,
|
||||||
|
/// Compatibility mode.
|
||||||
|
pub compat_mode: CompatMode,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||||
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
/// Whether we used the modern notation or the compatibility `-webkit` prefix.
|
||||||
|
pub enum CompatMode {
|
||||||
|
/// Modern syntax.
|
||||||
|
Modern,
|
||||||
|
/// `-webkit` prefix.
|
||||||
|
WebKit,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A gradient item.
|
||||||
|
/// https://drafts.csswg.org/css-images-4/#color-stop-syntax
|
||||||
|
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||||
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
pub enum GradientItem<C, L> {
|
||||||
|
/// A color stop.
|
||||||
|
ColorStop(ColorStop<C, L>),
|
||||||
|
/// An interpolation hint.
|
||||||
|
InterpolationHint(L),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A color stop.
|
||||||
|
/// https://drafts.csswg.org/css-images/#typedef-color-stop-list
|
||||||
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
pub struct ColorStop<C, L> {
|
||||||
|
/// The color of this stop.
|
||||||
|
pub color: C,
|
||||||
|
/// The position of this stop.
|
||||||
|
pub position: Option<L>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Values for `moz-image-rect`.
|
||||||
|
///
|
||||||
|
/// `-moz-image-rect(<uri>, top, right, bottom, left);`
|
||||||
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub struct ImageRect<C> {
|
||||||
|
pub url: SpecifiedUrl,
|
||||||
|
pub top: C,
|
||||||
|
pub bottom: C,
|
||||||
|
pub right: C,
|
||||||
|
pub left: C,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<G, N> fmt::Debug for Image<G, N>
|
||||||
|
where G: fmt::Debug, N: fmt::Debug,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
Image::Url(ref url) => url.to_css(f),
|
||||||
|
Image::Gradient(ref grad) => grad.fmt(f),
|
||||||
|
Image::Rect(ref rect) => rect.fmt(f),
|
||||||
|
Image::Element(ref selector) => {
|
||||||
|
f.write_str("-moz-element(#")?;
|
||||||
|
serialize_identifier(&selector.to_string(), f)?;
|
||||||
|
f.write_str(")")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<G, N> ToCss for Image<G, N>
|
||||||
|
where G: ToCss, N: ToCss,
|
||||||
|
{
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
match *self {
|
||||||
|
Image::Url(ref url) => url.to_css(dest),
|
||||||
|
Image::Gradient(ref gradient) => gradient.to_css(dest),
|
||||||
|
Image::Rect(ref rect) => rect.to_css(dest),
|
||||||
|
Image::Element(ref selector) => {
|
||||||
|
dest.write_str("-moz-element(#")?;
|
||||||
|
serialize_identifier(&selector.to_string(), dest)?;
|
||||||
|
dest.write_str(")")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<G, N> HasViewportPercentage for Image<G, N>
|
||||||
|
where G: HasViewportPercentage
|
||||||
|
{
|
||||||
|
fn has_viewport_percentage(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Image::Gradient(ref gradient) => gradient.has_viewport_percentage(),
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<G, N> ToComputedValue for Image<G, N>
|
||||||
|
where G: ToComputedValue, N: ToComputedValue,
|
||||||
|
{
|
||||||
|
type ComputedValue = Image<<G as ToComputedValue>::ComputedValue,
|
||||||
|
<N as ToComputedValue>::ComputedValue>;
|
||||||
|
|
||||||
|
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||||
|
match *self {
|
||||||
|
Image::Url(ref url) => {
|
||||||
|
Image::Url(url.clone())
|
||||||
|
},
|
||||||
|
Image::Gradient(ref gradient) => {
|
||||||
|
Image::Gradient(gradient.to_computed_value(context))
|
||||||
|
},
|
||||||
|
Image::Rect(ref rect) => {
|
||||||
|
Image::Rect(rect.to_computed_value(context))
|
||||||
|
},
|
||||||
|
Image::Element(ref selector) => {
|
||||||
|
Image::Element(selector.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||||
|
match *computed {
|
||||||
|
Image::Url(ref url) => {
|
||||||
|
Image::Url(url.clone())
|
||||||
|
},
|
||||||
|
Image::Gradient(ref gradient) => {
|
||||||
|
Image::Gradient(ToComputedValue::from_computed_value(gradient))
|
||||||
|
},
|
||||||
|
Image::Rect(ref rect) => {
|
||||||
|
Image::Rect(ToComputedValue::from_computed_value(rect))
|
||||||
|
},
|
||||||
|
Image::Element(ref selector) => {
|
||||||
|
Image::Element(selector.clone())
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K, C, L> HasViewportPercentage for Gradient<K, C, L>
|
||||||
|
where K: HasViewportPercentage, L: HasViewportPercentage,
|
||||||
|
{
|
||||||
|
fn has_viewport_percentage(&self) -> bool {
|
||||||
|
self.kind.has_viewport_percentage() ||
|
||||||
|
self.items.iter().any(|i| i.has_viewport_percentage())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K, C, L> ToComputedValue for Gradient<K, C, L>
|
||||||
|
where K: ToComputedValue, C: ToComputedValue, L: ToComputedValue,
|
||||||
|
{
|
||||||
|
type ComputedValue = Gradient<<K as ToComputedValue>::ComputedValue,
|
||||||
|
<C as ToComputedValue>::ComputedValue,
|
||||||
|
<L as ToComputedValue>::ComputedValue>;
|
||||||
|
|
||||||
|
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||||
|
Gradient {
|
||||||
|
kind: self.kind.to_computed_value(context),
|
||||||
|
items: self.items.iter().map(|s| s.to_computed_value(context)).collect(),
|
||||||
|
repeating: self.repeating,
|
||||||
|
compat_mode: self.compat_mode,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||||
|
Gradient {
|
||||||
|
kind: ToComputedValue::from_computed_value(&computed.kind),
|
||||||
|
items: computed.items.iter().map(ToComputedValue::from_computed_value).collect(),
|
||||||
|
repeating: computed.repeating,
|
||||||
|
compat_mode: computed.compat_mode,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C, L> ToCss for GradientItem<C, L>
|
||||||
|
where C: ToCss, L: ToCss,
|
||||||
|
{
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
match *self {
|
||||||
|
GradientItem::ColorStop(ref stop) => stop.to_css(dest),
|
||||||
|
GradientItem::InterpolationHint(ref hint) => hint.to_css(dest),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C, L> HasViewportPercentage for GradientItem<C, L>
|
||||||
|
where L: HasViewportPercentage,
|
||||||
|
{
|
||||||
|
fn has_viewport_percentage(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
GradientItem::ColorStop(ref stop) => stop.has_viewport_percentage(),
|
||||||
|
GradientItem::InterpolationHint(ref hint) => hint.has_viewport_percentage(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C, L> ToComputedValue for GradientItem<C, L>
|
||||||
|
where C: ToComputedValue, L: ToComputedValue,
|
||||||
|
{
|
||||||
|
type ComputedValue = GradientItem<<C as ToComputedValue>::ComputedValue,
|
||||||
|
<L as ToComputedValue>::ComputedValue>;
|
||||||
|
|
||||||
|
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||||
|
match *self {
|
||||||
|
GradientItem::ColorStop(ref stop) => {
|
||||||
|
GradientItem::ColorStop(stop.to_computed_value(context))
|
||||||
|
},
|
||||||
|
GradientItem::InterpolationHint(ref hint) => {
|
||||||
|
GradientItem::InterpolationHint(hint.to_computed_value(context))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||||
|
match *computed {
|
||||||
|
GradientItem::ColorStop(ref stop) => {
|
||||||
|
GradientItem::ColorStop(ToComputedValue::from_computed_value(stop))
|
||||||
|
},
|
||||||
|
GradientItem::InterpolationHint(ref hint) => {
|
||||||
|
GradientItem::InterpolationHint(ToComputedValue::from_computed_value(hint))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C, L> fmt::Debug for ColorStop<C, L>
|
||||||
|
where C: fmt::Debug, L: fmt::Debug,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{:?}", self.color)?;
|
||||||
|
if let Some(ref pos) = self.position {
|
||||||
|
write!(f, " {:?}", pos)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C, L> ToCss for ColorStop<C, L>
|
||||||
|
where C: ToCss, L: ToCss,
|
||||||
|
{
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
self.color.to_css(dest)?;
|
||||||
|
if let Some(ref position) = self.position {
|
||||||
|
dest.write_str(" ")?;
|
||||||
|
position.to_css(dest)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C, L> HasViewportPercentage for ColorStop<C, L>
|
||||||
|
where L: HasViewportPercentage,
|
||||||
|
{
|
||||||
|
fn has_viewport_percentage(&self) -> bool {
|
||||||
|
self.position.as_ref().map_or(false, HasViewportPercentage::has_viewport_percentage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C, L> ToComputedValue for ColorStop<C, L>
|
||||||
|
where C: ToComputedValue, L: ToComputedValue,
|
||||||
|
{
|
||||||
|
type ComputedValue = ColorStop<<C as ToComputedValue>::ComputedValue,
|
||||||
|
<L as ToComputedValue>::ComputedValue>;
|
||||||
|
|
||||||
|
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||||
|
ColorStop {
|
||||||
|
color: self.color.to_computed_value(context),
|
||||||
|
position: self.position.as_ref().map(|p| p.to_computed_value(context)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||||
|
ColorStop {
|
||||||
|
color: ToComputedValue::from_computed_value(&computed.color),
|
||||||
|
position: computed.position.as_ref().map(ToComputedValue::from_computed_value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C> ToCss for ImageRect<C>
|
||||||
|
where C: ToCss,
|
||||||
|
{
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
dest.write_str("-moz-image-rect(")?;
|
||||||
|
self.url.to_css(dest)?;
|
||||||
|
dest.write_str(", ")?;
|
||||||
|
self.top.to_css(dest)?;
|
||||||
|
dest.write_str(", ")?;
|
||||||
|
self.right.to_css(dest)?;
|
||||||
|
dest.write_str(", ")?;
|
||||||
|
self.bottom.to_css(dest)?;
|
||||||
|
dest.write_str(", ")?;
|
||||||
|
self.left.to_css(dest)?;
|
||||||
|
dest.write_str(")")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C> ToComputedValue for ImageRect<C>
|
||||||
|
where C: ToComputedValue,
|
||||||
|
{
|
||||||
|
type ComputedValue = ImageRect<<C as ToComputedValue>::ComputedValue>;
|
||||||
|
|
||||||
|
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||||
|
ImageRect {
|
||||||
|
url: self.url.clone(),
|
||||||
|
top: self.top.to_computed_value(context),
|
||||||
|
right: self.right.to_computed_value(context),
|
||||||
|
bottom: self.bottom.to_computed_value(context),
|
||||||
|
left: self.left.to_computed_value(context),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||||
|
ImageRect {
|
||||||
|
url: computed.url.clone(),
|
||||||
|
top: ToComputedValue::from_computed_value(&computed.top),
|
||||||
|
right: ToComputedValue::from_computed_value(&computed.right),
|
||||||
|
bottom: ToComputedValue::from_computed_value(&computed.bottom),
|
||||||
|
left: ToComputedValue::from_computed_value(&computed.left),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,6 +14,7 @@ use super::computed::{Context, ToComputedValue};
|
||||||
pub use self::basic_shape::serialize_radius_values;
|
pub use self::basic_shape::serialize_radius_values;
|
||||||
|
|
||||||
pub mod basic_shape;
|
pub mod basic_shape;
|
||||||
|
pub mod image;
|
||||||
pub mod position;
|
pub mod position;
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
|
|
|
@ -8,68 +8,58 @@
|
||||||
//! [image]: https://drafts.csswg.org/css-images/#image-values
|
//! [image]: https://drafts.csswg.org/css-images/#image-values
|
||||||
|
|
||||||
use Atom;
|
use Atom;
|
||||||
use cssparser::{Parser, Token, serialize_identifier};
|
use cssparser::{Parser, Token};
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
|
use values::generics::image::{CompatMode, ColorStop as GenericColorStop};
|
||||||
|
use values::generics::image::{Gradient as GenericGradient, GradientItem as GenericGradientItem};
|
||||||
|
use values::generics::image::{Image as GenericImage, ImageRect as GenericImageRect};
|
||||||
use values::specified::{Angle, CSSColor, Length, LengthOrPercentage, NumberOrPercentage};
|
use values::specified::{Angle, CSSColor, Length, LengthOrPercentage, NumberOrPercentage};
|
||||||
use values::specified::position::Position;
|
use values::specified::position::Position;
|
||||||
use values::specified::url::SpecifiedUrl;
|
use values::specified::url::SpecifiedUrl;
|
||||||
|
|
||||||
/// 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
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
pub type Image = GenericImage<Gradient, NumberOrPercentage>;
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
|
||||||
pub enum Image {
|
|
||||||
/// A `<url()>` image.
|
|
||||||
Url(SpecifiedUrl),
|
|
||||||
/// A `<gradient>` image.
|
|
||||||
Gradient(Gradient),
|
|
||||||
/// A `-moz-image-rect` image
|
|
||||||
ImageRect(ImageRect),
|
|
||||||
/// A `-moz-element(# <element-id>)`
|
|
||||||
Element(Atom),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToCss for Image {
|
/// Specified values for a CSS gradient.
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
/// https://drafts.csswg.org/css-images/#gradients
|
||||||
match *self {
|
pub type Gradient = GenericGradient<GradientKind, CSSColor, LengthOrPercentage>;
|
||||||
Image::Url(ref url_value) => url_value.to_css(dest),
|
|
||||||
Image::Gradient(ref gradient) => gradient.to_css(dest),
|
/// A specified gradient item.
|
||||||
Image::ImageRect(ref image_rect) => image_rect.to_css(dest),
|
pub type GradientItem = GenericGradientItem<CSSColor, LengthOrPercentage>;
|
||||||
Image::Element(ref selector) => {
|
|
||||||
dest.write_str("-moz-element(#")?;
|
/// A computed color stop.
|
||||||
// FIXME: We should get rid of these intermediate strings.
|
pub type ColorStop = GenericColorStop<CSSColor, LengthOrPercentage>;
|
||||||
serialize_identifier(&*selector.to_string(), dest)?;
|
|
||||||
dest.write_str(")")
|
/// Specified values for `moz-image-rect`
|
||||||
},
|
/// -moz-image-rect(<uri>, top, right, bottom, left);
|
||||||
}
|
pub type ImageRect = GenericImageRect<NumberOrPercentage>;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Image {
|
impl Image {
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<Image, ()> {
|
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<Image, ()> {
|
||||||
if let Ok(url) = input.try(|input| SpecifiedUrl::parse(context, input)) {
|
if let Ok(url) = input.try(|input| SpecifiedUrl::parse(context, input)) {
|
||||||
return Ok(Image::Url(url));
|
return Ok(GenericImage::Url(url));
|
||||||
}
|
}
|
||||||
if let Ok(gradient) = input.try(|input| Gradient::parse_function(context, input)) {
|
if let Ok(gradient) = input.try(|input| Gradient::parse_function(context, input)) {
|
||||||
return Ok(Image::Gradient(gradient));
|
return Ok(GenericImage::Gradient(gradient));
|
||||||
}
|
}
|
||||||
if let Ok(image_rect) = input.try(|input| ImageRect::parse(context, input)) {
|
if let Ok(image_rect) = input.try(|input| ImageRect::parse(context, input)) {
|
||||||
return Ok(Image::ImageRect(image_rect));
|
return Ok(GenericImage::Rect(image_rect));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Image::Element(Image::parse_element(input)?))
|
Ok(GenericImage::Element(Image::parse_element(input)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates an already specified image value from an already resolved URL
|
/// Creates an already specified image value from an already resolved URL
|
||||||
/// for insertion in the cascade.
|
/// for insertion in the cascade.
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
pub fn for_cascade(url: ServoUrl) -> Self {
|
pub fn for_cascade(url: ServoUrl) -> Self {
|
||||||
Image::Url(SpecifiedUrl::for_cascade(url))
|
GenericImage::Url(SpecifiedUrl::for_cascade(url))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a `-moz-element(# <element-id>)`.
|
/// Parses a `-moz-element(# <element-id>)`.
|
||||||
|
@ -87,21 +77,6 @@ impl Image {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specified values for a CSS gradient.
|
|
||||||
/// https://drafts.csswg.org/css-images/#gradients
|
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
|
||||||
pub struct Gradient {
|
|
||||||
/// The color stops and interpolation hints.
|
|
||||||
pub items: Vec<GradientItem>,
|
|
||||||
/// True if this is a repeating gradient.
|
|
||||||
pub repeating: bool,
|
|
||||||
/// Gradients can be linear or radial.
|
|
||||||
pub gradient_kind: GradientKind,
|
|
||||||
/// Compatibility mode.
|
|
||||||
pub compat_mode: CompatMode,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToCss for Gradient {
|
impl ToCss for Gradient {
|
||||||
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 {
|
||||||
if self.compat_mode == CompatMode::WebKit {
|
if self.compat_mode == CompatMode::WebKit {
|
||||||
|
@ -111,7 +86,7 @@ impl ToCss for Gradient {
|
||||||
try!(dest.write_str("repeating-"));
|
try!(dest.write_str("repeating-"));
|
||||||
}
|
}
|
||||||
let mut skipcomma = false;
|
let mut skipcomma = false;
|
||||||
match self.gradient_kind {
|
match self.kind {
|
||||||
GradientKind::Linear(angle_or_corner) => {
|
GradientKind::Linear(angle_or_corner) => {
|
||||||
try!(dest.write_str("linear-gradient("));
|
try!(dest.write_str("linear-gradient("));
|
||||||
try!(angle_or_corner.to_css(dest, self.compat_mode));
|
try!(angle_or_corner.to_css(dest, self.compat_mode));
|
||||||
|
@ -198,7 +173,7 @@ impl Gradient {
|
||||||
Ok(Gradient {
|
Ok(Gradient {
|
||||||
items: items,
|
items: items,
|
||||||
repeating: repeating,
|
repeating: repeating,
|
||||||
gradient_kind: gradient_kind,
|
kind: gradient_kind,
|
||||||
compat_mode: compat_mode,
|
compat_mode: compat_mode,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -209,11 +184,11 @@ impl Gradient {
|
||||||
if seen_stop {
|
if seen_stop {
|
||||||
if let Ok(hint) = input.try(|i| LengthOrPercentage::parse(context, i)) {
|
if let Ok(hint) = input.try(|i| LengthOrPercentage::parse(context, i)) {
|
||||||
seen_stop = false;
|
seen_stop = false;
|
||||||
return Ok(GradientItem::InterpolationHint(hint));
|
return Ok(GenericGradientItem::InterpolationHint(hint));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
seen_stop = true;
|
seen_stop = true;
|
||||||
ColorStop::parse(context, input).map(GradientItem::ColorStop)
|
ColorStop::parse(context, input).map(GenericGradientItem::ColorStop)
|
||||||
}));
|
}));
|
||||||
if !seen_stop || items.len() < 2 {
|
if !seen_stop || items.len() < 2 {
|
||||||
return Err(());
|
return Err(());
|
||||||
|
@ -238,16 +213,6 @@ pub enum GradientKind {
|
||||||
Radial(EndingShape, Position),
|
Radial(EndingShape, Position),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
|
||||||
/// Whether we used the modern notation or the compatibility `-webkit` prefix.
|
|
||||||
pub enum CompatMode {
|
|
||||||
/// Modern syntax.
|
|
||||||
Modern,
|
|
||||||
/// `-webkit` prefix.
|
|
||||||
WebKit,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GradientKind {
|
impl GradientKind {
|
||||||
/// Parses a linear gradient kind from the given arguments.
|
/// Parses a linear gradient kind from the given arguments.
|
||||||
fn parse_modern_linear(context: &ParserContext, input: &mut Parser) -> Result<GradientKind, ()> {
|
fn parse_modern_linear(context: &ParserContext, input: &mut Parser) -> Result<GradientKind, ()> {
|
||||||
|
@ -396,35 +361,6 @@ impl GradientKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specified values for `moz-image-rect`
|
|
||||||
/// -moz-image-rect(<uri>, top, right, bottom, left);
|
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
pub struct ImageRect {
|
|
||||||
pub url: SpecifiedUrl,
|
|
||||||
pub top: NumberOrPercentage,
|
|
||||||
pub bottom: NumberOrPercentage,
|
|
||||||
pub right: NumberOrPercentage,
|
|
||||||
pub left: NumberOrPercentage,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToCss for ImageRect {
|
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
|
||||||
dest.write_str("-moz-image-rect(")?;
|
|
||||||
self.url.to_css(dest)?;
|
|
||||||
dest.write_str(", ")?;
|
|
||||||
self.top.to_css(dest)?;
|
|
||||||
dest.write_str(", ")?;
|
|
||||||
self.right.to_css(dest)?;
|
|
||||||
dest.write_str(", ")?;
|
|
||||||
self.bottom.to_css(dest)?;
|
|
||||||
dest.write_str(", ")?;
|
|
||||||
self.left.to_css(dest)?;
|
|
||||||
dest.write_str(")")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Parse for ImageRect {
|
impl Parse for ImageRect {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||||
match_ignore_ascii_case! { &try!(input.expect_function()),
|
match_ignore_ascii_case! { &try!(input.expect_function()),
|
||||||
|
@ -502,50 +438,6 @@ impl AngleOrCorner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specified values for color stops and interpolation hints.
|
|
||||||
/// https://drafts.csswg.org/css-images-4/#color-stop-syntax
|
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
|
||||||
pub enum GradientItem {
|
|
||||||
/// A color stop.
|
|
||||||
ColorStop(ColorStop),
|
|
||||||
/// An interpolation hint.
|
|
||||||
InterpolationHint(LengthOrPercentage),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToCss for GradientItem {
|
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
|
||||||
match *self {
|
|
||||||
GradientItem::ColorStop(ref stop) => stop.to_css(dest),
|
|
||||||
GradientItem::InterpolationHint(ref hint) => hint.to_css(dest),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Specified values for one color stop in a gradient.
|
|
||||||
/// https://drafts.csswg.org/css-images/#typedef-color-stop-list
|
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
|
||||||
pub struct ColorStop {
|
|
||||||
/// The color of this stop.
|
|
||||||
pub color: CSSColor,
|
|
||||||
|
|
||||||
/// The position of this stop. If not specified, this stop is placed halfway between the
|
|
||||||
/// point that precedes it and the point that follows it.
|
|
||||||
pub position: Option<LengthOrPercentage>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToCss for ColorStop {
|
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
|
||||||
try!(self.color.to_css(dest));
|
|
||||||
if let Some(ref position) = self.position {
|
|
||||||
try!(dest.write_str(" "));
|
|
||||||
try!(position.to_css(dest));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_css_keyword_enum!(HorizontalDirection: "left" => Left, "right" => Right);
|
define_css_keyword_enum!(HorizontalDirection: "left" => Left, "right" => Right);
|
||||||
define_css_keyword_enum!(VerticalDirection: "top" => Top, "bottom" => Bottom);
|
define_css_keyword_enum!(VerticalDirection: "top" => Top, "bottom" => Bottom);
|
||||||
|
|
||||||
|
|
|
@ -1801,7 +1801,7 @@ pub extern "C" fn Servo_DeclarationBlock_SetBackgroundImage(declarations:
|
||||||
use style::properties::PropertyDeclaration;
|
use style::properties::PropertyDeclaration;
|
||||||
use style::properties::longhands::background_image::SpecifiedValue as BackgroundImage;
|
use style::properties::longhands::background_image::SpecifiedValue as BackgroundImage;
|
||||||
use style::properties::longhands::background_image::single_value::SpecifiedValue as SingleBackgroundImage;
|
use style::properties::longhands::background_image::single_value::SpecifiedValue as SingleBackgroundImage;
|
||||||
use style::values::specified::image::Image;
|
use style::values::generics::image::Image;
|
||||||
use style::values::specified::url::SpecifiedUrl;
|
use style::values::specified::url::SpecifiedUrl;
|
||||||
|
|
||||||
let url_data = unsafe { RefPtr::from_ptr_ref(&raw_extra_data) };
|
let url_data = unsafe { RefPtr::from_ptr_ref(&raw_extra_data) };
|
||||||
|
|
|
@ -799,7 +799,7 @@ mod shorthand_serialization {
|
||||||
use style::properties::longhands::mask_position_y as position_y;
|
use style::properties::longhands::mask_position_y as position_y;
|
||||||
use style::properties::longhands::mask_repeat as repeat;
|
use style::properties::longhands::mask_repeat as repeat;
|
||||||
use style::properties::longhands::mask_size as size;
|
use style::properties::longhands::mask_size as size;
|
||||||
use style::values::specified::Image;
|
use style::values::generics::image::Image;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
macro_rules! single_vec_value_typedef {
|
macro_rules! single_vec_value_typedef {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue