tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SVGAnimatedNumber.cpp (5402B)


      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 #include "SVGAnimatedNumber.h"
      8 
      9 #include "SMILFloatType.h"
     10 #include "SVGAttrTearoffTable.h"
     11 #include "mozilla/Attributes.h"
     12 #include "mozilla/SMILValue.h"
     13 #include "mozilla/SVGContentUtils.h"
     14 #include "nsContentUtils.h"
     15 
     16 using namespace mozilla::dom;
     17 
     18 namespace mozilla {
     19 
     20 /* Implementation */
     21 
     22 //----------------------------------------------------------------------
     23 // Helper class: AutoChangeNumberNotifier
     24 // Stack-based helper class to ensure DidChangeNumber is called.
     25 class MOZ_RAII AutoChangeNumberNotifier {
     26 public:
     27  AutoChangeNumberNotifier(SVGAnimatedNumber* aNumber, SVGElement* aSVGElement)
     28      : mNumber(aNumber), mSVGElement(aSVGElement) {
     29    MOZ_ASSERT(mNumber, "Expecting non-null number");
     30    MOZ_ASSERT(mSVGElement, "Expecting non-null element");
     31  }
     32 
     33  ~AutoChangeNumberNotifier() {
     34    mSVGElement->DidChangeNumber(mNumber->mAttrEnum);
     35    if (mNumber->mIsAnimated) {
     36      mSVGElement->AnimationNeedsResample();
     37    }
     38  }
     39 
     40 private:
     41  SVGAnimatedNumber* const mNumber;
     42  SVGElement* const mSVGElement;
     43 };
     44 
     45 constinit static SVGAttrTearoffTable<SVGAnimatedNumber,
     46                                     SVGAnimatedNumber::DOMAnimatedNumber>
     47    sSVGAnimatedNumberTearoffTable;
     48 
     49 static bool GetValueFromString(const nsAString& aString,
     50                               bool aPercentagesAllowed, float& aValue) {
     51  bool success;
     52  auto token = SVGContentUtils::GetAndEnsureOneToken(aString, success);
     53 
     54  if (!success) {
     55    return false;
     56  }
     57 
     58  nsAString::const_iterator iter, end;
     59  token.BeginReading(iter);
     60  token.EndReading(end);
     61 
     62  if (!SVGContentUtils::ParseNumber(iter, end, aValue)) {
     63    return false;
     64  }
     65 
     66  if (aPercentagesAllowed) {
     67    const nsAString& units = Substring(iter, end);
     68    if (units.EqualsLiteral("%")) {
     69      aValue /= 100;
     70      return true;
     71    }
     72  }
     73 
     74  return iter == end;
     75 }
     76 
     77 nsresult SVGAnimatedNumber::SetBaseValueString(const nsAString& aValueAsString,
     78                                               SVGElement* aSVGElement) {
     79  float val;
     80 
     81  if (!GetValueFromString(aValueAsString,
     82                          aSVGElement->NumberAttrAllowsPercentage(mAttrEnum),
     83                          val)) {
     84    return NS_ERROR_DOM_SYNTAX_ERR;
     85  }
     86 
     87  mBaseVal = val;
     88  mIsBaseSet = true;
     89  if (!mIsAnimated) {
     90    mAnimVal = mBaseVal;
     91  } else {
     92    aSVGElement->AnimationNeedsResample();
     93  }
     94 
     95  // We don't need to call DidChange* here - we're only called by
     96  // SVGElement::ParseAttribute under Element::SetAttr,
     97  // which takes care of notifying.
     98  return NS_OK;
     99 }
    100 
    101 void SVGAnimatedNumber::GetBaseValueString(nsAString& aValueAsString) {
    102  aValueAsString.Truncate();
    103  aValueAsString.AppendFloat(mBaseVal);
    104 }
    105 
    106 void SVGAnimatedNumber::SetBaseValue(float aValue, SVGElement* aSVGElement) {
    107  if (mIsBaseSet && aValue == mBaseVal) {
    108    return;
    109  }
    110 
    111  AutoChangeNumberNotifier notifier(this, aSVGElement);
    112 
    113  mBaseVal = aValue;
    114  mIsBaseSet = true;
    115  if (!mIsAnimated) {
    116    mAnimVal = mBaseVal;
    117  }
    118 }
    119 
    120 void SVGAnimatedNumber::SetAnimValue(float aValue, SVGElement* aSVGElement) {
    121  if (mIsAnimated && aValue == mAnimVal) {
    122    return;
    123  }
    124  mAnimVal = aValue;
    125  mIsAnimated = true;
    126  aSVGElement->DidAnimateNumber(mAttrEnum);
    127 }
    128 
    129 already_AddRefed<DOMSVGAnimatedNumber> SVGAnimatedNumber::ToDOMAnimatedNumber(
    130    SVGElement* aSVGElement) {
    131  RefPtr<DOMAnimatedNumber> domAnimatedNumber =
    132      sSVGAnimatedNumberTearoffTable.GetTearoff(this);
    133  if (!domAnimatedNumber) {
    134    domAnimatedNumber = new DOMAnimatedNumber(this, aSVGElement);
    135    sSVGAnimatedNumberTearoffTable.AddTearoff(this, domAnimatedNumber);
    136  }
    137 
    138  return domAnimatedNumber.forget();
    139 }
    140 
    141 SVGAnimatedNumber::DOMAnimatedNumber::~DOMAnimatedNumber() {
    142  sSVGAnimatedNumberTearoffTable.RemoveTearoff(mVal);
    143 }
    144 
    145 UniquePtr<SMILAttr> SVGAnimatedNumber::ToSMILAttr(SVGElement* aSVGElement) {
    146  return MakeUnique<SMILNumber>(this, aSVGElement);
    147 }
    148 
    149 nsresult SVGAnimatedNumber::SMILNumber::ValueFromString(
    150    const nsAString& aStr,
    151    const mozilla::dom::SVGAnimationElement* /*aSrcElement*/, SMILValue& aValue,
    152    bool& aPreventCachingOfSandwich) const {
    153  float value;
    154 
    155  if (!GetValueFromString(
    156          aStr, mSVGElement->NumberAttrAllowsPercentage(mVal->mAttrEnum),
    157          value)) {
    158    return NS_ERROR_DOM_SYNTAX_ERR;
    159  }
    160 
    161  SMILValue val(SMILFloatType::Singleton());
    162  val.mU.mDouble = value;
    163  aValue = val;
    164 
    165  return NS_OK;
    166 }
    167 
    168 SMILValue SVGAnimatedNumber::SMILNumber::GetBaseValue() const {
    169  SMILValue val(SMILFloatType::Singleton());
    170  val.mU.mDouble = mVal->mBaseVal;
    171  return val;
    172 }
    173 
    174 void SVGAnimatedNumber::SMILNumber::ClearAnimValue() {
    175  if (mVal->mIsAnimated) {
    176    mVal->mIsAnimated = false;
    177    mVal->mAnimVal = mVal->mBaseVal;
    178    mSVGElement->DidAnimateNumber(mVal->mAttrEnum);
    179  }
    180 }
    181 
    182 nsresult SVGAnimatedNumber::SMILNumber::SetAnimValue(const SMILValue& aValue) {
    183  NS_ASSERTION(aValue.mType == SMILFloatType::Singleton(),
    184               "Unexpected type to assign animated value");
    185  if (aValue.mType == SMILFloatType::Singleton()) {
    186    mVal->SetAnimValue(float(aValue.mU.mDouble), mSVGElement);
    187  }
    188  return NS_OK;
    189 }
    190 
    191 }  // namespace mozilla