am e0ef973b: Merge change 8323 into donut
Merge commit 'e0ef973b1358585d039989ee5572e16751078aaf'
* commit 'e0ef973b1358585d039989ee5572e16751078aaf':
* a best effort fix for apps that uses get/set Matrix API on canvas.
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index e6bbf9f5..9178131 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -16,6 +16,7 @@
package android.view;
+import android.content.res.CompatibilityInfo.Translator;
import android.graphics.*;
import android.os.Parcelable;
import android.os.Parcel;
@@ -135,8 +136,12 @@
private Canvas mCanvas;
// The display metrics used to provide the pseudo canvas size for applications
- // running in compatibility mode. This is set to null for regular mode.
- private DisplayMetrics mDisplayMetrics;
+ // running in compatibility mode. This is set to null for non compatibility mode.
+ private DisplayMetrics mCompatibleDisplayMetrics;
+
+ // A matrix to scale the matrix set by application. This is set to null for
+ // non compatibility mode.
+ private Matrix mCompatibleMatrix;
/**
* Exception thrown when a surface couldn't be created or resized
@@ -174,23 +179,70 @@
* {@hide}
*/
public Surface() {
- mCanvas = new Canvas() {
- @Override
- public int getWidth() {
- return mDisplayMetrics == null ? super.getWidth() : mDisplayMetrics.widthPixels;
- }
- @Override
- public int getHeight() {
- return mDisplayMetrics == null ? super.getHeight() : mDisplayMetrics.heightPixels;
- }
- };
+ mCanvas = new CompatibleCanvas();
}
/**
+ * A Canvas class that can handle the compatibility mode. This does two things differently.
+ * <ul>
+ * <li> Returns the width and height of the target metrics, rather than native.
+ * For example, the canvas returns 320x480 even if an app is running in WVGA high density.
+ * <li> Scales the matrix in setMatrix by the application scale, except if the matrix looks
+ * like obtained from getMatrix. This is a hack to handle the case that an application
+ * uses getMatrix to keep the original matrix, set matrix of its own, then set the original
+ * matrix back. There is no perfect solution that works for all cases, and there are a lot of
+ * cases that this model dose not work, but we hope this works for many apps.
+ * </ul>
+ */
+ private class CompatibleCanvas extends Canvas {
+ // A temp matrix to remember what an application obtained via {@link getMatrix}
+ private Matrix mOrigMatrix = null;
+
+ @Override
+ public int getWidth() {
+ return mCompatibleDisplayMetrics == null ?
+ super.getWidth() : mCompatibleDisplayMetrics.widthPixels;
+ }
+
+ @Override
+ public int getHeight() {
+ return mCompatibleDisplayMetrics == null ?
+ super.getHeight() : mCompatibleDisplayMetrics.heightPixels;
+ }
+
+ @Override
+ public void setMatrix(Matrix matrix) {
+ if (mCompatibleMatrix == null || mOrigMatrix == null || mOrigMatrix.equals(matrix)) {
+ // don't scale the matrix if it's not compatibility mode, or
+ // the matrix was obtained from getMatrix.
+ super.setMatrix(matrix);
+ } else {
+ Matrix m = new Matrix(mCompatibleMatrix);
+ m.preConcat(matrix);
+ super.setMatrix(m);
+ }
+ }
+
+ @Override
+ public void getMatrix(Matrix m) {
+ super.getMatrix(m);
+ if (mOrigMatrix == null) {
+ mOrigMatrix = new Matrix();
+ }
+ mOrigMatrix.set(m);
+ }
+ };
+
+ /**
* Sets the display metrics used to provide canva's width/height in comaptibility mode.
*/
- void setCompatibleDisplayMetrics(DisplayMetrics metrics) {
- mDisplayMetrics = metrics;
+ void setCompatibleDisplayMetrics(DisplayMetrics metrics, Translator translator) {
+ mCompatibleDisplayMetrics = metrics;
+ if (translator != null) {
+ float appScale = translator.applicationScale;
+ mCompatibleMatrix = new Matrix();
+ mCompatibleMatrix.setScale(appScale, appScale);
+ }
}
/**
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index a854535..ae5968e 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -313,7 +313,7 @@
Resources res = getContext().getResources();
if (mTranslator != null || !res.getCompatibilityInfo().supportsScreen()) {
- mSurface.setCompatibleDisplayMetrics(res.getDisplayMetrics());
+ mSurface.setCompatibleDisplayMetrics(res.getDisplayMetrics(), mTranslator);
}
int myWidth = mRequestedWidth;
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 242690b..7429a89 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -399,7 +399,8 @@
mTranslator = compatibilityInfo.getTranslator(attrs);
if (mTranslator != null || !compatibilityInfo.supportsScreen()) {
- mSurface.setCompatibleDisplayMetrics(resources.getDisplayMetrics());
+ mSurface.setCompatibleDisplayMetrics(resources.getDisplayMetrics(),
+ mTranslator);
}
boolean restore = false;