Backout 12b227a42623, bug 653928 (changes to SVG arc path segment animation).
authorJonathan Watt <jwatt@jwatt.org>
Wed, 02 Nov 2011 19:15:32 +0000
changeset 80272 ae79993b6eb9ef433a823c1a20cca4188de27730
parent 80271 c9a39f3b26e1a5b030e1517d0c11bf7f505df769
child 80273 ab1bb3e98ff918d9a13719d591bdbee515ead7d0
push idunknown
push userunknown
push dateunknown
bugs653928
milestone10.0a1
backs out12b227a42623e4b1a399775023b177d3943ff0eb
Backout 12b227a42623, bug 653928 (changes to SVG arc path segment animation).
content/svg/content/src/SVGPathSegListSMILType.cpp
content/svg/content/test/test_pathAnimInterpolation.xhtml
--- a/content/svg/content/src/SVGPathSegListSMILType.cpp
+++ b/content/svg/content/src/SVGPathSegListSMILType.cpp
@@ -90,16 +90,31 @@ SVGPathSegListSMILType::IsEqual(const ns
 {
   NS_PRECONDITION(aLeft.mType == aRight.mType, "Incompatible SMIL types");
   NS_PRECONDITION(aLeft.mType == this, "Unexpected type for SMIL value");
 
   return *static_cast<const SVGPathDataAndOwner*>(aLeft.mU.mPtr) ==
          *static_cast<const SVGPathDataAndOwner*>(aRight.mU.mPtr);
 }
 
+static bool
+ArcFlagsDiffer(SVGPathDataAndOwner::const_iterator aPathData1,
+               SVGPathDataAndOwner::const_iterator aPathData2)
+{
+  NS_ABORT_IF_FALSE
+    (SVGPathSegUtils::IsArcType(SVGPathSegUtils::DecodeType(aPathData1[0])),
+                                "ArcFlagsDiffer called with non-arc segment");
+  NS_ABORT_IF_FALSE
+    (SVGPathSegUtils::IsArcType(SVGPathSegUtils::DecodeType(aPathData2[0])),
+                                "ArcFlagsDiffer called with non-arc segment");
+
+  return aPathData1[LARGE_ARC_FLAG_IDX] != aPathData2[LARGE_ARC_FLAG_IDX] ||
+         aPathData1[SWEEP_FLAG_IDX]     != aPathData2[SWEEP_FLAG_IDX];
+}
+
 enum PathInterpolationResult {
   eCannotInterpolate,
   eRequiresConversion,
   eCanInterpolate
 };
 
 static PathInterpolationResult
 CanInterpolate(const SVGPathDataAndOwner& aStart,
@@ -119,16 +134,22 @@ CanInterpolate(const SVGPathDataAndOwner
   SVGPathDataAndOwner::const_iterator pEnd = aEnd.begin();
   SVGPathDataAndOwner::const_iterator pStartDataEnd = aStart.end();
   SVGPathDataAndOwner::const_iterator pEndDataEnd = aEnd.end();
 
   while (pStart < pStartDataEnd && pEnd < pEndDataEnd) {
     PRUint32 startType = SVGPathSegUtils::DecodeType(*pStart);
     PRUint32 endType = SVGPathSegUtils::DecodeType(*pEnd);
 
+    if (SVGPathSegUtils::IsArcType(startType) &&
+        SVGPathSegUtils::IsArcType(endType) &&
+        ArcFlagsDiffer(pStart, pEnd)) {
+      return eCannotInterpolate;
+    }
+
     if (startType != endType) {
       if (!SVGPathSegUtils::SameTypeModuloRelativeness(startType, endType)) {
         return eCannotInterpolate;
       }
 
       result = eRequiresConversion;
     }
 
@@ -189,32 +210,35 @@ AddWeightedPathSegs(double aCoeff1,
 {
   NS_ABORT_IF_FALSE(aSeg2, "2nd segment must be non-null");
   NS_ABORT_IF_FALSE(aResultSeg, "result segment must be non-null");
 
   PRUint32 segType = SVGPathSegUtils::DecodeType(aSeg2[0]);
   NS_ABORT_IF_FALSE(!aSeg1 || SVGPathSegUtils::DecodeType(*aSeg1) == segType,
                     "unexpected segment type");
 
+  // FIRST: Directly copy the arguments that don't make sense to add.
   aResultSeg[0] = aSeg2[0];  // encoded segment type
 
-  // FIRST: Add all the arguments.
+  bool isArcType = SVGPathSegUtils::IsArcType(segType);
+  if (isArcType) {
+    // Copy boolean arc flags.
+    NS_ABORT_IF_FALSE(!aSeg1 || !ArcFlagsDiffer(aSeg1, aSeg2),
+                      "Expecting arc flags to match");
+    aResultSeg[LARGE_ARC_FLAG_IDX] = aSeg2[LARGE_ARC_FLAG_IDX];
+    aResultSeg[SWEEP_FLAG_IDX]     = aSeg2[SWEEP_FLAG_IDX];
+  }
+
+  // SECOND: Add the arguments that are supposed to be added.
   // (The 1's below are to account for segment type)
   PRUint32 numArgs = SVGPathSegUtils::ArgCountForType(segType);
   for (PRUint32 i = 1; i < 1 + numArgs; ++i) {
-    aResultSeg[i] = (aSeg1 ? aCoeff1 * aSeg1[i] : 0.0) + aCoeff2 * aSeg2[i];
-  }
-
-  // SECOND: ensure non-zero flags become 1.
-  if (SVGPathSegUtils::IsArcType(segType)) {
-    if (aResultSeg[LARGE_ARC_FLAG_IDX] != 0.0f) {
-      aResultSeg[LARGE_ARC_FLAG_IDX] = 1.0f;
-    }
-    if (aResultSeg[SWEEP_FLAG_IDX] != 0.0f) {
-      aResultSeg[SWEEP_FLAG_IDX] = 1.0f;
+     // Need to skip arc flags for arc-type segments. (already handled them)
+    if (!(isArcType && (i == LARGE_ARC_FLAG_IDX || i == SWEEP_FLAG_IDX))) {
+      aResultSeg[i] = (aSeg1 ? aCoeff1 * aSeg1[i] : 0.0) + aCoeff2 * aSeg2[i];
     }
   }
 
   // FINALLY: Shift iterators forward. ("1+" is to include seg-type)
   if (aSeg1) {
     aSeg1 += 1 + numArgs;
   }
   aSeg2 += 1 + numArgs;
--- a/content/svg/content/test/test_pathAnimInterpolation.xhtml
+++ b/content/svg/content/test/test_pathAnimInterpolation.xhtml
@@ -133,20 +133,20 @@ var gSuffixes = {
   LL: [[10, 20], [30, 40], [20, 30], [30, 50]],
   ll: [[10, 20], [30, 40], [20, 30], [30, 50]],
   CC: [[10, 20, 30, 40, 50, 60], [70, 80, 90, 100, 110, 120],
        [40, 50, 60, 70, 80, 90], [50, 70, 90, 110, 130, 150]],
   cc: [[10, 20, 30, 40, 50, 60], [70, 80, 90, 100, 110, 120],
        [40, 50, 60, 70, 80, 90], [50, 70, 90, 110, 130, 150]],
   QQ: [[10, 20, 30, 40], [50, 60, 70, 80], [30, 40, 50, 60], [40, 60, 80, 100]],
   qq: [[10, 20, 30, 40], [50, 60, 70, 80], [30, 40, 50, 60], [40, 60, 80, 100]],
-  AA: [[10, 20, 30, 1, 0, 40, 50], [60, 70, 80, 0, 0, 90, 100],
-       [35, 45, 55, 1, 0, 65, 75], [45, 65, 85, 1, 0, 105, 125]],
-  aa: [[10, 20, 30, 0, 1, 40, 50], [60, 70, 80, 0, 0, 90, 100],
-       [35, 45, 55, 0, 1, 65, 75], [45, 65, 85, 0, 1, 105, 125]],
+  AA: [[10, 20, 30, 0, 0, 40, 50], [60, 70, 80, 0, 0, 90, 100],
+       [35, 45, 55, 0, 0, 65, 75], [45, 65, 85, 0, 0, 105, 125]],
+  aa: [[10, 20, 30, 0, 0, 40, 50], [60, 70, 80, 0, 0, 90, 100],
+       [35, 45, 55, 0, 0, 65, 75], [45, 65, 85, 0, 0, 105, 125]],
   HH: [[10], [20], [15], [25]],
   hh: [[10], [20], [15], [25]],
   VV: [[10], [20], [15], [25]],
   vv: [[10], [20], [15], [25]],
   SS: [[10, 20, 30, 40], [50, 60, 70, 80], [30, 40, 50, 60], [40, 60, 80, 100]],
   ss: [[10, 20, 30, 40], [50, 60, 70, 80], [30, 40, 50, 60], [40, 60, 80, 100]],
   TT: [[10, 20], [30, 40], [20, 30], [30, 50]],
   tt: [[10, 20], [30, 40], [20, 30], [30, 50]],
@@ -281,16 +281,27 @@ function run()
 
       for each (let prefixEntry in gPrefixes) {
         let [prefixLength, prefix] = prefixEntry;
         addTest(prefixLength, prefix, fromType, fromArguments,
 	        toType, toArguments, toType, expectedArguments, additive);
       }
     }
 
+    // Test that differences in arc flag parameters cause the
+    // interpolation/addition not to occur.
+    addTest(1, "M100,100",
+            "A", [10, 20, 30, 0, 0, 40, 50],
+            "a", [60, 70, 80, 0, 1, 90, 100],
+	    "a", [60, 70, 80, 0, 1, 90, 100], additive);
+    addTest(1, "M100,100",
+            "A", [10, 20, 30, 0, 0, 40, 50],
+            "a", [60, 70, 80, 1, 0, 90, 100],
+	    "a", [60, 70, 80, 1, 0, 90, 100], additive);
+
     // Test all pairs of segment types that cannot be interpolated between.
     for each (let fromType in gTypes) {
       let fromArguments = generatePathSegmentArguments(fromType, 0);
       for each (let toType in gTypes) {
         if (!isValidInterpolation(fromType, toType)) {
           let toArguments = generatePathSegmentArguments(toType, 1000);
           addTest(1, "M100,100", fromType, fromArguments,
 	          toType, toArguments, toType, toArguments, additive);