OSDN Git Service

NAIBU.stop関数の修正をして、フレーム処理から時間処理に再び変更
[sie/sie.git] / org / w3c / dom / svg.js
index 3dbe0aa..7dc35d7 100644 (file)
@@ -5082,77 +5082,117 @@ function SVGAnimationElement(es) {
   this.style.setProperty = function(){};
   this._tar = null;
   /*readonly SVGElement*/ this.targetElement;
-  this._beginValue = null;
-  this._endValue = null;
+  /*それぞれのプロパティは、_を除いた属性に対応している*/
+  this._begin = this._end = this._repeatCount = this._repeatDur = null;
+  this._dur = "indefinite";
   this._currentFrame = 0;
-  this._currentCount = 0;
   /*_maxCountはrepeatCount属性で指定された数値
    *_maxDurはrepeatDur属性で指定された数値
    */
   this._maxCount = 0;
   this._maxDur = 0;
+  /*_isRepeatと_numRepeatは繰り返し再生のときに使う。なお、後者は現在のリピート回数*/
   this._isRepeat = false;
-  /*_simpleDurationプロパティは
-   *dur属性の数値を収納しておく。属性がなければnullのまま
-   */
-  this._simpleDuration = null;
-  /*_beginと_endプロパティはミリ秒数を収納する。リピート時に書き換えられることがある。
-   *_beginはアニメ開始時の秒数。_endはアニメ終了時の秒数。
+  this._numRepeat = 0;
+  /*_startと_finishプロパティはミリ秒数を収納する。
+   *_startはアニメ開始時の秒数。_finishはアニメ終了時の秒数。
    *なお、文書読み込み終了時(アニメ開始時刻)の秒数を0とする。
    */
-  this._begin = null;
-  this._end = null;
+  this._start = this._finish = null;
   this._from = this._to = this._values = this._by = null;
   this._keyTimes = null;
   this.addEventListener("beginEvent", function(evt) {
-    var tar = evt.target;
-    if (!tar.isRepeat) {
-      tar.endElementAt(tar.getSimpleDuration());
-    } else {
-      tar.beginElementAt(tar.getSimpleDuration());
-      if (tar.getCurrentTime() !== 0) {
-        var ttd = tar.ownerDocument, evt = ttd.createEvent("TimeEvents");
-        tar._currentCount++;
-        evt.initTimeEvent("repeatEvent", ttd.defaultView, tar._currentCount);
-        tar.dispatchEvent(evt);
+    try {
+      var tar = evt.target,
+      be = tar._start,
+      dur = tar.getSimpleDuration(),
+      durv = tar._dur,
+      end = tar._finish,
+      endv= tar._end,
+      td = tar._repeatDur,
+      tc = tar._repeatCount,
+      ac = 0;
+      /*Activate Duration (活性持続時間と呼ぶことにする)を計算
+       *計算方法は以下を参照のこと
+       *http://www.w3.org/TR/smil-animation/#ComputingActiveDur
+       *3.3.4. Computing the active duration
+       */
+      if ((td === "indefinte") || (tc === "indefinte")) {
+        if (endv) {
+          ac = end - begin;
+        } else {
+          /*活性持続時間が不定(indefinte)なので、強制的にアニメを終了させる*/
+        }
+      } else if (durv === "indefinte") {
+        if (!tc && !endv) {
+          /*活性持続時間が不定(indefinte)なので、強制的にアニメを終了させる*/   
+        } else if (tc && !endv) {
+          ac = tar._getOffset(td);
+        } else if (!tc && endv) {
+          ac = end - begin;
+        } else {
+          ac = (tar._getOffset(td) > (end - begin)) ? tar._getOffset(td) : (end - begin);
+        }
+      } else if (durv && !td && !tc && !endv) {
+        ac = dur;
+      } else if (durv && !td && tc && !endv) {
+        ac = dur * (+tc);
+      } else if (durv && td && !tc && !endv) {
+        ac = tar._getOffset(td);
+      } else if (durv && !td && !tc && endv) {
+        ac = (dur > (end - begin)) ? dur : (end - begin);
+      } else if (durv && td && tc && !endv) {
+        ac = (+tc*dur > tar._getOffset(td)) ? +tc*dur : tar._getOffset(td);
+      } else if (durv && td && tc && endv) {
+        ac = (+tc*dur > Math.min(+td, (end-begin))) ? +tc*dur : Math.min(tar._getOffset(td), (end - begin));
+      } else if (durv && td && !tc && endv) {
+        ac = (tar._getOffset(td) > (end - begin)) ? tar._getOffset(td) : (end - begin);
+      } else if (durv && !td && tc && endv) {
+        ac = (+tc*dur > (end - begin)) ? +tc*dur : (end - begin)
       }
+    } catch (e) {
+      throw new DOMException(DOMException.INVALID_STATE_ERR);
     }
+    tar.endElementAt(active);
   }, false);
   this.addEventListener("DOMAttrModified", function(evt){
     if (evt.eventPhase === /*Event.BUBBLING_PHASE*/ 3) {
       return;
     }
     var tar = evt.target,
-        name = evt.attrName;
+        name = evt.attrName,
+        evtv = evt.newValue;
     if (name === "begin") {
-      tar._beginValue = evt.newValue;
+      tar._begin = evtv;
     } else if (name === "end") {
-      tar._endValue = evt.newValue;
+      tar._end = evtv;
     } else if (name === "dur") {
-      tar._simpleDuration = tar._getOffset(evt.newValue);
+      tar._dur = evtv;
     } else if (name === "repeatCount") {
-      tar._maxCount = parseFloat(evt.newValue);
+      tar._maxCount = parseFloat(evtv);
+      tar._repeatCount = evtv;
       tar._isRepeat = true;
     } else if (name === "repeatDur") {
-      tar._maxDur = parseFloat(evt.newValue);
+      tar._maxDur = parseFloat(evtv);
+      tar._repeatCount = evtv;
       tar._isRepeat = true;
     } else if (name === "from") {
-      tar._from = evt.newValue;
+      tar._from = evtv;
     } else if (name === "to") {
-      tar._to = evt.newValue;
+      tar._to = evtv;
     } else if (name === "values") {
-      tar._values = evt.newValue.split(";");
+      tar._values = evtv.split(";");
     } else if (name === "by") {
-      tar._by = evt.newValue;
+      tar._by = evtv;
     } else if (name === "keyTimes") {
-      var s = evt.newValue.split(";");
+      var s = evtv.split(";");
       tar._keyTimes = []; //_keyTimesプロパティを初期化
       for (var i=0;i<s.length;++i) {
         tar._keyTimes[i] = parseFloat(s[i]);
       }
       s = void 0;
     }
-    evt = void 0;
+    evt = evtv = void 0;
   }, false);
   this.addEventListener("DOMNodeInserted", function(evt){
     if (evt.eventPhase === /*Event.BUBBLING_PHASE*/ 3) {
@@ -5184,6 +5224,77 @@ function SVGAnimationElement(es) {
          */
         return this;
       }
+      /*begin属性とend属性を処理する*/
+      var _begin =  tar._begin ? tar._getOffset(tar._begin) : 0,
+          that = tar,
+          timing = function(val, name, offset) {
+        /*timing関数は時間のタイミングをidとeventと、clock-value(offset)に分割して処理していく
+         *まず、idを検出するためのsearcIdローカル関数を作る
+         */
+        var searchId = function () {
+              var n = val.indexOf(".");
+              if ((n > 0) && (/[a-z]/i).test(val.charAt(n+1))) { //. (dot)の後がアルファベットならば
+                return (val.slice(0, n));
+              }
+              n = nn = void 0;
+              return "";
+            },
+            id;
+        /*
+         *W3CのSMIl AnimationのTimingモデルは7パターンがあるので、場合分けする
+         */
+        if (isFinite(parseFloat(val))) { //1) offset-valueの場合
+          that[name](offset);
+        } else if (val.indexOf("repeat(") > -1) { //2) repeat-valueの場合
+          var inte = parseFloat(val.slice(7)),
+              ds = function (evt) {
+                if (inte === evt.target._numRepeat) {
+                  that[name](offset);
+                }
+              };
+              id = searchId();
+              if (id) {
+                that.ownerDocument.getElementById(id).addEventListener("repeatEvent", ds);
+              } else {
+                that.addEventListener("repeatEvent", ds);
+              }
+        } else if ((/\.(begin|end)/).test(val)) { //3) syncbase-valueの場合
+          id = searchId();
+          if (id) {
+            var ds = function (evt) {
+                  that[name](offset);
+                },
+                ev = "";
+            if (RegExp.$1 === "begin") {
+              ev = "beginEvent";
+            } else if (RegExp.$1 === "end") {
+              ev = "endEvent";
+            }
+            that.ownerDocument.getElementById(id).addEventListener(ev, ds);
+          }
+        } else if (val.indexOf("wallclock(") === 0) { //4) wallclock-valueの場合
+          
+        } else if (val === "indefinte") { //5) indefinteの場合
+        } else if (val.indexOf("accesskey(") > -1) { //6) accesskey-valueの場合
+          
+        } else { //7) event-valueの場合
+          id = searchId();
+          var ds = function (evt) {
+               that[name](offset);
+              };
+          if (id && val.match(/\.([a-z]+)/i)) {
+            that.ownerDocument.getElementById(id).addEventListener(RegExp.$1, ds);
+          } else if (val){
+            that.targetElement.addEventListener(val.match(/^[a-z]+/i)[0], ds)
+          }
+        }
+        val = searchId = id = void 0;
+      };
+      timing((tar._begin || "0ms"), "beginElementAt", _begin);
+      if (tar._end) {
+        timing(tar._end, "endElementAt", tar._getOffset(tar._end));
+      }
+      that = void 0;
       if (tar.hasAttributeNS("http://www.w3.org/1999/xlink", "xlink:href")) {
         tar.targetElement = tar.ownerDocument.getElementById(tar.getAttributeNS("http://www.w3.org/1999/xlink", "xlink:href").substring(1))
       } else {
@@ -5193,12 +5304,6 @@ function SVGAnimationElement(es) {
     }, false);
     evt = tar = void 0;
   }, false);
-  this.addEventListener("repeatEvent", function(evt) {
-    var tar = evt.target;
-    if ((tar._currentCount >= tar._maxCount) || (tar.getCurrentTime() >= (tar._maxDur+tar.getStartTime()))) {
-      tar._isRepeat = false;
-    }
-  }, false);
   return this;
 };
 SVGAnimationElement.constructor = SVGElement;
@@ -5218,11 +5323,11 @@ SVGAnimationElement.prototype = new SVGElement();
 };
 /*void*/ SVGAnimationElement.prototype.beginElementAt = function(/*float*/ offset) {
   var ntc = this.ownerDocument.documentElement.getCurrentTime();
-  this._begin = offset + ntc;
+  this._start = offset + ntc;
 };
 /*void*/ SVGAnimationElement.prototype.endElementAt = function(/*float*/ offset) {
   var ntc = this.ownerDocument.documentElement.getCurrentTime();
-  this._end = offset + ntc;
+  this._finish = offset + ntc;
 };
 SVGAnimationElement.prototype._eventRegExp = /(mouse|activ|clic|begi|en)[a-z]+/;
 SVGAnimationElement.prototype._timeRegExp = /[\-\d\.]+(h|min|s|ms)?$/;
@@ -5253,81 +5358,10 @@ SVGAnimationElement.prototype._getOffset = function(/*string*/ t) {
 };
 
 /*float*/ SVGAnimationElement.prototype.getStartTime = function(){
-  if (this._begin || (this._begin === 0)) {
-    return (this._begin);
+  if (this._start || (this._start === 0)) {
+    return (this._start);
   } else {
-    var _begin =  this._beginValue ? this._getOffset(this._beginValue) : 0,
-        that = this,
-        timing = function(val, name, offset) {
-      /*timing関数は時間のタイミングをidとeventと、clock-value(offset)に分割して処理していく
-       *まず、idを検出するためのsearcIdローカル関数を作る
-       */
-      var searchId = function () {
-            var n = val.indexOf(".");
-            if ((n > 0) && (/[a-z]/i).test(val.charAt(n+1))) { //. (dot)の後がアルファベットならば
-              return (val.slice(0, n));
-            }
-            n = nn = void 0;
-            return "";
-          },
-          id;
-      /*
-       *W3CのSMIl AnimationのTimingモデルは7パターンがあるので、場合分けする
-       */
-      if (isFinite(parseFloat(val))) { //1) offset-valueの場合
-        that[name](offset);
-      } else if (val.indexOf("repeat(") > -1) { //2) repeat-valueの場合
-        n = 0;
-        var inte = parseFloat(val.slice(7)),
-            ds = function (evt) {
-              ++n;
-              if (inte === n) {
-                that[name](offset);
-              }
-            };
-            id = searchId();
-            if (id) {
-              that.ownerDocument.getElementById(id).addEventListener("repeatEvent", ds);
-            } else {
-              that.addEventListener("repeatEvent", ds);
-            }
-      } else if ((/\.(begin|end)/).test(val)) { //3) syncbase-valueの場合
-        id = searchId();
-        if (id) {
-          var ds = function (evt) {
-                that[name](offset);
-              },
-              ev = "";
-          if (RegExp.$1 === "begin") {
-            ev = "beginEvent";
-          } else if (RegExp.$1 === "end") {
-            ev = "endEvent";
-          }
-          that.ownerDocument.getElementById(id).addEventListener(ev, ds);
-        }
-      } else if (val.indexOf("wallclock(") === 0) { //4) wallclock-valueの場合
-        
-      } else if (val === "indefinte") { //5) indefinteの場合
-      } else if (val.indexOf("accesskey(") > -1) { //6) accesskey-valueの場合
-        
-      } else { //7) event-valueの場合
-        id = searchId();
-        var ds = function (evt) {
-             that[name](offset);
-            };
-        if (id && val.match(new RegExp(id+"\.([a-zA-Z]+)"))) {
-          that.ownerDocument.getElementById(id).addEventListener(RegExp.$1, ds);
-        } else if (val){
-          that.targetElement.addEventListener(val.match(/^[a-z]+/i)[0], ds)
-        }
-      }
-    };
-    timing((this._beginValue || "0ms"), "beginElementAt", _begin);
-    if (this._endValue) {
-      timing(this._endValue, "endElementAt", this._getOffset(this._endValue));
-    }
-    that = void 0;
-    //throw new DOMException(DOMException.INVALID_STATE_ERR);
+    throw new DOMException(DOMException.INVALID_STATE_ERR);
   }
 };
 /*getCurrentTimeメソッド
@@ -5338,14 +5372,11 @@ SVGAnimationElement.prototype._getOffset = function(/*string*/ t) {
   return (this._currentFrame * 125 * 0.8);
 };
 /*float*/ SVGAnimationElement.prototype.getSimpleDuration = function(){
-  if (!this._simpleDuration && !this._end && (this._simpleDuration !== 0)) {
+  if (!this._dur && !this._finish && (this._dur === "indefinte")) {
     throw new DOMException(DOMException.NOT_SUPPORTED_ERR);
-  } else if (this._simpleDuration && this._end) {
-    var s = (this._simpleDuration > (this._end - this._begin)) ? this._end - this._begin : this._simpleDuration;
   } else {
-    var s = this._end ? this._end - this._begin : this._simpleDuration;
+    return (this._getOffset(this._dur));
   }
- return s;
 };
                     //raises( DOMException );
 NAIBU.Time = {
@@ -5360,34 +5391,40 @@ NAIBU.Time = {
     }
     NAIBU.stop = setInterval( (function() {
 /*      try{*/
-        var ntc = NAIBU.Time.currentFrame++;
-        var nc = NAIBU.Clip;
-        var s = ntc * 100; //フレーム数ntcをミリ秒数sに変換
+        var ntc = NAIBU.Time.currentFrame,
+            nc = NAIBU.Clip,
+            s = ntc * 100; //フレーム数ntcをミリ秒数sに変換 (100 = 125 * 0.8)
         if (ntc > NAIBU.Time.Max) {
           clearInterval(NAIBU.stop);
         }
+        nc[0] && nc[0].ownerDocument.documentElement.setCurrentTime(s);
         for (var i=0,ncli=nc.length;i<ncli;++i) {
-          var nci = nc[i];
-          nci.ownerDocument.documentElement.setCurrentTime(s);
-          if ("_begin" in nci) {
-            if (nci.getStartTime() <= s) {
-              if (nci.getCurrentTime() === 0) {
-                nci.beginElement();
-              }
-              nci._currentFrame++;
-            }
-            if (nci._end && (nci._end <= s) && (nci.getCurrentTime() !== 0)) {
-              nci.endElement();
-              nci._frame && nci._frame();
-              nci._currentFrame = 0;
-              delete nci._begin;
-              nci._end = null;
-            } else if (!!nci._frame) {
-              nci._frame();
-            }
+          var nci = nc[i]
+              s2 = s + 100,
+              s1 = s - 100;
+          if ((nci._start || (nci._start === 0)) && (nci.getCurrentTime() === 0) && (s1 <= nci._start && nci._start < s2)) {
+            nci.beginElement();
+          }
+          if (nci._isRepeat && (nci.getCurrentTime() !== 0) && ((nci.getSimpleDuration() % s) === 0)) {
+            var ttd = nci.ownerDocument,
+                evt = ttd.createEvent("TimeEvents");
+            ++nci._numRepeat;
+            evt.initTimeEvent("repeatEvent", ttd.defaultView, nci._numRepeat);
+            nci.dispatchEvent(evt);
+            ttd = evt = void 0;
+          }
+          if ((nci._finish || (nci._finish === 0)) && (s1 <= nci._finish && nci._finish < s2) && (nci.getCurrentTime() !== 0)) {
+            nci.endElement();
+            nci._frame && nci._frame();
+            nci._currentFrame = 0;
+          }
+          if (nci._frame) {
+            nci._currentFrame++;
+            nci._frame();
           }
-          nci = void 0;
         }
+        ++NAIBU.Time.currentFrame;
+        nci = s1 = s2 = void 0;
 /*      } catch (e) {
         stlog.add(e, 4157);
       }*/