+ // For filled charts, we draw points from left to right, then back along
+ // the x-axis to complete a shape for filling.
+ // For stacked plots, this "back path" is a more complex shape. This array
+ // stores the [x, y] values needed to trace that shape.
+ var pathBack = [];
+
+ var traceBackPath = function(baselineX, baselineY) {
+ ctx.lineTo(baselineX, baselineY);
+ if (stackedGraph) {
+ for (var i = pathBack.length - 1; i >= 0; i--) {
+ var pt = pathBack[i];
+ ctx.lineTo(pt[0], pt[1]);
+ }
+ }
+ pathBack = [];
+ };
+
+ // TODO(danvk): there are a lot of options at play in this loop.
+ // The logic would be much clearer if some (e.g. stackGraph and
+ // stepPlot) were split off into separate sub-plotters.
+ while (iter.hasNext) {
+ var point = iter.next();
+ if (!Dygraph.isOK(point.y) && !stepPlot) {
+ traceBackPath(prevX, prevYs[1]);
+ prevX = NaN;
+ if (point.y_stacked !== null && !isNaN(point.y_stacked)) {
+ baseline[point.canvasx] = area.h * point.y_stacked + area.y;
+ }
+ continue;
+ }
+ if (stackedGraph) {
+ if (!is_first && last_x == point.xval) {
+ continue;
+ } else {
+ is_first = false;
+ last_x = point.xval;
+ }
+
+ currBaseline = baseline[point.canvasx];
+ var lastY;
+ if (currBaseline === undefined) {
+ lastY = axisY;
+ } else {
+ if(prevStepPlot) {
+ lastY = currBaseline[0];
+ } else {
+ lastY = currBaseline;
+ }
+ }
+ newYs = [ point.canvasy, lastY ];
+
+ if (stepPlot) {
+ // Step plots must keep track of the top and bottom of
+ // the baseline at each point.
+ if (prevYs[0] === -1) {
+ baseline[point.canvasx] = [ point.canvasy, axisY ];
+ } else {
+ baseline[point.canvasx] = [ point.canvasy, prevYs[0] ];
+ }
+ } else {
+ baseline[point.canvasx] = point.canvasy;
+ }
+
+ } else {
+ if (isNaN(point.canvasy) && stepPlot) {
+ newYs = [ area.y + area.h, axisY ];
+ } else {
+ newYs = [ point.canvasy, axisY ];
+ }
+ }
+ if (!isNaN(prevX)) {
+ // Move to top fill point
+ if (stepPlot) {
+ ctx.lineTo(point.canvasx, prevYs[0]);
+ ctx.lineTo(point.canvasx, newYs[0]);
+ } else {
+ ctx.lineTo(point.canvasx, newYs[0]);
+ }
+
+ // Record the baseline for the reverse path.
+ if (stackedGraph) {
+ pathBack.push([prevX, prevYs[1]]);
+ if (prevStepPlot && currBaseline) {
+ // Draw to the bottom of the baseline
+ pathBack.push([point.canvasx, currBaseline[1]]);
+ } else {
+ pathBack.push([point.canvasx, newYs[1]]);
+ }
+ }
+ } else {
+ ctx.moveTo(point.canvasx, newYs[1]);
+ ctx.lineTo(point.canvasx, newYs[0]);
+ }
+ prevYs = newYs;
+ prevX = point.canvasx;
+ }
+ prevStepPlot = stepPlot;
+ if (newYs) {
+ traceBackPath(point.canvasx, newYs[1]);