Source code

Revision control

Copy as Markdown

Other Tools

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