canvas、bitmap、paint之间是什么关系


官方文档翻译过来的解释:

要绘图,需要4个基本组件:

  • Bitmap 保存像素的容器
  • Canvas 执行绘图命令的宿主
  • Rect/Path/text/Bitmap 要绘制的元素
  • Paint 用什么样的方式绘制

android的canvas绘图,基于skia,想要了解canvas的绘图过程,需要对canvasskia的源码有所了解。

查看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;
}

发现如果指定了SkBitmapinitRaster会以指定的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进行写操作,

    而是写入到mBitmapmNativeCanvas自己的SkBitmap中。

  • 源码中指明Canvas最大绘图大小为32766 * 32766。超过这个大小会直接报错。


文章作者: Caden
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Caden !
 上一篇
对javascript中的Variable Object的理解 对javascript中的Variable Object的理解
Variable Object在ECMAScipt中,通过变量对象Variable Object (VO)机制来存贮、访问变量variables。VO中包含了: 1. variables (通过var 声明的变量)2. function
2014-11-01
下一篇 
Drawable小研究 Drawable小研究
Drawable,官方给出的解释是“something that can be drawn”,翻译过来就是可以被画的东西。 官方把“可以被画的东西”分为了7种形式: Bitmap 最简单的“可以被画的东西”,可能是png,或jpg Ni
2014-04-13
  目录