Merge "Fix NinePatchDrawable handling of density changes" into nyc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
5f8e0603e6
@@ -11947,6 +11947,8 @@ package android.graphics {
|
||||
ctor public Outline(android.graphics.Outline);
|
||||
method public boolean canClip();
|
||||
method public float getAlpha();
|
||||
method public float getRadius();
|
||||
method public boolean getRect(android.graphics.Rect);
|
||||
method public boolean isEmpty();
|
||||
method public void offset(int, int);
|
||||
method public void set(android.graphics.Outline);
|
||||
@@ -12974,12 +12976,10 @@ package android.graphics.drawable {
|
||||
ctor public deprecated NinePatchDrawable(android.graphics.NinePatch);
|
||||
ctor public NinePatchDrawable(android.content.res.Resources, android.graphics.NinePatch);
|
||||
method public void draw(android.graphics.Canvas);
|
||||
method public android.graphics.NinePatch getNinePatch();
|
||||
method public int getOpacity();
|
||||
method public android.graphics.Paint getPaint();
|
||||
method public void setAlpha(int);
|
||||
method public void setColorFilter(android.graphics.ColorFilter);
|
||||
method public void setNinePatch(android.graphics.NinePatch);
|
||||
method public void setTargetDensity(android.graphics.Canvas);
|
||||
method public void setTargetDensity(android.util.DisplayMetrics);
|
||||
method public void setTargetDensity(int);
|
||||
|
||||
@@ -12357,6 +12357,8 @@ package android.graphics {
|
||||
ctor public Outline(android.graphics.Outline);
|
||||
method public boolean canClip();
|
||||
method public float getAlpha();
|
||||
method public float getRadius();
|
||||
method public boolean getRect(android.graphics.Rect);
|
||||
method public boolean isEmpty();
|
||||
method public void offset(int, int);
|
||||
method public void set(android.graphics.Outline);
|
||||
@@ -13384,12 +13386,10 @@ package android.graphics.drawable {
|
||||
ctor public deprecated NinePatchDrawable(android.graphics.NinePatch);
|
||||
ctor public NinePatchDrawable(android.content.res.Resources, android.graphics.NinePatch);
|
||||
method public void draw(android.graphics.Canvas);
|
||||
method public android.graphics.NinePatch getNinePatch();
|
||||
method public int getOpacity();
|
||||
method public android.graphics.Paint getPaint();
|
||||
method public void setAlpha(int);
|
||||
method public void setColorFilter(android.graphics.ColorFilter);
|
||||
method public void setNinePatch(android.graphics.NinePatch);
|
||||
method public void setTargetDensity(android.graphics.Canvas);
|
||||
method public void setTargetDensity(android.util.DisplayMetrics);
|
||||
method public void setTargetDensity(int);
|
||||
|
||||
@@ -11955,6 +11955,8 @@ package android.graphics {
|
||||
ctor public Outline(android.graphics.Outline);
|
||||
method public boolean canClip();
|
||||
method public float getAlpha();
|
||||
method public float getRadius();
|
||||
method public boolean getRect(android.graphics.Rect);
|
||||
method public boolean isEmpty();
|
||||
method public void offset(int, int);
|
||||
method public void set(android.graphics.Outline);
|
||||
@@ -12982,12 +12984,10 @@ package android.graphics.drawable {
|
||||
ctor public deprecated NinePatchDrawable(android.graphics.NinePatch);
|
||||
ctor public NinePatchDrawable(android.content.res.Resources, android.graphics.NinePatch);
|
||||
method public void draw(android.graphics.Canvas);
|
||||
method public android.graphics.NinePatch getNinePatch();
|
||||
method public int getOpacity();
|
||||
method public android.graphics.Paint getPaint();
|
||||
method public void setAlpha(int);
|
||||
method public void setColorFilter(android.graphics.ColorFilter);
|
||||
method public void setNinePatch(android.graphics.NinePatch);
|
||||
method public void setTargetDensity(android.graphics.Canvas);
|
||||
method public void setTargetDensity(android.util.DisplayMetrics);
|
||||
method public void setTargetDensity(int);
|
||||
|
||||
@@ -18,6 +18,7 @@ package android.graphics;
|
||||
|
||||
import android.annotation.FloatRange;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
/**
|
||||
@@ -175,6 +176,34 @@ public final class Outline {
|
||||
setRoundRect(rect.left, rect.top, rect.right, rect.bottom, radius);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates {@code outBounds} with the outline bounds, if set, and returns
|
||||
* {@code true}. If no outline bounds are set, or if a path has been set
|
||||
* via {@link #setConvexPath(Path)}, returns {@code false}.
|
||||
*
|
||||
* @param outRect the rect to populate with the outline bounds, if set
|
||||
* @return {@code true} if {@code outBounds} was populated with outline
|
||||
* bounds, or {@code false} if no outline bounds are set
|
||||
*/
|
||||
public boolean getRect(@NonNull Rect outRect) {
|
||||
if (mRect == null) {
|
||||
return false;
|
||||
}
|
||||
outRect.set(mRect);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the rounded rect radius, if set, or {@code -1} if a path has
|
||||
* been set via {@link #setConvexPath(Path)}. A return value of {@code 0}
|
||||
* indicates a non-rounded rect.
|
||||
*
|
||||
* @return the rounded rect radius or {@code -1}
|
||||
*/
|
||||
public float getRadius() {
|
||||
return mRadius;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the outline to the oval defined by input rect.
|
||||
*/
|
||||
|
||||
@@ -66,11 +66,16 @@ import java.util.Collection;
|
||||
public class NinePatchDrawable extends Drawable {
|
||||
// dithering helps a lot, and is pretty cheap, so default is true
|
||||
private static final boolean DEFAULT_DITHER = false;
|
||||
|
||||
/** Temporary rect used for density scaling. */
|
||||
private Rect mTempRect;
|
||||
|
||||
private NinePatchState mNinePatchState;
|
||||
private NinePatch mNinePatch;
|
||||
private PorterDuffColorFilter mTintFilter;
|
||||
private Rect mPadding;
|
||||
private Insets mOpticalInsets = Insets.NONE;
|
||||
private Rect mOutlineInsets;
|
||||
private float mOutlineRadius;
|
||||
private Paint mPaint;
|
||||
private boolean mMutated;
|
||||
|
||||
@@ -86,8 +91,9 @@ public class NinePatchDrawable extends Drawable {
|
||||
|
||||
/**
|
||||
* Create drawable from raw nine-patch data, not dealing with density.
|
||||
*
|
||||
* @deprecated Use {@link #NinePatchDrawable(Resources, Bitmap, byte[], Rect, String)}
|
||||
* to ensure that the drawable has correctly set its target density.
|
||||
* to ensure that the drawable has correctly set its target density.
|
||||
*/
|
||||
@Deprecated
|
||||
public NinePatchDrawable(Bitmap bitmap, byte[] chunk, Rect padding, String srcName) {
|
||||
@@ -101,7 +107,6 @@ public class NinePatchDrawable extends Drawable {
|
||||
public NinePatchDrawable(Resources res, Bitmap bitmap, byte[] chunk,
|
||||
Rect padding, String srcName) {
|
||||
this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding), res);
|
||||
mNinePatchState.mTargetDensity = mTargetDensity;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,16 +119,17 @@ public class NinePatchDrawable extends Drawable {
|
||||
Rect padding, Rect opticalInsets, String srcName) {
|
||||
this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding, opticalInsets),
|
||||
res);
|
||||
mNinePatchState.mTargetDensity = mTargetDensity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create drawable from existing nine-patch, not dealing with density.
|
||||
*
|
||||
* @deprecated Use {@link #NinePatchDrawable(Resources, NinePatch)}
|
||||
* to ensure that the drawable has correctly set its target density.
|
||||
* to ensure that the drawable has correctly set its target
|
||||
* density.
|
||||
*/
|
||||
@Deprecated
|
||||
public NinePatchDrawable(NinePatch patch) {
|
||||
public NinePatchDrawable(@NonNull NinePatch patch) {
|
||||
this(new NinePatchState(patch, new Rect()), null);
|
||||
}
|
||||
|
||||
@@ -131,9 +137,8 @@ public class NinePatchDrawable extends Drawable {
|
||||
* Create drawable from existing nine-patch, setting initial target density
|
||||
* based on the display metrics of the resources.
|
||||
*/
|
||||
public NinePatchDrawable(Resources res, NinePatch patch) {
|
||||
public NinePatchDrawable(@Nullable Resources res, @NonNull NinePatch patch) {
|
||||
this(new NinePatchState(patch, new Rect()), res);
|
||||
mNinePatchState.mTargetDensity = mTargetDensity;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,7 +151,7 @@ public class NinePatchDrawable extends Drawable {
|
||||
* @see android.graphics.Bitmap#setDensity(int)
|
||||
* @see android.graphics.Bitmap#getDensity()
|
||||
*/
|
||||
public void setTargetDensity(Canvas canvas) {
|
||||
public void setTargetDensity(@NonNull Canvas canvas) {
|
||||
setTargetDensity(canvas.getDensity());
|
||||
}
|
||||
|
||||
@@ -158,7 +163,7 @@ public class NinePatchDrawable extends Drawable {
|
||||
* @see android.graphics.Bitmap#setDensity(int)
|
||||
* @see android.graphics.Bitmap#getDensity()
|
||||
*/
|
||||
public void setTargetDensity(DisplayMetrics metrics) {
|
||||
public void setTargetDensity(@NonNull DisplayMetrics metrics) {
|
||||
setTargetDensity(metrics.densityDpi);
|
||||
}
|
||||
|
||||
@@ -171,78 +176,24 @@ public class NinePatchDrawable extends Drawable {
|
||||
* @see android.graphics.Bitmap#getDensity()
|
||||
*/
|
||||
public void setTargetDensity(int density) {
|
||||
if (density != mTargetDensity) {
|
||||
mTargetDensity = density == 0 ? DisplayMetrics.DENSITY_DEFAULT : density;
|
||||
if (mNinePatch != null) {
|
||||
computeBitmapSize();
|
||||
}
|
||||
if (density == 0) {
|
||||
density = DisplayMetrics.DENSITY_DEFAULT;
|
||||
}
|
||||
|
||||
if (mTargetDensity != density) {
|
||||
mTargetDensity = density;
|
||||
|
||||
computeBitmapSize();
|
||||
invalidateSelf();
|
||||
}
|
||||
}
|
||||
|
||||
private static Insets scaleFromDensity(Insets insets, int sdensity, int tdensity) {
|
||||
int left = Drawable.scaleFromDensity(insets.left, sdensity, tdensity, true);
|
||||
int top = Drawable.scaleFromDensity(insets.top, sdensity, tdensity, true);
|
||||
int right = Drawable.scaleFromDensity(insets.right, sdensity, tdensity, true);
|
||||
int bottom = Drawable.scaleFromDensity(insets.bottom, sdensity, tdensity, true);
|
||||
return Insets.of(left, top, right, bottom);
|
||||
}
|
||||
|
||||
private void computeBitmapSize() {
|
||||
final int sdensity = mNinePatch.getDensity();
|
||||
final int tdensity = mTargetDensity;
|
||||
if (sdensity == tdensity) {
|
||||
mBitmapWidth = mNinePatch.getWidth();
|
||||
mBitmapHeight = mNinePatch.getHeight();
|
||||
mOpticalInsets = mNinePatchState.mOpticalInsets;
|
||||
} else {
|
||||
mBitmapWidth = Drawable.scaleFromDensity(
|
||||
mNinePatch.getWidth(), sdensity, tdensity, true);
|
||||
mBitmapHeight = Drawable.scaleFromDensity(
|
||||
mNinePatch.getHeight(), sdensity, tdensity, true);
|
||||
if (mNinePatchState.mPadding != null && mPadding != null) {
|
||||
Rect dest = mPadding;
|
||||
Rect src = mNinePatchState.mPadding;
|
||||
if (dest == src) {
|
||||
mPadding = dest = new Rect(src);
|
||||
}
|
||||
dest.left = Drawable.scaleFromDensity(src.left, sdensity, tdensity, true);
|
||||
dest.top = Drawable.scaleFromDensity(src.top, sdensity, tdensity, true);
|
||||
dest.right = Drawable.scaleFromDensity(src.right, sdensity, tdensity, true);
|
||||
dest.bottom = Drawable.scaleFromDensity(src.bottom, sdensity, tdensity, true);
|
||||
}
|
||||
mOpticalInsets = scaleFromDensity(mNinePatchState.mOpticalInsets, sdensity, tdensity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the nine patch used by this drawable.
|
||||
*
|
||||
* @param ninePatch the nine patch for this drawable
|
||||
*/
|
||||
public void setNinePatch(NinePatch ninePatch) {
|
||||
if (mNinePatch != ninePatch) {
|
||||
mNinePatch = ninePatch;
|
||||
if (ninePatch != null) {
|
||||
computeBitmapSize();
|
||||
} else {
|
||||
mBitmapWidth = mBitmapHeight = -1;
|
||||
mOpticalInsets = Insets.NONE;
|
||||
}
|
||||
invalidateSelf();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the nine patch used by this drawable
|
||||
*/
|
||||
public NinePatch getNinePatch() {
|
||||
return mNinePatch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
final Rect bounds = getBounds();
|
||||
final NinePatchState state = mNinePatchState;
|
||||
|
||||
Rect bounds = getBounds();
|
||||
int restoreToCount = -1;
|
||||
|
||||
final boolean clearColorFilter;
|
||||
if (mTintFilter != null && getPaint().getColorFilter() == null) {
|
||||
@@ -252,22 +203,52 @@ public class NinePatchDrawable extends Drawable {
|
||||
clearColorFilter = false;
|
||||
}
|
||||
|
||||
final boolean needsMirroring = needsMirroring();
|
||||
if (needsMirroring) {
|
||||
// Mirror the 9patch
|
||||
canvas.translate(bounds.right - bounds.left, 0);
|
||||
canvas.scale(-1.0f, 1.0f);
|
||||
}
|
||||
|
||||
final int restoreAlpha;
|
||||
if (mNinePatchState.mBaseAlpha != 1.0f) {
|
||||
restoreAlpha = mPaint.getAlpha();
|
||||
mPaint.setAlpha((int) (restoreAlpha * mNinePatchState.mBaseAlpha + 0.5f));
|
||||
if (state.mBaseAlpha != 1.0f) {
|
||||
restoreAlpha = getPaint().getAlpha();
|
||||
mPaint.setAlpha((int) (restoreAlpha * state.mBaseAlpha + 0.5f));
|
||||
} else {
|
||||
restoreAlpha = -1;
|
||||
}
|
||||
|
||||
mNinePatch.draw(canvas, bounds, mPaint);
|
||||
final boolean needsDensityScaling = canvas.getDensity() == 0;
|
||||
if (needsDensityScaling) {
|
||||
restoreToCount = restoreToCount >= 0 ? restoreToCount : canvas.save();
|
||||
|
||||
// Apply density scaling.
|
||||
final float scale = mTargetDensity / (float) state.mNinePatch.getDensity();
|
||||
final float px = bounds.left;
|
||||
final float py = bounds.top;
|
||||
canvas.scale(scale, scale, px, py);
|
||||
|
||||
if (mTempRect == null) {
|
||||
mTempRect = new Rect();
|
||||
}
|
||||
|
||||
// Scale the bounds to match.
|
||||
final Rect scaledBounds = mTempRect;
|
||||
scaledBounds.left = bounds.left;
|
||||
scaledBounds.top = bounds.top;
|
||||
scaledBounds.right = bounds.left + Math.round(bounds.width() / scale);
|
||||
scaledBounds.bottom = bounds.top + Math.round(bounds.height() / scale);
|
||||
bounds = scaledBounds;
|
||||
}
|
||||
|
||||
final boolean needsMirroring = needsMirroring();
|
||||
if (needsMirroring) {
|
||||
restoreToCount = restoreToCount >= 0 ? restoreToCount : canvas.save();
|
||||
|
||||
// Mirror the 9patch.
|
||||
final float cx = (bounds.left + bounds.right) / 2.0f;
|
||||
final float cy = (bounds.top + bounds.bottom) / 2.0f;
|
||||
canvas.scale(-1.0f, 1.0f, cx, cy);
|
||||
}
|
||||
|
||||
state.mNinePatch.draw(canvas, bounds, mPaint);
|
||||
|
||||
if (restoreToCount >= 0) {
|
||||
canvas.restoreToCount(restoreToCount);
|
||||
}
|
||||
|
||||
if (clearColorFilter) {
|
||||
mPaint.setColorFilter(null);
|
||||
@@ -284,38 +265,36 @@ public class NinePatchDrawable extends Drawable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getPadding(Rect padding) {
|
||||
final Rect scaledPadding = mPadding;
|
||||
if (scaledPadding != null) {
|
||||
if (needsMirroring()) {
|
||||
padding.set(scaledPadding.right, scaledPadding.top,
|
||||
scaledPadding.left, scaledPadding.bottom);
|
||||
} else {
|
||||
padding.set(scaledPadding);
|
||||
}
|
||||
public boolean getPadding(@NonNull Rect padding) {
|
||||
if (mPadding != null) {
|
||||
padding.set(mPadding);
|
||||
return (padding.left | padding.top | padding.right | padding.bottom) != 0;
|
||||
} else {
|
||||
return super.getPadding(padding);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getOutline(@NonNull Outline outline) {
|
||||
final Rect bounds = getBounds();
|
||||
if (bounds.isEmpty()) return;
|
||||
if (bounds.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mNinePatchState != null) {
|
||||
NinePatch.InsetStruct insets = mNinePatchState.mNinePatch.getBitmap().getNinePatchInsets();
|
||||
if (mNinePatchState != null && mOutlineInsets != null) {
|
||||
final NinePatch.InsetStruct insets =
|
||||
mNinePatchState.mNinePatch.getBitmap().getNinePatchInsets();
|
||||
if (insets != null) {
|
||||
final Rect outlineInsets = insets.outlineRect;
|
||||
outline.setRoundRect(bounds.left + outlineInsets.left,
|
||||
bounds.top + outlineInsets.top,
|
||||
bounds.right - outlineInsets.right,
|
||||
bounds.bottom - outlineInsets.bottom,
|
||||
insets.outlineRadius);
|
||||
outline.setRoundRect(bounds.left + mOutlineInsets.left,
|
||||
bounds.top + mOutlineInsets.top,
|
||||
bounds.right - mOutlineInsets.right,
|
||||
bounds.bottom - mOutlineInsets.bottom,
|
||||
mOutlineRadius);
|
||||
outline.setAlpha(insets.outlineAlpha * (getAlpha() / 255.0f));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
super.getOutline(outline);
|
||||
}
|
||||
|
||||
@@ -324,11 +303,12 @@ public class NinePatchDrawable extends Drawable {
|
||||
*/
|
||||
@Override
|
||||
public Insets getOpticalInsets() {
|
||||
final Insets opticalInsets = mOpticalInsets;
|
||||
if (needsMirroring()) {
|
||||
return Insets.of(mOpticalInsets.right, mOpticalInsets.top,
|
||||
mOpticalInsets.left, mOpticalInsets.bottom);
|
||||
return Insets.of(opticalInsets.right, opticalInsets.top,
|
||||
opticalInsets.left, opticalInsets.bottom);
|
||||
} else {
|
||||
return mOpticalInsets;
|
||||
return opticalInsets;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,7 +332,7 @@ public class NinePatchDrawable extends Drawable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(ColorFilter colorFilter) {
|
||||
public void setColorFilter(@Nullable ColorFilter colorFilter) {
|
||||
if (mPaint == null && colorFilter == null) {
|
||||
// Fast common case -- leave at no color filter.
|
||||
return;
|
||||
@@ -362,14 +342,14 @@ public class NinePatchDrawable extends Drawable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTintList(ColorStateList tint) {
|
||||
public void setTintList(@Nullable ColorStateList tint) {
|
||||
mNinePatchState.mTint = tint;
|
||||
mTintFilter = updateTintFilter(mTintFilter, tint, mNinePatchState.mTintMode);
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTintMode(PorterDuff.Mode tintMode) {
|
||||
public void setTintMode(@Nullable PorterDuff.Mode tintMode) {
|
||||
mNinePatchState.mTintMode = tintMode;
|
||||
mTintFilter = updateTintFilter(mTintFilter, mNinePatchState.mTint, tintMode);
|
||||
invalidateSelf();
|
||||
@@ -409,10 +389,7 @@ public class NinePatchDrawable extends Drawable {
|
||||
|
||||
@Override
|
||||
public boolean isFilterBitmap() {
|
||||
if (mPaint == null) {
|
||||
return false;
|
||||
}
|
||||
return getPaint().isFilterBitmap();
|
||||
return mPaint != null && getPaint().isFilterBitmap();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -430,7 +407,7 @@ public class NinePatchDrawable extends Drawable {
|
||||
/**
|
||||
* Updates the constant state from the values in the typed array.
|
||||
*/
|
||||
private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserException {
|
||||
private void updateStateFromTypedArray(@NonNull TypedArray a) throws XmlPullParserException {
|
||||
final Resources r = a.getResources();
|
||||
final NinePatchState state = mNinePatchState;
|
||||
|
||||
@@ -491,12 +468,10 @@ public class NinePatchDrawable extends Drawable {
|
||||
if (tint != null) {
|
||||
state.mTint = tint;
|
||||
}
|
||||
|
||||
state.mTargetDensity = Drawable.resolveDensity(r, state.mTargetDensity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTheme(Theme t) {
|
||||
public void applyTheme(@NonNull Theme t) {
|
||||
super.applyTheme(t);
|
||||
|
||||
final NinePatchState state = mNinePatchState;
|
||||
@@ -528,6 +503,7 @@ public class NinePatchDrawable extends Drawable {
|
||||
return mNinePatchState != null && mNinePatchState.canApplyTheme();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Paint getPaint() {
|
||||
if (mPaint == null) {
|
||||
mPaint = new Paint();
|
||||
@@ -536,45 +512,26 @@ public class NinePatchDrawable extends Drawable {
|
||||
return mPaint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the width of the source .png file (before resizing).
|
||||
*/
|
||||
@Override
|
||||
public int getIntrinsicWidth() {
|
||||
return mBitmapWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the height of the source .png file (before resizing).
|
||||
*/
|
||||
@Override
|
||||
public int getIntrinsicHeight() {
|
||||
return mBitmapHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinimumWidth() {
|
||||
return mBitmapWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinimumHeight() {
|
||||
return mBitmapHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link android.graphics.PixelFormat graphics.PixelFormat}
|
||||
* value of OPAQUE or TRANSLUCENT.
|
||||
*/
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return mNinePatch.hasAlpha() || (mPaint != null && mPaint.getAlpha() < 255) ?
|
||||
PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE;
|
||||
return mNinePatchState.mNinePatch.hasAlpha()
|
||||
|| (mPaint != null && mPaint.getAlpha() < 255) ?
|
||||
PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Region getTransparentRegion() {
|
||||
return mNinePatch.getTransparentRegion(getBounds());
|
||||
return mNinePatchState.mNinePatch.getTransparentRegion(getBounds());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -587,7 +544,6 @@ public class NinePatchDrawable extends Drawable {
|
||||
public Drawable mutate() {
|
||||
if (!mMutated && super.mutate() == this) {
|
||||
mNinePatchState = new NinePatchState(mNinePatchState);
|
||||
mNinePatch = mNinePatchState.mNinePatch;
|
||||
mMutated = true;
|
||||
}
|
||||
return this;
|
||||
@@ -619,8 +575,9 @@ public class NinePatchDrawable extends Drawable {
|
||||
}
|
||||
|
||||
final static class NinePatchState extends ConstantState {
|
||||
int mChangingConfigurations;
|
||||
|
||||
// Values loaded during inflation.
|
||||
int[] mThemeAttrs = null;
|
||||
NinePatch mNinePatch = null;
|
||||
ColorStateList mTint = null;
|
||||
Mode mTintMode = DEFAULT_TINT_MODE;
|
||||
@@ -628,10 +585,9 @@ public class NinePatchDrawable extends Drawable {
|
||||
Insets mOpticalInsets = Insets.NONE;
|
||||
float mBaseAlpha = 1.0f;
|
||||
boolean mDither = DEFAULT_DITHER;
|
||||
int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
|
||||
boolean mAutoMirrored = false;
|
||||
|
||||
int mChangingConfigurations;
|
||||
int[] mThemeAttrs;
|
||||
|
||||
NinePatchState() {
|
||||
// Empty constructor.
|
||||
@@ -655,27 +611,24 @@ public class NinePatchDrawable extends Drawable {
|
||||
mAutoMirrored = autoMirror;
|
||||
}
|
||||
|
||||
// Copy constructor
|
||||
|
||||
NinePatchState(@NonNull NinePatchState state) {
|
||||
// We don't deep-copy any fields because they are all immutable.
|
||||
mNinePatch = state.mNinePatch;
|
||||
mTint = state.mTint;
|
||||
mTintMode = state.mTintMode;
|
||||
mThemeAttrs = state.mThemeAttrs;
|
||||
mPadding = state.mPadding;
|
||||
mOpticalInsets = state.mOpticalInsets;
|
||||
mBaseAlpha = state.mBaseAlpha;
|
||||
mDither = state.mDither;
|
||||
mChangingConfigurations = state.mChangingConfigurations;
|
||||
mTargetDensity = state.mTargetDensity;
|
||||
mAutoMirrored = state.mAutoMirrored;
|
||||
NinePatchState(@NonNull NinePatchState orig) {
|
||||
mChangingConfigurations = orig.mChangingConfigurations;
|
||||
mNinePatch = orig.mNinePatch;
|
||||
mTint = orig.mTint;
|
||||
mTintMode = orig.mTintMode;
|
||||
mPadding = orig.mPadding;
|
||||
mOpticalInsets = orig.mOpticalInsets;
|
||||
mBaseAlpha = orig.mBaseAlpha;
|
||||
mDither = orig.mDither;
|
||||
mAutoMirrored = orig.mAutoMirrored;
|
||||
mThemeAttrs = orig.mThemeAttrs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canApplyTheme() {
|
||||
return mThemeAttrs != null
|
||||
|| (mTint != null && mTint.canApplyTheme());
|
||||
|| (mTint != null && mTint.canApplyTheme())
|
||||
|| super.canApplyTheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -704,44 +657,98 @@ public class NinePatchDrawable extends Drawable {
|
||||
}
|
||||
}
|
||||
|
||||
private void computeBitmapSize() {
|
||||
final NinePatch ninePatch = mNinePatchState.mNinePatch;
|
||||
if (ninePatch == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int sourceDensity = ninePatch.getDensity();
|
||||
final int targetDensity = mTargetDensity;
|
||||
|
||||
final Insets sourceOpticalInsets = mNinePatchState.mOpticalInsets;
|
||||
if (sourceOpticalInsets != Insets.NONE) {
|
||||
final int left = Drawable.scaleFromDensity(
|
||||
sourceOpticalInsets.left, sourceDensity, targetDensity, true);
|
||||
final int top = Drawable.scaleFromDensity(
|
||||
sourceOpticalInsets.top, sourceDensity, targetDensity, true);
|
||||
final int right = Drawable.scaleFromDensity(
|
||||
sourceOpticalInsets.right, sourceDensity, targetDensity, true);
|
||||
final int bottom = Drawable.scaleFromDensity(
|
||||
sourceOpticalInsets.bottom, sourceDensity, targetDensity, true);
|
||||
mOpticalInsets = Insets.of(left, top, right, bottom);
|
||||
} else {
|
||||
mOpticalInsets = Insets.NONE;
|
||||
}
|
||||
|
||||
final Rect sourcePadding = mNinePatchState.mPadding;
|
||||
if (sourcePadding != null) {
|
||||
if (mPadding == null) {
|
||||
mPadding = new Rect();
|
||||
}
|
||||
mPadding.left = Drawable.scaleFromDensity(
|
||||
sourcePadding.left, sourceDensity, targetDensity, false);
|
||||
mPadding.top = Drawable.scaleFromDensity(
|
||||
sourcePadding.top, sourceDensity, targetDensity, false);
|
||||
mPadding.right = Drawable.scaleFromDensity(
|
||||
sourcePadding.right, sourceDensity, targetDensity, false);
|
||||
mPadding.bottom = Drawable.scaleFromDensity(
|
||||
sourcePadding.bottom, sourceDensity, targetDensity, false);
|
||||
} else {
|
||||
mPadding = null;
|
||||
}
|
||||
|
||||
mBitmapHeight = Drawable.scaleFromDensity(
|
||||
ninePatch.getHeight(), sourceDensity, targetDensity, true);
|
||||
mBitmapWidth = Drawable.scaleFromDensity(
|
||||
ninePatch.getWidth(), sourceDensity, targetDensity, true);
|
||||
|
||||
final NinePatch.InsetStruct insets = ninePatch.getBitmap().getNinePatchInsets();
|
||||
if (insets != null) {
|
||||
if (mOutlineInsets == null) {
|
||||
mOutlineInsets = new Rect();
|
||||
}
|
||||
final Rect outlineInsets = insets.outlineRect;
|
||||
mOutlineInsets.left = Drawable.scaleFromDensity(
|
||||
outlineInsets.left, sourceDensity, targetDensity, false);
|
||||
mOutlineInsets.top = Drawable.scaleFromDensity(
|
||||
outlineInsets.top, sourceDensity, targetDensity, false);
|
||||
mOutlineInsets.right = Drawable.scaleFromDensity(
|
||||
outlineInsets.right, sourceDensity, targetDensity, false);
|
||||
mOutlineInsets.bottom = Drawable.scaleFromDensity(
|
||||
outlineInsets.bottom, sourceDensity, targetDensity, false);
|
||||
mOutlineRadius = Drawable.scaleFromDensity(
|
||||
insets.outlineRadius, sourceDensity, targetDensity);
|
||||
} else {
|
||||
mOutlineInsets = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The one constructor to rule them all. This is called by all public
|
||||
* constructors to set the state and initialize local properties.
|
||||
*
|
||||
* @param state constant state to assign to the new drawable
|
||||
*/
|
||||
private NinePatchDrawable(NinePatchState state, Resources res) {
|
||||
private NinePatchDrawable(@NonNull NinePatchState state, @Nullable Resources res) {
|
||||
mNinePatchState = state;
|
||||
|
||||
updateLocalState(res);
|
||||
|
||||
// Push density applied by setNinePatchState into state.
|
||||
mNinePatchState.mTargetDensity = mTargetDensity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes local dynamic properties from state.
|
||||
*/
|
||||
private void updateLocalState(Resources res) {
|
||||
private void updateLocalState(@Nullable Resources res) {
|
||||
final NinePatchState state = mNinePatchState;
|
||||
|
||||
if (res != null) {
|
||||
final int densityDpi = res.getDisplayMetrics().densityDpi;
|
||||
mTargetDensity = densityDpi == 0 ? DisplayMetrics.DENSITY_DEFAULT : densityDpi;
|
||||
} else {
|
||||
mTargetDensity = state.mTargetDensity;
|
||||
}
|
||||
|
||||
|
||||
// If we can, avoid calling any methods that initialize Paint.
|
||||
if (state.mDither != DEFAULT_DITHER) {
|
||||
setDither(state.mDither);
|
||||
}
|
||||
|
||||
// Make a local copy of the padding.
|
||||
if (state.mPadding != null) {
|
||||
mPadding = new Rect(state.mPadding);
|
||||
}
|
||||
|
||||
mTargetDensity = Drawable.resolveDensity(res, mTargetDensity);
|
||||
mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
|
||||
setNinePatch(state.mNinePatch);
|
||||
computeBitmapSize();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user