diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index c3a80eda360..ad64c3e7224 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -27,8 +27,9 @@ use properties::{LonghandId, ShorthandId}; use selectors::parser::SelectorParseErrorKind; use servo_arc::Arc; use smallvec::SmallVec; -use std::{cmp, mem, ptr}; +use std::{cmp, ptr}; use std::fmt::{self, Write}; +use std::mem::{self, ManuallyDrop}; #[cfg(feature = "gecko")] use hash::FnvHashMap; use style_traits::{CssWriter, ParseError, ToCss}; use super::ComputedValues; @@ -346,7 +347,7 @@ unsafe impl HasSimpleFFI for AnimationValueMap {} /// FIXME: We need to add a path for custom properties, but that's trivial after /// this (is a similar path to that of PropertyDeclaration). #[cfg_attr(feature = "servo", derive(MallocSizeOf))] -#[derive(Clone, Debug)] +#[derive(Debug)] #[repr(u16)] pub enum AnimationValue { % for prop in data.longhands: @@ -376,6 +377,61 @@ struct AnimationValueVariantRepr { value: T } +impl Clone for AnimationValue { + #[inline] + fn clone(&self) -> Self { + use self::AnimationValue::*; + + <% + [copy, others] = [list(g) for _, g in groupby(animated, key=lambda x: not x.specified_is_copy())] + %> + + let self_tag = unsafe { *(self as *const _ as *const u16) }; + if self_tag <= LonghandId::${copy[-1].camel_case} as u16 { + #[derive(Clone, Copy)] + #[repr(u16)] + enum CopyVariants { + % for prop in copy: + _${prop.camel_case}(${prop.animated_type()}), + % endfor + } + + unsafe { + let mut out = mem::uninitialized(); + ptr::write( + &mut out as *mut _ as *mut CopyVariants, + *(self as *const _ as *const CopyVariants), + ); + return out; + } + } + + match *self { + % for ty, props in groupby(others, key=lambda x: x.animated_type()): + <% props = list(props) %> + ${" |\n".join("{}(ref value)".format(prop.camel_case) for prop in props)} => { + % if len(props) == 1: + ${props[0].camel_case}(value.clone()) + % else: + unsafe { + let mut out = ManuallyDrop::new(mem::uninitialized()); + ptr::write( + &mut out as *mut _ as *mut AnimationValueVariantRepr<${ty}>, + AnimationValueVariantRepr { + tag: *(self as *const _ as *const u16), + value: value.clone(), + }, + ); + ManuallyDrop::into_inner(out) + } + % endif + } + % endfor + _ => unsafe { debug_unreachable!() } + } + } +} + impl PartialEq for AnimationValue { #[inline] fn eq(&self, other: &Self) -> bool { diff --git a/components/style/values/computed/border.rs b/components/style/values/computed/border.rs index bb9b71edeb6..cfef89a62e1 100644 --- a/components/style/values/computed/border.rs +++ b/components/style/values/computed/border.rs @@ -88,7 +88,7 @@ impl ToAnimatedZero for BorderCornerRadius { /// The computed value of the `border-image-repeat` property: /// /// https://drafts.csswg.org/css-backgrounds/#the-border-image-repeat -#[derive(Clone, Debug, MallocSizeOf, PartialEq)] +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq)] pub struct BorderImageRepeat(pub BorderImageRepeatKeyword, pub BorderImageRepeatKeyword); impl BorderImageRepeat {