8.3.4 Surface和画图
最后更新于:2022-04-02 05:52:20
下面,来看最后两个和Surface相关的函数调用:一个是lockCanvas;另外一个是unlockCanvasAndPost。
1. lockCanvas的分析
要对lockCanvas进行分析,须先来看Java层的函数,代码如下所示:
**Surface.java::lockCanvas()**
~~~
public Canvas lockCanvas(Rect dirty)
throws OutOfResourcesException,IllegalArgumentException
{
return lockCanvasNative(dirty);//调用native的lockCanvasNative函数。
}
~~~
**android_view_Surface.cpp::Surface_lockCanvas()**
~~~
static jobject Surface_lockCanvas(JNIEnv* env,jobject clazz, jobject dirtyRect)
{
//从Java中的Surface对象中,取出费尽千辛万苦得到的Native的Surface对象
constsp& surface(getSurface(env, clazz));
......
// dirtyRect表示需要重绘的矩形块,下面根据这个dirtyRect设置dirtyRegion
RegiondirtyRegion;
if(dirtyRect) {
Rect dirty;
dirty.left =env->GetIntField(dirtyRect, ro.l);
dirty.top =env->GetIntField(dirtyRect, ro.t);
dirty.right = env->GetIntField(dirtyRect, ro.r);
dirty.bottom=env->GetIntField(dirtyRect, ro.b);
if(!dirty.isEmpty()) {
dirtyRegion.set(dirty);
}
} else{
dirtyRegion.set(Rect(0x3FFF,0x3FFF));
}
//调用NativeSurface对象的lock函数,
//传入了一个参数Surface::SurfaceInfo info和一块表示脏区域的dirtyRegion
Surface::SurfaceInfo info;
status_t err = surface->lock(&info, &dirtyRegion);
......
//Java的Surface对象构造的时候会创建一个CompatibleCanvas。
//这里就取出这个CompatibleCanvas对象
jobject canvas = env->GetObjectField(clazz, so.canvas);
env->SetIntField(canvas, co.surfaceFormat, info.format);
//从Canvas对象中取出SkCanvas对象
SkCanvas* nativeCanvas =(SkCanvas*)env->GetIntField(
canvas, no.native_canvas);
SkBitmap bitmap;
ssize_t bpr = info.s *bytesPerPixel(info.format);
bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, bpr);
......
if (info.w > 0 && info.h > 0) {
//info.bits指向一块存储区域。
bitmap.setPixels(info.bits);
} else{
bitmap.setPixels(NULL);
}
//给这个SkCanvas设置一个Bitmap,还记得前面说的,画图需要的四大金刚吗?
//这里将Bitmap设置到这个Canvas中,这样进UI绘画时就有画布了。
nativeCanvas->setBitmapDevice(bitmap);
......
returncanvas;
}
~~~
lockCanvas还算比较简单:
- 先获得一块存储区域,然后将它和Canvas绑定到一起,这样,UI绘画的结果就记录在这块存储区域里了。
注意,本书不拟讨论Android系统上Skia和OpenGL方面的知识,有兴趣的读者可自行研究。
接下来看unlockCanvasAndPost函数,它也是一个native函数:
2. unlockCanvasAndPost的分析
来看unlockCanvasAndPost的代码,如下所示:
**android_view_Surface.cpp**
~~~
static void Surface_unlockCanvasAndPost(JNIEnv*env, jobject clazz,
jobject argCanvas)
{
jobjectcanvas = env->GetObjectField(clazz, so.canvas);
//取出Native的Surface对象
const sp& surface(getSurface(env,clazz));
//下面这些内容,不拟讨论,读者若有兴趣,可结合Skia库,自行研究。
SkCanvas* nativeCanvas =(SkCanvas*)env->GetIntField(canvas,
no.native_canvas);
intsaveCount = env->GetIntField(clazz, so.saveCount);
nativeCanvas->restoreToCount(saveCount);
nativeCanvas->setBitmapDevice(SkBitmap());
env->SetIntField(clazz, so.saveCount, 0);
//调用Surface对象的unlockAndPost函数。
status_t err = surface->unlockAndPost();
......
}
~~~
unlockCanvasAndPost也很简单,这里就不再多说了。
';