Merge "Revert "Use ImageDecoder for NinePatchDrawable and BitmapDrawable""
This commit is contained in:
committed by
Android (Google) Code Review
commit
72698e6f39
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,21 +165,10 @@ 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);
|
||||
if (mBitmapState.mBitmap == null) {
|
||||
android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath);
|
||||
}
|
||||
this(new BitmapState(BitmapFactory.decodeFile(filepath)), null);
|
||||
mBitmapState.mTargetDensity = mTargetDensity;
|
||||
if (mBitmapState.mBitmap == null) {
|
||||
android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,21 +190,10 @@ 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);
|
||||
if (mBitmapState.mBitmap == null) {
|
||||
android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is);
|
||||
}
|
||||
this(new BitmapState(BitmapFactory.decodeStream(is)), null);
|
||||
mBitmapState.mTargetDensity = mTargetDensity;
|
||||
if (mBitmapState.mBitmap == null) {
|
||||
android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user