D3D显示FreeType读取的TFF字库

来源:互联网 发布:net域名怎么样 编辑:程序博客网 时间:2024/06/05 10:06

网上COPY的一段代码,进行了修改,效率有所提升,比IDirectFont显示字符的效率提高3-4倍,需要继续优化。

1.纹理淘汰算法需要修改,LRU算法不错。
#pragma once#include <d3dx9.h>#include <ft2build.h>#include <freetype/freetype.h>#include <freetype/ftglyph.h>#include <freetype/fttypes.h>#include <map>#include <vector>const int TEXTURE_SIZE = 500;class CFreeTypeFont{public:// 顶点数据结构struct FontVertex{FontVertex():x(0), y(0), z(0), rhw(0), color(0), u(0), v(0){}FontVertex(float _x, float _y, float _z, float _rhw, DWORD _color, float _u, float _v): x(_x), y(_y), z(_z), rhw(_rhw), color(_color), u(_u), v(_v){}float x, y, z, rhw;DWORDcolor;float u, v;};#define VERTEX_FVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1)typedef struct _CHAR_TEX{unsigned long c;bool used; long useCount;long row;  //texture rowlong col;   //texture collong width;//char widthlong height;//char heightlong deltaX;long deltaY;}CHAR_TEX, *LPCHAR_TEX;public:CFreeTypeFont(IDirect3DDevice9* pDevice);~CFreeTypeFont(void);void DrawSimpleText(const std::string& str, const int& size, const RECT& rect, const DWORD& color, bool bOutLine = false);private:void init(const std::string& fontFile, const int& fontSize);bool copyCharToTexture(LPCHAR_TEX pCharTex);void render(std::vector<FontVertex>& fontVecs);protected:LPDIRECT3DDEVICE9 m_pDevice;FT_Librarym_FT2Lib;FT_Facem_FT_Face;private:LPDIRECT3DTEXTURE9 _pTex;BYTE* _pTexBuf;bool _bOutLine;//纹理采用,先进先出的淘汰原则long _texUnitSize;  //单元纹理的大小long _texUnitLen;   //单元纹理的个数,横坐标或者纵坐标long _texUnitIndex;//单元纹理使用的索引LPCHAR_TEX* _pTexIndices;   //纹理对应字符索引LPCHAR_TEX* _pCharIndices;  //字符对应纹理索引bool _isInit;};



#include "FreeTypeFont.h"#include <assert.h>#include <fstream>#pragma   warning(   push   ) #pragma   warning(   disable   :   4244   )  /*disable long to float*/#pragma   warning(   disable   :   4267   )  /*disable size_t to int*/CFreeTypeFont::CFreeTypeFont(IDirect3DDevice9* pDevice):m_pDevice(pDevice),m_FT2Lib(NULL),m_FT_Face(NULL),_bOutLine(false),_isInit(false),_texUnitSize(0),_texUnitLen(0),_texUnitIndex(-1){init("幼圆.TTF", 20);assert(_isInit);_texUnitLen = TEXTURE_SIZE / _texUnitSize;_pTexIndices = new LPCHAR_TEX[_texUnitLen * _texUnitLen];memset(_pTexIndices, 0, sizeof(_pTexIndices) * _texUnitLen * _texUnitLen);_pCharIndices = new LPCHAR_TEX[256 * 256];memset(_pCharIndices, 0, sizeof(_pCharIndices) * 256 * 256);}CFreeTypeFont::~CFreeTypeFont(void){if (_pTex){_pTex->Release();_pTex = NULL;}if(m_FT2Lib)FT_Done_FreeType(m_FT2Lib);for (int i = 0; i < _texUnitLen * _texUnitLen; i++){if (_pTexIndices[i]){delete _pTexIndices[i];}}delete []_pTexIndices;delete []_pCharIndices;}void CFreeTypeFont::init(const std::string& fontFile, const int& fontSize){_texUnitSize = fontSize;if (FT_Init_FreeType( &m_FT2Lib) ) {FT_Done_FreeType(m_FT2Lib);m_FT2Lib = NULL;return;}if (FT_New_Face(m_FT2Lib,fontFile.c_str(),0,&m_FT_Face )){FT_Done_FreeType(m_FT2Lib);m_FT2Lib = NULL;return;}FT_Select_Charmap(m_FT_Face, FT_ENCODING_UNICODE);FT_Set_Pixel_Sizes(m_FT_Face,fontSize, fontSize);if (m_pDevice->CreateTexture(TEXTURE_SIZE, TEXTURE_SIZE, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &_pTex, NULL) != D3D_OK){FT_Done_FreeType(m_FT2Lib);m_FT2Lib = NULL;return;}_pTexBuf = new BYTE[TEXTURE_SIZE*TEXTURE_SIZE*4];memset( _pTexBuf , 0 , TEXTURE_SIZE*TEXTURE_SIZE*4 );_isInit = true;}void CFreeTypeFont::DrawSimpleText( const std::string& str, const int& size, const RECT& rect, const DWORD& color, bool bOutLine /*= false*/ ){if (str.empty()){return;}float scale = (float)size /_texUnitSize; int lineHeight = _texUnitSize + 4;std::vector<FontVertex> fontVecs;unsigned long charcode = 0;const char* p = str.c_str();long xPos = rect.left, yPos = rect.top;while (*p){if (*p == '\n'){p++;xPos = rect.left;yPos += lineHeight * scale;continue;}if (*p & 0x80){charcode = *(WORD*)p;}else {charcode = *(char*)p;}LPCHAR_TEX pCharTex = _pCharIndices[charcode];if (pCharTex == NULL){_texUnitIndex++;if (_pTexIndices[_texUnitIndex] == NULL){_pCharIndices[charcode] = new CHAR_TEX();_pCharIndices[charcode]->c = charcode;_pTexIndices[_texUnitIndex] = _pCharIndices[charcode];}else{//exchange texturelong tempIndex= _texUnitIndex;while(_pTexIndices[_texUnitIndex]->used){if (_texUnitIndex == _texUnitLen * _texUnitLen){_texUnitIndex = -1;}_texUnitIndex++;if (_texUnitIndex == tempIndex){//all usedassert(false);}}_pTexIndices[_pTexIndices[_texUnitIndex]->c] = NULL;_pTexIndices[charcode] = _pTexIndices[_texUnitIndex];}_pCharIndices[charcode]->c = charcode;_pCharIndices[charcode]->used = true;_pCharIndices[charcode]->row = _texUnitIndex / _texUnitLen;_pCharIndices[charcode]->col = _texUnitIndex % _texUnitLen;copyCharToTexture(_pCharIndices[charcode]);}float x = xPos + _pCharIndices[charcode]->deltaX* scale - 0.5;float y = yPos - _pCharIndices[charcode]->deltaY* scale + (lineHeight - _texUnitSize ) / 2  - 0.5 ;float addX = _pCharIndices[charcode]->width * scale;float addY = _pCharIndices[charcode]->height * scale;if (*p & 0x80){p += 2;}else {p += 1;}xPos += _pCharIndices[charcode]->width * scale;//renderFontVertex vecs[4];float bround = 0.001f;float u = (float)(_pCharIndices[charcode]->col * _texUnitSize)  / TEXTURE_SIZE ;float v = (float)(_pCharIndices[charcode]->row * _texUnitSize)  / TEXTURE_SIZE ; float addU = (float)(_pCharIndices[charcode]->width) / TEXTURE_SIZE - bround ;float addV = (float)(_pCharIndices[charcode]->height)/ TEXTURE_SIZE - bround ;vecs[0] = FontVertex(x , y, 0.0f, 1.0f, color, u, v);vecs[1] = FontVertex(x, y + addY , 0.0f, 1.0f, color, u, v + addV);vecs[2] = FontVertex(x + addX, y, 0.0f, 1.0f, color, u + addU, v);vecs[3] = FontVertex(x + addX, y + addY, 0.0f, 1.0f, color, u + addU, v + addV);fontVecs.push_back(vecs[0]);fontVecs.push_back(vecs[1]);fontVecs.push_back(vecs[2]);fontVecs.push_back(vecs[1]);fontVecs.push_back(vecs[2]);fontVecs.push_back(vecs[3]);}render(fontVecs);}bool CFreeTypeFont::copyCharToTexture(LPCHAR_TEX pCharTex){char*  chr = (char*)&(pCharTex->c);wchar_t wchar;MultiByteToWideChar( CP_ACP, 0, chr,strlen(chr)+1, &wchar,1 );if(FT_Load_Char(m_FT_Face, wchar,FT_LOAD_RENDER | FT_LOAD_TARGET_LIGHT) )return false;FT_GlyphSlot slot = m_FT_Face->glyph;FT_Bitmap bitmap = slot->bitmap;int width  =  bitmap.width;int height =  bitmap.rows;int row = pCharTex->row;int col = pCharTex->col;pCharTex->width = BYTE(m_FT_Face->glyph->advance.x / 64);pCharTex->height = BYTE(m_FT_Face->size->metrics.y_ppem);pCharTex->deltaX = (slot->metrics.horiBearingX >> 6);pCharTex->deltaY = (slot->bitmap_top-_texUnitSize);int dstStride = TEXTURE_SIZE * 4;int dstbegin = row * _texUnitSize * TEXTURE_SIZE * 4 + col * _texUnitSize * 4;unsigned char* src = bitmap.buffer;switch (m_FT_Face->glyph->bitmap.pixel_mode){case FT_PIXEL_MODE_GRAY:{for(int j=0; j  < height ; j++){for(int i=0; i < width; i++){unsigned char _vl =  src[i + bitmap.width*j];_pTexBuf[dstbegin + (4*i + j * dstStride)  ] = 0xFF;_pTexBuf[dstbegin + (4*i + j * dstStride)+1] = 0xFF;_pTexBuf[dstbegin + (4*i + j * dstStride)+2] = 0xFF;_pTexBuf[dstbegin + (4*i + j * dstStride)+3] = _vl;_pTexBuf[4 *(i + j * TEXTURE_SIZE) + 0] = 0xff;}}}break;case FT_PIXEL_MODE_MONO:{for(int i=0; i  < height ; i++){for(int j=0; j < width; j++){unsigned char _vl = 0;if(src[i*bitmap.pitch + j/8] & (0x80 >> (j & 7)))_vl = 0xFF;else_vl = 0x00;_pTexBuf[dstbegin + (4*j + i * dstStride)  ] = 0xFF;_pTexBuf[dstbegin + (4*j + i * dstStride)+1] = 0xFF;_pTexBuf[dstbegin + (4*j + i * dstStride)+2] = 0xFF;_pTexBuf[dstbegin + (4*j + i * dstStride)+3] = _vl;}}}break;}D3DLOCKED_RECT desc;if (_pTex->LockRect(0, &desc, NULL, 0)!=D3D_OK)return false;for (int y = 0; y < TEXTURE_SIZE; ++y){for (int x = 0; x < TEXTURE_SIZE; ++x){byte* source_pixel = _pTexBuf + (TEXTURE_SIZE * 4 * y) + (x * 4);byte* destination_pixel = ((byte*) desc.pBits) + desc.Pitch * y + x * 4;destination_pixel[0] = source_pixel[2];destination_pixel[1] = source_pixel[1];destination_pixel[2] = source_pixel[0];destination_pixel[3] = source_pixel[3];}}_pTex->UnlockRect(0);return true;}void CFreeTypeFont::render(std::vector<FontVertex>& fontVecs){m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);m_pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);m_pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);m_pDevice->SetTextureStageState( 0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG1 );//m_pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);m_pDevice->SetSamplerState(0,D3DSAMP_MIPFILTER,D3DTEXF_POINT);m_pDevice->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR);m_pDevice->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR);m_pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);m_pDevice->SetFVF(VERTEX_FVF);m_pDevice->SetTexture(0,_pTex);int count = fontVecs.size() / 3;if (count > 0){m_pDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, count, &fontVecs[0], sizeof(FontVertex));}m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);}#pragma   warning(   pop   ) 


原创粉丝点击