LCOV - code coverage report
Current view: top level - dom/svg - SVGTransform.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 161 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 29 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 "SVGTransform.h"
       8             : 
       9             : #include "mozilla/dom/SVGTransform.h"
      10             : #include "mozilla/dom/SVGMatrix.h"
      11             : #include "mozilla/dom/SVGTransformBinding.h"
      12             : #include "nsError.h"
      13             : #include "nsSVGAnimatedTransformList.h"
      14             : #include "nsSVGAttrTearoffTable.h"
      15             : #include "mozilla/DebugOnly.h"
      16             : #include "mozilla/FloatingPoint.h"
      17             : 
      18             : namespace {
      19             :   const double kRadPerDegree = 2.0 * M_PI / 360.0;
      20             : } // namespace
      21             : 
      22             : namespace mozilla {
      23             : namespace dom {
      24             : 
      25             : static nsSVGAttrTearoffTable<SVGTransform, SVGMatrix>&
      26           0 : SVGMatrixTearoffTable()
      27             : {
      28           0 :   static nsSVGAttrTearoffTable<SVGTransform, SVGMatrix> sSVGMatrixTearoffTable;
      29           0 :   return sSVGMatrixTearoffTable;
      30             : }
      31             : 
      32             : //----------------------------------------------------------------------
      33             : 
      34             : // We could use NS_IMPL_CYCLE_COLLECTION(, except that in Unlink() we need to
      35             : // clear our list's weak ref to us to be safe. (The other option would be to
      36             : // not unlink and rely on the breaking of the other edges in the cycle, as
      37             : // NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
      38             : NS_IMPL_CYCLE_COLLECTION_CLASS(SVGTransform)
      39             : 
      40           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(SVGTransform)
      41             :   // We may not belong to a list, so we must null check tmp->mList.
      42           0 :   if (tmp->mList) {
      43           0 :     tmp->mList->mItems[tmp->mListIndex] = nullptr;
      44             :   }
      45           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mList)
      46           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
      47           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
      48             : 
      49           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(SVGTransform)
      50           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mList)
      51             :   SVGMatrix* matrix =
      52           0 :     SVGMatrixTearoffTable().GetTearoff(tmp);
      53           0 :   CycleCollectionNoteChild(cb, matrix, "matrix");
      54           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
      55             : 
      56           0 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(SVGTransform)
      57           0 : NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
      58           0 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
      59             : 
      60           0 : NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(SVGTransform, AddRef)
      61           0 : NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(SVGTransform, Release)
      62             : 
      63             : JSObject*
      64           0 : SVGTransform::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
      65             : {
      66           0 :   return SVGTransformBinding::Wrap(aCx, this, aGivenProto);
      67             : }
      68             : 
      69             : //----------------------------------------------------------------------
      70             : // Helper class: AutoChangeTransformNotifier
      71             : // Stack-based helper class to pair calls to WillChangeTransformList
      72             : // and DidChangeTransformList.
      73             : class MOZ_RAII AutoChangeTransformNotifier
      74             : {
      75             : public:
      76           0 :   explicit AutoChangeTransformNotifier(SVGTransform* aTransform MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
      77           0 :     : mTransform(aTransform)
      78             :   {
      79           0 :     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
      80           0 :     MOZ_ASSERT(mTransform, "Expecting non-null transform");
      81           0 :     if (mTransform->HasOwner()) {
      82             :       mEmptyOrOldValue =
      83           0 :         mTransform->Element()->WillChangeTransformList();
      84             :     }
      85           0 :   }
      86             : 
      87           0 :   ~AutoChangeTransformNotifier()
      88           0 :   {
      89           0 :     if (mTransform->HasOwner()) {
      90           0 :       mTransform->Element()->DidChangeTransformList(mEmptyOrOldValue);
      91           0 :       if (mTransform->mList->IsAnimating()) {
      92           0 :         mTransform->Element()->AnimationNeedsResample();
      93             :       }
      94             :     }
      95           0 :   }
      96             : 
      97             : private:
      98             :   SVGTransform* const mTransform;
      99             :   nsAttrValue   mEmptyOrOldValue;
     100             :   MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
     101             : };
     102             : 
     103             : //----------------------------------------------------------------------
     104             : // Ctors:
     105             : 
     106           0 : SVGTransform::SVGTransform(DOMSVGTransformList *aList,
     107             :                            uint32_t aListIndex,
     108           0 :                            bool aIsAnimValItem)
     109             :   : mList(aList)
     110             :   , mListIndex(aListIndex)
     111             :   , mIsAnimValItem(aIsAnimValItem)
     112           0 :   , mTransform(nullptr)
     113             : {
     114             :   // These shifts are in sync with the members in the header.
     115           0 :   MOZ_ASSERT(aList && aListIndex <= MaxListIndex(), "bad arg");
     116             : 
     117           0 :   MOZ_ASSERT(IndexIsValid(), "Bad index for DOMSVGNumber!");
     118           0 : }
     119             : 
     120           0 : SVGTransform::SVGTransform()
     121             :   : mList(nullptr)
     122             :   , mListIndex(0)
     123             :   , mIsAnimValItem(false)
     124           0 :   , mTransform(new nsSVGTransform()) // Default ctor for objects not in a list
     125             :                                      // initialises to matrix type with identity
     126             :                                      // matrix
     127             : {
     128           0 : }
     129             : 
     130           0 : SVGTransform::SVGTransform(const gfxMatrix &aMatrix)
     131             :   : mList(nullptr)
     132             :   , mListIndex(0)
     133             :   , mIsAnimValItem(false)
     134           0 :   , mTransform(new nsSVGTransform(aMatrix))
     135             : {
     136           0 : }
     137             : 
     138           0 : SVGTransform::SVGTransform(const nsSVGTransform &aTransform)
     139             :   : mList(nullptr)
     140             :   , mListIndex(0)
     141             :   , mIsAnimValItem(false)
     142           0 :   , mTransform(new nsSVGTransform(aTransform))
     143             : {
     144           0 : }
     145             : 
     146           0 : SVGTransform::~SVGTransform()
     147             : {
     148           0 :   SVGMatrix* matrix = SVGMatrixTearoffTable().GetTearoff(this);
     149           0 :   if (matrix) {
     150           0 :     SVGMatrixTearoffTable().RemoveTearoff(this);
     151           0 :     NS_RELEASE(matrix);
     152             :   }
     153             :   // Our mList's weak ref to us must be nulled out when we die. If GC has
     154             :   // unlinked us using the cycle collector code, then that has already
     155             :   // happened, and mList is null.
     156           0 :   if (mList) {
     157           0 :     mList->mItems[mListIndex] = nullptr;
     158             :   }
     159           0 : }
     160             : 
     161             : uint16_t
     162           0 : SVGTransform::Type() const
     163             : {
     164           0 :   return Transform().Type();
     165             : }
     166             : 
     167             : SVGMatrix*
     168           0 : SVGTransform::GetMatrix()
     169             : {
     170             :   SVGMatrix* wrapper =
     171           0 :     SVGMatrixTearoffTable().GetTearoff(this);
     172           0 :   if (!wrapper) {
     173           0 :     NS_ADDREF(wrapper = new SVGMatrix(*this));
     174           0 :     SVGMatrixTearoffTable().AddTearoff(this, wrapper);
     175             :   }
     176           0 :   return wrapper;
     177             : }
     178             : 
     179             : float
     180           0 : SVGTransform::Angle() const
     181             : {
     182           0 :   return Transform().Angle();
     183             : }
     184             : 
     185             : void
     186           0 : SVGTransform::SetMatrix(SVGMatrix& aMatrix, ErrorResult& rv)
     187             : {
     188           0 :   if (mIsAnimValItem) {
     189           0 :     rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
     190           0 :     return;
     191             :   }
     192           0 :   SetMatrix(aMatrix.GetMatrix());
     193             : }
     194             : 
     195             : void
     196           0 : SVGTransform::SetTranslate(float tx, float ty, ErrorResult& rv)
     197             : {
     198           0 :   if (mIsAnimValItem) {
     199           0 :     rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
     200           0 :     return;
     201             :   }
     202             : 
     203           0 :   if (Transform().Type() == SVG_TRANSFORM_TRANSLATE &&
     204           0 :       Matrixgfx()._31 == tx && Matrixgfx()._32 == ty) {
     205           0 :     return;
     206             :   }
     207             : 
     208           0 :   AutoChangeTransformNotifier notifier(this);
     209           0 :   Transform().SetTranslate(tx, ty);
     210             : }
     211             : 
     212             : void
     213           0 : SVGTransform::SetScale(float sx, float sy, ErrorResult& rv)
     214             : {
     215           0 :   if (mIsAnimValItem) {
     216           0 :     rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
     217           0 :     return;
     218             :   }
     219             : 
     220           0 :   if (Transform().Type() == SVG_TRANSFORM_SCALE &&
     221           0 :       Matrixgfx()._11 == sx && Matrixgfx()._22 == sy) {
     222           0 :     return;
     223             :   }
     224           0 :   AutoChangeTransformNotifier notifier(this);
     225           0 :   Transform().SetScale(sx, sy);
     226             : }
     227             : 
     228             : void
     229           0 : SVGTransform::SetRotate(float angle, float cx, float cy, ErrorResult& rv)
     230             : {
     231           0 :   if (mIsAnimValItem) {
     232           0 :     rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
     233           0 :     return;
     234             :   }
     235             : 
     236           0 :   if (Transform().Type() == SVG_TRANSFORM_ROTATE) {
     237             :     float currentCx, currentCy;
     238           0 :     Transform().GetRotationOrigin(currentCx, currentCy);
     239           0 :     if (Transform().Angle() == angle && currentCx == cx && currentCy == cy) {
     240           0 :       return;
     241             :     }
     242             :   }
     243             : 
     244           0 :   AutoChangeTransformNotifier notifier(this);
     245           0 :   Transform().SetRotate(angle, cx, cy);
     246             : }
     247             : 
     248             : void
     249           0 : SVGTransform::SetSkewX(float angle, ErrorResult& rv)
     250             : {
     251           0 :   if (mIsAnimValItem) {
     252           0 :     rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
     253           0 :     return;
     254             :   }
     255             : 
     256           0 :   if (Transform().Type() == SVG_TRANSFORM_SKEWX &&
     257           0 :       Transform().Angle() == angle) {
     258           0 :     return;
     259             :   }
     260             : 
     261           0 :   if (!IsFinite(tan(angle * kRadPerDegree))) {
     262           0 :     rv.ThrowRangeError<MSG_INVALID_TRANSFORM_ANGLE_ERROR>();
     263           0 :     return;
     264             :   }
     265             : 
     266           0 :   AutoChangeTransformNotifier notifier(this);
     267           0 :   DebugOnly<nsresult> result = Transform().SetSkewX(angle);
     268           0 :   MOZ_ASSERT(NS_SUCCEEDED(result), "SetSkewX unexpectedly failed");
     269             : }
     270             : 
     271             : void
     272           0 : SVGTransform::SetSkewY(float angle, ErrorResult& rv)
     273             : {
     274           0 :   if (mIsAnimValItem) {
     275           0 :     rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
     276           0 :     return;
     277             :   }
     278             : 
     279           0 :   if (Transform().Type() == SVG_TRANSFORM_SKEWY &&
     280           0 :       Transform().Angle() == angle) {
     281           0 :     return;
     282             :   }
     283             : 
     284           0 :   if (!IsFinite(tan(angle * kRadPerDegree))) {
     285           0 :     rv.ThrowRangeError<MSG_INVALID_TRANSFORM_ANGLE_ERROR>();
     286           0 :     return;
     287             :   }
     288             : 
     289           0 :   AutoChangeTransformNotifier notifier(this);
     290           0 :   DebugOnly<nsresult> result = Transform().SetSkewY(angle);
     291           0 :   MOZ_ASSERT(NS_SUCCEEDED(result), "SetSkewY unexpectedly failed");
     292             : }
     293             : 
     294             : //----------------------------------------------------------------------
     295             : // List management methods:
     296             : 
     297             : void
     298           0 : SVGTransform::InsertingIntoList(DOMSVGTransformList *aList,
     299             :                                 uint32_t aListIndex,
     300             :                                 bool aIsAnimValItem)
     301             : {
     302           0 :   MOZ_ASSERT(!HasOwner(), "Inserting item that is already in a list");
     303             : 
     304           0 :   mList = aList;
     305           0 :   mListIndex = aListIndex;
     306           0 :   mIsAnimValItem = aIsAnimValItem;
     307           0 :   mTransform = nullptr;
     308             : 
     309           0 :   MOZ_ASSERT(IndexIsValid(), "Bad index for DOMSVGLength!");
     310           0 : }
     311             : 
     312             : void
     313           0 : SVGTransform::RemovingFromList()
     314             : {
     315           0 :   MOZ_ASSERT(!mTransform,
     316             :              "Item in list also has another non-list value associated with it");
     317             : 
     318           0 :   mTransform = new nsSVGTransform(InternalItem());
     319           0 :   mList = nullptr;
     320           0 :   mIsAnimValItem = false;
     321           0 : }
     322             : 
     323             : nsSVGTransform&
     324           0 : SVGTransform::InternalItem()
     325             : {
     326           0 :   nsSVGAnimatedTransformList *alist = Element()->GetAnimatedTransformList();
     327           0 :   return mIsAnimValItem && alist->mAnimVal ?
     328           0 :     (*alist->mAnimVal)[mListIndex] :
     329           0 :     alist->mBaseVal[mListIndex];
     330             : }
     331             : 
     332             : const nsSVGTransform&
     333           0 : SVGTransform::InternalItem() const
     334             : {
     335           0 :   return const_cast<SVGTransform*>(this)->InternalItem();
     336             : }
     337             : 
     338             : #ifdef DEBUG
     339             : bool
     340           0 : SVGTransform::IndexIsValid()
     341             : {
     342           0 :   nsSVGAnimatedTransformList *alist = Element()->GetAnimatedTransformList();
     343           0 :   return (mIsAnimValItem &&
     344           0 :           mListIndex < alist->GetAnimValue().Length()) ||
     345           0 :          (!mIsAnimValItem &&
     346           0 :           mListIndex < alist->GetBaseValue().Length());
     347             : }
     348             : #endif // DEBUG
     349             : 
     350             : 
     351             : //----------------------------------------------------------------------
     352             : // Interface for SVGMatrix's use
     353             : 
     354             : void
     355           0 : SVGTransform::SetMatrix(const gfxMatrix& aMatrix)
     356             : {
     357           0 :   MOZ_ASSERT(!mIsAnimValItem,
     358             :              "Attempting to modify read-only transform");
     359             : 
     360           0 :   if (Transform().Type() == SVG_TRANSFORM_MATRIX &&
     361           0 :       nsSVGTransform::MatricesEqual(Matrixgfx(), aMatrix)) {
     362           0 :     return;
     363             :   }
     364             : 
     365           0 :   AutoChangeTransformNotifier notifier(this);
     366           0 :   Transform().SetMatrix(aMatrix);
     367             : }
     368             : 
     369             : } // namespace dom
     370             : } // namespace mozilla

Generated by: LCOV version 1.13