1 : /* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is AnimationCommon, common animation code for transitions
16 : * and animations.
17 : *
18 : * The Initial Developer of the Original Code is the Mozilla Foundation.
19 : * Portions created by the Initial Developer are Copyright (C) 2011
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * L. David Baron <dbaron@dbaron.org>, Mozilla Corporation (original author)
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #include "AnimationCommon.h"
40 : #include "nsRuleData.h"
41 : #include "nsCSSValue.h"
42 : #include "nsStyleContext.h"
43 :
44 : namespace mozilla {
45 : namespace css {
46 :
47 0 : CommonAnimationManager::CommonAnimationManager(nsPresContext *aPresContext)
48 0 : : mPresContext(aPresContext)
49 : {
50 0 : PR_INIT_CLIST(&mElementData);
51 0 : }
52 :
53 0 : CommonAnimationManager::~CommonAnimationManager()
54 : {
55 0 : NS_ABORT_IF_FALSE(!mPresContext, "Disconnect should have been called");
56 0 : }
57 :
58 : void
59 0 : CommonAnimationManager::Disconnect()
60 : {
61 : // Content nodes might outlive the transition or animation manager.
62 0 : RemoveAllElementData();
63 :
64 0 : mPresContext = nsnull;
65 0 : }
66 :
67 : void
68 0 : CommonAnimationManager::AddElementData(CommonElementAnimationData* aData)
69 : {
70 0 : if (PR_CLIST_IS_EMPTY(&mElementData)) {
71 : // We need to observe the refresh driver.
72 0 : nsRefreshDriver *rd = mPresContext->RefreshDriver();
73 0 : rd->AddRefreshObserver(this, Flush_Style);
74 : }
75 :
76 0 : PR_INSERT_BEFORE(aData, &mElementData);
77 0 : }
78 :
79 : void
80 0 : CommonAnimationManager::ElementDataRemoved()
81 : {
82 : // If we have no transitions or animations left, remove ourselves from
83 : // the refresh driver.
84 0 : if (PR_CLIST_IS_EMPTY(&mElementData)) {
85 0 : mPresContext->RefreshDriver()->RemoveRefreshObserver(this, Flush_Style);
86 : }
87 0 : }
88 :
89 : void
90 0 : CommonAnimationManager::RemoveAllElementData()
91 : {
92 0 : while (!PR_CLIST_IS_EMPTY(&mElementData)) {
93 : CommonElementAnimationData *head =
94 0 : static_cast<CommonElementAnimationData*>(PR_LIST_HEAD(&mElementData));
95 0 : head->Destroy();
96 : }
97 0 : }
98 :
99 : /*
100 : * nsISupports implementation
101 : */
102 :
103 0 : NS_IMPL_ISUPPORTS1(CommonAnimationManager, nsIStyleRuleProcessor)
104 :
105 : nsRestyleHint
106 0 : CommonAnimationManager::HasStateDependentStyle(StateRuleProcessorData* aData)
107 : {
108 0 : return nsRestyleHint(0);
109 : }
110 :
111 : bool
112 0 : CommonAnimationManager::HasDocumentStateDependentStyle(StateRuleProcessorData* aData)
113 : {
114 0 : return false;
115 : }
116 :
117 : nsRestyleHint
118 0 : CommonAnimationManager::HasAttributeDependentStyle(AttributeRuleProcessorData* aData)
119 : {
120 0 : return nsRestyleHint(0);
121 : }
122 :
123 : /* virtual */ bool
124 0 : CommonAnimationManager::MediumFeaturesChanged(nsPresContext* aPresContext)
125 : {
126 0 : return false;
127 : }
128 :
129 : /* virtual */ size_t
130 0 : CommonAnimationManager::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
131 : {
132 : // Measurement of the following members may be added later if DMD finds it is
133 : // worthwhile:
134 : // - mElementData
135 : //
136 : // The following members are not measured
137 : // - mPresContext, because it's non-owning
138 :
139 0 : return 0;
140 : }
141 :
142 : /* virtual */ size_t
143 0 : CommonAnimationManager::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
144 : {
145 0 : return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
146 : }
147 :
148 : /* static */ bool
149 0 : CommonAnimationManager::ExtractComputedValueForTransition(
150 : nsCSSProperty aProperty,
151 : nsStyleContext* aStyleContext,
152 : nsStyleAnimation::Value& aComputedValue)
153 : {
154 : bool result =
155 : nsStyleAnimation::ExtractComputedValue(aProperty, aStyleContext,
156 0 : aComputedValue);
157 0 : if (aProperty == eCSSProperty_visibility) {
158 0 : NS_ABORT_IF_FALSE(aComputedValue.GetUnit() ==
159 : nsStyleAnimation::eUnit_Enumerated,
160 : "unexpected unit");
161 : aComputedValue.SetIntValue(aComputedValue.GetIntValue(),
162 0 : nsStyleAnimation::eUnit_Visibility);
163 : }
164 0 : return result;
165 : }
166 :
167 0 : NS_IMPL_ISUPPORTS1(AnimValuesStyleRule, nsIStyleRule)
168 :
169 : /* virtual */ void
170 0 : AnimValuesStyleRule::MapRuleInfoInto(nsRuleData* aRuleData)
171 : {
172 0 : nsStyleContext *contextParent = aRuleData->mStyleContext->GetParent();
173 0 : if (contextParent && contextParent->HasPseudoElementData()) {
174 : // Don't apply transitions or animations to things inside of
175 : // pseudo-elements.
176 : // FIXME (Bug 522599): Add tests for this.
177 0 : return;
178 : }
179 :
180 0 : for (PRUint32 i = 0, i_end = mPropertyValuePairs.Length(); i < i_end; ++i) {
181 0 : PropertyValuePair &cv = mPropertyValuePairs[i];
182 0 : if (aRuleData->mSIDs & nsCachedStyleData::GetBitForSID(
183 0 : nsCSSProps::kSIDTable[cv.mProperty]))
184 : {
185 0 : nsCSSValue *prop = aRuleData->ValueFor(cv.mProperty);
186 0 : if (prop->GetUnit() == eCSSUnit_Null) {
187 : #ifdef DEBUG
188 : bool ok =
189 : #endif
190 : nsStyleAnimation::UncomputeValue(cv.mProperty,
191 : aRuleData->mPresContext,
192 0 : cv.mValue, *prop);
193 0 : NS_ABORT_IF_FALSE(ok, "could not store computed value");
194 : }
195 : }
196 : }
197 : }
198 :
199 : #ifdef DEBUG
200 : /* virtual */ void
201 0 : AnimValuesStyleRule::List(FILE* out, PRInt32 aIndent) const
202 : {
203 : // WRITE ME?
204 0 : }
205 : #endif
206 :
207 : void
208 0 : ComputedTimingFunction::Init(const nsTimingFunction &aFunction)
209 : {
210 0 : mType = aFunction.mType;
211 0 : if (mType == nsTimingFunction::Function) {
212 : mTimingFunction.Init(aFunction.mFunc.mX1, aFunction.mFunc.mY1,
213 0 : aFunction.mFunc.mX2, aFunction.mFunc.mY2);
214 : } else {
215 0 : mSteps = aFunction.mSteps;
216 : }
217 0 : }
218 :
219 : static inline double
220 0 : StepEnd(PRUint32 aSteps, double aPortion)
221 : {
222 0 : NS_ABORT_IF_FALSE(0.0 <= aPortion && aPortion <= 1.0, "out of range");
223 0 : PRUint32 step = PRUint32(aPortion * aSteps); // floor
224 0 : return double(step) / double(aSteps);
225 : }
226 :
227 : double
228 0 : ComputedTimingFunction::GetValue(double aPortion) const
229 : {
230 0 : switch (mType) {
231 : case nsTimingFunction::Function:
232 0 : return mTimingFunction.GetSplineValue(aPortion);
233 : case nsTimingFunction::StepStart:
234 : // There are diagrams in the spec that seem to suggest this check
235 : // and the bounds point should not be symmetric with StepEnd, but
236 : // should actually step up at rather than immediately after the
237 : // fraction points. However, we rely on rounding negative values
238 : // up to zero, so we can't do that. And it's not clear the spec
239 : // really meant it.
240 0 : return 1.0 - StepEnd(mSteps, 1.0 - aPortion);
241 : default:
242 0 : NS_ABORT_IF_FALSE(false, "bad type");
243 : // fall through
244 : case nsTimingFunction::StepEnd:
245 0 : return StepEnd(mSteps, aPortion);
246 : }
247 : }
248 :
249 : }
250 : }
|