michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef NS_ISMILTYPE_H_ michael@0: #define NS_ISMILTYPE_H_ michael@0: michael@0: #include "mozilla/Attributes.h" michael@0: #include "nscore.h" michael@0: michael@0: class nsSMILValue; michael@0: michael@0: ////////////////////////////////////////////////////////////////////////////// michael@0: // nsISMILType: Interface for defining the basic operations needed for animating michael@0: // a particular kind of data (e.g. lengths, colors, transformation matrices). michael@0: // michael@0: // This interface is never used directly but always through an nsSMILValue that michael@0: // bundles together a pointer to a concrete implementation of this interface and michael@0: // the data upon which it should operate. michael@0: // michael@0: // We keep the data and type separate rather than just providing different michael@0: // subclasses of nsSMILValue. This is so that sizeof(nsSMILValue) is the same michael@0: // for all value types, allowing us to have a type-agnostic nsTArray of michael@0: // nsSMILValue objects (actual objects, not pointers). It also allows most michael@0: // nsSMILValues (except those that need to allocate extra memory for their michael@0: // data) to be allocated on the stack and directly assigned to one another michael@0: // provided performance benefits for the animation code. michael@0: // michael@0: // Note that different types have different capabilities. Roughly speaking there michael@0: // are probably three main types: michael@0: // michael@0: // +---------------------+---------------+-------------+------------------+ michael@0: // | CATEGORY: | DISCRETE | LINEAR | ADDITIVE | michael@0: // +---------------------+---------------+-------------+------------------+ michael@0: // | Example: | strings, | path data? | lengths, | michael@0: // | | color k/words?| | RGB color values | michael@0: // | | | | | michael@0: // | -- Assign? | X | X | X | michael@0: // | -- Add? | - | X? | X | michael@0: // | -- SandwichAdd? | - | -? | X | michael@0: // | -- ComputeDistance? | - | - | X? | michael@0: // | -- Interpolate? | - | X | X | michael@0: // +---------------------+---------------+-------------+------------------+ michael@0: // michael@0: michael@0: class nsISMILType michael@0: { michael@0: /** michael@0: * Only give the nsSMILValue class access to this interface. michael@0: */ michael@0: friend class nsSMILValue; michael@0: michael@0: protected: michael@0: /** michael@0: * Initialises aValue and sets it to some identity value such that adding michael@0: * aValue to another value of the same type has no effect. michael@0: * michael@0: * @pre aValue.IsNull() michael@0: * @post aValue.mType == this michael@0: */ michael@0: virtual void Init(nsSMILValue& aValue) const = 0; michael@0: michael@0: /** michael@0: * Destroys any data associated with a value of this type. michael@0: * michael@0: * @pre aValue.mType == this michael@0: * @post aValue.IsNull() michael@0: */ michael@0: virtual void Destroy(nsSMILValue& aValue) const = 0; michael@0: michael@0: /** michael@0: * Assign this object the value of another. Think of this as the assignment michael@0: * operator. michael@0: * michael@0: * @param aDest The left-hand side of the assignment. michael@0: * @param aSrc The right-hand side of the assignment. michael@0: * @return NS_OK on success, an error code on failure such as when the michael@0: * underlying type of the specified object differs. michael@0: * michael@0: * @pre aDest.mType == aSrc.mType == this michael@0: */ michael@0: virtual nsresult Assign(nsSMILValue& aDest, michael@0: const nsSMILValue& aSrc) const = 0; michael@0: michael@0: /** michael@0: * Test two nsSMILValue objects (of this nsISMILType) for equality. michael@0: * michael@0: * A return value of true represents a guarantee that aLeft and aRight are michael@0: * equal. (That is, they would behave identically if passed to the methods michael@0: * Add, SandwichAdd, ComputeDistance, and Interpolate). michael@0: * michael@0: * A return value of false simply indicates that we make no guarantee michael@0: * about equality. michael@0: * michael@0: * NOTE: It's perfectly legal for implementations of this method to return michael@0: * false in all cases. However, smarter implementations will make this michael@0: * method more useful for optimization. michael@0: * michael@0: * @param aLeft The left-hand side of the equality check. michael@0: * @param aRight The right-hand side of the equality check. michael@0: * @return true if we're sure the values are equal, false otherwise. michael@0: * michael@0: * @pre aDest.mType == aSrc.mType == this michael@0: */ michael@0: virtual bool IsEqual(const nsSMILValue& aLeft, michael@0: const nsSMILValue& aRight) const = 0; michael@0: michael@0: /** michael@0: * Adds two values. michael@0: * michael@0: * The count parameter facilitates repetition. michael@0: * michael@0: * By equation, michael@0: * michael@0: * aDest += aValueToAdd * aCount michael@0: * michael@0: * Therefore, if aCount == 0, aDest will be unaltered. michael@0: * michael@0: * This method will fail if this data type is not additive or the value was michael@0: * not specified using an additive syntax. michael@0: * michael@0: * See SVG 1.1, section 19.2.5. In particular, michael@0: * michael@0: * "If a given attribute or property can take values of keywords (which are michael@0: * not additive) or numeric values (which are additive), then additive michael@0: * animations are possible if the subsequent animation uses a numeric value michael@0: * even if the base animation uses a keyword value; however, if the michael@0: * subsequent animation uses a keyword value, additive animation is not michael@0: * possible." michael@0: * michael@0: * If this method fails (e.g. because the data type is not additive), aDest michael@0: * will be unaltered. michael@0: * michael@0: * @param aDest The value to add to. michael@0: * @param aValueToAdd The value to add. michael@0: * @param aCount The number of times to add aValueToAdd. michael@0: * @return NS_OK on success, an error code on failure. michael@0: * michael@0: * @pre aValueToAdd.mType == aDest.mType == this michael@0: */ michael@0: virtual nsresult Add(nsSMILValue& aDest, michael@0: const nsSMILValue& aValueToAdd, michael@0: uint32_t aCount) const = 0; michael@0: michael@0: /** michael@0: * Adds aValueToAdd to the underlying value in the animation sandwich, aDest. michael@0: * michael@0: * For most types this operation is identical to a regular Add() but for some michael@0: * types (notably ) the operation differs. For michael@0: * Add() corresponds to simply adding together the michael@0: * transform parameters and is used when calculating cumulative values or michael@0: * by-animation values. On the other hand SandwichAdd() is used when adding to michael@0: * the underlying value and requires matrix post-multiplication. (This michael@0: * distinction is most clearly indicated by the SVGT1.2 test suite. It is not michael@0: * obvious within the SMIL specifications.) michael@0: * michael@0: * @param aDest The value to add to. michael@0: * @param aValueToAdd The value to add. michael@0: * @return NS_OK on success, an error code on failure. michael@0: * michael@0: * @pre aValueToAdd.mType == aDest.mType == this michael@0: */ michael@0: virtual nsresult SandwichAdd(nsSMILValue& aDest, michael@0: const nsSMILValue& aValueToAdd) const michael@0: { michael@0: return Add(aDest, aValueToAdd, 1); michael@0: } michael@0: michael@0: /** michael@0: * Calculates the 'distance' between two values. This is the distance used in michael@0: * paced interpolation. michael@0: * michael@0: * @param aFrom The start of the interval for which the distance should michael@0: * be calculated. michael@0: * @param aTo The end of the interval for which the distance should be michael@0: * calculated. michael@0: * @param aDistance The result of the calculation. michael@0: * @return NS_OK on success, or an appropriate error code if there is no michael@0: * notion of distance for the underlying data type or the distance michael@0: * could not be calculated. michael@0: * michael@0: * @pre aFrom.mType == aTo.mType == this michael@0: */ michael@0: virtual nsresult ComputeDistance(const nsSMILValue& aFrom, michael@0: const nsSMILValue& aTo, michael@0: double& aDistance) const = 0; michael@0: michael@0: /** michael@0: * Calculates an interpolated value between two values using the specified michael@0: * proportion. michael@0: * michael@0: * @param aStartVal The value defining the start of the interval of michael@0: * interpolation. michael@0: * @param aEndVal The value defining the end of the interval of michael@0: * interpolation. michael@0: * @param aUnitDistance A number between 0.0 and 1.0 (inclusive) defining michael@0: * the distance of the interpolated value in the michael@0: * interval. michael@0: * @param aResult The interpolated value. michael@0: * @return NS_OK on success, NS_ERROR_FAILURE if this data type cannot be michael@0: * interpolated or NS_ERROR_OUT_OF_MEMORY if insufficient memory was michael@0: * available for storing the result. michael@0: * michael@0: * @pre aStartVal.mType == aEndVal.mType == aResult.mType == this michael@0: */ michael@0: virtual nsresult Interpolate(const nsSMILValue& aStartVal, michael@0: const nsSMILValue& aEndVal, michael@0: double aUnitDistance, michael@0: nsSMILValue& aResult) const = 0; michael@0: }; michael@0: michael@0: #endif // NS_ISMILTYPE_H_