Bug 1371115 - Part 3: implements nsStyleSides type properties animatable. r?hiro
In this patch, implements following properties:
* border-image-outset
* border-image-slice
* border-image-width
MozReview-Commit-ID: K4w1zqX6Zkd
--- a/servo/components/style/gecko/conversions.rs
+++ b/servo/components/style/gecko/conversions.rs
@@ -15,16 +15,17 @@ use gecko_bindings::bindings::{Gecko_Ini
use gecko_bindings::structs::{nsCSSUnit, nsStyleCoord_CalcValue, nsStyleImage};
use gecko_bindings::structs::{nsresult, SheetType};
use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordDataMut};
use stylesheets::{Origin, RulesMutateError};
use values::computed::{Angle, CalcLengthOrPercentage, Gradient, Image};
use values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
use values::generics::grid::TrackSize;
use values::generics::image::{CompatMode, Image as GenericImage, GradientItem};
+use values::generics::rect::Rect;
use values::specified::length::Percentage;
impl From<CalcLengthOrPercentage> for nsStyleCoord_CalcValue {
fn from(other: CalcLengthOrPercentage) -> nsStyleCoord_CalcValue {
let has_percentage = other.percentage.is_some();
nsStyleCoord_CalcValue {
mLength: other.unclamped_length().0,
mPercent: other.percentage.map_or(0., |p| p.0),
@@ -630,8 +631,33 @@ impl TrackSize<LengthOrPercentage> {
},
TrackSize::MinMax(ref min, ref max) => {
min.to_gecko_style_coord(gecko_min);
max.to_gecko_style_coord(gecko_max);
},
}
}
}
+
+impl<T> Rect<T> where T: GeckoStyleCoordConvertible {
+ /// Convert this generic Rect to given Gecko fields.
+ pub fn to_gecko_rect(&self, sides: &mut ::gecko_bindings::structs::nsStyleSides) {
+ self.0.to_gecko_style_coord(&mut sides.data_at_mut(0));
+ self.1.to_gecko_style_coord(&mut sides.data_at_mut(1));
+ self.2.to_gecko_style_coord(&mut sides.data_at_mut(2));
+ self.3.to_gecko_style_coord(&mut sides.data_at_mut(3));
+ }
+
+ /// Convert from given Gecko data to generic Rect.
+ pub fn from_gecko_rect(sides: &::gecko_bindings::structs::nsStyleSides)
+ -> Option<::values::generics::rect::Rect<T>> {
+ use values::generics::rect::Rect;
+
+ Some(
+ Rect::new(
+ T::from_gecko_style_coord(&sides.data_at(0)).expect("coord[0] cound not convert"),
+ T::from_gecko_style_coord(&sides.data_at(1)).expect("coord[1] cound not convert"),
+ T::from_gecko_style_coord(&sides.data_at(2)).expect("coord[2] cound not convert"),
+ T::from_gecko_style_coord(&sides.data_at(3)).expect("coord[3] cound not convert")
+ )
+ )
+ }
+}
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -576,16 +576,45 @@ def set_gecko_property(ffi_name, expr):
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
use properties::longhands::${ident}::computed_value::T;
T::from_gecko_style_coord(&self.gecko.${gecko_ffi_name})
.expect("clone for ${ident} failed")
}
% endif
</%def>
+<%def name="impl_style_sides(ident)">
+ <% gecko_ffi_name = "m" + to_camel_case(ident) %>
+
+ #[allow(non_snake_case)]
+ pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
+ v.to_gecko_rect(&mut self.gecko.${gecko_ffi_name});
+ }
+
+ <%self:copy_sides_style_coord ident="${ident}"></%self:copy_sides_style_coord>
+
+ #[allow(non_snake_case)]
+ pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
+ longhands::${ident}::computed_value::T::from_gecko_rect(&self.gecko.${gecko_ffi_name})
+ .expect("clone for ${ident} failed")
+ }
+</%def>
+
+<%def name="copy_sides_style_coord(ident)">
+ <% gecko_ffi_name = "m" + to_camel_case(ident) %>
+ #[allow(non_snake_case)]
+ pub fn copy_${ident}_from(&mut self, other: &Self) {
+ % for side in SIDES:
+ self.gecko.${gecko_ffi_name}.data_at_mut(${side.index})
+ .copy_from(&other.gecko.${gecko_ffi_name}.data_at(${side.index}));
+ % endfor
+ ${ caller.body() }
+ }
+</%def>
+
<%def name="impl_corner_style_coord(ident, gecko_ffi_name, x_index, y_index, need_clone)">
#[allow(non_snake_case)]
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
v.0.width.to_gecko_style_coord(&mut self.gecko.${gecko_ffi_name}.data_at_mut(${x_index}));
v.0.height.to_gecko_style_coord(&mut self.gecko.${gecko_ffi_name}.data_at_mut(${y_index}));
}
#[allow(non_snake_case)]
pub fn copy_${ident}_from(&mut self, other: &Self) {
@@ -1014,28 +1043,17 @@ fn static_assert() {
pub fn copy_border_image_source_from(&mut self, other: &Self) {
unsafe {
Gecko_CopyImageValueFrom(&mut self.gecko.mBorderImageSource,
&other.gecko.mBorderImageSource);
}
}
- pub fn set_border_image_outset(&mut self, v: longhands::border_image_outset::computed_value::T) {
- % for side in SIDES:
- v.${side.index}.to_gecko_style_coord(&mut self.gecko.mBorderImageOutset.data_at_mut(${side.index}));
- % endfor
- }
-
- pub fn copy_border_image_outset_from(&mut self, other: &Self) {
- % for side in SIDES:
- self.gecko.mBorderImageOutset.data_at_mut(${side.index})
- .copy_from(&other.gecko.mBorderImageOutset.data_at(${side.index}));
- % endfor
- }
+ <% impl_style_sides("border_image_outset") %>
<%
border_image_repeat_keywords = ["Stretch", "Repeat", "Round", "Space"]
%>
pub fn set_border_image_repeat(&mut self, v: longhands::border_image_repeat::computed_value::T) {
use properties::longhands::border_image_repeat::computed_value::RepeatKeyword;
use gecko_bindings::structs;
@@ -1066,62 +1084,46 @@ fn static_assert() {
structs::NS_STYLE_BORDER_IMAGE_REPEAT_${keyword.upper()} => RepeatKeyword::${keyword},
% endfor
x => panic!("Found unexpected value in mBorderImageRepeat${side}: {:?}", x),
};
% endfor
longhands::border_image_repeat::computed_value::T(servo_h, servo_v)
}
- pub fn set_border_image_width(&mut self, v: longhands::border_image_width::computed_value::T) {
- use values::generics::border::BorderImageSideWidth;
-
- % for side in SIDES:
- match v.${side.index} {
- BorderImageSideWidth::Auto => {
- self.gecko.mBorderImageWidth.data_at_mut(${side.index}).set_value(CoordDataValue::Auto)
- },
- BorderImageSideWidth::Length(l) => {
- l.to_gecko_style_coord(&mut self.gecko.mBorderImageWidth.data_at_mut(${side.index}))
- },
- BorderImageSideWidth::Number(n) => {
- self.gecko.mBorderImageWidth.data_at_mut(${side.index}).set_value(CoordDataValue::Factor(n))
- },
- }
- % endfor
- }
-
- pub fn copy_border_image_width_from(&mut self, other: &Self) {
- % for side in SIDES:
- self.gecko.mBorderImageWidth.data_at_mut(${side.index})
- .copy_from(&other.gecko.mBorderImageWidth.data_at(${side.index}));
- % endfor
- }
+ <% impl_style_sides("border_image_width") %>
pub fn set_border_image_slice(&mut self, v: longhands::border_image_slice::computed_value::T) {
use gecko_bindings::structs::{NS_STYLE_BORDER_IMAGE_SLICE_NOFILL, NS_STYLE_BORDER_IMAGE_SLICE_FILL};
- % for side in SIDES:
- v.offsets.${side.index}.to_gecko_style_coord(&mut self.gecko.mBorderImageSlice.data_at_mut(${side.index}));
- % endfor
+ v.offsets.to_gecko_rect(&mut self.gecko.mBorderImageSlice);
let fill = if v.fill {
NS_STYLE_BORDER_IMAGE_SLICE_FILL
} else {
NS_STYLE_BORDER_IMAGE_SLICE_NOFILL
};
self.gecko.mBorderImageFill = fill as u8;
}
- pub fn copy_border_image_slice_from(&mut self, other: &Self) {
- for i in 0..4 {
- self.gecko.mBorderImageSlice.data_at_mut(i)
- .copy_from(&other.gecko.mBorderImageSlice.data_at(i));
+ <%self:copy_sides_style_coord ident="border_image_slice">
+ self.gecko.mBorderImageFill = other.gecko.mBorderImageFill;
+ </%self:copy_sides_style_coord>
+
+ pub fn clone_border_image_slice(&self) -> longhands::border_image_slice::computed_value::T {
+ use gecko_bindings::structs::NS_STYLE_BORDER_IMAGE_SLICE_FILL;
+ use values::computed::{BorderImageSlice, NumberOrPercentage};
+ type NumberOrPercentageRect = ::values::generics::rect::Rect<NumberOrPercentage>;
+
+ BorderImageSlice {
+ offsets:
+ NumberOrPercentageRect::from_gecko_rect(&self.gecko.mBorderImageSlice)
+ .expect("mBorderImageSlice[${side.index}] could not convert to NumberOrPercentageRect"),
+ fill: self.gecko.mBorderImageFill as u32 == NS_STYLE_BORDER_IMAGE_SLICE_FILL
}
- self.gecko.mBorderImageFill = other.gecko.mBorderImageFill;
}
</%self:impl_trait>
<% skip_margin_longhands = " ".join(["margin-%s" % x.ident for x in SIDES]) %>
<%self:impl_trait style_struct_name="Margin"
skip_longhands="${skip_margin_longhands}">
% for side in SIDES:
--- a/servo/components/style/properties/longhand/border.mako.rs
+++ b/servo/components/style/properties/longhand/border.mako.rs
@@ -204,17 +204,17 @@
has_uncacheable_values=False,
boxed="True")}
${helpers.predefined_type("border-image-outset", "LengthOrNumberRect",
parse_method="parse_non_negative",
initial_value="computed::LengthOrNumber::zero().into()",
initial_specified_value="specified::LengthOrNumber::zero().into()",
spec="https://drafts.csswg.org/css-backgrounds/#border-image-outset",
- animation_value_type="none",
+ animation_value_type="discrete",
boxed=True)}
<%helpers:longhand name="border-image-repeat" animation_value_type="discrete"
spec="https://drafts.csswg.org/css-backgrounds/#border-image-repeat">
use style_traits::ToCss;
no_viewport_percentage!(SpecifiedValue);
@@ -268,17 +268,70 @@
Ok(SpecifiedValue(first, second))
}
</%helpers:longhand>
${helpers.predefined_type("border-image-width", "BorderImageWidth",
initial_value="computed::BorderImageSideWidth::one().into()",
initial_specified_value="specified::BorderImageSideWidth::one().into()",
spec="https://drafts.csswg.org/css-backgrounds/#border-image-width",
- animation_value_type="none",
+ animation_value_type="discrete",
boxed=True)}
${helpers.predefined_type("border-image-slice", "BorderImageSlice",
initial_value="computed::NumberOrPercentage::Percentage(computed::Percentage(1.)).into()",
initial_specified_value="specified::NumberOrPercentage::Percentage(specified::Percentage(1.)).into()",
spec="https://drafts.csswg.org/css-backgrounds/#border-image-slice",
- animation_value_type="none",
+ animation_value_type="discrete",
boxed=True)}
+
+#[cfg(feature = "gecko")]
+impl ::values::computed::BorderImageWidth {
+ pub fn to_gecko_rect(&self, sides: &mut ::gecko_bindings::structs::nsStyleSides) {
+ use gecko_bindings::sugar::ns_style_coord::{CoordDataMut, CoordDataValue};
+ use gecko::values::GeckoStyleCoordConvertible;
+ use values::generics::border::BorderImageSideWidth;
+
+ % for i in range(0, 4):
+ match self.${i} {
+ BorderImageSideWidth::Auto => {
+ sides.data_at_mut(${i}).set_value(CoordDataValue::Auto)
+ },
+ BorderImageSideWidth::Length(l) => {
+ l.to_gecko_style_coord(&mut sides.data_at_mut(${i}))
+ },
+ BorderImageSideWidth::Number(n) => {
+ sides.data_at_mut(${i}).set_value(CoordDataValue::Factor(n))
+ },
+ }
+ % endfor
+ }
+
+ pub fn from_gecko_rect(sides: &::gecko_bindings::structs::nsStyleSides) -> Option<::values::computed::BorderImageWidth> {
+ use gecko_bindings::structs::nsStyleUnit::{eStyleUnit_Factor, eStyleUnit_Auto};
+ use gecko_bindings::sugar::ns_style_coord::CoordData;
+ use gecko::values::GeckoStyleCoordConvertible;
+ use values::computed::{LengthOrPercentage, Number};
+ use values::generics::border::BorderImageSideWidth;
+
+ Some(
+ ::values::computed::BorderImageWidth::new(
+ % for i in range(0, 4):
+ match sides.data_at(${i}).unit() {
+ eStyleUnit_Auto => {
+ BorderImageSideWidth::Auto
+ },
+ eStyleUnit_Factor => {
+ BorderImageSideWidth::Number(
+ Number::from_gecko_style_coord(&sides.data_at(${i}))
+ .expect("sides[${i}] could not convert to Number"))
+ },
+ _ => {
+ BorderImageSideWidth::Length(
+ LengthOrPercentage::from_gecko_style_coord(&sides.data_at(${i}))
+ .expect("sides[${i}] could not convert to LengthOrPercentager"))
+ },
+ },
+ % endfor
+ )
+ )
+ }
+}