var canvas = dygraph.hidden_;
var ctx = canvas.getContext("2d");
this.imageData_ = ctx.getImageData(0, 0, canvas.width, canvas.height);
+ this.scale = canvas.width / dygraph.width_;
};
/**
* are in [0, 255]. A pixel which has never been touched will be [0,0,0,0].
*/
PixelSampler.prototype.colorAtPixel = function(x, y) {
- var i = 4 * (x + this.imageData_.width * y);
+ var i = 4 * (x * this.scale + this.imageData_.width * y * this.scale);
var d = this.imageData_.data;
return [d[i], d[i+1], d[i+2], d[i+3]];
};
// TODO(danvk): Any performance issues with this?
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
- var i = 4 * (x + imageData.width * y);
+ var scale = Dygraph.getContextPixelRatio(ctx);
+
+ var i = 4 * (x * scale + imageData.width * y * scale);
var d = imageData.data;
return [d[i], d[i+1], d[i+2], d[i+3]];
};
for ( var i = 0; i < gridlines[axis].length; i++) {
y = halfDown(g.toDomYCoord(gridlines[axis][i], axis));
// Ignore the alpha value
+
+ // FIXME(pholden): this test fails with a context pixel ratio of 2.
var drawnPixeldown2 = Util.samplePixel(g.hidden_, x, y - 2).slice(0, 3);
var drawnPixeldown1 = Util.samplePixel(g.hidden_, x, y - 1).slice(0, 3);
var drawnPixel = Util.samplePixel(g.hidden_, x, y).slice(0, 3);
// y pixel 100 = y1 line (green)
// y pixels 0-99 = nothing (white)
- // TODO(danvk): factor this and getPixel() into a utility usable by all tests.
- var ctx = g.hidden_ctx_;
- var imageData = ctx.getImageData(0, 0, 400, 300);
-
- assertEquals(400, imageData.width);
- assertEquals(300, imageData.height);
-
- // returns an (r, g, b, alpha) tuple for the pixel.
- // values are in [0, 255].
- var getPixel = function(imageData, x, y) {
- var i = 4 * (x + imageData.width * y);
- var d = imageData.data;
- return [d[i], d[i+1], d[i+2], d[i+3]];
- };
-
// 38 = round(0.15 * 255)
- assertEquals([0, 0, 255, 38], getPixel(imageData, 200, 250));
- assertEquals([0, 255, 0, 38], getPixel(imageData, 200, 150));
+ assertEquals([0, 0, 255, 38], Util.samplePixel(g.hidden_, 200, 250));
+ assertEquals([0, 255, 0, 38], Util.samplePixel(g.hidden_, 200, 150));
};
// Regression test for http://code.google.com/p/dygraphs/issues/detail?id=358
};
/**
+ * Returns the context's pixel ratio, which is the ratio between the device
+ * pixel ratio and the backing store ratio. Typically this is 1 for conventional
+ * displays, and > 1 for HiDPI displays (such as the Retina MBP).
+ * See http://www.html5rocks.com/en/tutorials/canvas/hidpi/ for more details.
+ *
+ * @param {!CanvasRenderingContext2D} context The canvas's 2d context.
+ * @return {number} The ratio of the device pixel ratio and the backing store
+ * ratio for the specified context.
+ */
+Dygraph.getContextPixelRatio = function(context) {
+ try {
+ var devicePixelRatio = window.devicePixelRatio || 1,
+ backingStoreRatio = context.webkitBackingStorePixelRatio ||
+ context.mozBackingStorePixelRatio ||
+ context.msBackingStorePixelRatio ||
+ context.oBackingStorePixelRatio ||
+ context.backingStorePixelRatio || 1;
+ return devicePixelRatio / backingStoreRatio;
+ } catch (e) {
+ return 1;
+ }
+};
+
+/**
* Checks whether the user is on an Android browser.
* Android does not fully support the <canvas> tag, e.g. w/r/t/ clipping.
* @return {boolean}
// ... and for static parts of the chart.
this.hidden_ = this.createPlotKitCanvas_(this.canvas_);
- this.resizeElements_();
-
this.canvas_ctx_ = Dygraph.getContext(this.canvas_);
this.hidden_ctx_ = Dygraph.getContext(this.hidden_);
+ this.resizeElements_();
+
// The interactive parts of the graph are drawn on top of the chart.
this.graphDiv.appendChild(this.hidden_);
this.graphDiv.appendChild(this.canvas_);
Dygraph.prototype.resizeElements_ = function() {
this.graphDiv.style.width = this.width_ + "px";
this.graphDiv.style.height = this.height_ + "px";
- this.canvas_.width = this.width_;
- this.canvas_.height = this.height_;
+
+ var canvasScale = Dygraph.getContextPixelRatio(this.canvas_ctx_);
+ this.canvas_.width = this.width_ * canvasScale;
+ this.canvas_.height = this.height_ * canvasScale;
this.canvas_.style.width = this.width_ + "px"; // for IE
this.canvas_.style.height = this.height_ + "px"; // for IE
- this.hidden_.width = this.width_;
- this.hidden_.height = this.height_;
+ if (canvasScale !== 1) {
+ this.canvas_ctx_.scale(canvasScale, canvasScale);
+ }
+
+ var hiddenScale = Dygraph.getContextPixelRatio(this.hidden_ctx_);
+ this.hidden_.width = this.width_ * hiddenScale;
+ this.hidden_.height = this.height_ * hiddenScale;
this.hidden_.style.width = this.width_ + "px"; // for IE
this.hidden_.style.height = this.height_ + "px"; // for IE
+ if (hiddenScale !== 1) {
+ this.hidden_ctx_.scale(hiddenScale, hiddenScale);
+ }
};
/**