mirror of
https://github.com/servo/servo.git
synced 2025-08-14 18:05:36 +01:00
style: Refactor vector types.
This fixes clamping of mask-size and moves it out of mako while at it. Bug: 1462829 Reviewed-by: hiro,xidorn MozReview-Commit-ID: 9hiTe63odna
This commit is contained in:
parent
3016a7f552
commit
32c6d5b7c6
18 changed files with 259 additions and 372 deletions
|
@ -164,7 +164,7 @@ class Longhand(object):
|
|||
allowed_in_keyframe_block=True, cast_type='u8',
|
||||
logical=False, alias=None, extra_prefixes=None, boxed=False,
|
||||
flags=None, allowed_in_page_rule=False, allow_quirks=False, ignored_when_colors_disabled=False,
|
||||
vector=False, need_animatable=False, servo_restyle_damage="repaint"):
|
||||
vector=False, servo_restyle_damage="repaint"):
|
||||
self.name = name
|
||||
if not spec:
|
||||
raise TypeError("Spec should be specified for %s" % name)
|
||||
|
|
|
@ -3249,7 +3249,7 @@ fn static_assert() {
|
|||
|
||||
pub fn clone_scroll_snap_coordinate(&self) -> longhands::scroll_snap_coordinate::computed_value::T {
|
||||
let vec = self.gecko.mScrollSnapCoordinate.iter().map(|f| f.into()).collect();
|
||||
longhands::scroll_snap_coordinate::computed_value::T(vec)
|
||||
longhands::scroll_snap_coordinate::computed_value::List(vec)
|
||||
}
|
||||
|
||||
${impl_css_url('_moz_binding', 'mBinding')}
|
||||
|
@ -3755,8 +3755,9 @@ fn static_assert() {
|
|||
<% copy_simple_image_array_property(name, shorthand, layer_field_name, field_name) %>
|
||||
|
||||
pub fn set_${ident}<I>(&mut self, v: I)
|
||||
where I: IntoIterator<Item=longhands::${ident}::computed_value::single_value::T>,
|
||||
I::IntoIter: ExactSizeIterator
|
||||
where
|
||||
I: IntoIterator<Item=longhands::${ident}::computed_value::single_value::T>,
|
||||
I::IntoIter: ExactSizeIterator,
|
||||
{
|
||||
use properties::longhands::${ident}::single_value::computed_value::T as Keyword;
|
||||
use gecko_bindings::structs::nsStyleImageLayers_LayerType as LayerType;
|
||||
|
@ -3791,7 +3792,7 @@ fn static_assert() {
|
|||
% endfor
|
||||
% endif
|
||||
|
||||
longhands::${ident}::computed_value::T (
|
||||
longhands::${ident}::computed_value::List(
|
||||
self.gecko.${layer_field_name}.mLayers.iter()
|
||||
.take(self.gecko.${layer_field_name}.${field_name}Count as usize)
|
||||
.map(|ref layer| {
|
||||
|
@ -3858,7 +3859,7 @@ fn static_assert() {
|
|||
}
|
||||
}
|
||||
|
||||
longhands::${shorthand}_repeat::computed_value::T (
|
||||
longhands::${shorthand}_repeat::computed_value::List(
|
||||
self.gecko.${image_layers_field}.mLayers.iter()
|
||||
.take(self.gecko.${image_layers_field}.mRepeatCount as usize)
|
||||
.map(|ref layer| {
|
||||
|
@ -3897,7 +3898,7 @@ fn static_assert() {
|
|||
|
||||
pub fn clone_${shorthand}_position_${orientation}(&self)
|
||||
-> longhands::${shorthand}_position_${orientation}::computed_value::T {
|
||||
longhands::${shorthand}_position_${orientation}::computed_value::T(
|
||||
longhands::${shorthand}_position_${orientation}::computed_value::List(
|
||||
self.gecko.${image_layers_field}.mLayers.iter()
|
||||
.take(self.gecko.${image_layers_field}.mPosition${orientation.upper()}Count as usize)
|
||||
.map(|position| position.mPosition.m${orientation.upper()}Position.into())
|
||||
|
@ -3941,11 +3942,11 @@ fn static_assert() {
|
|||
BackgroundSize::Explicit { width: explicit_width, height: explicit_height } => {
|
||||
let mut w_type = nsStyleImageLayers_Size_DimensionType::eAuto;
|
||||
let mut h_type = nsStyleImageLayers_Size_DimensionType::eAuto;
|
||||
if let Some(w) = explicit_width.to_calc_value() {
|
||||
if let Some(w) = explicit_width.0.to_calc_value() {
|
||||
width = w;
|
||||
w_type = nsStyleImageLayers_Size_DimensionType::eLengthPercentage;
|
||||
}
|
||||
if let Some(h) = explicit_height.to_calc_value() {
|
||||
if let Some(h) = explicit_height.0.to_calc_value() {
|
||||
height = h;
|
||||
h_type = nsStyleImageLayers_Size_DimensionType::eLengthPercentage;
|
||||
}
|
||||
|
@ -3973,22 +3974,23 @@ fn static_assert() {
|
|||
}
|
||||
</%self:simple_image_array_property>
|
||||
|
||||
pub fn clone_${shorthand}_size(&self) -> longhands::background_size::computed_value::T {
|
||||
pub fn clone_${shorthand}_size(&self) -> longhands::${shorthand}_size::computed_value::T {
|
||||
use gecko_bindings::structs::nsStyleCoord_CalcValue as CalcValue;
|
||||
use gecko_bindings::structs::nsStyleImageLayers_Size_DimensionType as DimensionType;
|
||||
use values::computed::LengthOrPercentageOrAuto;
|
||||
use values::generics::NonNegative;
|
||||
use values::computed::NonNegativeLengthOrPercentageOrAuto;
|
||||
use values::generics::background::BackgroundSize;
|
||||
|
||||
fn to_servo(value: CalcValue, ty: u8) -> LengthOrPercentageOrAuto {
|
||||
fn to_servo(value: CalcValue, ty: u8) -> NonNegativeLengthOrPercentageOrAuto {
|
||||
if ty == DimensionType::eAuto as u8 {
|
||||
LengthOrPercentageOrAuto::Auto
|
||||
NonNegativeLengthOrPercentageOrAuto::auto()
|
||||
} else {
|
||||
debug_assert_eq!(ty, DimensionType::eLengthPercentage as u8);
|
||||
value.into()
|
||||
NonNegative(value.into())
|
||||
}
|
||||
}
|
||||
|
||||
longhands::background_size::computed_value::T(
|
||||
longhands::${shorthand}_size::computed_value::List(
|
||||
self.gecko.${image_layers_field}.mLayers.iter().map(|ref layer| {
|
||||
if DimensionType::eCover as u8 == layer.mSize.mWidthType {
|
||||
debug_assert_eq!(layer.mSize.mHeightType, DimensionType::eCover as u8);
|
||||
|
@ -4059,7 +4061,7 @@ fn static_assert() {
|
|||
pub fn clone_${shorthand}_image(&self) -> longhands::${shorthand}_image::computed_value::T {
|
||||
use values::None_;
|
||||
|
||||
longhands::${shorthand}_image::computed_value::T(
|
||||
longhands::${shorthand}_image::computed_value::List(
|
||||
self.gecko.${image_layers_field}.mLayers.iter()
|
||||
.take(self.gecko.${image_layers_field}.mImageCount as usize)
|
||||
.map(|ref layer| {
|
||||
|
@ -4315,7 +4317,7 @@ fn static_assert() {
|
|||
|
||||
pub fn clone_box_shadow(&self) -> longhands::box_shadow::computed_value::T {
|
||||
let buf = self.gecko.mBoxShadow.iter().map(|v| v.to_box_shadow()).collect();
|
||||
longhands::box_shadow::computed_value::T(buf)
|
||||
longhands::box_shadow::computed_value::List(buf)
|
||||
}
|
||||
|
||||
pub fn set_clip(&mut self, v: longhands::clip::computed_value::T) {
|
||||
|
@ -4560,7 +4562,7 @@ fn static_assert() {
|
|||
_ => {},
|
||||
}
|
||||
}
|
||||
longhands::filter::computed_value::T(filters)
|
||||
longhands::filter::computed_value::List(filters)
|
||||
}
|
||||
|
||||
</%self:impl_trait>
|
||||
|
@ -4681,7 +4683,7 @@ fn static_assert() {
|
|||
|
||||
pub fn clone_text_shadow(&self) -> longhands::text_shadow::computed_value::T {
|
||||
let buf = self.gecko.mTextShadow.iter().map(|v| v.to_simple_shadow()).collect();
|
||||
longhands::text_shadow::computed_value::T(buf)
|
||||
longhands::text_shadow::computed_value::List(buf)
|
||||
}
|
||||
|
||||
pub fn set_line_height(&mut self, v: longhands::line_height::computed_value::T) {
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
%>
|
||||
|
||||
<%def name="predefined_type(name, type, initial_value, parse_method='parse',
|
||||
needs_context=True, vector=False, computed_type=None, initial_specified_value=None,
|
||||
needs_context=True, vector=False,
|
||||
computed_type=None, initial_specified_value=None,
|
||||
allow_quirks=False, allow_empty=False, **kwargs)">
|
||||
<%def name="predefined_type_inner(name, type, initial_value, parse_method)">
|
||||
#[allow(unused_imports)]
|
||||
|
@ -77,10 +78,12 @@
|
|||
We assume that the default/initial value is an empty vector for these.
|
||||
`initial_value` need not be defined for these.
|
||||
</%doc>
|
||||
<%def name="vector_longhand(name, animation_value_type=None, allow_empty=False, separator='Comma',
|
||||
need_animatable=False, **kwargs)">
|
||||
<%def name="vector_longhand(name, animation_value_type=None,
|
||||
vector_animation_type=None, allow_empty=False,
|
||||
separator='Comma',
|
||||
**kwargs)">
|
||||
<%call expr="longhand(name, animation_value_type=animation_value_type, vector=True,
|
||||
need_animatable=need_animatable, **kwargs)">
|
||||
**kwargs)">
|
||||
#[allow(unused_imports)]
|
||||
use smallvec::SmallVec;
|
||||
|
||||
|
@ -115,36 +118,68 @@
|
|||
% endif
|
||||
use values::computed::ComputedVecIter;
|
||||
|
||||
/// The computed value, effectively a list of single values.
|
||||
/// The generic type defining the value for this property.
|
||||
% if separator == "Comma":
|
||||
#[css(comma)]
|
||||
% endif
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
|
||||
% if need_animatable or animation_value_type == "ComputedValue":
|
||||
#[derive(Animate, ComputeSquaredDistance)]
|
||||
% endif
|
||||
pub struct T(
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToAnimatedValue,
|
||||
ToCss)]
|
||||
pub struct List<T>(
|
||||
% if not allow_empty:
|
||||
#[css(iterable)]
|
||||
% else:
|
||||
#[css(if_empty = "none", iterable)]
|
||||
% endif
|
||||
% if allow_empty and allow_empty != "NotInitial":
|
||||
pub Vec<single_value::T>,
|
||||
pub Vec<T>,
|
||||
% else:
|
||||
pub SmallVec<[single_value::T; 1]>,
|
||||
pub SmallVec<[T; 1]>,
|
||||
% endif
|
||||
);
|
||||
|
||||
% if need_animatable or animation_value_type == "ComputedValue":
|
||||
use values::animated::{ToAnimatedZero};
|
||||
|
||||
impl ToAnimatedZero for T {
|
||||
#[inline]
|
||||
fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }
|
||||
}
|
||||
/// The computed value, effectively a list of single values.
|
||||
% if vector_animation_type:
|
||||
% if not animation_value_type:
|
||||
Sorry, this is stupid but needed for now.
|
||||
% endif
|
||||
|
||||
use properties::animated_properties::ListAnimation;
|
||||
use values::animated::{Animate, ToAnimatedValue, ToAnimatedZero, Procedure};
|
||||
use values::distance::{SquaredDistance, ComputeSquaredDistance};
|
||||
|
||||
// FIXME(emilio): For some reason rust thinks that this alias is
|
||||
// unused, even though it's clearly used below?
|
||||
#[allow(unused)]
|
||||
type AnimatedList = <List<single_value::T> as ToAnimatedValue>::AnimatedValue;
|
||||
|
||||
impl ToAnimatedZero for AnimatedList {
|
||||
fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }
|
||||
}
|
||||
|
||||
impl Animate for AnimatedList {
|
||||
fn animate(
|
||||
&self,
|
||||
other: &Self,
|
||||
procedure: Procedure,
|
||||
) -> Result<Self, ()> {
|
||||
Ok(List(
|
||||
self.0.animate_${vector_animation_type}(&other.0, procedure)?
|
||||
))
|
||||
}
|
||||
}
|
||||
impl ComputeSquaredDistance for AnimatedList {
|
||||
fn compute_squared_distance(
|
||||
&self,
|
||||
other: &Self,
|
||||
) -> Result<SquaredDistance, ()> {
|
||||
self.0.squared_distance_${vector_animation_type}(&other.0)
|
||||
}
|
||||
}
|
||||
% endif
|
||||
|
||||
pub type T = List<single_value::T>;
|
||||
|
||||
pub type Iter<'a, 'cx, 'cx_a> = ComputedVecIter<'a, 'cx, 'cx_a, super::single_value::SpecifiedValue>;
|
||||
|
||||
impl IntoIterator for T {
|
||||
|
@ -176,16 +211,18 @@
|
|||
|
||||
pub fn get_initial_value() -> computed_value::T {
|
||||
% if allow_empty and allow_empty != "NotInitial":
|
||||
computed_value::T(vec![])
|
||||
computed_value::List(vec![])
|
||||
% else:
|
||||
let mut v = SmallVec::new();
|
||||
v.push(single_value::get_initial_value());
|
||||
computed_value::T(v)
|
||||
computed_value::List(v)
|
||||
% endif
|
||||
}
|
||||
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
pub fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<SpecifiedValue, ParseError<'i>> {
|
||||
use style_traits::Separator;
|
||||
|
||||
% if allow_empty:
|
||||
|
@ -202,8 +239,10 @@
|
|||
pub use self::single_value::SpecifiedValue as SingleSpecifiedValue;
|
||||
|
||||
impl SpecifiedValue {
|
||||
pub fn compute_iter<'a, 'cx, 'cx_a>(&'a self, context: &'cx Context<'cx_a>)
|
||||
-> computed_value::Iter<'a, 'cx, 'cx_a> {
|
||||
pub fn compute_iter<'a, 'cx, 'cx_a>(
|
||||
&'a self,
|
||||
context: &'cx Context<'cx_a>,
|
||||
) -> computed_value::Iter<'a, 'cx, 'cx_a> {
|
||||
computed_value::Iter::new(context, &self.0)
|
||||
}
|
||||
}
|
||||
|
@ -213,7 +252,7 @@
|
|||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
||||
computed_value::T(self.compute_iter(context).collect())
|
||||
computed_value::List(self.compute_iter(context).collect())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -29,11 +29,10 @@ use std::mem::{self, ManuallyDrop};
|
|||
#[cfg(feature = "gecko")] use hash::FnvHashMap;
|
||||
use style_traits::{KeywordsCollectFn, ParseError, SpecifiedValueInfo};
|
||||
use super::ComputedValues;
|
||||
use values::{CSSFloat, CustomIdent, Either};
|
||||
use values::{CSSFloat, CustomIdent};
|
||||
use values::animated::{Animate, Procedure, ToAnimatedValue, ToAnimatedZero};
|
||||
use values::animated::color::RGBA as AnimatedRGBA;
|
||||
use values::animated::effects::Filter as AnimatedFilter;
|
||||
use values::animated::effects::FilterList as AnimatedFilterList;
|
||||
use values::computed::{Angle, CalcLengthOrPercentage};
|
||||
use values::computed::{ClipRect, Context};
|
||||
use values::computed::{Length, LengthOrPercentage, LengthOrPercentageOrAuto};
|
||||
|
@ -53,13 +52,10 @@ use values::distance::{ComputeSquaredDistance, SquaredDistance};
|
|||
use values::generics::font::{FontSettings as GenericFontSettings, FontTag, VariationValue};
|
||||
use values::computed::font::FontVariationSettings;
|
||||
use values::generics::effects::Filter;
|
||||
use values::generics::position as generic_position;
|
||||
use values::generics::svg::{SVGLength, SvgLengthOrPercentageOrNumber, SVGPaint};
|
||||
use values::generics::svg::{SVGPaintKind, SVGStrokeDashArray, SVGOpacity};
|
||||
use void::{self, Void};
|
||||
|
||||
/// <https://drafts.csswg.org/css-transitions/#animtype-repeatable-list>
|
||||
pub trait RepeatableListAnimatable: Animate {}
|
||||
|
||||
/// Returns true if this nsCSSPropertyID is one of the animatable properties.
|
||||
#[cfg(feature = "gecko")]
|
||||
|
@ -755,18 +751,45 @@ impl ToAnimatedZero for AnimationValue {
|
|||
}
|
||||
}
|
||||
|
||||
impl RepeatableListAnimatable for LengthOrPercentage {}
|
||||
impl RepeatableListAnimatable for Either<f32, LengthOrPercentage> {}
|
||||
impl RepeatableListAnimatable for Either<NonNegativeNumber, NonNegativeLengthOrPercentage> {}
|
||||
impl RepeatableListAnimatable for SvgLengthOrPercentageOrNumber<LengthOrPercentage, Number> {}
|
||||
/// A trait to abstract away the different kind of animations over a list that
|
||||
/// there may be.
|
||||
pub trait ListAnimation<T> : Sized {
|
||||
/// <https://drafts.csswg.org/css-transitions/#animtype-repeatable-list>
|
||||
fn animate_repeatable_list(&self, other: &Self, procedure: Procedure) -> Result<Self, ()>
|
||||
where
|
||||
T: Animate;
|
||||
|
||||
macro_rules! repeated_vec_impl {
|
||||
($($ty:ty),*) => {
|
||||
$(impl<T> Animate for $ty
|
||||
where
|
||||
T: RepeatableListAnimatable,
|
||||
{
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
/// <https://drafts.csswg.org/css-transitions/#animtype-repeatable-list>
|
||||
fn squared_distance_repeatable_list(&self, other: &Self) -> Result<SquaredDistance, ()>
|
||||
where
|
||||
T: ComputeSquaredDistance;
|
||||
|
||||
/// This is the animation used for some of the types like shadows and
|
||||
/// filters, where the interpolation happens with the zero value if one of
|
||||
/// the sides is not present.
|
||||
fn animate_with_zero(&self, other: &Self, procedure: Procedure) -> Result<Self, ()>
|
||||
where
|
||||
T: Animate + Clone + ToAnimatedZero;
|
||||
|
||||
/// This is the animation used for some of the types like shadows and
|
||||
/// filters, where the interpolation happens with the zero value if one of
|
||||
/// the sides is not present.
|
||||
fn squared_distance_with_zero(&self, other: &Self) -> Result<SquaredDistance, ()>
|
||||
where
|
||||
T: ToAnimatedZero + ComputeSquaredDistance;
|
||||
}
|
||||
|
||||
macro_rules! animated_list_impl {
|
||||
(<$t:ident> for $ty:ty) => {
|
||||
impl<$t> ListAnimation<$t> for $ty {
|
||||
fn animate_repeatable_list(
|
||||
&self,
|
||||
other: &Self,
|
||||
procedure: Procedure,
|
||||
) -> Result<Self, ()>
|
||||
where
|
||||
T: Animate,
|
||||
{
|
||||
// If the length of either list is zero, the least common multiple is undefined.
|
||||
if self.is_empty() || other.is_empty() {
|
||||
return Err(());
|
||||
|
@ -777,14 +800,14 @@ macro_rules! repeated_vec_impl {
|
|||
this.animate(other, procedure)
|
||||
}).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ComputeSquaredDistance for $ty
|
||||
where
|
||||
T: ComputeSquaredDistance + RepeatableListAnimatable,
|
||||
{
|
||||
#[inline]
|
||||
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
||||
fn squared_distance_repeatable_list(
|
||||
&self,
|
||||
other: &Self,
|
||||
) -> Result<SquaredDistance, ()>
|
||||
where
|
||||
T: ComputeSquaredDistance,
|
||||
{
|
||||
if self.is_empty() || other.is_empty() {
|
||||
return Err(());
|
||||
}
|
||||
|
@ -794,11 +817,59 @@ macro_rules! repeated_vec_impl {
|
|||
this.compute_squared_distance(other)
|
||||
}).sum()
|
||||
}
|
||||
})*
|
||||
};
|
||||
|
||||
fn animate_with_zero(
|
||||
&self,
|
||||
other: &Self,
|
||||
procedure: Procedure,
|
||||
) -> Result<Self, ()>
|
||||
where
|
||||
T: Animate + Clone + ToAnimatedZero
|
||||
{
|
||||
if procedure == Procedure::Add {
|
||||
return Ok(
|
||||
self.iter().chain(other.iter()).cloned().collect()
|
||||
);
|
||||
}
|
||||
self.iter().zip_longest(other.iter()).map(|it| {
|
||||
match it {
|
||||
EitherOrBoth::Both(this, other) => {
|
||||
this.animate(other, procedure)
|
||||
},
|
||||
EitherOrBoth::Left(this) => {
|
||||
this.animate(&this.to_animated_zero()?, procedure)
|
||||
},
|
||||
EitherOrBoth::Right(other) => {
|
||||
other.to_animated_zero()?.animate(other, procedure)
|
||||
}
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
|
||||
fn squared_distance_with_zero(
|
||||
&self,
|
||||
other: &Self,
|
||||
) -> Result<SquaredDistance, ()>
|
||||
where
|
||||
T: ToAnimatedZero + ComputeSquaredDistance
|
||||
{
|
||||
self.iter().zip_longest(other.iter()).map(|it| {
|
||||
match it {
|
||||
EitherOrBoth::Both(this, other) => {
|
||||
this.compute_squared_distance(other)
|
||||
},
|
||||
EitherOrBoth::Left(list) | EitherOrBoth::Right(list) => {
|
||||
list.to_animated_zero()?.compute_squared_distance(list)
|
||||
},
|
||||
}
|
||||
}).sum()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repeated_vec_impl!(SmallVec<[T; 1]>, Vec<T>);
|
||||
animated_list_impl!(<T> for SmallVec<[T; 1]>);
|
||||
animated_list_impl!(<T> for Vec<T>);
|
||||
|
||||
/// <https://drafts.csswg.org/css-transitions/#animtype-visibility>
|
||||
impl Animate for Visibility {
|
||||
|
@ -1027,9 +1098,6 @@ impl<'a> Iterator for FontSettingTagIter<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<H, V> RepeatableListAnimatable for generic_position::Position<H, V>
|
||||
where H: RepeatableListAnimatable, V: RepeatableListAnimatable {}
|
||||
|
||||
/// <https://drafts.csswg.org/css-transitions/#animtype-rect>
|
||||
impl Animate for ClipRect {
|
||||
#[inline]
|
||||
|
@ -2668,27 +2736,16 @@ impl ComputeSquaredDistance for ComputedTransformOperation {
|
|||
impl ComputeSquaredDistance for ComputedTransform {
|
||||
#[inline]
|
||||
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
||||
let list1 = &self.0;
|
||||
let list2 = &other.0;
|
||||
let squared_dist = self.0.squared_distance_with_zero(&other.0);
|
||||
|
||||
let squared_dist: Result<SquaredDistance, _> = list1.iter().zip_longest(list2).map(|it| {
|
||||
match it {
|
||||
EitherOrBoth::Both(this, other) => {
|
||||
this.compute_squared_distance(other)
|
||||
},
|
||||
EitherOrBoth::Left(list) | EitherOrBoth::Right(list) => {
|
||||
list.to_animated_zero()?.compute_squared_distance(list)
|
||||
},
|
||||
}
|
||||
}).sum();
|
||||
|
||||
// Roll back to matrix interpolation if there is any Err(()) in the transform lists, such
|
||||
// as mismatched transform functions.
|
||||
if let Err(_) = squared_dist {
|
||||
// Roll back to matrix interpolation if there is any Err(()) in the
|
||||
// transform lists, such as mismatched transform functions.
|
||||
if squared_dist.is_err() {
|
||||
let matrix1: Matrix3D = self.to_transform_3d_matrix(None)?.0.into();
|
||||
let matrix2: Matrix3D = other.to_transform_3d_matrix(None)?.0.into();
|
||||
return matrix1.compute_squared_distance(&matrix2);
|
||||
}
|
||||
|
||||
squared_dist
|
||||
}
|
||||
}
|
||||
|
@ -2828,7 +2885,7 @@ where
|
|||
/// <https://www.w3.org/TR/SVG11/painting.html#StrokeDasharrayProperty>
|
||||
impl<L> Animate for SVGStrokeDashArray<L>
|
||||
where
|
||||
L: Clone + RepeatableListAnimatable,
|
||||
L: Clone + Animate,
|
||||
{
|
||||
#[inline]
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
|
@ -2838,7 +2895,22 @@ where
|
|||
}
|
||||
match (self, other) {
|
||||
(&SVGStrokeDashArray::Values(ref this), &SVGStrokeDashArray::Values(ref other)) => {
|
||||
Ok(SVGStrokeDashArray::Values(this.animate(other, procedure)?))
|
||||
Ok(SVGStrokeDashArray::Values(this.animate_repeatable_list(other, procedure)?))
|
||||
},
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<L> ComputeSquaredDistance for SVGStrokeDashArray<L>
|
||||
where
|
||||
L: ComputeSquaredDistance,
|
||||
{
|
||||
#[inline]
|
||||
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
||||
match (self, other) {
|
||||
(&SVGStrokeDashArray::Values(ref this), &SVGStrokeDashArray::Values(ref other)) => {
|
||||
this.squared_distance_repeatable_list(other)
|
||||
},
|
||||
_ => Err(()),
|
||||
}
|
||||
|
@ -2929,50 +3001,6 @@ impl ToAnimatedZero for AnimatedFilter {
|
|||
}
|
||||
}
|
||||
|
||||
impl Animate for AnimatedFilterList {
|
||||
#[inline]
|
||||
fn animate(
|
||||
&self,
|
||||
other: &Self,
|
||||
procedure: Procedure,
|
||||
) -> Result<Self, ()> {
|
||||
if procedure == Procedure::Add {
|
||||
return Ok(AnimatedFilterList(
|
||||
self.0.iter().chain(other.0.iter()).cloned().collect(),
|
||||
));
|
||||
}
|
||||
Ok(AnimatedFilterList(self.0.iter().zip_longest(other.0.iter()).map(|it| {
|
||||
match it {
|
||||
EitherOrBoth::Both(this, other) => {
|
||||
this.animate(other, procedure)
|
||||
},
|
||||
EitherOrBoth::Left(this) => {
|
||||
this.animate(&this.to_animated_zero()?, procedure)
|
||||
},
|
||||
EitherOrBoth::Right(other) => {
|
||||
other.to_animated_zero()?.animate(other, procedure)
|
||||
},
|
||||
}
|
||||
}).collect::<Result<Vec<_>, _>>()?))
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeSquaredDistance for AnimatedFilterList {
|
||||
#[inline]
|
||||
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
||||
self.0.iter().zip_longest(other.0.iter()).map(|it| {
|
||||
match it {
|
||||
EitherOrBoth::Both(this, other) => {
|
||||
this.compute_squared_distance(other)
|
||||
},
|
||||
EitherOrBoth::Left(list) | EitherOrBoth::Right(list) => {
|
||||
list.to_animated_zero()?.compute_squared_distance(list)
|
||||
},
|
||||
}
|
||||
}).sum()
|
||||
}
|
||||
}
|
||||
|
||||
/// A comparator to sort PropertyIds such that longhands are sorted before shorthands,
|
||||
/// shorthands with fewer components are sorted before shorthands with more components,
|
||||
/// and otherwise shorthands are sorted by IDL name as defined by [Web Animations][property-order].
|
||||
|
|
|
@ -36,6 +36,7 @@ ${helpers.predefined_type("background-image", "ImageLayer",
|
|||
spec="https://drafts.csswg.org/css-backgrounds-4/#propdef-background-position-" + axis,
|
||||
animation_value_type="ComputedValue",
|
||||
vector=True,
|
||||
vector_animation_type="repeatable_list",
|
||||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
)}
|
||||
% endfor
|
||||
|
@ -76,13 +77,15 @@ ${helpers.single_keyword("background-origin",
|
|||
animation_value_type="discrete",
|
||||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER")}
|
||||
|
||||
${helpers.predefined_type("background-size", "BackgroundSize",
|
||||
${helpers.predefined_type(
|
||||
"background-size",
|
||||
"BackgroundSize",
|
||||
initial_value="computed::BackgroundSize::auto()",
|
||||
initial_specified_value="specified::BackgroundSize::auto()",
|
||||
spec="https://drafts.csswg.org/css-backgrounds/#the-background-size",
|
||||
vector=True,
|
||||
vector_animation_type="repeatable_list",
|
||||
animation_value_type="BackgroundSizeList",
|
||||
need_animatable=True,
|
||||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
extra_prefixes="webkit")}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ ${helpers.predefined_type(
|
|||
None,
|
||||
vector=True,
|
||||
animation_value_type="AnimatedBoxShadowList",
|
||||
vector_animation_type="with_zero",
|
||||
extra_prefixes="webkit",
|
||||
ignored_when_colors_disabled=True,
|
||||
flags="APPLIES_TO_FIRST_LETTER",
|
||||
|
@ -45,6 +46,7 @@ ${helpers.predefined_type(
|
|||
vector=True,
|
||||
separator="Space",
|
||||
animation_value_type="AnimatedFilterList",
|
||||
vector_animation_type="with_zero",
|
||||
extra_prefixes="webkit",
|
||||
flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
|
||||
spec="https://drafts.fxtf.org/filters/#propdef-filter",
|
||||
|
|
|
@ -192,6 +192,7 @@ ${helpers.predefined_type(
|
|||
"SimpleShadow",
|
||||
None,
|
||||
vector=True,
|
||||
vector_animation_type="with_zero",
|
||||
animation_value_type="AnimatedTextShadowList",
|
||||
ignored_when_colors_disabled=True,
|
||||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
|
|
|
@ -103,6 +103,7 @@ ${helpers.predefined_type(
|
|||
initial_specified_value="specified::PositionComponent::Center",
|
||||
spec="https://drafts.fxtf.org/css-masking/#propdef-mask-position",
|
||||
animation_value_type="ComputedValue",
|
||||
vector_animation_type="repeatable_list",
|
||||
vector=True,
|
||||
)}
|
||||
% endfor
|
||||
|
@ -126,26 +127,18 @@ ${helpers.single_keyword("mask-origin",
|
|||
gecko_enum_prefix="StyleGeometryBox",
|
||||
animation_value_type="discrete",
|
||||
spec="https://drafts.fxtf.org/css-masking/#propdef-mask-origin")}
|
||||
|
||||
<%helpers:longhand name="mask-size" products="gecko" animation_value_type="ComputedValue" extra_prefixes="webkit"
|
||||
spec="https://drafts.fxtf.org/css-masking/#propdef-mask-size">
|
||||
use properties::longhands::background_size;
|
||||
pub use ::properties::longhands::background_size::SpecifiedValue;
|
||||
pub use ::properties::longhands::background_size::single_value as single_value;
|
||||
pub use ::properties::longhands::background_size::computed_value as computed_value;
|
||||
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> computed_value::T {
|
||||
background_size::get_initial_value()
|
||||
}
|
||||
|
||||
pub fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<SpecifiedValue, ParseError<'i>> {
|
||||
background_size::parse(context, input)
|
||||
}
|
||||
</%helpers:longhand>
|
||||
${helpers.predefined_type(
|
||||
"mask-size",
|
||||
"background::BackgroundSize",
|
||||
"computed::BackgroundSize::auto()",
|
||||
initial_specified_value="specified::BackgroundSize::auto()",
|
||||
products="gecko",
|
||||
extra_prefixes="webkit",
|
||||
spec="https://drafts.fxtf.org/css-masking/#propdef-mask-size",
|
||||
animation_value_type="MaskSizeList",
|
||||
vector=True,
|
||||
vector_animation_type="repeatable_list",
|
||||
)}
|
||||
|
||||
${helpers.single_keyword("mask-composite",
|
||||
"add subtract intersect exclude",
|
||||
|
|
|
@ -2216,12 +2216,13 @@ pub mod style_structs {
|
|||
#[allow(non_snake_case)]
|
||||
#[inline]
|
||||
pub fn set_${longhand.ident}<I>(&mut self, v: I)
|
||||
where I: IntoIterator<Item = longhands::${longhand.ident}
|
||||
::computed_value::single_value::T>,
|
||||
I::IntoIter: ExactSizeIterator
|
||||
where
|
||||
I: IntoIterator<Item = longhands::${longhand.ident}
|
||||
::computed_value::single_value::T>,
|
||||
I::IntoIter: ExactSizeIterator
|
||||
{
|
||||
self.${longhand.ident} = longhands::${longhand.ident}::computed_value
|
||||
::T(v.into_iter().collect());
|
||||
::List(v.into_iter().collect());
|
||||
}
|
||||
% elif longhand.ident == "display":
|
||||
/// Set `display`.
|
||||
|
@ -2404,7 +2405,7 @@ pub mod style_structs {
|
|||
pub fn clone_${longhand.ident}(
|
||||
&self,
|
||||
) -> longhands::${longhand.ident}::computed_value::T {
|
||||
longhands::${longhand.ident}::computed_value::T(
|
||||
longhands::${longhand.ident}::computed_value::List(
|
||||
self.${longhand.ident}_iter().collect()
|
||||
)
|
||||
}
|
||||
|
|
|
@ -188,8 +188,10 @@
|
|||
use values::specified::position::Position;
|
||||
use parser::Parse;
|
||||
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
pub fn parse_value<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Longhands, ParseError<'i>> {
|
||||
// Vec grows from 0 to 4 by default on first push(). So allocate with
|
||||
// capacity 1, so in the common case of only one item we don't way
|
||||
// overallocate. Note that we always push at least one item if parsing
|
||||
|
@ -205,7 +207,8 @@
|
|||
any = true;
|
||||
Ok(())
|
||||
})?;
|
||||
if any == false {
|
||||
|
||||
if !any {
|
||||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue