VectorDrawable native rendering - Step 2 of MANY
Introduced PathData in Java, which is effectively a thin layer around the
native instance. PathData holds the verbs and points which is being used
in path morphing/interpolation. The verbs and points can be interpreted
into skia path commands, which is now done in native and therefore saves
a handful of JNI calls during path creation.
Removed the old PathDataNode mechanism and changed the PathEvaluator
to use PathData instead.
Also added tests and a microbench. Also ran CTS tests for VectorDrawable
and AnimatedVectorDrawable, and passed all of the existing tests.
Change-Id: Ia166f5172ff031fe18b154327967f911a62caec1
diff --git a/core/jni/android_util_PathParser.cpp b/core/jni/android_util_PathParser.cpp
index 245aa0f..0927120 100644
--- a/core/jni/android_util_PathParser.cpp
+++ b/core/jni/android_util_PathParser.cpp
@@ -18,19 +18,22 @@
#include <PathParser.h>
#include <SkPath.h>
+#include <utils/VectorDrawableUtils.h>
#include <android/log.h>
#include "core_jni_helpers.h"
namespace android {
+using namespace uirenderer;
+
static bool parseStringForPath(JNIEnv* env, jobject, jlong skPathHandle, jstring inputPathStr,
jint strLength) {
const char* pathString = env->GetStringUTFChars(inputPathStr, NULL);
SkPath* skPath = reinterpret_cast<SkPath*>(skPathHandle);
- android::uirenderer::PathParser::ParseResult result;
- android::uirenderer::PathParser::parseStringForSkPath(skPath, &result, pathString, strLength);
+ PathParser::ParseResult result;
+ PathParser::parseStringForSkPath(skPath, &result, pathString, strLength);
env->ReleaseStringUTFChars(inputPathStr, pathString);
if (result.failureOccurred) {
ALOGE(result.failureMessage.c_str());
@@ -38,8 +41,74 @@
return !result.failureOccurred;
}
+static long createEmptyPathData(JNIEnv*, jobject) {
+ PathData* pathData = new PathData();
+ return reinterpret_cast<jlong>(pathData);
+}
+
+static long createPathData(JNIEnv*, jobject, jlong pathDataPtr) {
+ PathData* pathData = reinterpret_cast<PathData*>(pathDataPtr);
+ PathData* newPathData = new PathData(*pathData);
+ return reinterpret_cast<jlong>(newPathData);
+}
+
+static long createPathDataFromStringPath(JNIEnv* env, jobject, jstring inputStr, jint strLength) {
+ const char* pathString = env->GetStringUTFChars(inputStr, NULL);
+ PathData* pathData = new PathData();
+ PathParser::ParseResult result;
+ PathParser::getPathDataFromString(pathData, &result, pathString, strLength);
+ env->ReleaseStringUTFChars(inputStr, pathString);
+ if (!result.failureOccurred) {
+ return reinterpret_cast<jlong>(pathData);
+ } else {
+ delete pathData;
+ ALOGE(result.failureMessage.c_str());
+ return NULL;
+ }
+}
+
+static bool interpolatePathData(JNIEnv*, jobject, jlong outPathDataPtr, jlong fromPathDataPtr,
+ jlong toPathDataPtr, jfloat fraction) {
+ PathData* outPathData = reinterpret_cast<PathData*>(outPathDataPtr);
+ PathData* fromPathData = reinterpret_cast<PathData*>(fromPathDataPtr);
+ PathData* toPathData = reinterpret_cast<PathData*>(toPathDataPtr);
+ return VectorDrawableUtils::interpolatePathData(outPathData, *fromPathData,
+ *toPathData, fraction);
+}
+
+static void deletePathData(JNIEnv*, jobject, jlong pathDataHandle) {
+ PathData* pathData = reinterpret_cast<PathData*>(pathDataHandle);
+ delete pathData;
+}
+
+static bool canMorphPathData(JNIEnv*, jobject, jlong fromPathDataPtr, jlong toPathDataPtr) {
+ PathData* fromPathData = reinterpret_cast<PathData*>(fromPathDataPtr);
+ PathData* toPathData = reinterpret_cast<PathData*>(toPathDataPtr);
+ return VectorDrawableUtils::canMorph(*fromPathData, *toPathData);
+}
+
+static void setPathData(JNIEnv*, jobject, jlong outPathDataPtr, jlong fromPathDataPtr) {
+ PathData* fromPathData = reinterpret_cast<PathData*>(fromPathDataPtr);
+ PathData* outPathData = reinterpret_cast<PathData*>(outPathDataPtr);
+ *outPathData = *fromPathData;
+}
+
+static void setSkPathFromPathData(JNIEnv*, jobject, jlong outPathPtr, jlong pathDataPtr) {
+ PathData* pathData = reinterpret_cast<PathData*>(pathDataPtr);
+ SkPath* skPath = reinterpret_cast<SkPath*>(outPathPtr);
+ VectorDrawableUtils::verbsToPath(skPath, *pathData);
+}
+
static const JNINativeMethod gMethods[] = {
- {"nParseStringForPath", "(JLjava/lang/String;I)Z", (void*)parseStringForPath}
+ {"nParseStringForPath", "(JLjava/lang/String;I)Z", (void*)parseStringForPath},
+ {"nCreateEmptyPathData", "!()J", (void*)createEmptyPathData},
+ {"nCreatePathData", "!(J)J", (void*)createPathData},
+ {"nCreatePathDataFromString", "(Ljava/lang/String;I)J", (void*)createPathDataFromStringPath},
+ {"nInterpolatePathData", "!(JJJF)Z", (void*)interpolatePathData},
+ {"nFinalize", "!(J)V", (void*)deletePathData},
+ {"nCanMorph", "!(JJ)Z", (void*)canMorphPathData},
+ {"nSetPathData", "!(JJ)V", (void*)setPathData},
+ {"nCreatePathFromPathData", "!(JJ)V", (void*)setSkPathFromPathData},
};
int register_android_util_PathParser(JNIEnv* env) {