dom/smil/test/test_smilChangeAfterFrozen.xhtml

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 <html xmlns="http://www.w3.org/1999/xhtml">
     2 <head>
     3   <title>Test for SMIL when things change after an animation is frozen</title>
     4   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
     5   <script type="text/javascript" src="smilTestUtils.js"></script>
     6   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
     7 </head>
     8 <body>
     9 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=533291">Mozilla Bug 533291</a>
    10 <p id="display"></p>
    11 <!-- Bug 628848: The following should be display: none but we currently don't
    12      handle percentage lengths properly when the whole fragment is display: none
    13      -->
    14 <div id="content" style="visibility: hidden">
    15 <svg id="svg" xmlns="http://www.w3.org/2000/svg" width="120px" height="120px"
    16      onload="this.pauseAnimations()">
    17   <g id="circleParent">
    18     <circle cx="0" cy="20" r="15" fill="blue" id="circle"/>
    19   </g>
    20 </svg>
    21 </div>
    22 <pre id="test">
    23 <script class="testbody" type="text/javascript">
    24 <![CDATA[
    25 /** Test for SMIL values that are context-sensitive **/
    27 /* See bugs 533291 and 562815.
    29    The format of each test is basically:
    30    1) create some animated and frozen state
    31    2) test the animated values
    32    3) change the context
    33    4) test that context-sensitive animation values have changed
    35    Ideally, after changing the context (3), the animated state would instantly
    36    update. However, this is not currently the case for many situations.
    38      For CSS properties we have bug 545282 - In animations involving 'inherit'
    39      / 'currentColor', changes to inherited value / 'color' don't show up in
    40      animated value immediately
    42      For SVG lengths we have bug 508206 - Relative units used in
    43      animation don't update immediately
    45      (There are a few of todo_is's in the following tests so that if those bugs
    46      are ever resolved we'll know to update this test case accordingly.)
    48    So in between (3) and (4) we force a sample. This is currently done by
    49    calling SVGSVGElement.setCurrentTime with the same current time which has the
    50    side effect of forcing a sample.
    52    What we *are* testing is that we're not too zealous with caching animation
    53    values whilst in the frozen state. Normally we'd say, "Hey, we're frozen,
    54    let's just use the same animation result as last time" but for some
    55    context-sensitive animation values that doesn't work.
    56 */
    58 /* Global Variables */
    59 const SVGNS = "http://www.w3.org/2000/svg";
    61 // Animation parameters -- not used for <set> animation
    62 const ANIM_DUR = "4s";
    63 const TIME_ANIM_END = "4";
    64 const TIME_AFTER_ANIM_END = "5";
    66 const gSvg = document.getElementById("svg");
    67 const gCircle = document.getElementById("circle");
    68 const gCircleParent = document.getElementById("circleParent");
    70 SimpleTest.waitForExplicitFinish();
    72 // MAIN FUNCTION
    73 // -------------
    75 function main()
    76 {
    77   ok(gSvg.animationsPaused(), "should be paused by <svg> load handler");
    78   is(gSvg.getCurrentTime(), 0, "should be paused at 0 in <svg> load handler");
    80   const tests =
    81     [ testBaseValueChange,
    82       testCurrentColorChange,
    83       testCurrentColorChangeUsingStyle,
    84       testCurrentColorChangeOnFallback,
    85       testInheritChange,
    86       testInheritChangeUsingStyle,
    87       testEmUnitChangeOnProp,
    88       testEmUnitChangeOnPropBase,
    89       testEmUnitChangeOnLength,
    90       testPercentUnitChangeOnProp,
    91       testPercentUnitChangeOnLength,
    92       testRelativeFontSize,
    93       testRelativeFontWeight,
    94       testRelativeFont,
    95       testCalcFontSize,
    96       testDashArray,
    97       testClip
    98      ];
   100   while (tests.length) {
   101     tests.shift()();
   102   }
   103   SimpleTest.finish();
   104 }
   106 // HELPER FUNCTIONS
   107 // ----------------
   108 function createAnimSetTo(attrName, toVal)
   109 {
   110   var anim = document.createElementNS(SVGNS,"set");
   111   anim.setAttribute("attributeName", attrName);
   112   anim.setAttribute("to", toVal);
   113   return gCircle.appendChild(anim);
   114 }
   116 function createAnimBy(attrName, byVal)
   117 {
   118   var anim = document.createElementNS(SVGNS,"animate");
   119   anim.setAttribute("attributeName", attrName);
   120   anim.setAttribute("dur", ANIM_DUR);
   121   anim.setAttribute("begin","0s");
   122   anim.setAttribute("by", byVal);
   123   anim.setAttribute("fill", "freeze");
   124   return gCircle.appendChild(anim);
   125 }
   127 function createAnimFromTo(attrName, fromVal, toVal)
   128 {
   129   var anim = document.createElementNS(SVGNS,"animate");
   130   anim.setAttribute("attributeName", attrName);
   131   anim.setAttribute("dur", ANIM_DUR);
   132   anim.setAttribute("begin","0s");
   133   anim.setAttribute("from", fromVal);
   134   anim.setAttribute("to", toVal);
   135   anim.setAttribute("fill", "freeze");
   136   return gCircle.appendChild(anim);
   137 }
   139 // Common setup code for each test function: seek to 0, and make sure
   140 // the previous test cleaned up its animations.
   141 function setupTest() {
   142   gSvg.setCurrentTime(0);
   143   if (gCircle.firstChild) {
   144     ok(false, "Previous test didn't clean up after itself.");
   145   }
   146 }
   148 // THE TESTS
   149 // ---------
   151 function testBaseValueChange()
   152 {
   153   setupTest();
   154   var anim = createAnimBy("cx", "50");
   155   gSvg.setCurrentTime(TIME_ANIM_END);
   156   is(gCircle.cx.animVal.value, 50,
   157      "Checking animated cx as anim ends");
   159   gSvg.setCurrentTime(TIME_AFTER_ANIM_END);
   160   is(gCircle.cx.animVal.value, 50,
   161      "Checking animated cx after anim ends");
   163   gCircle.setAttribute("cx", 20);
   164   is(gCircle.cx.animVal.value, 70,
   165      "Checking animated cx after anim ends & after changing base val");
   167   anim.parentNode.removeChild(anim); // clean up
   168 }
   170 function testCurrentColorChange()
   171 {
   172   gCircle.setAttribute("color", "red"); // At first: currentColor=red
   173   var anim = createAnimSetTo("fill", "currentColor");
   175   gSvg.setCurrentTime(0); // trigger synchronous sample
   176   is(SMILUtil.getComputedStyleSimple(gCircle, "fill"), "rgb(255, 0, 0)",
   177      "Checking animated fill=currentColor after animating");
   179   gCircle.setAttribute("color", "lime"); // Change: currentColor=lime
   180   // Bug 545282: We should really detect this change and update immediately but
   181   // currently we don't until we get sampled again
   182   todo_is(SMILUtil.getComputedStyleSimple(gCircle, "fill"), "rgb(0, 255, 0)",
   183      "Checking animated fill=currentColor after updating context but before " +
   184      "sampling");
   185   gSvg.setCurrentTime(0);
   186   is(SMILUtil.getComputedStyleSimple(gCircle, "fill"), "rgb(0, 255, 0)",
   187      "Checking animated fill=currentColor after updating context");
   189   // Clean up
   190   gCircle.removeAttribute("color");
   191   gCircle.removeChild(gCircle.firstChild);
   192 }
   194 function testCurrentColorChangeUsingStyle()
   195 {
   196   setupTest();
   197   gCircle.setAttribute("style", "color: red"); // At first: currentColor=red
   198   var anim = createAnimSetTo("fill", "currentColor");
   200   gSvg.setCurrentTime(0);
   201   is(SMILUtil.getComputedStyleSimple(gCircle, "fill"), "rgb(255, 0, 0)",
   202      "Checking animated fill=currentColor after animating (using style attr)");
   204   gCircle.setAttribute("style", "color: lime"); // Change: currentColor=lime
   205   gSvg.setCurrentTime(0);
   206   is(SMILUtil.getComputedStyleSimple(gCircle, "fill"), "rgb(0, 255, 0)",
   207      "Checking animated fill=currentColor after updating context "
   208      + "(using style attr)");
   210   // Clean up
   211   gCircle.removeAttribute("style");
   212   gCircle.removeChild(gCircle.firstChild);
   213 }
   215 function getFallbackColor(pServerStr)
   216 {
   217   return pServerStr.substr(pServerStr.indexOf(" ")+1);
   218 }
   220 function testCurrentColorChangeOnFallback()
   221 {
   222   setupTest();
   223   gCircle.setAttribute("color", "red"); // At first: currentColor=red
   224   var anim = createAnimSetTo("fill", "url(#missingGrad) currentColor");
   226   gSvg.setCurrentTime(0);
   227   var fallback =
   228     getFallbackColor(SMILUtil.getComputedStyleSimple(gCircle, "fill"));
   229   is(fallback, "rgb(255, 0, 0)",
   230      "Checking animated fallback fill=currentColor after animating");
   232   gCircle.setAttribute("color", "lime"); // Change: currentColor=lime
   233   gSvg.setCurrentTime(0);
   234   fallback = getFallbackColor(SMILUtil.getComputedStyleSimple(gCircle, "fill"));
   235   is(fallback, "rgb(0, 255, 0)",
   236      "Checking animated fallback fill=currentColor after updating context");
   238   gCircle.removeAttribute("style");
   239   gCircle.removeChild(gCircle.firstChild);
   240 }
   242 function testInheritChange()
   243 {
   244   setupTest();
   245   gCircleParent.setAttribute("fill", "red"); // At first: inherit=red
   246   var anim = createAnimSetTo("fill", "inherit");
   248   gSvg.setCurrentTime(0);
   249   is(SMILUtil.getComputedStyleSimple(gCircle, "fill"), "rgb(255, 0, 0)",
   250      "Checking animated fill=inherit after animating");
   252   gCircleParent.setAttribute("fill", "lime"); // Change: inherit=lime
   253   gSvg.setCurrentTime(0);
   254   is(SMILUtil.getComputedStyleSimple(gCircle, "fill"), "rgb(0, 255, 0)",
   255      "Checking animated fill=inherit after updating context");
   257   gCircleParent.removeAttribute("fill");
   258   gCircle.removeChild(gCircle.firstChild);
   259 }
   261 function testInheritChangeUsingStyle()
   262 {
   263   setupTest();
   264   gCircleParent.setAttribute("style", "fill: red"); // At first: inherit=red
   265   var anim = createAnimSetTo("fill", "inherit");
   267   gSvg.setCurrentTime(0);
   268   is(SMILUtil.getComputedStyleSimple(gCircle, "fill"), "rgb(255, 0, 0)",
   269      "Checking animated fill=inherit after animating (using style attr)");
   271   gCircleParent.setAttribute("style", "fill: lime"); // Change: inherit=lime
   272   gSvg.setCurrentTime(0);
   273   is(SMILUtil.getComputedStyleSimple(gCircle, "fill"), "rgb(0, 255, 0)",
   274      "Checking animated fill=inherit after updating context "
   275      + "(using style attr)");
   277   gCircleParent.removeAttribute("style");
   278   gCircle.removeChild(gCircle.firstChild);
   279 }
   281 function testEmUnitChangeOnProp()
   282 {
   283   setupTest();
   284   gCircleParent.setAttribute("font-size", "10px"); // At first: font-size: 10px
   285   var anim = createAnimSetTo("font-size", "2em");
   287   gSvg.setCurrentTime(0);
   288   is(SMILUtil.getComputedStyleSimple(gCircle, "font-size"), "20px",
   289      "Checking animated font-size=2em after animating ends");
   291   gCircleParent.setAttribute("font-size", "20px"); // Change: font-size: 20px
   292   gSvg.setCurrentTime(0);
   293   is(SMILUtil.getComputedStyleSimple(gCircle, "font-size"), "40px",
   294      "Checking animated font-size=2em after updating context");
   296   gCircleParent.removeAttribute("font-size");
   297   gCircle.removeChild(gCircle.firstChild);
   298 }
   300 function testEmUnitChangeOnPropBase()
   301 {
   302   // Test the case where the base value for our animation sandwich is
   303   // context-sensitive.
   304   // Currently, this is taken care of by the compositor which keeps a cached
   305   // base value and compares it with the current base value. This test then just
   306   // serves as a regression test in case the compositor's behaviour changes.
   307   setupTest();
   308   gSvg.setAttribute("font-size", "10px"); // At first: font-size: 10px
   309   gCircleParent.setAttribute("font-size", "1em"); // Base: 10px
   310   var anim = createAnimBy("font-size", "10px");
   312   gSvg.setCurrentTime(TIME_AFTER_ANIM_END);
   313   is(SMILUtil.getComputedStyleSimple(gCircle, "font-size"), "20px",
   314      "Checking animated font-size=20px after anim ends");
   316   gSvg.setAttribute("font-size", "20px"); // Change: font-size: 20px
   317   gSvg.setCurrentTime(TIME_AFTER_ANIM_END);
   318   is(SMILUtil.getComputedStyleSimple(gCircle, "font-size"), "30px",
   319      "Checking animated font-size=30px after updating context");
   321   gCircleParent.removeAttribute("font-size");
   322   gCircle.removeChild(gCircle.firstChild);
   323 }
   325 function testEmUnitChangeOnLength()
   326 {
   327   setupTest();
   328   gCircleParent.setAttribute("font-size", "10px"); // At first: font-size: 10px
   329   var anim = createAnimSetTo("cx", "2em");
   331   gSvg.setCurrentTime(0);
   332   is(gCircle.cx.animVal.value, 20,
   333      "Checking animated length=2em after animating");
   335   gCircleParent.setAttribute("font-size", "20px"); // Change: font-size: 20px
   336   // Bug 508206: We should really detect this change and update immediately but
   337   // currently we don't until we get sampled again
   338   todo_is(gCircle.cx.animVal.value, 40,
   339      "Checking animated length=2em after updating context but before sampling");
   341   gSvg.setCurrentTime(0);
   342   is(gCircle.cx.animVal.value, 40,
   343      "Checking animated length=2em after updating context and after " +
   344      "resampling");
   346   gCircleParent.removeAttribute("font-size");
   347   gCircle.removeChild(gCircle.firstChild);
   348 }
   350 function testPercentUnitChangeOnProp()
   351 {
   352   setupTest();
   353   gCircleParent.setAttribute("font-size", "10px"); // At first: font-size: 10px
   354   var anim = createAnimSetTo("font-size", "150%");
   356   gSvg.setCurrentTime(0);
   357   is(SMILUtil.getComputedStyleSimple(gCircle, "font-size"), "15px",
   358      "Checking animated font-size=150% after animating");
   360   gCircleParent.setAttribute("font-size", "20px"); // Change: font-size: 20px
   361   gSvg.setCurrentTime(0);
   362   is(SMILUtil.getComputedStyleSimple(gCircle, "font-size"), "30px",
   363      "Checking animated font-size=150% after updating context");
   365   gCircleParent.removeAttribute("font-size");
   366   gCircle.removeChild(gCircle.firstChild);
   367 }
   369 function testPercentUnitChangeOnLength()
   370 {
   371   setupTest();
   372   var oldHeight = gSvg.getAttribute("height");
   373   gSvg.setAttribute("height", "100px"); // At first: viewport height: 100px
   374   var anim = createAnimSetTo("cy", "100%");
   376   gSvg.setCurrentTime(0); // Force synchronous sample so animation takes effect
   377   // Due to bug 627594 (SVGLength.value for percent value lengths doesn't
   378   // reflect updated viewport until reflow) the following will fail.
   379   // Check that it does indeed fail so that when that bug is fixed this test
   380   // can be updated.
   381   todo_is(gCircle.cy.animVal.value, 100,
   382      "Checking animated length=100% after animating but before reflow");
   383   gSvg.forceRedraw();
   384   // Even after doing a reflow though we'll still fail due to bug 508206
   385   // (Relative units used in animation don't update immediately)
   386   todo_is(gCircle.cy.animVal.value, 100,
   387      "Checking animated length=100% after animating but before resampling");
   388   gSvg.setCurrentTime(0);
   389   // Now we should be up to date
   390   is(gCircle.cy.animVal.value, 100,
   391      "Checking animated length=100% after animating");
   393   gSvg.setAttribute("height", "50px"); // Change: height: 50px
   394   gSvg.forceRedraw(); // Bug 627594
   395   gSvg.setCurrentTime(0); // Bug 508206
   396   is(gCircle.cy.animVal.value, 50,
   397      "Checking animated length=100% after updating context");
   399   gSvg.setAttribute("height", oldHeight);
   400   gCircle.removeChild(gCircle.firstChild);
   401 }
   403 function testRelativeFontSize()
   404 {
   405   setupTest();
   406   gCircleParent.setAttribute("font-size", "10px"); // At first: font-size: 10px
   407   var anim = createAnimSetTo("font-size", "larger");
   409   gSvg.setCurrentTime(0);
   410   var fsize = parseInt(SMILUtil.getComputedStyleSimple(gCircle, "font-size"));
   411   // CSS 2 suggests a scaling factor of 1.2 so we should be looking at something
   412   // around about 12 or so
   413   ok(fsize > 10 && fsize < 20,
   414     "Checking animated font-size > 10px after animating");
   416   gCircleParent.setAttribute("font-size", "20px"); // Change: font-size: 20px
   417   gSvg.setCurrentTime(0);
   418   fsize = parseInt(SMILUtil.getComputedStyleSimple(gCircle, "font-size"));
   419   ok(fsize > 20, "Checking animated font-size > 20px after updating context");
   421   gCircleParent.removeAttribute("font-size");
   422   gCircle.removeChild(gCircle.firstChild);
   423 }
   425 function testRelativeFontWeight()
   426 {
   427   setupTest();
   428   gCircleParent.setAttribute("font-weight", "100"); // At first: font-weight 100
   429   var anim = createAnimSetTo("font-weight", "bolder");
   430   // CSS 2: 'bolder': Specifies the next weight that is assigned to a font
   431   // that is darker than the inherited one. If there is no such weight, it
   432   // simply results in the next darker numerical value (and the font remains
   433   // unchanged), unless the inherited value was '900', in which case the
   434   // resulting weight is also '900'.
   436   gSvg.setCurrentTime(0);
   437   var weight =
   438     parseInt(SMILUtil.getComputedStyleSimple(gCircle, "font-weight"));
   439   ok(weight > 100, "Checking animated font-weight > 100 after animating");
   441   gCircleParent.setAttribute("font-weight", "800"); // Change: font-weight 800
   442   gSvg.setCurrentTime(0);
   443   weight = parseInt(SMILUtil.getComputedStyleSimple(gCircle, "font-weight"));
   444   is(weight, 900,
   445      "Checking animated font-weight = 900 after updating context");
   447   gCircleParent.removeAttribute("font-weight");
   448   gCircle.removeChild(gCircle.firstChild);
   449 }
   451 function testRelativeFont()
   452 {
   453   // Test a relative font-size as part of a 'font' spec since the code path
   454   // is different in this case
   455   // It turns out that, due to the way we store shorthand font properties, we
   456   // don't need to worry about marking such values as context-sensitive since we
   457   // seem to store them in their relative form. If, however, we change the way
   458   // we store shorthand font properties in the future, this will serve as
   459   // a useful regression test.
   460   setupTest();
   461   gCircleParent.setAttribute("font-size", "10px"); // At first: font-size: 10px
   462   // We must be sure to set every part of the shorthand property to some
   463   // non-context sensitive value because we want to test that even if only the
   464   // font-size is relative we will update it appropriately.
   465   var anim =
   466     createAnimSetTo("font", "normal normal bold larger/normal sans-serif");
   468   gSvg.setCurrentTime(0);
   469   var fsize = parseInt(SMILUtil.getComputedStyleSimple(gCircle, "font-size"));
   470   ok(fsize > 10 && fsize < 20,
   471     "Checking size of shorthand 'font' > 10px after animating");
   473   gCircleParent.setAttribute("font-size", "20px"); // Change: font-size: 20px
   474   gSvg.setCurrentTime(0);
   475   fsize  = parseInt(SMILUtil.getComputedStyleSimple(gCircle, "font-size"));
   476   ok(fsize > 20,
   477      "Checking size of shorthand 'font' > 20px after updating context");
   479   gCircleParent.removeAttribute("font-size");
   480   gCircle.removeChild(gCircle.firstChild);
   481 }
   483 function testCalcFontSize()
   484 {
   485   setupTest();
   486   gCircleParent.setAttribute("font-size", "10px"); // At first: font-size: 10px
   487   var anim = createAnimSetTo("font-size", "-moz-calc(110% + 0.1em)");
   489   gSvg.setCurrentTime(0);
   490   var fsize = parseInt(SMILUtil.getComputedStyleSimple(gCircle, "font-size"));
   491   // Font size should be 1.1 * 10px + 0.1 * 10px = 12
   492   is(fsize, 12, "Checking animated calc font-size == 12px after animating");
   494   gCircleParent.setAttribute("font-size", "20px"); // Change: font-size: 20px
   495   gSvg.setCurrentTime(0);
   496   fsize = parseInt(SMILUtil.getComputedStyleSimple(gCircle, "font-size"));
   497   is(fsize, 24, "Checking animated calc font-size == 24px after updating " +
   498                 "context");
   500   gCircleParent.removeAttribute("font-size");
   501   gCircle.removeChild(gCircle.firstChild);
   502 }
   504 function testDashArray()
   505 {
   506   // stroke dasharrays don't currently convert units--but if someone ever fixes
   507   // that, hopefully this test will fail and remind us not to cache percentage
   508   // values in that case
   509   setupTest();
   510   var oldHeight = gSvg.getAttribute("height");
   511   var oldWidth  = gSvg.getAttribute("width");
   512   gSvg.setAttribute("height", "100px"); // At first: viewport: 100x100px
   513   gSvg.setAttribute("width",  "100px");
   514   var anim = createAnimFromTo("stroke-dasharray", "0 5", "0 50%");
   516   gSvg.setCurrentTime(TIME_AFTER_ANIM_END);
   518   // Now we should be up to date
   519   is(SMILUtil.getComputedStyleSimple(gCircle, "stroke-dasharray"), "0, 50%",
   520      "Checking animated stroke-dasharray after animating");
   522   gSvg.setAttribute("height", "50px"); // Change viewport: 50x50px
   523   gSvg.setAttribute("width",  "50px");
   524   gSvg.setCurrentTime(TIME_AFTER_ANIM_END);
   525   is(SMILUtil.getComputedStyleSimple(gCircle, "stroke-dasharray"), "0, 50%",
   526      "Checking animated stroke-dasharray after updating context");
   528   gSvg.setAttribute("height", oldHeight);
   529   gSvg.setAttribute("width",  oldWidth);
   530   gCircle.removeChild(gCircle.firstChild);
   531 }
   533 function testClip()
   534 {
   535   setupTest();
   536   gCircleParent.setAttribute("font-size", "20px"); // At first: font-size: 20px
   538   // The clip property only applies to elements that establish a new
   539   // viewport so we need to create a nested svg and add animation to that
   540   var nestedSVG = document.createElementNS(SVGNS, "svg");
   541   nestedSVG.setAttribute("clip", "rect(0px 0px 0px 0px)");
   542   gCircleParent.appendChild(nestedSVG);
   544   var anim = createAnimSetTo("clip", "rect(1em 1em 1em 1em)");
   545   // createAnimSetTo will make the animation a child of gCircle so we need to
   546   // move it so it targets nestedSVG instead
   547   nestedSVG.appendChild(anim);
   549   gSvg.setCurrentTime(TIME_AFTER_ANIM_END);
   550   is(SMILUtil.getComputedStyleSimple(nestedSVG, "clip"),
   551      "rect(20px, 20px, 20px, 20px)",
   552      "Checking animated clip rect after animating");
   554   gCircleParent.setAttribute("font-size", "10px"); // Change: font-size: 10px
   555   gSvg.setCurrentTime(TIME_AFTER_ANIM_END);
   556   is(SMILUtil.getComputedStyleSimple(nestedSVG, "clip"),
   557      "rect(10px, 10px, 10px, 10px)",
   558      "Checking animated clip rect after updating context");
   560   gCircleParent.removeAttribute("font-size");
   561   gCircleParent.removeChild(nestedSVG);
   562 }
   564 window.addEventListener("load", main, false);
   565 ]]>
   566 </script>
   567 </pre>
   568 </body>
   569 </html>

mercurial