Google Skia is a complete 2D graphic library for drawing Text, Geometries, and Images.
- 3×3 matrices w/ perspective
- antialiasing, transparency, filters
- shaders, xfermodes, maskfilters, patheffects
- subpixel text
Skia是一个C++的开源2D图形库,Raster、OpenGL和PDF目前都在使用它。Skia可提供的功能包括:
- 3 × 3 带角度的矩阵
- 抗锯齿、透明化和滤镜
- 阴影、XFER模式、模板过滤器、通道效果
picture from Google
Chrome开发者Elliot Poger宣布Chrome for Mac将很快换用Skia 2D图形库替换以前的Apple核心图形库,这也使得Linux、Windows和Mac OS X系统使用的图形库完全统一。
使用 Skia 的 API 进行图形绘制时主要会用到一下几个类:其实现代码主要在 src/core 目录下。
- SkBitmap 用来设置像素;
- SkCanvas 写入位图;
- SkPaint 设置颜色和样式;
- SkRect 用来绘制矩形。
使用 Skia 绘图的步骤:
a) 定义一个位图 32 位像素并初始化 SkBitmap bitmap;
b) 分配位图所占的空间
c) 指定输出设备
d) 设备绘制的风格
图形图像特效
skia中effect文件夹中的类继承图
src/effects 目录的文件主要实现一些图形图像的特效,包括 遮罩、浮雕、模糊、滤镜、渐变色、离散、透明以及 PATH 的各种特效等。
除了颜色、笔画、字体大小这样的简单属性,paint也支持effect, effect是绘图管线不同方面的子类,(每个effect都是引用计数的)当一个effect被一个paint引用的时候,将会覆盖paint的绘制管线的一些部分。例如 ,使用gradient代替单个也是,给paint指定一个SkShader:
SkShader* shader = SkGradientShader::CreateLinear(...);
paint.setShader(shader);
shader->unref();
|
现在,所有使用这个paint绘制的东西都会使用由CreateLiner指定的gradient,CreateLiner返回的Shader对象是引用计数的。当一个像shader这样的effect对象被指定给一个paint的时候,paint会增加他的引用计数,为了平衡引用计数,上面的例子调用了shader的unref(),现在这个paint就是shader的唯一拥有者,这样,无论是出了paint作用域或者指定了其他的shader(可以为空),会自动调用shader的unref()。
有6种effect可以绑定到paint:
- SkPathEffect
- SkRasterizer
- SkMaskFilter
- SkMaskFilter的使用介绍:http://www.cnblogs.com/ezhong/archive/2011/11/30/2269501.html
- SkShader 例如三种过渡色方式(linear,radial,sweep),重复模式(clamp,repeat,mirror)
- linear方式GradientShader的使用介绍: http://www.cnblogs.com/ezhong/archive/2011/11/24/2261856.html
- SkColorFilter
- SkXfermode
paint也保持SkTypeface的引用,SkTypeface代表指定的字体风格,可以用来测量和绘制文字,也就是说不仅可以用于绘制文本,还可以用来测量文本
动画
src/animator 目录的文件主要实现了 Skia 的动画效果,Android不支持。
界面 UI 库
src/view 目录 构建了一套界面 UI 库。 组件包括 Window,Menu, TextBox, ListView, ProgressBar, Widget, ScrollBar,TagList,Image 等。
Skia 的图像编解码部分
这部分的接口主要是:
- external/include/image/SKImageDecoder.h // 把图像文件或者流解码到 skia 的内部内存 SKBitmap 中 ;
- external/include/image/SKImageEncoder.h // 把 skia 内部内存 SKBitmap 编码成文件或流的形式;
这些接口需要具体的类实现,主要代码在 src/image 文件中。
Android 图形系统的 JNI 接口
主要提供了从 Skia 底层库到 Java 上层的支持,代码路径为:frameworks/base/core/jni/android/graphic/,主要为 Canvas.cpp 文件。
GDI+是Windows的一套图形绘制库
Windows系统下,所有图形图像绘制,最终都是通过GDI来实现的。在Android下也需要一套能绘制出点、线、面等复杂图形,或者渲染界面等图像方面的一个可供开发者调用的绘图函数接口,Skia就是这套绘制工具。
e.g.现在让你来画一幅画,比如我们的国画—山水画。画一幅画需要哪些工具呢?从常识上来说,我们需要一张纸,比如白纸,或者带有某些背景图的纸张;需要毛笔,不同型号的毛笔;墨汁;颜料等等。然后我们规定在纸张的哪个区域画图,用什么样的毛笔,用什么样的颜色,画什么样的图形,是点、线、面?还是花草等。Skia就是类似上面画图所有需要的一系列设备、工具等。要在Android里画图或者渲染图像,都需要Skia提供的API接口,或者是间接提供。
所有Activity或者View或者其他控件的显示,在底层都是通过Skia提供的函数进行显示的。常见的Canvas类,假如你跟踪一下代码,会发现,Canvas是通过Native方式,调用底层的SkCanvas的。在Android系统下,通过OpenGL ES绘制的3d图形,最终还是被合并到Skia定义的显示缓存中进行显示的。
Skia 主要涉及到的3个库:
- libcorecg.so 包含/skia/src/core的部分内容,比如其中的Region,Rect是在SurfaceFlinger里面计算可是区域的操作基本单位
- libsgl.so 包含/skia/src/core|effects|images|ports|utils的部分和全部内容,这个实现了skia大部分的图形效果,以及图形格式的编解码
- libskiagl.so 包含/skia/src/gl里面的内容,主要用来调用opengl实现部分效果
要想在底层使用skia的接口来画图需要全面了解skia的一整套机制,实际上skia开源到现在还没多久,在网上能找到的资料是也是很粗浅的,如果将来真需要在这方面下功夫肯定是需要一定的工作量的。
Skia在android源码里的目录位置
- 头文件(也可以说是internal API, 因为google没有在NDK里面提供他)位置:android/external/skia/include。其中还包含以下几个子目录:animator, core, effects, images, views…, 最重要的就是core目录了,我们在这里的分析也主要针对core目录里面的API。
- 源文件位于: android/external/skia/src目录,子目录结构和头文件目录相同。
- 封装层:android对Skia引擎进行了封装,以便让java代码方便的调用,对skia封装的代码存在于android/framework/base/core/jni以及android/framework/base/core/jni/android/graphics目录下面。主要是对Canvas, Bitmap, Graphics, Picture等等的封装,以及和libui库的结合使用。
在Android apk里面画图有2种方式 [2D]:
1、Simple Graphics in View
就是直接使用Android已经实现的一些画图操作,比如说images,shapes,colors,pre-defined animation等等,这些简单的画图操作实际上是由skia来提供的2D图形操作。
如贴一张背景图啊,画出简单地形状阿,实现一些简单的动画之类的操作。没有一笔一画地构造出一个图形出来,我们只是把我们的Graphic 资源放入View体系中,由系统 来将这些Graphic画出来。
种方式只能画静态或者极为简单的2D图画,对于实时性很强的动画,高品质的游戏都是没法实现 的。
2、Canvas
首先我们要明白这个Canvas是一个2D的概念,是在Skia中定义的。也就是说在这个方式下还是说的画2D图形。我们可以把这个Canvas理解成系统提供给我们的一块内存区域(但实际上它只是一套画图的API,真正的内存是下面的Bitmap),而且它还提供了一整套对这个内存区域进行操作的方法, 所有的这些操作都是画图API。
能一笔一划或者使用Graphic来画我们所需要的东西了,要画什么要显示什么都由我们自己 控制。这种方式根据环境还分为两种:
- 使用普通View的canvas画图,适合处理量比较小,帧率比较小的动画,比如说象棋游戏之类的
- 使用专门的SurfaceView的canvas来画图。主要用在游戏,高品质动画方面的画图。
- 可以在SurfaceView中定义一个专门的线程来完成画图工作,应用程序不需要等待View的刷图,提高性能。
关于Activity的 :
(1) 首先尽量把UI的设计放在XML中实现,而不要放在代码中实现,这样方便设计,修改和移植 ;
(2) 所有使用到的component都必须在manifest中声明,不然程序中找不到相应的conponet的时候会报错 ;
(3) 一般每一个Activity都对应于一个类和一个相应的布局文件xml ;
(4) 每一个Activity只有使用setContentView()绑定内容后才会显示,而且你才能从这个内容(比如xml中)获取到你需要的元素 ;
(5) res/drawable和res/raw中的元素的区别是drawable中的元素像素可能会被系统优化,而raw中的不会被优化 ;
(6) 当多个Activity都从res/drawable中获得同一个元素,如果其中一个修改它的属性,所有其他的Activity中这个元素的相应属性都会改变 ;
(7) res/anim中保存的是动画相关的xml ;