diff options
-rw-r--r-- | components/malloc_size_of/Cargo.toml | 3 | ||||
-rw-r--r-- | components/malloc_size_of/lib.rs | 2 | ||||
-rw-r--r-- | components/style/animation.rs | 8 | ||||
-rw-r--r-- | components/style/gecko/media_features.rs | 115 | ||||
-rw-r--r-- | components/style/gecko/media_queries.rs | 5 | ||||
-rw-r--r-- | components/style/gecko/url.rs | 24 | ||||
-rw-r--r-- | components/style/properties/gecko.mako.rs | 24 | ||||
-rw-r--r-- | components/style/rule_tree/mod.rs | 3 | ||||
-rw-r--r-- | components/style/servo/url.rs | 12 | ||||
-rw-r--r-- | components/style/values/animated/effects.rs | 12 | ||||
-rw-r--r-- | components/style/values/generics/effects.rs | 1 | ||||
-rw-r--r-- | components/style/values/generics/font.rs | 25 | ||||
-rw-r--r-- | components/style/values/specified/basic_shape.rs | 20 | ||||
-rw-r--r-- | components/style/values/specified/font.rs | 10 | ||||
-rw-r--r-- | components/style/values/specified/image.rs | 15 | ||||
-rw-r--r-- | components/style/values/specified/svg_path.rs | 7 | ||||
-rw-r--r-- | components/style_derive/compute_squared_distance.rs | 21 |
17 files changed, 239 insertions, 68 deletions
diff --git a/components/malloc_size_of/Cargo.toml b/components/malloc_size_of/Cargo.toml index 8a401dd012f..cd05b5d50c0 100644 --- a/components/malloc_size_of/Cargo.toml +++ b/components/malloc_size_of/Cargo.toml @@ -15,6 +15,7 @@ servo = [ "mozjs", "serde", "serde_bytes", + "servo_channel", "string_cache", "time", "url", @@ -34,7 +35,7 @@ selectors = { path = "../selectors" } serde = { version = "1.0.27", optional = true } serde_bytes = { version = "0.10", optional = true } servo_arc = { path = "../servo_arc" } -servo_channel = {path = "../channel"} +servo_channel = { path = "../channel", optional = true } smallbitvec = "2.1.0" smallvec = "0.6" string_cache = { version = "0.7", optional = true } diff --git a/components/malloc_size_of/lib.rs b/components/malloc_size_of/lib.rs index d39d162f6b3..72b7f81595a 100644 --- a/components/malloc_size_of/lib.rs +++ b/components/malloc_size_of/lib.rs @@ -59,6 +59,7 @@ extern crate serde; #[cfg(feature = "servo")] extern crate serde_bytes; extern crate servo_arc; +#[cfg(feature = "servo")] extern crate servo_channel; extern crate smallbitvec; extern crate smallvec; @@ -1024,6 +1025,7 @@ where // Placeholder for unique case where internals of Sender cannot be measured. // malloc size of is 0 macro complains about type supplied! +#[cfg(feature = "servo")] impl<T> MallocSizeOf for servo_channel::Sender<T> { fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { 0 diff --git a/components/style/animation.rs b/components/style/animation.rs index bcb42653cbd..5c0a7103426 100644 --- a/components/style/animation.rs +++ b/components/style/animation.rs @@ -4,6 +4,10 @@ //! CSS transitions and animations. +// NOTE(emilio): This code isn't really executed in Gecko, but we don't want to +// compile it out so that people remember it exists, thus the cfg'd Sender +// import. + use Atom; use bezier::Bezier; use context::SharedStyleContext; @@ -15,8 +19,11 @@ use properties::longhands::animation_direction::computed_value::single_value::T use properties::longhands::animation_play_state::computed_value::single_value::T as AnimationPlayState; use rule_tree::CascadeLevel; use servo_arc::Arc; +#[cfg(feature = "servo")] use servo_channel::Sender; use std::fmt; +#[cfg(feature = "gecko")] +use std::sync::mpsc::Sender; use stylesheets::keyframes_rule::{KeyframesAnimation, KeyframesStep, KeyframesStepValue}; use timer::Timer; use values::computed::Time; @@ -25,6 +32,7 @@ use values::computed::transform::TimingFunction; use values::generics::box_::AnimationIterationCount; use values::generics::transform::{StepPosition, TimingFunction as GenericTimingFunction}; + /// This structure represents a keyframes animation current iteration state. /// /// If the iteration count is infinite, there's no other state, otherwise we diff --git a/components/style/gecko/media_features.rs b/components/style/gecko/media_features.rs index 85f0ba27d43..5c744f24220 100644 --- a/components/style/gecko/media_features.rs +++ b/components/style/gecko/media_features.rs @@ -8,6 +8,7 @@ use Atom; use app_units::Au; use euclid::Size2D; use gecko_bindings::bindings; +use gecko_bindings::structs; use media_queries::Device; use media_queries::media_feature::{AllowsRanges, ParsingRequirements}; use media_queries::media_feature::{MediaFeatureDescription, Evaluator}; @@ -300,6 +301,94 @@ fn eval_prefers_reduced_motion(device: &Device, query_value: Option<PrefersReduc } } +/// https://drafts.csswg.org/mediaqueries-4/#mf-interaction +bitflags! { + struct PointerCapabilities: u8 { + const COARSE = structs::PointerCapabilities_Coarse; + const FINE = structs::PointerCapabilities_Fine; + const HOVER = structs::PointerCapabilities_Hover; + } +} + +fn primary_pointer_capabilities(device: &Device) -> PointerCapabilities { + PointerCapabilities::from_bits_truncate( + unsafe { bindings::Gecko_MediaFeatures_PrimaryPointerCapabilities(device.document()) } + ) +} + +fn all_pointer_capabilities(device: &Device) -> PointerCapabilities { + PointerCapabilities::from_bits_truncate( + unsafe { bindings::Gecko_MediaFeatures_AllPointerCapabilities(device.document()) } + ) +} + +#[derive(Clone, Copy, Debug, FromPrimitive, Parse, ToCss)] +#[repr(u8)] +enum Pointer { + None, + Coarse, + Fine, +} + +fn eval_pointer_capabilities( + query_value: Option<Pointer>, + pointer_capabilities: PointerCapabilities, +) -> bool { + let query_value = match query_value { + Some(v) => v, + None => return !pointer_capabilities.is_empty(), + }; + + match query_value { + Pointer::None => pointer_capabilities.is_empty(), + Pointer::Coarse => pointer_capabilities.intersects(PointerCapabilities::COARSE), + Pointer::Fine => pointer_capabilities.intersects(PointerCapabilities::FINE), + } +} + +/// https://drafts.csswg.org/mediaqueries-4/#pointer +fn eval_pointer(device: &Device, query_value: Option<Pointer>) -> bool { + eval_pointer_capabilities(query_value, primary_pointer_capabilities(device)) +} + +/// https://drafts.csswg.org/mediaqueries-4/#descdef-media-any-pointer +fn eval_any_pointer(device: &Device, query_value: Option<Pointer>) -> bool { + eval_pointer_capabilities(query_value, all_pointer_capabilities(device)) +} + +#[derive(Clone, Copy, Debug, FromPrimitive, Parse, ToCss)] +#[repr(u8)] +enum Hover { + None, + Hover, +} + +fn eval_hover_capabilities( + query_value: Option<Hover>, + pointer_capabilities: PointerCapabilities, +) -> bool { + let can_hover = pointer_capabilities.intersects(PointerCapabilities::HOVER); + let query_value = match query_value { + Some(v) => v, + None => return can_hover, + }; + + match query_value { + Hover::None => !can_hover, + Hover::Hover => can_hover, + } +} + +/// https://drafts.csswg.org/mediaqueries-4/#hover +fn eval_hover(device: &Device, query_value: Option<Hover>) -> bool { + eval_hover_capabilities(query_value, primary_pointer_capabilities(device)) +} + +/// https://drafts.csswg.org/mediaqueries-4/#descdef-media-any-hover +fn eval_any_hover(device: &Device, query_value: Option<Hover>) -> bool { + eval_hover_capabilities(query_value, all_pointer_capabilities(device)) +} + fn eval_moz_is_glyph( device: &Device, query_value: Option<bool>, @@ -390,7 +479,7 @@ lazy_static! { /// to support new types in these entries and (2) ensuring that either /// nsPresContext::MediaFeatureValuesChanged is called when the value that /// would be returned by the evaluator function could change. - pub static ref MEDIA_FEATURES: [MediaFeatureDescription; 43] = [ + pub static ref MEDIA_FEATURES: [MediaFeatureDescription; 47] = [ feature!( atom!("width"), AllowsRanges::Yes, @@ -509,6 +598,30 @@ lazy_static! { keyword_evaluator!(eval_prefers_reduced_motion, PrefersReducedMotion), ParsingRequirements::empty(), ), + feature!( + atom!("pointer"), + AllowsRanges::No, + keyword_evaluator!(eval_pointer, Pointer), + ParsingRequirements::empty(), + ), + feature!( + atom!("any-pointer"), + AllowsRanges::No, + keyword_evaluator!(eval_any_pointer, Pointer), + ParsingRequirements::empty(), + ), + feature!( + atom!("hover"), + AllowsRanges::No, + keyword_evaluator!(eval_hover, Hover), + ParsingRequirements::empty(), + ), + feature!( + atom!("any-hover"), + AllowsRanges::No, + keyword_evaluator!(eval_any_hover, Hover), + ParsingRequirements::empty(), + ), // Internal -moz-is-glyph media feature: applies only inside SVG glyphs. // Internal because it is really only useful in the user agent anyway diff --git a/components/style/gecko/media_queries.rs b/components/style/gecko/media_queries.rs index ccf5b7a5180..65855b0a8a3 100644 --- a/components/style/gecko/media_queries.rs +++ b/components/style/gecko/media_queries.rs @@ -234,10 +234,13 @@ impl Device { } /// Applies text zoom to a font-size or line-height value (see nsStyleFont::ZoomText). + #[inline] pub fn zoom_text(&self, size: Au) -> Au { size.scale_by(self.pres_context().mEffectiveTextZoom) } - /// Un-apply text zoom (see nsStyleFont::UnzoomText). + + /// Un-apply text zoom. + #[inline] pub fn unzoom_text(&self, size: Au) -> Au { size.scale_by(1. / self.pres_context().mEffectiveTextZoom) } diff --git a/components/style/gecko/url.rs b/components/style/gecko/url.rs index 8d785cae679..c00fc8c27e3 100644 --- a/components/style/gecko/url.rs +++ b/components/style/gecko/url.rs @@ -9,6 +9,7 @@ use gecko_bindings::bindings; use gecko_bindings::structs::ServoBundledURI; use gecko_bindings::structs::mozilla::css::URLValueData; use gecko_bindings::structs::root::{RustString, nsStyleImageRequest}; +use gecko_bindings::structs::root::mozilla::CORSMode; use gecko_bindings::structs::root::mozilla::css::{ImageValue, URLValue}; use gecko_bindings::sugar::refptr::RefPtr; use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; @@ -186,15 +187,34 @@ impl SpecifiedImageUrl { Self::from_css_url(CssUrl::parse_from_string(url, context)) } - fn from_css_url(url: CssUrl) -> Self { + fn from_css_url_with_cors(url: CssUrl, cors: CORSMode) -> Self { let image_value = unsafe { - let ptr = bindings::Gecko_ImageValue_Create(url.for_ffi()); + let ptr = bindings::Gecko_ImageValue_Create(url.for_ffi(), cors); // We do not expect Gecko_ImageValue_Create returns null. debug_assert!(!ptr.is_null()); RefPtr::from_addrefed(ptr) }; Self { url, image_value } } + + fn from_css_url(url: CssUrl) -> Self { + use gecko_bindings::structs::root::mozilla::CORSMode_CORS_NONE; + Self::from_css_url_with_cors(url, CORSMode_CORS_NONE) + } + + fn from_css_url_with_cors_anonymous(url: CssUrl) -> Self { + use gecko_bindings::structs::root::mozilla::CORSMode_CORS_ANONYMOUS; + Self::from_css_url_with_cors(url, CORSMode_CORS_ANONYMOUS) + } + + /// Provides an alternate method for parsing that associates the URL + /// with anonymous CORS headers. + pub fn parse_with_cors_anonymous<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result<Self, ParseError<'i>> { + CssUrl::parse(context, input).map(Self::from_css_url_with_cors_anonymous) + } } impl Parse for SpecifiedImageUrl { diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 9e9a6835a42..1de99ec16f1 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -2403,7 +2403,8 @@ fn static_assert() { /// Calculates the constrained and unconstrained font sizes to be inherited /// from the parent. /// - /// See ComputeScriptLevelSize in Gecko's nsRuleNode.cpp + /// This is a port of Gecko's old ComputeScriptLevelSize function: + /// https://dxr.mozilla.org/mozilla-central/rev/35fbf14b9/layout/style/nsRuleNode.cpp#3197-3254 /// /// scriptlevel is a property that affects how font-size is inherited. If scriptlevel is /// +1, for example, it will inherit as the script size multiplier times @@ -2511,17 +2512,18 @@ fn static_assert() { = self.calculate_script_level_size(parent, device); if adjusted_size.0 != parent.gecko.mSize || adjusted_unconstrained_size.0 != parent.gecko.mScriptUnconstrainedSize { - // This is incorrect. When there is both a keyword size being inherited - // and a scriptlevel change, we must handle the keyword size the same - // way we handle em units. This complicates things because we now have - // to keep track of the adjusted and unadjusted ratios in the kw font size. - // This only affects the use case of a generic font being used in MathML. + // FIXME(Manishearth): This is incorrect. When there is both a + // keyword size being inherited and a scriptlevel change, we must + // handle the keyword size the same way we handle em units. This + // complicates things because we now have to keep track of the + // adjusted and unadjusted ratios in the kw font size. This only + // affects the use case of a generic font being used in MathML. // - // If we were to fix this I would prefer doing it by removing the - // ruletree walk on the Gecko side in nsRuleNode::SetGenericFont - // and instead using extra bookkeeping in the mSize and mScriptUnconstrainedSize - // values, and reusing those instead of font_size_keyword. - + // If we were to fix this I would prefer doing it not doing + // something like the ruletree walk that Gecko used to do in + // nsRuleNode::SetGenericFont and instead using extra bookkeeping in + // the mSize and mScriptUnconstrainedSize values, and reusing those + // instead of font_size_keyword. // In the case that MathML has given us an adjusted size, apply it. // Keep track of the unconstrained adjusted size. diff --git a/components/style/rule_tree/mod.rs b/components/style/rule_tree/mod.rs index d4fb0d00925..26c089eb4ad 100644 --- a/components/style/rule_tree/mod.rs +++ b/components/style/rule_tree/mod.rs @@ -1200,9 +1200,6 @@ impl StrongRuleNode { } } - /// Implementation of `nsRuleNode::HasAuthorSpecifiedRules` for Servo rule - /// nodes. - /// /// Returns true if any properties specified by `rule_type_mask` was set by /// an author rule. #[cfg(feature = "gecko")] diff --git a/components/style/servo/url.rs b/components/style/servo/url.rs index b4821f21e66..91521c8a120 100644 --- a/components/style/servo/url.rs +++ b/components/style/servo/url.rs @@ -98,6 +98,18 @@ impl CssUrl { resolved: ServoUrl::parse(url).ok(), } } + + /// Parses a URL request and records that the corresponding request needs to + /// be CORS-enabled. + /// + /// This is only for shape images and masks in Gecko, thus unimplemented for + /// now so somebody notices when trying to do so. + pub fn parse_with_cors_anonymous<'i, 't>( + _context: &ParserContext, + _input: &mut Parser<'i, 't>, + ) -> Result<Self, ParseError<'i>> { + unimplemented!("Need to record somewhere that the request needs to be CORS-enabled") + } } impl Parse for CssUrl { diff --git a/components/style/values/animated/effects.rs b/components/style/values/animated/effects.rs index a201ec0549e..a86396506df 100644 --- a/components/style/values/animated/effects.rs +++ b/components/style/values/animated/effects.rs @@ -11,7 +11,6 @@ use values::computed::{Angle, Number}; use values::computed::length::Length; #[cfg(feature = "gecko")] use values::computed::url::ComputedUrl; -use values::distance::{ComputeSquaredDistance, SquaredDistance}; use values::generics::effects::BoxShadow as GenericBoxShadow; use values::generics::effects::Filter as GenericFilter; use values::generics::effects::SimpleShadow as GenericSimpleShadow; @@ -29,14 +28,3 @@ pub type Filter = GenericFilter<Angle, Number, Length, Impossible, Impossible>; /// An animated value for the `drop-shadow()` filter. pub type SimpleShadow = GenericSimpleShadow<Color, Length, Length>; - -impl ComputeSquaredDistance for BoxShadow { - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> { - if self.inset != other.inset { - return Err(()); - } - Ok(self.base.compute_squared_distance(&other.base)? + - self.spread.compute_squared_distance(&other.spread)?) - } -} diff --git a/components/style/values/generics/effects.rs b/components/style/values/generics/effects.rs index 7c7e3f4bef3..7b8e64f90bf 100644 --- a/components/style/values/generics/effects.rs +++ b/components/style/values/generics/effects.rs @@ -8,6 +8,7 @@ #[derive( Animate, Clone, + ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq, diff --git a/components/style/values/generics/font.rs b/components/style/values/generics/font.rs index 03a76c5a32d..fa1e160273c 100644 --- a/components/style/values/generics/font.rs +++ b/components/style/values/generics/font.rs @@ -13,7 +13,6 @@ use std::fmt::{self, Write}; use std::io::Cursor; use style_traits::{CssWriter, KeywordsCollectFn, ParseError}; use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss}; -use values::distance::{ComputeSquaredDistance, SquaredDistance}; /// https://drafts.csswg.org/css-fonts-4/#feature-tag-value #[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)] @@ -47,7 +46,16 @@ where /// /// https://drafts.csswg.org/css-fonts-4/#font-variation-settings-def #[derive( - Animate, Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, + Animate, + Clone, + ComputeSquaredDistance, + Debug, + Eq, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, )] pub struct VariationValue<Number> { /// A four-character tag, packed into a u32 (one byte per character). @@ -57,19 +65,6 @@ pub struct VariationValue<Number> { pub value: Number, } -impl<Number> ComputeSquaredDistance for VariationValue<Number> -where - Number: ComputeSquaredDistance, -{ - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> { - if self.tag != other.tag { - return Err(()); - } - self.value.compute_squared_distance(&other.value) - } -} - /// A value both for font-variation-settings and font-feature-settings. #[css(comma)] #[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] diff --git a/components/style/values/specified/basic_shape.rs b/components/style/values/specified/basic_shape.rs index cdafbf14b37..52343621b5e 100644 --- a/components/style/values/specified/basic_shape.rs +++ b/components/style/values/specified/basic_shape.rs @@ -71,7 +71,12 @@ impl Parse for ClippingShape { return Ok(ShapeSource::Path(p)); } } - Self::parse_internal(context, input) + + if let Ok(url) = input.try(|i| SpecifiedUrl::parse(context, i)) { + return Ok(ShapeSource::ImageOrUrl(url)); + } + + Self::parse_common(context, input) } } @@ -81,17 +86,20 @@ impl Parse for FloatAreaShape { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - Self::parse_internal(context, input) + if let Ok(image) = input.try(|i| Image::parse_with_cors_anonymous(context, i)) { + return Ok(ShapeSource::ImageOrUrl(image)); + } + + Self::parse_common(context, input) } } impl<ReferenceBox, ImageOrUrl> ShapeSource<BasicShape, ReferenceBox, ImageOrUrl> where ReferenceBox: Parse, - ImageOrUrl: Parse, { /// The internal parser for ShapeSource. - fn parse_internal<'i, 't>( + fn parse_common<'i, 't>( context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { @@ -99,10 +107,6 @@ where return Ok(ShapeSource::None); } - if let Ok(image_or_url) = input.try(|i| ImageOrUrl::parse(context, i)) { - return Ok(ShapeSource::ImageOrUrl(image_or_url)); - } - fn parse_component<U: Parse>( context: &ParserContext, input: &mut Parser, diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index d9cf921bca5..5613ae603d2 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -746,7 +746,12 @@ impl ToComputedValue for KeywordSize { fn to_computed_value(&self, cx: &Context) -> NonNegativeLength { use context::QuirksMode; use values::specified::length::au_to_int_px; - // Data from nsRuleNode.cpp in Gecko + + // The tables in this function are originally from + // nsRuleNode::CalcFontPointSize in Gecko: + // + // https://dxr.mozilla.org/mozilla-central/rev/35fbf14b9/layout/style/nsRuleNode.cpp#3262-3336 + // Mapping from base size and HTML size to pixels // The first index is (base_size - 9), the second is the // HTML size. "0" is CSS keyword xx-small, not HTML size 0, @@ -765,9 +770,6 @@ impl ToComputedValue for KeywordSize { [9, 10, 13, 16, 18, 24, 32, 48], ]; - // Data from nsRuleNode.cpp in Gecko - // (https://dxr.mozilla.org/mozilla-central/rev/35fbf14b9/layout/style/nsRuleNode.cpp#3303) - // // This table gives us compatibility with WinNav4 for the default fonts only. // In WinNav4, the default fonts were: // diff --git a/components/style/values/specified/image.rs b/components/style/values/specified/image.rs index 1c0a613e488..1b080816e83 100644 --- a/components/style/values/specified/image.rs +++ b/components/style/values/specified/image.rs @@ -166,6 +166,21 @@ impl Image { ref t => Err(location.new_unexpected_token_error(t.clone())), }) } + + /// Provides an alternate method for parsing that associates the URL with + /// anonymous CORS headers. + /// + /// FIXME(emilio): It'd be nicer for this to pass a `CorsMode` parameter to + /// a shared function instead. + pub fn parse_with_cors_anonymous<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result<Image, ParseError<'i>> { + if let Ok(url) = input.try(|input| SpecifiedImageUrl::parse_with_cors_anonymous(context, input)) { + return Ok(generic::Image::Url(url)); + } + Self::parse(context, input) + } } impl Parse for Gradient { diff --git a/components/style/values/specified/svg_path.rs b/components/style/values/specified/svg_path.rs index f0973b545a5..5d397558d25 100644 --- a/components/style/values/specified/svg_path.rs +++ b/components/style/values/specified/svg_path.rs @@ -538,13 +538,6 @@ impl ToCss for ArcFlag { } } -impl ComputeSquaredDistance for ArcFlag { - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> { - (self.0 as i32).compute_squared_distance(&(other.0 as i32)) - } -} - /// SVG Path parser. struct PathParser<'a> { chars: Peekable<Cloned<slice::Iter<'a, u8>>>, diff --git a/components/style_derive/compute_squared_distance.rs b/components/style_derive/compute_squared_distance.rs index 5b414206cda..f7e50c6bb00 100644 --- a/components/style_derive/compute_squared_distance.rs +++ b/components/style_derive/compute_squared_distance.rs @@ -2,7 +2,7 @@ * 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/. */ -use animate::{AnimationInputAttrs, AnimationVariantAttrs}; +use animate::{AnimationInputAttrs, AnimationVariantAttrs, AnimationFieldAttrs}; use cg; use quote::Tokens; use syn::{DeriveInput, Path}; @@ -47,8 +47,23 @@ pub fn derive(mut input: DeriveInput) -> Tokens { parse_quote!(#ty: ::values::distance::ComputeSquaredDistance), ); } - quote! { - ::values::distance::ComputeSquaredDistance::compute_squared_distance(#this, #other)? + + let animation_field_attrs = + cg::parse_field_attrs::<AnimationFieldAttrs>(&this.ast()); + + if animation_field_attrs.constant { + quote! { + { + if #this != #other { + return Err(()); + } + ::values::distance::SquaredDistance::from_sqrt(0.) + } + } + } else { + quote! { + ::values::distance::ComputeSquaredDistance::compute_squared_distance(#this, #other)? + } } }), quote!(+)); sum |