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
Родитель 49f7583105
Коммит cd90c75d3b
8 изменённых файлов: 81 добавлений и 29 удалений

Просмотреть файл

@ -603,6 +603,11 @@ public class GeckoAppShell
imm, text, start, end, newEnd);
}
public static void notifyScreenShot(ByteBuffer data, int tabId, int width, int height) {
// this stub is never called in XUL Fennec, but we need it so that the JNI code
// shared between XUL and Native Fennec doesn't die.
}
private static CountDownLatch sGeckoPendingAcks = null;
// Block the current thread until the Gecko event loop is caught up

Просмотреть файл

@ -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;

Просмотреть файл

@ -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

Просмотреть файл

@ -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")) {

Просмотреть файл

@ -1615,24 +1615,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);

Просмотреть файл

@ -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);
}

Просмотреть файл

@ -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;

Просмотреть файл

@ -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);
};