mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
implements nsStyleImage type properties animatable
This commit is contained in:
parent
4924a4832f
commit
d885747a18
6 changed files with 240 additions and 4 deletions
|
@ -22,6 +22,7 @@ use values::generics::grid::TrackSize;
|
||||||
use values::generics::image::{CompatMode, Image as GenericImage, GradientItem};
|
use values::generics::image::{CompatMode, Image as GenericImage, GradientItem};
|
||||||
use values::generics::rect::Rect;
|
use values::generics::rect::Rect;
|
||||||
use values::specified::length::Percentage;
|
use values::specified::length::Percentage;
|
||||||
|
use values::specified::url::SpecifiedUrl;
|
||||||
|
|
||||||
impl From<CalcLengthOrPercentage> for nsStyleCoord_CalcValue {
|
impl From<CalcLengthOrPercentage> for nsStyleCoord_CalcValue {
|
||||||
fn from(other: CalcLengthOrPercentage) -> nsStyleCoord_CalcValue {
|
fn from(other: CalcLengthOrPercentage) -> nsStyleCoord_CalcValue {
|
||||||
|
@ -364,6 +365,212 @@ impl nsStyleImage {
|
||||||
Gecko_SetGradientImageValue(self, gecko_gradient);
|
Gecko_SetGradientImageValue(self, gecko_gradient);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts into Image.
|
||||||
|
pub unsafe fn into_image(self: &nsStyleImage) -> Option<Image> {
|
||||||
|
use gecko_bindings::bindings::Gecko_GetImageElement;
|
||||||
|
use gecko_bindings::structs::nsStyleImageType;
|
||||||
|
use values::computed::{NumberOrPercentage, ImageRect};
|
||||||
|
|
||||||
|
match self.mType {
|
||||||
|
nsStyleImageType::eStyleImageType_Null => {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
nsStyleImageType::eStyleImageType_Image => {
|
||||||
|
let url = self.get_image_url();
|
||||||
|
if self.mCropRect.mPtr.is_null() {
|
||||||
|
Some(GenericImage::Url(url))
|
||||||
|
} else {
|
||||||
|
let ref rect = *self.mCropRect.mPtr;
|
||||||
|
match (NumberOrPercentage::from_gecko_style_coord(&rect.data_at(0)),
|
||||||
|
NumberOrPercentage::from_gecko_style_coord(&rect.data_at(1)),
|
||||||
|
NumberOrPercentage::from_gecko_style_coord(&rect.data_at(2)),
|
||||||
|
NumberOrPercentage::from_gecko_style_coord(&rect.data_at(3))) {
|
||||||
|
(Some(top), Some(right), Some(bottom), Some(left)) =>
|
||||||
|
Some(GenericImage::Rect(ImageRect { url, top, right, bottom, left } )),
|
||||||
|
_ => {
|
||||||
|
debug_assert!(false, "mCropRect could not convert to NumberOrPercentage");
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
nsStyleImageType::eStyleImageType_Gradient => {
|
||||||
|
Some(GenericImage::Gradient(self.get_gradient()))
|
||||||
|
},
|
||||||
|
nsStyleImageType::eStyleImageType_Element => {
|
||||||
|
use gecko_string_cache::Atom;
|
||||||
|
let atom = Gecko_GetImageElement(self);
|
||||||
|
Some(GenericImage::Element(Atom::from(atom)))
|
||||||
|
},
|
||||||
|
x => panic!("Unexpected image type {:?}", x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn get_image_url(self: &nsStyleImage) -> SpecifiedUrl {
|
||||||
|
use gecko_bindings::bindings::Gecko_GetURLValue;
|
||||||
|
let url_value = Gecko_GetURLValue(self);
|
||||||
|
let mut url = SpecifiedUrl::from_url_value_data(url_value.as_ref().unwrap())
|
||||||
|
.expect("Could not convert to SpecifiedUrl");
|
||||||
|
url.build_image_value();
|
||||||
|
url
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn get_gradient(self: &nsStyleImage) -> Gradient {
|
||||||
|
use gecko::values::convert_nscolor_to_rgba;
|
||||||
|
use gecko_bindings::bindings::Gecko_GetGradientImageValue;
|
||||||
|
use gecko_bindings::structs::{NS_STYLE_GRADIENT_SHAPE_CIRCULAR, NS_STYLE_GRADIENT_SHAPE_ELLIPTICAL};
|
||||||
|
use gecko_bindings::structs::{NS_STYLE_GRADIENT_SHAPE_LINEAR, NS_STYLE_GRADIENT_SIZE_CLOSEST_CORNER};
|
||||||
|
use gecko_bindings::structs::{NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE, NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE};
|
||||||
|
use gecko_bindings::structs::{NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER, NS_STYLE_GRADIENT_SIZE_FARTHEST_SIDE};
|
||||||
|
use values::computed::{Length, LengthOrPercentage};
|
||||||
|
use values::computed::image::LineDirection;
|
||||||
|
use values::computed::position::Position;
|
||||||
|
use values::generics::image::{ColorStop, CompatMode, Circle, Ellipse, EndingShape, GradientKind, ShapeExtent};
|
||||||
|
use values::specified::position::{X, Y};
|
||||||
|
|
||||||
|
let gecko_gradient = Gecko_GetGradientImageValue(self).as_ref().unwrap();
|
||||||
|
let angle = Angle::from_gecko_style_coord(&gecko_gradient.mAngle);
|
||||||
|
let horizontal_style = LengthOrPercentage::from_gecko_style_coord(&gecko_gradient.mBgPosX);
|
||||||
|
let vertical_style = LengthOrPercentage::from_gecko_style_coord(&gecko_gradient.mBgPosY);
|
||||||
|
|
||||||
|
let kind = match gecko_gradient.mShape as u32 {
|
||||||
|
NS_STYLE_GRADIENT_SHAPE_LINEAR => {
|
||||||
|
let line_direction = match (angle, horizontal_style, vertical_style) {
|
||||||
|
(Some(a), None, None) => LineDirection::Angle(a),
|
||||||
|
(None, Some(horizontal), Some(vertical)) => {
|
||||||
|
let horizontal_as_corner = match horizontal {
|
||||||
|
LengthOrPercentage::Percentage(percentage) => {
|
||||||
|
if percentage.0 == 0.0 {
|
||||||
|
Some(X::Left)
|
||||||
|
} else if percentage.0 == 1.0 {
|
||||||
|
Some(X::Right)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => None
|
||||||
|
};
|
||||||
|
let vertical_as_corner = match vertical {
|
||||||
|
LengthOrPercentage::Percentage(percentage) => {
|
||||||
|
if percentage.0 == 0.0 {
|
||||||
|
Some(Y::Top)
|
||||||
|
} else if percentage.0 == 1.0 {
|
||||||
|
Some(Y::Bottom)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => None
|
||||||
|
};
|
||||||
|
|
||||||
|
match (horizontal_as_corner, vertical_as_corner) {
|
||||||
|
(Some(hc), Some(vc)) => LineDirection::Corner(hc, vc),
|
||||||
|
_ => LineDirection::MozPosition(
|
||||||
|
Some(Position { horizontal, vertical }), None)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(Some(_), Some(horizontal), Some(vertical)) =>
|
||||||
|
LineDirection::MozPosition(
|
||||||
|
Some(Position { horizontal, vertical }), angle),
|
||||||
|
_ => {
|
||||||
|
debug_assert!(horizontal_style.is_none() && vertical_style.is_none(),
|
||||||
|
"Unexpected linear gradient direction");
|
||||||
|
LineDirection::MozPosition(None, None)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
GradientKind::Linear(line_direction)
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
let gecko_size_to_keyword = |gecko_size| {
|
||||||
|
match gecko_size {
|
||||||
|
NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE => ShapeExtent::ClosestSide,
|
||||||
|
NS_STYLE_GRADIENT_SIZE_FARTHEST_SIDE => ShapeExtent::FarthestSide,
|
||||||
|
NS_STYLE_GRADIENT_SIZE_CLOSEST_CORNER => ShapeExtent::ClosestCorner,
|
||||||
|
NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER => ShapeExtent::FarthestCorner,
|
||||||
|
// FIXME: We should support ShapeExtent::Contain and ShapeExtent::Cover.
|
||||||
|
// But we can't choose those yet since Gecko does not support both values.
|
||||||
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=1217664
|
||||||
|
x => panic!("Found unexpected gecko_size: {:?}", x),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let shape = match gecko_gradient.mShape as u32 {
|
||||||
|
NS_STYLE_GRADIENT_SHAPE_CIRCULAR => {
|
||||||
|
let circle = match gecko_gradient.mSize as u32 {
|
||||||
|
NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE => {
|
||||||
|
let radius = Length::from_gecko_style_coord(&gecko_gradient.mRadiusX)
|
||||||
|
.expect("mRadiusX could not convert to Length");
|
||||||
|
debug_assert_eq!(radius,
|
||||||
|
Length::from_gecko_style_coord(&gecko_gradient.mRadiusY).unwrap());
|
||||||
|
Circle::Radius(radius)
|
||||||
|
},
|
||||||
|
size => Circle::Extent(gecko_size_to_keyword(size))
|
||||||
|
};
|
||||||
|
EndingShape::Circle(circle)
|
||||||
|
},
|
||||||
|
NS_STYLE_GRADIENT_SHAPE_ELLIPTICAL => {
|
||||||
|
let length_percentage_keyword = match gecko_gradient.mSize as u32 {
|
||||||
|
NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE => {
|
||||||
|
match (LengthOrPercentage::from_gecko_style_coord(&gecko_gradient.mRadiusX),
|
||||||
|
LengthOrPercentage::from_gecko_style_coord(&gecko_gradient.mRadiusY)) {
|
||||||
|
(Some(x), Some(y)) => Ellipse::Radii(x, y),
|
||||||
|
_ => {
|
||||||
|
debug_assert!(false,
|
||||||
|
"mRadiusX, mRadiusY could not convert to LengthOrPercentage");
|
||||||
|
Ellipse::Radii(LengthOrPercentage::zero(),
|
||||||
|
LengthOrPercentage::zero())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
size => Ellipse::Extent(gecko_size_to_keyword(size))
|
||||||
|
};
|
||||||
|
EndingShape::Ellipse(length_percentage_keyword)
|
||||||
|
},
|
||||||
|
x => panic!("Found unexpected mShape: {:?}", x),
|
||||||
|
};
|
||||||
|
|
||||||
|
let position = match (horizontal_style, vertical_style) {
|
||||||
|
(Some(horizontal), Some(vertical)) => Position { horizontal, vertical },
|
||||||
|
_ => {
|
||||||
|
debug_assert!(false,
|
||||||
|
"mRadiusX, mRadiusY could not convert to LengthOrPercentage");
|
||||||
|
Position {
|
||||||
|
horizontal: LengthOrPercentage::zero(),
|
||||||
|
vertical: LengthOrPercentage::zero()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
GradientKind::Radial(shape, position, angle)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let items = gecko_gradient.mStops.iter().map(|ref stop| {
|
||||||
|
if stop.mIsInterpolationHint {
|
||||||
|
GradientItem::InterpolationHint(
|
||||||
|
LengthOrPercentage::from_gecko_style_coord(&stop.mLocation)
|
||||||
|
.expect("mLocation could not convert to LengthOrPercentage")
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
GradientItem::ColorStop(ColorStop {
|
||||||
|
color: convert_nscolor_to_rgba(stop.mColor),
|
||||||
|
position: LengthOrPercentage::from_gecko_style_coord(&stop.mLocation)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}).collect();
|
||||||
|
|
||||||
|
let compat_mode =
|
||||||
|
if gecko_gradient.mMozLegacySyntax {
|
||||||
|
CompatMode::Moz
|
||||||
|
} else if gecko_gradient.mLegacySyntax {
|
||||||
|
CompatMode::WebKit
|
||||||
|
} else {
|
||||||
|
CompatMode::Modern
|
||||||
|
};
|
||||||
|
|
||||||
|
Gradient { items, repeating: gecko_gradient.mRepeating, kind, compat_mode }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod basic_shape {
|
pub mod basic_shape {
|
||||||
|
|
|
@ -1085,6 +1085,15 @@ fn static_assert() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clone_border_image_source(&self) -> longhands::border_image_source::computed_value::T {
|
||||||
|
use values::None_;
|
||||||
|
|
||||||
|
match unsafe { self.gecko.mBorderImageSource.into_image() } {
|
||||||
|
Some(image) => Either::Second(image),
|
||||||
|
None => Either::First(None_),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
<% impl_style_sides("border_image_outset") %>
|
<% impl_style_sides("border_image_outset") %>
|
||||||
|
|
||||||
<%
|
<%
|
||||||
|
@ -3318,6 +3327,21 @@ fn static_assert() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clone_${shorthand}_image(&self) -> longhands::${shorthand}_image::computed_value::T {
|
||||||
|
use values::None_;
|
||||||
|
|
||||||
|
longhands::${shorthand}_image::computed_value::T(
|
||||||
|
self.gecko.${image_layers_field}.mLayers.iter()
|
||||||
|
.take(self.gecko.${image_layers_field}.mImageCount as usize)
|
||||||
|
.map(|ref layer| {
|
||||||
|
match unsafe { layer.mImage.into_image() } {
|
||||||
|
Some(image) => Either::Second(image),
|
||||||
|
None => Either::First(None_),
|
||||||
|
}
|
||||||
|
}).collect()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
<%
|
<%
|
||||||
fill_fields = "mRepeat mClip mOrigin mPositionX mPositionY mImage mSize"
|
fill_fields = "mRepeat mClip mOrigin mPositionX mPositionY mImage mSize"
|
||||||
if shorthand == "background":
|
if shorthand == "background":
|
||||||
|
|
|
@ -414,7 +414,12 @@ impl AnimatedProperty {
|
||||||
let value: longhands::${prop.ident}::computed_value::T =
|
let value: longhands::${prop.ident}::computed_value::T =
|
||||||
ToAnimatedValue::from_animated_value(value);
|
ToAnimatedValue::from_animated_value(value);
|
||||||
% endif
|
% endif
|
||||||
style.mutate_${prop.style_struct.ident.strip("_")}().set_${prop.ident}(value);
|
<% method = "style.mutate_" + prop.style_struct.ident.strip("_") + "().set_" + prop.ident %>
|
||||||
|
% if prop.has_uncacheable_values is "True":
|
||||||
|
${method}(value, &mut false);
|
||||||
|
% else:
|
||||||
|
${method}(value);
|
||||||
|
% endif
|
||||||
}
|
}
|
||||||
% endif
|
% endif
|
||||||
% endfor
|
% endfor
|
||||||
|
|
|
@ -19,7 +19,7 @@ ${helpers.predefined_type("background-image", "ImageLayer",
|
||||||
initial_specified_value="Either::First(None_)",
|
initial_specified_value="Either::First(None_)",
|
||||||
spec="https://drafts.csswg.org/css-backgrounds/#the-background-image",
|
spec="https://drafts.csswg.org/css-backgrounds/#the-background-image",
|
||||||
vector="True",
|
vector="True",
|
||||||
animation_value_type="none",
|
animation_value_type="discrete",
|
||||||
has_uncacheable_values="True" if product == "gecko" else "False",
|
has_uncacheable_values="True" if product == "gecko" else "False",
|
||||||
ignored_when_colors_disabled="True")}
|
ignored_when_colors_disabled="True")}
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,7 @@ ${helpers.predefined_type("border-image-source", "ImageLayer",
|
||||||
initial_specified_value="Either::First(None_)",
|
initial_specified_value="Either::First(None_)",
|
||||||
spec="https://drafts.csswg.org/css-backgrounds/#the-background-image",
|
spec="https://drafts.csswg.org/css-backgrounds/#the-background-image",
|
||||||
vector=False,
|
vector=False,
|
||||||
animation_value_type="none",
|
animation_value_type="discrete",
|
||||||
has_uncacheable_values=False,
|
has_uncacheable_values=False,
|
||||||
boxed="True")}
|
boxed="True")}
|
||||||
|
|
||||||
|
|
|
@ -150,6 +150,6 @@ ${helpers.predefined_type("mask-image", "ImageLayer",
|
||||||
vector=True,
|
vector=True,
|
||||||
products="gecko",
|
products="gecko",
|
||||||
extra_prefixes="webkit",
|
extra_prefixes="webkit",
|
||||||
animation_value_type="none",
|
animation_value_type="discrete",
|
||||||
flags="CREATES_STACKING_CONTEXT",
|
flags="CREATES_STACKING_CONTEXT",
|
||||||
has_uncacheable_values="True" if product == "gecko" else "False")}
|
has_uncacheable_values="True" if product == "gecko" else "False")}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue