tor-browser

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

SVGAnimatedPreserveAspectRatio.cpp (7920B)


      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 "SVGAnimatedPreserveAspectRatio.h"
      8 
      9 #include "SMILEnumType.h"
     10 #include "SVGAttrTearoffTable.h"
     11 #include "mozAutoDocUpdate.h"
     12 #include "mozilla/Maybe.h"
     13 #include "mozilla/SMILValue.h"
     14 #include "mozilla/SVGContentUtils.h"
     15 #include "mozilla/dom/SVGAnimatedPreserveAspectRatioBinding.h"
     16 
     17 using namespace mozilla::dom;
     18 
     19 namespace mozilla {
     20 
     21 ////////////////////////////////////////////////////////////////////////
     22 // SVGAnimatedPreserveAspectRatio class
     23 NS_SVG_VAL_IMPL_CYCLE_COLLECTION_WRAPPERCACHED(
     24    DOMSVGAnimatedPreserveAspectRatio, mSVGElement)
     25 
     26 JSObject* DOMSVGAnimatedPreserveAspectRatio::WrapObject(
     27    JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
     28  return SVGAnimatedPreserveAspectRatio_Binding::Wrap(aCx, this, aGivenProto);
     29 }
     30 
     31 /* Implementation */
     32 
     33 //----------------------------------------------------------------------
     34 // Helper class: AutoChangePreserveAspectRatioNotifier
     35 // Stack-based helper class to pair calls to WillChangePreserveAspectRatio and
     36 // DidChangePreserveAspectRatio.
     37 class MOZ_RAII AutoChangePreserveAspectRatioNotifier {
     38 public:
     39  AutoChangePreserveAspectRatioNotifier(
     40      SVGAnimatedPreserveAspectRatio* aPreserveAspectRatio,
     41      SVGElement* aSVGElement, bool aDoSetAttr = true)
     42      : mPreserveAspectRatio(aPreserveAspectRatio),
     43        mSVGElement(aSVGElement),
     44        mDoSetAttr(aDoSetAttr) {
     45    MOZ_ASSERT(mPreserveAspectRatio, "Expecting non-null preserveAspectRatio");
     46    MOZ_ASSERT(mSVGElement, "Expecting non-null element");
     47    if (mDoSetAttr) {
     48      mUpdateBatch.emplace(aSVGElement->GetComposedDoc(), true);
     49      mSVGElement->WillChangePreserveAspectRatio(mUpdateBatch.ref());
     50    }
     51  }
     52 
     53  ~AutoChangePreserveAspectRatioNotifier() {
     54    if (mDoSetAttr) {
     55      mSVGElement->DidChangePreserveAspectRatio(mUpdateBatch.ref());
     56    }
     57    if (mPreserveAspectRatio->mIsAnimated) {
     58      mSVGElement->AnimationNeedsResample();
     59    }
     60  }
     61 
     62 private:
     63  SVGAnimatedPreserveAspectRatio* const mPreserveAspectRatio;
     64  SVGElement* const mSVGElement;
     65  Maybe<mozAutoDocUpdate> mUpdateBatch;
     66  bool mDoSetAttr;
     67 };
     68 
     69 constinit static SVGAttrTearoffTable<SVGAnimatedPreserveAspectRatio,
     70                                     DOMSVGAnimatedPreserveAspectRatio>
     71    sSVGAnimatedPAspectRatioTearoffTable;
     72 constinit static SVGAttrTearoffTable<SVGAnimatedPreserveAspectRatio,
     73                                     DOMSVGPreserveAspectRatio>
     74    sBaseSVGPAspectRatioTearoffTable;
     75 constinit static SVGAttrTearoffTable<SVGAnimatedPreserveAspectRatio,
     76                                     DOMSVGPreserveAspectRatio>
     77    sAnimSVGPAspectRatioTearoffTable;
     78 
     79 already_AddRefed<DOMSVGPreserveAspectRatio>
     80 DOMSVGAnimatedPreserveAspectRatio::BaseVal() {
     81  RefPtr<DOMSVGPreserveAspectRatio> domBaseVal =
     82      sBaseSVGPAspectRatioTearoffTable.GetTearoff(mVal);
     83  if (!domBaseVal) {
     84    domBaseVal = new DOMSVGPreserveAspectRatio(mVal, mSVGElement, true);
     85    sBaseSVGPAspectRatioTearoffTable.AddTearoff(mVal, domBaseVal);
     86  }
     87 
     88  return domBaseVal.forget();
     89 }
     90 
     91 DOMSVGPreserveAspectRatio::~DOMSVGPreserveAspectRatio() {
     92  if (mIsBaseValue) {
     93    sBaseSVGPAspectRatioTearoffTable.RemoveTearoff(mVal);
     94  } else {
     95    sAnimSVGPAspectRatioTearoffTable.RemoveTearoff(mVal);
     96  }
     97 }
     98 
     99 already_AddRefed<DOMSVGPreserveAspectRatio>
    100 DOMSVGAnimatedPreserveAspectRatio::AnimVal() {
    101  RefPtr<DOMSVGPreserveAspectRatio> domAnimVal =
    102      sAnimSVGPAspectRatioTearoffTable.GetTearoff(mVal);
    103  if (!domAnimVal) {
    104    domAnimVal = new DOMSVGPreserveAspectRatio(mVal, mSVGElement, false);
    105    sAnimSVGPAspectRatioTearoffTable.AddTearoff(mVal, domAnimVal);
    106  }
    107 
    108  return domAnimVal.forget();
    109 }
    110 
    111 nsresult SVGAnimatedPreserveAspectRatio::SetBaseValueString(
    112    const nsAString& aValueAsString, SVGElement* aSVGElement, bool aDoSetAttr) {
    113  SVGPreserveAspectRatio val;
    114  nsresult res = SVGPreserveAspectRatio::FromString(aValueAsString, &val);
    115  if (NS_FAILED(res)) {
    116    return res;
    117  }
    118 
    119  AutoChangePreserveAspectRatioNotifier notifier(this, aSVGElement, aDoSetAttr);
    120 
    121  mBaseVal = val;
    122  mIsBaseSet = true;
    123  if (!mIsAnimated) {
    124    mAnimVal = mBaseVal;
    125  }
    126 
    127  return NS_OK;
    128 }
    129 
    130 void SVGAnimatedPreserveAspectRatio::GetBaseValueString(
    131    nsAString& aValueAsString) const {
    132  mBaseVal.ToString(aValueAsString);
    133 }
    134 
    135 void SVGAnimatedPreserveAspectRatio::SetBaseValue(
    136    const SVGPreserveAspectRatio& aValue, SVGElement* aSVGElement) {
    137  if (mIsBaseSet && mBaseVal == aValue) {
    138    return;
    139  }
    140 
    141  AutoChangePreserveAspectRatioNotifier notifier(this, aSVGElement);
    142 
    143  mBaseVal = aValue;
    144  mIsBaseSet = true;
    145  if (!mIsAnimated) {
    146    mAnimVal = mBaseVal;
    147  }
    148 }
    149 
    150 static uint64_t PackPreserveAspectRatio(const SVGPreserveAspectRatio& par) {
    151  // All preserveAspectRatio values are enum values (do not interpolate), so we
    152  // can safely collate them and treat them as a single enum as for SMIL.
    153  uint64_t packed = 0;
    154  packed |= uint64_t(par.GetAlign()) << 8;
    155  packed |= uint64_t(par.GetMeetOrSlice());
    156  return packed;
    157 }
    158 
    159 void SVGAnimatedPreserveAspectRatio::SetAnimValue(uint64_t aPackedValue,
    160                                                  SVGElement* aSVGElement) {
    161  if (mIsAnimated && PackPreserveAspectRatio(mAnimVal) == aPackedValue) {
    162    return;
    163  }
    164  mAnimVal.SetAlign(uint16_t((aPackedValue & 0xff00) >> 8));
    165  mAnimVal.SetMeetOrSlice(uint16_t(aPackedValue & 0xff));
    166  mIsAnimated = true;
    167  aSVGElement->DidAnimatePreserveAspectRatio();
    168 }
    169 
    170 already_AddRefed<DOMSVGAnimatedPreserveAspectRatio>
    171 SVGAnimatedPreserveAspectRatio::ToDOMAnimatedPreserveAspectRatio(
    172    SVGElement* aSVGElement) {
    173  RefPtr<DOMSVGAnimatedPreserveAspectRatio> domAnimatedPAspectRatio =
    174      sSVGAnimatedPAspectRatioTearoffTable.GetTearoff(this);
    175  if (!domAnimatedPAspectRatio) {
    176    domAnimatedPAspectRatio =
    177        new DOMSVGAnimatedPreserveAspectRatio(this, aSVGElement);
    178    sSVGAnimatedPAspectRatioTearoffTable.AddTearoff(this,
    179                                                    domAnimatedPAspectRatio);
    180  }
    181  return domAnimatedPAspectRatio.forget();
    182 }
    183 
    184 DOMSVGAnimatedPreserveAspectRatio::~DOMSVGAnimatedPreserveAspectRatio() {
    185  sSVGAnimatedPAspectRatioTearoffTable.RemoveTearoff(mVal);
    186 }
    187 
    188 UniquePtr<SMILAttr> SVGAnimatedPreserveAspectRatio::ToSMILAttr(
    189    SVGElement* aSVGElement) {
    190  return MakeUnique<SMILPreserveAspectRatio>(this, aSVGElement);
    191 }
    192 
    193 // typedef for inner class, to make function signatures shorter below:
    194 using SMILPreserveAspectRatio =
    195    SVGAnimatedPreserveAspectRatio::SMILPreserveAspectRatio;
    196 
    197 nsresult SMILPreserveAspectRatio::ValueFromString(
    198    const nsAString& aStr, const SVGAnimationElement* /*aSrcElement*/,
    199    SMILValue& aValue, bool& aPreventCachingOfSandwich) const {
    200  SVGPreserveAspectRatio par;
    201  nsresult res = SVGPreserveAspectRatio::FromString(aStr, &par);
    202  NS_ENSURE_SUCCESS(res, res);
    203 
    204  SMILValue val(SMILEnumType::Singleton());
    205  val.mU.mUint = PackPreserveAspectRatio(par);
    206  aValue = val;
    207  return NS_OK;
    208 }
    209 
    210 SMILValue SMILPreserveAspectRatio::GetBaseValue() const {
    211  SMILValue val(SMILEnumType::Singleton());
    212  val.mU.mUint = PackPreserveAspectRatio(mVal->GetBaseValue());
    213  return val;
    214 }
    215 
    216 void SMILPreserveAspectRatio::ClearAnimValue() {
    217  if (mVal->mIsAnimated) {
    218    mVal->mIsAnimated = false;
    219    mVal->mAnimVal = mVal->mBaseVal;
    220    mSVGElement->DidAnimatePreserveAspectRatio();
    221  }
    222 }
    223 
    224 nsresult SMILPreserveAspectRatio::SetAnimValue(const SMILValue& aValue) {
    225  NS_ASSERTION(aValue.mType == SMILEnumType::Singleton(),
    226               "Unexpected type to assign animated value");
    227  if (aValue.mType == SMILEnumType::Singleton()) {
    228    mVal->SetAnimValue(aValue.mU.mUint, mSVGElement);
    229  }
    230  return NS_OK;
    231 }
    232 
    233 }  // namespace mozilla