简体   繁体   English

如何在 Android 上的 Java Canvas 对象上使用 SKIA C++ API 进行绘制?

[英]How to draw using the SKIA C++ API on a Java Canvas object on Android?

I am experimenting with native drawing using the Java Canvas API on Android.我正在尝试使用 Android 上的 Java Canvas API 进行本机绘图。 As far as I can understand, Canvas is built as an abstraction on top of SKCanvas from the Skia graphics engine.据我所知,Canvas 是作为Skia图形引擎的SKCanvas之上的抽象构建的。 I'm willing to pass the Canvas object obtained in the OnDraw() method of a view to native code and draw using C++ and the Skia API.我愿意将视图的 OnDraw() 方法中获得的 Canvas 对象传递给本机代码,并使用 C++ 和 Skia API 进行绘制。

What would be the best way to gain access to the SkCanvas pointer after passing the java Canvas object to native code using JNI ?使用JNI将 java Canvas对象传递给本机代码后,访问SkCanvas指针的最佳方法是什么?

Here is the information I have been able to assimilate, which ultimately boils down to accessing a private member from the instance a native platform object .这是我能够吸收的信息,最终归结为从本机平台对象实例访问私有成员

Source code of Canvas.java from https://cs.android.com/android/platform/superproject/+/master:frameworks/base/graphics/java/android/graphics/Canvas.java;l=59 shows that it has private variable named mNativeCanvasWrapper (defined in frameworks/base/graphics/java/android/graphics/BaseCanvas.java ) which can be accessed via reflection through the function declared below.来自https://cs.android.com/android/platform/superproject/+/master:frameworks/base/graphics/java/android/graphics/Canvas.java;l=59Canvas.java的源代码表明它具有名为mNativeCanvasWrapper的私有变量(在frameworks/base/graphics/java/android/graphics/BaseCanvas.java中定义)可以通过下面声明的函数通过反射访问。

/** @hide */
@UnsupportedAppUsage
public long getNativeCanvasWrapper() {
    return mNativeCanvasWrapper;
}

mNativeCanvasWrapper , among other things, is passed to all functions responsible for drawing. mNativeCanvasWrapper被传递给所有负责绘图的函数。 Following the trail of one such function ( getWidth() ), I can see it's JNI registration in https://cs.android.com/android/platform/superproject/+/master:frameworks/base/libs/hwui/jni/android_graphics_Canvas.cpp;l=692跟踪一个这样的函数( getWidth() ),我可以在https://cs.android.com/android/platform/superproject/+/master:frameworks/base/libs/hwui/jni/中看到它的 JNI 注册android_graphics_Canvas.cpp;l=692

{"nGetWidth","(J)I", (void*) CanvasJNI::getWidth},

Definition of CanvasJNI::getWidth() CanvasJNI::getWidth()的定义

static jint getWidth(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle) {
    return static_cast<jint>(get_canvas(canvasHandle)->width());
}

Definition of get_canvas(canvasHandle) get_canvas(canvasHandle)的定义

static Canvas* get_canvas(jlong canvasHandle) {
    return reinterpret_cast<Canvas*>(canvasHandle);
}

The above Canvas* pointer actually points to a class called SkiaCanvas , which inherits from the Canvas base class.上面的Canvas*指针实际上指向了一个名为SkiaCanvas的类,它继承自 Canvas 基类。 Definition for the class can be found at frameworks/base/libs/hwui/SkiaCanvas.cpp .可以在frameworks/base/libs/hwui/SkiaCanvas.cpp中找到该类的定义。 This is the class that contains the actual pointer to the SKCanvas object that I need (marked private), as can be seen at https://cs.android.com/android/platform/superproject/+/master:frameworks/base/libs/hwui/SkiaCanvas.h;l=219 .这是包含指向我需要的SKCanvas对象的实际指针的类(标记为私有),如https://cs.android.com/android/platform/superproject/+/master:frameworks/base/所示库/hwui/SkiaCanvas.h;l=219

How can I obtain the SKCanvas pointer from a SkiaCanvas pointer, given that it's marked private and the only getter is marked protected?考虑到它被标记为私有并且唯一的 getter 被标记为受保护,我如何从SkiaCanvas指针获取SKCanvas指针?

The answer is in two parts.答案分为两部分。
First, getting the Canvas* out of the JNI object:首先,从 JNI 对象中获取Canvas*

jclass cls_Canvas = env->GetObjectClass(obj);
jmethodID mid_Canvas_getNativeCanvasWrapper = env->getMethodID("getNativeCanvasWrapper", "()J");
jlong canvas_ptr = env->CallLongMethod(obj, mid_Canvas_getNativeCanvasWrapper);

The second part goes from there:第二部分从那里开始:

class MyCanvas : public SkiaCanvas { public: SkCanvas* getCanvas() { return asSkCanvas(); };
MyCanvas* skc = reinterpret_cast<MyCanvas*>(canvas_ptr);
SkCanvas* s = myc->getCanvas();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM