AGG入门

AGG入门

 

一、配置开发环境

 

AGG入门(一) - 配置开发环境

AGG是一个高效的、高质量的、开源的矢量图形库,类似的有:GTK+CairoMicrosoftGDI+。在三者中,AGG的性能是最高的(不讨论SkiaDirect2D,他们有OGLDX的硬件加速,绘图速度根本不是一个档次的)。让我们细数一下他的优缺点:

  • 优点:效率高,质量高(有反锯齿),功能强大,跨平台和平台GUI支持,……
  • 缺点:没有硬件加速,文档少,门槛有那么点高,……

 

一、准备

  • http://www.antigrain.com/download/index.html下载源码包。
  • 今天用Visual C++ 6.0来做IDE和编译器啦!要多经典有多经典。

 

二、工作

  1. VC6里新建一个工程“AGG”,类型为静态库Win32 Static Library
  2. 将下列源文件都加入工程:
    1. ./src/ 目录下所有cpp文件【核心库】*
    2. ./src/ctrl/ 目录下所有cpp文件【控件库】*
    3. ./src/platform/ 下对应平台目录(win32)下的所有cpp文件【平台支持库】*
    4. ./font_freetype/ 下所有的cpp文件【Freetype字体支持库】
    5. ./font_win32_tt/ 下所有的cpp文件【Truetype字体支持库】*
    6. ./gpc/ 下所有的cpp文件【Generic Polygon Clipper裁切库】
  3. 将下列目录加入Tools(工具)菜单– Options(选项)菜单 – Directory(目录)选项卡中的Include Files目录列表中:
    1. ./include/ *
    2. ./font_freetype/
    3. ./font_win32_tt/ *
    4. ./gpc/
  4. 选择配置为Win32 Release,编译
  5. 编译成功后,Tools(工具)菜单– Options(选项)菜单 – Directory(目录)选项卡中的Library Files目录列表中加入【工程所在目录】\Release\
  6. 没有成功编译的童鞋,奖励已经编译好的AGG.lib一枚…… AGG.zip

三、测试

  1. 新建一个Win32 Application 空工程,新建一源文件,加入下面的代码:

#include 
#include 
#include 

class the_application : public agg::platform_support
{
public:
    the_application(agg::pix_format_e format, bool flip_y) : 
        agg::platform_support(format, flip_y),
        pix_fmt(rbuf_window()),
        ren_bas(pix_fmt) //
初始化渲染器
    { }

    virtual void on_draw()
    {
        ren_bas.reset_clipping(true);
        ren_bas.clear(agg::rgba8(204, 204, 204));
    }

private:
    agg::pixfmt_rgb24 pix_fmt;
    agg::renderer_base ren_bas;

};

int agg_main(int argc, char* argv[])
{
    the_application app(agg::pix_format_rgb24, true);
    app.caption("AGG Test");
    
    if(app.init(500, 500, agg::window_resize)) {
        return app.run();
    }
    return -1;
}

  1. 在【工程】菜单 - 【设置】菜单 - 【连接】选项卡 - 【对象/库模块】文本框中加入AGG.lib
  2. 编译运行,不出意外,可以得到下面的结果:

 

二、平台支持

AGG入门(二) - 平台支持

一、先看看下面的代码,并试着编译下:

#include 
#include 
#include 
#include 

#include 

class the_application : public agg::platform_support
{
public:
    the_application(agg::pix_format_e format, bool flip_y) : 
        agg::platform_support(format, flip_y),
        pix_fmt(rbuf_window()),
        ren_bas(pix_fmt) //
初始化渲染器
    {
    }

    virtual void on_draw()
    {
        ren_bas.reset_clipping(true);
        ren_bas.clear(agg::rgba8(255, 255, 255));
    }

    virtual void on_mouse_button_down(int x, int y, unsigned flags)
    {
        if(flags == agg::mouse_left) {
            char str[50];
            sprintf(str, "Mouse location:(%d, %d)", x, y);
            message(str);
        }
    }

    virtual void on_key(int x, int y, unsigned key, unsigned flags)
    {
        if(key == agg::key_return && flags == agg::kbd_shift) {
            unsigned img = 0, states;
            states = create_img(0, 500, 500);
            states = load_img(img, "Steve-and-Bill.bmp");
            copy_img_to_window(img);
            update_window();
        }
    }

private:
    agg::pixfmt_rgb24 pix_fmt;
    agg::renderer_base ren_bas;

};

int agg_main(int argc, char* argv[])
{
    the_application app(agg::pix_format_rgb24, true);
    app.caption("AGG Test");
    
    if(app.init(500, 500, agg::window_resize)) {
        return app.run();
    }
    return -1;
}

如果不出意外,在窗口中点击鼠标左键将会出现对话框提示当前鼠标的位置,而按下Shift+Enter将会在窗口中显示在工作目录下的位图“Steve-and-Bill.bmp”

二、解释

先看看头文件:platform/agg_platform_support.h,它里边定义了一个platform_support——它允许你建立一个窗口来测试你的图形,并用鼠标键盘去控制它。

类型

  • class platform_support 

主要成员函数

  • platform_support(pix_format_e, bool) : 构造函数。设置窗口风格和y轴是否上下翻转;
  • width() :返回窗口的宽;
  • height() :返回窗口的高;
  • caption([ const char* ]) :设置标题或返回标题字符串;
  • format() :返回窗口风格;
  • message(const char*) :弹出对话框(没有风格可选);
  • run() :运行窗口;
  • force_redraw() :重绘窗口,调用on_draw()
  • update_window() :更新窗口,既是把渲染缓存中已有的内容写入窗口,不调用on_draw()
  • platform_support为我们提供了一个很好地绘图平台,它有一系列的函数可用于操作位图(BMPPPM):
    • create_img():创建一个编号为idx的位图;
    • save_img():将位图idx保存到文件中;
    • load_img():从文件中加载位图到idx中;
    • copy_img_to_window():把idx拷贝到渲染缓存里;
    • copy_img_to_img():把idx拷贝到另一幅位图里;
    • copy_window_to_img() :将渲染缓存里的内容拷贝到位图。

虚函数(一般都是些消息,要覆盖它以让消息循环调用)

  • on_init() :窗口初始化时调用;
  • on_resize(int, int) :改变大小时调用;
  • on_idle()  :空闲时调用;
  • on_mouse_move(int, int, unsigned) :鼠标移动时调用;
  • on_mouse_button_down(int, int, unsigned) :鼠标按下时调用;
  • on_mouse_button_up(int, int, unsigned)  :鼠标弹起时调用;
  • on_key(int, int, unsigned, unsigned)  :键盘打字时调用;
  • on_draw()  :窗口重绘时调用。

三、结语

platform_support 的功能不仅仅是这么多,除此之外,他还能使用控件,等等。但很多时候,成熟的应用是不会使用它的,因为它封装了太多,虽然保证了跨平台性,却缺乏了自由性。platform_support 的主要作用是测试图像和修改图像,方便工作和移植……还有,方便初学者入门……

 

三、渲染器介绍

AGG入门(三) - 渲染器介绍

一、看回AGG入门(二)时on_draw()虚函数里的代码:

        agg::rendering_buffer &rbuf = rbuf_window();
        agg::pixfmt_rgb24 pixf(rbuf);

        agg::renderer_base renb(pixf);
        renb.clear(agg::rgba8(255, 255, 255));

        pixf.copy_pixel(20, 20, agg::rgba8(0, 0, 255));

二、渲染器

什么是渲染?

渲染是把内存中的绘图指令真正执行的过程。比如说,绘制一条线段,在内存里只会保存着两个端点的坐标和线段的宽度,而渲染就把这两个端点转换为位图、缓存甚至显示屏上的一个个像素的数据。又比如说,纸飞机下面肯定是要有投影的了,但这个投影的质量,就由渲染器决定;线段是走样的(A),还是反走样的(B),靠的就是渲染器的指令了。

AGG里的渲染器

AGG分有多种渲染器。在AGG中,渲染器负责表现扫描线中的每个线段。在渲染器之前,AGG图形中的线段是没有颜色值的,只是位置、长度和覆盖率(透明度)。渲染器赋于线段色彩,最终成为一幅完整的图像。其中最常用的是:

  • 像素格式渲染器
  • 基础渲染器
  • 扫描线(反锯齿)渲染器

三、三种渲染器间的关系

  • 像素格式渲染器(PixelFormat Renderer)是最基础的渲染器,不需要任何其他渲染器的支持,所以可以直接声明;
  • 基础渲染器(Base Renderer)是中级渲染器,需要像素格式作为模版和像素格式渲染器的支持;
  • 扫描线渲染器(Scanline Renderer)是高级渲染器,需要基础渲染器作为模版和支持;

(注:模版主要是为了获取像素格式的信息)

所以,除像素格式渲染器声明为:
agg::class object(agg::rendering_buffer &);
之外其他的渲染器都声明为:

agg::class