diff --git a/mobile/android/base/GeckoApp.java b/mobile/android/base/GeckoApp.java index 01438b7323c..fd1211e8e44 100644 --- a/mobile/android/base/GeckoApp.java +++ b/mobile/android/base/GeckoApp.java @@ -554,6 +554,11 @@ abstract public class GeckoApp boolean isSelectedTab = Tabs.getInstance().isSelectedTab(tab); final Bitmap bitmap = isSelectedTab ? mLayerClient.getBitmap() : null; + if ("about:home".equals(tab.getURL())) { + tab.updateThumbnail(null); + return; + } + if (bitmap != null) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 0, bos); @@ -566,11 +571,9 @@ abstract public class GeckoApp return; } - int sw = tab.getMinScreenshotWidth(); - int sh = tab.getMinScreenshotHeight(); int dw = tab.getThumbnailWidth(); int dh = tab.getThumbnailHeight(); - GeckoAppShell.sendEventToGecko(GeckoEvent.createScreenshotEvent(tab.getId(), 0, 0, sw, sh, 0, 0, dw, dh, GeckoAppShell.SCREENSHOT_THUMBNAIL)); + GeckoAppShell.sendEventToGecko(GeckoEvent.createScreenshotEvent(tab.getId(), 0, 0, 0, 0, 0, 0, dw, dh, GeckoAppShell.SCREENSHOT_THUMBNAIL)); } } @@ -583,10 +586,6 @@ abstract public class GeckoApp } } - if ("about:home".equals(thumbnailTab.getURL())) { - thumbnailTab.updateThumbnail(null); - return; - } try { if (bitmap == null) bitmap = BitmapFactory.decodeByteArray(compressed, 0, compressed.length); diff --git a/mobile/android/base/Tab.java b/mobile/android/base/Tab.java index 38d4a84d828..531ad8bff65 100644 --- a/mobile/android/base/Tab.java +++ b/mobile/android/base/Tab.java @@ -67,10 +67,7 @@ public final class Tab { private static final int kThumbnailWidth = 136; private static final int kThumbnailHeight = 78; - private static float sMinDim = 0; - private static float sDensity = 1; - private static int sMinScreenshotWidth = 0; - private static int sMinScreenshotHeight = 0; + private static float sDensity = 0.0f; private static Pattern sColorPattern; private int mId; private String mUrl; @@ -178,37 +175,15 @@ public final class Tab { return mThumbnail; } - void initMetrics() { - DisplayMetrics metrics = new DisplayMetrics(); - GeckoApp.mAppContext.getWindowManager().getDefaultDisplay().getMetrics(metrics); - sMinDim = Math.min(metrics.widthPixels / kThumbnailWidth, metrics.heightPixels / kThumbnailHeight); - sDensity = metrics.density; - } - - float getMinDim() { - if (sMinDim == 0) - initMetrics(); - return sMinDim; - } - float getDensity() { - if (sDensity == 0.0f) - initMetrics(); + if (sDensity == 0.0f) { + DisplayMetrics metrics = new DisplayMetrics(); + GeckoApp.mAppContext.getWindowManager().getDefaultDisplay().getMetrics(metrics); + sDensity = metrics.density; + } return sDensity; } - int getMinScreenshotWidth() { - if (sMinScreenshotWidth != 0) - return sMinScreenshotWidth; - return sMinScreenshotWidth = (int)(getMinDim() * kThumbnailWidth); - } - - int getMinScreenshotHeight() { - if (sMinScreenshotHeight != 0) - return sMinScreenshotHeight; - return sMinScreenshotHeight = (int)(getMinDim() * kThumbnailHeight); - } - int getThumbnailWidth() { return (int)(kThumbnailWidth * getDensity()); } @@ -223,32 +198,13 @@ public final class Tab { public void run() { if (b != null) { try { - Bitmap cropped = null; - /* Crop to screen width if the bitmap is larger than the screen width or height. If smaller and the - * the aspect ratio is correct, just use the bitmap as is. Otherwise, fit the smaller - * smaller dimension, then crop the larger dimention. - */ - if (getMinScreenshotWidth() < b.getWidth() && getMinScreenshotHeight() < b.getHeight()) - cropped = Bitmap.createBitmap(b, 0, 0, getMinScreenshotWidth(), getMinScreenshotHeight()); - else if (b.getWidth() * getMinScreenshotHeight() == b.getHeight() * getMinScreenshotWidth()) - cropped = b; - else if (b.getWidth() * getMinScreenshotHeight() < b.getHeight() * getMinScreenshotWidth()) - cropped = Bitmap.createBitmap(b, 0, 0, b.getWidth(), - b.getWidth() * getMinScreenshotHeight() / getMinScreenshotWidth()); - else - cropped = Bitmap.createBitmap(b, 0, 0, - b.getHeight() * getMinScreenshotWidth() / getMinScreenshotHeight(), - b.getHeight()); - - Bitmap bitmap = Bitmap.createScaledBitmap(cropped, getThumbnailWidth(), getThumbnailHeight(), false); + Bitmap bitmap = Bitmap.createScaledBitmap(b, getThumbnailWidth(), getThumbnailHeight(), false); if (mState == Tab.STATE_SUCCESS) saveThumbnailToDB(new BitmapDrawable(bitmap)); - if (!cropped.equals(b)) - b.recycle(); mThumbnail = new BitmapDrawable(bitmap); - cropped.recycle(); + b.recycle(); } catch (OutOfMemoryError oom) { Log.e(LOGTAG, "Unable to create/scale bitmap", oom); mThumbnail = null; diff --git a/widget/android/AndroidBridge.cpp b/widget/android/AndroidBridge.cpp index 287b1292bd8..462cc10e757 100644 --- a/widget/android/AndroidBridge.cpp +++ b/widget/android/AndroidBridge.cpp @@ -2395,6 +2395,42 @@ Java_org_mozilla_gecko_GeckoAppShell_allocateDirectBuffer(JNIEnv *env, jclass, j nsresult AndroidBridge::TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt32 srcY, PRInt32 srcW, PRInt32 srcH, PRInt32 dstW, PRInt32 dstH, PRInt32 tabId, float scale, PRInt32 token) { + nsresult rv; + + // take a screenshot, as wide as possible, proportional to the destination size + if (!srcW && !srcH) { + nsCOMPtr doc; + rv = window->GetDocument(getter_AddRefs(doc)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr docElement; + rv = doc->GetDocumentElement(getter_AddRefs(docElement)); + NS_ENSURE_SUCCESS(rv, rv); + + PRInt32 viewportHeight; + PRInt32 pageWidth; + PRInt32 pageHeight; + window->GetInnerHeight(&viewportHeight); + docElement->GetScrollWidth(&pageWidth); + docElement->GetScrollHeight(&pageHeight); + + // use the page or viewport dimensions, whichever is larger + PRInt32 width = pageWidth; + PRInt32 height = viewportHeight > pageHeight ? viewportHeight : pageHeight; + + if (!width || !height) + return NS_ERROR_FAILURE; + + float aspectRatio = ((float) dstW) / dstH; + if (width / aspectRatio < height) { + srcW = width; + srcH = width / aspectRatio; + } else { + srcW = height * aspectRatio; + srcH = height; + } + } + JNIEnv* env = GetJNIEnv(); if (!env) return NS_OK; @@ -2432,7 +2468,7 @@ nsresult AndroidBridge::TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt nsRefPtr surf = new gfxImageSurface(static_cast(data), nsIntSize(dstW, dstH), stride, gfxASurface::ImageFormatRGB16_565); nsRefPtr context = new gfxContext(surf); context->Scale(scale * dstW / srcW, scale * dstH / srcH); - nsresult rv = presShell->RenderDocument(r, renderDocFlags, bgColor, context); + 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); return NS_OK; diff --git a/widget/android/nsAppShell.cpp b/widget/android/nsAppShell.cpp index 5bbdb62b107..f4e934c3bf8 100644 --- a/widget/android/nsAppShell.cpp +++ b/widget/android/nsAppShell.cpp @@ -470,11 +470,6 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait) break; float scale = 1.0; - if (token == AndroidBridge::SCREENSHOT_THUMBNAIL) { - if (NS_FAILED(tab->GetScale(&scale))) - break; - } - nsTArray points = curEvent->Points(); NS_ASSERTION(points.Length() == 4, "Screenshot event does not have enough coordinates"); bridge->TakeScreenshot(domWindow, points[0].x, points[0].y, points[1].x, points[1].y, points[3].x, points[3].y, curEvent->MetaState(), scale, curEvent->Flags());