小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

[翻譯] AGG Reference 之 Basic Renderers(基礎(chǔ)渲染器)

 昵稱880622 2014-03-06

翻譯:唐風(fēng)

Rendering Buffer

我們先從這里開(kāi)始:在內(nèi)存中開(kāi)辟一塊存儲(chǔ)區(qū),然后將它的內(nèi)容以最簡(jiǎn)單的光柵格式寫到文件中,也就是 PPM(Portable Pixel Map)格式。雖然 Windows 對(duì)這種格式并沒(méi)有原生的支持,但很多圖像瀏覽器和轉(zhuǎn)換器都能使用這種格式,比如 IrfanView(www.irfanview.com)。所有 AGG 的控制臺(tái)例子都使用了 P6 256 格式,也就是 RGB,每個(gè)字節(jié)代碼一個(gè)顏色?,F(xiàn)在假設(shè)我們將在下圖所示的 RGB-buffer 內(nèi)存區(qū)中工作:

pixfmt_rgb24

The first and the Simplest Example

這是第一個(gè)例子:

#include <stdio.h>
#include <string.h>
#include "agg_rendering_buffer.h"

enum
{
    frame_width = 320,
    frame_height = 200
};

// Writing the buffer to a .PPM file, assuming it has 
// RGB-structure, one byte per color component
//--------------------------------------------------
bool write_ppm(const unsigned char* buf, 
               unsigned width, 
               unsigned height, 
               const char* file_name)
{
    FILE* fd = fopen(file_name, "wb");
    if(fd)
    {
        fprintf(fd, "P6 %d %d 255 ", width, height);
        fwrite(buf, 1, width * height * 3, fd);
        fclose(fd);
        return true;
    }
    return false;
}

// Draw a black frame around the rendering buffer, assuming it has 
// RGB-structure, one byte per color component
//--------------------------------------------------
void draw_black_frame(agg::rendering_buffer& rbuf)
{
    unsigned i;
    for(i = 0; i < rbuf.height(); ++i)
    {
        unsigned char* p = rbuf.row_ptr(i);
        *p++ = 0; *p++ = 0; *p++ = 0;
        p += (rbuf.width() - 2) * 3;
        *p++ = 0; *p++ = 0; *p++ = 0;
    }
    memset(rbuf.row_ptr(0), 0, rbuf.width() * 3);
    memset(rbuf.row_ptr(rbuf.height() - 1), 0, rbuf.width() * 3);
}


int main()
{
    // In the first example we do the following:
    //--------------------
    // Allocate the buffer.
    // Clear the buffer, for now "manually"
    // Create the rendering buffer object
    // Do something simple, draw a diagonal line
    // Write the buffer to agg_test.ppm
    // Free memory

    unsigned char* buffer = new unsigned char[frame_width * frame_height * 3];

    memset(buffer, 255, frame_width * frame_height * 3);

    agg::rendering_buffer rbuf(buffer, 
        frame_width, 
        frame_height, 
        frame_width * 3);

    unsigned i;
    for(i = 0; i < rbuf.height()/2; ++i)
    {
        // Get the pointer to the beginning of the i-th row (Y-coordinate)
        // and shift it to the i-th position, that is, X-coordinate.
        //---------------
        unsigned char* ptr = rbuf.row_ptr(i) + i * 3;

        // PutPixel, very sophisticated, huh? :)
        //-------------
        *ptr++ = 127; // R
        *ptr++ = 200; // G
        *ptr++ = 98;  // B
    }

    draw_black_frame(rbuf);
    write_ppm(buffer, frame_width, frame_height, "agg_test.ppm");

    delete [] buffer;
    return 0;
}

在這個(gè)例子中,你甚至不需要鏈接任何的 AGG 的代碼文件,你只需要在你的編譯器命令行中設(shè)置好 AGG 的包含路徑就行了。

編譯并運(yùn)行它,你會(huì)看到現(xiàn)圖所示的結(jié)果:

tmp66E

這個(gè)例子中幾乎所有東西都“手工打制”的,使用的唯一一個(gè)現(xiàn)成的類是 rendering_buffer。這個(gè)類本身并不知道關(guān)于內(nèi)存中像素格式的任何信息,它只是保存了一個(gè)數(shù)組,數(shù)組中的元素分別指向每行(像素的開(kāi)頭)。為申請(qǐng)和釋放這塊存儲(chǔ)區(qū)是使用者的責(zé)任,你可以使用任何可行的方式來(lái)申請(qǐng)和釋放內(nèi)存,比如使用系統(tǒng)提供的 API 函數(shù),或是簡(jiǎn)單的用內(nèi)存分配器(譯注:應(yīng)該是new、delete、malloc、free等),甚至是直接使用一個(gè)靜態(tài)數(shù)組。在上面這個(gè)例子中,因?yàn)槊總€(gè)像素要占用3個(gè)字節(jié),所以我們申請(qǐng)了 width*height*3 字節(jié)的內(nèi)存,在實(shí)際內(nèi)存中是不存在“行”這種布局方式的,但這樣做可以提高程序的性能,而且有時(shí)候在使用 API 的時(shí)候需要。

Class rendering_buffer

包含文件: agg_rendering_buffer.h

rendering_buffer 這個(gè)類保存了指向每一行像素的指針,基本上這個(gè)類做的事就是這些了??雌饋?lái)好像不是什么了不起的事,不過(guò)我們還是繼續(xù)分析下去。這個(gè)類的接口和功能都很簡(jiǎn)單,它只是模板類 row_ptr_cache 的一個(gè) typedef 而已:

typedef row_ptr_cache<int8u> rendering_buffer;

row_prt_cache 這個(gè)類的接口的功能如下:

template<class T> class row_ptr_cache
{
public:
    row_ptr_cache();

    row_ptr_cache(T* buf, unsigned width, unsigned height, int stride);

    void attach(T* buf, unsigned width, unsigned height, int stride);

    T* buf();
    const T* buf()    const;
    unsigned width()  const;
    unsigned height() const;
    int      stride() const;
    unsigned stride_abs() const;

    T* row_ptr(int, int y, unsigned); 
    T* row_ptr(int y);
    const T* row_ptr(int y) const;
    row_data row    (int y) const; 
    T const* const* rows() const;

    template<class RenBuf> void copy_from(const RenBuf& src);

    void clear(T value)
};

這個(gè)類的實(shí)現(xiàn)里沒(méi)有使用斷言或是驗(yàn)證的措施,所以,使用者有責(zé)任在用這個(gè)類對(duì)象時(shí)正確地將它初始化到實(shí)際的內(nèi)存塊中,這可以在構(gòu)造函數(shù)中完成,也可以使用 attach() 函數(shù)。它們的參數(shù)解釋如下:

  • buf      — 指向內(nèi)存塊的指針。
  • width  — 以像素為單位表示的圖像寬度。rendering buffer(渲染內(nèi)存區(qū))并不知道像素格式和每個(gè)像素在內(nèi)存中大小等信息。這個(gè)值會(huì)直接存儲(chǔ)在m_width這個(gè)成員變量中,使用 width() 函數(shù)就可以獲取它的值。
  • height — 以像素為單位表示的圖像高度(同樣也是行數(shù))
  • stride  — Stride(大步幅,-_-; 不知道怎么翻了……),也就是用類型T來(lái)度量的一行的長(zhǎng)度。 rendering_buffer是一個(gè) typedef,也就是 row_prt_cache<int8u>,所以這個(gè)值是以字節(jié)數(shù)來(lái)算的。Stride 決定內(nèi)存中每一行的實(shí)現(xiàn)長(zhǎng)度。如果這個(gè)值是負(fù)的,那么Y軸的方向就是反過(guò)來(lái)的。也就是說(shuō) Y 等 0 的點(diǎn)是是內(nèi)在塊的最后一行的。Y == height - 1 則是第一行。stride 的絕對(duì)值也很重要,因?yàn)樗屇憧梢苑奖愕夭僮鲀?nèi)存中的“行”(就像 windows 中的 BMP)。另外,這個(gè)參數(shù)允許使用者可以像操作整個(gè)內(nèi)存區(qū)塊一樣,操作其中任意一個(gè)“矩形”內(nèi)存區(qū)。

attach()函數(shù)會(huì)改變緩沖區(qū)或是它的參數(shù),它自己會(huì)為“行指針”數(shù)組重新分配內(nèi)存,所以你可以在任何時(shí)候調(diào)用它。當(dāng)(且僅當(dāng))新的height值比之前使用過(guò)的最大的height值還要大時(shí),它才會(huì)重新申請(qǐng)內(nèi)存。

構(gòu)造的這個(gè)對(duì)象的開(kāi)銷僅僅是初始化它的成員變量(設(shè)置為0),attach()的開(kāi)銷則是分配sizeof(ptr)*height個(gè)字節(jié)的內(nèi)存,然后將這些指針指向?qū)?yīng)的“行”。

最常使用的函數(shù)是 row_prt(y),這個(gè)函數(shù)只是簡(jiǎn)單地返回指向第y函數(shù)指針,這個(gè)指針指向的位置已經(jīng)考慮到了Y軸的方向了。

注意:

渲染內(nèi)存區(qū)(rendering buffer)并不管任何裁減或是邊界檢查的事,這是更高層的類的責(zé)任。

buf(), width(), height(), stride(), stride_abs() 這些函數(shù)的意義顯而易見(jiàn),就不解釋了。

copy_from()函數(shù)會(huì)將其它內(nèi)存的內(nèi)容拷貝至“本”內(nèi)存中。這個(gè)函數(shù)是安全的,如果(兩者的)width和height值不相同,那它會(huì)盡可能拷貝大一些的區(qū)域。一般來(lái)講都用于拷貝相同大小區(qū)域。

Two Modifications of the Example

首先,在創(chuàng)建 rendering buffer 的對(duì)象時(shí)將 stride 取負(fù)值:

agg::rendering_buffer rbuf(buffer, 
                           frame_width, 
                           frame_height, 
                           -frame_width * 3);

那么結(jié)果將變成這樣:

tmp66F

然后,我們?cè)囅聦?rendering buffer 附著(attach)到被分配的內(nèi)存區(qū)的某部分。這個(gè)修改會(huì)使得 rendering buffer 兩次附著在同一塊內(nèi)存區(qū)上,第一次是整個(gè)被分配的內(nèi)存區(qū)域,第二次是其中的一部分:

int main()
{
    unsigned char* buffer = new unsigned char[frame_width * frame_height * 3];

    memset(buffer, 255, frame_width * frame_height * 3);

    agg::rendering_buffer rbuf(buffer, 
        frame_width, 
        frame_height, 
        frame_width * 3);

    // Draw the outer black frame
    //------------------------
    draw_black_frame(rbuf);

    // Attach to the part of the buffer, 
    // with 20 pixel margins at each side.
    rbuf.attach(buffer + 
        frame_width * 3 * 20 +      // initial Y-offset
        3 * 20,                     // initial X-offset
        frame_width - 40,
        frame_height - 40,
        frame_width * 3               // Note that the stride
        // remains the same
        );               

    // Draw a diagonal line
    //------------------------
    unsigned i;
    for(i = 0; i < rbuf.height()/2; ++i)
    {
        // Get the pointer to the beginning of the i-th row (Y-coordinate)
        // and shift it to the i-th position, that is, X-coordinate.
        //---------------
        unsigned char* ptr = rbuf.row_ptr(i) + i * 3;

        // PutPixel, very sophisticated, huh? :)
        //-------------
        *ptr++ = 127; // R
        *ptr++ = 200; // G
        *ptr++ = 98;  // B
    }

    // Draw the inner black frame
    //------------------------
    draw_black_frame(rbuf);

    // Write to a file
    //------------------------
    write_ppm(buffer, frame_width, frame_height, "agg_test.ppm");

    delete [] buffer;
    return 0;
}

最后描畫出來(lái)的結(jié)果是這樣:

tmp672

最后一處修改是:

// Attach to the part of the buffer, 
// with 20 pixel margins at each side and negative 'stride'
rbuf.attach(buffer + 
            frame_width * 3 * 20 +      // initial Y-offset
            3 * 20,                     // initial X-offset
            frame_width - 40,
            frame_height - 40,
            -frame_width * 3              // Negate the stride
            );   

運(yùn)行結(jié)果如下:

tmp673

在最后的一個(gè)例子里,我們只是使 stride 取了負(fù)值,而指針則和上個(gè)例子一樣,仍然指向內(nèi)存區(qū)的起啟處。

注意:Function write_ppm() writes the pixel map to a file. Hereafter it will be omited in this text, but duplicated when necessary in source code in the agg2/tutorial directory.。

Pixel Format Renderers

首先,我們創(chuàng)建一個(gè)更“文明”(譯注:顯得更高級(jí)一點(diǎn))的例子:

#include <stdio.h>
#include <string.h>
#include "agg_pixfmt_rgb24.h"

enum
{
    frame_width = 320,
    frame_height = 200
};

// [...write_ppm is skipped...]

// Draw a black frame around the rendering buffer
//--------------------------------------------------
template<class Ren>
void draw_black_frame(Ren& ren)
{
    unsigned i;
    agg::rgba8 c(0,0,0);
    for(i = 0; i < ren.height(); ++i)
    {
        ren.copy_pixel(0,               i, c);
        ren.copy_pixel(ren.width() - 1, i, c);
    }
    for(i = 0; i < ren.width(); ++i)
    {
        ren.copy_pixel(i, 0,                c);
        ren.copy_pixel(i, ren.height() - 1, c);
    }
}


int main()
{
    //--------------------
    // Allocate the buffer.
    // Clear the buffer, for now "manually"
    // Create the rendering buffer object
    // Create the Pixel Format renderer
    // Do something simple, draw a diagonal line
    // Write the buffer to agg_test.ppm
    // Free memory

    unsigned char* buffer = new unsigned char[frame_width * frame_height * 3];

    memset(buffer, 255, frame_width * frame_height * 3);

    agg::rendering_buffer rbuf(buffer, 
        frame_width, 
        frame_height, 
        frame_width * 3);

    agg::pixfmt_rgb24 pixf(rbuf);

    unsigned i;
    for(i = 0; i < pixf.height()/2; ++i)
    {
        pixf.copy_pixel(i, i, agg::rgba8(127, 200, 98));
    }

    draw_black_frame(pixf);
    write_ppm(buffer, frame_width, frame_height, "agg_test.ppm");

    delete [] buffer;
    return 0;
}

這個(gè)例子看起來(lái)和前面的沒(méi)什么不一樣的,但其實(shí)他們差別很大,看看這個(gè)聲明:

agg::pixfmt_rgb24 pixf(rbuf);

這里我們創(chuàng)建了一個(gè)底層的像素渲染對(duì)象(pixel rendering object)并將它附著到渲染內(nèi)存區(qū)(rendering buffer)上,它是這樣定義的:

typedef pixel_formats_rgb24<order_rgb24> pixfmt_rgb24;

類模板 pixel_formats_rgb24 掌握了內(nèi)存中具體的像素格式信息。唯一的模板參數(shù)可以是 order_rgb24 或是 order_rgb23,它們定義了顏色字節(jié)(color channels)的順序。

與 rendering buffer 不同的是,這些類使用整型的像素坐標(biāo)進(jìn)行操作,因?yàn)樗鼈冎涝趺从?jì)算對(duì)于特定點(diǎn) X 的偏移。你可能會(huì)說(shuō),如果在 rendering buffer 中保存像素的寬度值的話會(huì)更容易,但是在實(shí)踐中會(huì)有很多限制。別忘了,像素寬度可能比一個(gè)字節(jié)還小,比如在打印機(jī)渲染高解析度的 B&W 圖像的時(shí)候就是這樣。因此,我們需要將這個(gè)功能分離出來(lái),rendering_buffer 這個(gè)類就用于加速對(duì)“行”的訪問(wèn),而 pixel format renderers 就負(fù)責(zé)如何解析“行”是什么。

現(xiàn)在,AGG 里下面這些文件實(shí)現(xiàn)了各種不同的像素格式:

  • agg_pixfmt_gray8.h:每個(gè)字節(jié)表示一個(gè)像素灰度。這種像素格式允許你將它和 rgb24 或是 rgb23 中的某個(gè)顏色成分放在一起工作。它有兩個(gè)模板參數(shù):Step 和 Offset,為方便起見(jiàn),還有下面這些 typedef :
    • typedef pixfmt_gray8_base<1, 0> pixfmt_gray8;
    • typedef pixfmt_gray8_base<3, 0> pixfmt_gray8_rgb24r;
    • typedef pixfmt_gray8_base<3, 1> pixfmt_gray8_rgb24g;
    • typedef pixfmt_gray8_base<3, 2> pixfmt_gray8_rgb24b;
    • typedef pixfmt_gray8_base<3, 2> pixfmt_gray8_bgr24r;
    • typedef pixfmt_gray8_base<3, 1> pixfmt_gray8_bgr24g;
    • typedef pixfmt_gray8_base<3, 0> pixfmt_gray8_bgr24b;
    • typedef pixfmt_gray8_base<4, 0> pixfmt_gray8_rgba32r;
    • typedef pixfmt_gray8_base<4, 1> pixfmt_gray8_rgba32g;
    • typedef pixfmt_gray8_base<4, 2> pixfmt_gray8_rgba32b;
    • typedef pixfmt_gray8_base<4, 3> pixfmt_gray8_rgba32a;
    • typedef pixfmt_gray8_base<4, 1> pixfmt_gray8_argb32r;
    • typedef pixfmt_gray8_base<4, 2> pixfmt_gray8_argb32g;
    • typedef pixfmt_gray8_base<4, 3> pixfmt_gray8_argb32b;
    • typedef pixfmt_gray8_base<4, 0> pixfmt_gray8_argb32a;
    • typedef pixfmt_gray8_base<4, 2> pixfmt_gray8_bgra32r;
    • typedef pixfmt_gray8_base<4, 1> pixfmt_gray8_bgra32g;
    • typedef pixfmt_gray8_base<4, 0> pixfmt_gray8_bgra32b;
    • typedef pixfmt_gray8_base<4, 3> pixfmt_gray8_bgra32a;
    • typedef pixfmt_gray8_base<4, 3> pixfmt_gray8_abgr32r;
    • typedef pixfmt_gray8_base<4, 2> pixfmt_gray8_abgr32g;
    • typedef pixfmt_gray8_base<4, 1> pixfmt_gray8_abgr32b;
    • typedef pixfmt_gray8_base<4, 0> pixfmt_gray8_abgr32a;
  • agg_pixfmt_rgb24.h, 每個(gè)像素占 3 個(gè)字節(jié),有 RGB 或是 BGR 兩種顏色順序。定義了下面這些像素類型:
    • typedef pixel_formats_rgb24<order_rgb24> pixfmt_rgb24;
    • typedef pixel_formats_rgb24<order_bgr24> pixfmt_bgr24;
  • agg_pixfmt_rgb555.h, 每個(gè)像素占 15 bits。 每 5 個(gè) bits 代表一種顏色成分,最低位沒(méi)用到。
  • agg_pixfmt_rgb565.h, 每個(gè)像素占 16 bits。紅色占 5 bits, 綠色占 6 bits, 藍(lán)色 5 bits。
  • agg_pixfmt_rgba32.h, 每個(gè)像素占 4 個(gè)字節(jié), RGB 再加 Alpha 通道值。下面有不同的顏色順序類型:
    • typedef pixel_formats_rgba32<order_rgba32> pixfmt_rgba32;
    • typedef pixel_formats_rgba32<order_argb32> pixfmt_argb32;
    • typedef pixel_formats_rgba32<order_abgr32> pixfmt_abgr32;
    • typedef pixel_formats_rgba32<order_bgra32> pixfmt_bgra32;

像素格式的類定義了它們?cè)嫉念伾臻g和顏色類型,像下面這樣:

typedef rgba8 color_type;

對(duì)于 pixfmt_gray8_nnn,這些都是 gray8,這種機(jī)制允許你寫自己的像素和顏色格式,舉個(gè)例子,HSV、CMYK 等等,AGG 的其它部分可以完全無(wú)誤地和你自己定義的新的像素格式一起工作。

注意

區(qū)分清楚 color type 和 buffer 代表的原始的顏色空間是非常重要的。比如說(shuō),你可以假設(shè)你正在使用 CMYK 進(jìn)行工作,但使用的是 RGB 的 buffer (你只需要寫一個(gè)簡(jiǎn)單的轉(zhuǎn)換函數(shù),就可以從 CMYK結(jié)構(gòu) 中創(chuàng)建 rgba8 的對(duì)象)。但這種轉(zhuǎn)換只是一個(gè)近似,可能會(huì)因此出現(xiàn)顏色上的失真,因?yàn)橛行?CMYK 中的顏色無(wú)法用 RGB 來(lái)表示,反之亦然。如果想完全使用某種顏色空間的表現(xiàn)能力,你可能要寫一個(gè)為這種顏色空間寫一個(gè)可以避免中間轉(zhuǎn)換的 pixel format renderer 。

Creation

重要!

像素格式相關(guān)的類并不進(jìn)行任何的裁剪操作,也就是說(shuō)直接使用這些類進(jìn)行工作一般來(lái)說(shuō)不太安全。裁剪是上層類的功能。采用這樣設(shè)計(jì)的理由很簡(jiǎn)單:要讓用戶設(shè)計(jì)自定義的像素格式類越簡(jiǎn)單越好。像素格式可能會(huì)五花八門,但裁剪操作的代碼一般都沒(méi)有什么區(qū)別。

pixel_formats_rgb24(rendering_buffer& rb);

像素格式渲染器(pixecl format renderers)的構(gòu)造函數(shù)需要一已經(jīng)創(chuàng)建并良好初始化的rendering_buffer對(duì)象的引用。這個(gè)構(gòu)建工作的開(kāi)銷很小,基本上只是初始化一個(gè)指針。

Member Functions

像素格式渲染器(pixecl format renderers)必須要實(shí)現(xiàn)以下這些接口:

unsigned width()  const { return m_rbuf->width();  }
unsigned height() const { return m_rbuf->height(); }

返回內(nèi)存區(qū)的寬和高(以像素?cái)?shù)來(lái)衡量)

color_type pixel(int x, int y);

返回(x,y)坐標(biāo)處的像素的顏色

void copy_pixel(int x, int y, const color_type& c); 

將帶顏色的像素拷入緩存區(qū)中。如果是本身 RGB 像素格式,那么它就不考慮 rgba8 拷貝源中的存在的 alpha 通道。如果本身是 RGBA,那么它就簡(jiǎn)單地把所有值都拷貝過(guò)來(lái),包括 R、G、B,以及 alpha 通道值。

void blend_pixel(int x, int y, const color_type& c, int8u cover);

這個(gè)函數(shù)將帶顏色信息的像素 c 與緩存區(qū)(x,y)處的像素進(jìn)行混合(blending)?,F(xiàn)在我們來(lái)解釋一下“混合”的概念?;旌?blending)是抗鋸齒(anti-aliasing)的關(guān)鍵特性。在 RGBA 的顏色空間中,我們使用 rgba8 結(jié)構(gòu)體來(lái)代表顏色。這個(gè)結(jié)構(gòu)體有一個(gè)數(shù)據(jù)成員 int8u a ,它就是 alpha 通道。不過(guò),在這個(gè)函數(shù)里,我們還看到一個(gè)參數(shù) cover ,表示像素的覆蓋值大小,比如,這個(gè)像素被多邊形所“覆蓋”的部分的大?。ㄗg注:這涉及到亞像素精度,因?yàn)橐粋€(gè)像素可以分為 256*256 份,所以這個(gè)像素并不一定全部被“覆蓋”,詳細(xì)可參考 AGG 對(duì)于亞像素的說(shuō)明)。其實(shí)你可以把它看成是另一個(gè) alpha(或者應(yīng)該叫它Beta?:))。這么做有兩個(gè)原因,首先,顏色類型(color type)不一定非要包含 alpha 值)。就算顏色類型帶有 alpha 值,它的類型也不一定非要與抗鋸齒算法中使用的顏色類型一致。假設(shè)你現(xiàn)在使用的是 "Hi-End" RGBA 顏色空間,這種顏色空間使用4個(gè)取值范圍是[0,1]浮點(diǎn)型來(lái)表示,alpha 通道值也使用浮點(diǎn)數(shù)————對(duì)于這種情況來(lái)說(shuō),混合時(shí)使用一個(gè)byte實(shí)在太少了,但在去鋸齒時(shí)卻非常夠用。所以,cover 值就是為去鋸齒而使用的一個(gè)統(tǒng)一的備用 alpha 值。在大部分情況來(lái)說(shuō),用 cover_type 來(lái)定義它,但在光柵化處理器(rasterizers)中是直接顯示地使用 int8u 類型的。這是故意這么定義的,因?yàn)槿绻枰訌?qiáng) cover_type 的能力時(shí),會(huì)使得所有已經(jīng)存在的像素格式光柵化處理器(pixel format rasterizres)變得與 cover_type 不兼容。它們確實(shí)是不兼容的,在進(jìn)行顏色混合時(shí),如果中間值使用 32-bit 值來(lái)暫存的話,那么最大只能使用 8-bit 的覆蓋值(coverage value)和 8-bit 的 alpha 值(alpha) 。如果使用 16-bit 的值的話,就要用 64-bit 的中間值暫存,這對(duì)于 32-bit 的平臺(tái)來(lái)說(shuō)會(huì)有非常昂貴的開(kāi)銷。

void copy_hline(int x, int y, unsigned len, const color_type& c); 
void copy_vline(int x, int y, unsigned len, const color_type& c);

使用某種顏色描畫一條水平或是垂直的線。

void blend_hline(int x, int y, unsigned len, const color_type& c, int8u cover); 
void blend_vline(int x, int y, unsigned len, const color_type& c, int8u cover);

采用混合顏色的模式描畫一帶某種顏色的水平(或垂直線)線。之所以要分開(kāi) copy 和 blend 兩個(gè)版本,是因?yàn)榭紤]到效率問(wèn)題。雖然可以使用一個(gè) if/else (其實(shí)在 blend 版的描畫函數(shù)中就有)來(lái)區(qū)分,但對(duì)于某些場(chǎng)合,比如要描畫很多小型標(biāo)識(shí)(markers)時(shí),這會(huì)很影響效率,這種場(chǎng)景在不同的散點(diǎn)圖描畫程序(scatter plot applicatioin)中常常遇到。

void blend_solid_hspan(int x, int y, unsigned len, 
                       const color_type& c, const int8u* covers);
void blend_solid_vspan(int x, int y, unsigned len, 
                       const color_type& c, const int8u* covers);

混合描畫一條水平或是垂直的 solid-color 的 span, Span與 hline 和 vline 幾乎是一樣的,但它擁有一個(gè)存有 coverage value 的數(shù)組。這兩個(gè)函數(shù)在渲染實(shí)心的去鋸齒多邊形時(shí)會(huì)用到。

void blend_color_hspan(int x, int y, unsigned len, 
                       const color_type* colors, const int8u* covers);
void blend_color_vspan(int x, int y, unsigned len, 
                       const color_type* colors, const int8u* covers);

混合描畫水平或是垂直的顏色 span ,這兩個(gè)函數(shù)用于不同的 span 產(chǎn)生器中,比如說(shuō) gradient,image,patterns,Gouraud interpolation 等等。函數(shù)接受一個(gè)顏色數(shù)組參數(shù),這個(gè)顏色數(shù)組必須與所使用的像素格式兼容。比如說(shuō),所有 AGG 中已經(jīng)有的 RGB 像素格式都與 rgb8 類型是兼容的。 covers 參數(shù)是一個(gè) coverage value 的數(shù)組,這與 blend_solid_hspan 中的是一樣的。這是參數(shù)可選,可以設(shè)置為 0 。

下面這個(gè)例子是描畫陽(yáng)光的光譜。rgba 類包含有 4 個(gè)浮點(diǎn)數(shù)的顏色部分(包括alpha),這個(gè)類有一個(gè)靜態(tài)函數(shù) from_wavelength ,以及相應(yīng)的構(gòu)造函數(shù)。rgba8 可以用 rgba 來(lái)構(gòu)造(在 AGG 中這是一個(gè)常見(jiàn)的策略,也就是任何的顏色類型都可以用 rgba 來(lái)構(gòu)造)。

#include <stdio.h>
#include <string.h>
#include "agg_pixfmt_rgb24.h" 

enum
{
    frame_width = 320,
    frame_height = 200
}; 

// [...write_ppm is skipped...] 
int main()
{
    //--------------------
    // Allocate the buffer.
    // Clear the buffer, for now "manually"
    // Create the rendering buffer object
    // Create the Pixel Format renderer
    // Create one line (span) of type rgba8.
    // Fill the buffer using blend_color_span
    // Write the buffer to agg_test.ppm
    // Free memory 
    unsigned char* buffer = new unsigned char[frame_width * frame_height * 3]; 
    memset(buffer, 255, frame_width * frame_height * 3); 
    agg::rendering_buffer rbuf(buffer, 
        frame_width, 
        frame_height, 
        frame_width * 3); 
    agg::pixfmt_rgb24 pixf(rbuf); 
    agg::rgba8 span[frame_width]; 
    unsigned i;
    for(i = 0; i < frame_width; ++i)
    {
        agg::rgba c(380.0 + 400.0 * i / frame_width, 0.8);
        span[i] = agg::rgba8(c);
    } 
    for(i = 0; i < frame_height; ++i)
    {
        pixf.blend_color_hspan(0, i, frame_width, span, 0);
    } 
    write_ppm(buffer, frame_width, frame_height, "agg_test.ppm"); 
    delete [] buffer;
    return 0;
} 

運(yùn)行結(jié)果如下:

tmp6D1

Alpha-Mask Adaptor

Alpha-Mask 是一個(gè)分離出來(lái)的緩存區(qū),通常用于在底層實(shí)現(xiàn)任意形狀的裁剪。有一個(gè)特制的適配器類,可以將所有對(duì)像素格式渲染器(pixel format renderes)的調(diào)用先丟給 alpha-mask 過(guò)濾器。alpha-mask 一般是一個(gè)灰度緩存區(qū)(每像素一個(gè)字節(jié)),大小與主渲染緩存區(qū)(main rendering buffer)是一樣的。在 alpha-mask 中的每個(gè)像素就是對(duì)應(yīng)著主渲染緩存區(qū)相應(yīng)像素的一個(gè)額外的覆蓋值(coverage value)。copy_hline()之類沒(méi)有酸辣值作為參數(shù)的函數(shù)會(huì)將調(diào)用轉(zhuǎn)向相應(yīng)的有覆蓋值的函數(shù)。比如,copy_hline()會(huì)從 alpha mask 緩存區(qū)中取出水平 span ,再用它來(lái)調(diào)用 blend_solid_hspan() 函數(shù)。

包含文件:

#include "agg_pixfmt_amask_adaptor.h"
#include "agg_alpha_mask_u8.h" 

下面是一個(gè)例子,它展示了如何聲明一個(gè)帶有 alpha-mask 適配器的像素格式渲染器。

#include "agg_pixfmt_rgb24.h"
#include "agg_pixfmt_amask_adaptor.h"
#include "agg_alpha_mask_u8.h" 
//. . . 
// Allocate the alpha-mask buffer, create the rendering buffer object
// and create the alpha-mask object.
//--------------------------------
agg::int8u* amask_buf = new agg::int8u[frame_width * frame_height];
agg::rendering_buffer amask_rbuf(amask_buf, 
                                 frame_width, 
                                 frame_height, 
                                 frame_width);
agg::amask_no_clip_gray8 amask(amask_rbuf); 
// Create the alpha-mask adaptor attached to the alpha-mask object
// and the pixel format renderer. Here pixf is a previously
// created pixel format renderer of type agg::pixfmt_rgb24.
agg::pixfmt_amask_adaptor<agg::pixfmt_rgb24, 
agg::amask_no_clip_gray8> pixf_amask(pixf, amask);
//. . . 

注意在這里我們用的是 amask_no_clip_gray8 ,它不帶區(qū)域裁剪功能。因?yàn)槲覀兪褂玫?alpha-mask 緩存區(qū)和主緩存區(qū)的大小是一樣的,所以只要主緩存區(qū)沒(méi)有非法訪問(wèn)的話,alpha-mask 緩存區(qū)也不會(huì)存在非法訪問(wèn)。裁剪在高層中實(shí)現(xiàn),如果你使用的 alpha-mask 緩存區(qū)比主緩存區(qū)小的話,你必須使用 alpha_mask_gray8 這個(gè)類來(lái)代替。

下面是一個(gè)完整的例子:

#include <stdio.h>
#include <string.h>
#include "agg_pixfmt_rgb24.h"
#include "agg_pixfmt_amask_adaptor.h"
#include "agg_alpha_mask_u8.h" 

enum
{
    frame_width = 320,
    frame_height = 200
}; 

// [...write_ppm is skipped...] 
int main()
{
    // Allocate the main rendering buffer and clear it, for now "manually",
    // and create the rendering_buffer object and the pixel format renderer
    //--------------------------------
    agg::int8u* buffer = new agg::int8u[frame_width * frame_height * 3];
    memset(buffer, 255, frame_width * frame_height * 3);
    agg::rendering_buffer rbuf(buffer, 
        frame_width, 
        frame_height, 
        frame_width * 3);
    agg::pixfmt_rgb24 pixf(rbuf); 
    // Allocate the alpha-mask buffer, create the rendering buffer object
    // and create the alpha-mask object.
    //--------------------------------
    agg::int8u* amask_buf = new agg::int8u[frame_width * frame_height];
    agg::rendering_buffer amask_rbuf(amask_buf, 
        frame_width, 
        frame_height, 
        frame_width);
    agg::amask_no_clip_gray8 amask(amask_rbuf); 
    // Create the alpha-mask adaptor attached to the alpha-mask object
    // and the pixel format renderer
    agg::pixfmt_amask_adaptor<agg::pixfmt_rgb24, 
        agg::amask_no_clip_gray8> pixf_amask(pixf, amask); 
    // Draw something in the alpha-mask buffer. 
    // In this case we fill the buffer with a simple verical gradient
    unsigned i;
    for(i = 0; i < frame_height; ++i)
    {
        unsigned val = 255 * i / frame_height;
        memset(amask_rbuf.row_ptr(i), val, frame_width);
    } 
    // Draw the spectrum, write a .ppm and free memory
    //----------------------
    agg::rgba8 span[frame_width]; 
    for(i = 0; i < frame_width; ++i)
    {
        agg::rgba c(380.0 + 400.0 * i / frame_width, 0.8);
        span[i] = agg::rgba8(c);
    } 
    for(i = 0; i < frame_height; ++i)
    {
        pixf_amask.blend_color_hspan(0, i, frame_width, span, 0);
    } 
    write_ppm(buffer, frame_width, frame_height, "agg_test.ppm"); 
    delete [] amask_buf;
    delete [] buffer;
    return 0;
} 

這是運(yùn)行結(jié)果:

tmp6D2

你看到了,我們是用白色來(lái)清空主緩存的,如果我們將:

memset(buffer, 255, frame_width * frame_height * 3); 

修改成:

memset(buffer, 0, frame_width * frame_height * 3);

那么結(jié)果就像下面這樣:

tmp6D3

換句話說(shuō),alpha-mask 是這樣工作的:它是一個(gè)分離出來(lái)的 alpha 通道,用于混合渲染基本的描畫物。因?yàn)樗氖?8-bit 的值,所以你可以將描畫裁剪成任意的形狀,而且這種裁剪可以有很非常好的去鋸齒效果。

Basic Renderers

有兩種基礎(chǔ)渲染器,renderer_base 和 renderer_mclip 它們的功能幾乎是一樣的。主要使用的是前者(renderer_base),它進(jìn)行低層次的裁剪處理。通用的裁剪處理(clipping)是一個(gè)復(fù)雜的任務(wù)。在 AGG 中,至少可以有兩層的裁剪,底層(像素級(jí))的,和高層的(向量級(jí))。這兩個(gè)類可以進(jìn)行像素級(jí)別的裁剪,用以防止對(duì)緩存區(qū)的越界訪問(wèn)。 renderer_mclip 類可以支持多個(gè)矩形區(qū)域的裁剪區(qū)域,但它的性能和裁剪區(qū)域的數(shù)量有關(guān)。

renderer_base 和 renderer_mclip 都是模板類,它們的模板參數(shù)就是像素格式渲染器(pixel format renderer)。

template<class PixelFormat> class renderer_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);

兩個(gè)類的構(gòu)造函數(shù)都可以接受像素格式渲染器(pixel format renderer)對(duì)象作為參數(shù)。 renderer_mclip 在內(nèi)部使用 renderer_base<PixelFormat> ,用來(lái)進(jìn)行單矩形區(qū)域的裁剪。注意,你也可以使用 pixfmt_amask_adaptor 作為參數(shù) PixelFormat。

構(gòu)造的開(kāi)銷是非常小的,它只是初始化各個(gè)成員變量。不過(guò),如果你添加新的裁剪區(qū)域,那么 renderer_mclip 需要申請(qǐng)新的內(nèi)存,在析構(gòu)時(shí)也會(huì)有相應(yīng)的釋放動(dòng)作。它會(huì)用 pod_deque 類來(lái)完成內(nèi)存塊的申請(qǐng),并且它不會(huì)(提前)釋放不需要的內(nèi)存,當(dāng)你重新設(shè)置裁剪區(qū)域的時(shí)候,它會(huì)重用原來(lái)申請(qǐng)的內(nèi)存區(qū)。 AGG 中廣泛使用了這種技術(shù),這可以避免產(chǎn)生過(guò)多的內(nèi)存碎片。

Member Functions

const pixfmt_type& ren() const;
pixfmt_type& ren();

返回指向像素渲染器(pixel format renderer)的引用。

unsigned width()  const;
unsigned height() const; 

返回渲染緩存區(qū)(rendering buffer)的高和度。

void reset_clipping(bool visibility);

這個(gè)函數(shù)會(huì)重設(shè)裁剪區(qū)域,如果 visibility 值設(shè)置為 true ,那么裁剪區(qū)域會(huì)被設(shè)置為 (0, 0, width()-1, height()-1),如果設(shè)置為 false,會(huì)設(shè)置一個(gè)不可見(jiàn)的區(qū)域,比如(1,1,0,0)。對(duì)于 renderer_mclip 的這個(gè)函數(shù)來(lái)說(shuō),它會(huì)移除之前添加的所有剪裁區(qū)域。

重要!

如果你將另一塊內(nèi)存區(qū)附著到 rendering_buffer 上的話(rendering_buffer是連接著這個(gè)(basic_renderer),你必須調(diào)用一次 reset_clipping() ,否則的話,原來(lái)的裁剪區(qū)域會(huì)變得無(wú)效。 因?yàn)檫@個(gè)內(nèi)存改變動(dòng)作做完之后并不會(huì),rendering buffer 不會(huì)給 renderers 任何反饋。也就是說(shuō),renderer_base 和 renderer_mclip 對(duì)于 rendering buffer 的變動(dòng)一無(wú)所知(譯注:renderer_base是用 pixel format render來(lái)構(gòu)造的,而 pixel format render 又是由 rendering buffer 來(lái)支撐,所以它們之間就有這樣的關(guān)系,具體可見(jiàn)前文)。如果有這樣的機(jī)制,可以在它們之間傳遞消息或是使用委托,那么這種機(jī)制可能成為 overkill (譯注:不知道怎么理解這個(gè)overkill)。

bool clip_box(int x1, int y1, int x2, int y2);

這個(gè)函數(shù)用于設(shè)置新的裁剪區(qū)域(clipping box)。只有 renderer_base 才有這個(gè)函數(shù)。裁剪區(qū)域包含了邊界位置,所以最大的裁剪區(qū)域是 (0, 0, width()-1, height()-1) 。裁剪區(qū)域在(重新)設(shè)置之前,會(huì)被設(shè)置為最大值。所以,就算你設(shè)置新區(qū)域的比 (0, 0, width()-1, height()-1) 還要大,也是安全的(譯注:因?yàn)椴粫?huì)被采用)

void add_clip_box(int x1, int y1, int x2, int y2);

添加一個(gè)新的裁剪區(qū)域。只有 renderer_mclip 才有這個(gè)函數(shù)。你可以添加任何個(gè)新的矩形區(qū)域,但他們之間不能有重疊的部分。如果有重疊的區(qū)域的話,有些元素就會(huì)被描畫兩次或兩次以上。被添加的新區(qū)域會(huì)在加入之時(shí)被 (0, 0, width()-1, height()-1) 這個(gè)區(qū)域預(yù)先裁剪掉,這主要是有效率上的考量。這也意味著調(diào)用 reset_clipping(false)沒(méi)有任何意義,因?yàn)樗斜惶砑拥男聟^(qū)域都會(huì)用一個(gè)不可見(jiàn)區(qū)域內(nèi)先裁剪掉,因此也就不會(huì)被添加。(譯注:原句如下:t also means that calling reset_clipping(false) for the renderer_mclip doesn't make any sense because all adding regions will be clipped by an invisible area and will not be actually added.對(duì)這個(gè)我不能理解它的意思,后面看了代碼再來(lái)修正吧)。可見(jiàn)區(qū)域包含裁剪區(qū)域的邊界,也就是說(shuō),調(diào)用 add_clip_box(100,100,100,100) 會(huì)添加一個(gè) 1 像素的裁剪區(qū)域。

void clip_box_naked(int x1, int y1, int x2, int y2);

只有 renderer_base 有這個(gè)函數(shù),它用來(lái)給 rendering buffer 大小設(shè)置一個(gè)新的裁剪區(qū)域。這個(gè)函數(shù)不安全,主要是 renderer_mclip 類在使用它,用來(lái)在不同的子區(qū)域之間快速的切換。這個(gè)函數(shù)的目的就是為了避免額外的開(kāi)銷。

bool inbox(int x, int y) const;

檢查 (x,y) 這個(gè)點(diǎn)是不是在裁剪區(qū)域內(nèi)。只有 renderer_base 才有這個(gè)函數(shù)。

void first_clip_box();
bool next_clip_box();

這兩個(gè)函數(shù)用于枚舉渲染器所有的裁剪區(qū)域。對(duì)于 renderer_base 類來(lái)說(shuō),它是返回的是空的, next_clip_box() 始終返回 false。

const rect& clip_box() const;
int         xmin()     const;
int         ymin()     const;
int         xmax()     const;
int         ymax()     const;

以一個(gè)矩形的形式可是以四個(gè)獨(dú)立的整數(shù)值形式返回裁剪區(qū)域。 renderer_mclip 的這個(gè)函數(shù)始終返回 (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;

以一個(gè)矩形的形式可是以四個(gè)獨(dú)立的整數(shù)值形式返回裁剪區(qū)域的邊界。對(duì)于 renderer_base ,這個(gè)函數(shù)返回的值于上面那組函數(shù)是一樣的。對(duì)于 renderer_mclip 來(lái)說(shuō),它們返回的邊界是由所有被添加的矩形合計(jì)得出的。

void clear(const color_type& c);

用 c 這個(gè)顏色來(lái)清除緩存區(qū)內(nèi)的所有區(qū)域(不考慮裁剪區(qū)域)。

void copy_pixel(int x, int y, const color_type& c);

設(shè)置一個(gè)像素的顏色(考慮裁剪區(qū)域clipping)。

void blend_pixel(int x, int y, const color_type& c, cover_type cover);

混合描畫一個(gè)像素。它的行為與 pixel format renderer 的對(duì)應(yīng)函數(shù)是一樣的。

color_type pixel(int x, int y) const; 

獲取指定坐標(biāo)(x,y)的顏色值,如果這個(gè)點(diǎn)在裁剪區(qū)域外,這個(gè)函數(shù)返回 color_type::no_color(). 對(duì)于 rgba8 來(lái)說(shuō),就是 (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 的相應(yīng)函數(shù)一樣。但在這里,使用的是線的起始點(diǎn)和終點(diǎn)坐標(biāo),而不是 pixfmt 中的(x, y, length)。

void copy_bar(int x1, int y1, int x2, int y2, const color_type& c);
void blend_bar(int x1, int y1, int x2, int y2, 
               const color_type& c, cover_type cover);

描畫(拷貝)或是混合渲染一個(gè)矩形區(qū)。

void blend_solid_hspan(int x, int y, int len, 
                       const color_type& c, const cover_type* covers);
void blend_solid_vspan(int x, int y, int len, 
                       const color_type& c, const cover_type* covers);

混合渲染一個(gè)水平或是垂直的純色(solid-color)的span。這些在渲染實(shí)多邊形時(shí)會(huì)用到。

void blend_color_hspan(int x, int y, int len, 
                       const color_type* colors, const cover_type* covers);
void blend_color_vspan(int x, int y, int len, 
                       const color_type* colors, const cover_type* covers);

混合渲染一個(gè)水平或是垂直的(? vertical -color)的span。這個(gè)函數(shù)與不同的 span 生成器一起使用,比如 gradients, images, patterns, Gouraud interpolation 等等。函數(shù)接受一個(gè)顏色數(shù)組,顏色的類型必須與正在使用 pixel format 兼容。

void blend_color_hspan_no_clip(int x, int y, int len, 
                               const color_type* colors, 
                               const cover_type* covers);
void blend_color_vspan_no_clip(int x, int y, int len, 
                               const color_type* colors, 
                               const cover_type* covers);

與上面的函數(shù)是一樣的,但不考慮裁剪區(qū)域。這兩個(gè)函數(shù)用到 scanline renderers 中。分離出這兩個(gè)函數(shù)的原因也是為了效率,scanline 由很多的 spans 組合而成,在進(jìn)行區(qū)域裁剪時(shí),擁有整個(gè) scanline 的信息會(huì)比逐個(gè)的裁剪每個(gè) span 來(lái)得更有效率一些,對(duì)于 renderer_mclip 這個(gè)類尤其如此。

void copy_from(const rendering_buffer& from, 
               const rect* rc=0, 
               int x_to=0, 
               int y_to=0);

將源緩存區(qū)的內(nèi)容拷入本緩存區(qū)中(考慮區(qū)域裁剪)。它假設(shè)兩塊緩存區(qū)的像素格式是一樣的。rc是一個(gè)可選項(xiàng),它指示的是源緩存區(qū)內(nèi)的一個(gè)矩形,x_to 、 y_to ———— rc->x1, rc->y1 坐標(biāo)值映射到目標(biāo)緩存區(qū)。

A common example

在使用 rendering buffer 和底層 renderers 時(shí),下面的代碼是非常常用的。

// Typedefs of the low level renderers to simplify the declarations.

// Here you can use any other pixel format renderer and

// agg::renderer_mclip if necessary.

//--------------------------

typedef agg::pixfmt_rgb24                     pixfmt_type;
typedef agg::renderer_base<agg::pixfmt_rgb24> renbase_type;

enum { bytes_per_pixel = 3 }; 

unsigned char* buffer = new unsigned char[frame_width * frame_height * bytes_per_pixel];
agg::rendering_buffer rbuf(buffer, 
                           frame_width, 
                           frame_height, 
                           frame_width * bytes_per_pixel);
pixfmt_type pixf(rbuf);
renbase_type rbase(pixf); 
rbase.clear(clear_color);
//. . . 

在最后,我們使用clear()函數(shù),以某種顏色清除了緩存區(qū)中,而沒(méi)有“手動(dòng)地”使用 memset() :-)。同時(shí)要注意,與例子所不同的是,stride 值并不是必須要和  frame_width * bytes_per_pixel 值一致。很多時(shí)候應(yīng)用時(shí)會(huì)有一些對(duì)齊上的要求,比如,對(duì)于 windows中的位圖(bitmap)來(lái)說(shuō),這個(gè)值必須是4的倍數(shù)。

Primitives and Markers Renderers

AGG 中也加入了一些基礎(chǔ)描畫對(duì)象(primitives)和標(biāo)記(marker)的渲染器。這個(gè)機(jī)制可以讓你很快地描畫一些常見(jiàn)的、帶鋸齒的對(duì)象,比如直線,矩形,橢圓等。標(biāo)記(marker)可以畫出一些在散點(diǎn)圖(scatter plots)中常見(jiàn)的形狀。如果你不打算用它們,那么你可以跳過(guò)這一節(jié)的內(nèi)容。

Primitives Renderer

頭文件: agg_renderer_primitives.h

Declaration

template<class BaseRenderer> class renderer_primitives
{
public:
    typedef BaseRenderer base_ren_type;
    typedef typename base_ren_type::color_type color_type;
    //. . .
}; 

這里的 BaseRenderer 可以用 renderer_base 或是 renderer_mclip.

Creation

renderer_primitives(base_ren_type& ren) :
                            m_ren(&ren),
                            m_fill_color(),
                            m_line_color(),
                            m_curr_x(0),
                            m_curr_y(0)
{} 

創(chuàng)建的開(kāi)銷非常小,只是初始化指向 base renderer 對(duì)象的指針、兩個(gè)顏色信息、以及初始化坐標(biāo)值,這些坐標(biāo)值會(huì)在 move_to 和 line_to 函數(shù)中用到。

Member functions

static int coord(double c);

將一個(gè) double 型的坐標(biāo)值轉(zhuǎn)換成亞像素精度的 int 型。它做的事就是將 double 值乘以256 ,然后返回它的整型部分。

void fill_color(const color_type& c);
void line_color(const color_type& c);
const color_type& fill_color() const;
const color_type& line_color() const;

獲取或是設(shè)置 fill 或是直線的顏色。顏色可以帶有 alpha 值并且這個(gè)值會(huì)生效,這樣的話,基礎(chǔ)畫面對(duì)象(primitives)就可以進(jìn)行 alpha 混合渲染。

void rectangle(int x1, int y1, int x2, int y2);

描畫一個(gè)矩形,但不填充線的顏色。使用的是正規(guī)的像素坐標(biāo),邊界的寬度始終是 1 像素,不能修改。

void solid_rectangle(int x1, int y1, int x2, int y2);

描畫一個(gè)不帶邊界的實(shí)心矩形,填充線的顏色。使用的是像素坐標(biāo)。

void outlined_rectangle(int x1, int y1, int x2, int y2);

描畫一個(gè)帶邊界的實(shí)心矩形。使用了顏色線(colors line)和填充(fill?)。

void ellipse(int x, int y, int rx, int ry);
void solid_ellipse(int x, int y, int rx, int ry);
void outlined_ellipse(int x, int y, int rx, int ry);

描畫橢圓,空心的、實(shí)心的或是實(shí)心帶邊界的。坐標(biāo)是整數(shù)值,以像素?cái)?shù)來(lái)衡量。rx 和 ry 是像素?cái)?shù)衡量的橢圓半徑。

void line(int x1, int y1, int x2, int y2, bool last=false); 

使用亞像素精度描畫一條 bresenham 光柵線。坐標(biāo)的格式是 24.8,即,1/256的像素精度。 last 決定是否描畫最后一個(gè)像素,這對(duì)于使用 alpha混合渲染來(lái)描畫 consecutive 線段會(huì)非常重要。不應(yīng)該有像素被多次描畫。

void move_to(int x, int y);
void line_to(int x, int y, bool last=false);

line()版本。

const base_ren_type& ren() const { return *m_ren; }        
base_ren_type& ren() { return *m_ren; }

返回 base renderer 對(duì)象的引用。

const rendering_buffer& rbuf() const { return m_ren->rbuf(); }
rendering_buffer& rbuf() { return m_ren->rbuf(); } 

返回附著于 base renderer 的 rendering buffer 的引用。

Marker Renderer

頭文件: agg_renderer_markers.h

marker renderer 可以描畫或是 alpha混合沉浸下面的這些圖形:

enum marker_e
{
    marker_square,
    marker_diamond,
    marker_circle,
    marker_crossed_circle,
    marker_semiellipse_left,
    marker_semiellipse_right,
    marker_semiellipse_up,
    marker_semiellipse_down,
    marker_triangle_left,
    marker_triangle_right,
    marker_triangle_up,
    marker_triangle_down,
    marker_four_rays,
    marker_cross,
    marker_x,
    marker_dash,
    marker_dot,
    marker_pixel
}; 

Declaration

template<class BaseRenderer> class renderer_markers :
public renderer_primitives<BaseRenderer>
{
public:
    typedef renderer_primitives<BaseRenderer> base_type;
    typedef BaseRenderer base_ren_type;
    typedef typename base_ren_type::color_type color_type;
    // . . .
}; 

Creation

renderer_markers(base_ren_type& rbuf) :
                        base_type(rbuf)
{} 

正如你所見(jiàn),構(gòu)造的過(guò)程和 renderer_primitives 是一樣簡(jiǎn)單的。

Member Functions

marker 的所有函數(shù)都接受 x 、y 和半徑作為參數(shù),這些值以像素?cái)?shù)來(lái)衡量。在pixel() 中,半徑值沒(méi)有任何作用。填充(fill)和邊線(line)顏色都來(lái)自 renderer_primitives 基類。

void square(int x, int y, int r);
void diamond(int x, int y, int r);
void circle(int x, int y, int r);
void crossed_circle(int x, int y, int r);
void semiellipse_left(int x, int y, int r);
void semiellipse_right(int x, int y, int r);
void semiellipse_up(int x, int y, int r);
void semiellipse_down(int x, int y, int r);
void triangle_left(int x, int y, int r);
void triangle_right(int x, int y, int r);
void triangle_up(int x, int y, int r);
void triangle_down(int x, int y, int r);
void four_rays(int x, int y, int r);
void cross(int x, int y, int r);
void xing(int x, int y, int r);
void dash(int x, int y, int r);
void dot(int x, int y, int r);
void pixel(int x, int y, int); 

當(dāng)然,有一些為圖方便的函數(shù)存在,這些函數(shù)基本上就是使用 switch/case 來(lái)構(gòu)造:

void marker(int x, int y, int r, marker_e type);

根據(jù)給定的類型來(lái)描畫一個(gè) marker。

template<class T>
void markers(int n, const T* x, const T* y, T r, marker_e type);

根據(jù)給定的類型描畫一系列的 marker,坐標(biāo)存儲(chǔ)在 x 和 y 兩個(gè)數(shù)組中。

template<class T>
void markers(int n, const T* x, const T* y, const T* r, marker_e type);

根據(jù)給定的類型描畫一系列的 marker,坐標(biāo)和半徑值分別存儲(chǔ)在 x、 y 和 r 三個(gè)數(shù)組中。

template<class T>
void markers(int n, const T* x, const T* y, const T* r, 
             const color_type* fill_colors, 
             marker_e type);

根據(jù)給定的類型描畫一系列的 marker,坐標(biāo)、半徑值以及顏色分別存儲(chǔ)在 x、 y 、 r 和 fill_colors 四個(gè)數(shù)組中。

template<class T>
void markers(int n, const T* x, const T* y, const T* r, 
             const color_type* fc, const color_type* lc, 
             marker_e type);

根據(jù)給定的類型描畫一系列的 marker,坐標(biāo)、半徑值以及顏色分別存儲(chǔ)在 x、 y 、 r 、fc 和 lc 等數(shù)組中。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多