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 /graphics | |
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
Diffstat (limited to 'graphics')
8 files changed, 136 insertions, 41 deletions
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(); } + } |