Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Fixing "imageSmoothingEnabled" resetting to 'True' (should fix #1593) #1595

Merged
merged 4 commits into from Feb 13, 2019

Conversation

doutsh
Copy link

@doutsh doutsh commented Feb 6, 2019

As explained in #1593, the main issue is that the property imageSmoothingEnabled of a canvas is being reset to "True" each time the canvas is resized (probably by design), while we only set it once on initialization.

This revealed another issue - when window.devicePixelRatio is > 1 and not an integer (this depends on the display type and browser's zoom and not IE vs Chrome as I thought before), _calculateCanvasSize often returns non-integer values.
As canvas width/height are always integers, this if in "clear" function will be evaluated to true on some window sizes:
( this.canvas.width != viewportSize.x || this.canvas.height != viewportSize.y )
which will "resize" the canvas to its current size, and will reset imageSmoothingEnabled as explained before.

In this commit I "floored" _calculateCanvasSize return values.
Regarding the main issue, we should set imageSmoothingEnabled after every resize. I will appreciate some help figuring out the best place to call setImageSmoothingEnabled().
It should be deep enough so it will happen after every resize, but we still need access to the user-defined value.

BTW, from what I see (here for instance), BackingStorePixelRatio is deprecated and always returns 1, so maybe we can get rid of it?

(Sorry for the long msg, and I hope this pull request was done correctly, it's my first one!)

@doutsh
Copy link
Author

doutsh commented Feb 6, 2019

OK, I think I figured it out, let me know what you think!

Copy link
Member

@iangilman iangilman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good! Thank you for tracking this down and fixing it!

src/drawer.js Outdated Show resolved Hide resolved
src/drawer.js Outdated
@@ -247,13 +247,15 @@ $.Drawer.prototype = {
var viewportSize = this._calculateCanvasSize();
if( this.canvas.width != viewportSize.x ||
this.canvas.height != viewportSize.y ) {
var imageSmoothingEnabled = this.canvas.getContext('2d').imageSmoothingEnabled;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think what I would do would be to keep our own _imageSmoothingEnabled property that gets set in setImageSmoothingEnabled and then used here. That way you are relying on an explicit variable and not something in the Canvas that might get changed out of our control.

src/drawer.js Outdated
this.canvas.width = viewportSize.x;
this.canvas.height = viewportSize.y;
if ( this.sketchCanvas !== null ) {
var sketchCanvasSize = this._calculateSketchCanvasSize();
this.sketchCanvas.width = sketchCanvasSize.x;
this.sketchCanvas.height = sketchCanvasSize.y;
}
this.setImageSmoothingEnabled(imageSmoothingEnabled);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be overkill, but I think I might actually split setImageSmoothingEnabled into two functions; a "private" one that just sets the various Canvas flags for different browsers, and the "public" one that sets _imageSmoothingEnabled, calls the "private" one, and tells the viewer to redraw. That way you can just call the "private" one from here, since you don't need the other stuff in this case. It could be called _setImageSmoothingEnabled or something.

@iangilman
Copy link
Member

iangilman commented Feb 6, 2019

We're pretty conservative about keeping around old code here in OSD... I think we still be mostly IE8 compatible... for that reason I'm in favor of leaving BackingStorePixelRatio around even if it's no longer a thing. Thanks for mentioning it though!

@doutsh
Copy link
Author

doutsh commented Feb 7, 2019

Something like this?

Copy link
Member

@iangilman iangilman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, just like that!

Just a couple more comments; one functional and the other stylistic.

src/drawer.js Outdated
@@ -609,6 +610,9 @@ $.Drawer.prototype = {
},


// private
_imageSmoothingEnabled: true,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's a subtle JavaScript gotcha: by putting this property directly on the prototype like this, it means if any instance changes it, it gets changed for all instances. The fix is to make it part of the object directly by doing this._imageSmoothingEnabled = true in the constructor instead of having it here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I'm realizing this gotcha doesn't apply to simple variables like booleans (it only applies to things like objects and arrays). That said, it would still be good to do the other way to keep everything together.

src/drawer.js Outdated
this.viewer.forceRedraw();
}
},

// private
_setImageSmoothingEnabled: function(){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking _updateImageSmoothingEnabled might be a better name for this, since it's just updating the canvas to match the value that's already been set elsewhere. That'll help with any confusion between this function and setImageSmoothingEnabled as well. I hope you don't mind the new suggestion (I realize the other name was my suggestion as well).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not at all, I agree and I'm happy to learn...

@iangilman
Copy link
Member

Beautiful! Thank you for finding and fixing this!

@iangilman iangilman merged commit d003aab into openseadragon:master Feb 13, 2019
iangilman added a commit that referenced this pull request Feb 13, 2019
iangilman added a commit that referenced this pull request Feb 13, 2019
@doutsh doutsh deleted the pr/imagesmoothing branch February 14, 2019 08:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants