1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/smil/nsSMILMappedAttribute.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,149 @@ 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 mapped attribute on an element */ 1.10 +#include "nsSMILMappedAttribute.h" 1.11 +#include "nsContentUtils.h" 1.12 +#include "nsError.h" // For NS_PROPTABLE_PROP_OVERWRITTEN 1.13 +#include "nsSMILValue.h" 1.14 +#include "nsSMILCSSValueType.h" 1.15 +#include "nsIDocument.h" 1.16 +#include "nsIPresShell.h" 1.17 +#include "nsCSSProps.h" 1.18 +#include "mozilla/dom/Element.h" 1.19 + 1.20 +// Callback function, for freeing string buffers stored in property table 1.21 +static void 1.22 +ReleaseStringBufferPropertyValue(void* aObject, /* unused */ 1.23 + nsIAtom* aPropertyName, /* unused */ 1.24 + void* aPropertyValue, 1.25 + void* aData /* unused */) 1.26 +{ 1.27 + nsStringBuffer* buf = static_cast<nsStringBuffer*>(aPropertyValue); 1.28 + buf->Release(); 1.29 +} 1.30 + 1.31 + 1.32 +nsresult 1.33 +nsSMILMappedAttribute::ValueFromString(const nsAString& aStr, 1.34 + const mozilla::dom::SVGAnimationElement* aSrcElement, 1.35 + nsSMILValue& aValue, 1.36 + bool& aPreventCachingOfSandwich) const 1.37 +{ 1.38 + NS_ENSURE_TRUE(IsPropertyAnimatable(mPropID), NS_ERROR_FAILURE); 1.39 + 1.40 + nsSMILCSSValueType::ValueFromString(mPropID, mElement, aStr, aValue, 1.41 + &aPreventCachingOfSandwich); 1.42 + return aValue.IsNull() ? NS_ERROR_FAILURE : NS_OK; 1.43 +} 1.44 + 1.45 +nsSMILValue 1.46 +nsSMILMappedAttribute::GetBaseValue() const 1.47 +{ 1.48 + nsAutoString baseStringValue; 1.49 + nsRefPtr<nsIAtom> attrName = GetAttrNameAtom(); 1.50 + bool success = mElement->GetAttr(kNameSpaceID_None, attrName, 1.51 + baseStringValue); 1.52 + nsSMILValue baseValue; 1.53 + if (success) { 1.54 + // For base values, we don't need to worry whether the value returned is 1.55 + // context-sensitive or not since the compositor will take care of comparing 1.56 + // the returned (computed) base value and its cached value and determining 1.57 + // if an update is required or not. 1.58 + nsSMILCSSValueType::ValueFromString(mPropID, mElement, 1.59 + baseStringValue, baseValue, nullptr); 1.60 + } else { 1.61 + // Attribute is unset -- use computed value. 1.62 + // FIRST: Temporarily clear animated value, to make sure it doesn't pollute 1.63 + // the computed value. (We want base value, _without_ animations applied.) 1.64 + void* buf = mElement->UnsetProperty(SMIL_MAPPED_ATTR_ANIMVAL, 1.65 + attrName, nullptr); 1.66 + FlushChangesToTargetAttr(); 1.67 + 1.68 + // SECOND: we use nsSMILCSSProperty::GetBaseValue to look up the property's 1.69 + // computed value. NOTE: This call will temporarily clear the SMIL 1.70 + // override-style for the corresponding CSS property on our target element. 1.71 + // This prevents any animations that target the CSS property from affecting 1.72 + // animations that target the mapped attribute. 1.73 + baseValue = nsSMILCSSProperty::GetBaseValue(); 1.74 + 1.75 + // FINALLY: If we originally had an animated value set, then set it again. 1.76 + if (buf) { 1.77 + mElement->SetProperty(SMIL_MAPPED_ATTR_ANIMVAL, attrName, buf, 1.78 + ReleaseStringBufferPropertyValue); 1.79 + FlushChangesToTargetAttr(); 1.80 + } 1.81 + } 1.82 + return baseValue; 1.83 +} 1.84 + 1.85 +nsresult 1.86 +nsSMILMappedAttribute::SetAnimValue(const nsSMILValue& aValue) 1.87 +{ 1.88 + NS_ENSURE_TRUE(IsPropertyAnimatable(mPropID), NS_ERROR_FAILURE); 1.89 + 1.90 + // Convert nsSMILValue to string 1.91 + nsAutoString valStr; 1.92 + if (!nsSMILCSSValueType::ValueToString(aValue, valStr)) { 1.93 + NS_WARNING("Failed to convert nsSMILValue for mapped attr into a string"); 1.94 + return NS_ERROR_FAILURE; 1.95 + } 1.96 + 1.97 + nsRefPtr<nsIAtom> attrName = GetAttrNameAtom(); 1.98 + nsStringBuffer* oldValStrBuf = static_cast<nsStringBuffer*> 1.99 + (mElement->GetProperty(SMIL_MAPPED_ATTR_ANIMVAL, attrName)); 1.100 + if (oldValStrBuf) { 1.101 + nsString oldValStr; 1.102 + nsContentUtils::PopulateStringFromStringBuffer(oldValStrBuf, oldValStr); 1.103 + if (valStr.Equals(oldValStr)) { 1.104 + // New animated value is the same as the old; nothing to do. 1.105 + return NS_OK; 1.106 + } 1.107 + } 1.108 + 1.109 + // Set the string as this mapped attribute's animated value. 1.110 + nsStringBuffer* valStrBuf = 1.111 + nsCSSValue::BufferFromString(nsString(valStr)).take(); 1.112 + nsresult rv = mElement->SetProperty(SMIL_MAPPED_ATTR_ANIMVAL, 1.113 + attrName, valStrBuf, 1.114 + ReleaseStringBufferPropertyValue); 1.115 + if (rv == NS_PROPTABLE_PROP_OVERWRITTEN) { 1.116 + rv = NS_OK; 1.117 + } 1.118 + FlushChangesToTargetAttr(); 1.119 + 1.120 + return rv; 1.121 +} 1.122 + 1.123 +void 1.124 +nsSMILMappedAttribute::ClearAnimValue() 1.125 +{ 1.126 + nsRefPtr<nsIAtom> attrName = GetAttrNameAtom(); 1.127 + mElement->DeleteProperty(SMIL_MAPPED_ATTR_ANIMVAL, attrName); 1.128 + FlushChangesToTargetAttr(); 1.129 +} 1.130 + 1.131 +void 1.132 +nsSMILMappedAttribute::FlushChangesToTargetAttr() const 1.133 +{ 1.134 + // Clear animated content-style-rule 1.135 + mElement->DeleteProperty(SMIL_MAPPED_ATTR_ANIMVAL, 1.136 + SMIL_MAPPED_ATTR_STYLERULE_ATOM); 1.137 + nsIDocument* doc = mElement->GetCurrentDoc(); 1.138 + 1.139 + // Request animation restyle 1.140 + if (doc) { 1.141 + nsIPresShell* shell = doc->GetShell(); 1.142 + if (shell) { 1.143 + shell->RestyleForAnimation(mElement, eRestyle_Self); 1.144 + } 1.145 + } 1.146 +} 1.147 + 1.148 +already_AddRefed<nsIAtom> 1.149 +nsSMILMappedAttribute::GetAttrNameAtom() const 1.150 +{ 1.151 + return do_GetAtom(nsCSSProps::GetStringValue(mPropID)); 1.152 +}