• <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>

            永遠也不完美的程序

            不斷學習,不斷實踐,不斷的重構……

            常用鏈接

            統計

            積分與排名

            好友鏈接

            最新評論

            FreeType2字體轉換到D3D紋理


            Font.h

            #ifndef __Font_H__
            #define __Font_H__

            #include 
            <vector>
            #include 
            <D3D9.h>

            typedef unsigned 
            char uint8;

            template
            <typename T> struct TRect
            {
                T left, top, right, bottom;
                TRect() {}
                TRect(T 
            const & l, T const & t, T const & r, T const & b)
                    : left(l), top(t), right(r), bottom(b)
                {
                }
                TRect(TRect 
            const & o)
                    : left(o.left), top(o.top), right(o.right), bottom(o.bottom)
                {
                }
                TRect 
            & operator=(TRect const & o)
                {
                    left 
            = o.left;
                    top 
            = o.top;
                    right 
            = o.right;
                    bottom 
            = o.bottom;
                    
            return *this;
                }
                T width() 
            const
                {
                    
            return right - left;
                }
                T height() 
            const
                {
                    
            return bottom - top;
                }
            };

            typedef unsigned 
            int uint32;
            typedef TRect
            <float> FloatRect;

            class Font
            {
            public:
                Font(IDirect3DDevice9
            * device);
                typedef uint32 CodePoint;
                typedef FloatRect UVRect;
                typedef std::pair
            <CodePoint, CodePoint> PairCodePoint;
                typedef std::vector
            <PairCodePoint> VectorPairCodePoint;

                
            struct GlyphInfo
                {
                    CodePoint codePoint;
            //codePoint碼
                    UVRect uvRect;//紋理區域
                    float aspectRatio;

                    GlyphInfo():codePoint(
            0),uvRect(UVRect(0000)),aspectRatio(1)
                    { 
                    }
                    GlyphInfo(CodePoint _code, 
            const UVRect& _rect, float _aspect) : codePoint(_code), uvRect(_rect), aspectRatio(_aspect)
                    { 
                    }
                };

                typedef std::vector
            <GlyphInfo> VectorGlyphInfo;

                
            struct RangeInfo
                {
                    CodePoint first;
                    CodePoint second;
                    VectorGlyphInfo range;

                    RangeInfo(CodePoint _first, CodePoint _second) : first(_first), second(_second) { }
                };


                
            enum constCodePoints
                {
                    FONT_CODE_SELECT 
            = 0,
                    FONT_CODE_TAB 
            = 0x0009,
                    FONT_CODE_LF 
            = 0x000A,
                    FONT_CODE_CR 
            = 0x000D,
                    FONT_CODE_SPACE 
            = 0x0020,
                    FONT_CODE_LATIN_START 
            = 0x0021,
                    FONT_CODE_NEL 
            = 0x0085,
                    FONT_CODE_LATIN_END 
            = 0x00A6,
                };

                typedef std::vector
            <RangeInfo> VectorRangeInfo;


                
            bool loadFont();

                inline 
            bool checkHidePointCode(CodePoint _id)
                {
                    
            for (VectorPairCodePoint::iterator iter=mVectorHideCodePoint.begin(); iter!=mVectorHideCodePoint.end(); ++iter) {
                        
            if ((_id >= iter->first) && (_id <= iter->second)) return true;
                    }
                    
            return false;
                }

            public:
                VectorPairCodePoint mVectorHideCodePoint;
                
            //字體范圍
                VectorRangeInfo mVectorRangeInfo;
                
                uint8 mCountSpaceTab;
                uint8 mCharSpacer;

                GlyphInfo mSpaceGlyphInfo, mTabGlyphInfo, mSelectGlyphInfo, mSelectDeactiveGlyphInfo, mCursorGlyphInfo;
                
                IDirect3DDevice9
            * p;
            };

            #endif

            Font.cpp

            #include 
            "Font.h"
            #include 
            <d3dx9tex.h>
            #include 
            <windows.h>
            #include 
            <ft2build.h>
            #include FT_FREETYPE_H
            #include FT_GLYPH_H

            const unsigned char FONT_MASK_SELECT = 0x88;
            const unsigned char FONT_MASK_SELECT_DEACTIVE = 0x60;
            const unsigned char FONT_MASK_SPACE = 0x00;
            const unsigned char FONT_MASK_CHAR = 0xFF;    
            const size_t FONT_TEXTURE_WIDTH = 1024;

            typedef unsigned 
            char uchar;

            Font::Font(IDirect3DDevice9
            * device)
            {
                p 
            = device;
                mCharSpacer 
            = 5;
                mCountSpaceTab 
            = 4;
            }

            bool Font::loadFont()
            {
                
            if (mVectorRangeInfo.empty())
                    mVectorRangeInfo.push_back(RangeInfo(FONT_CODE_LATIN_START, FONT_CODE_LATIN_END));


                FT_Library ftLibrary;
            //定義FT庫

                
            //第一步:初始化庫 
                if(FT_Init_FreeType(&ftLibrary))
                    MessageBox(NULL,
            "FreeType初始化庫時發生了一個錯誤!", NULL, NULL);


                
            //第二步:裝載一個字體face (可以從一個字體文件裝載, 也可以內存裝載)
                
            //字體文件裝載:
                FT_Face face;
                
            if(FT_New_Face(ftLibrary, "msyh.ttf"0&face)) 
                    MessageBox(NULL,
            "Could not open font face!",NULL,NULL);

                
            //內存裝載:
                
            //FT_New_Memory_Face( library,
                
            //buffer, /* 緩存的第一個字節 */ 
                
            //size, /* 緩存的大小(以字節表示) */ 
                
            //0, /* face索引 */ 
                
            //&face ); 內存裝載


                
            //第三步:設置當前象素尺寸
                
            //當一個新的face對象建立時,對于可伸縮字體格式,size對象默認值為字符大小水平和垂直均為10象素。
                
            //對于定長字體格式,這個大小是未定義的,這就是你必須在裝載一個字形前設置該值的原因。 
                
            //設置FreeType2字體大小
                
            //FT_Set_Char_Size( 
                
            //    face, /* face對象的句柄 */ 
                
            //    0, /* 以1/64點為單位的字符寬度 */ 
                
            //    16*64, /* 以1/64點為單位的字符高度 */ 
                
            //    300, /* 設備水平分辨率 */ 
                
            //    300 ); /* 設備垂直分辨率 */ 
                FT_F26Dot6 ftSize = (FT_F26Dot6)(24 * (1 << 6));
                
            if(FT_Set_Char_Size( face, ftSize, 07272))
                    MessageBox(NULL,
            "Could not set char size!",NULL,NULL);


                
            int max_height = 0, max_width = 0, max_bear = 0;

                
            //讀取字體
                FT_Error ftResult = FT_Load_Char( face, 97, FT_LOAD_RENDER );
                
            if(ftResult)
                    MessageBox(NULL ,
            "cannot load character 97", NULL, NULL);
                FT_Int advance 
            = (face->glyph->advance.x >> 6 ) + ( face->glyph->metrics.horiBearingX >> 6 );

                
            //位圖指針
                unsigned char* buffer = face->glyph->bitmap.buffer;
                
            if(NULL == buffer)
                    MessageBox(NULL,
            "位圖指針error", NULL, NULL);


                
            //計算 最大寬, 高  
                size_t glyphCount = 4;
                size_t l 
            = glyphCount * (advance + 5), m = 0;


                
            //在這里計算字體紋理需要的大小
                for (VectorRangeInfo::iterator iter=mVectorRangeInfo.begin(); iter!=mVectorRangeInfo.end(); ++iter) {
                    
            for (CodePoint index=iter->first; index<=iter->second; ++index, ++glyphCount) {

                        
            if (checkHidePointCode(index)) continue;
                        
            //讀取字體(單個)
                        if (FT_Load_Char( face, index, FT_LOAD_RENDER )) continue;
                        
            //這里判斷是否有這個CodePoint碼
                        if (NULL == face->glyph->bitmap.buffer) continue;

                        
            //應該是字寬 
                        FT_Int advance = (face->glyph->advance.x >> 6 ) + ( face->glyph->metrics.horiBearingX >> 6 );

                        
            if ( ( 2 * ( face->glyph->bitmap.rows << 6 ) - face->glyph->metrics.horiBearingY ) > max_height )
                            max_height 
            = ( 2 * ( face->glyph->bitmap.rows << 6 ) - face->glyph->metrics.horiBearingY );

                        
            if ( face->glyph->metrics.horiBearingY > max_bear )
                            max_bear 
            = face->glyph->metrics.horiBearingY;

                        
            if ( (face->glyph->advance.x >> 6 ) + ( face->glyph->metrics.horiBearingX >> 6 ) > max_width)
                            max_width 
            = (face->glyph->advance.x >> 6 ) + ( face->glyph->metrics.horiBearingX >> 6 );

                        l 
            += (advance + 5);
                        
            if ( (FONT_TEXTURE_WIDTH - 1< (l + advance) ) { m ++; l = 0;}

                    }
                }

                max_height 
            >>= 6;
                max_bear 
            >>= 6;

                size_t finalWidth 
            = FONT_TEXTURE_WIDTH;//字體紋理的寬度
                size_t finalHeight = (m+1* (max_height + 5);//字體紋理的高度

                
            //字節對齊
                size_t needHeight = 1;
                
            while (needHeight < finalHeight) needHeight <<= 1;
                finalHeight 
            = needHeight;

                
            //字體文理寬高比例
                float textureAspect = (float)finalWidth / (float)finalHeight;


                
            //圖象格式A8L8
                const size_t pixel_bytes = 2;
                size_t data_width 
            = finalWidth * pixel_bytes;
                size_t data_size 
            = finalWidth * finalHeight * pixel_bytes;//字體紋理需要的字節數

                
            //字體位圖指針
                uchar* imageData = new uchar[data_size];

                
            //8位表示亮度8位表示alpha值
                for (size_t i = 0; i < data_size; i += pixel_bytes) {
                    imageData[i 
            + 0= 0x00//亮度
                    imageData[i + 1= 0x00//alpha值
                }
                l 
            = 0;
                m 
            = 0;


                ftResult 
            = FT_Load_Char( face, 97, FT_LOAD_RENDER );
                
            if (ftResult) 
                    MessageBox(NULL, 
            "cannot load character ", NULL, NULL);
                advance 
            = (face->glyph->advance.x >> 6 ) + ( face->glyph->metrics.horiBearingX >> 6 );
                buffer 
            = face->glyph->bitmap.buffer;

                
            //得到y的空隙
                int y_bearnig = max_bear - ( face->glyph->metrics.horiBearingY >> 6 );

                
            ///////////////////////////////////////////////////////////////////////////////////////
                //設置空格符紋理
                for (int j = 0; j < face->glyph->bitmap.rows; j++ ) {
                    
            int row = j + (int)m + y_bearnig;
                    uchar
            * pDest = &imageData[(row * data_width) + l * pixel_bytes];//找起點
                    for (int k = 0; k < face->glyph->bitmap.width; k++ ) {
                        
            *pDest++= FONT_MASK_CHAR;
                        
            *pDest++= FONT_MASK_SPACE;
                        buffer
            ++;
                    }
                }
                
            //設置空格符紋理坐標
                mSpaceGlyphInfo.codePoint = FONT_CODE_SPACE;
                mSpaceGlyphInfo.uvRect.left 
            = (float)l / (float)finalWidth;  // u1
                mSpaceGlyphInfo.uvRect.top = (float)m / (float)finalHeight;  // v1
                mSpaceGlyphInfo.uvRect.right = (float)( l + ( face->glyph->advance.x >> 6 ) ) / (float)finalWidth; // u2
                mSpaceGlyphInfo.uvRect.bottom = ( m + max_height ) / (float)finalHeight; // v2
                mSpaceGlyphInfo.aspectRatio = textureAspect * (mSpaceGlyphInfo.uvRect.right - mSpaceGlyphInfo.uvRect.left)  / (mSpaceGlyphInfo.uvRect.bottom - mSpaceGlyphInfo.uvRect.top);

                
            ///////////////////////////////////////////////////////////////////////////////////////

                mTabGlyphInfo 
            = mSpaceGlyphInfo;
                mTabGlyphInfo.aspectRatio 
            = textureAspect * (float)mCountSpaceTab;

                l 
            += (advance + mCharSpacer);
                
            if ( (FONT_TEXTURE_WIDTH - 1< (l + advance) ) { m += max_height + mCharSpacer;l = 0;}

                
            ///////////////////////////////////////////////////////////////////////////////////////
                for (int j = 0; j < face->glyph->bitmap.rows; j++ ) {
                    
            int row = j + (int)m + y_bearnig;
                    uchar
            * pDest = &imageData[(row * data_width) + l * pixel_bytes];
                    
            for(int k = 0; k < face->glyph->bitmap.width; k++ ) {
                        
            *pDest++= FONT_MASK_CHAR;
                        
            *pDest++= FONT_MASK_SELECT;
                        buffer
            ++;
                    }
                }

                mSelectGlyphInfo.codePoint 
            = FONT_CODE_SELECT;
                mSelectGlyphInfo.uvRect.left 
            = (float)l / (float)finalWidth;  // u1
                mSelectGlyphInfo.uvRect.top = (float)m / (float)finalHeight;  // v1
                mSelectGlyphInfo.uvRect.right = (float)( l + ( face->glyph->advance.x >> 6 ) ) / (float)finalWidth; // u2
                mSelectGlyphInfo.uvRect.bottom = ( m + max_height ) / (float)finalHeight; // v2
                mSelectGlyphInfo.aspectRatio = textureAspect * (mSelectGlyphInfo.uvRect.right - mSelectGlyphInfo.uvRect.left)  / (mSelectGlyphInfo.uvRect.bottom - mSelectGlyphInfo.uvRect.top);

                
            //l+= 本字寬+字空 
                l += (advance + mCharSpacer);
                
            //如果到頭容不下一個字
                if ( (FONT_TEXTURE_WIDTH - 1< (l + advance) ) { m += max_height + mCharSpacer;l = 0;}

                
            ///////////////////////////////////////////////////////////////////////////////////////
                for (int j = 0; j < face->glyph->bitmap.rows; j++ ) {
                    
            int row = j + (int)m + y_bearnig;
                    uchar
            * pDest = &imageData[(row * data_width) + l * pixel_bytes];
                    
            for(int k = 0; k < face->glyph->bitmap.width; k++ ) {
                        
            *pDest++= FONT_MASK_CHAR;
                        
            *pDest++= FONT_MASK_SELECT_DEACTIVE;
                        buffer
            ++;
                    }
                }

                mSelectDeactiveGlyphInfo.codePoint 
            = FONT_CODE_SELECT;
                mSelectDeactiveGlyphInfo.uvRect.left 
            = (float)l / (float)finalWidth;  // u1
                mSelectDeactiveGlyphInfo.uvRect.top = (float)m / (float)finalHeight;  // v1
                mSelectDeactiveGlyphInfo.uvRect.right = (float)( l + ( face->glyph->advance.x >> 6 ) ) / (float)finalWidth; // u2
                mSelectDeactiveGlyphInfo.uvRect.bottom = ( m + max_height ) / (float)finalHeight; // v2
                mSelectDeactiveGlyphInfo.aspectRatio = textureAspect * (mSelectDeactiveGlyphInfo.uvRect.right - mSelectDeactiveGlyphInfo.uvRect.left)  / (mSelectDeactiveGlyphInfo.uvRect.bottom - mSelectDeactiveGlyphInfo.uvRect.top);

                l 
            += (advance + mCharSpacer);
                
            if ( (FONT_TEXTURE_WIDTH - 1< (l + advance) ) { m += max_height + mCharSpacer;l = 0;}

                
            ///////////////////////////////////////////////////////////////////////////////////////

                
            for (int j = 0; j < face->glyph->bitmap.rows; j++ ) {
                    
            int row = j + (int)m + y_bearnig;
                    uchar
            * pDest = &imageData[(row * data_width) + l * pixel_bytes];
                    
            for(int k = 0; k < face->glyph->bitmap.width; k++ ) {
                        
            *pDest++= FONT_MASK_CHAR;
                        
            *pDest++= FONT_MASK_CHAR;
                        buffer
            ++;
                    }
                }

                mCursorGlyphInfo.codePoint 
            = FONT_CODE_SELECT;
                mCursorGlyphInfo.uvRect.left 
            = (float)l / (float)finalWidth;  // u1
                mCursorGlyphInfo.uvRect.top = (float)m / (float)finalHeight;  // v1
                mCursorGlyphInfo.uvRect.right = (float)( l + ( face->glyph->advance.x >> 6 ) ) / (float)finalWidth; // u2
                mCursorGlyphInfo.uvRect.bottom = ( m + max_height ) / (float)finalHeight; // v2
                mCursorGlyphInfo.aspectRatio = textureAspect * (mCursorGlyphInfo.uvRect.right - mCursorGlyphInfo.uvRect.left)  / (mCursorGlyphInfo.uvRect.bottom - mCursorGlyphInfo.uvRect.top);

                l 
            += (advance + mCharSpacer);
                
            if ( (FONT_TEXTURE_WIDTH - 1< (l + advance) ) { m += max_height + mCharSpacer;l = 0;}
                
            ///////////////////////////////////////////////////////////////////////////////////////

                
            for (VectorRangeInfo::iterator iter=mVectorRangeInfo.begin(); iter!=mVectorRangeInfo.end(); ++iter) 
                {

                    iter
            ->range.resize(iter->second - iter->first + 1);
                    size_t pos 
            = 0;

                    
            for (CodePoint index=iter->first; index<=iter->second; ++index, ++pos) {

                        
            if (checkHidePointCode(index)) continue;

                        GlyphInfo 
            & info = iter->range.at(pos);

                        ftResult 
            = FT_Load_Char( face, index, FT_LOAD_RENDER );
                        
            if (ftResult) {
                            MessageBox(NULL, 
            "cannot load character ", NULL, NULL);
                            
            continue;
                        }

                        FT_Int advance 
            = (face->glyph->advance.x >> 6 ) + ( face->glyph->metrics.horiBearingX >> 6 );
                        
            //位圖指針
                        unsigned char* buffer = face->glyph->bitmap.buffer;

                        
            if (NULL == buffer) {
                            MessageBox(NULL, 
            "Freetype returned null for character ", NULL, NULL);
                            
            continue;
                        }

                        
            int y_bearnig = max_bear - ( face->glyph->metrics.horiBearingY >> 6 );

                        
            for(int j = 0; j < face->glyph->bitmap.rows; j++ ) {//TTF字體紋理高度
                            int row = j + (int)m + y_bearnig;
                            uchar
            * pDest = &imageData[(row * data_width) + l * pixel_bytes];
                            
            for(int k = 0; k < face->glyph->bitmap.width; k++ ) 
                            {
                                
            if(true)//WBW TEST
                                {
                                    
            *pDest++= *buffer;
                                }
                                
            else
                                {
                                    
            *pDest++= FONT_MASK_CHAR;
                                }
                                
            *pDest++= *buffer;//D3DFMT_A8L8
                                buffer++;


                            }
                        }
                        
            //CodePoint碼(字符對應的紋理坐標)a,b,c,d,e. . .一,二,三. . .
                        info.codePoint = index;
                        info.uvRect.left 
            = (float)l / (float)finalWidth;  // u1
                        info.uvRect.top = (float)m / (float)finalHeight;  // v1
                        info.uvRect.right = (float)( l + ( face->glyph->advance.x >> 6 ) ) / (float)finalWidth; // u2
                        info.uvRect.bottom = ( m + max_height ) / (float)finalHeight; // v2
                        info.aspectRatio = textureAspect * (info.uvRect.right - info.uvRect.left)  / (info.uvRect.bottom - info.uvRect.top);

                        l 
            += (advance + mCharSpacer);
                        
            if ( (FONT_TEXTURE_WIDTH - 1< (l + advance) ) { m += max_height + mCharSpacer;l = 0;}

                    }
                }

                
            //保存到D3D紋理
                IDirect3DTexture9*      _tex;
                HRESULT hr 
            = 0;

                hr 
            = ::D3DXCreateTexture(
                    p,
                    finalWidth, finalHeight,
                    
            0
                    
            0
                    D3DFMT_A8L8,
            //紋理格式
                    D3DPOOL_MANAGED, &_tex);

                
            if(FAILED(hr))
                    ::MessageBox(NULL,
            "D3DXCreateTexture error", NULL, NULL);

                D3DSURFACE_DESC textureDesc; 
                _tex
            ->GetLevelDesc(0&textureDesc);

                
            if(textureDesc.Format != D3DFMT_A8L8) 
                    
            return false;

                D3DLOCKED_RECT lockedRect;
                _tex
            ->LockRect(0&lockedRect,00);         

                
            //使用類型要對應(unsigned short --- D3DFMT_A8L8)
                unsigned short* imageData2 = (unsigned short*)lockedRect.pBits;

                
            for(int i = 0; i < finalHeight; i++){
                    
            for(int j = 0; j < finalWidth; j++){

                        
            //Pitch數據的總長度
                        int index = i * lockedRect.Pitch / 2/*D3DFMT_A8L8 二字節*/ + j;
                        
            //if(i < finalHeight/2)
                        
            //    imageData2[index] = 0x00;
                        
            //else
                        
            //    imageData2[index] = 0xFF;
                        imageData2[index] = imageData[index*2];

                    }
                }

                _tex
            ->UnlockRect(0);

                
            //保存紋理
                hr = ::D3DXSaveTextureToFile("test.jpg", D3DXIFF_JPG, _tex, NULL);
                
            if(D3DERR_INVALIDCALL == hr)
                    ::MessageBox(NULL,NULL,NULL,NULL);

                
            return true;
            }

             

            posted on 2008-12-16 21:50 狂爛球 閱讀(2804) 評論(2)  編輯 收藏 引用 所屬分類: 圖形編程

            評論

            # re: FreeType2字體轉換到D3D紋理 2009-08-09 10:37 102

            美好卻不完美  回復  更多評論   

            # re: FreeType2字體轉換到D3D紋理 [未登錄] 2012-09-03 19:22 li

            H  回復  更多評論   

            精品久久国产一区二区三区香蕉| 亚洲人成伊人成综合网久久久| 伊人久久大香线蕉亚洲 | 99热成人精品免费久久| 亚洲精品乱码久久久久久中文字幕| 久久99精品久久久久久野外 | 狠狠色丁香婷婷久久综合不卡| 久久久久久免费视频| 午夜精品久久久久久久无码| 久久综合色区| 国产成人精品三上悠亚久久 | 婷婷伊人久久大香线蕉AV| 亚洲国产精品成人久久| 久久99精品国产自在现线小黄鸭 | 无码AV波多野结衣久久| 蜜臀av性久久久久蜜臀aⅴ麻豆| 狠狠色婷婷久久综合频道日韩| 综合久久国产九一剧情麻豆| 久久久久无码精品国产不卡| 久久香蕉超碰97国产精品| 国产精品久久久天天影视| 99久久免费国产精品| 亚洲国产成人久久综合碰| 久久久无码精品亚洲日韩按摩 | 亚洲精品无码久久久久| 久久综合给合久久狠狠狠97色| 99久久久国产精品免费无卡顿| 久久久久久免费一区二区三区| 国产毛片久久久久久国产毛片| 青青青青久久精品国产h久久精品五福影院1421| 欧美麻豆久久久久久中文| 日韩精品久久久久久久电影蜜臀 | 亚洲AV无码久久| 99久久精品费精品国产| 亚洲人成电影网站久久| 日本久久久久久中文字幕| 久久伊人五月丁香狠狠色| 日韩欧美亚洲综合久久影院d3| 久久午夜无码鲁丝片秋霞 | 久久AⅤ人妻少妇嫩草影院| 色综合久久无码五十路人妻|