Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 424a1bb0 authored by Romain Guy's avatar Romain Guy Committed by Android (Google) Code Review
Browse files

Merge "New layers API for Views." into honeycomb

parents 646897cb 171c592f
Loading
Loading
Loading
Loading
+70 −0
Original line number Diff line number Diff line
@@ -5900,6 +5900,17 @@
 visibility="public"
>
</field>
<field name="layerType"
 type="int"
 transient="false"
 volatile="false"
 value="16843606"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="layout"
 type="int"
 transient="false"
@@ -213314,6 +213325,17 @@
 visibility="public"
>
</method>
<method name="getLayerType"
 return="int"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="getLayoutParams"
 return="android.view.ViewGroup.LayoutParams"
 abstract="false"
@@ -215816,6 +215838,21 @@
<parameter name="keepScreenOn" type="boolean">
</parameter>
</method>
<method name="setLayerType"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="layerType" type="int">
</parameter>
<parameter name="paint" type="android.graphics.Paint">
</parameter>
</method>
<method name="setLayoutParams"
 return="void"
 abstract="false"
@@ -216903,6 +216940,39 @@
 visibility="public"
>
</field>
<field name="LAYER_TYPE_HARDWARE"
 type="int"
 transient="false"
 volatile="false"
 value="2"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="LAYER_TYPE_NONE"
 type="int"
 transient="false"
 volatile="false"
 value="0"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="LAYER_TYPE_SOFTWARE"
 type="int"
 transient="false"
 volatile="false"
 value="1"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="MEASURED_HEIGHT_STATE_SHIFT"
 type="int"
 transient="false"
+10 −3
Original line number Diff line number Diff line
@@ -127,7 +127,11 @@ class GLES20Canvas extends HardwareCanvas {

        @Override
        protected void finalize() throws Throwable {
            try {
                replaceNativeObject(0);
            } finally {
                super.finalize();
            }
        }
    }

@@ -395,8 +399,11 @@ class GLES20Canvas extends HardwareCanvas {
    @Override
    public int saveLayer(float left, float top, float right, float bottom, Paint paint,
            int saveFlags) {
        int nativePaint = paint == null ? 0 : paint.mNativePaint;
        return nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags);
        boolean hasColorFilter = paint != null && setupColorFilter(paint);
        final int nativePaint = paint == null ? 0 : paint.mNativePaint;
        int count = nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags);
        if (hasColorFilter) nResetModifiers(mRenderer);
        return count;
    }

    private native int nSaveLayer(int renderer, float left, float top, float right, float bottom,
+172 −4
Original line number Diff line number Diff line
@@ -58,7 +58,6 @@ import android.util.PoolableManager;
import android.util.Pools;
import android.util.SparseArray;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.MeasureSpec;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityEventSource;
import android.view.accessibility.AccessibilityManager;
@@ -546,6 +545,10 @@ import java.util.WeakHashMap;
 * subtree rooted by that node. When an animation is started, the framework will
 * take care of redrawing the appropriate views until the animation completes.
 * </p>
 * <p>
 * Starting with Android 3.0, the preferred way of animating views is to use the
 * {@link android.animation} package APIs.
 * </p>
 *
 * <a name="Security"></a>
 * <h3>Security</h3>
@@ -569,6 +572,7 @@ import java.util.WeakHashMap;
 * See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
 * </p>
 *
 * @attr ref android.R.styleable#View_alpha
 * @attr ref android.R.styleable#View_background
 * @attr ref android.R.styleable#View_clickable
 * @attr ref android.R.styleable#View_contentDescription
@@ -584,6 +588,7 @@ import java.util.WeakHashMap;
 * @attr ref android.R.styleable#View_focusableInTouchMode
 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
 * @attr ref android.R.styleable#View_keepScreenOn
 * @attr ref android.R.styleable#View_layerType
 * @attr ref android.R.styleable#View_longClickable
 * @attr ref android.R.styleable#View_minHeight
 * @attr ref android.R.styleable#View_minWidth
@@ -2151,6 +2156,69 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
     */
    public static final int SCROLLBAR_POSITION_RIGHT = 2;

    /**
     * Indicates that the view does not have a layer.
     * 
     * @see #getLayerType() 
     * @see #setLayerType(int, android.graphics.Paint) 
     * @see #LAYER_TYPE_SOFTWARE
     * @see #LAYER_TYPE_HARDWARE 
     */
    public static final int LAYER_TYPE_NONE = 0;

    /**
     * <p>Indicates that the view has a software layer. A software layer is backed
     * by a bitmap and causes the view to be rendered using Android's software
     * rendering pipeline, even if hardware acceleration is enabled.</p>
     * 
     * <p>Software layers have various usages:</p>
     * <p>When the application is not using hardware acceleration, a software layer
     * is useful to apply a specific color filter and/or blending mode and/or
     * translucency to a view and all its children.</p>
     * <p>When the application is using hardware acceleration, a software layer
     * is useful to render drawing primitives not supported by the hardware
     * accelerated pipeline. It can also be used to cache a complex view tree
     * into a texture and reduce the complexity of drawing operations. For instance,
     * when animating a complex view tree with a translation, a software layer can
     * be used to render the view tree only once.</p>
     * <p>Software layers should be avoided when the affected view tree updates
     * often. Every update will require to re-render the software layer, which can
     * potentially be slow (particularly when hardware acceleration is turned on
     * since the layer will have to be uploaded into a hardware texture after every
     * update.)</p>
     * 
     * @see #getLayerType() 
     * @see #setLayerType(int, android.graphics.Paint) 
     * @see #LAYER_TYPE_NONE
     * @see #LAYER_TYPE_HARDWARE 
     */
    public static final int LAYER_TYPE_SOFTWARE = 1;

    /**
     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
     * OpenGL hardware) and causes the view to be rendered using Android's hardware
     * rendering pipeline, but only if hardware acceleration is turned on for the
     * view hierarchy. When hardware acceleration is turned off, hardware layers
     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
     * 
     * <p>A hardware layer is useful to apply a specific color filter and/or
     * blending mode and/or translucency to a view and all its children.</p>
     * <p>A hardware layer can also be used to increase the rendering quality when
     * rotation transformations are applied on a view. It can also be used to
     * prevent potential clipping issues when applying 3D transforms on a view.</p>
     * 
     * @see #getLayerType() 
     * @see #setLayerType(int, android.graphics.Paint)
     * @see #LAYER_TYPE_NONE
     * @see #LAYER_TYPE_SOFTWARE
     */
    public static final int LAYER_TYPE_HARDWARE = 2;
    
    @ViewDebug.ExportedProperty(category = "drawing")
    int mLayerType = LAYER_TYPE_NONE;
    Paint mLayerPaint;

    /**
     * Simple constructor to use when creating a view from code.
     *
@@ -2489,6 +2557,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
                case R.styleable.View_verticalScrollbarPosition:
                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
                    break;
                case R.styleable.View_layerType:
                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
                    break;
            }
        }

@@ -5763,11 +5834,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
    }

    /**
     * Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
     * completely transparent and 1 means the view is completely opaque.
     * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
     * completely transparent and 1 means the view is completely opaque.</p>
     * 
     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
     * responsible for applying the opacity itself. Otherwise, calling this method is
     * equivalent to calling {@link #setLayerType(int, android.graphics.Paint)} and
     * setting a hardware layer.</p> 
     *
     * @param alpha The opacity of the view.
     *
     * @see #setLayerType(int, android.graphics.Paint) 
     * 
     * @attr ref android.R.styleable#View_alpha
     */
    public void setAlpha(float alpha) {
@@ -7746,6 +7824,88 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
    }

    /**
     * <p>Specifies the type of layer backing this view. The layer can be
     * {@link #LAYER_TYPE_NONE disabled}, {@link #LAYER_TYPE_SOFTWARE software} or
     * {@link #LAYER_TYPE_HARDWARE hardware}.</p>
     * 
     * <p>A layer is associated with an optional {@link android.graphics.Paint}
     * instance that controls how the layer is composed on screen. The following
     * properties of the paint are taken into account when composing the layer:</p>
     * <ul>
     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
     * </ul>
     * 
     * <p>If this view has an alpha value set to < 1.0 by calling
     * {@link #setAlpha(float)}, the alpha value of the layer's paint is replaced by
     * this view's alpha value. Calling {@link #setAlpha(float)} is therefore
     * equivalent to setting a hardware layer on this view and providing a paint with
     * the desired alpha value.<p>
     * 
     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE disabled},
     * {@link #LAYER_TYPE_SOFTWARE software} and {@link #LAYER_TYPE_HARDWARE hardware}
     * for more information on when and how to use layers.</p>
     * 
     * @param layerType The ype of layer to use with this view, must be one of
     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
     *        {@link #LAYER_TYPE_HARDWARE}
     * @param paint The paint used to compose the layer. This argument is optional
     *        and can be null. It is ignored when the layer type is
     *        {@link #LAYER_TYPE_NONE}
     * 
     * @see #getLayerType() 
     * @see #LAYER_TYPE_NONE
     * @see #LAYER_TYPE_SOFTWARE
     * @see #LAYER_TYPE_HARDWARE
     * @see #setAlpha(float) 
     * 
     * @attr ref android.R.styleable#View_layerType
     */
    public void setLayerType(int layerType, Paint paint) {
        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, " 
                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
        }

        // Destroy any previous software drawing cache if needed
        if (mLayerType == LAYER_TYPE_SOFTWARE && layerType != LAYER_TYPE_SOFTWARE) {
            if (mDrawingCache != null) {
                mDrawingCache.recycle();
                mDrawingCache = null;
            }

            if (mUnscaledDrawingCache != null) {
                mUnscaledDrawingCache.recycle();
                mUnscaledDrawingCache = null;
            }
        }

        mLayerType = layerType;
        mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;

        invalidate();
    }

    /**
     * Indicates what type of layer is currently associated with this view. By default
     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
     * for more information on the different types of layers.
     * 
     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
     *         {@link #LAYER_TYPE_HARDWARE}
     * 
     * @see #setLayerType(int, android.graphics.Paint) 
     * @see #LAYER_TYPE_NONE
     * @see #LAYER_TYPE_SOFTWARE
     * @see #LAYER_TYPE_HARDWARE
     */
    public int getLayerType() {
        return mLayerType;
    }

    /**
     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
@@ -7754,11 +7914,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
     * null.</p>
     * 
     * <p>Enabling the drawing cache is similar to
     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
     * acceleration is turned off. When hardware acceleration is turned on enabling the
     * drawing cache has either no effect or the cache used at drawing time is not a bitmap.
     * This API can however be used to manually generate a bitmap copy of this view.</p>
     *
     * @param enabled true to enable the drawing cache, false otherwise
     *
     * @see #isDrawingCacheEnabled()
     * @see #getDrawingCache()
     * @see #buildDrawingCache()
     * @see #setLayerType(int, android.graphics.Paint) 
     */
    public void setDrawingCacheEnabled(boolean enabled) {
        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
@@ -8077,7 +8244,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
            canvas.translate(-mScrollX, -mScrollY);

            mPrivateFlags |= DRAWN;
            if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated) {
            if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
                    mLayerType != LAYER_TYPE_NONE) {
                mPrivateFlags |= DRAWING_CACHE_VALID;
            }

+51 −12
Original line number Diff line number Diff line
@@ -2175,11 +2175,15 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        boolean concatMatrix = false;

        boolean scalingRequired = false;
        boolean caching = false;
        boolean caching;
        final int layerType = child.getLayerType();
        
        if ((flags & FLAG_CHILDREN_DRAWN_WITH_CACHE) == FLAG_CHILDREN_DRAWN_WITH_CACHE ||
                (flags & FLAG_ALWAYS_DRAWN_WITH_CACHE) == FLAG_ALWAYS_DRAWN_WITH_CACHE) {
            caching = true;
            if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
        } else {
            caching = layerType != LAYER_TYPE_NONE;
        }

        if (a != null) {
@@ -2270,11 +2274,19 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        Bitmap cache = null;
        if (caching) {
            if (!canvas.isHardwareAccelerated()) {
                if (layerType != LAYER_TYPE_NONE) {
                    child.buildDrawingCache(true);
                }
                cache = child.getDrawingCache(true);
            } else {
                if (layerType == LAYER_TYPE_SOFTWARE) {
                    child.buildDrawingCache(true);
                    cache = child.getDrawingCache(true);
                } else {
                    displayList = child.getDisplayList();
                }
            }
        }

        final boolean hasDisplayList = displayList != null && displayList.isReady();
        final boolean hasNoCache = cache == null || hasDisplayList;
@@ -2291,6 +2303,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
            }
        }
        
        boolean layerSaved = false;

        if (transformToApply != null || alpha < 1.0f || !child.hasIdentityMatrix()) {
            if (transformToApply != null || !childHasIdentityMatrix) {
                int transX = 0;
@@ -2331,12 +2345,24 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
                    final int multipliedAlpha = (int) (255 * alpha);
                    if (!child.onSetAlpha(multipliedAlpha)) {
                        int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
                        if ((flags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN) {
                        if ((flags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN ||
                                layerType != LAYER_TYPE_NONE) {
                            layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
                        }
                        canvas.saveLayerAlpha(sx, sy, sx + cr - cl, sy + cb - ct, multipliedAlpha,
                                layerFlags);
                        if (layerType != LAYER_TYPE_NONE && child.mLayerPaint != null) {
                            child.mLayerPaint.setAlpha(multipliedAlpha);
                            canvas.saveLayer(sx, sy, sx + cr - cl, sy + cb - ct,
                                    child.mLayerPaint, layerFlags);
                        } else {
                            canvas.saveLayerAlpha(sx, sy, sx + cr - cl, sy + cb - ct,
                                    multipliedAlpha, layerFlags);
                        }
                        layerSaved = true;
                    } else {
                        // Alpha is handled by the child directly, clobber the layer's alpha
                        if (layerType != LAYER_TYPE_NONE && child.mLayerPaint != null) {
                            child.mLayerPaint.setAlpha(255);
                        }
                        child.mPrivateFlags |= ALPHA_SET;
                    }
                }
@@ -2359,6 +2385,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        }

        if (hasNoCache) {
            if (!layerSaved && layerType == LAYER_TYPE_HARDWARE) {
                canvas.saveLayer(sx, sy, sx + cr - cl, sy + cb - ct, child.mLayerPaint,
                        Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
            }
            if (!hasDisplayList) {
                // Fast path for layouts with no backgrounds
                if ((child.mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
@@ -2376,7 +2406,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
            }
        } else if (cache != null) {
            child.mPrivateFlags &= ~DIRTY_MASK;
            final Paint cachePaint = mCachePaint;
            Paint cachePaint;

            if (layerType == LAYER_TYPE_NONE || child.mLayerPaint == null) {
                cachePaint = mCachePaint;
                if (alpha < 1.0f) {
                    cachePaint.setAlpha((int) (alpha * 255));
                    mGroupFlags |= FLAG_ALPHA_LOWER_THAN_ONE;
@@ -2384,6 +2417,12 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
                    cachePaint.setAlpha(255);
                    mGroupFlags &= ~FLAG_ALPHA_LOWER_THAN_ONE;
                }
            } else {
                cachePaint = child.mLayerPaint;
                if (alpha < 1.0f) {
                    cachePaint.setAlpha((int) (alpha * 255));
                }
            }
            canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
        }

+16 −0
Original line number Diff line number Diff line
@@ -1784,6 +1784,22 @@
            <!-- Place the scroll bar on the right. -->
            <enum name="right" value="2" />
        </attr>
        
        <!-- Specifies the type of layer backing this view. The default value is none.
             Refer to {@link android.view.View#setLayerType(int, android.graphics.Paint)
             for more information.-->
        <attr name="layerType">
            <!-- Don't use a layer. -->
            <enum name="none" value="0" />
            <!-- Use a software layer. Refer to
                 {@link android.view.View#setLayerType(int, android.graphics.Paint) for
                 more information. -->
            <enum name="software" value="1" />
            <!-- Use a hardware layer. Refer to
                 {@link android.view.View#setLayerType(int, android.graphics.Paint) for
                 more information. -->
            <enum name="hardware" value="2" />
        </attr>
    </declare-styleable>

    <!-- Attributes that can be used with a {@link android.view.ViewGroup} or any
Loading