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;