LCOV - code coverage report
Current view: directory - content/svg/content/src - SVGPathSegListSMILType.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 197 2 1.0 %
Date: 2012-06-02 Functions: 17 2 11.8 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is the Mozilla SVG project.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is the Mozilla Foundation.
      18                 :  * Portions created by the Initial Developer are Copyright (C) 2010
      19                 :  * the Initial Developer. All Rights Reserved.
      20                 :  *
      21                 :  * Contributor(s):
      22                 :  *
      23                 :  * Alternatively, the contents of this file may be used under the terms of
      24                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      25                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      26                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      27                 :  * of those above. If you wish to allow use of your version of this file only
      28                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      29                 :  * use your version of this file under the terms of the MPL, indicate your
      30                 :  * decision by deleting the provisions above and replace them with the notice
      31                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      32                 :  * the provisions above, a recipient may use your version of this file under
      33                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      34                 :  *
      35                 :  * ***** END LICENSE BLOCK ***** */
      36                 : 
      37                 : #include "SVGPathSegListSMILType.h"
      38                 : #include "nsSMILValue.h"
      39                 : #include "SVGPathSegUtils.h"
      40                 : #include "SVGPathData.h"
      41                 : #include "mozilla/Util.h"
      42                 : #include <math.h>
      43                 : 
      44                 : // Indices of boolean flags within 'arc' segment chunks in path-data arrays
      45                 : // (where '0' would correspond to the index of the encoded segment type):
      46                 : #define LARGE_ARC_FLAG_IDX 4
      47                 : #define SWEEP_FLAG_IDX     5
      48                 : 
      49                 : namespace mozilla {
      50                 : 
      51            1464 : /*static*/ SVGPathSegListSMILType SVGPathSegListSMILType::sSingleton;
      52                 : 
      53                 : //----------------------------------------------------------------------
      54                 : // nsISMILType implementation
      55                 : 
      56                 : void
      57               0 : SVGPathSegListSMILType::Init(nsSMILValue &aValue) const
      58                 : {
      59               0 :   NS_ABORT_IF_FALSE(aValue.IsNull(), "Unexpected value type");
      60               0 :   aValue.mU.mPtr = new SVGPathDataAndOwner();
      61               0 :   aValue.mType = this;
      62               0 : }
      63                 : 
      64                 : void
      65               0 : SVGPathSegListSMILType::Destroy(nsSMILValue& aValue) const
      66                 : {
      67               0 :   NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value type");
      68               0 :   delete static_cast<SVGPathDataAndOwner*>(aValue.mU.mPtr);
      69               0 :   aValue.mU.mPtr = nsnull;
      70               0 :   aValue.mType = &nsSMILNullType::sSingleton;
      71               0 : }
      72                 : 
      73                 : nsresult
      74               0 : SVGPathSegListSMILType::Assign(nsSMILValue& aDest,
      75                 :                                const nsSMILValue& aSrc) const
      76                 : {
      77               0 :   NS_PRECONDITION(aDest.mType == aSrc.mType, "Incompatible SMIL types");
      78               0 :   NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL value");
      79                 : 
      80                 :   const SVGPathDataAndOwner* src =
      81               0 :     static_cast<const SVGPathDataAndOwner*>(aSrc.mU.mPtr);
      82                 :   SVGPathDataAndOwner* dest =
      83               0 :     static_cast<SVGPathDataAndOwner*>(aDest.mU.mPtr);
      84                 : 
      85               0 :   return dest->CopyFrom(*src);
      86                 : }
      87                 : 
      88                 : bool
      89               0 : SVGPathSegListSMILType::IsEqual(const nsSMILValue& aLeft,
      90                 :                                 const nsSMILValue& aRight) const
      91                 : {
      92               0 :   NS_PRECONDITION(aLeft.mType == aRight.mType, "Incompatible SMIL types");
      93               0 :   NS_PRECONDITION(aLeft.mType == this, "Unexpected type for SMIL value");
      94                 : 
      95                 :   return *static_cast<const SVGPathDataAndOwner*>(aLeft.mU.mPtr) ==
      96               0 :          *static_cast<const SVGPathDataAndOwner*>(aRight.mU.mPtr);
      97                 : }
      98                 : 
      99                 : static bool
     100               0 : ArcFlagsDiffer(SVGPathDataAndOwner::const_iterator aPathData1,
     101                 :                SVGPathDataAndOwner::const_iterator aPathData2)
     102                 : {
     103               0 :   NS_ABORT_IF_FALSE
     104                 :     (SVGPathSegUtils::IsArcType(SVGPathSegUtils::DecodeType(aPathData1[0])),
     105                 :                                 "ArcFlagsDiffer called with non-arc segment");
     106               0 :   NS_ABORT_IF_FALSE
     107                 :     (SVGPathSegUtils::IsArcType(SVGPathSegUtils::DecodeType(aPathData2[0])),
     108                 :                                 "ArcFlagsDiffer called with non-arc segment");
     109                 : 
     110               0 :   return aPathData1[LARGE_ARC_FLAG_IDX] != aPathData2[LARGE_ARC_FLAG_IDX] ||
     111               0 :          aPathData1[SWEEP_FLAG_IDX]     != aPathData2[SWEEP_FLAG_IDX];
     112                 : }
     113                 : 
     114                 : enum PathInterpolationResult {
     115                 :   eCannotInterpolate,
     116                 :   eRequiresConversion,
     117                 :   eCanInterpolate
     118                 : };
     119                 : 
     120                 : static PathInterpolationResult
     121               0 : CanInterpolate(const SVGPathDataAndOwner& aStart,
     122                 :                const SVGPathDataAndOwner& aEnd)
     123                 : {
     124               0 :   if (aStart.IsIdentity()) {
     125               0 :     return eCanInterpolate;
     126                 :   }
     127                 : 
     128               0 :   if (aStart.Length() != aEnd.Length()) {
     129               0 :     return eCannotInterpolate;
     130                 :   }
     131                 : 
     132               0 :   PathInterpolationResult result = eCanInterpolate;
     133                 : 
     134               0 :   SVGPathDataAndOwner::const_iterator pStart = aStart.begin();
     135               0 :   SVGPathDataAndOwner::const_iterator pEnd = aEnd.begin();
     136               0 :   SVGPathDataAndOwner::const_iterator pStartDataEnd = aStart.end();
     137               0 :   SVGPathDataAndOwner::const_iterator pEndDataEnd = aEnd.end();
     138                 : 
     139               0 :   while (pStart < pStartDataEnd && pEnd < pEndDataEnd) {
     140               0 :     PRUint32 startType = SVGPathSegUtils::DecodeType(*pStart);
     141               0 :     PRUint32 endType = SVGPathSegUtils::DecodeType(*pEnd);
     142                 : 
     143               0 :     if (SVGPathSegUtils::IsArcType(startType) &&
     144               0 :         SVGPathSegUtils::IsArcType(endType) &&
     145               0 :         ArcFlagsDiffer(pStart, pEnd)) {
     146               0 :       return eCannotInterpolate;
     147                 :     }
     148                 : 
     149               0 :     if (startType != endType) {
     150               0 :       if (!SVGPathSegUtils::SameTypeModuloRelativeness(startType, endType)) {
     151               0 :         return eCannotInterpolate;
     152                 :       }
     153                 : 
     154               0 :       result = eRequiresConversion;
     155                 :     }
     156                 : 
     157               0 :     pStart += 1 + SVGPathSegUtils::ArgCountForType(startType);
     158               0 :     pEnd += 1 + SVGPathSegUtils::ArgCountForType(endType);
     159                 :   }
     160                 : 
     161               0 :   NS_ABORT_IF_FALSE(pStart <= pStartDataEnd && pEnd <= pEndDataEnd,
     162                 :                     "Iterated past end of buffer! (Corrupt path data?)");
     163                 : 
     164               0 :   if (pStart != pStartDataEnd || pEnd != pEndDataEnd) {
     165               0 :     return eCannotInterpolate;
     166                 :   }
     167                 : 
     168               0 :   return result;
     169                 : }
     170                 : 
     171                 : enum RelativenessAdjustmentType {
     172                 :   eAbsoluteToRelative,
     173                 :   eRelativeToAbsolute
     174                 : };
     175                 : 
     176                 : static inline void
     177               0 : AdjustSegmentForRelativeness(RelativenessAdjustmentType aAdjustmentType,
     178                 :                              const SVGPathDataAndOwner::iterator& aSegmentToAdjust,
     179                 :                              const SVGPathTraversalState& aState)
     180                 : {
     181               0 :   if (aAdjustmentType == eAbsoluteToRelative) {
     182               0 :     aSegmentToAdjust[0] -= aState.pos.x;
     183               0 :     aSegmentToAdjust[1] -= aState.pos.y;
     184                 :   } else {
     185               0 :     aSegmentToAdjust[0] += aState.pos.x;
     186               0 :     aSegmentToAdjust[1] += aState.pos.y;
     187                 :   }
     188               0 : }
     189                 : 
     190                 : /**
     191                 :  * Helper function for AddWeightedPathSegLists, to add multiples of two
     192                 :  * path-segments of the same type.
     193                 :  *
     194                 :  * NOTE: |aSeg1| is allowed to be nsnull, so we use |aSeg2| as the
     195                 :  * authoritative source of things like segment-type and boolean arc flags.
     196                 :  *
     197                 :  * @param aCoeff1    The coefficient to use on the first segment.
     198                 :  * @param aSeg1      An iterator pointing to the first segment.  This can be
     199                 :  *                   null, which is treated as identity (zero).
     200                 :  * @param aCoeff2    The coefficient to use on the second segment.
     201                 :  * @param aSeg2      An iterator pointing to the second segment.
     202                 :  * @param [out] aResultSeg An iterator pointing to where we should write the
     203                 :  *                         result of this operation.
     204                 :  */
     205                 : static inline void
     206               0 : AddWeightedPathSegs(double aCoeff1,
     207                 :                     SVGPathDataAndOwner::const_iterator& aSeg1,
     208                 :                     double aCoeff2,
     209                 :                     SVGPathDataAndOwner::const_iterator& aSeg2,
     210                 :                     SVGPathDataAndOwner::iterator& aResultSeg)
     211                 : {
     212               0 :   NS_ABORT_IF_FALSE(aSeg2, "2nd segment must be non-null");
     213               0 :   NS_ABORT_IF_FALSE(aResultSeg, "result segment must be non-null");
     214                 : 
     215               0 :   PRUint32 segType = SVGPathSegUtils::DecodeType(aSeg2[0]);
     216               0 :   NS_ABORT_IF_FALSE(!aSeg1 || SVGPathSegUtils::DecodeType(*aSeg1) == segType,
     217                 :                     "unexpected segment type");
     218                 : 
     219                 :   // FIRST: Directly copy the arguments that don't make sense to add.
     220               0 :   aResultSeg[0] = aSeg2[0];  // encoded segment type
     221                 : 
     222               0 :   bool isArcType = SVGPathSegUtils::IsArcType(segType);
     223               0 :   if (isArcType) {
     224                 :     // Copy boolean arc flags.
     225               0 :     NS_ABORT_IF_FALSE(!aSeg1 || !ArcFlagsDiffer(aSeg1, aSeg2),
     226                 :                       "Expecting arc flags to match");
     227               0 :     aResultSeg[LARGE_ARC_FLAG_IDX] = aSeg2[LARGE_ARC_FLAG_IDX];
     228               0 :     aResultSeg[SWEEP_FLAG_IDX]     = aSeg2[SWEEP_FLAG_IDX];
     229                 :   }
     230                 : 
     231                 :   // SECOND: Add the arguments that are supposed to be added.
     232                 :   // (The 1's below are to account for segment type)
     233               0 :   PRUint32 numArgs = SVGPathSegUtils::ArgCountForType(segType);
     234               0 :   for (PRUint32 i = 1; i < 1 + numArgs; ++i) {
     235                 :      // Need to skip arc flags for arc-type segments. (already handled them)
     236               0 :     if (!(isArcType && (i == LARGE_ARC_FLAG_IDX || i == SWEEP_FLAG_IDX))) {
     237               0 :       aResultSeg[i] = (aSeg1 ? aCoeff1 * aSeg1[i] : 0.0) + aCoeff2 * aSeg2[i];
     238                 :     }
     239                 :   }
     240                 : 
     241                 :   // FINALLY: Shift iterators forward. ("1+" is to include seg-type)
     242               0 :   if (aSeg1) {
     243               0 :     aSeg1 += 1 + numArgs;
     244                 :   }
     245               0 :   aSeg2 += 1 + numArgs;
     246               0 :   aResultSeg += 1 + numArgs;
     247               0 : }
     248                 : 
     249                 : /**
     250                 :  * Helper function for Add & Interpolate, to add multiples of two path-segment
     251                 :  * lists.
     252                 :  *
     253                 :  * NOTE: aList1 and aList2 are assumed to have their segment-types and
     254                 :  * segment-count match exactly (unless aList1 is an identity value).
     255                 :  *
     256                 :  * NOTE: aResult, the output list, is expected to either be an identity value
     257                 :  * (in which case we'll grow it) *or* to already have the exactly right length
     258                 :  * (e.g. in cases where aList1 and aResult are actually the same list).
     259                 :  *
     260                 :  * @param aCoeff1    The coefficient to use on the first path segment list.
     261                 :  * @param aList1     The first path segment list. Allowed to be identity.
     262                 :  * @param aCoeff2    The coefficient to use on the second path segment list.
     263                 :  * @param aList2     The second path segment list.
     264                 :  * @param [out] aResultSeg The resulting path segment list. Allowed to be
     265                 :  *                         identity, in which case we'll grow it to the right
     266                 :  *                         size. Also allowed to be the same list as aList1.
     267                 :  */
     268                 : static void
     269               0 : AddWeightedPathSegLists(double aCoeff1, const SVGPathDataAndOwner& aList1,
     270                 :                         double aCoeff2, const SVGPathDataAndOwner& aList2,
     271                 :                         SVGPathDataAndOwner& aResult)
     272                 : {
     273               0 :   NS_ABORT_IF_FALSE(aCoeff1 >= 0.0 && aCoeff2 >= 0.0,
     274                 :                     "expecting non-negative coefficients");
     275               0 :   NS_ABORT_IF_FALSE(!aList2.IsIdentity(),
     276                 :                     "expecting 2nd list to be non-identity");
     277               0 :   NS_ABORT_IF_FALSE(aList1.IsIdentity() || aList1.Length() == aList2.Length(),
     278                 :                     "expecting 1st list to be identity or to have same "
     279                 :                     "length as 2nd list");
     280               0 :   NS_ABORT_IF_FALSE(aResult.IsIdentity() || aResult.Length() == aList2.Length(),
     281                 :                     "expecting result list to be identity or to have same "
     282                 :                     "length as 2nd list");
     283                 : 
     284                 :   SVGPathDataAndOwner::const_iterator iter1, end1;
     285               0 :   if (aList1.IsIdentity()) {
     286               0 :     iter1 = end1 = nsnull; // indicate that this is an identity list
     287                 :   } else {
     288               0 :     iter1 = aList1.begin();
     289               0 :     end1 = aList1.end();
     290                 :   }
     291               0 :   SVGPathDataAndOwner::const_iterator iter2 = aList2.begin();
     292               0 :   SVGPathDataAndOwner::const_iterator end2 = aList2.end();
     293                 : 
     294                 :   // Grow |aResult| if necessary. (NOTE: It's possible that aResult and aList1
     295                 :   // are the same list, so this may implicitly resize aList1. That's fine,
     296                 :   // because in that case, we will have already set iter1 to nsnull above, to
     297                 :   // record that our first operand is an identity value.)
     298               0 :   if (aResult.IsIdentity()) {
     299               0 :     DebugOnly<bool> success = aResult.SetLength(aList2.Length());
     300               0 :     NS_ABORT_IF_FALSE(success, "infallible nsTArray::SetLength should succeed");
     301               0 :     aResult.SetElement(aList2.Element()); // propagate target element info!
     302                 :   }
     303                 : 
     304               0 :   SVGPathDataAndOwner::iterator resultIter = aResult.begin();
     305                 : 
     306               0 :   while ((!iter1 || iter1 != end1) &&
     307                 :          iter2 != end2) {
     308                 :     AddWeightedPathSegs(aCoeff1, iter1,
     309                 :                         aCoeff2, iter2,
     310               0 :                         resultIter);
     311                 :   }
     312               0 :   NS_ABORT_IF_FALSE((!iter1 || iter1 == end1) &&
     313                 :                     iter2 == end2 &&
     314                 :                     resultIter == aResult.end(),
     315                 :                     "Very, very bad - path data corrupt");
     316               0 : }
     317                 : 
     318                 : static void
     319               0 : ConvertPathSegmentData(SVGPathDataAndOwner::const_iterator& aStart,
     320                 :                        SVGPathDataAndOwner::const_iterator& aEnd,
     321                 :                        SVGPathDataAndOwner::iterator& aResult,
     322                 :                        SVGPathTraversalState& aState)
     323                 : {
     324               0 :   PRUint32 startType = SVGPathSegUtils::DecodeType(*aStart);
     325               0 :   PRUint32 endType = SVGPathSegUtils::DecodeType(*aEnd);
     326                 : 
     327                 :   PRUint32 segmentLengthIncludingType =
     328               0 :       1 + SVGPathSegUtils::ArgCountForType(startType);
     329                 : 
     330               0 :   SVGPathDataAndOwner::const_iterator pResultSegmentBegin = aResult;
     331                 : 
     332               0 :   if (startType == endType) {
     333                 :     // No conversion need, just directly copy aStart.
     334               0 :     aEnd += segmentLengthIncludingType;
     335               0 :     while (segmentLengthIncludingType) {
     336               0 :       *aResult++ = *aStart++;
     337               0 :       --segmentLengthIncludingType;
     338                 :     }
     339               0 :     SVGPathSegUtils::TraversePathSegment(pResultSegmentBegin, aState);
     340               0 :     return;
     341                 :   }
     342                 : 
     343               0 :   NS_ABORT_IF_FALSE
     344                 :       (SVGPathSegUtils::SameTypeModuloRelativeness(startType, endType),
     345                 :        "Incompatible path segment types passed to ConvertPathSegmentData!");
     346                 : 
     347                 :   RelativenessAdjustmentType adjustmentType =
     348               0 :     SVGPathSegUtils::IsRelativeType(startType) ? eRelativeToAbsolute
     349               0 :                                                : eAbsoluteToRelative;
     350                 : 
     351               0 :   NS_ABORT_IF_FALSE
     352                 :     (segmentLengthIncludingType ==
     353                 :        1 + SVGPathSegUtils::ArgCountForType(endType),
     354                 :      "Compatible path segment types for interpolation had different lengths!");
     355                 : 
     356               0 :   aResult[0] = aEnd[0];
     357                 : 
     358               0 :   switch (endType) {
     359                 :     case nsIDOMSVGPathSeg::PATHSEG_LINETO_HORIZONTAL_ABS:
     360                 :     case nsIDOMSVGPathSeg::PATHSEG_LINETO_HORIZONTAL_REL:
     361               0 :       aResult[1] = aStart[1] +
     362               0 :         (adjustmentType == eRelativeToAbsolute ? 1 : -1) * aState.pos.x;
     363               0 :       break;
     364                 :     case nsIDOMSVGPathSeg::PATHSEG_LINETO_VERTICAL_ABS:
     365                 :     case nsIDOMSVGPathSeg::PATHSEG_LINETO_VERTICAL_REL:
     366               0 :       aResult[1] = aStart[1] +
     367               0 :         (adjustmentType == eRelativeToAbsolute  ? 1 : -1) * aState.pos.y;
     368               0 :       break;
     369                 :     case nsIDOMSVGPathSeg::PATHSEG_ARC_ABS:
     370                 :     case nsIDOMSVGPathSeg::PATHSEG_ARC_REL:
     371               0 :       aResult[1] = aStart[1];
     372               0 :       aResult[2] = aStart[2];
     373               0 :       aResult[3] = aStart[3];
     374               0 :       aResult[4] = aStart[4];
     375               0 :       aResult[5] = aStart[5];
     376               0 :       aResult[6] = aStart[6];
     377               0 :       aResult[7] = aStart[7];
     378               0 :       AdjustSegmentForRelativeness(adjustmentType, aResult + 6, aState);
     379               0 :       break;
     380                 :     case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS:
     381                 :     case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_REL:
     382               0 :       aResult[5] = aStart[5];
     383               0 :       aResult[6] = aStart[6];
     384               0 :       AdjustSegmentForRelativeness(adjustmentType, aResult + 5, aState);
     385                 :       // fall through
     386                 :     case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_ABS:
     387                 :     case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_REL:
     388                 :     case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
     389                 :     case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
     390               0 :       aResult[3] = aStart[3];
     391               0 :       aResult[4] = aStart[4];
     392               0 :       AdjustSegmentForRelativeness(adjustmentType, aResult + 3, aState);
     393                 :       // fall through
     394                 :     case nsIDOMSVGPathSeg::PATHSEG_MOVETO_ABS:
     395                 :     case nsIDOMSVGPathSeg::PATHSEG_MOVETO_REL:
     396                 :     case nsIDOMSVGPathSeg::PATHSEG_LINETO_ABS:
     397                 :     case nsIDOMSVGPathSeg::PATHSEG_LINETO_REL:
     398                 :     case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
     399                 :     case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
     400               0 :       aResult[1] = aStart[1];
     401               0 :       aResult[2] = aStart[2];
     402               0 :       AdjustSegmentForRelativeness(adjustmentType, aResult + 1, aState);
     403               0 :       break;
     404                 :   }
     405                 : 
     406               0 :   SVGPathSegUtils::TraversePathSegment(pResultSegmentBegin, aState);
     407               0 :   aStart += segmentLengthIncludingType;
     408               0 :   aEnd += segmentLengthIncludingType;
     409               0 :   aResult += segmentLengthIncludingType;
     410                 : }
     411                 : 
     412                 : static void
     413               0 : ConvertAllPathSegmentData(SVGPathDataAndOwner::const_iterator aStart,
     414                 :                           SVGPathDataAndOwner::const_iterator aStartDataEnd,
     415                 :                           SVGPathDataAndOwner::const_iterator aEnd,
     416                 :                           SVGPathDataAndOwner::const_iterator aEndDataEnd,
     417                 :                           SVGPathDataAndOwner::iterator aResult)
     418                 : {
     419               0 :   SVGPathTraversalState state;
     420               0 :   state.mode = SVGPathTraversalState::eUpdateOnlyStartAndCurrentPos;
     421               0 :   while (aStart < aStartDataEnd && aEnd < aEndDataEnd) {
     422               0 :     ConvertPathSegmentData(aStart, aEnd, aResult, state);
     423                 :   }
     424               0 :   NS_ABORT_IF_FALSE(aStart == aStartDataEnd && aEnd == aEndDataEnd,
     425                 :                     "Failed to convert all path segment data! (Corrupt?)");
     426               0 : }
     427                 : 
     428                 : nsresult
     429               0 : SVGPathSegListSMILType::Add(nsSMILValue& aDest,
     430                 :                             const nsSMILValue& aValueToAdd,
     431                 :                             PRUint32 aCount) const
     432                 : {
     433               0 :   NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL type");
     434               0 :   NS_PRECONDITION(aValueToAdd.mType == this, "Incompatible SMIL type");
     435                 : 
     436                 :   SVGPathDataAndOwner& dest =
     437               0 :     *static_cast<SVGPathDataAndOwner*>(aDest.mU.mPtr);
     438                 :   const SVGPathDataAndOwner& valueToAdd =
     439               0 :     *static_cast<const SVGPathDataAndOwner*>(aValueToAdd.mU.mPtr);
     440                 : 
     441               0 :   if (valueToAdd.IsIdentity()) { // Adding identity value - no-op
     442               0 :     return NS_OK;
     443                 :   }
     444                 : 
     445               0 :   if (!dest.IsIdentity()) {
     446                 :     // Neither value is identity; make sure they're compatible.
     447               0 :     NS_ABORT_IF_FALSE(dest.Element() == valueToAdd.Element(),
     448                 :                       "adding values from different elements...?");
     449                 : 
     450               0 :     PathInterpolationResult check = CanInterpolate(dest, valueToAdd);
     451               0 :     if (check == eCannotInterpolate) {
     452                 :       // nsSVGUtils::ReportToConsole - can't add path segment lists with
     453                 :       // different numbers of segments, with arcs that have different flag
     454                 :       // values, or with incompatible segment types.
     455               0 :       return NS_ERROR_FAILURE;
     456                 :     }
     457               0 :     if (check == eRequiresConversion) {
     458                 :       // Convert dest, in-place, to match the types in valueToAdd:
     459               0 :       ConvertAllPathSegmentData(dest.begin(), dest.end(),
     460                 :                                 valueToAdd.begin(), valueToAdd.end(),
     461               0 :                                 dest.begin());
     462                 :     }
     463                 :   }
     464                 : 
     465               0 :   AddWeightedPathSegLists(1.0, dest, aCount, valueToAdd, dest);
     466                 : 
     467               0 :   return NS_OK;
     468                 : }
     469                 : 
     470                 : nsresult
     471               0 : SVGPathSegListSMILType::ComputeDistance(const nsSMILValue& aFrom,
     472                 :                                         const nsSMILValue& aTo,
     473                 :                                         double& aDistance) const
     474                 : {
     475               0 :   NS_PRECONDITION(aFrom.mType == this, "Unexpected SMIL type");
     476               0 :   NS_PRECONDITION(aTo.mType == this, "Incompatible SMIL type");
     477                 : 
     478                 :   // See https://bugzilla.mozilla.org/show_bug.cgi?id=522306#c18
     479                 : 
     480                 :   // nsSVGUtils::ReportToConsole
     481               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     482                 : }
     483                 : 
     484                 : nsresult
     485               0 : SVGPathSegListSMILType::Interpolate(const nsSMILValue& aStartVal,
     486                 :                                     const nsSMILValue& aEndVal,
     487                 :                                     double aUnitDistance,
     488                 :                                     nsSMILValue& aResult) const
     489                 : {
     490               0 :   NS_PRECONDITION(aStartVal.mType == aEndVal.mType,
     491                 :                   "Trying to interpolate different types");
     492               0 :   NS_PRECONDITION(aStartVal.mType == this,
     493                 :                   "Unexpected types for interpolation");
     494               0 :   NS_PRECONDITION(aResult.mType == this, "Unexpected result type");
     495                 : 
     496                 :   const SVGPathDataAndOwner& start =
     497               0 :     *static_cast<const SVGPathDataAndOwner*>(aStartVal.mU.mPtr);
     498                 :   const SVGPathDataAndOwner& end =
     499               0 :     *static_cast<const SVGPathDataAndOwner*>(aEndVal.mU.mPtr);
     500                 :   SVGPathDataAndOwner& result =
     501               0 :     *static_cast<SVGPathDataAndOwner*>(aResult.mU.mPtr);
     502               0 :   NS_ABORT_IF_FALSE(result.IsIdentity(),
     503                 :                     "expecting outparam to start out as identity");
     504                 : 
     505               0 :   PathInterpolationResult check = CanInterpolate(start, end); 
     506                 : 
     507               0 :   if (check == eCannotInterpolate) {
     508                 :     // nsSVGUtils::ReportToConsole - can't interpolate path segment lists with
     509                 :     // different numbers of segments, with arcs with different flag values, or
     510                 :     // with incompatible segment types.
     511               0 :     return NS_ERROR_FAILURE;
     512                 :   }
     513                 : 
     514               0 :   const SVGPathDataAndOwner* startListToUse = &start;
     515               0 :   if (check == eRequiresConversion) {
     516                 :     // Can't convert |start| in-place, since it's const. Instead, we copy it
     517                 :     // into |result|, converting the types as we go, and use that as our start.
     518               0 :     DebugOnly<bool> success = result.SetLength(end.Length());
     519               0 :     NS_ABORT_IF_FALSE(success, "infallible nsTArray::SetLength should succeed");
     520               0 :     result.SetElement(end.Element()); // propagate target element info!
     521                 : 
     522                 :     ConvertAllPathSegmentData(start.begin(), start.end(),
     523                 :                               end.begin(), end.end(),
     524               0 :                               result.begin());
     525               0 :     startListToUse = &result;
     526                 :   }
     527                 : 
     528                 :   AddWeightedPathSegLists(1.0 - aUnitDistance, *startListToUse,
     529               0 :                           aUnitDistance, end, result);
     530                 : 
     531               0 :   return NS_OK;
     532                 : }
     533                 : 
     534            4392 : } // namespace mozilla

Generated by: LCOV version 1.7