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

Commit ac9c8f7c authored by Leon Scroggins III's avatar Leon Scroggins III
Browse files

Revert "Use ImageDecoder for NinePatchDrawable and BitmapDrawable"

Test: CTS tests

This reverts commit 5aec67ca.

Reason for revert: b/73166619

Bug: 73166619
Change-Id: Ic8b2a83abf5567119c8b6af1ec00445a5a6a9cc2
parent 90f285ba
Loading
Loading
Loading
Loading
+2 −35
Original line number Diff line number Diff line
@@ -23,10 +23,6 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
@@ -400,33 +396,6 @@ public final class PointerIcon implements Parcelable {
        return true;
    }

    /**
     *  Get the Bitmap from the Drawable.
     *
     *  If the Bitmap needed to be scaled up to account for density, BitmapDrawable
     *  handles this at draw time. But this class doesn't actually draw the Bitmap;
     *  it is just a holder for native code to access its SkBitmap. So this needs to
     *  get a version that is scaled to account for density.
     */
    private Bitmap getBitmapFromDrawable(BitmapDrawable bitmapDrawable) {
        Bitmap bitmap = bitmapDrawable.getBitmap();
        final int scaledWidth  = bitmapDrawable.getIntrinsicWidth();
        final int scaledHeight = bitmapDrawable.getIntrinsicHeight();
        if (scaledWidth == bitmap.getWidth() && scaledHeight == bitmap.getHeight()) {
            return bitmap;
        }

        Rect src = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        RectF dst = new RectF(0, 0, scaledWidth, scaledHeight);

        Bitmap scaled = Bitmap.createBitmap(scaledWidth, scaledHeight, bitmap.getConfig());
        Canvas canvas = new Canvas(scaled);
        Paint paint = new Paint();
        paint.setFilterBitmap(true);
        canvas.drawBitmap(bitmap, src, dst, paint);
        return scaled;
    }

    private void loadResource(Context context, Resources resources, @XmlRes int resourceId) {
        final XmlResourceParser parser = resources.getXml(resourceId);
        final int bitmapRes;
@@ -483,8 +452,7 @@ public final class PointerIcon implements Parcelable {
                                + "is different. All frames should have the exact same size and "
                                + "share the same hotspot.");
                    }
                    BitmapDrawable bitmapDrawableFrame = (BitmapDrawable) drawableFrame;
                    mBitmapFrames[i - 1] = getBitmapFromDrawable(bitmapDrawableFrame);
                    mBitmapFrames[i - 1] = ((BitmapDrawable)drawableFrame).getBitmap();
                }
            }
        }
@@ -493,8 +461,7 @@ public final class PointerIcon implements Parcelable {
                    + "refer to a bitmap drawable.");
        }

        BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
        final Bitmap bitmap = getBitmapFromDrawable(bitmapDrawable);
        final Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
        validateHotSpot(bitmap, hotSpotX, hotSpotY);
        // Set the properties now that we have successfully loaded the icon.
        mBitmap = bitmap;
+2 −26
Original line number Diff line number Diff line
@@ -444,7 +444,6 @@ public final class ImageDecoder implements AutoCloseable {
    private boolean mPreferRamOverQuality = false;
    private boolean mAsAlphaMask = false;
    private Rect    mCropRect;
    private Rect    mOutPaddingRect;
    private Source  mSource;

    private PostProcessor          mPostProcessor;
@@ -782,18 +781,6 @@ public final class ImageDecoder implements AutoCloseable {
        mCropRect = subset;
    }

    /**
     *  Set a Rect for retrieving nine patch padding.
     *
     *  If the image is a nine patch, this Rect will be set to the padding
     *  rectangle during decode. Otherwise it will not be modified.
     *
     *  @hide
     */
    public void setOutPaddingRect(@NonNull Rect outPadding) {
        mOutPaddingRect = outPadding;
    }

    /**
     *  Specify whether the {@link Bitmap} should be mutable.
     *
@@ -905,6 +892,7 @@ public final class ImageDecoder implements AutoCloseable {
                postProcessPtr, mDesiredWidth, mDesiredHeight, mCropRect,
                mMutable, mAllocator, mRequireUnpremultiplied,
                mPreferRamOverQuality, mAsAlphaMask);

    }

    private void callHeaderDecoded(@Nullable OnHeaderDecodedListener listener,
@@ -977,10 +965,7 @@ public final class ImageDecoder implements AutoCloseable {
            if (np != null && NinePatch.isNinePatchChunk(np)) {
                Rect opticalInsets = new Rect();
                bm.getOpticalInsets(opticalInsets);
                Rect padding = decoder.mOutPaddingRect;
                if (padding == null) {
                    padding = new Rect();
                }
                Rect padding = new Rect();
                nGetPadding(decoder.mNativePtr, padding);
                return new NinePatchDrawable(res, bm, np, padding,
                        opticalInsets, null);
@@ -1023,15 +1008,6 @@ public final class ImageDecoder implements AutoCloseable {
            final int srcDensity = computeDensity(src, decoder);
            Bitmap bm = decoder.decodeBitmap();
            bm.setDensity(srcDensity);

            Rect padding = decoder.mOutPaddingRect;
            if (padding != null) {
                byte[] np = bm.getNinePatchChunk();
                if (np != null && NinePatch.isNinePatchChunk(np)) {
                    nGetPadding(decoder.mNativePtr, padding);
                }
            }

            return bm;
        }
    }
+26 −59
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.ImageDecoder;
import android.graphics.Insets;
import android.graphics.Matrix;
import android.graphics.Outline;
@@ -50,7 +49,6 @@ import com.android.internal.R;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

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

@@ -113,7 +111,7 @@ public class BitmapDrawable extends Drawable {
     */
    @Deprecated
    public BitmapDrawable() {
        init(new BitmapState((Bitmap) null), null);
        mBitmapState = new BitmapState((Bitmap) null);
    }

    /**
@@ -126,7 +124,8 @@ public class BitmapDrawable extends Drawable {
    @SuppressWarnings("unused")
    @Deprecated
    public BitmapDrawable(Resources res) {
        init(new BitmapState((Bitmap) null), res);
        mBitmapState = new BitmapState((Bitmap) null);
        mBitmapState.mTargetDensity = mTargetDensity;
    }

    /**
@@ -136,7 +135,7 @@ public class BitmapDrawable extends Drawable {
     */
    @Deprecated
    public BitmapDrawable(Bitmap bitmap) {
        init(new BitmapState(bitmap), null);
        this(new BitmapState(bitmap), null);
    }

    /**
@@ -144,7 +143,8 @@ public class BitmapDrawable extends Drawable {
     * the display metrics of the resources.
     */
    public BitmapDrawable(Resources res, Bitmap bitmap) {
        init(new BitmapState(bitmap), res);
        this(new BitmapState(bitmap), res);
        mBitmapState.mTargetDensity = mTargetDensity;
    }

    /**
@@ -154,7 +154,10 @@ public class BitmapDrawable extends Drawable {
     */
    @Deprecated
    public BitmapDrawable(String filepath) {
        this(null, filepath);
        this(new BitmapState(BitmapFactory.decodeFile(filepath)), null);
        if (mBitmapState.mBitmap == null) {
            android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath);
        }
    }

    /**
@@ -162,23 +165,12 @@ public class BitmapDrawable extends Drawable {
     */
    @SuppressWarnings({ "unused", "ChainingConstructorIgnoresParameter" })
    public BitmapDrawable(Resources res, String filepath) {
        Bitmap bitmap = null;
        try (FileInputStream stream = new FileInputStream(filepath)) {
            bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(res, stream),
                    (decoder, info, src) -> {
                decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
            });
        } catch (Exception e) {
            /*  do nothing. This matches the behavior of BitmapFactory.decodeFile()
                If the exception happened on decode, mBitmapState.mBitmap will be null.
            */
        } finally {
            init(new BitmapState(bitmap), res);
        this(new BitmapState(BitmapFactory.decodeFile(filepath)), null);
        mBitmapState.mTargetDensity = mTargetDensity;
        if (mBitmapState.mBitmap == null) {
            android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath);
        }
    }
    }

    /**
     * Create a drawable by decoding a bitmap from the given input stream.
@@ -187,7 +179,10 @@ public class BitmapDrawable extends Drawable {
     */
    @Deprecated
    public BitmapDrawable(java.io.InputStream is) {
        this(null, is);
        this(new BitmapState(BitmapFactory.decodeStream(is)), null);
        if (mBitmapState.mBitmap == null) {
            android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is);
        }
    }

    /**
@@ -195,23 +190,12 @@ public class BitmapDrawable extends Drawable {
     */
    @SuppressWarnings({ "unused", "ChainingConstructorIgnoresParameter" })
    public BitmapDrawable(Resources res, java.io.InputStream is) {
        Bitmap bitmap = null;
        try {
            bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(res, is),
                    (decoder, info, src) -> {
                decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
            });
        } catch (Exception e) {
            /*  do nothing. This matches the behavior of BitmapFactory.decodeStream()
                If the exception happened on decode, mBitmapState.mBitmap will be null.
            */
        } finally {
            init(new BitmapState(bitmap), res);
        this(new BitmapState(BitmapFactory.decodeStream(is)), null);
        mBitmapState.mTargetDensity = mTargetDensity;
        if (mBitmapState.mBitmap == null) {
            android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is);
        }
    }
    }

    /**
     * Returns the paint used to render this drawable.
@@ -828,19 +812,9 @@ public class BitmapDrawable extends Drawable {
                }
            }

            int density = Bitmap.DENSITY_NONE;
            if (value.density == TypedValue.DENSITY_DEFAULT) {
                density = DisplayMetrics.DENSITY_DEFAULT;
            } else if (value.density != TypedValue.DENSITY_NONE) {
                density = value.density;
            }

            Bitmap bitmap = null;
            try (InputStream is = r.openRawResource(srcResId, value)) {
                ImageDecoder.Source source = ImageDecoder.createSource(r, is, density);
                bitmap = ImageDecoder.decodeBitmap(source, (decoder, info, src) -> {
                    decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
                });
                bitmap = BitmapFactory.decodeResourceStream(r, value, is, null, null);
            } catch (Exception e) {
                // Do nothing and pick up the error below.
            }
@@ -1039,21 +1013,14 @@ public class BitmapDrawable extends Drawable {
        }
    }

    private BitmapDrawable(BitmapState state, Resources res) {
        init(state, res);
    }

    /**
     * The one helper to rule them all. This is called by all public & private
     * The one constructor to rule them all. This is called by all public
     * constructors to set the state and initialize local properties.
     */
    private void init(BitmapState state, Resources res) {
    private BitmapDrawable(BitmapState state, Resources res) {
        mBitmapState = state;
        updateLocalState(res);

        if (mBitmapState != null && res != null) {
            mBitmapState.mTargetDensity = mTargetDensity;
        }
        updateLocalState(res);
    }

    /**
+6 −38
Original line number Diff line number Diff line
@@ -37,7 +37,6 @@ import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.ImageDecoder;
import android.graphics.Insets;
import android.graphics.NinePatch;
import android.graphics.Outline;
@@ -51,13 +50,11 @@ import android.graphics.Xfermode;
import android.os.Trace;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.StateSet;
import android.util.TypedValue;
import android.util.Xml;
import android.view.View;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
@@ -1182,10 +1179,6 @@ public abstract class Drawable {
            return null;
        }

        if (opts == null) {
            return getBitmapDrawable(res, value, is);
        }

        /*  ugh. The decodeStream contract is that we have already allocated
            the pad rect, but if the bitmap does not had a ninepatch chunk,
            then the pad will be ignored. If we could change this to lazily
@@ -1201,6 +1194,7 @@ public abstract class Drawable {
        // an application in compatibility mode, without scaling those down
        // to the compatibility density only to have them scaled back up when
        // drawn to the screen.
        if (opts == null) opts = new BitmapFactory.Options();
        opts.inScreenDensity = Drawable.resolveDensity(res, 0);
        Bitmap  bm = BitmapFactory.decodeResourceStream(res, value, is, pad, opts);
        if (bm != null) {
@@ -1217,33 +1211,6 @@ public abstract class Drawable {
        return null;
    }

    private static Drawable getBitmapDrawable(Resources res, TypedValue value, InputStream is) {
        try {
            ImageDecoder.Source source = null;
            if (value != null) {
                int density = Bitmap.DENSITY_NONE;
                if (value.density == TypedValue.DENSITY_DEFAULT) {
                    density = DisplayMetrics.DENSITY_DEFAULT;
                } else if (value.density != TypedValue.DENSITY_NONE) {
                    density = value.density;
                }
                source = ImageDecoder.createSource(res, is, density);
            } else {
                source = ImageDecoder.createSource(res, is);
            }

            return ImageDecoder.decodeDrawable(source, (decoder, info, src) -> {
                decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
            });
        } catch (IOException e) {
            /*  do nothing.
                If the exception happened on decode, the drawable will be null.
            */
            Log.e("Drawable", "Unable to decode stream: " + e);
        }
        return null;
    }

    /**
     * Create a drawable from an XML document. For more information on how to
     * create resources in XML, see
@@ -1343,10 +1310,11 @@ public abstract class Drawable {
        }

        Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, pathName);
        try (FileInputStream stream = new FileInputStream(pathName)) {
            return getBitmapDrawable(null, null, stream);
        } catch(IOException e) {
            // Do nothing; we will just return null if the FileInputStream had an error
        try {
            Bitmap bm = BitmapFactory.decodeFile(pathName);
            if (bm != null) {
                return drawableFromBitmap(null, bm, null, null, null, pathName);
            }
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
        }
+7 −14
Original line number Diff line number Diff line
@@ -24,9 +24,9 @@ import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.ImageDecoder;
import android.graphics.Insets;
import android.graphics.NinePatch;
import android.graphics.Outline;
@@ -211,8 +211,7 @@ public class NinePatchDrawable extends Drawable {
            restoreAlpha = -1;
        }

        final boolean needsDensityScaling = canvas.getDensity() == 0
                && Bitmap.DENSITY_NONE != state.mNinePatch.getDensity();
        final boolean needsDensityScaling = canvas.getDensity() == 0;
        if (needsDensityScaling) {
            restoreToCount = restoreToCount >= 0 ? restoreToCount : canvas.save();

@@ -422,6 +421,10 @@ public class NinePatchDrawable extends Drawable {

        final int srcResId = a.getResourceId(R.styleable.NinePatchDrawable_src, 0);
        if (srcResId != 0) {
            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inDither = !state.mDither;
            options.inScreenDensity = r.getDisplayMetrics().noncompatDensityDpi;

            final Rect padding = new Rect();
            final Rect opticalInsets = new Rect();
            Bitmap bitmap = null;
@@ -430,17 +433,7 @@ public class NinePatchDrawable extends Drawable {
                final TypedValue value = new TypedValue();
                final InputStream is = r.openRawResource(srcResId, value);

                int density = Bitmap.DENSITY_NONE;
                if (value.density == TypedValue.DENSITY_DEFAULT) {
                    density = DisplayMetrics.DENSITY_DEFAULT;
                } else if (value.density != TypedValue.DENSITY_NONE) {
                    density = value.density;
                }
                ImageDecoder.Source source = ImageDecoder.createSource(r, is, density);
                bitmap = ImageDecoder.decodeBitmap(source, (decoder, info, src) -> {
                    decoder.setOutPaddingRect(padding);
                    decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
                });
                bitmap = BitmapFactory.decodeResourceStream(r, value, is, padding, options);

                is.close();
            } catch (IOException e) {