tor-browser

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

SVGAnimatedEnumeration.cpp (6220B)


      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 "SVGAnimatedEnumeration.h"
      8 
      9 #include "SMILEnumType.h"
     10 #include "SVGAttrTearoffTable.h"
     11 #include "mozilla/SMILValue.h"
     12 #include "mozilla/dom/SVGElement.h"
     13 #include "nsAtom.h"
     14 #include "nsError.h"
     15 
     16 using namespace mozilla::dom;
     17 
     18 namespace mozilla {
     19 
     20 //----------------------------------------------------------------------
     21 // Helper class: AutoChangeEnumNotifier
     22 // Stack-based helper class to ensure DidChangeEnum is called.
     23 class MOZ_RAII AutoChangeEnumNotifier {
     24 public:
     25  AutoChangeEnumNotifier(SVGAnimatedEnumeration* aEnum, SVGElement* aSVGElement,
     26                         bool aDoSetAttr = true)
     27      : mEnum(aEnum), mSVGElement(aSVGElement), mDoSetAttr(aDoSetAttr) {
     28    MOZ_ASSERT(mEnum, "Expecting non-null enum");
     29    MOZ_ASSERT(mSVGElement, "Expecting non-null element");
     30  }
     31 
     32  ~AutoChangeEnumNotifier() {
     33    if (mDoSetAttr) {
     34      mSVGElement->DidChangeEnum(mEnum->mAttrEnum);
     35    }
     36    if (mEnum->mIsAnimated) {
     37      mSVGElement->AnimationNeedsResample();
     38    }
     39  }
     40 
     41 private:
     42  SVGAnimatedEnumeration* const mEnum;
     43  SVGElement* const mSVGElement;
     44  bool mDoSetAttr;
     45 };
     46 
     47 constinit static SVGAttrTearoffTable<SVGAnimatedEnumeration,
     48                                     SVGAnimatedEnumeration::DOMAnimatedEnum>
     49    sSVGAnimatedEnumTearoffTable;
     50 
     51 const SVGEnumMapping* SVGAnimatedEnumeration::GetMapping(
     52    SVGElement* aSVGElement) {
     53  SVGElement::EnumAttributesInfo info = aSVGElement->GetEnumInfo();
     54 
     55  NS_ASSERTION(info.mCount > 0 && mAttrEnum < info.mCount,
     56               "mapping request for a non-attrib enum");
     57 
     58  return info.mInfos[mAttrEnum].mMapping;
     59 }
     60 
     61 bool SVGAnimatedEnumeration::SetBaseValueAtom(const nsAtom* aValue,
     62                                              SVGElement* aSVGElement) {
     63  const SVGEnumMapping* mapping = GetMapping(aSVGElement);
     64 
     65  while (mapping && mapping->mKey) {
     66    if (aValue == mapping->mKey) {
     67      if (!mIsBaseSet || mBaseVal != mapping->mVal) {
     68        mIsBaseSet = true;
     69        // We don't need to call DidChange* here - we're only called by
     70        // SVGElement::ParseAttribute under Element::SetAttr,
     71        // which takes care of notifying.
     72        AutoChangeEnumNotifier notifier(this, aSVGElement, false);
     73 
     74        mBaseVal = mapping->mVal;
     75        if (!mIsAnimated) {
     76          mAnimVal = mBaseVal;
     77        }
     78      }
     79      return true;
     80    }
     81    mapping++;
     82  }
     83 
     84  return false;
     85 }
     86 
     87 nsAtom* SVGAnimatedEnumeration::GetBaseValueAtom(SVGElement* aSVGElement) {
     88  const SVGEnumMapping* mapping = GetMapping(aSVGElement);
     89 
     90  while (mapping && mapping->mKey) {
     91    if (mBaseVal == mapping->mVal) {
     92      return mapping->mKey;
     93    }
     94    mapping++;
     95  }
     96  NS_ERROR("unknown enumeration value");
     97  return nsGkAtoms::_empty;
     98 }
     99 
    100 void SVGAnimatedEnumeration::SetBaseValue(uint16_t aValue,
    101                                          SVGElement* aSVGElement,
    102                                          ErrorResult& aRv) {
    103  const SVGEnumMapping* mapping = GetMapping(aSVGElement);
    104 
    105  while (mapping && mapping->mKey) {
    106    if (mapping->mVal == aValue) {
    107      if (!mIsBaseSet || mBaseVal != uint8_t(aValue)) {
    108        mIsBaseSet = true;
    109        AutoChangeEnumNotifier notifier(this, aSVGElement);
    110 
    111        mBaseVal = uint8_t(aValue);
    112        if (!mIsAnimated) {
    113          mAnimVal = mBaseVal;
    114        }
    115      }
    116      return;
    117    }
    118    mapping++;
    119  }
    120  return aRv.ThrowTypeError("Invalid SVGAnimatedEnumeration base value");
    121 }
    122 
    123 void SVGAnimatedEnumeration::SetAnimValue(uint16_t aValue,
    124                                          SVGElement* aSVGElement) {
    125  if (mIsAnimated && aValue == mAnimVal) {
    126    return;
    127  }
    128  mAnimVal = aValue;
    129  mIsAnimated = true;
    130  aSVGElement->DidAnimateEnum(mAttrEnum);
    131 }
    132 
    133 already_AddRefed<DOMSVGAnimatedEnumeration>
    134 SVGAnimatedEnumeration::ToDOMAnimatedEnum(SVGElement* aSVGElement) {
    135  RefPtr<DOMAnimatedEnum> domAnimatedEnum =
    136      sSVGAnimatedEnumTearoffTable.GetTearoff(this);
    137  if (!domAnimatedEnum) {
    138    domAnimatedEnum = new DOMAnimatedEnum(this, aSVGElement);
    139    sSVGAnimatedEnumTearoffTable.AddTearoff(this, domAnimatedEnum);
    140  }
    141 
    142  return domAnimatedEnum.forget();
    143 }
    144 
    145 SVGAnimatedEnumeration::DOMAnimatedEnum::~DOMAnimatedEnum() {
    146  sSVGAnimatedEnumTearoffTable.RemoveTearoff(mVal);
    147 }
    148 
    149 UniquePtr<SMILAttr> SVGAnimatedEnumeration::ToSMILAttr(
    150    SVGElement* aSVGElement) {
    151  return MakeUnique<SMILEnum>(this, aSVGElement);
    152 }
    153 
    154 nsresult SVGAnimatedEnumeration::SMILEnum::ValueFromString(
    155    const nsAString& aStr, const SVGAnimationElement* /*aSrcElement*/,
    156    SMILValue& aValue, bool& aPreventCachingOfSandwich) const {
    157  nsAtom* valAtom = NS_GetStaticAtom(aStr);
    158  if (valAtom) {
    159    const SVGEnumMapping* mapping = mVal->GetMapping(mSVGElement);
    160 
    161    while (mapping && mapping->mKey) {
    162      if (valAtom == mapping->mKey) {
    163        SMILValue val(SMILEnumType::Singleton());
    164        val.mU.mUint = mapping->mVal;
    165        aValue = val;
    166        return NS_OK;
    167      }
    168      mapping++;
    169    }
    170  }
    171 
    172  // only a warning since authors may mistype attribute values
    173  NS_WARNING("unknown enumeration key");
    174  return NS_ERROR_FAILURE;
    175 }
    176 
    177 SMILValue SVGAnimatedEnumeration::SMILEnum::GetBaseValue() const {
    178  SMILValue val(SMILEnumType::Singleton());
    179  val.mU.mUint = mVal->mBaseVal;
    180  return val;
    181 }
    182 
    183 void SVGAnimatedEnumeration::SMILEnum::ClearAnimValue() {
    184  if (mVal->mIsAnimated) {
    185    mVal->mIsAnimated = false;
    186    mVal->mAnimVal = mVal->mBaseVal;
    187    mSVGElement->DidAnimateEnum(mVal->mAttrEnum);
    188  }
    189 }
    190 
    191 nsresult SVGAnimatedEnumeration::SMILEnum::SetAnimValue(
    192    const SMILValue& aValue) {
    193  NS_ASSERTION(aValue.mType == SMILEnumType::Singleton(),
    194               "Unexpected type to assign animated value");
    195  if (aValue.mType == SMILEnumType::Singleton()) {
    196    MOZ_ASSERT(aValue.mU.mUint <= USHRT_MAX,
    197               "Very large enumerated value - too big for uint16_t");
    198    mVal->SetAnimValue(uint16_t(aValue.mU.mUint), mSVGElement);
    199  }
    200  return NS_OK;
    201 }
    202 
    203 }  // namespace mozilla