1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/style/nsStyleAnimation.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,407 @@ 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 +/* Utilities for animation of computed style values */ 1.10 + 1.11 +#ifndef nsStyleAnimation_h_ 1.12 +#define nsStyleAnimation_h_ 1.13 + 1.14 +#include "nsStringFwd.h" 1.15 +#include "nsCRTGlue.h" 1.16 +#include "nsStringBuffer.h" 1.17 +#include "nsCSSProperty.h" 1.18 +#include "nsCoord.h" 1.19 +#include "nsColor.h" 1.20 +#include "nsCSSValue.h" 1.21 + 1.22 +class nsStyleContext; 1.23 +class gfx3DMatrix; 1.24 + 1.25 +namespace mozilla { 1.26 +namespace dom { 1.27 +class Element; 1.28 +} // namespace dom 1.29 +} // namespace mozilla 1.30 + 1.31 +/** 1.32 + * Utility class to handle animated style values 1.33 + */ 1.34 +class nsStyleAnimation { 1.35 +public: 1.36 + class Value; 1.37 + 1.38 + // Mathematical methods 1.39 + // -------------------- 1.40 + /** 1.41 + * Adds |aCount| copies of |aValueToAdd| to |aDest|. The result of this 1.42 + * addition is stored in aDest. 1.43 + * 1.44 + * Note that if |aCount| is 0, then |aDest| will be unchanged. Also, if 1.45 + * this method fails, then |aDest| will be unchanged. 1.46 + * 1.47 + * @param aDest The value to add to. 1.48 + * @param aValueToAdd The value to add. 1.49 + * @param aCount The number of times to add aValueToAdd. 1.50 + * @return true on success, false on failure. 1.51 + */ 1.52 + static bool Add(nsCSSProperty aProperty, Value& aDest, 1.53 + const Value& aValueToAdd, uint32_t aCount) { 1.54 + return AddWeighted(aProperty, 1.0, aDest, aCount, aValueToAdd, aDest); 1.55 + } 1.56 + 1.57 + /** 1.58 + * Calculates a measure of 'distance' between two values. 1.59 + * 1.60 + * This measure of Distance is guaranteed to be proportional to 1.61 + * portions passed to Interpolate, Add, or AddWeighted. However, for 1.62 + * some types of Value it may not produce sensible results for paced 1.63 + * animation. 1.64 + * 1.65 + * If this method succeeds, the returned distance value is guaranteed to be 1.66 + * non-negative. 1.67 + * 1.68 + * @param aStartValue The start of the interval for which the distance 1.69 + * should be calculated. 1.70 + * @param aEndValue The end of the interval for which the distance 1.71 + * should be calculated. 1.72 + * @param aDistance The result of the calculation. 1.73 + * @return true on success, false on failure. 1.74 + */ 1.75 + static bool ComputeDistance(nsCSSProperty aProperty, 1.76 + const Value& aStartValue, 1.77 + const Value& aEndValue, 1.78 + double& aDistance); 1.79 + 1.80 + /** 1.81 + * Calculates an interpolated value that is the specified |aPortion| between 1.82 + * the two given values. 1.83 + * 1.84 + * This really just does the following calculation: 1.85 + * aResultValue = (1.0 - aPortion) * aStartValue + aPortion * aEndValue 1.86 + * 1.87 + * @param aStartValue The value defining the start of the interval of 1.88 + * interpolation. 1.89 + * @param aEndValue The value defining the end of the interval of 1.90 + * interpolation. 1.91 + * @param aPortion A number in the range [0.0, 1.0] defining the 1.92 + * distance of the interpolated value in the interval. 1.93 + * @param [out] aResultValue The resulting interpolated value. 1.94 + * @return true on success, false on failure. 1.95 + */ 1.96 + static bool Interpolate(nsCSSProperty aProperty, 1.97 + const Value& aStartValue, 1.98 + const Value& aEndValue, 1.99 + double aPortion, 1.100 + Value& aResultValue) { 1.101 + return AddWeighted(aProperty, 1.0 - aPortion, aStartValue, 1.102 + aPortion, aEndValue, aResultValue); 1.103 + } 1.104 + 1.105 + /** 1.106 + * Does the calculation: 1.107 + * aResultValue = aCoeff1 * aValue1 + aCoeff2 * aValue2 1.108 + * 1.109 + * @param [out] aResultValue The resulting interpolated value. May be 1.110 + * the same as aValue1 or aValue2. 1.111 + * @return true on success, false on failure. 1.112 + * 1.113 + * NOTE: Current callers always pass aCoeff1 and aCoeff2 >= 0. They 1.114 + * are currently permitted to be negative; however, if, as we add 1.115 + * support more value types types, we find that this causes 1.116 + * difficulty, we might change this to restrict them to being 1.117 + * positive. 1.118 + */ 1.119 + static bool AddWeighted(nsCSSProperty aProperty, 1.120 + double aCoeff1, const Value& aValue1, 1.121 + double aCoeff2, const Value& aValue2, 1.122 + Value& aResultValue); 1.123 + 1.124 + // Type-conversion methods 1.125 + // ----------------------- 1.126 + /** 1.127 + * Creates a computed value for the given specified value 1.128 + * (property ID + string). A style context is needed in case the 1.129 + * specified value depends on inherited style or on the values of other 1.130 + * properties. 1.131 + * 1.132 + * @param aProperty The property whose value we're computing. 1.133 + * @param aTargetElement The content node to which our computed value is 1.134 + * applicable. 1.135 + * @param aSpecifiedValue The specified value, from which we'll build our 1.136 + * computed value. 1.137 + * @param aUseSVGMode A flag to indicate whether we should parse 1.138 + * |aSpecifiedValue| in SVG mode. 1.139 + * @param [out] aComputedValue The resulting computed value. 1.140 + * @param [out] aIsContextSensitive 1.141 + * Set to true if |aSpecifiedValue| may produce 1.142 + * a different |aComputedValue| depending on other CSS 1.143 + * properties on |aTargetElement| or its ancestors. 1.144 + * false otherwise. 1.145 + * Note that the operation of this method is 1.146 + * significantly faster when |aIsContextSensitive| is 1.147 + * nullptr. 1.148 + * @return true on success, false on failure. 1.149 + */ 1.150 + static bool ComputeValue(nsCSSProperty aProperty, 1.151 + mozilla::dom::Element* aTargetElement, 1.152 + const nsAString& aSpecifiedValue, 1.153 + bool aUseSVGMode, 1.154 + Value& aComputedValue, 1.155 + bool* aIsContextSensitive = nullptr); 1.156 + 1.157 + /** 1.158 + * Creates a specified value for the given computed value. 1.159 + * 1.160 + * The first overload fills in an nsCSSValue object; the second 1.161 + * produces a string. The nsCSSValue result may depend on objects 1.162 + * owned by the |aComputedValue| object, so users of that variant 1.163 + * must keep |aComputedValue| alive longer than |aSpecifiedValue|. 1.164 + * 1.165 + * @param aProperty The property whose value we're uncomputing. 1.166 + * @param aComputedValue The computed value to be converted. 1.167 + * @param [out] aSpecifiedValue The resulting specified value. 1.168 + * @return true on success, false on failure. 1.169 + */ 1.170 + static bool UncomputeValue(nsCSSProperty aProperty, 1.171 + const Value& aComputedValue, 1.172 + nsCSSValue& aSpecifiedValue); 1.173 + static bool UncomputeValue(nsCSSProperty aProperty, 1.174 + const Value& aComputedValue, 1.175 + nsAString& aSpecifiedValue); 1.176 + 1.177 + /** 1.178 + * Gets the computed value for the given property from the given style 1.179 + * context. 1.180 + * 1.181 + * @param aProperty The property whose value we're looking up. 1.182 + * @param aStyleContext The style context to check for the computed value. 1.183 + * @param [out] aComputedValue The resulting computed value. 1.184 + * @return true on success, false on failure. 1.185 + */ 1.186 + static bool ExtractComputedValue(nsCSSProperty aProperty, 1.187 + nsStyleContext* aStyleContext, 1.188 + Value& aComputedValue); 1.189 + 1.190 + /** 1.191 + * Interpolates between 2 matrices by decomposing them. 1.192 + * 1.193 + * @param aMatrix1 First matrix, using CSS pixel units. 1.194 + * @param aMatrix2 Second matrix, using CSS pixel units. 1.195 + * @param aProgress Interpolation value in the range [0.0, 1.0] 1.196 + */ 1.197 + static gfx3DMatrix InterpolateTransformMatrix(const gfx3DMatrix &aMatrix1, 1.198 + const gfx3DMatrix &aMatrix2, 1.199 + double aProgress); 1.200 + 1.201 + static already_AddRefed<nsCSSValue::Array> 1.202 + AppendTransformFunction(nsCSSKeyword aTransformFunction, 1.203 + nsCSSValueList**& aListTail); 1.204 + 1.205 + /** 1.206 + * The types and values for the values that we extract and animate. 1.207 + */ 1.208 + enum Unit { 1.209 + eUnit_Null, // not initialized 1.210 + eUnit_Normal, 1.211 + eUnit_Auto, 1.212 + eUnit_None, 1.213 + eUnit_Enumerated, 1.214 + eUnit_Visibility, // special case for transitions (which converts 1.215 + // Enumerated to Visibility as needed) 1.216 + eUnit_Integer, 1.217 + eUnit_Coord, 1.218 + eUnit_Percent, 1.219 + eUnit_Float, 1.220 + eUnit_Color, 1.221 + eUnit_Calc, // nsCSSValue* (never null), always with a single 1.222 + // calc() expression that's either length or length+percent 1.223 + eUnit_CSSValuePair, // nsCSSValuePair* (never null) 1.224 + eUnit_CSSValueTriplet, // nsCSSValueTriplet* (never null) 1.225 + eUnit_CSSRect, // nsCSSRect* (never null) 1.226 + eUnit_Dasharray, // nsCSSValueList* (never null) 1.227 + eUnit_Filter, // nsCSSValueList* (may be null) 1.228 + eUnit_Shadow, // nsCSSValueList* (may be null) 1.229 + eUnit_Transform, // nsCSSValueList* (never null) 1.230 + eUnit_BackgroundPosition, // nsCSSValueList* (never null) 1.231 + eUnit_CSSValuePairList, // nsCSSValuePairList* (never null) 1.232 + eUnit_UnparsedString // nsStringBuffer* (never null) 1.233 + }; 1.234 + 1.235 + class Value { 1.236 + private: 1.237 + Unit mUnit; 1.238 + union { 1.239 + int32_t mInt; 1.240 + nscoord mCoord; 1.241 + float mFloat; 1.242 + nscolor mColor; 1.243 + nsCSSValue* mCSSValue; 1.244 + nsCSSValuePair* mCSSValuePair; 1.245 + nsCSSValueTriplet* mCSSValueTriplet; 1.246 + nsCSSRect* mCSSRect; 1.247 + nsCSSValueList* mCSSValueList; 1.248 + nsCSSValueSharedList* mCSSValueSharedList; 1.249 + nsCSSValuePairList* mCSSValuePairList; 1.250 + nsStringBuffer* mString; 1.251 + } mValue; 1.252 + public: 1.253 + Unit GetUnit() const { 1.254 + NS_ASSERTION(mUnit != eUnit_Null, "uninitialized"); 1.255 + return mUnit; 1.256 + } 1.257 + 1.258 + // Accessor to let us verify assumptions about presence of null unit, 1.259 + // without tripping the assertion in GetUnit(). 1.260 + bool IsNull() const { 1.261 + return mUnit == eUnit_Null; 1.262 + } 1.263 + 1.264 + int32_t GetIntValue() const { 1.265 + NS_ASSERTION(IsIntUnit(mUnit), "unit mismatch"); 1.266 + return mValue.mInt; 1.267 + } 1.268 + nscoord GetCoordValue() const { 1.269 + NS_ASSERTION(mUnit == eUnit_Coord, "unit mismatch"); 1.270 + return mValue.mCoord; 1.271 + } 1.272 + float GetPercentValue() const { 1.273 + NS_ASSERTION(mUnit == eUnit_Percent, "unit mismatch"); 1.274 + return mValue.mFloat; 1.275 + } 1.276 + float GetFloatValue() const { 1.277 + NS_ASSERTION(mUnit == eUnit_Float, "unit mismatch"); 1.278 + return mValue.mFloat; 1.279 + } 1.280 + nscolor GetColorValue() const { 1.281 + NS_ASSERTION(mUnit == eUnit_Color, "unit mismatch"); 1.282 + return mValue.mColor; 1.283 + } 1.284 + nsCSSValue* GetCSSValueValue() const { 1.285 + NS_ASSERTION(IsCSSValueUnit(mUnit), "unit mismatch"); 1.286 + return mValue.mCSSValue; 1.287 + } 1.288 + nsCSSValuePair* GetCSSValuePairValue() const { 1.289 + NS_ASSERTION(IsCSSValuePairUnit(mUnit), "unit mismatch"); 1.290 + return mValue.mCSSValuePair; 1.291 + } 1.292 + nsCSSValueTriplet* GetCSSValueTripletValue() const { 1.293 + NS_ASSERTION(IsCSSValueTripletUnit(mUnit), "unit mismatch"); 1.294 + return mValue.mCSSValueTriplet; 1.295 + } 1.296 + nsCSSRect* GetCSSRectValue() const { 1.297 + NS_ASSERTION(IsCSSRectUnit(mUnit), "unit mismatch"); 1.298 + return mValue.mCSSRect; 1.299 + } 1.300 + nsCSSValueList* GetCSSValueListValue() const { 1.301 + NS_ASSERTION(IsCSSValueListUnit(mUnit), "unit mismatch"); 1.302 + return mValue.mCSSValueList; 1.303 + } 1.304 + nsCSSValueSharedList* GetCSSValueSharedListValue() const { 1.305 + NS_ASSERTION(IsCSSValueSharedListValue(mUnit), "unit mismatch"); 1.306 + return mValue.mCSSValueSharedList; 1.307 + } 1.308 + nsCSSValuePairList* GetCSSValuePairListValue() const { 1.309 + NS_ASSERTION(IsCSSValuePairListUnit(mUnit), "unit mismatch"); 1.310 + return mValue.mCSSValuePairList; 1.311 + } 1.312 + const char16_t* GetStringBufferValue() const { 1.313 + NS_ASSERTION(IsStringUnit(mUnit), "unit mismatch"); 1.314 + return GetBufferValue(mValue.mString); 1.315 + } 1.316 + 1.317 + void GetStringValue(nsAString& aBuffer) const { 1.318 + NS_ASSERTION(IsStringUnit(mUnit), "unit mismatch"); 1.319 + aBuffer.Truncate(); 1.320 + uint32_t len = NS_strlen(GetBufferValue(mValue.mString)); 1.321 + mValue.mString->ToString(len, aBuffer); 1.322 + } 1.323 + 1.324 + explicit Value(Unit aUnit = eUnit_Null) : mUnit(aUnit) { 1.325 + NS_ASSERTION(aUnit == eUnit_Null || aUnit == eUnit_Normal || 1.326 + aUnit == eUnit_Auto || aUnit == eUnit_None, 1.327 + "must be valueless unit"); 1.328 + } 1.329 + Value(const Value& aOther) : mUnit(eUnit_Null) { *this = aOther; } 1.330 + enum IntegerConstructorType { IntegerConstructor }; 1.331 + Value(int32_t aInt, Unit aUnit, IntegerConstructorType); 1.332 + enum CoordConstructorType { CoordConstructor }; 1.333 + Value(nscoord aLength, CoordConstructorType); 1.334 + enum PercentConstructorType { PercentConstructor }; 1.335 + Value(float aPercent, PercentConstructorType); 1.336 + enum FloatConstructorType { FloatConstructor }; 1.337 + Value(float aFloat, FloatConstructorType); 1.338 + enum ColorConstructorType { ColorConstructor }; 1.339 + Value(nscolor aColor, ColorConstructorType); 1.340 + 1.341 + ~Value() { FreeValue(); } 1.342 + 1.343 + void SetNormalValue(); 1.344 + void SetAutoValue(); 1.345 + void SetNoneValue(); 1.346 + void SetIntValue(int32_t aInt, Unit aUnit); 1.347 + void SetCoordValue(nscoord aCoord); 1.348 + void SetPercentValue(float aPercent); 1.349 + void SetFloatValue(float aFloat); 1.350 + void SetColorValue(nscolor aColor); 1.351 + void SetUnparsedStringValue(const nsString& aString); 1.352 + 1.353 + // These setters take ownership of |aValue|, and are therefore named 1.354 + // "SetAndAdopt*". 1.355 + void SetAndAdoptCSSValueValue(nsCSSValue *aValue, Unit aUnit); 1.356 + void SetAndAdoptCSSValuePairValue(nsCSSValuePair *aValue, Unit aUnit); 1.357 + void SetAndAdoptCSSValueTripletValue(nsCSSValueTriplet *aValue, Unit aUnit); 1.358 + void SetAndAdoptCSSRectValue(nsCSSRect *aValue, Unit aUnit); 1.359 + void SetAndAdoptCSSValueListValue(nsCSSValueList *aValue, Unit aUnit); 1.360 + void SetAndAdoptCSSValuePairListValue(nsCSSValuePairList *aValue); 1.361 + 1.362 + void SetTransformValue(nsCSSValueSharedList* aList); 1.363 + 1.364 + Value& operator=(const Value& aOther); 1.365 + 1.366 + bool operator==(const Value& aOther) const; 1.367 + bool operator!=(const Value& aOther) const 1.368 + { return !(*this == aOther); } 1.369 + 1.370 + private: 1.371 + void FreeValue(); 1.372 + 1.373 + static const char16_t* GetBufferValue(nsStringBuffer* aBuffer) { 1.374 + return static_cast<char16_t*>(aBuffer->Data()); 1.375 + } 1.376 + 1.377 + static bool IsIntUnit(Unit aUnit) { 1.378 + return aUnit == eUnit_Enumerated || aUnit == eUnit_Visibility || 1.379 + aUnit == eUnit_Integer; 1.380 + } 1.381 + static bool IsCSSValueUnit(Unit aUnit) { 1.382 + return aUnit == eUnit_Calc; 1.383 + } 1.384 + static bool IsCSSValuePairUnit(Unit aUnit) { 1.385 + return aUnit == eUnit_CSSValuePair; 1.386 + } 1.387 + static bool IsCSSValueTripletUnit(Unit aUnit) { 1.388 + return aUnit == eUnit_CSSValueTriplet; 1.389 + } 1.390 + static bool IsCSSRectUnit(Unit aUnit) { 1.391 + return aUnit == eUnit_CSSRect; 1.392 + } 1.393 + static bool IsCSSValueListUnit(Unit aUnit) { 1.394 + return aUnit == eUnit_Dasharray || aUnit == eUnit_Filter || 1.395 + aUnit == eUnit_Shadow || 1.396 + aUnit == eUnit_BackgroundPosition; 1.397 + } 1.398 + static bool IsCSSValueSharedListValue(Unit aUnit) { 1.399 + return aUnit == eUnit_Transform; 1.400 + } 1.401 + static bool IsCSSValuePairListUnit(Unit aUnit) { 1.402 + return aUnit == eUnit_CSSValuePairList; 1.403 + } 1.404 + static bool IsStringUnit(Unit aUnit) { 1.405 + return aUnit == eUnit_UnparsedString; 1.406 + } 1.407 + }; 1.408 +}; 1.409 + 1.410 +#endif