LCOV - code coverage report
Current view: top level - dom/svg - SVGTransformListSMILType.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 137 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 11 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 "SVGTransformListSMILType.h"
       8             : #include "SVGTransformList.h"
       9             : #include "nsSVGTransform.h"
      10             : #include "nsSMILValue.h"
      11             : #include "nsCRT.h"
      12             : #include <math.h>
      13             : 
      14             : using namespace mozilla;
      15             : 
      16             : typedef FallibleTArray<SVGTransformSMILData> TransformArray;
      17             : 
      18             : //----------------------------------------------------------------------
      19             : // nsISMILType implementation
      20             : 
      21             : void
      22           0 : SVGTransformListSMILType::Init(nsSMILValue &aValue) const
      23             : {
      24           0 :   NS_PRECONDITION(aValue.IsNull(), "Unexpected value type");
      25             : 
      26           0 :   TransformArray* transforms = new TransformArray(1);
      27           0 :   aValue.mU.mPtr = transforms;
      28           0 :   aValue.mType = this;
      29           0 : }
      30             : 
      31             : void
      32           0 : SVGTransformListSMILType::Destroy(nsSMILValue& aValue) const
      33             : {
      34           0 :   NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value type");
      35           0 :   TransformArray* params = static_cast<TransformArray*>(aValue.mU.mPtr);
      36           0 :   delete params;
      37           0 :   aValue.mU.mPtr = nullptr;
      38           0 :   aValue.mType = nsSMILNullType::Singleton();
      39           0 : }
      40             : 
      41             : nsresult
      42           0 : SVGTransformListSMILType::Assign(nsSMILValue& aDest,
      43             :                                const nsSMILValue& aSrc) const
      44             : {
      45           0 :   NS_PRECONDITION(aDest.mType == aSrc.mType, "Incompatible SMIL types");
      46           0 :   NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL value");
      47             : 
      48             :   const TransformArray* srcTransforms =
      49           0 :     static_cast<const TransformArray*>(aSrc.mU.mPtr);
      50           0 :   TransformArray* dstTransforms = static_cast<TransformArray*>(aDest.mU.mPtr);
      51           0 :   if (!dstTransforms->Assign(*srcTransforms, fallible)) {
      52           0 :     return NS_ERROR_OUT_OF_MEMORY;
      53             :   }
      54             : 
      55           0 :   return NS_OK;
      56             : }
      57             : 
      58             : bool
      59           0 : SVGTransformListSMILType::IsEqual(const nsSMILValue& aLeft,
      60             :                                   const nsSMILValue& aRight) const
      61             : {
      62           0 :   NS_PRECONDITION(aLeft.mType == aRight.mType, "Incompatible SMIL types");
      63           0 :   NS_PRECONDITION(aLeft.mType == this, "Unexpected SMIL type");
      64             : 
      65             :   const TransformArray& leftArr
      66           0 :     (*static_cast<const TransformArray*>(aLeft.mU.mPtr));
      67             :   const TransformArray& rightArr
      68           0 :     (*static_cast<const TransformArray*>(aRight.mU.mPtr));
      69             : 
      70             :   // If array-lengths don't match, we're trivially non-equal.
      71           0 :   if (leftArr.Length() != rightArr.Length()) {
      72           0 :     return false;
      73             :   }
      74             : 
      75             :   // Array-lengths match -- check each array-entry for equality.
      76           0 :   uint32_t length = leftArr.Length(); // == rightArr->Length(), if we get here
      77           0 :   for (uint32_t i = 0; i < length; ++i) {
      78           0 :     if (leftArr[i] != rightArr[i]) {
      79           0 :       return false;
      80             :     }
      81             :   }
      82             : 
      83             :   // Found no differences.
      84           0 :   return true;
      85             : }
      86             : 
      87             : nsresult
      88           0 : SVGTransformListSMILType::Add(nsSMILValue& aDest,
      89             :                               const nsSMILValue& aValueToAdd,
      90             :                               uint32_t aCount) const
      91             : {
      92           0 :   NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL type");
      93           0 :   NS_PRECONDITION(aDest.mType == aValueToAdd.mType, "Incompatible SMIL types");
      94             : 
      95           0 :   TransformArray& dstTransforms(*static_cast<TransformArray*>(aDest.mU.mPtr));
      96             :   const TransformArray& srcTransforms
      97           0 :     (*static_cast<const TransformArray*>(aValueToAdd.mU.mPtr));
      98             : 
      99             :   // We're doing a simple add here (as opposed to a sandwich add below).
     100             :   // We only do this when we're accumulating a repeat result or calculating
     101             :   // a by-animation value.
     102             :   //
     103             :   // In either case we should have 1 transform in the source array.
     104           0 :   NS_ASSERTION(srcTransforms.Length() == 1,
     105             :     "Invalid source transform list to add");
     106             : 
     107             :   // And we should have 0 or 1 transforms in the dest array.
     108             :   // (We can have 0 transforms in the case of by-animation when we are
     109             :   // calculating the by-value as "0 + by". Zero being represented by an
     110             :   // nsSMILValue with an empty transform array.)
     111           0 :   NS_ASSERTION(dstTransforms.Length() < 2,
     112             :     "Invalid dest transform list to add to");
     113             : 
     114             :   // Get the individual transforms to add
     115           0 :   const SVGTransformSMILData& srcTransform = srcTransforms[0];
     116           0 :   if (dstTransforms.IsEmpty()) {
     117           0 :     SVGTransformSMILData* result = dstTransforms.AppendElement(
     118           0 :       SVGTransformSMILData(srcTransform.mTransformType), fallible);
     119           0 :     NS_ENSURE_TRUE(result,NS_ERROR_OUT_OF_MEMORY);
     120             :   }
     121           0 :   SVGTransformSMILData& dstTransform = dstTransforms[0];
     122             : 
     123             :   // The types must be the same
     124           0 :   NS_ASSERTION(srcTransform.mTransformType == dstTransform.mTransformType,
     125             :     "Trying to perform simple add of different transform types");
     126             : 
     127             :   // And it should be impossible that one of them is of matrix type
     128           0 :   NS_ASSERTION(
     129             :     srcTransform.mTransformType != SVG_TRANSFORM_MATRIX,
     130             :     "Trying to perform simple add with matrix transform");
     131             : 
     132             :   // Add the parameters
     133           0 :   for (int i = 0; i <= 2; ++i) {
     134           0 :     dstTransform.mParams[i] += srcTransform.mParams[i] * aCount;
     135             :   }
     136             : 
     137           0 :   return NS_OK;
     138             : }
     139             : 
     140             : nsresult
     141           0 : SVGTransformListSMILType::SandwichAdd(nsSMILValue& aDest,
     142             :                                       const nsSMILValue& aValueToAdd) const
     143             : {
     144           0 :   NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL type");
     145           0 :   NS_PRECONDITION(aDest.mType == aValueToAdd.mType, "Incompatible SMIL types");
     146             : 
     147             :   // For <animateTransform> a sandwich add means a matrix post-multiplication
     148             :   // which just means to put the additional transform on the end of the array
     149             : 
     150           0 :   TransformArray& dstTransforms(*static_cast<TransformArray*>(aDest.mU.mPtr));
     151             :   const TransformArray& srcTransforms
     152           0 :     (*static_cast<const TransformArray*>(aValueToAdd.mU.mPtr));
     153             : 
     154             :   // We should have 0 or 1 transforms in the src list.
     155           0 :   NS_ASSERTION(srcTransforms.Length() < 2,
     156             :     "Trying to do sandwich add of more than one value");
     157             : 
     158             :   // The empty src transform list case only occurs in some limited circumstances
     159             :   // where we create an empty 'from' value to interpolate from (e.g.
     160             :   // by-animation) but then skip the interpolation step for some reason (e.g.
     161             :   // because we have an indefinite duration which means we'll never get past the
     162             :   // first value) and instead attempt to add that empty value to the underlying
     163             :   // value.
     164             :   // In any case, the expected result is that nothing is added.
     165           0 :   if (srcTransforms.IsEmpty())
     166           0 :     return NS_OK;
     167             : 
     168             :   // Stick the src on the end of the array
     169           0 :   const SVGTransformSMILData& srcTransform = srcTransforms[0];
     170             :   SVGTransformSMILData* result =
     171           0 :     dstTransforms.AppendElement(srcTransform, fallible);
     172           0 :   NS_ENSURE_TRUE(result,NS_ERROR_OUT_OF_MEMORY);
     173             : 
     174           0 :   return NS_OK;
     175             : }
     176             : 
     177             : nsresult
     178           0 : SVGTransformListSMILType::ComputeDistance(const nsSMILValue& aFrom,
     179             :                                           const nsSMILValue& aTo,
     180             :                                           double& aDistance) const
     181             : {
     182           0 :   NS_PRECONDITION(aFrom.mType == aTo.mType,
     183             :       "Can't compute difference between different SMIL types");
     184           0 :   NS_PRECONDITION(aFrom.mType == this, "Unexpected SMIL type");
     185             : 
     186             :   const TransformArray* fromTransforms =
     187           0 :     static_cast<const TransformArray*>(aFrom.mU.mPtr);
     188             :   const TransformArray* toTransforms =
     189           0 :     static_cast<const TransformArray*>(aTo.mU.mPtr);
     190             : 
     191             :   // ComputeDistance is only used for calculating distances between single
     192             :   // values in a values array which necessarily have the same type
     193             :   //
     194             :   // So we should only have one transform in each array and they should be of
     195             :   // the same type
     196           0 :   NS_ASSERTION(fromTransforms->Length() == 1,
     197             :     "Wrong number of elements in from value");
     198           0 :   NS_ASSERTION(toTransforms->Length() == 1,
     199             :     "Wrong number of elements in to value");
     200             : 
     201           0 :   const SVGTransformSMILData& fromTransform = (*fromTransforms)[0];
     202           0 :   const SVGTransformSMILData& toTransform = (*toTransforms)[0];
     203           0 :   NS_ASSERTION(fromTransform.mTransformType == toTransform.mTransformType,
     204             :     "Incompatible transform types to calculate distance between");
     205             : 
     206           0 :   switch (fromTransform.mTransformType)
     207             :   {
     208             :     // We adopt the SVGT1.2 notions of distance here
     209             :     // See: http://www.w3.org/TR/SVGTiny12/animate.html#complexDistances
     210             :     // (As discussed in bug #469040)
     211             :     case SVG_TRANSFORM_TRANSLATE:
     212             :     case SVG_TRANSFORM_SCALE:
     213             :       {
     214           0 :         const float& a_tx = fromTransform.mParams[0];
     215           0 :         const float& a_ty = fromTransform.mParams[1];
     216           0 :         const float& b_tx = toTransform.mParams[0];
     217           0 :         const float& b_ty = toTransform.mParams[1];
     218           0 :         aDistance = sqrt(pow(a_tx - b_tx, 2) + (pow(a_ty - b_ty, 2)));
     219             :       }
     220           0 :       break;
     221             : 
     222             :     case SVG_TRANSFORM_ROTATE:
     223             :     case SVG_TRANSFORM_SKEWX:
     224             :     case SVG_TRANSFORM_SKEWY:
     225             :       {
     226           0 :         const float& a = fromTransform.mParams[0];
     227           0 :         const float& b = toTransform.mParams[0];
     228           0 :         aDistance = fabs(a-b);
     229             :       }
     230           0 :       break;
     231             : 
     232             :     default:
     233           0 :       NS_ERROR("Got bad transform types for calculating distances");
     234           0 :       aDistance = 1.0;
     235           0 :       return NS_ERROR_FAILURE;
     236             :   }
     237             : 
     238           0 :   return NS_OK;
     239             : }
     240             : 
     241             : nsresult
     242           0 : SVGTransformListSMILType::Interpolate(const nsSMILValue& aStartVal,
     243             :                                       const nsSMILValue& aEndVal,
     244             :                                       double aUnitDistance,
     245             :                                       nsSMILValue& aResult) const
     246             : {
     247           0 :   NS_PRECONDITION(aStartVal.mType == aEndVal.mType,
     248             :       "Can't interpolate between different SMIL types");
     249           0 :   NS_PRECONDITION(aStartVal.mType == this,
     250             :       "Unexpected type for interpolation");
     251           0 :   NS_PRECONDITION(aResult.mType == this, "Unexpected result type");
     252             : 
     253             :   const TransformArray& startTransforms =
     254           0 :     (*static_cast<const TransformArray*>(aStartVal.mU.mPtr));
     255             :   const TransformArray& endTransforms
     256           0 :     (*static_cast<const TransformArray*>(aEndVal.mU.mPtr));
     257             : 
     258             :   // We may have 0..n transforms in the start transform array (the base
     259             :   // value) but we should only have 1 transform in the end transform array
     260           0 :   NS_ASSERTION(endTransforms.Length() == 1,
     261             :     "Invalid end-point for interpolating between transform values");
     262             : 
     263             :   // The end point should never be a matrix transform
     264           0 :   const SVGTransformSMILData& endTransform = endTransforms[0];
     265           0 :   NS_ASSERTION(
     266             :     endTransform.mTransformType != SVG_TRANSFORM_MATRIX,
     267             :     "End point for interpolation should not be a matrix transform");
     268             : 
     269             :   // If we have 0 or more than 1 transform in the start transform array then we
     270             :   // just interpolate from 0, 0, 0
     271             :   // Likewise, even if there's only 1 transform in the start transform array
     272             :   // then if the type of the start transform doesn't match the end then we
     273             :   // can't interpolate and should just use 0, 0, 0
     274             :   static float identityParams[3] = { 0.f };
     275           0 :   const float* startParams = nullptr;
     276           0 :   if (startTransforms.Length() == 1) {
     277           0 :     const SVGTransformSMILData& startTransform = startTransforms[0];
     278           0 :     if (startTransform.mTransformType == endTransform.mTransformType) {
     279           0 :       startParams = startTransform.mParams;
     280             :     }
     281             :   }
     282           0 :   if (!startParams) {
     283           0 :     startParams = identityParams;
     284             :   }
     285             : 
     286           0 :   const float* endParams = endTransform.mParams;
     287             : 
     288             :   // Interpolate between the params
     289             :   float newParams[3];
     290           0 :   for (int i = 0; i <= 2; ++i) {
     291           0 :     const float& a = startParams[i];
     292           0 :     const float& b = endParams[i];
     293           0 :     newParams[i] = static_cast<float>(a + (b - a) * aUnitDistance);
     294             :   }
     295             : 
     296             :   // Make the result
     297           0 :   SVGTransformSMILData resultTransform(endTransform.mTransformType, newParams);
     298             : 
     299             :   // Clear the way for it in the result array
     300             :   TransformArray& dstTransforms =
     301           0 :     (*static_cast<TransformArray*>(aResult.mU.mPtr));
     302           0 :   dstTransforms.Clear();
     303             : 
     304             :   // Assign the result
     305             :   SVGTransformSMILData* transform =
     306           0 :     dstTransforms.AppendElement(resultTransform, fallible);
     307           0 :   NS_ENSURE_TRUE(transform,NS_ERROR_OUT_OF_MEMORY);
     308             : 
     309           0 :   return NS_OK;
     310             : }
     311             : 
     312             : //----------------------------------------------------------------------
     313             : // Transform array accessors
     314             : 
     315             : // static
     316             : nsresult
     317           0 : SVGTransformListSMILType::AppendTransform(
     318             :   const SVGTransformSMILData& aTransform,
     319             :   nsSMILValue& aValue)
     320             : {
     321           0 :   NS_PRECONDITION(aValue.mType == Singleton(), "Unexpected SMIL value type");
     322             : 
     323           0 :   TransformArray& transforms = *static_cast<TransformArray*>(aValue.mU.mPtr);
     324           0 :   return transforms.AppendElement(aTransform, fallible) ?
     325           0 :     NS_OK : NS_ERROR_OUT_OF_MEMORY;
     326             : }
     327             : 
     328             : // static
     329             : bool
     330           0 : SVGTransformListSMILType::AppendTransforms(const SVGTransformList& aList,
     331             :                                            nsSMILValue& aValue)
     332             : {
     333           0 :   NS_PRECONDITION(aValue.mType == Singleton(), "Unexpected SMIL value type");
     334             : 
     335           0 :   TransformArray& transforms = *static_cast<TransformArray*>(aValue.mU.mPtr);
     336             : 
     337           0 :   if (!transforms.SetCapacity(transforms.Length() + aList.Length(), fallible))
     338           0 :     return false;
     339             : 
     340           0 :   for (uint32_t i = 0; i < aList.Length(); ++i) {
     341             :     // No need to check the return value below since we have already allocated
     342             :     // the necessary space
     343           0 :     MOZ_ALWAYS_TRUE(transforms.AppendElement(SVGTransformSMILData(aList[i]),
     344             :                                              fallible));
     345             :   }
     346           0 :   return true;
     347             : }
     348             : 
     349             : // static
     350             : bool
     351           0 : SVGTransformListSMILType::GetTransforms(const nsSMILValue& aValue,
     352             :                                         FallibleTArray<nsSVGTransform>& aTransforms)
     353             : {
     354           0 :   NS_PRECONDITION(aValue.mType == Singleton(), "Unexpected SMIL value type");
     355             : 
     356             :   const TransformArray& smilTransforms =
     357           0 :     *static_cast<const TransformArray*>(aValue.mU.mPtr);
     358             : 
     359           0 :   aTransforms.Clear();
     360           0 :   if (!aTransforms.SetCapacity(smilTransforms.Length(), fallible))
     361           0 :       return false;
     362             : 
     363           0 :   for (uint32_t i = 0; i < smilTransforms.Length(); ++i) {
     364             :     // No need to check the return value below since we have already allocated
     365             :     // the necessary space
     366           0 :     aTransforms.AppendElement(smilTransforms[i].ToSVGTransform(), fallible);
     367             :   }
     368           0 :   return true;
     369             : }

Generated by: LCOV version 1.13