]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Fix context state restoration on destroy
authorSimon Brunel <simonbrunel@users.noreply.github.com>
Mon, 7 Nov 2016 23:16:58 +0000 (00:16 +0100)
committerEvert Timberg <evert.timberg+github@gmail.com>
Tue, 8 Nov 2016 00:16:45 +0000 (19:16 -0500)
In many cases, the canvas render size is changed by the lib, causing the state stack to be discarded, meaning that we can't use save() and restore() to release the context with its initial state (i.e. before creating the chart). Since we don't need (want) to manually save / restore the context initial state, simply make sure to reset it to the default state to give a fresh context back to the user. That also means we don't need to revert the scale when the pixel device ratio is not 1.

src/core/core.controller.js
src/core/core.helpers.js
test/core.controller.tests.js

index 8d0bda0f3a67e80feae26ed1f0aac2b6e83bcda8..c746bd66496a08d36bfaf0668c1779695500d732 100644 (file)
@@ -109,6 +109,12 @@ module.exports = function(Chart) {
                        canvas.style[key] = value;
                });
 
+               // The canvas render size might have been changed (and thus the state stack discarded),
+               // we can't use save() and restore() to restore the initial state. So make sure that at
+               // least the canvas context is reset to the default state by setting the canvas width.
+               // https://www.w3.org/TR/2011/WD-html5-20110525/the-canvas-element.html
+               canvas.width = canvas.width;
+
                delete canvas._chartjs;
        }
 
@@ -673,11 +679,6 @@ module.exports = function(Chart) {
                                me.chart.ctx = null;
                        }
 
-                       // if we scaled the canvas in response to a devicePixelRatio !== 1, we need to undo that transform here
-                       if (me.chart.originalDevicePixelRatio !== undefined) {
-                               me.chart.ctx.scale(1 / me.chart.originalDevicePixelRatio, 1 / me.chart.originalDevicePixelRatio);
-                       }
-
                        Chart.plugins.notify('destroy', [me]);
 
                        delete Chart.instances[me.id];
index 8d911fb15bdb3b7cb9b388da1c39229edcbfd32a..11eb6545cd6836c39bed1b96c7649e8d2be232d0 100644 (file)
@@ -842,11 +842,6 @@ module.exports = function(Chart) {
                        canvas.height = height * pixelRatio;
                        canvas.width = width * pixelRatio;
                        ctx.scale(pixelRatio, pixelRatio);
-
-                       // Store the device pixel ratio so that we can go backwards in `destroy`.
-                       // The devicePixelRatio changes with zoom, so there are no guarantees that it is the same
-                       // when destroy is called
-                       chart.originalDevicePixelRatio = chart.originalDevicePixelRatio || pixelRatio;
                }
        };
        // -- Canvas methods
index 13b381060b1c4a1ab8fd7c3d5747ac735bf198ed..9a991d07fd2573ee1b7dee57de72aae60e9fbcc7 100644 (file)
@@ -667,7 +667,33 @@ describe('Chart.Controller', function() {
        });
 
        describe('controller.destroy', function() {
-               it('should restore canvas (and context) initial values', function(done) {
+               it('should reset context to default values', function() {
+                       var chart = acquireChart({});
+                       var context = chart.chart.ctx;
+
+                       chart.destroy();
+
+                       // https://www.w3.org/TR/2dcontext/#conformance-requirements
+                       Chart.helpers.each({
+                               fillStyle: '#000000',
+                               font: '10px sans-serif',
+                               lineJoin: 'miter',
+                               lineCap: 'butt',
+                               lineWidth: 1,
+                               miterLimit: 10,
+                               shadowBlur: 0,
+                               shadowColor: 'rgba(0, 0, 0, 0)',
+                               shadowOffsetX: 0,
+                               shadowOffsetY: 0,
+                               strokeStyle: '#000000',
+                               textAlign: 'start',
+                               textBaseline: 'alphabetic'
+                       }, function(value, key) {
+                               expect(context[key]).toBe(value);
+                       });
+               });
+
+               it('should restore canvas initial values', function(done) {
                        var chart = acquireChart({
                                options: {
                                        responsive: true,