[Sie-announce] SIEコード [1794] getEndPositionOfCharメソッドの実装

Back to archive index

svnno****@sourc***** svnno****@sourc*****
2010年 4月 17日 (土) 23:07:14 JST


Revision: 1794
          http://sourceforge.jp/projects/sie/svn/view?view=rev&revision=1794
Author:   dhrname
Date:     2010-04-17 23:07:14 +0900 (Sat, 17 Apr 2010)

Log Message:
-----------
getEndPositionOfCharメソッドの実装

Modified Paths:
--------------
    branches/ufltima/dom/svg.js

Modified: branches/ufltima/dom/svg.js
===================================================================
--- branches/ufltima/dom/svg.js	2010-04-14 14:17:44 UTC (rev 1793)
+++ branches/ufltima/dom/svg.js	2010-04-17 14:07:14 UTC (rev 1794)
@@ -356,7 +356,11 @@
     return newItem;
   },
   /*DOMString*/ getItem : function(/*unsigned long*/ index ) {
-    return (this._list[index]);
+    if (index >= this.numberOfItems || index < 0) {
+      throw (new DOMException(DOMException.INDEX_SIZE_ERR));
+    } else {
+      return (this._list[index]);
+    }
   },
   /*DOMString*/ insertItemBefore : function(/*DOMString*/ newItem, /*unsigned long*/ index ){
     if (index >= this.numberOfItems) {
@@ -368,7 +372,7 @@
     return newItem;
   },
   /*DOMString*/ replaceItem : function(/*DOMString*/ newItem, /*unsigned long*/ index ){
-    if (index >= this.numberOfItems || this.numberOfItems < 0) {
+    if (index >= this.numberOfItems || index < 0) {
       throw (new DOMException(DOMException.INDEX_SIZE_ERR));
     } else {
       this._list.splice(index, 1, newItem);
@@ -377,7 +381,7 @@
   },
                   //raises( DOMException, SVGException );
   /*DOMString*/ removeItem : function(/*unsigned long*/ index ){
-    if (index >= this.numberOfItems || this.numberOfItems < 0) {
+    if (index >= this.numberOfItems || index < 0) {
       throw (new DOMException(DOMException.INDEX_SIZE_ERR));
     } else {
       this._list.splice(index, 1);
@@ -2627,52 +2631,94 @@
   return (this._tar.innerText.length);
 };
 /*float*/    SVGTextContentElement.prototype.getComputedTextLength = function() {
-  var s = 0, t = this.firstChild, f = /[fijlt.,:;1]/g;
-  //以下のメソッドに関しては、css.js(org.w3c.dom.css)をご覧下さい
-  var style = this.ownerDocument.defaultView.getComputedStyle(this, null);
-  var isYokogaki = (style.getPropertyValue("writing-mode")) === "lr-tb" true : false;
-  var fontSize = parseFloat(style.getPropertyValue("font-size"));
-  /*以下はCTM処理後の、fontの実際の大きさを算出するための処理。
-   *つまり、CTMの行列式の2乗を掛け合わせることにより、CTMを組み入れる
-   */
-  fontSize = fontSize * Math.sqrt(Math.abs(this.getScreenCTM().determinant()));
-  while (t) {
-    if (t.nodeName === "#text") {
-      var kerning = t.data.match(f).length; //カーニングの対象となる文字の数(SVGFontのときはhkernとvkern要素を考慮する)
-      var n = t.length;
-      n = n * fontSize - kerning;
-      s += n;
-    } else if (t.localName === "tspan") {
-      s += t.getComputedTextLength();
-      //dx(縦書きのときはdy)属性のずらしを考慮に入れて、長さを計算する
-      var td = isYokogaki ? t.dx.baseVal : t.dy.baseVal;
-      for (var i=0;i<td.numberOfItems;++i) {
-        s += td.getItem(i);
-      }
-    }
-    t = t.nextSibling;
-  }
-  return s;
+  this.getSubStringLength(0, this.getNumberOfChars());
 };
 /*float*/    SVGTextContentElement.prototype.getSubStringLength = function(/*unsigned long*/ charnum, /*unsigned long*/ nchars ) {
-  
+  var style = this.ownerDocument.defaultView.getComputedStyle(this, null);
+  var isYokogaki = ((style.getPropertyValue("writing-mode")) === "lr-tb") ? true : false;
+  var t = isYokogaki ? "x" : "y";
+  return (this.getEndPositionOfChar(charnum+nchars)[t] - this.getStartPositionOfChar(charnum)[t]);
 }
 /*SVGPoint*/ SVGTextContentElement.prototype.getStartPositionOfChar = function (/*unsigned long*/ charnum ) {
   if (charnum > this.getNumberOfChars() || charnum < 0) {
-    return (new DOMException(DOMException.INDEX_SIZE_ERR));
+    throw (new DOMException(DOMException.INDEX_SIZE_ERR));
   } else {
   }
 };
 /*SVGPoint*/ SVGTextContentElement.prototype.getEndPositionOfChar = function(/*unsigned long*/ charnum ) {
   if (charnum > this.getNumberOfChars() || charnum < 0) {
-    return (new DOMException(DOMException.INDEX_SIZE_ERR));
+    throw (new DOMException(DOMException.INDEX_SIZE_ERR));
   } else {
-    //以下のメソッドに関しては、css.js(org.w3c.dom.css)をご覧下さい
-    var fontSize = this.style.getPropertyCSSValue("font-size").getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
-    fontSize = fontSize * Math.sqrt(Math.abs(ttm.determinant())); //現在の座標系で文字の大きさを変換する
-    var s = this.ownerDocument.documentElement.createSVGPoint();
-    s.x = (fontSize*(charnum+1));
-    s.y = 0;
+    var s = this.ownerDocument.createSVGPoint(), d = charnum + 1, t = this.firstChild, f = /[fijlt.,:;1]/g;
+    var x = y = 0;
+    var style = this.ownerDocument.defaultView.getComputedStyle(this, null);
+    var isYokogaki = ((style.getPropertyValue("writing-mode")) === "lr-tb") ? true : false;
+    var fontSize = parseFloat(style.getPropertyValue("font-size"));
+    /*変数fontSizeはCTM処理後の、fontの実際の大きさを算出するための変数。
+     *つまり、CTMの行列式の2乗を掛け合わせることにより、fontの大きさにCTMを組み入れる
+     */
+    var matrix = this.getScreenCTM();
+    fontSize = fontSize * Math.sqrt(Math.abs(matrix.determinant()));
+    /*文字の終了位置における座標(x, y)を求める方法としては、
+     *まず、文字の長さ(h)を算出して、相対座標(x, y)を導き出す
+     */
+    var h = 0;
+    while (t) {
+      if (t.nodeName === "#text") {
+        var n = t.length, isBreak = false;
+        if (d > n) {
+          d -= n;
+          var data = t.data;
+        } else {
+          n = d;
+          var data = t.substringData(0, d);
+          isBreak = true;
+        }
+        if (isYokogaki) {
+          var kerning = data.match(f).length;
+        } else {
+          var kerinig = 0;
+        }
+        h = n * fontSize - kerning;
+        n = data = kerning = null;
+        if (isBreak) {
+          break;
+        }
+      } else if (t.localName === "tspan") {
+        if (t.getNumberOfChars() > d) {
+          h += t.getEndPositionOfChar(d);
+        }
+        //dx(縦書きのときはdy)属性のずらしを考慮に入れて、長さを計算する
+        if (isYokogaki) {
+          var tb = t.dx.baseVal;
+        } else {
+          var tb = t.dy.baseVal;
+        }
+        h += tb.getItem(0).value;
+      }
+      t = t.nextSibling;
+    }
+    if (isYokogaki) {
+      x = h;
+    } else {
+      y = h;
+    }
+    /*続けて、求めておいた相対座標(x, y)に、絶対座標を付け加えることによって、
+     *文字の位置の絶対座標を割り出すことができる。そのためにはx属性とy属性を計算に入れることが肝要
+     */
+    var txb = this.x.baseVal, tyb = this.y.baseVal;
+    if (txb.numberOfItems > charnum) {
+      x = txb.getItem(charnum).value;
+    } else {
+      x += txb.getItem(txb.numberOfItems-1).value;
+    }
+    if (tyb.numberOfItems > charnum) {
+      y = tyb.getItem(charnum).value;
+    } else {
+      y += tyb.getItem(tyb.numberOfItems-1).value;
+    }
+    s.x = x;
+    s.y = y;
     return s;
   }
 };
@@ -2696,8 +2742,14 @@
   /*readonly SVGAnimatedLengthList*/ this.dx = new SVGAnimatedLengthList();
   /*readonly SVGAnimatedLengthList*/ this.dy = new SVGAnimatedLengthList();
   /*readonly SVGAnimatedNumberList*/ this.rotate = new SVGAnimatedNumberList();
-  this.x.baseVal.appendItem(this.ownerDocument.createSVGLength());
-  this.y.baseVal.appendItem(this.ownerDocument.createSVGLength());
+  this.addEventListener("DOMAttrModified", function(evt){
+    var tar = evt.target;
+    if (evt.eventPhase === Event.BUBBLING_PHASE) {
+      return; //強制終了させる
+    }
+    tar.x.baseVal.appendItem(tar.ownerDocument.documentElement.createSVGLength());
+    tar.y.baseVal.appendItem(tar.ownerDocument.documentElement.createSVGLength());
+  }, false);
   return this;
 };
 SVGTextPositioningElement.constructor = SVGTextContentElement;




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