From db67186c8599391334620a39625a5abdfc9bfedf Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Tue, 2 Aug 2022 11:45:01 -0700 Subject: [PATCH] Update to pathway 0.5.0 - Added offset to next() to use large arrays --- .idea/deploymentTargetDropDown.xml | 17 ------------- README.md | 2 +- gradle.properties | 2 +- .../graphics/path/PathIteratorTest.kt | 24 ++++++++++++++++++- pathway/src/main/cpp/pathway.cpp | 14 ++++++----- .../java/dev/romainguy/graphics/path/Paths.kt | 18 +++++++++----- 6 files changed, 45 insertions(+), 32 deletions(-) delete mode 100644 .idea/deploymentTargetDropDown.xml diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml deleted file mode 100644 index 9101858..0000000 --- a/.idea/deploymentTargetDropDown.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/README.md b/README.md index 17a62cc..f13d6f1 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ repositories { } dependencies { - implementation 'dev.romainguy:pathway:0.4.0' + implementation 'dev.romainguy:pathway:0.5.0' } ``` diff --git a/gradle.properties b/gradle.properties index 994ff9d..1458023 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ GROUP=dev.romainguy -VERSION_NAME=0.4.0 +VERSION_NAME=0.5.0 POM_DESCRIPTION=Android library to extend the functionality of the graphics Path API diff --git a/pathway/src/androidTest/java/dev/romainguy/graphics/path/PathIteratorTest.kt b/pathway/src/androidTest/java/dev/romainguy/graphics/path/PathIteratorTest.kt index 9138938..f7d0207 100644 --- a/pathway/src/androidTest/java/dev/romainguy/graphics/path/PathIteratorTest.kt +++ b/pathway/src/androidTest/java/dev/romainguy/graphics/path/PathIteratorTest.kt @@ -169,27 +169,37 @@ class PathIteratorTest { val iterator1 = path.iterator(PathIterator.ConicEvaluation.AsConic) val iterator2 = path.iterator(PathIterator.ConicEvaluation.AsConic) + val iterator3 = path.iterator(PathIterator.ConicEvaluation.AsConic) val points = FloatArray(8) + val points2 = FloatArray(16) - while (iterator1.hasNext() || iterator2.hasNext()) { + while (iterator1.hasNext() || iterator2.hasNext() || iterator3.hasNext()) { val segment = iterator1.next() val type = iterator2.next(points) + val type2 = iterator3.next(points2, 8) assertEquals(type, segment.type) + assertEquals(type2, segment.type) when (type) { PathSegment.Type.Move -> { assertPointsEquals(points, 0, segment.points[0]) + assertPointsEquals(points2, 4, segment.points[0]) } PathSegment.Type.Line -> { assertPointsEquals(points, 0, segment.points[0]) assertPointsEquals(points, 1, segment.points[1]) + assertPointsEquals(points2, 4, segment.points[0]) + assertPointsEquals(points2, 5, segment.points[1]) } PathSegment.Type.Quadratic -> { assertPointsEquals(points, 0, segment.points[0]) assertPointsEquals(points, 1, segment.points[1]) assertPointsEquals(points, 2, segment.points[2]) + assertPointsEquals(points2, 4, segment.points[0]) + assertPointsEquals(points2, 5, segment.points[1]) + assertPointsEquals(points2, 6, segment.points[2]) } PathSegment.Type.Conic -> { assertPointsEquals(points, 0, segment.points[0]) @@ -198,12 +208,24 @@ class PathIteratorTest { // We store the weight twice assertEquals(points[6], segment.weight) assertEquals(points[7], segment.weight) + + assertPointsEquals(points2, 4, segment.points[0]) + assertPointsEquals(points2, 5, segment.points[1]) + assertPointsEquals(points2, 6, segment.points[2]) + // We store the weight twice + assertEquals(points2[14], segment.weight) + assertEquals(points2[15], segment.weight) } PathSegment.Type.Cubic -> { assertPointsEquals(points, 0, segment.points[0]) assertPointsEquals(points, 1, segment.points[1]) assertPointsEquals(points, 2, segment.points[2]) assertPointsEquals(points, 3, segment.points[3]) + + assertPointsEquals(points2, 4, segment.points[0]) + assertPointsEquals(points2, 5, segment.points[1]) + assertPointsEquals(points2, 6, segment.points[2]) + assertPointsEquals(points2, 7, segment.points[3]) } PathSegment.Type.Close -> { } PathSegment.Type.Done -> { } diff --git a/pathway/src/main/cpp/pathway.cpp b/pathway/src/main/cpp/pathway.cpp index 4e5e1d1..737e2d7 100644 --- a/pathway/src/main/cpp/pathway.cpp +++ b/pathway/src/main/cpp/pathway.cpp @@ -38,7 +38,7 @@ struct { uint32_t sApiLevel = 0; std::once_flag sApiLevelOnceFlag; -static int api_level() { +static uint32_t api_level() { std::call_once(sApiLevelOnceFlag, []() { char sdkVersion[PROP_VALUE_MAX]; __system_property_get("ro.build.version.sdk", sdkVersion); @@ -59,7 +59,7 @@ static jlong createPathIterator(JNIEnv* env, jobject, int count; PathIterator::VerbDirection direction; - const int apiLevel = api_level(); + const uint32_t apiLevel = api_level(); if (apiLevel >= 30) { auto* ref = reinterpret_cast(path->pathRef); points = ref->points; @@ -104,13 +104,15 @@ static jboolean pathIteratorHasNext(JNIEnv*, jobject, jlong pathIterator_) { return reinterpret_cast(pathIterator_)->hasNext(); } -static jint pathIteratorNext(JNIEnv* env, jobject, jlong pathIterator_, jfloatArray points_) { +static jint pathIteratorNext( + JNIEnv* env, jobject, jlong pathIterator_, jfloatArray points_, jint offset_) { auto pathIterator = reinterpret_cast(pathIterator_); Point pointsData[4]; Verb verb = pathIterator->next(pointsData); if (verb != Verb::Done && verb != Verb::Close) { - jfloat* points = env->GetFloatArrayElements(points_, nullptr); + auto* pointsArray = static_cast(env->GetPrimitiveArrayCritical(points_, nullptr)); + jfloat* points = pointsArray + offset_; switch (verb) { case Verb::Cubic: case Verb::Conic: // to copy the weight @@ -133,7 +135,7 @@ static jint pathIteratorNext(JNIEnv* env, jobject, jlong pathIterator_, jfloatAr break; #pragma clang diagnostic pop } - env->ReleaseFloatArrayElements(points_, points, 0); + env->ReleasePrimitiveArrayCritical(points_, pointsArray, 0); } return static_cast(verb); @@ -177,7 +179,7 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) { }, { (char*) "internalPathIteratorNext", - (char*) "(J[F)I", + (char*) "(J[FI)I", reinterpret_cast(pathIteratorNext) }, { diff --git a/pathway/src/main/java/dev/romainguy/graphics/path/Paths.kt b/pathway/src/main/java/dev/romainguy/graphics/path/Paths.kt index 8eb26ac..09f56cf 100644 --- a/pathway/src/main/java/dev/romainguy/graphics/path/Paths.kt +++ b/pathway/src/main/java/dev/romainguy/graphics/path/Paths.kt @@ -175,7 +175,11 @@ class PathIterator( @JvmStatic @Suppress("KotlinJniMissingFunction") - external fun internalPathIteratorNext(internalPathIterator: Long, points: FloatArray): Int + external fun internalPathIteratorNext( + internalPathIterator: Long, + points: FloatArray, + offset: Int + ): Int @JvmStatic @Suppress("KotlinJniMissingFunction") @@ -228,11 +232,13 @@ class PathIterator( * - [Done][PathSegment.Type.Done]: 0 pair * This method does not allocate any memory. * - * @param points *Must* be a [FloatArray] of size 8, throws an [IllegalStateException] otherwise. + * @param points A [FloatArray] large enough to hold 8 floats starting at [offset], + * throws an [IllegalStateException] otherwise. + * @param offset Offset in [points] where to store the result */ - fun next(points: FloatArray): PathSegment.Type { - check(points.size >= 8) { "The points array must contain at least 8 floats" } - val typeValue = internalPathIteratorNext(internalPathIterator, points) + fun next(points: FloatArray, offset: Int = 0): PathSegment.Type { + check(points.size - offset >= 8) { "The points array must contain at least 8 floats" } + val typeValue = internalPathIteratorNext(internalPathIterator, points, offset) return pathSegmentTypes[typeValue] } @@ -242,7 +248,7 @@ class PathIterator( * [next] method. */ override fun next(): PathSegment { - val typeValue = internalPathIteratorNext(internalPathIterator, pointsData) + val typeValue = internalPathIteratorNext(internalPathIterator, pointsData, 0) val type = pathSegmentTypes[typeValue] if (type == PathSegment.Type.Done) return DoneSegment