Merge "Apply VectorDrawable density scaling before applying theme"

This commit is contained in:
Alan Viverette
2015-11-19 14:50:40 +00:00
committed by Android (Google) Code Review
2 changed files with 75 additions and 35 deletions

View File

@@ -1424,7 +1424,7 @@ public abstract class Drawable {
}
}
static int resolveDensity(@NonNull Resources r, int parentDensity) {
static int resolveDensity(@Nullable Resources r, int parentDensity) {
final int densityDpi = r == null ? parentDensity : r.getDisplayMetrics().densityDpi;
return densityDpi == 0 ? DisplayMetrics.DENSITY_DEFAULT : densityDpi;
}

View File

@@ -231,6 +231,9 @@ public class VectorDrawable extends Drawable {
private int mDpiScaledHeight = 0;
private Insets mDpiScaledInsets = Insets.NONE;
/** Whether DPI-scaled width, height, and insets need to be updated. */
private boolean mDpiScaledDirty = true;
// Temp variable, only for saving "new" operation at the draw() time.
private final float[] mTmpFloats = new float[9];
private final Matrix mTmpMatrix = new Matrix();
@@ -259,9 +262,13 @@ public class VectorDrawable extends Drawable {
* displayed, or {@code null} to use the constant state defaults
*/
private void updateLocalState(Resources res) {
mTargetDensity = Drawable.resolveDensity(res, mVectorState.mVPathRenderer.mSourceDensity);
final int density = Drawable.resolveDensity(res, mVectorState.mVPathRenderer.mDensity);
if (mTargetDensity != density) {
mTargetDensity = density;
mDpiScaledDirty = true;
}
mTintFilter = updateTintFilter(mTintFilter, mVectorState.mTint, mVectorState.mTintMode);
computeVectorSize();
}
@Override
@@ -422,17 +429,26 @@ public class VectorDrawable extends Drawable {
@Override
public int getIntrinsicWidth() {
if (mDpiScaledDirty) {
computeVectorSize();
}
return mDpiScaledWidth;
}
@Override
public int getIntrinsicHeight() {
if (mDpiScaledDirty) {
computeVectorSize();
}
return mDpiScaledHeight;
}
/** @hide */
@Override
public Insets getOpticalInsets() {
if (mDpiScaledDirty) {
computeVectorSize();
}
return mDpiScaledInsets;
}
@@ -444,7 +460,7 @@ public class VectorDrawable extends Drawable {
final VPathRenderer pathRenderer = mVectorState.mVPathRenderer;
final Insets opticalInsets = pathRenderer.mOpticalInsets;
final int sourceDensity = pathRenderer.mSourceDensity;
final int sourceDensity = pathRenderer.mDensity;
final int targetDensity = mTargetDensity;
if (targetDensity != sourceDensity) {
mDpiScaledWidth = Drawable.scaleFromDensity(
@@ -465,6 +481,8 @@ public class VectorDrawable extends Drawable {
mDpiScaledHeight = (int) pathRenderer.mBaseHeight;
mDpiScaledInsets = opticalInsets;
}
mDpiScaledDirty = false;
}
@Override
@@ -481,6 +499,11 @@ public class VectorDrawable extends Drawable {
return;
}
final VPathRenderer path = state.mVPathRenderer;
final boolean changedDensity = path.setDensity(
Drawable.resolveDensity(t.getResources(), 0));
mDpiScaledDirty |= changedDensity;
if (state.mThemeAttrs != null) {
final TypedArray a = t.resolveAttributes(
state.mThemeAttrs, R.styleable.VectorDrawable);
@@ -492,6 +515,9 @@ public class VectorDrawable extends Drawable {
} finally {
a.recycle();
}
// May have changed size.
mDpiScaledDirty = true;
}
// Apply theme to contained color state list.
@@ -499,7 +525,6 @@ public class VectorDrawable extends Drawable {
state.mTint = state.mTint.obtainForTheme(t);
}
final VPathRenderer path = state.mVPathRenderer;
if (path != null && path.canApplyTheme()) {
path.applyTheme(t);
}
@@ -565,21 +590,24 @@ public class VectorDrawable extends Drawable {
}
@Override
public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
@NonNull AttributeSet attrs, @Nullable Theme theme)
throws XmlPullParserException, IOException {
final VectorDrawableState state = mVectorState;
final VPathRenderer pathRenderer = new VPathRenderer();
state.mVPathRenderer = pathRenderer;
state.mVPathRenderer = new VPathRenderer();
state.mVPathRenderer.setDensity(Drawable.resolveDensity(r, 0));
final TypedArray a = obtainAttributes(res, theme, attrs, R.styleable.VectorDrawable);
final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.VectorDrawable);
updateStateFromTypedArray(a);
a.recycle();
mDpiScaledDirty = true;
state.mCacheDirty = true;
inflateInternal(res, parser, attrs, theme);
inflateChildElements(r, parser, attrs, theme);
// Update local properties.
updateLocalState(res);
updateLocalState(r);
}
private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserException {
@@ -592,13 +620,6 @@ public class VectorDrawable extends Drawable {
// Extract the theme attributes, if any.
state.mThemeAttrs = a.extractThemeAttrs();
// The density may have changed since the last update (if any). Any
// dimension-type attributes will need their default values scaled.
final int targetDensity = Drawable.resolveDensity(a.getResources(), 0);
final int sourceDensity = pathRenderer.mSourceDensity;
final float densityScale = targetDensity / (float) sourceDensity;
pathRenderer.mSourceDensity = targetDensity;
final int tintMode = a.getInt(R.styleable.VectorDrawable_tintMode, -1);
if (tintMode != -1) {
state.mTintMode = Drawable.parseTintMode(tintMode, Mode.SRC_IN);
@@ -626,11 +647,9 @@ public class VectorDrawable extends Drawable {
}
pathRenderer.mBaseWidth = a.getDimension(
R.styleable.VectorDrawable_width,
pathRenderer.mBaseWidth * densityScale);
R.styleable.VectorDrawable_width, pathRenderer.mBaseWidth);
pathRenderer.mBaseHeight = a.getDimension(
R.styleable.VectorDrawable_height,
pathRenderer.mBaseHeight * densityScale);
R.styleable.VectorDrawable_height, pathRenderer.mBaseHeight);
if (pathRenderer.mBaseWidth <= 0) {
throw new XmlPullParserException(a.getPositionDescription() +
@@ -641,21 +660,17 @@ public class VectorDrawable extends Drawable {
}
final int insetLeft = a.getDimensionPixelOffset(
R.styleable.VectorDrawable_opticalInsetLeft,
(int) (pathRenderer.mOpticalInsets.left * densityScale));
R.styleable.VectorDrawable_opticalInsetLeft, pathRenderer.mOpticalInsets.left);
final int insetTop = a.getDimensionPixelOffset(
R.styleable.VectorDrawable_opticalInsetTop,
(int) (pathRenderer.mOpticalInsets.top * densityScale));
R.styleable.VectorDrawable_opticalInsetTop, pathRenderer.mOpticalInsets.top);
final int insetRight = a.getDimensionPixelOffset(
R.styleable.VectorDrawable_opticalInsetRight,
(int) (pathRenderer.mOpticalInsets.right * densityScale));
R.styleable.VectorDrawable_opticalInsetRight, pathRenderer.mOpticalInsets.right);
final int insetBottom = a.getDimensionPixelOffset(
R.styleable.VectorDrawable_opticalInsetBottom,
(int) (pathRenderer.mOpticalInsets.bottom * densityScale));
R.styleable.VectorDrawable_opticalInsetBottom, pathRenderer.mOpticalInsets.bottom);
pathRenderer.mOpticalInsets = Insets.of(insetLeft, insetTop, insetRight, insetBottom);
final float alphaInFloat = a.getFloat(R.styleable.VectorDrawable_alpha,
pathRenderer.getAlpha());
final float alphaInFloat = a.getFloat(
R.styleable.VectorDrawable_alpha, pathRenderer.getAlpha());
pathRenderer.setAlpha(alphaInFloat);
final String name = a.getString(R.styleable.VectorDrawable_name);
@@ -665,7 +680,7 @@ public class VectorDrawable extends Drawable {
}
}
private void inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs,
private void inflateChildElements(Resources res, XmlPullParser parser, AttributeSet attrs,
Theme theme) throws XmlPullParserException, IOException {
final VectorDrawableState state = mVectorState;
final VPathRenderer pathRenderer = state.mVPathRenderer;
@@ -929,7 +944,7 @@ public class VectorDrawable extends Drawable {
int mRootAlpha = 0xFF;
String mRootName = null;
int mSourceDensity = DisplayMetrics.DENSITY_DEFAULT;
int mDensity = DisplayMetrics.DENSITY_DEFAULT;
final ArrayMap<String, Object> mVGTargetsMap = new ArrayMap<>();
@@ -966,12 +981,37 @@ public class VectorDrawable extends Drawable {
mChangingConfigurations = copy.mChangingConfigurations;
mRootAlpha = copy.mRootAlpha;
mRootName = copy.mRootName;
mSourceDensity = copy.mSourceDensity;
mDensity = copy.mDensity;
if (copy.mRootName != null) {
mVGTargetsMap.put(copy.mRootName, this);
}
}
public final boolean setDensity(int targetDensity) {
if (mDensity != targetDensity) {
final int sourceDensity = mDensity;
mDensity = targetDensity;
applyDensityScaling(sourceDensity, targetDensity);
return true;
}
return false;
}
private void applyDensityScaling(int sourceDensity, int targetDensity) {
mBaseWidth = Drawable.scaleFromDensity(mBaseWidth, sourceDensity, targetDensity);
mBaseHeight = Drawable.scaleFromDensity(mBaseHeight, sourceDensity, targetDensity);
final int insetLeft = Drawable.scaleFromDensity(
mOpticalInsets.left, sourceDensity, targetDensity, false);
final int insetTop = Drawable.scaleFromDensity(
mOpticalInsets.top, sourceDensity, targetDensity, false);
final int insetRight = Drawable.scaleFromDensity(
mOpticalInsets.right, sourceDensity, targetDensity, false);
final int insetBottom = Drawable.scaleFromDensity(
mOpticalInsets.bottom, sourceDensity, targetDensity, false);
mOpticalInsets = Insets.of(insetLeft, insetTop, insetRight, insetBottom);
}
public boolean canApplyTheme() {
return mRootGroup.canApplyTheme();
}