diff --git a/mobile/android/base/GeckoApp.java b/mobile/android/base/GeckoApp.java index e910c250820..034a10ba857 100644 --- a/mobile/android/base/GeckoApp.java +++ b/mobile/android/base/GeckoApp.java @@ -738,7 +738,7 @@ abstract public class GeckoApp int dw = tab.getThumbnailWidth(); int dh = tab.getThumbnailHeight(); - GeckoAppShell.sendEventToGecko(GeckoEvent.createScreenshotEvent(tab.getId(), 0, 0, 0, 0, 0, 0, dw, dh, GeckoAppShell.SCREENSHOT_THUMBNAIL)); + GeckoAppShell.sendEventToGecko(GeckoEvent.createScreenshotEvent(tab.getId(), 0, 0, 0, 0, 0, 0, dw, dh, dw, dh, GeckoAppShell.SCREENSHOT_THUMBNAIL, tab.getThumbnailBuffer())); } } diff --git a/mobile/android/base/GeckoAppShell.java b/mobile/android/base/GeckoAppShell.java index 3867e4ab3b6..8f2e9c3116e 100644 --- a/mobile/android/base/GeckoAppShell.java +++ b/mobile/android/base/GeckoAppShell.java @@ -15,6 +15,7 @@ import org.mozilla.gecko.gfx.ScreenshotLayer; import org.mozilla.gecko.FloatUtils; import org.mozilla.gecko.gfx.ImmutableViewportMetrics; import org.mozilla.gecko.gfx.ViewportMetrics; +import org.mozilla.gecko.gfx.RectUtils; import java.io.*; import java.lang.reflect.*; @@ -2109,9 +2110,11 @@ class ScreenshotHandler { private static RectF sCheckerboardPageRect; private static float sLastCheckerboardWidthRatio, sLastCheckerboardHeightRatio; private static RepaintRunnable sRepaintRunnable = new RepaintRunnable(); - static private int sMaxTextureSize = 0; - static final String LOGTAG = "GeckoScreenshot"; + private static int sMaxTextureSize = 0; + private static final String LOGTAG = "GeckoScreenshot"; private static boolean sDisableScreenshot = false; + private static ByteBuffer sWholePageScreenshotBuffer; + private static int sCheckerboardBufferWidth, sCheckerboardBufferHeight; static class RepaintRunnable implements Runnable { private boolean mIsRepaintRunnablePosted = false; @@ -2134,16 +2137,36 @@ class ScreenshotHandler { mIsRepaintRunnablePosted = false; } + Tab tab = Tabs.getInstance().getSelectedTab(); - GeckoAppShell.screenshotWholePage(tab); + ImmutableViewportMetrics viewport = GeckoApp.mAppContext.getLayerController().getViewportMetrics(); + + if (RectUtils.fuzzyEquals(sCheckerboardPageRect, viewport.getCssPageRect())) { + float width = right - left; + float height = bottom - top; + GeckoEvent event = GeckoEvent. + createScreenshotEvent(tab.getId(), + (int)left, (int)top, (int)width, (int)height, + (int)(sLastCheckerboardWidthRatio * left), + (int)(sLastCheckerboardHeightRatio * top), + (int)(sLastCheckerboardWidthRatio * width), + (int)(sLastCheckerboardHeightRatio * height), + sCheckerboardBufferWidth, sCheckerboardBufferHeight, + GeckoAppShell.SCREENSHOT_UPDATE, + sWholePageScreenshotBuffer); + GeckoAppShell.sendEventToGecko(event); + } else { + GeckoAppShell.screenshotWholePage(tab); + } } void addRectToRepaint(float top, float left, float bottom, float right) { synchronized(this) { - mDirtyTop = Math.min(top, mDirtyTop); - mDirtyLeft = Math.min(left, mDirtyLeft); - mDirtyBottom = Math.max(bottom, mDirtyBottom); - mDirtyRight = Math.max(right, mDirtyRight); + ImmutableViewportMetrics viewport = GeckoApp.mAppContext.getLayerController().getViewportMetrics(); + mDirtyTop = Math.max(sCheckerboardPageRect.top, Math.min(top, mDirtyTop)); + mDirtyLeft = Math.max(sCheckerboardPageRect.left, Math.min(left, mDirtyLeft)); + mDirtyBottom = Math.min(sCheckerboardPageRect.bottom, Math.max(bottom, mDirtyBottom)); + mDirtyRight = Math.min(sCheckerboardPageRect.right, Math.max(right, mDirtyRight)); if (!mIsRepaintRunnablePosted) { GeckoAppShell.getHandler().postDelayed(this, 5000); mIsRepaintRunnablePosted = true; @@ -2178,6 +2201,7 @@ class ScreenshotHandler { sMaxTextureSize = maxTextureSize[0]; if (sMaxTextureSize == 0) return; + sWholePageScreenshotBuffer = GeckoAppShell.allocateDirectBuffer(ScreenshotLayer.getMaxNumPixels() * 2 /* 16 bpp */); } ImmutableViewportMetrics viewport = GeckoApp.mAppContext.getLayerController().getViewportMetrics(); @@ -2200,6 +2224,8 @@ class ScreenshotHandler { int dy = 0; int dw = clamp(minTextureSize, idealDstWidth, sMaxTextureSize); int dh = maxPixels / dw; + sCheckerboardBufferWidth = dw; + sCheckerboardBufferHeight = dh; sLastCheckerboardWidthRatio = dw / sw; sLastCheckerboardHeightRatio = dh / sh; @@ -2214,7 +2240,7 @@ class ScreenshotHandler { GeckoAppShell.sendEventToGecko(GeckoEvent.createScreenshotEvent(tab.getId(), (int)FloatMath.ceil(sx), (int)FloatMath.ceil(sy), (int)FloatMath.floor(sw), (int)FloatMath.floor(sh), - dx, dy, dw, dh, GeckoAppShell.SCREENSHOT_WHOLE_PAGE)); + dx, dy, dw, dh, dw, dh, GeckoAppShell.SCREENSHOT_WHOLE_PAGE, sWholePageScreenshotBuffer)); } static class PendingScreenshot { @@ -2246,37 +2272,29 @@ class ScreenshotHandler { GeckoAppShell.getHandler().post(new Runnable() { public void run() { - try { - final Tab tab = Tabs.getInstance().getTab(tabId); - if (tab == null) - return; + final Tab tab = Tabs.getInstance().getTab(tabId); + if (tab == null) + return; - if (!Tabs.getInstance().isSelectedTab(tab) && GeckoAppShell.SCREENSHOT_THUMBNAIL != token) - return; + if (!Tabs.getInstance().isSelectedTab(tab) && GeckoAppShell.SCREENSHOT_THUMBNAIL != token) + return; - Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); - b.copyPixelsFromBuffer(data); - switch (token) { + switch (token) { + case GeckoAppShell.SCREENSHOT_UPDATE: case GeckoAppShell.SCREENSHOT_WHOLE_PAGE: + { GeckoApp.mAppContext.getLayerController() .getView().getRenderer() - .setCheckerboardBitmap(b, sCheckerboardPageRect); - break; - case GeckoAppShell.SCREENSHOT_UPDATE: - GeckoApp.mAppContext.getLayerController().getView().getRenderer(). - updateCheckerboardBitmap( - b, sLastCheckerboardWidthRatio * x, - sLastCheckerboardHeightRatio * y, - sLastCheckerboardWidthRatio * width, - sLastCheckerboardHeightRatio * height, - sCheckerboardPageRect); + .setCheckerboardBitmap(data, width, height, sCheckerboardPageRect); break; + } case GeckoAppShell.SCREENSHOT_THUMBNAIL: + { + Bitmap b = tab.getThumbnailBitmap(); + b.copyPixelsFromBuffer(data); GeckoApp.mAppContext.processThumbnail(tab, b, null); break; } - } finally { - GeckoAppShell.freeDirectBuffer(data); } } }); diff --git a/mobile/android/base/GeckoEvent.java b/mobile/android/base/GeckoEvent.java index f9682507715..1b01bd7fcd0 100644 --- a/mobile/android/base/GeckoEvent.java +++ b/mobile/android/base/GeckoEvent.java @@ -23,6 +23,7 @@ import android.text.format.Time; import android.os.SystemClock; import java.lang.Math; import java.lang.System; +import java.nio.ByteBuffer; import android.util.Log; @@ -116,6 +117,8 @@ public class GeckoEvent { public short mScreenOrientation; + public ByteBuffer mBuffer; + private GeckoEvent(int evType) { mType = evType; } @@ -456,15 +459,17 @@ public class GeckoEvent { return event; } - public static GeckoEvent createScreenshotEvent(int tabId, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int token) { + public static GeckoEvent createScreenshotEvent(int tabId, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int bw, int bh, int token, ByteBuffer buffer) { GeckoEvent event = new GeckoEvent(SCREENSHOT); - event.mPoints = new Point[4]; + event.mPoints = new Point[5]; event.mPoints[0] = new Point(sx, sy); event.mPoints[1] = new Point(sw, sh); event.mPoints[2] = new Point(dx, dy); event.mPoints[3] = new Point(dw, dh); + event.mPoints[4] = new Point(bw, bh); event.mMetaState = tabId; event.mFlags = token; + event.mBuffer = buffer; return event; } diff --git a/mobile/android/base/Tab.java b/mobile/android/base/Tab.java index e7737c4ef76..6b8d4491000 100644 --- a/mobile/android/base/Tab.java +++ b/mobile/android/base/Tab.java @@ -21,6 +21,7 @@ import org.json.JSONObject; import org.mozilla.gecko.db.BrowserDB; import org.mozilla.gecko.gfx.Layer; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -65,6 +66,8 @@ public final class Tab { private ContentObserver mContentObserver; private int mCheckerboardColor = Color.WHITE; private int mState; + private ByteBuffer mThumbnailBuffer; + private Bitmap mThumbnailBitmap; public static final int STATE_DELAYED = 0; public static final int STATE_LOADING = 1; @@ -140,6 +143,31 @@ public final class Tab { return mThumbnail; } + synchronized public ByteBuffer getThumbnailBuffer() { + int capacity = getThumbnailWidth() * getThumbnailHeight() * 2 /* 16 bpp */; + if (mThumbnailBuffer != null && mThumbnailBuffer.capacity() == capacity) + return mThumbnailBuffer; + if (mThumbnailBuffer != null) + GeckoAppShell.freeDirectBuffer(mThumbnailBuffer); // not calling freeBuffer() because it would deadlock + return mThumbnailBuffer = GeckoAppShell.allocateDirectBuffer(capacity); + } + + public Bitmap getThumbnailBitmap() { + if (mThumbnailBitmap != null) + return mThumbnailBitmap; + return mThumbnailBitmap = Bitmap.createBitmap(getThumbnailWidth(), getThumbnailHeight(), Bitmap.Config.RGB_565); + } + + public void finalize() { + freeBuffer(); + } + + synchronized void freeBuffer() { + if (mThumbnailBuffer != null) + GeckoAppShell.freeDirectBuffer(mThumbnailBuffer); + mThumbnailBuffer = null; + } + float getDensity() { if (sDensity == 0.0f) { sDensity = GeckoApp.mAppContext.getDisplayMetrics().density; @@ -161,13 +189,10 @@ public final class Tab { public void run() { if (b != null) { try { - Bitmap bitmap = Bitmap.createScaledBitmap(b, getThumbnailWidth(), getThumbnailHeight(), false); - if (mState == Tab.STATE_SUCCESS) - saveThumbnailToDB(new BitmapDrawable(bitmap)); + saveThumbnailToDB(new BitmapDrawable(b)); - mThumbnail = new BitmapDrawable(bitmap); - b.recycle(); + mThumbnail = new BitmapDrawable(b); } catch (OutOfMemoryError oom) { Log.e(LOGTAG, "Unable to create/scale bitmap", oom); mThumbnail = null; diff --git a/mobile/android/base/Tabs.java b/mobile/android/base/Tabs.java index c688a76d7be..e8123d51332 100644 --- a/mobile/android/base/Tabs.java +++ b/mobile/android/base/Tabs.java @@ -76,8 +76,10 @@ public class Tabs implements GeckoEventListener { public void removeTab(int id) { if (tabs.containsKey(id)) { - order.remove(getTab(id)); + Tab tab = getTab(id); + order.remove(tab); tabs.remove(id); + tab.freeBuffer(); Log.i(LOGTAG, "Removed a tab with id: " + id); } } diff --git a/mobile/android/base/gfx/IntSize.java b/mobile/android/base/gfx/IntSize.java index 8560ca23e91..dfc59488533 100644 --- a/mobile/android/base/gfx/IntSize.java +++ b/mobile/android/base/gfx/IntSize.java @@ -71,5 +71,11 @@ public class IntSize { public IntSize nextPowerOfTwo() { return new IntSize(nextPowerOfTwo(width), nextPowerOfTwo(height)); } + + public static boolean isPowerOfTwo(int value) { + if (value == 0) + return false; + return (value & (value - 1)) == 0; + } } diff --git a/mobile/android/base/gfx/LayerRenderer.java b/mobile/android/base/gfx/LayerRenderer.java index be5bbc38899..e896c283aa4 100644 --- a/mobile/android/base/gfx/LayerRenderer.java +++ b/mobile/android/base/gfx/LayerRenderer.java @@ -134,8 +134,8 @@ public class LayerRenderer { " gl_FragColor = texture2D(sTexture, vTexCoord);\n" + "}\n"; - public void setCheckerboardBitmap(Bitmap bitmap, RectF pageRect) { - mCheckerboardLayer.setBitmap(bitmap); + public void setCheckerboardBitmap(ByteBuffer data, int width, int height, RectF pageRect) { + mCheckerboardLayer.setBitmap(data, width, height); mCheckerboardLayer.beginTransaction(); try { mCheckerboardLayer.setPosition(RectUtils.round(pageRect)); diff --git a/mobile/android/base/gfx/ScreenshotLayer.java b/mobile/android/base/gfx/ScreenshotLayer.java index 355cea78560..1a3ed9fc7b6 100644 --- a/mobile/android/base/gfx/ScreenshotLayer.java +++ b/mobile/android/base/gfx/ScreenshotLayer.java @@ -35,6 +35,7 @@ public class ScreenshotLayer extends SingleTileLayer { private IntSize mImageSize; // Whether we have an up-to-date image to draw private boolean mHasImage; + private static String LOGTAG = "GeckoScreenshot"; public static int getMaxNumPixels() { return SCREENSHOT_SIZE_LIMIT; @@ -44,6 +45,19 @@ public class ScreenshotLayer extends SingleTileLayer { mHasImage = false; } + void setBitmap(ByteBuffer data, int width, int height) { + mImageSize = new IntSize(width, height); + if (IntSize.isPowerOfTwo(width) && IntSize.isPowerOfTwo(height)) { + mBufferSize = mImageSize; + mHasImage = true; + mImage.setBitmap(data, width, height, CairoImage.FORMAT_RGB16_565); + } else { + Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); + b.copyPixelsFromBuffer(data); + setBitmap(b); + } + } + void setBitmap(Bitmap bitmap) { mImageSize = new IntSize(bitmap.getWidth(), bitmap.getHeight()); int width = IntSize.nextPowerOfTwo(bitmap.getWidth()); @@ -116,7 +130,17 @@ public class ScreenshotLayer extends SingleTileLayer { } } - void setBitmap(Bitmap bitmap, int width, int height, int format) { + void copyBuffer(ByteBuffer src, ByteBuffer dst, int size) { + dst.asIntBuffer().put(src.asIntBuffer()); + } + + synchronized void setBitmap(ByteBuffer data, int width, int height, int format) { + mSize = new IntSize(width, height); + mFormat = format; + copyBuffer(data, mBuffer, width * height * 2); + } + + synchronized void setBitmap(Bitmap bitmap, int width, int height, int format) { Bitmap tmp; mSize = new IntSize(width, height); mFormat = format; @@ -138,10 +162,10 @@ public class ScreenshotLayer extends SingleTileLayer { } @Override - public ByteBuffer getBuffer() { return mBuffer; } + synchronized public ByteBuffer getBuffer() { return mBuffer; } @Override - public IntSize getSize() { return mSize; } + synchronized public IntSize getSize() { return mSize; } @Override - public int getFormat() { return mFormat; } + synchronized public int getFormat() { return mFormat; } } } diff --git a/widget/android/AndroidBridge.cpp b/widget/android/AndroidBridge.cpp index c735c313e1b..d13a14d5da8 100644 --- a/widget/android/AndroidBridge.cpp +++ b/widget/android/AndroidBridge.cpp @@ -2350,9 +2350,13 @@ jobject JNICALL Java_org_mozilla_gecko_GeckoAppShell_allocateDirectBuffer(JNIEnv *env, jclass, jlong size); -nsresult AndroidBridge::TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt32 srcY, PRInt32 srcW, PRInt32 srcH, PRInt32 dstW, PRInt32 dstH, PRInt32 tabId, float scale, PRInt32 token) +nsresult AndroidBridge::TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt32 srcY, PRInt32 srcW, PRInt32 srcH, PRInt32 dstX, PRInt32 dstY, PRInt32 dstW, PRInt32 dstH, PRInt32 bufW, PRInt32 bufH, PRInt32 tabId, PRInt32 token, jobject buffer) { nsresult rv; + float scale = 1.0; + + if (!buffer) + return NS_OK; // take a screenshot, as wide as possible, proportional to the destination size if (!srcW && !srcH) { @@ -2413,21 +2417,17 @@ nsresult AndroidBridge::TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt nsPresContext::CSSPixelsToAppUnits(srcW / scale), nsPresContext::CSSPixelsToAppUnits(srcH / scale)); - PRUint32 stride = dstW * 2; - PRUint32 bufferSize = dstH * stride; - - jobject buffer = Java_org_mozilla_gecko_GeckoAppShell_allocateDirectBuffer(env, NULL, bufferSize); - if (!buffer) - return NS_OK; + PRUint32 stride = bufW * 2 /* 16 bpp */; void* data = env->GetDirectBufferAddress(buffer); - memset(data, 0, bufferSize); - nsRefPtr surf = new gfxImageSurface(static_cast(data), nsIntSize(dstW, dstH), stride, gfxASurface::ImageFormatRGB16_565); + nsRefPtr surf = new gfxImageSurface(static_cast(data), nsIntSize(bufW, bufH), stride, gfxASurface::ImageFormatRGB16_565); nsRefPtr context = new gfxContext(surf); + gfxPoint pt(dstX, dstY); + context->Translate(pt); context->Scale(scale * dstW / srcW, scale * dstH / srcH); rv = presShell->RenderDocument(r, renderDocFlags, bgColor, context); NS_ENSURE_SUCCESS(rv, rv); - env->CallStaticVoidMethod(AndroidBridge::Bridge()->mGeckoAppShellClass, AndroidBridge::Bridge()->jNotifyScreenShot, buffer, tabId, srcX * dstW / srcW , srcY * dstH / srcH, dstW, dstH, token); + env->CallStaticVoidMethod(AndroidBridge::Bridge()->mGeckoAppShellClass, AndroidBridge::Bridge()->jNotifyScreenShot, buffer, tabId, srcX * dstW / srcW , srcY * dstH / srcH, bufW, bufH, token); return NS_OK; } diff --git a/widget/android/AndroidBridge.h b/widget/android/AndroidBridge.h index 5f3f383bfb0..6917cb7300a 100644 --- a/widget/android/AndroidBridge.h +++ b/widget/android/AndroidBridge.h @@ -155,7 +155,7 @@ public: SCREENSHOT_UPDATE = 2 }; - nsresult TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt32 srcY, PRInt32 srcW, PRInt32 srcH, PRInt32 dstW, PRInt32 dstH, PRInt32 tabId, float scale, PRInt32 token); + nsresult TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt32 srcY, PRInt32 srcW, PRInt32 srcH, PRInt32 dstY, PRInt32 dstX, PRInt32 dstW, PRInt32 dstH, PRInt32 bufW, PRInt32 bufH, PRInt32 tabId, PRInt32 token, jobject buffer); static void NotifyPaintedRect(float top, float left, float bottom, float right); diff --git a/widget/android/AndroidJavaWrappers.cpp b/widget/android/AndroidJavaWrappers.cpp index 92335267620..698de5f4127 100644 --- a/widget/android/AndroidJavaWrappers.cpp +++ b/widget/android/AndroidJavaWrappers.cpp @@ -42,6 +42,7 @@ jfieldID AndroidGeckoEvent::jLocationField = 0; jfieldID AndroidGeckoEvent::jBandwidthField = 0; jfieldID AndroidGeckoEvent::jCanBeMeteredField = 0; jfieldID AndroidGeckoEvent::jScreenOrientationField = 0; +jfieldID AndroidGeckoEvent::jByteBufferField = 0; jclass AndroidPoint::jPointClass = 0; jfieldID AndroidPoint::jXField = 0; @@ -103,6 +104,12 @@ jmethodID AndroidGeckoSurfaceView::jGetHolderMethod = 0; #define getMethod(fname, ftype) \ ((jmethodID) jEnv->GetMethodID(jClass, fname, ftype)) +RefCountedJavaObject::~RefCountedJavaObject() { + if (mObject) + GetJNIForThread()->DeleteGlobalRef(mObject); + mObject = NULL; +} + void mozilla::InitAndroidJavaWrappers(JNIEnv *jEnv) { @@ -154,6 +161,7 @@ AndroidGeckoEvent::InitGeckoEventClass(JNIEnv *jEnv) jBandwidthField = getField("mBandwidth", "D"); jCanBeMeteredField = getField("mCanBeMetered", "Z"); jScreenOrientationField = getField("mScreenOrientation", "S"); + jByteBufferField = getField("mBuffer", "Ljava/nio/ByteBuffer;"); } void @@ -498,7 +506,8 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj) case SCREENSHOT: { mMetaState = jenv->GetIntField(jobj, jMetaStateField); mFlags = jenv->GetIntField(jobj, jFlagsField); - ReadPointArray(mPoints, jenv, jPoints, 4); + ReadPointArray(mPoints, jenv, jPoints, 5); + mByteBuffer = new RefCountedJavaObject(jenv, jenv->GetObjectField(jobj, jByteBufferField)); break; } diff --git a/widget/android/AndroidJavaWrappers.h b/widget/android/AndroidJavaWrappers.h index a152adad420..9efa1049e31 100644 --- a/widget/android/AndroidJavaWrappers.h +++ b/widget/android/AndroidJavaWrappers.h @@ -41,6 +41,27 @@ void InitAndroidJavaWrappers(JNIEnv *jEnv); * handle it. */ +class RefCountedJavaObject { +public: + RefCountedJavaObject(JNIEnv* env, jobject obj) : mObject(env->NewGlobalRef(obj)) {} + + ~RefCountedJavaObject(); + + PRInt32 AddRef() { return ++mRefCnt; } + + PRInt32 Release() { + PRInt32 refcnt = --mRefCnt; + if (refcnt == 0) + delete this; + return refcnt; + } + + jobject GetObject() { return mObject; } +private: + PRInt32 mRefCnt; + jobject mObject; +}; + class WrappedJavaObject { public: WrappedJavaObject() : @@ -576,6 +597,7 @@ public: double Bandwidth() { return mBandwidth; } bool CanBeMetered() { return mCanBeMetered; } short ScreenOrientation() { return mScreenOrientation; } + RefCountedJavaObject* ByteBuffer() { return mByteBuffer; } protected: int mAction; @@ -600,6 +622,7 @@ protected: double mBandwidth; bool mCanBeMetered; short mScreenOrientation; + nsRefPtr mByteBuffer; void ReadIntArray(nsTArray &aVals, JNIEnv *jenv, @@ -653,6 +676,7 @@ protected: static jfieldID jCanBeMeteredField; static jfieldID jScreenOrientationField; + static jfieldID jByteBufferField; public: enum { diff --git a/widget/android/nsAppShell.cpp b/widget/android/nsAppShell.cpp index ab44320379a..ef7a5f5cff4 100644 --- a/widget/android/nsAppShell.cpp +++ b/widget/android/nsAppShell.cpp @@ -67,8 +67,8 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsAppShell, nsBaseAppShell, nsIObserver) class ScreenshotRunnable : public nsRunnable { public: - ScreenshotRunnable(nsIAndroidBrowserApp* aBrowserApp, int aTabId, nsTArray& aPoints, int aToken): - mBrowserApp(aBrowserApp), mTabId(aTabId), mPoints(aPoints), mToken(aToken) {} + ScreenshotRunnable(nsIAndroidBrowserApp* aBrowserApp, int aTabId, nsTArray& aPoints, int aToken, RefCountedJavaObject* aBuffer): + mBrowserApp(aBrowserApp), mTabId(aTabId), mPoints(aPoints), mToken(aToken), mBuffer(aBuffer) {} virtual nsresult Run() { nsCOMPtr domWindow; @@ -81,16 +81,16 @@ public: if (!domWindow) return NS_OK; - float scale = 1.0; - NS_ASSERTION(mPoints.Length() == 4, "Screenshot event does not have enough coordinates"); + NS_ASSERTION(mPoints.Length() == 5, "Screenshot event does not have enough coordinates"); - AndroidBridge::Bridge()->TakeScreenshot(domWindow, mPoints[0].x, mPoints[0].y, mPoints[1].x, mPoints[1].y, mPoints[3].x, mPoints[3].y, mTabId, scale, mToken); + AndroidBridge::Bridge()->TakeScreenshot(domWindow, mPoints[0].x, mPoints[0].y, mPoints[1].x, mPoints[1].y, mPoints[2].x, mPoints[2].y, mPoints[3].x, mPoints[3].y, mPoints[4].x, mPoints[4].y, mTabId, mToken, mBuffer->GetObject()); return NS_OK; } private: nsCOMPtr mBrowserApp; nsTArray mPoints; int mTabId, mToken; + nsRefPtr mBuffer; }; class AfterPaintListener : public nsIDOMEventListener { @@ -119,23 +119,15 @@ class AfterPaintListener : public nsIDOMEventListener { if (!paintEvent) return NS_OK; - nsCOMPtr rects; - paintEvent->GetClientRects(getter_AddRefs(rects)); - if (!rects) - return NS_OK; - PRUint32 length; - rects->GetLength(&length); - for (PRUint32 i = 0; i < length; ++i) { - float top, left, bottom, right; - nsCOMPtr rect = rects->GetItemAt(i); - if (!rect) - continue; - rect->GetTop(&top); - rect->GetLeft(&left); - rect->GetRight(&right); - rect->GetBottom(&bottom); - AndroidBridge::NotifyPaintedRect(top, left, bottom, right); - } + nsCOMPtr rect; + paintEvent->GetBoundingClientRect(getter_AddRefs(rect)); + float top, left, bottom, right; + rect->GetTop(&top); + rect->GetLeft(&left); + rect->GetRight(&right); + rect->GetBottom(&bottom); + __android_log_print(ANDROID_LOG_INFO, "GeckoScreenshot", "rect: %f, %f, %f, %f", top, left, right, bottom); + AndroidBridge::NotifyPaintedRect(top, left, bottom, right); return NS_OK; } @@ -457,8 +449,9 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait) PRInt32 token = curEvent->Flags(); PRInt32 tabId = curEvent->MetaState(); nsTArray points = curEvent->Points(); + RefCountedJavaObject* buffer = curEvent->ByteBuffer(); nsCOMPtr sr = - new ScreenshotRunnable(mBrowserApp, tabId, points, token); + new ScreenshotRunnable(mBrowserApp, tabId, points, token, buffer); MessageLoop::current()->PostIdleTask( FROM_HERE, NewRunnableMethod(sr.get(), &ScreenshotRunnable::Run)); break;