android系统对于可以随内容拉伸的9宫格png图片处理流程分析如下:
(1)隶属于canvas and Drawables,查看官方介绍可以知道java层面的类和函数关系:
----->android.graphics.drawable.NinePatchDrawable
----->NinePatchDrawable.draw(Canvas canvas)-画图函数,把png图片画到canvas上去。
(2)在源代码frameworks\base\graphics\java\android\graphics\NinePatch.java里面有方法:
---->public void draw(Canvas canvas, Rect location)
----->nativeDraw() (本地调用,需要查看jni文件)
(3)在源代码frameworks\base\core\jni\android\graphics目录下定义:
NinePatch.cpp
---->{ "nativeDraw", "(ILandroid/graphics/RectF;I[BIII)V",(void*)SkNinePatchGlue::drawF }, (浮点边界值类型??)
----> { "nativeDraw", "(ILandroid/graphics/Rect;I[BIII)V", (void*)SkNinePatchGlue::drawI }, (整数边界值类型??)
(4)最终调用skia图形库函数,具体算法有待进一步分析。
(5)drawI 和drawF最终调用的是NinePatchImpl.cpp中的NinePatch_Draw,里面有具体流程,有待分析。
(6)如何判断9.png图片是有区域定义的呢??分析如下:
android/graphics/BitmapFactory.java里面是解析图片流方法类,其中有一行:
private static Bitmap finishDecode(Bitmap bm,Rect outPadding,Options opts)
函数里面有判断是否是9png格式的函数:
final boolean isNinePatch=np!=null&&NinePatch.isNinePatchChunk(np);
跟踪NinePatch.isNinePatchChunk(np)函数,是本地调用,查看frameworks\base\core\jni\android\graphics里面有定义类NinePatch.cpp类,在文件最后定义了isNinePatchChunk方法。这个方法是判断9png格式文件的主要方法。
(7)查看isNinePatchChunk函数有一行:
const Res_png_9patch* chunk =reinterpret_cast<const Res_png_9patch*>(array);
看看Res_png_9patch的定义:
struct Res_png_9patch
{ ...
int8_t wasDeserialized;
int8_t numXDivs;
int8_t numYDivs;
int8_t numColors;
// These tell where the next section of a patch starts.
// For example, the first patch includes the pixels from
// 0 to xDivs[0]-1 and the second patch includes the pixels
// from xDivs[0] to xDivs[1]-1.
// Note: allocation/free of these pointers is left to the caller.
int32_t* xDivs;
int32_t* yDivs;
int32_t paddingLeft, paddingRight;
int32_t paddingTop, paddingBottom;
enum {
// The 9 patch segment is not a solid color.
NO_COLOR = 0x00000001,
// The 9 patch segment is completely transparent.
TRANSPARENT_COLOR = 0x00000000
};
// Note: allocation/free of this pointer is left to the caller.
uint32_t* colors;
}
其中开头就定义了是否9png格式。