Bug 724210 - Stop using canvas to take screenshots. r=kats

This commit is contained in:
Brad Lassey 2012-02-04 01:48:26 -05:00
parent 39b5ea6269
commit f9149ad377
7 changed files with 76 additions and 29 deletions

View File

@ -622,8 +622,8 @@ abstract public class GeckoApp
message.put("source", source);
JSONObject destination = new JSONObject();
source.put("width", dw);
source.put("height", dh);
destination.put("width", dw);
destination.put("height", dh);
message.put("destination", destination);
String json = message.toString();
@ -635,8 +635,14 @@ abstract public class GeckoApp
}
void processThumbnail(Tab thumbnailTab, Bitmap bitmap, byte[] compressed) {
if (Tabs.getInstance().isSelectedTab(thumbnailTab))
if (Tabs.getInstance().isSelectedTab(thumbnailTab)) {
if (compressed == null) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 0, bos);
compressed = bos.toByteArray();
}
mLastScreen = compressed;
}
if (thumbnailTab.getURL().equals("about:home")) {
thumbnailTab.updateThumbnail(null);
return;

View File

@ -558,6 +558,17 @@ public class GeckoAppShell
mInputConnection.notifyIMEChange(text, start, end, newEnd);
}
public static void notifyScreenShot(ByteBuffer data, int tabId, int width, int height) {
final Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
b.copyPixelsFromBuffer(data);
final Tab tab = Tabs.getInstance().getTab(tabId);
getHandler().post(new Runnable() {
public void run() {
GeckoApp.mAppContext.processThumbnail(tab, b, null);
}
});
}
private static CountDownLatch sGeckoPendingAcks = null;
// Block the current thread until the Gecko event loop is caught up

View File

@ -68,7 +68,6 @@ public class Tabs implements GeckoEventListener {
GeckoAppShell.registerGeckoEventListener("Tab:Added", this);
GeckoAppShell.registerGeckoEventListener("Tab:Close", this);
GeckoAppShell.registerGeckoEventListener("Tab:Select", this);
GeckoAppShell.registerGeckoEventListener("Tab:ScreenshotData", this);
GeckoAppShell.registerGeckoEventListener("Session:RestoreBegin", this);
GeckoAppShell.registerGeckoEventListener("Session:RestoreEnd", this);
}
@ -288,13 +287,6 @@ public class Tabs implements GeckoEventListener {
closeTab(tab);
} else if (event.equals("Tab:Select")) {
selectTab(message.getInt("tabID"));
} else if (event.equals("Tab:ScreenshotData")) {
Tab tab = getTab(message.getInt("tabID"));
String data = message.getString("data");
if (data.length() < 22)
return;
byte[] compressed = GeckoAppShell.decodeBase64(data.substring(22), GeckoAppShell.BASE64_DEFAULT);
GeckoApp.mAppContext.processThumbnail(tab, null, compressed);
} else if (event.equals("Session:RestoreBegin")) {
mRestoringSession = true;
} else if (event.equals("Session:RestoreEnd")) {

View File

@ -1601,24 +1601,7 @@ Tab.prototype = {
if (!this.browser || !this.browser.contentWindow)
return;
let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
canvas.setAttribute("width", aDst.width);
canvas.setAttribute("height", aDst.height);
canvas.setAttribute("moz-opaque", "true");
let ctx = canvas.getContext("2d");
let flags = ctx.DRAWWINDOW_DO_NOT_FLUSH;
ctx.drawWindow(this.browser.contentWindow, 0, 0, aSrc.width, aSrc.height, "#fff", flags);
let message = {
gecko: {
type: "Tab:ScreenshotData",
tabID: this.id,
width: aDst.width,
height: aDst.height,
data: canvas.toDataURL()
}
};
sendMessageToJava(message);
getBridge().takeScreenshot(this.browser.contentWindow, 0, 0, aSrc.width, aSrc.height, aDst.width, aDst.height, this.id);
Services.tm.mainThread.dispatch(function() {
BrowserApp.doNextScreenshot()
}, Ci.nsIThread.DISPATCH_NORMAL);

View File

@ -51,6 +51,11 @@
#include "nsThreadUtils.h"
#include "nsIThreadManager.h"
#include "mozilla/dom/sms/PSms.h"
#include "gfxImageSurface.h"
#include "gfxContext.h"
#include "nsPresContext.h"
#include "nsIDocShell.h"
#include "nsPIDOMWindow.h"
#ifdef DEBUG
#define ALOG_BRIDGE(args...) ALOG(args)
@ -103,6 +108,7 @@ AndroidBridge::Init(JNIEnv *jEnv,
jNotifyIME = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "notifyIME", "(II)V");
jNotifyIMEEnabled = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "notifyIMEEnabled", "(ILjava/lang/String;Ljava/lang/String;Z)V");
jNotifyIMEChange = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "notifyIMEChange", "(Ljava/lang/String;III)V");
jNotifyScreenShot = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "notifyScreenShot", "(Ljava/nio/ByteBuffer;III)V");
jAcknowledgeEventSync = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "acknowledgeEventSync", "()V");
jEnableDeviceMotion = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "enableDeviceMotion", "(Z)V");
@ -1959,3 +1965,46 @@ AndroidBridge::HideSurface(jobject surface)
env->CallStaticVoidMethod(cls, method, surface);
#endif
}
/* void takeScreenshot (in nsIDOMWindow win, in PRInt32 srcX, in PRInt32 srcY, in PRInt32 srcW, in PRInt32 srcH, in PRInt32 dstX, in PRInt32 dstY, in PRInt32 dstW, in PRInt32 dstH, in AString color); */
NS_IMETHODIMP nsAndroidBridge::TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt32 srcY, PRInt32 srcW, PRInt32 srcH, PRInt32 dstW, PRInt32 dstH, PRInt32 tabId)
{
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(window);
if (!win)
return NS_ERROR_FAILURE;
nsRefPtr<nsPresContext> presContext;
nsIDocShell* docshell = win->GetDocShell();
if (docshell) {
docshell->GetPresContext(getter_AddRefs(presContext));
}
if (!presContext)
return NS_ERROR_FAILURE;
nscolor bgColor = NS_RGB(255, 255, 255);
nsIPresShell* presShell = presContext->PresShell();
PRUint32 renderDocFlags = (nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING |
nsIPresShell::RENDER_DOCUMENT_RELATIVE);
nsRect r(nsPresContext::CSSPixelsToAppUnits(srcX),
nsPresContext::CSSPixelsToAppUnits(srcY),
nsPresContext::CSSPixelsToAppUnits(srcW),
nsPresContext::CSSPixelsToAppUnits(srcH));
nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(nsIntSize(dstW, dstH), gfxASurface::ImageFormatRGB16_565);
nsRefPtr<gfxContext> context = new gfxContext(surf);
nsresult rv = presShell->RenderDocument(r, renderDocFlags, bgColor, context);
NS_ENSURE_SUCCESS(rv, rv);
AndroidBridge::Bridge()->NotifyScreenshot(surf->Data(), surf->GetDataSize(), tabId, dstW, dstH);
return NS_OK;
}
void AndroidBridge::NotifyScreenshot(unsigned char* data, int size, int tabId, int width, int height)
{
JNIEnv* jenv = GetJNIEnv();
if (!jenv)
return;
AutoLocalJNIFrame jniFrame(jenv, 1);
jobject buffer = jenv->NewDirectByteBuffer(data, size);
if (!buffer)
return;
jenv->CallStaticVoidMethod(mGeckoAppShellClass, jNotifyScreenShot, buffer, tabId, width, height);
}

View File

@ -156,6 +156,8 @@ public:
static void NotifyIMEChange(const PRUnichar *aText, PRUint32 aTextLen, int aStart, int aEnd, int aNewEnd);
void NotifyScreenshot(unsigned char* data, int size, int tabId, int width, int height);
void AcknowledgeEventSync();
void EnableDeviceMotion(bool aEnable);
@ -420,6 +422,7 @@ protected:
jmethodID jNotifyIME;
jmethodID jNotifyIMEEnabled;
jmethodID jNotifyIMEChange;
jmethodID jNotifyScreenShot;
jmethodID jAcknowledgeEventSync;
jmethodID jEnableDeviceMotion;
jmethodID jEnableLocation;

View File

@ -1,4 +1,5 @@
#include "nsISupports.idl"
#include "nsIDOMWindow.idl"
[scriptable, uuid(38b5c83a-3e8d-45c2-8311-6e36bd5116c0)]
interface nsIAndroidDrawMetadataProvider : nsISupports {
@ -16,4 +17,6 @@ interface nsIAndroidBridge : nsISupports
{
AString handleGeckoMessage(in AString message);
void setDrawMetadataProvider(in nsIAndroidDrawMetadataProvider provider);
void takeScreenshot(in nsIDOMWindow win, in PRInt32 srcX, in PRInt32 srcY, in PRInt32 srcW, in PRInt32 srcH,
in PRInt32 dstW, in PRInt32 dstH, in PRInt32 tabId);
};