Bug 750846 - Move thumbnail size logic to Gecko. r=blassey

--HG--
extra : rebase_source : f8194c78ff0acc530db15a0aed6472475a0e0eed
This commit is contained in:
Brian Nicholson 2012-05-03 16:29:59 -07:00
parent cb33167c33
commit fe13e9cb1d
4 changed files with 55 additions and 65 deletions

View File

@ -554,6 +554,11 @@ abstract public class GeckoApp
boolean isSelectedTab = Tabs.getInstance().isSelectedTab(tab); boolean isSelectedTab = Tabs.getInstance().isSelectedTab(tab);
final Bitmap bitmap = isSelectedTab ? mLayerClient.getBitmap() : null; final Bitmap bitmap = isSelectedTab ? mLayerClient.getBitmap() : null;
if ("about:home".equals(tab.getURL())) {
tab.updateThumbnail(null);
return;
}
if (bitmap != null) { if (bitmap != null) {
ByteArrayOutputStream bos = new ByteArrayOutputStream(); ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 0, bos); bitmap.compress(Bitmap.CompressFormat.PNG, 0, bos);
@ -566,11 +571,9 @@ abstract public class GeckoApp
return; return;
} }
int sw = tab.getMinScreenshotWidth();
int sh = tab.getMinScreenshotHeight();
int dw = tab.getThumbnailWidth(); int dw = tab.getThumbnailWidth();
int dh = tab.getThumbnailHeight(); 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 { try {
if (bitmap == null) if (bitmap == null)
bitmap = BitmapFactory.decodeByteArray(compressed, 0, compressed.length); bitmap = BitmapFactory.decodeByteArray(compressed, 0, compressed.length);

View File

@ -67,10 +67,7 @@ public final class Tab {
private static final int kThumbnailWidth = 136; private static final int kThumbnailWidth = 136;
private static final int kThumbnailHeight = 78; private static final int kThumbnailHeight = 78;
private static float sMinDim = 0; private static float sDensity = 0.0f;
private static float sDensity = 1;
private static int sMinScreenshotWidth = 0;
private static int sMinScreenshotHeight = 0;
private static Pattern sColorPattern; private static Pattern sColorPattern;
private int mId; private int mId;
private String mUrl; private String mUrl;
@ -178,37 +175,15 @@ public final class Tab {
return mThumbnail; 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() { float getDensity() {
if (sDensity == 0.0f) if (sDensity == 0.0f) {
initMetrics(); DisplayMetrics metrics = new DisplayMetrics();
GeckoApp.mAppContext.getWindowManager().getDefaultDisplay().getMetrics(metrics);
sDensity = metrics.density;
}
return sDensity; 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() { int getThumbnailWidth() {
return (int)(kThumbnailWidth * getDensity()); return (int)(kThumbnailWidth * getDensity());
} }
@ -223,32 +198,13 @@ public final class Tab {
public void run() { public void run() {
if (b != null) { if (b != null) {
try { try {
Bitmap cropped = null; Bitmap bitmap = Bitmap.createScaledBitmap(b, getThumbnailWidth(), getThumbnailHeight(), false);
/* 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);
if (mState == Tab.STATE_SUCCESS) if (mState == Tab.STATE_SUCCESS)
saveThumbnailToDB(new BitmapDrawable(bitmap)); saveThumbnailToDB(new BitmapDrawable(bitmap));
if (!cropped.equals(b))
b.recycle();
mThumbnail = new BitmapDrawable(bitmap); mThumbnail = new BitmapDrawable(bitmap);
cropped.recycle(); b.recycle();
} catch (OutOfMemoryError oom) { } catch (OutOfMemoryError oom) {
Log.e(LOGTAG, "Unable to create/scale bitmap", oom); Log.e(LOGTAG, "Unable to create/scale bitmap", oom);
mThumbnail = null; mThumbnail = null;

View File

@ -2256,6 +2256,46 @@ Java_org_mozilla_gecko_GeckoAppShell_allocateDirectBuffer(JNIEnv *jenv, jclass,
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 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<nsIDOMDocument> doc;
rv = window->GetDocument(getter_AddRefs(doc));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMElement> docElement;
rv = doc->GetDocumentElement(getter_AddRefs(docElement));
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 viewportWidth;
PRInt32 viewportHeight;
PRInt32 pageWidth;
PRInt32 pageHeight;
window->GetInnerWidth(&viewportWidth);
window->GetInnerHeight(&viewportHeight);
docElement->GetScrollWidth(&pageWidth);
docElement->GetScrollHeight(&pageHeight);
// use the page or viewport dimensions, whichever is larger
PRInt32 width;
PRInt32 height;
width = viewportWidth > pageWidth ? viewportWidth : pageWidth;
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;
}
}
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(window); nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(window);
if (!win) if (!win)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
@ -2291,7 +2331,7 @@ nsresult AndroidBridge::TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt
nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(static_cast<unsigned char*>(data), nsIntSize(dstW, dstH), stride, gfxASurface::ImageFormatRGB16_565); nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(static_cast<unsigned char*>(data), nsIntSize(dstW, dstH), stride, gfxASurface::ImageFormatRGB16_565);
nsRefPtr<gfxContext> context = new gfxContext(surf); nsRefPtr<gfxContext> context = new gfxContext(surf);
context->Scale(scale * dstW / srcW, scale * dstH / srcH); 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); NS_ENSURE_SUCCESS(rv, rv);
AndroidBridge::AutoLocalJNIFrame jniFrame(jenv, 1); AndroidBridge::AutoLocalJNIFrame jniFrame(jenv, 1);
jenv->CallStaticVoidMethod(AndroidBridge::Bridge()->mGeckoAppShellClass, AndroidBridge::Bridge()->jNotifyScreenShot, buffer, tabId, srcX * dstW / srcW , srcY * dstH / srcH, dstW, dstH, token); jenv->CallStaticVoidMethod(AndroidBridge::Bridge()->mGeckoAppShellClass, AndroidBridge::Bridge()->jNotifyScreenShot, buffer, tabId, srcX * dstW / srcW , srcY * dstH / srcH, dstW, dstH, token);

View File

@ -469,11 +469,6 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
break; break;
float scale = 1.0; float scale = 1.0;
if (token == AndroidBridge::SCREENSHOT_THUMBNAIL) {
if (NS_FAILED(tab->GetScale(&scale)))
break;
}
nsTArray<nsIntPoint> points = curEvent->Points(); nsTArray<nsIntPoint> points = curEvent->Points();
NS_ASSERTION(points.Length() == 4, "Screenshot event does not have enough coordinates"); 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()); 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());