Unverified Commit 9faacd53 authored by Shagen Ogandzhanian's avatar Shagen Ogandzhanian Committed by GitHub

Commonize PathMeasure (#250)

parent 7b0af915
...@@ -37,91 +37,80 @@ SKIKO_EXPORT KFloat org_jetbrains_skia_PathMeasure__1nGetLength ...@@ -37,91 +37,80 @@ SKIKO_EXPORT KFloat org_jetbrains_skia_PathMeasure__1nGetLength
} }
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_PathMeasure__1nGetPosition SKIKO_EXPORT KBoolean org_jetbrains_skia_PathMeasure__1nGetPosition
(KNativePointer ptr, KFloat distance) { (KNativePointer ptr, KFloat distance, KFloat* data) {
TODO("implement org_jetbrains_skia_PathMeasure__1nGetPosition");
}
#if 0
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_PathMeasure__1nGetPosition
(KNativePointer ptr, KFloat distance) {
SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>((ptr)); SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>((ptr));
SkPoint position; SkPoint position;
if (instance->getPosTan(distance, &position, nullptr)) if (instance->getPosTan(distance, &position, nullptr)) {
return skija::Point::fromSkPoint(env, position); data[0] = position.fX;
else data[1] = position.fY;
return nullptr; return true;
} }
#endif
return false;
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_PathMeasure__1nGetTangent
(KNativePointer ptr, KFloat distance) {
TODO("implement org_jetbrains_skia_PathMeasure__1nGetTangent");
} }
#if 0 SKIKO_EXPORT KBoolean org_jetbrains_skia_PathMeasure__1nGetTangent
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_PathMeasure__1nGetTangent (KNativePointer ptr, KFloat distance, KFloat* data) {
(KNativePointer ptr, KFloat distance) {
SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>((ptr)); SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>((ptr));
SkVector tangent; SkVector tangent;
if (instance->getPosTan(distance, nullptr, &tangent))
return skija::Point::fromSkPoint(env, tangent);
else
return nullptr;
}
#endif
if (instance->getPosTan(distance, nullptr, &tangent)) {
data[0] = tangent.fX;
data[1] = tangent.fY;
return true;
}
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_PathMeasure__1nGetRSXform return false;
(KNativePointer ptr, KFloat distance) {
TODO("implement org_jetbrains_skia_PathMeasure__1nGetRSXform");
} }
#if 0 SKIKO_EXPORT KBoolean org_jetbrains_skia_PathMeasure__1nGetRSXform
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_PathMeasure__1nGetRSXform (KNativePointer ptr, KFloat distance, KFloat* data) {
(KNativePointer ptr, KFloat distance) {
SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>((ptr)); SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>((ptr));
SkPoint position; SkPoint position;
SkVector tangent; SkVector tangent;
if (instance->getPosTan(distance, &position, &tangent)) if (instance->getPosTan(distance, &position, &tangent)) {
return env->NewObject(skija::RSXform::cls, skija::RSXform::ctor, tangent.fX, tangent.fY, position.fX, position.fY); data[0] = tangent.fX;
else data[1] = tangent.fY;
return nullptr; data[2] = position.fX;
} data[3] = position.fY;
#endif return true;
}
return false;
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_PathMeasure__1nGetMatrix
(KNativePointer ptr, KFloat distance, KBoolean getPosition, KBoolean getTangent) {
TODO("implement org_jetbrains_skia_PathMeasure__1nGetMatrix");
} }
#if 0 SKIKO_EXPORT KBoolean org_jetbrains_skia_PathMeasure__1nGetMatrix
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_PathMeasure__1nGetMatrix (KNativePointer ptr, KFloat distance, KBoolean getPosition, KBoolean getTangent, KFloat* data) {
(KNativePointer ptr, KFloat distance, KBoolean getPosition, KBoolean getTangent) { SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>((ptr));
SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>((ptr)); SkMatrix matrix;
SkMatrix matrix; int flags = 0;
int flags = 0;
if (getPosition)
if (getPosition) flags |= SkPathMeasure::MatrixFlags::kGetPosition_MatrixFlag;
flags |= SkPathMeasure::MatrixFlags::kGetPosition_MatrixFlag; if (getTangent)
if (getTangent) flags |= SkPathMeasure::MatrixFlags::kGetTangent_MatrixFlag;
flags |= SkPathMeasure::MatrixFlags::kGetTangent_MatrixFlag;
if (instance->getMatrix(distance, &matrix, static_cast<SkPathMeasure::MatrixFlags>(flags))) {
if (instance->getMatrix(distance, &matrix, static_cast<SkPathMeasure::MatrixFlags>(flags))) { float* f;
std::vector<float> floats(9); matrix.get9(f);
matrix.get9(floats.data());
return javaFloatArray(env, floats); data[0] = data[0];
} else data[1] = data[1];
return nullptr; data[2] = data[2];
data[3] = data[3];
data[4] = data[4];
data[5] = data[5];
data[6] = data[6];
data[7] = data[7];
data[8] = data[8];
return true;
}
return false;
} }
#endif
SKIKO_EXPORT KBoolean org_jetbrains_skia_PathMeasure__1nGetSegment SKIKO_EXPORT KBoolean org_jetbrains_skia_PathMeasure__1nGetSegment
(KNativePointer ptr, KFloat startD, KFloat endD, KNativePointer dstPtr, KBoolean startWithMoveTo) { (KNativePointer ptr, KFloat startD, KFloat endD, KNativePointer dstPtr, KBoolean startWithMoveTo) {
SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>((ptr)); SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>((ptr));
......
package org.jetbrains.skia package org.jetbrains.skia
import org.jetbrains.skia.impl.InteropPointer
import org.jetbrains.skia.impl.Library.Companion.staticLoad import org.jetbrains.skia.impl.Library.Companion.staticLoad
import org.jetbrains.skia.impl.Managed import org.jetbrains.skia.impl.Managed
import org.jetbrains.skia.impl.Stats
import org.jetbrains.skia.impl.reachabilityBarrier
import org.jetbrains.skia.impl.NativePointer import org.jetbrains.skia.impl.NativePointer
import org.jetbrains.skia.impl.Stats
import org.jetbrains.skia.impl.getPtr import org.jetbrains.skia.impl.getPtr
import org.jetbrains.skia.impl.interopScope
import org.jetbrains.skia.impl.reachabilityBarrier
class PathMeasure internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHolder.PTR) { class PathMeasure internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHolder.PTR) {
companion object { companion object {
...@@ -78,7 +80,9 @@ class PathMeasure internal constructor(ptr: NativePointer) : Managed(ptr, _Final ...@@ -78,7 +80,9 @@ class PathMeasure internal constructor(ptr: NativePointer) : Managed(ptr, _Final
fun getPosition(distance: Float): Point? { fun getPosition(distance: Float): Point? {
return try { return try {
Stats.onNativeCall() Stats.onNativeCall()
_nGetPosition(_ptr, distance) withNullableResult(FloatArray(2)) { _nGetPosition(_ptr, distance, it) }?.let { points ->
Point(points[0], points[1])
}
} finally { } finally {
reachabilityBarrier(this) reachabilityBarrier(this)
} }
...@@ -93,7 +97,9 @@ class PathMeasure internal constructor(ptr: NativePointer) : Managed(ptr, _Final ...@@ -93,7 +97,9 @@ class PathMeasure internal constructor(ptr: NativePointer) : Managed(ptr, _Final
fun getTangent(distance: Float): Point? { fun getTangent(distance: Float): Point? {
return try { return try {
Stats.onNativeCall() Stats.onNativeCall()
_nGetTangent(_ptr, distance) withNullableResult(FloatArray(2)) { _nGetTangent(_ptr, distance, it) }?.let { points ->
Point(points[0], points[1])
}
} finally { } finally {
reachabilityBarrier(this) reachabilityBarrier(this)
} }
...@@ -108,7 +114,16 @@ class PathMeasure internal constructor(ptr: NativePointer) : Managed(ptr, _Final ...@@ -108,7 +114,16 @@ class PathMeasure internal constructor(ptr: NativePointer) : Managed(ptr, _Final
fun getRSXform(distance: Float): RSXform? { fun getRSXform(distance: Float): RSXform? {
return try { return try {
Stats.onNativeCall() Stats.onNativeCall()
_nGetRSXform(_ptr, distance) withNullableResult(FloatArray(4)) {
_nGetRSXform(_ptr, distance, it)
}?.let { data ->
RSXform(
data[0],
data[1],
data[2],
data[3]
)
}
} finally { } finally {
reachabilityBarrier(this) reachabilityBarrier(this)
} }
...@@ -123,8 +138,21 @@ class PathMeasure internal constructor(ptr: NativePointer) : Managed(ptr, _Final ...@@ -123,8 +138,21 @@ class PathMeasure internal constructor(ptr: NativePointer) : Managed(ptr, _Final
fun getMatrix(distance: Float, getPosition: Boolean, getTangent: Boolean): Matrix33? { fun getMatrix(distance: Float, getPosition: Boolean, getTangent: Boolean): Matrix33? {
return try { return try {
Stats.onNativeCall() Stats.onNativeCall()
val mat = _nGetMatrix(_ptr, distance, getPosition, getTangent) withNullableResult(FloatArray(9)) {
mat?.let { Matrix33(*it.copyOf()) } _nGetMatrix(_ptr, distance, getPosition, getTangent, it)
}?.let { data ->
Matrix33(
data[0],
data[1],
data[2],
data[3],
data[4],
data[5],
data[6],
data[7],
data[8]
)
}
} finally { } finally {
reachabilityBarrier(this) reachabilityBarrier(this)
} }
...@@ -182,6 +210,17 @@ class PathMeasure internal constructor(ptr: NativePointer) : Managed(ptr, _Final ...@@ -182,6 +210,17 @@ class PathMeasure internal constructor(ptr: NativePointer) : Managed(ptr, _Final
} }
} }
private inline fun withNullableResult(result: FloatArray, block: (InteropPointer) -> Boolean): FloatArray? = interopScope {
val handle = toInterop(result)
val blockResult = block(handle)
if (blockResult) {
handle.fromInterop(result)
result
} else {
null
}
}
@ExternalSymbolName("org_jetbrains_skia_PathMeasure__1nGetFinalizer") @ExternalSymbolName("org_jetbrains_skia_PathMeasure__1nGetFinalizer")
private external fun PathMeasure_nGetFinalizer(): NativePointer private external fun PathMeasure_nGetFinalizer(): NativePointer
...@@ -198,16 +237,22 @@ private external fun _nSetPath(ptr: NativePointer, pathPtr: NativePointer, force ...@@ -198,16 +237,22 @@ private external fun _nSetPath(ptr: NativePointer, pathPtr: NativePointer, force
private external fun _nGetLength(ptr: NativePointer): Float private external fun _nGetLength(ptr: NativePointer): Float
@ExternalSymbolName("org_jetbrains_skia_PathMeasure__1nGetPosition") @ExternalSymbolName("org_jetbrains_skia_PathMeasure__1nGetPosition")
private external fun _nGetPosition(ptr: NativePointer, distance: Float): Point? private external fun _nGetPosition(ptr: NativePointer, distance: Float, data: InteropPointer): Boolean
@ExternalSymbolName("org_jetbrains_skia_PathMeasure__1nGetTangent") @ExternalSymbolName("org_jetbrains_skia_PathMeasure__1nGetTangent")
private external fun _nGetTangent(ptr: NativePointer, distance: Float): Point? private external fun _nGetTangent(ptr: NativePointer, distance: Float, data: InteropPointer): Boolean
@ExternalSymbolName("org_jetbrains_skia_PathMeasure__1nGetRSXform") @ExternalSymbolName("org_jetbrains_skia_PathMeasure__1nGetRSXform")
private external fun _nGetRSXform(ptr: NativePointer, distance: Float): RSXform? private external fun _nGetRSXform(ptr: NativePointer, distance: Float, data: InteropPointer): Boolean
@ExternalSymbolName("org_jetbrains_skia_PathMeasure__1nGetMatrix") @ExternalSymbolName("org_jetbrains_skia_PathMeasure__1nGetMatrix")
private external fun _nGetMatrix(ptr: NativePointer, distance: Float, getPosition: Boolean, getTangent: Boolean): FloatArray? private external fun _nGetMatrix(
ptr: NativePointer,
distance: Float,
getPosition: Boolean,
getTangent: Boolean,
data: InteropPointer
): Boolean
@ExternalSymbolName("org_jetbrains_skia_PathMeasure__1nGetSegment") @ExternalSymbolName("org_jetbrains_skia_PathMeasure__1nGetSegment")
private external fun _nGetSegment( private external fun _nGetSegment(
......
package org.jetbrains.skiko package org.jetbrains.skia
import org.jetbrains.skia.Matrix33
import org.jetbrains.skia.Path
import org.jetbrains.skia.PathMeasure
import org.jetbrains.skia.Point
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import org.jetbrains.skia.tests.assertCloseEnough import org.jetbrains.skia.tests.assertCloseEnough
import org.jetbrains.skia.impl.use
import org.jetbrains.skiko.tests.runTest
import kotlin.test.Ignore
class PathMeasureTest { class PathMeasureTest {
@Test
fun getRSXformTest() = runTest {
Path().moveTo(0f, 0f).lineTo(40f, 0f).moveTo(0f, 40f).lineTo(10f, 50f).use { path ->
PathMeasure(path, false).use { measure ->
assertEquals(RSXform(1.0f, 0f, 0.5f, 0f), measure.getRSXform(0.5f))
}
}
}
@Test
fun getTangent() = runTest {
Path().moveTo(0f, 0f).lineTo(20f, 0f).moveTo(0f, 40f).lineTo(30f, 50f).use { path ->
PathMeasure(path, false).use { measure ->
assertEquals(Point(1f, 0f), measure.getTangent(2f))
}
}
}
@Test
fun getPosition() = runTest {
Path().moveTo(0f, 10f).lineTo(20f, 0f).moveTo(0f, 40f).lineTo(30f, 50f).use { path ->
PathMeasure(path, false).use { measure ->
assertCloseEnough(Point(0.89442724f, 9.552787f), measure.getPosition(1f))
}
}
}
@Test @Test
fun pathMeasureTest() { @Ignore
fun pathMeasureTest() = runTest {
Path().moveTo(0f, 0f).lineTo(40f, 0f).moveTo(0f, 40f).lineTo(10f, 50f).use { path -> Path().moveTo(0f, 0f).lineTo(40f, 0f).moveTo(0f, 40f).lineTo(10f, 50f).use { path ->
PathMeasure(path, false).use { measure -> PathMeasure(path, false).use { measure ->
Path().lineTo(10f, 10f).use { path2 -> Path().lineTo(10f, 10f).use { path2 ->
......
...@@ -7,7 +7,6 @@ import kotlin.test.assertFalse ...@@ -7,7 +7,6 @@ import kotlin.test.assertFalse
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertFailsWith import kotlin.test.assertFailsWith
import org.jetbrains.skiko.tests.runTest import org.jetbrains.skiko.tests.runTest
import org.jetbrains.skia.tests.assertCloseEnough
class PathTests { class PathTests {
......
...@@ -34,39 +34,50 @@ extern "C" JNIEXPORT jfloat JNICALL Java_org_jetbrains_skia_PathMeasureKt__1nGet ...@@ -34,39 +34,50 @@ extern "C" JNIEXPORT jfloat JNICALL Java_org_jetbrains_skia_PathMeasureKt__1nGet
return instance->getLength(); return instance->getLength();
} }
extern "C" JNIEXPORT jobject JNICALL Java_org_jetbrains_skia_PathMeasureKt__1nGetPosition extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathMeasureKt__1nGetPosition
(JNIEnv* env, jclass jclass, jlong ptr, jfloat distance) { (JNIEnv* env, jclass jclass, jlong ptr, jfloat distance, jfloatArray data) {
SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>(static_cast<uintptr_t>(ptr)); SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>(static_cast<uintptr_t>(ptr));
SkPoint position; SkPoint position;
if (instance->getPosTan(distance, &position, nullptr)) if (instance->getPosTan(distance, &position, nullptr)) {
return skija::Point::fromSkPoint(env, position); jfloat d[2] = { position.fX, position.fY };
else env->SetFloatArrayRegion(data, 0, 2, d);
return nullptr; return true;
}
return false;
} }
extern "C" JNIEXPORT jobject JNICALL Java_org_jetbrains_skia_PathMeasureKt__1nGetTangent extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathMeasureKt__1nGetTangent
(JNIEnv* env, jclass jclass, jlong ptr, jfloat distance) { (JNIEnv* env, jclass jclass, jlong ptr, jfloat distance, jfloatArray data) {
SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>(static_cast<uintptr_t>(ptr)); SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>(static_cast<uintptr_t>(ptr));
SkVector tangent; SkVector tangent;
if (instance->getPosTan(distance, nullptr, &tangent)) if (instance->getPosTan(distance, nullptr, &tangent)) {
return skija::Point::fromSkPoint(env, tangent); jfloat d[2] = { tangent.fX, tangent.fY };
else env->SetFloatArrayRegion(data, 0, 2, d);
return nullptr; return true;
}
return false;
} }
extern "C" JNIEXPORT jobject JNICALL Java_org_jetbrains_skia_PathMeasureKt__1nGetRSXform extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathMeasureKt__1nGetRSXform
(JNIEnv* env, jclass jclass, jlong ptr, jfloat distance) { (JNIEnv* env, jclass jclass, jlong ptr, jfloat distance, jfloatArray data) {
SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>(static_cast<uintptr_t>(ptr)); SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>(static_cast<uintptr_t>(ptr));
SkPoint position; SkPoint position;
SkVector tangent; SkVector tangent;
if (instance->getPosTan(distance, &position, &tangent)) if (instance->getPosTan(distance, &position, &tangent)) {
return env->NewObject(skija::RSXform::cls, skija::RSXform::ctor, tangent.fX, tangent.fY, position.fX, position.fY); jfloat d[4] = {
else tangent.fX, tangent.fY, position.fX, position.fY
return nullptr; };
env->SetFloatArrayRegion(data, 0, 4, d);
return true;
}
return false;
} }
extern "C" JNIEXPORT jobject JNICALL Java_org_jetbrains_skia_PathMeasureKt__1nGetMatrix extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathMeasureKt__1nGetMatrix
(JNIEnv* env, jclass jclass, jlong ptr, jfloat distance, jboolean getPosition, jboolean getTangent) { (JNIEnv* env, jclass jclass, jlong ptr, jfloat distance, jboolean getPosition, jboolean getTangent, jfloatArray data) {
SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>(static_cast<uintptr_t>(ptr)); SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>(static_cast<uintptr_t>(ptr));
SkMatrix matrix; SkMatrix matrix;
int flags = 0; int flags = 0;
...@@ -77,11 +88,27 @@ extern "C" JNIEXPORT jobject JNICALL Java_org_jetbrains_skia_PathMeasureKt__1nGe ...@@ -77,11 +88,27 @@ extern "C" JNIEXPORT jobject JNICALL Java_org_jetbrains_skia_PathMeasureKt__1nGe
flags |= SkPathMeasure::MatrixFlags::kGetTangent_MatrixFlag; flags |= SkPathMeasure::MatrixFlags::kGetTangent_MatrixFlag;
if (instance->getMatrix(distance, &matrix, static_cast<SkPathMeasure::MatrixFlags>(flags))) { if (instance->getMatrix(distance, &matrix, static_cast<SkPathMeasure::MatrixFlags>(flags))) {
std::vector<float> floats(9); float* floats;
matrix.get9(floats.data()); matrix.get9(floats);
return javaFloatArray(env, floats);
} else jfloat d[9] = {
return nullptr; floats[0],
floats[1],
floats[2],
floats[3],
floats[4],
floats[5],
floats[6],
floats[7],
floats[8]
};
env->SetFloatArrayRegion(data, 0, 9, d);
return true;
}
return false;
} }
extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathMeasureKt__1nGetSegment extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathMeasureKt__1nGetSegment
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment