Implement proper support for HiDPI screens.

For performance reason optional for now, activated by setting the hidpi attribute on the canvas element.
This commit is contained in:
Jürg Lehni 2013-11-06 11:54:05 +01:00
parent b514d04f58
commit 8d7fc43de2
3 changed files with 39 additions and 25 deletions

View file

@ -23,7 +23,6 @@ var options = {
fatline: true,
paperscript: true,
palette: true,
hiDPI: false,
nativeContains: false,
debug: false
};

View file

@ -45,26 +45,34 @@ var CanvasView = View.extend(/** @lends CanvasView# */{
var ctx = this._context = canvas.getContext('2d');
// Have Item count installed mouse events.
this._eventCounters = {};
/*#*/ if (options.hiDPI) {
// Hi-DPI Canvas support based on:
// http://www.html5rocks.com/en/tutorials/canvas/hidpi/
var ratio = (window.devicePixelRatio || 1) / (DomElement.getPrefixValue(
ctx, 'backingStorePixelRatio') || 1);
this._ratio = 1;
if (PaperScope.hasAttribute(canvas, 'hidpi')) {
// Hi-DPI Canvas support based on:
// http://www.html5rocks.com/en/tutorials/canvas/hidpi/
var deviceRatio = window.devicePixelRatio || 1,
backingStoreRatio = DomElement.getPrefixValue(ctx,
'backingStorePixelRatio') || 1;
this._ratio = deviceRatio / backingStoreRatio;
}
View.call(this, canvas);
},
_setViewSize: function(size) {
var width = size.width,
height = size.height,
ratio = this._ratio,
element = this._element,
style = element.style;
// Upscale the canvas if the two ratios don't match.
if (ratio > 1) {
var width = canvas.clientWidth,
height = canvas.clientHeight,
style = canvas.style;
canvas.width = width * ratio;
canvas.height = height * ratio;
element.width = width * ratio;
element.height = height * ratio;
if (ratio !== 1) {
style.width = width + 'px';
style.height = height + 'px';
// Now scale the context to counter the fact that we've manually
// scaled our canvas element.
ctx.scale(ratio, ratio);
this._context.scale(ratio, ratio);
}
/*#*/ } // options.hiDPI
View.call(this, canvas);
},
/**
@ -81,7 +89,7 @@ var CanvasView = View.extend(/** @lends CanvasView# */{
// http://jsperf.com/clearrect-vs-setting-width/7
var ctx = this._context,
size = this._viewSize;
ctx.clearRect(0, 0, size._width + 1, size._height + 1);
ctx.clearRect(0, 0, size.width + 1, size.height + 1);
this._project.draw(ctx, this._matrix);
this._project._needsRedraw = false;
return true;

View file

@ -71,8 +71,8 @@ var View = Base.extend(Callback, /** @lends View# */{
// Set canvas size even if we just deterined the size from it, since
// it might have been set to a % size, in which case it would use some
// default internal size (300x150 on WebKit) and scale up the pixels.
element.width = size.width;
element.height = size.height;
// We also need this call here for HiDPI support.
this._setViewSize(size);
// TODO: Test this on IE:
if (PaperScope.hasAttribute(element, 'stats')
&& typeof Stats !== 'undefined') {
@ -95,8 +95,7 @@ var View = Base.extend(Callback, /** @lends View# */{
View._views.push(this);
// Link this id to our view
View._viewsById[this._id] = this;
this._viewSize = new LinkedSize(size.width, size.height,
this, 'setViewSize');
this._viewSize = size;
this._matrix = new Matrix();
this._zoom = 1;
// Make sure the first view is focused for keyboard input straight away
@ -281,7 +280,8 @@ var View = Base.extend(Callback, /** @lends View# */{
* @bean
*/
getViewSize: function() {
return this._viewSize;
var size = this._viewSize;
return new LinkedSize(size.width, size.height, this, 'setViewSize');
},
setViewSize: function(size) {
@ -289,10 +289,8 @@ var View = Base.extend(Callback, /** @lends View# */{
var delta = size.subtract(this._viewSize);
if (delta.isZero())
return;
this._element.width = size.width;
this._element.height = size.height;
// Update _viewSize but don't notify of change.
this._viewSize.set(size.width, size.height, true);
this._viewSize.set(size.width, size.height);
this._setViewSize(size);
this._bounds = null; // Force recalculation
// Call onResize handler on any size change
this.fire('resize', {
@ -302,6 +300,15 @@ var View = Base.extend(Callback, /** @lends View# */{
this._redraw();
},
/**
* Private method, overriden in CanvasView for HiDPI support.
*/
_setViewSize: function(size) {
var element = this._element;
element.width = size.width;
element.height = size.height;
},
/**
* The bounds of the currently visible area in project coordinates.
*