bug 713874 - Black thumbnails are produced by GeckoSoftwareLayerClient.getBitmap() r=mfinkle

This commit is contained in:
Brad Lassey 2012-01-13 13:10:13 -05:00
parent c67b3f82e3
commit 6af65a3e2d
3 changed files with 73 additions and 14 deletions

View File

@ -593,25 +593,34 @@ abstract public class GeckoApp
mLastUri = lastHistoryEntry.mUri;
mLastTitle = lastHistoryEntry.mTitle;
Bitmap bitmap = mSoftwareLayerClient.getBitmap();
if (bitmap != null) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 0, bos);
mLastScreen = bos.toByteArray();
// Make a thumbnail for the given tab, if it's still selected
// NOTE: bitmap is recycled in updateThumbnail
if (tab == mThumbnailTab) {
if (mThumbnailTab.getURL().equals("about:home"))
mThumbnailTab.updateThumbnail(null);
else
mThumbnailTab.updateThumbnail(bitmap);
}
processThumbnail(tab, bitmap, bos.toByteArray());
} else {
mLastScreen = null;
GeckoAppShell.sendEventToGecko(
new GeckoEvent("Tab:Screenshot",
"{\"width\": \"" + mSoftwareLayerClient.getWidth() + "\", " +
"\"height\": \"" + mSoftwareLayerClient.getHeight() + "\", " +
"\"tabID\": \"" + tab.getId() + "\" }"));
}
}
}
}
void processThumbnail(Tab thumbnailTab, Bitmap bitmap, byte[] compressed) {
if (Tabs.getInstance().isSelectedTab(thumbnailTab))
mLastScreen = compressed;
if (thumbnailTab.getURL().equals("about:home")) {
thumbnailTab.updateThumbnail(null);
return;
}
if (bitmap == null)
bitmap = BitmapFactory.decodeByteArray(compressed, 0, compressed.length);
thumbnailTab.updateThumbnail(bitmap);
}
private void maybeCancelFaviconLoad(Tab tab) {
long faviconLoadId = tab.getFaviconLoadId();
@ -898,6 +907,10 @@ abstract public class GeckoApp
Log.i(LOGTAG, "Destroyed a tab");
int tabId = message.getInt("tabID");
handleCloseTab(tabId);
} else if (event.equals("Tab:ScreenshotData")) {
int tabId = message.getInt("tabID");
Tab tab = Tabs.getInstance().getTab(tabId);
processThumbnail(tab, null, Base64.decode(message.getString("data").substring(22), Base64.DEFAULT));
} else if (event.equals("Tab:Selected")) {
int tabId = message.getInt("tabID");
Log.i(LOGTAG, "Switched to tab: " + tabId);
@ -1534,6 +1547,7 @@ abstract public class GeckoApp
GeckoAppShell.registerGeckoEventListener("Tab:Added", GeckoApp.mAppContext);
GeckoAppShell.registerGeckoEventListener("Tab:Closed", GeckoApp.mAppContext);
GeckoAppShell.registerGeckoEventListener("Tab:Selected", GeckoApp.mAppContext);
GeckoAppShell.registerGeckoEventListener("Tab:ScreenshotData", GeckoApp.mAppContext);
GeckoAppShell.registerGeckoEventListener("Doorhanger:Add", GeckoApp.mAppContext);
GeckoAppShell.registerGeckoEventListener("Doorhanger:Remove", GeckoApp.mAppContext);
GeckoAppShell.registerGeckoEventListener("Menu:Add", GeckoApp.mAppContext);
@ -1770,6 +1784,7 @@ abstract public class GeckoApp
GeckoAppShell.unregisterGeckoEventListener("Tab:Added", GeckoApp.mAppContext);
GeckoAppShell.unregisterGeckoEventListener("Tab:Closed", GeckoApp.mAppContext);
GeckoAppShell.unregisterGeckoEventListener("Tab:Selected", GeckoApp.mAppContext);
GeckoAppShell.unregisterGeckoEventListener("Tab:ScreenshotData", GeckoApp.mAppContext);
GeckoAppShell.unregisterGeckoEventListener("Doorhanger:Add", GeckoApp.mAppContext);
GeckoAppShell.unregisterGeckoEventListener("Menu:Add", GeckoApp.mAppContext);
GeckoAppShell.unregisterGeckoEventListener("Menu:Remove", GeckoApp.mAppContext);

View File

@ -118,6 +118,13 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
mTileLayer = new MultiTileLayer(mCairoImage, TILE_SIZE);
}
public int getWidth() {
return mBufferSize.width;
}
public int getHeight() {
return mBufferSize.height;
}
protected void finalize() throws Throwable {
try {
@ -274,13 +281,19 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
if (mBuffer == null || mBufferSize.width <= 0 || mBufferSize.height <= 0)
return null;
try {
Bitmap b = Bitmap.createBitmap(mBufferSize.width, mBufferSize.height,
CairoUtils.cairoFormatTobitmapConfig(mFormat));
Bitmap b = null;
if (mTileLayer instanceof MultiTileLayer)
if (mTileLayer instanceof MultiTileLayer) {
b = Bitmap.createBitmap(mBufferSize.width, mBufferSize.height,
CairoUtils.cairoFormatTobitmapConfig(mFormat));
copyPixelsFromMultiTileLayer(b);
else
} else if (mTileLayer instanceof SingleTileLayer) {
b = Bitmap.createBitmap(mBufferSize.width, mBufferSize.height,
CairoUtils.cairoFormatTobitmapConfig(mFormat));
b.copyPixelsFromBuffer(mBuffer.asIntBuffer());
} else {
Log.w(LOGTAG, "getBitmap() called on a layer (" + mTileLayer + ") we don't know how to get a bitmap from");
}
return b;
} catch (OutOfMemoryError oom) {

View File

@ -208,6 +208,7 @@ var BrowserApp = {
Services.obs.addObserver(this, "Tab:Load", false);
Services.obs.addObserver(this, "Tab:Select", false);
Services.obs.addObserver(this, "Tab:Close", false);
Services.obs.addObserver(this, "Tab:Screenshot", false);
Services.obs.addObserver(this, "Session:Back", false);
Services.obs.addObserver(this, "Session:Forward", false);
Services.obs.addObserver(this, "Session:Reload", false);
@ -470,6 +471,14 @@ var BrowserApp = {
this._tabs.splice(this._tabs.indexOf(aTab), 1);
},
screenshotTab: function screenshotTab(aData) {
let json = JSON.parse(aData);
let tab = this.getTabForId(parseInt(json.tabID));
let width = parseInt(json.width);
let height = parseInt(json.height);
tab.screenshot(width, height);
},
selectTab: function selectTab(aTab) {
if (aTab != null) {
this.selectedTab = aTab;
@ -823,6 +832,8 @@ var BrowserApp = {
this.selectTab(this.getTabForId(parseInt(aData)));
} else if (aTopic == "Tab:Close") {
this.closeTab(this.getTabForId(parseInt(aData)));
} else if (aTopic == "Tab:Screenshot") {
this.screenshotTab(aData);
} else if (aTopic == "Browser:Quit") {
this.quit();
} else if (aTopic == "SaveAs:PDF") {
@ -1467,6 +1478,26 @@ Tab.prototype = {
this.updateTransform();
},
screenshot: function(aWidth, aHeight) {
if (!this.browser || !this.browser.contentWindow)
return;
let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
canvas.setAttribute("width", aWidth);
canvas.setAttribute("height", aHeight);
let ctx = canvas.getContext("2d");
ctx.drawWindow(this.browser.contentWindow, 0, 0, aWidth, aHeight, "rgb(255, 255, 255)");
let message = {
gecko: {
type: "Tab:ScreenshotData",
tabID: this.id,
width: aWidth,
height: aHeight,
data: canvas.toDataURL()
}
};
sendMessageToJava(message);
},
updateTransform: function() {
let hasZoom = (Math.abs(this._viewport.zoom - 1.0) >= 1e-6);
let x = this._viewport.offsetX + Math.round(-this.viewportExcess.x * this._viewport.zoom);