Unverified Commit b1dfd1ce authored by Oleksandr Karpovich's avatar Oleksandr Karpovich Committed by GitHub

Commonize BitmapTest.kt (#248)

* commonize BitmapTest.kt

* commonize BitmapTest.kt: refactor org_jetbrains_skia_Bitmap__1nGetImageInfo

* commonize BitmapTest.kt: org_jetbrains_skia_Bitmap__1nReadPixels org_jetbrains_skia_Bitmap__1nExtractAlpha org_jetbrains_skia_Bitmap__1nMakeShader

* commonize BitmapTest.kt: fix for CI-found issue

* BitmapTest fixes

* refactor Bitmap.cc

* add `canInstallPixels` to BitmapTest.kt

* refactor org_jetbrains_skia_Bitmap__1nGetImageInfo: remove unnecessary casts
Co-authored-by: 's avatarOleksandr Karpovich <oleksandr.karpovich@jetbrains.com>
parent 27a93c41
...@@ -35,12 +35,21 @@ SKIKO_EXPORT void org_jetbrains_skia_Bitmap__1nSwap ...@@ -35,12 +35,21 @@ SKIKO_EXPORT void org_jetbrains_skia_Bitmap__1nSwap
} }
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Bitmap__1nGetImageInfo SKIKO_EXPORT void org_jetbrains_skia_Bitmap__1nGetImageInfo
(KNativePointer ptr) { (KNativePointer ptr, KInt* imageInfoResult, KNativePointer* colorSpacePtrsArray) {
TODO("implement org_jetbrains_skia_Bitmap__1nGetImageInfo");
SkBitmap* instance = reinterpret_cast<SkBitmap*>(ptr);
SkImageInfo imageInfo = instance->info();
imageInfoResult[0] = instance->width();
imageInfoResult[1] = instance->height();
imageInfoResult[2] = static_cast<int>(imageInfo.colorType());
imageInfoResult[3] = static_cast<int>(imageInfo.alphaType());
colorSpacePtrsArray[0] = imageInfo.refColorSpace().release();
} }
#if 0 #if 0
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Bitmap__1nGetImageInfo SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Bitmap__1nGetImageInfo
(KNativePointer ptr) { (KNativePointer ptr) {
SkBitmap* instance = reinterpret_cast<SkBitmap*>((ptr)); SkBitmap* instance = reinterpret_cast<SkBitmap*>((ptr));
...@@ -141,28 +150,16 @@ SKIKO_EXPORT KBoolean org_jetbrains_skia_Bitmap__1nAllocPixelsRowBytes ...@@ -141,28 +150,16 @@ SKIKO_EXPORT KBoolean org_jetbrains_skia_Bitmap__1nAllocPixelsRowBytes
SKIKO_EXPORT KBoolean org_jetbrains_skia_Bitmap__1nInstallPixels SKIKO_EXPORT KBoolean org_jetbrains_skia_Bitmap__1nInstallPixels
(KNativePointer ptr, KInt width, KInt height, KInt colorType, KInt alphaType, KNativePointer colorSpacePtr, KByte* pixelsArr, KNativePointer rowBytes) { (KNativePointer ptr, KInt width, KInt height, KInt colorType, KInt alphaType, KNativePointer colorSpacePtr, KByte* pixelsArr, KInt rowBytes) {
TODO("implement org_jetbrains_skia_Bitmap__1nInstallPixels"); SkBitmap* instance = reinterpret_cast<SkBitmap*>(ptr);
SkColorSpace* colorSpace = reinterpret_cast<SkColorSpace*>(colorSpacePtr);
SkImageInfo imageInfo = SkImageInfo::Make(width,
height,
static_cast<SkColorType>(colorType),
static_cast<SkAlphaType>(alphaType),
sk_ref_sp<SkColorSpace>(colorSpace));
return instance->installPixels(imageInfo, pixelsArr, rowBytes, nullptr, nullptr);
} }
#if 0
SKIKO_EXPORT KBoolean org_jetbrains_skia_Bitmap__1nInstallPixels
(KNativePointer ptr, KInt width, KInt height, KInt colorType, KInt alphaType, KNativePointer colorSpacePtr, KByte* pixelsArr, KNativePointer rowBytes) {
SkBitmap* instance = reinterpret_cast<SkBitmap*>((ptr));
SkColorSpace* colorSpace = reinterpret_cast<SkColorSpace*>((colorSpacePtr));
SkImageInfo imageInfo = SkImageInfo::Make(width,
height,
static_cast<SkColorType>(colorType),
static_cast<SkAlphaType>(alphaType),
sk_ref_sp<SkColorSpace>(colorSpace));
jsize len = env->GetArrayLength(pixelsArr);
KByte* pixels = new KByte[len];
env->GetByteArrayRegion(pixelsArr, 0, len, pixels);
return instance->installPixels(imageInfo, pixels, rowBytes, deleteJBytes, nullptr);
}
#endif
SKIKO_EXPORT KBoolean org_jetbrains_skia_Bitmap__1nAllocPixels SKIKO_EXPORT KBoolean org_jetbrains_skia_Bitmap__1nAllocPixels
(KNativePointer ptr) { (KNativePointer ptr) {
...@@ -242,32 +239,41 @@ SKIKO_EXPORT KBoolean org_jetbrains_skia_Bitmap__1nExtractSubset ...@@ -242,32 +239,41 @@ SKIKO_EXPORT KBoolean org_jetbrains_skia_Bitmap__1nExtractSubset
} }
SKIKO_EXPORT KByte* org_jetbrains_skia_Bitmap__1nReadPixels // returns true if readBytes array contains successfully read bytes. returns false otherwise
(KNativePointer ptr, KInt width, KInt height, KInt colorType, KInt alphaType, KNativePointer colorSpacePtr, KNativePointer rowBytes, KInt srcX, KInt srcY) { SKIKO_EXPORT KBoolean org_jetbrains_skia_Bitmap__1nReadPixels
TODO("implement org_jetbrains_skia_Bitmap__1nReadPixels"); (KNativePointer ptr, KInt width, KInt height, KInt colorType,
} KInt alphaType, KNativePointer colorSpacePtr, KInt rowBytes, KInt srcX, KInt srcY, KByte* resultBytes
) {
#if 0 SkBitmap* instance = reinterpret_cast<SkBitmap*>(ptr);
SKIKO_EXPORT KByte* org_jetbrains_skia_Bitmap__1nReadPixels SkColorSpace* colorSpace = reinterpret_cast<SkColorSpace*>(colorSpacePtr);
(KNativePointer ptr, KInt width, KInt height, KInt colorType, KInt alphaType, KNativePointer colorSpacePtr, KNativePointer rowBytes, KInt srcX, KInt srcY) {
SkBitmap* instance = reinterpret_cast<SkBitmap*>((ptr));
SkColorSpace* colorSpace = reinterpret_cast<SkColorSpace*>((colorSpacePtr));
SkImageInfo imageInfo = SkImageInfo::Make(width, SkImageInfo imageInfo = SkImageInfo::Make(width,
height, height,
static_cast<SkColorType>(colorType), static_cast<SkColorType>(colorType),
static_cast<SkAlphaType>(alphaType), static_cast<SkAlphaType>(alphaType),
sk_ref_sp<SkColorSpace>(colorSpace)); sk_ref_sp<SkColorSpace>(colorSpace));
std::vector<KByte> pixels(std::min(height, instance->height() - srcY) * rowBytes);
if (instance->readPixels(imageInfo, pixels.data(), rowBytes, srcX, srcY)) if (instance->readPixels(imageInfo, resultBytes, rowBytes, srcX, srcY)) {
return javaByteArray(env, pixels); return true;
else } else {
return nullptr; return false;
}
} }
#endif
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Bitmap__1nExtractAlpha SKIKO_EXPORT KBoolean org_jetbrains_skia_Bitmap__1nExtractAlpha
(KNativePointer ptr, KNativePointer dstPtr, KNativePointer paintPtr) { (KNativePointer ptr, KNativePointer dstPtr, KNativePointer paintPtr, KInt* result) {
TODO("implement org_jetbrains_skia_Bitmap__1nExtractAlpha");
SkBitmap* instance = reinterpret_cast<SkBitmap*>(ptr);
SkBitmap* dst = reinterpret_cast<SkBitmap*>(dstPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
SkIPoint offset;
if (instance->extractAlpha(dst, paint, &offset)) {
result[0] = offset.fX;
result[1] = offset.fY;
return true;
} else {
return false;
}
} }
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Bitmap__1nPeekPixels SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Bitmap__1nPeekPixels
...@@ -276,7 +282,15 @@ SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Bitmap__1nPeekPixels ...@@ -276,7 +282,15 @@ SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Bitmap__1nPeekPixels
} }
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Bitmap__1nMakeShader SKIKO_EXPORT KNativePointer org_jetbrains_skia_Bitmap__1nMakeShader
(KNativePointer ptr, KInt tmx, KInt tmy, KNativePointer samplingMode, KFloat* localMatrixArr) { (KNativePointer ptr, KInt tmx, KInt tmy, KLong samplingMode, KFloat* localMatrixArr) {
TODO("implement org_jetbrains_skia_Bitmap__1nMakeShader"); SkBitmap* instance = reinterpret_cast<SkBitmap*>(ptr);
std::unique_ptr<SkMatrix> localMatrix = skMatrix(localMatrixArr);
sk_sp<SkShader> shader = instance->makeShader(
static_cast<SkTileMode>(tmx),
static_cast<SkTileMode>(tmy),
skija::SamplingMode::unpack(samplingMode),
localMatrix.get()
);
return reinterpret_cast<KNativePointer>(shader.release());
} }
...@@ -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
class Bitmap internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHolder.PTR), IHasImageInfo { class Bitmap internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHolder.PTR), IHasImageInfo {
companion object { companion object {
...@@ -70,7 +71,21 @@ class Bitmap internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerH ...@@ -70,7 +71,21 @@ class Bitmap internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerH
get() = try { get() = try {
if (_imageInfo == null) { if (_imageInfo == null) {
Stats.onNativeCall() Stats.onNativeCall()
_imageInfo = _nGetImageInfo(_ptr) var colorSpacePtr: NativePointer? = null
_imageInfo = withResult(IntArray(4)) { intArrayPointer ->
colorSpacePtr = withResult(NativePointerArray(1)) { nativePointerArrayPtr ->
_nGetImageInfo(_ptr, intArrayPointer, nativePointerArrayPtr)
}[0]
}.let {
ImageInfo(
width = it[0],
height = it[1],
colorType = it[2],
alphaType = it[3],
colorSpace = colorSpacePtr!!
)
}
} }
_imageInfo!! _imageInfo!!
} finally { } finally {
...@@ -126,7 +141,7 @@ class Bitmap internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerH ...@@ -126,7 +141,7 @@ class Bitmap internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerH
* *
* @return byte length of pixel row * @return byte length of pixel row
*/ */
val rowBytes: Long val rowBytes: Int
get() = try { get() = try {
Stats.onNativeCall() Stats.onNativeCall()
_nGetRowBytes(_ptr) _nGetRowBytes(_ptr)
...@@ -371,7 +386,7 @@ class Bitmap internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerH ...@@ -371,7 +386,7 @@ class Bitmap internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerH
* *
* @see [https://fiddle.skia.org/c/@Bitmap_setInfo](https://fiddle.skia.org/c/@Bitmap_setInfo) * @see [https://fiddle.skia.org/c/@Bitmap_setInfo](https://fiddle.skia.org/c/@Bitmap_setInfo)
*/ */
fun setImageInfo(imageInfo: ImageInfo, rowBytes: Long): Boolean { fun setImageInfo(imageInfo: ImageInfo, rowBytes: Int): Boolean {
return try { return try {
_imageInfo = null _imageInfo = null
Stats.onNativeCall() Stats.onNativeCall()
...@@ -448,7 +463,7 @@ class Bitmap internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerH ...@@ -448,7 +463,7 @@ class Bitmap internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerH
* @param rowBytes size of pixel row or larger; may be zero * @param rowBytes size of pixel row or larger; may be zero
* @return true if pixel storage is allocated * @return true if pixel storage is allocated
*/ */
fun allocPixels(info: ImageInfo, rowBytes: Long): Boolean { fun allocPixels(info: ImageInfo, rowBytes: Int): Boolean {
return try { return try {
_imageInfo = null _imageInfo = null
Stats.onNativeCall() Stats.onNativeCall()
...@@ -554,7 +569,7 @@ class Bitmap internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerH ...@@ -554,7 +569,7 @@ class Bitmap internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerH
fun installPixels( fun installPixels(
info: ImageInfo, info: ImageInfo,
pixels: ByteArray?, pixels: ByteArray?,
rowBytes: Long rowBytes: Int
): Boolean { ): Boolean {
return try { return try {
_imageInfo = null _imageInfo = null
...@@ -896,23 +911,28 @@ class Bitmap internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerH ...@@ -896,23 +911,28 @@ class Bitmap internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerH
*/ */
fun readPixels( fun readPixels(
dstInfo: ImageInfo = imageInfo, dstInfo: ImageInfo = imageInfo,
dstRowBytes: Long = rowBytes, dstRowBytes: Int = rowBytes,
srcX: Int = 0, srcX: Int = 0,
srcY: Int = 0 srcY: Int = 0
): ByteArray? { ): ByteArray? {
return try { return try {
val size = min(dstInfo.height, height - srcY) * rowBytes
Stats.onNativeCall() Stats.onNativeCall()
_nReadPixels( withNullableResult(ByteArray(size)) {
_ptr, _nReadPixels(
dstInfo.width, _ptr,
dstInfo.height, dstInfo.width,
dstInfo.colorInfo.colorType.ordinal, dstInfo.height,
dstInfo.colorInfo.alphaType.ordinal, dstInfo.colorInfo.colorType.ordinal,
getPtr(dstInfo.colorInfo.colorSpace), dstInfo.colorInfo.alphaType.ordinal,
dstRowBytes, getPtr(dstInfo.colorInfo.colorSpace),
srcX, dstRowBytes,
srcY srcX,
) srcY,
it
)
}
} finally { } finally {
reachabilityBarrier(this) reachabilityBarrier(this)
reachabilityBarrier(dstInfo.colorInfo.colorSpace) reachabilityBarrier(dstInfo.colorInfo.colorSpace)
...@@ -948,11 +968,16 @@ class Bitmap internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerH ...@@ -948,11 +968,16 @@ class Bitmap internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerH
fun extractAlpha(dst: Bitmap, paint: Paint?): IPoint? { fun extractAlpha(dst: Bitmap, paint: Paint?): IPoint? {
return try { return try {
Stats.onNativeCall() Stats.onNativeCall()
_nExtractAlpha( withNullableResult(IntArray(2)) {
_ptr, _nExtractAlpha(
getPtr(dst), ptr = _ptr,
getPtr(paint) dstPtr = getPtr(dst),
) paintPtr = getPtr(paint),
iPointResultIntArray = it
)
}?.let {
IPoint(x = it[0], y = it[1])
}
} finally { } finally {
reachabilityBarrier(this) reachabilityBarrier(this)
reachabilityBarrier(dst) reachabilityBarrier(dst)
...@@ -1035,7 +1060,7 @@ private external fun _nSwap(ptr: NativePointer, otherPtr: NativePointer) ...@@ -1035,7 +1060,7 @@ private external fun _nSwap(ptr: NativePointer, otherPtr: NativePointer)
private external fun _nGetPixmap(ptr: NativePointer): NativePointer private external fun _nGetPixmap(ptr: NativePointer): NativePointer
@ExternalSymbolName("org_jetbrains_skia_Bitmap__1nGetImageInfo") @ExternalSymbolName("org_jetbrains_skia_Bitmap__1nGetImageInfo")
private external fun _nGetImageInfo(ptr: NativePointer): ImageInfo? private external fun _nGetImageInfo(ptr: NativePointer, imageInfo: InteropPointer, colorSpacePtrs: InteropPointer)
@ExternalSymbolName("org_jetbrains_skia_Bitmap__1nGetRowBytesAsPixels") @ExternalSymbolName("org_jetbrains_skia_Bitmap__1nGetRowBytesAsPixels")
private external fun _nGetRowBytesAsPixels(ptr: NativePointer): Int private external fun _nGetRowBytesAsPixels(ptr: NativePointer): Int
...@@ -1044,7 +1069,7 @@ private external fun _nGetRowBytesAsPixels(ptr: NativePointer): Int ...@@ -1044,7 +1069,7 @@ private external fun _nGetRowBytesAsPixels(ptr: NativePointer): Int
private external fun _nIsNull(ptr: NativePointer): Boolean private external fun _nIsNull(ptr: NativePointer): Boolean
@ExternalSymbolName("org_jetbrains_skia_Bitmap__1nGetRowBytes") @ExternalSymbolName("org_jetbrains_skia_Bitmap__1nGetRowBytes")
private external fun _nGetRowBytes(ptr: NativePointer): Long private external fun _nGetRowBytes(ptr: NativePointer): Int
@ExternalSymbolName("org_jetbrains_skia_Bitmap__1nSetAlphaType") @ExternalSymbolName("org_jetbrains_skia_Bitmap__1nSetAlphaType")
private external fun _nSetAlphaType(ptr: NativePointer, alphaType: Int): Boolean private external fun _nSetAlphaType(ptr: NativePointer, alphaType: Int): Boolean
...@@ -1078,7 +1103,7 @@ private external fun _nSetImageInfo( ...@@ -1078,7 +1103,7 @@ private external fun _nSetImageInfo(
colorType: Int, colorType: Int,
alphaType: Int, alphaType: Int,
colorSpacePtr: NativePointer, colorSpacePtr: NativePointer,
rowBytes: Long rowBytes: Int
): Boolean ): Boolean
...@@ -1102,7 +1127,7 @@ private external fun _nAllocPixelsRowBytes( ...@@ -1102,7 +1127,7 @@ private external fun _nAllocPixelsRowBytes(
colorType: Int, colorType: Int,
alphaType: Int, alphaType: Int,
colorSpacePtr: NativePointer, colorSpacePtr: NativePointer,
rowBytes: Long rowBytes: Int
): Boolean ): Boolean
...@@ -1115,7 +1140,7 @@ private external fun _nInstallPixels( ...@@ -1115,7 +1140,7 @@ private external fun _nInstallPixels(
alphaType: Int, alphaType: Int,
colorSpacePtr: NativePointer, colorSpacePtr: NativePointer,
pixels: InteropPointer, pixels: InteropPointer,
rowBytes: Long rowBytes: Int
): Boolean ): Boolean
...@@ -1163,17 +1188,18 @@ private external fun _nReadPixels( ...@@ -1163,17 +1188,18 @@ private external fun _nReadPixels(
colorType: Int, colorType: Int,
alphaType: Int, alphaType: Int,
colorSpacePtr: NativePointer, colorSpacePtr: NativePointer,
dstRowBytes: Long, dstRowBytes: Int,
srcX: Int, srcX: Int,
srcY: Int srcY: Int,
): ByteArray? resultBytes: InteropPointer
): Boolean
@ExternalSymbolName("org_jetbrains_skia_Bitmap__1nExtractAlpha") @ExternalSymbolName("org_jetbrains_skia_Bitmap__1nExtractAlpha")
private external fun _nExtractAlpha(ptr: NativePointer, dstPtr: NativePointer, paintPtr: NativePointer): IPoint? private external fun _nExtractAlpha(ptr: NativePointer, dstPtr: NativePointer, paintPtr: NativePointer, iPointResultIntArray: InteropPointer): Boolean
@ExternalSymbolName("org_jetbrains_skia_Bitmap__1nPeekPixels") @ExternalSymbolName("org_jetbrains_skia_Bitmap__1nPeekPixels")
private external fun _nPeekPixels(ptr: NativePointer): ByteBuffer? private external fun _nPeekPixels(ptr: NativePointer): ByteBuffer?
@ExternalSymbolName("org_jetbrains_skia_Bitmap__1nMakeShader") @ExternalSymbolName("org_jetbrains_skia_Bitmap__1nMakeShader")
private external fun _nMakeShader(ptr: NativePointer, tmx: Int, tmy: Int, samplingMode: Long, localMatrix: InteropPointer): NativePointer private external fun _nMakeShader(ptr: NativePointer, tmx: Int, tmy: Int, samplingMode: Long, localMatrix: InteropPointer): NativePointer
\ No newline at end of file
...@@ -48,8 +48,8 @@ class ImageInfo(val colorInfo: ColorInfo, val width: Int, val height: Int) { ...@@ -48,8 +48,8 @@ class ImageInfo(val colorInfo: ColorInfo, val width: Int, val height: Int) {
* specifies getBytesPerPixel(). Bitmap maximum value for row bytes must fit * specifies getBytesPerPixel(). Bitmap maximum value for row bytes must fit
* in 31 bits. * in 31 bits.
*/ */
val minRowBytes: Long val minRowBytes: Int
get() = (width * bytesPerPixel).toLong() get() = (width * bytesPerPixel)
val colorType: ColorType val colorType: ColorType
get() = colorInfo.colorType get() = colorInfo.colorType
...@@ -172,7 +172,7 @@ class ImageInfo(val colorInfo: ColorInfo, val width: Int, val height: Int) { ...@@ -172,7 +172,7 @@ class ImageInfo(val colorInfo: ColorInfo, val width: Int, val height: Int) {
* *
* @see [https://fiddle.skia.org/c/@ImageInfo_computeByteSize](https://fiddle.skia.org/c/@ImageInfo_computeByteSize) * @see [https://fiddle.skia.org/c/@ImageInfo_computeByteSize](https://fiddle.skia.org/c/@ImageInfo_computeByteSize)
*/ */
fun computeByteSize(rowBytes: Long): Long { fun computeByteSize(rowBytes: Int): Int {
return if (0 == height) 0 else (height - 1) * rowBytes + width * bytesPerPixel return if (0 == height) 0 else (height - 1) * rowBytes + width * bytesPerPixel
} }
...@@ -185,7 +185,7 @@ class ImageInfo(val colorInfo: ColorInfo, val width: Int, val height: Int) { ...@@ -185,7 +185,7 @@ class ImageInfo(val colorInfo: ColorInfo, val width: Int, val height: Int) {
* *
* @return least memory required by pixel buffer * @return least memory required by pixel buffer
*/ */
fun computeMinByteSize(): Long { fun computeMinByteSize(): Int {
return computeByteSize(minRowBytes) return computeByteSize(minRowBytes)
} }
......
...@@ -51,6 +51,16 @@ inline fun withResult(result: ByteArray, block: (InteropPointer) -> Unit): ByteA ...@@ -51,6 +51,16 @@ inline fun withResult(result: ByteArray, block: (InteropPointer) -> Unit): ByteA
result result
} }
inline fun withNullableResult(result: ByteArray, block: (InteropPointer) -> Boolean): ByteArray? = interopScope {
val handle = toInterop(result)
return if (block(handle)) {
handle.fromInterop(result)
result
} else {
null
}
}
inline fun withResult(result: FloatArray, block: (InteropPointer) -> Unit): FloatArray = interopScope { inline fun withResult(result: FloatArray, block: (InteropPointer) -> Unit): FloatArray = interopScope {
val handle = toInterop(result) val handle = toInterop(result)
block(handle) block(handle)
...@@ -65,6 +75,16 @@ inline fun withResult(result: IntArray, block: (InteropPointer) -> Unit): IntArr ...@@ -65,6 +75,16 @@ inline fun withResult(result: IntArray, block: (InteropPointer) -> Unit): IntArr
result result
} }
inline fun withNullableResult(result: IntArray, block: (InteropPointer) -> Boolean): IntArray? = interopScope {
val handle = toInterop(result)
return if (block(handle)) {
handle.fromInterop(result)
result
} else {
null
}
}
inline fun withResult(result: ShortArray, block: (InteropPointer) -> Unit): ShortArray = interopScope { inline fun withResult(result: ShortArray, block: (InteropPointer) -> Unit): ShortArray = interopScope {
val handle = toInterop(result) val handle = toInterop(result)
block(handle) block(handle)
......
package org.jetbrains.skiko package org.jetbrains.skia
import org.jetbrains.skia.Bitmap import org.jetbrains.skiko.tests.runTest
import org.jetbrains.skia.ColorAlphaType import kotlin.test.*
import org.jetbrains.skia.ImageInfo
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertNotEquals
import kotlin.test.assertTrue
class BitmapTest { class BitmapTest {
@Test @Test
fun bitmapTest() { fun bitmapTest() = runTest {
val bitmap = Bitmap() val bitmap = Bitmap()
val id1: Int = bitmap.generationId val id1: Int = bitmap.generationId
...@@ -23,19 +17,22 @@ class BitmapTest { ...@@ -23,19 +17,22 @@ class BitmapTest {
assertNotEquals(id1, bitmap.generationId) assertNotEquals(id1, bitmap.generationId)
assertFalse(bitmap.isNull) assertFalse(bitmap.isNull)
assertFalse(bitmap.isEmpty) assertFalse(bitmap.isEmpty)
assertEquals(7L * 4, bitmap.rowBytes) assertEquals(7 * 4, bitmap.rowBytes)
assertEquals(4, bitmap.bytesPerPixel) assertEquals(4, bitmap.bytesPerPixel)
assertEquals(7, bitmap.rowBytesAsPixels) assertEquals(7, bitmap.rowBytesAsPixels)
assertTrue(bitmap.imageInfo.colorSpace!!.isSRGB)
bitmap.allocPixels(ImageInfo.makeS32(7, 3, ColorAlphaType.OPAQUE), 32) bitmap.allocPixels(ImageInfo.makeS32(7, 3, ColorAlphaType.OPAQUE), 32)
assertEquals(32L, bitmap.rowBytes) assertEquals(32, bitmap.rowBytes)
assertEquals(4, bitmap.bytesPerPixel) assertEquals(4, bitmap.bytesPerPixel)
assertEquals(8, bitmap.rowBytesAsPixels) assertEquals(8, bitmap.rowBytesAsPixels)
assertTrue(bitmap.imageInfo.colorSpace!!.isSRGB)
bitmap.setImageInfo(ImageInfo.makeS32(7, 3, ColorAlphaType.OPAQUE)) bitmap.setImageInfo(ImageInfo.makeS32(7, 3, ColorAlphaType.OPAQUE))
assertTrue(bitmap.isNull) assertTrue(bitmap.isNull)
assertFalse(bitmap.isEmpty) assertFalse(bitmap.isEmpty)
assertFalse(bitmap.isReadyToDraw) assertFalse(bitmap.isReadyToDraw)
assertTrue(bitmap.imageInfo.colorSpace!!.isSRGB)
bitmap.allocPixels() bitmap.allocPixels()
assertFalse(bitmap.isNull) assertFalse(bitmap.isNull)
...@@ -43,4 +40,46 @@ class BitmapTest { ...@@ -43,4 +40,46 @@ class BitmapTest {
bitmap.generationId bitmap.generationId
} }
}
\ No newline at end of file @Test
fun canMakeShader() = runTest {
val bitmap = Bitmap()
bitmap.allocPixels(ImageInfo.makeS32(25, 25, ColorAlphaType.OPAQUE))
val shader = bitmap.makeShader(Matrix33.makeRotate(45f))
}
@Test
fun canExtractAlpha() = runTest {
val bitmap = Bitmap()
bitmap.allocPixels(ImageInfo.makeS32(25, 25, ColorAlphaType.OPAQUE))
val bitmap2 = Bitmap()
bitmap2.allocPixels(ImageInfo.makeS32(15, 15, ColorAlphaType.OPAQUE))
assertTrue(bitmap.extractAlpha(bitmap2))
}
@Test
fun canReadPixels() = runTest {
val bitmap = Bitmap()
bitmap.allocPixels(ImageInfo.makeS32(10, 10, ColorAlphaType.OPAQUE))
val result = bitmap.readPixels(srcY = 5)!!
assertTrue(bitmap.rowBytes > 0)
assertEquals(5 * bitmap.rowBytes, result.size)
}
@Test
fun canInstallPixels() = runTest {
val bitmap = Bitmap()
bitmap.allocPixels(ImageInfo.makeS32(2, 2, ColorAlphaType.OPAQUE))
val setArray = byteArrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)
assertTrue(bitmap.installPixels(setArray))
val result = bitmap.readPixels()!!
assertTrue(bitmap.rowBytes > 0)
assertEquals(16, result.size)
assertContentEquals(setArray, result)
}
}
...@@ -32,10 +32,21 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_BitmapKt__1nSwap ...@@ -32,10 +32,21 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_BitmapKt__1nSwap
instance->swap(*other); instance->swap(*other);
} }
extern "C" JNIEXPORT jobject JNICALL Java_org_jetbrains_skia_BitmapKt__1nGetImageInfo extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_BitmapKt__1nGetImageInfo
(JNIEnv* env, jclass jclass, jlong ptr) { (JNIEnv* env, jclass jclass, jlong ptr, jintArray imageInfoResult, jlongArray colorSpaceResultPtr) {
SkBitmap* instance = reinterpret_cast<SkBitmap*>(static_cast<uintptr_t>(ptr)); SkBitmap* instance = reinterpret_cast<SkBitmap*>(static_cast<uintptr_t>(ptr));
return skija::ImageInfo::toJava(env, instance->info()); SkImageInfo imageInfo = instance->info();
jint *result_int = env->GetIntArrayElements(imageInfoResult, NULL);
result_int[0] = instance->width();
result_int[1] = instance->height();
result_int[2] = static_cast<int>(imageInfo.colorType());
result_int[3] = static_cast<int>(imageInfo.alphaType());
env->ReleaseIntArrayElements(imageInfoResult, result_int, 0);
jlong *result_long = env->GetLongArrayElements(colorSpaceResultPtr, NULL);
result_long[0] = reinterpret_cast<jlong>(imageInfo.refColorSpace().release());
env->ReleaseLongArrayElements(colorSpaceResultPtr, result_long, 0);
} }
extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_BitmapKt__1nGetRowBytesAsPixels extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_BitmapKt__1nGetRowBytesAsPixels
...@@ -50,7 +61,7 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_BitmapKt__1nIsNull ...@@ -50,7 +61,7 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_BitmapKt__1nIsNull
return instance->isNull(); return instance->isNull();
} }
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_BitmapKt__1nGetRowBytes extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_BitmapKt__1nGetRowBytes
(JNIEnv* env, jclass jclass, jlong ptr) { (JNIEnv* env, jclass jclass, jlong ptr) {
SkBitmap* instance = reinterpret_cast<SkBitmap*>(static_cast<uintptr_t>(ptr)); SkBitmap* instance = reinterpret_cast<SkBitmap*>(static_cast<uintptr_t>(ptr));
return instance->rowBytes(); return instance->rowBytes();
...@@ -93,7 +104,7 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_BitmapKt__1nComput ...@@ -93,7 +104,7 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_BitmapKt__1nComput
} }
extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_BitmapKt__1nSetImageInfo extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_BitmapKt__1nSetImageInfo
(JNIEnv* env, jclass jclass, jlong ptr, jint width, jint height, jint colorType, jint alphaType, jlong colorSpacePtr, jlong rowBytes) { (JNIEnv* env, jclass jclass, jlong ptr, jint width, jint height, jint colorType, jint alphaType, jlong colorSpacePtr, jint rowBytes) {
SkBitmap* instance = reinterpret_cast<SkBitmap*>(static_cast<uintptr_t>(ptr)); SkBitmap* instance = reinterpret_cast<SkBitmap*>(static_cast<uintptr_t>(ptr));
SkColorSpace* colorSpace = reinterpret_cast<SkColorSpace*>(static_cast<uintptr_t>(colorSpacePtr)); SkColorSpace* colorSpace = reinterpret_cast<SkColorSpace*>(static_cast<uintptr_t>(colorSpacePtr));
SkImageInfo imageInfo = SkImageInfo::Make(width, SkImageInfo imageInfo = SkImageInfo::Make(width,
...@@ -117,7 +128,7 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_BitmapKt__1nAllocP ...@@ -117,7 +128,7 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_BitmapKt__1nAllocP
} }
extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_BitmapKt__1nAllocPixelsRowBytes extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_BitmapKt__1nAllocPixelsRowBytes
(JNIEnv* env, jclass jclass, jlong ptr, jint width, jint height, jint colorType, jint alphaType, jlong colorSpacePtr, jlong rowBytes) { (JNIEnv* env, jclass jclass, jlong ptr, jint width, jint height, jint colorType, jint alphaType, jlong colorSpacePtr, jint rowBytes) {
SkBitmap* instance = reinterpret_cast<SkBitmap*>(static_cast<uintptr_t>(ptr)); SkBitmap* instance = reinterpret_cast<SkBitmap*>(static_cast<uintptr_t>(ptr));
SkColorSpace* colorSpace = reinterpret_cast<SkColorSpace*>(static_cast<uintptr_t>(colorSpacePtr)); SkColorSpace* colorSpace = reinterpret_cast<SkColorSpace*>(static_cast<uintptr_t>(colorSpacePtr));
SkImageInfo imageInfo = SkImageInfo::Make(width, SkImageInfo imageInfo = SkImageInfo::Make(width,
...@@ -129,7 +140,7 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_BitmapKt__1nAllocP ...@@ -129,7 +140,7 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_BitmapKt__1nAllocP
} }
extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_BitmapKt__1nInstallPixels extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_BitmapKt__1nInstallPixels
(JNIEnv* env, jclass jclass, jlong ptr, jint width, jint height, jint colorType, jint alphaType, jlong colorSpacePtr, jbyteArray pixelsArr, jlong rowBytes) { (JNIEnv* env, jclass jclass, jlong ptr, jint width, jint height, jint colorType, jint alphaType, jlong colorSpacePtr, jbyteArray pixelsArr, jint rowBytes) {
SkBitmap* instance = reinterpret_cast<SkBitmap*>(static_cast<uintptr_t>(ptr)); SkBitmap* instance = reinterpret_cast<SkBitmap*>(static_cast<uintptr_t>(ptr));
SkColorSpace* colorSpace = reinterpret_cast<SkColorSpace*>(static_cast<uintptr_t>(colorSpacePtr)); SkColorSpace* colorSpace = reinterpret_cast<SkColorSpace*>(static_cast<uintptr_t>(colorSpacePtr));
SkImageInfo imageInfo = SkImageInfo::Make(width, SkImageInfo imageInfo = SkImageInfo::Make(width,
...@@ -221,8 +232,11 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_BitmapKt__1nExtrac ...@@ -221,8 +232,11 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_BitmapKt__1nExtrac
return instance->extractSubset(dst, {left, top, right, bottom}); return instance->extractSubset(dst, {left, top, right, bottom});
} }
extern "C" JNIEXPORT jbyteArray JNICALL Java_org_jetbrains_skia_BitmapKt__1nReadPixels // returns true if readBytes array contains successfully read bytes. returns false otherwise
(JNIEnv* env, jclass jclass, jlong ptr, jint width, jint height, jint colorType, jint alphaType, jlong colorSpacePtr, jlong rowBytes, jint srcX, jint srcY) { extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_BitmapKt__1nReadPixels
(JNIEnv* env, jclass jclass, jlong ptr, jint width, jint height, jint colorType, jint alphaType, jlong colorSpacePtr, jint rowBytes, jint srcX, jint srcY, jbyteArray readBytes) {
jbyte *result_bytes = env->GetByteArrayElements(readBytes, NULL);
SkBitmap* instance = reinterpret_cast<SkBitmap*>(static_cast<uintptr_t>(ptr)); SkBitmap* instance = reinterpret_cast<SkBitmap*>(static_cast<uintptr_t>(ptr));
SkColorSpace* colorSpace = reinterpret_cast<SkColorSpace*>(static_cast<uintptr_t>(colorSpacePtr)); SkColorSpace* colorSpace = reinterpret_cast<SkColorSpace*>(static_cast<uintptr_t>(colorSpacePtr));
SkImageInfo imageInfo = SkImageInfo::Make(width, SkImageInfo imageInfo = SkImageInfo::Make(width,
...@@ -230,23 +244,30 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_org_jetbrains_skia_BitmapKt__1nRead ...@@ -230,23 +244,30 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_org_jetbrains_skia_BitmapKt__1nRead
static_cast<SkColorType>(colorType), static_cast<SkColorType>(colorType),
static_cast<SkAlphaType>(alphaType), static_cast<SkAlphaType>(alphaType),
sk_ref_sp<SkColorSpace>(colorSpace)); sk_ref_sp<SkColorSpace>(colorSpace));
std::vector<jbyte> pixels(std::min(height, instance->height() - srcY) * rowBytes); if (instance->readPixels(imageInfo, result_bytes, rowBytes, srcX, srcY)) {
if (instance->readPixels(imageInfo, pixels.data(), rowBytes, srcX, srcY)) env->ReleaseByteArrayElements(readBytes, result_bytes, 0);
return javaByteArray(env, pixels); return true;
else } else {
return nullptr; return false;
}
} }
extern "C" JNIEXPORT jobject JNICALL Java_org_jetbrains_skia_BitmapKt__1nExtractAlpha extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_BitmapKt__1nExtractAlpha
(JNIEnv* env, jclass jclass, jlong ptr, jlong dstPtr, jlong paintPtr) { (JNIEnv* env, jclass jclass, jlong ptr, jlong dstPtr, jlong paintPtr, jintArray resultPoint) {
SkBitmap* instance = reinterpret_cast<SkBitmap*>(static_cast<uintptr_t>(ptr)); SkBitmap* instance = reinterpret_cast<SkBitmap*>(static_cast<uintptr_t>(ptr));
SkBitmap* dst = reinterpret_cast<SkBitmap*>(static_cast<uintptr_t>(dstPtr)); SkBitmap* dst = reinterpret_cast<SkBitmap*>(static_cast<uintptr_t>(dstPtr));
SkPaint* paint = reinterpret_cast<SkPaint*>(static_cast<uintptr_t>(paintPtr)); SkPaint* paint = reinterpret_cast<SkPaint*>(static_cast<uintptr_t>(paintPtr));
SkIPoint offset; SkIPoint offset;
if (instance->extractAlpha(dst, paint, &offset))
return skija::IPoint::fromSkIPoint(env, offset); jint *result_int = env->GetIntArrayElements(resultPoint, NULL);
else if (instance->extractAlpha(dst, paint, &offset)) {
return nullptr; result_int[0] = offset.fX;
result_int[1] = offset.fY;
env->ReleaseIntArrayElements(resultPoint, result_int, 0);
return true;
} else {
return false;
}
} }
extern "C" JNIEXPORT jobject JNICALL Java_org_jetbrains_skia_BitmapKt__1nPeekPixels extern "C" JNIEXPORT jobject JNICALL Java_org_jetbrains_skia_BitmapKt__1nPeekPixels
......
...@@ -47,11 +47,11 @@ internal class SoftwareContextHandler(layer: SkiaLayer) : ContextHandler(layer) ...@@ -47,11 +47,11 @@ internal class SoftwareContextHandler(layer: SkiaLayer) : ContextHandler(layer)
override fun initCanvas() { override fun initCanvas() {
disposeCanvas() disposeCanvas()
val scale = layer.contentScale val scale = layer.contentScale
val w = (layer.width * scale).toInt().coerceAtLeast(0) val w = (layer.width * scale).toInt().coerceAtLeast(0)
val h = (layer.height * scale).toInt().coerceAtLeast(0) val h = (layer.height * scale).toInt().coerceAtLeast(0)
if (storage.width != w || storage.height != h) { if (storage.width != w || storage.height != h) {
storage.allocPixelsFlags(ImageInfo.makeS32(w, h, ColorAlphaType.PREMUL), false) storage.allocPixelsFlags(ImageInfo.makeS32(w, h, ColorAlphaType.PREMUL), false)
} }
...@@ -67,7 +67,7 @@ internal class SoftwareContextHandler(layer: SkiaLayer) : ContextHandler(layer) ...@@ -67,7 +67,7 @@ internal class SoftwareContextHandler(layer: SkiaLayer) : ContextHandler(layer)
val h = (layer.height * scale).toInt().coerceAtLeast(0) val h = (layer.height * scale).toInt().coerceAtLeast(0)
val bytes = storage.readPixels(storage.imageInfo, (w * 4).toLong(), 0, 0) val bytes = storage.readPixels(storage.imageInfo, (w * 4), 0, 0)
if (bytes != null) { if (bytes != null) {
val buffer = DataBufferByte(bytes, bytes.size) val buffer = DataBufferByte(bytes, bytes.size)
raster = Raster.createInterleavedRaster( raster = Raster.createInterleavedRaster(
......
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