forked from mirrors/gecko-dev
Currently SMILAnimationFunction::ParseAttr only sets its aPreventCachingOfSandwich outparam when it needs to be set to true. (This lets us pass the same initially-false outparam into ParseAttr multiple times, and then check it for trueness at the end to see if any of the parsed values need us to prevent caching the sandwich.) Our impls for ISMILAttr::ValueFromString should behave like that, too. Then, we can pass ParseAttr's outparam directly to ValueFromString. Differential Revision: https://phabricator.services.mozilla.com/D174353
185 lines
5.1 KiB
C++
185 lines
5.1 KiB
C++
/* -*- 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/. */
|
|
|
|
#include "SVGAnimatedBoolean.h"
|
|
|
|
#include "DOMSVGAnimatedBoolean.h"
|
|
#include "nsError.h"
|
|
#include "SMILBoolType.h"
|
|
#include "SVGAttrTearoffTable.h"
|
|
#include "mozilla/SMILValue.h"
|
|
|
|
using namespace mozilla::dom;
|
|
|
|
namespace mozilla {
|
|
|
|
/* Implementation */
|
|
|
|
//----------------------------------------------------------------------
|
|
// Helper class: AutoChangeBooleanNotifier
|
|
// Stack-based helper class to ensure DidChangeBoolean is called.
|
|
class MOZ_RAII AutoChangeBooleanNotifier {
|
|
public:
|
|
AutoChangeBooleanNotifier(SVGAnimatedBoolean* aBoolean,
|
|
SVGElement* aSVGElement, bool aDoSetAttr = true)
|
|
: mBoolean(aBoolean), mSVGElement(aSVGElement), mDoSetAttr(aDoSetAttr) {
|
|
MOZ_ASSERT(mBoolean, "Expecting non-null boolean");
|
|
MOZ_ASSERT(mSVGElement, "Expecting non-null element");
|
|
}
|
|
|
|
~AutoChangeBooleanNotifier() {
|
|
if (mDoSetAttr) {
|
|
mSVGElement->DidChangeBoolean(mBoolean->mAttrEnum);
|
|
}
|
|
if (mBoolean->mIsAnimated) {
|
|
mSVGElement->AnimationNeedsResample();
|
|
}
|
|
}
|
|
|
|
private:
|
|
SVGAnimatedBoolean* const mBoolean;
|
|
SVGElement* const mSVGElement;
|
|
bool mDoSetAttr;
|
|
};
|
|
|
|
static inline SVGAttrTearoffTable<SVGAnimatedBoolean, DOMSVGAnimatedBoolean>&
|
|
SVGAnimatedBooleanTearoffTable() {
|
|
static SVGAttrTearoffTable<SVGAnimatedBoolean, DOMSVGAnimatedBoolean>
|
|
sSVGAnimatedBooleanTearoffTable;
|
|
return sSVGAnimatedBooleanTearoffTable;
|
|
}
|
|
|
|
static bool GetValueFromString(const nsAString& aValueAsString, bool& aValue) {
|
|
if (aValueAsString.EqualsLiteral("true")) {
|
|
aValue = true;
|
|
return true;
|
|
}
|
|
if (aValueAsString.EqualsLiteral("false")) {
|
|
aValue = false;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static nsresult GetValueFromAtom(const nsAtom* aValueAsAtom, bool* aValue) {
|
|
if (aValueAsAtom == nsGkAtoms::_true) {
|
|
*aValue = true;
|
|
return NS_OK;
|
|
}
|
|
if (aValueAsAtom == nsGkAtoms::_false) {
|
|
*aValue = false;
|
|
return NS_OK;
|
|
}
|
|
return NS_ERROR_DOM_SYNTAX_ERR;
|
|
}
|
|
|
|
nsresult SVGAnimatedBoolean::SetBaseValueAtom(const nsAtom* aValue,
|
|
SVGElement* aSVGElement) {
|
|
bool val = false;
|
|
|
|
nsresult rv = GetValueFromAtom(aValue, &val);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
// We don't need to call DidChange* here - we're only called by
|
|
// SVGElement::ParseAttribute under Element::SetAttr,
|
|
// which takes care of notifying.
|
|
AutoChangeBooleanNotifier notifier(this, aSVGElement, false);
|
|
|
|
mBaseVal = val;
|
|
if (!mIsAnimated) {
|
|
mAnimVal = mBaseVal;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsAtom* SVGAnimatedBoolean::GetBaseValueAtom() const {
|
|
return mBaseVal ? nsGkAtoms::_true : nsGkAtoms::_false;
|
|
}
|
|
|
|
void SVGAnimatedBoolean::SetBaseValue(bool aValue, SVGElement* aSVGElement) {
|
|
if (aValue == mBaseVal) {
|
|
return;
|
|
}
|
|
|
|
AutoChangeBooleanNotifier notifier(this, aSVGElement);
|
|
|
|
mBaseVal = aValue;
|
|
if (!mIsAnimated) {
|
|
mAnimVal = mBaseVal;
|
|
}
|
|
}
|
|
|
|
void SVGAnimatedBoolean::SetAnimValue(bool aValue, SVGElement* aSVGElement) {
|
|
if (mIsAnimated && mAnimVal == aValue) {
|
|
return;
|
|
}
|
|
mAnimVal = aValue;
|
|
mIsAnimated = true;
|
|
aSVGElement->DidAnimateBoolean(mAttrEnum);
|
|
}
|
|
|
|
already_AddRefed<DOMSVGAnimatedBoolean>
|
|
SVGAnimatedBoolean::ToDOMAnimatedBoolean(SVGElement* aSVGElement) {
|
|
RefPtr<DOMSVGAnimatedBoolean> domAnimatedBoolean =
|
|
SVGAnimatedBooleanTearoffTable().GetTearoff(this);
|
|
if (!domAnimatedBoolean) {
|
|
domAnimatedBoolean = new DOMSVGAnimatedBoolean(this, aSVGElement);
|
|
SVGAnimatedBooleanTearoffTable().AddTearoff(this, domAnimatedBoolean);
|
|
}
|
|
|
|
return domAnimatedBoolean.forget();
|
|
}
|
|
|
|
DOMSVGAnimatedBoolean::~DOMSVGAnimatedBoolean() {
|
|
SVGAnimatedBooleanTearoffTable().RemoveTearoff(mVal);
|
|
}
|
|
|
|
UniquePtr<SMILAttr> SVGAnimatedBoolean::ToSMILAttr(SVGElement* aSVGElement) {
|
|
return MakeUnique<SMILBool>(this, aSVGElement);
|
|
}
|
|
|
|
nsresult SVGAnimatedBoolean::SMILBool::ValueFromString(
|
|
const nsAString& aStr, const SVGAnimationElement* /*aSrcElement*/,
|
|
SMILValue& aValue, bool& aPreventCachingOfSandwich) const {
|
|
bool value;
|
|
if (!GetValueFromString(aStr, value)) {
|
|
return NS_ERROR_DOM_SYNTAX_ERR;
|
|
}
|
|
|
|
SMILValue val(SMILBoolType::Singleton());
|
|
val.mU.mBool = value;
|
|
aValue = val;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
SMILValue SVGAnimatedBoolean::SMILBool::GetBaseValue() const {
|
|
SMILValue val(SMILBoolType::Singleton());
|
|
val.mU.mBool = mVal->mBaseVal;
|
|
return val;
|
|
}
|
|
|
|
void SVGAnimatedBoolean::SMILBool::ClearAnimValue() {
|
|
if (mVal->mIsAnimated) {
|
|
mVal->mIsAnimated = false;
|
|
mVal->mAnimVal = mVal->mBaseVal;
|
|
mSVGElement->DidAnimateBoolean(mVal->mAttrEnum);
|
|
}
|
|
}
|
|
|
|
nsresult SVGAnimatedBoolean::SMILBool::SetAnimValue(const SMILValue& aValue) {
|
|
NS_ASSERTION(aValue.mType == SMILBoolType::Singleton(),
|
|
"Unexpected type to assign animated value");
|
|
if (aValue.mType == SMILBoolType::Singleton()) {
|
|
mVal->SetAnimValue(uint16_t(aValue.mU.mBool), mSVGElement);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
} // namespace mozilla
|