Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  test_pathAnimInterpolation.xhtml   Sprache: unbekannt

 
<html xmlns="http://www.w3.org/1999/xhtml">
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=619498
-->
<head>
  <title>Test interpolation between different path segment types</title>
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=619498">Mozilla Bug 619498</a>
<svg xmlns="http://www.w3.org/2000/svg" id="svg" visibility="hidden"
     onload="this.pauseAnimations()"/>
<script type="application/javascript"><![CDATA[
SimpleTest.waitForExplicitFinish();

var gSVG = document.getElementById("svg");

// Array of all subtests to run.  This is populated by addTest.
var gTests = [];

// Array of all path segment types.
var gTypes = "ZMmLlCcQqAaHhVvSsTt".split("");

// Property names on the SVGPathSeg objects for the given segment type, in the
// order that they would appear in a path data string.
var gArgumentNames = {
  Z: [],
  M: ["x", "y"],
  L: ["x", "y"],
  C: ["x1", "y1", "x2", "y2", "x", "y"],
  Q: ["x1", "y1", "x", "y"],
  A: ["r1", "r2", "angle", "largeArcFlag", "sweepFlag", "x", "y"],
  H: ["x"],
  V: ["y"],
  S: ["x2", "y2", "x", "y"],
  T: ["x", "y"],
};

// All of these prefixes leave the current point at 100,100.  Some of them
// affect the implied control point if followed by a smooth quadratic or
// cubic segment, but no valid interpolations depend on those control points.
var gPrefixes = [
  [1, "M100,100"],
  [2, "M50,50 M100,100"],
  [2, "M50,50 m50,50"],
  [2, "M50,50 L100,100"],
  [2, "M50,50 l50,50"],
  [3, "M50,50 H100 V100"],
  [3, "M50,50 h50 V100"],
  [3, "M50,50 H100 v50"],
  [2, "M50,50 A10,10,10,0,0,100,100"],
  [2, "M50,50 a10,10,10,0,0,50,50"],
  [4, "M50,50 l50,50 Z m50,50"],

  // These leave the quadratic implied control point at 125,125.
  [2, "M50,50 Q75,75,100,100"],
  [2, "M50,50 q25,25,50,50"],
  [2, "M75,75 T100,100"],
  [2, "M75,75 t25,25"],
  [3, "M50,50 T62.5,62.5 t37.5,37.5"],
  [3, "M50,50 T62.5,62.5 T100,100"],
  [3, "M50,50 t12.5,12.5 t37.5,37.5"],
  [3, "M50,50 t12.5,12.5 T100,100"],
  [3, "M50,50 Q50,50,62.5,62.5 t37.5,37.5"],
  [3, "M50,50 Q50,50,62.5,62.5 T100,100"],
  [3, "M50,50 q0,0,12.5,12.5 t37.5,37.5"],
  [3, "M50,50 q0,0,12.5,12.5 T100,100"],

  // These leave the cubic implied control point at 125,125.
  [2, "M50,50 C10,10,75,75,100,100"],
  [2, "M50,50 c10,10,25,25,50,50"],
  [2, "M50,50 S75,75,100,100"],
  [2, "M50,50 s25,25,50,50"],
  [3, "M50,50 S10,10,75,75 S75,75,100,100"],
  [3, "M50,50 S10,10,75,75 s0,0,25,25"],
  [3, "M50,50 s10,10,25,25 S75,75,100,100"],
  [3, "M50,50 s10,10,25,25 s0,0,25,25"],
  [3, "M50,50 C10,10,20,20,75,75 S75,75,100,100"],
  [3, "M50,50 C10,10,20,20,75,75 s0,0,25,25"],
  [3, "M50,50 c10,10,20,20,25,25 S75,75,100,100"],
  [3, "M50,50 c10,10,20,20,25,25 s0,0,25,25"],
];

// These are all of the suffixes whose result is not dependent on whether the
// preceding segment types are quadratic or cubic types.  Each entry is:
//
//   "<fromType><toType>": [fromArguments,
//                          toArguments,
//                          expectedArguments,
//                          expectedArgumentsAdditive]
//
// As an example:
//
//   "Mm": [[10, 20], [30, 40], [-30, -20], [-120, -100]]
//
// This will testing interpolating between "M10,20" and "m30,40". All of the
// these tests assume that the current point is left at 100,100.  So the above
// entry represents two kinds of tests, one where additive and one not:
//
//   <path d="... M10,20">
//     <animate attributeName="d" from="... M10,20" to="... m30,40"/>
//   </path>
//
// and
//
//   <path d="... M10,20">
//     <animate attributeName="d" from="... M10,20" to="... m30,40"
//              additive="sum"/>
//   </path>
//
// where the "..." is some prefix that leaves the current point at 100,100.
// Each of the suffixes here in gSuffixes will be paired with each of the
// prefixes in gPrefixes, all of which leave the current point at 100,100.
// (Thus the above two tests for interpolating between "M" and "m" will be
// performed many times, with different preceding commands.)
//
// The expected result of the non-additive test is "m-30,-20".  Since the
// animation is from an absolute moveto to a relative moveto, we first
// convert the "M10,20" into its relative form, which is "m-90,-80" due to the
// current point being 100,100.  Half way through the animation between
// "m-90,-80" and "m30,40" is thus "m-30,-20".
//
// The expected result of the additive test is "m-120,-100".  We take the
// halfway value of the animation, "m-30,-20" and add it on to the underlying
// value.  Since the underlying value "M10,20" is an absolute moveto, we first
// convert it to relative, "m-90,-80", and then add the "m-30,-20" to it,
// giving us the result "m-120,-100".
var gSuffixes = {
  // Same path segment type, no conversion required.
  MM: [[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]],
  QQ: [[10, 20, 30, 40], [50, 60, 70, 80], [30, 40, 50, 60], [40, 60, 80, 100]],
  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]],
  VV: [[10], [20], [15], [25]],
  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]],

  // Relative <-> absolute conversion.
  mM: [[10, 20], [30, 40], [70, 80], [180, 200]],
  lL: [[10, 20], [30, 40], [70, 80], [180, 200]],
  cC: [[10, 20, 30, 40, 50, 60], [70, 80, 90, 100, 110, 120],
       [90, 100, 110, 120, 130, 140], [200, 220, 240, 260, 280, 300]],
  qQ: [[10, 20, 30, 40], [50, 60, 70, 80],
       [80, 90, 100, 110], [190, 210, 230, 250]],
  aA: [[10, 20, 30, 0, 0, 40, 50], [60, 70, 80, 0, 0, 90, 100],
       [35, 45, 55, 0, 0, 115, 125], [45, 65, 85, 0, 0, 255, 275]],
  hH: [[10], [20], [65], [175]],
  vV: [[10], [20], [65], [175]],
  tT: [[10, 20], [30, 40], [70, 80], [180, 200]],
  sS: [[10, 20, 30, 40], [50, 60, 70, 80],
       [80, 90, 100, 110], [190, 210, 230, 250]],
};

// Returns an array of property names that exist on an SVGPathSeg object
// corresponding to the given segment type, in the order that they would
// be present in a path data string.
function argumentNames(aType) {
  return gArgumentNames[aType.toUpperCase()];
}

// Creates and returns a new element and sets some attributes on it.
function newElement(aNamespaceURI, aLocalName, aAttributes) {
  var e = document.createElementNS(aNamespaceURI, aLocalName);
  if (aAttributes) {
    for (let [name, value] of Object.entries(aAttributes)) {
      e.setAttribute(name, value);
    }
  }
  return e;
}

// Creates and returns a new SVG element and sets some attributes on it.
function newSVGElement(aLocalName, aAttributes) {
  return newElement("http://www.w3.org/2000/svg", aLocalName, aAttributes);
}

// Creates a subtest and adds it to the document.
//
// * aPrefixLength/aPrefix              the prefix to use
// * aFromType/aFromArguments           the segment to interpolate from
// * aToType/aToArguments               the segment to interpolate to
// * aExpectedType/aExpectedArguments   the expected result of the interpolated
//                                        segment half way through the animation
//                                        duration
// * aAdditive                          whether the subtest is for an additive
//                                        animation
function addTest(aPrefixLength, aPrefix, aFromType, aFromArguments,
                 aToType, aToArguments, aExpectedType, aExpectedArguments,
                 aAdditive) {
  var fromPath = aPrefix + aFromType + aFromArguments,
      toPath = aPrefix + aToType + aToArguments;

  var path = newSVGElement("path", { d: fromPath });
  var animate =
    newSVGElement("animate", { attributeName: "d",
                               from: fromPath,
                               to: toPath,
                               dur: "8s",
                               additive: aAdditive ? "sum" : "replace" });
  path.appendChild(animate);
  gSVG.appendChild(path);

  gTests.push({ element: path,
                prefixLength: aPrefixLength,
                from: fromPath,
                to: toPath,
                toType: aToType,
                expectedType: aExpectedType,
                expected: aExpectedArguments,
                usesAddition: aAdditive });
}

// Generates an array of path segment arguments for the given type.  aOffset
// is a number to add on to all non-Boolean segment arguments.
function generatePathSegmentArguments(aType, aOffset) {
  var args = new Array(argumentNames(aType).length);
  for (let i = 0; i < args.length; i++) {
    args[i] = i * 10 + aOffset;
  }
  if (aType == "A" || aType == "a") {
    args[3] = 0;
    args[4] = 0;
  }
  return args;
}

// Returns whether interpolating between the two given types is valid.
function isValidInterpolation(aFromType, aToType) {
  return aFromType.toUpperCase() == aToType.toUpperCase();
}

// Runs the test.
function run() {
  for (let additive of [false, true]) {
    let indexOfExpectedArguments = additive ? 3 : 2;

    // Add subtests for each combination of prefix and suffix, and additive
    // or not.
    for (let [typePair, suffixEntry] of Object.entries(gSuffixes)) {
      let fromType = typePair[0],
          toType = typePair[1],
          fromArguments = suffixEntry[0],
          toArguments = suffixEntry[1],
          expectedArguments = suffixEntry[indexOfExpectedArguments];

      for (let prefixEntry of gPrefixes) {
        let [prefixLength, prefix] = prefixEntry;
        addTest(prefixLength, prefix, fromType, fromArguments,
                toType, toArguments, toType, expectedArguments, additive);
      }
    }

    // Test all pairs of segment types that cannot be interpolated between.
    for (let fromType of gTypes) {
      let fromArguments = generatePathSegmentArguments(fromType, 0);
      for (let toType of gTypes) {
        if (!isValidInterpolation(fromType, toType)) {
          let toArguments = generatePathSegmentArguments(toType, 1000);
          addTest(1, "M100,100", fromType, fromArguments,
          toType, toArguments, toType, toArguments, additive);
        }
      }
    }
  }

  // Move the document time to half way through the animations.
  gSVG.setCurrentTime(4);

  // Inspect the results of each subtest.
  for (let test of gTests) {
    let list = test.element.getPathData();
    is(list.length, test.prefixLength + 1,
       "Length of animatedPathSegList for interpolation " +
         (test.usesAddition ? "with addition " : "") +
         " from " + test.from + " to " + test.to);

    let seg = list.at(-1);

    let actual = [];
    for (let i = 0; i < test.expected.length; i++) {
      actual.push(seg.values[i]);
    }

    is(seg.type + actual, test.expectedType + test.expected,
       "Path segment for interpolation " +
         (test.usesAddition ? "with addition " : "") +
         " from " + test.from + " to " + test.to);
  }

  // Clear all the tests. We have tons of them attached to the DOM and refresh driver tick will
  // go through them all by calling animation controller.
  gSVG.remove();

  SimpleTest.finish();
}

window.addEventListener("load", run);
]]></script>
</body>
</html>

[ Dauer der Verarbeitung: 0.2 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge