Unverified Commit 9372822b authored by Aleksandr Veselov's avatar Aleksandr Veselov Committed by GitHub

Implement Path methods (#322)

parent 73ca2ed4
...@@ -2,6 +2,7 @@ package org.jetbrains.skia ...@@ -2,6 +2,7 @@ package org.jetbrains.skia
import org.jetbrains.skia.impl.* import org.jetbrains.skia.impl.*
import org.jetbrains.skia.impl.Library.Companion.staticLoad import org.jetbrains.skia.impl.Library.Companion.staticLoad
import kotlin.math.min
/** /**
* *
...@@ -29,11 +30,17 @@ import org.jetbrains.skia.impl.Library.Companion.staticLoad ...@@ -29,11 +30,17 @@ import org.jetbrains.skia.impl.Library.Companion.staticLoad
*/ */
class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHolder.PTR), Iterable<PathSegment?> { class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHolder.PTR), Iterable<PathSegment?> {
companion object { companion object {
fun makeFromSVGString(svg: String): Path { fun makeFromSVGString(svg: String): Path {
val res = _nMakeFromSVGString(svg) Stats.onNativeCall()
return if (res == NullPointer) throw IllegalArgumentException("Failed to parse SVG Path string: $svg") else Path( val result = interopScope {
res _nMakeFromSVGString(toInterop(svg))
) }
if (result == NullPointer) {
throw IllegalArgumentException("Failed to parse SVG Path string: $svg")
} else {
return Path(result)
}
} }
/** /**
...@@ -140,7 +147,12 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol ...@@ -140,7 +147,12 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
*/ */
fun convertConicToQuads(p0: Point, p1: Point, p2: Point, w: Float, pow2: Int): Array<Point> { fun convertConicToQuads(p0: Point, p1: Point, p2: Point, w: Float, pow2: Int): Array<Point> {
Stats.onNativeCall() Stats.onNativeCall()
return _nConvertConicToQuads(p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, w, pow2) val maxResultPointCount = (1 + 2 * (1 shl pow2)) // See Skia docs
var pointCount = 0
val coords = withResult(FloatArray(maxResultPointCount * 2)) {
pointCount = _nConvertConicToQuads(p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, w, pow2, it)
}
return Array(pointCount) { Point(coords[2 * it], coords[2 * it + 1]) }
} }
/** /**
...@@ -190,13 +202,17 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol ...@@ -190,13 +202,17 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
* *
* @see [https://fiddle.skia.org/c/@Path_readFromMemory](https://fiddle.skia.org/c/@Path_readFromMemory) * @see [https://fiddle.skia.org/c/@Path_readFromMemory](https://fiddle.skia.org/c/@Path_readFromMemory)
*/ */
fun makeFromBytes(data: ByteArray?): Path { fun makeFromBytes(data: ByteArray): Path {
Stats.onNativeCall() Stats.onNativeCall()
return Path( val result = interopScope {
interopScope { _nMakeFromBytes(toInterop(data), data.size)
_nMakeFromBytes(toInterop(data)) }
}
) if (result == NullPointer) {
throw IllegalArgumentException("Failed to parse serialized Path")
} else {
return Path(result)
}
} }
init { init {
...@@ -335,10 +351,10 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol ...@@ -335,10 +351,10 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
* *
* @see [https://fiddle.skia.org/c/@Path_isOval](https://fiddle.skia.org/c/@Path_isOval) * @see [https://fiddle.skia.org/c/@Path_isOval](https://fiddle.skia.org/c/@Path_isOval)
*/ */
val isOval: Rect val isOval: Rect?
get() = try { get() = try {
Stats.onNativeCall() Stats.onNativeCall()
_nIsOval(_ptr) Rect.fromInteropPointerNullable { _nIsOval(_ptr, it) }
} finally { } finally {
reachabilityBarrier(this) reachabilityBarrier(this)
} }
...@@ -350,10 +366,10 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol ...@@ -350,10 +366,10 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
* *
* @see [https://fiddle.skia.org/c/@Path_isRRect](https://fiddle.skia.org/c/@Path_isRRect) * @see [https://fiddle.skia.org/c/@Path_isRRect](https://fiddle.skia.org/c/@Path_isRRect)
*/ */
val isRRect: RRect val isRRect: RRect?
get() = try { get() = try {
Stats.onNativeCall() Stats.onNativeCall()
_nIsRRect(_ptr) RRect.fromInteropPointerNullable { _nIsRRect(_ptr, it) }
} finally { } finally {
reachabilityBarrier(this) reachabilityBarrier(this)
} }
...@@ -444,7 +460,8 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol ...@@ -444,7 +460,8 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
val isFinite: Boolean val isFinite: Boolean
get() = try { get() = try {
Stats.onNativeCall() Stats.onNativeCall()
_nIsFinite(_ptr) // TODO For some reason this method returns 0 instead of false in JS target, investigate
!!_nIsFinite(_ptr)
} finally { } finally {
reachabilityBarrier(this) reachabilityBarrier(this)
} }
...@@ -521,10 +538,17 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol ...@@ -521,10 +538,17 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
* *
* @see [https://fiddle.skia.org/c/@Path_isLine](https://fiddle.skia.org/c/@Path_isLine) * @see [https://fiddle.skia.org/c/@Path_isLine](https://fiddle.skia.org/c/@Path_isLine)
*/ */
val asLine: Array<Point> val asLine: Array<Point>?
get() = try { get() = try {
Stats.onNativeCall() Stats.onNativeCall()
_nMaybeGetAsLine(_ptr) // HACK Use a temporary Rect as a buffer to store two points
val rectBuffer = Rect.fromInteropPointerNullable { _nMaybeGetAsLine(_ptr, it) }
rectBuffer?.run {
arrayOf(
Point(left, top),
Point(right, bottom)
)
}
} finally { } finally {
reachabilityBarrier(this) reachabilityBarrier(this)
} }
...@@ -561,7 +585,7 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol ...@@ -561,7 +585,7 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
fun getPoint(index: Int): Point { fun getPoint(index: Int): Point {
return try { return try {
Stats.onNativeCall() Stats.onNativeCall()
_nGetPoint(_ptr, index) Point.fromInteropPointer { _nGetPoint(_ptr, index, it) }
} finally { } finally {
reachabilityBarrier(this) reachabilityBarrier(this)
} }
...@@ -598,9 +622,22 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol ...@@ -598,9 +622,22 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
*/ */
fun getPoints(points: Array<Point?>?, max: Int): Int { fun getPoints(points: Array<Point?>?, max: Int): Int {
return try { return try {
require(if (points == null) max == 0 else true) require(if (points == null) max == 0 else max >= 0)
Stats.onNativeCall() Stats.onNativeCall()
_nGetPoints(_ptr, points, max) if (points == null) {
interopScope {
_nGetPoints(_ptr, toInterop(null as FloatArray?), max)
}
} else {
var result = 0
val coords = withResult(FloatArray(max * 2)) {
result = _nGetPoints(_ptr, it, max)
}
for (i in 0 until min(max, result)) {
points[i] = Point(coords[2 * i], coords[2 * i + 1])
}
result
}
} finally { } finally {
reachabilityBarrier(this) reachabilityBarrier(this)
} }
...@@ -643,7 +680,10 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol ...@@ -643,7 +680,10 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
Stats.onNativeCall() Stats.onNativeCall()
val out = if (verbs == null) null else ByteArray(max) val out = if (verbs == null) null else ByteArray(max)
val count = interopScope { val count = interopScope {
_nGetVerbs(_ptr, toInterop(out), max) val ptr = toInterop(out)
_nGetVerbs(_ptr, ptr, max).also {
out?.let { ptr.fromInterop(it) }
}
} }
if (verbs != null) for (i in 0 until minOf(count, max)) verbs[i] = PathVerb.values().get( if (verbs != null) for (i in 0 until minOf(count, max)) verbs[i] = PathVerb.values().get(
out!![i].toInt() out!![i].toInt()
...@@ -705,7 +745,7 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol ...@@ -705,7 +745,7 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
val bounds: Rect val bounds: Rect
get() = try { get() = try {
Stats.onNativeCall() Stats.onNativeCall()
_nGetBounds(_ptr) Rect.fromInteropPointer { _nGetBounds(_ptr, it) }
} finally { } finally {
reachabilityBarrier(this) reachabilityBarrier(this)
} }
...@@ -753,7 +793,7 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol ...@@ -753,7 +793,7 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
fun computeTightBounds(): Rect { fun computeTightBounds(): Rect {
return try { return try {
Stats.onNativeCall() Stats.onNativeCall()
_nComputeTightBounds(_ptr) Rect.fromInteropPointer { _nComputeTightBounds(_ptr, it) }
} finally { } finally {
reachabilityBarrier(this) reachabilityBarrier(this)
} }
...@@ -1440,10 +1480,10 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol ...@@ -1440,10 +1480,10 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
* *
* @see [https://fiddle.skia.org/c/@Path_isRect](https://fiddle.skia.org/c/@Path_isRect) * @see [https://fiddle.skia.org/c/@Path_isRect](https://fiddle.skia.org/c/@Path_isRect)
*/ */
val isRect: Rect val isRect: Rect?
get() = try { get() = try {
Stats.onNativeCall() Stats.onNativeCall()
_nIsRect(_ptr) Rect.fromInteropPointerNullable { _nIsRect(_ptr, it) }
} finally { } finally {
reachabilityBarrier(this) reachabilityBarrier(this)
} }
...@@ -1673,7 +1713,7 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol ...@@ -1673,7 +1713,7 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
require(pts.size % 2 == 0) { "Expected even amount of pts, got " + pts.size } require(pts.size % 2 == 0) { "Expected even amount of pts, got " + pts.size }
Stats.onNativeCall() Stats.onNativeCall()
interopScope { interopScope {
_nAddPoly(_ptr, toInterop(pts), close) _nAddPoly(_ptr, toInterop(pts), pts.size / 2, close)
} }
return this return this
} }
...@@ -1920,7 +1960,7 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol ...@@ -1920,7 +1960,7 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
var lastPt: Point var lastPt: Point
get() = try { get() = try {
Stats.onNativeCall() Stats.onNativeCall()
_nGetLastPt(_ptr) Point.fromInteropPointer { _nGetLastPt(_ptr, it) }
} finally { } finally {
reachabilityBarrier(this) reachabilityBarrier(this)
} }
...@@ -2068,7 +2108,13 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol ...@@ -2068,7 +2108,13 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
fun serializeToBytes(): ByteArray { fun serializeToBytes(): ByteArray {
return try { return try {
Stats.onNativeCall() Stats.onNativeCall()
_nSerializeToBytes(_ptr) val size = interopScope { _nSerializeToBytes(_ptr, toInterop(null as ByteArray?)) }
if (size == -1) {
throw Error("Path is too big")
}
withResult(ByteArray(size)) {
_nSerializeToBytes(_ptr, it)
}
} finally { } finally {
reachabilityBarrier(this) reachabilityBarrier(this)
} }
...@@ -2142,7 +2188,7 @@ private external fun Path_nSwap(ptr: NativePointer, otherPtr: NativePointer) ...@@ -2142,7 +2188,7 @@ private external fun Path_nSwap(ptr: NativePointer, otherPtr: NativePointer)
private external fun Path_nGetGenerationId(ptr: NativePointer): Int private external fun Path_nGetGenerationId(ptr: NativePointer): Int
@ExternalSymbolName("org_jetbrains_skia_Path__1nMakeFromSVGString") @ExternalSymbolName("org_jetbrains_skia_Path__1nMakeFromSVGString")
private external fun _nMakeFromSVGString(s: String?): NativePointer private external fun _nMakeFromSVGString(svg: InteropPointer): NativePointer
@ExternalSymbolName("org_jetbrains_skia_Path__1nIsInterpolatable") @ExternalSymbolName("org_jetbrains_skia_Path__1nIsInterpolatable")
private external fun _nIsInterpolatable(ptr: NativePointer, comparePtr: NativePointer): Boolean private external fun _nIsInterpolatable(ptr: NativePointer, comparePtr: NativePointer): Boolean
...@@ -2160,10 +2206,10 @@ private external fun _nSetFillMode(ptr: NativePointer, fillMode: Int) ...@@ -2160,10 +2206,10 @@ private external fun _nSetFillMode(ptr: NativePointer, fillMode: Int)
private external fun _nIsConvex(ptr: NativePointer): Boolean private external fun _nIsConvex(ptr: NativePointer): Boolean
@ExternalSymbolName("org_jetbrains_skia_Path__1nIsOval") @ExternalSymbolName("org_jetbrains_skia_Path__1nIsOval")
private external fun _nIsOval(ptr: NativePointer): Rect private external fun _nIsOval(ptr: NativePointer, rect: InteropPointer): Boolean
@ExternalSymbolName("org_jetbrains_skia_Path__1nIsRRect") @ExternalSymbolName("org_jetbrains_skia_Path__1nIsRRect")
private external fun _nIsRRect(ptr: NativePointer): RRect private external fun _nIsRRect(ptr: NativePointer, rrect: InteropPointer): Boolean
@ExternalSymbolName("org_jetbrains_skia_Path__1nRewind") @ExternalSymbolName("org_jetbrains_skia_Path__1nRewind")
private external fun _nRewind(ptr: NativePointer) private external fun _nRewind(ptr: NativePointer)
...@@ -2207,16 +2253,16 @@ private external fun _nIsCubicDegenerate( ...@@ -2207,16 +2253,16 @@ private external fun _nIsCubicDegenerate(
@ExternalSymbolName("org_jetbrains_skia_Path__1nMaybeGetAsLine") @ExternalSymbolName("org_jetbrains_skia_Path__1nMaybeGetAsLine")
private external fun _nMaybeGetAsLine(ptr: NativePointer): Array<Point> private external fun _nMaybeGetAsLine(ptr: NativePointer, rectBuffer: InteropPointer): Boolean
@ExternalSymbolName("org_jetbrains_skia_Path__1nGetPointsCount") @ExternalSymbolName("org_jetbrains_skia_Path__1nGetPointsCount")
private external fun _nGetPointsCount(ptr: NativePointer): Int private external fun _nGetPointsCount(ptr: NativePointer): Int
@ExternalSymbolName("org_jetbrains_skia_Path__1nGetPoint") @ExternalSymbolName("org_jetbrains_skia_Path__1nGetPoint")
private external fun _nGetPoint(ptr: NativePointer, index: Int): Point private external fun _nGetPoint(ptr: NativePointer, index: Int, result: InteropPointer)
@ExternalSymbolName("org_jetbrains_skia_Path__1nGetPoints") @ExternalSymbolName("org_jetbrains_skia_Path__1nGetPoints")
private external fun _nGetPoints(ptr: NativePointer, points: Array<Point?>?, max: Int): Int private external fun _nGetPoints(ptr: NativePointer, points: InteropPointer, max: Int): Int
@ExternalSymbolName("org_jetbrains_skia_Path__1nCountVerbs") @ExternalSymbolName("org_jetbrains_skia_Path__1nCountVerbs")
private external fun _nCountVerbs(ptr: NativePointer): Int private external fun _nCountVerbs(ptr: NativePointer): Int
...@@ -2228,13 +2274,13 @@ private external fun _nGetVerbs(ptr: NativePointer, verbs: InteropPointer, max: ...@@ -2228,13 +2274,13 @@ private external fun _nGetVerbs(ptr: NativePointer, verbs: InteropPointer, max:
private external fun _nApproximateBytesUsed(ptr: NativePointer): NativePointer private external fun _nApproximateBytesUsed(ptr: NativePointer): NativePointer
@ExternalSymbolName("org_jetbrains_skia_Path__1nGetBounds") @ExternalSymbolName("org_jetbrains_skia_Path__1nGetBounds")
private external fun _nGetBounds(ptr: NativePointer): Rect private external fun _nGetBounds(ptr: NativePointer, rect: InteropPointer)
@ExternalSymbolName("org_jetbrains_skia_Path__1nUpdateBoundsCache") @ExternalSymbolName("org_jetbrains_skia_Path__1nUpdateBoundsCache")
private external fun _nUpdateBoundsCache(ptr: NativePointer) private external fun _nUpdateBoundsCache(ptr: NativePointer)
@ExternalSymbolName("org_jetbrains_skia_Path__1nComputeTightBounds") @ExternalSymbolName("org_jetbrains_skia_Path__1nComputeTightBounds")
private external fun _nComputeTightBounds(ptr: NativePointer): Rect private external fun _nComputeTightBounds(ptr: NativePointer, rect: InteropPointer)
@ExternalSymbolName("org_jetbrains_skia_Path__1nConservativelyContainsRect") @ExternalSymbolName("org_jetbrains_skia_Path__1nConservativelyContainsRect")
private external fun _nConservativelyContainsRect(ptr: NativePointer, l: Float, t: Float, r: Float, b: Float): Boolean private external fun _nConservativelyContainsRect(ptr: NativePointer, l: Float, t: Float, r: Float, b: Float): Boolean
...@@ -2326,12 +2372,13 @@ private external fun _nConvertConicToQuads( ...@@ -2326,12 +2372,13 @@ private external fun _nConvertConicToQuads(
x2: Float, x2: Float,
y2: Float, y2: Float,
w: Float, w: Float,
pow2: Int pow2: Int,
): Array<Point> result: InteropPointer
): Int
@ExternalSymbolName("org_jetbrains_skia_Path__1nIsRect") @ExternalSymbolName("org_jetbrains_skia_Path__1nIsRect")
private external fun _nIsRect(ptr: NativePointer): Rect private external fun _nIsRect(ptr: NativePointer, rect: InteropPointer): Boolean
@ExternalSymbolName("org_jetbrains_skia_Path__1nAddRect") @ExternalSymbolName("org_jetbrains_skia_Path__1nAddRect")
private external fun _nAddRect(ptr: NativePointer, l: Float, t: Float, r: Float, b: Float, dir: Int, start: Int) private external fun _nAddRect(ptr: NativePointer, l: Float, t: Float, r: Float, b: Float, dir: Int, start: Int)
...@@ -2360,7 +2407,7 @@ private external fun _nAddRRect( ...@@ -2360,7 +2407,7 @@ private external fun _nAddRRect(
@ExternalSymbolName("org_jetbrains_skia_Path__1nAddPoly") @ExternalSymbolName("org_jetbrains_skia_Path__1nAddPoly")
private external fun _nAddPoly(ptr: NativePointer, coords: InteropPointer, close: Boolean) private external fun _nAddPoly(ptr: NativePointer, coords: InteropPointer, count: Int, close: Boolean)
@ExternalSymbolName("org_jetbrains_skia_Path__1nAddPath") @ExternalSymbolName("org_jetbrains_skia_Path__1nAddPath")
private external fun _nAddPath(ptr: NativePointer, srcPtr: NativePointer, extend: Boolean) private external fun _nAddPath(ptr: NativePointer, srcPtr: NativePointer, extend: Boolean)
...@@ -2381,7 +2428,7 @@ private external fun _nOffset(ptr: NativePointer, dx: Float, dy: Float, dst: Nat ...@@ -2381,7 +2428,7 @@ private external fun _nOffset(ptr: NativePointer, dx: Float, dy: Float, dst: Nat
private external fun _nTransform(ptr: NativePointer, matrix: InteropPointer, dst: NativePointer, applyPerspectiveClip: Boolean) private external fun _nTransform(ptr: NativePointer, matrix: InteropPointer, dst: NativePointer, applyPerspectiveClip: Boolean)
@ExternalSymbolName("org_jetbrains_skia_Path__1nGetLastPt") @ExternalSymbolName("org_jetbrains_skia_Path__1nGetLastPt")
private external fun _nGetLastPt(ptr: NativePointer): Point private external fun _nGetLastPt(ptr: NativePointer, result: InteropPointer): Boolean
@ExternalSymbolName("org_jetbrains_skia_Path__1nSetLastPt") @ExternalSymbolName("org_jetbrains_skia_Path__1nSetLastPt")
private external fun _nSetLastPt(ptr: NativePointer, x: Float, y: Float) private external fun _nSetLastPt(ptr: NativePointer, x: Float, y: Float)
...@@ -2399,13 +2446,13 @@ private external fun _nDump(ptr: NativePointer) ...@@ -2399,13 +2446,13 @@ private external fun _nDump(ptr: NativePointer)
private external fun _nDumpHex(ptr: NativePointer) private external fun _nDumpHex(ptr: NativePointer)
@ExternalSymbolName("org_jetbrains_skia_Path__1nSerializeToBytes") @ExternalSymbolName("org_jetbrains_skia_Path__1nSerializeToBytes")
private external fun _nSerializeToBytes(ptr: NativePointer): ByteArray private external fun _nSerializeToBytes(ptr: NativePointer, dst: InteropPointer): Int
@ExternalSymbolName("org_jetbrains_skia_Path__1nMakeCombining") @ExternalSymbolName("org_jetbrains_skia_Path__1nMakeCombining")
private external fun _nMakeCombining(onePtr: NativePointer, twoPtr: NativePointer, op: Int): NativePointer private external fun _nMakeCombining(onePtr: NativePointer, twoPtr: NativePointer, op: Int): NativePointer
@ExternalSymbolName("org_jetbrains_skia_Path__1nMakeFromBytes") @ExternalSymbolName("org_jetbrains_skia_Path__1nMakeFromBytes")
private external fun _nMakeFromBytes(data: InteropPointer): NativePointer private external fun _nMakeFromBytes(data: InteropPointer, size: Int): NativePointer
@ExternalSymbolName("org_jetbrains_skia_Path__1nIsValid") @ExternalSymbolName("org_jetbrains_skia_Path__1nIsValid")
private external fun _nIsValid(ptr: NativePointer): Boolean private external fun _nIsValid(ptr: NativePointer): Boolean
\ No newline at end of file
package org.jetbrains.skia package org.jetbrains.skia
import org.jetbrains.skia.impl.InteropPointer
import org.jetbrains.skia.impl.withResult
class Point(val x: Float, val y: Float) { class Point(val x: Float, val y: Float) {
fun offset(dx: Float, dy: Float): Point { fun offset(dx: Float, dy: Float): Point {
...@@ -59,5 +62,10 @@ class Point(val x: Float, val y: Float) { ...@@ -59,5 +62,10 @@ class Point(val x: Float, val y: Float) {
for (i in 0 until pts.size / 2) arr[i] = Point(pts[i * 2], pts[i * 2 + 1]) for (i in 0 until pts.size / 2) arr[i] = Point(pts[i * 2], pts[i * 2 + 1])
return arr return arr
} }
internal fun fromInteropPointer(block: (InteropPointer) -> Unit): Point {
val result = withResult(FloatArray(2), block)
return Point(result[0], result[1])
}
} }
} }
\ No newline at end of file
package org.jetbrains.skia package org.jetbrains.skia
import org.jetbrains.skia.impl.InteropPointer
import org.jetbrains.skia.impl.withResult
import kotlin.jvm.JvmStatic import kotlin.jvm.JvmStatic
import kotlin.math.abs import kotlin.math.abs
...@@ -32,14 +34,18 @@ class RRect internal constructor(l: Float, t: Float, r: Float, b: Float, val rad ...@@ -32,14 +34,18 @@ class RRect internal constructor(l: Float, t: Float, r: Float, b: Float, val rad
} }
override fun toString(): String { override fun toString(): String {
return "RRect(_left=$left, _top=$top, _right=$right, _bottom=$bottom, _radii=$radii)" return "RRect(_left=$left, _top=$top, _right=$right, _bottom=$bottom, _radii=${radii.joinToString()})"
} }
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (other === this) return true if (other === this) return true
if (other !is RRect) return false if (other !is RRect) return false
if (!super.equals(other)) return false if (!super.equals(other)) return false
return radii.contentEquals(other.radii) return if (radii.size == other.radii.size) {
radii.contentEquals(other.radii)
} else {
normalizeRadii(radii).contentEquals(normalizeRadii(other.radii))
}
} }
override fun hashCode(): Int { override fun hashCode(): Int {
...@@ -146,5 +152,27 @@ class RRect internal constructor(l: Float, t: Float, r: Float, b: Float, val rad ...@@ -146,5 +152,27 @@ class RRect internal constructor(l: Float, t: Float, r: Float, b: Float, val rad
fun makePillXYWH(l: Float, t: Float, w: Float, h: Float): RRect { fun makePillXYWH(l: Float, t: Float, w: Float, h: Float): RRect {
return RRect(l, t, l + w, t + h, floatArrayOf(minOf(w, h) / 2.0f)) return RRect(l, t, l + w, t + h, floatArrayOf(minOf(w, h) / 2.0f))
} }
internal fun fromInteropPointer(block: (InteropPointer) -> Unit): RRect {
val result = withResult(FloatArray(12 /* 4 dimensions + 4 radii * 2 */), block)
return RRect(result[0], result[1], result[2], result[3], result.copyOfRange(4, 12))
}
internal fun fromInteropPointerNullable(block: (InteropPointer) -> Boolean): RRect? {
var result = true
val rect = fromInteropPointer { result = block(it) }
return if (result) { rect } else { null }
}
}
}
private fun normalizeRadii(radii: FloatArray): FloatArray {
return when (radii.size) {
0 -> FloatArray(8) { 0.0f }
1 -> FloatArray(8) { radii[0] } // All are the same
2 -> FloatArray(8) { radii[it % 2] } // Corresponding values are same for each corner
4 -> FloatArray(8) { radii[it / 2] } // Horizontal and vertical are same for each corner
8 -> radii
else -> throw Error("illegal radii array")
} }
} }
\ No newline at end of file
package org.jetbrains.skia package org.jetbrains.skia
import org.jetbrains.skia.ExternalSymbolName import org.jetbrains.skia.ExternalSymbolName
import org.jetbrains.skia.impl.InteropPointer
import org.jetbrains.skia.impl.withResult
import kotlin.jvm.JvmStatic import kotlin.jvm.JvmStatic
open class Rect constructor(val left: Float, val top: Float, val right: Float, val bottom: Float) { open class Rect constructor(val left: Float, val top: Float, val right: Float, val bottom: Float) {
...@@ -103,5 +105,16 @@ open class Rect constructor(val left: Float, val top: Float, val right: Float, v ...@@ -103,5 +105,16 @@ open class Rect constructor(val left: Float, val top: Float, val right: Float, v
require(h >= 0) { "Rect::makeXYWH expected h >= 0, got: $h" } require(h >= 0) { "Rect::makeXYWH expected h >= 0, got: $h" }
return Rect(l, t, l + w, t + h) return Rect(l, t, l + w, t + h)
} }
internal fun fromInteropPointer(block: (InteropPointer) -> Unit): Rect {
val result = withResult(FloatArray(4), block)
return Rect(result[0], result[1], result[2], result[3])
}
internal fun fromInteropPointerNullable(block: (InteropPointer) -> Boolean): Rect? {
var result = true
val rect = fromInteropPointer { result = block(it) }
return if (result) { rect } else { null }
}
} }
} }
\ No newline at end of file
package org.jetbrains.skiko package org.jetbrains.skia
import org.jetbrains.skia.Path import org.jetbrains.skia.impl.Native.Companion.NullPointer
import org.jetbrains.skia.PathSegmentMask import org.jetbrains.skia.tests.assertCloseEnough
import org.jetbrains.skia.PathVerb
import org.jetbrains.skia.Point
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertContentEquals import kotlin.test.assertContentEquals
import kotlin.test.assertEquals import kotlin.test.assertEquals
...@@ -83,9 +81,16 @@ class PathTest { ...@@ -83,9 +81,16 @@ class PathTest {
null null
), verbs ), verbs
) )
assertNotEquals(0L, p.approximateBytesUsed) assertNotEquals(NullPointer, p.approximateBytesUsed)
assertEquals(PathSegmentMask.LINE, p.segmentMasks) assertEquals(PathSegmentMask.LINE, p.segmentMasks)
} }
} }
@Test
fun canGetBounds() {
val path = Path().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath()
val bounds = Rect(0.0f, 0.0f, 40.0f, 40.0f)
assertCloseEnough(bounds, path.bounds)
assertCloseEnough(bounds, path.computeTightBounds())
}
} }
\ No newline at end of file
package org.jetbrains.skia package org.jetbrains.skia
import org.jetbrains.skia.impl.use import org.jetbrains.skia.impl.use
import org.jetbrains.skiko.tests.SkipJsTarget import org.jetbrains.skia.tests.assertContentCloseEnough
import org.jetbrains.skiko.tests.SkipNativeTarget
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertTrue import kotlin.test.assertTrue
import kotlin.test.assertFalse import kotlin.test.assertFalse
...@@ -69,8 +68,6 @@ class PathTests { ...@@ -69,8 +68,6 @@ class PathTests {
@Test @Test
@SkipJsTarget
@SkipNativeTarget
fun isShapeTest() { fun isShapeTest() {
for (dir in PathDirection.values()) { for (dir in PathDirection.values()) {
for (start in 0..3) { for (start in 0..3) {
...@@ -124,8 +121,6 @@ class PathTests { ...@@ -124,8 +121,6 @@ class PathTests {
} }
@Test @Test
@SkipJsTarget
@SkipNativeTarget
fun checksTest() { fun checksTest() {
Path().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath().use { p -> Path().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath().use { p ->
assertFalse(p.isEmpty) assertFalse(p.isEmpty)
...@@ -174,8 +169,6 @@ class PathTests { ...@@ -174,8 +169,6 @@ class PathTests {
} }
@Test @Test
@SkipJsTarget
@SkipNativeTarget
fun swapTest() { fun swapTest() {
Path().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath().use { p1 -> Path().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath().use { p1 ->
Path().lineTo(0f, 0f).lineTo(20f, 20f).use { p2 -> Path().lineTo(0f, 0f).lineTo(20f, 20f).use { p2 ->
...@@ -187,8 +180,6 @@ class PathTests { ...@@ -187,8 +180,6 @@ class PathTests {
} }
@Test @Test
@SkipJsTarget
@SkipNativeTarget
fun containsTest() { fun containsTest() {
Path().addRRect(RRect.makeLTRB(10f, 20f, 54f, 120f, 10f, 20f)).use { p -> Path().addRRect(RRect.makeLTRB(10f, 20f, 54f, 120f, 10f, 20f)).use { p ->
assertTrue(p.conservativelyContainsRect(Rect.makeLTRB(10f, 40f, 54f, 80f))) assertTrue(p.conservativelyContainsRect(Rect.makeLTRB(10f, 40f, 54f, 80f)))
...@@ -202,8 +193,6 @@ class PathTests { ...@@ -202,8 +193,6 @@ class PathTests {
} }
@Test @Test
@SkipJsTarget
@SkipNativeTarget
fun utilsTest() { fun utilsTest() {
assertFalse(Path.isLineDegenerate(Point(0f, 0f), Point(10f, 0f), false)) assertFalse(Path.isLineDegenerate(Point(0f, 0f), Point(10f, 0f), false))
assertTrue(Path.isLineDegenerate(Point(0f, 0f), Point(0f, 0f), true)) assertTrue(Path.isLineDegenerate(Point(0f, 0f), Point(0f, 0f), true))
...@@ -213,11 +202,11 @@ class PathTests { ...@@ -213,11 +202,11 @@ class PathTests {
assertTrue(Path.isQuadDegenerate(Point(0f, 0f), Point(0f, 0f), Point(0f, 0f), false)) assertTrue(Path.isQuadDegenerate(Point(0f, 0f), Point(0f, 0f), Point(0f, 0f), false))
assertFalse(Path.isCubicDegenerate(Point(0f, 0f), Point(10f, 0f), Point(0f, 0f), Point(0f, 0f), false)) assertFalse(Path.isCubicDegenerate(Point(0f, 0f), Point(10f, 0f), Point(0f, 0f), Point(0f, 0f), false))
assertTrue(Path.isCubicDegenerate(Point(0f, 0f), Point(0f, 0f), Point(0f, 0f), Point(0f, 0f), false)) assertTrue(Path.isCubicDegenerate(Point(0f, 0f), Point(0f, 0f), Point(0f, 0f), Point(0f, 0f), false))
assertContentEquals( assertContentCloseEnough(
arrayOf(Point(0f, 20f), Point(6.666667f, 13.333334f)), arrayOf(Point(0f, 20f), Point(6.666667f, 13.333334f)),
Path.convertConicToQuads(Point(0f, 20f), Point(20f, 0f), Point(40f, 20f), 0.5f, 1) Path.convertConicToQuads(Point(0f, 20f), Point(20f, 0f), Point(40f, 20f), 0.5f, 1)
) )
assertContentEquals( assertContentCloseEnough(
arrayOf( arrayOf(
Point(0f, 20f), Point(0f, 20f),
Point(3.0940108f, 16.905989f), Point(3.0940108f, 16.905989f),
...@@ -238,12 +227,15 @@ class PathTests { ...@@ -238,12 +227,15 @@ class PathTests {
} }
@Test @Test
@SkipJsTarget
@SkipNativeTarget
fun serializeTest() { fun serializeTest() {
Path().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath().use { p -> Path().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath().use { p ->
val p2: Path = Path.makeFromBytes(p.serializeToBytes()) val p2: Path = Path.makeFromBytes(p.serializeToBytes())
assertEquals(p, p2) assertEquals(p, p2)
} }
} }
@Test
fun svgTest() {
Path.makeFromSVGString("M0 0 L10 10 Z").use { }
}
} }
\ No newline at end of file
...@@ -3,7 +3,9 @@ package org.jetbrains.skia.tests ...@@ -3,7 +3,9 @@ package org.jetbrains.skia.tests
import org.jetbrains.skia.Color4f import org.jetbrains.skia.Color4f
import org.jetbrains.skia.Matrix33 import org.jetbrains.skia.Matrix33
import org.jetbrains.skia.Point import org.jetbrains.skia.Point
import org.jetbrains.skia.Rect
import kotlin.math.abs import kotlin.math.abs
import kotlin.test.assertNotNull
import kotlin.test.assertTrue import kotlin.test.assertTrue
private const val EPSILON = 0.00001f private const val EPSILON = 0.00001f
...@@ -21,10 +23,39 @@ internal fun assertCloseEnough(expected: Matrix33, actual: Matrix33?, epsilon: F ...@@ -21,10 +23,39 @@ internal fun assertCloseEnough(expected: Matrix33, actual: Matrix33?, epsilon: F
expected.mat.zip(actual!!.mat).forEach { (a, b) -> assertCloseEnough(a, b, epsilon) } expected.mat.zip(actual!!.mat).forEach { (a, b) -> assertCloseEnough(a, b, epsilon) }
} }
internal fun assertCloseEnough(expected: Color4f, actual: Color4f?, epsilon: Float = EPSILON) { internal fun assertCloseEnough(expected: Color4f, actual: Color4f?, epsilon: Float = EPSILON) {
assertCloseEnough(expected.r, actual!!.r, epsilon) assertCloseEnough(expected.r, actual!!.r, epsilon)
assertCloseEnough(expected.g, actual.g, epsilon) assertCloseEnough(expected.g, actual.g, epsilon)
assertCloseEnough(expected.b, actual.b, epsilon) assertCloseEnough(expected.b, actual.b, epsilon)
assertCloseEnough(expected.a, actual.a, epsilon) assertCloseEnough(expected.a, actual.a, epsilon)
} }
\ No newline at end of file
internal fun assertCloseEnough(expected: Rect, actual: Rect?, epsilon: Float = EPSILON) {
assertCloseEnough(expected.left, actual!!.left, epsilon)
assertCloseEnough(expected.top, actual.top, epsilon)
assertCloseEnough(expected.right, actual.right, epsilon)
assertCloseEnough(expected.bottom, actual.bottom, epsilon)
}
internal fun assertContentCloseEnough(expected: FloatArray, actual: FloatArray?, epsilon: Float = EPSILON) {
if (actual == null) {
throw AssertionError("expected $expected, got null")
}
for (i in expected.indices) {
if (abs(expected[i] - actual[i]) > epsilon) {
throw AssertionError("results differ at index$i, expected ${expected[i]}, got ${actual[i]}")
}
}
}
internal fun assertContentCloseEnough(expected: Array<Point>, actual: Array<Point>?, epsilon: Float = EPSILON) {
assertNotNull(actual)
for (i in expected.indices) {
try {
assertCloseEnough(expected[i], actual[i], epsilon)
} catch (e: AssertionError) {
throw AssertionError("results differ at index $i, ${e.message}")
}
}
}
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include <cfloat> #include <cfloat>
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <limits>
#include <jni.h> #include <jni.h>
#include "SkPath.h" #include "SkPath.h"
#include "SkPathOps.h" #include "SkPathOps.h"
...@@ -73,22 +74,26 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathKt__1nIsConvex ...@@ -73,22 +74,26 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathKt__1nIsConvex
return instance->isConvex(); return instance->isConvex();
} }
extern "C" JNIEXPORT jobject JNICALL Java_org_jetbrains_skia_PathKt__1nIsOval(JNIEnv* env, jclass jclass, jlong ptr) { extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathKt__1nIsOval(JNIEnv* env, jclass jclass, jlong ptr, jfloatArray resultArray) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr)); SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
SkRect bounds; SkRect bounds;
if (instance->isOval(&bounds)) if (instance->isOval(&bounds)) {
return skija::Rect::fromSkRect(env, bounds); skija::Rect::copyToInterop(env, bounds, resultArray);
else return true;
return nullptr; } else {
return false;
}
} }
extern "C" JNIEXPORT jobject JNICALL Java_org_jetbrains_skia_PathKt__1nIsRRect(JNIEnv* env, jclass jclass, jlong ptr) { extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathKt__1nIsRRect(JNIEnv* env, jclass jclass, jlong ptr, jfloatArray resultArray) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr)); SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
SkRRect rrect; SkRRect rrect;
if (instance->isRRect(&rrect)) if (instance->isRRect(&rrect)) {
return skija::RRect::fromSkRRect(env, rrect); skija::RRect::copyToInterop(env, rrect, resultArray);
else return true;
return nullptr; } else {
return false;
}
} }
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt_Path_1nReset(JNIEnv* env, jclass jclass, jlong ptr) { extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt_Path_1nReset(JNIEnv* env, jclass jclass, jlong ptr) {
...@@ -138,16 +143,16 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathKt__1nIsCubicD ...@@ -138,16 +143,16 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathKt__1nIsCubicD
return SkPath::IsCubicDegenerate({x0, y0}, {x1, y1}, {x2, y2}, {x3, y3}, exact); return SkPath::IsCubicDegenerate({x0, y0}, {x1, y1}, {x2, y2}, {x3, y3}, exact);
} }
extern "C" JNIEXPORT jobjectArray JNICALL Java_org_jetbrains_skia_PathKt__1nMaybeGetAsLine(JNIEnv* env, jclass jclass, jlong ptr) { extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathKt__1nMaybeGetAsLine(JNIEnv* env, jclass jclass, jlong ptr, jfloatArray resultArray) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr)); SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
SkPoint line[2]; SkPoint line[2];
if (instance->isLine(line)) { if (instance->isLine(line)) {
jobjectArray res = env->NewObjectArray(2, skija::Point::cls, nullptr); SkRect rect = SkRect::MakeLTRB(line[0].x(), line[0].y(), line[1].x(), line[1].y());
env->SetObjectArrayElement(res, 0, skija::Point::fromSkPoint(env, line[0])); skija::Rect::copyToInterop(env, rect, resultArray);
env->SetObjectArrayElement(res, 1, skija::Point::fromSkPoint(env, line[1])); return true;
return res; } else {
} else return false;
return nullptr; }
} }
extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_PathKt__1nGetPointsCount(JNIEnv* env, jclass jclass, jlong ptr) { extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_PathKt__1nGetPointsCount(JNIEnv* env, jclass jclass, jlong ptr) {
...@@ -155,18 +160,18 @@ extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_PathKt__1nGetPointsCou ...@@ -155,18 +160,18 @@ extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_PathKt__1nGetPointsCou
return instance->countPoints(); return instance->countPoints();
} }
extern "C" JNIEXPORT jobject JNICALL Java_org_jetbrains_skia_PathKt__1nGetPoint(JNIEnv* env, jclass jclass, jlong ptr, jint index) { extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nGetPoint(JNIEnv* env, jclass jclass, jlong ptr, jint index, jfloatArray resultArray) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr)); SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
SkPoint p = instance->getPoint(index); skija::Point::copyToInterop(env, instance->getPoint(index), resultArray);
return skija::Point::fromSkPoint(env, p);
} }
extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_PathKt__1nGetPoints(JNIEnv* env, jclass jclass, jlong ptr, jobjectArray pointsArray, jint max) { extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_PathKt__1nGetPoints(JNIEnv* env, jclass jclass, jlong ptr, jfloatArray pointsArray, jint max) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr)); SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
std::vector<SkPoint> p(std::min<jint>(max, instance->countPoints())); jfloat* points = pointsArray == nullptr ? nullptr : env->GetFloatArrayElements(pointsArray, 0);
int count = instance->getPoints(p.data(), max); int count = instance->getPoints(reinterpret_cast<SkPoint*>(points), max);
for (int i = 0; i < max && i < count; ++ i) if (pointsArray != nullptr) {
env->SetObjectArrayElement(pointsArray, i, skija::Point::fromSkPoint(env, p[i])); env->ReleaseFloatArrayElements(pointsArray, points, 0);
}
return count; return count;
} }
...@@ -195,9 +200,9 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt_Path_1nSwap(JNI ...@@ -195,9 +200,9 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt_Path_1nSwap(JNI
instance->swap(*other); instance->swap(*other);
} }
extern "C" JNIEXPORT jobject JNICALL Java_org_jetbrains_skia_PathKt__1nGetBounds(JNIEnv* env, jclass jclass, jlong ptr) { extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nGetBounds(JNIEnv* env, jclass jclass, jlong ptr, jfloatArray resultArray) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr)); SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
return skija::Rect::fromSkRect(env, instance->getBounds()); skija::Rect::copyToInterop(env, instance->getBounds(), resultArray);
} }
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nUpdateBoundsCache(JNIEnv* env, jclass jclass, jlong ptr) { extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nUpdateBoundsCache(JNIEnv* env, jclass jclass, jlong ptr) {
...@@ -205,9 +210,9 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nUpdateBounds ...@@ -205,9 +210,9 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nUpdateBounds
instance->updateBoundsCache(); instance->updateBoundsCache();
} }
extern "C" JNIEXPORT jobject JNICALL Java_org_jetbrains_skia_PathKt__1nComputeTightBounds(JNIEnv* env, jclass jclass, jlong ptr) { extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nComputeTightBounds(JNIEnv* env, jclass jclass, jlong ptr, jfloatArray resultArray) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr)); SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
return skija::Rect::fromSkRect(env, instance->computeTightBounds()); skija::Rect::copyToInterop(env, instance->computeTightBounds(), resultArray);
} }
extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathKt__1nConservativelyContainsRect(JNIEnv* env, jclass jclass, jlong ptr, float l, float t, float r, float b) { extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathKt__1nConservativelyContainsRect(JNIEnv* env, jclass jclass, jlong ptr, float l, float t, float r, float b) {
...@@ -296,25 +301,24 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nClosePath(JN ...@@ -296,25 +301,24 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nClosePath(JN
instance->close(); instance->close();
} }
extern "C" JNIEXPORT jobjectArray Java_org_jetbrains_skia_PathKt__1nConvertConicToQuads extern "C" JNIEXPORT jint Java_org_jetbrains_skia_PathKt__1nConvertConicToQuads
(JNIEnv* env, jclass jclass, jfloat x0, jfloat y0, jfloat x1, jfloat y1, jfloat x2, jfloat y2, jfloat w, jint pow2) { (JNIEnv* env, jclass jclass, jfloat x0, jfloat y0, jfloat x1, jfloat y1, jfloat x2, jfloat y2, jfloat w, jint pow2, jfloatArray resultArray) {
std::vector<SkPoint> pts(1 + 2 * (1 << pow2)); jfloat* points = env->GetFloatArrayElements(resultArray, 0);
int count = SkPath::ConvertConicToQuads({x0, y0}, {x1, y1}, {x2, y2}, w, pts.data(), pow2); int count = SkPath::ConvertConicToQuads({x0, y0}, {x1, y1}, {x2, y2}, w, reinterpret_cast<SkPoint*>(points), pow2);
jobjectArray res = env->NewObjectArray(count, skija::Point::cls, nullptr); env->ReleaseFloatArrayElements(resultArray, points, 0);
for (int i = 0; i < count; ++i) { return count;
env->SetObjectArrayElement(res, i, skija::Point::fromSkPoint(env, pts[i]));
}
return res;
} }
extern "C" JNIEXPORT jobject Java_org_jetbrains_skia_PathKt__1nIsRect extern "C" JNIEXPORT jboolean Java_org_jetbrains_skia_PathKt__1nIsRect
(JNIEnv* env, jclass jclass, jlong ptr) { (JNIEnv* env, jclass jclass, jlong ptr, jfloatArray resultArray) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr)); SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
SkRect rect; SkRect rect;
if (instance->isRect(&rect)) if (instance->isRect(&rect)) {
return skija::Rect::fromSkRect(env, rect); skija::Rect::copyToInterop(env, rect, resultArray);
else return true;
return nullptr; } else {
return false;
}
} }
extern "C" JNIEXPORT void Java_org_jetbrains_skia_PathKt__1nAddRect extern "C" JNIEXPORT void Java_org_jetbrains_skia_PathKt__1nAddRect
...@@ -353,7 +357,7 @@ extern "C" JNIEXPORT void Java_org_jetbrains_skia_PathKt__1nAddRRect ...@@ -353,7 +357,7 @@ extern "C" JNIEXPORT void Java_org_jetbrains_skia_PathKt__1nAddRRect
} }
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nAddPoly extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nAddPoly
(JNIEnv* env, jclass jclass, jlong ptr, jfloatArray coords, jboolean close) { (JNIEnv* env, jclass jclass, jlong ptr, jfloatArray coords, jint _count, jboolean close) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr)); SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
jsize len = env->GetArrayLength(coords); jsize len = env->GetArrayLength(coords);
jfloat* arr = env->GetFloatArrayElements(coords, 0); jfloat* arr = env->GetFloatArrayElements(coords, 0);
...@@ -409,14 +413,16 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nTransform ...@@ -409,14 +413,16 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nTransform
instance->transform(*matrix, dst, pc); instance->transform(*matrix, dst, pc);
} }
extern "C" JNIEXPORT jobject JNICALL Java_org_jetbrains_skia_PathKt__1nGetLastPt extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathKt__1nGetLastPt
(JNIEnv* env, jclass jclass, jlong ptr) { (JNIEnv* env, jclass jclass, jlong ptr, jfloatArray resultArray) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr)); SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
SkPoint out; SkPoint out;
if (instance->getLastPt(&out)) if (instance->getLastPt(&out)) {
return skija::Point::fromSkPoint(env, out); skija::Point::copyToInterop(env, out, resultArray);
else return true;
return nullptr; } else {
return false;
}
} }
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nSetLastPt extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nSetLastPt
...@@ -449,15 +455,20 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nDumpHex ...@@ -449,15 +455,20 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nDumpHex
instance->dumpHex(); instance->dumpHex();
} }
extern "C" JNIEXPORT jbyteArray JNICALL Java_org_jetbrains_skia_PathKt__1nSerializeToBytes extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_PathKt__1nSerializeToBytes
(JNIEnv* env, jclass jclass, jlong ptr) { (JNIEnv* env, jclass jclass, jlong ptr, jbyteArray dstArray) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr)); SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
size_t count = instance->writeToMemory(nullptr); jbyte* dst = dstArray == nullptr ? nullptr : env->GetByteArrayElements(dstArray, 0);
jbyteArray bytesArray = env->NewByteArray((jsize) count); size_t count = instance->writeToMemory(reinterpret_cast<void*>(dst));
jbyte* bytes = env->GetByteArrayElements(bytesArray, 0); if (dst != nullptr) {
instance->writeToMemory(bytes); env->ReleaseByteArrayElements(dstArray, dst, 0);
env->ReleaseByteArrayElements(bytesArray, bytes, 0); }
return bytesArray;
if (count > std::numeric_limits<jint>::max()) {
return -1;
} else {
return count;
}
} }
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_PathKt__1nMakeCombining extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_PathKt__1nMakeCombining
...@@ -473,7 +484,7 @@ extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_PathKt__1nMakeCombini ...@@ -473,7 +484,7 @@ extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_PathKt__1nMakeCombini
} }
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_PathKt__1nMakeFromBytes extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_PathKt__1nMakeFromBytes
(JNIEnv* env, jclass jclass, jbyteArray bytesArray) { (JNIEnv* env, jclass jclass, jbyteArray bytesArray, jint _size) {
SkPath* instance = new SkPath(); SkPath* instance = new SkPath();
int count = env->GetArrayLength(bytesArray); int count = env->GetArrayLength(bytesArray);
jbyte* bytes = env->GetByteArrayElements(bytesArray, 0); jbyte* bytes = env->GetByteArrayElements(bytesArray, 0);
......
...@@ -579,6 +579,15 @@ namespace skija { ...@@ -579,6 +579,15 @@ namespace skija {
} }
return res; return res;
} }
void copyToInterop(JNIEnv* env, const SkPoint& point, jfloatArray pointer) {
jfloat* xy = pointer == nullptr ? nullptr : env->GetFloatArrayElements(pointer, 0);
if (xy != nullptr) {
xy[0] = point.x();
xy[1] = point.y();
env->ReleaseFloatArrayElements(pointer, xy, 0);
}
}
} }
namespace PaintFilterCanvas { namespace PaintFilterCanvas {
...@@ -659,6 +668,17 @@ namespace skija { ...@@ -659,6 +668,17 @@ namespace skija {
jobject fromSkRect(JNIEnv* env, const SkRect& rect) { jobject fromSkRect(JNIEnv* env, const SkRect& rect) {
return fromLTRB(env, rect.fLeft, rect.fTop, rect.fRight, rect.fBottom); return fromLTRB(env, rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
} }
void copyToInterop(JNIEnv* env, const SkRect& rect, jfloatArray pointer) {
jfloat* ltrb = pointer == nullptr ? nullptr : env->GetFloatArrayElements(pointer, 0);
if (ltrb != nullptr) {
ltrb[0] = rect.left();
ltrb[1] = rect.top();
ltrb[2] = rect.right();
ltrb[3] = rect.bottom();
env->ReleaseFloatArrayElements(pointer, ltrb, 0);
}
}
} }
namespace RRect { namespace RRect {
...@@ -761,6 +781,27 @@ namespace skija { ...@@ -761,6 +781,27 @@ namespace skija {
return nullptr; return nullptr;
} }
void copyToInterop(JNIEnv* env, const SkRRect& rect, jfloatArray pointer) {
jfloat* ltrb = pointer == nullptr ? nullptr : env->GetFloatArrayElements(pointer, 0);
if (ltrb != nullptr) {
ltrb[0] = rect.rect().left();
ltrb[1] = rect.rect().top();
ltrb[2] = rect.rect().right();
ltrb[3] = rect.rect().bottom();
ltrb[4] = rect.radii(SkRRect::kUpperLeft_Corner).x();
ltrb[5] = rect.radii(SkRRect::kUpperLeft_Corner).y();
ltrb[6] = rect.radii(SkRRect::kUpperRight_Corner).x();
ltrb[7] = rect.radii(SkRRect::kUpperRight_Corner).y();
ltrb[8] = rect.radii(SkRRect::kLowerRight_Corner).x();
ltrb[9] = rect.radii(SkRRect::kLowerRight_Corner).y();
ltrb[10] = rect.radii(SkRRect::kLowerLeft_Corner).x();
ltrb[11] = rect.radii(SkRRect::kLowerLeft_Corner).y();
env->ReleaseFloatArrayElements(pointer, ltrb, 0);
}
}
} }
namespace RSXform { namespace RSXform {
......
...@@ -250,6 +250,8 @@ namespace skija { ...@@ -250,6 +250,8 @@ namespace skija {
jobject make(JNIEnv* env, float x, float y); jobject make(JNIEnv* env, float x, float y);
jobject fromSkPoint(JNIEnv* env, const SkPoint& p); jobject fromSkPoint(JNIEnv* env, const SkPoint& p);
jobjectArray fromSkPoints(JNIEnv* env, const std::vector<SkPoint>& ps); jobjectArray fromSkPoints(JNIEnv* env, const std::vector<SkPoint>& ps);
void copyToInterop(JNIEnv* env, const SkPoint& point, jfloatArray pointer);
} }
namespace PaintFilterCanvas { namespace PaintFilterCanvas {
...@@ -273,6 +275,8 @@ namespace skija { ...@@ -273,6 +275,8 @@ namespace skija {
std::unique_ptr<SkRect> toSkRect(JNIEnv* env, jobject rect); std::unique_ptr<SkRect> toSkRect(JNIEnv* env, jobject rect);
jobject fromLTRB(JNIEnv* env, float left, float top, float right, float bottom); jobject fromLTRB(JNIEnv* env, float left, float top, float right, float bottom);
jobject fromSkRect(JNIEnv* env, const SkRect& rect); jobject fromSkRect(JNIEnv* env, const SkRect& rect);
void copyToInterop(JNIEnv* env, const SkRect& rect, jfloatArray pointer);
} }
namespace RRect { namespace RRect {
...@@ -291,6 +295,8 @@ namespace skija { ...@@ -291,6 +295,8 @@ namespace skija {
void onUnload(JNIEnv* env); void onUnload(JNIEnv* env);
SkRRect toSkRRect(JNIEnv* env, jfloat left, jfloat top, jfloat right, jfloat bottom, jfloatArray jradii); SkRRect toSkRRect(JNIEnv* env, jfloat left, jfloat top, jfloat right, jfloat bottom, jfloatArray jradii);
jobject fromSkRRect(JNIEnv* env, const SkRRect& rect); jobject fromSkRRect(JNIEnv* env, const SkRRect& rect);
void copyToInterop(JNIEnv* env, const SkRRect& rect, jfloatArray pointer);
} }
namespace RSXform { namespace RSXform {
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <cfloat> #include <cfloat>
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <limits>
#include "SkPath.h" #include "SkPath.h"
#include "SkPathOps.h" #include "SkPathOps.h"
#include "include/utils/SkParsePath.h" #include "include/utils/SkParsePath.h"
...@@ -24,16 +25,10 @@ SKIKO_EXPORT KNativePointer org_jetbrains_skia_Path__1nMake() { ...@@ -24,16 +25,10 @@ SKIKO_EXPORT KNativePointer org_jetbrains_skia_Path__1nMake() {
return reinterpret_cast<KNativePointer>(obj); return reinterpret_cast<KNativePointer>(obj);
} }
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Path__1nMakeFromSVGString
(KInteropPointer d) {
TODO("implement org_jetbrains_skia_Path__1nMakeFromSVGString");
}
#if 0
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Path__1nMakeFromSVGString SKIKO_EXPORT KNativePointer org_jetbrains_skia_Path__1nMakeFromSVGString
(KInteropPointer d) { (KInteropPointer d) {
SkPath* obj = new SkPath(); SkPath* obj = new SkPath();
SkString s = skString(env, d); SkString s = skString(d);
if (SkParsePath::FromSVGString(s.c_str(), obj)) if (SkParsePath::FromSVGString(s.c_str(), obj))
return reinterpret_cast<KNativePointer>(obj); return reinterpret_cast<KNativePointer>(obj);
else { else {
...@@ -41,8 +36,6 @@ SKIKO_EXPORT KNativePointer org_jetbrains_skia_Path__1nMakeFromSVGString ...@@ -41,8 +36,6 @@ SKIKO_EXPORT KNativePointer org_jetbrains_skia_Path__1nMakeFromSVGString
return 0; return 0;
} }
} }
#endif
SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nEquals(KNativePointer aPtr, KNativePointer bPtr) { SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nEquals(KNativePointer aPtr, KNativePointer bPtr) {
SkPath* a = reinterpret_cast<SkPath*>((aPtr)); SkPath* a = reinterpret_cast<SkPath*>((aPtr));
...@@ -84,37 +77,27 @@ SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nIsConvex(KNativePointer ptr) { ...@@ -84,37 +77,27 @@ SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nIsConvex(KNativePointer ptr) {
} }
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Path__1nIsOval(KNativePointer ptr) { SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nIsOval(KNativePointer ptr, KInteropPointer resultArray) {
TODO("implement org_jetbrains_skia_Path__1nIsOval(KInteropPointer");
}
#if 0
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Path__1nIsOval(KNativePointer ptr) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr)); SkPath* instance = reinterpret_cast<SkPath*>((ptr));
SkRect bounds; SkRect bounds;
if (instance->isOval(&bounds)) if (instance->isOval(&bounds)) {
return skija::Rect::fromSkRect(env, bounds); skija::Rect::copyToInterop(bounds, resultArray);
else return true;
return nullptr; } else {
return false;
}
} }
#endif
SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nIsRRect(KNativePointer ptr, KInteropPointer resultArray) {
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Path__1nIsRRect(KNativePointer ptr) {
TODO("implement org_jetbrains_skia_Path__1nIsRRect(KInteropPointer");
}
#if 0
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Path__1nIsRRect(KNativePointer ptr) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr)); SkPath* instance = reinterpret_cast<SkPath*>((ptr));
SkRRect rrect; SkRRect rrect;
if (instance->isRRect(&rrect)) if (instance->isRRect(&rrect)) {
return skija::RRect::fromSkRRect(env, rrect); skija::RRect::copyToInterop(rrect, resultArray);
else return true;
return nullptr; } else {
return false;
}
} }
#endif
SKIKO_EXPORT void org_jetbrains_skia_Path__1nReset(KNativePointer ptr) { SKIKO_EXPORT void org_jetbrains_skia_Path__1nReset(KNativePointer ptr) {
...@@ -165,23 +148,17 @@ SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nIsCubicDegenerate(KFloat x0, KF ...@@ -165,23 +148,17 @@ SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nIsCubicDegenerate(KFloat x0, KF
} }
SKIKO_EXPORT KInteropPointerArray org_jetbrains_skia_Path__1nMaybeGetAsLine(KNativePointer ptr) { SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nMaybeGetAsLine(KNativePointer ptr, KInteropPointer resultArray) {
TODO("implement org_jetbrains_skia_Path__1nMaybeGetAsLine(KInteropPointer");
}
#if 0
SKIKO_EXPORT KInteropPointerArray org_jetbrains_skia_Path__1nMaybeGetAsLine(KNativePointer ptr) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr)); SkPath* instance = reinterpret_cast<SkPath*>((ptr));
SkPoint line[2]; SkPoint line[2];
if (instance->isLine(line)) { if (instance->isLine(line)) {
KInteropPointerArray res = env->NewObjectArray(2, skija::Point::cls, nullptr); SkRect rect = SkRect::MakeLTRB(line[0].x(), line[0].y(), line[1].x(), line[1].y());
env->SetObjectArrayElement(res, 0, skija::Point::fromSkPoint(env, line[0])); skija::Rect::copyToInterop(rect, resultArray);
env->SetObjectArrayElement(res, 1, skija::Point::fromSkPoint(env, line[1])); return true;
return res; } else {
} else return false;
return nullptr; }
} }
#endif
SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nGetPointsCount(KNativePointer ptr) { SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nGetPointsCount(KNativePointer ptr) {
...@@ -189,56 +166,26 @@ SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nGetPointsCount(KNativePointer ptr) ...@@ -189,56 +166,26 @@ SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nGetPointsCount(KNativePointer ptr)
return instance->countPoints(); return instance->countPoints();
} }
SKIKO_EXPORT void org_jetbrains_skia_Path__1nGetPoint(KNativePointer ptr, KInt index, KInteropPointer resultArray) {
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Path__1nGetPoint(KNativePointer ptr, KInt index) {
TODO("implement org_jetbrains_skia_Path__1nGetPoint(KInteropPointer");
}
#if 0
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Path__1nGetPoint(KNativePointer ptr, KInt index) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr)); SkPath* instance = reinterpret_cast<SkPath*>((ptr));
SkPoint p = instance->getPoint(index); skija::Point::copyToInterop(instance->getPoint(index), resultArray);
return skija::Point::fromSkPoint(env, p);
} }
#endif
SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nGetPoints(KNativePointer ptr, KInteropPointer pointsArray, KInt max) {
SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nGetPoints(KNativePointer ptr, KInteropPointerArray pointsArray, KInt max) {
TODO("implement org_jetbrains_skia_Path__1nGetPoints(KInteropPointer");
}
#if 0
SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nGetPoints(KNativePointer ptr, KInteropPointerArray pointsArray, KInt max) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr)); SkPath* instance = reinterpret_cast<SkPath*>((ptr));
std::vector<SkPoint> p(std::min<KInt>(max, instance->countPoints())); SkPoint* points = reinterpret_cast<SkPoint*>(pointsArray);
int count = instance->getPoints(p.data(), max); return instance->getPoints(points, max);
for (int i = 0; i < max && i < count; ++ i)
env->SetObjectArrayElement(pointsArray, i, skija::Point::fromSkPoint(env, p[i]));
return count;
} }
#endif
SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nCountVerbs(KNativePointer ptr) { SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nCountVerbs(KNativePointer ptr) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr)); SkPath* instance = reinterpret_cast<SkPath*>((ptr));
return instance->countVerbs(); return instance->countVerbs();
} }
SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nGetVerbs(KNativePointer ptr, KByte* verbsArray, KInt max) {
TODO("implement org_jetbrains_skia_Path__1nGetVerbs(KInteropPointer");
}
#if 0
SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nGetVerbs(KNativePointer ptr, KByte* verbsArray, KInt max) { SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nGetVerbs(KNativePointer ptr, KByte* verbsArray, KInt max) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr)); SkPath* instance = reinterpret_cast<SkPath*>((ptr));
KByte* verbs = verbsArray == nullptr ? nullptr : env->GetByteArrayElements(verbsArray, 0); return instance->getVerbs(reinterpret_cast<uint8_t *>(verbsArray), max);
int count = instance->getVerbs(reinterpret_cast<uint8_t *>(verbs), max);
if (verbsArray != nullptr)
env->ReleaseByteArrayElements(verbsArray, verbs, 0);
return count;
} }
#endif
SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nApproximateBytesUsed(KNativePointer ptr) { SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nApproximateBytesUsed(KNativePointer ptr) {
...@@ -252,36 +199,22 @@ SKIKO_EXPORT void org_jetbrains_skia_Path__1nSwap(KNativePointer ptr, KNativePoi ...@@ -252,36 +199,22 @@ SKIKO_EXPORT void org_jetbrains_skia_Path__1nSwap(KNativePointer ptr, KNativePoi
instance->swap(*other); instance->swap(*other);
} }
SKIKO_EXPORT void org_jetbrains_skia_Path__1nGetBounds(KNativePointer ptr, KInteropPointer resultArray) {
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Path__1nGetBounds(KNativePointer ptr) {
TODO("implement org_jetbrains_skia_Path__1nGetBounds(KInteropPointer");
}
#if 0
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Path__1nGetBounds(KNativePointer ptr) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr)); SkPath* instance = reinterpret_cast<SkPath*>((ptr));
return skija::Rect::fromSkRect(env, instance->getBounds()); SkRect bounds = instance->getBounds();
skija::Rect::copyToInterop(bounds, resultArray);
} }
#endif
SKIKO_EXPORT void org_jetbrains_skia_Path__1nUpdateBoundsCache(KNativePointer ptr) { SKIKO_EXPORT void org_jetbrains_skia_Path__1nUpdateBoundsCache(KNativePointer ptr) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr)); SkPath* instance = reinterpret_cast<SkPath*>((ptr));
instance->updateBoundsCache(); instance->updateBoundsCache();
} }
SKIKO_EXPORT void org_jetbrains_skia_Path__1nComputeTightBounds(KNativePointer ptr, KInteropPointer resultArray) {
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Path__1nComputeTightBounds(KNativePointer ptr) {
TODO("implement org_jetbrains_skia_Path__1nComputeTightBounds(KInteropPointer");
}
#if 0
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Path__1nComputeTightBounds(KNativePointer ptr) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr)); SkPath* instance = reinterpret_cast<SkPath*>((ptr));
return skija::Rect::fromSkRect(env, instance->computeTightBounds()); SkRect bounds = instance->computeTightBounds();
skija::Rect::copyToInterop(bounds, resultArray);
} }
#endif
SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nConservativelyContainsRect(KNativePointer ptr, float l, float t, float r, float b) { SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nConservativelyContainsRect(KNativePointer ptr, float l, float t, float r, float b) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr)); SkPath* instance = reinterpret_cast<SkPath*>((ptr));
...@@ -370,42 +303,24 @@ SKIKO_EXPORT void org_jetbrains_skia_Path__1nClosePath(KNativePointer ptr) { ...@@ -370,42 +303,24 @@ SKIKO_EXPORT void org_jetbrains_skia_Path__1nClosePath(KNativePointer ptr) {
} }
SKIKO_EXPORT KInteropPointerArray org_jetbrains_skia_Path__1nConvertConicToQuads SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nConvertConicToQuads
(KFloat x0, KFloat y0, KFloat x1, KFloat y1, KFloat x2, KFloat y2, KFloat w, KInt pow2) { (KFloat x0, KFloat y0, KFloat x1, KFloat y1, KFloat x2, KFloat y2, KFloat w, KInt pow2, KInteropPointer resultArray) {
TODO("implement org_jetbrains_skia_Path__1nConvertConicToQuads"); SkPoint* result = reinterpret_cast<SkPoint*>(resultArray);
return SkPath::ConvertConicToQuads({x0, y0}, {x1, y1}, {x2, y2}, w, result, pow2);
} }
#if 0
SKIKO_EXPORT KInteropPointerArray org_jetbrains_skia_Path__1nConvertConicToQuads
(KFloat x0, KFloat y0, KFloat x1, KFloat y1, KFloat x2, KFloat y2, KFloat w, KInt pow2) {
std::vector<SkPoint> pts(1 + 2 * (1 << pow2));
int count = SkPath::ConvertConicToQuads({x0, y0}, {x1, y1}, {x2, y2}, w, pts.data(), pow2);
KInteropPointerArray res = env->NewObjectArray(count, skija::Point::cls, nullptr);
for (int i = 0; i < count; ++i) {
env->SetObjectArrayElement(res, i, skija::Point::fromSkPoint(env, pts[i]));
}
return res;
}
#endif
SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nIsRect
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Path__1nIsRect (KNativePointer ptr, KInteropPointer resultArray) {
(KNativePointer ptr) {
TODO("implement org_jetbrains_skia_Path__1nIsRect");
}
#if 0
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Path__1nIsRect
(KNativePointer ptr) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr)); SkPath* instance = reinterpret_cast<SkPath*>((ptr));
SkRect rect; SkRect rect;
if (instance->isRect(&rect)) if (instance->isRect(&rect)) {
return skija::Rect::fromSkRect(env, rect); skija::Rect::copyToInterop(rect, resultArray);
else return true;
return nullptr; } else {
return false;
}
} }
#endif
SKIKO_EXPORT void org_jetbrains_skia_Path__1nAddRect SKIKO_EXPORT void org_jetbrains_skia_Path__1nAddRect
...@@ -444,20 +359,10 @@ SKIKO_EXPORT void org_jetbrains_skia_Path__1nAddRRect ...@@ -444,20 +359,10 @@ SKIKO_EXPORT void org_jetbrains_skia_Path__1nAddRRect
} }
SKIKO_EXPORT void org_jetbrains_skia_Path__1nAddPoly SKIKO_EXPORT void org_jetbrains_skia_Path__1nAddPoly
(KNativePointer ptr, KFloat* coords, KBoolean close) { (KNativePointer ptr, KFloat* coords, KInt count, KBoolean close) {
TODO("implement org_jetbrains_skia_Path__1nAddPoly");
}
#if 0
SKIKO_EXPORT void org_jetbrains_skia_Path__1nAddPoly
(KNativePointer ptr, KFloat* coords, KBoolean close) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr)); SkPath* instance = reinterpret_cast<SkPath*>((ptr));
jsize len = env->GetArrayLength(coords); instance->addPoly(reinterpret_cast<SkPoint*>(coords), count, close);
KFloat* arr = env->GetFloatArrayElements(coords, 0);
instance->addPoly(reinterpret_cast<SkPoint*>(arr), len / 2, close);
env->ReleaseFloatArrayElements(coords, arr, 0);
} }
#endif
SKIKO_EXPORT void org_jetbrains_skia_Path__1nAddPath SKIKO_EXPORT void org_jetbrains_skia_Path__1nAddPath
...@@ -477,21 +382,14 @@ SKIKO_EXPORT void org_jetbrains_skia_Path__1nAddPathOffset ...@@ -477,21 +382,14 @@ SKIKO_EXPORT void org_jetbrains_skia_Path__1nAddPathOffset
} }
SKIKO_EXPORT void org_jetbrains_skia_Path__1nAddPathTransform
(KNativePointer ptr, KNativePointer srcPtr, KFloat* matrixArr, KBoolean extend) {
TODO("implement org_jetbrains_skia_Path__1nAddPathTransform");
}
#if 0
SKIKO_EXPORT void org_jetbrains_skia_Path__1nAddPathTransform SKIKO_EXPORT void org_jetbrains_skia_Path__1nAddPathTransform
(KNativePointer ptr, KNativePointer srcPtr, KFloat* matrixArr, KBoolean extend) { (KNativePointer ptr, KNativePointer srcPtr, KFloat* matrixArr, KBoolean extend) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr)); SkPath* instance = reinterpret_cast<SkPath*>((ptr));
SkPath* src = reinterpret_cast<SkPath*>((srcPtr)); SkPath* src = reinterpret_cast<SkPath*>((srcPtr));
std::unique_ptr<SkMatrix> matrix = skMatrix(env, matrixArr); std::unique_ptr<SkMatrix> matrix = skMatrix(matrixArr);
SkPath::AddPathMode mode = extend ? SkPath::AddPathMode::kExtend_AddPathMode : SkPath::AddPathMode::kAppend_AddPathMode; SkPath::AddPathMode mode = extend ? SkPath::AddPathMode::kExtend_AddPathMode : SkPath::AddPathMode::kAppend_AddPathMode;
instance->addPath(*src, *matrix, mode); instance->addPath(*src, *matrix, mode);
} }
#endif
SKIKO_EXPORT void org_jetbrains_skia_Path__1nReverseAddPath SKIKO_EXPORT void org_jetbrains_skia_Path__1nReverseAddPath
...@@ -509,40 +407,27 @@ SKIKO_EXPORT void org_jetbrains_skia_Path__1nOffset ...@@ -509,40 +407,27 @@ SKIKO_EXPORT void org_jetbrains_skia_Path__1nOffset
} }
SKIKO_EXPORT void org_jetbrains_skia_Path__1nTransform
(KNativePointer ptr, KFloat* matrixArr, KNativePointer dstPtr, KBoolean pcBool) {
TODO("implement org_jetbrains_skia_Path__1nTransform");
}
#if 0
SKIKO_EXPORT void org_jetbrains_skia_Path__1nTransform SKIKO_EXPORT void org_jetbrains_skia_Path__1nTransform
(KNativePointer ptr, KFloat* matrixArr, KNativePointer dstPtr, KBoolean pcBool) { (KNativePointer ptr, KFloat* matrixArr, KNativePointer dstPtr, KBoolean pcBool) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr)); SkPath* instance = reinterpret_cast<SkPath*>((ptr));
SkPath* dst = reinterpret_cast<SkPath*>((dstPtr)); SkPath* dst = reinterpret_cast<SkPath*>((dstPtr));
std::unique_ptr<SkMatrix> matrix = skMatrix(env, matrixArr); std::unique_ptr<SkMatrix> matrix = skMatrix(matrixArr);
SkApplyPerspectiveClip pc = pcBool ? SkApplyPerspectiveClip::kYes : SkApplyPerspectiveClip::kNo; SkApplyPerspectiveClip pc = pcBool ? SkApplyPerspectiveClip::kYes : SkApplyPerspectiveClip::kNo;
instance->transform(*matrix, dst, pc); instance->transform(*matrix, dst, pc);
} }
#endif
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Path__1nGetLastPt SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nGetLastPt
(KNativePointer ptr) { (KNativePointer ptr, KInteropPointer resultArray) {
TODO("implement org_jetbrains_skia_Path__1nGetLastPt");
}
#if 0
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Path__1nGetLastPt
(KNativePointer ptr) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr)); SkPath* instance = reinterpret_cast<SkPath*>((ptr));
SkPoint out; SkPoint out;
if (instance->getLastPt(&out)) if (instance->getLastPt(&out)) {
return skija::Point::fromSkPoint(env, out); skija::Point::copyToInterop(out, resultArray);
else return true;
return nullptr; } else {
return false;
}
} }
#endif
SKIKO_EXPORT void org_jetbrains_skia_Path__1nSetLastPt SKIKO_EXPORT void org_jetbrains_skia_Path__1nSetLastPt
...@@ -576,23 +461,16 @@ SKIKO_EXPORT void org_jetbrains_skia_Path__1nDumpHex ...@@ -576,23 +461,16 @@ SKIKO_EXPORT void org_jetbrains_skia_Path__1nDumpHex
} }
SKIKO_EXPORT KByte* org_jetbrains_skia_Path__1nSerializeToBytes SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nSerializeToBytes
(KNativePointer ptr) { (KNativePointer ptr, KInteropPointer dst) {
TODO("implement org_jetbrains_skia_Path__1nSerializeToBytes");
}
#if 0
SKIKO_EXPORT KByte* org_jetbrains_skia_Path__1nSerializeToBytes
(KNativePointer ptr) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr)); SkPath* instance = reinterpret_cast<SkPath*>((ptr));
size_t count = instance->writeToMemory(nullptr); size_t count = instance->writeToMemory(reinterpret_cast<void*>(dst));
KByte* bytesArray = env->NewByteArray((jsize) count); if (count > std::numeric_limits<KInt>::max()) {
KByte* bytes = env->GetByteArrayElements(bytesArray, 0); return -1;
instance->writeToMemory(bytes); } else {
env->ReleaseByteArrayElements(bytesArray, bytes, 0); return count;
return bytesArray; }
} }
#endif
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Path__1nMakeCombining SKIKO_EXPORT KNativePointer org_jetbrains_skia_Path__1nMakeCombining
...@@ -609,26 +487,16 @@ SKIKO_EXPORT KNativePointer org_jetbrains_skia_Path__1nMakeCombining ...@@ -609,26 +487,16 @@ SKIKO_EXPORT KNativePointer org_jetbrains_skia_Path__1nMakeCombining
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Path__1nMakeFromBytes SKIKO_EXPORT KNativePointer org_jetbrains_skia_Path__1nMakeFromBytes
(KByte* bytesArray) { (KByte* bytesArray, KInt size) {
TODO("implement org_jetbrains_skia_Path__1nMakeFromBytes");
}
#if 0
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Path__1nMakeFromBytes
(KByte* bytesArray) {
SkPath* instance = new SkPath(); SkPath* instance = new SkPath();
int count = env->GetArrayLength(bytesArray); void* bytes = reinterpret_cast<void*>(bytesArray);
KByte* bytes = env->GetByteArrayElements(bytesArray, 0); if (instance->readFromMemory(bytes, size)) {
if (instance->readFromMemory(bytes, count)) {
env->ReleaseByteArrayElements(bytesArray, bytes, 0);
return reinterpret_cast<KNativePointer>(instance); return reinterpret_cast<KNativePointer>(instance);
} else { } else {
env->ReleaseByteArrayElements(bytesArray, bytes, 0);
delete instance; delete instance;
return 0; return 0;
} }
} }
#endif
SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nGetGenerationId SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nGetGenerationId
......
...@@ -49,6 +49,18 @@ namespace skija { ...@@ -49,6 +49,18 @@ namespace skija {
uint32_t from8To16(size_t i8); uint32_t from8To16(size_t i8);
}; };
namespace Rect {
void copyToInterop(const SkRect& rect, KInteropPointer pointer);
}
namespace RRect {
void copyToInterop(const SkRRect& rect, KInteropPointer pointer);
}
namespace Point {
void copyToInterop(const SkPoint& rect, KInteropPointer pointer);
}
namespace RRect { namespace RRect {
SkRRect toSkRRect(KFloat left, KFloat top, KFloat right, KFloat bottom, KFloat* jradii, KInt size); SkRRect toSkRRect(KFloat left, KFloat top, KFloat right, KFloat bottom, KFloat* jradii, KInt size);
} }
......
...@@ -175,6 +175,48 @@ std::vector<SkString> skStringVector(KInteropPointerArray arr, KInt len) { ...@@ -175,6 +175,48 @@ std::vector<SkString> skStringVector(KInteropPointerArray arr, KInt len) {
} }
namespace skija { namespace skija {
namespace Rect {
void copyToInterop(const SkRect& rect, KInteropPointer pointer) {
float* ltrb = reinterpret_cast<float*>(pointer);
if (ltrb != nullptr) {
ltrb[0] = rect.left();
ltrb[1] = rect.top();
ltrb[2] = rect.right();
ltrb[3] = rect.bottom();
}
}
}
namespace RRect {
void copyToInterop(const SkRRect& rect, KInteropPointer pointer) {
float* ltrb = reinterpret_cast<float*>(pointer);
if (ltrb != nullptr) {
ltrb[0] = rect.rect().left();
ltrb[1] = rect.rect().top();
ltrb[2] = rect.rect().right();
ltrb[3] = rect.rect().bottom();
ltrb[4] = rect.radii(SkRRect::kUpperLeft_Corner).x();
ltrb[5] = rect.radii(SkRRect::kUpperLeft_Corner).y();
ltrb[6] = rect.radii(SkRRect::kUpperRight_Corner).x();
ltrb[7] = rect.radii(SkRRect::kUpperRight_Corner).y();
ltrb[8] = rect.radii(SkRRect::kLowerRight_Corner).x();
ltrb[9] = rect.radii(SkRRect::kLowerRight_Corner).y();
ltrb[10] = rect.radii(SkRRect::kLowerLeft_Corner).x();
ltrb[11] = rect.radii(SkRRect::kLowerLeft_Corner).y();
}
}
}
namespace Point {
void copyToInterop(const SkPoint& point, KInteropPointer pointer) {
float* xy = reinterpret_cast<float*>(pointer);
if (xy != nullptr) {
xy[0] = point.x();
xy[1] = point.y();
}
}
}
namespace RRect { namespace RRect {
SkRRect toSkRRect(KFloat left, KFloat top, KFloat right, KFloat bottom, KFloat* radii, KInt radiiSize) { SkRRect toSkRRect(KFloat left, KFloat top, KFloat right, KFloat bottom, KFloat* radii, KInt radiiSize) {
SkRect rect {left, top, right, bottom}; SkRect rect {left, top, right, bottom};
......
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