svnno****@sourc*****
svnno****@sourc*****
2010年 10月 7日 (木) 19:15:02 JST
Revision: 2041
http://sourceforge.jp/projects/sie/svn/view?view=rev&revision=2041
Author: dhrname
Date: 2010-10-07 19:15:02 +0900 (Thu, 07 Oct 2010)
Log Message:
-----------
tspan要素の実装とtext要素のバグを修正
Modified Paths:
--------------
branches/06x/061/org/w3c/dom/svg.js
Modified: branches/06x/061/org/w3c/dom/svg.js
===================================================================
--- branches/06x/061/org/w3c/dom/svg.js 2010-10-05 13:54:09 UTC (rev 2040)
+++ branches/06x/061/org/w3c/dom/svg.js 2010-10-07 10:15:02 UTC (rev 2041)
@@ -3250,8 +3250,10 @@
function SVGTextContentElement() {
SVGElement.apply(this);
- this._list = []; //文字の位置を格納しておくリスト
- this._length = 0; //全文字数
+ this._list = null; //文字の位置を格納しておくリストのキャッシュ
+ this._length = 0; //全文字数
+ this._stx = this._sty = 0; //初めの文字の位置
+ this._chars = 0; //tspan要素が全体の何文字目から始まっているか
/*readonly SVGAnimatedLength*/ this.textLength = new SVGAnimatedLength();
/*readonly SVGAnimatedEnumeration*/ this.lengthAdjust = new SVGAnimatedEnumeration(SVGTextContentElement.LENGTHADJUST_UNKNOWN);
this._isYokogaki = true;
@@ -3327,6 +3329,136 @@
if (charnum > this.getNumberOfChars() || charnum < 0) {
throw (new DOMException(DOMException.INDEX_SIZE_ERR));
} else {
+ var tar = this, ti = tar.firstChild, tp = tar.parentNode;
+ if (!!!tar._list) {
+ tar._list = [];
+ var chars = tar._chars; //現在、何文字目にあるのか
+ var x = tar._stx, y = tar._sty, n = 0; //現在のテキスト位置と順番
+ var style = tar.ownerDocument.defaultView.getComputedStyle(tar, null);
+ var isYokogaki = ((style.getPropertyValue("writing-mode")) === "lr-tb") ? true : false;
+ var fontSize = parseFloat(style.getPropertyValue("font-size"));
+ var tx = tar.x.baseVal, ty = tar.y.baseVal, tdx = tar.dx.baseVal, tdy = tar.dy.baseVal;
+ /*親要素の属性も参照しておく*/
+ var isText = tp.localName === "text";
+ if (tp && (isText ||(tp.localName === "tspan"))) {
+ var ptx = tp.x.baseVal, pty = tp.y.baseVal, ptdx = tp.dx.baseVal, ptdy = tp.dy.baseVal;
+ } else {
+ var ptx = pty = ptdx = ptdy = {numberOfItems : 0};
+ }
+ var kern = "f ijltIr.,:;'-\"()", akern = "1234567890abcdeghknopquvxyz";
+ if (isYokogaki && isText) {
+ y += fontSize * 0.2;
+ } else if (isText){
+ x -= fontSize * 0.5;
+ }
+ while (ti) {
+ if (ti.nodeType === Node.TEXT_NODE) {
+ var tt = ti._tars;
+ /*tspan要素のx属性で指定された座標の個数よりも、文字数が多い場合は、祖先(親)のx属性を
+ *使う。また、属性が指定されていないときも同様に祖先や親を使う。
+ *もし、仮に祖先や親がx属性を指定されていなければ、現在のテキスト位置(変数xに格納している)を使う。
+ *この処理はdx属性やdy、y属性でも同様とする
+ *参照資料SVG1.1 Text
+ *http://www.hcn.zaq.ne.jp/___/REC-SVG11-20030114/text.html
+ *
+ *注意:ここでは、tspan要素だけではなく、text要素にも適用しているが、本来はtspan要素のみに処理させること
+ */
+ for (var i=0, tli=tt.length;i<tli;++i) {
+ if (n < ptx.numberOfItems - chars) {
+ x = ptx.getItem(n).value;
+ if (!isYokogaki) {
+ x -= fontSize * 0.5;
+ }
+ } else if (n < tx.numberOfItems) {
+ x = tx.getItem(n).value;
+ if (!isYokogaki) {
+ x -= fontSize * 0.5;
+ }
+ }
+ if (n < pty.numberOfItems - chars) {
+ y = pty.getItem(n).value;
+ if (isYokogaki) {
+ y += fontSize * 0.2;
+ }
+ } else if (n < ty.numberOfItems) {
+ y = ty.getItem(n).value;
+ if (isYokogaki) {
+ y += fontSize * 0.2;
+ }
+ }
+ if (n < ptdx.numberOfItems - chars) {
+ x += ptdx.getItem(n).value;
+ } else if (n < tdx.numberOfItems) {
+ x += tdx.getItem(n).value;
+ }
+ if (n < ptdy.numberOfItems - chars) {
+ y += ptdy.getItem(n).value;
+ } else if (n < tdy.numberOfItems) {
+ y += tdy.getItem(n).value;
+ }
+ var alm = 0;
+ if (isYokogaki) {
+ //カーニングを求めて、字の幅を文字ごとに調整する
+ var tdc = ti.data.charAt(i);
+ if (kern.indexOf(tdc) > -1) {
+ alm = fontSize * 0.68;
+ } else if (tdc === "s"){
+ alm = fontSize * 0.52;
+ } else if ((tdc === "C") || (tdc === "D") || (tdc === "M") || (tdc === "W") || (tdc === "G") || (tdc === "m")){
+ alm = fontSize * 0.2;
+ } else if (akern.indexOf(tdc) > -1){
+ alm = fontSize * 0.45;
+ } else {
+ alm = fontSize * 0.3;
+ }
+ var tcca = tdc.charCodeAt(0);
+ if ((12288 <= tcca) && (tcca <= 65533)) {
+ alm = -fontSize * 0.01;
+ if ((tdc === "う") || (tdc === "く") || (tdc === "し") || (tdc === "ち")) {
+ alm += fontSize * 0.2;
+ }
+ }
+ tcca = null;
+ }
+ tar._list[tar._list.length] = x;
+ tar._list[tar._list.length] = y;
+ tar._list[tar._list.length] = fontSize - alm;
+ if (isYokogaki) {
+ x += fontSize;
+ x -= alm;
+ } else {
+ y += fontSize;
+ }
+ ++n;
+ }
+ chars += tli;
+ } else if ((ti.localName === "tspan") && (ti.namespaceURI === "http://www.w3.org/2000/svg") && ti.firstChild) {
+ /*現在のテキスト位置(x,y)の分だけ、tspan要素をずらしておく。
+ *さらに、現在のテキスト位置を更新する
+ */
+ ti._stx = x;
+ ti._sty = y;
+ ti._chars = chars;
+ var p = ti.getStartPositionOfChar(ti.getNumberOfChars());
+ var almx = 0, almy = 0;
+ if (isYokogaki) {
+ almx = ti._list[ti._list.length-1];
+ } else {
+ almy = ti._list[ti._list.length-1];
+ }
+ x = ti._list[ti._list.length-3] + almx;
+ y = ti._list[ti._list.length-2] + almy;
+ tar._list = tar._list.concat(ti._list);
+ var tg = ti.getNumberOfChars();
+ n += tg;
+ chars += tg;
+ p = tg = null;
+ }
+ ti = ti.nextSibling;
+ }
+ tar._isYokogaki = isYokogaki //getEndPositionOfCharメソッドなどで使う
+ tar = ti = tp = ptx = pty = tx = ty = chars = style = x = y = isYokogaki = null;
+ }
var s = this.ownerDocument.documentElement.createSVGPoint();
s.x = this._list[charnum*3];
s.y = this._list[charnum*3 + 1];
@@ -3414,140 +3546,17 @@
tea.newValueSpecifiedUnits(type, s);
teas.appendItem(tea);
}
+ tar._list = null;
}
evt = tar = null;
}, false);
this.addEventListener("DOMNodeInserted", function(evt){
if (evt.eventPhase === Event.BUBBLING_PHASE) {
- var tar = evt.target, ttn = 2;
- if ((tar.nodeType === Node.TEXT_NODE)) {
- /*もし、仮にテキストノードであれば、以下のループ処理については、
- *currentTargetの一回だけで済ますようにする
- */
- tar = evt.currentTarget;
- ttn = 1;
+ var tar = evt.target;
+ if (tar.nodeType !== Node.TEXT_NODE) {
+ tar._list = null;
+ evt.currentTarget._list = null;
}
- for (var k=0;k<ttn;++k) {
- var ti = tar.firstChild, tp = tar.parentNode;
- tar._list = []; //リストの初期化
- var x = 0, y = 0, n = 0; //現在のテキスト位置と順番
- var style = tar.ownerDocument.defaultView.getComputedStyle(tar, null);
- var isYokogaki = ((style.getPropertyValue("writing-mode")) === "lr-tb") ? true : false;
- var fontSize = parseFloat(style.getPropertyValue("font-size"));
- var tx = tar.x.baseVal, ty = tar.y.baseVal, tdx = tar.dx.baseVal, tdy = tar.dy.baseVal;
- /*親要素の属性も参照しておく*/
- if (tp && ((tp.localName === "text")||(tp.localName === "tspan"))) {
- var ptx = tp.x.baseVal, pty = tp.y.baseVal, ptdx = tp.dx.baseVal, ptdy = tp.dy.baseVal;
- } else {
- var ptx = pty = ptdx = ptdy = {numberOfItems : 0};
- }
- var kern = "f ijltIr.,:;'-\"()", akern = "1234567890abcdeghknopquvxyz";
- if (isYokogaki) {
- y += fontSize * 0.2;
- } else {
- x -= fontSize * 0.5;
- }
- while (ti) {
- if (ti.nodeType === Node.TEXT_NODE) {
- var tt = ti._tars;
- /*tspan要素のx属性で指定された座標の個数よりも、文字数が多い場合は、祖先(親)のx属性を
- *使う。また、属性が指定されていないときも同様に祖先や親を使う。
- *もし、仮に祖先や親がx属性を指定されていなければ、現在のテキスト位置(変数xに格納している)を使う。
- *この処理はdx属性やdy、y属性でも同様とする
- *参照資料SVG1.1 Text
- *http://www.hcn.zaq.ne.jp/___/REC-SVG11-20030114/text.html
- *
- *注意:ここでは、tspan要素だけではなく、text要素にも適用しているが、本来はtspan要素のみに処理させること
- */
- for (var i=0, tli=tt.length;i<tli;++i) {
- if (n < ptx.numberOfItems) {
- x = ptx.getItem(n).value;
- if (!isYokogaki) {
- x -= fontSize * 0.5;
- }
- } else if (n < tx.numberOfItems) {
- x = tx.getItem(n).value;
- if (!isYokogaki) {
- x -= fontSize * 0.5;
- }
- }
- if (n < pty.numberOfItems) {
- y = pty.getItem(n).value;
- if (isYokogaki) {
- y += fontSize * 0.2;
- }
- } else if (n < ty.numberOfItems) {
- y = ty.getItem(n).value;
- if (isYokogaki) {
- y += fontSize * 0.2;
- }
- }
- if (n < ptdx.numberOfItems) {
- x += ptdx.getItem(n).value;
- } else if (n < tdx.numberOfItems) {
- x += tdx.getItem(n).value;
- }
- if (n < ptdy.numberOfItems) {
- y += ptdy.getItem(n).value;
- } else if (n < tdy.numberOfItems) {
- y += tdy.getItem(n).value;
- }
- var alm = 0;
- if (isYokogaki) {
- //カーニングを求めて、字の幅を文字ごとに調整する
- var tdc = ti.data.charAt(i);
- if (kern.indexOf(tdc) > -1) {
- alm = fontSize * 0.68;
- } else if (tdc === "s"){
- alm = fontSize * 0.52;
- } else if ((tdc === "C") || (tdc === "D") || (tdc === "M") || (tdc === "W") || (tdc === "G") || (tdc === "m")){
- alm = fontSize * 0.2;
- } else if (akern.indexOf(tdc) > -1){
- alm = fontSize * 0.45;
- } else {
- alm = fontSize * 0.3;
- }
- var tcca = tdc.charCodeAt(0);
- if ((12288 <= tcca) && (tcca <= 65533)) {
- alm = -fontSize * 0.01;
- if ((tdc === "う") || (tdc === "く") || (tdc === "し") || (tdc === "ち")) {
- alm += fontSize * 0.2;
- }
- }
- tcca = null;
- }
- tar._list[tar._list.length] = x;
- tar._list[tar._list.length] = y;
- tar._list[tar._list.length] = fontSize - alm;
- if (isYokogaki) {
- x += fontSize;
- x -= alm;
- } else {
- y += fontSize;
- }
- ++n;
- }
- } else if ((ti.localName === "tspan") && (ti.namespaceURI === "http://www.w3.org/2000/svg") && ti.firstChild) {
- /*現在のテキスト位置(x,y)の分だけ、tspan要素をずらしておく。
- *さらに、現在のテキスト位置を更新する
- */
- for (var j=0, ttls=ti._list.length;j<ttls;++j) {
- ti._list[j] += x;
- ++j;
- ti._list[j] += y;
- ++j;
- }
- x = ti._list[ti._list.length-3];
- y = ti._list[ti._list.length-2];
- tar._list = tar._list.concat(ti._list);
- n += ti.getNumberOfChars();
- }
- ti = ti.nextSibling;
- }
- tar._isYokogaki = isYokogaki //getEndPositionOfCharメソッドなどで使う
- tar = evt.currentTarget;
- style = null;
- }
evt = tar = null;
}
}, false);
@@ -3605,7 +3614,8 @@
for (var i=0, j=0, tli=tar.getNumberOfChars();i<tli;++i) {
if (ti) {
if (!!ti._tars) {
- var sty = ti._tars[i-j].style, p = tar.getStartPositionOfChar(i);
+ var ij = (i > j) ? i - j : j - i
+ var sty = ti._tars[ij].style, p = tar.getStartPositionOfChar(i);
sty.position = "absolute";
if (tar._isYokogaki) {
if (anchor === "middle") {
@@ -3626,7 +3636,7 @@
sty.height = "0px";
sty.marginTop = tar._isYokogaki ? -n+ "px" : "0px";
sty.lineHeight = n+ "px";
- tar._tar.appendChild(ti._tars[i]);
+ tar._tar.appendChild(ti._tars[ij]);
sty = p = null;
}
if (!!ti.data) {
@@ -3637,7 +3647,6 @@
} else if (!!ti.getNumberOfChars) {
if ((ti.getNumberOfChars()+j) <= i+1) {
j = j + i + 1;
- i += j;
ti = ti.nextSibling;
}
}