+DygraphCanvasRenderer._drawSeries = function(e,
+ iter, strokeWidth, pointSize, drawPoints, drawGapPoints, stepPlot, color) {
+
+ var prevCanvasX = null;
+ var prevCanvasY = null;
+ var nextCanvasY = null;
+ var isIsolated; // true if this point is isolated (no line segments)
+ var point; // the point being processed in the while loop
+ var pointsOnLine = []; // Array of [canvasx, canvasy] pairs.
+ var first = true; // the first cycle through the while loop
+
+ var ctx = e.drawingContext;
+ ctx.beginPath();
+ ctx.strokeStyle = color;
+ ctx.lineWidth = strokeWidth;
+
+ // NOTE: we break the iterator's encapsulation here for about a 25% speedup.
+ var arr = iter.array_;
+ var limit = iter.end_;
+ var predicate = iter.predicate_;
+
+ for (var i = iter.start_; i < limit; i++) {
+ point = arr[i];
+ if (predicate) {
+ while (i < limit && !predicate(arr, i)) {
+ i++;
+ }
+ if (i == limit) break;
+ point = arr[i];
+ }
+
+ // FIXME: The 'canvasy != canvasy' test here catches NaN values but the test
+ // doesn't catch Infinity values. Could change this to
+ // !isFinite(point.canvasy), but I assume it avoids isNaN for performance?
+ if (point.canvasy === null || point.canvasy != point.canvasy) {
+ if (stepPlot && prevCanvasX !== null) {
+ // Draw a horizontal line to the start of the missing data
+ ctx.moveTo(prevCanvasX, prevCanvasY);
+ ctx.lineTo(point.canvasx, prevCanvasY);
+ }
+ prevCanvasX = prevCanvasY = null;
+ } else {
+ isIsolated = false;
+ if (drawGapPoints || !prevCanvasX) {
+ iter.nextIdx_ = i;
+ iter.next();
+ nextCanvasY = iter.hasNext ? iter.peek.canvasy : null;
+
+ var isNextCanvasYNullOrNaN = nextCanvasY === null ||
+ nextCanvasY != nextCanvasY;
+ isIsolated = (!prevCanvasX && isNextCanvasYNullOrNaN);
+ if (drawGapPoints) {
+ // Also consider a point to be "isolated" if it's adjacent to a
+ // null point, excluding the graph edges.
+ if ((!first && !prevCanvasX) ||
+ (iter.hasNext && isNextCanvasYNullOrNaN)) {
+ isIsolated = true;
+ }
+ }
+ }
+
+ if (prevCanvasX !== null) {
+ if (strokeWidth) {
+ if (stepPlot) {
+ ctx.moveTo(prevCanvasX, prevCanvasY);
+ ctx.lineTo(point.canvasx, prevCanvasY);
+ }
+
+ ctx.lineTo(point.canvasx, point.canvasy);
+ }
+ } else {
+ ctx.moveTo(point.canvasx, point.canvasy);
+ }
+ if (drawPoints || isIsolated) {
+ pointsOnLine.push([point.canvasx, point.canvasy, point.idx]);
+ }
+ prevCanvasX = point.canvasx;
+ prevCanvasY = point.canvasy;
+ }
+ first = false;
+ }
+ ctx.stroke();
+ return pointsOnLine;