很久前就听一大牛说起Agg,据说是一个架构极度牛B的2D引擎,沉寂了许久,最后花了两周时间走马观花地把它过了一遍。果然如那大牛所言,这家伙简直就是巧夺天工的艺术品。今天稍稍瞄了一下Google扔出来的,也宣称极度牛B的2D引擎Skia,不过个人感觉整体架构大不如Agg漂亮。至于两者的性能,没做过比较,只是听说skia性能表现优异。

在啃这块骨头之前,有两点建议:

  1. 稍了解一点2D计算机图形学的知识。这一点在学习Agg的过程中至关重要。

  2. 至少尝试使用过一种UI框架,诸如Wtl、Mfc等。

很多人曾说Agg将C++模板用到了炉火纯青的地步,不过就我现在的认知,发现其用法也就正规正矩而已,没用像Boost那样到处是奇技淫巧,让人眼花缭乱,找不到北。也许我功底还不行,无法体会高人的用意。

学习代码最好的办法莫过于编译,看运行效果。下载源码见这里【http://www.antigrain.com/download/index.html】。Agg源码包中并没有对Virtual Studio的直接支持,不过建一个Project,然后将文件拖到里面编译即可(为了保证可移植性,Agg对标准的支持还是很得力的)。在源码包中的examples目录有很多sample,可以另建Project编译运行看效果。如果想偷懒,可以去这里【http://www.antigrain.com/demo/index.html 】下载编译好的可执行文件先睹为快。我围观了下,效果很“炫”。

对于开源的东西,找学习资料总是值得先去官网瞄瞄。Agg官网的Reference 不多,不过强烈建议看下这里【http://www.antigrain.com/doc/index.html 】。如果不喜欢看E文,国内有人翻译(感谢之),质量还不错,见这里【http://www.cnblogs.com/liyiwen/category/248229.html 】。认真看完第一篇【Basic Renderers】很重要,这篇文章对Agg的底层架构做了清晰的讲述,包括RenderBuffer和底层Render,以及两者的职责分离。这种设计相当好,因为RenderBuffer并不应该知道上层使用何种颜色模式。

为了对Agg有一个总体的了解(非技术层次),可以参考这里【http://www.cnblogs.com/Kane_zzt/archive/2009/02/15/1271793.html 】。下面这张图是Agg总体框架的一个总体表述

最后一项Screen Output可以不理会,那是OS的事。Agg处理的最底层是Rendering Buffer 。说白了Rendering Buffer就是一块内存块,类似Bitmap。当然这也不一定,它也可以是通过OS API获得窗口屏幕的映射地址Windows下可以通过GDI函数获得),或者是FrameBuffer,这样整个屏幕就可以任意虐,如果没猜错的话,Android这鸟毛就这么干的。

在讲Renderers之前,有必要区分两个概念,图形和图像。简单地讲,图形就是一些点线组成的形状,可以通过LineTo和MoveTo原语构造。而图像一般包含形状和具体的颜色信息。而Readerers【渲染器】就是将图形信息渲染成图像。

渲染器层实际上包含三层:

  1. 颜色模式(例如RGBA相关的底层渲染层,这一层直接跟Rendering Buffer日。在这一层,每一个像素的大小、颜色的表示被确定。

  2. Basic Render层,这一层在底层的基础上进行简单的裁剪支持。包括单裁剪和多区域裁剪。多区域裁剪性能和区域数量相关。

  3. 应用渲染层,这一层负责渲染具体的线段。在后面会讲到,在Agg中任何一个多边形在光栅化后都会分解成一条条水平线(span),然后依次渲染。

Scanline Rasterizer就是将任意多边形(顶点源)分解成水平线,然后交给顶层渲染器渲染。在这一层也可以进行适当的裁剪。反锯齿功能在这一层引入,Agg中的像素存储使用浮点型,小数部分即传说中的亚像素。

Coordinate conversion pipeline对顶点源进行坐标转换,我们熟悉的操作如放大/缩小、旋转等操作都在这一层完成,这部分代码对数学基础和算法要求较高,我直接死不鸟跳过。在反走样插值功能在这一层引入。

Vertex Source提供光栅化的多边形,它通过一个迭代器来传递顶点。顶点源包括普通的图形,例如矩形、椭圆、三角形,也包括字体等复杂多边形。在Linux下被广泛应用的Freetype库就是根据字符编码、其他字符参数来生成一个字体多边形。这在Agg中也被支持。

前面提到的都是一些很简单的矢量绘图操作,那么Agg对贴图、渐变色和字体引擎的支持怎么样呢?

关于Agg对贴图的支持,默认包含对bmp格式的支持,Agg源码内置了对bmp图片格式的解码代码,不过默认并不支持png和jpg等流行格式。我想作者可能是为了保持简单,不想引入libpng和libjpeg。Agg对所有图片格式除了解码部分外,处理是一致的。

前面一直讲到渲染,那何谓渲染呢,说白了就是将一个像素用颜色填充(或混合Blend)。而前面一直忽略了一个问题,就是渲染时用什么颜色来填充(准确的讲,并不是填充,而是混合(Blend))特定的像素呢?在Agg中其实也包含一个虚拟的“颜色源”,这个颜色源中的每一个点和“顶点源“中的点一一对应。可以有多种方式构造这个虚拟的颜色源,首先可以指定一种颜色,即纯色填充,其次可以通过一定算法来生成”渐变“效果,当然也可以从图片中获取。

说到图片,其实任何格式在处理前都必须转化成bitmap格式,所谓的libpng和libjpeg就是干这个事。而bitmap说到底就是一个矩形颜色源。也许有人会疑惑,某些图片不是支持不规则形状么,例如png图片格式。其实png并不支持不规则形状,而是支持Alpha通道。而2D引擎在渲染时通过Alpha Blend后某些地方就成了透明色,用户看起来就是不规则形状了。

说到这里,Agg对贴图的支持就很简单了,从贴图资源中获得颜色源,然后使用它渲染特定多边形(裁剪在这个多边形中完成)。而对图片的放大/缩小、旋转等过程类似Coordinate conversion pipeline对顶点源的操作。

Agg对渐变的支持和贴图一致。

Agg内置对英文字符的支持,我没有仔细研究源码,不过可以推测它将所有英文字符的路径存储在一个全局(静态)变量中,渲染前直接通过这些路径生成顶点,因而效率极高。不过这种方式有几个不足:

  1. 不支持未存储的字符,很显然不要靠他来支持”我日“。

  2. 不支持字体,因为字体路径表述都是写死的,除非修改源代码。

更高级的字体支持来自字体引擎,Agg支持Windows Gdi的字体接口,也可以使用第三方的字体引擎,例如Freetype。Agg可以通过字体引擎提供的字模来包装一个顶点源,因而可以将字体渲染成任意效果。此外Agg也可以对字体引擎进一步封装,实现一个类似贴图的接口,然后渲染多边形,不过个人觉得这种方式很别扭,而且渲染时不太灵活。暂时没有测试两种方式的效率差别。

最后,因本人水平有限,错误之处在所难免,欢迎指正。

Agg学习笔记的更多相关文章

  1. 23 DesignPatterns学习笔记:C++语言实现 --- 2.4 Composite

    23 DesignPatterns学习笔记:C++语言实现 --- 2.4 Composite 2016-07-22 (www.cnblogs.com/icmzn) 模式理解

  2. 23 DesignPatterns学习笔记:C++语言实现 --- 1.3 Singletion

    23 DesignPatterns学习笔记:C++语言实现 --- 1.3 Singletion 2016-07-21 (www.cnblogs.com/icmzn) 模式理解  

  3. Flink学习笔记:Flink Runtime

    本文为<Flink大数据项目实战>学习笔记,想通过视频系统学习Flink这个最火爆的大数据计算框架的同学,推荐学习课程: Flink大数据项目实战:http://t.cn/EJtKhaz ...

  4. flink学习笔记-各种Time

    说明:本文为<Flink大数据项目实战>学习笔记,想通过视频系统学习Flink这个最火爆的大数据计算框架的同学,推荐学习课程: Flink大数据项目实战:http://t.cn/EJtKh ...

  5. Elasticsearch7.6学习笔记1 Getting start with Elasticsearch

    Elasticsearch7.6学习笔记1 Getting start with Elasticsearch 前言 权威指南中文只有2.x, 但现在es已经到7.6. 就安装最新的来学下. 安装 这里 ...

  6. hive学习笔记之十:用户自定义聚合函数(UDAF)

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是<hive学习笔记>的第十 ...

  7. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  8. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  9. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

随机推荐

  1. [置顶] 内存映射失败MapViewOfFile 失败 返回 8

    问题描述1 在使用内存映射方式读写数据时,将文件A的内容拷贝至文件B中,偶尔会出来文件拷贝后的文件,内容为空,或部分为空 问题分析1 怀疑是内存映射方式读写数据的稳定性(可笑的怀疑,内存映射可以Win ...

  2. 全面理解js面向对象

    前言 当今 JavaScript 大行其道,各种应用对其依赖日深.web 程序员已逐渐习惯使用各种优秀的 JavaScript 框架快速开发 Web 应用,从而忽略了对原生 JavaScript 的学 ...

  3. Shader程序中内置的状态变量

    经常在着色器程序需要访问一些全局状态,像当前的 model view projection 矩阵,当前环境的颜色诸如此类. 内置的矩阵 UNITY_MATRIX_MVP:当前模型 视窗 投影矩阵 UN ...

  4. Android应用开发提高篇(4)-----Socket编程(多线程、双向通信)

    链接地址:http://www.cnblogs.com/lknlfy/archive/2012/03/04/2379628.html 一.概述 关于Socket编程的基本方法在基础篇里已经讲过,今天把 ...

  5. 1.3. chromium源代码分析 - chromiumframe - 窗口系列

    在_tWinMain中有这样两条语句: MainWindowDelegate delegate; view::Window::CreateNativeWindow(NULL, gfx::Rect(), ...

  6. apache 配置文件管理

    1. Apache配置系统 从整体来看apache的配置系统包括三个部分: (1) 配置文件:比如 httpd.conf   .htaccess (2) 配置指令:在配置文件 httpd.conf  ...

  7. Android 开发笔记“浅谈DDMS视图”

    DDMS 的全称是Dalvik Debug Monitor Service,即Dalvik调试监控服务,是一个可视化的调试监控工具.它主要是对系统运行后台日志的监控,还有系统线程,模拟器状态的监控.此 ...

  8. Android 开发笔记“程序安装包APK的制作”

    资源来源:http://blog.csdn.net/qualcent/article/details/6959547 完成Android项目后,需要将程序打包成APK文件(Android Packag ...

  9. multi-threaded copy command - robocopy

    we can copy files by the powerful robocopy tool, and it allow copy using muliti-threaded as well. As ...

  10. 韦根(Wiegand)数据传输格式

    韦根数据传输使用TTL电平,有两条数据线,分别称为DATA0和DATA1.无数据传输时,两条线都是高电平,当传输“1”时,DATA0为高,DATA1为低:当传输“0”时,DATA0为低,DATA1为高 ...