summaryrefslogtreecommitdiffstats
path: root/graphics
diff options
context:
space:
mode:
Diffstat (limited to 'graphics')
-rw-r--r--graphics/java/android/graphics/AvoidXfermode.java2
-rw-r--r--graphics/java/android/graphics/Bitmap.java2
-rw-r--r--graphics/java/android/graphics/Canvas.java77
-rw-r--r--graphics/java/android/graphics/CanvasProperty.java2
-rw-r--r--graphics/java/android/graphics/DrawFilter.java7
-rw-r--r--graphics/java/android/graphics/LayerRasterizer.java4
-rw-r--r--graphics/java/android/graphics/Movie.java13
-rw-r--r--graphics/java/android/graphics/NinePatch.java4
-rw-r--r--graphics/java/android/graphics/Paint.java36
-rw-r--r--graphics/java/android/graphics/PaintFlagsDrawFilter.java7
-rw-r--r--graphics/java/android/graphics/Picture.java5
-rw-r--r--graphics/java/android/graphics/Shader.java5
-rw-r--r--graphics/java/android/graphics/drawable/BitmapDrawable.java53
-rw-r--r--graphics/java/android/graphics/drawable/ColorDrawable.java41
-rw-r--r--graphics/java/android/graphics/drawable/Drawable.java32
-rw-r--r--graphics/java/android/graphics/drawable/DrawableContainer.java5
-rw-r--r--graphics/java/android/graphics/drawable/GradientDrawable.java62
-rw-r--r--graphics/java/android/graphics/drawable/InsetDrawable.java211
-rw-r--r--graphics/java/android/graphics/drawable/LayerDrawable.java410
-rw-r--r--graphics/java/android/graphics/drawable/NinePatchDrawable.java53
-rw-r--r--graphics/java/android/graphics/drawable/PictureDrawable.java6
-rw-r--r--graphics/java/android/graphics/drawable/Ripple.java7
-rw-r--r--graphics/java/android/graphics/drawable/RippleBackground.java7
-rw-r--r--graphics/java/android/graphics/drawable/RippleDrawable.java117
-rw-r--r--graphics/java/android/graphics/drawable/ShapeDrawable.java33
-rw-r--r--graphics/java/android/graphics/drawable/VectorDrawable.java28
26 files changed, 866 insertions, 363 deletions
diff --git a/graphics/java/android/graphics/AvoidXfermode.java b/graphics/java/android/graphics/AvoidXfermode.java
index 206c959..48ee6fa 100644
--- a/graphics/java/android/graphics/AvoidXfermode.java
+++ b/graphics/java/android/graphics/AvoidXfermode.java
@@ -23,7 +23,7 @@ package android.graphics;
@Deprecated
public class AvoidXfermode extends Xfermode {
- // these need to match the enum in SkAvoidXfermode.h on the native side
+ // these need to match the enum in AvoidXfermode.h on the native side
public enum Mode {
AVOID (0), //!< draw everywhere except on the opColor
TARGET (1); //!< draw only on top of the opColor
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 72f6118..132c6ef 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -1537,7 +1537,7 @@ public final class Bitmap implements Parcelable {
*/
public Bitmap extractAlpha(Paint paint, int[] offsetXY) {
checkRecycled("Can't extractAlpha on a recycled bitmap");
- long nativePaint = paint != null ? paint.mNativePaint : 0;
+ long nativePaint = paint != null ? paint.getNativeInstance() : 0;
Bitmap bm = nativeExtractAlpha(mNativeBitmap, nativePaint, offsetXY);
if (bm == null) {
throw new RuntimeException("Failed to extractAlpha on Bitmap");
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index b0580d5..e4c2f0e 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -44,8 +44,12 @@ import javax.microedition.khronos.opengles.GL;
*/
public class Canvas {
- // assigned in constructors or setBitmap, freed in finalizer
- private long mNativeCanvasWrapper;
+ /**
+ * Should only be assigned in constructors (or setBitmap if software canvas),
+ * freed in finalizer.
+ * @hide
+ */
+ protected long mNativeCanvasWrapper;
/** @hide */
public long getNativeCanvasWrapper() {
@@ -475,7 +479,7 @@ public class Canvas {
public int saveLayer(float left, float top, float right, float bottom, @Nullable Paint paint,
@Saveflags int saveFlags) {
return native_saveLayer(mNativeCanvasWrapper, left, top, right, bottom,
- paint != null ? paint.mNativePaint : 0,
+ paint != null ? paint.getNativeInstance() : 0,
saveFlags);
}
@@ -1031,7 +1035,7 @@ public class Canvas {
* @param paint The paint used to draw onto the canvas
*/
public void drawPaint(@NonNull Paint paint) {
- native_drawPaint(mNativeCanvasWrapper, paint.mNativePaint);
+ native_drawPaint(mNativeCanvasWrapper, paint.getNativeInstance());
}
/**
@@ -1051,7 +1055,7 @@ public class Canvas {
* @param paint The paint used to draw the points
*/
public void drawPoints(float[] pts, int offset, int count, @NonNull Paint paint) {
- native_drawPoints(mNativeCanvasWrapper, pts, offset, count, paint.mNativePaint);
+ native_drawPoints(mNativeCanvasWrapper, pts, offset, count, paint.getNativeInstance());
}
/**
@@ -1065,7 +1069,7 @@ public class Canvas {
* Helper for drawPoints() for drawing a single point.
*/
public void drawPoint(float x, float y, @NonNull Paint paint) {
- native_drawPoint(mNativeCanvasWrapper, x, y, paint.mNativePaint);
+ native_drawPoint(mNativeCanvasWrapper, x, y, paint.getNativeInstance());
}
/**
@@ -1082,7 +1086,7 @@ public class Canvas {
*/
public void drawLine(float startX, float startY, float stopX, float stopY,
@NonNull Paint paint) {
- native_drawLine(mNativeCanvasWrapper, startX, startY, stopX, stopY, paint.mNativePaint);
+ native_drawLine(mNativeCanvasWrapper, startX, startY, stopX, stopY, paint.getNativeInstance());
}
/**
@@ -1101,7 +1105,7 @@ public class Canvas {
* @param paint The paint used to draw the points
*/
public void drawLines(float[] pts, int offset, int count, Paint paint) {
- native_drawLines(mNativeCanvasWrapper, pts, offset, count, paint.mNativePaint);
+ native_drawLines(mNativeCanvasWrapper, pts, offset, count, paint.getNativeInstance());
}
public void drawLines(@NonNull float[] pts, @NonNull Paint paint) {
@@ -1117,7 +1121,7 @@ public class Canvas {
*/
public void drawRect(@NonNull RectF rect, @NonNull Paint paint) {
native_drawRect(mNativeCanvasWrapper,
- rect.left, rect.top, rect.right, rect.bottom, paint.mNativePaint);
+ rect.left, rect.top, rect.right, rect.bottom, paint.getNativeInstance());
}
/**
@@ -1143,7 +1147,7 @@ public class Canvas {
* @param paint The paint used to draw the rect
*/
public void drawRect(float left, float top, float right, float bottom, @NonNull Paint paint) {
- native_drawRect(mNativeCanvasWrapper, left, top, right, bottom, paint.mNativePaint);
+ native_drawRect(mNativeCanvasWrapper, left, top, right, bottom, paint.getNativeInstance());
}
/**
@@ -1164,7 +1168,7 @@ public class Canvas {
* filled or framed based on the Style in the paint.
*/
public void drawOval(float left, float top, float right, float bottom, @NonNull Paint paint) {
- native_drawOval(mNativeCanvasWrapper, left, top, right, bottom, paint.mNativePaint);
+ native_drawOval(mNativeCanvasWrapper, left, top, right, bottom, paint.getNativeInstance());
}
/**
@@ -1178,7 +1182,7 @@ public class Canvas {
* @param paint The paint used to draw the circle
*/
public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) {
- native_drawCircle(mNativeCanvasWrapper, cx, cy, radius, paint.mNativePaint);
+ native_drawCircle(mNativeCanvasWrapper, cx, cy, radius, paint.getNativeInstance());
}
/**
@@ -1234,7 +1238,7 @@ public class Canvas {
public void drawArc(float left, float top, float right, float bottom, float startAngle,
float sweepAngle, boolean useCenter, @NonNull Paint paint) {
native_drawArc(mNativeCanvasWrapper, left, top, right, bottom, startAngle, sweepAngle,
- useCenter, paint.mNativePaint);
+ useCenter, paint.getNativeInstance());
}
/**
@@ -1260,7 +1264,7 @@ public class Canvas {
*/
public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
@NonNull Paint paint) {
- native_drawRoundRect(mNativeCanvasWrapper, left, top, right, bottom, rx, ry, paint.mNativePaint);
+ native_drawRoundRect(mNativeCanvasWrapper, left, top, right, bottom, rx, ry, paint.getNativeInstance());
}
/**
@@ -1271,7 +1275,7 @@ public class Canvas {
* @param paint The paint used to draw the path
*/
public void drawPath(@NonNull Path path, @NonNull Paint paint) {
- native_drawPath(mNativeCanvasWrapper, path.ni(), paint.mNativePaint);
+ native_drawPath(mNativeCanvasWrapper, path.ni(), paint.getNativeInstance());
}
/**
@@ -1336,7 +1340,7 @@ public class Canvas {
public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) {
throwIfCannotDraw(bitmap);
native_drawBitmap(mNativeCanvasWrapper, bitmap.ni(), left, top,
- paint != null ? paint.mNativePaint : 0, mDensity, mScreenDensity, bitmap.mDensity);
+ paint != null ? paint.getNativeInstance() : 0, mDensity, mScreenDensity, bitmap.mDensity);
}
/**
@@ -1367,7 +1371,7 @@ public class Canvas {
throw new NullPointerException();
}
throwIfCannotDraw(bitmap);
- final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+ final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
float left, top, right, bottom;
if (src == null) {
@@ -1414,7 +1418,7 @@ public class Canvas {
throw new NullPointerException();
}
throwIfCannotDraw(bitmap);
- final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+ final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
int left, top, right, bottom;
if (src == null) {
@@ -1482,7 +1486,7 @@ public class Canvas {
}
// punch down to native for the actual draw
native_drawBitmap(mNativeCanvasWrapper, colors, offset, stride, x, y, width, height, hasAlpha,
- paint != null ? paint.mNativePaint : 0);
+ paint != null ? paint.getNativeInstance() : 0);
}
/**
@@ -1510,7 +1514,7 @@ public class Canvas {
*/
public void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint) {
nativeDrawBitmapMatrix(mNativeCanvasWrapper, bitmap.ni(), matrix.ni(),
- paint != null ? paint.mNativePaint : 0);
+ paint != null ? paint.getNativeInstance() : 0);
}
/**
@@ -1566,7 +1570,7 @@ public class Canvas {
}
nativeDrawBitmapMesh(mNativeCanvasWrapper, bitmap.ni(), meshWidth, meshHeight,
verts, vertOffset, colors, colorOffset,
- paint != null ? paint.mNativePaint : 0);
+ paint != null ? paint.getNativeInstance() : 0);
}
public enum VertexMode {
@@ -1619,6 +1623,9 @@ public class Canvas {
int colorOffset, @Nullable short[] indices, int indexOffset, int indexCount,
@NonNull Paint paint) {
checkRange(verts.length, vertOffset, vertexCount);
+ if (isHardwareAccelerated()) {
+ return;
+ }
if (texs != null) {
checkRange(texs.length, texOffset, vertexCount);
}
@@ -1630,7 +1637,7 @@ public class Canvas {
}
nativeDrawVertices(mNativeCanvasWrapper, mode.nativeInt, vertexCount, verts,
vertOffset, texs, texOffset, colors, colorOffset,
- indices, indexOffset, indexCount, paint.mNativePaint);
+ indices, indexOffset, indexCount, paint.getNativeInstance());
}
/**
@@ -1639,7 +1646,7 @@ public class Canvas {
*
* @param text The text to be drawn
* @param x The x-coordinate of the origin of the text being drawn
- * @param y The y-coordinate of the origin of the text being drawn
+ * @param y The y-coordinate of the baseline of the text being drawn
* @param paint The paint used for the text (e.g. color, size, style)
*/
public void drawText(@NonNull char[] text, int index, int count, float x, float y,
@@ -1649,7 +1656,7 @@ public class Canvas {
throw new IndexOutOfBoundsException();
}
native_drawText(mNativeCanvasWrapper, text, index, count, x, y, paint.mBidiFlags,
- paint.mNativePaint, paint.mNativeTypeface);
+ paint.getNativeInstance(), paint.mNativeTypeface);
}
/**
@@ -1658,12 +1665,12 @@ public class Canvas {
*
* @param text The text to be drawn
* @param x The x-coordinate of the origin of the text being drawn
- * @param y The y-coordinate of the origin of the text being drawn
+ * @param y The y-coordinate of the baseline of the text being drawn
* @param paint The paint used for the text (e.g. color, size, style)
*/
public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) {
native_drawText(mNativeCanvasWrapper, text, 0, text.length(), x, y, paint.mBidiFlags,
- paint.mNativePaint, paint.mNativeTypeface);
+ paint.getNativeInstance(), paint.mNativeTypeface);
}
/**
@@ -1674,7 +1681,7 @@ public class Canvas {
* @param start The index of the first character in text to draw
* @param end (end - 1) is the index of the last character in text to draw
* @param x The x-coordinate of the origin of the text being drawn
- * @param y The y-coordinate of the origin of the text being drawn
+ * @param y The y-coordinate of the baseline of the text being drawn
* @param paint The paint used for the text (e.g. color, size, style)
*/
public void drawText(@NonNull String text, int start, int end, float x, float y,
@@ -1683,7 +1690,7 @@ public class Canvas {
throw new IndexOutOfBoundsException();
}
native_drawText(mNativeCanvasWrapper, text, start, end, x, y, paint.mBidiFlags,
- paint.mNativePaint, paint.mNativeTypeface);
+ paint.getNativeInstance(), paint.mNativeTypeface);
}
/**
@@ -1707,7 +1714,7 @@ public class Canvas {
if (text instanceof String || text instanceof SpannedString ||
text instanceof SpannableString) {
native_drawText(mNativeCanvasWrapper, text.toString(), start, end, x, y,
- paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
+ paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
} else if (text instanceof GraphicsOperations) {
((GraphicsOperations) text).drawText(this, start, end, x, y,
paint);
@@ -1715,7 +1722,7 @@ public class Canvas {
char[] buf = TemporaryBuffer.obtain(end - start);
TextUtils.getChars(text, start, end, buf, 0);
native_drawText(mNativeCanvasWrapper, buf, 0, end - start, x, y,
- paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
+ paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
TemporaryBuffer.recycle(buf);
}
}
@@ -1754,7 +1761,7 @@ public class Canvas {
}
native_drawTextRun(mNativeCanvasWrapper, text, index, count,
- contextIndex, contextCount, x, y, isRtl, paint.mNativePaint, paint.mNativeTypeface);
+ contextIndex, contextCount, x, y, isRtl, paint.getNativeInstance(), paint.mNativeTypeface);
}
/**
@@ -1790,7 +1797,7 @@ public class Canvas {
if (text instanceof String || text instanceof SpannedString ||
text instanceof SpannableString) {
native_drawTextRun(mNativeCanvasWrapper, text.toString(), start, end,
- contextStart, contextEnd, x, y, isRtl, paint.mNativePaint, paint.mNativeTypeface);
+ contextStart, contextEnd, x, y, isRtl, paint.getNativeInstance(), paint.mNativeTypeface);
} else if (text instanceof GraphicsOperations) {
((GraphicsOperations) text).drawTextRun(this, start, end,
contextStart, contextEnd, x, y, isRtl, paint);
@@ -1800,7 +1807,7 @@ public class Canvas {
char[] buf = TemporaryBuffer.obtain(contextLen);
TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
native_drawTextRun(mNativeCanvasWrapper, buf, start - contextStart, len,
- 0, contextLen, x, y, isRtl, paint.mNativePaint, paint.mNativeTypeface);
+ 0, contextLen, x, y, isRtl, paint.getNativeInstance(), paint.mNativeTypeface);
TemporaryBuffer.recycle(buf);
}
}
@@ -1868,7 +1875,7 @@ public class Canvas {
}
native_drawTextOnPath(mNativeCanvasWrapper, text, index, count,
path.ni(), hOffset, vOffset,
- paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
+ paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
}
/**
@@ -1888,7 +1895,7 @@ public class Canvas {
float vOffset, @NonNull Paint paint) {
if (text.length() > 0) {
native_drawTextOnPath(mNativeCanvasWrapper, text, path.ni(), hOffset, vOffset,
- paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
+ paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
}
}
diff --git a/graphics/java/android/graphics/CanvasProperty.java b/graphics/java/android/graphics/CanvasProperty.java
index be86060..ea3886c 100644
--- a/graphics/java/android/graphics/CanvasProperty.java
+++ b/graphics/java/android/graphics/CanvasProperty.java
@@ -31,7 +31,7 @@ public final class CanvasProperty<T> {
}
public static CanvasProperty<Paint> createPaint(Paint initialValue) {
- return new CanvasProperty<Paint>(nCreatePaint(initialValue.mNativePaint));
+ return new CanvasProperty<Paint>(nCreatePaint(initialValue.getNativeInstance()));
}
private CanvasProperty(long nativeContainer) {
diff --git a/graphics/java/android/graphics/DrawFilter.java b/graphics/java/android/graphics/DrawFilter.java
index ed38f37..aaefce9 100644
--- a/graphics/java/android/graphics/DrawFilter.java
+++ b/graphics/java/android/graphics/DrawFilter.java
@@ -24,8 +24,11 @@ package android.graphics;
*/
public class DrawFilter {
- // this is set by subclasses, but don't make it public
- /* package */ long mNativeInt; // pointer to native object
+ /**
+ * this is set by subclasses
+ * @hide
+ */
+ public long mNativeInt;
protected void finalize() throws Throwable {
try {
diff --git a/graphics/java/android/graphics/LayerRasterizer.java b/graphics/java/android/graphics/LayerRasterizer.java
index e7a24a4..b692ecf 100644
--- a/graphics/java/android/graphics/LayerRasterizer.java
+++ b/graphics/java/android/graphics/LayerRasterizer.java
@@ -28,11 +28,11 @@ public class LayerRasterizer extends Rasterizer {
object itself, so it may be reused without danger of side-effects.
*/
public void addLayer(Paint paint, float dx, float dy) {
- nativeAddLayer(native_instance, paint.mNativePaint, dx, dy);
+ nativeAddLayer(native_instance, paint.getNativeInstance(), dx, dy);
}
public void addLayer(Paint paint) {
- nativeAddLayer(native_instance, paint.mNativePaint, 0, 0);
+ nativeAddLayer(native_instance, paint.getNativeInstance(), 0, 0);
}
private static native long nativeConstructor();
diff --git a/graphics/java/android/graphics/Movie.java b/graphics/java/android/graphics/Movie.java
index b0a4553..ecb4255 100644
--- a/graphics/java/android/graphics/Movie.java
+++ b/graphics/java/android/graphics/Movie.java
@@ -35,12 +35,17 @@ public class Movie {
public native boolean isOpaque();
public native int duration();
- public native boolean setTime(int relativeMilliseconds);
+ public native boolean setTime(int relativeMilliseconds);
+
+ private native void nDraw(long nativeCanvas, float x, float y, long paintHandle);
+
+ public void draw(Canvas canvas, float x, float y, Paint paint) {
+ nDraw(canvas.getNativeCanvasWrapper(), x, y,
+ paint != null ? paint.getNativeInstance() : 0);
+ }
- public native void draw(Canvas canvas, float x, float y, Paint paint);
-
public void draw(Canvas canvas, float x, float y) {
- draw(canvas, x, y, null);
+ nDraw(canvas.getNativeCanvasWrapper(), x, y, 0);
}
public static Movie decodeStream(InputStream is) {
diff --git a/graphics/java/android/graphics/NinePatch.java b/graphics/java/android/graphics/NinePatch.java
index 6f42046..ebc86aa 100644
--- a/graphics/java/android/graphics/NinePatch.java
+++ b/graphics/java/android/graphics/NinePatch.java
@@ -200,12 +200,12 @@ public class NinePatch {
void drawSoftware(Canvas canvas, RectF location, Paint paint) {
nativeDraw(canvas.getNativeCanvasWrapper(), location, mBitmap.ni(), mNativeChunk,
- paint != null ? paint.mNativePaint : 0, canvas.mDensity, mBitmap.mDensity);
+ paint != null ? paint.getNativeInstance() : 0, canvas.mDensity, mBitmap.mDensity);
}
void drawSoftware(Canvas canvas, Rect location, Paint paint) {
nativeDraw(canvas.getNativeCanvasWrapper(), location, mBitmap.ni(), mNativeChunk,
- paint != null ? paint.mNativePaint : 0, canvas.mDensity, mBitmap.mDensity);
+ paint != null ? paint.getNativeInstance() : 0, canvas.mDensity, mBitmap.mDensity);
}
/**
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 652fe64..91c8dba 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -29,10 +29,9 @@ import java.util.Locale;
*/
public class Paint {
- /**
- * @hide
- */
- public long mNativePaint;
+ private long mNativePaint;
+ private long mNativeShader = 0;
+
/**
* @hide
*/
@@ -445,7 +444,7 @@ public class Paint {
* new paint.
*/
public Paint(Paint paint) {
- mNativePaint = native_initWithPaint(paint.mNativePaint);
+ mNativePaint = native_initWithPaint(paint.getNativeInstance());
setClassVariablesFrom(paint);
}
@@ -464,6 +463,7 @@ public class Paint {
mPathEffect = null;
mRasterizer = null;
mShader = null;
+ mNativeShader = 0;
mTypeface = null;
mNativeTypeface = 0;
mXfermode = null;
@@ -500,11 +500,8 @@ public class Paint {
mMaskFilter = paint.mMaskFilter;
mPathEffect = paint.mPathEffect;
mRasterizer = paint.mRasterizer;
- if (paint.mShader != null) {
- mShader = paint.mShader.copy();
- } else {
- mShader = null;
- }
+ mShader = paint.mShader;
+ mNativeShader = paint.mNativeShader;
mTypeface = paint.mTypeface;
mNativeTypeface = paint.mNativeTypeface;
mXfermode = paint.mXfermode;
@@ -531,6 +528,20 @@ public class Paint {
}
/**
+ * Return the pointer to the native object while ensuring that any
+ * mutable objects that are attached to the paint are also up-to-date.
+ *
+ * @hide
+ */
+ public long getNativeInstance() {
+ if (mShader != null && mShader.getNativeInstance() != mNativeShader) {
+ mNativeShader = mShader.getNativeInstance();
+ native_setShader(mNativePaint, mNativeShader);
+ }
+ return mNativePaint;
+ }
+
+ /**
* Return the bidi flags on the paint.
*
* @return the bidi flags on the paint
@@ -920,10 +931,7 @@ public class Paint {
* @return shader
*/
public Shader setShader(Shader shader) {
- long shaderNative = 0;
- if (shader != null)
- shaderNative = shader.getNativeInstance();
- native_setShader(mNativePaint, shaderNative);
+ // Defer setting the shader natively until getNativeInstance() is called
mShader = shader;
return shader;
}
diff --git a/graphics/java/android/graphics/PaintFlagsDrawFilter.java b/graphics/java/android/graphics/PaintFlagsDrawFilter.java
index 65a6218..2326611 100644
--- a/graphics/java/android/graphics/PaintFlagsDrawFilter.java
+++ b/graphics/java/android/graphics/PaintFlagsDrawFilter.java
@@ -17,11 +17,6 @@
package android.graphics;
public class PaintFlagsDrawFilter extends DrawFilter {
- /** @hide **/
- public final int clearBits;
- /** @hide **/
- public final int setBits;
-
/**
* Subclass of DrawFilter that affects every paint by first clearing
* the specified clearBits in the paint's flags, and then setting the
@@ -31,8 +26,6 @@ public class PaintFlagsDrawFilter extends DrawFilter {
* @param setBits These bits will be set in the paint's flags
*/
public PaintFlagsDrawFilter(int clearBits, int setBits) {
- this.clearBits = clearBits;
- this.setBits = setBits;
// our native constructor can return 0, if the specified bits
// are effectively a no-op
mNativeInt = nativeConstructor(clearBits, setBits);
diff --git a/graphics/java/android/graphics/Picture.java b/graphics/java/android/graphics/Picture.java
index fa9af2a..39272b9 100644
--- a/graphics/java/android/graphics/Picture.java
+++ b/graphics/java/android/graphics/Picture.java
@@ -122,11 +122,6 @@ public class Picture {
* @param canvas The picture is drawn to this canvas
*/
public void draw(Canvas canvas) {
- if (canvas.isHardwareAccelerated()) {
- throw new IllegalArgumentException(
- "Picture playback is only supported on software canvas.");
- }
-
if (mRecordingCanvas != null) {
endRecording();
}
diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java
index 6934955..a96d2cb 100644
--- a/graphics/java/android/graphics/Shader.java
+++ b/graphics/java/android/graphics/Shader.java
@@ -82,7 +82,8 @@ public class Shader {
*/
public void setLocalMatrix(Matrix localM) {
mLocalMatrix = localM;
- nativeSetLocalMatrix(native_instance, localM == null ? 0 : localM.native_instance);
+ native_instance = nativeSetLocalMatrix(native_instance,
+ localM == null ? 0 : localM.native_instance);
}
protected void finalize() throws Throwable {
@@ -120,5 +121,5 @@ public class Shader {
}
private static native void nativeDestructor(long native_shader);
- private static native void nativeSetLocalMatrix(long native_shader, long matrix_instance);
+ private static native long nativeSetLocalMatrix(long native_shader, long matrix_instance);
}
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 9be296a..945ae2e 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -357,6 +357,11 @@ public class BitmapDrawable extends Drawable {
invalidateSelf();
}
+ @Override
+ public boolean getDither() {
+ return mBitmapState.mPaint.isDither();
+ }
+
/**
* Indicates the repeat behavior of this drawable on the X axis.
*
@@ -705,8 +710,8 @@ public class BitmapDrawable extends Drawable {
@Override
public boolean isStateful() {
- final BitmapState s = mBitmapState;
- return super.isStateful() || (s.mTint != null && s.mTint.isStateful());
+ return (mBitmapState.mTint != null && mBitmapState.mTint.isStateful())
+ || super.isStateful();
}
@Override
@@ -718,6 +723,9 @@ public class BitmapDrawable extends Drawable {
updateStateFromTypedArray(a);
verifyState(a);
a.recycle();
+
+ // Update local properties.
+ updateLocalState(r);
}
/**
@@ -800,9 +808,6 @@ public class BitmapDrawable extends Drawable {
if (tileModeY != TILE_MODE_UNDEFINED) {
setTileModeY(parseTileMode(tileModeY));
}
-
- // Update local properties.
- initializeWithState(state, r);
}
@Override
@@ -810,18 +815,28 @@ public class BitmapDrawable extends Drawable {
super.applyTheme(t);
final BitmapState state = mBitmapState;
- if (state == null || state.mThemeAttrs == null) {
+ if (state == null) {
return;
}
- final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.BitmapDrawable);
- try {
- updateStateFromTypedArray(a);
- } catch (XmlPullParserException e) {
- throw new RuntimeException(e);
- } finally {
- a.recycle();
+ if (state.mThemeAttrs != null) {
+ final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.BitmapDrawable);
+ try {
+ updateStateFromTypedArray(a);
+ } catch (XmlPullParserException e) {
+ throw new RuntimeException(e);
+ } finally {
+ a.recycle();
+ }
+ }
+
+ // Apply theme to contained color state list.
+ if (state.mTint != null && state.mTint.canApplyTheme()) {
+ state.mTint.applyTheme(t);
}
+
+ // Update local properties.
+ updateLocalState(t.getResources());
}
private static Shader.TileMode parseTileMode(int tileMode) {
@@ -839,7 +854,7 @@ public class BitmapDrawable extends Drawable {
@Override
public boolean canApplyTheme() {
- return mBitmapState != null && mBitmapState.mThemeAttrs != null;
+ return mBitmapState != null && mBitmapState.canApplyTheme();
}
@Override
@@ -910,7 +925,7 @@ public class BitmapDrawable extends Drawable {
@Override
public boolean canApplyTheme() {
- return mThemeAttrs != null;
+ return mThemeAttrs != null || mTint != null && mTint.canApplyTheme();
}
@Override
@@ -944,7 +959,7 @@ public class BitmapDrawable extends Drawable {
private BitmapDrawable(BitmapState state, Resources res) {
mBitmapState = state;
- initializeWithState(mBitmapState, res);
+ updateLocalState(res);
}
/**
@@ -952,14 +967,14 @@ public class BitmapDrawable extends Drawable {
* after significant state changes, e.g. from the One True Constructor and
* after inflating or applying a theme.
*/
- private void initializeWithState(BitmapState state, Resources res) {
+ private void updateLocalState(Resources res) {
if (res != null) {
mTargetDensity = res.getDisplayMetrics().densityDpi;
} else {
- mTargetDensity = state.mTargetDensity;
+ mTargetDensity = mBitmapState.mTargetDensity;
}
- mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
+ mTintFilter = updateTintFilter(mTintFilter, mBitmapState.mTint, mBitmapState.mTintMode);
computeBitmapSize();
}
}
diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java
index e3b50ea..85e02b7 100644
--- a/graphics/java/android/graphics/drawable/ColorDrawable.java
+++ b/graphics/java/android/graphics/drawable/ColorDrawable.java
@@ -70,7 +70,7 @@ public class ColorDrawable extends Drawable {
@Override
public int getChangingConfigurations() {
- return super.getChangingConfigurations() | mColorState.mChangingConfigurations;
+ return super.getChangingConfigurations() | mColorState.getChangingConfigurations();
}
/**
@@ -233,6 +233,8 @@ public class ColorDrawable extends Drawable {
final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.ColorDrawable);
updateStateFromTypedArray(a);
a.recycle();
+
+ updateLocalState(r);
}
/**
@@ -261,13 +263,21 @@ public class ColorDrawable extends Drawable {
super.applyTheme(t);
final ColorState state = mColorState;
- if (state == null || state.mThemeAttrs == null) {
+ if (state == null) {
return;
}
- final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.ColorDrawable);
- updateStateFromTypedArray(a);
- a.recycle();
+ if (state.mThemeAttrs != null) {
+ final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.ColorDrawable);
+ updateStateFromTypedArray(a);
+ a.recycle();
+ }
+
+ if (state.mTint != null && state.mTint.canApplyTheme()) {
+ state.mTint.applyTheme(t);
+ }
+
+ updateLocalState(t.getResources());
}
@Override
@@ -299,17 +309,18 @@ public class ColorDrawable extends Drawable {
@Override
public boolean canApplyTheme() {
- return mThemeAttrs != null;
+ return mThemeAttrs != null
+ || (mTint != null && mTint.canApplyTheme());
}
@Override
public Drawable newDrawable() {
- return new ColorDrawable(this);
+ return new ColorDrawable(this, null);
}
@Override
public Drawable newDrawable(Resources res) {
- return new ColorDrawable(this);
+ return new ColorDrawable(this, res);
}
@Override
@@ -318,8 +329,18 @@ public class ColorDrawable extends Drawable {
}
}
- private ColorDrawable(ColorState state) {
+ private ColorDrawable(ColorState state, Resources res) {
mColorState = state;
- mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
+
+ updateLocalState(res);
+ }
+
+ /**
+ * Initializes local dynamic properties from state. This should be called
+ * after significant state changes, e.g. from the One True Constructor and
+ * after inflating or applying a theme.
+ */
+ private void updateLocalState(Resources r) {
+ mTintFilter = updateTintFilter(mTintFilter, mColorState.mTint, mColorState.mTintMode);
}
}
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 0e38cc0..c9d7869 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -39,6 +39,7 @@ import android.graphics.Xfermode;
import android.os.Trace;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
+import android.util.IntProperty;
import android.util.StateSet;
import android.util.TypedValue;
import android.util.Xml;
@@ -274,6 +275,14 @@ public abstract class Drawable {
public void setDither(boolean dither) {}
/**
+ * @return whether this drawable dither its colors
+ * @see #setDither(boolean)
+ */
+ public boolean getDither() {
+ return false;
+ }
+
+ /**
* Set to true to have the drawable filter its bitmap when scaled or rotated
* (for drawables that use bitmaps). If the drawable does not use bitmaps,
* this call is ignored. This can improve the look when scaled or rotated,
@@ -282,6 +291,14 @@ public abstract class Drawable {
public void setFilterBitmap(boolean filter) {}
/**
+ * @return whether this drawable filters its bitmap
+ * @see #setFilterBitmap(boolean)
+ */
+ public boolean getFilterBitmap() {
+ return false;
+ }
+
+ /**
* Implement this interface if you want to create an animated drawable that
* extends {@link android.graphics.drawable.Drawable Drawable}.
* Upon retrieving a drawable, use
@@ -1335,5 +1352,20 @@ public abstract class Drawable {
default: return defaultMode;
}
}
+
+ /** @hide */
+ public static final IntProperty<Drawable> ALPHA = new IntProperty<Drawable>("alpha") {
+ @Override
+ public void setValue(Drawable object, int value) {
+ object.mutate();
+ object.setAlpha(value);
+ object.invalidateSelf();
+ }
+
+ @Override
+ public Integer get(Drawable object) {
+ return object.getAlpha();
+ }
+ };
}
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 39ef10c..557f563 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -167,6 +167,11 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
}
@Override
+ public boolean getDither() {
+ return mDrawableContainerState.mDither;
+ }
+
+ @Override
public void setColorFilter(ColorFilter cf) {
mDrawableContainerState.mHasColorFilter = (cf != null);
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 72707e6..cc2de22 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -143,7 +143,7 @@ public class GradientDrawable extends Drawable {
private final RectF mRect = new RectF();
private Paint mLayerPaint; // internal, used if we use saveLayer()
- private boolean mGradientIsDirty; // internal state
+ private boolean mGradientIsDirty;
private boolean mMutated;
private Path mRingPath;
private boolean mPathIsDirty = true;
@@ -174,7 +174,7 @@ public class GradientDrawable extends Drawable {
}
public GradientDrawable() {
- this(new GradientState(Orientation.TOP_BOTTOM, null));
+ this(new GradientState(Orientation.TOP_BOTTOM, null), null);
}
/**
@@ -182,7 +182,7 @@ public class GradientDrawable extends Drawable {
* of colors for the gradient.
*/
public GradientDrawable(Orientation orientation, int[] colors) {
- this(new GradientState(orientation, colors));
+ this(new GradientState(orientation, colors), null);
}
@Override
@@ -822,6 +822,11 @@ public class GradientDrawable extends Drawable {
}
@Override
+ public boolean getDither() {
+ return mGradientState.mDither;
+ }
+
+ @Override
public ColorFilter getColorFilter() {
return mColorFilter;
}
@@ -1018,7 +1023,7 @@ public class GradientDrawable extends Drawable {
inflateChildElements(r, parser, attrs, theme);
- mGradientState.computeOpacity();
+ updateLocalState(r);
}
@Override
@@ -1037,9 +1042,21 @@ public class GradientDrawable extends Drawable {
a.recycle();
}
+ if (state.mTint != null && state.mTint.canApplyTheme()) {
+ state.mTint.applyTheme(t);
+ }
+
+ if (state.mColorStateList != null && state.mColorStateList.canApplyTheme()) {
+ state.mColorStateList.applyTheme(t);
+ }
+
+ if (state.mStrokeColorStateList != null && state.mStrokeColorStateList.canApplyTheme()) {
+ state.mStrokeColorStateList.applyTheme(t);
+ }
+
applyThemeChildElements(t);
- state.computeOpacity();
+ updateLocalState(t.getResources());
}
/**
@@ -1087,8 +1104,6 @@ public class GradientDrawable extends Drawable {
if (tint != null) {
state.mTint = tint;
}
-
- mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
}
@Override
@@ -1516,7 +1531,7 @@ public class GradientDrawable extends Drawable {
public Drawable mutate() {
if (!mMutated && super.mutate() == this) {
mGradientState = new GradientState(mGradientState);
- initializeWithState(mGradientState);
+ updateLocalState(null);
mMutated = true;
}
return this;
@@ -1577,7 +1592,7 @@ public class GradientDrawable extends Drawable {
int[] mAttrCorners;
int[] mAttrPadding;
- GradientState(Orientation orientation, int[] colors) {
+ public GradientState(Orientation orientation, int[] colors) {
mOrientation = orientation;
setColors(colors);
}
@@ -1634,19 +1649,24 @@ public class GradientDrawable extends Drawable {
@Override
public boolean canApplyTheme() {
- return mThemeAttrs != null || mAttrSize != null || mAttrGradient != null
- || mAttrSolid != null || mAttrStroke != null || mAttrCorners != null
- || mAttrPadding != null || super.canApplyTheme();
+ return mThemeAttrs != null
+ || mAttrSize != null || mAttrGradient != null
+ || mAttrSolid != null || mAttrStroke != null
+ || mAttrCorners != null || mAttrPadding != null
+ || (mTint != null && mTint.canApplyTheme())
+ || (mStrokeColorStateList != null && mStrokeColorStateList.canApplyTheme())
+ || (mColorStateList != null && mColorStateList.canApplyTheme())
+ || super.canApplyTheme();
}
@Override
public Drawable newDrawable() {
- return new GradientDrawable(this);
+ return new GradientDrawable(this, null);
}
@Override
public Drawable newDrawable(Resources res) {
- return new GradientDrawable(this);
+ return new GradientDrawable(this, res);
}
@Override
@@ -1751,16 +1771,15 @@ public class GradientDrawable extends Drawable {
*
* @param state Constant state from which the drawable inherits
*/
- private GradientDrawable(GradientState state) {
+ private GradientDrawable(GradientState state, Resources res) {
mGradientState = state;
- initializeWithState(mGradientState);
-
- mGradientIsDirty = true;
- mMutated = false;
+ updateLocalState(res);
}
- private void initializeWithState(GradientState state) {
+ private void updateLocalState(Resources res) {
+ final GradientState state = mGradientState;
+
if (state.mColorStateList != null) {
final int[] currentState = getState();
final int stateColor = state.mColorStateList.getColorForState(currentState, 0);
@@ -1797,5 +1816,8 @@ public class GradientDrawable extends Drawable {
}
mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
+ mGradientIsDirty = true;
+
+ state.computeOpacity();
}
}
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index 8b70a08..50a6df4 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -34,7 +34,6 @@ import android.graphics.Insets;
import android.graphics.Outline;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff.Mode;
-import android.graphics.drawable.Drawable.ConstantState;
import android.graphics.Rect;
import android.util.AttributeSet;
@@ -60,28 +59,49 @@ import java.util.Collection;
public class InsetDrawable extends Drawable implements Drawable.Callback {
private final Rect mTmpRect = new Rect();
- private final InsetState mState;
+ private InsetState mState;
+ private Drawable mDrawable;
private boolean mMutated;
- /*package*/ InsetDrawable() {
- this(null, null);
+ /**
+ * No-arg constructor used by drawable inflation.
+ */
+ InsetDrawable() {
+ this(new InsetState(), null);
}
+ /**
+ * Creates a new inset drawable with the specified inset.
+ *
+ * @param drawable The drawable to inset.
+ * @param inset Inset in pixels around the drawable.
+ */
public InsetDrawable(Drawable drawable, int inset) {
this(drawable, inset, inset, inset, inset);
}
- public InsetDrawable(Drawable drawable, int insetLeft, int insetTop,
- int insetRight, int insetBottom) {
- this(null, null);
+ /**
+ * Creates a new inset drawable with the specified insets.
+ *
+ * @param drawable The drawable to inset.
+ * @param insetLeft Left inset in pixels.
+ * @param insetTop Top inset in pixels.
+ * @param insetRight Right inset in pixels.
+ * @param insetBottom Bottom inset in pixels.
+ */
+ public InsetDrawable(Drawable drawable, int insetLeft, int insetTop,int insetRight,
+ int insetBottom) {
+ this(new InsetState(), null);
- mState.mDrawable = drawable;
+ mState.mDrawableState = drawable == null ? null : drawable.getConstantState();
mState.mInsetLeft = insetLeft;
mState.mInsetTop = insetTop;
mState.mInsetRight = insetRight;
mState.mInsetBottom = insetBottom;
+ mDrawable = drawable;
+
if (drawable != null) {
drawable.setCallback(this);
}
@@ -93,38 +113,53 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.InsetDrawable);
super.inflateWithAttributes(r, parser, a, R.styleable.InsetDrawable_visible);
- // Reset mDrawable to preserve old multiple-inflate behavior. This is
- // silly, but we have CTS tests that rely on it.
- mState.mDrawable = null;
-
updateStateFromTypedArray(a);
inflateChildElements(r, parser, attrs, theme);
verifyRequiredAttributes(a);
a.recycle();
}
+ private void setDrawable(Drawable dr) {
+ if (mDrawable != null) {
+ mDrawable.setCallback(null);
+ }
+
+ mDrawable = dr;
+
+ if (dr != null) {
+ dr.setCallback(this);
+ dr.setVisible(isVisible(), true);
+ dr.setState(getState());
+ dr.setLevel(getLevel());
+ dr.setBounds(getBounds());
+ dr.setLayoutDirection(getLayoutDirection());
+ }
+ }
+
private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
Theme theme) throws XmlPullParserException, IOException {
// Load inner XML elements.
- if (mState.mDrawable == null) {
+ if (mDrawable == null) {
int type;
while ((type=parser.next()) == XmlPullParser.TEXT) {
}
if (type != XmlPullParser.START_TAG) {
- throw new XmlPullParserException(
- parser.getPositionDescription()
- + ": <inset> tag requires a 'drawable' attribute or "
- + "child tag defining a drawable");
+ throw new XmlPullParserException(parser.getPositionDescription()
+ + ": <inset> tag requires a 'drawable' attribute or "
+ + "child tag defining a drawable");
}
+
final Drawable dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
- mState.mDrawable = dr;
- dr.setCallback(this);
+ if (dr != null) {
+ mState.mDrawableState = dr.getConstantState();
+ setDrawable(dr);
+ }
}
}
private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
// If we're not waiting on a theme, verify required attributes.
- if (mState.mDrawable == null && (mState.mThemeAttrs == null
+ if (mDrawable == null && (mState.mThemeAttrs == null
|| mState.mThemeAttrs[R.styleable.InsetDrawable_drawable] == 0)) {
throw new XmlPullParserException(a.getPositionDescription()
+ ": <inset> tag requires a 'drawable' attribute or "
@@ -148,8 +183,8 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
case R.styleable.InsetDrawable_drawable:
final Drawable dr = a.getDrawable(attr);
if (dr != null) {
- state.mDrawable = dr;
- dr.setCallback(this);
+ mState.mDrawableState = dr.getConstantState();
+ setDrawable(dr);
}
break;
case R.styleable.InsetDrawable_inset:
@@ -198,8 +233,8 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
}
}
- if (state.mDrawable != null && state.mDrawable.canApplyTheme()) {
- state.mDrawable.applyTheme(t);
+ if (mDrawable != null && mDrawable.canApplyTheme()) {
+ mDrawable.applyTheme(t);
}
}
@@ -234,27 +269,27 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
@Override
public void draw(Canvas canvas) {
- mState.mDrawable.draw(canvas);
+ mDrawable.draw(canvas);
}
@Override
public int getChangingConfigurations() {
return super.getChangingConfigurations()
| mState.mChangingConfigurations
- | mState.mDrawable.getChangingConfigurations();
+ | mDrawable.getChangingConfigurations();
}
@Override
public boolean getPadding(Rect padding) {
- boolean pad = mState.mDrawable.getPadding(padding);
+ final boolean pad = mDrawable.getPadding(padding);
padding.left += mState.mInsetLeft;
padding.right += mState.mInsetRight;
padding.top += mState.mInsetTop;
padding.bottom += mState.mInsetBottom;
- return pad || (mState.mInsetLeft | mState.mInsetRight |
- mState.mInsetTop | mState.mInsetBottom) != 0;
+ return pad || (mState.mInsetLeft | mState.mInsetRight
+ | mState.mInsetTop | mState.mInsetBottom) != 0;
}
/** @hide */
@@ -269,61 +304,61 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
@Override
public void setHotspot(float x, float y) {
- mState.mDrawable.setHotspot(x, y);
+ mDrawable.setHotspot(x, y);
}
@Override
public void setHotspotBounds(int left, int top, int right, int bottom) {
- mState.mDrawable.setHotspotBounds(left, top, right, bottom);
+ mDrawable.setHotspotBounds(left, top, right, bottom);
}
/** @hide */
@Override
public void getHotspotBounds(Rect outRect) {
- mState.mDrawable.getHotspotBounds(outRect);
+ mDrawable.getHotspotBounds(outRect);
}
@Override
public boolean setVisible(boolean visible, boolean restart) {
- mState.mDrawable.setVisible(visible, restart);
+ mDrawable.setVisible(visible, restart);
return super.setVisible(visible, restart);
}
@Override
public void setAlpha(int alpha) {
- mState.mDrawable.setAlpha(alpha);
+ mDrawable.setAlpha(alpha);
}
@Override
public int getAlpha() {
- return mState.mDrawable.getAlpha();
+ return mDrawable.getAlpha();
}
@Override
public void setColorFilter(ColorFilter cf) {
- mState.mDrawable.setColorFilter(cf);
+ mDrawable.setColorFilter(cf);
}
@Override
public void setTintList(ColorStateList tint) {
- mState.mDrawable.setTintList(tint);
+ mDrawable.setTintList(tint);
}
@Override
public void setTintMode(Mode tintMode) {
- mState.mDrawable.setTintMode(tintMode);
+ mDrawable.setTintMode(tintMode);
}
/** {@hide} */
@Override
public void setLayoutDirection(int layoutDirection) {
- mState.mDrawable.setLayoutDirection(layoutDirection);
+ mDrawable.setLayoutDirection(layoutDirection);
}
@Override
public int getOpacity() {
final InsetState state = mState;
- final int opacity = state.mDrawable.getOpacity();
+ final int opacity = mDrawable.getOpacity();
if (opacity == PixelFormat.OPAQUE && (state.mInsetLeft > 0 || state.mInsetTop > 0
|| state.mInsetRight > 0 || state.mInsetBottom > 0)) {
return PixelFormat.TRANSLUCENT;
@@ -333,19 +368,19 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
@Override
public boolean isStateful() {
- return mState.mDrawable.isStateful();
+ return mDrawable.isStateful();
}
@Override
protected boolean onStateChange(int[] state) {
- boolean changed = mState.mDrawable.setState(state);
+ final boolean changed = mDrawable.setState(state);
onBoundsChange(getBounds());
return changed;
}
@Override
protected boolean onLevelChange(int level) {
- return mState.mDrawable.setLevel(level);
+ return mDrawable.setLevel(level);
}
@Override
@@ -358,24 +393,22 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
r.right -= mState.mInsetRight;
r.bottom -= mState.mInsetBottom;
- mState.mDrawable.setBounds(r.left, r.top, r.right, r.bottom);
+ mDrawable.setBounds(r.left, r.top, r.right, r.bottom);
}
@Override
public int getIntrinsicWidth() {
- return mState.mDrawable.getIntrinsicWidth()
- + mState.mInsetLeft + mState.mInsetRight;
+ return mDrawable.getIntrinsicWidth() + mState.mInsetLeft + mState.mInsetRight;
}
@Override
public int getIntrinsicHeight() {
- return mState.mDrawable.getIntrinsicHeight()
- + mState.mInsetTop + mState.mInsetBottom;
+ return mDrawable.getIntrinsicHeight() + mState.mInsetTop + mState.mInsetBottom;
}
@Override
public void getOutline(@NonNull Outline outline) {
- mState.mDrawable.getOutline(outline);
+ mDrawable.getOutline(outline);
}
@Override
@@ -390,7 +423,9 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
@Override
public Drawable mutate() {
if (!mMutated && super.mutate() == this) {
- mState.mDrawable.mutate();
+ mState = new InsetState(mState);
+ mDrawable.mutate();
+ mState.mDrawableState = mDrawable.getConstantState();
mMutated = true;
}
return this;
@@ -401,7 +436,7 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
*/
public void clearMutated() {
super.clearMutated();
- mState.mDrawable.clearMutated();
+ mDrawable.clearMutated();
mMutated = false;
}
@@ -409,51 +444,53 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
* Returns the drawable wrapped by this InsetDrawable. May be null.
*/
public Drawable getDrawable() {
- return mState.mDrawable;
+ return mDrawable;
}
- final static class InsetState extends ConstantState {
+ private static final class InsetState extends ConstantState {
int[] mThemeAttrs;
int mChangingConfigurations;
- Drawable mDrawable;
+ ConstantState mDrawableState;
int mInsetLeft = 0;
int mInsetTop = 0;
int mInsetRight = 0;
int mInsetBottom = 0;
- private boolean mCheckedConstantState;
- private boolean mCanConstantState;
+ public InsetState() {
+ // Empty constructor.
+ }
- InsetState(InsetState orig, InsetDrawable owner, Resources res) {
+ public InsetState(InsetState orig) {
if (orig != null) {
mThemeAttrs = orig.mThemeAttrs;
mChangingConfigurations = orig.mChangingConfigurations;
- if (res != null) {
- mDrawable = orig.mDrawable.getConstantState().newDrawable(res);
- } else {
- mDrawable = orig.mDrawable.getConstantState().newDrawable();
- }
- mDrawable.setCallback(owner);
- mDrawable.setLayoutDirection(orig.mDrawable.getLayoutDirection());
- mDrawable.setBounds(orig.mDrawable.getBounds());
- mDrawable.setLevel(orig.mDrawable.getLevel());
+ mDrawableState = orig.mDrawableState;
mInsetLeft = orig.mInsetLeft;
mInsetTop = orig.mInsetTop;
mInsetRight = orig.mInsetRight;
mInsetBottom = orig.mInsetBottom;
- mCheckedConstantState = mCanConstantState = true;
}
}
@Override
public boolean canApplyTheme() {
- return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme())
+ return mThemeAttrs != null
+ || (mDrawableState != null && mDrawableState.canApplyTheme())
|| super.canApplyTheme();
}
@Override
+ public int addAtlasableBitmaps(Collection<Bitmap> atlasList) {
+ final ConstantState state = mDrawableState;
+ if (state != null) {
+ return state.addAtlasableBitmaps(atlasList);
+ }
+ return 0;
+ }
+
+ @Override
public Drawable newDrawable() {
return new InsetDrawable(this, null);
}
@@ -468,27 +505,31 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
return mChangingConfigurations;
}
- boolean canConstantState() {
- if (!mCheckedConstantState) {
- mCanConstantState = mDrawable.getConstantState() != null;
- mCheckedConstantState = true;
- }
-
- return mCanConstantState;
- }
-
- @Override
- public int addAtlasableBitmaps(Collection<Bitmap> atlasList) {
- final ConstantState state = mDrawable.getConstantState();
- if (state != null) {
- return state.addAtlasableBitmaps(atlasList);
- }
- return 0;
+ public boolean canConstantState() {
+ return mDrawableState != null;
}
}
+ /**
+ * The one constructor to rule them all. This is called by all public
+ * constructors to set the state and initialize local properties.
+ */
private InsetDrawable(InsetState state, Resources res) {
- mState = new InsetState(state, this, res);
+ mState = state;
+
+ updateLocalState(res);
+ }
+
+ /**
+ * Initializes local dynamic properties from state. This should be called
+ * after significant state changes, e.g. from the One True Constructor and
+ * after inflating or applying a theme.
+ */
+ private void updateLocalState(Resources res) {
+ if (mState.mDrawableState != null) {
+ final Drawable dr = mState.mDrawableState.newDrawable(res);
+ setDrawable(dr);
+ }
}
}
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 4aa5f59..616aebd 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -29,6 +29,8 @@ import android.graphics.PixelFormat;
import android.graphics.PorterDuff.Mode;
import android.graphics.Rect;
import android.util.AttributeSet;
+import android.util.LayoutDirection;
+import android.view.Gravity;
import android.view.View;
import com.android.internal.R;
@@ -54,6 +56,11 @@ import java.util.Collection;
* @attr ref android.R.styleable#LayerDrawableItem_top
* @attr ref android.R.styleable#LayerDrawableItem_right
* @attr ref android.R.styleable#LayerDrawableItem_bottom
+ * @attr ref android.R.styleable#LayerDrawableItem_start
+ * @attr ref android.R.styleable#LayerDrawableItem_end
+ * @attr ref android.R.styleable#LayerDrawableItem_width
+ * @attr ref android.R.styleable#LayerDrawableItem_height
+ * @attr ref android.R.styleable#LayerDrawableItem_gravity
* @attr ref android.R.styleable#LayerDrawableItem_drawable
* @attr ref android.R.styleable#LayerDrawableItem_id
*/
@@ -73,6 +80,9 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
*/
public static final int PADDING_MODE_STACK = 1;
+ /** Value used for undefined start and end insets. */
+ private static final int UNDEFINED_INSET = Integer.MIN_VALUE;
+
LayerState mLayerState;
private int mOpacityOverride = PixelFormat.UNKNOWN;
@@ -82,6 +92,8 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
private int[] mPaddingB;
private final Rect mTmpRect = new Rect();
+ private final Rect mTmpOutRect = new Rect();
+ private final Rect mTmpContainer = new Rect();
private Rect mHotspotBounds;
private boolean mMutated;
@@ -231,6 +243,16 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
R.styleable.LayerDrawableItem_right, layer.mInsetR);
layer.mInsetB = a.getDimensionPixelOffset(
R.styleable.LayerDrawableItem_bottom, layer.mInsetB);
+ layer.mInsetS = a.getDimensionPixelOffset(
+ R.styleable.LayerDrawableItem_start, layer.mInsetS);
+ layer.mInsetE = a.getDimensionPixelOffset(
+ R.styleable.LayerDrawableItem_end, layer.mInsetE);
+ layer.mWidth = a.getDimensionPixelSize(
+ R.styleable.LayerDrawableItem_width, layer.mWidth);
+ layer.mHeight = a.getDimensionPixelSize(
+ R.styleable.LayerDrawableItem_height, layer.mHeight);
+ layer.mGravity = a.getInteger(
+ R.styleable.LayerDrawableItem_gravity, layer.mGravity);
layer.mId = a.getResourceId(R.styleable.LayerDrawableItem_id, layer.mId);
final Drawable dr = a.getDrawable(R.styleable.LayerDrawableItem_drawable);
@@ -300,7 +322,13 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
return false;
}
- void addLayer(ChildDrawable layer) {
+ /**
+ * Adds a new layer at the end of list of layers and returns its index.
+ *
+ * @param layer The layer to add.
+ * @return The index of the layer.
+ */
+ int addLayer(ChildDrawable layer) {
final LayerState st = mLayerState;
final int N = st.mChildren != null ? st.mChildren.length : 0;
final int i = st.mNum;
@@ -316,12 +344,13 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
st.mChildren[i] = layer;
st.mNum++;
st.invalidateCache();
+ return i;
}
/**
* Add a new layer to this drawable. The new layer is identified by an id.
*
- * @param layer The drawable to add as a layer.
+ * @param dr The drawable to add as a layer.
* @param themeAttrs Theme attributes extracted from the layer.
* @param id The id of the new layer.
* @param left The left padding of the new layer.
@@ -329,12 +358,11 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
* @param right The right padding of the new layer.
* @param bottom The bottom padding of the new layer.
*/
- ChildDrawable addLayer(Drawable layer, int[] themeAttrs, int id, int left, int top, int right,
- int bottom) {
- final ChildDrawable childDrawable = new ChildDrawable();
+ ChildDrawable addLayer(Drawable dr, int[] themeAttrs, int id,
+ int left, int top, int right, int bottom) {
+ final ChildDrawable childDrawable = createLayer(dr);
childDrawable.mId = id;
childDrawable.mThemeAttrs = themeAttrs;
- childDrawable.mDrawable = layer;
childDrawable.mDrawable.setAutoMirrored(isAutoMirrored());
childDrawable.mInsetL = left;
childDrawable.mInsetT = top;
@@ -343,12 +371,31 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
addLayer(childDrawable);
- mLayerState.mChildrenChangingConfigurations |= layer.getChangingConfigurations();
- layer.setCallback(this);
+ mLayerState.mChildrenChangingConfigurations |= dr.getChangingConfigurations();
+ dr.setCallback(this);
return childDrawable;
}
+ private ChildDrawable createLayer(Drawable dr) {
+ final ChildDrawable layer = new ChildDrawable();
+ layer.mDrawable = dr;
+ return layer;
+ }
+
+ /**
+ * Adds a new layer containing the specified {@code drawable} to the end of
+ * the layer list and returns its index.
+ *
+ * @param dr The drawable to add as a new layer.
+ * @return The index of the new layer.
+ */
+ public int addLayer(Drawable dr) {
+ final ChildDrawable layer = createLayer(dr);
+ final int index = addLayer(layer);
+ return index;
+ }
+
/**
* Looks for a layer with the given ID and returns its {@link Drawable}.
* <p>
@@ -373,45 +420,46 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
/**
* Sets the ID of a layer.
*
- * @param index The index of the layer which will received the ID.
- * @param id The ID to assign to the layer.
+ * @param index The index of the layer to modify, must be in the range
+ * {@code 0...getNumberOfLayers()-1}.
+ * @param id The id to assign to the layer.
+ *
+ * @see #getId(int)
+ * @attr ref android.R.styleable#LayerDrawableItem_id
*/
public void setId(int index, int id) {
mLayerState.mChildren[index].mId = id;
}
/**
- * Returns the number of layers contained within this.
- * @return The number of layers.
- */
- public int getNumberOfLayers() {
- return mLayerState.mNum;
- }
-
- /**
- * Returns the drawable at the specified layer index.
+ * Returns the ID of the specified layer.
*
- * @param index The layer index of the drawable to retrieve.
+ * @param index The index of the layer, must be in the range
+ * {@code 0...getNumberOfLayers()-1}.
+ * @return The id of the layer or {@link android.view.View#NO_ID} if the
+ * layer has no id.
*
- * @return The {@link android.graphics.drawable.Drawable} at the specified layer index.
+ * @see #setId(int, int)
+ * @attr ref android.R.styleable#LayerDrawableItem_id
*/
- public Drawable getDrawable(int index) {
- return mLayerState.mChildren[index].mDrawable;
+ public int getId(int index) {
+ if (index >= mLayerState.mNum) {
+ throw new IndexOutOfBoundsException();
+ }
+ return mLayerState.mChildren[index].mId;
}
/**
- * Returns the id of the specified layer.
- *
- * @param index The index of the layer.
+ * Returns the number of layers contained within this layer drawable.
*
- * @return The id of the layer or {@link android.view.View#NO_ID} if the layer has no id.
+ * @return The number of layers.
*/
- public int getId(int index) {
- return mLayerState.mChildren[index].mId;
+ public int getNumberOfLayers() {
+ return mLayerState.mNum;
}
/**
- * Sets (or replaces) the {@link Drawable} for the layer with the given id.
+ * Replaces the {@link Drawable} for the layer with the given id.
*
* @param id The layer ID to search for.
* @param drawable The replacement {@link Drawable}.
@@ -419,31 +467,171 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
* the id was not found).
*/
public boolean setDrawableByLayerId(int id, Drawable drawable) {
+ final int index = findIndexByLayerId(id);
+ if (index < 0) {
+ return false;
+ }
+
+ setDrawable(index, drawable);
+ return true;
+ }
+
+ /**
+ * Returns the layer with the specified {@code id}.
+ * <p>
+ * If multiple layers have the same ID, returns the layer with the lowest
+ * index.
+ *
+ * @param id The ID of the layer to return.
+ * @return The index of the layer with the specified ID.
+ */
+ public int findIndexByLayerId(int id) {
final ChildDrawable[] layers = mLayerState.mChildren;
final int N = mLayerState.mNum;
for (int i = 0; i < N; i++) {
final ChildDrawable childDrawable = layers[i];
if (childDrawable.mId == id) {
- if (childDrawable.mDrawable != null) {
- if (drawable != null) {
- final Rect bounds = childDrawable.mDrawable.getBounds();
- drawable.setBounds(bounds);
- }
+ return i;
+ }
+ }
- childDrawable.mDrawable.setCallback(null);
- }
+ return -1;
+ }
- if (drawable != null) {
- drawable.setCallback(this);
- }
+ /**
+ * Sets the drawable for the layer at the specified index.
+ *
+ * @param index The index of the layer to modify, must be in the range
+ * {@code 0...getNumberOfLayers()-1}.
+ * @param drawable The drawable to set for the layer.
+ *
+ * @see #getDrawable(int)
+ * @attr ref android.R.styleable#LayerDrawableItem_drawable
+ */
+ public void setDrawable(int index, Drawable drawable) {
+ if (index >= mLayerState.mNum) {
+ throw new IndexOutOfBoundsException();
+ }
- childDrawable.mDrawable = drawable;
- mLayerState.invalidateCache();
- return true;
+ final ChildDrawable[] layers = mLayerState.mChildren;
+ final ChildDrawable childDrawable = layers[index];
+ if (childDrawable.mDrawable != null) {
+ if (drawable != null) {
+ final Rect bounds = childDrawable.mDrawable.getBounds();
+ drawable.setBounds(bounds);
}
+
+ childDrawable.mDrawable.setCallback(null);
}
- return false;
+ if (drawable != null) {
+ drawable.setCallback(this);
+ drawable.setLayoutDirection(getLayoutDirection());
+ drawable.setLevel(getLevel());
+ }
+
+ childDrawable.mDrawable = drawable;
+ mLayerState.invalidateCache();
+ }
+
+ /**
+ * Returns the drawable for the layer at the specified index.
+ *
+ * @param index The index of the layer, must be in the range
+ * {@code 0...getNumberOfLayers()-1}.
+ * @return The {@link Drawable} at the specified layer index.
+ *
+ * @see #setDrawable(int, Drawable)
+ * @attr ref android.R.styleable#LayerDrawableItem_drawable
+ */
+ public Drawable getDrawable(int index) {
+ if (index >= mLayerState.mNum) {
+ throw new IndexOutOfBoundsException();
+ }
+ return mLayerState.mChildren[index].mDrawable;
+ }
+
+ /**
+ * Sets an explicit size for the specified layer.
+ * <p>
+ * <strong>Note:</strong> Setting an explicit layer size changes the
+ * default layer gravity behavior. See {@link #setLayerGravity(int, int)}
+ * for more information.
+ *
+ * @param index the index of the drawable to adjust
+ * @param w width in pixels, or -1 to use the intrinsic width
+ * @param h height in pixels, or -1 to use the intrinsic height
+ *
+ * @see #getLayerWidth(int)
+ * @see #getLayerHeight(int)
+ * @attr ref android.R.styleable#LayerDrawableItem_width
+ * @attr ref android.R.styleable#LayerDrawableItem_height
+ */
+ public void setLayerSize(int index, int w, int h) {
+ final ChildDrawable childDrawable = mLayerState.mChildren[index];
+ childDrawable.mWidth = w;
+ childDrawable.mHeight = h;
+ }
+
+ /**
+ * @param index the index of the drawable to adjust
+ * @return the explicit width of the layer, or -1 if not specified
+ *
+ * @see #setLayerSize(int, int, int)
+ * @attr ref android.R.styleable#LayerDrawableItem_width
+ */
+ public int getLayerWidth(int index) {
+ final ChildDrawable childDrawable = mLayerState.mChildren[index];
+ return childDrawable.mWidth;
+ }
+
+ /**
+ * @param index the index of the drawable to adjust
+ * @return the explicit height of the layer, or -1 if not specified
+ *
+ * @see #setLayerSize(int, int, int)
+ * @attr ref android.R.styleable#LayerDrawableItem_height
+ */
+ public int getLayerHeight(int index) {
+ final ChildDrawable childDrawable = mLayerState.mChildren[index];
+ return childDrawable.mHeight;
+ }
+
+ /**
+ * Sets the gravity used to position or stretch the specified layer within
+ * its container. Gravity is applied after any layer insets (see
+ * {@link #setLayerInset(int, int, int, int, int)}) or padding (see
+ * {@link #setPaddingMode(int)}).
+ * <p>
+ * If gravity is specified as {@link Gravity#NO_GRAVITY}, the default
+ * behavior depends on whether an explicit width or height has been set
+ * (see {@link #setLayerSize(int, int, int)}), If a dimension is not set,
+ * gravity in that direction defaults to {@link Gravity#FILL_HORIZONTAL} or
+ * {@link Gravity#FILL_VERTICAL}; otherwise, gravity in that direction
+ * defaults to {@link Gravity#LEFT} or {@link Gravity#TOP}.
+ *
+ * @param index the index of the drawable to adjust
+ * @param gravity the gravity to set for the layer
+ *
+ * @see #getLayerGravity(int)
+ * @attr ref android.R.styleable#LayerDrawableItem_gravity
+ */
+ public void setLayerGravity(int index, int gravity) {
+ final ChildDrawable childDrawable = mLayerState.mChildren[index];
+ childDrawable.mGravity = gravity;
+ }
+
+ /**
+ * @param index the index of the layer
+ * @return the gravity used to position or stretch the specified layer
+ * within its container
+ *
+ * @see #setLayerGravity(int, int)
+ * @attr ref android.R.styleable#LayerDrawableItem_gravity
+ */
+ public int getLayerGravity(int index) {
+ final ChildDrawable childDrawable = mLayerState.mChildren[index];
+ return childDrawable.mGravity;
}
/**
@@ -454,13 +642,43 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
* @param t number of pixels to add to the top bound
* @param r number of pixels to subtract from the right bound
* @param b number of pixels to subtract from the bottom bound
+ *
+ * @attr ref android.R.styleable#LayerDrawableItem_left
+ * @attr ref android.R.styleable#LayerDrawableItem_top
+ * @attr ref android.R.styleable#LayerDrawableItem_right
+ * @attr ref android.R.styleable#LayerDrawableItem_bottom
*/
public void setLayerInset(int index, int l, int t, int r, int b) {
+ setLayerInsetInternal(index, l, t, r, b, UNDEFINED_INSET, UNDEFINED_INSET);
+ }
+
+ /**
+ * Specifies the relative insets in pixels for the drawable at the
+ * specified index.
+ *
+ * @param index the index of the drawable to adjust
+ * @param s number of pixels to inset from the start bound
+ * @param t number of pixels to inset from the top bound
+ * @param e number of pixels to inset from the end bound
+ * @param b number of pixels to inset from the bottom bound
+ *
+ * @attr ref android.R.styleable#LayerDrawableItem_start
+ * @attr ref android.R.styleable#LayerDrawableItem_top
+ * @attr ref android.R.styleable#LayerDrawableItem_end
+ * @attr ref android.R.styleable#LayerDrawableItem_bottom
+ */
+ public void setLayerInsetRelative(int index, int s, int t, int e, int b) {
+ setLayerInsetInternal(index, 0, t, 0, b, s, e);
+ }
+
+ private void setLayerInsetInternal(int index, int l, int t, int r, int b, int s, int e) {
final ChildDrawable childDrawable = mLayerState.mChildren[index];
childDrawable.mInsetL = l;
childDrawable.mInsetT = t;
childDrawable.mInsetR = r;
childDrawable.mInsetB = b;
+ childDrawable.mInsetS = s;
+ childDrawable.mInsetE = e;
}
/**
@@ -648,6 +866,18 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
}
@Override
+ public boolean getDither() {
+ final ChildDrawable[] array = mLayerState.mChildren;
+ if (mLayerState.mNum > 0) {
+ // All layers should have the same dither set on them - just return
+ // the first one
+ return array[0].mDrawable.getDither();
+ } else {
+ return super.getDither();
+ }
+ }
+
+ @Override
public void setAlpha(int alpha) {
final ChildDrawable[] array = mLayerState.mChildren;
final int N = mLayerState.mNum;
@@ -758,7 +988,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
}
if (paddingChanged) {
- onBoundsChange(getBounds());
+ updateLayerBounds(getBounds());
}
return changed;
@@ -783,7 +1013,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
}
if (paddingChanged) {
- onBoundsChange(getBounds());
+ updateLayerBounds(getBounds());
}
return changed;
@@ -791,18 +1021,51 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
@Override
protected void onBoundsChange(Rect bounds) {
+ updateLayerBounds(bounds);
+ }
+
+ private void updateLayerBounds(Rect bounds) {
int padL = 0;
int padT = 0;
int padR = 0;
int padB = 0;
+ final Rect outRect = mTmpOutRect;
+ final int layoutDirection = getLayoutDirection();
final boolean nest = mLayerState.mPaddingMode == PADDING_MODE_NEST;
final ChildDrawable[] array = mLayerState.mChildren;
final int N = mLayerState.mNum;
for (int i = 0; i < N; i++) {
final ChildDrawable r = array[i];
- r.mDrawable.setBounds(bounds.left + r.mInsetL + padL, bounds.top + r.mInsetT + padT,
- bounds.right - r.mInsetR - padR, bounds.bottom - r.mInsetB - padB);
+ final Drawable d = r.mDrawable;
+ final Rect container = mTmpContainer;
+ container.set(d.getBounds());
+
+ // Take the resolved layout direction into account. If start / end
+ // padding are defined, they will be resolved (hence overriding) to
+ // left / right or right / left depending on the resolved layout
+ // direction. If start / end padding are not defined, use the
+ // left / right ones.
+ final int insetL, insetR;
+ if (layoutDirection == LayoutDirection.RTL) {
+ insetL = r.mInsetE == UNDEFINED_INSET ? r.mInsetL : r.mInsetE;
+ insetR = r.mInsetS == UNDEFINED_INSET ? r.mInsetR : r.mInsetS;
+ } else {
+ insetL = r.mInsetS == UNDEFINED_INSET ? r.mInsetL : r.mInsetS;
+ insetR = r.mInsetE == UNDEFINED_INSET ? r.mInsetR : r.mInsetE;
+ }
+
+ // Establish containing region based on aggregate padding and
+ // requested insets for the current layer.
+ container.set(bounds.left + insetL + padL, bounds.top + r.mInsetT + padT,
+ bounds.right - insetR - padR, bounds.bottom - r.mInsetB - padB);
+
+ // Apply resolved gravity to drawable based on resolved size.
+ final int gravity = resolveGravity(r.mGravity, r.mWidth, r.mHeight);
+ final int w = r.mWidth < 0 ? d.getIntrinsicWidth() : r.mWidth;
+ final int h = r.mHeight < 0 ? d.getIntrinsicHeight() : r.mHeight;
+ Gravity.apply(gravity, w, h, container, outRect, layoutDirection);
+ d.setBounds(outRect);
if (nest) {
padL += mPaddingL[i];
@@ -813,6 +1076,38 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
}
}
+ /**
+ * Resolves layer gravity given explicit gravity and dimensions.
+ * <p>
+ * If the client hasn't specified a gravity but has specified an explicit
+ * dimension, defaults to START or TOP. Otherwise, defaults to FILL to
+ * preserve legacy behavior.
+ *
+ * @param gravity
+ * @param width
+ * @param height
+ * @return
+ */
+ private int resolveGravity(int gravity, int width, int height) {
+ if (!Gravity.isHorizontal(gravity)) {
+ if (width < 0) {
+ gravity |= Gravity.FILL_HORIZONTAL;
+ } else {
+ gravity |= Gravity.START;
+ }
+ }
+
+ if (!Gravity.isVertical(gravity)) {
+ if (height < 0) {
+ gravity |= Gravity.FILL_VERTICAL;
+ } else {
+ gravity |= Gravity.TOP;
+ }
+ }
+
+ return gravity;
+ }
+
@Override
public int getIntrinsicWidth() {
int width = -1;
@@ -824,7 +1119,8 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
final int N = mLayerState.mNum;
for (int i = 0; i < N; i++) {
final ChildDrawable r = array[i];
- final int w = r.mDrawable.getIntrinsicWidth() + r.mInsetL + r.mInsetR + padL + padR;
+ final int minWidth = r.mWidth < 0 ? r.mDrawable.getIntrinsicWidth() : r.mWidth;
+ final int w = minWidth + r.mInsetL + r.mInsetR + padL + padR;
if (w > width) {
width = w;
}
@@ -849,7 +1145,8 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
final int N = mLayerState.mNum;
for (int i = 0; i < N; i++) {
final ChildDrawable r = array[i];
- int h = r.mDrawable.getIntrinsicHeight() + r.mInsetT + r.mInsetB + padT + padB;
+ final int minHeight = r.mHeight < 0 ? r.mDrawable.getIntrinsicHeight() : r.mHeight;
+ final int h = minHeight + r.mInsetT + r.mInsetB + padT + padB;
if (h > height) {
height = h;
}
@@ -936,18 +1233,24 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
/** @hide */
@Override
public void setLayoutDirection(int layoutDirection) {
+ super.setLayoutDirection(layoutDirection);
final ChildDrawable[] array = mLayerState.mChildren;
final int N = mLayerState.mNum;
for (int i = 0; i < N; i++) {
array[i].mDrawable.setLayoutDirection(layoutDirection);
}
- super.setLayoutDirection(layoutDirection);
+ updateLayerBounds(getBounds());
}
static class ChildDrawable {
public Drawable mDrawable;
public int[] mThemeAttrs;
public int mInsetL, mInsetT, mInsetR, mInsetB;
+ public int mInsetS = UNDEFINED_INSET;
+ public int mInsetE = UNDEFINED_INSET;
+ public int mWidth = -1;
+ public int mHeight = -1;
+ public int mGravity = Gravity.NO_GRAVITY;
public int mId = View.NO_ID;
ChildDrawable() {
@@ -969,6 +1272,11 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
mInsetT = orig.mInsetT;
mInsetR = orig.mInsetR;
mInsetB = orig.mInsetB;
+ mInsetS = orig.mInsetS;
+ mInsetE = orig.mInsetE;
+ mWidth = orig.mWidth;
+ mHeight = orig.mHeight;
+ mGravity = orig.mGravity;
mId = orig.mId;
}
}
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index b87ae92..617bf7c 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -374,6 +374,11 @@ public class NinePatchDrawable extends Drawable {
}
@Override
+ public boolean getDither() {
+ return mPaint == null ? DEFAULT_DITHER : mPaint.isDither();
+ }
+
+ @Override
public void setAutoMirrored(boolean mirrored) {
mNinePatchState.mAutoMirrored = mirrored;
}
@@ -401,6 +406,8 @@ public class NinePatchDrawable extends Drawable {
final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.NinePatchDrawable);
updateStateFromTypedArray(a);
a.recycle();
+
+ updateLocalState(r);
}
/**
@@ -467,12 +474,6 @@ public class NinePatchDrawable extends Drawable {
if (tint != null) {
state.mTint = tint;
}
-
- // Update local properties.
- initializeWithState(state, r);
-
- // Push density applied by setNinePatchState into state.
- state.mTargetDensity = mTargetDensity;
}
@Override
@@ -480,23 +481,32 @@ public class NinePatchDrawable extends Drawable {
super.applyTheme(t);
final NinePatchState state = mNinePatchState;
- if (state == null || state.mThemeAttrs == null) {
+ if (state == null) {
return;
}
- final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.NinePatchDrawable);
- try {
- updateStateFromTypedArray(a);
- } catch (XmlPullParserException e) {
- throw new RuntimeException(e);
- } finally {
- a.recycle();
+ if (state.mThemeAttrs != null) {
+ final TypedArray a = t.resolveAttributes(
+ state.mThemeAttrs, R.styleable.NinePatchDrawable);
+ try {
+ updateStateFromTypedArray(a);
+ } catch (XmlPullParserException e) {
+ throw new RuntimeException(e);
+ } finally {
+ a.recycle();
+ }
+ }
+
+ if (state.mTint != null && state.mTint.canApplyTheme()) {
+ state.mTint.applyTheme(t);
}
+
+ updateLocalState(t.getResources());
}
@Override
public boolean canApplyTheme() {
- return mNinePatchState != null && mNinePatchState.mThemeAttrs != null;
+ return mNinePatchState != null && mNinePatchState.canApplyTheme();
}
public Paint getPaint() {
@@ -645,7 +655,8 @@ public class NinePatchDrawable extends Drawable {
@Override
public boolean canApplyTheme() {
- return mThemeAttrs != null;
+ return mThemeAttrs != null
+ || (mTint != null && mTint.canApplyTheme());
}
@Override
@@ -680,19 +691,25 @@ public class NinePatchDrawable extends Drawable {
private NinePatchDrawable(NinePatchState state, Resources res) {
mNinePatchState = state;
- initializeWithState(mNinePatchState, res);
+ updateLocalState(res);
+
+ // Push density applied by setNinePatchState into state.
+ mNinePatchState.mTargetDensity = mTargetDensity;
}
/**
* Initializes local dynamic properties from state.
*/
- private void initializeWithState(NinePatchState state, Resources res) {
+ private void updateLocalState(Resources res) {
+ final NinePatchState state = mNinePatchState;
+
if (res != null) {
mTargetDensity = res.getDisplayMetrics().densityDpi;
} else {
mTargetDensity = state.mTargetDensity;
}
+
// If we can, avoid calling any methods that initialize Paint.
if (state.mDither != DEFAULT_DITHER) {
setDither(state.mDither);
diff --git a/graphics/java/android/graphics/drawable/PictureDrawable.java b/graphics/java/android/graphics/drawable/PictureDrawable.java
index 6dcda1f..583cffb 100644
--- a/graphics/java/android/graphics/drawable/PictureDrawable.java
+++ b/graphics/java/android/graphics/drawable/PictureDrawable.java
@@ -88,12 +88,6 @@ public class PictureDrawable extends Drawable {
}
@Override
- public void setFilterBitmap(boolean filter) {}
-
- @Override
- public void setDither(boolean dither) {}
-
- @Override
public void setColorFilter(ColorFilter colorFilter) {}
@Override
diff --git a/graphics/java/android/graphics/drawable/Ripple.java b/graphics/java/android/graphics/drawable/Ripple.java
index bb1d3cb..138d73a 100644
--- a/graphics/java/android/graphics/drawable/Ripple.java
+++ b/graphics/java/android/graphics/drawable/Ripple.java
@@ -46,8 +46,7 @@ class Ripple {
private static final long RIPPLE_ENTER_DELAY = 80;
// Hardware animators.
- private final ArrayList<RenderNodeAnimator> mRunningAnimations =
- new ArrayList<RenderNodeAnimator>();
+ private final ArrayList<RenderNodeAnimator> mRunningAnimations = new ArrayList<>();
private final RippleDrawable mOwner;
@@ -117,8 +116,8 @@ class Ripple {
mStartingY = startingY;
}
- public void setup(int maxRadius, float density) {
- if (maxRadius != RippleDrawable.RADIUS_AUTO) {
+ public void setup(float maxRadius, float density) {
+ if (maxRadius >= 0) {
mHasMaxRadius = true;
mOuterRadius = maxRadius;
} else {
diff --git a/graphics/java/android/graphics/drawable/RippleBackground.java b/graphics/java/android/graphics/drawable/RippleBackground.java
index fae4902..ef35289 100644
--- a/graphics/java/android/graphics/drawable/RippleBackground.java
+++ b/graphics/java/android/graphics/drawable/RippleBackground.java
@@ -49,8 +49,7 @@ class RippleBackground {
private static final int ENTER_DURATION_FAST = 100;
// Hardware animators.
- private final ArrayList<RenderNodeAnimator> mRunningAnimations =
- new ArrayList<RenderNodeAnimator>();
+ private final ArrayList<RenderNodeAnimator> mRunningAnimations = new ArrayList<>();
private final RippleDrawable mOwner;
@@ -105,8 +104,8 @@ class RippleBackground {
mBounds = bounds;
}
- public void setup(int maxRadius, float density) {
- if (maxRadius != RippleDrawable.RADIUS_AUTO) {
+ public void setup(float maxRadius, float density) {
+ if (maxRadius >= 0) {
mHasMaxRadius = true;
mOuterRadius = maxRadius;
} else {
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 1263447..556c59f 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -92,19 +92,17 @@ import java.util.Arrays;
* @attr ref android.R.styleable#RippleDrawable_color
*/
public class RippleDrawable extends LayerDrawable {
+ /**
+ * Radius value that specifies the ripple radius should be computed based
+ * on the size of the ripple's container.
+ */
+ public static final int RADIUS_AUTO = -1;
+
private static final int MASK_UNKNOWN = -1;
private static final int MASK_NONE = 0;
private static final int MASK_CONTENT = 1;
private static final int MASK_EXPLICIT = 2;
- /**
- * Constant for automatically determining the maximum ripple radius.
- *
- * @see #setMaxRadius(int)
- * @hide
- */
- public static final int RADIUS_AUTO = -1;
-
/** The maximum number of ripples supported. */
private static final int MAX_RIPPLES = 10;
@@ -198,7 +196,7 @@ public class RippleDrawable extends LayerDrawable {
setColor(color);
ensurePadding();
- initializeFromState();
+ updateLocalState();
}
@Override
@@ -352,11 +350,40 @@ public class RippleDrawable extends LayerDrawable {
return true;
}
+ /**
+ * Sets the ripple color.
+ *
+ * @param color Ripple color as a color state list.
+ *
+ * @attr ref android.R.styleable#RippleDrawable_color
+ */
public void setColor(ColorStateList color) {
mState.mColor = color;
invalidateSelf();
}
+ /**
+ * Sets the radius in pixels of the fully expanded ripple.
+ *
+ * @param radius ripple radius in pixels, or {@link #RADIUS_AUTO} to
+ * compute the radius based on the container size
+ * @attr ref android.R.styleable#RippleDrawable_radius
+ */
+ public void setRadius(int radius) {
+ mState.mMaxRadius = radius;
+ invalidateSelf();
+ }
+
+ /**
+ * @return the radius in pixels of the fully expanded ripple if an explicit
+ * radius has been set, or {@link #RADIUS_AUTO} if the radius is
+ * computed based on the container size
+ * @attr ref android.R.styleable#RippleDrawable_radius
+ */
+ public int getRadius() {
+ return mState.mMaxRadius;
+ }
+
@Override
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
throws XmlPullParserException, IOException {
@@ -370,7 +397,8 @@ public class RippleDrawable extends LayerDrawable {
super.inflate(r, parser, attrs, theme);
setTargetDensity(r.getDisplayMetrics());
- initializeFromState();
+
+ updateLocalState();
}
@Override
@@ -422,6 +450,9 @@ public class RippleDrawable extends LayerDrawable {
mState.mColor = color;
}
+ mState.mMaxRadius = a.getDimensionPixelSize(
+ R.styleable.RippleDrawable_radius, mState.mMaxRadius);
+
verifyRequiredAttributes(a);
}
@@ -450,21 +481,27 @@ public class RippleDrawable extends LayerDrawable {
super.applyTheme(t);
final RippleState state = mState;
- if (state == null || state.mTouchThemeAttrs == null) {
+ if (state == null) {
return;
}
- final TypedArray a = t.resolveAttributes(state.mTouchThemeAttrs,
- R.styleable.RippleDrawable);
- try {
- updateStateFromTypedArray(a);
- } catch (XmlPullParserException e) {
- throw new RuntimeException(e);
- } finally {
- a.recycle();
+ if (state.mTouchThemeAttrs != null) {
+ final TypedArray a = t.resolveAttributes(state.mTouchThemeAttrs,
+ R.styleable.RippleDrawable);
+ try {
+ updateStateFromTypedArray(a);
+ } catch (XmlPullParserException e) {
+ throw new RuntimeException(e);
+ } finally {
+ a.recycle();
+ }
}
- initializeFromState();
+ if (state.mColor != null && state.mColor.canApplyTheme()) {
+ state.mColor.applyTheme(t);
+ }
+
+ updateLocalState();
}
@Override
@@ -931,7 +968,9 @@ public class RippleDrawable extends LayerDrawable {
@Override
public boolean canApplyTheme() {
- return mTouchThemeAttrs != null || super.canApplyTheme();
+ return mTouchThemeAttrs != null
+ || (mColor != null && mColor.canApplyTheme())
+ || super.canApplyTheme();
}
@Override
@@ -945,36 +984,6 @@ public class RippleDrawable extends LayerDrawable {
}
}
- /**
- * Sets the maximum ripple radius in pixels. The default value of
- * {@link #RADIUS_AUTO} defines the radius as the distance from the center
- * of the drawable bounds (or hotspot bounds, if specified) to a corner.
- *
- * @param maxRadius the maximum ripple radius in pixels or
- * {@link #RADIUS_AUTO} to automatically determine the maximum
- * radius based on the bounds
- * @see #getMaxRadius()
- * @see #setHotspotBounds(int, int, int, int)
- * @hide
- */
- public void setMaxRadius(int maxRadius) {
- if (maxRadius != RADIUS_AUTO && maxRadius < 0) {
- throw new IllegalArgumentException("maxRadius must be RADIUS_AUTO or >= 0");
- }
-
- mState.mMaxRadius = maxRadius;
- }
-
- /**
- * @return the maximum ripple radius in pixels, or {@link #RADIUS_AUTO} if
- * the radius is determined automatically
- * @see #setMaxRadius(int)
- * @hide
- */
- public int getMaxRadius() {
- return mState.mMaxRadius;
- }
-
private RippleDrawable(RippleState state, Resources res) {
mState = new RippleState(state, this, res);
mLayerState = mState;
@@ -987,10 +996,10 @@ public class RippleDrawable extends LayerDrawable {
mDensity = res.getDisplayMetrics().density;
}
- initializeFromState();
+ updateLocalState();
}
- private void initializeFromState() {
+ private void updateLocalState() {
// Initialize from constant state.
mMask = findDrawableByLayerId(R.id.mask);
}
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index a3d8c92..c208c03 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -329,6 +329,11 @@ public class ShapeDrawable extends Drawable {
}
@Override
+ public boolean getDither() {
+ return mShapeState.mPaint.isDither();
+ }
+
+ @Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
updateShape();
@@ -402,7 +407,7 @@ public class ShapeDrawable extends Drawable {
}
// Update local properties.
- initializeWithState(mShapeState, r);
+ updateLocalState(r);
}
@Override
@@ -410,16 +415,23 @@ public class ShapeDrawable extends Drawable {
super.applyTheme(t);
final ShapeState state = mShapeState;
- if (state == null || state.mThemeAttrs == null) {
+ if (state == null) {
return;
}
- final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.ShapeDrawable);
- updateStateFromTypedArray(a);
- a.recycle();
+ if (state.mThemeAttrs != null) {
+ final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.ShapeDrawable);
+ updateStateFromTypedArray(a);
+ a.recycle();
+ }
+
+ // Apply theme to contained color state list.
+ if (state.mTint != null && state.mTint.canApplyTheme()) {
+ state.mTint.applyTheme(t);
+ }
// Update local properties.
- initializeWithState(state, t.getResources());
+ updateLocalState(t.getResources());
}
private void updateStateFromTypedArray(TypedArray a) {
@@ -550,7 +562,8 @@ public class ShapeDrawable extends Drawable {
@Override
public boolean canApplyTheme() {
- return mThemeAttrs != null;
+ return mThemeAttrs != null
+ || (mTint != null && mTint.canApplyTheme());
}
@Override
@@ -576,7 +589,7 @@ public class ShapeDrawable extends Drawable {
private ShapeDrawable(ShapeState state, Resources res) {
mShapeState = state;
- initializeWithState(state, res);
+ updateLocalState(res);
}
/**
@@ -584,8 +597,8 @@ public class ShapeDrawable extends Drawable {
* after significant state changes, e.g. from the One True Constructor and
* after inflating or applying a theme.
*/
- private void initializeWithState(ShapeState state, Resources res) {
- mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
+ private void updateLocalState(Resources res) {
+ mTintFilter = updateTintFilter(mTintFilter, mShapeState.mTint, mShapeState.mTintMode);
}
/**
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 8b0f635..5f1dcec 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -150,7 +150,8 @@ import java.util.Stack;
*
* <dl>
* <dt><code>&lt;clip-path></code></dt>
- * <dd>Defines path to be the current clip.
+ * <dd>Defines path to be the current clip. Note that the clip path only apply to
+ * the current group and its children.
* <dl>
* <dt><code>android:name</code></dt>
* <dd>Defines the name of the clip path.</dd>
@@ -369,8 +370,13 @@ public class VectorDrawable extends Drawable {
super.applyTheme(t);
final VectorDrawableState state = mVectorState;
- if (state != null && state.mThemeAttrs != null) {
- final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.VectorDrawable);
+ if (state == null) {
+ return;
+ }
+
+ if (state.mThemeAttrs != null) {
+ final TypedArray a = t.resolveAttributes(
+ state.mThemeAttrs, R.styleable.VectorDrawable);
try {
state.mCacheDirty = true;
updateStateFromTypedArray(a);
@@ -379,14 +385,20 @@ public class VectorDrawable extends Drawable {
} finally {
a.recycle();
}
+ }
- mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
+ // Apply theme to contained color state list.
+ if (state.mTint != null && state.mTint.canApplyTheme()) {
+ state.mTint.applyTheme(t);
}
final VPathRenderer path = state.mVPathRenderer;
if (path != null && path.canApplyTheme()) {
path.applyTheme(t);
}
+
+ // Update local state.
+ mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
}
/**
@@ -750,7 +762,9 @@ public class VectorDrawable extends Drawable {
@Override
public boolean canApplyTheme() {
- return mThemeAttrs != null || (mVPathRenderer != null && mVPathRenderer.canApplyTheme())
+ return mThemeAttrs != null
+ || (mVPathRenderer != null && mVPathRenderer.canApplyTheme())
+ || (mTint != null && mTint.canApplyTheme())
|| super.canApplyTheme();
}
@@ -913,9 +927,10 @@ public class VectorDrawable extends Drawable {
// Basically the Mfinal = Mviewport * M0 * M1 * M2;
// Mi the local matrix at level i of the group tree.
currentGroup.mStackedMatrix.set(currentMatrix);
-
currentGroup.mStackedMatrix.preConcat(currentGroup.mLocalMatrix);
+ // Save the current clip information, which is local to this group.
+ canvas.save();
// Draw the group tree in the same order as the XML file.
for (int i = 0; i < currentGroup.mChildren.size(); i++) {
Object child = currentGroup.mChildren.get(i);
@@ -928,6 +943,7 @@ public class VectorDrawable extends Drawable {
drawPath(currentGroup, childPath, canvas, w, h, filter);
}
}
+ canvas.restore();
}
public void draw(Canvas canvas, int w, int h, ColorFilter filter) {