mirror of
https://github.com/openseadragon/openseadragon.git
synced 2024-11-22 05:06:09 +03:00
commit
eb8b9ccd50
@ -328,8 +328,7 @@ $.Drawer.prototype = {
|
||||
// the viewport get rotated later on, we will need to resize it.
|
||||
if (this.viewport.getRotation() === 0) {
|
||||
var self = this;
|
||||
this.viewer.addHandler('rotate', function resizeSketchCanvas() {
|
||||
self.viewer.removeHandler('rotate', resizeSketchCanvas);
|
||||
this.viewer.addOnceHandler('rotate', function resizeSketchCanvas() {
|
||||
var sketchCanvasSize = self._calculateSketchCanvasSize();
|
||||
self.sketchCanvas.width = sketchCanvasSize.x;
|
||||
self.sketchCanvas.height = sketchCanvasSize.y;
|
||||
@ -482,7 +481,7 @@ $.Drawer.prototype = {
|
||||
},
|
||||
|
||||
// private
|
||||
drawDebugInfo: function( tile, count, i ){
|
||||
drawDebugInfo: function(tile, count, i, tiledImage) {
|
||||
if ( !this.useCanvas ) {
|
||||
return;
|
||||
}
|
||||
@ -495,7 +494,14 @@ $.Drawer.prototype = {
|
||||
context.fillStyle = this.debugGridColor;
|
||||
|
||||
if ( this.viewport.degrees !== 0 ) {
|
||||
this._offsetForRotation(this.viewport.degrees);
|
||||
this._offsetForRotation({degrees: this.viewport.degrees});
|
||||
}
|
||||
if (tiledImage.getRotation() !== 0) {
|
||||
this._offsetForRotation({
|
||||
degrees: tiledImage.getRotation(),
|
||||
point: tiledImage.viewport.pixelFromPointNoRotate(
|
||||
tiledImage._getRotationPoint(true), true)
|
||||
});
|
||||
}
|
||||
|
||||
context.strokeRect(
|
||||
@ -559,6 +565,9 @@ $.Drawer.prototype = {
|
||||
if ( this.viewport.degrees !== 0 ) {
|
||||
this._restoreRotationChanges();
|
||||
}
|
||||
if (tiledImage.getRotation() !== 0) {
|
||||
this._restoreRotationChanges();
|
||||
}
|
||||
context.restore();
|
||||
},
|
||||
|
||||
@ -592,17 +601,22 @@ $.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);
|
||||
},
|
||||
|
||||
var context = this._getContext(useSketch);
|
||||
// private
|
||||
_offsetForRotation: function(options) {
|
||||
var point = options.point ?
|
||||
options.point.times($.pixelDensityRatio) :
|
||||
this.getCanvasCenter();
|
||||
|
||||
var context = this._getContext(options.useSketch);
|
||||
context.save();
|
||||
|
||||
context.translate(cx, cy);
|
||||
context.rotate(Math.PI / 180 * degrees);
|
||||
context.translate(-cx, -cy);
|
||||
context.translate(point.x, point.y);
|
||||
context.rotate(Math.PI / 180 * options.degrees);
|
||||
context.translate(-point.x, -point.y);
|
||||
},
|
||||
|
||||
// private
|
||||
|
@ -341,9 +341,12 @@ $.extend( $.Navigator.prototype, $.EventSource.prototype, $.Viewer.prototype, /*
|
||||
myItem._originalForNavigator = original;
|
||||
_this._matchBounds(myItem, original, true);
|
||||
|
||||
original.addHandler('bounds-change', function() {
|
||||
function matchBounds() {
|
||||
_this._matchBounds(myItem, original);
|
||||
});
|
||||
}
|
||||
|
||||
original.addHandler('bounds-change', matchBounds);
|
||||
original.addHandler('clip-change', matchBounds);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -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
|
||||
|
@ -202,10 +202,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,19 +439,21 @@ $.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);
|
||||
var newTopRight = this.getTopRight().rotate(degrees, pivot);
|
||||
|
||||
var diff = newTopRight.minus(newTopLeft);
|
||||
// Handle floating point error
|
||||
diff = diff.apply(function(x) {
|
||||
var EPSILON = 1e-15;
|
||||
return Math.abs(x) < EPSILON ? 0 : x;
|
||||
});
|
||||
var radians = Math.atan(diff.y / diff.x);
|
||||
if (diff.x < 0) {
|
||||
radians += Math.PI;
|
||||
|
@ -132,6 +132,9 @@ $.TiledImage = function( options ) {
|
||||
var fitBoundsPlacement = options.fitBoundsPlacement || OpenSeadragon.Placement.CENTER;
|
||||
delete options.fitBoundsPlacement;
|
||||
|
||||
this._degrees = $.positiveModulo(options.degrees || 0, 360);
|
||||
delete options.degrees;
|
||||
|
||||
$.extend( true, this, {
|
||||
|
||||
//internal state properties
|
||||
@ -160,7 +163,6 @@ $.TiledImage = function( options ) {
|
||||
placeholderFillStyle: $.DEFAULT_SETTINGS.placeholderFillStyle,
|
||||
opacity: $.DEFAULT_SETTINGS.opacity,
|
||||
compositeOperation: $.DEFAULT_SETTINGS.compositeOperation
|
||||
|
||||
}, options );
|
||||
|
||||
this._fullyLoaded = false;
|
||||
@ -290,7 +292,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
draw: function() {
|
||||
if (this.opacity !== 0) {
|
||||
this._midDraw = true;
|
||||
updateViewport(this);
|
||||
this._updateViewport();
|
||||
this._midDraw = false;
|
||||
}
|
||||
},
|
||||
@ -303,17 +305,35 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
},
|
||||
|
||||
/**
|
||||
* Get this TiledImage's bounds in viewport coordinates.
|
||||
* @param {Boolean} [current=false] - Pass true for the current location;
|
||||
* false for target location.
|
||||
* @returns {OpenSeadragon.Rect} This TiledImage's bounds in viewport coordinates.
|
||||
* @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 this.getBoundsNoRotate(current)
|
||||
.rotate(this._degrees, this._getRotationPoint(current));
|
||||
},
|
||||
|
||||
return new $.Rect( this._xSpring.target.value, this._ySpring.target.value,
|
||||
this._worldWidthTarget, this._worldHeightTarget );
|
||||
/**
|
||||
* Get this TiledImage's bounds in viewport coordinates without taking
|
||||
* rotation into account.
|
||||
* @param {Boolean} [current=false] - Pass true for the current location;
|
||||
* false for target location.
|
||||
* @returns {OpenSeadragon.Rect} This TiledImage's bounds in viewport coordinates.
|
||||
*/
|
||||
getBoundsNoRotate: function(current) {
|
||||
return current ?
|
||||
new $.Rect(
|
||||
this._xSpring.current.value,
|
||||
this._ySpring.current.value,
|
||||
this._worldWidthCurrent,
|
||||
this._worldHeightCurrent) :
|
||||
new $.Rect(
|
||||
this._xSpring.target.value,
|
||||
this._ySpring.target.value,
|
||||
this._worldWidthTarget,
|
||||
this._worldHeightTarget);
|
||||
},
|
||||
|
||||
// deprecated
|
||||
@ -329,9 +349,11 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
* @returns {$.Rect} The clipped bounds in viewport coordinates.
|
||||
*/
|
||||
getClippedBounds: function(current) {
|
||||
var bounds = this.getBounds(current);
|
||||
var bounds = this.getBoundsNoRotate(current);
|
||||
if (this._clip) {
|
||||
var ratio = this._worldWidthCurrent / this.source.dimensions.x;
|
||||
var worldWidth = current ?
|
||||
this._worldWidthCurrent : this._worldWidthTarget;
|
||||
var ratio = worldWidth / this.source.dimensions.x;
|
||||
var clip = this._clip.times(ratio);
|
||||
bounds = new $.Rect(
|
||||
bounds.x + clip.x,
|
||||
@ -339,7 +361,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
clip.width,
|
||||
clip.height);
|
||||
}
|
||||
return bounds;
|
||||
return bounds.rotate(this._degrees, this._getRotationPoint(current));
|
||||
},
|
||||
|
||||
/**
|
||||
@ -364,21 +386,24 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
* @param {Boolean} [current=false] - Pass true to use the current location; false for target location.
|
||||
* @return {OpenSeadragon.Point} A point representing the coordinates in the image.
|
||||
*/
|
||||
viewportToImageCoordinates: function( viewerX, viewerY, current ) {
|
||||
viewportToImageCoordinates: function(viewerX, viewerY, current) {
|
||||
var point;
|
||||
if (viewerX instanceof $.Point) {
|
||||
//they passed a point instead of individual components
|
||||
current = viewerY;
|
||||
viewerY = viewerX.y;
|
||||
viewerX = viewerX.x;
|
||||
point = viewerX;
|
||||
} else {
|
||||
point = new $.Point(viewerX, viewerY);
|
||||
}
|
||||
|
||||
if (current) {
|
||||
return this._viewportToImageDelta(viewerX - this._xSpring.current.value,
|
||||
viewerY - this._ySpring.current.value);
|
||||
}
|
||||
|
||||
return this._viewportToImageDelta(viewerX - this._xSpring.target.value,
|
||||
viewerY - this._ySpring.target.value);
|
||||
point = point.rotate(-this._degrees, this._getRotationPoint(current));
|
||||
return current ?
|
||||
this._viewportToImageDelta(
|
||||
point.x - this._xSpring.current.value,
|
||||
point.y - this._ySpring.current.value) :
|
||||
this._viewportToImageDelta(
|
||||
point.x - this._xSpring.target.value,
|
||||
point.y - this._ySpring.target.value);
|
||||
},
|
||||
|
||||
// private
|
||||
@ -396,7 +421,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
* @param {Boolean} [current=false] - Pass true to use the current location; false for target location.
|
||||
* @return {OpenSeadragon.Point} A point representing the coordinates in the viewport.
|
||||
*/
|
||||
imageToViewportCoordinates: function( imageX, imageY, current ) {
|
||||
imageToViewportCoordinates: function(imageX, imageY, current) {
|
||||
if (imageX instanceof $.Point) {
|
||||
//they passed a point instead of individual components
|
||||
current = imageY;
|
||||
@ -413,7 +438,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
point.y += this._ySpring.target.value;
|
||||
}
|
||||
|
||||
return point;
|
||||
return point.rotate(this._degrees, this._getRotationPoint(current));
|
||||
},
|
||||
|
||||
/**
|
||||
@ -444,7 +469,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
coordA.y,
|
||||
coordB.x,
|
||||
coordB.y,
|
||||
rect.degrees
|
||||
rect.degrees + this._degrees
|
||||
);
|
||||
},
|
||||
|
||||
@ -476,7 +501,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
coordA.y,
|
||||
coordB.x,
|
||||
coordB.y,
|
||||
rect.degrees
|
||||
rect.degrees - this._degrees
|
||||
);
|
||||
},
|
||||
|
||||
@ -524,6 +549,20 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
OpenSeadragon.getElementPosition( this.viewer.element ));
|
||||
},
|
||||
|
||||
// private
|
||||
// Convert rectangle in viewport coordinates to this tiled image point
|
||||
// coordinates (x in [0, 1] and y in [0, aspectRatio])
|
||||
_viewportToTiledImageRectangle: function(rect) {
|
||||
var scale = this._scaleSpring.current.value;
|
||||
rect = rect.rotate(-this.getRotation(), this._getRotationPoint(true));
|
||||
return new $.Rect(
|
||||
(rect.x - this._xSpring.current.value) / scale,
|
||||
(rect.y - this._ySpring.current.value) / scale,
|
||||
rect.width / scale,
|
||||
rect.height / scale,
|
||||
rect.degrees);
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert a viewport zoom to an image zoom.
|
||||
* Image zoom: ratio of the original image size to displayed image size.
|
||||
@ -688,6 +727,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
* @param {OpenSeadragon.Rect|null} newClip - An area, in image pixels, to clip to
|
||||
* (portions of the image outside of this area will not be visible). Only works on
|
||||
* browsers that support the HTML5 canvas.
|
||||
* @fires OpenSeadragon.TiledImage.event:clip-change
|
||||
*/
|
||||
setClip: function(newClip) {
|
||||
$.console.assert(!newClip || newClip instanceof $.Rect,
|
||||
@ -700,6 +740,16 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
}
|
||||
|
||||
this._needsDraw = true;
|
||||
/**
|
||||
* Raised when the TiledImage's clip is changed.
|
||||
* @event clip-change
|
||||
* @memberOf OpenSeadragon.TiledImage
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.TiledImage} eventSource - A reference to the
|
||||
* TiledImage which raised the event.
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
this.raiseEvent('clip-change');
|
||||
},
|
||||
|
||||
/**
|
||||
@ -717,6 +767,39 @@ $.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} degrees the rotation in degrees.
|
||||
* @fires OpenSeadragon.TiledImage.event:bounds-change
|
||||
*/
|
||||
setRotation: function(degrees) {
|
||||
degrees = $.positiveModulo(degrees, 360);
|
||||
if (this._degrees === degrees) {
|
||||
return;
|
||||
}
|
||||
this._degrees = degrees;
|
||||
this._needsDraw = true;
|
||||
this._raiseBoundsChange();
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Get the point around which this tiled image is rotated
|
||||
* @param {Boolean} current True for current rotation point, false for target.
|
||||
* @returns {OpenSeadragon.Point}
|
||||
*/
|
||||
_getRotationPoint: function(current) {
|
||||
return this.getBoundsNoRotate(current).getCenter();
|
||||
},
|
||||
|
||||
/**
|
||||
* @returns {String} The TiledImage's current compositeOperation.
|
||||
*/
|
||||
@ -775,7 +858,8 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
* @event bounds-change
|
||||
* @memberOf OpenSeadragon.TiledImage
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.World} eventSource - A reference to the TiledImage which raised the event.
|
||||
* @property {OpenSeadragon.TiledImage} eventSource - A reference to the
|
||||
* TiledImage which raised the event.
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
this.raiseEvent('bounds-change');
|
||||
@ -784,187 +868,144 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
// private
|
||||
_isBottomItem: function() {
|
||||
return this.viewer.world.getItemAt(0) === this;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @inner
|
||||
* Pretty much every other line in this needs to be documented so it's clear
|
||||
* how each piece of this routine contributes to the drawing process. That's
|
||||
* why there are so many TODO's inside this function.
|
||||
*/
|
||||
function updateViewport( tiledImage ) {
|
||||
|
||||
tiledImage._needsDraw = false;
|
||||
|
||||
var tile,
|
||||
level,
|
||||
best = null,
|
||||
haveDrawn = false,
|
||||
currentTime = $.now(),
|
||||
viewportBounds = tiledImage.viewport.getBoundsWithMargins( true ),
|
||||
zeroRatioC = tiledImage.viewport.deltaPixelsFromPointsNoRotate(
|
||||
tiledImage.source.getPixelRatio( 0 ),
|
||||
true
|
||||
).x * tiledImage._scaleSpring.current.value,
|
||||
lowestLevel = Math.max(
|
||||
tiledImage.source.minLevel,
|
||||
Math.floor(
|
||||
Math.log( tiledImage.minZoomImageRatio ) /
|
||||
Math.log( 2 )
|
||||
)
|
||||
),
|
||||
highestLevel = Math.min(
|
||||
Math.abs(tiledImage.source.maxLevel),
|
||||
// private
|
||||
_getLevelsInterval: function() {
|
||||
var lowestLevel = Math.max(
|
||||
this.source.minLevel,
|
||||
Math.floor(Math.log(this.minZoomImageRatio) / Math.log(2))
|
||||
);
|
||||
var currentZeroRatio = this.viewport.deltaPixelsFromPointsNoRotate(
|
||||
this.source.getPixelRatio(0), true).x *
|
||||
this._scaleSpring.current.value;
|
||||
var highestLevel = Math.min(
|
||||
Math.abs(this.source.maxLevel),
|
||||
Math.abs(Math.floor(
|
||||
Math.log( zeroRatioC / tiledImage.minPixelRatio ) /
|
||||
Math.log( 2 )
|
||||
Math.log(currentZeroRatio / this.minPixelRatio) / Math.log(2)
|
||||
))
|
||||
),
|
||||
renderPixelRatioC,
|
||||
renderPixelRatioT,
|
||||
zeroRatioT,
|
||||
optimalRatio,
|
||||
levelOpacity,
|
||||
levelVisibility;
|
||||
);
|
||||
|
||||
// Calculations for the interval of levels to draw
|
||||
// can return invalid intervals; fix that here if necessary
|
||||
lowestLevel = Math.min(lowestLevel, highestLevel);
|
||||
return {
|
||||
lowestLevel: lowestLevel,
|
||||
highestLevel: highestLevel
|
||||
};
|
||||
},
|
||||
|
||||
// private
|
||||
_updateViewport: function() {
|
||||
this._needsDraw = false;
|
||||
|
||||
// Reset tile's internal drawn state
|
||||
while (tiledImage.lastDrawn.length > 0) {
|
||||
tile = tiledImage.lastDrawn.pop();
|
||||
while (this.lastDrawn.length > 0) {
|
||||
var tile = this.lastDrawn.pop();
|
||||
tile.beingDrawn = false;
|
||||
}
|
||||
|
||||
if (!tiledImage.wrapHorizontal && !tiledImage.wrapVertical) {
|
||||
var tiledImageBounds = tiledImage.getClippedBounds(true);
|
||||
var intersection = viewportBounds.intersection(tiledImageBounds);
|
||||
if (intersection === null) {
|
||||
var viewport = this.viewport;
|
||||
var drawArea = this._viewportToTiledImageRectangle(
|
||||
viewport.getBoundsWithMargins(true));
|
||||
|
||||
if (!this.wrapHorizontal && !this.wrapVertical) {
|
||||
var tiledImageBounds = this._viewportToTiledImageRectangle(
|
||||
this.getClippedBounds(true));
|
||||
drawArea = drawArea.intersection(tiledImageBounds);
|
||||
if (drawArea === null) {
|
||||
return;
|
||||
}
|
||||
viewportBounds = intersection;
|
||||
}
|
||||
viewportBounds = viewportBounds.getBoundingBox();
|
||||
viewportBounds.x -= tiledImage._xSpring.current.value;
|
||||
viewportBounds.y -= tiledImage._ySpring.current.value;
|
||||
|
||||
var viewportTL = viewportBounds.getTopLeft();
|
||||
var viewportBR = viewportBounds.getBottomRight();
|
||||
|
||||
//Don't draw if completely outside of the viewport
|
||||
if ( !tiledImage.wrapHorizontal && (viewportBR.x < 0 || viewportTL.x > tiledImage._worldWidthCurrent ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !tiledImage.wrapVertical && ( viewportBR.y < 0 || viewportTL.y > tiledImage._worldHeightCurrent ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate viewport rect / bounds
|
||||
if ( !tiledImage.wrapHorizontal ) {
|
||||
viewportTL.x = Math.max( viewportTL.x, 0 );
|
||||
viewportBR.x = Math.min( viewportBR.x, tiledImage._worldWidthCurrent );
|
||||
}
|
||||
|
||||
if ( !tiledImage.wrapVertical ) {
|
||||
viewportTL.y = Math.max( viewportTL.y, 0 );
|
||||
viewportBR.y = Math.min( viewportBR.y, tiledImage._worldHeightCurrent );
|
||||
}
|
||||
|
||||
// Calculations for the interval of levels to draw
|
||||
// (above in initial var statement)
|
||||
// can return invalid intervals; fix that here if necessary
|
||||
lowestLevel = Math.min( lowestLevel, highestLevel );
|
||||
var levelsInterval = this._getLevelsInterval();
|
||||
var lowestLevel = levelsInterval.lowestLevel;
|
||||
var highestLevel = levelsInterval.highestLevel;
|
||||
var bestTile = null;
|
||||
var haveDrawn = false;
|
||||
var currentTime = $.now();
|
||||
|
||||
// Update any level that will be drawn
|
||||
var drawLevel; // FIXME: drawLevel should have a more explanatory name
|
||||
for ( level = highestLevel; level >= lowestLevel; level-- ) {
|
||||
drawLevel = false;
|
||||
for (var level = highestLevel; level >= lowestLevel; level--) {
|
||||
var drawLevel = false;
|
||||
|
||||
//Avoid calculations for draw if we have already drawn this
|
||||
renderPixelRatioC = tiledImage.viewport.deltaPixelsFromPointsNoRotate(
|
||||
tiledImage.source.getPixelRatio( level ),
|
||||
var currentRenderPixelRatio = viewport.deltaPixelsFromPointsNoRotate(
|
||||
this.source.getPixelRatio(level),
|
||||
true
|
||||
).x * tiledImage._scaleSpring.current.value;
|
||||
).x * this._scaleSpring.current.value;
|
||||
|
||||
if ( ( !haveDrawn && renderPixelRatioC >= tiledImage.minPixelRatio ) ||
|
||||
( level == lowestLevel ) ) {
|
||||
if (level === lowestLevel ||
|
||||
(!haveDrawn && currentRenderPixelRatio >= this.minPixelRatio)) {
|
||||
drawLevel = true;
|
||||
haveDrawn = true;
|
||||
} else if ( !haveDrawn ) {
|
||||
} else if (!haveDrawn) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//Perform calculations for draw if we haven't drawn this
|
||||
renderPixelRatioT = tiledImage.viewport.deltaPixelsFromPointsNoRotate(
|
||||
tiledImage.source.getPixelRatio( level ),
|
||||
var targetRenderPixelRatio = viewport.deltaPixelsFromPointsNoRotate(
|
||||
this.source.getPixelRatio(level),
|
||||
false
|
||||
).x * tiledImage._scaleSpring.current.value;
|
||||
).x * this._scaleSpring.current.value;
|
||||
|
||||
zeroRatioT = tiledImage.viewport.deltaPixelsFromPointsNoRotate(
|
||||
tiledImage.source.getPixelRatio(
|
||||
var targetZeroRatio = viewport.deltaPixelsFromPointsNoRotate(
|
||||
this.source.getPixelRatio(
|
||||
Math.max(
|
||||
tiledImage.source.getClosestLevel( tiledImage.viewport.containerSize ) - 1,
|
||||
this.source.getClosestLevel(viewport.containerSize) - 1,
|
||||
0
|
||||
)
|
||||
),
|
||||
false
|
||||
).x * tiledImage._scaleSpring.current.value;
|
||||
).x * this._scaleSpring.current.value;
|
||||
|
||||
optimalRatio = tiledImage.immediateRender ?
|
||||
1 :
|
||||
zeroRatioT;
|
||||
|
||||
levelOpacity = Math.min( 1, ( renderPixelRatioC - 0.5 ) / 0.5 );
|
||||
|
||||
levelVisibility = optimalRatio / Math.abs(
|
||||
optimalRatio - renderPixelRatioT
|
||||
var optimalRatio = this.immediateRender ? 1 : targetZeroRatio;
|
||||
var levelOpacity = Math.min(1, (currentRenderPixelRatio - 0.5) / 0.5);
|
||||
var levelVisibility = optimalRatio / Math.abs(
|
||||
optimalRatio - targetRenderPixelRatio
|
||||
);
|
||||
|
||||
// Update the level and keep track of 'best' tile to load
|
||||
best = updateLevel(
|
||||
tiledImage,
|
||||
bestTile = updateLevel(
|
||||
this,
|
||||
haveDrawn,
|
||||
drawLevel,
|
||||
level,
|
||||
levelOpacity,
|
||||
levelVisibility,
|
||||
viewportTL,
|
||||
viewportBR,
|
||||
drawArea,
|
||||
currentTime,
|
||||
best
|
||||
bestTile
|
||||
);
|
||||
|
||||
// Stop the loop if lower-res tiles would all be covered by
|
||||
// already drawn tiles
|
||||
if ( providesCoverage( tiledImage.coverage, level ) ) {
|
||||
if (providesCoverage(this.coverage, level)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Perform the actual drawing
|
||||
drawTiles( tiledImage, tiledImage.lastDrawn );
|
||||
drawTiles(this, this.lastDrawn);
|
||||
|
||||
// Load the new 'best' tile
|
||||
if (best && !best.context2D) {
|
||||
loadTile( tiledImage, best, currentTime );
|
||||
tiledImage._needsDraw = true;
|
||||
tiledImage._setFullyLoaded(false);
|
||||
if (bestTile && !bestTile.context2D) {
|
||||
loadTile(this, bestTile, currentTime);
|
||||
this._needsDraw = true;
|
||||
this._setFullyLoaded(false);
|
||||
} else {
|
||||
tiledImage._setFullyLoaded(true);
|
||||
this._setFullyLoaded(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function updateLevel(tiledImage, haveDrawn, drawLevel, level, levelOpacity,
|
||||
levelVisibility, drawArea, currentTime, best) {
|
||||
|
||||
function updateLevel( tiledImage, haveDrawn, drawLevel, level, levelOpacity, levelVisibility, viewportTL, viewportBR, currentTime, best ){
|
||||
var topLeftBound = drawArea.getBoundingBox().getTopLeft();
|
||||
var bottomRightBound = drawArea.getBoundingBox().getBottomRight();
|
||||
|
||||
var x, y,
|
||||
tileTL,
|
||||
tileBR,
|
||||
numberOfTiles,
|
||||
viewportCenter = tiledImage.viewport.pixelFromPoint( tiledImage.viewport.getCenter() );
|
||||
|
||||
|
||||
if( tiledImage.viewer ){
|
||||
if (tiledImage.viewer) {
|
||||
/**
|
||||
* <em>- Needs documentation -</em>
|
||||
*
|
||||
@ -977,45 +1018,59 @@ function updateLevel( tiledImage, haveDrawn, drawLevel, level, levelOpacity, lev
|
||||
* @property {Object} level
|
||||
* @property {Object} opacity
|
||||
* @property {Object} visibility
|
||||
* @property {Object} topleft
|
||||
* @property {Object} bottomright
|
||||
* @property {OpenSeadragon.Rect} drawArea
|
||||
* @property {Object} topleft deprecated, use drawArea instead
|
||||
* @property {Object} bottomright deprecated, use drawArea instead
|
||||
* @property {Object} currenttime
|
||||
* @property {Object} best
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
tiledImage.viewer.raiseEvent( 'update-level', {
|
||||
tiledImage.viewer.raiseEvent('update-level', {
|
||||
tiledImage: tiledImage,
|
||||
havedrawn: haveDrawn,
|
||||
level: level,
|
||||
opacity: levelOpacity,
|
||||
visibility: levelVisibility,
|
||||
topleft: viewportTL,
|
||||
bottomright: viewportBR,
|
||||
drawArea: drawArea,
|
||||
topleft: topLeftBound,
|
||||
bottomright: bottomRightBound,
|
||||
currenttime: currentTime,
|
||||
best: best
|
||||
});
|
||||
}
|
||||
|
||||
//OK, a new drawing so do your calculations
|
||||
tileTL = tiledImage.source.getTileAtPoint( level, viewportTL.divide( tiledImage._scaleSpring.current.value ));
|
||||
tileBR = tiledImage.source.getTileAtPoint( level, viewportBR.divide( tiledImage._scaleSpring.current.value ));
|
||||
numberOfTiles = tiledImage.source.getNumTiles( level );
|
||||
var topLeftTile = tiledImage.source.getTileAtPoint(level, topLeftBound);
|
||||
var bottomRightTile = tiledImage.source.getTileAtPoint(level, bottomRightBound);
|
||||
var numberOfTiles = tiledImage.source.getNumTiles(level);
|
||||
|
||||
resetCoverage( tiledImage.coverage, level );
|
||||
resetCoverage(tiledImage.coverage, level);
|
||||
|
||||
if ( tiledImage.wrapHorizontal ) {
|
||||
tileTL.x -= 1; // left invisible column (othervise we will have empty space after scroll at left)
|
||||
} else {
|
||||
tileBR.x = Math.min( tileBR.x, numberOfTiles.x - 1 );
|
||||
if (!tiledImage.wrapHorizontal) {
|
||||
// Adjust for floating point error
|
||||
topLeftTile.x = Math.max(topLeftTile.x, 0);
|
||||
bottomRightTile.x = Math.min(bottomRightTile.x, numberOfTiles.x - 1);
|
||||
}
|
||||
if ( tiledImage.wrapVertical ) {
|
||||
tileTL.y -= 1; // top invisible row (othervise we will have empty space after scroll at top)
|
||||
} else {
|
||||
tileBR.y = Math.min( tileBR.y, numberOfTiles.y - 1 );
|
||||
if (!tiledImage.wrapVertical) {
|
||||
// Adjust for floating point error
|
||||
topLeftTile.y = Math.max(topLeftTile.y, 0);
|
||||
bottomRightTile.y = Math.min(bottomRightTile.y, numberOfTiles.y - 1);
|
||||
}
|
||||
|
||||
for ( x = tileTL.x; x <= tileBR.x; x++ ) {
|
||||
for ( y = tileTL.y; y <= tileBR.y; y++ ) {
|
||||
var viewportCenter = tiledImage.viewport.pixelFromPoint(
|
||||
tiledImage.viewport.getCenter());
|
||||
for (var x = topLeftTile.x; x <= bottomRightTile.x; x++) {
|
||||
for (var y = topLeftTile.y; y <= bottomRightTile.y; y++) {
|
||||
|
||||
// Optimisation disabled with wrapping because getTileBounds does not
|
||||
// work correctly with x and y outside of the number of tiles
|
||||
if (!tiledImage.wrapHorizontal && !tiledImage.wrapVertical) {
|
||||
var tileBounds = tiledImage.source.getTileBounds(level, x, y);
|
||||
if (drawArea.intersection(tileBounds) === null) {
|
||||
// This tile is outside of the viewport, no need to draw it
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
best = updateTile(
|
||||
tiledImage,
|
||||
@ -1476,7 +1531,9 @@ function drawTiles( tiledImage, lastDrawn ) {
|
||||
|
||||
var zoom = tiledImage.viewport.getZoom(true);
|
||||
var imageZoom = tiledImage.viewportToImageZoom(zoom);
|
||||
if (imageZoom > tiledImage.smoothTileEdgesMinZoom && !tiledImage.iOSDevice) {
|
||||
// TODO: support tile edge smoothing with tiled image rotation.
|
||||
if (imageZoom > tiledImage.smoothTileEdgesMinZoom && !tiledImage.iOSDevice &&
|
||||
tiledImage.getRotation() === 0) {
|
||||
// When zoomed in a lot (>100%) the tile edges are visible.
|
||||
// So we have to composite them at ~100% and scale them up together.
|
||||
// Note: Disabled on iOS devices per default as it causes a native crash
|
||||
@ -1500,10 +1557,23 @@ 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({
|
||||
degrees: tiledImage.viewport.degrees,
|
||||
useSketch: useSketch
|
||||
});
|
||||
}
|
||||
if (tiledImage._degrees !== 0) {
|
||||
tiledImage._drawer._offsetForRotation({
|
||||
degrees: tiledImage._degrees,
|
||||
point: tiledImage.viewport.pixelFromPointNoRotate(
|
||||
tiledImage._getRotationPoint(true), true),
|
||||
useSketch: useSketch
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var usedClip = false;
|
||||
@ -1511,6 +1581,7 @@ function drawTiles( tiledImage, lastDrawn ) {
|
||||
tiledImage._drawer.saveContext(useSketch);
|
||||
|
||||
var box = tiledImage.imageToViewportRectangle(tiledImage._clip, true);
|
||||
box = box.rotate(-tiledImage._degrees, tiledImage._getRotationPoint());
|
||||
var clipRect = tiledImage._drawer.viewportToDrawerRectangle(box);
|
||||
if (sketchScale) {
|
||||
clipRect = clipRect.times(sketchScale);
|
||||
@ -1571,14 +1642,31 @@ 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({
|
||||
degrees: tiledImage.viewport.degrees,
|
||||
useSketch: false
|
||||
});
|
||||
}
|
||||
if (tiledImage._degrees !== 0) {
|
||||
tiledImage._drawer._offsetForRotation({
|
||||
degrees: tiledImage._degrees,
|
||||
point: tiledImage.viewport.pixelFromPointNoRotate(
|
||||
tiledImage._getRotationPoint(true), true),
|
||||
useSketch: false
|
||||
});
|
||||
}
|
||||
}
|
||||
tiledImage._drawer.blendSketch({
|
||||
opacity: tiledImage.opacity,
|
||||
@ -1587,9 +1675,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 );
|
||||
}
|
||||
@ -1599,7 +1692,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);
|
||||
}
|
||||
|
@ -344,12 +344,20 @@ $.TileSource.prototype = {
|
||||
* @param {Number} level
|
||||
* @param {OpenSeadragon.Point} point
|
||||
*/
|
||||
getTileAtPoint: function( level, point ) {
|
||||
var numTiles = this.getNumTiles( level );
|
||||
return new $.Point(
|
||||
Math.floor( (point.x * numTiles.x) / 1 ),
|
||||
Math.floor( (point.y * numTiles.y * this.dimensions.x) / this.dimensions.y )
|
||||
);
|
||||
getTileAtPoint: function(level, point) {
|
||||
var widthScaled = this.dimensions.x * this.getLevelScale(level);
|
||||
var pixelX = $.positiveModulo(point.x, 1) * widthScaled;
|
||||
var pixelY = $.positiveModulo(point.y, 1 / this.aspectRatio) * widthScaled;
|
||||
|
||||
var x = Math.floor(pixelX / this.getTileWidth());
|
||||
var y = Math.floor(pixelY / this.getTileHeight());
|
||||
|
||||
// Fix for wrapping
|
||||
var numTiles = this.getNumTiles(level);
|
||||
x += numTiles.x * Math.floor(point.x);
|
||||
y += numTiles.y * Math.floor(point.y * this.aspectRatio);
|
||||
|
||||
return new $.Point(x, y);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1228,6 +1228,8 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
||||
* (portions of the image outside of this area will not be visible). Only works on
|
||||
* browsers that support the HTML5 canvas.
|
||||
* @param {Number} [options.opacity] Opacity the tiled image should be drawn at by default.
|
||||
* @param {Number} [options.degrees=0] Initial rotation of the tiled image around
|
||||
* its top left corner in degrees.
|
||||
* @param {String} [options.compositeOperation] How the image is composited onto other images.
|
||||
* @param {String} [options.crossOriginPolicy] The crossOriginPolicy for this specific image,
|
||||
* overriding viewer.crossOriginPolicy.
|
||||
@ -1369,6 +1371,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());
|
||||
|
@ -94,6 +94,7 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W
|
||||
this._needsDraw = true;
|
||||
|
||||
item.addHandler('bounds-change', this._delegatedFigureSizes);
|
||||
item.addHandler('clip-change', this._delegatedFigureSizes);
|
||||
|
||||
/**
|
||||
* Raised when an item is added to the World.
|
||||
@ -194,6 +195,7 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W
|
||||
}
|
||||
|
||||
item.removeHandler('bounds-change', this._delegatedFigureSizes);
|
||||
item.removeHandler('clip-change', this._delegatedFigureSizes);
|
||||
item.destroy();
|
||||
this._items.splice( index, 1 );
|
||||
this._figureSizes();
|
||||
@ -213,6 +215,7 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W
|
||||
for (var i = 0; i < this._items.length; i++) {
|
||||
item = this._items[i];
|
||||
item.removeHandler('bounds-change', this._delegatedFigureSizes);
|
||||
item.removeHandler('clip-change', this._delegatedFigureSizes);
|
||||
item.destroy();
|
||||
}
|
||||
|
||||
@ -383,7 +386,7 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W
|
||||
var item = this._items[0];
|
||||
var bounds = item.getBounds();
|
||||
this._contentFactor = item.getContentSize().x / bounds.width;
|
||||
var clippedBounds = item.getClippedBounds();
|
||||
var clippedBounds = item.getClippedBounds().getBoundingBox();
|
||||
var left = clippedBounds.x;
|
||||
var top = clippedBounds.y;
|
||||
var right = clippedBounds.x + clippedBounds.width;
|
||||
@ -393,7 +396,7 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W
|
||||
bounds = item.getBounds();
|
||||
this._contentFactor = Math.max(this._contentFactor,
|
||||
item.getContentSize().x / bounds.width);
|
||||
clippedBounds = item.getClippedBounds();
|
||||
clippedBounds = item.getClippedBounds().getBoundingBox();
|
||||
left = Math.min(left, clippedBounds.x);
|
||||
top = Math.min(top, clippedBounds.y);
|
||||
right = Math.max(right, clippedBounds.x + clippedBounds.width);
|
||||
|
@ -222,6 +222,27 @@
|
||||
});
|
||||
});
|
||||
|
||||
// ----------
|
||||
asyncTest('clip-change event', function() {
|
||||
expect(0);
|
||||
var clip = new OpenSeadragon.Rect(100, 100, 800, 800);
|
||||
|
||||
viewer.addHandler('open', function() {
|
||||
var image = viewer.world.getItemAt(0);
|
||||
image.addOnceHandler('clip-change', function() {
|
||||
image.addOnceHandler('clip-change', function() {
|
||||
start();
|
||||
});
|
||||
image.setClip(clip);
|
||||
});
|
||||
image.setClip(null);
|
||||
});
|
||||
|
||||
viewer.open({
|
||||
tileSource: '/test/data/testpattern.dzi'
|
||||
});
|
||||
});
|
||||
|
||||
// ----------
|
||||
asyncTest('getClipBounds', function() {
|
||||
var clip = new OpenSeadragon.Rect(100, 200, 800, 500);
|
||||
@ -294,6 +315,34 @@
|
||||
});
|
||||
|
||||
// ----------
|
||||
asyncTest('rotation', function() {
|
||||
|
||||
function testDefaultRotation() {
|
||||
var image = viewer.world.getItemAt(0);
|
||||
strictEqual(image.getRotation(), 0, 'image has default rotation');
|
||||
|
||||
image.setRotation(400);
|
||||
strictEqual(image.getRotation(), 40, 'rotation is set correctly');
|
||||
|
||||
viewer.addOnceHandler('open', testTileSourceRotation);
|
||||
viewer.open({
|
||||
tileSource: '/test/data/testpattern.dzi',
|
||||
degrees: -60
|
||||
});
|
||||
}
|
||||
|
||||
function testTileSourceRotation() {
|
||||
var image = viewer.world.getItemAt(0);
|
||||
strictEqual(image.getRotation(), 300, 'image has correct rotation');
|
||||
start();
|
||||
}
|
||||
|
||||
viewer.addOnceHandler('open', testDefaultRotation);
|
||||
viewer.open({
|
||||
tileSource: '/test/data/testpattern.dzi',
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('fitBounds', function() {
|
||||
|
||||
function assertRectEquals(actual, expected, message) {
|
||||
|
@ -105,7 +105,8 @@
|
||||
orig = config.getOrig(config.testArray[i], viewport);
|
||||
expected = config.getExpected(orig, viewport);
|
||||
actual = viewport[config.method](orig);
|
||||
propEqual(
|
||||
var assert = config.assert || propEqual;
|
||||
assert(
|
||||
actual,
|
||||
expected,
|
||||
"Correctly converted coordinates " + orig
|
||||
@ -118,6 +119,10 @@
|
||||
viewer.open(DZI_PATH);
|
||||
};
|
||||
|
||||
function assertPointsEquals(actual, expected, message) {
|
||||
Util.assertPointsEquals(actual, expected, 1e-15, message);
|
||||
}
|
||||
|
||||
// Tests start here.
|
||||
|
||||
asyncTest('getContainerSize', function() {
|
||||
@ -872,7 +877,8 @@
|
||||
getExpected: function(orig, viewport) {
|
||||
return orig.divide(viewer.source.dimensions.x);
|
||||
},
|
||||
method: 'imageToViewportCoordinates'
|
||||
method: 'imageToViewportCoordinates',
|
||||
assert: assertPointsEquals
|
||||
});
|
||||
});
|
||||
|
||||
@ -885,7 +891,8 @@
|
||||
getExpected: function(orig, viewport) {
|
||||
return orig.divide(ZOOM_FACTOR * viewport.getContainerSize().x);
|
||||
},
|
||||
method: 'imageToViewportCoordinates'
|
||||
method: 'imageToViewportCoordinates',
|
||||
assert: assertPointsEquals
|
||||
});
|
||||
});
|
||||
asyncTest('imageToViewportRectangle', function() {
|
||||
@ -902,7 +909,8 @@
|
||||
orig.height / viewer.source.dimensions.x
|
||||
);
|
||||
},
|
||||
method: 'imageToViewportRectangle'
|
||||
method: 'imageToViewportRectangle',
|
||||
assert: assertPointsEquals
|
||||
});
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user