Duilib 改造之路 渲染效果 1 不打馬賽克的世界

<不附帶任何源碼,求源碼者離場,請自行修改>

大約耗時:3-4小時

由於開發時間等問題,duilib的渲染方式是使用GDI的方式的,這意味着渲染效果會存在一定缺陷,當我們拉伸圖片的時候很容易就會出現鋸齒,一些圖片的顯示質量差,文字出現凹槽鋸齒,無論你怎麼修改xml,差一兩個像素就會有一堆馬賽克,怎麼辦?使用GDI+替代GDI


去瞄一下duilib的文檔,duilib的所有繪製都會通過CRenderClip和CRenderEngine這個兩個類來完成,然後我們分析一下類結構,可以發現所有的圖像繪製都是通過DrawImage函數實現的,但問題的關鍵不在於繪製而是圖片的存儲

這是圖片存儲的結構體,裏面描述了圖片的一些屬性,因爲我們將會使用GDI+代替原來的GDI,所以我們修改一下這個結構體

好吧,先不要吐槽,這裏也不是玩大家來找茬,我們使用GDI+的Bitmap代替HBITMAP,然後直接按一下F5,就會報一大堆錯誤,

這些錯誤可以幫助我們快速找到需要修改的地方,還是那句:沒有必要完全掌握所有代碼,因爲只是"分工合作"


這些錯誤大概是類型不匹配和無法找到Bitmap*類型之流.後者只要添加GDI+支持就可以了,前者只需要一個轉換函數就可了,但是具體的修改方案自行制定吧,不過有以下兩個建議,

統一出入口,試想一下如果duilib原作者沒有通過DrawImage函數來實現繪製,而是每個控件都有自己的繪製函數或者繪製流程,那麼現在會發生什麼事?

減少轉換次數,應該在加載的時候進行轉換,而不是繪製時轉換

和duilib源碼相比,我的duilib庫引入了stl來代替原來的容器類,這樣很大程度上使duilib的源碼更加清晰,同時避免了duilib在實際工作中的不穩定性(duilib的很多BUG都是來源於自身的容器類,建議就是使用stl替換,但是這項工程非常龐大,所以現在還是逐步更替比較合適)


完成一大堆轉換(複製黏貼)後,回到DrawImage函數,接下來就是GDI繪製轉GDI+繪製的時間了,你需要的是一大堆紙和筆做四則運算(找個小學生來做可能快一點......),至於GDI+的繪製方式網上一大堆,我就不復制黏貼了.


下面就是文字的繪製,上面我們還可以修改一下結構體,但是這裏我們只能直接面對DrawText函數了,因爲GDI的文字繪製方式和GDI+完全不同,而且源碼中沒有對繪製文字的參數集中處理,部分控件對文字進行了處理,所以我們不可能像上面的方法那樣去修改文字繪製,只能直接對DrawText函數(最後輸出點)進行修改這裏存在HFONT轉Font(自行百度)


最後就是字串風格了,在GDI中是通過一個UINT來控制,但是到GDI+中卻分門別類地進行,怎麼統一?

下面提供一種參考方法

    

在GDI我們會通過不段對uStyle進行"|"(位或運算) 來添加風格,當要分解的時候我們可以像上面那樣通過&(位與運算)來分解,然後轉換成GDI+的字串風格,這組位運算可以用在很多地方,例如管理軟件權限分配,遊戲中的任務狀態等.


最後就是一個小細節,關於字體繪製方式,TextRenderingHintClearTypeGridFit和TextRenderingHintAntiAlias(這兩種比較合適),TextRenderingHintClearTypeGridFit會使字體更加"清晰"(連橫豎的凹槽都看見了),而TextRenderingHintAntiAlias會使字體更加"模糊"(筆畫長度變短,厚度均勻),基本上用哪一種都會有問題,所以建議大號字用TextRenderingHintAntiAlias,這樣就不會有凹槽出現,小號字用TextRenderingHintClearTypeGridFit,這樣字就會清晰沒有鋸齒

if(m_tfi->iSize <= 12)
{
graphics.SetTextRenderingHint( TextRenderingHintClearTypeGridFit );
}
else
{
graphics.SetTextRenderingHint( TextRenderingHintAntiAlias );
}






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章