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

Commit 256a5f8c authored by Alan Viverette's avatar Alan Viverette Committed by Android (Google) Code Review
Browse files

Merge "Postpone creating new drawables for DrawableContainerState."

parents 4969fecf f390f770
Loading
Loading
Loading
Loading
+224 −101
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.graphics.Insets;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.SystemClock;
import android.util.SparseArray;

/**
 * A helper class that contains several {@link Drawable}s and selects which one to use.
@@ -316,7 +317,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
        }

        if (idx >= 0 && idx < mDrawableContainerState.mNumChildren) {
            Drawable d = mDrawableContainerState.mDrawables[idx];
            final Drawable d = mDrawableContainerState.getChild(idx);
            mCurrDrawable = d;
            mCurIndex = idx;
            if (d != null) {
@@ -432,6 +433,9 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
     */
    public abstract static class DrawableContainerState extends ConstantState {
        final DrawableContainer mOwner;
        final Resources mRes;

        SparseArray<ConstantStateFuture> mDrawableFutures;

        int mChangingConfigurations;
        int mChildrenChangingConfigurations;
@@ -439,80 +443,92 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
        Drawable[] mDrawables;
        int mNumChildren;

        boolean     mVariablePadding = false;
        Rect        mConstantPadding = null;
        boolean mVariablePadding;
        boolean mPaddingChecked;
        Rect mConstantPadding;

        boolean     mConstantSize = false;
        boolean     mComputedConstantSize = false;
        boolean mConstantSize;
        boolean mComputedConstantSize;
        int mConstantWidth;
        int mConstantHeight;
        int mConstantMinimumWidth;
        int mConstantMinimumHeight;

        boolean mCheckedOpacity;
        int mOpacity;

        boolean     mHaveStateful = false;
        boolean mCheckedStateful;
        boolean mStateful;

        boolean mCheckedConstantState;
        boolean mCanConstantState;

        boolean     mPaddingChecked = false;
        
        boolean mDither = DEFAULT_DITHER;

        boolean mMutated;
        int mLayoutDirection;

        int mEnterFadeDuration;
        int mExitFadeDuration;

        DrawableContainerState(DrawableContainerState orig, DrawableContainer owner,
                Resources res) {
            mOwner = owner;
            mRes = res;

            if (orig != null) {
                mChangingConfigurations = orig.mChangingConfigurations;
                mChildrenChangingConfigurations = orig.mChildrenChangingConfigurations;

                final Drawable[] origDr = orig.mDrawables;
                mCheckedConstantState = true;
                mCanConstantState = true;

                mVariablePadding = orig.mVariablePadding;
                mConstantSize = orig.mConstantSize;
                mDither = orig.mDither;
                mMutated = orig.mMutated;
                mLayoutDirection = orig.mLayoutDirection;
                mEnterFadeDuration = orig.mEnterFadeDuration;
                mExitFadeDuration = orig.mExitFadeDuration;

                // Cloning the following values may require creating futures.
                mConstantPadding = orig.getConstantPadding();
                mPaddingChecked = true;

                mConstantWidth = orig.getConstantWidth();
                mConstantHeight = orig.getConstantHeight();
                mConstantMinimumWidth = orig.getConstantMinimumWidth();
                mConstantMinimumHeight = orig.getConstantMinimumHeight();
                mComputedConstantSize = true;

                mOpacity = orig.getOpacity();
                mCheckedOpacity = true;

                mStateful = orig.isStateful();
                mCheckedStateful = true;

                // Postpone cloning children and futures until we're absolutely
                // sure that we're done computing values for the original state.
                final Drawable[] origDr = orig.mDrawables;
                mDrawables = new Drawable[origDr.length];
                mNumChildren = orig.mNumChildren;

                final int N = mNumChildren;
                for (int i=0; i<N; i++) {
                    if (res != null) {
                        mDrawables[i] = origDr[i].getConstantState().newDrawable(res);
                final SparseArray<ConstantStateFuture> origDf = orig.mDrawableFutures;
                if (origDf != null) {
                    mDrawableFutures = origDf.clone();
                } else {
                        mDrawables[i] = origDr[i].getConstantState().newDrawable();
                    }
                    mDrawables[i].setCallback(owner);
                    mDrawables[i].setLayoutDirection(origDr[i].getLayoutDirection());
                    mDrawableFutures = new SparseArray<ConstantStateFuture>(mNumChildren);
                }

                mCheckedConstantState = mCanConstantState = true;
                mVariablePadding = orig.mVariablePadding;
                if (orig.mConstantPadding != null) {
                    mConstantPadding = new Rect(orig.mConstantPadding);
                final int N = mNumChildren;
                for (int i = 0; i < N; i++) {
                    if (origDr[i] != null) {
                        mDrawableFutures.put(i, new ConstantStateFuture(origDr[i]));
                    }
                }
                mConstantSize = orig.mConstantSize;
                mComputedConstantSize = orig.mComputedConstantSize;
                mConstantWidth = orig.mConstantWidth;
                mConstantHeight = orig.mConstantHeight;
                mConstantMinimumWidth = orig.mConstantMinimumWidth;
                mConstantMinimumHeight = orig.mConstantMinimumHeight;
                
                mOpacity = orig.mOpacity;
                mHaveStateful = orig.mHaveStateful;
                mStateful = orig.mStateful;
                
                mDither = orig.mDither;

                mEnterFadeDuration = orig.mEnterFadeDuration;
                mExitFadeDuration = orig.mExitFadeDuration;

            } else {
                mDrawables = new Drawable[10];
                mNumChildren = 0;
                mCheckedConstantState = mCanConstantState = false;
            }
        }

@@ -534,7 +550,8 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
            mDrawables[pos] = dr;
            mNumChildren++;
            mChildrenChangingConfigurations |= dr.getChangingConfigurations();
            mHaveStateful = false;
            mCheckedStateful = false;
            mCheckedOpacity = false;

            mConstantPadding = null;
            mPaddingChecked = false;
@@ -547,6 +564,18 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
            return mDrawables.length;
        }

        private final void createAllFutures() {
            if (mDrawableFutures != null) {
                final int futureCount = mDrawableFutures.size();
                for (int keyIndex = 0; keyIndex < futureCount; keyIndex++) {
                    final int index = mDrawableFutures.keyAt(keyIndex);
                    mDrawables[index] = mDrawableFutures.valueAt(keyIndex).get(this);
                }

                mDrawableFutures = null;
            }
        }

        public final int getChildCount() {
            return mNumChildren;
        }
@@ -555,24 +584,64 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
         * @deprecated Use {@link #getChild} instead.
         */
        public final Drawable[] getChildren() {
            // Create all futures for backwards compatibility.
            createAllFutures();

            return mDrawables;
        }

        public final Drawable getChild(int index) {
            return mDrawables[index];
            final Drawable result = mDrawables[index];
            if (result != null) {
                return result;
            }

            // Prepare future drawable if necessary.
            if (mDrawableFutures != null) {
                final int keyIndex = mDrawableFutures.indexOfKey(index);
                if (keyIndex >= 0) {
                    final Drawable prepared = mDrawableFutures.valueAt(keyIndex).get(this);
                    mDrawables[index] = prepared;
                    mDrawableFutures.removeAt(keyIndex);
                    return prepared;
                }
            }

            return null;
        }

        final void setLayoutDirection(int layoutDirection) {
            // No need to call createAllFutures, since future drawables will
            // change layout direction when they are prepared.
            final int N = mNumChildren;
            final Drawable[] drawables = mDrawables;
            for (int i = 0; i < N; i++) {
                if (drawables[i] != null) {
                    drawables[i].setLayoutDirection(layoutDirection);
                }
            }

            mLayoutDirection = layoutDirection;
        }

        final void mutate() {
            final int N = getChildCount();
            // No need to call createAllFutures, since future drawables will
            // mutate when they are prepared.
            final int N = mNumChildren;
            final Drawable[] drawables = mDrawables;
            for (int i = 0; i < N; i++) {
                if (drawables[i] != null) drawables[i].mutate();
                if (drawables[i] != null) {
                    drawables[i].mutate();
                }
            }

        /** A boolean value indicating whether to use the maximum padding value of 
          * all frames in the set (false), or to use the padding value of the frame 
          * being shown (true). Default value is false. 
            mMutated = true;
        }

        /**
         * A boolean value indicating whether to use the maximum padding value
         * of all frames in the set (false), or to use the padding value of the
         * frame being shown (true). Default value is false.
         */
        public final void setVariablePadding(boolean variable) {
            mVariablePadding = variable;
@@ -582,13 +651,16 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
            if (mVariablePadding) {
                return null;
            }
            if (mConstantPadding != null || mPaddingChecked) {

            if ((mConstantPadding != null) || mPaddingChecked) {
                return mConstantPadding;
            }

            createAllFutures();

            Rect r = null;
            final Rect t = new Rect();
            final int N = getChildCount();
            final int N = mNumChildren;
            final Drawable[] drawables = mDrawables;
            for (int i = 0; i < N; i++) {
                if (drawables[i].getPadding(t)) {
@@ -599,6 +671,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
                    if (t.bottom > r.bottom) r.bottom = t.bottom;
                }
            }

            mPaddingChecked = true;
            return (mConstantPadding = r);
        }
@@ -646,12 +719,14 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
        protected void computeConstantSize() {
            mComputedConstantSize = true;

            final int N = getChildCount();
            createAllFutures();

            final int N = mNumChildren;
            final Drawable[] drawables = mDrawables;
            mConstantWidth = mConstantHeight = -1;
            mConstantMinimumWidth = mConstantMinimumHeight = 0;
            for (int i = 0; i < N; i++) {
                Drawable dr = drawables[i];
                final Drawable dr = drawables[i];
                int s = dr.getIntrinsicWidth();
                if (s > mConstantWidth) mConstantWidth = s;
                s = dr.getIntrinsicHeight();
@@ -680,33 +755,45 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
        }

        public final int getOpacity() {
            final int N = getChildCount();
            if (mCheckedOpacity) {
                return mOpacity;
            }

            createAllFutures();

            mCheckedOpacity = true;

            final int N = mNumChildren;
            final Drawable[] drawables = mDrawables;
            int op = N > 0 ? drawables[0].getOpacity() : PixelFormat.TRANSPARENT;
            int op = (N > 0) ? drawables[0].getOpacity() : PixelFormat.TRANSPARENT;
            for (int i = 1; i < N; i++) {
                op = Drawable.resolveOpacity(op, drawables[i].getOpacity());
            }

            mOpacity = op;
            return op;
        }

        public final boolean isStateful() {
            if (mHaveStateful) {
            if (mCheckedStateful) {
                return mStateful;
            }

            boolean stateful = false;
            final int N = getChildCount();
            createAllFutures();

            mCheckedStateful = true;

            final int N = mNumChildren;
            final Drawable[] drawables = mDrawables;
            for (int i = 0; i < N; i++) {
                if (mDrawables[i].isStateful()) {
                    stateful = true;
                    break;
                if (drawables[i].isStateful()) {
                    mStateful = true;
                    return true;
                }
            }

            mStateful = stateful;
            mHaveStateful = true;
            return stateful;
            mStateful = false;
            return false;
        }

        public void growArray(int oldSize, int newSize) {
@@ -716,24 +803,60 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
        }

        public synchronized boolean canConstantState() {
            if (!mCheckedConstantState) {
                mCanConstantState = true;
            if (mCheckedConstantState) {
                return mCanConstantState;
            }

            createAllFutures();

            mCheckedConstantState = true;

            final int N = mNumChildren;
            final Drawable[] drawables = mDrawables;
            for (int i = 0; i < N; i++) {
                    if (mDrawables[i].getConstantState() == null) {
                if (drawables[i].getConstantState() == null) {
                    mCanConstantState = false;
                        break;
                    return false;
                }
            }
                mCheckedConstantState = true;

            mCanConstantState = true;
            return true;
        }

            return mCanConstantState;
        /**
         * Class capable of cloning a Drawable from another Drawable's
         * ConstantState.
         */
        private static class ConstantStateFuture {
            private final ConstantState mConstantState;

            private ConstantStateFuture(Drawable source) {
                mConstantState = source.getConstantState();
            }

            /**
             * Obtains and prepares the Drawable represented by this future.
             *
             * @param state the container into which this future will be placed
             * @return a prepared Drawable
             */
            public Drawable get(DrawableContainerState state) {
                final Drawable result = (state.mRes == null) ?
                        mConstantState.newDrawable() : mConstantState.newDrawable(state.mRes);
                result.setLayoutDirection(state.mLayoutDirection);
                result.setCallback(state.mOwner);

                if (state.mMutated) {
                    result.mutate();
                }

                return result;
            }
        }
    }

    protected void setConstantState(DrawableContainerState state)
    {
    protected void setConstantState(DrawableContainerState state) {
        mDrawableContainerState = state;
    }
}
+4 −4
Original line number Diff line number Diff line
@@ -264,11 +264,11 @@ public class StateListDrawable extends DrawableContainer {
    /** @hide */
    @Override
    public void setLayoutDirection(int layoutDirection) {
        final int numStates = getStateCount();
        for (int i = 0; i < numStates; i++) {
            getStateDrawable(i).setLayoutDirection(layoutDirection);
        }
        super.setLayoutDirection(layoutDirection);

        // Let the container handle setting its own layout direction. Otherwise,
        // we're accessing potentially unused states.
        mStateListState.setLayoutDirection(layoutDirection);
    }

    static final class StateListState extends DrawableContainerState {