學習cairo的心得及資料

最近一直忙於cairo渲染接口的封裝,目前該任務已接近尾聲,在此記錄一下學習cairo的心得體會。

cairo是linux系統上一款高質量2D圖形渲染庫,與Gdiplus庫相比,其優勢是支持繪製<1.0的線寬、提供了直接輸出到內存buffer、pdf文件、png文件、ps、xlib、XCB、win32、svg的接口。關於cairo的簡單介紹,詳見這裏

學習cairo的過程,也是“山重水複疑無路,柳暗花明又一村”的一種體驗。當前網上對cairo的介紹僅限於粗略的入門,想要很好的完成封裝cairo畫圖接口的任務,還必須結合實際情況,深入到cairo源碼的底層,去分析它的具體實現思路。此外,價值量最大的就是去查閱官方文檔,在這裏先放上“導學”部分的翻譯內容,以及官方的函數文檔

使用cairo,重點在於對path的理解,以及對內存圖像緩衝區數據的靈活讀取(例如,使用cairo_image_surface_get_data或者使用cairo_image_surface_create_for_data取出或綁定的內存,其半透明像素點的顏色值與實際保存到png文件的顏色值並不相同,解決這個問題最簡單的辦法就是使用cairo提供的cairo_surface_write_to_png_stream和cairo_image_surface_create_from_png_stream接口,並且自定義滿足自己任務要求的回調函數,如下所示)。

struct st_png_data
{
	unsigned char* pdata;
	unsigned int length;
};

static cairo_status_t cairo_read_func_mine (void *closure, unsigned char *data, unsigned int length)
{
	st_png_data* pPngData = (st_png_data*)closure;
	memcpy(data, pPngData->pdata + pPngData->length, length);
	pPngData->length += length;
	return CAIRO_STATUS_SUCCESS;
}

static cairo_status_t cairo_write_func_mine (void *closure, const unsigned char *data, unsigned int length)
{
	vector<unsigned char>& vecData = *((vector<unsigned char>*)closure);
	for (unsigned int i = 0; i < length; ++i)
	{
		vecData.push_back(data[i]);
	}
	return CAIRO_STATUS_SUCCESS;
}

st_png_data pngData = {(unsigned char*)pImgBinary, 0};
m_surface = cairo_image_surface_create_from_png_stream(cairo_read_func_mine, &pngData);

vector<unsigned char> vecData;
cairo_surface_write_to_png_stream(m_surface, cairo_write_func_mine, &vecData);
此外,在繪製字體部分,你會發現cairo默認不支持輸出漢字。仔細分析其原因,是因爲其接口僅接受utf-8格式的字符串,而我們輸入的字符串是ANSI編碼格式或者Unicode編碼格式,因此,我們只需轉化一下輸入字符串的編碼格式便可以支持輸出漢字了,比如使用boost庫提供的boost::locale::conv::between方法進行轉化。

寫本文的目的只是想給初學cairo的新手一個快速入門的方法指導,以及對我遇到的一些難點的簡單分析,如果你對GDI+十分熟悉,學習cairo也是大同小異的,凡是GDI+能實現的功能,我們都可以使用cairo實現,在此處順便向大家推薦一篇不錯的GDI+博文,可供大家對比學習。

發佈了28 篇原創文章 · 獲贊 50 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章