diff --git a/src/imagetilesource.js b/src/imagetilesource.js index 72ab4917..9f8796db 100644 --- a/src/imagetilesource.js +++ b/src/imagetilesource.js @@ -205,6 +205,20 @@ } return url; }, + /** + * Retrieves a tile context 2D + * @function + * @param {Number} level Level of the tile + * @param {Number} x x coordinate of the tile + * @param {Number} y y coordinate of the tile + */ + getContext2D: function (level, x, y) { + var context = null; + if (level >= this.minLevel && level <= this.maxLevel) { + context = this.levels[level].context2D; + } + return context; + }, /** * @private Build the differents levels of the pyramid if possible * (canvas API enabled and no canvas tainting issue) @@ -239,33 +253,28 @@ return levels; } levels.splice(0, 0, { - url: bigCanvas.toDataURL(), + context2D: bigContext, width: currentWidth, height: currentHeight }); - var smallCanvas = document.createElement("canvas"); - var smallContext = smallCanvas.getContext("2d"); while (currentWidth >= minWidth * 2 && currentHeight >= minHeight * 2) { currentWidth = Math.floor(currentWidth / 2); currentHeight = Math.floor(currentHeight / 2); + var smallCanvas = document.createElement("canvas"); + var smallContext = smallCanvas.getContext("2d"); smallCanvas.width = currentWidth; smallCanvas.height = currentHeight; smallContext.drawImage(bigCanvas, 0, 0, currentWidth, currentHeight); levels.splice(0, 0, { - url: smallCanvas.toDataURL(), + context2D: smallContext, width: currentWidth, height: currentHeight }); - var tempCanvas = bigCanvas; bigCanvas = smallCanvas; - smallCanvas = tempCanvas; - - var tempContext = bigContext; bigContext = smallContext; - smallContext = tempContext; } return levels; } diff --git a/src/tile.js b/src/tile.js index ad018ba7..97d88e17 100644 --- a/src/tile.js +++ b/src/tile.js @@ -45,8 +45,10 @@ * @param {Boolean} exists Is this tile a part of a sparse image? ( Also has * this tile failed to load? ) * @param {String} url The URL of this tile's image. + * @param {CanvasRenderingContext2D} context2D The context2D of this tile if it + * is provided directly by the tile source. */ -$.Tile = function(level, x, y, bounds, exists, url) { +$.Tile = function(level, x, y, bounds, exists, url, context2D) { /** * The zoom level this tile belongs to. * @member {Number} level @@ -83,6 +85,12 @@ $.Tile = function(level, x, y, bounds, exists, url) { * @memberof OpenSeadragon.Tile# */ this.url = url; + /** + * The context2D of this tile if it is provided directly by the tile source. + * @member {CanvasRenderingContext2D} context2D + * @memberOf OpenSeadragon.Tile# + */ + this.context2D = context2D; /** * Is this tile loaded? * @member {Boolean} loaded @@ -247,14 +255,14 @@ $.Tile.prototype = /** @lends OpenSeadragon.Tile.prototype */{ size = this.size, rendered; - if (!this.cacheImageRecord) { + if (!this.context2D && !this.cacheImageRecord) { $.console.warn( '[Tile.drawCanvas] attempting to draw tile %s when it\'s not cached', this.toString()); return; } - rendered = this.cacheImageRecord.getRenderedContext(); + rendered = this.context2D || this.cacheImageRecord.getRenderedContext(); if ( !this.loaded || !rendered ){ $.console.warn( @@ -273,7 +281,8 @@ $.Tile.prototype = /** @lends OpenSeadragon.Tile.prototype */{ //ie its done fading or fading is turned off, and if we are drawing //an image with an alpha channel, then the only way //to avoid seeing the tile underneath is to clear the rectangle - if( context.globalAlpha == 1 && this.url.match('.png') ){ + if (context.globalAlpha === 1 && + (this.context2D || this.url.match('.png'))) { //clearing only the inside of the rectangle occupied //by the png prevents edge flikering context.clearRect( diff --git a/src/tiledimage.js b/src/tiledimage.js index a6943de4..410edbd2 100644 --- a/src/tiledimage.js +++ b/src/tiledimage.js @@ -791,7 +791,7 @@ function updateViewport( tiledImage ) { drawTiles( tiledImage, tiledImage.lastDrawn ); // Load the new 'best' tile - if ( best ) { + if (best && !best.context2D) { loadTile( tiledImage, best, currentTime ); } @@ -936,10 +936,14 @@ function updateTile( tiledImage, drawLevel, haveDrawn, x, y, level, levelOpacity ); if (!tile.loaded) { - var imageRecord = tiledImage._tileCache.getImageRecord(tile.url); - if (imageRecord) { - var image = imageRecord.getImage(); - setTileLoaded(tiledImage, tile, image); + if (tile.context2D) { + setTileLoaded(tiledImage, tile); + } else { + var imageRecord = tiledImage._tileCache.getImageRecord(tile.url); + if (imageRecord) { + var image = imageRecord.getImage(); + setTileLoaded(tiledImage, tile, image); + } } } @@ -972,6 +976,7 @@ function getTile( x, y, level, tileSource, tilesMatrix, time, numTiles, worldWid bounds, exists, url, + context2D, tile; if ( !tilesMatrix[ level ] ) { @@ -987,6 +992,8 @@ function getTile( x, y, level, tileSource, tilesMatrix, time, numTiles, worldWid bounds = tileSource.getTileBounds( level, xMod, yMod ); exists = tileSource.tileExists( level, xMod, yMod ); url = tileSource.getTileUrl( level, xMod, yMod ); + context2D = tileSource.getContext2D ? + tileSource.getContext2D(level, xMod, yMod) : undefined; bounds.x += ( x - xMod ) / numTiles.x; bounds.y += (worldHeight / worldWidth) * (( y - yMod ) / numTiles.y); @@ -997,7 +1004,8 @@ function getTile( x, y, level, tileSource, tilesMatrix, time, numTiles, worldWid y, bounds, exists, - url + url, + context2D ); } @@ -1076,12 +1084,14 @@ function setTileLoaded(tiledImage, tile, image, cutoff) { if (increment === 0) { tile.loading = false; tile.loaded = true; - tiledImage._tileCache.cacheTile({ - image: image, - tile: tile, - cutoff: cutoff, - tiledImage: tiledImage - }); + if (!tile.context2D) { + tiledImage._tileCache.cacheTile({ + image: image, + tile: tile, + cutoff: cutoff, + tiledImage: tiledImage + }); + } tiledImage._needsDraw = true; } }