diff --git a/.idea/androidTestResultsUserPreferences.xml b/.idea/androidTestResultsUserPreferences.xml
index 9773c22..25fa9ac 100644
--- a/.idea/androidTestResultsUserPreferences.xml
+++ b/.idea/androidTestResultsUserPreferences.xml
@@ -52,6 +52,7 @@
+
diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml
index 2ac6b25..678d26c 100644
--- a/.idea/deploymentTargetDropDown.xml
+++ b/.idea/deploymentTargetDropDown.xml
@@ -1,17 +1,23 @@
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
index fdf8d99..ae3f30a 100644
--- a/.idea/kotlinc.xml
+++ b/.idea/kotlinc.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index b4b4525..82807bf 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,4 +1,3 @@
-
diff --git a/README.md b/README.md
index c087b28..5fbe850 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@ repositories {
}
dependencies {
- implementation 'dev.romainguy:pathway:0.15.0'
+ implementation 'dev.romainguy:pathway:0.16.0'
}
```
diff --git a/build.gradle b/build.gradle
index 1f6fd30..8ccd3b3 100644
--- a/build.gradle
+++ b/build.gradle
@@ -5,9 +5,9 @@ buildscript {
}
dependencies {
- classpath "com.android.tools.build:gradle:8.0.2"
+ classpath "com.android.tools.build:gradle:8.2.0"
classpath "com.vanniktech:gradle-maven-publish-plugin:0.25.3"
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0"
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.21"
classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.8.20"
}
@@ -29,5 +29,6 @@ buildscript {
"-fdata-sections",
"-Wl,--gc-sections",
"-Wl,-Bsymbolic-functions",
+ "-nostdlib++"
]
}
diff --git a/gradle.properties b/gradle.properties
index 5e9777a..caf023d 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,5 +1,5 @@
GROUP=dev.romainguy
-VERSION_NAME=0.15.0
+VERSION_NAME=0.16.0
SONATYPE_HOST=S01
RELEASE_SIGNING_ENABLED=true
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index c2a0986..f446e80 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Wed Jul 12 13:05:07 PDT 2023
+#Tue Dec 12 17:22:13 PST 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/pathway/build.gradle b/pathway/build.gradle
index b5964f9..413cddc 100644
--- a/pathway/build.gradle
+++ b/pathway/build.gradle
@@ -23,6 +23,8 @@ android {
}
}
+ consumerProguardFiles "proguard-rules.pro"
+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
diff --git a/pathway/proguard-rules.pro b/pathway/proguard-rules.pro
new file mode 100644
index 0000000..34187b3
--- /dev/null
+++ b/pathway/proguard-rules.pro
@@ -0,0 +1,3 @@
+-keepclasseswithmembernames,includedescriptorclasses class dev.romainguy.graphics.path.** {
+ native ;
+}
diff --git a/pathway/src/main/cpp/Conic.cpp b/pathway/src/main/cpp/Conic.cpp
index f6e28f2..56bb9b7 100644
--- a/pathway/src/main/cpp/Conic.cpp
+++ b/pathway/src/main/cpp/Conic.cpp
@@ -26,8 +26,6 @@
using namespace filament::math;
-constexpr int kMaxConicToQuadCount = 5;
-
constexpr bool isFinite(const Point points[], int count) noexcept {
return isFinite(&points[0].x, count << 1);
}
@@ -53,17 +51,9 @@ const Point* ConicConverter::toQuadratics(
Conic conic(points[0], points[1], points[2], weight);
int count = conic.computeQuadraticCount(tolerance);
- mQuadraticCount = 1 << count;
-
- int newSize = 1 + 2 * mQuadraticCount;
- if (newSize > mStorage.size()) {
- mStorage.resize(newSize);
- }
-
- Point* data = mStorage.data();
- mQuadraticCount = conic.splitIntoQuadratics(data, count);
+ mQuadraticCount = conic.splitIntoQuadratics(mStorage, count);
- return data;
+ return mStorage;
}
int Conic::computeQuadraticCount(float tolerance) const noexcept {
diff --git a/pathway/src/main/cpp/Conic.h b/pathway/src/main/cpp/Conic.h
index eeebf3f..0d4a95a 100644
--- a/pathway/src/main/cpp/Conic.h
+++ b/pathway/src/main/cpp/Conic.h
@@ -19,9 +19,8 @@
#include "Path.h"
-#include
-
-constexpr int kDefaultQuadraticCount = 8;
+constexpr int kMaxConicToQuadCount = 5;
+constexpr int kMaxQuadraticCount = 1 << kMaxConicToQuadCount;
class ConicConverter {
public:
@@ -32,12 +31,12 @@ class ConicConverter {
int quadraticCount() const noexcept { return mQuadraticCount; }
const Point* quadratics() const noexcept {
- return mQuadraticCount > 0 ? mStorage.data() : nullptr;
+ return mQuadraticCount > 0 ? mStorage : nullptr;
}
private:
int mQuadraticCount = 0;
- std::vector mStorage{1 + 2 * kDefaultQuadraticCount};
+ Point mStorage[1 + 2 * kMaxQuadraticCount];
};
struct Conic {
diff --git a/pathway/src/main/cpp/pathway.cpp b/pathway/src/main/cpp/pathway.cpp
index cb9f617..7700d15 100644
--- a/pathway/src/main/cpp/pathway.cpp
+++ b/pathway/src/main/cpp/pathway.cpp
@@ -20,6 +20,9 @@
#include
+#include
+#include
+
#define JNI_CLASS_NAME "dev/romainguy/graphics/path/Paths"
struct {
@@ -77,14 +80,17 @@ static jlong createPathIterator(JNIEnv* env, jclass,
direction = PathIterator::VerbDirection::Backward;
}
- return jlong(new PathIterator(
+ PathIterator* iterator = static_cast(malloc(sizeof(PathIterator)));
+ return jlong(new(iterator) PathIterator(
points, verbs, conicWeights, count, direction,
PathIterator::ConicEvaluation(conicEvaluation_), tolerance_
));
}
static void destroyPathIterator(JNIEnv*, jclass, jlong pathIterator_) {
- delete reinterpret_cast(pathIterator_);
+ PathIterator* iterator = reinterpret_cast(pathIterator_);
+ iterator->~PathIterator();
+ free(iterator);
}
static jboolean pathIteratorHasNext(JNIEnv*, jclass, jlong pathIterator_) {
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 b0a3bea..d9022dd 100644
--- a/pathway/src/main/java/dev/romainguy/graphics/path/Paths.kt
+++ b/pathway/src/main/java/dev/romainguy/graphics/path/Paths.kt
@@ -103,9 +103,7 @@ class PathSegment internal constructor(val type: Type, val points: Array
if (type != other.type) return false
if (!points.contentEquals(other.points)) return false
- if (weight != other.weight) return false
-
- return true
+ return weight == other.weight
}
override fun hashCode(): Int {
@@ -130,11 +128,6 @@ val DoneSegment = PathSegment(PathSegment.Type.Done, emptyArray(), 0.0f)
*/
val CloseSegment = PathSegment(PathSegment.Type.Close, emptyArray(), 0.0f)
-/**
- * Cache of [PathSegment.Type] values to avoid internal allocation on each use.
- */
-private val pathSegmentTypes = PathSegment.Type.values()
-
/**
* Creates a new [PathIterator] for this [path][android.graphics.Path] that evaluates
* conics as quadratics. To preserve conics, use [Path.iterator].
@@ -211,7 +204,7 @@ class PathIterator(
* Returns the type of the current segment in the iteration, or [Done][PathSegment.Type.Done]
* if the iteration is finished.
*/
- fun peek() = pathSegmentTypes[internalPathIteratorPeek(internalPathIterator)]
+ fun peek() = PathSegment.Type.entries[internalPathIteratorPeek(internalPathIterator)]
/**
* Returns the [type][PathSegment.Type] of the next [path segment][PathSegment] in the iteration
@@ -236,7 +229,7 @@ class PathIterator(
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]
+ return PathSegment.Type.entries[typeValue]
}
/**
@@ -246,7 +239,7 @@ class PathIterator(
*/
override fun next(): PathSegment {
val typeValue = internalPathIteratorNext(internalPathIterator, pointsData, 0)
- val type = pathSegmentTypes[typeValue]
+ val type = PathSegment.Type.entries[typeValue]
if (type == PathSegment.Type.Done) return DoneSegment
if (type == PathSegment.Type.Close) return CloseSegment
@@ -255,12 +248,14 @@ class PathIterator(
PathSegment.Type.Move -> {
arrayOf(PointF(pointsData[0], pointsData[1]))
}
+
PathSegment.Type.Line -> {
arrayOf(
PointF(pointsData[0], pointsData[1]),
PointF(pointsData[2], pointsData[3])
)
}
+
PathSegment.Type.Quadratic,
PathSegment.Type.Conic -> {
arrayOf(
@@ -269,6 +264,7 @@ class PathIterator(
PointF(pointsData[4], pointsData[5])
)
}
+
PathSegment.Type.Cubic -> {
arrayOf(
PointF(pointsData[0], pointsData[1]),
@@ -291,29 +287,22 @@ class PathIterator(
}
}
-@Suppress("KotlinJniMissingFunction")
private external fun createInternalPathIterator(
path: Path, conicEvaluation: Int, tolerance: Float
): Long
-@Suppress("KotlinJniMissingFunction")
private external fun destroyInternalPathIterator(internalPathIterator: Long)
-@Suppress("KotlinJniMissingFunction")
private external fun internalPathIteratorHasNext(internalPathIterator: Long): Boolean
-@Suppress("KotlinJniMissingFunction")
private external fun internalPathIteratorNext(
internalPathIterator: Long,
points: FloatArray,
offset: Int
): Int
-@Suppress("KotlinJniMissingFunction")
private external fun internalPathIteratorPeek(internalPathIterator: Long): Int
-@Suppress("KotlinJniMissingFunction")
private external fun internalPathIteratorRawSize(internalPathIterator: Long): Int
-@Suppress("KotlinJniMissingFunction")
private external fun internalPathIteratorSize(internalPathIterator: Long): Int