🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
下面,来看最后两个和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>& 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>& 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也很简单,这里就不再多说了。