1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/smil/nsSMILCSSProperty.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,273 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* representation of a SMIL-animatable CSS property on an element */ 1.10 + 1.11 +#include "nsSMILCSSProperty.h" 1.12 +#include "nsSMILCSSValueType.h" 1.13 +#include "nsSMILValue.h" 1.14 +#include "nsComputedDOMStyle.h" 1.15 +#include "nsCSSProps.h" 1.16 +#include "nsStyleAnimation.h" 1.17 +#include "mozilla/dom/Element.h" 1.18 +#include "nsIDOMElement.h" 1.19 +#include "nsIDocument.h" 1.20 + 1.21 +using namespace mozilla::dom; 1.22 + 1.23 +// Helper function 1.24 +static bool 1.25 +GetCSSComputedValue(Element* aElem, 1.26 + nsCSSProperty aPropID, 1.27 + nsAString& aResult) 1.28 +{ 1.29 + NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(aPropID), 1.30 + "Can't look up computed value of shorthand property"); 1.31 + NS_ABORT_IF_FALSE(nsSMILCSSProperty::IsPropertyAnimatable(aPropID), 1.32 + "Shouldn't get here for non-animatable properties"); 1.33 + 1.34 + nsIDocument* doc = aElem->GetCurrentDoc(); 1.35 + if (!doc) { 1.36 + // This can happen if we process certain types of restyles mid-sample 1.37 + // and remove anonymous animated content from the document as a result. 1.38 + // See bug 534975. 1.39 + return false; 1.40 + } 1.41 + 1.42 + nsIPresShell* shell = doc->GetShell(); 1.43 + if (!shell) { 1.44 + NS_WARNING("Unable to look up computed style -- no pres shell"); 1.45 + return false; 1.46 + } 1.47 + 1.48 + nsRefPtr<nsComputedDOMStyle> computedStyle = 1.49 + NS_NewComputedDOMStyle(aElem, EmptyString(), shell); 1.50 + 1.51 + computedStyle->GetPropertyValue(aPropID, aResult); 1.52 + return true; 1.53 +} 1.54 + 1.55 +// Class Methods 1.56 +nsSMILCSSProperty::nsSMILCSSProperty(nsCSSProperty aPropID, 1.57 + Element* aElement) 1.58 + : mPropID(aPropID), mElement(aElement) 1.59 +{ 1.60 + NS_ABORT_IF_FALSE(IsPropertyAnimatable(mPropID), 1.61 + "Creating a nsSMILCSSProperty for a property " 1.62 + "that's not supported for animation"); 1.63 +} 1.64 + 1.65 +nsSMILValue 1.66 +nsSMILCSSProperty::GetBaseValue() const 1.67 +{ 1.68 + // To benefit from Return Value Optimization and avoid copy constructor calls 1.69 + // due to our use of return-by-value, we must return the exact same object 1.70 + // from ALL return points. This function must only return THIS variable: 1.71 + nsSMILValue baseValue; 1.72 + 1.73 + // SPECIAL CASE: (a) Shorthands 1.74 + // (b) 'display' 1.75 + if (nsCSSProps::IsShorthand(mPropID) || mPropID == eCSSProperty_display) { 1.76 + // We can't look up the base (computed-style) value of shorthand 1.77 + // properties because they aren't guaranteed to have a consistent computed 1.78 + // value. 1.79 + // 1.80 + // Also, although we can look up the base value of the display property, 1.81 + // doing so involves clearing and resetting the property which can cause 1.82 + // frames to be recreated which we'd like to avoid. 1.83 + // 1.84 + // In either case, just return a dummy value (initialized with the right 1.85 + // type, so as not to indicate failure). 1.86 + nsSMILValue tmpVal(&nsSMILCSSValueType::sSingleton); 1.87 + baseValue.Swap(tmpVal); 1.88 + return baseValue; 1.89 + } 1.90 + 1.91 + // GENERAL CASE: Non-Shorthands 1.92 + // (1) Put empty string in override style for property mPropID 1.93 + // (saving old override style value, so we can set it again when we're done) 1.94 + nsICSSDeclaration* overrideDecl = mElement->GetSMILOverrideStyle(); 1.95 + nsAutoString cachedOverrideStyleVal; 1.96 + if (overrideDecl) { 1.97 + overrideDecl->GetPropertyValue(mPropID, cachedOverrideStyleVal); 1.98 + // (Don't bother clearing override style if it's already empty) 1.99 + if (!cachedOverrideStyleVal.IsEmpty()) { 1.100 + overrideDecl->SetPropertyValue(mPropID, EmptyString()); 1.101 + } 1.102 + } 1.103 + 1.104 + // (2) Get Computed Style 1.105 + nsAutoString computedStyleVal; 1.106 + bool didGetComputedVal = GetCSSComputedValue(mElement, mPropID, 1.107 + computedStyleVal); 1.108 + 1.109 + // (3) Put cached override style back (if it's non-empty) 1.110 + if (overrideDecl && !cachedOverrideStyleVal.IsEmpty()) { 1.111 + overrideDecl->SetPropertyValue(mPropID, cachedOverrideStyleVal); 1.112 + } 1.113 + 1.114 + // (4) Populate our nsSMILValue from the computed style 1.115 + if (didGetComputedVal) { 1.116 + // When we parse animation values we check if they are context-sensitive or 1.117 + // not so that we don't cache animation values whose meaning may change. 1.118 + // For base values however this is unnecessary since on each sample the 1.119 + // compositor will fetch the (computed) base value and compare it against 1.120 + // the cached (computed) value and detect changes for us. 1.121 + nsSMILCSSValueType::ValueFromString(mPropID, mElement, 1.122 + computedStyleVal, baseValue, 1.123 + nullptr); 1.124 + } 1.125 + return baseValue; 1.126 +} 1.127 + 1.128 +nsresult 1.129 +nsSMILCSSProperty::ValueFromString(const nsAString& aStr, 1.130 + const SVGAnimationElement* aSrcElement, 1.131 + nsSMILValue& aValue, 1.132 + bool& aPreventCachingOfSandwich) const 1.133 +{ 1.134 + NS_ENSURE_TRUE(IsPropertyAnimatable(mPropID), NS_ERROR_FAILURE); 1.135 + 1.136 + nsSMILCSSValueType::ValueFromString(mPropID, mElement, aStr, aValue, 1.137 + &aPreventCachingOfSandwich); 1.138 + 1.139 + if (aValue.IsNull()) { 1.140 + return NS_ERROR_FAILURE; 1.141 + } 1.142 + 1.143 + // XXX Due to bug 536660 (or at least that seems to be the most likely 1.144 + // culprit), when we have animation setting display:none on a <use> element, 1.145 + // if we DON'T set the property every sample, chaos ensues. 1.146 + if (!aPreventCachingOfSandwich && mPropID == eCSSProperty_display) { 1.147 + aPreventCachingOfSandwich = true; 1.148 + } 1.149 + return NS_OK; 1.150 +} 1.151 + 1.152 +nsresult 1.153 +nsSMILCSSProperty::SetAnimValue(const nsSMILValue& aValue) 1.154 +{ 1.155 + NS_ENSURE_TRUE(IsPropertyAnimatable(mPropID), NS_ERROR_FAILURE); 1.156 + 1.157 + // Convert nsSMILValue to string 1.158 + nsAutoString valStr; 1.159 + if (!nsSMILCSSValueType::ValueToString(aValue, valStr)) { 1.160 + NS_WARNING("Failed to convert nsSMILValue for CSS property into a string"); 1.161 + return NS_ERROR_FAILURE; 1.162 + } 1.163 + 1.164 + // Use string value to style the target element 1.165 + nsICSSDeclaration* overrideDecl = mElement->GetSMILOverrideStyle(); 1.166 + if (overrideDecl) { 1.167 + nsAutoString oldValStr; 1.168 + overrideDecl->GetPropertyValue(mPropID, oldValStr); 1.169 + if (valStr.Equals(oldValStr)) { 1.170 + return NS_OK; 1.171 + } 1.172 + overrideDecl->SetPropertyValue(mPropID, valStr); 1.173 + } 1.174 + return NS_OK; 1.175 +} 1.176 + 1.177 +void 1.178 +nsSMILCSSProperty::ClearAnimValue() 1.179 +{ 1.180 + // Put empty string in override style for our property 1.181 + nsICSSDeclaration* overrideDecl = mElement->GetSMILOverrideStyle(); 1.182 + if (overrideDecl) { 1.183 + overrideDecl->SetPropertyValue(mPropID, EmptyString()); 1.184 + } 1.185 +} 1.186 + 1.187 +// Based on http://www.w3.org/TR/SVG/propidx.html 1.188 +// static 1.189 +bool 1.190 +nsSMILCSSProperty::IsPropertyAnimatable(nsCSSProperty aPropID) 1.191 +{ 1.192 + // NOTE: Right now, Gecko doesn't recognize the following properties from 1.193 + // the SVG Property Index: 1.194 + // alignment-baseline 1.195 + // baseline-shift 1.196 + // color-profile 1.197 + // color-rendering 1.198 + // glyph-orientation-horizontal 1.199 + // glyph-orientation-vertical 1.200 + // kerning 1.201 + // writing-mode 1.202 + 1.203 + switch (aPropID) { 1.204 + case eCSSProperty_clip: 1.205 + case eCSSProperty_clip_rule: 1.206 + case eCSSProperty_clip_path: 1.207 + case eCSSProperty_color: 1.208 + case eCSSProperty_color_interpolation: 1.209 + case eCSSProperty_color_interpolation_filters: 1.210 + case eCSSProperty_cursor: 1.211 + case eCSSProperty_display: 1.212 + case eCSSProperty_dominant_baseline: 1.213 + case eCSSProperty_fill: 1.214 + case eCSSProperty_fill_opacity: 1.215 + case eCSSProperty_fill_rule: 1.216 + case eCSSProperty_filter: 1.217 + case eCSSProperty_flood_color: 1.218 + case eCSSProperty_flood_opacity: 1.219 + case eCSSProperty_font: 1.220 + case eCSSProperty_font_family: 1.221 + case eCSSProperty_font_size: 1.222 + case eCSSProperty_font_size_adjust: 1.223 + case eCSSProperty_font_stretch: 1.224 + case eCSSProperty_font_style: 1.225 + case eCSSProperty_font_variant: 1.226 + case eCSSProperty_font_weight: 1.227 + case eCSSProperty_height: 1.228 + case eCSSProperty_image_rendering: 1.229 + case eCSSProperty_letter_spacing: 1.230 + case eCSSProperty_lighting_color: 1.231 + case eCSSProperty_marker: 1.232 + case eCSSProperty_marker_end: 1.233 + case eCSSProperty_marker_mid: 1.234 + case eCSSProperty_marker_start: 1.235 + case eCSSProperty_mask: 1.236 + case eCSSProperty_mask_type: 1.237 + case eCSSProperty_opacity: 1.238 + case eCSSProperty_overflow: 1.239 + case eCSSProperty_pointer_events: 1.240 + case eCSSProperty_shape_rendering: 1.241 + case eCSSProperty_stop_color: 1.242 + case eCSSProperty_stop_opacity: 1.243 + case eCSSProperty_stroke: 1.244 + case eCSSProperty_stroke_dasharray: 1.245 + case eCSSProperty_stroke_dashoffset: 1.246 + case eCSSProperty_stroke_linecap: 1.247 + case eCSSProperty_stroke_linejoin: 1.248 + case eCSSProperty_stroke_miterlimit: 1.249 + case eCSSProperty_stroke_opacity: 1.250 + case eCSSProperty_stroke_width: 1.251 + case eCSSProperty_text_anchor: 1.252 + case eCSSProperty_text_decoration: 1.253 + case eCSSProperty_text_decoration_line: 1.254 + case eCSSProperty_text_rendering: 1.255 + case eCSSProperty_vector_effect: 1.256 + case eCSSProperty_width: 1.257 + case eCSSProperty_visibility: 1.258 + case eCSSProperty_word_spacing: 1.259 + return true; 1.260 + 1.261 + // EXPLICITLY NON-ANIMATABLE PROPERTIES: 1.262 + // (Some of these aren't supported at all in Gecko -- I've commented those 1.263 + // ones out. If/when we add support for them, uncomment their line here) 1.264 + // ---------------------------------------------------------------------- 1.265 + // case eCSSProperty_enable_background: 1.266 + // case eCSSProperty_glyph_orientation_horizontal: 1.267 + // case eCSSProperty_glyph_orientation_vertical: 1.268 + // case eCSSProperty_writing_mode: 1.269 + case eCSSProperty_direction: 1.270 + case eCSSProperty_unicode_bidi: 1.271 + return false; 1.272 + 1.273 + default: 1.274 + return false; 1.275 + } 1.276 +}