diff options
author | Alan Viverette <alanv@google.com> | 2014-02-04 22:05:26 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-02-04 22:05:26 +0000 |
commit | 9f244efbfac8d592a0af0321f7985761ed17ec6c (patch) | |
tree | 79fa9a35e6b4ee5f9c99ec65e8aa0cd3ac106c44 /core | |
parent | 40675bdd3857a9e29b2e61b5bc1660e9bb2e82a2 (diff) | |
parent | 4085aac5833e6d88c3f77b6c86cc7520a2550bfc (diff) | |
download | frameworks_base-9f244efbfac8d592a0af0321f7985761ed17ec6c.zip frameworks_base-9f244efbfac8d592a0af0321f7985761ed17ec6c.tar.gz frameworks_base-9f244efbfac8d592a0af0321f7985761ed17ec6c.tar.bz2 |
Merge "Make background projection a property of View"
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/view/View.java | 165 |
1 files changed, 140 insertions, 25 deletions
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 15ede96..12dc044 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -2325,7 +2325,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /* End of masks for mPrivateFlags2 */ - /* Masks for mPrivateFlags3 */ + /** + * Masks for mPrivateFlags3, as generated by dumpFlags(): + * + * |-------|-------|-------|-------| + * 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM + * 1 PFLAG3_VIEW_IS_ANIMATING_ALPHA + * 1 PFLAG3_IS_LAID_OUT + * 1 PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT + * 1 PFLAG3_CALLED_SUPER + * 1 PFLAG3_PROJECT_BACKGROUND + * |-------|-------|-------|-------| + */ /** * Flag indicating that view has a transform animation set on it. This is used to track whether @@ -2359,6 +2370,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ static final int PFLAG3_CALLED_SUPER = 0x10; + /** + * Flag indicating that the background of this view will be drawn into a + * display list and projected onto the closest parent projection surface. + */ + static final int PFLAG3_PROJECT_BACKGROUND = 0x20; /* End of masks for mPrivateFlags3 */ @@ -3225,6 +3241,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback, @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_") private Drawable mBackground; + /** + * Display list used for backgrounds. + * <p> + * When non-null and valid, this is expected to contain an up-to-date copy + * of the background drawable. It is cleared on temporary detach and reset + * on cleanup. + */ + private DisplayList mBackgroundDisplayList; + private int mBackgroundResource; private boolean mBackgroundSizeChanged; @@ -3503,6 +3528,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private Bitmap mDrawingCache; private Bitmap mUnscaledDrawingCache; + /** + * Display list used for the View content. + * <p> + * When non-null and valid, this is expected to contain an up-to-date copy + * of the View content. It is cleared on temporary detach and reset on + * cleanup. + */ DisplayList mDisplayList; /** @@ -13688,12 +13720,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (mDisplayList != null) { mDisplayList.clear(); } + + if (mBackgroundDisplayList != null) { + mBackgroundDisplayList.clear(); + } } private void resetDisplayList() { if (mDisplayList != null) { mDisplayList.reset(); } + + if (mBackgroundDisplayList != null) { + mBackgroundDisplayList.reset(); + } } /** @@ -14721,24 +14761,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, int saveCount; if (!dirtyOpaque) { - final Drawable background = mBackground; - if (background != null) { - final int scrollX = mScrollX; - final int scrollY = mScrollY; - - if (mBackgroundSizeChanged) { - background.setBounds(0, 0, mRight - mLeft, mBottom - mTop); - mBackgroundSizeChanged = false; - } - - if ((scrollX | scrollY) == 0) { - background.draw(canvas); - } else { - canvas.translate(scrollX, scrollY); - background.draw(canvas); - canvas.translate(-scrollX, -scrollY); - } - } + drawBackground(canvas); } // skip step 2 & 5 if possible (common case) @@ -14905,6 +14928,90 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Draws the background onto the specified canvas. + * + * @param canvas Canvas on which to draw the background + */ + private void drawBackground(Canvas canvas) { + final Drawable background = mBackground; + if (background == null) { + return; + } + + if (mBackgroundSizeChanged) { + // We should see the background invalidate itself, but just to be + // careful we're going to clear the display list and force redraw. + mBackgroundDisplayList.clear(); + background.setBounds(0, 0, mRight - mLeft, mBottom - mTop); + mBackgroundSizeChanged = false; + } + + + // Attempt to use a display list if requested. + if (canvas != null && canvas.isHardwareAccelerated()) { + mBackgroundDisplayList = getDrawableDisplayList(background, mBackgroundDisplayList); + + final DisplayList displayList = mBackgroundDisplayList; + if (displayList != null && displayList.isValid()) { + setBackgroundDisplayListProperties(displayList); + ((HardwareCanvas) canvas).drawDisplayList(displayList); + return; + } + } + + final int scrollX = mScrollX; + final int scrollY = mScrollY; + if ((scrollX | scrollY) == 0) { + background.draw(canvas); + } else { + canvas.translate(scrollX, scrollY); + background.draw(canvas); + canvas.translate(-scrollX, -scrollY); + } + } + + /** + * Set up background drawable display list properties. + * + * @param displayList Valid display list for the background drawable + */ + private void setBackgroundDisplayListProperties(DisplayList displayList) { + displayList.setProjectBackwards((mPrivateFlags3 & PFLAG3_PROJECT_BACKGROUND) != 0); + displayList.setTranslationX(mScrollX); + displayList.setTranslationY(mScrollY); + } + + /** + * Creates a new display list or updates the existing display list for the + * specified Drawable. + * + * @param drawable Drawable for which to create a display list + * @param displayList Existing display list, or {@code null} + * @return A valid display list for the specified drawable + */ + private static DisplayList getDrawableDisplayList(Drawable drawable, DisplayList displayList) { + if (displayList != null && displayList.isValid()) { + return displayList; + } + + if (displayList == null) { + displayList = DisplayList.create(drawable.getClass().getName()); + } + + final Rect bounds = drawable.getBounds(); + final int width = bounds.width(); + final int height = bounds.height(); + final HardwareCanvas canvas = displayList.start(width, height); + drawable.draw(canvas); + displayList.end(); + + // Set up drawable properties that are view-independent. + displayList.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom); + displayList.setClipToBounds(false); + return displayList; + } + + /** * Returns the overlay for this view, creating it if it does not yet exist. * Adding drawables to the overlay will cause them to be displayed whenever * the view itself is redrawn. Objects in the overlay should be actively @@ -15245,14 +15352,22 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * * @param drawable the drawable to invalidate */ + @Override public void invalidateDrawable(Drawable drawable) { if (verifyDrawable(drawable)) { - final Rect dirty = drawable.getBounds(); - final int scrollX = mScrollX; - final int scrollY = mScrollY; + if (drawable == mBackground && mBackgroundDisplayList != null) { + // If we're using a background display list, we only need to + // invalidate the display list and notify the parent to redraw. + mBackgroundDisplayList.clear(); + invalidateViewProperty(true, false); + } else { + final Rect dirty = drawable.getBounds(); + final int scrollX = mScrollX; + final int scrollY = mScrollY; - invalidate(dirty.left + scrollX, dirty.top + scrollY, - dirty.right + scrollX, dirty.bottom + scrollY); + invalidate(dirty.left + scrollX, dirty.top + scrollY, + dirty.right + scrollX, dirty.bottom + scrollY); + } } } @@ -15399,7 +15514,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @see Drawable#setState(int[]) */ protected void drawableStateChanged() { - Drawable d = mBackground; + final Drawable d = mBackground; if (d != null && d.isStateful()) { d.setState(getDrawableState()); } |