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

Commit 5be3647a authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Propagate density through AdaptiveIconDrawable and BitmapDrawable" into oc-dev

parents faf37bab 50954d2b
Loading
Loading
Loading
Loading
+13 −39
Original line number Diff line number Diff line
@@ -815,14 +815,7 @@ public class Resources {
     */
    public Drawable getDrawable(@DrawableRes int id, @Nullable Theme theme)
            throws NotFoundException {
        final TypedValue value = obtainTempTypedValue();
        try {
            final ResourcesImpl impl = mResourcesImpl;
            impl.getValue(id, value, true);
            return impl.loadDrawable(this, value, id, theme, true);
        } finally {
            releaseTempTypedValue(value);
        }
        return getDrawableForDensity(id, 0, theme);
    }

    /**
@@ -844,7 +837,9 @@ public class Resources {
     *            This integer encodes the package, type, and resource entry.
     *            The value 0 is an invalid identifier.
     * @param density the desired screen density indicated by the resource as
     *            found in {@link DisplayMetrics}.
     *            found in {@link DisplayMetrics}. A value of 0 means to use the
     *            density returned from {@link #getConfiguration()}.
     *            This is equivalent to calling {@link #getDrawable(int)}.
     * @return Drawable An object that can be used to draw this resource.
     * @throws NotFoundException Throws NotFoundException if the given ID does
     *             not exist.
@@ -865,7 +860,9 @@ public class Resources {
     *            This integer encodes the package, type, and resource entry.
     *            The value 0 is an invalid identifier.
     * @param density The desired screen density indicated by the resource as
     *            found in {@link DisplayMetrics}.
     *            found in {@link DisplayMetrics}. A value of 0 means to use the
     *            density returned from {@link #getConfiguration()}.
     *            This is equivalent to calling {@link #getDrawable(int, Theme)}.
     * @param theme The theme used to style the drawable attributes, may be {@code null}.
     * @return Drawable An object that can be used to draw this resource.
     * @throws NotFoundException Throws NotFoundException if the given ID does
@@ -876,37 +873,16 @@ public class Resources {
        try {
            final ResourcesImpl impl = mResourcesImpl;
            impl.getValueForDensity(id, density, value, true);

            // If the drawable's XML lives in our current density qualifier,
            // it's okay to use a scaled version from the cache. Otherwise, we
            // need to actually load the drawable from XML.
            final DisplayMetrics metrics = impl.getDisplayMetrics();
            final boolean useCache = value.density == metrics.densityDpi;

            /*
             * Pretend the requested density is actually the display density. If
             * the drawable returned is not the requested density, then force it
             * to be scaled later by dividing its density by the ratio of
             * requested density to actual device density. Drawables that have
             * undefined density or no density don't need to be handled here.
             */
            if (value.density > 0 && value.density != TypedValue.DENSITY_NONE) {
                if (value.density == density) {
                    value.density = metrics.densityDpi;
                } else {
                    value.density = (value.density * metrics.densityDpi) / density;
                }
            }
            return impl.loadDrawable(this, value, id, theme, useCache);
            return impl.loadDrawable(this, value, id, density, theme);
        } finally {
            releaseTempTypedValue(value);
        }
    }

    @NonNull
    Drawable loadDrawable(@NonNull TypedValue value, int id, @Nullable Theme theme)
    Drawable loadDrawable(@NonNull TypedValue value, int id, int density, @Nullable Theme theme)
            throws NotFoundException {
        return mResourcesImpl.loadDrawable(this, value, id, theme, true);
        return mResourcesImpl.loadDrawable(this, value, id, density, theme);
    }

    /**
@@ -1221,8 +1197,7 @@ public class Resources {
     * used to open drawable, sound, and raw resources; it will fail on string
     * and color resources.
     * 
     * @param id The resource identifier to open, as generated by the appt
     *           tool.
     * @param id The resource identifier to open, as generated by the aapt tool.
     * 
     * @return InputStream Access to the resource data.
     *
@@ -1278,7 +1253,7 @@ public class Resources {
     * used to open drawable, sound, and raw resources; it will fail on string
     * and color resources.
     *
     * @param id The resource identifier to open, as generated by the appt tool.
     * @param id The resource identifier to open, as generated by the aapt tool.
     * @param value The TypedValue object to hold the resource information.
     *
     * @return InputStream Access to the resource data.
@@ -1300,8 +1275,7 @@ public class Resources {
     * as uncompressed data, which typically includes things like mp3 files
     * and png images.
     * 
     * @param id The resource identifier to open, as generated by the appt
     *           tool.
     * @param id The resource identifier to open, as generated by the aapt tool.
     * 
     * @return AssetFileDescriptor A new file descriptor you can use to read
     * the resource.  This includes the file descriptor itself, as well as the
+25 −6
Original line number Diff line number Diff line
@@ -523,8 +523,27 @@ public class ResourcesImpl {
    }

    @Nullable
    Drawable loadDrawable(Resources wrapper, TypedValue value, int id, Resources.Theme theme,
            boolean useCache) throws NotFoundException {
    Drawable loadDrawable(@NonNull Resources wrapper, @NonNull TypedValue value, int id,
            int density, @Nullable Resources.Theme theme)
            throws NotFoundException {
        // If the drawable's XML lives in our current density qualifier,
        // it's okay to use a scaled version from the cache. Otherwise, we
        // need to actually load the drawable from XML.
        final boolean useCache = density == 0 || value.density == mMetrics.densityDpi;

        // Pretend the requested density is actually the display density. If
        // the drawable returned is not the requested density, then force it
        // to be scaled later by dividing its density by the ratio of
        // requested density to actual device density. Drawables that have
        // undefined density or no density don't need to be handled here.
        if (density > 0 && value.density > 0 && value.density != TypedValue.DENSITY_NONE) {
            if (value.density == density) {
                value.density = mMetrics.densityDpi;
            } else {
                value.density = (value.density * mMetrics.densityDpi) / density;
            }
        }

        try {
            if (TRACE_FOR_PRELOAD) {
                // Log only framework resources
@@ -576,7 +595,7 @@ public class ResourcesImpl {
            } else if (isColorDrawable) {
                dr = new ColorDrawable(value.data);
            } else {
                dr = loadDrawableForCookie(wrapper, value, id, null);
                dr = loadDrawableForCookie(wrapper, value, id, density, null);
            }

            // Determine if the drawable has unresolved theme attributes. If it
@@ -691,8 +710,8 @@ public class ResourcesImpl {
    /**
     * Loads a drawable from XML or resources stream.
     */
    private Drawable loadDrawableForCookie(Resources wrapper, TypedValue value, int id,
            Resources.Theme theme) {
    private Drawable loadDrawableForCookie(@NonNull Resources wrapper, @NonNull TypedValue value,
            int id, int density, @Nullable Resources.Theme theme) {
        if (value.string == null) {
            throw new NotFoundException("Resource \"" + getResourceName(id) + "\" ("
                    + Integer.toHexString(id) + ") is not a Drawable (color or path): " + value);
@@ -722,7 +741,7 @@ public class ResourcesImpl {
            if (file.endsWith(".xml")) {
                final XmlResourceParser rp = loadXmlResourceParser(
                        file, id, value.assetCookie, "drawable");
                dr = Drawable.createFromXml(wrapper, rp, theme);
                dr = Drawable.createFromXmlForDensity(wrapper, rp, density, theme);
                rp.close();
            } else {
                final InputStream is = mAssets.openNonAsset(
+16 −1
Original line number Diff line number Diff line
@@ -923,6 +923,15 @@ public class TypedArray {
     */
    @Nullable
    public Drawable getDrawable(@StyleableRes int index) {
        return getDrawableForDensity(index, 0);
    }

    /**
     * Version of {@link #getDrawable(int)} that accepts an override density.
     * @hide
     */
    @Nullable
    public Drawable getDrawableForDensity(@StyleableRes int index, int density) {
        if (mRecycled) {
            throw new RuntimeException("Cannot make calls to a recycled instance!");
        }
@@ -933,7 +942,13 @@ public class TypedArray {
                throw new UnsupportedOperationException(
                        "Failed to resolve attribute at index " + index + ": " + value);
            }
            return mResources.loadDrawable(value, value.resourceId, mTheme);

            if (density > 0) {
                // If the density is overridden, the value in the TypedArray will not reflect this.
                // Do a separate lookup of the resourceId with the density override.
                mResources.getValueForDensity(value.resourceId, density, value, true);
            }
            return mResources.loadDrawable(value, value.resourceId, density, mTheme);
        }
        return null;
    }
+17 −8
Original line number Diff line number Diff line
@@ -16,8 +16,6 @@

package android.graphics.drawable;

import static android.graphics.drawable.Drawable.obtainAttributes;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
@@ -218,14 +216,16 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback

        // The density may have changed since the last update. This will
        // apply scaling to any existing constant state properties.
        final int density = Drawable.resolveDensity(r, 0);
        state.setDensity(density);
        final int deviceDensity = Drawable.resolveDensity(r, 0);
        state.setDensity(deviceDensity);
        state.mSrcDensityOverride = mSrcDensityOverride;

        final ChildDrawable[] array = state.mChildren;
        for (int i = 0; i < state.mChildren.length; i++) {
            final ChildDrawable layer = array[i];
            layer.setDensity(density);
            layer.setDensity(deviceDensity);
        }

        inflateLayers(r, parser, attrs, theme);
    }

@@ -444,7 +444,7 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback
    /**
     * Inflates child layers using the specified parser.
     */
    void inflateLayers(@NonNull Resources r, @NonNull XmlPullParser parser,
    private void inflateLayers(@NonNull Resources r, @NonNull XmlPullParser parser,
            @NonNull AttributeSet attrs, @Nullable Theme theme)
            throws XmlPullParserException, IOException {
        final LayerState state = mLayerState;
@@ -491,7 +491,8 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback
                }

                // We found a child drawable. Take ownership.
                layer.mDrawable = Drawable.createFromXmlInner(r, parser, attrs, theme);
                layer.mDrawable = Drawable.createFromXmlInnerForDensity(r, parser, attrs,
                        mLayerState.mSrcDensityOverride, theme);
                layer.mDrawable.setCallback(this);
                state.mChildrenChangingConfigurations |=
                        layer.mDrawable.getChangingConfigurations();
@@ -509,7 +510,8 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback
        // Extract the theme attributes, if any.
        layer.mThemeAttrs = a.extractThemeAttrs();

        Drawable dr = a.getDrawable(R.styleable.AdaptiveIconDrawableLayer_drawable);
        Drawable dr = a.getDrawableForDensity(R.styleable.AdaptiveIconDrawableLayer_drawable,
                state.mSrcDensityOverride);
        if (dr != null) {
            if (layer.mDrawable != null) {
                // It's possible that a drawable was already set, in which case
@@ -951,7 +953,13 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback
        final static int N_CHILDREN = 2;
        ChildDrawable[] mChildren;

        // The density at which to render the drawable and its children.
        int mDensity;

        // The density to use when inflating/looking up the children drawables. A value of 0 means
        // use the system's density.
        int mSrcDensityOverride = 0;

        int mOpacityOverride = PixelFormat.UNKNOWN;

        @Config int mChangingConfigurations;
@@ -986,6 +994,7 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback
                mAutoMirrored = orig.mAutoMirrored;
                mThemeAttrs = orig.mThemeAttrs;
                mOpacityOverride = orig.mOpacityOverride;
                mSrcDensityOverride = orig.mSrcDensityOverride;
            } else {
                for (int i = 0; i < N_CHILDREN; i++) {
                    mChildren[i] = new ChildDrawable(mDensity);
+43 −8
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import android.graphics.Xfermode;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.LayoutDirection;
import android.util.TypedValue;
import android.view.Gravity;

import com.android.internal.R;
@@ -49,6 +50,7 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.io.InputStream;

/**
 * A Drawable that wraps a bitmap and can be tiled, stretched, or aligned. You can create a
@@ -749,7 +751,7 @@ public class BitmapDrawable extends Drawable {
        super.inflate(r, parser, attrs, theme);

        final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.BitmapDrawable);
        updateStateFromTypedArray(a);
        updateStateFromTypedArray(a, mSrcDensityOverride);
        verifyRequiredAttributes(a);
        a.recycle();

@@ -775,7 +777,8 @@ public class BitmapDrawable extends Drawable {
    /**
     * Updates the constant state from the values in the typed array.
     */
    private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserException {
    private void updateStateFromTypedArray(TypedArray a, int srcDensityOverride)
            throws XmlPullParserException {
        final Resources r = a.getResources();
        final BitmapState state = mBitmapState;

@@ -785,9 +788,37 @@ public class BitmapDrawable extends Drawable {
        // Extract the theme attributes, if any.
        state.mThemeAttrs = a.extractThemeAttrs();

        state.mSrcDensityOverride = srcDensityOverride;

        state.mTargetDensity = Drawable.resolveDensity(r, 0);

        final int srcResId = a.getResourceId(R.styleable.BitmapDrawable_src, 0);
        if (srcResId != 0) {
            final Bitmap bitmap = BitmapFactory.decodeResource(r, srcResId);
            final TypedValue value = new TypedValue();
            r.getValueForDensity(srcResId, srcDensityOverride, value, true);

            // Pretend the requested density is actually the display density. If
            // the drawable returned is not the requested density, then force it
            // to be scaled later by dividing its density by the ratio of
            // requested density to actual device density. Drawables that have
            // undefined density or no density don't need to be handled here.
            if (srcDensityOverride > 0 && value.density > 0
                    && value.density != TypedValue.DENSITY_NONE) {
                if (value.density == srcDensityOverride) {
                    value.density = r.getDisplayMetrics().densityDpi;
                } else {
                    value.density =
                            (value.density * r.getDisplayMetrics().densityDpi) / srcDensityOverride;
                }
            }

            Bitmap bitmap = null;
            try (InputStream is = r.openRawResource(srcResId, value)) {
                bitmap = BitmapFactory.decodeResourceStream(r, value, is, null, null);
            } catch (Exception e) {
                // Do nothing and pick up the error below.
            }

            if (bitmap == null) {
                throw new XmlPullParserException(a.getPositionDescription() +
                        ": <bitmap> requires a valid 'src' attribute");
@@ -796,8 +827,6 @@ public class BitmapDrawable extends Drawable {
            state.mBitmap = bitmap;
        }

        state.mTargetDensity = r.getDisplayMetrics().densityDpi;

        final boolean defMipMap = state.mBitmap != null ? state.mBitmap.hasMipMap() : false;
        setMipMap(a.getBoolean(R.styleable.BitmapDrawable_mipMap, defMipMap));

@@ -839,8 +868,6 @@ public class BitmapDrawable extends Drawable {
        if (tileModeY != TILE_MODE_UNDEFINED) {
            setTileModeY(parseTileMode(tileModeY));
        }

        state.mTargetDensity = Drawable.resolveDensity(r, 0);
    }

    @Override
@@ -855,7 +882,7 @@ public class BitmapDrawable extends Drawable {
        if (state.mThemeAttrs != null) {
            final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.BitmapDrawable);
            try {
                updateStateFromTypedArray(a);
                updateStateFromTypedArray(a, state.mSrcDensityOverride);
            } catch (XmlPullParserException e) {
                rethrowAsRuntimeException(e);
            } finally {
@@ -929,7 +956,14 @@ public class BitmapDrawable extends Drawable {
        float mBaseAlpha = 1.0f;
        Shader.TileMode mTileModeX = null;
        Shader.TileMode mTileModeY = null;

        // The density to use when looking up the bitmap in Resources. A value of 0 means use
        // the system's density.
        int mSrcDensityOverride = 0;

        // The density at which to render the bitmap.
        int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;

        boolean mAutoMirrored = false;

        @Config int mChangingConfigurations;
@@ -949,6 +983,7 @@ public class BitmapDrawable extends Drawable {
            mGravity = bitmapState.mGravity;
            mTileModeX = bitmapState.mTileModeX;
            mTileModeY = bitmapState.mTileModeY;
            mSrcDensityOverride = bitmapState.mSrcDensityOverride;
            mTargetDensity = bitmapState.mTargetDensity;
            mBaseAlpha = bitmapState.mBaseAlpha;
            mPaint = new Paint(bitmapState.mPaint);
Loading