comments
[dygraphs.git] / dygraph-canvas.js
index 887c6ff..450c8a9 100644 (file)
@@ -243,7 +243,6 @@ DygraphCanvasRenderer._predicateThatSkipsEmptyPoints =
 };
 
 /**
- *
  * @private
  */
 DygraphCanvasRenderer.prototype._drawStyledLine = function(
@@ -306,14 +305,19 @@ DygraphCanvasRenderer.prototype._drawSeries = function(
   ctx.strokeStyle = color;
   ctx.lineWidth = strokeWidth;
 
-  for (var i = iter.start_; i < iter.end_; i++) {
-    // while (iter.hasNext) {
-    point = iter.array_[i];
-    if (iter.predicate_) {
-      while (i < iter.end_ && !iter.predicate_(iter.array_, i)) {
+  // 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 == iter.end_) break;
+      if (i == limit) break;
+      point = arr[i];
     }
 
     if (point.canvasy === null || point.canvasy != point.canvasy) {
@@ -326,18 +330,10 @@ DygraphCanvasRenderer.prototype._drawSeries = function(
     } else {
       isIsolated = false;
       if (drawGapPoints || !prevCanvasX) {
-        // nextCanvasY = iter.hasNext ? iter.peek.canvasy : null;
-        // var next_i = i + 1;
-        // while (next_i < iter.end_ && (!iter.predicate_ || !iter.predicate_(iter.array_, next_i))) {
-        //   next_i++;
-        // }
         iter.nextIdx_ = i;
         var peek = iter.next();
-        nextCanvasY = peek ? peek.canvasy : null;
-        // nextCanvasY = next_i < iter.end_ ? iter.array_[next_i].canvasy : null;
+        nextCanvasY = iter.hasNext ? iter.peek.canvasy : null;
 
-        // TODO: we calculate isNullOrNaN for this point, and the next, and then,
-        // when we iterate, test for isNullOrNaN again. Why bother?
         var isNextCanvasYNullOrNaN = nextCanvasY === null ||
             nextCanvasY != nextCanvasY;
         isIsolated = (!prevCanvasX && isNextCanvasYNullOrNaN);
@@ -358,6 +354,8 @@ DygraphCanvasRenderer.prototype._drawSeries = function(
             ctx.lineTo(point.canvasx, prevCanvasY);
             prevCanvasX = point.canvasx;
           }
+
+          // TODO(danvk): this moveTo is rarely necessary
           ctx.moveTo(prevCanvasX, prevCanvasY);
           ctx.lineTo(point.canvasx, point.canvasy);
         }
@@ -423,6 +421,12 @@ DygraphCanvasRenderer.prototype._renderLineChart = function() {
   // TODO(bhs): this loop is a hot-spot for high-point-count charts. These
   // transformations can be pushed into the canvas via linear transformation
   // matrices.
+  // NOTE(danvk): this is trickier than it sounds at first. The transformation
+  // needs to be done before the .moveTo() and .lineTo() calls, but must be
+  // undone before the .stroke() call to ensure that the stroke width is
+  // unaffected.  An alternative is to reduce the stroke width in the
+  // transformed coordinate space, but you can't specify different values for
+  // each dimension (as you can with .scale()). The speedup here is ~12%.
   var points = this.layout.points;
   for (i = points.length; i--;) {
     var point = points[i];
@@ -499,7 +503,6 @@ DygraphCanvasRenderer.prototype.drawErrorBars_ = function(points) {
         continue;
       }
 
-      // TODO(danvk): here
       if (stepPlot) {
         newYs = [ point.y_bottom, point.y_top ];
         prevY = point.y;