|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include "nsSMILValue.h" |
|
7 #include "nsDebug.h" |
|
8 #include <string.h> |
|
9 |
|
10 //---------------------------------------------------------------------- |
|
11 // Public methods |
|
12 |
|
13 nsSMILValue::nsSMILValue(const nsISMILType* aType) |
|
14 : mType(nsSMILNullType::Singleton()) |
|
15 { |
|
16 if (!aType) { |
|
17 NS_ERROR("Trying to construct nsSMILValue with null mType pointer"); |
|
18 return; |
|
19 } |
|
20 |
|
21 InitAndCheckPostcondition(aType); |
|
22 } |
|
23 |
|
24 nsSMILValue::nsSMILValue(const nsSMILValue& aVal) |
|
25 : mType(nsSMILNullType::Singleton()) |
|
26 { |
|
27 InitAndCheckPostcondition(aVal.mType); |
|
28 mType->Assign(*this, aVal); |
|
29 } |
|
30 |
|
31 const nsSMILValue& |
|
32 nsSMILValue::operator=(const nsSMILValue& aVal) |
|
33 { |
|
34 if (&aVal == this) |
|
35 return *this; |
|
36 |
|
37 if (mType != aVal.mType) { |
|
38 DestroyAndReinit(aVal.mType); |
|
39 } |
|
40 |
|
41 mType->Assign(*this, aVal); |
|
42 |
|
43 return *this; |
|
44 } |
|
45 |
|
46 bool |
|
47 nsSMILValue::operator==(const nsSMILValue& aVal) const |
|
48 { |
|
49 if (&aVal == this) |
|
50 return true; |
|
51 |
|
52 return mType == aVal.mType && mType->IsEqual(*this, aVal); |
|
53 } |
|
54 |
|
55 void |
|
56 nsSMILValue::Swap(nsSMILValue& aOther) |
|
57 { |
|
58 nsSMILValue tmp; |
|
59 memcpy(&tmp, &aOther, sizeof(nsSMILValue)); // tmp = aOther |
|
60 memcpy(&aOther, this, sizeof(nsSMILValue)); // aOther = this |
|
61 memcpy(this, &tmp, sizeof(nsSMILValue)); // this = tmp |
|
62 |
|
63 // |tmp| is about to die -- we need to clear its mType, so that its |
|
64 // destructor doesn't muck with the data we just transferred out of it. |
|
65 tmp.mType = nsSMILNullType::Singleton(); |
|
66 } |
|
67 |
|
68 nsresult |
|
69 nsSMILValue::Add(const nsSMILValue& aValueToAdd, uint32_t aCount) |
|
70 { |
|
71 if (aValueToAdd.mType != mType) { |
|
72 NS_ERROR("Trying to add incompatible types"); |
|
73 return NS_ERROR_FAILURE; |
|
74 } |
|
75 |
|
76 return mType->Add(*this, aValueToAdd, aCount); |
|
77 } |
|
78 |
|
79 nsresult |
|
80 nsSMILValue::SandwichAdd(const nsSMILValue& aValueToAdd) |
|
81 { |
|
82 if (aValueToAdd.mType != mType) { |
|
83 NS_ERROR("Trying to add incompatible types"); |
|
84 return NS_ERROR_FAILURE; |
|
85 } |
|
86 |
|
87 return mType->SandwichAdd(*this, aValueToAdd); |
|
88 } |
|
89 |
|
90 nsresult |
|
91 nsSMILValue::ComputeDistance(const nsSMILValue& aTo, double& aDistance) const |
|
92 { |
|
93 if (aTo.mType != mType) { |
|
94 NS_ERROR("Trying to calculate distance between incompatible types"); |
|
95 return NS_ERROR_FAILURE; |
|
96 } |
|
97 |
|
98 return mType->ComputeDistance(*this, aTo, aDistance); |
|
99 } |
|
100 |
|
101 nsresult |
|
102 nsSMILValue::Interpolate(const nsSMILValue& aEndVal, |
|
103 double aUnitDistance, |
|
104 nsSMILValue& aResult) const |
|
105 { |
|
106 if (aEndVal.mType != mType) { |
|
107 NS_ERROR("Trying to interpolate between incompatible types"); |
|
108 return NS_ERROR_FAILURE; |
|
109 } |
|
110 |
|
111 if (aResult.mType != mType) { |
|
112 // Outparam has wrong type |
|
113 aResult.DestroyAndReinit(mType); |
|
114 } |
|
115 |
|
116 return mType->Interpolate(*this, aEndVal, aUnitDistance, aResult); |
|
117 } |
|
118 |
|
119 //---------------------------------------------------------------------- |
|
120 // Helper methods |
|
121 |
|
122 // Wrappers for nsISMILType::Init & ::Destroy that verify their postconditions |
|
123 void |
|
124 nsSMILValue::InitAndCheckPostcondition(const nsISMILType* aNewType) |
|
125 { |
|
126 aNewType->Init(*this); |
|
127 NS_ABORT_IF_FALSE(mType == aNewType, |
|
128 "Post-condition of Init failed. nsSMILValue is invalid"); |
|
129 } |
|
130 |
|
131 void |
|
132 nsSMILValue::DestroyAndCheckPostcondition() |
|
133 { |
|
134 mType->Destroy(*this); |
|
135 NS_ABORT_IF_FALSE(IsNull(), "Post-condition of Destroy failed. " |
|
136 "nsSMILValue not null after destroying"); |
|
137 } |
|
138 |
|
139 void |
|
140 nsSMILValue::DestroyAndReinit(const nsISMILType* aNewType) |
|
141 { |
|
142 DestroyAndCheckPostcondition(); |
|
143 InitAndCheckPostcondition(aNewType); |
|
144 } |