|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 /* representation of a SMIL-animatable mapped attribute on an element */ |
|
7 #include "nsSMILMappedAttribute.h" |
|
8 #include "nsContentUtils.h" |
|
9 #include "nsError.h" // For NS_PROPTABLE_PROP_OVERWRITTEN |
|
10 #include "nsSMILValue.h" |
|
11 #include "nsSMILCSSValueType.h" |
|
12 #include "nsIDocument.h" |
|
13 #include "nsIPresShell.h" |
|
14 #include "nsCSSProps.h" |
|
15 #include "mozilla/dom/Element.h" |
|
16 |
|
17 // Callback function, for freeing string buffers stored in property table |
|
18 static void |
|
19 ReleaseStringBufferPropertyValue(void* aObject, /* unused */ |
|
20 nsIAtom* aPropertyName, /* unused */ |
|
21 void* aPropertyValue, |
|
22 void* aData /* unused */) |
|
23 { |
|
24 nsStringBuffer* buf = static_cast<nsStringBuffer*>(aPropertyValue); |
|
25 buf->Release(); |
|
26 } |
|
27 |
|
28 |
|
29 nsresult |
|
30 nsSMILMappedAttribute::ValueFromString(const nsAString& aStr, |
|
31 const mozilla::dom::SVGAnimationElement* aSrcElement, |
|
32 nsSMILValue& aValue, |
|
33 bool& aPreventCachingOfSandwich) const |
|
34 { |
|
35 NS_ENSURE_TRUE(IsPropertyAnimatable(mPropID), NS_ERROR_FAILURE); |
|
36 |
|
37 nsSMILCSSValueType::ValueFromString(mPropID, mElement, aStr, aValue, |
|
38 &aPreventCachingOfSandwich); |
|
39 return aValue.IsNull() ? NS_ERROR_FAILURE : NS_OK; |
|
40 } |
|
41 |
|
42 nsSMILValue |
|
43 nsSMILMappedAttribute::GetBaseValue() const |
|
44 { |
|
45 nsAutoString baseStringValue; |
|
46 nsRefPtr<nsIAtom> attrName = GetAttrNameAtom(); |
|
47 bool success = mElement->GetAttr(kNameSpaceID_None, attrName, |
|
48 baseStringValue); |
|
49 nsSMILValue baseValue; |
|
50 if (success) { |
|
51 // For base values, we don't need to worry whether the value returned is |
|
52 // context-sensitive or not since the compositor will take care of comparing |
|
53 // the returned (computed) base value and its cached value and determining |
|
54 // if an update is required or not. |
|
55 nsSMILCSSValueType::ValueFromString(mPropID, mElement, |
|
56 baseStringValue, baseValue, nullptr); |
|
57 } else { |
|
58 // Attribute is unset -- use computed value. |
|
59 // FIRST: Temporarily clear animated value, to make sure it doesn't pollute |
|
60 // the computed value. (We want base value, _without_ animations applied.) |
|
61 void* buf = mElement->UnsetProperty(SMIL_MAPPED_ATTR_ANIMVAL, |
|
62 attrName, nullptr); |
|
63 FlushChangesToTargetAttr(); |
|
64 |
|
65 // SECOND: we use nsSMILCSSProperty::GetBaseValue to look up the property's |
|
66 // computed value. NOTE: This call will temporarily clear the SMIL |
|
67 // override-style for the corresponding CSS property on our target element. |
|
68 // This prevents any animations that target the CSS property from affecting |
|
69 // animations that target the mapped attribute. |
|
70 baseValue = nsSMILCSSProperty::GetBaseValue(); |
|
71 |
|
72 // FINALLY: If we originally had an animated value set, then set it again. |
|
73 if (buf) { |
|
74 mElement->SetProperty(SMIL_MAPPED_ATTR_ANIMVAL, attrName, buf, |
|
75 ReleaseStringBufferPropertyValue); |
|
76 FlushChangesToTargetAttr(); |
|
77 } |
|
78 } |
|
79 return baseValue; |
|
80 } |
|
81 |
|
82 nsresult |
|
83 nsSMILMappedAttribute::SetAnimValue(const nsSMILValue& aValue) |
|
84 { |
|
85 NS_ENSURE_TRUE(IsPropertyAnimatable(mPropID), NS_ERROR_FAILURE); |
|
86 |
|
87 // Convert nsSMILValue to string |
|
88 nsAutoString valStr; |
|
89 if (!nsSMILCSSValueType::ValueToString(aValue, valStr)) { |
|
90 NS_WARNING("Failed to convert nsSMILValue for mapped attr into a string"); |
|
91 return NS_ERROR_FAILURE; |
|
92 } |
|
93 |
|
94 nsRefPtr<nsIAtom> attrName = GetAttrNameAtom(); |
|
95 nsStringBuffer* oldValStrBuf = static_cast<nsStringBuffer*> |
|
96 (mElement->GetProperty(SMIL_MAPPED_ATTR_ANIMVAL, attrName)); |
|
97 if (oldValStrBuf) { |
|
98 nsString oldValStr; |
|
99 nsContentUtils::PopulateStringFromStringBuffer(oldValStrBuf, oldValStr); |
|
100 if (valStr.Equals(oldValStr)) { |
|
101 // New animated value is the same as the old; nothing to do. |
|
102 return NS_OK; |
|
103 } |
|
104 } |
|
105 |
|
106 // Set the string as this mapped attribute's animated value. |
|
107 nsStringBuffer* valStrBuf = |
|
108 nsCSSValue::BufferFromString(nsString(valStr)).take(); |
|
109 nsresult rv = mElement->SetProperty(SMIL_MAPPED_ATTR_ANIMVAL, |
|
110 attrName, valStrBuf, |
|
111 ReleaseStringBufferPropertyValue); |
|
112 if (rv == NS_PROPTABLE_PROP_OVERWRITTEN) { |
|
113 rv = NS_OK; |
|
114 } |
|
115 FlushChangesToTargetAttr(); |
|
116 |
|
117 return rv; |
|
118 } |
|
119 |
|
120 void |
|
121 nsSMILMappedAttribute::ClearAnimValue() |
|
122 { |
|
123 nsRefPtr<nsIAtom> attrName = GetAttrNameAtom(); |
|
124 mElement->DeleteProperty(SMIL_MAPPED_ATTR_ANIMVAL, attrName); |
|
125 FlushChangesToTargetAttr(); |
|
126 } |
|
127 |
|
128 void |
|
129 nsSMILMappedAttribute::FlushChangesToTargetAttr() const |
|
130 { |
|
131 // Clear animated content-style-rule |
|
132 mElement->DeleteProperty(SMIL_MAPPED_ATTR_ANIMVAL, |
|
133 SMIL_MAPPED_ATTR_STYLERULE_ATOM); |
|
134 nsIDocument* doc = mElement->GetCurrentDoc(); |
|
135 |
|
136 // Request animation restyle |
|
137 if (doc) { |
|
138 nsIPresShell* shell = doc->GetShell(); |
|
139 if (shell) { |
|
140 shell->RestyleForAnimation(mElement, eRestyle_Self); |
|
141 } |
|
142 } |
|
143 } |
|
144 |
|
145 already_AddRefed<nsIAtom> |
|
146 nsSMILMappedAttribute::GetAttrNameAtom() const |
|
147 { |
|
148 return do_GetAtom(nsCSSProps::GetStringValue(mPropID)); |
|
149 } |