Merge "Outline & Path perf improvements"

This commit is contained in:
Chris Craik
2016-12-14 18:03:18 +00:00
committed by Android (Google) Code Review
4 changed files with 382 additions and 215 deletions

View File

@ -58,8 +58,12 @@ public final class Outline {
@Mode
public int mMode = MODE_EMPTY;
/** @hide */
public final Path mPath = new Path();
/**
* Only guaranteed to be non-null when mode == MODE_CONVEX_PATH
*
* @hide
*/
public Path mPath;
/** @hide */
public final Rect mRect = new Rect();
@ -87,8 +91,11 @@ public final class Outline {
* @see #isEmpty()
*/
public void setEmpty() {
if (mPath != null) {
// rewind here to avoid thrashing the allocations, but could alternately clear ref
mPath.rewind();
}
mMode = MODE_EMPTY;
mPath.rewind();
mRect.setEmpty();
mRadius = RADIUS_UNDEFINED;
}
@ -148,7 +155,12 @@ public final class Outline {
*/
public void set(@NonNull Outline src) {
mMode = src.mMode;
mPath.set(src.mPath);
if (src.mMode == MODE_CONVEX_PATH) {
if (mPath == null) {
mPath = new Path();
}
mPath.set(src.mPath);
}
mRect.set(src.mRect);
mRadius = src.mRadius;
mAlpha = src.mAlpha;
@ -180,10 +192,13 @@ public final class Outline {
return;
}
if (mMode == MODE_CONVEX_PATH) {
// rewind here to avoid thrashing the allocations, but could alternately clear ref
mPath.rewind();
}
mMode = MODE_ROUND_RECT;
mRect.set(left, top, right, bottom);
mRadius = radius;
mPath.rewind();
}
/**
@ -236,8 +251,13 @@ public final class Outline {
return;
}
if (mPath == null) {
mPath = new Path();
} else {
mPath.rewind();
}
mMode = MODE_CONVEX_PATH;
mPath.rewind();
mPath.addOval(left, top, right, bottom, Path.Direction.CW);
mRect.setEmpty();
mRadius = RADIUS_UNDEFINED;
@ -264,6 +284,10 @@ public final class Outline {
throw new IllegalArgumentException("path must be convex");
}
if (mPath == null) {
mPath = new Path();
}
mMode = MODE_CONVEX_PATH;
mPath.set(convexPath);
mRect.setEmpty();

View File

@ -19,6 +19,9 @@ package android.graphics;
import android.annotation.NonNull;
import android.annotation.Nullable;
import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;
/**
* The Path class encapsulates compound (multiple contour) geometric paths
* consisting of straight line segments, quadratic curves, and cubic curves.
@ -46,7 +49,7 @@ public class Path {
* Create an empty path
*/
public Path() {
mNativePath = init1();
mNativePath = nInit();
}
/**
@ -63,7 +66,7 @@ public class Path {
rects = new Region(src.rects);
}
}
mNativePath = init2(valNative);
mNativePath = nInit(valNative);
}
/**
@ -77,7 +80,7 @@ public class Path {
// We promised not to change this, so preserve it around the native
// call, which does now reset fill type.
final FillType fillType = getFillType();
native_reset(mNativePath);
nReset(mNativePath);
setFillType(fillType);
}
@ -89,7 +92,7 @@ public class Path {
isSimplePath = true;
mLastDirection = null;
if (rects != null) rects.setEmpty();
native_rewind(mNativePath);
nRewind(mNativePath);
}
/** Replace the contents of this with the contents of src.
@ -99,7 +102,7 @@ public class Path {
return;
}
isSimplePath = src.isSimplePath;
native_set(mNativePath, src.mNativePath);
nSet(mNativePath, src.mNativePath);
if (!isSimplePath) {
return;
}
@ -174,7 +177,7 @@ public class Path {
* @see #op(Path, android.graphics.Path.Op)
*/
public boolean op(Path path1, Path path2, Op op) {
if (native_op(path1.mNativePath, path2.mNativePath, op.ordinal(), this.mNativePath)) {
if (nOp(path1.mNativePath, path2.mNativePath, op.ordinal(), this.mNativePath)) {
isSimplePath = false;
rects = null;
return true;
@ -194,7 +197,7 @@ public class Path {
* @return True if the path is convex.
*/
public boolean isConvex() {
return native_isConvex(mNativePath);
return nIsConvex(mNativePath);
}
/**
@ -243,7 +246,7 @@ public class Path {
* @return the path's fill type
*/
public FillType getFillType() {
return sFillTypeArray[native_getFillType(mNativePath)];
return sFillTypeArray[nGetFillType(mNativePath)];
}
/**
@ -252,7 +255,7 @@ public class Path {
* @param ft The new fill type for this path
*/
public void setFillType(FillType ft) {
native_setFillType(mNativePath, ft.nativeInt);
nSetFillType(mNativePath, ft.nativeInt);
}
/**
@ -261,7 +264,7 @@ public class Path {
* @return true if the filltype is one of the INVERSE variants
*/
public boolean isInverseFillType() {
final int ft = native_getFillType(mNativePath);
final int ft = nGetFillType(mNativePath);
return (ft & FillType.INVERSE_WINDING.nativeInt) != 0;
}
@ -269,9 +272,9 @@ public class Path {
* Toggles the INVERSE state of the filltype
*/
public void toggleInverseFillType() {
int ft = native_getFillType(mNativePath);
int ft = nGetFillType(mNativePath);
ft ^= FillType.INVERSE_WINDING.nativeInt;
native_setFillType(mNativePath, ft);
nSetFillType(mNativePath, ft);
}
/**
@ -280,7 +283,7 @@ public class Path {
* @return true if the path is empty (contains no lines or curves)
*/
public boolean isEmpty() {
return native_isEmpty(mNativePath);
return nIsEmpty(mNativePath);
}
/**
@ -293,7 +296,7 @@ public class Path {
* @return true if the path specifies a rectangle
*/
public boolean isRect(RectF rect) {
return native_isRect(mNativePath, rect);
return nIsRect(mNativePath, rect);
}
/**
@ -306,7 +309,7 @@ public class Path {
*/
@SuppressWarnings({"UnusedDeclaration"})
public void computeBounds(RectF bounds, boolean exact) {
native_computeBounds(mNativePath, bounds);
nComputeBounds(mNativePath, bounds);
}
/**
@ -317,7 +320,7 @@ public class Path {
* path
*/
public void incReserve(int extraPtCount) {
native_incReserve(mNativePath, extraPtCount);
nIncReserve(mNativePath, extraPtCount);
}
/**
@ -327,7 +330,7 @@ public class Path {
* @param y The y-coordinate of the start of a new contour
*/
public void moveTo(float x, float y) {
native_moveTo(mNativePath, x, y);
nMoveTo(mNativePath, x, y);
}
/**
@ -341,7 +344,7 @@ public class Path {
* previous contour, to specify the start of a new contour
*/
public void rMoveTo(float dx, float dy) {
native_rMoveTo(mNativePath, dx, dy);
nRMoveTo(mNativePath, dx, dy);
}
/**
@ -354,7 +357,7 @@ public class Path {
*/
public void lineTo(float x, float y) {
isSimplePath = false;
native_lineTo(mNativePath, x, y);
nLineTo(mNativePath, x, y);
}
/**
@ -369,7 +372,7 @@ public class Path {
*/
public void rLineTo(float dx, float dy) {
isSimplePath = false;
native_rLineTo(mNativePath, dx, dy);
nRLineTo(mNativePath, dx, dy);
}
/**
@ -384,7 +387,7 @@ public class Path {
*/
public void quadTo(float x1, float y1, float x2, float y2) {
isSimplePath = false;
native_quadTo(mNativePath, x1, y1, x2, y2);
nQuadTo(mNativePath, x1, y1, x2, y2);
}
/**
@ -403,7 +406,7 @@ public class Path {
*/
public void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
isSimplePath = false;
native_rQuadTo(mNativePath, dx1, dy1, dx2, dy2);
nRQuadTo(mNativePath, dx1, dy1, dx2, dy2);
}
/**
@ -421,7 +424,7 @@ public class Path {
public void cubicTo(float x1, float y1, float x2, float y2,
float x3, float y3) {
isSimplePath = false;
native_cubicTo(mNativePath, x1, y1, x2, y2, x3, y3);
nCubicTo(mNativePath, x1, y1, x2, y2, x3, y3);
}
/**
@ -432,7 +435,7 @@ public class Path {
public void rCubicTo(float x1, float y1, float x2, float y2,
float x3, float y3) {
isSimplePath = false;
native_rCubicTo(mNativePath, x1, y1, x2, y2, x3, y3);
nRCubicTo(mNativePath, x1, y1, x2, y2, x3, y3);
}
/**
@ -483,7 +486,7 @@ public class Path {
public void arcTo(float left, float top, float right, float bottom, float startAngle,
float sweepAngle, boolean forceMoveTo) {
isSimplePath = false;
native_arcTo(mNativePath, left, top, right, bottom, startAngle, sweepAngle, forceMoveTo);
nArcTo(mNativePath, left, top, right, bottom, startAngle, sweepAngle, forceMoveTo);
}
/**
@ -492,7 +495,7 @@ public class Path {
*/
public void close() {
isSimplePath = false;
native_close(mNativePath);
nClose(mNativePath);
}
/**
@ -544,7 +547,7 @@ public class Path {
*/
public void addRect(float left, float top, float right, float bottom, Direction dir) {
detectSimplePath(left, top, right, bottom, dir);
native_addRect(mNativePath, left, top, right, bottom, dir.nativeInt);
nAddRect(mNativePath, left, top, right, bottom, dir.nativeInt);
}
/**
@ -564,7 +567,7 @@ public class Path {
*/
public void addOval(float left, float top, float right, float bottom, Direction dir) {
isSimplePath = false;
native_addOval(mNativePath, left, top, right, bottom, dir.nativeInt);
nAddOval(mNativePath, left, top, right, bottom, dir.nativeInt);
}
/**
@ -577,7 +580,7 @@ public class Path {
*/
public void addCircle(float x, float y, float radius, Direction dir) {
isSimplePath = false;
native_addCircle(mNativePath, x, y, radius, dir.nativeInt);
nAddCircle(mNativePath, x, y, radius, dir.nativeInt);
}
/**
@ -600,7 +603,7 @@ public class Path {
public void addArc(float left, float top, float right, float bottom, float startAngle,
float sweepAngle) {
isSimplePath = false;
native_addArc(mNativePath, left, top, right, bottom, startAngle, sweepAngle);
nAddArc(mNativePath, left, top, right, bottom, startAngle, sweepAngle);
}
/**
@ -625,7 +628,7 @@ public class Path {
public void addRoundRect(float left, float top, float right, float bottom, float rx, float ry,
Direction dir) {
isSimplePath = false;
native_addRoundRect(mNativePath, left, top, right, bottom, rx, ry, dir.nativeInt);
nAddRoundRect(mNativePath, left, top, right, bottom, rx, ry, dir.nativeInt);
}
/**
@ -658,7 +661,7 @@ public class Path {
throw new ArrayIndexOutOfBoundsException("radii[] needs 8 values");
}
isSimplePath = false;
native_addRoundRect(mNativePath, left, top, right, bottom, radii, dir.nativeInt);
nAddRoundRect(mNativePath, left, top, right, bottom, radii, dir.nativeInt);
}
/**
@ -669,7 +672,7 @@ public class Path {
*/
public void addPath(Path src, float dx, float dy) {
isSimplePath = false;
native_addPath(mNativePath, src.mNativePath, dx, dy);
nAddPath(mNativePath, src.mNativePath, dx, dy);
}
/**
@ -679,7 +682,7 @@ public class Path {
*/
public void addPath(Path src) {
isSimplePath = false;
native_addPath(mNativePath, src.mNativePath);
nAddPath(mNativePath, src.mNativePath);
}
/**
@ -689,7 +692,7 @@ public class Path {
*/
public void addPath(Path src, Matrix matrix) {
if (!src.isSimplePath) isSimplePath = false;
native_addPath(mNativePath, src.mNativePath, matrix.native_instance);
nAddPath(mNativePath, src.mNativePath, matrix.native_instance);
}
/**
@ -725,7 +728,7 @@ public class Path {
} else {
isSimplePath = false;
}
native_offset(mNativePath, dx, dy);
nOffset(mNativePath, dx, dy);
}
/**
@ -736,7 +739,7 @@ public class Path {
*/
public void setLastPoint(float dx, float dy) {
isSimplePath = false;
native_setLastPoint(mNativePath, dx, dy);
nSetLastPoint(mNativePath, dx, dy);
}
/**
@ -753,7 +756,7 @@ public class Path {
dst.isSimplePath = false;
dstNative = dst.mNativePath;
}
native_transform(mNativePath, matrix.native_instance, dstNative);
nTransform(mNativePath, matrix.native_instance, dstNative);
}
/**
@ -763,12 +766,12 @@ public class Path {
*/
public void transform(Matrix matrix) {
isSimplePath = false;
native_transform(mNativePath, matrix.native_instance);
nTransform(mNativePath, matrix.native_instance);
}
protected void finalize() throws Throwable {
try {
finalizer(mNativePath);
nFinalize(mNativePath);
mNativePath = 0; // Other finalizers can still call us.
} finally {
super.finalize();
@ -803,59 +806,68 @@ public class Path {
* @return An array of components for points approximating the Path.
*/
public float[] approximate(float acceptableError) {
return native_approximate(mNativePath, acceptableError);
return nApproximate(mNativePath, acceptableError);
}
private static native long init1();
private static native long init2(long nPath);
private static native void native_reset(long nPath);
private static native void native_rewind(long nPath);
private static native void native_set(long native_dst, long native_src);
private static native boolean native_isConvex(long nPath);
private static native int native_getFillType(long nPath);
private static native void native_setFillType(long nPath, int ft);
private static native boolean native_isEmpty(long nPath);
private static native boolean native_isRect(long nPath, RectF rect);
private static native void native_computeBounds(long nPath, RectF bounds);
private static native void native_incReserve(long nPath, int extraPtCount);
private static native void native_moveTo(long nPath, float x, float y);
private static native void native_rMoveTo(long nPath, float dx, float dy);
private static native void native_lineTo(long nPath, float x, float y);
private static native void native_rLineTo(long nPath, float dx, float dy);
private static native void native_quadTo(long nPath, float x1, float y1,
float x2, float y2);
private static native void native_rQuadTo(long nPath, float dx1, float dy1,
float dx2, float dy2);
private static native void native_cubicTo(long nPath, float x1, float y1,
float x2, float y2, float x3, float y3);
private static native void native_rCubicTo(long nPath, float x1, float y1,
float x2, float y2, float x3, float y3);
private static native void native_arcTo(long nPath, float left, float top,
float right, float bottom, float startAngle,
float sweepAngle, boolean forceMoveTo);
private static native void native_close(long nPath);
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, float left, float top,
// ------------------ Regular JNI ------------------------
private static native long nInit();
private static native long nInit(long nPath);
private static native void nFinalize(long nPath);
private static native void nSet(long native_dst, long nSrc);
private static native void nComputeBounds(long nPath, RectF bounds);
private static native void nIncReserve(long nPath, int extraPtCount);
private static native void nMoveTo(long nPath, float x, float y);
private static native void nRMoveTo(long nPath, float dx, float dy);
private static native void nLineTo(long nPath, float x, float y);
private static native void nRLineTo(long nPath, float dx, float dy);
private static native void nQuadTo(long nPath, float x1, float y1, float x2, float y2);
private static native void nRQuadTo(long nPath, float dx1, float dy1, float dx2, float dy2);
private static native void nCubicTo(long nPath, float x1, float y1, float x2, float y2,
float x3, float y3);
private static native void nRCubicTo(long nPath, float x1, float y1, float x2, float y2,
float x3, float y3);
private static native void nArcTo(long nPath, float left, float top, float right, float bottom,
float startAngle, float sweepAngle, boolean forceMoveTo);
private static native void nClose(long nPath);
private static native void nAddRect(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, float left, float top,
float right, float bottom,
float startAngle, float sweepAngle);
private static native void native_addRoundRect(long nPath, float left, float top,
float right, float bottom,
float rx, float ry, int dir);
private static native void native_addRoundRect(long nPath, float left, float top,
float right, float bottom,
float[] radii, int dir);
private static native void native_addPath(long nPath, long src, float dx, float dy);
private static native void native_addPath(long nPath, long src);
private static native void native_addPath(long nPath, long src, long matrix);
private static native void native_offset(long nPath, float dx, float dy);
private static native void native_setLastPoint(long nPath, float dx, float dy);
private static native void native_transform(long nPath, long matrix, long dst_path);
private static native void native_transform(long nPath, long matrix);
private static native boolean native_op(long path1, long path2, int op, long result);
private static native void finalizer(long nPath);
private static native float[] native_approximate(long nPath, float error);
private static native void nAddOval(long nPath, float left, float top,
float right, float bottom, int dir);
private static native void nAddCircle(long nPath, float x, float y, float radius, int dir);
private static native void nAddArc(long nPath, float left, float top, float right, float bottom,
float startAngle, float sweepAngle);
private static native void nAddRoundRect(long nPath, float left, float top,
float right, float bottom, float rx, float ry, int dir);
private static native void nAddRoundRect(long nPath, float left, float top,
float right, float bottom, float[] radii, int dir);
private static native void nAddPath(long nPath, long src, float dx, float dy);
private static native void nAddPath(long nPath, long src);
private static native void nAddPath(long nPath, long src, long matrix);
private static native void nOffset(long nPath, float dx, float dy);
private static native void nSetLastPoint(long nPath, float dx, float dy);
private static native void nTransform(long nPath, long matrix, long dst_path);
private static native void nTransform(long nPath, long matrix);
private static native boolean nOp(long path1, long path2, int op, long result);
private static native float[] nApproximate(long nPath, float error);
// ------------------ Fast JNI ------------------------
@FastNative
private static native boolean nIsRect(long nPath, RectF rect);
// ------------------ Critical JNI ------------------------
@CriticalNative
private static native void nReset(long nPath);
@CriticalNative
private static native void nRewind(long nPath);
@CriticalNative
private static native boolean nIsEmpty(long nPath);
@CriticalNative
private static native boolean nIsConvex(long nPath);
@CriticalNative
private static native int nGetFillType(long nPath);
@CriticalNative
private static native void nSetFillType(long nPath, int ft);
}