summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeorge Mount <mount@google.com>2013-12-11 15:08:58 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2013-12-11 15:08:59 +0000
commited62560f69d8a5445d2cae253937f3e4a4900b12 (patch)
treef8b23c4d48948cb5e5b51cdf3a83f1395bd178d1
parent94f71949f7c2bbf9a23f96f53ab963f252374de9 (diff)
parent7fe03a267e6edb65142444765ce29ad5ff126052 (diff)
downloadframeworks_base-ed62560f69d8a5445d2cae253937f3e4a4900b12.zip
frameworks_base-ed62560f69d8a5445d2cae253937f3e4a4900b12.tar.gz
frameworks_base-ed62560f69d8a5445d2cae253937f3e4a4900b12.tar.bz2
Merge "Add Path trimming."
-rw-r--r--api/current.txt2
-rw-r--r--core/jni/android/graphics/Path.cpp52
-rw-r--r--graphics/java/android/graphics/Path.java117
3 files changed, 169 insertions, 2 deletions
diff --git a/api/current.txt b/api/current.txt
index ce92fcb..203a8e9 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -9712,6 +9712,8 @@ package android.graphics {
method public void toggleInverseFillType();
method public void transform(android.graphics.Matrix, android.graphics.Path);
method public void transform(android.graphics.Matrix);
+ method public void trim(float, float, float);
+ method public void trim(float, float, float, android.graphics.Path);
}
public static final class Path.Direction extends java.lang.Enum {
diff --git a/core/jni/android/graphics/Path.cpp b/core/jni/android/graphics/Path.cpp
index 97a7de6..2126ed4 100644
--- a/core/jni/android/graphics/Path.cpp
+++ b/core/jni/android/graphics/Path.cpp
@@ -268,7 +268,6 @@ public:
return Op(*p1, *p2, op, r);
}
-
typedef SkPoint (*bezierCalculation)(float t, const SkPoint* points);
static void addMove(std::vector<SkPoint>& segmentPoints, std::vector<float>& lengths,
@@ -396,6 +395,8 @@ public:
addMove(segmentPoints, lengths, points[0]);
break;
case SkPath::kClose_Verb:
+ addLine(segmentPoints, lengths, points[0]);
+ break;
case SkPath::kLine_Verb:
addLine(segmentPoints, lengths, points[1]);
break;
@@ -445,7 +446,7 @@ public:
float totalLength = lengths.back();
int approximationIndex = 0;
- for (int i = 0; i < numPoints; i++) {
+ for (size_t i = 0; i < numPoints; i++) {
const SkPoint& point = segmentPoints[i];
approximation[approximationIndex++] = lengths[i] / totalLength;
approximation[approximationIndex++] = point.x();
@@ -457,6 +458,51 @@ public:
delete[] approximation;
return result;
}
+
+ static SkPathMeasure* trim(JNIEnv* env, jobject clazz, SkPath* inPath, SkPath* outPath,
+ SkPathMeasure* pathMeasure, jfloat trimStart, jfloat trimEnd, jfloat trimOffset) {
+ if (trimStart == 0 && trimEnd == 1) {
+ if (outPath != NULL) {
+ *outPath = *inPath;
+ }
+ return pathMeasure;
+ }
+
+ bool modifyPath = (outPath == NULL);
+ if (modifyPath) {
+ outPath = new SkPath();
+ } else {
+ outPath->reset();
+ }
+ if (pathMeasure == NULL) {
+ pathMeasure = new SkPathMeasure(*inPath, false);
+ }
+ float length = pathMeasure->getLength();
+ float start = (trimStart + trimOffset) * length;
+ float end = (trimEnd + trimOffset) * length;
+
+ if (end > length && start <= length) {
+ pathMeasure->getSegment(start, length, outPath, true);
+ pathMeasure->getSegment(0, end - length, outPath, true);
+ } else {
+ if (start > length) {
+ start -= length;
+ end -= length;
+ }
+ pathMeasure->getSegment(start, end, outPath, true);
+ }
+ if (modifyPath) {
+ delete pathMeasure;
+ pathMeasure = NULL;
+ *inPath = *outPath;
+ delete outPath;
+ }
+ return pathMeasure;
+ }
+
+ static void destroyMeasure(JNIEnv* env, jobject clazz, SkPathMeasure* measure) {
+ delete measure;
+ }
};
static JNINativeMethod methods[] = {
@@ -499,6 +545,8 @@ static JNINativeMethod methods[] = {
{"native_transform","(II)V", (void*) SkPathGlue::transform__Matrix},
{"native_op","(IIII)Z", (void*) SkPathGlue::op},
{"native_approximate", "(IF)[F", (void*) SkPathGlue::approximate},
+ {"native_destroyMeasure","(I)V", (void*) SkPathGlue::destroyMeasure},
+ {"native_trim","(IIIFFF)I", (void*) SkPathGlue::trim},
};
int register_android_graphics_Path(JNIEnv* env) {
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index 1a7e3ec..4776088 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -28,6 +28,7 @@ public class Path {
* @hide
*/
public final int mNativePath;
+ private int mNativePathMeasure;
/**
* @hide
@@ -76,6 +77,14 @@ public class Path {
final FillType fillType = getFillType();
native_reset(mNativePath);
setFillType(fillType);
+ clearMeasure();
+ }
+
+ private void clearMeasure() {
+ if (mNativePathMeasure != 0) {
+ native_destroyMeasure(mNativePathMeasure);
+ mNativePathMeasure = 0;
+ }
}
/**
@@ -87,6 +96,7 @@ public class Path {
mLastDirection = null;
if (rects != null) rects.setEmpty();
native_rewind(mNativePath);
+ clearMeasure();
}
/** Replace the contents of this with the contents of src.
@@ -95,6 +105,7 @@ public class Path {
if (this != src) {
isSimplePath = src.isSimplePath;
native_set(mNativePath, src.mNativePath);
+ clearMeasure();
}
}
@@ -223,6 +234,7 @@ public class Path {
*/
public void setFillType(FillType ft) {
native_setFillType(mNativePath, ft.nativeInt);
+ clearMeasure();
}
/**
@@ -242,6 +254,7 @@ public class Path {
int ft = native_getFillType(mNativePath);
ft ^= 2;
native_setFillType(mNativePath, ft);
+ clearMeasure();
}
/**
@@ -298,6 +311,7 @@ public class Path {
*/
public void moveTo(float x, float y) {
native_moveTo(mNativePath, x, y);
+ clearMeasure();
}
/**
@@ -312,6 +326,7 @@ public class Path {
*/
public void rMoveTo(float dx, float dy) {
native_rMoveTo(mNativePath, dx, dy);
+ clearMeasure();
}
/**
@@ -325,6 +340,7 @@ public class Path {
public void lineTo(float x, float y) {
isSimplePath = false;
native_lineTo(mNativePath, x, y);
+ clearMeasure();
}
/**
@@ -340,6 +356,7 @@ public class Path {
public void rLineTo(float dx, float dy) {
isSimplePath = false;
native_rLineTo(mNativePath, dx, dy);
+ clearMeasure();
}
/**
@@ -355,6 +372,7 @@ public class Path {
public void quadTo(float x1, float y1, float x2, float y2) {
isSimplePath = false;
native_quadTo(mNativePath, x1, y1, x2, y2);
+ clearMeasure();
}
/**
@@ -374,6 +392,7 @@ public class Path {
public void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
isSimplePath = false;
native_rQuadTo(mNativePath, dx1, dy1, dx2, dy2);
+ clearMeasure();
}
/**
@@ -392,6 +411,7 @@ public class Path {
float x3, float y3) {
isSimplePath = false;
native_cubicTo(mNativePath, x1, y1, x2, y2, x3, y3);
+ clearMeasure();
}
/**
@@ -403,6 +423,7 @@ public class Path {
float x3, float y3) {
isSimplePath = false;
native_rCubicTo(mNativePath, x1, y1, x2, y2, x3, y3);
+ clearMeasure();
}
/**
@@ -422,6 +443,7 @@ public class Path {
boolean forceMoveTo) {
isSimplePath = false;
native_arcTo(mNativePath, oval, startAngle, sweepAngle, forceMoveTo);
+ clearMeasure();
}
/**
@@ -438,6 +460,7 @@ public class Path {
public void arcTo(RectF oval, float startAngle, float sweepAngle) {
isSimplePath = false;
native_arcTo(mNativePath, oval, startAngle, sweepAngle, false);
+ clearMeasure();
}
/**
@@ -447,6 +470,7 @@ public class Path {
public void close() {
isSimplePath = false;
native_close(mNativePath);
+ clearMeasure();
}
/**
@@ -489,6 +513,7 @@ public class Path {
}
detectSimplePath(rect.left, rect.top, rect.right, rect.bottom, dir);
native_addRect(mNativePath, rect, dir.nativeInt);
+ clearMeasure();
}
/**
@@ -503,6 +528,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);
+ clearMeasure();
}
/**
@@ -517,6 +543,7 @@ public class Path {
}
isSimplePath = false;
native_addOval(mNativePath, oval, dir.nativeInt);
+ clearMeasure();
}
/**
@@ -530,6 +557,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);
+ clearMeasure();
}
/**
@@ -545,6 +573,7 @@ public class Path {
}
isSimplePath = false;
native_addArc(mNativePath, oval, startAngle, sweepAngle);
+ clearMeasure();
}
/**
@@ -561,6 +590,7 @@ public class Path {
}
isSimplePath = false;
native_addRoundRect(mNativePath, rect, rx, ry, dir.nativeInt);
+ clearMeasure();
}
/**
@@ -581,6 +611,7 @@ public class Path {
}
isSimplePath = false;
native_addRoundRect(mNativePath, rect, radii, dir.nativeInt);
+ clearMeasure();
}
/**
@@ -592,6 +623,7 @@ public class Path {
public void addPath(Path src, float dx, float dy) {
isSimplePath = false;
native_addPath(mNativePath, src.mNativePath, dx, dy);
+ clearMeasure();
}
/**
@@ -602,6 +634,7 @@ public class Path {
public void addPath(Path src) {
isSimplePath = false;
native_addPath(mNativePath, src.mNativePath);
+ clearMeasure();
}
/**
@@ -612,6 +645,7 @@ public class Path {
public void addPath(Path src, Matrix matrix) {
if (!src.isSimplePath) isSimplePath = false;
native_addPath(mNativePath, src.mNativePath, matrix.native_instance);
+ clearMeasure();
}
/**
@@ -629,6 +663,11 @@ public class Path {
dst.isSimplePath = false;
}
native_offset(mNativePath, dx, dy, dstNative);
+ if (dst != null) {
+ dst.clearMeasure();
+ } else {
+ clearMeasure();
+ }
}
/**
@@ -640,6 +679,7 @@ public class Path {
public void offset(float dx, float dy) {
isSimplePath = false;
native_offset(mNativePath, dx, dy);
+ clearMeasure();
}
/**
@@ -651,6 +691,7 @@ public class Path {
public void setLastPoint(float dx, float dy) {
isSimplePath = false;
native_setLastPoint(mNativePath, dx, dy);
+ clearMeasure();
}
/**
@@ -668,6 +709,11 @@ public class Path {
dstNative = dst.mNativePath;
}
native_transform(mNativePath, matrix.native_instance, dstNative);
+ if (dst != null) {
+ dst.clearMeasure();
+ } else {
+ clearMeasure();
+ }
}
/**
@@ -678,10 +724,14 @@ public class Path {
public void transform(Matrix matrix) {
isSimplePath = false;
native_transform(mNativePath, matrix.native_instance);
+ clearMeasure();
}
protected void finalize() throws Throwable {
try {
+ if (mNativePathMeasure != 0) {
+ native_destroyMeasure(mNativePathMeasure);
+ }
finalizer(mNativePath);
} finally {
super.finalize();
@@ -714,6 +764,70 @@ public class Path {
return native_approximate(mNativePath, acceptableError);
}
+ /**
+ * Modifies the <code>Path</code> by extracting a portion of it.
+ * The portion of the <code>Path</code> used is between <code>trimStart</code> and
+ * <code>trimEnd</code> with the value offset by <code>trimOffset</code>. When
+ * <code>trimOffset</code> added to <code>trimEnd</code> is greater than 1, the
+ * trimmed portion "wraps" to the start of the <code>Path</code>.
+ * <p>For example, if <code>Path</code> is a circle and <code>trimStart</code> is 0
+ * and <code>trimEnd</code> is 0.5, the resulting <code>Path</code> is the arc of
+ * a semicircle. If <code>trimOffset</code> is set to 0.75, the arc will start at
+ * 3/4 of the circle and continue to the end of the circle, then start again at the
+ * beginning of the circle and end at 1/4 of the way around. It will appear as if
+ * the semicircle arc wrapped around the <code>Path</code> start and end.</p>
+ * @param trimStart A number between 0 and <code>trimEnd</code> indicating the fraction of the
+ * <code>Path</code> to start. A value of 0 trims nothing from the start.
+ * @param trimEnd A number between <code>trimStart</code> and 1 indicating the fraction of the
+ * <code>Path</code> to end. A value of 1 trims nothing from the end.
+ * @param trimOffset A fraction between 0 and 1 indicating the offset of the trimmed
+ * portion of the <code>Path</code>.
+ * @see #trim(float, float, float, Path)
+ */
+ public void trim(float trimStart, float trimEnd, float trimOffset) {
+ trim(trimStart, trimEnd, trimOffset, null);
+ }
+
+ /**
+ * Extracts a portion of the <code>Path</code> and writes it to <code>dst</code>.
+ * The portion of the <code>Path</code> used is between <code>trimStart</code> and
+ * <code>trimEnd</code> with the value offset by <code>trimOffset</code>. When
+ * <code>trimOffset</code> added to <code>trimEnd</code> is greater than 1, the
+ * trimmed portion "wraps" to the start of the <code>Path</code>.
+ * <p>For example, if <code>Path</code> is a circle and <code>trimStart</code> is 0
+ * and <code>trimEnd</code> is 0.5, the resulting <code>Path</code> is the arc of
+ * a semicircle. If <code>trimOffset</code> is set to 0.75, the arc will start at
+ * 3/4 of the circle and continue to the end of the circle, then start again at the
+ * beginning of the circle and end at 1/4 of the way around. It will appear as if
+ * the semicircle arc wrapped around the <code>Path</code> start and end.</p>
+ * @param trimStart A number between 0 and <code>trimEnd</code> indicating the fraction of the
+ * <code>Path</code> to start. A value of 0 trims nothing from the start.
+ * @param trimEnd A number between <code>trimStart</code> and 1 indicating the fraction of the
+ * <code>Path</code> to end. A value of 1 trims nothing from the end.
+ * @param trimOffset A fraction between 0 and 1 indicating the offset of the trimmed
+ * portion of the <code>Path</code>.
+ * @param dst The trimmed <code>Path</code> is written here. If <code>dst</code> is null,
+ * then the original <code>Path</code> is modified.
+ * @see #trim(float, float, float)
+ */
+ public void trim(float trimStart, float trimEnd, float trimOffset, Path dst) {
+ if (trimStart > 1 || trimEnd > 1 || trimOffset > 1
+ || trimStart < 0 || trimEnd < 0 || trimOffset < 0) {
+ throw new IllegalArgumentException("trim must be between 0 and 1");
+ }
+ if (trimStart > trimEnd) {
+ throw new IllegalArgumentException("trim end cannot be less than start");
+ }
+ int dstNative = 0;
+ if (dst != null) {
+ dstNative = dst.mNativePath;
+ dst.isSimplePath = false;
+ dst.clearMeasure();
+ }
+ mNativePathMeasure = native_trim(mNativePath, dstNative, mNativePathMeasure,
+ trimStart, trimEnd, trimOffset);
+ }
+
private static native int init1();
private static native int init2(int nPath);
private static native void native_reset(int nPath);
@@ -761,4 +875,7 @@ public class Path {
private static native boolean native_op(int path1, int path2, int op, int result);
private static native void finalizer(int nPath);
private static native float[] native_approximate(int nPath, float error);
+ private static native int native_trim(int nPath, int nTargetPath, int nPathMeasure,
+ float trimStart, float trimEnd, float trimOffset);
+ private static native void native_destroyMeasure(int nPathMeasure);
}