canvas、bitmap、paint之间是什么关系
官方文档翻译过来的解释:要绘图,需要4个基本组件:Bitmap 保存像素的容器Canvas 执行绘图命令的宿主Rect/Path/text/Bitmap 要绘制的元素Paint 用什么样的方式绘制android的canvas绘图,基于skia,想要了解canvas的绘图过程,需要对canvas和skia的源码有所了解。查看Canvas源码,发现Canvas与Bitmap类似,都
官方文档翻译过来的解释:
要绘图,需要4个基本组件:
- Bitmap 保存像素的容器
- Canvas 执行绘图命令的宿主
- Rect/Path/text/Bitmap 要绘制的元素
- Paint 用什么样的方式绘制
android的canvas绘图,基于skia,想要了解canvas的绘图过程,需要对canvas和skia的源码有所了解。
查看Canvas源码,发现Canvas与Bitmap类似,都是对其native方法进行了封装。
真正起绘图作用的是mNativeCanvas
,保存有nativeCanvas(SkCanvas)的指针。
mNativeCanvas
注释上指明
assigned in constructors or setBitmap, freed in finalizer
说明mNativeCanvas(SkCanvas)
是在构造函数、或者setBitmap
时分配的。
继续查看源码,发现mNativeCanvas
是调用native方法
initRaster(int nativeBitmapOrZero)
方法生成。
initRaster
中的参数就是Canvas私有属性mBitmap
的nativeBitmap(SkBitmap)的指针。
查看frameworks/base/core/jni/android/graphics/下的Canvas.cpp文件,
static SkCanvas* initRaster(JNIEnv* env, jobject, SkBitmap* bitmap) {
return bitmap ? new SkCanvas(*bitmap) : new SkCanvas;
}
发现如果指定了SkBitmap,initRaster
会以指定的SkBitmap生成SkCanvas;
反之会生成默认的SkCanvas。
继续查看android/external/skia/src/core/下SkCanvas的源码,
默认构造函数
SkCanvas::SkCanvas()
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
inc_canvas();
this->init(NULL);
}
init
方法调用setDevice
方法,生成默认的SkDevice,而SkDeveice最终会生成默认的SkBitmap
总结
-
Canvas的属性
mNativeCanvas(SkCanvas)
是根据mBitmap
生成的,如果mBitmap
不为空,则
mNativeCanvas
操作/修改的SkBitmap就是mBitmap
;否则会操作/修改
mNativeCanvas
自己的SkBitmap. -
Canvas最终操作/修改的内存还是Bitmap(SkBitmap)中的数据.
-
Canvas(bitmap)
与canvas.setBitmap(bitmap)
中的bitmap是Canvas的mBitmap
,直接操作/修改的对象。canvas.drawBitmap(bitmap)
中的bitmap是源bitmap,draw时,不对源bitmap进行写操作,而是写入到
mBitmap
或mNativeCanvas
自己的SkBitmap中。 -
源码中指明Canvas最大绘图大小为32766 * 32766。超过这个大小会直接报错。
更多推荐
所有评论(0)