summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Craik <ccraik@google.com>2014-04-25 13:08:25 -0700
committerChris Craik <ccraik@google.com>2014-04-25 15:59:47 -0700
commit7979388d4f7d5d9dbfcf7e1cc4709f8088c034ae (patch)
treefb8460098f57d66ed696b65a9cc70b51cf1128ff
parent07f0b8ee730be00a2a4bccf797bd8cb71e556546 (diff)
downloadframeworks_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.txt4
-rw-r--r--core/java/android/view/View.java3
-rw-r--r--core/jni/android/graphics/Path.cpp34
-rw-r--r--graphics/java/android/graphics/Outline.java67
-rw-r--r--graphics/java/android/graphics/Path.java24
-rw-r--r--graphics/java/android/graphics/drawable/GradientDrawable.java11
-rw-r--r--graphics/java/android/graphics/drawable/ShapeDrawable.java11
-rw-r--r--graphics/java/android/graphics/drawable/shapes/OvalShape.java10
-rw-r--r--graphics/java/android/graphics/drawable/shapes/RectShape.java11
-rw-r--r--graphics/java/android/graphics/drawable/shapes/RoundRectShape.java28
-rw-r--r--graphics/java/android/graphics/drawable/shapes/Shape.java15
-rw-r--r--tests/HwAccelerationTest/AndroidManifest.xml3
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>