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/. */
7 #include "SVGAnimatedPreserveAspectRatio.h"
9 #include "mozAutoDocUpdate.h"
10 #include "mozilla/ArrayUtils.h"
11 #include "mozilla/Maybe.h"
12 #include "mozilla/SMILValue.h"
13 #include "mozilla/SVGContentUtils.h"
14 #include "mozilla/dom/SVGAnimatedPreserveAspectRatioBinding.h"
15 #include "SMILEnumType.h"
16 #include "SVGAttrTearoffTable.h"
18 using namespace mozilla::dom
;
22 ////////////////////////////////////////////////////////////////////////
23 // SVGAnimatedPreserveAspectRatio class
24 NS_SVG_VAL_IMPL_CYCLE_COLLECTION_WRAPPERCACHED(
25 DOMSVGAnimatedPreserveAspectRatio
, mSVGElement
)
27 JSObject
* DOMSVGAnimatedPreserveAspectRatio::WrapObject(
28 JSContext
* aCx
, JS::Handle
<JSObject
*> aGivenProto
) {
29 return SVGAnimatedPreserveAspectRatio_Binding::Wrap(aCx
, this, aGivenProto
);
34 //----------------------------------------------------------------------
35 // Helper class: AutoChangePreserveAspectRatioNotifier
36 // Stack-based helper class to pair calls to WillChangePreserveAspectRatio and
37 // DidChangePreserveAspectRatio.
38 class MOZ_RAII AutoChangePreserveAspectRatioNotifier
{
40 AutoChangePreserveAspectRatioNotifier(
41 SVGAnimatedPreserveAspectRatio
* aPreserveAspectRatio
,
42 SVGElement
* aSVGElement
, bool aDoSetAttr
= true)
43 : mPreserveAspectRatio(aPreserveAspectRatio
),
44 mSVGElement(aSVGElement
),
45 mDoSetAttr(aDoSetAttr
) {
46 MOZ_ASSERT(mPreserveAspectRatio
, "Expecting non-null preserveAspectRatio");
47 MOZ_ASSERT(mSVGElement
, "Expecting non-null element");
49 mUpdateBatch
.emplace(aSVGElement
->GetComposedDoc(), true);
51 mSVGElement
->WillChangePreserveAspectRatio(mUpdateBatch
.ref());
55 ~AutoChangePreserveAspectRatioNotifier() {
57 mSVGElement
->DidChangePreserveAspectRatio(mEmptyOrOldValue
,
60 if (mPreserveAspectRatio
->mIsAnimated
) {
61 mSVGElement
->AnimationNeedsResample();
66 SVGAnimatedPreserveAspectRatio
* const mPreserveAspectRatio
;
67 SVGElement
* const mSVGElement
;
68 Maybe
<mozAutoDocUpdate
> mUpdateBatch
;
69 nsAttrValue mEmptyOrOldValue
;
73 MOZ_CONSTINIT
static SVGAttrTearoffTable
<SVGAnimatedPreserveAspectRatio
,
74 DOMSVGAnimatedPreserveAspectRatio
>
75 sSVGAnimatedPAspectRatioTearoffTable
;
76 MOZ_CONSTINIT
static SVGAttrTearoffTable
<SVGAnimatedPreserveAspectRatio
,
77 DOMSVGPreserveAspectRatio
>
78 sBaseSVGPAspectRatioTearoffTable
;
79 MOZ_CONSTINIT
static SVGAttrTearoffTable
<SVGAnimatedPreserveAspectRatio
,
80 DOMSVGPreserveAspectRatio
>
81 sAnimSVGPAspectRatioTearoffTable
;
83 already_AddRefed
<DOMSVGPreserveAspectRatio
>
84 DOMSVGAnimatedPreserveAspectRatio::BaseVal() {
85 RefPtr
<DOMSVGPreserveAspectRatio
> domBaseVal
=
86 sBaseSVGPAspectRatioTearoffTable
.GetTearoff(mVal
);
88 domBaseVal
= new DOMSVGPreserveAspectRatio(mVal
, mSVGElement
, true);
89 sBaseSVGPAspectRatioTearoffTable
.AddTearoff(mVal
, domBaseVal
);
92 return domBaseVal
.forget();
95 DOMSVGPreserveAspectRatio::~DOMSVGPreserveAspectRatio() {
97 sBaseSVGPAspectRatioTearoffTable
.RemoveTearoff(mVal
);
99 sAnimSVGPAspectRatioTearoffTable
.RemoveTearoff(mVal
);
103 already_AddRefed
<DOMSVGPreserveAspectRatio
>
104 DOMSVGAnimatedPreserveAspectRatio::AnimVal() {
105 RefPtr
<DOMSVGPreserveAspectRatio
> domAnimVal
=
106 sAnimSVGPAspectRatioTearoffTable
.GetTearoff(mVal
);
108 domAnimVal
= new DOMSVGPreserveAspectRatio(mVal
, mSVGElement
, false);
109 sAnimSVGPAspectRatioTearoffTable
.AddTearoff(mVal
, domAnimVal
);
112 return domAnimVal
.forget();
115 nsresult
SVGAnimatedPreserveAspectRatio::SetBaseValueString(
116 const nsAString
& aValueAsString
, SVGElement
* aSVGElement
, bool aDoSetAttr
) {
117 SVGPreserveAspectRatio val
;
118 nsresult res
= SVGPreserveAspectRatio::FromString(aValueAsString
, &val
);
119 if (NS_FAILED(res
)) {
123 AutoChangePreserveAspectRatioNotifier
notifier(this, aSVGElement
, aDoSetAttr
);
134 void SVGAnimatedPreserveAspectRatio::GetBaseValueString(
135 nsAString
& aValueAsString
) const {
136 mBaseVal
.ToString(aValueAsString
);
139 void SVGAnimatedPreserveAspectRatio::SetBaseValue(
140 const SVGPreserveAspectRatio
& aValue
, SVGElement
* aSVGElement
) {
141 if (mIsBaseSet
&& mBaseVal
== aValue
) {
145 AutoChangePreserveAspectRatioNotifier
notifier(this, aSVGElement
);
154 static uint64_t PackPreserveAspectRatio(const SVGPreserveAspectRatio
& par
) {
155 // All preserveAspectRatio values are enum values (do not interpolate), so we
156 // can safely collate them and treat them as a single enum as for SMIL.
158 packed
|= uint64_t(par
.GetAlign()) << 8;
159 packed
|= uint64_t(par
.GetMeetOrSlice());
163 void SVGAnimatedPreserveAspectRatio::SetAnimValue(uint64_t aPackedValue
,
164 SVGElement
* aSVGElement
) {
165 if (mIsAnimated
&& PackPreserveAspectRatio(mAnimVal
) == aPackedValue
) {
168 mAnimVal
.SetAlign(uint16_t((aPackedValue
& 0xff00) >> 8));
169 mAnimVal
.SetMeetOrSlice(uint16_t(aPackedValue
& 0xff));
171 aSVGElement
->DidAnimatePreserveAspectRatio();
174 already_AddRefed
<DOMSVGAnimatedPreserveAspectRatio
>
175 SVGAnimatedPreserveAspectRatio::ToDOMAnimatedPreserveAspectRatio(
176 SVGElement
* aSVGElement
) {
177 RefPtr
<DOMSVGAnimatedPreserveAspectRatio
> domAnimatedPAspectRatio
=
178 sSVGAnimatedPAspectRatioTearoffTable
.GetTearoff(this);
179 if (!domAnimatedPAspectRatio
) {
180 domAnimatedPAspectRatio
=
181 new DOMSVGAnimatedPreserveAspectRatio(this, aSVGElement
);
182 sSVGAnimatedPAspectRatioTearoffTable
.AddTearoff(this,
183 domAnimatedPAspectRatio
);
185 return domAnimatedPAspectRatio
.forget();
188 DOMSVGAnimatedPreserveAspectRatio::~DOMSVGAnimatedPreserveAspectRatio() {
189 sSVGAnimatedPAspectRatioTearoffTable
.RemoveTearoff(mVal
);
192 UniquePtr
<SMILAttr
> SVGAnimatedPreserveAspectRatio::ToSMILAttr(
193 SVGElement
* aSVGElement
) {
194 return MakeUnique
<SMILPreserveAspectRatio
>(this, aSVGElement
);
197 // typedef for inner class, to make function signatures shorter below:
198 using SMILPreserveAspectRatio
=
199 SVGAnimatedPreserveAspectRatio::SMILPreserveAspectRatio
;
201 nsresult
SMILPreserveAspectRatio::ValueFromString(
202 const nsAString
& aStr
, const SVGAnimationElement
* /*aSrcElement*/,
203 SMILValue
& aValue
, bool& aPreventCachingOfSandwich
) const {
204 SVGPreserveAspectRatio par
;
205 nsresult res
= SVGPreserveAspectRatio::FromString(aStr
, &par
);
206 NS_ENSURE_SUCCESS(res
, res
);
208 SMILValue
val(SMILEnumType::Singleton());
209 val
.mU
.mUint
= PackPreserveAspectRatio(par
);
214 SMILValue
SMILPreserveAspectRatio::GetBaseValue() const {
215 SMILValue
val(SMILEnumType::Singleton());
216 val
.mU
.mUint
= PackPreserveAspectRatio(mVal
->GetBaseValue());
220 void SMILPreserveAspectRatio::ClearAnimValue() {
221 if (mVal
->mIsAnimated
) {
222 mVal
->mIsAnimated
= false;
223 mVal
->mAnimVal
= mVal
->mBaseVal
;
224 mSVGElement
->DidAnimatePreserveAspectRatio();
228 nsresult
SMILPreserveAspectRatio::SetAnimValue(const SMILValue
& aValue
) {
229 NS_ASSERTION(aValue
.mType
== SMILEnumType::Singleton(),
230 "Unexpected type to assign animated value");
231 if (aValue
.mType
== SMILEnumType::Singleton()) {
232 mVal
->SetAnimValue(aValue
.mU
.mUint
, mSVGElement
);
237 } // namespace mozilla