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
}
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_PathMeasure__1nGetPosition
(KNativePointer ptr, KFloat distance) {
TODO("implement org_jetbrains_skia_PathMeasure__1nGetPosition");
}
#if 0
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_PathMeasure__1nGetPosition
(KNativePointer ptr, KFloat distance) {
SKIKO_EXPORT KBoolean org_jetbrains_skia_PathMeasure__1nGetPosition
(KNativePointer ptr, KFloat distance, KFloat* data) {
SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>((ptr));
SkPoint position;
if (instance->getPosTan(distance, &position, nullptr))
return skija::Point::fromSkPoint(env, position);
else
return nullptr;
}
#endif
if (instance->getPosTan(distance, &position, nullptr)) {
data[0] = position.fX;
data[1] = position.fY;
return true;
}
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_PathMeasure__1nGetTangent
(KNativePointer ptr, KFloat distance) {
TODO("implement org_jetbrains_skia_PathMeasure__1nGetTangent");
return false;
}
#if 0
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_PathMeasure__1nGetTangent
(KNativePointer ptr, KFloat distance) {
SKIKO_EXPORT KBoolean org_jetbrains_skia_PathMeasure__1nGetTangent
(KNativePointer ptr, KFloat distance, KFloat* data) {
SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>((ptr));
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
(KNativePointer ptr, KFloat distance) {
TODO("implement org_jetbrains_skia_PathMeasure__1nGetRSXform");
return false;
}
#if 0
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_PathMeasure__1nGetRSXform
(KNativePointer ptr, KFloat distance) {
SKIKO_EXPORT KBoolean org_jetbrains_skia_PathMeasure__1nGetRSXform
(KNativePointer ptr, KFloat distance, KFloat* data) {
SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>((ptr));
SkPoint position;
SkVector tangent;
if (instance->getPosTan(distance, &position, &tangent))
return env->NewObject(skija::RSXform::cls, skija::RSXform::ctor, tangent.fX, tangent.fY, position.fX, position.fY);
else
return nullptr;
}
#endif
if (instance->getPosTan(distance, &position, &tangent)) {
data[0] = tangent.fX;
data[1] = tangent.fY;
data[2] = position.fX;
data[3] = position.fY;
return true;
}
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_PathMeasure__1nGetMatrix
(KNativePointer ptr, KFloat distance, KBoolean getPosition, KBoolean getTangent) {
TODO("implement org_jetbrains_skia_PathMeasure__1nGetMatrix");
return false;
}
#if 0
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_PathMeasure__1nGetMatrix
(KNativePointer ptr, KFloat distance, KBoolean getPosition, KBoolean getTangent) {
SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>((ptr));
SkMatrix matrix;
int flags = 0;
if (getPosition)
flags |= SkPathMeasure::MatrixFlags::kGetPosition_MatrixFlag;
if (getTangent)
flags |= SkPathMeasure::MatrixFlags::kGetTangent_MatrixFlag;
if (instance->getMatrix(distance, &matrix, static_cast<SkPathMeasure::MatrixFlags>(flags))) {
std::vector<float> floats(9);
matrix.get9(floats.data());
return javaFloatArray(env, floats);
} else
return nullptr;
SKIKO_EXPORT KBoolean org_jetbrains_skia_PathMeasure__1nGetMatrix
(KNativePointer ptr, KFloat distance, KBoolean getPosition, KBoolean getTangent, KFloat* data) {
SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>((ptr));
SkMatrix matrix;
int flags = 0;
if (getPosition)
flags |= SkPathMeasure::MatrixFlags::kGetPosition_MatrixFlag;
if (getTangent)
flags |= SkPathMeasure::MatrixFlags::kGetTangent_MatrixFlag;
if (instance->getMatrix(distance, &matrix, static_cast<SkPathMeasure::MatrixFlags>(flags))) {
float* f;
matrix.get9(f);
data[0] = data[0];
data[1] = data[1];
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
(KNativePointer ptr, KFloat startD, KFloat endD, KNativePointer dstPtr, KBoolean startWithMoveTo) {
SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>((ptr));
......
package org.jetbrains.skia
import org.jetbrains.skia.impl.InteropPointer
import org.jetbrains.skia.impl.Library.Companion.staticLoad
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.Stats
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) {
companion object {
......@@ -78,7 +80,9 @@ class PathMeasure internal constructor(ptr: NativePointer) : Managed(ptr, _Final
fun getPosition(distance: Float): Point? {
return try {
Stats.onNativeCall()
_nGetPosition(_ptr, distance)
withNullableResult(FloatArray(2)) { _nGetPosition(_ptr, distance, it) }?.let { points ->
Point(points[0], points[1])
}
} finally {
reachabilityBarrier(this)
}
......@@ -93,7 +97,9 @@ class PathMeasure internal constructor(ptr: NativePointer) : Managed(ptr, _Final
fun getTangent(distance: Float): Point? {
return try {
Stats.onNativeCall()
_nGetTangent(_ptr, distance)
withNullableResult(FloatArray(2)) { _nGetTangent(_ptr, distance, it) }?.let { points ->
Point(points[0], points[1])
}
} finally {
reachabilityBarrier(this)
}
......@@ -108,7 +114,16 @@ class PathMeasure internal constructor(ptr: NativePointer) : Managed(ptr, _Final
fun getRSXform(distance: Float): RSXform? {
return try {
Stats.onNativeCall()
_nGetRSXform(_ptr, distance)
withNullableResult(FloatArray(4)) {
_nGetRSXform(_ptr, distance, it)
}?.let { data ->
RSXform(
data[0],
data[1],
data[2],
data[3]
)
}
} finally {
reachabilityBarrier(this)
}
......@@ -123,8 +138,21 @@ class PathMeasure internal constructor(ptr: NativePointer) : Managed(ptr, _Final
fun getMatrix(distance: Float, getPosition: Boolean, getTangent: Boolean): Matrix33? {
return try {
Stats.onNativeCall()
val mat = _nGetMatrix(_ptr, distance, getPosition, getTangent)
mat?.let { Matrix33(*it.copyOf()) }
withNullableResult(FloatArray(9)) {
_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 {
reachabilityBarrier(this)
}
......@@ -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")
private external fun PathMeasure_nGetFinalizer(): NativePointer
......@@ -198,16 +237,22 @@ private external fun _nSetPath(ptr: NativePointer, pathPtr: NativePointer, force
private external fun _nGetLength(ptr: NativePointer): Float
@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")
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")
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")
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")
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.assertEquals
import org.jetbrains.skia.tests.assertCloseEnough
import org.jetbrains.skia.impl.use
import org.jetbrains.skiko.tests.runTest
import kotlin.test.Ignore
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
fun pathMeasureTest() {
@Ignore
fun pathMeasureTest() = runTest {
Path().moveTo(0f, 0f).lineTo(40f, 0f).moveTo(0f, 40f).lineTo(10f, 50f).use { path ->
PathMeasure(path, false).use { measure ->
Path().lineTo(10f, 10f).use { path2 ->
......
......@@ -7,7 +7,6 @@ import kotlin.test.assertFalse
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import org.jetbrains.skiko.tests.runTest
import org.jetbrains.skia.tests.assertCloseEnough
class PathTests {
......
......@@ -34,39 +34,50 @@ extern "C" JNIEXPORT jfloat JNICALL Java_org_jetbrains_skia_PathMeasureKt__1nGet
return instance->getLength();
}
extern "C" JNIEXPORT jobject JNICALL Java_org_jetbrains_skia_PathMeasureKt__1nGetPosition
(JNIEnv* env, jclass jclass, jlong ptr, jfloat distance) {
extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathMeasureKt__1nGetPosition
(JNIEnv* env, jclass jclass, jlong ptr, jfloat distance, jfloatArray data) {
SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>(static_cast<uintptr_t>(ptr));
SkPoint position;
if (instance->getPosTan(distance, &position, nullptr))
return skija::Point::fromSkPoint(env, position);
else
return nullptr;
if (instance->getPosTan(distance, &position, nullptr)) {
jfloat d[2] = { position.fX, position.fY };
env->SetFloatArrayRegion(data, 0, 2, d);
return true;
}
return false;
}
extern "C" JNIEXPORT jobject JNICALL Java_org_jetbrains_skia_PathMeasureKt__1nGetTangent
(JNIEnv* env, jclass jclass, jlong ptr, jfloat distance) {
extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathMeasureKt__1nGetTangent
(JNIEnv* env, jclass jclass, jlong ptr, jfloat distance, jfloatArray data) {
SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>(static_cast<uintptr_t>(ptr));
SkVector tangent;
if (instance->getPosTan(distance, nullptr, &tangent))
return skija::Point::fromSkPoint(env, tangent);
else
return nullptr;
if (instance->getPosTan(distance, nullptr, &tangent)) {
jfloat d[2] = { tangent.fX, tangent.fY };
env->SetFloatArrayRegion(data, 0, 2, d);
return true;
}
return false;
}
extern "C" JNIEXPORT jobject JNICALL Java_org_jetbrains_skia_PathMeasureKt__1nGetRSXform
(JNIEnv* env, jclass jclass, jlong ptr, jfloat distance) {
extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathMeasureKt__1nGetRSXform
(JNIEnv* env, jclass jclass, jlong ptr, jfloat distance, jfloatArray data) {
SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>(static_cast<uintptr_t>(ptr));
SkPoint position;
SkVector tangent;
if (instance->getPosTan(distance, &position, &tangent))
return env->NewObject(skija::RSXform::cls, skija::RSXform::ctor, tangent.fX, tangent.fY, position.fX, position.fY);
else
return nullptr;
if (instance->getPosTan(distance, &position, &tangent)) {
jfloat d[4] = {
tangent.fX, tangent.fY, position.fX, position.fY
};
env->SetFloatArrayRegion(data, 0, 4, d);
return true;
}
return false;
}
extern "C" JNIEXPORT jobject JNICALL Java_org_jetbrains_skia_PathMeasureKt__1nGetMatrix
(JNIEnv* env, jclass jclass, jlong ptr, jfloat distance, jboolean getPosition, jboolean getTangent) {
extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathMeasureKt__1nGetMatrix
(JNIEnv* env, jclass jclass, jlong ptr, jfloat distance, jboolean getPosition, jboolean getTangent, jfloatArray data) {
SkPathMeasure* instance = reinterpret_cast<SkPathMeasure*>(static_cast<uintptr_t>(ptr));
SkMatrix matrix;
int flags = 0;
......@@ -77,11 +88,27 @@ extern "C" JNIEXPORT jobject JNICALL Java_org_jetbrains_skia_PathMeasureKt__1nGe
flags |= SkPathMeasure::MatrixFlags::kGetTangent_MatrixFlag;
if (instance->getMatrix(distance, &matrix, static_cast<SkPathMeasure::MatrixFlags>(flags))) {
std::vector<float> floats(9);
matrix.get9(floats.data());
return javaFloatArray(env, floats);
} else
return nullptr;
float* floats;
matrix.get9(floats);
jfloat d[9] = {
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
......
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