mirror of
https://github.com/openseadragon/openseadragon.git
synced 2024-11-22 13:16:10 +03:00
First draft of tiled image rotation.
This commit is contained in:
parent
bbf354b6b6
commit
65b59c08d6
@ -464,7 +464,7 @@ $.Drawer.prototype = {
|
||||
},
|
||||
|
||||
// private
|
||||
drawDebugInfo: function( tile, count, i ){
|
||||
drawDebugInfo: function(tile, count, i, tiledImage) {
|
||||
if ( !this.useCanvas ) {
|
||||
return;
|
||||
}
|
||||
@ -479,6 +479,12 @@ $.Drawer.prototype = {
|
||||
if ( this.viewport.degrees !== 0 ) {
|
||||
this._offsetForRotation(this.viewport.degrees);
|
||||
}
|
||||
if (tiledImage.degrees) {
|
||||
this._offsetForRotation(
|
||||
tiledImage.degrees,
|
||||
tiledImage.viewport.pixelFromPointNoRotate(
|
||||
tiledImage.getBounds(true).getTopLeft(), true));
|
||||
}
|
||||
|
||||
context.strokeRect(
|
||||
tile.position.x * $.pixelDensityRatio,
|
||||
@ -541,6 +547,9 @@ $.Drawer.prototype = {
|
||||
if ( this.viewport.degrees !== 0 ) {
|
||||
this._restoreRotationChanges();
|
||||
}
|
||||
if (tiledImage.degrees) {
|
||||
this._restoreRotationChanges();
|
||||
}
|
||||
context.restore();
|
||||
},
|
||||
|
||||
@ -574,17 +583,19 @@ $.Drawer.prototype = {
|
||||
return new $.Point(canvas.width, canvas.height);
|
||||
},
|
||||
|
||||
// private
|
||||
_offsetForRotation: function(degrees, useSketch) {
|
||||
var cx = this.canvas.width / 2;
|
||||
var cy = this.canvas.height / 2;
|
||||
getCanvasCenter: function() {
|
||||
return new $.Point(this.canvas.width / 2, this.canvas.height / 2);
|
||||
},
|
||||
|
||||
// private
|
||||
_offsetForRotation: function(degrees, point, useSketch) {
|
||||
point = point || this.getCanvasCenter();
|
||||
var context = this._getContext(useSketch);
|
||||
context.save();
|
||||
|
||||
context.translate(cx, cy);
|
||||
context.translate(point.x, point.y);
|
||||
context.rotate(Math.PI / 180 * degrees);
|
||||
context.translate(-cx, -cy);
|
||||
context.translate(-point.x, -point.y);
|
||||
},
|
||||
|
||||
// private
|
||||
|
@ -1375,6 +1375,21 @@ function OpenSeadragon( options ){
|
||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||
},
|
||||
|
||||
/**
|
||||
* Compute the modulo of a number but makes sure to always return
|
||||
* a positive value.
|
||||
* @param {Number} number the number to computes the modulo of
|
||||
* @param {Number} modulo the modulo
|
||||
* @returns {Number} the result of the modulo of number
|
||||
*/
|
||||
positiveModulo: function(number, modulo) {
|
||||
var result = number % modulo;
|
||||
if (result < 0) {
|
||||
result += modulo;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Determines if a point is within the bounding rectangle of the given element (hit-test).
|
||||
* @function
|
||||
|
@ -190,10 +190,7 @@ $.Point.prototype = {
|
||||
var sin;
|
||||
// Avoid float computations when possible
|
||||
if (degrees % 90 === 0) {
|
||||
var d = degrees % 360;
|
||||
if (d < 0) {
|
||||
d += 360;
|
||||
}
|
||||
var d = $.positiveModulo(degrees, 360);
|
||||
switch (d) {
|
||||
case 0:
|
||||
cos = 1;
|
||||
|
@ -81,10 +81,7 @@ $.Rect = function(x, y, width, height, degrees) {
|
||||
this.degrees = typeof(degrees) === "number" ? degrees : 0;
|
||||
|
||||
// Normalizes the rectangle.
|
||||
this.degrees = this.degrees % 360;
|
||||
if (this.degrees < 0) {
|
||||
this.degrees += 360;
|
||||
}
|
||||
this.degrees = $.positiveModulo(this.degrees, 360);
|
||||
var newTopLeft, newWidth;
|
||||
if (this.degrees >= 270) {
|
||||
newTopLeft = this.getTopRight();
|
||||
@ -442,13 +439,10 @@ $.Rect.prototype = {
|
||||
* @return {OpenSeadragon.Rect}
|
||||
*/
|
||||
rotate: function(degrees, pivot) {
|
||||
degrees = degrees % 360;
|
||||
degrees = $.positiveModulo(degrees, 360);
|
||||
if (degrees === 0) {
|
||||
return this.clone();
|
||||
}
|
||||
if (degrees < 0) {
|
||||
degrees += 360;
|
||||
}
|
||||
|
||||
pivot = pivot || this.getCenter();
|
||||
var newTopLeft = this.getTopLeft().rotate(degrees, pivot);
|
||||
|
@ -159,8 +159,8 @@ $.TiledImage = function( options ) {
|
||||
crossOriginPolicy: $.DEFAULT_SETTINGS.crossOriginPolicy,
|
||||
placeholderFillStyle: $.DEFAULT_SETTINGS.placeholderFillStyle,
|
||||
opacity: $.DEFAULT_SETTINGS.opacity,
|
||||
compositeOperation: $.DEFAULT_SETTINGS.compositeOperation
|
||||
|
||||
compositeOperation: $.DEFAULT_SETTINGS.compositeOperation,
|
||||
degrees: 0
|
||||
}, options );
|
||||
|
||||
this._xSpring = new $.Spring({
|
||||
@ -274,13 +274,19 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
* @param {Boolean} [current=false] - Pass true for the current location; false for target location.
|
||||
*/
|
||||
getBounds: function(current) {
|
||||
if (current) {
|
||||
return new $.Rect( this._xSpring.current.value, this._ySpring.current.value,
|
||||
this._worldWidthCurrent, this._worldHeightCurrent );
|
||||
}
|
||||
|
||||
return new $.Rect( this._xSpring.target.value, this._ySpring.target.value,
|
||||
this._worldWidthTarget, this._worldHeightTarget );
|
||||
return current ?
|
||||
new $.Rect(
|
||||
this._xSpring.current.value,
|
||||
this._ySpring.current.value,
|
||||
this._worldWidthCurrent,
|
||||
this._worldHeightCurrent,
|
||||
this.degrees) :
|
||||
new $.Rect(
|
||||
this._xSpring.target.value,
|
||||
this._ySpring.target.value,
|
||||
this._worldWidthTarget,
|
||||
this._worldHeightTarget,
|
||||
this.degrees);
|
||||
},
|
||||
|
||||
// deprecated
|
||||
@ -304,7 +310,8 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
bounds.x + clip.x,
|
||||
bounds.y + clip.y,
|
||||
clip.width,
|
||||
clip.height);
|
||||
clip.height,
|
||||
this.degrees);
|
||||
}
|
||||
return bounds;
|
||||
},
|
||||
@ -660,6 +667,8 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
$.console.assert(!newClip || newClip instanceof $.Rect,
|
||||
"[TiledImage.setClip] newClip must be an OpenSeadragon.Rect or null");
|
||||
|
||||
//TODO: should this._raiseBoundsChange(); be called?
|
||||
|
||||
if (newClip instanceof $.Rect) {
|
||||
this._clip = newClip.clone();
|
||||
} else {
|
||||
@ -684,6 +693,23 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
this._needsDraw = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the current rotation of this tiled image in degrees.
|
||||
* @returns {Number} the current rotation of this tiled image in degrees.
|
||||
*/
|
||||
getRotation: function() {
|
||||
return this.degrees;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the current rotation of this tiled image in degrees.
|
||||
* @param {Number} the rotation in degrees.
|
||||
*/
|
||||
setRotation: function(degrees) {
|
||||
this.degrees = $.positiveModulo(degrees, 360);
|
||||
this._needsDraw = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* @returns {String} The TiledImage's current compositeOperation.
|
||||
*/
|
||||
@ -803,7 +829,8 @@ function updateViewport( tiledImage ) {
|
||||
}
|
||||
|
||||
if (!tiledImage.wrapHorizontal && !tiledImage.wrapVertical) {
|
||||
var tiledImageBounds = tiledImage.getClippedBounds(true);
|
||||
var tiledImageBounds = tiledImage.getClippedBounds(true)
|
||||
.getBoundingBox();
|
||||
var intersection = viewportBounds.intersection(tiledImageBounds);
|
||||
if (intersection === null) {
|
||||
return;
|
||||
@ -1464,10 +1491,20 @@ function drawTiles( tiledImage, lastDrawn ) {
|
||||
tiledImage._drawer._clear(true, bounds);
|
||||
}
|
||||
|
||||
// When scaling, we must rotate only when blending the sketch canvas to avoid
|
||||
// interpolation
|
||||
if (tiledImage.viewport.degrees !== 0 && !sketchScale) {
|
||||
tiledImage._drawer._offsetForRotation(tiledImage.viewport.degrees, useSketch);
|
||||
// When scaling, we must rotate only when blending the sketch canvas to
|
||||
// avoid interpolation
|
||||
if (!sketchScale) {
|
||||
if (tiledImage.viewport.degrees !== 0) {
|
||||
tiledImage._drawer._offsetForRotation(
|
||||
tiledImage.viewport.degrees, useSketch);
|
||||
}
|
||||
if (tiledImage.degrees !== 0) {
|
||||
tiledImage._drawer._offsetForRotation(
|
||||
tiledImage.degrees,
|
||||
tiledImage.viewport.pixelFromPointNoRotate(
|
||||
tiledImage.getBounds(true).getTopLeft(), true),
|
||||
useSketch);
|
||||
}
|
||||
}
|
||||
|
||||
var usedClip = false;
|
||||
@ -1535,14 +1572,28 @@ function drawTiles( tiledImage, lastDrawn ) {
|
||||
tiledImage._drawer.restoreContext( useSketch );
|
||||
}
|
||||
|
||||
if (tiledImage.viewport.degrees !== 0 && !sketchScale) {
|
||||
if (!sketchScale) {
|
||||
if (tiledImage.degrees !== 0) {
|
||||
tiledImage._drawer._restoreRotationChanges(useSketch);
|
||||
}
|
||||
if (tiledImage.viewport.degrees !== 0) {
|
||||
tiledImage._drawer._restoreRotationChanges(useSketch);
|
||||
}
|
||||
}
|
||||
|
||||
if (useSketch) {
|
||||
var offsetForRotation = tiledImage.viewport.degrees !== 0 && sketchScale;
|
||||
if (offsetForRotation) {
|
||||
tiledImage._drawer._offsetForRotation(tiledImage.viewport.degrees, false);
|
||||
if (sketchScale) {
|
||||
if (tiledImage.viewport.degrees !== 0) {
|
||||
tiledImage._drawer._offsetForRotation(
|
||||
tiledImage.viewport.degrees, false);
|
||||
}
|
||||
if (tiledImage.degrees !== 0) {
|
||||
tiledImage._drawer._offsetForRotation(
|
||||
tiledImage.degrees,
|
||||
tiledImage.viewport.pixelFromPointNoRotate(
|
||||
tiledImage.getBounds(true).getTopLeft(), true),
|
||||
useSketch);
|
||||
}
|
||||
}
|
||||
tiledImage._drawer.blendSketch({
|
||||
opacity: tiledImage.opacity,
|
||||
@ -1551,9 +1602,14 @@ function drawTiles( tiledImage, lastDrawn ) {
|
||||
compositeOperation: tiledImage.compositeOperation,
|
||||
bounds: bounds
|
||||
});
|
||||
if (offsetForRotation) {
|
||||
if (sketchScale) {
|
||||
if (tiledImage.degrees !== 0) {
|
||||
tiledImage._drawer._restoreRotationChanges(false);
|
||||
}
|
||||
if (tiledImage.viewport.degrees !== 0) {
|
||||
tiledImage._drawer._restoreRotationChanges(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
drawDebugInfo( tiledImage, lastDrawn );
|
||||
}
|
||||
@ -1563,7 +1619,8 @@ function drawDebugInfo( tiledImage, lastDrawn ) {
|
||||
for ( var i = lastDrawn.length - 1; i >= 0; i-- ) {
|
||||
var tile = lastDrawn[ i ];
|
||||
try {
|
||||
tiledImage._drawer.drawDebugInfo( tile, lastDrawn.length, i );
|
||||
tiledImage._drawer.drawDebugInfo(
|
||||
tile, lastDrawn.length, i, tiledImage);
|
||||
} catch(e) {
|
||||
$.console.error(e);
|
||||
}
|
||||
|
@ -1369,6 +1369,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
||||
clip: queueItem.options.clip,
|
||||
placeholderFillStyle: queueItem.options.placeholderFillStyle,
|
||||
opacity: queueItem.options.opacity,
|
||||
degrees: queueItem.options.degrees,
|
||||
compositeOperation: queueItem.options.compositeOperation,
|
||||
springStiffness: _this.springStiffness,
|
||||
animationTime: _this.animationTime,
|
||||
|
@ -852,11 +852,7 @@ $.Viewport.prototype = {
|
||||
return this;
|
||||
}
|
||||
|
||||
degrees = degrees % 360;
|
||||
if (degrees < 0) {
|
||||
degrees += 360;
|
||||
}
|
||||
this.degrees = degrees;
|
||||
this.degrees = $.positiveModulo(degrees, 360);
|
||||
this._setContentBounds(
|
||||
this.viewer.world.getHomeBounds(),
|
||||
this.viewer.world.getContentFactor());
|
||||
|
Loading…
Reference in New Issue
Block a user