Fixes #1946141. Introduce new caching API to control scaling.

This change fixes issues with existing applications that access the drawing cache
directly. The API now lets application choose whether they want to get a scaled
drawing cache or not. The framework relies on the scaled cache for quality
purposes.
This commit is contained in:
Romain Guy
2009-06-26 14:51:58 -07:00
parent a1590586e4
commit fbd8f69a84
3 changed files with 108 additions and 28 deletions

View File

@@ -139488,6 +139488,19 @@
visibility="public"
>
</method>
<method name="buildDrawingCache"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="autoScale" type="boolean">
</parameter>
</method>
<method name="cancelLongPress"
return="void"
abstract="false"
@@ -140064,6 +140077,19 @@
visibility="public"
>
</method>
<method name="getDrawingCache"
return="android.graphics.Bitmap"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="autoScale" type="boolean">
</parameter>
</method>
<method name="getDrawingCacheBackgroundColor"
return="int"
abstract="false"

View File

@@ -1690,6 +1690,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
private int[] mDrawableState = null;
private SoftReference<Bitmap> mDrawingCache;
private SoftReference<Bitmap> mUnscaledDrawingCache;
/**
* When this view has focus and the next focus is {@link #FOCUS_LEFT},
@@ -5782,6 +5783,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
}
/**
* <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
*
* @return A non-scaled bitmap representing this view or null if cache is disabled.
*
* @see #getDrawingCache(boolean)
*/
public Bitmap getDrawingCache() {
return getDrawingCache(false);
}
/**
* <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
* is null when caching is disabled. If caching is enabled and the cache is not ready,
@@ -5789,22 +5801,35 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
* draw from the cache when the cache is enabled. To benefit from the cache, you must
* request the drawing cache by calling this method and draw it on screen if the
* returned bitmap is not null.</p>
*
* <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
* this method will create a bitmap of the same size as this view. Because this bitmap
* will be drawn scaled by the parent ViewGroup, the result on screen might show
* scaling artifacts. To avoid such artifacts, you should call this method by setting
* the auto scaling to true. Doing so, however, will generate a bitmap of a different
* size than the view. This implies that your application must be able to handle this
* size.</p>
*
* @param autoScale Indicates whether the generated bitmap should be scaled based on
* the current density of the screen when the application is in compatibility
* mode.
*
* @return a bitmap representing this view or null if cache is disabled
*
* @return A bitmap representing this view or null if cache is disabled.
*
* @see #setDrawingCacheEnabled(boolean)
* @see #isDrawingCacheEnabled()
* @see #buildDrawingCache()
* @see #buildDrawingCache(boolean)
* @see #destroyDrawingCache()
*/
public Bitmap getDrawingCache() {
public Bitmap getDrawingCache(boolean autoScale) {
if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
return null;
}
if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
buildDrawingCache();
buildDrawingCache(autoScale);
}
return mDrawingCache == null ? null : mDrawingCache.get();
return autoScale ? (mDrawingCache == null ? null : mDrawingCache.get()) :
(mUnscaledDrawingCache == null ? null : mUnscaledDrawingCache.get());
}
/**
@@ -5823,6 +5848,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
if (bitmap != null) bitmap.recycle();
mDrawingCache = null;
}
if (mUnscaledDrawingCache != null) {
final Bitmap bitmap = mUnscaledDrawingCache.get();
if (bitmap != null) bitmap.recycle();
mUnscaledDrawingCache = null;
}
}
/**
@@ -5849,19 +5879,37 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
return mDrawingCacheBackgroundColor;
}
/**
* <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
*
* @see #buildDrawingCache(boolean)
*/
public void buildDrawingCache() {
buildDrawingCache(false);
}
/**
* <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
*
* <p>If you call {@link #buildDrawingCache()} manually without calling
* {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
* should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
*
* <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
* this method will create a bitmap of the same size as this view. Because this bitmap
* will be drawn scaled by the parent ViewGroup, the result on screen might show
* scaling artifacts. To avoid such artifacts, you should call this method by setting
* the auto scaling to true. Doing so, however, will generate a bitmap of a different
* size than the view. This implies that your application must be able to handle this
* size.</p>
*
* @see #getDrawingCache()
* @see #destroyDrawingCache()
*/
public void buildDrawingCache() {
if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || mDrawingCache == null ||
mDrawingCache.get() == null) {
public void buildDrawingCache(boolean autoScale) {
if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || (autoScale ?
(mDrawingCache == null || mDrawingCache.get() == null) :
(mUnscaledDrawingCache == null || mUnscaledDrawingCache.get() == null))) {
if (ViewDebug.TRACE_HIERARCHY) {
ViewDebug.trace(this, ViewDebug.HierarchyTraceType.BUILD_CACHE);
@@ -5874,12 +5922,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
int height = mBottom - mTop;
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
final boolean scalingRequired = attachInfo.mScalingRequired;
if (scalingRequired) {
width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
}
if (autoScale && attachInfo != null && attachInfo.mScalingRequired) {
width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
}
final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
@@ -5894,7 +5940,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
}
boolean clear = true;
Bitmap bitmap = mDrawingCache == null ? null : mDrawingCache.get();
Bitmap bitmap = autoScale ? (mDrawingCache == null ? null : mDrawingCache.get()) :
(mUnscaledDrawingCache == null ? null : mUnscaledDrawingCache.get());
if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
@@ -5923,12 +5970,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
try {
bitmap = Bitmap.createBitmap(width, height, quality);
mDrawingCache = new SoftReference<Bitmap>(bitmap);
if (autoScale) {
mDrawingCache = new SoftReference<Bitmap>(bitmap);
} else {
mUnscaledDrawingCache = new SoftReference<Bitmap>(bitmap);
}
} catch (OutOfMemoryError e) {
// If there is not enough memory to create the bitmap cache, just
// ignore the issue as bitmap caches are not required to draw the
// view hierarchy
mDrawingCache = null;
if (autoScale) {
mDrawingCache = null;
} else {
mUnscaledDrawingCache = null;
}
return;
}
@@ -5940,13 +5995,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
canvas = attachInfo.mCanvas;
if (canvas == null) {
canvas = new Canvas();
// NOTE: This should have to happen only once since compatibility
// mode should not change at runtime
if (attachInfo.mScalingRequired) {
final float scale = attachInfo.mApplicationScale;
canvas.scale(scale, scale);
}
}
canvas.setBitmap(bitmap);
// Temporarily clobber the cached Canvas in case one of our children
@@ -5965,6 +6013,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
computeScroll();
final int restoreCount = canvas.save();
if (autoScale && attachInfo.mScalingRequired) {
final float scale = attachInfo.mApplicationScale;
canvas.scale(scale, scale);
}
canvas.translate(-mScrollX, -mScrollY);
mPrivateFlags |= DRAWN;

View File

@@ -1166,7 +1166,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
final View child = children[i];
if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
child.setDrawingCacheEnabled(true);
child.buildDrawingCache();
child.buildDrawingCache(true);
}
}
@@ -1208,7 +1208,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
bindLayoutAnimation(child);
if (cache) {
child.setDrawingCacheEnabled(true);
child.buildDrawingCache();
child.buildDrawingCache(true);
}
}
}
@@ -1448,7 +1448,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
Bitmap cache = null;
if ((flags & FLAG_CHILDREN_DRAWN_WITH_CACHE) == FLAG_CHILDREN_DRAWN_WITH_CACHE ||
(flags & FLAG_ALWAYS_DRAWN_WITH_CACHE) == FLAG_ALWAYS_DRAWN_WITH_CACHE) {
cache = child.getDrawingCache();
cache = child.getDrawingCache(true);
if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
}