pv.SvgScene.area = function(scenes) { var e = scenes.$g.firstChild; if (!scenes.length) return e; var s = scenes[0]; /* segmented */ if (s.segmented) return this.areaSegment(scenes); /* visible */ if (!s.visible) return e; var fill = s.fillStyle, stroke = s.strokeStyle; if (!fill.opacity && !stroke.opacity) return e; /** @private Computes the straight path for the range [i, j]. */ function path(i, j) { var p1 = [], p2 = []; for (var k = j; i <= k; i++, j--) { var si = scenes[i], sj = scenes[j], pi = si.left + "," + si.top, pj = (sj.left + sj.width) + "," + (sj.top + sj.height); /* interpolate */ if (i < k) { var sk = scenes[i + 1], sl = scenes[j - 1]; switch (s.interpolate) { case "step-before": { pi += "V" + sk.top; pj += "H" + (sl.left + sl.width); break; } case "step-after": { pi += "H" + sk.left; pj += "V" + (sl.top + sl.height); break; } } } p1.push(pi); p2.push(pj); } return p1.concat(p2).join("L"); } /** @private Computes the curved path for the range [i, j]. */ function pathCurve(i, j) { var pointsT = [], pointsB = [], pathT, pathB; for (var k = j; i <= k; i++, j--) { var sj = scenes[j]; pointsT.push(scenes[i]); pointsB.push({left: sj.left + sj.width, top: sj.top + sj.height}); } if (s.interpolate == "basis") { pathT = pv.SvgScene.curveBasis(pointsT); pathB = pv.SvgScene.curveBasis(pointsB); } else if (s.interpolate == "cardinal") { pathT = pv.SvgScene.curveCardinal(pointsT, s.tension); pathB = pv.SvgScene.curveCardinal(pointsB, s.tension); } else { // monotone pathT = pv.SvgScene.curveMonotone(pointsT); pathB = pv.SvgScene.curveMonotone(pointsB); } return pointsT[0].left + "," + pointsT[0].top + pathT + "L" + pointsB[0].left + "," + pointsB[0].top + pathB; } /* points */ var d = [], si, sj; for (var i = 0; i < scenes.length; i++) { si = scenes[i]; if (!si.width && !si.height) continue; for (var j = i + 1; j < scenes.length; j++) { sj = scenes[j]; if (!sj.width && !sj.height) break; } if (i && (s.interpolate != "step-after")) i--; if ((j < scenes.length) && (s.interpolate != "step-before")) j++; d.push(((j - i > 2 && (s.interpolate == "basis" || s.interpolate == "cardinal" || s.interpolate == "monotone")) ? pathCurve : path)(i, j - 1)); i = j - 1; } if (!d.length) return e; e = this.expect(e, "path", { "shape-rendering": s.antialias ? null : "crispEdges", "pointer-events": s.events, "cursor": s.cursor, "d": "M" + d.join("ZM") + "Z", "fill": fill.color, "fill-opacity": fill.opacity || null, "stroke": stroke.color, "stroke-opacity": stroke.opacity || null, "stroke-width": stroke.opacity ? s.lineWidth / this.scale : null }); return this.append(e, scenes, 0); }; pv.SvgScene.areaSegment = function(scenes) { var e = scenes.$g.firstChild, s = scenes[0], pathsT, pathsB; if (s.interpolate == "basis" || s.interpolate == "cardinal" || s.interpolate == "monotone") { var pointsT = [], pointsB = []; for (var i = 0, n = scenes.length; i < n; i++) { var sj = scenes[n - i - 1]; pointsT.push(scenes[i]); pointsB.push({left: sj.left + sj.width, top: sj.top + sj.height}); } if (s.interpolate == "basis") { pathsT = this.curveBasisSegments(pointsT); pathsB = this.curveBasisSegments(pointsB); } else if (s.interpolate == "cardinal") { pathsT = this.curveCardinalSegments(pointsT, s.tension); pathsB = this.curveCardinalSegments(pointsB, s.tension); } else { // monotone pathsT = this.curveMonotoneSegments(pointsT); pathsB = this.curveMonotoneSegments(pointsB); } } for (var i = 0, n = scenes.length - 1; i < n; i++) { var s1 = scenes[i], s2 = scenes[i + 1]; /* visible */ if (!s1.visible || !s2.visible) continue; var fill = s1.fillStyle, stroke = s1.strokeStyle; if (!fill.opacity && !stroke.opacity) continue; var d; if (pathsT) { var pathT = pathsT[i], pathB = "L" + pathsB[n - i - 1].substr(1); d = pathT + pathB + "Z"; } else { /* interpolate */ var si = s1, sj = s2; switch (s1.interpolate) { case "step-before": si = s2; break; case "step-after": sj = s1; break; } /* path */ d = "M" + s1.left + "," + si.top + "L" + s2.left + "," + sj.top + "L" + (s2.left + s2.width) + "," + (sj.top + sj.height) + "L" + (s1.left + s1.width) + "," + (si.top + si.height) + "Z"; } e = this.expect(e, "path", { "shape-rendering": s1.antialias ? null : "crispEdges", "pointer-events": s1.events, "cursor": s1.cursor, "d": d, "fill": fill.color, "fill-opacity": fill.opacity || null, "stroke": stroke.color, "stroke-opacity": stroke.opacity || null, "stroke-width": stroke.opacity ? s1.lineWidth / this.scale : null }); e = this.append(e, scenes, i); } return e; };