diff --git a/mobile/chrome/content/BrowserView.js b/mobile/chrome/content/BrowserView.js index dca9c6cbfdd7..58f9cbaa26cb 100644 --- a/mobile/chrome/content/BrowserView.js +++ b/mobile/chrome/content/BrowserView.js @@ -509,6 +509,37 @@ BrowserView.prototype = { this.setZoomLevel(bvs.zoomLevel + zoomDelta); }, + /** + * Render a rectangle within the browser viewport to the destination canvas + * under the given scale. + * + * @param destCanvas The destination canvas into which the image is rendered. + * @param destWidth Destination width + * @param destHeight Destination height + * @param srcRect [optional] The source rectangle in BrowserView coordinates. + * This defaults to the visible rect rooted at the x,y of the critical rect. + */ + renderToCanvas: function renderToCanvas(destCanvas, destWidth, destHeight, srcRect) { + let bvs = this._browserViewportState; + if (!bvs) { + throw "Browser viewport state null in call to renderToCanvas (probably no browser set on BrowserView)."; + } + + if (!srcRect) { + let vr = this.getVisibleRect(); + let cr = BrowserView.Util.visibleRectToCriticalRect(vr, bvs); + vr.x = cr.left; + vr.y = cr.top; + srcRect = vr; + } + + let scalex = (destWidth / srcRect.width) || 1; + let scaley = (destHeight / srcRect.height) || 1; + + srcRect.restrictTo(bvs.viewportRect); + this._tileManager.renderRectToCanvas(srcRect, destCanvas, scalex, scaley); + }, + viewportToBrowser: function viewportToBrowser(x) { let bvs = this._browserViewportState; diff --git a/mobile/chrome/content/TileManager.js.in b/mobile/chrome/content/TileManager.js.in index 5ee6c138610a..c0a5f239ffb6 100644 --- a/mobile/chrome/content/TileManager.js.in +++ b/mobile/chrome/content/TileManager.js.in @@ -305,6 +305,46 @@ TileManager.prototype = { }); }, + renderRectToCanvas: function renderRectToCanvas(srcRect, destCanvas, scalex, scaley) { + let tc = this._tileCache; + let ctx = destCanvas.getContext("2d"); + + let completed = (function breakableLoop() { + BEGIN_FOREACH_IN_RECT(srcRect, tc, tile) + + if (tile.isDirty()) + return false; + + let dx = Math.round(scalex * (tile.boundRect.left - srcRect.left)); + let dy = Math.round(scaley * (tile.boundRect.top - srcRect.top)); + + ctx.drawImage(tile._canvas, dx, dy, + Math.round(scalex * kTileWidth), + Math.round(scaley * kTileHeight)); + + END_FOREACH_IN_RECT + + return true; + })(); + + if (!completed) { + let bv = this._browserView; + + bv.viewportToBrowserRect(srcRect); + + ctx.save(); + + bv.browserToViewportCanvasContext(ctx); + ctx.scale(scalex, scaley); + ctx.drawWindow(bv._contentWindow, + 0, 0, srcRect.width, srcRect.height, + "white", + (ctx.DRAWWINDOW_DO_NOT_FLUSH | ctx.DRAWWINDOW_DRAW_CARET)); + + ctx.restore(); + } + }, + _renderTile: function _renderTile(tile) { if (tile.isDirty()) tile.render(this._browserView); diff --git a/mobile/chrome/content/browser.js b/mobile/chrome/content/browser.js index 131358313a36..e7cc236247dd 100644 --- a/mobile/chrome/content/browser.js +++ b/mobile/chrome/content/browser.js @@ -172,7 +172,7 @@ function onDebugKeyPress(ev) { return; // use capitals so we require SHIFT here too - + const a = 65; // debug all critical tiles const b = 66; // dump an ASCII graphic of the tile map const c = 67; // set tilecache capacity @@ -2431,8 +2431,7 @@ Tab.prototype = { if (!this._browser) return; - // XXX draw from the tiles in to the source - let srcCanvas = (Browser.selectedBrowser == this._browser) ? document.getElementById("browser-canvas") : null; - this._chromeTab.updateThumbnail(this._browser, srcCanvas); + let browserView = (Browser.selectedBrowser == this._browser) ? Browser._browserView : null; + this._chromeTab.updateThumbnail(this._browser, browserView); } }; diff --git a/mobile/chrome/content/tabs.xml b/mobile/chrome/content/tabs.xml index c3abaf9b3972..a1764bf13314 100644 --- a/mobile/chrome/content/tabs.xml +++ b/mobile/chrome/content/tabs.xml @@ -27,20 +27,19 @@ - +