Fix and regression test for fast proxy artifacts. 558-fill-artifacts
authorDan Vanderkam <danvdk@gmail.com>
Tue, 21 Apr 2015 22:02:04 +0000 (18:02 -0400)
committerDan Vanderkam <danvdk@gmail.com>
Wed, 22 Apr 2015 14:42:53 +0000 (10:42 -0400)
See issue #558

auto_tests/tests/fast_canvas_proxy.js
src/dygraph-canvas.js

index a06fe40..5d3322b 100644 (file)
@@ -98,4 +98,61 @@ it('testSuperfluousSegmentsElided', function() {
                 ['moveTo', 3, 0]], extractMoveToAndLineToCalls(htx));
 });
 
+
+// For a more visual version of this test, see
+// https://gist.github.com/danvk/e98dbb24253c9b153696
+// The drawing commands in the following two tests are taken from there.
+it('should handle gaps on the left', function() {
+  var htx = new Proxy(fakeCanvasContext);
+  var fastProxy = DygraphCanvasRenderer._fastCanvasProxy(htx);
+
+  fastProxy.moveTo(0, 320);
+  fastProxy.lineTo(0, 320);
+  fastProxy.lineTo(53.21, 187);
+  fastProxy.lineTo(53.23, 29);
+  fastProxy.lineTo(53.41, 320);
+  fastProxy.lineTo(54.15, 320);
+  fastProxy.lineTo(475, 320);
+  fastProxy.lineTo(475, 320);
+  fastProxy.fill();
+
+  assert.deepEqual([
+    ['moveTo', 0, 320],
+    ['lineTo', 0, 320],
+    ['lineTo', 53.21, 187],
+    ['lineTo', 53.23, 29],
+    ['lineTo', 53.41, 320],
+    ['lineTo', 54.15, 320],
+    ['lineTo', 475, 320],
+    ['lineTo', 475, 320]
+  ], extractMoveToAndLineToCalls(htx));
+});
+
+it('should handle gaps on the right', function() {
+  var htx = new Proxy(fakeCanvasContext);
+  var fastProxy = DygraphCanvasRenderer._fastCanvasProxy(htx);
+  fastProxy.moveTo(240.2, 320);
+  fastProxy.lineTo(240.2, 320);
+  fastProxy.lineTo(240.2, 174);
+  fastProxy.lineTo(240.7, 145);
+  fastProxy.lineTo(240.8, 320);
+  fastProxy.lineTo(241.3, 29);
+  fastProxy.lineTo(241.4, 320);
+  fastProxy.lineTo(715.9, 320);
+  fastProxy.lineTo(715.9, 320);
+  fastProxy.fill();
+
+  assert.deepEqual([
+    ['moveTo', 240.2, 320],
+    ['lineTo', 240.2, 320],
+    ['lineTo', 240.2, 174],
+    ['lineTo', 240.7, 145],
+    ['lineTo', 240.8, 320],
+    ['lineTo', 241.3, 29],
+    ['lineTo', 241.4, 320],
+    ['lineTo', 715.9, 320],
+    ['lineTo', 715.9, 320]
+  ], extractMoveToAndLineToCalls(htx));
+});
+
 });
index a688c43..a547e05 100644 (file)
@@ -548,6 +548,7 @@ DygraphCanvasRenderer._errorPlotter = function(e) {
 DygraphCanvasRenderer._fastCanvasProxy = function(context) {
   var pendingActions = [];  // array of [type, x, y] tuples
   var lastRoundedX = null;
+  var lastFlushedX = null;
 
   var LINE_TO = 1,
       MOVE_TO = 2;
@@ -626,6 +627,9 @@ DygraphCanvasRenderer._fastCanvasProxy = function(context) {
         context.moveTo(action[1], action[2]);
       }
     }
+    if (pendingActions.length) {
+      lastFlushedX = pendingActions[pendingActions.length - 1][1];
+    }
     actionCount += pendingActions.length;
     pendingActions = [];
   };
@@ -633,7 +637,12 @@ DygraphCanvasRenderer._fastCanvasProxy = function(context) {
   var addAction = function(action, x, y) {
     var rx = Math.round(x);
     if (lastRoundedX === null || rx != lastRoundedX) {
-      flushActions();
+      // if there are large gaps on the x-axis, it's essential to keep the
+      // first and last point as well.
+      var hasGapOnLeft = (lastRoundedX - lastFlushedX > 1),
+          hasGapOnRight = (rx - lastRoundedX > 1),
+          hasGap = hasGapOnLeft || hasGapOnRight;
+      flushActions(hasGap);
       lastRoundedX = rx;
     }
     pendingActions.push([action, x, y]);
@@ -757,7 +766,7 @@ DygraphCanvasRenderer._fillPlotter = function(e) {
 
     // If the point density is high enough, dropping segments on their way to
     // the canvas justifies the overhead of doing so.
-    if (points.length > 2 * g.width_) {
+    if (points.length > 2 * g.width_ || Dygraph.FORCE_FAST_PROXY) {
       ctx = DygraphCanvasRenderer._fastCanvasProxy(ctx);
     }