[Sie-announce] SIEコード [2547] SVGPathElementのクロージャーをやめて、最適化

Back to archive index

svnno****@sourc***** svnno****@sourc*****
2011年 4月 1日 (金) 23:55:52 JST


Revision: 2547
          http://sourceforge.jp/projects/sie/svn/view?view=rev&revision=2547
Author:   dhrname
Date:     2011-04-01 23:55:52 +0900 (Fri, 01 Apr 2011)

Log Message:
-----------
SVGPathElementのクロージャーをやめて、最適化

Modified Paths:
--------------
    branches/07x/074/org/w3c/dom/svg.js

Modified: branches/07x/074/org/w3c/dom/svg.js
===================================================================
--- branches/07x/074/org/w3c/dom/svg.js	2011-04-01 14:44:29 UTC (rev 2546)
+++ branches/07x/074/org/w3c/dom/svg.js	2011-04-01 14:55:52 UTC (rev 2547)
@@ -2535,382 +2535,385 @@
   this.animatedNormalizedPathSegList = this.normalizedPathSegList;
   /*readonly SVGAnimatedNumber*/ this.pathLength = new SVGAnimatedNumber();
   //以下は、d属性に変更があった場合の処理
-  this.addEventListener("DOMAttrModified", function(evt){
-    var tar = evt.target;
-    if (evt.attrName === "d" && evt.newValue !== ""){
-      /* d属性の値が空の場合は、描画を行わないようにする
-       * 
-       *SVG1.1 「8.3.9 The grammar for path data」の項目にある最後の文章を参照
-       */
-      var tnl = tar.normalizedPathSegList,
-          tlist = tar.pathSegList,
-          D = [];
-      if (tnl.numberOfItems > 0) {
-        tnl.clear();
-        tlist.clear();
+  this.addEventListener("DOMAttrModified", this._attrModi, false);
+  /*以下の処理は、このpath要素ノードがDOMツリーに追加されて初めて、
+   *描画が開始されることを示す。つまり、appendChildで挿入されない限り、描画をしない。
+   */
+  this.addEventListener("DOMNodeInserted", this._nodeInsert, false);
+  return this;
+};
+SVGPathElement.constructor = SVGElement;
+SVGPathElement.prototype = new SVGElement();
+SVGPathElement.prototype._attrModi = function(evt){
+  var tar = evt.target;
+  if (evt.attrName === "d" && evt.newValue !== ""){
+    /* d属性の値が空の場合は、描画を行わないようにする
+     * 
+     *SVG1.1 「8.3.9 The grammar for path data」の項目にある最後の文章を参照
+     */
+    var tnl = tar.normalizedPathSegList,
+        tlist = tar.pathSegList,
+        D = [];
+    if (tnl.numberOfItems > 0) {
+      tnl.clear();
+      tlist.clear();
+    }
+    /*d属性の値を正規表現を用いて、二次元配列Dに変換している。もし、d属性の値が"M 20 30 L20 40"ならば、
+     *JSONにおける表現は以下のとおり
+     *D = [["M", 20, 30], ["L", 20 40]]
+     */
+    var taco = tar._com,
+        sgs = taco.isSp,
+        dd = evt.newValue
+    .replace(taco.isRa, " -")
+    .replace(taco.isRb, " ")
+    .replace(taco.isRc, ",$1 ")
+    .replace(taco.isRd, ",$1 1")
+    .replace(taco.isRe, "")
+    .split(","),
+        dli=dd.length;
+    for (var i=0;i<dli;++i) {
+      D[i] = dd[i].match(sgs);
+      for (var j=1, dili=D[i].length;j<dili;++j) {
+        D[i][j] = +(D[i][j]);
       }
-      /*d属性の値を正規表現を用いて、二次元配列Dに変換している。もし、d属性の値が"M 20 30 L20 40"ならば、
-       *JSONにおける表現は以下のとおり
-       *D = [["M", 20, 30], ["L", 20 40]]
-       */
-      var taco = tar._com,
-          sgs = taco.isSp,
-          dd = evt.newValue
-      .replace(taco.isRa, " -")
-      .replace(taco.isRb, " ")
-      .replace(taco.isRc, ",$1 ")
-      .replace(taco.isRd, ",$1 1")
-      .replace(taco.isRe, "")
-      .split(","),
-          dli=dd.length;
-      for (var i=0;i<dli;++i) {
-        D[i] = dd[i].match(sgs);
-        for (var j=1, dili=D[i].length;j<dili;++j) {
-          D[i][j] = +(D[i][j]);
+    }
+    sgs = dd = null;
+    var isZ = taco._isZ, isM = taco._isM, isC = taco._isC, isL = taco._isL;
+    for (var i=0; i < dli; ++i) {
+      var di = D[i], s;
+      for (var j=1, dii=di[0], dili=di.length; j < dili; ++j) {
+        if (isM[dii]) {
+          s = tar.createSVGPathSegMovetoAbs(di[j], di[j+1]);
+          ++j;
+        } else if (dii === "m") {
+          s = tar.createSVGPathSegMovetoRel(di[j], di[j+1]);
+          ++j;
+        } else if (isL[dii]) {
+          s = tar.createSVGPathSegLinetoAbs(di[j], di[j+1]);
+          ++j;
+        } else if (dii === "l") {
+          s = tar.createSVGPathSegLinetoRel(di[j], di[j+1]);
+          ++j;
+        } else if (isC[dii]) {
+          s = tar.createSVGPathSegCurvetoCubicAbs(di[j+4], di[j+5], di[j], di[j+1], di[j+2], di[j+3]);
+          j += 5;
+        } else if (dii === "c") {
+          s = tar.createSVGPathSegCurvetoCubicRel(di[j+4], di[j+5], di[j], di[j+1], di[j+2], di[j+3]);
+          j += 5;
+        } else if (dii === "Q") {
+          s = tar.createSVGPathSegCurvetoQuadraticAbs(di[j+2], di[j+3], di[j], di[j+1]);
+          j += 3;
+        } else if (dii === "q") {
+          s = tar.createSVGPathSegCurvetoQuadraticRel(di[j+2], di[j+3], di[j], di[j+1]);
+          j += 3;
+        } else if (dii === "A") {
+          s = tar.createSVGPathSegArcAbs(di[j+5], di[j+6], di[j], di[j+1], di[j+2], di[j+3], di[j+4]);
+          j += 6;
+        } else if (dii === "a") {
+          s = tar.createSVGPathSegArcRel(di[j+5], di[j+6], di[j], di[j+1], di[j+2], di[j+3], di[j+4]);
+          j += 6;
+        } else if (isZ[dii]) {
+          s = tar.createSVGPathSegClosePath();
+        } else if (dii === "S") {
+          s = tar.createSVGPathSegCurvetoCubicSmoothAbs(di[j+2], di[j+3], di[j], di[j+1]);
+          j += 3;
+        } else if (dii === "s") {
+          s = tar.createSVGPathSegCurvetoCubicSmoothRel(di[j+2], di[j+3], di[j], di[j+1]);
+          j += 3;
+        } else if (dii === "T") {
+          s = tar.createSVGPathSegCurvetoQuadraticSmoothAbs(di[j], di[j+1]);
+          ++j;
+        } else if (dii === "t") {
+          s = tar.createSVGPathSegCurvetoQuadraticSmoothRel(di[j], di[j+1]);
+          ++j;
+        } else if (dii === "H") {
+          s = tar.createSVGPathSegLinetoHorizontalAbs(di[j]);
+        } else if (dii === "h") {
+          s = tar.createSVGPathSegLinetoHorizontalRel(di[j]);
+        } else if (dii === "V") {
+          s = tar.createSVGPathSegLinetoVerticalAbs(di[j]);
+        } else if (dii === "v") {
+          s = tar.createSVGPathSegLinetoVerticalRel(di[j]);
+        } else {
+          s = new SVGPathSeg();
         }
+        tlist.appendItem(s);
       }
-      sgs = dd = null;
-      var isZ = taco._isZ, isM = taco._isM, isC = taco._isC, isL = taco._isL;
-      for (var i=0; i < dli; ++i) {
-        var di = D[i], s;
-        for (var j=1, dii=di[0], dili=di.length; j < dili; ++j) {
-          if (isM[dii]) {
-            s = tar.createSVGPathSegMovetoAbs(di[j], di[j+1]);
-            ++j;
-          } else if (dii === "m") {
-            s = tar.createSVGPathSegMovetoRel(di[j], di[j+1]);
-            ++j;
-          } else if (isL[dii]) {
-            s = tar.createSVGPathSegLinetoAbs(di[j], di[j+1]);
-            ++j;
-          } else if (dii === "l") {
-            s = tar.createSVGPathSegLinetoRel(di[j], di[j+1]);
-            ++j;
-          } else if (isC[dii]) {
-            s = tar.createSVGPathSegCurvetoCubicAbs(di[j+4], di[j+5], di[j], di[j+1], di[j+2], di[j+3]);
-            j += 5;
-          } else if (dii === "c") {
-            s = tar.createSVGPathSegCurvetoCubicRel(di[j+4], di[j+5], di[j], di[j+1], di[j+2], di[j+3]);
-            j += 5;
-          } else if (dii === "Q") {
-            s = tar.createSVGPathSegCurvetoQuadraticAbs(di[j+2], di[j+3], di[j], di[j+1]);
-            j += 3;
-          } else if (dii === "q") {
-            s = tar.createSVGPathSegCurvetoQuadraticRel(di[j+2], di[j+3], di[j], di[j+1]);
-            j += 3;
-          } else if (dii === "A") {
-            s = tar.createSVGPathSegArcAbs(di[j+5], di[j+6], di[j], di[j+1], di[j+2], di[j+3], di[j+4]);
-            j += 6;
-          } else if (dii === "a") {
-            s = tar.createSVGPathSegArcRel(di[j+5], di[j+6], di[j], di[j+1], di[j+2], di[j+3], di[j+4]);
-            j += 6;
-          } else if (isZ[dii]) {
-            s = tar.createSVGPathSegClosePath();
-          } else if (dii === "S") {
-            s = tar.createSVGPathSegCurvetoCubicSmoothAbs(di[j+2], di[j+3], di[j], di[j+1]);
-            j += 3;
-          } else if (dii === "s") {
-            s = tar.createSVGPathSegCurvetoCubicSmoothRel(di[j+2], di[j+3], di[j], di[j+1]);
-            j += 3;
-          } else if (dii === "T") {
-            s = tar.createSVGPathSegCurvetoQuadraticSmoothAbs(di[j], di[j+1]);
-            ++j;
-          } else if (dii === "t") {
-            s = tar.createSVGPathSegCurvetoQuadraticSmoothRel(di[j], di[j+1]);
-            ++j;
-          } else if (dii === "H") {
-            s = tar.createSVGPathSegLinetoHorizontalAbs(di[j]);
-          } else if (dii === "h") {
-            s = tar.createSVGPathSegLinetoHorizontalRel(di[j]);
-          } else if (dii === "V") {
-            s = tar.createSVGPathSegLinetoVerticalAbs(di[j]);
-          } else if (dii === "v") {
-            s = tar.createSVGPathSegLinetoVerticalRel(di[j]);
-          } else {
-            s = new SVGPathSeg();
-          }
-          tlist.appendItem(s);
+    }
+    D = null;
+    /*以下の処理は、pathSegListからnormalizedPathSegListへの
+     *変換をする処理。相対座標を絶対座標に変換して、M、L、Cコマンドに正規化していく
+     */
+    var cx = 0, cy = 0,         //現在セグメントの終了点の絶対座標を示す (相対座標を絶対座標に変換するときに使用)
+        xn = 0, yn = 0,         //T,tコマンドで仮想的な座標を算出するのに用いる。第一コントロール点
+        startx = 0, starty = 0; //M,mコマンドにおける始点座標(Z,zコマンドで用いる)
+    for (var j=0, tli=tlist.numberOfItems;j<tli;++j) {
+      var ti = tlist.getItem(j),
+          ts = ti.pathSegType,
+          dii = ti.pathSegTypeAsLetter;
+      if (ts === /*SVGPathSeg.PATHSEG_UNKNOWN*/ 0) {
+      } else {
+        var rx = cx, ry = cy;   //rx, ryは前のセグメントの終了点
+        if (ts % 2 === 1) {     //相対座標ならば
+          cx += ti.x;
+          cy += ti.y;
+        } else {
+          cx = ti.x;
+          cy = ti.y;
         }
-      }
-      D = null;
-      /*以下の処理は、pathSegListからnormalizedPathSegListへの
-       *変換をする処理。相対座標を絶対座標に変換して、M、L、Cコマンドに正規化していく
-       */
-      var cx = 0, cy = 0,         //現在セグメントの終了点の絶対座標を示す (相対座標を絶対座標に変換するときに使用)
-          xn = 0, yn = 0,         //T,tコマンドで仮想的な座標を算出するのに用いる。第一コントロール点
-          startx = 0, starty = 0; //M,mコマンドにおける始点座標(Z,zコマンドで用いる)
-      for (var j=0, tli=tlist.numberOfItems;j<tli;++j) {
-        var ti = tlist.getItem(j),
-            ts = ti.pathSegType,
-            dii = ti.pathSegTypeAsLetter;
-        if (ts === /*SVGPathSeg.PATHSEG_UNKNOWN*/ 0) {
-        } else {
-          var rx = cx, ry = cy;   //rx, ryは前のセグメントの終了点
-          if (ts % 2 === 1) {     //相対座標ならば
-            cx += ti.x;
-            cy += ti.y;
-          } else {
-            cx = ti.x;
-            cy = ti.y;
+        if (isC[dii]) {
+          tnl.appendItem(ti);
+        } else if (isL[dii]) {
+          tnl.appendItem(ti);
+        } else if (isM[dii]) {
+          if (j !== 0) {
+            /*Mコマンドが続いた場合は、2番目以降はLコマンドと解釈する
+             *W3C SVG1.1の「8.3.2 The "moveto" commands」を参照
+             *http://www.w3.org/TR/SVG11/paths.html#PathDataMovetoCommands
+             */
+            var tg = tlist.getItem(j-1);
+            if (tg.pathSegTypeAsLetter === "M") {
+              tnl.appendItem(tar.createSVGPathSegLinetoAbs(cx, cy));
+              continue;
+            }
           }
-          if (isC[dii]) {
-            tnl.appendItem(ti);
-          } else if (isL[dii]) {
-            tnl.appendItem(ti);
-          } else if (isM[dii]) {
-            if (j !== 0) {
-              /*Mコマンドが続いた場合は、2番目以降はLコマンドと解釈する
-               *W3C SVG1.1の「8.3.2 The "moveto" commands」を参照
-               *http://www.w3.org/TR/SVG11/paths.html#PathDataMovetoCommands
-               */
-              var tg = tlist.getItem(j-1);
-              if (tg.pathSegTypeAsLetter === "M") {
-                tnl.appendItem(tar.createSVGPathSegLinetoAbs(cx, cy));
-                continue;
-              }
+          startx = cx;
+          starty = cy;
+          tnl.appendItem(ti);
+        } else if (dii === "m") {
+          if (j !== 0) {
+            var tg = tlist.getItem(j-1);
+            if (tg.pathSegTypeAsLetter === "m") {
+              tnl.appendItem(tar.createSVGPathSegLinetoAbs(cx, cy));
+              continue;
             }
-            startx = cx;
-            starty = cy;
-            tnl.appendItem(ti);
-          } else if (dii === "m") {
-            if (j !== 0) {
-              var tg = tlist.getItem(j-1);
-              if (tg.pathSegTypeAsLetter === "m") {
-                tnl.appendItem(tar.createSVGPathSegLinetoAbs(cx, cy));
-                continue;
+          }
+          startx = cx;
+          starty = cy;
+          tnl.appendItem(tar.createSVGPathSegMovetoAbs(cx, cy));
+        } else if (dii === "l") {
+          tnl.appendItem(tar.createSVGPathSegLinetoAbs(cx, cy));
+        } else if (dii === "c") {
+          tnl.appendItem(tar.createSVGPathSegCurvetoCubicAbs(cx, cy, ti.x1+rx, ti.y1+ry, ti.x2+rx, ti.y2+ry));
+        } else if (isZ[dii]) {
+          cx = startx;
+          cy = starty;
+          tnl.appendItem(ti);
+        } else if (dii === "Q") {
+          xn = 2*cx - ti.x1;
+          yn = 2*cy - ti.y1;
+          //2次スプライン曲線は近似的な3次ベジェ曲線に変換している
+          tnl.appendItem(tar.createSVGPathSegCurvetoCubicAbs(cx, cy, (rx + 2*ti.x1) / 3, (ry + 2*ti.y1) / 3, (2*ti.x1 + cx) / 3, (2*ti.y1 + cy) / 3));
+        } else if (dii === "q") {
+          var x1 = ti.x1 + rx, y1 = ti.y1 + ry;
+          xn = 2*cx - x1;
+          yn = 2*cy - y1;
+          tnl.appendItem(tar.createSVGPathSegCurvetoCubicAbs(cx, cy, (rx + 2*x1) / 3, (ry + 2*y1) / 3, (2*x1 + cx) / 3, (2*y1 + cy) / 3));
+          x1 = y1 = null;
+        } else if (dii === "A" || dii === "a") {
+          (function(ti, cx, cy, rx, ry, tar, tnl) { //変数を隠蔽するためのfunction
+            /*以下は、Arctoを複数のCuvetoに変換する処理
+             *SVG 1.1 「F.6 Elliptical arc implementation notes」の章を参照
+             *http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
+             */
+            if (ti.r1 === 0 || ti.r2 === 0) {
+              return;
+            }
+            var fS = ti.sweepFlag,
+                psai = ti.angle,
+                r1 = _math.abs(ti.r1),
+                r2 = _math.abs(ti.r2),
+                ctx = (rx - cx) / 2,  cty = (ry - cy) / 2,
+                cpsi = _math.cos(psai * _math.PI / 180),
+                spsi = _math.sin(psai * _math.PI / 180),
+                rxd = cpsi*ctx + spsi*cty,
+                ryd = -1*spsi*ctx + cpsi*cty,
+                rxdd = rxd * rxd, rydd = ryd * ryd,
+                r1x = r1 * r1,
+                r2y = r2 * r2,
+                lamda = rxdd/r1x + rydd/r2y,
+                sds;
+            if (lamda > 1) {
+              r1 = _math.sqrt(lamda) * r1;
+              r2 = _math.sqrt(lamda) * r2;
+              sds = 0;
+            }  else{
+              var seif = 1;
+              if (ti.largeArcFlag === fS) {
+                seif = -1;
               }
+              sds = seif * _math.sqrt((r1x*r2y - r1x*rydd - r2y*rxdd) / (r1x*rydd + r2y*rxdd));
             }
-            startx = cx;
-            starty = cy;
-            tnl.appendItem(tar.createSVGPathSegMovetoAbs(cx, cy));
-          } else if (dii === "l") {
-            tnl.appendItem(tar.createSVGPathSegLinetoAbs(cx, cy));
-          } else if (dii === "c") {
-            tnl.appendItem(tar.createSVGPathSegCurvetoCubicAbs(cx, cy, ti.x1+rx, ti.y1+ry, ti.x2+rx, ti.y2+ry));
-          } else if (isZ[dii]) {
-            cx = startx;
-            cy = starty;
-            tnl.appendItem(ti);
-          } else if (dii === "Q") {
-            xn = 2*cx - ti.x1;
-            yn = 2*cy - ti.y1;
-            //2次スプライン曲線は近似的な3次ベジェ曲線に変換している
-            tnl.appendItem(tar.createSVGPathSegCurvetoCubicAbs(cx, cy, (rx + 2*ti.x1) / 3, (ry + 2*ti.y1) / 3, (2*ti.x1 + cx) / 3, (2*ti.y1 + cy) / 3));
-          } else if (dii === "q") {
-            var x1 = ti.x1 + rx, y1 = ti.y1 + ry;
-            xn = 2*cx - x1;
-            yn = 2*cy - y1;
-            tnl.appendItem(tar.createSVGPathSegCurvetoCubicAbs(cx, cy, (rx + 2*x1) / 3, (ry + 2*y1) / 3, (2*x1 + cx) / 3, (2*y1 + cy) / 3));
-            x1 = y1 = null;
-          } else if (dii === "A" || dii === "a") {
-            (function(ti, cx, cy, rx, ry, tar, tnl) { //変数を隠蔽するためのfunction
-              /*以下は、Arctoを複数のCuvetoに変換する処理
-               *SVG 1.1 「F.6 Elliptical arc implementation notes」の章を参照
-               *http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
-               */
-              if (ti.r1 === 0 || ti.r2 === 0) {
-                return;
-              }
-              var fS = ti.sweepFlag,
-                  psai = ti.angle,
-                  r1 = _math.abs(ti.r1),
-                  r2 = _math.abs(ti.r2),
-                  ctx = (rx - cx) / 2,  cty = (ry - cy) / 2,
-                  cpsi = _math.cos(psai * _math.PI / 180),
-                  spsi = _math.sin(psai * _math.PI / 180),
-                  rxd = cpsi*ctx + spsi*cty,
-                  ryd = -1*spsi*ctx + cpsi*cty,
-                  rxdd = rxd * rxd, rydd = ryd * ryd,
-                  r1x = r1 * r1,
-                  r2y = r2 * r2,
-                  lamda = rxdd/r1x + rydd/r2y,
-                  sds;
-              if (lamda > 1) {
-                r1 = _math.sqrt(lamda) * r1;
-                r2 = _math.sqrt(lamda) * r2;
-                sds = 0;
-              }  else{
-                var seif = 1;
-                if (ti.largeArcFlag === fS) {
-                  seif = -1;
-                }
-                sds = seif * _math.sqrt((r1x*r2y - r1x*rydd - r2y*rxdd) / (r1x*rydd + r2y*rxdd));
-              }
-              var txd = sds*r1*ryd / r2,
-                  tyd = -1 * sds*r2*rxd / r1,
-                  tx = cpsi*txd - spsi*tyd + (rx+cx)/2,
-                  ty = spsi*txd + cpsi*tyd + (ry+cy)/2,
-                  rad = _math.atan2((ryd-tyd)/r2, (rxd-txd)/r1) - _math.atan2(0, 1),
-                  s1 = (rad >= 0) ? rad : 2 * _math.PI + rad,
-                  rad = _math.atan2((-ryd-tyd)/r2, (-rxd-txd)/r1) - _math.atan2((ryd-tyd)/r2, (rxd-txd)/r1),
-                  dr = (rad >= 0) ? rad : 2 * _math.PI + rad;
-              if (!fS  &&  dr > 0) {
-                dr -=   2*_math.PI;
-              } else if (fS  &&  dr < 0) {
-                dr += 2*_math.PI;
-              }
-              var sse = dr * 2 / _math.PI,
-                  seg = _math.ceil(sse<0 ? -1*sse  :  sse),
-                  segr = dr / seg,
-                  t = 8/3 * _math.sin(segr/4) * _math.sin(segr/4) / _math.sin(segr/2),
-                  cpsir1 = cpsi * r1, cpsir2 = cpsi * r2,
-                  spsir1 = spsi * r1, spsir2 = spsi * r2,
-                  mc = _math.cos(s1),
-                  ms = _math.sin(s1),
-                  x2 = rx - t * (cpsir1*ms + spsir2*mc),
-                  y2 = ry - t * (spsir1*ms - cpsir2*mc);
-              for (var n = 0; n < seg; ++n) {
-                s1 += segr;
-                mc = _math.cos(s1);
-                ms = _math.sin(s1);
-                var x3 = cpsir1*mc - spsir2*ms + tx,
-                    y3 = spsir1*mc + cpsir2*ms + ty,
-                    dx = -t * (cpsir1*ms + spsir2*mc),
-                    dy = -t * (spsir1*ms - cpsir2*mc);
-                tnl.appendItem(tar.createSVGPathSegCurvetoCubicAbs(x3, y3, x2, y2, x3-dx, y3-dy));
-                x2 = x3 + dx;
-                y2 = y3 + dy;
-              }
-            })(ti, cx, cy, rx, ry, tar, tnl);
-          } else if (dii === "S") {
-            if (j !== 0) {
-              var tg = tnl.getItem(tnl.numberOfItems-1);
-              if (tg.pathSegTypeAsLetter === "C") {
-                var x1 = 2*tg.x - tg.x2,
-                    y1 = 2*tg.y - tg.y2;
-              } else { //前のコマンドがCでなければ、現在の座標を第1コントロール点に用いる
-                var x1 = rx,
-                    y1 = ry;
-              }
-            } else {
+            var txd = sds*r1*ryd / r2,
+                tyd = -1 * sds*r2*rxd / r1,
+                tx = cpsi*txd - spsi*tyd + (rx+cx)/2,
+                ty = spsi*txd + cpsi*tyd + (ry+cy)/2,
+                rad = _math.atan2((ryd-tyd)/r2, (rxd-txd)/r1) - _math.atan2(0, 1),
+                s1 = (rad >= 0) ? rad : 2 * _math.PI + rad,
+                rad = _math.atan2((-ryd-tyd)/r2, (-rxd-txd)/r1) - _math.atan2((ryd-tyd)/r2, (rxd-txd)/r1),
+                dr = (rad >= 0) ? rad : 2 * _math.PI + rad;
+            if (!fS  &&  dr > 0) {
+              dr -=   2*_math.PI;
+            } else if (fS  &&  dr < 0) {
+              dr += 2*_math.PI;
+            }
+            var sse = dr * 2 / _math.PI,
+                seg = _math.ceil(sse<0 ? -1*sse  :  sse),
+                segr = dr / seg,
+                t = 8/3 * _math.sin(segr/4) * _math.sin(segr/4) / _math.sin(segr/2),
+                cpsir1 = cpsi * r1, cpsir2 = cpsi * r2,
+                spsir1 = spsi * r1, spsir2 = spsi * r2,
+                mc = _math.cos(s1),
+                ms = _math.sin(s1),
+                x2 = rx - t * (cpsir1*ms + spsir2*mc),
+                y2 = ry - t * (spsir1*ms - cpsir2*mc);
+            for (var n = 0; n < seg; ++n) {
+              s1 += segr;
+              mc = _math.cos(s1);
+              ms = _math.sin(s1);
+              var x3 = cpsir1*mc - spsir2*ms + tx,
+                  y3 = spsir1*mc + cpsir2*ms + ty,
+                  dx = -t * (cpsir1*ms + spsir2*mc),
+                  dy = -t * (spsir1*ms - cpsir2*mc);
+              tnl.appendItem(tar.createSVGPathSegCurvetoCubicAbs(x3, y3, x2, y2, x3-dx, y3-dy));
+              x2 = x3 + dx;
+              y2 = y3 + dy;
+            }
+          })(ti, cx, cy, rx, ry, tar, tnl);
+        } else if (dii === "S") {
+          if (j !== 0) {
+            var tg = tnl.getItem(tnl.numberOfItems-1);
+            if (tg.pathSegTypeAsLetter === "C") {
+              var x1 = 2*tg.x - tg.x2,
+                  y1 = 2*tg.y - tg.y2;
+            } else { //前のコマンドがCでなければ、現在の座標を第1コントロール点に用いる
               var x1 = rx,
                   y1 = ry;
             }
-            tnl.appendItem(tar.createSVGPathSegCurvetoCubicAbs(cx, cy, x1, y1, ti.x2, ti.y2));
-            x1 = y1 = null;
-          } else if (dii === "s") {
-            if (j !== 0) {
-              var tg = tnl.getItem(tnl.numberOfItems-1);
-              if (tg.pathSegTypeAsLetter === "C") {
-                var x1 = 2*tg.x - tg.x2,
-                    y1 = 2*tg.y - tg.y2;
-              } else {
-                var x1 = rx,
-                    y1 = ry;
-              }
+          } else {
+            var x1 = rx,
+                y1 = ry;
+          }
+          tnl.appendItem(tar.createSVGPathSegCurvetoCubicAbs(cx, cy, x1, y1, ti.x2, ti.y2));
+          x1 = y1 = null;
+        } else if (dii === "s") {
+          if (j !== 0) {
+            var tg = tnl.getItem(tnl.numberOfItems-1);
+            if (tg.pathSegTypeAsLetter === "C") {
+              var x1 = 2*tg.x - tg.x2,
+                  y1 = 2*tg.y - tg.y2;
             } else {
               var x1 = rx,
                   y1 = ry;
             }
-            tnl.appendItem(tar.createSVGPathSegCurvetoCubicAbs(cx, cy, x1, y1, ti.x2+rx, ti.y2+ry));
-            x1 = y1 = null;
-          } else if (dii === "T" || dii === "t") {
-            if (j !== 0) {
-              var tg = tlist.getItem(j-1);
-              if ("QqTt".indexOf(tg.pathSegTypeAsLetter) > -1) {
-               } else {
-                xn = rx, yn = ry;
-              }
-            } else {
+          } else {
+            var x1 = rx,
+                y1 = ry;
+          }
+          tnl.appendItem(tar.createSVGPathSegCurvetoCubicAbs(cx, cy, x1, y1, ti.x2+rx, ti.y2+ry));
+          x1 = y1 = null;
+        } else if (dii === "T" || dii === "t") {
+          if (j !== 0) {
+            var tg = tlist.getItem(j-1);
+            if ("QqTt".indexOf(tg.pathSegTypeAsLetter) > -1) {
+             } else {
               xn = rx, yn = ry;
             }
-            tnl.appendItem(tar.createSVGPathSegCurvetoCubicAbs(cx, cy, (rx + 2*xn) / 3, (ry + 2*yn) / 3, (2*xn + cx) / 3, (2*yn + cy) / 3));
-            xn = 2*cx - xn;
-            yn = 2*cy - yn;
-            xx1 = yy1 = null;
-          } else if (dii === "H" || dii === "h") {
-            tnl.appendItem(tar.createSVGPathSegLinetoAbs(cx, ry));
-            cy = ry; //勝手にti.yが0としているため
-          } else if (dii === "V" || dii === "v") {
-            tnl.appendItem(tar.createSVGPathSegLinetoAbs(rx, cy));
-            cx = rx;
+          } else {
+            xn = rx, yn = ry;
           }
+          tnl.appendItem(tar.createSVGPathSegCurvetoCubicAbs(cx, cy, (rx + 2*xn) / 3, (ry + 2*yn) / 3, (2*xn + cx) / 3, (2*yn + cy) / 3));
+          xn = 2*cx - xn;
+          yn = 2*cy - yn;
+          xx1 = yy1 = null;
+        } else if (dii === "H" || dii === "h") {
+          tnl.appendItem(tar.createSVGPathSegLinetoAbs(cx, ry));
+          cy = ry; //勝手にti.yが0としているため
+        } else if (dii === "V" || dii === "v") {
+          tnl.appendItem(tar.createSVGPathSegLinetoAbs(rx, cy));
+          cx = rx;
         }
       }
     }
-    evt = tar = taco = cx = cy = xn = yn = startx = starty = tnl = tlist = ti = dii = ts = isZ = isM = isL = isC = s = null;
-  }, false);
-  /*以下の処理は、このpath要素ノードがDOMツリーに追加されて初めて、
-   *描画が開始されることを示す。つまり、appendChildで挿入されない限り、描画をしない。
+  }
+  evt = tar = taco = cx = cy = xn = yn = startx = starty = tnl = tlist = ti = dii = ts = isZ = isM = isL = isC = s = null;
+};
+SVGPathElement.prototype._nodeInsert = function(evt){
+  var tar = evt.target;
+  if (evt.eventPhase === /*Event.BUBBLING_PHASE*/ 3) {
+    return; //強制終了させる
+  }
+  var tnext = tar.nextSibling,
+      tpar = tar.parentNode,
+      isLast = true;
+  if (tnext && tnext._tar && tpar._tar && (tnext._tar.parentNode === tpar._tar)) {
+    tpar._tar.insertBefore(tar._tar, tnext._tar);
+  } else if (tnext && !tnext._tar && tpar._tar) {
+    /*以下の処理は、_tarプロパティがない要素オブジェクトがあるため、それに対処するもの
+     *use要素や実体参照などは_tarプロパティがないことに注意
+     */
+    while (tnext) {
+      if (tnext._tar && (tnext._tar.parentNode === tpar._tar)) {
+        tpar._tar.insertBefore(tar._tar, tnext._tar);
+        isLast = false;
+      } 
+      tnext = tnext.nextSibling;
+    }
+    if (isLast) {
+      tpar._tar.appendChild(tar._tar);
+    }
+  } else if (!tnext && tpar._tar) {
+    tpar._tar.appendChild(tar._tar);      
+  }
+  tnext = tpar = isLast = null;
+  tar.addEventListener("DOMNodeInsertedIntoDocument", tar._nodeInsertInto, false);
+  evt = tar = null;
+};
+SVGPathElement.prototype._nodeInsertInto = function(evt){
+  /*以下の処理は、normalizedpathSegListとCTMに基づいて、
+   *SVGのd属性をVMLに変換していく処理である。
    */
-  this.addEventListener("DOMNodeInserted", function(evt){
-    var tar = evt.target;
-    if (evt.eventPhase === /*Event.BUBBLING_PHASE*/ 3) {
-      return; //強制終了させる
-    }
-    var tnext = tar.nextSibling,
-        tpar = tar.parentNode,
-        isLast = true;
-    if (tnext && tnext._tar && tpar._tar && (tnext._tar.parentNode === tpar._tar)) {
-      tpar._tar.insertBefore(tar._tar, tnext._tar);
-    } else if (tnext && !tnext._tar && tpar._tar) {
-      /*以下の処理は、_tarプロパティがない要素オブジェクトがあるため、それに対処するもの
-       *use要素や実体参照などは_tarプロパティがないことに注意
+  var tar = evt.target,
+      matrix = tar.getScreenCTM(),
+      tlist = tar.normalizedPathSegList,
+      _parseInt = _pInt,
+      dat = [],
+      ma = matrix.a, mb = matrix.b, mc = matrix.c, md = matrix.d, me = matrix.e, mf = matrix.f,
+      cname = tar._com._nameCom,
+      isZ = tar._com._isZ, isC = tar._com._isC;
+  for (var i=0, tli=tlist.numberOfItems;i<tli;++i) {
+    var ti = tlist[i],
+        tps = ti.pathSegTypeAsLetter,
+        t = cname[tps];
+    if (isC[tps]) {
+      /*CTM(mx)の行列と座標(x, y)の積を算出する。数学における表現は以下のとおり
+       *[ma mc me]   [x]
+       *[mb md mf] * [y]
+       *[0  0  1 ]   [1]
        */
-      while (tnext) {
-        if (tnext._tar && (tnext._tar.parentNode === tpar._tar)) {
-          tpar._tar.insertBefore(tar._tar, tnext._tar);
-          isLast = false;
-        } 
-        tnext = tnext.nextSibling;
-      }
-      if (isLast) {
-        tpar._tar.appendChild(tar._tar);
-      }
-    } else if (!tnext && tpar._tar) {
-      tpar._tar.appendChild(tar._tar);      
+      t += ([_parseInt(ma*ti.x1 + mc*ti.y1 + me, 10),
+             _parseInt(mb*ti.x1 + md*ti.y1 + mf, 10),
+             _parseInt(ma*ti.x2 + mc*ti.y2 + me, 10),
+             _parseInt(mb*ti.x2 + md*ti.y2 + mf, 10),
+             _parseInt(ma*ti.x + mc*ti.y + me, 10),
+             _parseInt(mb*ti.x + md*ti.y + mf, 10)]).join(" ");
+    } else if (!isZ[tps]) {
+      t += _parseInt(ma*ti.x + mc*ti.y + me, 10)+ " " +_parseInt(mb*ti.x + md*ti.y + mf, 10);
     }
-    tnext = tpar = isLast = null;
-    tar.addEventListener("DOMNodeInsertedIntoDocument", function(evt){
-      /*以下の処理は、normalizedpathSegListとCTMに基づいて、
-       *SVGのd属性をVMLに変換していく処理である。
-       */
-      var tar = evt.target,
-          matrix = tar.getScreenCTM(),
-          tlist = tar.normalizedPathSegList,
-          _parseInt = _pInt,
-          dat = [],
-          ma = matrix.a, mb = matrix.b, mc = matrix.c, md = matrix.d, me = matrix.e, mf = matrix.f,
-          cname = tar._com._nameCom,
-          isZ = tar._com._isZ, isC = tar._com._isC;
-      for (var i=0, tli=tlist.numberOfItems;i<tli;++i) {
-        var ti = tlist[i],
-            tps = ti.pathSegTypeAsLetter,
-            t = cname[tps];
-        if (isC[tps]) {
-          /*CTM(mx)の行列と座標(x, y)の積を算出する。数学における表現は以下のとおり
-           *[ma mc me]   [x]
-           *[mb md mf] * [y]
-           *[0  0  1 ]   [1]
-           */
-          t += ([_parseInt(ma*ti.x1 + mc*ti.y1 + me, 10),
-                 _parseInt(mb*ti.x1 + md*ti.y1 + mf, 10),
-                 _parseInt(ma*ti.x2 + mc*ti.y2 + me, 10),
-                 _parseInt(mb*ti.x2 + md*ti.y2 + mf, 10),
-                 _parseInt(ma*ti.x + mc*ti.y + me, 10),
-                 _parseInt(mb*ti.x + md*ti.y + mf, 10)]).join(" ");
-        } else if (!isZ[tps]) {
-          t += _parseInt(ma*ti.x + mc*ti.y + me, 10)+ " " +_parseInt(mb*ti.x + md*ti.y + mf, 10);
-        }
-        dat[i] = t;
-      }
-      var vi = tar.ownerDocument.documentElement,
-          w = vi.width.baseVal.value,
-          h = vi.height.baseVal.value,
-          tt = tar._tar;
-      dat[dat.length] = " e";
-      tt.path = dat.join(" ");
-      tt.coordsize = w + " " + h;
-      NAIBU._setPaint(tar, matrix);
-      delete tar._cacheMatrix, tar._currentStyle;
-      evt = tar = dat = t = w = h = matrix = tlist = x = y = _parseInt = ma = mb = mc = md = me = mf = vi = isZ = isC = i = tli = tps = ti = cname = tt = null;
-    }, false);
-    evt = tar = null;
-  }, false);
-  return this;
+    dat[i] = t;
+  }
+  var vi = tar.ownerDocument.documentElement,
+      w = vi.width.baseVal.value,
+      h = vi.height.baseVal.value,
+      tt = tar._tar;
+  dat[dat.length] = " e";
+  tt.path = dat.join(" ");
+  tt.coordsize = w + " " + h;
+  NAIBU._setPaint(tar, matrix);
+  delete tar._cacheMatrix, tar._currentStyle;
+  evt = tar = dat = t = w = h = matrix = tlist = x = y = _parseInt = ma = mb = mc = md = me = mf = vi = isZ = isC = i = tli = tps = ti = cname = tt = null;
 };
-SVGPathElement.constructor = SVGElement;
-SVGPathElement.prototype = new SVGElement();
 SVGPathElement.prototype._com = {
   _nameCom : {
     z : " x ",




Sie-announce メーリングリストの案内
Back to archive index