• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            飯中淹的避難所~~~~~

            偶爾來(lái)避難的地方~

              C++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
              94 隨筆 :: 0 文章 :: 257 評(píng)論 :: 0 Trackbacks

            【簡(jiǎn)述】

            本文講述了一個(gè)簡(jiǎn)單的平臺(tái)無(wú)關(guān)的RICHTEXT的實(shí)現(xiàn)方法。

            這個(gè)RICHTEXT特性如下:

            -          使用UTF-16作為字符編碼

            -          使用行來(lái)排版,文字從左到右顯示

            -          支持可獨(dú)立設(shè)置字體顏色的文字和鏈接

            -          支持自定義元素用來(lái)實(shí)現(xiàn)圖像和動(dòng)畫(huà)

             

            【平臺(tái)無(wú)關(guān)】

             

            平臺(tái)無(wú)關(guān)實(shí)際上是使用統(tǒng)一的接口來(lái)封裝不同平臺(tái)的實(shí)現(xiàn)方法來(lái)做到的。在RICHTEXT中使用到的平臺(tái)相關(guān)的有兩個(gè):

            1-       文字大小獲取。

            2-       文字的繪制。

             

            我們把它封裝到一個(gè)字體的純虛接口類中去:

            class IFont {

            public:

            // 獲取字體的高度

            virtual float GetHeight() const = 0;

            // 獲取文字的橫向步進(jìn)

            virtual float GetCharsAdvance( const UTF16_CHAR * pChars, float * pAdvanceArray, size_t uCount ) const = 0;

            // 繪制文字

            virtual void DrawChars( const UTF16_CHAR * pChars, size_t uCount, float fX, float fY, unsigned long ulColor ) const = 0;

            };

             

            對(duì)于自定義的元素,也是一個(gè)純虛的接口類:

                     class IRichTextCustomElement

                     {

                     public:

                               //      獲取元素寬度

                               virtual float GetWidth() const = 0;

                               //      獲取元素的高度

                               virtual float GetHeight() const = 0;

                               //      繪制元素

                               virtual void Draw( float fX, float fY ) const = 0;

                     };

             

            【實(shí)現(xiàn)】

             

            1-       模塊劃分

            RICHTEXT在這里劃分為兩個(gè)模塊:一個(gè)稱為RichTextDoc,用來(lái)存儲(chǔ)內(nèi)容的,稱為文檔;一個(gè)稱為RichTextView,用來(lái)存儲(chǔ)表現(xiàn)的,稱為視圖。

             

            2-       模塊實(shí)現(xiàn):RichTextDoc

             

            RichTextDoc主要實(shí)現(xiàn)了內(nèi)容管理。

             

            RichTextDoc內(nèi)部存儲(chǔ)兩項(xiàng)內(nèi)容

            1)       字符

            2)       元素(不同的元素類型,或者同種元素類型但屬性不同)

             

            字符存儲(chǔ)了文字和鏈接的原始字符,而元素存儲(chǔ)了同屬性的一組字符、鏈接或者一個(gè)自定義元素。他們使用idxlen關(guān)聯(lián)到字符存儲(chǔ)中的原始字符。對(duì)于一個(gè)圖片,在字符中使用了一個(gè)空格作為占位符。

            元素中同時(shí)存儲(chǔ)了是否作為一個(gè)段落ID,這用來(lái)描述一組元素是否在同一個(gè)段落里,這個(gè)ID為一個(gè)不為0的正整數(shù)。

             

                     RichTextDoc提供了以下接口來(lái)添加內(nèi)容以及訪問(wèn)元素。

             

                     class IRichTextDoc

                     {

                     public:

                               //      添加一段文本

                              virtual void AddText( const UTF16_CHAR * pText, size_t uTextLen ) = 0;

                               //      添加一個(gè)鏈接

                               virtual void AddLink( const UTF16_CHAR * pText, size_t uTextLen, unsigned long ulLinkID ) = 0;

                               //      添加一個(gè)自定義的元素

                               virtual void AddCustom( IRichTextCustomElement * pElement ) = 0;

                               //      添加一個(gè)段落

                               virtual unsigned long AddParagraph() = 0;

                               //      設(shè)置文字顏色

                               virtual void SetTextColor( unsigned long ulColor ) = 0;

                               //      設(shè)置文字字體

                               virtual void SetTextFont( IFont * pFont ) = 0;

                               //      獲取元素的數(shù)量

                               virtual void GetElementCount() const = 0;

                               //      獲取元素類型

                               //      result: -1 = 非法索引 0=文字 1=鏈接 2=自定義元素

                               virtual int GetElementType( size_t uElementIndex ) const = 0;

                               //      獲取元素的字體和顏色

                               //      result: -1 = 失敗 0=成功

                               //      pFont: 返回字體接口

                               //      ulColor: 返回顏色值

                               virtual int GetElementFontAndColor( size_t uElementIndex, IFont *& ppFont, unsigned long & ulColor ) const = 0;

                               //      獲取元素的字符

                               virtual void GetElementChars( size_t uElementIndex, const UTF16_CHAR * &pChars, size_t & uCount ) const = 0;

                               //      獲取自定義元素

                               virtual IRichTextCustomElement * GetCustomElement( size_t uElementIndex ) const = 0;

                               //      獲取元素的段落ID

                               virtual unsigned long GetElementParagraphID( size_t uElementIndex ) const = 0;

                               //      獲取元素的鏈接ID

                               virtual unsigned long GetElementLinkID( size_t uElementIndex ) const = 0;

                     };

             

            3-       模塊實(shí)現(xiàn):RichTextView

            RichTextView 主要實(shí)現(xiàn)了排版和繪制。

             

            A        排版功能

            它的基本排版單位是LINE(行),也就是顯示行。在LINE的內(nèi)部存儲(chǔ)了數(shù)個(gè)RUN。每個(gè)RUN僅對(duì)應(yīng)一個(gè)DOC中的元素,但是一個(gè)DOC中的元素可以對(duì)應(yīng)多個(gè)RUN(被拆分成多行的情況)。

             

            RichTextView中排版是通過(guò)拆分DOC中的每個(gè)元素實(shí)現(xiàn)的。因?yàn)橛?/span>IFont接口以及IRichTextCustomElement接口,就可以獲取到文字和自定義元素的大小,依次累加到元素結(jié)束或者LINE寬度溢出,就可以結(jié)束一個(gè)RUN,開(kāi)始下一個(gè)RUN

             

            在這個(gè)模塊的實(shí)現(xiàn)中,需要注意下面幾個(gè)問(wèn)題:

             

            1)       如何確定一個(gè)LINE的高度:在實(shí)現(xiàn)里,是根據(jù)每個(gè)RUN對(duì)應(yīng)的元素的高度取MAX來(lái)實(shí)現(xiàn)的。

            2)       根據(jù)段落來(lái)適時(shí)的換行。

            3)       LINK根據(jù)需求來(lái)決定是否可以拆分成多個(gè)LINE中的多個(gè)RUN。(實(shí)際需求里是禁止拆分LINK

            4)       行間距與RUNLINEHITTEST

             

            RUN的結(jié)構(gòu)是這樣的:

            struct RUN_S {

                             size_t uElementIndex;                       //      元素的索引

                             size_t uInElementCharIndex;           //      在元素的字符中的索引

                             size_t uInElementCharCount;                   //      在元素中的字符數(shù)量

                             float fWidth;                                          //      RUN的寬度

                             float fHeight;                                        //      RUN的高度

            };

             

            LINE 的結(jié)構(gòu)是這樣的:

            struct LINE_S {

                               vector<RUN_S*> vecRuns;               //      行內(nèi)的RUN

                               float fPosY;                                            //      LINE在整個(gè)VIEW中的Y坐標(biāo)。

                               float fHeight;                                        //      LINE的高度

            };

            B- 繪制功能

            繪制功能和拆分排版差不多,主要就是繪制坐標(biāo)根據(jù)RUNLINE的寬度和高度的累計(jì)。

            然后調(diào)用IFontIRichTextCustomElement的繪制方法。

            C- HITTEST

            除了排版和繪制之外,VIEW還提供了HITTEST,用來(lái)檢測(cè)點(diǎn)擊命中了哪個(gè)LINERUN、或者對(duì)應(yīng)到DOC中的元素,從而實(shí)現(xiàn)點(diǎn)擊鏈接的檢測(cè)。

             

            RichTextView接口如下:

             

             

            class IRichTextView

            {

            public:

                       //      獲取行數(shù)

                       virtual size_t GetLineCount() const = 0;

                       //      獲取行的RUN數(shù)量

                       virtual size_t GetRunCount( size_t uLineIndex ) const = 0;

                       //      獲取RUN對(duì)應(yīng)的元素索引

                       virtual size_t GetRunElementIndex( size_t uLineIndex, size_t uRunIndex ) const = 0;

                       //      DOC,行寬和行間距建立排版內(nèi)容。

                       virtual void Build( IRichTextDoc * pDoc, float fLineWidth, float fLineGap ) = 0;

                       //      檢測(cè)點(diǎn)擊的行

                       virtual size_t LineHitTest( float fX, float fY ) const = 0;

                       //      檢測(cè)點(diǎn)擊的RUN

                       virtual size_t RunHitTest( size_t uLineIndex, float fX, float fY ) const = 0;

                       //      檢測(cè)點(diǎn)擊的元素索引

                       virtual size_t ElementHitTest( float fX, float fY ) const = 0;

                       //      獲取VIEW的高度。

                       virtual float GetHeight() const = 0;         

                       //      繪制

                       virtual void Draw(float fX, float fY, float fWidth, float fHeight) const = 0;

                       //      從某行開(kāi)始繪制

                       virtual void Draw(size_t uBeginLineIndex, float fX, float fY, float fWidth, float fHeight) const = 0;

            };

             

             

            【應(yīng)用】

                     目前應(yīng)用在一個(gè)手機(jī)網(wǎng)游的項(xiàng)目中,來(lái)顯示聊天內(nèi)容。

                   平臺(tái)目前是IOSWIN32IOS下字體使用的是CORETEXT+COREGRAPHICS來(lái)實(shí)現(xiàn)的。WIN32下用的是GetGlyphOutline API。渲染使用的OPENGLES 1.1,內(nèi)部用glTexSubImage2D來(lái)實(shí)現(xiàn)了一個(gè)字形的貼圖緩沖。

             

                     在項(xiàng)目中,View被綁定在一個(gè)RichTextUI控件中。

             

            【擴(kuò)展】

                     目前只能顯示富文本,后面需要擴(kuò)展為RICHEDIT使用。

                     需要增加光標(biāo)的位置判定和光標(biāo)的顯示位置和大小的獲取。

                     考慮在DOC上增加存儲(chǔ)文字寬度,以便于VIEW上進(jìn)行CHARHITTEST時(shí)的快速取用。

             

             

             

             

            posted on 2012-11-07 15:48 飯中淹 閱讀(3356) 評(píng)論(0)  編輯 收藏 引用 所屬分類: 游戲客戶端手機(jī)開(kāi)發(fā)(ios)
            午夜精品久久久久成人| 91久久精品国产成人久久| 亚洲精品国产自在久久| 久久人人青草97香蕉| 久久夜色精品国产噜噜噜亚洲AV| 国产精品久久久久AV福利动漫 | 午夜精品久久久久久影视777| 亚洲成av人片不卡无码久久| 久久国产热精品波多野结衣AV| 久久成人精品视频| 久久久这里只有精品加勒比| 99久久免费国产特黄| 日韩欧美亚洲国产精品字幕久久久| 久久亚洲日韩看片无码| 99久久精品免费看国产| 久久久久女人精品毛片| 亚洲欧美日韩精品久久亚洲区| 丰满少妇高潮惨叫久久久| 思思久久精品在热线热| 久久精品国产99久久丝袜| 国产精品9999久久久久| 久久99热这里只有精品国产| 国产精品xxxx国产喷水亚洲国产精品无码久久一区 | 亚洲国产精品无码久久久蜜芽| A级毛片无码久久精品免费| 久久久一本精品99久久精品88| 久久久久久亚洲精品无码| 欧美日韩中文字幕久久伊人| 色欲久久久天天天综合网精品| 久久亚洲精品无码观看不卡| 国产成人AV综合久久| 久久久青草青青亚洲国产免观| 婷婷久久久亚洲欧洲日产国码AV | 日本久久久久亚洲中字幕| 久久天天躁夜夜躁狠狠| 久久亚洲AV成人无码软件| 日本精品久久久久久久久免费| 久久国产美女免费观看精品| AAA级久久久精品无码区| 国产精品99久久精品爆乳| 久久久久综合中文字幕|