From c0ec1a37745bf3aa5317b2fb77cbb745e5b4cf33 Mon Sep 17 00:00:00 2001 From: Dan Vanderkam Date: Tue, 21 Apr 2015 18:02:04 -0400 Subject: [PATCH] Fix and regression test for fast proxy artifacts. See issue #558 --- auto_tests/tests/fast_canvas_proxy.js | 57 +++++++++++++++++++++++++++++++++++ src/dygraph-canvas.js | 13 ++++++-- 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/auto_tests/tests/fast_canvas_proxy.js b/auto_tests/tests/fast_canvas_proxy.js index a06fe40..5d3322b 100644 --- a/auto_tests/tests/fast_canvas_proxy.js +++ b/auto_tests/tests/fast_canvas_proxy.js @@ -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)); +}); + }); diff --git a/src/dygraph-canvas.js b/src/dygraph-canvas.js index a688c43..a547e05 100644 --- a/src/dygraph-canvas.js +++ b/src/dygraph-canvas.js @@ -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); } -- 2.7.4