svnno****@sourc*****
svnno****@sourc*****
2010年 3月 27日 (土) 00:09:53 JST
Revision: 1760 http://sourceforge.jp/projects/sie/svn/view?view=rev&revision=1760 Author: dhrname Date: 2010-03-27 00:09:53 +0900 (Sat, 27 Mar 2010) Log Message: ----------- グラデーション関連の修正 Modified Paths: -------------- branches/ufltima/dom/svg.js Modified: branches/ufltima/dom/svg.js =================================================================== --- branches/ufltima/dom/svg.js 2010-03-25 14:45:24 UTC (rev 1759) +++ branches/ufltima/dom/svg.js 2010-03-26 15:09:53 UTC (rev 1760) @@ -737,8 +737,7 @@ /*SVGURIReferenceオブジェクトはURI参照を用いる要素に適用される *SIEでは、もっぱらXLink言語の処理を行う */ -function SVGURIReference( /*element*/ ele) { - this._tar = ele; +function SVGURIReference() { /*readonly SVGAnimatedString*/ this.href = new SVGAnimatedString(); return this; }; @@ -863,6 +862,10 @@ } tp.align = sa; tp.meetOrSlice = mos; + } else if (name === "width") { + tar.viewport.width = tar.width.baseVal.value; //width属性があれば、viewportの値を上書きする + } else if (name === "height") { + tar.viewport.height = tar.height.baseVal.value; } }, false); this.addEventListener("DOMNodeInsertedIntoDocument", function(evt){ @@ -1995,7 +1998,7 @@ var style = tar.ownerDocument.defaultView.getComputedStyle(tar, ""); var el = tar._tar, fill = style.getPropertyCSSValue("fill"), stroke = style.getPropertyCSSValue("stroke"); if (fill.paintType === SVGPaint.SVG_PAINTTYPE_RGBCOLOR || fill.paintType === SVGPaint.SVG_PAINTTYPE_CURRENTCOLOR) { - var fillElement = !!this.fillElement ? this.fillElement : document.createElement("v:fill"); + var fillElement = !!tar.fillElement ? tar.fillElement : document.createElement("v:fill"); var isRadial = false; var fc = fill.rgbColor, num = CSSPrimitiveValue.CSS_NUMBER; fillElement.setAttribute("color", "rgb(" +fc.red.getFloatValue(num)+ "," +fc.green.getFloatValue(num)+ "," +fc.blue.getFloatValue(num)+ ")"); @@ -2003,9 +2006,9 @@ if (fillOpacity < 1) { fillElement.setAttribute("opacity", fillOpacity+""); } - if (!isRadial && !!!this.fillElement) { + if (!isRadial && !!!tar.fillElement) { el.appendChild(fillElement); - this.fillElement = fillElement; //キャッシュを作る + tar.fillElement = fillElement; //キャッシュを作る } fc = isRadial = fillOpacity = null; } else { @@ -2571,10 +2574,44 @@ function SVGGradientElement() { SVGElement.apply(this, arguments); + SVGURIReference.apply(this, arguments); /*readonly SVGAnimatedEnumeration*/ this.gradientUnits = new SVGAnimatedEnumeration(); /*readonly SVGAnimatedTransformList*/ this.gradientTransform = new SVGAnimatedTransformList(); /*readonly SVGAnimatedEnumeration*/ this.spreadMethod = new SVGAnimatedEnumeration(); - this._xlink = new SVGURIReference(this); + this.addEventListener("DOMNodeInserted", function(evt) { + var grad = evt.target, ele = evt._tar; //eleはv:fill要素やv:stroke要素のノードを収納 + if (!!!ele) { //まだ、path要素などが設定されていない場合 + return; + } + if (grad) { + var grad2 = grad; + while (grad2 && !grad2.hasChildNodes()) { //stopを子要素に持つgradient要素を探す + grad2.getAttributeNS("http://www.w3.org/xlink/1999", "xlink:href").match(/#(.+)/); + grad2 = evt.target.ownerDocument.getElementById(RegExp.$1); + } + var stops = grad2.getElementsByTagNameNS(null, "stop"); + if (!stops) { + grad = grad2 = stops = null; + return; + } + var length = stops.length; + var color = [], colors = [], opacity = []; + for (var i = 0; i < length; ++i) { + var stop = stops[i]; + color[i] = this.color(stop.style.stopcolor || stop.getAttribute("stopcolor")) || "black"; + colors[i] = stop.getAttribute("offset") + " " + color[i]; + opacity[i] = (stop.style.stopopacity || stop.getAttribute("stopopacity") || 1) * this.fillopacity * this.opacity; + } + ele.setAttribute("method", "none"); + ele.setAttribute("color", color[0]); + ele.setAttribute("color2", color[length-1]); + ele.setAttribute("colors", colors.join(",")); + // When colors attribute is used, the meanings of opacity and o:opacity2 are reversed. + ele.setAttribute("opacity", opacity[length-1]+ ""); + ele.setAttribute("o:opacity2", opacity[0]+ ""); + grad = ele = stops = lengh = color = colors = opacity = null; + } + }, false); return this; }; SVGGradientElement.constructor = SVGElement; @@ -2591,6 +2628,19 @@ /*readonly SVGAnimatedLength*/ this.y1 = new SVGAnimatedLength(); /*readonly SVGAnimatedLength*/ this.x2 = new SVGAnimatedLength(); /*readonly SVGAnimatedLength*/ this.y2 = new SVGAnimatedLength(); + this.addEventListener("DOMNodeInsertedIntoDocument", function(evt) { + var grad = evt.target, ele = evt._tar, angle = 270; + if (!!!ele) { //まだ、path要素などが設定されていない場合 + return; + } + angle = 270 - Math.atan2(this.y2.baseVal.value-this.y1.baseVal.value, this.x2.baseVal.value-this.x1.baseVal.value) * 180 / Math.PI; + if (angle >= 360) { + angle -= 360; + } + ele.setAttribute("type", "gradient"); + ele.setAttribute("angle", angle + ""); + grad = angle = null; + }, false); return this; }; SVGLinearGradientElement.constructor = SVGGradientElement; @@ -2603,6 +2653,65 @@ /*readonly SVGAnimatedLength*/ this.r = new SVGAnimatedLength(); /*readonly SVGAnimatedLength*/ this.fx = new SVGAnimatedLength(); /*readonly SVGAnimatedLength*/ this.fy = new SVGAnimatedLength(); + this.addEventListener("DOMNodeInsertedIntoDocument", function(evt) { + var grad = evt.target, ele = evt._tar; + if (!!!ele) { //まだ、path要素などが設定されていない場合 + return; + } + ele.setAttribute("type", "gradientTitle"); + ele.setAttribute("focus", "100%"); + ele.setAttribute("focusposition", "0.5 0.5"); + if (this.tar.getAttribute("tag") === "rect") { + var cx = parseFloat((grad.getAttribute("cx") || "0.5")); + var cy = parseFloat((grad.getAttribute("cy") || "0.5")); + var r = rx = ry = parseFloat((grad.getAttribute("r") || "0.5")); + var el = this.w, et = this.h, er = 0, eb = 0; + var data = this.tar.path.value; + var units = grad.getAttribute("gradientUnits"); + if (!units || units === "objectBoundingBox") { + //%の場合は小数点に変換(10% -> 0.1) + cx = cx > 1 ? cx/100 : cx; cy = cy > 1 ? cy/100 : cy; r = r > 1 ? r/100 : r; + //要素の境界領域を求める(四隅の座標を求める) + var degis = data.match(/[0-9\-]+/g); + for (var i=0,degisli=degis.length;i<degisli;i+=2) { + var nx = parseInt(degis[i]), ny = parseInt(degis[i+1]); + el = el > nx ? nx : el; + et = et > ny ? ny : et; + er = er > nx ? er : nx; + eb = eb > ny ? eb : ny; nx = ny = null; + } + degis = null; + cx = cx*(er - el) + el; cy = cy*(eb - et) + et; rx = r*(er - el); ry = r*(eb - et); + } + var gt = grad.getAttribute("gradientTransform"); + if (gt) { + grad.setAttribute("transform",gt); + matrix = NAIBU.transformToCTM(grad, matrix); + } + el = cx - rx; et = cy - ry; er = cx + rx; eb = cy + ry; + var rrx = rx * 0.55228, rry = ry * 0.55228; + var list = ["m", cx,et, "c", cx-rrx,et, el,cy-rry, el,cy, el,cy+rry, cx-rrx,eb, cx,eb, cx+rrx,eb, er,cy+rry, er,cy, er,cy-rry, cx+rrx,et, cx,et, "x e"]; + var pl = new PList(list); + var plm = pl.matrixTransform(matrix); + var ellipse = plm.list.join(" "); + var outline = document.getElementById("_NAIBU_outline"); + var background = document.createElement("div"), bstyle = background.style; + bstyle.position = "absolute"; + bstyle.display = "inline-block"; + bstyle.textAlign = "left"; bstyle.top = "0px"; bstyle.left = "0px"; bstyle.width = this.w+ "px"; bstyle.height = this.h+ "px"; + outline.appendChild(background); + bstyle.filter = "progid:DXImageTransform.Microsoft.Compositor"; + background.filters.item('DXImageTransform.Microsoft.Compositor').Function = 23; + var circle = '<v:shape style="display:inline-block; position:relative; antialias:false; top:0px; left:0px;" coordsize="' +this.w+ ' ' +this.h+ '" path="' +ellipse+ '" stroked="f">' +ele.outerHTML+ '</v:shape>'; + background.innerHTML = '<v:shape style="display:inline-block; position:relative; top:0px; left:0px;" coordsize="' +this.w+ ' ' +this.h+ '" path="' +data+ '" stroked="f" fillcolor="' +color[color.length-1]+ '" ></v:shape>'; + background.filters[0].apply(); + background.innerHTML = circle; + background.filters[0].play(); + this.tar.parentNode.insertBefore(background, this.tar); + this.tar.filled = "false"; + ellipse = circle = data = list = pl = plm = gt = cx = cy = r = null; + } + }, false); return this; }; SVGRadialGradientElement.constructor = SVGGradientElement;