1 var guid = 0;
  2 
  3 pv.SvgScene.panel = function(scenes) {
  4   var g = scenes.$g, e = g && g.firstChild;
  5   for (var i = 0; i < scenes.length; i++) {
  6     var s = scenes[i];
  7 
  8     /* visible */
  9     if (!s.visible) continue;
 10 
 11     /* svg */
 12     if (!scenes.parent) {
 13       s.canvas.style.display = "inline-block";
 14       g = s.canvas.firstChild;
 15       if (!g) {
 16         g = s.canvas.appendChild(this.create("svg"));
 17         g.onclick
 18             = g.onmousedown
 19             = g.onmouseup
 20             = g.onmousemove
 21             = g.onmouseout
 22             = g.onmouseover
 23             = pv.SvgScene.dispatch;
 24       }
 25       scenes.$g = g;
 26       g.setAttribute("width", s.width + s.left + s.right);
 27       g.setAttribute("height", s.height + s.top + s.bottom);
 28       if (typeof e == "undefined") e = g.firstChild;
 29     }
 30 
 31     /* clip (nest children) */
 32     if (s.overflow == "hidden") {
 33       var c = this.expect("g", e), id = (guid++).toString(36);
 34       c.setAttribute("clip-path", "url(#" + id + ")");
 35       if (!c.parentNode) g.appendChild(c);
 36       scenes.$g = g = c;
 37       e = c.firstChild;
 38 
 39       e = this.expect("clipPath", e);
 40       e.setAttribute("id", id);
 41       var r = e.firstChild ||  e.appendChild(this.create("rect"));
 42       r.setAttribute("x", s.left);
 43       r.setAttribute("y", s.top);
 44       r.setAttribute("width", s.width);
 45       r.setAttribute("height", s.height);
 46       if (!e.parentNode) g.appendChild(e);
 47       e = e.nextSibling;
 48     }
 49 
 50     /* fill */
 51     e = this.fill(e, scenes, i);
 52 
 53     /* children */
 54     for (var j = 0; j < s.children.length; j++) {
 55       s.children[j].$g = e = this.expect("g", e);
 56       e.setAttribute("transform", "translate(" + s.left + "," + s.top + ")");
 57       this.updateAll(s.children[j]);
 58       if (!e.parentNode) g.appendChild(e);
 59       e = e.nextSibling;
 60     }
 61 
 62     /* stroke */
 63     e = this.stroke(e, scenes, i);
 64 
 65     /* clip (restore group) */
 66     if (s.overflow == "hidden") {
 67       scenes.$g = g = c.parentNode;
 68       e = c.nextSibling;
 69     }
 70   }
 71   return e;
 72 };
 73 
 74 pv.SvgScene.fill = function(e, scenes, i) {
 75   var s = scenes[i], fill = pv.color(s.fillStyle);
 76   if (fill.opacity) {
 77     e = this.expect("rect", e);
 78     e.setAttribute("x", s.left);
 79     e.setAttribute("y", s.top);
 80     e.setAttribute("width", s.width);
 81     e.setAttribute("height", s.height);
 82     e.setAttribute("cursor", s.cursor);
 83     e.setAttribute("fill", fill.color);
 84     e.setAttribute("fill-opacity", fill.opacity);
 85     e = this.append(e, scenes, i);
 86   }
 87   return e;
 88 };
 89 
 90 pv.SvgScene.stroke = function(e, scenes, i) {
 91   var s = scenes[i], stroke = pv.color(s.strokeStyle);
 92   if (stroke.opacity) {
 93     e = this.expect("rect", e);
 94     e.setAttribute("x", s.left);
 95     e.setAttribute("y", s.top);
 96     e.setAttribute("width", Math.max(1E-10, s.width));
 97     e.setAttribute("height", Math.max(1E-10, s.height));
 98     e.setAttribute("cursor", s.cursor);
 99     e.setAttribute("fill", "none");
100     e.setAttribute("stroke", stroke.color);
101     e.setAttribute("stroke-opacity", stroke.opacity);
102     e.setAttribute("stroke-width", s.lineWidth);
103     e = this.append(e, scenes, i);
104   }
105   return e;
106 };
107