LCOV - code coverage report
Current view: directory - content/svg/content/src - DOMSVGTransform.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 156 2 1.3 %
Date: 2012-06-02 Functions: 29 2 6.9 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2                 :  * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
       3                 :  * ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is the Mozilla SVG project.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Crocodile Clips Ltd..
      20                 :  * Portions created by the Initial Developer are Copyright (C) 2001
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
      25                 :  *   Brian Birtles <birtles@gmail.com>
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      29                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : #include "DOMSVGTransform.h"
      42                 : #include "DOMSVGMatrix.h"
      43                 : #include "SVGAnimatedTransformList.h"
      44                 : #include "nsDOMError.h"
      45                 : #include <math.h>
      46                 : #include "nsContentUtils.h"
      47                 : 
      48                 : namespace mozilla {
      49                 : 
      50                 : //----------------------------------------------------------------------
      51                 : // nsISupports methods:
      52                 : 
      53                 : // We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
      54                 : // clear our list's weak ref to us to be safe. (The other option would be to
      55                 : // not unlink and rely on the breaking of the other edges in the cycle, as
      56                 : // NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
      57            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGTransform)
      58               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGTransform)
      59                 :   // We may not belong to a list, so we must null check tmp->mList.
      60               0 :   if (tmp->mList) {
      61               0 :     tmp->mList->mItems[tmp->mListIndex] = nsnull;
      62                 :   }
      63               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mList)
      64               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
      65               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGTransform)
      66               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mList)
      67               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
      68                 : 
      69               0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGTransform)
      70               0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGTransform)
      71                 : 
      72                 : } // namespace mozilla
      73                 : DOMCI_DATA(SVGTransform, mozilla::DOMSVGTransform)
      74                 : namespace mozilla {
      75                 : 
      76               0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGTransform)
      77               0 :   NS_INTERFACE_MAP_ENTRY(mozilla::DOMSVGTransform)
      78               0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGTransform)
      79               0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMSVGTransform)
      80               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGTransform)
      81               0 : NS_INTERFACE_MAP_END
      82                 : 
      83                 : 
      84                 : //----------------------------------------------------------------------
      85                 : // Ctors:
      86                 : 
      87               0 : DOMSVGTransform::DOMSVGTransform(DOMSVGTransformList *aList,
      88                 :                                  PRUint32 aListIndex,
      89                 :                                  bool aIsAnimValItem)
      90                 :   : mList(aList)
      91                 :   , mListIndex(aListIndex)
      92                 :   , mIsAnimValItem(aIsAnimValItem)
      93                 :   , mTransform(nsnull)
      94               0 :   , mMatrixTearoff(nsnull)
      95                 : {
      96                 :   // These shifts are in sync with the members in the header.
      97               0 :   NS_ABORT_IF_FALSE(aList &&
      98                 :                     aListIndex <= MaxListIndex() &&
      99                 :                     aIsAnimValItem < (1 << 1), "bad arg");
     100                 : 
     101               0 :   NS_ABORT_IF_FALSE(IndexIsValid(), "Bad index for DOMSVGNumber!");
     102               0 : }
     103                 : 
     104               0 : DOMSVGTransform::DOMSVGTransform()
     105                 :   : mList(nsnull)
     106                 :   , mListIndex(0)
     107                 :   , mIsAnimValItem(false)
     108                 :   , mTransform(new SVGTransform()) // Default ctor for objects not in a list
     109                 :                                    // initialises to matrix type with identity
     110                 :                                    // matrix
     111               0 :   , mMatrixTearoff(nsnull)
     112                 : {
     113               0 : }
     114                 : 
     115               0 : DOMSVGTransform::DOMSVGTransform(const gfxMatrix &aMatrix)
     116                 :   : mList(nsnull)
     117                 :   , mListIndex(0)
     118                 :   , mIsAnimValItem(false)
     119               0 :   , mTransform(new SVGTransform(aMatrix))
     120               0 :   , mMatrixTearoff(nsnull)
     121                 : {
     122               0 : }
     123                 : 
     124               0 : DOMSVGTransform::DOMSVGTransform(const SVGTransform &aTransform)
     125                 :   : mList(nsnull)
     126                 :   , mListIndex(0)
     127                 :   , mIsAnimValItem(false)
     128                 :   , mTransform(new SVGTransform(aTransform))
     129               0 :   , mMatrixTearoff(nsnull)
     130                 : {
     131               0 : }
     132                 : 
     133                 : 
     134                 : //----------------------------------------------------------------------
     135                 : // nsIDOMSVGTransform methods:
     136                 : 
     137                 : /* readonly attribute unsigned short type; */
     138                 : NS_IMETHODIMP
     139               0 : DOMSVGTransform::GetType(PRUint16 *aType)
     140                 : {
     141               0 :   *aType = Transform().Type();
     142               0 :   return NS_OK;
     143                 : }
     144                 : 
     145                 : /* readonly attribute nsIDOMSVGMatrix matrix; */
     146                 : NS_IMETHODIMP
     147               0 : DOMSVGTransform::GetMatrix(nsIDOMSVGMatrix * *aMatrix)
     148                 : {
     149               0 :   if (!mMatrixTearoff) {
     150               0 :     mMatrixTearoff = new DOMSVGMatrix(*this);
     151                 :   }
     152                 : 
     153               0 :   NS_ADDREF(*aMatrix = mMatrixTearoff);
     154               0 :   return NS_OK;
     155                 : }
     156                 : 
     157                 : /* readonly attribute float angle; */
     158                 : NS_IMETHODIMP
     159               0 : DOMSVGTransform::GetAngle(float *aAngle)
     160                 : {
     161               0 :   *aAngle = Transform().Angle();
     162               0 :   return NS_OK;
     163                 : }
     164                 : 
     165                 : /* void setMatrix (in nsIDOMSVGMatrix matrix); */
     166                 : NS_IMETHODIMP
     167               0 : DOMSVGTransform::SetMatrix(nsIDOMSVGMatrix *matrix)
     168                 : {
     169               0 :   if (mIsAnimValItem)
     170               0 :     return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
     171                 : 
     172               0 :   nsCOMPtr<DOMSVGMatrix> domMatrix = do_QueryInterface(matrix);
     173               0 :   if (!domMatrix)
     174               0 :     return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
     175                 : 
     176               0 :   SetMatrix(domMatrix->Matrix());
     177               0 :   return NS_OK;
     178                 : }
     179                 : 
     180                 : /* void setTranslate (in float tx, in float ty); */
     181                 : NS_IMETHODIMP
     182               0 : DOMSVGTransform::SetTranslate(float tx, float ty)
     183                 : {
     184               0 :   if (mIsAnimValItem) {
     185               0 :     return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
     186                 :   }
     187               0 :   NS_ENSURE_FINITE2(tx, ty, NS_ERROR_ILLEGAL_VALUE);
     188                 : 
     189               0 :   if (Transform().Type() == nsIDOMSVGTransform::SVG_TRANSFORM_TRANSLATE &&
     190               0 :       Matrix().x0 == tx && Matrix().y0 == ty) {
     191               0 :     return NS_OK;
     192                 :   }
     193                 : 
     194               0 :   nsAttrValue emptyOrOldValue = NotifyElementWillChange();
     195               0 :   Transform().SetTranslate(tx, ty);
     196               0 :   NotifyElementDidChange(emptyOrOldValue);
     197                 : 
     198               0 :   return NS_OK;
     199                 : }
     200                 : 
     201                 : /* void setScale (in float sx, in float sy); */
     202                 : NS_IMETHODIMP
     203               0 : DOMSVGTransform::SetScale(float sx, float sy)
     204                 : {
     205               0 :   if (mIsAnimValItem) {
     206               0 :     return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
     207                 :   }
     208               0 :   NS_ENSURE_FINITE2(sx, sy, NS_ERROR_ILLEGAL_VALUE);
     209                 : 
     210               0 :   if (Transform().Type() == nsIDOMSVGTransform::SVG_TRANSFORM_SCALE &&
     211               0 :       Matrix().xx == sx && Matrix().yy == sy) {
     212               0 :     return NS_OK;
     213                 :   }
     214                 : 
     215               0 :   nsAttrValue emptyOrOldValue = NotifyElementWillChange();
     216               0 :   Transform().SetScale(sx, sy);
     217               0 :   NotifyElementDidChange(emptyOrOldValue);
     218                 : 
     219               0 :   return NS_OK;
     220                 : }
     221                 : 
     222                 : /* void setRotate (in float angle, in float cx, in float cy); */
     223                 : NS_IMETHODIMP
     224               0 : DOMSVGTransform::SetRotate(float angle, float cx, float cy)
     225                 : {
     226               0 :   if (mIsAnimValItem) {
     227               0 :     return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
     228                 :   }
     229               0 :   NS_ENSURE_FINITE3(angle, cx, cy, NS_ERROR_ILLEGAL_VALUE);
     230                 : 
     231               0 :   if (Transform().Type() == nsIDOMSVGTransform::SVG_TRANSFORM_ROTATE) {
     232                 :     float currentCx, currentCy;
     233               0 :     Transform().GetRotationOrigin(currentCx, currentCy);
     234               0 :     if (Transform().Angle() == angle && currentCx == cx && currentCy == cy) {
     235               0 :       return NS_OK;
     236                 :     }
     237                 :   }
     238                 : 
     239               0 :   nsAttrValue emptyOrOldValue = NotifyElementWillChange();
     240               0 :   Transform().SetRotate(angle, cx, cy);
     241               0 :   NotifyElementDidChange(emptyOrOldValue);
     242                 : 
     243               0 :   return NS_OK;
     244                 : }
     245                 : 
     246                 : /* void setSkewX (in float angle); */
     247                 : NS_IMETHODIMP
     248               0 : DOMSVGTransform::SetSkewX(float angle)
     249                 : {
     250               0 :   if (mIsAnimValItem) {
     251               0 :     return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
     252                 :   }
     253               0 :   NS_ENSURE_FINITE(angle, NS_ERROR_ILLEGAL_VALUE);
     254                 : 
     255               0 :   if (Transform().Type() == nsIDOMSVGTransform::SVG_TRANSFORM_SKEWX &&
     256               0 :       Transform().Angle() == angle) {
     257               0 :     return NS_OK;
     258                 :   }
     259                 : 
     260               0 :   nsAttrValue emptyOrOldValue = NotifyElementWillChange();
     261               0 :   nsresult rv = Transform().SetSkewX(angle);
     262               0 :   if (NS_FAILED(rv))
     263               0 :     return rv;
     264               0 :   NotifyElementDidChange(emptyOrOldValue);
     265                 : 
     266               0 :   return NS_OK;
     267                 : }
     268                 : 
     269                 : /* void setSkewY (in float angle); */
     270                 : NS_IMETHODIMP
     271               0 : DOMSVGTransform::SetSkewY(float angle)
     272                 : {
     273               0 :   if (mIsAnimValItem) {
     274               0 :     return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
     275                 :   }
     276               0 :   NS_ENSURE_FINITE(angle, NS_ERROR_ILLEGAL_VALUE);
     277                 : 
     278               0 :   if (Transform().Type() == nsIDOMSVGTransform::SVG_TRANSFORM_SKEWY &&
     279               0 :       Transform().Angle() == angle) {
     280               0 :     return NS_OK;
     281                 :   }
     282                 : 
     283               0 :   nsAttrValue emptyOrOldValue = NotifyElementWillChange();
     284               0 :   nsresult rv = Transform().SetSkewY(angle);
     285               0 :   if (NS_FAILED(rv))
     286               0 :     return rv;
     287               0 :   NotifyElementDidChange(emptyOrOldValue);
     288                 : 
     289               0 :   return NS_OK;
     290                 : }
     291                 : 
     292                 : 
     293                 : //----------------------------------------------------------------------
     294                 : // List management methods:
     295                 : 
     296                 : void
     297               0 : DOMSVGTransform::InsertingIntoList(DOMSVGTransformList *aList,
     298                 :                                    PRUint32 aListIndex,
     299                 :                                    bool aIsAnimValItem)
     300                 : {
     301               0 :   NS_ABORT_IF_FALSE(!HasOwner(), "Inserting item that is already in a list");
     302                 : 
     303               0 :   mList = aList;
     304               0 :   mListIndex = aListIndex;
     305               0 :   mIsAnimValItem = aIsAnimValItem;
     306               0 :   mTransform = nsnull;
     307                 : 
     308               0 :   NS_ABORT_IF_FALSE(IndexIsValid(), "Bad index for DOMSVGLength!");
     309               0 : }
     310                 : 
     311                 : void
     312               0 : DOMSVGTransform::RemovingFromList()
     313                 : {
     314               0 :   NS_ABORT_IF_FALSE(!mTransform,
     315                 :       "Item in list also has another non-list value associated with it");
     316                 : 
     317               0 :   mTransform = new SVGTransform(InternalItem());
     318               0 :   mList = nsnull;
     319               0 :   mIsAnimValItem = false;
     320               0 : }
     321                 : 
     322                 : SVGTransform&
     323               0 : DOMSVGTransform::InternalItem()
     324                 : {
     325               0 :   SVGAnimatedTransformList *alist = Element()->GetAnimatedTransformList();
     326               0 :   return mIsAnimValItem && alist->mAnimVal ?
     327               0 :     (*alist->mAnimVal)[mListIndex] :
     328               0 :     alist->mBaseVal[mListIndex];
     329                 : }
     330                 : 
     331                 : const SVGTransform&
     332               0 : DOMSVGTransform::InternalItem() const
     333                 : {
     334               0 :   return const_cast<DOMSVGTransform *>(this)->InternalItem();
     335                 : }
     336                 : 
     337                 : #ifdef DEBUG
     338                 : bool
     339               0 : DOMSVGTransform::IndexIsValid()
     340                 : {
     341               0 :   SVGAnimatedTransformList *alist = Element()->GetAnimatedTransformList();
     342                 :   return (mIsAnimValItem &&
     343               0 :           mListIndex < alist->GetAnimValue().Length()) ||
     344               0 :          (!mIsAnimValItem &&
     345               0 :           mListIndex < alist->GetBaseValue().Length());
     346                 : }
     347                 : #endif // DEBUG
     348                 : 
     349                 : 
     350                 : //----------------------------------------------------------------------
     351                 : // Interface for DOMSVGMatrix's use
     352                 : 
     353                 : void
     354               0 : DOMSVGTransform::SetMatrix(const gfxMatrix& aMatrix)
     355                 : {
     356               0 :   NS_ABORT_IF_FALSE(!mIsAnimValItem,
     357                 :       "Attempting to modify read-only transform");
     358                 : 
     359               0 :   if (Transform().Type() == nsIDOMSVGTransform::SVG_TRANSFORM_MATRIX &&
     360               0 :       SVGTransform::MatricesEqual(Matrix(), aMatrix)) {
     361               0 :     return;
     362                 :   }
     363                 : 
     364               0 :   nsAttrValue emptyOrOldValue = NotifyElementWillChange();
     365               0 :   Transform().SetMatrix(aMatrix);
     366               0 :   NotifyElementDidChange(emptyOrOldValue);
     367                 : }
     368                 : 
     369                 : void
     370               0 : DOMSVGTransform::ClearMatrixTearoff(DOMSVGMatrix* aMatrix)
     371                 : {
     372               0 :   NS_ABORT_IF_FALSE(mMatrixTearoff == aMatrix,
     373                 :       "Unexpected matrix pointer to be cleared");
     374               0 :   mMatrixTearoff = nsnull;
     375               0 : }
     376                 : 
     377                 : 
     378                 : //----------------------------------------------------------------------
     379                 : // Implementation helpers
     380                 : 
     381                 : void
     382               0 : DOMSVGTransform::NotifyElementDidChange(const nsAttrValue& aEmptyOrOldValue)
     383                 : {
     384               0 :   if (HasOwner()) {
     385               0 :     Element()->DidChangeTransformList(aEmptyOrOldValue);
     386               0 :     if (mList->mAList->IsAnimating()) {
     387               0 :       Element()->AnimationNeedsResample();
     388                 :     }
     389                 :   }
     390               0 : }
     391                 : 
     392            4392 : } // namespace mozilla

Generated by: LCOV version 1.7