diff options
author | Chris Craik <ccraik@google.com> | 2014-04-25 13:08:25 -0700 |
---|---|---|
committer | Chris Craik <ccraik@google.com> | 2014-04-25 15:59:47 -0700 |
commit | 7979388d4f7d5d9dbfcf7e1cc4709f8088c034ae (patch) | |
tree | fb8460098f57d66ed696b65a9cc70b51cf1128ff | |
parent | 07f0b8ee730be00a2a4bccf797bd8cb71e556546 (diff) | |
download | frameworks_base-7979388d4f7d5d9dbfcf7e1cc4709f8088c034ae.zip frameworks_base-7979388d4f7d5d9dbfcf7e1cc4709f8088c034ae.tar.gz frameworks_base-7979388d4f7d5d9dbfcf7e1cc4709f8088c034ae.tar.bz2 |
Support Oval GradientDrawable outlines, and ShapeDrawable
Change-Id: Ifc9e55757d3325cb28a1a812ec696512d4a18b39
-rw-r--r-- | api/current.txt | 4 | ||||
-rw-r--r-- | core/java/android/view/View.java | 3 | ||||
-rw-r--r-- | core/jni/android/graphics/Path.cpp | 34 | ||||
-rw-r--r-- | graphics/java/android/graphics/Outline.java | 67 | ||||
-rw-r--r-- | graphics/java/android/graphics/Path.java | 24 | ||||
-rw-r--r-- | graphics/java/android/graphics/drawable/GradientDrawable.java | 11 | ||||
-rw-r--r-- | graphics/java/android/graphics/drawable/ShapeDrawable.java | 11 | ||||
-rw-r--r-- | graphics/java/android/graphics/drawable/shapes/OvalShape.java | 10 | ||||
-rw-r--r-- | graphics/java/android/graphics/drawable/shapes/RectShape.java | 11 | ||||
-rw-r--r-- | graphics/java/android/graphics/drawable/shapes/RoundRectShape.java | 28 | ||||
-rw-r--r-- | graphics/java/android/graphics/drawable/shapes/Shape.java | 15 | ||||
-rw-r--r-- | tests/HwAccelerationTest/AndroidManifest.xml | 3 |
12 files changed, 155 insertions, 66 deletions
diff --git a/api/current.txt b/api/current.txt index dcda77c..2271720 100644 --- a/api/current.txt +++ b/api/current.txt @@ -10029,6 +10029,8 @@ package android.graphics { method public boolean isValid(); method public void set(android.graphics.Outline); method public void setConvexPath(android.graphics.Path); + method public void setOval(int, int, int, int); + method public void setOval(android.graphics.Rect); method public void setRect(int, int, int, int); method public void setRect(android.graphics.Rect); method public void setRoundRect(int, int, int, int, float); @@ -10201,6 +10203,7 @@ package android.graphics { method public void addArc(android.graphics.RectF, float, float); method public void addCircle(float, float, float, android.graphics.Path.Direction); method public void addOval(android.graphics.RectF, android.graphics.Path.Direction); + method public void addOval(float, float, float, float, android.graphics.Path.Direction); method public void addPath(android.graphics.Path, float, float); method public void addPath(android.graphics.Path); method public void addPath(android.graphics.Path, android.graphics.Matrix); @@ -11128,6 +11131,7 @@ package android.graphics.drawable.shapes { method public android.graphics.drawable.shapes.Shape clone() throws java.lang.CloneNotSupportedException; method public abstract void draw(android.graphics.Canvas, android.graphics.Paint); method public final float getHeight(); + method public boolean getOutline(android.graphics.Outline); method public final float getWidth(); method public boolean hasAlpha(); method protected void onResize(float, float); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index c8e229a..46d3b6f 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -10601,7 +10601,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (mOutline == null) { mOutline = new Outline(); } else { - mOutline.markInvalid(); + //invalidate outline, to ensure background calculates it + mOutline.set(null); } if (mBackground.getOutline(mOutline)) { if (!mOutline.isValid()) { diff --git a/core/jni/android/graphics/Path.cpp b/core/jni/android/graphics/Path.cpp index 1ad1a8a..420a17f 100644 --- a/core/jni/android/graphics/Path.cpp +++ b/core/jni/android/graphics/Path.cpp @@ -163,42 +163,35 @@ public: SkPath* obj = reinterpret_cast<SkPath*>(objHandle); obj->close(); } - - static void addRect__RectFI(JNIEnv* env, jobject clazz, jlong objHandle, jobject jrect, jint dirHandle) { - SkRect rect; - SkPath* obj = reinterpret_cast<SkPath*>(objHandle); - SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle); - GraphicsJNI::jrectf_to_rect(env, jrect, &rect); - obj->addRect(rect, dir); - } - - static void addRect__FFFFI(JNIEnv* env, jobject clazz, jlong objHandle, jfloat left, jfloat top, jfloat right, jfloat bottom, jint dirHandle) { + + static void addRect(JNIEnv* env, jobject clazz, jlong objHandle, + jfloat left, jfloat top, jfloat right, jfloat bottom, jint dirHandle) { SkPath* obj = reinterpret_cast<SkPath*>(objHandle); SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle); obj->addRect(left, top, right, bottom, dir); } - - static void addOval(JNIEnv* env, jobject clazz, jlong objHandle, jobject oval, jint dirHandle) { + + static void addOval(JNIEnv* env, jobject clazz, jlong objHandle, + jfloat left, jfloat top, jfloat right, jfloat bottom, jint dirHandle) { SkPath* obj = reinterpret_cast<SkPath*>(objHandle); SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle); - SkRect oval_; - GraphicsJNI::jrectf_to_rect(env, oval, &oval_); - obj->addOval(oval_, dir); + SkRect oval = SkRect::MakeLTRB(left, top, right, bottom); + obj->addOval(oval, dir); } - + static void addCircle(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x, jfloat y, jfloat radius, jint dirHandle) { SkPath* obj = reinterpret_cast<SkPath*>(objHandle); SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle); obj->addCircle(x, y, radius, dir); } - + static void addArc(JNIEnv* env, jobject clazz, jlong objHandle, jobject oval, jfloat startAngle, jfloat sweepAngle) { SkRect oval_; SkPath* obj = reinterpret_cast<SkPath*>(objHandle); GraphicsJNI::jrectf_to_rect(env, oval, &oval_); obj->addArc(oval_, startAngle, sweepAngle); } - + static void addRoundRectXY(JNIEnv* env, jobject clazz, jlong objHandle, jobject jrect, jfloat rx, jfloat ry, jint dirHandle) { SkRect rect; @@ -496,9 +489,8 @@ static JNINativeMethod methods[] = { {"native_rCubicTo","(JFFFFFF)V", (void*) SkPathGlue::rCubicTo}, {"native_arcTo","(JLandroid/graphics/RectF;FFZ)V", (void*) SkPathGlue::arcTo}, {"native_close","(J)V", (void*) SkPathGlue::close}, - {"native_addRect","(JLandroid/graphics/RectF;I)V", (void*) SkPathGlue::addRect__RectFI}, - {"native_addRect","(JFFFFI)V", (void*) SkPathGlue::addRect__FFFFI}, - {"native_addOval","(JLandroid/graphics/RectF;I)V", (void*) SkPathGlue::addOval}, + {"native_addRect","(JFFFFI)V", (void*) SkPathGlue::addRect}, + {"native_addOval","(JFFFFI)V", (void*) SkPathGlue::addOval}, {"native_addCircle","(JFFFI)V", (void*) SkPathGlue::addCircle}, {"native_addArc","(JLandroid/graphics/RectF;FF)V", (void*) SkPathGlue::addArc}, {"native_addRoundRect","(JLandroid/graphics/RectF;FFI)V", (void*) SkPathGlue::addRoundRectXY}, diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java index d3aac79..b5c0801 100644 --- a/graphics/java/android/graphics/Outline.java +++ b/graphics/java/android/graphics/Outline.java @@ -16,14 +16,16 @@ package android.graphics; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.graphics.drawable.Drawable; import android.view.View; /** - * Defines an area of content. + * Defines a simple shape, used for bounding graphical regions. * * Can be used with a View, or computed by a Drawable, to drive the shape of shadows cast by a - * View, and allowing Views to clip inner content. + * View. * * @see View#setOutline(Outline) * @see Drawable#getOutline(Outline) @@ -47,7 +49,7 @@ public final class Outline { /** * Constructs an Outline with a copy of the data in src. */ - public Outline(Outline src) { + public Outline(@Nullable Outline src) { set(src); } @@ -69,22 +71,30 @@ public final class Outline { /** * Replace the contents of this Outline with the contents of src. + * + * @param src Source outline to copy from. */ - public void set(Outline src) { - if (src.mPath != null) { - if (mPath == null) { - mPath = new Path(); - } - mPath.set(src.mPath); + public void set(@Nullable Outline src) { + if (src == null) { + mRadius = 0; mRect = null; - } - if (src.mRect != null) { - if (mRect == null) { - mRect = new Rect(); + mPath = null; + } else { + if (src.mPath != null) { + if (mPath == null) { + mPath = new Path(); + } + mPath.set(src.mPath); + mRect = null; } - mRect.set(src.mRect); + if (src.mRect != null) { + if (mRect == null) { + mRect = new Rect(); + } + mRect.set(src.mRect); + } + mRadius = src.mRadius; } - mRadius = src.mRadius; } /** @@ -97,12 +107,14 @@ public final class Outline { /** * Convenience for {@link #setRect(int, int, int, int)} */ - public void setRect(Rect rect) { + public void setRect(@NonNull Rect rect) { setRect(rect.left, rect.top, rect.right, rect.bottom); } /** * Sets the Outline to the rounded rect defined by the input rect, and corner radius. + * + * Passing a zero radius is equivalent to calling {@link #setRect(int, int, int, int)} */ public void setRoundRect(int left, int top, int right, int bottom, float radius) { if (mRect == null) mRect = new Rect(); @@ -113,17 +125,32 @@ public final class Outline { /** * Convenience for {@link #setRoundRect(int, int, int, int, float)} - * @param rect - * @param radius */ - public void setRoundRect(Rect rect, float radius) { + public void setRoundRect(@NonNull Rect rect, float radius) { setRoundRect(rect.left, rect.top, rect.right, rect.bottom, radius); } /** + * Sets the outline to the oval defined by input rect. + */ + public void setOval(int left, int top, int right, int bottom) { + mRect = null; + if (mPath == null) mPath = new Path(); + mPath.reset(); + mPath.addOval(left, top, right, bottom, Path.Direction.CW); + } + + /** + * Convenience for {@link #setOval(int, int, int, int)} + */ + public void setOval(@NonNull Rect rect) { + setOval(rect.left, rect.top, rect.right, rect.bottom); + } + + /** * Sets the Constructs an Outline from a {@link android.graphics.Path#isConvex() convex path}. */ - public void setConvexPath(Path convexPath) { + public void setConvexPath(@NonNull Path convexPath) { if (!convexPath.isConvex()) { throw new IllegalArgumentException("path must be convex"); } diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java index c07a6da..c600f47 100644 --- a/graphics/java/android/graphics/Path.java +++ b/graphics/java/android/graphics/Path.java @@ -499,11 +499,7 @@ public class Path { * @param dir The direction to wind the rectangle's contour */ public void addRect(RectF rect, Direction dir) { - if (rect == null) { - throw new NullPointerException("need rect parameter"); - } - detectSimplePath(rect.left, rect.top, rect.right, rect.bottom, dir); - native_addRect(mNativePath, rect, dir.nativeInt); + addRect(rect.left, rect.top, rect.right, rect.bottom, dir); } /** @@ -527,11 +523,17 @@ public class Path { * @param dir The direction to wind the oval's contour */ public void addOval(RectF oval, Direction dir) { - if (oval == null) { - throw new NullPointerException("need oval parameter"); - } + addOval(oval.left, oval.top, oval.right, oval.bottom, dir); + } + + /** + * Add a closed oval contour to the path + * + * @param dir The direction to wind the oval's contour + */ + public void addOval(float left, float top, float right, float bottom, Direction dir) { isSimplePath = false; - native_addOval(mNativePath, oval, dir.nativeInt); + native_addOval(mNativePath, left, top, right, bottom, dir.nativeInt); } /** @@ -756,10 +758,10 @@ public class Path { private static native void native_arcTo(long nPath, RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo); private static native void native_close(long nPath); - private static native void native_addRect(long nPath, RectF rect, int dir); private static native void native_addRect(long nPath, float left, float top, float right, float bottom, int dir); - private static native void native_addOval(long nPath, RectF oval, int dir); + private static native void native_addOval(long nPath, float left, float top, + float right, float bottom, int dir); private static native void native_addCircle(long nPath, float x, float y, float radius, int dir); private static native void native_addArc(long nPath, RectF oval, float startAngle, float sweepAngle); diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java index 708c8b0..dc06350 100644 --- a/graphics/java/android/graphics/drawable/GradientDrawable.java +++ b/graphics/java/android/graphics/drawable/GradientDrawable.java @@ -866,7 +866,7 @@ public class GradientDrawable extends Drawable { float x0, x1, y0, y1; if (st.mGradient == LINEAR_GRADIENT) { - final float level = st.mUseLevel ? getLevel() / 10000.0f : 1.0f; + final float level = st.mUseLevel ? getLevel() / 10000.0f : 1.0f; switch (st.mOrientation) { case TOP_BOTTOM: x0 = r.left; y0 = r.top; @@ -1450,10 +1450,12 @@ public class GradientDrawable extends Drawable { rad = Math.min(st.mRadius, Math.min(bounds.width(), bounds.height()) * 0.5f); } - outline.setRoundRect(bounds.left, bounds.top, - bounds.right, bounds.bottom, rad); + outline.setRoundRect(bounds, rad); return true; - case LINE: { + case OVAL: + outline.setOval(bounds); + return true; + case LINE: float halfStrokeWidth = mStrokePaint.getStrokeWidth() * 0.5f; float centerY = bounds.centerY(); int top = (int) Math.floor(centerY - halfStrokeWidth); @@ -1461,7 +1463,6 @@ public class GradientDrawable extends Drawable { outline.setRect(bounds.left, top, bounds.right, bottom); return true; - } default: // TODO: investigate return false; diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java index 96309f9..61b1b85 100644 --- a/graphics/java/android/graphics/drawable/ShapeDrawable.java +++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java @@ -21,6 +21,7 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.ColorFilter; +import android.graphics.Outline; import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.PorterDuff.Mode; @@ -496,6 +497,16 @@ public class ShapeDrawable extends Drawable { } @Override + public boolean getOutline(Outline outline) { + if (mShapeState.mShape == null) { + // don't publish outline without a shape + return false; + } + + return mShapeState.mShape.getOutline(outline); + } + + @Override public ConstantState getConstantState() { mShapeState.mChangingConfigurations = getChangingConfigurations(); return mShapeState; diff --git a/graphics/java/android/graphics/drawable/shapes/OvalShape.java b/graphics/java/android/graphics/drawable/shapes/OvalShape.java index c914999..198dcc1 100644 --- a/graphics/java/android/graphics/drawable/shapes/OvalShape.java +++ b/graphics/java/android/graphics/drawable/shapes/OvalShape.java @@ -17,7 +17,9 @@ package android.graphics.drawable.shapes; import android.graphics.Canvas; +import android.graphics.Outline; import android.graphics.Paint; +import android.graphics.RectF; /** * Defines an oval shape. @@ -36,5 +38,13 @@ public class OvalShape extends RectShape { public void draw(Canvas canvas, Paint paint) { canvas.drawOval(rect(), paint); } + + @Override + public boolean getOutline(Outline outline) { + final RectF rect = rect(); + outline.setOval((int) Math.ceil(rect.left), (int) Math.ceil(rect.top), + (int) Math.floor(rect.right), (int) Math.floor(rect.bottom)); + return true; + } } diff --git a/graphics/java/android/graphics/drawable/shapes/RectShape.java b/graphics/java/android/graphics/drawable/shapes/RectShape.java index a3d2654..2a0256c 100644 --- a/graphics/java/android/graphics/drawable/shapes/RectShape.java +++ b/graphics/java/android/graphics/drawable/shapes/RectShape.java @@ -17,6 +17,7 @@ package android.graphics.drawable.shapes; import android.graphics.Canvas; +import android.graphics.Outline; import android.graphics.Paint; import android.graphics.RectF; @@ -40,10 +41,18 @@ public class RectShape extends Shape { } @Override + public boolean getOutline(Outline outline) { + final RectF rect = rect(); + outline.setRect((int) Math.ceil(rect.left), (int) Math.ceil(rect.top), + (int) Math.floor(rect.right), (int) Math.floor(rect.bottom)); + return true; + } + + @Override protected void onResize(float width, float height) { mRect.set(0, 0, width, height); } - + /** * Returns the RectF that defines this rectangle's bounds. */ diff --git a/graphics/java/android/graphics/drawable/shapes/RoundRectShape.java b/graphics/java/android/graphics/drawable/shapes/RoundRectShape.java index b469d2a..a6bb1bb 100644 --- a/graphics/java/android/graphics/drawable/shapes/RoundRectShape.java +++ b/graphics/java/android/graphics/drawable/shapes/RoundRectShape.java @@ -17,6 +17,7 @@ package android.graphics.drawable.shapes; import android.graphics.Canvas; +import android.graphics.Outline; import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; @@ -77,11 +78,34 @@ public class RoundRectShape extends RectShape { public void draw(Canvas canvas, Paint paint) { canvas.drawPath(mPath, paint); } - + + @Override + public boolean getOutline(Outline outline) { + if (mInnerRect != null) return false; // have a hole, can't produce valid outline + + float radius = 0; + if (mOuterRadii != null) { + radius = mOuterRadii[0]; + for (int i = 1; i < 8; i++) { + if (mOuterRadii[i] != radius) { + // can't call simple constructors, use path + outline.setConvexPath(mPath); + return true; + } + } + } + + final RectF rect = rect(); + outline.setRoundRect((int) Math.ceil(rect.left), (int) Math.ceil(rect.top), + (int) Math.floor(rect.right), (int) Math.floor(rect.bottom), + radius); + return true; + } + @Override protected void onResize(float w, float h) { super.onResize(w, h); - + RectF r = rect(); mPath.reset(); diff --git a/graphics/java/android/graphics/drawable/shapes/Shape.java b/graphics/java/android/graphics/drawable/shapes/Shape.java index 4e192f9..1a20e8b 100644 --- a/graphics/java/android/graphics/drawable/shapes/Shape.java +++ b/graphics/java/android/graphics/drawable/shapes/Shape.java @@ -17,6 +17,7 @@ package android.graphics.drawable.shapes; import android.graphics.Canvas; +import android.graphics.Outline; import android.graphics.Paint; /** @@ -43,7 +44,6 @@ public abstract class Shape implements Cloneable { return mHeight; } - /** * Draw this shape into the provided Canvas, with the provided Paint. * Before calling this, you must call {@link #resize(float,float)}. @@ -52,7 +52,6 @@ public abstract class Shape implements Cloneable { * @param paint the Paint object that defines this shape's characteristics */ public abstract void draw(Canvas canvas, Paint paint); - /** * Resizes the dimensions of this shape. @@ -93,8 +92,20 @@ public abstract class Shape implements Cloneable { */ protected void onResize(float width, float height) {} + /** + * Compute the Outline of the shape. + * + * The default implementation does not supply an outline. + * + * @return True if a valid outline has been computed, false otherwise. + */ + public boolean getOutline(Outline outline) { + return false; + } + @Override public Shape clone() throws CloneNotSupportedException { return (Shape) super.clone(); } + } diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml index ac741e7..5c2583b 100644 --- a/tests/HwAccelerationTest/AndroidManifest.xml +++ b/tests/HwAccelerationTest/AndroidManifest.xml @@ -873,9 +873,6 @@ <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="com.android.test.hwui.TEST" /> - - <category android:name="android.intent.category.DEFAULT" /> - <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> |