2008 年九月,Google 宣布以改良过的 WebKit 为核心的网络浏览器 Chrome,揭露了众多新特征,比方说崭新的 [V8] JavaScript (ECMAscript) 执行引擎,或许因为太亮眼,掩蔽了所使用另一个开放原始码项目 [skia], 后者是个 2D 向量图形处理函式库,包含字型、坐标转换,以及位图都有高效能且简洁的表现。不仅用于 Google Chrome浏览器,新兴的 Android 开放手机平台也采用 skia 作为绘图处理,搭配 OpenGL/ES 与特定的硬件特征,强化显示的效果,本文简介 Google Skia 的历史背景、应用层面,并探讨其程序设计模型。

Google 为了搭建 Open Handset Alliance (OHA) 的 Android 平台,布局极久,背后的百人研发团队部份来自之前的并购案,其中两项具指标性意义:

  • 2005 年八月 17 日,收购美国 Android 公司,业务是手机软件开发,这当然就是现在开放源码Android 计划的前身
  • 2005 年十一月,收购美国 Skia 公司,业务是向量绘图软件

被 Google 收购前的 Android 公司有着在 IT 产业为人所津津乐道的成果,本文就不多谈,而 Skia公司自然也不是省油的灯。Skia Inc. 设立于北卡罗莱纳州的 Chapel HIll,由 Michael Reed (也称为Mike Reed) 所创办,他在图形技术领域是相当顶尖的人物,与 Benoit Schillings (BeOS 主要开发者, Be Inc. 第二位工程师,现为 Nokia CTO) 于专业手机软件开发公司 OpenWave 共事时,即在该公司产品 OpenWave Phone Suite Version 7.0 (以下简称 V7) 引入精湛的向量图形技术,在 50-300 kb 空间的实做中,提供了图层 overlay 之间 alpha blended 预览、全功能向量矩阵转换等进阶功能。在加入 OpenWave 之前,Mike Reed 服务于 Apple,代表项目为 QuickDraw GX,主导进阶图形与字型处理技术。Benoit Schillings 离开 OpenWave 转任 Trolltech CTO 期间,Mike Reed 开创了 Skia Inc.,该公司第一个产品为 SGL (Skia Graphics Library),一个非常严谨的向量显示引擎,能在低端设备比如手机、电视及其它手持设备之上,呈现高质量的 2D 图形。根据 LocalTechWire 的描述:

"Skia’s first product, SGL, is a portable graphics engine capable of rendering state-of-the-art 2D graphics on low-end devices such as mobile phones, TVs, and handhelds,” the Web site said. “SGL is feature-set compatible with existing 2D standards, making it ideal to serve as a back-end for public formats such as SVG, PDF, and OpenVG. SGL is licensed as source or binary, and can be customized to match specific HW/framebuffer requirements.”

自 2005 年 Skia 被 Google 收购后,一直相当神秘低调,直到 2007 年初,Skia GL 相关的程序代码才被揭露,作为Google Android 平台的图形引擎,稍候的 Google Chrome 浏览器也采用 Skia 引擎。随着 Android 与 Chrome (开放版本称为 "Chromium") 两大项目公布程序代码后,skia 也一并公开原始程序代码,以 Apache License v2 释出 (注意,这意味着与 GPLv2 授权不兼容),而 Android 与 Chrome 的程序代码库中都有一份 [skia] 的复制,因需求不同,做了部份的修改,比方说 Chrome 项目底下的 [chrome/trunk/src/skia], 需要注意的是,Skia 本身是不涉及底层环境,如 Linux Framebuffer 或 Gtk+ 衔接的处理,这也是何以 Android (透过 Linux Framebuffer) 与Chrome (开发中的 Linux 版本使用 Gtk+) 需要提供一份修改,以便系统接轨,关于这方面的信息,可参照 Google Chromium 的开发日志 [Graphics in Google Chrome]

相较于 Firefox 1.x,后继的 Firefox 2.x/3.x 在图形显示方面有相当大的进展,很大层面归功于引入 Cario 向量图形链接库来处理网页绘制,而 Skia 就相当于扮演 Cairo 的角色,不过更轻量些。快速发展的 WebKit 俨然是从桌面应用跨足移动装置之网页引擎解决方案的首选,Apple 与 Google 都有为数可观的全职工程师投入,拜因特网的威力,也有其它厂商与团体个人积极投入开发,目前 WebKit 支持的图形函式库计有 Cairo, Gtk+, Qt4, WxWidgets, Cg (Mac 的非开放原始码函式库), Skia 等等,并以 WebKit 中 class GraphicsContext 处理前述图形函式库的实做,可针对不同平台的特性,规范不同平台所需的宏与成员,详情可参考程序代码 WebCore/platform/graphics/GraphicsContext.{h,cpp}。
Skia 以 C++ 实做,程序代码约八万行,基本某些未知的因素,可参考的文件相当有限,但 Chromium 的 SVN log 与程序代码则是现在最完整的文件,以下是其特征:

  • 高度优化的软件 rasteriser (module sgl/)
  • 选择性透过 OpenGL/ES,加速特定操作,如 shader 与 textures (module gl/)
  • 动画处理能力(module animator/)
  • 内建 SVG 支援 (module (svg/)
  • 内建若干 image codec,如 PNG, JPEG, GIF, BMP (modules images/)
  • 内建文字处理,但缺乏泰文、藏文一类复杂文字处理的能力
  • 效能特性:
    • 对 image 与特定数据型态的 Copy-on-write
    • 内部存储器管理,谨慎地被免 fragmentation
    • Thread-safety

Skia 实做所需的相依性:

  • 字型: FreeType (值得注意的是,FreeType 的维护者 David Turner 目前任职于 Google), Windows GDI
  • 多执行绪模型: pthread, Windows threads
  • XML: expat, tinyxml

理解历史背景,我们终于可以来作点有趣的事。首先,自 Google Code 取得 Skia 原始程序代码:

# svn co http://skia.googlecode.com/svn/trunk skia-trunk

乍看这「清爽」的目录架构,很难想象过去这是商业软件,或许 Google 有些「不能说的秘密」,除了 samplecode/ 目录若干的程序代码之外,就几乎没有充分的文档了。用 svn log 可浏览 Skia 开发的纪录,"reed@android.com" 就是 Mike Reed 本人,至今仍相当活跃地改良 Skia 的实做。编译方式很单纯,先看看说明:(本文对应于 svn r130)

# cd skia-trunk

# make help

可得到以下说明:

Targets:

: out/libskia.a

bench: out/bench/bench

tests: out/tests/tests

clean: removes entire out/ directory

help: this text

Options: (after make, or in bash shell)

SKIA_DEBUG=true for debug build

SKIA_SCALAR=fixed for fixed-point build

SKIA_BUILD_FOR=mac for mac build (e.g. CG for image decoding)

期望的编译输出就是静态函式库 out/libskia.a,而 Skia 的内部运算可选择浮点数与定点 (fixed-point),不过笔者发现,目前尙未能透地选择,但这不影响我们理解 Skia 的使用与体验其威力。以笔者使用的 GNU/Linux 来说,可下达以下指令要求编译:

# make SKIA_BUILD_FOR=linux

没意外的话,系统就会乖乖的编译:

compiling out/src/core/Sk64.o

compiling out/src/core/SkAlphaRuns.o

compiling out/src/core/SkBitmap.o

...

至于编译 benchmark 程序,则可透过以下指令:

# make SKIA_BUILD_FOR=linux bench

benchmark 程序算是除了 Chromium 之外,最佳的「文件」了,不过 SKia API 本来就简洁强大,这也不妨碍。执行 benchmark 程序:

./out/bench/bench -o `pwd`

陆续会有类似以下的输出:

running bench          polygon

running bench            lines

running bench           points

running bench          rrects3

running bench          rrects1

running bench           ovals3

running bench           ovals1

running bench           rects3

running bench           rects1

running bench    bitmap_index8

running bench      bitmap_4444

running bench       bitmap_565

running bench      bitmap_8888

可大概窥知 Skia 涵盖的范畴,接着笔者就写个小程序,使用 Skia C++ API: [test-skia.c]

/* Simple vector graphics demo utilizing Skia toolkit.

* Authored by Jim Huang <jserv.tw@gmail.com>

*/

#include "SkBitmap.h"

#include "SkDevice.h"

#include "SkPaint.h"

#include "SkImageEncoder.h"

{

// Declare a raster bitmap, which has an integer width and height,

// and a format (config), and a pointer to the actual pixels.

// Bitmaps can be drawn into a SkCanvas, but they are also used to

SkBitmap bitmap;

bitmap.setConfig(SkBitmap::kARGB_8888_Config, 200, 200);

bitmap.allocPixels();

// device (bitmap).  This includes a reference to the device itself,

// and a stack of matrix/clip values. For any given draw call (e.g.

// drawRect), the geometry of the object being drawn is transformed

// by the concatenation of all the matrices in the stack. The

// transformed geometry is clipped by the intersection of all of the

SkCanvas canvas(new SkDevice(bitmap));

// draw geometries, text and bitmaps.

SkPaint paint;

r.set(25, 25, 145, 145);

canvas.drawRect(r, paint); /** Draw the specified rectangle using

the specified paint. The rectangle

will be filled or stroked based on

the Style in the paint. */

r.offset(20, 20);

canvas.drawRect(r, paint);

r.offset(20, 20);

canvas.drawRect(r, paint);

// from a specific SkBitmap.

SkImageEncoder::EncodeFile("snapshot.png", bitmap,

SkImageEncoder::kPNG_Type,

/* Quality ranges from 0..100 */ 100);

return 0;

}

编译方式:

g++ \

-I./include \

-I./include/core \

-I./include/images \

-Wall -o test-skia test-skia.c \

out/src/images/SkImageDecoder_libpng.o out/libskia.a \

-lpng -lpthread -g

笔者做了简要的批注,大概可知晓 Sk 开头的这些 API 的功用,而上述的范例程序一开始就要求Skia 配置画布 (SkCanvas),接着透过一份 SkRect 对象 r,给定 ARGB 的描述,使其有着不同的颜色,再来就是调整向量对象的位移并绘制。正如前文提及,Skia 仅是绘图引擎,并未如 Cairo 一般广泛对应到 PDF, X11, GDI 等等底层绘图装置,所以为了方便观察绘图结果,我们透过 Skia 内建的image codec 来输出 PNG 图档,所以执行前述编译后的执行档 "test-skia",应该会得到以下图档:(本无外框与底色,但为了清楚于文章呈现,额外用绘图软件追加)

<!--[if !vml]--><!--[endif]-->

迭合的三个不同色的矩形对象,就是透过以下 API 呼叫达成:

paint.setARGB(255, 0, 255, 0);

r.offset(20, 20);

canvas.drawRect(r, paint);

由于 Skia 与 Cairo 的同构型相当高,也可参照 [Cairo :: documentation] 建立所需的背景知识。

http://yp.oss.org.cn/software/show_resource.php?resource_id=192

// SkImageEncoder is the base class for encoding compressed images

paint.setARGB(255, 0, 0, 255);

paint.setARGB(255, 0, 255, 0);

paint.setARGB(255, 255, 0, 0);

SkRect r;

// SkIRect holds four 32 bit integer coordinates for a rectangle.

// SkPaint class holds the style and color information about how to

// clips in the stack.

// A Canvas encapsulates all of the state about drawing into a

// specify the target of a SkCanvas' drawing operations.

int main()

#include "SkRect.h"

另一篇文章:

使用vs编译所有的skia 文件 ,然后会得到大概3500条错误消息。这很可能 是某些宏定义不正确,或者某些编译开关没有正确设置 ,或者某些接口没有实现等。但编译器给出的错误消息往往对解决 问题没有帮助,编译器给出的绝大部分错误 都是不可能出错的地方,标准的C++语法。于是只能先看一下SKIA的结构。
使用svn从 http://code.google.com/p/skia/ 下载最新的代码,没有任何文档信息。skia的源文件及部分头文件都在skia/src目录下,导出的头文件在skia/include 目录下。打开Skia源文件夹,主要有以下部分:
animator 目录
顾名思意,这部分是用来实现Skia的动画效果。主要包含79个CPP文件。从文件名来看,主要分为以下几类:
以SkAnimator开头的一些文件,SkAnimatorActive,SkAnimatorBase,SkAnimatorField,SkAnimatorSet,SkAnimatorScript等。
以SkDisplay开头的一些文件,SkDisplayAdle, SkDisplayAdd, SkDisplayEvents, SkDisplayList, SkDisplayInput, SkDisplayMovie等等。
以SkDraw开头的一些文件,SkDraw3D, SkDrawBitmap, SkDrawClip, SkDrawColor, SkDrawBlur, SkDrawLine, SkDrawPaint, SkDrawPath, SkDrawPoint等。
以SkScript开头的一些文件,包括SkScript, SkScriptRuntime, SkScriptDecompile等。
这里,skia实现了一个脚本语言,可能是用于控制动画。
skia的这个脚本语言包括基本的数学运算:加(ADD)、减(SUB)、乘(MUL)、除(DIV)、模(MOD);基本逻辑及判断:大于(GT)、小 于(LT)、等于(EQ)、与(AND)、或(OR)、非(NOT)等;还包括基本的位运算(bit operation)。
在这个脚本中,主要有以下几个数据 类型:NoType, Int, Scalar(等同于Float), String, Array, Object。
这个目录下还包含一些辅助性的文件,如SkBase64, SkTime等。
core 目录
这就是skia的核心了,主要包含89个CPP文件。
基本都是一些图形绘制函数。
主要包括SkColor, SkCanvas,SkBitmap,SkPicture,SkBlitter,SkCordic,SkPath,SkPoint,SkRect,SkRegion,SkMask 等等图形绘制类,还包括一些辅助性的类文件,sk64, skbuffer, skutils等。
skia是分层次绘制的,当需要绘制时,通知每个layer上对象的canvas来绘制。
effects 目录
这是skia实现一些图形图像效果的部分
主要包括20个CPP文件。
主要实现了以下特效:遮罩、浮雕、模糊、滤镜、渐变色、离散、透明等。
并且实现了PATH的各种特效。
gl 目录
从名字看,并不知道这是做什么用的,gl=graphics library,图形库。
主要包括7个CPP文件。
开打SkGL.h,可以发现
#ifdef SK_BUILD_FOR_MAC
    #include <OpenGL/gl.h>
    #include <OpenGL/glext.h>
    #include <AGL/agl.h>
    // use FBOs for devices
    #define SK_GL_DEVICE_FBO
#elif defined(ANDROID)
    #include <GLES/gl.h>
    #include <EGL/egl.h>
#endif
所以,这部分是skia调用OpenGL或OpenGL ES来实现3D效果。
如果定义了MAC,则使用OpenGL,如果定义了Android,则使用嵌入式系统 上的esgl三维图形库。porting的时候要加上#elif defined(SYMBIAN)之类的,防止别的地方也有android宏定义。
打开SkGL,发现是几个基本的材质贴图函数。
images目录
这部分是用来处理images的,共23个CPP文件和一些头文件。
主要是SkImageDecoder和SkImageEncoder以及SkMovie。
Skia能处理的图像类型包括以下
BMP
JPEG/PVJPEG
PNG
ICO
另外,skia还能处理PDF文档。
使用了一个fpdfemb库。
而SkMovie就是处理gif动画。
ports目录
这部分是skia的一些接口在不同系统上的实现,共24个CPP文件。
主要包括几个部分:Font,Event,File,Thread,Time,XMLParser
这些与Skia的接口,需要针对不同的操作系统 实现。
svg 目录
这个目录包含28个CPP文件,从文件名看,都是一些画图文件。
SkSVGPath, SkSVGPolyline, SkSVGRect, SkSVGText, SkSVGLine, SkSVGImage, SkSVGEllipse等等。
utils 目录
包含9个CPP文件,是一些辅助工具类。
SkCamera, SkColorMatrix,SkOSFile,SkProxyCanvas,SkInterpolator等文件
views目录
这个目录包含24个CPP文件。
skia构建了一套界面UI库。
组件包括Window,Menu, TextBox, ListView, ProgressBar, Widget, ScrollBar,TagList,Image等。
还有组件的事件类。
window对象负责接收事件,并传递给当前focus对象,若无focus对象,则focus自身。focus对象处理相应的key events和mouse events。
在SkiView基类类中定义并实现了draw, acceptFocus,moveFocus,click等方法。
xml 目录
当然,这是处理xml数据的部分了。
skia在这里只是对xml解析器做了一层包装,具体的xml解析器的实现需要根据不同的操作系统及宿主程序来实现。

third-party library
以上就是所有的skia source code了,当然,仅仅依靠这些是不可能编译通过了,skia还使用了一些third-party library以及包含了不少linux 上的头文件。
通过分析skia源程序,发现skia主要使用以下几个第三方库:
Zlib,处理数据的压缩和解压缩
Jpeglib,处理jpeg图像的编码解码
Pnglib,处理png图像的编码解码
giflib,处理gif图像
fpdfemb,处理pdf文档
skia还需要一些linux/unix下的头文件(可能还需要更多):
stdint.h
unistd.h
features.h
cdefs.h
stubs.h
posix_opt.h
types.h
wordsize.h
typesizes.h
confname.h
getopt.h
mman.h
OS
1. Android & Linux
天然的支持Skia
2. Symbian
Symbian 3rd开始支持部分POSIX标准,所以以上的头文件函数实现,可能有部分不为Symbian所支持,不支持的必须自行实现。
参见: http://innovator.samsungmobile.c ... latformId=1&amp;cateId=159 
►C标准库和POSIX转义符(equivalents)
Symbian OS包括ANSI C / POSIX标准库应用 ,提供了stdlib子集以支持将C和混合C / C++代码移植到Symbian OS。
它还包括P.I.P.S. POSIX库。如果您有一个现成应用, P.I.P.S.尤其可以使核心应用逻辑的移植容易得多。 P.I.P.S. 被专门的Wiki全面涵盖。
3. Windows Mobile & Windows CE
支持POSIX,所以应该也可以支持SKIA

google skia相关推荐

  1. 开源项目推荐:OpenGL/Vulkan/Cairo/Skia/angle/VTK/OpenVG/MyPaint/GIMP/Krita/Pencil2D/inkspace/enve等绘图库或画图软件

    绘图引擎简介 Windows环境下二维绘图引擎有多种选择:GDI.GDI+.DirectDraw.Qt/QPainter.Agg.Cairo.skia.Direct2D.Direct3D.OpenGL ...

  2. Android编译Skia库

    Android编译Skia库 本文档提供两种方法编译Skia库 使用aosp源码进行编译 使用skia源码进行编译 两种编译方法都可以编译,并且都可以使用在多个平台中,且可以使用在不同Android版 ...

  3. 深入理解Flutter的图形图像绘制原理——图形库skia剖析

    Flutter是目前流行的高性能跨平台UI框架,图形库skia是其跨平台的基石.本文将深入分析skia的图形.字体.图片的渲染原理,如何挖掘硬件特性,为UI性能优化提供思路. 1. 引言 Flutte ...

  4. 通过skia/freetype 解析字体获取fontfamily fontstyle name 支持多语言翻译

    前言 我们的项目是基于google skia的渲染引擎 然后skia关于文字处理这块 是用的 freetype + harfbuzz 不太清楚的可以先了解下这些库的背景,这里就不说了 怎么解析字体文件 ...

  5. skia windows编译

    skia官网: https://skia.org/ 官网下载和编译说明: https://skia.org/user/download https://skia.org/user/build 下载参考 ...

  6. Flutter的绘制剖析——图形库skia

    Flutter是Google打造的高性能.跨平台的UI框架,不仅支持Android.iOS,还支持Windows.Linux等操作系统.它可以给开发者提供简单.高效的方式来构建和部署跨平台.高性能移动 ...

  7. 通过skia导出pdf 生成超链接 skia pdfdocument annotation pdflink

    如题 最近导出pdf ,想实现文本支持超链接跳转, 看了下skia的官网文档, 翻墙找各种资料 就是找不到关于怎么实现,毫无头绪咋办呢 我想了一下 1.粗略翻阅了下pdf的格式 了解了下基本的构成 啥 ...

  8. 独家 | 5个只有少数程序员知道的用例

    作者:Shalitha Suranga 翻译:闫晓雨 校对:赵茹萱 本文约2900字,建议阅读6分钟. Python不仅能够应用于数据科学和Web后端--还可以做更多的事. 照片由Chris Ried ...

  9. surfaceflinger类图

    frameworks/base/libs/ui 和 frameworks/base/libs/surfaceflinger ISurface 定义了基础的Surface接口,供图形系统客户端 (应用) ...

最新文章

  1. 一种不会导致资源泄露的“终止”线程的方法
  2. 输入一行字符,判断单词数
  3. Ubuntu 设置程序开机启动(以指定用户身份)
  4. 【MYSQL命令】查看一个表的建表语句
  5. powershell 运行策略
  6. 基于Rx-netty和Karyon2的云就绪微服务
  7. Mr. Kitayuta‘s Technology CodeForces - 505D(并查集+拓扑排序或dfs找环) 题解
  8. require.js用法简介
  9. 这就是数据分析之数据分析入门
  10. java基础01-java历史
  11. 在Linux集群上部署Spark之前准备
  12. Android安全:代码注入
  13. 听阿里P8聊完这个 SpringBoot 的项目,瞬间觉得自己白学了…
  14. 《零基础入门学习Python》学习过程笔记【40类和对象的相关内置函数】
  15. 使用DxVcl为Python的飞信库写一个简单的GUI
  16. Ubuntu(小名乌班图)的安装顺便附带VMware的安装教程,以及VM的激活密钥
  17. QCA-WIFI技术研讨
  18. 卸载IE8 恢复IE6 的两种方法
  19. 电脑小写字母怎么切换_WPS“文档”——大小写字母快速转换
  20. 实时视频带宽的计算过程

热门文章

  1. 【java】关于java编程语言开发
  2. 邮件营销 | 精准投放,独立站可提升6倍转化率
  3. 认识3DMAX的各种插件
  4. 最简单的SpringCloudStream集成Kafka教程
  5. 辽宁大学新闻与传播硕士(MJC)专业考研上岸经验分享
  6. Linux | (WGET、Curl、Aria2、Axel)的最佳命令行下载加速工具【详解】
  7. 论 致命错误c0000005
  8. php2-3v690,php网页版文件浏览器
  9. 连接一个HTTPS网站的前300毫秒,都发生了什么? | ArcBlock 课堂预告
  10. oracle密码过期策略管理