From 2784ff0af88128f66ae690b73d48fb7e4a211e68 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Sat, 18 Jul 2009 17:13:29 -0700 Subject: [PATCH] Fix issue where scaled bitmap sizes could be wrong. The Bitmap functions to get the scaled width/height couldn't actually do the right thing because they didn't know the destination they would be drawing to. Now there are two forms of them, taking an explicit parameter specifying the destination. --- api/current.xml | 30 ++++++++++++ .../content/res/CompatibilityInfo.java | 20 ++++++-- graphics/java/android/graphics/Bitmap.java | 47 +++++++++++++++++-- tests/DpiTest/AndroidManifest.xml | 2 +- .../android/test/dpi/DpiTestActivity.java | 15 ++++-- 5 files changed, 103 insertions(+), 11 deletions(-) diff --git a/api/current.xml b/api/current.xml index bb932e675fbe7..779d1228709e5 100644 --- a/api/current.xml +++ b/api/current.xml @@ -49036,6 +49036,21 @@ deprecated="not deprecated" visibility="public" > + + + + + + + + + + + + 1.0), unless that's only option. if (tmpDiff < minDiff && packageDensityScale < 1.0f) { + packageDensity = density; packageDensityScale = DisplayMetrics.DENSITY_DEVICE / (float) density; minDiff = tmpDiff; } } } if (packageDensityScale > 0.0f) { + applicationDensity = packageDensity; applicationScale = packageDensityScale; } else { + applicationDensity = DisplayMetrics.DENSITY_DEFAULT; applicationScale = DisplayMetrics.DENSITY_DEVICE / (float) DisplayMetrics.DENSITY_DEFAULT; } @@ -139,9 +150,11 @@ public class CompatibilityInfo { } } - private CompatibilityInfo(int appFlags, int compFlags, float scale, float invertedScale) { + private CompatibilityInfo(int appFlags, int compFlags, + int dens, float scale, float invertedScale) { this.appFlags = appFlags; mCompatibilityFlags = compFlags; + applicationDensity = dens; applicationScale = scale; applicationInvertedScale = invertedScale; } @@ -151,6 +164,7 @@ public class CompatibilityInfo { | ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS | ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS, EXPANDABLE | CONFIGURED_EXPANDABLE, + DisplayMetrics.DENSITY_DEVICE, 1.0f, 1.0f); } @@ -160,7 +174,7 @@ public class CompatibilityInfo { */ public CompatibilityInfo copy() { CompatibilityInfo info = new CompatibilityInfo(appFlags, mCompatibilityFlags, - applicationScale, applicationInvertedScale); + applicationDensity, applicationScale, applicationInvertedScale); return info; } diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index 141553e9ca74c..df659ef224dee 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -18,6 +18,7 @@ package android.graphics; import android.os.Parcel; import android.os.Parcelable; +import android.util.DisplayMetrics; import java.io.OutputStream; import java.nio.Buffer; @@ -605,22 +606,60 @@ public final class Bitmap implements Parcelable { * Convenience method that returns the width of this bitmap divided * by the density scale factor. * + * @param canvas The Canvas the bitmap will be drawn to. * @return The scaled width of this bitmap, according to the density scale factor. */ - public int getScaledWidth() { + public int getScaledWidth(Canvas canvas) { final float scale = mDensityScale; - return scale == DENSITY_SCALE_UNKNOWN ? getWidth() : (int) (getWidth() / scale); + if (!mAutoScaling || scale < 0) { + return getWidth(); + } + return (int)(getWidth() * canvas.getDensityScale() / scale); } /** * Convenience method that returns the height of this bitmap divided * by the density scale factor. * + * @param canvas The Canvas the bitmap will be drawn to. * @return The scaled height of this bitmap, according to the density scale factor. */ - public int getScaledHeight() { + public int getScaledHeight(Canvas canvas) { final float scale = mDensityScale; - return scale == DENSITY_SCALE_UNKNOWN ? getWidth() : (int) (getHeight() / scale); + if (!mAutoScaling || scale < 0) { + return getHeight(); + } + return (int)(getHeight() * canvas.getDensityScale() / scale); + } + + /** + * Convenience method that returns the width of this bitmap divided + * by the density scale factor. + * + * @param metrics The target display metrics. + * @return The scaled width of this bitmap, according to the density scale factor. + */ + public int getScaledWidth(DisplayMetrics metrics) { + final float scale = mDensityScale; + if (!mAutoScaling || scale < 0) { + return getWidth(); + } + return (int)(getWidth() * metrics.density / scale); + } + + /** + * Convenience method that returns the height of this bitmap divided + * by the density scale factor. + * + * @param metrics The target display metrics. + * @return The scaled height of this bitmap, according to the density scale factor. + */ + public int getScaledHeight(DisplayMetrics metrics) { + final float scale = mDensityScale; + if (!mAutoScaling || scale < 0) { + return getHeight(); + } + return (int)(getHeight() * metrics.density / scale); } /** diff --git a/tests/DpiTest/AndroidManifest.xml b/tests/DpiTest/AndroidManifest.xml index ea355a4c72d18..68ecc6e89934a 100644 --- a/tests/DpiTest/AndroidManifest.xml +++ b/tests/DpiTest/AndroidManifest.xml @@ -25,7 +25,7 @@ - + diff --git a/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java b/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java index 9169025035af2..8c69305d57609 100644 --- a/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java +++ b/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java @@ -17,6 +17,8 @@ package com.google.android.test.dpi; import android.app.Activity; +import android.app.ActivityThread; +import android.app.Application; import android.os.Bundle; import android.graphics.BitmapFactory; import android.graphics.Bitmap; @@ -31,6 +33,7 @@ import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.CompatibilityInfo; +import android.util.DisplayMetrics; public class DpiTestActivity extends Activity { public DpiTestActivity() { @@ -45,7 +48,10 @@ public class DpiTestActivity extends Activity { public void init(boolean noCompat) { try { - ApplicationInfo ai = getPackageManager().getApplicationInfo( + // This is all a dirty hack. Don't think a real application should + // be doing it. + Application app = ActivityThread.currentActivityThread().getApplication(); + ApplicationInfo ai = app.getPackageManager().getApplicationInfo( "com.google.android.test.dpi", PackageManager.GET_SUPPORTS_DENSITIES); if (noCompat) { @@ -53,8 +59,8 @@ public class DpiTestActivity extends Activity { | ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS | ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS; ai.supportsDensities = new int[] { ApplicationInfo.ANY_DENSITY }; + app.getResources().setCompatibilityInfo(new CompatibilityInfo(ai)); } - getResources().setCompatibilityInfo(new CompatibilityInfo(ai)); } catch (PackageManager.NameNotFoundException e) { throw new RuntimeException("ouch", e); } @@ -192,7 +198,10 @@ public class DpiTestActivity extends Activity { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); - setMeasuredDimension(mBitmap.getScaledWidth(), mBitmap.getScaledHeight()); + final DisplayMetrics metrics = getResources().getDisplayMetrics(); + setMeasuredDimension( + mBitmap.getScaledWidth(metrics), + mBitmap.getScaledHeight(metrics)); } @Override