Skia overview

来源:互联网 发布:雪纺衫淘宝好评 编辑:程序博客网 时间:2024/06/05 15:06

转自:http://blog.csdn.net/fengbingchun/article/details/38492061

Skia是一个C++的开源2D向量图形处理函数库(Cairo是一个矢量库),包括字型、坐标转换、位图等等,相当于轻量级的Cairo,目前主要用于Google的Android和Chrome平台,Skia搭配OpenGL/ES与特定的硬件特征,强化显示的效果。另外,Skia是WebKit支持的众多图形平台之一,在WebKit的GraphicsContext.h/.c中有相关实现。

Android与Chrome的源代码库中都有一份Skia的复制,因需求不同,做了部分的修改。

Skia需要的底层库有:freetype2,expat,tinyxml。

可以用svn从Google下载源码:svncheckout http://skia.googlecode.com/svn 。

Skia的头文件以及库函数接口是以C++实现的。

代码结构,src目录下:

(1)、animator目录:用来实现Skia的动画效果,Android不支持;

(2)、core目录:Skia的核心,基本都是一些图形绘制函数;

(3)、effects目录:实现一些图形图像的特效效果,包括遮罩、浮雕、模糊、滤镜、渐变色、离散、透明等,并且实现了PATH的各种特效;

(4)gl目录:实现了Skia的图形库,Skia调用OpenGL或OpenGL ES来实现一些简单的3D效果;

(5)、images目录:用来处理images的,支持常见图像的解码、部分图像的编码和动画。Skia能处理的图像类型包括:BMP、JPEG/PVJPEG、PNG、ICO、SkMovie处理gif动画;

(6)、ports目录:是Skia的一些接口在不同系统上的实现,平台相关的代码,比如字体、线程、时间等。这些与Skia的接口,需要针对不同的操作系统实现;

(7)、svg目录:实现了Skia对矢量图SVG的支持,Android不支持;

(8)、utils目录:一些辅助工具类;

(9)、views目录:Skia构建了一套界面UI库;

(10)、xml目录:处理xml的数据,Skia在这里只是对xml解析器做了一层包装,具体的xml解析器的实现需要根据不同的操作系统及宿主程序来实现;

(11)、opts目录:性能优化的代码;

(12)、pdf目录:处理PDF文档,用了一个fpdfemb库;

Skia主要使用的第三方库:Zlib、Jpeglib、Pnglib、giflib、fpdfemb(处理pdf文档)。

Skia引擎在android源代码当中的位置:(1)、头文件:android/external/skia/include,其中还包含几个子目录:animotor,core,effects,images,views,…;(2)、源文件位于:android/external/skia/src目录,子目录结构和头文件目录相同;(3)、封装层:android对Skia引擎进行了封装,以便让java代码方便的调用,对Skia封装的代码存在于android/framework/base/core/jni以及android/framework/base/core/jni/android/graphics目录下面。在Android中Skia以扩展库的形式存在,目录为external/skia。

Skia本身是一个opensource的project,集成于android系统中。所以Skia不是android框架的一部分,不需要实现框架的api来支持Skia。不过Skia同样可以挂接其它的第3方编码解码库或者硬件编解码库。

Android版本不同,Skia版本也不太相同,接口有些细微的差别。

Skia主要包含三个库:(1)、libcorecg.so:包含/skia/src/core的部分内容,比如其中的Region,Rect是在SurfaceFlinger里面用来计算可视区域的;(2)、libsgl.so:包含/skia/src/core|effects|images|ports|utils的部分和全部内容,这个实现了skia大部分的图形效果,以及图形格式的编解码;(3)、libskiagl.so:包含/skia/src/gl里面的内容,主要用来调用opengl实现部分效果。

Skia对上层的接口:Skia的源文件及部分头文件都在external/skia/src目录下,导出的头文件在external/skia/include目录下。最主要的是SKCanvas类,几乎整个AndroidGUI系统的底层绘制都是由这个类来完成的。SKCanvas类主要有三种绘制功能:(1)、基本图形绘制(如drawARGB,drawLine函数);(2)、图像文件绘制(如drawBitmap函数);(3)、文本绘制(drawText函数)。

Skia的图像编解码部分:(1)、/include/image/SKImageDecoder.h:把图像文件或者流解码到skia的内部内存SKBitmap中;(2)、/include/image/SKImageEncoder.h :把skia内部内存SKBitmap编码成文件或流的形式。这些接口需要具体的类实现,主要代码在src/image文件中。

Skia引擎重要类:(1)、SkCanvas:Skia引擎的一个核心类,它封装了所有对设备进行的画图操作.

Skia中用到的硬件加速技术:(1)、OpenGL/OpenGLES;(2)、SIMD:SSE2/SSSE3,NEON.

 

Skia在Windows下的编译:

1、   从https://www.python.org/download/releases/2.7.8/下载python-2.7.8.amd64.msi并安装;安装到D:\ProgramFiles\Python27目录下,并将D:\ProgramFiles\Python27添加到环境变量Path中,重启电脑;

2、    从 https://cygwin.com/install.html 下载setup-x86_64.exe 并安装;

3、   使用svn,下载gyp: http://gyp.googlecode.com/svn/trunk, 将整个gyp文件夹存放到/trunk_no_commit/third_party/externals文件夹下;

4、   在其它分支中将jsoncpp、jsoncpp-chromium、libjpeg、libwebp四个文件夹内容全部拷贝到/trunk_no_commit/third_party/externals文件夹下;

5、   打开Cygwin,将其切换到Skia的trunk_no_commit目录下,执行 python gyp_skia,会生成一个out文件夹,里面有生成的skia.sln工程;

6、   如果在执行python gyp_skia命令过程中,提示/third_party/externals/libwebp/src/dec/frame.c 等文件丢失,则从相关网站下载最新代码替换之即可。

7、   (1)、如果出现errorC2220:warning treated as error -no ‘object’ file generated,则将相应工程中的C/C++->General:Treat Warning As Errors,由原来的Level3(/W3)改为No(/WX-),如effects、gm工程;(2)、选中gm/verttext.cpp文件->File->AdvancedSave Options->Encoding:由原来的Unicode(UTF-8 without signature)-Codepage 65001改为ChineseSimplified(GB2312)-Codepage 936;(3)、如果third_party/extternal中的第三方库文件编译时与其它源代码不匹配,可以通过改动gyp文件夹下的相应.gyp文件来做相应的调整;

8、   通过svn http://skia.googlecode.com/svn下载所有相应的Skia源码,包括branchestrunk,下载后发现没有trunk,只有trunk_no_commit

9、   打开Cygwin,将其定位到trunk_no_commit文件夹,执行 python gyp_skia 命令,如果出现Warning: Missing input files相关信息,说明缺少相关文件,则根据提示查找原因,否则在后期编译时会报错;

10、 正确执行完pythongyp_skia命令后,会在trunk_no_commit目录下生成out文件夹,打开里面的skia.sln,编译SampleApp工程,会生成SampleApp.exe和其它相应静态库。

11、仿照tests工程新创建一个TestSkia工程,工程设置及代码如下:

(1)、Debug和Release下,Character Set:Use Unicode Character Set;

(2)、C/C++ ->Additional Include Directories:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. E:\Skia\code\google\trunk_no_commit\include  
  2. E:\Skia\code\google\trunk_no_commit\include\animator  
  3. E:\Skia\code\google\trunk_no_commit\include\config  
  4. E:\Skia\code\google\trunk_no_commit\include\core  
  5. E:\Skia\code\google\trunk_no_commit\include\device\xps  
  6. E:\Skia\code\google\trunk_no_commit\include\effects  
  7. E:\Skia\code\google\trunk_no_commit\include\gpu  
  8. E:\Skia\code\google\trunk_no_commit\include\gpu\gl  
  9. E:\Skia\code\google\trunk_no_commit\include\images  
  10. E:\Skia\code\google\trunk_no_commit\include\pathops  
  11. E:\Skia\code\google\trunk_no_commit\include\pdf  
  12. E:\Skia\code\google\trunk_no_commit\include\pipe  
  13. E:\Skia\code\google\trunk_no_commit\include\ports  
  14. E:\Skia\code\google\trunk_no_commit\include\record  
  15. E:\Skia\code\google\trunk_no_commit\include\svg  
  16. E:\Skia\code\google\trunk_no_commit\include\text  
  17. E:\Skia\code\google\trunk_no_commit\include\utils  
  18. E:\Skia\code\google\trunk_no_commit\include\utils\win  
  19. E:\Skia\code\google\trunk_no_commit\include\views  
  20. E:\Skia\code\google\trunk_no_commit\include\views\animated  
  21. E:\Skia\code\google\trunk_no_commit\include\xml  
  22. E:\Skia\code\google\trunk_no_commit\tools  
(3)、C/C++ -> Preprocessor: 

Debug:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. WIN32  
  2. _DEBUG  
  3. _CONSOLE  
  4. SK_INTERNAL  
  5. SK_GAMMA_SRGB  
  6. SK_GAMMA_APPLY_TO_A8  
  7. SK_SCALAR_TO_FLOAT_EXCLUDED  
  8. SK_ALLOW_STATIC_GLOBAL_INITIALIZERS=1  
  9. SK_SUPPORT_GPU=1  
  10. SK_SUPPORT_OPENCL=0  
  11. SK_FORCE_DISTANCEFIELD_FONTS=0  
  12. SK_SCALAR_IS_FLOAT  
  13. SK_CAN_USE_FLOAT  
  14. SK_BUILD_FOR_WIN32  
  15. _CRT_SECURE_NO_WARNINGS  
  16. GR_GL_FUNCTION_TYPE=__stdcall  
  17. SK_BUILD_JSON_WRITER  
  18. SK_SUPPORT_PDF  
  19. SK_DEBUG  
  20. SK_DEVELOPER=1  

Release:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. WIN32  
  2. NDEBUG  
  3. _CONSOLE  
  4. SK_INTERNAL  
  5. SK_GAMMA_SRGB  
  6. SK_GAMMA_APPLY_TO_A8  
  7. SK_SCALAR_TO_FLOAT_EXCLUDED  
  8. SK_ALLOW_STATIC_GLOBAL_INITIALIZERS=1  
  9. SK_SUPPORT_GPU=1  
  10. SK_SUPPORT_OPENCL=0  
  11. SK_FORCE_DISTANCEFIELD_FONTS=0  
  12. SK_SCALAR_IS_FLOAT  
  13. SK_CAN_USE_FLOAT  
  14. SK_BUILD_FOR_WIN32  
  15. _CRT_SECURE_NO_WARNINGS  
  16. GR_GL_FUNCTION_TYPE=__stdcall  
  17. SK_BUILD_JSON_WRITER  
  18. SK_SUPPORT_PDF  
  19. SK_RELEASE  

(4)、Linker -> Input -> Additional Dependencies:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. OpenGL32.lib  
  2. usp10.lib  
  3. DelayImp.lib  
  4. windowscodecs.lib  

(5)、将trunk_no_commit->tools->flags中的SkCommandLineFlags两个文件拷贝到此测试工程下并加入到工程中;

(6)、stdafx.h:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #pragma once  
  2.   
  3. #include "targetver.h"  
  4.   
  5. #include <stdio.h>  
  6.   
  7. #include "SkCanvas.h"  
  8. #include "SkData.h"  
  9. #include "SkDocument.h"  
  10. #include "SkForceLinking.h"  
  11. #include "SkGraphics.h"  
  12. #include "SkSurface.h"  
  13. #include "SkImage.h"  
  14. #include "SkStream.h"  
  15. #include "SkString.h"  
  16.   
  17. #include "SkCommandLineFlags.h"  

(7)、stdafx.cpp:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include "stdafx.h"  
  2.   
  3. // TODO: reference any additional headers you need in STDAFX.H  
  4. // and not in this file  
  5. #ifdef _DEBUG  
  6.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/lib/experimental.lib")  
  7.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/lib/libetc1.lib")  
  8.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/lib/libjpeg.lib")  
  9.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/lib/libwebp_dec.lib")  
  10.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/lib/libwebp_dsp.lib")  
  11.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/lib/libwebp_enc.lib")  
  12.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/lib/libwebp_utils.lib")  
  13.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/lib/lua.lib")  
  14.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/lib/skflate.lib")  
  15.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/lib/views_animated.lib")  
  16.   
  17.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_animator.lib")  
  18.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_core.lib")  
  19.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_effects.lib")  
  20.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_images.lib")  
  21.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_opts.lib")  
  22.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_opts_ssse3.lib")  
  23.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_pdf.lib")  
  24.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_ports.lib")  
  25.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_sfnt.lib")  
  26.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_skgpu.lib")  
  27.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_skgputest.lib")  
  28.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_utils.lib")  
  29.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_views.lib")  
  30.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_xml.lib")  
  31. #else  
  32.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/lib/experimental.lib")  
  33.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/lib/libetc1.lib")  
  34.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/lib/libjpeg.lib")  
  35.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/lib/libwebp_dec.lib")  
  36.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/lib/libwebp_dsp.lib")  
  37.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/lib/libwebp_enc.lib")  
  38.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/lib/libwebp_utils.lib")  
  39.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/lib/lua.lib")  
  40.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/lib/skflate.lib")  
  41.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/lib/views_animated.lib")  
  42.   
  43.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_animator.lib")  
  44.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_core.lib")  
  45.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_effects.lib")  
  46.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_images.lib")  
  47.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_opts.lib")  
  48.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_opts_ssse3.lib")  
  49.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_pdf.lib")  
  50.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_ports.lib")  
  51.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_sfnt.lib")  
  52.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_skgpu.lib")  
  53.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_skgputest.lib")  
  54.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_utils.lib")  
  55.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_views.lib")  
  56.     #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_xml.lib")  
  57. #endif  

(8)、TestSkia.cpp:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include "stdafx.h"  
  2. #include <iostream>  
  3.   
  4. using namespace std;  
  5.   
  6. __SK_FORCE_IMAGE_DECODER_LINKING;  
  7.   
  8. DEFINE_string2(outFile, o, "skhello""The filename to write the image.");  
  9. DEFINE_string2(text, t, "Hello""The string to write.");  
  10.   
  11. static void doDraw(SkCanvas* canvas, const SkPaint& paint, const char text[])   
  12. {  
  13.     SkRect bounds;  
  14.     canvas->getClipBounds(&bounds);  
  15.   
  16.     canvas->drawColor(SK_ColorWHITE);  
  17.     canvas->drawText(text, strlen(text), bounds.centerX(), bounds.centerY(), paint);  
  18. }  
  19.   
  20. static bool do_surface(int w, int h, const char path[], const char text[], const SkPaint& paint)   
  21. {  
  22.     SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterPMColor(w, h));  
  23.     doDraw(surface->getCanvas(), paint, text);  
  24.   
  25.     SkAutoTUnref<SkImage> image(surface->newImageSnapshot());  
  26.     SkAutoDataUnref data(image->encode());  
  27.     if (NULL == data.get()) {  
  28.         return false;  
  29.     }  
  30.     SkFILEWStream stream(path);  
  31.     return stream.write(data->data(), data->size());  
  32. }  
  33.   
  34. static bool do_document(int w, int h, const char path[], const char text[], const SkPaint& paint)   
  35. {  
  36.     SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(path));  
  37.     if (doc.get()) {  
  38.         SkScalar width = SkIntToScalar(w);  
  39.         SkScalar height = SkIntToScalar(h);  
  40.         doDraw(doc->beginPage(width, height, NULL), paint, text);  
  41.         return true;  
  42.     }  
  43.     return false;  
  44. }  
  45.   
  46. int tool_main(int argc, char** argv)   
  47. {  
  48.     SkCommandLineFlags::SetUsage("");  
  49.     SkCommandLineFlags::Parse(argc, argv);  
  50.   
  51.     SkAutoGraphics ag;  
  52.     SkString path("skhello");  
  53.     SkString text("Hello");  
  54.   
  55.     if (!FLAGS_outFile.isEmpty()) {  
  56.         path.set(FLAGS_outFile[0]);  
  57.     }  
  58.     if (!FLAGS_text.isEmpty()) {  
  59.         text.set(FLAGS_text[0]);  
  60.     }  
  61.   
  62.     SkPaint paint;  
  63.     paint.setAntiAlias(true);  
  64.     paint.setTextSize(SkIntToScalar(30));  
  65.     paint.setTextAlign(SkPaint::kCenter_Align);  
  66.   
  67.     SkScalar width = paint.measureText(text.c_str(), text.size());  
  68.     SkScalar spacing = paint.getFontSpacing();  
  69.   
  70.     int w = SkScalarRoundToInt(width) + 30;  
  71.     int h = SkScalarRoundToInt(spacing) + 30;  
  72.   
  73.     static const struct {  
  74.         bool (*fProc)(int w, int h, const char path[], const char text[],  
  75.             const SkPaint&);  
  76.         const char* fSuffix;  
  77.     } gRec[] = {  
  78.         { do_surface, ".png" },  
  79.         { do_document, ".pdf" },  
  80.     };  
  81.   
  82.     for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) {  
  83.         SkString file;  
  84.         file.printf("%s%s", path.c_str(), gRec[i].fSuffix);  
  85.         if (!gRec[i].fProc(w, h, file.c_str(), text.c_str(), paint)) {  
  86.             return -1;  
  87.         }  
  88.     }  
  89.     return 0;  
  90. }  
  91.   
  92. int main(int argc, char* argv[])  
  93. {  
  94.     int flag = tool_main(argc, (char**) argv);  
  95.   
  96.     if (flag == 0)  
  97.         cout<<"ok"<<endl;  
  98.     else   
  99.         cout<<"error"<<endl;  
  100.   
  101.     return 0;  
  102. }  

运行此工程,会在此工程目录下生成 skhello.pdf 和 skhello.png 两个文件,文件内容为Hello
0 0