Unverified Commit 9e73ff16 authored by Ivan Matkov's avatar Ivan Matkov Committed by GitHub

Revert 0.8.22 changes: remove `PictureFilterCanvas` (#1013)

That approach worked but had performance issues. Also, `SkPicture` is
immutable by design, so we shouldn't try to change that.

#1014 is a more correct and efficient way to implement it
parent 555dcff9
package org.jetbrains.skia
import org.jetbrains.skia.impl.Library.Companion.staticLoad
import org.jetbrains.skia.impl.NativePointer
import org.jetbrains.skia.impl.Stats
import org.jetbrains.skia.impl.getPtr
import org.jetbrains.skia.impl.reachabilityBarrier
abstract class PictureFilterCanvas(canvas: Canvas) :
Canvas(makePictureFilterCanvas(canvas), true, this) {
private companion object {
init {
staticLoad()
}
}
init {
Stats.onNativeCall()
try {
doInit(_ptr)
} finally {
reachabilityBarrier(this)
}
}
protected abstract fun onDrawPicture(picture: Picture, matrix: Matrix33? = null, paint: Paint? = null): Boolean
fun onDrawPicture(picturePtr: NativePointer, matrixPtr: NativePointer, paintPtr: NativePointer): Boolean {
val picture = Picture(picturePtr, managed = false)
// TODO: Provide mapping for matrix arg
val paint = if (paintPtr == NullPointer) null else Paint(paintPtr, managed = false)
return onDrawPicture(picture, null, paint)
}
}
private fun makePictureFilterCanvas(canvas: Canvas): NativePointer {
Stats.onNativeCall()
return try {
PictureFilterCanvas_nMake(getPtr(canvas))
} finally {
reachabilityBarrier(canvas)
}
}
internal expect fun PictureFilterCanvas.doInit(ptr: NativePointer)
@ExternalSymbolName("org_jetbrains_skia_PictureFilterCanvas__1nMake")
@ModuleImport("./skiko.mjs", "org_jetbrains_skia_PictureFilterCanvas__1nMake")
private external fun PictureFilterCanvas_nMake(canvasPtr: NativePointer): NativePointer
package org.jetbrains.skia
import kotlin.test.Test
import kotlin.test.assertEquals
class PictureFilterCanvasTest {
@Test
fun canOverrideOnDrawPicture() {
val surface = Surface.makeRasterN32Premul(16, 16)
val bounds = Rect(0f, 0f, 16f, 16f)
var callCount = 0
// Prepare picture
val recorder = PictureRecorder()
val recordingCanvas = recorder.beginRecording(bounds)
val placeholder = Picture.makePlaceholder(bounds)
recordingCanvas.drawPicture(placeholder)
val picture = recorder.finishRecordingAsPicture()
// Filtering
val filterCanvas = object : PictureFilterCanvas(surface.canvas) {
override fun onDrawPicture(picture: Picture, matrix: Matrix33?, paint: Paint?): Boolean {
callCount++
drawRect(
Rect(0f, 0f, 8f, 8f),
Paint().apply { color = Color.RED }
)
return true
}
}
filterCanvas.drawPicture(picture)
filterCanvas.close()
// Render result
val pixels = Bitmap.makeFromImage(surface.makeImageSnapshot())
assertEquals(1, callCount)
assertEquals(Color.RED, pixels.getColor(2, 2))
placeholder.close()
picture.close()
recorder.close()
surface.close()
}
}
\ No newline at end of file
#include <jni.h>
#include "SkNWayCanvas.h"
#include "interop.hh"
class SkikoPictureFilterCanvas : public SkNWayCanvas {
public:
SkikoPictureFilterCanvas(SkCanvas* canvas) :
SkNWayCanvas(canvas->imageInfo().width(), canvas->imageInfo().height()),
_jobject(nullptr) {
this->addCanvas(canvas);
}
virtual ~SkikoPictureFilterCanvas() {
skija::PictureFilterCanvas::detach(_jobject);
}
jobject _jobject;
protected:
void onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) override {
jboolean handled = skija::PictureFilterCanvas::onDrawPicture(_jobject, picture, matrix, paint);
if (!handled) {
SkCanvas::onDrawPicture(picture, matrix, paint);
}
}
};
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PictureFilterCanvas_1jvmKt_PictureFilterCanvas_1nInit
(JNIEnv* env, jclass jclass, jobject pictureFilterCanvas, jlong canvasPtr) {
SkikoPictureFilterCanvas* canvas = reinterpret_cast<SkikoPictureFilterCanvas*>(static_cast<uintptr_t>(canvasPtr));
canvas->_jobject = skija::PictureFilterCanvas::attach(env, pictureFilterCanvas);
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_PictureFilterCanvasKt_PictureFilterCanvas_1nMake
(JNIEnv* env, jclass jclass, SkCanvas* canvas) {
SkikoPictureFilterCanvas* filterCanvas = new SkikoPictureFilterCanvas(canvas);
return reinterpret_cast<jlong>(filterCanvas);
}
...@@ -653,39 +653,6 @@ namespace skija { ...@@ -653,39 +653,6 @@ namespace skija {
} }
} }
namespace PictureFilterCanvas {
JavaVM* _vm;
jmethodID onDrawPictureId;
void onLoad(JNIEnv* env) {
env->GetJavaVM(&_vm);
jclass local = env->FindClass("org/jetbrains/skia/PictureFilterCanvas");
onDrawPictureId = env->GetMethodID(local, "onDrawPicture", "(JJJ)Z");
}
void onUnload(JNIEnv* env) {
}
bool onDrawPicture(jobject obj, const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
JNIEnv *env;
_vm->AttachCurrentThread(AS_JNI_ENV_PTR(&env), NULL);
jboolean result = env->CallBooleanMethod(obj, onDrawPictureId, reinterpret_cast<jlong>(picture), reinterpret_cast<jlong>(matrix), reinterpret_cast<jlong>(paint));
_vm->DetachCurrentThread();
return result;
}
jobject attach(JNIEnv* env, jobject obj) {
return env->NewGlobalRef(obj);
}
void detach(jobject obj) {
JNIEnv *env;
_vm->AttachCurrentThread(AS_JNI_ENV_PTR(&env), NULL);
env->DeleteGlobalRef(obj);
_vm->DetachCurrentThread();
}
}
namespace Rect { namespace Rect {
jclass cls; jclass cls;
jmethodID makeLTRB; jmethodID makeLTRB;
...@@ -930,7 +897,6 @@ namespace skija { ...@@ -930,7 +897,6 @@ namespace skija {
PathSegment::onLoad(env); PathSegment::onLoad(env);
Point::onLoad(env); Point::onLoad(env);
PaintFilterCanvas::onLoad(env); PaintFilterCanvas::onLoad(env);
PictureFilterCanvas::onLoad(env);
Rect::onLoad(env); Rect::onLoad(env);
RRect::onLoad(env); RRect::onLoad(env);
RSXform::onLoad(env); RSXform::onLoad(env);
...@@ -943,7 +909,6 @@ namespace skija { ...@@ -943,7 +909,6 @@ namespace skija {
RRect::onUnload(env); RRect::onUnload(env);
Rect::onUnload(env); Rect::onUnload(env);
PaintFilterCanvas::onUnload(env); PaintFilterCanvas::onUnload(env);
PictureFilterCanvas::onUnload(env);
Point::onUnload(env); Point::onUnload(env);
PathSegment::onUnload(env); PathSegment::onUnload(env);
Path::onUnload(env); Path::onUnload(env);
......
...@@ -272,15 +272,6 @@ namespace skija { ...@@ -272,15 +272,6 @@ namespace skija {
void detach(jobject obj); void detach(jobject obj);
} }
namespace PictureFilterCanvas {
extern jmethodID onDrawPictureId;
void onLoad(JNIEnv* env);
void onUnload(JNIEnv* env);
bool onDrawPicture(jobject obj, const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint);
jobject attach(JNIEnv* env, jobject obj);
void detach(jobject obj);
}
namespace Rect { namespace Rect {
extern jclass cls; extern jclass cls;
extern jmethodID makeLTRB; extern jmethodID makeLTRB;
......
package org.jetbrains.skia
import org.jetbrains.skia.impl.NativePointer
internal actual fun PictureFilterCanvas.doInit(ptr: NativePointer) {
PictureFilterCanvas_nInit(this, ptr)
}
private external fun PictureFilterCanvas_nInit(thisPtr: PictureFilterCanvas, canvasPtr: NativePointer)
#include "SkNWayCanvas.h"
#include "common.h"
class SkikoPictureFilterCanvas : public SkNWayCanvas {
public:
SkikoPictureFilterCanvas(SkCanvas* canvas) :
SkNWayCanvas(canvas->imageInfo().width(), canvas->imageInfo().height()),
_onDrawPicture(nullptr),
_onDrawPicture_picture(nullptr),
_onDrawPicture_matrix(nullptr),
_onDrawPicture_paint(nullptr) {
this->addCanvas(canvas);
}
KBooleanCallback _onDrawPicture;
// TODO: Support callback with parameters properly
const SkPicture* _onDrawPicture_picture;
const SkMatrix* _onDrawPicture_matrix;
const SkPaint* _onDrawPicture_paint;
protected:
void onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) override {
_onDrawPicture_picture = picture;
_onDrawPicture_matrix = matrix;
_onDrawPicture_paint = paint;
KBoolean handled = _onDrawPicture();
_onDrawPicture_picture = nullptr;
_onDrawPicture_matrix = nullptr;
_onDrawPicture_paint = nullptr;
if (!handled) {
SkCanvas::onDrawPicture(picture, matrix, paint);
}
}
};
SKIKO_EXPORT KNativePointer org_jetbrains_skia_PictureFilterCanvas__1nMake
(SkCanvas* canvas) {
SkikoPictureFilterCanvas* filterCanvas = new SkikoPictureFilterCanvas(canvas);
return reinterpret_cast<KNativePointer>(filterCanvas);
}
SKIKO_EXPORT void org_jetbrains_skia_PictureFilterCanvas__1nInit
(KNativePointer canvasPtr, KInteropPointer onDrawPicture) {
SkikoPictureFilterCanvas* canvas = reinterpret_cast<SkikoPictureFilterCanvas*>(canvasPtr);
canvas->_onDrawPicture = KBooleanCallback(onDrawPicture);
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_PictureFilterCanvas__1nGetOnDrawPicture_picture
(KNativePointer canvasPtr) {
SkikoPictureFilterCanvas* canvas = reinterpret_cast<SkikoPictureFilterCanvas*>(canvasPtr);
return reinterpret_cast<KNativePointer>(const_cast<SkPicture *>(canvas->_onDrawPicture_picture));
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_PictureFilterCanvas__1nGetOnDrawPicture_matrix
(KNativePointer canvasPtr) {
SkikoPictureFilterCanvas* canvas = reinterpret_cast<SkikoPictureFilterCanvas*>(canvasPtr);
return reinterpret_cast<KNativePointer>(const_cast<SkMatrix *>(canvas->_onDrawPicture_matrix));
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_PictureFilterCanvas__1nGetOnDrawPicture_paint
(KNativePointer canvasPtr) {
SkikoPictureFilterCanvas* canvas = reinterpret_cast<SkikoPictureFilterCanvas*>(canvasPtr);
return reinterpret_cast<KNativePointer>(const_cast<SkPaint *>(canvas->_onDrawPicture_paint));
}
package org.jetbrains.skia
import org.jetbrains.skia.impl.InteropPointer
import org.jetbrains.skia.impl.NativePointer
import org.jetbrains.skia.impl.interopScope
internal actual fun PictureFilterCanvas.doInit(ptr: NativePointer) {
interopScope {
val onFilter = virtualBoolean {
onDrawPicture(
picturePtr = PictureFilterCanvas_nGetOnDrawPicture_picture(ptr),
matrixPtr = PictureFilterCanvas_nGetOnDrawPicture_matrix(ptr),
paintPtr = PictureFilterCanvas_nGetOnDrawPicture_paint(ptr)
)
}
PictureFilterCanvas_nInit(ptr, onFilter)
}
}
@ExternalSymbolName("org_jetbrains_skia_PictureFilterCanvas__1nInit")
@ModuleImport("./skiko.mjs", "org_jetbrains_skia_PictureFilterCanvas__1nInit")
internal external fun PictureFilterCanvas_nInit(ptr: NativePointer, onFilter: InteropPointer)
@ExternalSymbolName("org_jetbrains_skia_PictureFilterCanvas__1nGetOnDrawPicture_picture")
@ModuleImport("./skiko.mjs", "org_jetbrains_skia_PictureFilterCanvas__1nGetOnDrawPicture_picture")
internal external fun PictureFilterCanvas_nGetOnDrawPicture_picture(ptr: NativePointer): NativePointer
@ExternalSymbolName("org_jetbrains_skia_PictureFilterCanvas__1nGetOnDrawPicture_matrix")
@ModuleImport("./skiko.mjs", "org_jetbrains_skia_PictureFilterCanvas__1nGetOnDrawPicture_matrix")
internal external fun PictureFilterCanvas_nGetOnDrawPicture_matrix(ptr: NativePointer): NativePointer
@ExternalSymbolName("org_jetbrains_skia_PictureFilterCanvas__1nGetOnDrawPicture_paint")
@ModuleImport("./skiko.mjs", "org_jetbrains_skia_PictureFilterCanvas__1nGetOnDrawPicture_paint")
internal external fun PictureFilterCanvas_nGetOnDrawPicture_paint(ptr: NativePointer): NativePointer
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