很久前就听一大牛说起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. WebKit的历史项管理

    标准定义 关于历史的管理,和HTML页面载入一样,都有其相应的标准.地址例如以下: WhatWG: https://html.spec.whatwg.org/multipage/browsers.ht ...

  2. 初探ListView

    ListView可能是Android开发中最常用的一个控件,但要用的纯熟还需要不断的锻炼. 建立简单的ListView 1.在布局文件(.xml)中添加<ListView>标签 2.在Ma ...

  3. ExtJs004define定义类

    Ext.onReady(function () { //在Ext中如何去定义一个类: Ext.define(className , properties , callback) Ext.define( ...

  4. QTableView另类打印解决方案(复用render函数去解决print问题)

    Qt QTableView另类打印解决方案     上回书说道Qt的model/view,我就做了个demo用于显示数据库中的内容.没想到tableview的打印竟然成了问题.我困惑了,难道Qt不应该 ...

  5. Java并发编程总结2——慎用CAS(转)

    一.CAS和synchronized适用场景 1.对于资源竞争较少的情况,使用synchronized同步锁进行线程阻塞和唤醒切换以及用户态内核态间的切换操作额外浪费消耗cpu资源:而CAS基于硬件实 ...

  6. 分布式配置管理平台 Disconf

    Distributed Configuration Management Platform(分布式配置管理平台) 专注于各种 分布式系统配置管理 的通用组件/通用平台, 提供统一的配置管理服务. 包括 ...

  7. Dijkstra算法详解

    1.dijkstra算法简介 Dijkstra算法是由E.W.Dijkstra于1959年提出,又叫迪杰斯特拉算法,它应用了贪心算法模式,是目前公认的最好的求解最短路径的方法.算法解决的是有向图中单个 ...

  8. hdu 4119 Isabella's Message

    Isabella's Message Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...

  9. OpenCV之Python学习笔记

    OpenCV之Python学习笔记 直都在用Python+OpenCV做一些算法的原型.本来想留下发布一些文章的,可是整理一下就有点无奈了,都是写零散不成系统的小片段.现在看 到一本国外的新书< ...

  10. In Action(最短路+01背包)

    In Action Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...