1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef DOM_SMIL_SMILTYPE_H_
8 #define DOM_SMIL_SMILTYPE_H_
9 
10 #include "mozilla/Attributes.h"
11 #include "nscore.h"
12 
13 namespace mozilla {
14 
15 class SMILValue;
16 
17 //////////////////////////////////////////////////////////////////////////////
18 // SMILType: Interface for defining the basic operations needed for animating
19 // a particular kind of data (e.g. lengths, colors, transformation matrices).
20 //
21 // This interface is never used directly but always through a SMILValue that
22 // bundles together a pointer to a concrete implementation of this interface and
23 // the data upon which it should operate.
24 //
25 // We keep the data and type separate rather than just providing different
26 // subclasses of SMILValue. This is so that sizeof(SMILValue) is the same
27 // for all value types, allowing us to have a type-agnostic nsTArray of
28 // SMILValue objects (actual objects, not pointers). It also allows most
29 // SMILValues (except those that need to allocate extra memory for their
30 // data) to be allocated on the stack and directly assigned to one another
31 // provided performance benefits for the animation code.
32 //
33 // Note that different types have different capabilities. Roughly speaking there
34 // are probably three main types:
35 //
36 // +---------------------+---------------+-------------+------------------+
37 // | CATEGORY:           | DISCRETE      | LINEAR      | ADDITIVE         |
38 // +---------------------+---------------+-------------+------------------+
39 // | Example:            | strings,      | path data?  | lengths,         |
40 // |                     | color k/words?|             | RGB color values |
41 // |                     |               |             |                  |
42 // | -- Assign?          |     X         |    X        |    X             |
43 // | -- Add?             |     -         |    X?       |    X             |
44 // | -- SandwichAdd?     |     -         |    -?       |    X             |
45 // | -- ComputeDistance? |     -         |    -        |    X?            |
46 // | -- Interpolate?     |     -         |    X        |    X             |
47 // +---------------------+---------------+-------------+------------------+
48 //
49 
50 class SMILType {
51   /**
52    * Only give the SMILValue class access to this interface.
53    */
54   friend class SMILValue;
55 
56  protected:
57   /**
58    * Initialises aValue and sets it to some identity value such that adding
59    * aValue to another value of the same type has no effect.
60    *
61    * @pre  aValue.IsNull()
62    * @post aValue.mType == this
63    */
64   virtual void Init(SMILValue& aValue) const = 0;
65 
66   /**
67    * Destroys any data associated with a value of this type.
68    *
69    * @pre  aValue.mType == this
70    * @post aValue.IsNull()
71    */
72   virtual void Destroy(SMILValue& aValue) const = 0;
73 
74   /**
75    * Assign this object the value of another. Think of this as the assignment
76    * operator.
77    *
78    * @param   aDest       The left-hand side of the assignment.
79    * @param   aSrc        The right-hand side of the assignment.
80    * @return  NS_OK on success, an error code on failure such as when the
81    *          underlying type of the specified object differs.
82    *
83    * @pre aDest.mType == aSrc.mType == this
84    */
85   virtual nsresult Assign(SMILValue& aDest, const SMILValue& aSrc) const = 0;
86 
87   /**
88    * Test two SMILValue objects (of this SMILType) for equality.
89    *
90    * A return value of true represents a guarantee that aLeft and aRight are
91    * equal. (That is, they would behave identically if passed to the methods
92    * Add, SandwichAdd, ComputeDistance, and Interpolate).
93    *
94    * A return value of false simply indicates that we make no guarantee
95    * about equality.
96    *
97    * NOTE: It's perfectly legal for implementations of this method to return
98    * false in all cases.  However, smarter implementations will make this
99    * method more useful for optimization.
100    *
101    * @param   aLeft       The left-hand side of the equality check.
102    * @param   aRight      The right-hand side of the equality check.
103    * @return  true if we're sure the values are equal, false otherwise.
104    *
105    * @pre aDest.mType == aSrc.mType == this
106    */
107   virtual bool IsEqual(const SMILValue& aLeft,
108                        const SMILValue& aRight) const = 0;
109 
110   /**
111    * Adds two values.
112    *
113    * The count parameter facilitates repetition.
114    *
115    * By equation,
116    *
117    *   aDest += aValueToAdd * aCount
118    *
119    * Therefore, if aCount == 0, aDest will be unaltered.
120    *
121    * This method will fail if this data type is not additive or the value was
122    * not specified using an additive syntax.
123    *
124    * See SVG 1.1, section 19.2.5. In particular,
125    *
126    *   "If a given attribute or property can take values of keywords (which are
127    *   not additive) or numeric values (which are additive), then additive
128    *   animations are possible if the subsequent animation uses a numeric value
129    *   even if the base animation uses a keyword value; however, if the
130    *   subsequent animation uses a keyword value, additive animation is not
131    *   possible."
132    *
133    * If this method fails (e.g. because the data type is not additive), aDest
134    * will be unaltered.
135    *
136    * @param   aDest       The value to add to.
137    * @param   aValueToAdd The value to add.
138    * @param   aCount      The number of times to add aValueToAdd.
139    * @return  NS_OK on success, an error code on failure.
140    *
141    * @pre aValueToAdd.mType == aDest.mType == this
142    */
143   virtual nsresult Add(SMILValue& aDest, const SMILValue& aValueToAdd,
144                        uint32_t aCount) const = 0;
145 
146   /**
147    * Adds aValueToAdd to the underlying value in the animation sandwich, aDest.
148    *
149    * For most types this operation is identical to a regular Add() but for some
150    * types (notably <animateTransform>) the operation differs. For
151    * <animateTransform> Add() corresponds to simply adding together the
152    * transform parameters and is used when calculating cumulative values or
153    * by-animation values. On the other hand SandwichAdd() is used when adding to
154    * the underlying value and requires matrix post-multiplication. (This
155    * distinction is most clearly indicated by the SVGT1.2 test suite. It is not
156    * obvious within the SMIL specifications.)
157    *
158    * @param   aDest       The value to add to.
159    * @param   aValueToAdd The value to add.
160    * @return  NS_OK on success, an error code on failure.
161    *
162    * @pre aValueToAdd.mType == aDest.mType == this
163    */
SandwichAdd(SMILValue & aDest,const SMILValue & aValueToAdd)164   virtual nsresult SandwichAdd(SMILValue& aDest,
165                                const SMILValue& aValueToAdd) const {
166     return Add(aDest, aValueToAdd, 1);
167   }
168 
169   /**
170    * Calculates the 'distance' between two values. This is the distance used in
171    * paced interpolation.
172    *
173    * @param   aFrom     The start of the interval for which the distance should
174    *                    be calculated.
175    * @param   aTo       The end of the interval for which the distance should be
176    *                    calculated.
177    * @param   aDistance The result of the calculation.
178    * @return  NS_OK on success, or an appropriate error code if there is no
179    *          notion of distance for the underlying data type or the distance
180    *          could not be calculated.
181    *
182    * @pre aFrom.mType == aTo.mType == this
183    */
184   virtual nsresult ComputeDistance(const SMILValue& aFrom, const SMILValue& aTo,
185                                    double& aDistance) const = 0;
186 
187   /**
188    * Calculates an interpolated value between two values using the specified
189    * proportion.
190    *
191    * @param   aStartVal     The value defining the start of the interval of
192    *                        interpolation.
193    * @param   aEndVal       The value defining the end of the interval of
194    *                        interpolation.
195    * @param   aUnitDistance A number between 0.0 and 1.0 (inclusive) defining
196    *                        the distance of the interpolated value in the
197    *                        interval.
198    * @param   aResult       The interpolated value.
199    * @return  NS_OK on success, NS_ERROR_FAILURE if this data type cannot be
200    *          interpolated or NS_ERROR_OUT_OF_MEMORY if insufficient memory was
201    *          available for storing the result.
202    *
203    * @pre aStartVal.mType == aEndVal.mType == aResult.mType == this
204    */
205   virtual nsresult Interpolate(const SMILValue& aStartVal,
206                                const SMILValue& aEndVal, double aUnitDistance,
207                                SMILValue& aResult) const = 0;
208 };
209 
210 }  // namespace mozilla
211 
212 #endif  // DOM_SMIL_SMILTYPE_H_
213