Skip to content

Commit

Permalink
2x speed up when iterating over paths
Browse files Browse the repository at this point in the history
  • Loading branch information
romainguy committed Feb 12, 2024
1 parent 75df15c commit 9a3ffdd
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 46 deletions.
1 change: 1 addition & 0 deletions .idea/androidTestResultsUserPreferences.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ repositories {
}
dependencies {
implementation 'dev.romainguy:pathway:0.17.0'
implementation 'dev.romainguy:pathway:0.18.0'
}
```

Expand Down Expand Up @@ -69,7 +69,7 @@ properly honor the path's fill type.
## Iterating over a Path

> [!IMPORTANT]
> It is preferred to use the new androidx
> Prefer the new androidx
> [graphics-path library](https://developer.android.com/jetpack/androidx/releases/graphic) to
> iterate over paths
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ buildscript {
}

dependencies {
classpath "com.android.tools.build:gradle:8.2.0"
classpath 'com.android.tools.build:gradle:8.2.2'
classpath "com.vanniktech:gradle-maven-publish-plugin:0.25.3"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.21"
classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.8.20"
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
GROUP=dev.romainguy
VERSION_NAME=0.17.0
VERSION_NAME=0.18.0

SONATYPE_HOST=S01
RELEASE_SIGNING_ENABLED=true
Expand Down
6 changes: 5 additions & 1 deletion pathway/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,16 @@ android {
namespace "dev.romainguy.graphics.path"

compileSdk 34
ndkVersion '25.1.8937393'
ndkVersion '26.2.11394342'

defaultConfig {
minSdk 21
targetSdk 34

ndk {
//noinspection ChromeOsAbiSupport
abiFilters 'arm64-v8a'
}
externalNativeBuild {
cmake {
cppFlags.addAll(rootProject.ext.cppFlags)
Expand Down
125 changes: 84 additions & 41 deletions pathway/src/main/cpp/pathway.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,47 +139,90 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) {
jclass pathsClass = env->FindClass(JNI_CLASS_NAME);
if (pathsClass == nullptr) return JNI_ERR;

static const JNINativeMethod methods[] = {
{
(char*) "createInternalPathIterator",
(char*) "(Landroid/graphics/Path;IF)J",
reinterpret_cast<void*>(createPathIterator)
},
{
(char*) "destroyInternalPathIterator",
(char*) "(J)V",
reinterpret_cast<void*>(destroyPathIterator)
},
{
(char*) "internalPathIteratorHasNext",
(char*) "(J)Z",
reinterpret_cast<void*>(pathIteratorHasNext)
},
{
(char*) "internalPathIteratorNext",
(char*) "(J[FI)I",
reinterpret_cast<void*>(pathIteratorNext)
},
{
(char*) "internalPathIteratorPeek",
(char*) "(J)I",
reinterpret_cast<void*>(pathIteratorPeek)
},
{
(char*) "internalPathIteratorRawSize",
(char*) "(J)I",
reinterpret_cast<void*>(pathIteratorRawSize)
},
{
(char*) "internalPathIteratorSize",
(char*) "(J)I",
reinterpret_cast<void*>(pathIteratorSize)
},
};

int result = env->RegisterNatives(
pathsClass, methods, sizeof(methods) / sizeof(JNINativeMethod)
);
jint result;

const uint32_t apiLevel = android_get_device_api_level();
if (apiLevel >= 26) { // Android 8.0
static const JNINativeMethod methods[] = {
{
(char *) "createInternalPathIterator",
(char *) "(Landroid/graphics/Path;IF)J",
reinterpret_cast<void *>(createPathIterator)
},
{
(char *) "destroyInternalPathIterator",
(char *) "(J)V",
reinterpret_cast<void *>(destroyPathIterator)
},
{
(char *) "internalPathIteratorHasNext",
(char *) "(J)Z",
reinterpret_cast<void *>(pathIteratorHasNext)
},
{
(char *) "internalPathIteratorNext",
(char *) "(J[FI)I",
reinterpret_cast<void *>(pathIteratorNext)
},
{
(char *) "internalPathIteratorPeek",
(char *) "(J)I",
reinterpret_cast<void *>(pathIteratorPeek)
},
{
(char *) "internalPathIteratorRawSize",
(char *) "(J)I",
reinterpret_cast<void *>(pathIteratorRawSize)
},
{
(char *) "internalPathIteratorSize",
(char *) "(J)I",
reinterpret_cast<void *>(pathIteratorSize)
},
};

result = env->RegisterNatives(
pathsClass, methods, sizeof(methods) / sizeof(JNINativeMethod)
);
} else {
static const JNINativeMethod methods[] = {
{
(char *) "createInternalPathIterator",
(char *) "(Landroid/graphics/Path;IF)J",
reinterpret_cast<void *>(createPathIterator)
},
{
(char *) "destroyInternalPathIterator",
(char *) "!(J)V",
reinterpret_cast<void *>(destroyPathIterator)
},
{
(char *) "internalPathIteratorHasNext",
(char *) "!(J)Z",
reinterpret_cast<void *>(pathIteratorHasNext)
},
{
(char *) "internalPathIteratorNext",
(char *) "!(J[FI)I",
reinterpret_cast<void *>(pathIteratorNext)
},
{
(char *) "internalPathIteratorPeek",
(char *) "!(J)I",
reinterpret_cast<void *>(pathIteratorPeek)
},
{
(char *) "internalPathIteratorRawSize",
(char *) "!(J)I",
reinterpret_cast<void *>(pathIteratorRawSize)
},
{
(char *) "internalPathIteratorSize",
(char *) "!(J)I",
reinterpret_cast<void *>(pathIteratorSize)
},
};
}
if (result != JNI_OK) return result;

env->DeleteLocalRef(pathsClass);
Expand Down
8 changes: 8 additions & 0 deletions pathway/src/main/java/dev/romainguy/graphics/path/Paths.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package dev.romainguy.graphics.path

import android.graphics.Path
import android.graphics.PointF
import dalvik.annotation.optimization.FastNative

/**
* A path segment represents a curve (line, cubic, quadratic or conic) or a command inside
Expand Down Expand Up @@ -211,6 +212,7 @@ class PathIterator(
* and fills [points] with the points specific to the segment type. Each pair of floats in
* the [points] array represents a point for the given segment. The number of pairs of floats
* depends on the [PathSegment.Type]:
*
* - [Move][PathSegment.Type.Move]: 1 pair (indices 0 to 1)
* - [Move][PathSegment.Type.Line]: 2 pairs (indices 0 to 3)
* - [Move][PathSegment.Type.Quadratic]: 3 pairs (indices 0 to 5)
Expand Down Expand Up @@ -291,18 +293,24 @@ private external fun createInternalPathIterator(
path: Path, conicEvaluation: Int, tolerance: Float
): Long

@FastNative
private external fun destroyInternalPathIterator(internalPathIterator: Long)

@FastNative
private external fun internalPathIteratorHasNext(internalPathIterator: Long): Boolean

@FastNative
private external fun internalPathIteratorNext(
internalPathIterator: Long,
points: FloatArray,
offset: Int
): Int

@FastNative
private external fun internalPathIteratorPeek(internalPathIterator: Long): Int

@FastNative
private external fun internalPathIteratorRawSize(internalPathIterator: Long): Int

@FastNative
private external fun internalPathIteratorSize(internalPathIterator: Long): Int

0 comments on commit 9a3ffdd

Please sign in to comment.