tor-browser

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

DOMSVGPoint.cpp (6879B)


      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 "DOMSVGPoint.h"
      8 
      9 #include "DOMSVGPointList.h"
     10 #include "gfx2DGlue.h"
     11 #include "mozilla/dom/DOMMatrix.h"
     12 #include "mozilla/dom/SVGPointBinding.h"
     13 #include "nsError.h"
     14 
     15 // See the architecture comment in DOMSVGPointList.h.
     16 
     17 using namespace mozilla::gfx;
     18 
     19 namespace mozilla::dom {
     20 
     21 //----------------------------------------------------------------------
     22 // Helper class: AutoChangePointNotifier
     23 //
     24 class MOZ_RAII AutoChangePointNotifier {
     25 public:
     26  explicit AutoChangePointNotifier(DOMSVGPoint* aValue) : mValue(aValue) {
     27    MOZ_ASSERT(mValue, "Expecting non-null value");
     28  }
     29 
     30  ~AutoChangePointNotifier() {
     31    if (mValue->IsTranslatePoint()) {
     32      mValue->DidChangeTranslate();
     33    }
     34  }
     35 
     36 private:
     37  DOMSVGPoint* const mValue;
     38 };
     39 
     40 constinit static SVGAttrTearoffTable<SVGPoint, DOMSVGPoint>
     41    sSVGTranslateTearOffTable;
     42 
     43 // We could use NS_IMPL_CYCLE_COLLECTION(, except that in Unlink() we need to
     44 // clear our list's weak ref to us to be safe. (The other option would be to
     45 // not unlink and rely on the breaking of the other edges in the cycle, as
     46 // NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
     47 NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGPoint)
     48 
     49 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGPoint)
     50  tmp->CleanupWeakRefs();
     51  NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
     52  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
     53 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     54 
     55 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGPoint)
     56  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
     57 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     58 
     59 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGPoint)
     60  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
     61 NS_IMPL_CYCLE_COLLECTION_TRACE_END
     62 
     63 JSObject* DOMSVGPoint::WrapObject(JSContext* aCx,
     64                                  JS::Handle<JSObject*> aGivenProto) {
     65  return SVGPoint_Binding::Wrap(aCx, this, aGivenProto);
     66 }
     67 
     68 float DOMSVGPoint::X() {
     69  if (mIsAnimValItem && IsInList()) {
     70    Element()->FlushAnimations();  // May make IsInList() == false
     71  }
     72  return InternalItem().mX;
     73 }
     74 
     75 void DOMSVGPoint::SetX(float aX, ErrorResult& aRv) {
     76  if (mIsAnimValItem) {
     77    aRv.ThrowNoModificationAllowedError("Animated values cannot be set");
     78    return;
     79  }
     80 
     81  auto& val = InternalItem();
     82 
     83  if (val.mX == aX) {
     84    return;
     85  }
     86 
     87  AutoChangePointListNotifier listNotifier(this);
     88  AutoChangePointNotifier translateNotifier(this);
     89 
     90  val.mX = aX;
     91 }
     92 
     93 float DOMSVGPoint::Y() {
     94  if (mIsAnimValItem && IsInList()) {
     95    Element()->FlushAnimations();  // May make IsInList() == false
     96  }
     97  return InternalItem().mY;
     98 }
     99 
    100 void DOMSVGPoint::SetY(float aY, ErrorResult& aRv) {
    101  if (mIsAnimValItem) {
    102    aRv.ThrowNoModificationAllowedError("Animated values cannot be set");
    103    return;
    104  }
    105  auto& val = InternalItem();
    106 
    107  if (val.mY == aY) {
    108    return;
    109  }
    110 
    111  AutoChangePointListNotifier listNotifier(this);
    112  AutoChangePointNotifier translateNotifier(this);
    113 
    114  val.mY = aY;
    115 }
    116 
    117 already_AddRefed<DOMSVGPoint> DOMSVGPoint::MatrixTransform(
    118    const DOMMatrix2DInit& aMatrix, ErrorResult& aRv) {
    119  auto matrix2D = DOMMatrixReadOnly::ToValidatedMatrixDouble(aMatrix, aRv);
    120  if (aRv.Failed()) {
    121    return nullptr;
    122  }
    123  if (!matrix2D.IsFinite()) {
    124    aRv.ThrowTypeError<MSG_NOT_FINITE>("MatrixTransform matrix");
    125    return nullptr;
    126  }
    127  auto pt = matrix2D.TransformPoint(InternalItem());
    128  return do_AddRef(new DOMSVGPoint(ToPoint(pt)));
    129 }
    130 
    131 void DOMSVGPoint::InsertingIntoList(DOMSVGPointList* aList, uint32_t aListIndex,
    132                                    bool aIsAnimValItem) {
    133  MOZ_RELEASE_ASSERT(!IsInList(), "Inserting item that is already in a list");
    134  MOZ_RELEASE_ASSERT(!mIsTranslatePoint,
    135                     "Inserting item that is a currentTranslate");
    136 
    137  delete mVal;
    138  mVal = nullptr;
    139 
    140  mOwner = aList;
    141  mListIndex = aListIndex;
    142  mIsAnimValItem = aIsAnimValItem;
    143 
    144  MOZ_ASSERT(IndexIsValid(), "Bad index for DOMSVGPoint!");
    145 }
    146 
    147 void DOMSVGPoint::RemovingFromList() {
    148  MOZ_ASSERT(
    149      IsInList(),
    150      "We should start in a list if we're going to be removed from one.");
    151  mVal = new SVGPoint(InternalItem());
    152  mOwner = nullptr;
    153  mIsAnimValItem = false;
    154 }
    155 
    156 SVGPoint& DOMSVGPoint::InternalItem() {
    157  if (nsCOMPtr<DOMSVGPointList> pointList = do_QueryInterface(mOwner)) {
    158    return pointList->InternalList().mItems[mListIndex];
    159  }
    160  return *mVal;
    161 }
    162 
    163 already_AddRefed<DOMSVGPoint> DOMSVGPoint::GetTranslateTearOff(
    164    SVGPoint* aVal, SVGSVGElement* aSVGSVGElement) {
    165  RefPtr<DOMSVGPoint> domPoint = sSVGTranslateTearOffTable.GetTearoff(aVal);
    166  if (!domPoint) {
    167    domPoint = new DOMSVGPoint(aVal, aSVGSVGElement);
    168    sSVGTranslateTearOffTable.AddTearoff(aVal, domPoint);
    169    domPoint->mIsInTearoffTable = true;
    170  }
    171 
    172  return domPoint.forget();
    173 }
    174 
    175 bool DOMSVGPoint::AttrIsAnimating() const {
    176  nsCOMPtr<DOMSVGPointList> pointList = do_QueryInterface(mOwner);
    177  return pointList && pointList->AttrIsAnimating();
    178 }
    179 
    180 void DOMSVGPoint::DidChangeTranslate() {
    181  nsCOMPtr<SVGSVGElement> svg = do_QueryInterface(mOwner);
    182  MOZ_ASSERT(svg);
    183  nsContentUtils::AddScriptRunner(
    184      NewRunnableMethod("dom::SVGSVGElement::DidChangeTranslate", svg,
    185                        &SVGSVGElement::DidChangeTranslate));
    186 }
    187 
    188 SVGElement* DOMSVGPoint::Element() {
    189  if (nsCOMPtr<DOMSVGPointList> pointList = do_QueryInterface(mOwner)) {
    190    return pointList->Element();
    191  }
    192  nsCOMPtr<SVGSVGElement> svg = do_QueryInterface(mOwner);
    193  return svg;
    194 }
    195 
    196 void DOMSVGPoint::CleanupWeakRefs() {
    197  // Our mList's weak ref to us must be nulled out when we die (or when we're
    198  // cycle collected), so we that don't leave behind a pointer to
    199  // free / soon-to-be-free memory.
    200  if (nsCOMPtr<DOMSVGPointList> pointList = do_QueryInterface(mOwner)) {
    201    MOZ_ASSERT(pointList->mItems[mListIndex] == this,
    202               "Clearing out the wrong list index...?");
    203    pointList->mItems[mListIndex] = nullptr;
    204  }
    205 
    206  if (mIsInTearoffTable) {
    207    // Similarly, we must update the tearoff table to remove its (non-owning)
    208    // pointer to mVal.
    209    MOZ_ASSERT(mVal && mIsTranslatePoint,
    210               "Tearoff table should only be used for translate-point objects "
    211               "with non-null mVal (see GetTranslateTearOff and its callers)");
    212    sSVGTranslateTearOffTable.RemoveTearoff(mVal);
    213    mIsInTearoffTable = false;
    214  }
    215 
    216  if (mVal) {
    217    if (!mIsTranslatePoint) {
    218      // In this case we own mVal
    219      delete mVal;
    220    }
    221    mVal = nullptr;
    222  }
    223 }
    224 
    225 #ifdef DEBUG
    226 bool DOMSVGPoint::IndexIsValid() {
    227  nsCOMPtr<DOMSVGPointList> pointList = do_QueryInterface(mOwner);
    228  return mListIndex < pointList->InternalList().Length();
    229 }
    230 #endif
    231 
    232 }  // namespace mozilla::dom