mirror of
https://github.com/openseadragon/openseadragon.git
synced 2024-11-22 13:16:10 +03:00
Merge branch 'master' of github.com:openseadragon/openseadragon
This commit is contained in:
commit
c59a2be322
@ -146,6 +146,7 @@ $.TiledImage = function( options ) {
|
|||||||
_midDraw: false, // Is the tiledImage currently updating the viewport?
|
_midDraw: false, // Is the tiledImage currently updating the viewport?
|
||||||
_needsDraw: true, // Does the tiledImage need to update the viewport again?
|
_needsDraw: true, // Does the tiledImage need to update the viewport again?
|
||||||
_hasOpaqueTile: false, // Do we have even one fully opaque tile?
|
_hasOpaqueTile: false, // Do we have even one fully opaque tile?
|
||||||
|
_tilesLoading: 0, // The number of pending tile requests.
|
||||||
//configurable settings
|
//configurable settings
|
||||||
springStiffness: $.DEFAULT_SETTINGS.springStiffness,
|
springStiffness: $.DEFAULT_SETTINGS.springStiffness,
|
||||||
animationTime: $.DEFAULT_SETTINGS.animationTime,
|
animationTime: $.DEFAULT_SETTINGS.animationTime,
|
||||||
@ -898,6 +899,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
// private
|
// private
|
||||||
_updateViewport: function() {
|
_updateViewport: function() {
|
||||||
this._needsDraw = false;
|
this._needsDraw = false;
|
||||||
|
this._tilesLoading = 0;
|
||||||
|
|
||||||
// Reset tile's internal drawn state
|
// Reset tile's internal drawn state
|
||||||
while (this.lastDrawn.length > 0) {
|
while (this.lastDrawn.length > 0) {
|
||||||
@ -994,8 +996,49 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
this._needsDraw = true;
|
this._needsDraw = true;
|
||||||
this._setFullyLoaded(false);
|
this._setFullyLoaded(false);
|
||||||
} else {
|
} else {
|
||||||
this._setFullyLoaded(true);
|
this._setFullyLoaded(this._tilesLoading === 0);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// private
|
||||||
|
_getCornerTiles: function(level, topLeftBound, bottomRightBound) {
|
||||||
|
var leftX;
|
||||||
|
var rightX;
|
||||||
|
if (this.wrapHorizontal) {
|
||||||
|
leftX = $.positiveModulo(topLeftBound.x, 1);
|
||||||
|
rightX = $.positiveModulo(bottomRightBound.x, 1);
|
||||||
|
} else {
|
||||||
|
leftX = Math.max(0, topLeftBound.x);
|
||||||
|
rightX = Math.min(1, bottomRightBound.x);
|
||||||
|
}
|
||||||
|
var topY;
|
||||||
|
var bottomY;
|
||||||
|
var aspectRatio = 1 / this.source.aspectRatio;
|
||||||
|
if (this.wrapVertical) {
|
||||||
|
topY = $.positiveModulo(topLeftBound.y, aspectRatio);
|
||||||
|
bottomY = $.positiveModulo(bottomRightBound.y, aspectRatio);
|
||||||
|
} else {
|
||||||
|
topY = Math.max(0, topLeftBound.y);
|
||||||
|
bottomY = Math.min(aspectRatio, bottomRightBound.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
var topLeftTile = this.source.getTileAtPoint(level, new $.Point(leftX, topY));
|
||||||
|
var bottomRightTile = this.source.getTileAtPoint(level, new $.Point(rightX, bottomY));
|
||||||
|
var numTiles = this.source.getNumTiles(level);
|
||||||
|
|
||||||
|
if (this.wrapHorizontal) {
|
||||||
|
topLeftTile.x += numTiles.x * Math.floor(topLeftBound.x);
|
||||||
|
bottomRightTile.x += numTiles.x * Math.floor(bottomRightBound.x);
|
||||||
|
}
|
||||||
|
if (this.wrapVertical) {
|
||||||
|
topLeftTile.y += numTiles.y * Math.floor(topLeftBound.y / aspectRatio);
|
||||||
|
bottomRightTile.y += numTiles.y * Math.floor(bottomRightBound.y / aspectRatio);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
topLeft: topLeftTile,
|
||||||
|
bottomRight: bottomRightTile,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1039,23 +1082,13 @@ function updateLevel(tiledImage, haveDrawn, drawLevel, level, levelOpacity,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//OK, a new drawing so do your calculations
|
|
||||||
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) {
|
//OK, a new drawing so do your calculations
|
||||||
// Adjust for floating point error
|
var cornerTiles = tiledImage._getCornerTiles(level, topLeftBound, bottomRightBound);
|
||||||
topLeftTile.x = Math.max(topLeftTile.x, 0);
|
var topLeftTile = cornerTiles.topLeft;
|
||||||
bottomRightTile.x = Math.min(bottomRightTile.x, numberOfTiles.x - 1);
|
var bottomRightTile = cornerTiles.bottomRight;
|
||||||
}
|
var numberOfTiles = tiledImage.source.getNumTiles(level);
|
||||||
if (!tiledImage.wrapVertical) {
|
|
||||||
// Adjust for floating point error
|
|
||||||
topLeftTile.y = Math.max(topLeftTile.y, 0);
|
|
||||||
bottomRightTile.y = Math.min(bottomRightTile.y, numberOfTiles.y - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
var viewportCenter = tiledImage.viewport.pixelFromPoint(
|
var viewportCenter = tiledImage.viewport.pixelFromPoint(
|
||||||
tiledImage.viewport.getCenter());
|
tiledImage.viewport.getCenter());
|
||||||
@ -1178,7 +1211,7 @@ function updateTile( tiledImage, drawLevel, haveDrawn, x, y, level, levelOpacity
|
|||||||
}
|
}
|
||||||
} else if ( tile.loading ) {
|
} else if ( tile.loading ) {
|
||||||
// the tile is already in the download queue
|
// the tile is already in the download queue
|
||||||
// thanks josh1093 for finally translating this typo
|
tiledImage._tilesLoading++;
|
||||||
} else {
|
} else {
|
||||||
best = compareTiles( best, tile );
|
best = compareTiles( best, tile );
|
||||||
}
|
}
|
||||||
|
@ -345,18 +345,17 @@ $.TileSource.prototype = {
|
|||||||
* @param {OpenSeadragon.Point} point
|
* @param {OpenSeadragon.Point} point
|
||||||
*/
|
*/
|
||||||
getTileAtPoint: function(level, point) {
|
getTileAtPoint: function(level, point) {
|
||||||
|
var validPoint = point.x >= 0 && point.x <= 1 &&
|
||||||
|
point.y >= 0 && point.y <= 1 / this.aspectRatio;
|
||||||
|
$.console.assert(validPoint, "[TileSource.getTileAtPoint] must be called with a valid point.");
|
||||||
|
|
||||||
var widthScaled = this.dimensions.x * this.getLevelScale(level);
|
var widthScaled = this.dimensions.x * this.getLevelScale(level);
|
||||||
var pixelX = $.positiveModulo(point.x, 1) * widthScaled;
|
var pixelX = point.x * widthScaled;
|
||||||
var pixelY = $.positiveModulo(point.y, 1 / this.aspectRatio) * widthScaled;
|
var pixelY = point.y * widthScaled;
|
||||||
|
|
||||||
var x = Math.floor(pixelX / this.getTileWidth());
|
var x = Math.floor(pixelX / this.getTileWidth());
|
||||||
var y = Math.floor(pixelY / this.getTileHeight());
|
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);
|
return new $.Point(x, y);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
<script src="/src/iiiftilesource.js"></script>
|
<script src="/src/iiiftilesource.js"></script>
|
||||||
<script src="/src/osmtilesource.js"></script>
|
<script src="/src/osmtilesource.js"></script>
|
||||||
<script src="/src/tmstilesource.js"></script>
|
<script src="/src/tmstilesource.js"></script>
|
||||||
|
<script src="/src/zoomifytilesource.js"></script>
|
||||||
<script src="/src/legacytilesource.js"></script>
|
<script src="/src/legacytilesource.js"></script>
|
||||||
<script src="/src/imagetilesource.js"></script>
|
<script src="/src/imagetilesource.js"></script>
|
||||||
<script src="/src/tilesourcecollection.js"></script>
|
<script src="/src/tilesourcecollection.js"></script>
|
||||||
|
@ -331,7 +331,7 @@
|
|||||||
height: 155
|
height: 155
|
||||||
} ]
|
} ]
|
||||||
} );
|
} );
|
||||||
viewer.addHandler('tile-drawn', function() {
|
viewer.addOnceHandler('tile-drawn', function() {
|
||||||
ok(OpenSeadragon.isCanvasTainted(viewer.drawer.context.canvas),
|
ok(OpenSeadragon.isCanvasTainted(viewer.drawer.context.canvas),
|
||||||
"Canvas should be tainted.");
|
"Canvas should be tainted.");
|
||||||
start();
|
start();
|
||||||
@ -355,7 +355,7 @@
|
|||||||
height: 155
|
height: 155
|
||||||
} ]
|
} ]
|
||||||
} );
|
} );
|
||||||
viewer.addHandler('tile-drawn', function() {
|
viewer.addOnceHandler('tile-drawn', function() {
|
||||||
ok(!OpenSeadragon.isCanvasTainted(viewer.drawer.context.canvas),
|
ok(!OpenSeadragon.isCanvasTainted(viewer.drawer.context.canvas),
|
||||||
"Canvas should not be tainted.");
|
"Canvas should not be tainted.");
|
||||||
start();
|
start();
|
||||||
@ -385,7 +385,7 @@
|
|||||||
},
|
},
|
||||||
crossOriginPolicy : false
|
crossOriginPolicy : false
|
||||||
} );
|
} );
|
||||||
viewer.addHandler('tile-drawn', function() {
|
viewer.addOnceHandler('tile-drawn', function() {
|
||||||
ok(OpenSeadragon.isCanvasTainted(viewer.drawer.context.canvas),
|
ok(OpenSeadragon.isCanvasTainted(viewer.drawer.context.canvas),
|
||||||
"Canvas should be tainted.");
|
"Canvas should be tainted.");
|
||||||
start();
|
start();
|
||||||
@ -414,7 +414,7 @@
|
|||||||
crossOriginPolicy : "Anonymous"
|
crossOriginPolicy : "Anonymous"
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
viewer.addHandler('tile-drawn', function() {
|
viewer.addOnceHandler('tile-drawn', function() {
|
||||||
ok(!OpenSeadragon.isCanvasTainted(viewer.drawer.context.canvas),
|
ok(!OpenSeadragon.isCanvasTainted(viewer.drawer.context.canvas),
|
||||||
"Canvas should not be tainted.");
|
"Canvas should not be tainted.");
|
||||||
start();
|
start();
|
||||||
|
@ -217,7 +217,7 @@
|
|||||||
var firstImage = viewer.world.getItemAt(0);
|
var firstImage = viewer.world.getItemAt(0);
|
||||||
firstImage.addHandler('fully-loaded-change', function() {
|
firstImage.addHandler('fully-loaded-change', function() {
|
||||||
var imageData = viewer.drawer.context.getImageData(0, 0,
|
var imageData = viewer.drawer.context.getImageData(0, 0,
|
||||||
500 * OpenSeadragon.pixelDensityRatio, 500 * density);
|
500 * density, 500 * density);
|
||||||
|
|
||||||
// Pixel 250,250 will be in the hole of the A
|
// Pixel 250,250 will be in the hole of the A
|
||||||
var expectedVal = getPixelValue(imageData, 250 * density, 250 * density);
|
var expectedVal = getPixelValue(imageData, 250 * density, 250 * density);
|
||||||
|
@ -515,4 +515,159 @@
|
|||||||
}]);
|
}]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// PhantomJS is missing Function.prototype.bind
|
||||||
|
function bind(func, _this) {
|
||||||
|
return function() {
|
||||||
|
return func.apply(_this, arguments);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
test('_getCornerTiles without wrapping', function() {
|
||||||
|
var tiledImageMock = {
|
||||||
|
wrapHorizontal: false,
|
||||||
|
wrapVertical: false,
|
||||||
|
source: new OpenSeadragon.TileSource({
|
||||||
|
width: 1500,
|
||||||
|
height: 1000,
|
||||||
|
tileWidth: 200,
|
||||||
|
tileHeight: 150,
|
||||||
|
tileOverlap: 1,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
var _getCornerTiles = bind(
|
||||||
|
OpenSeadragon.TiledImage.prototype._getCornerTiles,
|
||||||
|
tiledImageMock);
|
||||||
|
|
||||||
|
function assertCornerTiles(topLeftBound, bottomRightBound,
|
||||||
|
expectedTopLeft, expectedBottomRight) {
|
||||||
|
var cornerTiles = _getCornerTiles(11, topLeftBound, bottomRightBound);
|
||||||
|
ok(cornerTiles.topLeft.equals(expectedTopLeft),
|
||||||
|
'Top left tile should be ' + expectedTopLeft.toString() +
|
||||||
|
' found ' + cornerTiles.topLeft.toString());
|
||||||
|
ok(cornerTiles.bottomRight.equals(expectedBottomRight),
|
||||||
|
'Bottom right tile should be ' + expectedBottomRight.toString() +
|
||||||
|
' found ' + cornerTiles.bottomRight.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
assertCornerTiles(
|
||||||
|
new OpenSeadragon.Point(0, 0),
|
||||||
|
new OpenSeadragon.Point(1, 10 / 15),
|
||||||
|
new OpenSeadragon.Point(0, 0),
|
||||||
|
new OpenSeadragon.Point(7, 6)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Floating point errors should be handled
|
||||||
|
assertCornerTiles(
|
||||||
|
new OpenSeadragon.Point(-1e-14, -1e-14),
|
||||||
|
new OpenSeadragon.Point(1 + 1e-14, 10 / 15 + 1e-14),
|
||||||
|
new OpenSeadragon.Point(0, 0),
|
||||||
|
new OpenSeadragon.Point(7, 6)
|
||||||
|
)
|
||||||
|
|
||||||
|
assertCornerTiles(
|
||||||
|
new OpenSeadragon.Point(0.3, 0.5),
|
||||||
|
new OpenSeadragon.Point(0.5, 0.6),
|
||||||
|
new OpenSeadragon.Point(2, 5),
|
||||||
|
new OpenSeadragon.Point(3, 6)
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
test('_getCornerTiles with horizontal wrapping', function() {
|
||||||
|
var tiledImageMock = {
|
||||||
|
wrapHorizontal: true,
|
||||||
|
wrapVertical: false,
|
||||||
|
source: new OpenSeadragon.TileSource({
|
||||||
|
width: 1500,
|
||||||
|
height: 1000,
|
||||||
|
tileWidth: 200,
|
||||||
|
tileHeight: 150,
|
||||||
|
tileOverlap: 1,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
var _getCornerTiles = bind(
|
||||||
|
OpenSeadragon.TiledImage.prototype._getCornerTiles,
|
||||||
|
tiledImageMock);
|
||||||
|
|
||||||
|
function assertCornerTiles(topLeftBound, bottomRightBound,
|
||||||
|
expectedTopLeft, expectedBottomRight) {
|
||||||
|
var cornerTiles = _getCornerTiles(11, topLeftBound, bottomRightBound);
|
||||||
|
ok(cornerTiles.topLeft.equals(expectedTopLeft),
|
||||||
|
'Top left tile should be ' + expectedTopLeft.toString() +
|
||||||
|
' found ' + cornerTiles.topLeft.toString());
|
||||||
|
ok(cornerTiles.bottomRight.equals(expectedBottomRight),
|
||||||
|
'Bottom right tile should be ' + expectedBottomRight.toString() +
|
||||||
|
' found ' + cornerTiles.bottomRight.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
assertCornerTiles(
|
||||||
|
new OpenSeadragon.Point(0, 0),
|
||||||
|
new OpenSeadragon.Point(1, 10 / 15),
|
||||||
|
new OpenSeadragon.Point(0, 0),
|
||||||
|
new OpenSeadragon.Point(8, 6)
|
||||||
|
)
|
||||||
|
|
||||||
|
assertCornerTiles(
|
||||||
|
new OpenSeadragon.Point(-1, 0),
|
||||||
|
new OpenSeadragon.Point(0.5, 10 / 15 + 1e-14),
|
||||||
|
new OpenSeadragon.Point(-8, 0),
|
||||||
|
new OpenSeadragon.Point(3, 6)
|
||||||
|
)
|
||||||
|
|
||||||
|
assertCornerTiles(
|
||||||
|
new OpenSeadragon.Point(1.3, 0.5),
|
||||||
|
new OpenSeadragon.Point(1.5, 0.6),
|
||||||
|
new OpenSeadragon.Point(10, 5),
|
||||||
|
new OpenSeadragon.Point(11, 6)
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
test('_getCornerTiles with vertical wrapping', function() {
|
||||||
|
var tiledImageMock = {
|
||||||
|
wrapHorizontal: false,
|
||||||
|
wrapVertical: true,
|
||||||
|
source: new OpenSeadragon.TileSource({
|
||||||
|
width: 1500,
|
||||||
|
height: 1000,
|
||||||
|
tileWidth: 200,
|
||||||
|
tileHeight: 150,
|
||||||
|
tileOverlap: 1,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
var _getCornerTiles = bind(
|
||||||
|
OpenSeadragon.TiledImage.prototype._getCornerTiles,
|
||||||
|
tiledImageMock);
|
||||||
|
|
||||||
|
function assertCornerTiles(topLeftBound, bottomRightBound,
|
||||||
|
expectedTopLeft, expectedBottomRight) {
|
||||||
|
var cornerTiles = _getCornerTiles(11, topLeftBound, bottomRightBound);
|
||||||
|
ok(cornerTiles.topLeft.equals(expectedTopLeft),
|
||||||
|
'Top left tile should be ' + expectedTopLeft.toString() +
|
||||||
|
' found ' + cornerTiles.topLeft.toString());
|
||||||
|
ok(cornerTiles.bottomRight.equals(expectedBottomRight),
|
||||||
|
'Bottom right tile should be ' + expectedBottomRight.toString() +
|
||||||
|
' found ' + cornerTiles.bottomRight.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
assertCornerTiles(
|
||||||
|
new OpenSeadragon.Point(0, 0),
|
||||||
|
new OpenSeadragon.Point(1, 10 / 15),
|
||||||
|
new OpenSeadragon.Point(0, 0),
|
||||||
|
new OpenSeadragon.Point(7, 7)
|
||||||
|
)
|
||||||
|
|
||||||
|
assertCornerTiles(
|
||||||
|
new OpenSeadragon.Point(0, -10 / 15 / 2),
|
||||||
|
new OpenSeadragon.Point(0.5, 0.5),
|
||||||
|
new OpenSeadragon.Point(0, -4),
|
||||||
|
new OpenSeadragon.Point(3, 5)
|
||||||
|
)
|
||||||
|
|
||||||
|
assertCornerTiles(
|
||||||
|
new OpenSeadragon.Point(0, 10 / 15 + 0.1),
|
||||||
|
new OpenSeadragon.Point(0.3, 10 / 15 + 0.3),
|
||||||
|
new OpenSeadragon.Point(0, 7),
|
||||||
|
new OpenSeadragon.Point(2, 9)
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -48,4 +48,43 @@
|
|||||||
Util.testDeprecation(source, 'getTileSize');
|
Util.testDeprecation(source, 'getTileSize');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('getTileAtPoint', function() {
|
||||||
|
var tileSource = new OpenSeadragon.TileSource({
|
||||||
|
width: 1500,
|
||||||
|
height: 1000,
|
||||||
|
tileWidth: 200,
|
||||||
|
tileHeight: 150,
|
||||||
|
tileOverlap: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
equal(tileSource.maxLevel, 11, "The max level should be 11.");
|
||||||
|
|
||||||
|
function assertTileAtPoint(level, position, expected) {
|
||||||
|
var actual = tileSource.getTileAtPoint(level, position);
|
||||||
|
ok(actual.equals(expected), "The tile at level " + level +
|
||||||
|
", position " + position.toString() +
|
||||||
|
" should be tile " + expected.toString() +
|
||||||
|
" got " + actual.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTileAtPoint(11, new OpenSeadragon.Point(0, 0), new OpenSeadragon.Point(0, 0));
|
||||||
|
assertTileAtPoint(11, new OpenSeadragon.Point(0.5, 0.5), new OpenSeadragon.Point(3, 5));
|
||||||
|
assertTileAtPoint(11, new OpenSeadragon.Point(1, 10 / 15), new OpenSeadragon.Point(7, 6));
|
||||||
|
|
||||||
|
assertTileAtPoint(10, new OpenSeadragon.Point(0, 0), new OpenSeadragon.Point(0, 0));
|
||||||
|
assertTileAtPoint(10, new OpenSeadragon.Point(0.5, 0.5), new OpenSeadragon.Point(1, 2));
|
||||||
|
assertTileAtPoint(10, new OpenSeadragon.Point(1, 10 / 15), new OpenSeadragon.Point(3, 3));
|
||||||
|
|
||||||
|
assertTileAtPoint(9, new OpenSeadragon.Point(0, 0), new OpenSeadragon.Point(0, 0));
|
||||||
|
assertTileAtPoint(9, new OpenSeadragon.Point(0.5, 0.5), new OpenSeadragon.Point(0, 1));
|
||||||
|
assertTileAtPoint(9, new OpenSeadragon.Point(1, 10 / 15), new OpenSeadragon.Point(1, 1));
|
||||||
|
|
||||||
|
// For all other levels, there is only one tile.
|
||||||
|
for (var level = 8; level >= 0; level--) {
|
||||||
|
assertTileAtPoint(level, new OpenSeadragon.Point(0, 0), new OpenSeadragon.Point(0, 0));
|
||||||
|
assertTileAtPoint(level, new OpenSeadragon.Point(0.5, 0.5), new OpenSeadragon.Point(0, 0));
|
||||||
|
assertTileAtPoint(level, new OpenSeadragon.Point(1, 10 / 15), new OpenSeadragon.Point(0, 0));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}());
|
}());
|
||||||
|
Loading…
Reference in New Issue
Block a user