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
168 lines
4.9 KiB
C++
168 lines
4.9 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 "SVGAnimatedInteger.h"
|
|
|
|
#include "nsError.h"
|
|
#include "SMILIntegerType.h"
|
|
#include "SVGAttrTearoffTable.h"
|
|
#include "mozilla/SMILValue.h"
|
|
#include "mozilla/SVGContentUtils.h"
|
|
|
|
using namespace mozilla::dom;
|
|
|
|
namespace mozilla {
|
|
|
|
/* Implementation */
|
|
|
|
//----------------------------------------------------------------------
|
|
// Helper class: AutoChangeIntegerNotifier
|
|
// Stack-based helper class ensure DidChangeInteger is called.
|
|
class MOZ_RAII AutoChangeIntegerNotifier {
|
|
public:
|
|
AutoChangeIntegerNotifier(SVGAnimatedInteger* aInteger,
|
|
SVGElement* aSVGElement, bool aDoSetAttr = true)
|
|
: mInteger(aInteger), mSVGElement(aSVGElement), mDoSetAttr(aDoSetAttr) {
|
|
MOZ_ASSERT(mInteger, "Expecting non-null integer");
|
|
MOZ_ASSERT(mSVGElement, "Expecting non-null element");
|
|
}
|
|
|
|
~AutoChangeIntegerNotifier() {
|
|
if (mDoSetAttr) {
|
|
mSVGElement->DidChangeInteger(mInteger->mAttrEnum);
|
|
}
|
|
if (mInteger->mIsAnimated) {
|
|
mSVGElement->AnimationNeedsResample();
|
|
}
|
|
}
|
|
|
|
private:
|
|
SVGAnimatedInteger* const mInteger;
|
|
SVGElement* const mSVGElement;
|
|
bool mDoSetAttr;
|
|
};
|
|
|
|
static SVGAttrTearoffTable<SVGAnimatedInteger,
|
|
SVGAnimatedInteger::DOMAnimatedInteger>
|
|
sSVGAnimatedIntegerTearoffTable;
|
|
|
|
nsresult SVGAnimatedInteger::SetBaseValueString(const nsAString& aValueAsString,
|
|
SVGElement* aSVGElement) {
|
|
bool success;
|
|
auto token = SVGContentUtils::GetAndEnsureOneToken(aValueAsString, success);
|
|
|
|
if (!success) {
|
|
return NS_ERROR_DOM_SYNTAX_ERR;
|
|
}
|
|
|
|
int32_t value;
|
|
|
|
if (!SVGContentUtils::ParseInteger(token, value)) {
|
|
return NS_ERROR_DOM_SYNTAX_ERR;
|
|
}
|
|
|
|
AutoChangeIntegerNotifier notifier(this, aSVGElement, false);
|
|
|
|
mIsBaseSet = true;
|
|
mBaseVal = value;
|
|
if (!mIsAnimated) {
|
|
mAnimVal = mBaseVal;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
void SVGAnimatedInteger::GetBaseValueString(nsAString& aValueAsString) {
|
|
aValueAsString.Truncate();
|
|
aValueAsString.AppendInt(mBaseVal);
|
|
}
|
|
|
|
void SVGAnimatedInteger::SetBaseValue(int aValue, SVGElement* aSVGElement) {
|
|
// We can't just rely on SetParsedAttrValue (as called by DidChangeInteger)
|
|
// detecting redundant changes since it will compare false if the existing
|
|
// attribute value has an associated serialized version (a string value) even
|
|
// if the integers match due to the way integers are stored in nsAttrValue.
|
|
if (aValue == mBaseVal && mIsBaseSet) {
|
|
return;
|
|
}
|
|
|
|
AutoChangeIntegerNotifier notifier(this, aSVGElement);
|
|
|
|
mBaseVal = aValue;
|
|
mIsBaseSet = true;
|
|
if (!mIsAnimated) {
|
|
mAnimVal = mBaseVal;
|
|
}
|
|
}
|
|
|
|
void SVGAnimatedInteger::SetAnimValue(int aValue, SVGElement* aSVGElement) {
|
|
if (mIsAnimated && aValue == mAnimVal) {
|
|
return;
|
|
}
|
|
mAnimVal = aValue;
|
|
mIsAnimated = true;
|
|
aSVGElement->DidAnimateInteger(mAttrEnum);
|
|
}
|
|
|
|
already_AddRefed<DOMSVGAnimatedInteger>
|
|
SVGAnimatedInteger::ToDOMAnimatedInteger(SVGElement* aSVGElement) {
|
|
RefPtr<DOMAnimatedInteger> domAnimatedInteger =
|
|
sSVGAnimatedIntegerTearoffTable.GetTearoff(this);
|
|
if (!domAnimatedInteger) {
|
|
domAnimatedInteger = new DOMAnimatedInteger(this, aSVGElement);
|
|
sSVGAnimatedIntegerTearoffTable.AddTearoff(this, domAnimatedInteger);
|
|
}
|
|
|
|
return domAnimatedInteger.forget();
|
|
}
|
|
|
|
SVGAnimatedInteger::DOMAnimatedInteger::~DOMAnimatedInteger() {
|
|
sSVGAnimatedIntegerTearoffTable.RemoveTearoff(mVal);
|
|
}
|
|
|
|
UniquePtr<SMILAttr> SVGAnimatedInteger::ToSMILAttr(SVGElement* aSVGElement) {
|
|
return MakeUnique<SMILInteger>(this, aSVGElement);
|
|
}
|
|
|
|
nsresult SVGAnimatedInteger::SMILInteger::ValueFromString(
|
|
const nsAString& aStr, const dom::SVGAnimationElement* /*aSrcElement*/,
|
|
SMILValue& aValue, bool& aPreventCachingOfSandwich) const {
|
|
int32_t val;
|
|
|
|
if (!SVGContentUtils::ParseInteger(aStr, val)) {
|
|
return NS_ERROR_DOM_SYNTAX_ERR;
|
|
}
|
|
|
|
SMILValue smilVal(SMILIntegerType::Singleton());
|
|
smilVal.mU.mInt = val;
|
|
aValue = smilVal;
|
|
return NS_OK;
|
|
}
|
|
|
|
SMILValue SVGAnimatedInteger::SMILInteger::GetBaseValue() const {
|
|
SMILValue val(SMILIntegerType::Singleton());
|
|
val.mU.mInt = mVal->mBaseVal;
|
|
return val;
|
|
}
|
|
|
|
void SVGAnimatedInteger::SMILInteger::ClearAnimValue() {
|
|
if (mVal->mIsAnimated) {
|
|
mVal->mIsAnimated = false;
|
|
mVal->mAnimVal = mVal->mBaseVal;
|
|
mSVGElement->DidAnimateInteger(mVal->mAttrEnum);
|
|
}
|
|
}
|
|
|
|
nsresult SVGAnimatedInteger::SMILInteger::SetAnimValue(
|
|
const SMILValue& aValue) {
|
|
NS_ASSERTION(aValue.mType == SMILIntegerType::Singleton(),
|
|
"Unexpected type to assign animated value");
|
|
if (aValue.mType == SMILIntegerType::Singleton()) {
|
|
mVal->SetAnimValue(int(aValue.mU.mInt), mSVGElement);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
} // namespace mozilla
|