[英]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=59的
Canvas.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.