Loading core/java/android/view/View.java +140 −25 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 */ Loading Loading @@ -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; Loading Loading @@ -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; /** Loading Loading @@ -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(); } } /** Loading Loading @@ -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) Loading Loading @@ -14904,6 +14927,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 Loading Loading @@ -15245,8 +15352,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * * @param drawable the drawable to invalidate */ @Override public void invalidateDrawable(Drawable drawable) { if (verifyDrawable(drawable)) { 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; Loading @@ -15255,6 +15369,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, dirty.right + scrollX, dirty.bottom + scrollY); } } } /** * Schedules an action on a drawable to occur at a specified time. Loading Loading @@ -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()); } Loading
core/java/android/view/View.java +140 −25 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 */ Loading Loading @@ -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; Loading Loading @@ -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; /** Loading Loading @@ -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(); } } /** Loading Loading @@ -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) Loading Loading @@ -14904,6 +14927,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 Loading Loading @@ -15245,8 +15352,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * * @param drawable the drawable to invalidate */ @Override public void invalidateDrawable(Drawable drawable) { if (verifyDrawable(drawable)) { 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; Loading @@ -15255,6 +15369,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, dirty.right + scrollX, dirty.bottom + scrollY); } } } /** * Schedules an action on a drawable to occur at a specified time. Loading Loading @@ -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()); }