摘自:http://www.cnblogs.com/muxue/archive/2010/06/03/1751094.html
学习经验:很多人在接触新的概念的时候,总会有抵触的情绪,并且由于不了解源码的内部结构而无法了解使用。现在进行简单的分析:
裁剪可能是一个模糊的概念,除非了解图形学,简单来说就是指定一个区域,在这个区域内的任何操作都是有效的,超出限制区域所有的操作都是无效的,最基本的一点就是在渲染像素的时候,先判断该像素是否在指定区域内,发现实际上renderer_base调用的还是像素对象的函数进行渲染,像素对象可以是agg::pixfmt_rgb24,这里几乎没有使用到任何的算法,完全是对像素点进行着色,类似用一支有颜色的毛笔对像素点进行描绘,提供了一些画点,画线的函数。
有两种基础渲染器,renderer_base 和 renderer_mclip 它们的功能几乎是一样的。主要使用的是前者(renderer_base),它进行低层次的裁剪处理。通用的裁剪处理(clipping)是一个复杂的任务。在 AGG 中,至少可以有两层的裁剪,底层(像素级)的,和高层的(向量级)。这两个类可以进行像素级别的裁剪,用以防止对缓存区的越界访问。 renderer_mclip 类可以支持多个矩形区域的裁剪区域,但它的性能和裁剪区域的数量有关。
renderer_base 和 renderer_mclip 都是模板类,它们的模板参数就是像素格式渲染器(pixelformat renderer)。
template<class PixelFormat> classrenderer_base
{
public:
typedef PixelFormat pixfmt_type;
typedef typename pixfmt_type::color_type color_type;
.. .
};
Creation
renderer_base(pixfmt_type& ren);
renderer_mclip(pixfmt_type& ren);
两个类的构造函数都可以接受像素格式渲染器(pixel format renderer)对象作为参数。 renderer_mclip 在内部使用renderer_base<PixelFormat> ,用来进行单矩形区域的裁剪。注意,你也可以使用pixfmt_amask_adaptor 作为参数 PixelFormat。
构造的开销是非常小的,它只是初始化各个成员变量。不过,如果你添加新的裁剪区域,那么renderer_mclip 需要申请新的内存,在析构时也会有相应的释放动作。它会用 pod_deque 类来完成内存块的申请,并且它不会(提前)释放不需要的内存,当你重新设置裁剪区域的时候,它会重用原来申请的内存区。 AGG 中广泛使用了这种技术,这可以避免产生过多的内存碎片。
Member Functions
const pixfmt_type& ren() const;
pixfmt_type& ren();
返回指向像素渲染器(pixel format renderer)的引用。
unsigned width() const;
unsigned height() const;
返回渲染缓存区(rendering buffer)的高和度。
void reset_clipping(bool visibility);
这个函数会重设裁剪区域,如果 visibility 值设置为 true ,那么裁剪区域会被设置为 (0, 0, width()-1, height()-1),如果设置为 false,会设置一个不可见的区域,比如(1,1,0,0)。对于 renderer_mclip 的这个函数来说,它会移除之前添加的所有剪裁区域。
重要!
如果你将另一块内存区附着到 rendering_buffer 上的话(rendering_buffer是连接着这个(basic_renderer),你必须调用一次 reset_clipping() ,否则的话,原来的裁剪区域会变得无效。 因为这个内存改变动作做完之后并不会,rendering buffer 不会给 renderers 任何反馈。也就是说,renderer_base 和 renderer_mclip 对于 rendering buffer 的变动一无所知(译注:renderer_base是用pixel format render来构造的,而pixel format render 又是由 rendering buffer 来支撑,所以它们之间就有这样的关系,具体可见前文)。如果有这样的机制,可以在它们之间传递消息或是使用委托,那么这种机制可能成为 overkill (译注:不知道怎么理解这个overkill)。
bool clip_box(int x1, int y1, int x2, inty2);
这个函数用于设置新的裁剪区域(clipping box)。只有 renderer_base 才有这个函数。裁剪区域包含了边界位置,所以最大的裁剪区域是 (0, 0, width()-1, height()-1) 。裁剪区域在(重新)设置之前,会被设置为最大值。所以,就算你设置新区域的比 (0, 0, width()-1, height()-1) 还要大,也是安全的(译注:因为不会被采用)
void add_clip_box(int x1, int y1, int x2,int y2);
添加一个新的裁剪区域。只有 renderer_mclip 才有这个函数。你可以添加任何个新的矩形区域,但他们之间不能有重叠的部分。如果有重叠的区域的话,有些元素就会被描画两次或两次以上。被添加的新区域会在加入之时被 (0, 0, width()-1, height()-1) 这个区域预先裁剪掉,这主要是有效率上的考量。这也意味着调用 reset_clipping(false)没有任何意义,因为所有被添加的新区域都会用一个不可见区域内先裁剪掉,因此也就不会被添加。(译注:原句如下:t also means that calling reset_clipping(false) for therenderer_mclip doesn‘t make any sense because all adding regions will beclipped by an invisible area and will not be actually added.对这个我不能理解它的意思,后面看了代码再来修正吧)。可见区域包含裁剪区域的边界,也就是说,调用 add_clip_box(100,100,100,100) 会添加一个 1 像素的裁剪区域。
void clip_box_naked(int x1, int y1, int x2,int y2);
只有 renderer_base 有这个函数,它用来给rendering buffer 大小设置一个新的裁剪区域。这个函数不安全,主要是 renderer_mclip 类在使用它,用来在不同的子区域之间快速的切换。这个函数的目的就是为了避免额外的开销。
bool inbox(int x, int y) const;
检查 (x,y) 这个点是不是在裁剪区域内。只有 renderer_base 才有这个函数。
void first_clip_box();
bool next_clip_box();
这两个函数用于枚举渲染器所有的裁剪区域。对于 renderer_base 类来说,它是返回的是空的, next_clip_box() 始终返回 false。
const rect& clip_box() const;
int xmin() const;
int ymin() const;
int xmax() const;
int ymax() const;
以一个矩形的形式可是以四个独立的整数值形式返回裁剪区域。 renderer_mclip 的这个函数始终返回 (0, 0, width()-1, height()-1)。
const rect& bounding_clip_box() const;
int bounding_xmin() const;
int bounding_ymin() const;
int bounding_xmax() const;
int bounding_ymax() const;
以一个矩形的形式可是以四个独立的整数值形式返回裁剪区域的边界。对于 renderer_base,这个函数返回的值于上面那组函数是一样的。对于 renderer_mclip 来说,它们返回的边界是由所有被添加的矩形合计得出的。
void clear(const color_type& c);
用 c 这个颜色来清除缓存区内的所有区域(不考虑裁剪区域)。
void copy_pixel(int x, int y, constcolor_type& c);
设置一个像素的颜色(考虑裁剪区域clipping)。
void blend_pixel(int x, int y, constcolor_type& c, cover_type cover);
混合描画一个像素。它的行为与 pixel format renderer 的对应函数是一样的。
color_type pixel(int x, int y) const;
获取指定坐标(x,y)的颜色值,如果这个点在裁剪区域外,这个函数返回 color_type::no_color(). 对于 rgba8 来说,就是 (0,0,0,0).
void copy_hline(int x1, int y, int x2,const color_type& c);
void copy_vline(int x, int y1, int y2,const color_type& c);
void blend_hline(int x1, int y, int x2,
const color_type& c,cover_type cover);
void blend_vline(int x, int y1, int y2,
const color_type& c,cover_type cover);
描画(拷贝)或是混合渲染水平或垂直的像素线。行为与 pixel format renders 的相应函数一样。但在这里,使用的是线的起始点和终点坐标,而不是 pixfmt 中的(x, y, length)。
void copy_bar(int x1, int y1, int x2, inty2, const color_type& c);
void blend_bar(int x1, int y1, int x2, inty2,
const color_type& c,cover_type cover);
描画(拷贝)或是混合渲染一个矩形区。
void blend_solid_hspan(int x, int y, intlen,
const color_type& c,const cover_type* covers);
void blend_solid_vspan(int x, int y, intlen,
const color_type& c,const cover_type* covers);
混合渲染一个水平或是垂直的纯色(solid-color)的span。这些在渲染实多边形时会用到。
void blend_color_hspan(int x, int y, intlen,
const color_type*colors, const cover_type* covers);
void blend_color_vspan(int x, int y, intlen,
const color_type*colors, const cover_type* covers);
混合渲染一个水平或是垂直的(? vertical -color)的span。这个函数与不同的 span 生成器一起使用,比如gradients, images, patterns, Gouraud interpolation 等等。函数接受一个颜色数组,颜色的类型必须与正在使用 pixel format 兼容。
void blend_color_hspan_no_clip(int x, inty, int len,
constcolor_type* colors,
const cover_type*covers);
void blend_color_vspan_no_clip(int x, inty, int len,
constcolor_type* colors,
constcover_type* covers);
与上面的函数是一样的,但不考虑裁剪区域。这两个函数用到 scanline renderers 中。分离出这两个函数的原因也是为了效率,scanline 由很多的 spans 组合而成,在进行区域裁剪时,拥有整个 scanline 的信息会比逐个的裁剪每个 span 来得更有效率一些,对于 renderer_mclip 这个类尤其如此。
void copy_from(const rendering_buffer&from,
const rect* rc=0,
int x_to=0,
int y_to=0);
将源缓存区的内容拷入本缓存区中(考虑区域裁剪)。它假设两块缓存区的像素格式是一样的。rc是一个可选项,它指示的是源缓存区内的一个矩形,x_to 、 y_to ————rc->x1, rc->y1 坐标值映射到目标缓存区。