[Sie-announce] SIEコード [1760] グラデーション関連の修正

Back to archive index

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;




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